Qarl's new Align tool.

Signed-off-by: Beeks <HgDelirium@gmail.com>
This commit is contained in:
Beeks
2010-10-22 02:40:40 -04:00
parent 58eff984da
commit 537e396882
7 changed files with 702 additions and 9 deletions

View File

@@ -81,6 +81,7 @@ set(viewer_SOURCE_FILES
hipporestrequest.cpp
jcfloaterareasearch.cpp
chatbar_as_cmdline.cpp
qtoolalign.cpp
llagent.cpp
llagentaccess.cpp
llagentdata.cpp
@@ -529,6 +530,7 @@ set(viewer_HEADER_FILES
hipporestrequest.h
jcfloaterareasearch.h
chatbar_as_cmdline.h
qtoolalign.h
llagent.h
llagentaccess.h
llagentdata.h

View File

@@ -81,6 +81,7 @@
#include "llviewerjoystick.h"
#include "lluictrlfactory.h"
#include "qtoolalign.h" //Thank Qarl!
// Globals
LLFloaterTools *gFloaterTools = NULL;
@@ -222,6 +223,8 @@ BOOL LLFloaterTools::postBuild()
childSetCommitCallback("radio stretch",commit_select_tool,LLToolCompScale::getInstance());
mRadioSelectFace = getChild<LLCheckBoxCtrl>("radio select face");
childSetCommitCallback("radio select face",commit_select_tool,LLToolFace::getInstance());
mRadioAlign = getChild<LLCheckBoxCtrl>("radio align");
childSetCommitCallback("radio align",commit_select_tool,QToolAlign::getInstance());
mCheckSelectIndividual = getChild<LLCheckBoxCtrl>("checkbox edit linked parts");
childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts"));
childSetCommitCallback("checkbox edit linked parts",commit_select_component,this);
@@ -332,6 +335,7 @@ BOOL LLFloaterTools::postBuild()
mStatusText["rotate"] = getString("status_rotate");
mStatusText["scale"] = getString("status_scale");
mStatusText["move"] = getString("status_move");
mStatusText["align"] = getString("status_align");
mStatusText["modifyland"] = getString("status_modifyland");
mStatusText["camera"] = getString("status_camera");
mStatusText["grab"] = getString("status_grab");
@@ -364,6 +368,7 @@ LLFloaterTools::LLFloaterTools()
mRadioRotate(NULL),
mRadioStretch(NULL),
mRadioSelectFace(NULL),
mRadioAlign(NULL),
mCheckSelectIndividual(NULL),
mCheckSnapToGrid(NULL),
@@ -627,6 +632,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
tool == LLToolCompRotate::getInstance() ||
tool == LLToolCompScale::getInstance() ||
tool == LLToolFace::getInstance() ||
tool == QToolAlign::getInstance() ||
tool == LLToolIndividual::getInstance() ||
tool == LLToolPipette::getInstance();
@@ -635,6 +641,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
mRadioPosition ->setVisible( edit_visible );
mRadioRotate ->setVisible( edit_visible );
mRadioStretch ->setVisible( edit_visible );
mRadioAlign ->setVisible( edit_visible );
if (mRadioSelectFace)
{
mRadioSelectFace->setVisible( edit_visible );
@@ -650,6 +657,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
mRadioPosition ->set( tool == LLToolCompTranslate::getInstance() );
mRadioRotate ->set( tool == LLToolCompRotate::getInstance() );
mRadioStretch ->set( tool == LLToolCompScale::getInstance() );
mRadioAlign ->set( tool == QToolAlign::getInstance() );
if (mComboGridMode)
{

View File

@@ -134,6 +134,7 @@ public:
LLCheckBoxCtrl *mRadioRotate;
LLCheckBoxCtrl *mRadioStretch;
LLCheckBoxCtrl *mRadioSelectFace;
LLCheckBoxCtrl *mRadioAlign;
LLCheckBoxCtrl *mCheckSelectIndividual;

View File

@@ -54,6 +54,7 @@
#include "llviewerwindow.h"
#include "llagent.h"
#include "llfloatertools.h"
#include "qtoolalign.h"
#include "llviewercontrol.h"
const S32 BUTTON_HEIGHT = 16;
@@ -277,6 +278,12 @@ BOOL LLToolCompTranslate::handleMouseUp(S32 x, S32 y, MASK mask)
}
LLTool* LLToolCompTranslate::getOverrideTool(MASK mask)
{
if (gKeyboard->getKeyDown('A') && mask & MASK_CONTROL)
{
return QToolAlign::getInstance();
}
else
{
if (mask == MASK_CONTROL)
{
@@ -286,6 +293,7 @@ LLTool* LLToolCompTranslate::getOverrideTool(MASK mask)
{
return LLToolCompScale::getInstance();
}
}
return LLToolComposite::getOverrideTool(mask);
}
@@ -397,11 +405,14 @@ BOOL LLToolCompScale::handleMouseUp(S32 x, S32 y, MASK mask)
LLTool* LLToolCompScale::getOverrideTool(MASK mask)
{
if (mask == MASK_CONTROL)
if (gKeyboard->getKeyDown('A') && mask & MASK_CONTROL)
{
return QToolAlign::getInstance();
}
else if (mask == MASK_CONTROL)
{
return LLToolCompRotate::getInstance();
}
return LLToolComposite::getOverrideTool(mask);
}
@@ -597,7 +608,11 @@ BOOL LLToolCompRotate::handleMouseUp(S32 x, S32 y, MASK mask)
LLTool* LLToolCompRotate::getOverrideTool(MASK mask)
{
if (mask == (MASK_CONTROL | MASK_SHIFT))
if (gKeyboard->getKeyDown('A') && mask & MASK_CONTROL)
{
return QToolAlign::getInstance();
}
else if (mask == (MASK_CONTROL | MASK_SHIFT))
{
return LLToolCompScale::getInstance();
}

View File

@@ -0,0 +1,612 @@
/**
* @file lltoolface.cpp
* @brief A tool to align objects
*/
#include "llviewerprecompiledheaders.h"
// File includes
#include "qtoolalign.h"
// Library includes
#include "llbbox.h"
#include "v3math.h"
// Viewer includes
#include "llagent.h"
#include "llbox.h"
#include "llcylinder.h"
#include "llfloatertools.h"
#include "llmanip.h"
#include "llselectmgr.h"
#include "lltoolcomp.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
const F32 MANIPULATOR_SIZE = 5.0;
const F32 MANIPULATOR_SELECT_SIZE = 20.0;
QToolAlign::QToolAlign()
: LLToolComposite(std::string("Align"))
{
}
QToolAlign::~QToolAlign()
{
}
BOOL QToolAlign::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (mHighlightedAxis != -1)
{
align();
}
else
{
gViewerWindow->pickAsync(x, y, mask, pickCallback);
}
return TRUE;
}
BOOL QToolAlign::handleMouseUp(S32 x, S32 y, MASK mask)
{
// first, perform normal processing in case this was a quick-click
handleHover(x, y, mask);
LLSelectMgr::getInstance()->updateSelectionCenter();
BOOL handled = FALSE;
if( hasMouseCapture() )
{
handled = TRUE;
setMouseCapture( FALSE );
}
return handled;
}
BOOL QToolAlign::handleDoubleClick(S32 x, S32 y, MASK mask)
{
return FALSE;
}
LLTool* QToolAlign::getOverrideTool(MASK mask)
{
if (!gKeyboard->getKeyDown('A'))
{
if (mask == MASK_CONTROL)
{
return LLToolCompRotate::getInstance();
}
else if (mask == (MASK_CONTROL | MASK_SHIFT))
{
return LLToolCompScale::getInstance();
}
}
return LLToolComposite::getOverrideTool(mask);
}
void QToolAlign::pickCallback(const LLPickInfo& pick_info)
{
LLViewerObject* object = pick_info.getObject();
if (object)
{
if (object->isAvatar())
{
return;
}
if (pick_info.mKeyMask & MASK_SHIFT)
{
// If object not selected, select it
if ( !object->isSelected() )
{
LLSelectMgr::getInstance()->selectObjectAndFamily(object);
}
else
{
LLSelectMgr::getInstance()->deselectObjectAndFamily(object);
}
}
else
{
LLSelectMgr::getInstance()->deselectAll();
LLSelectMgr::getInstance()->selectObjectAndFamily(object);
}
}
else
{
if (!(pick_info.mKeyMask == MASK_SHIFT))
{
LLSelectMgr::getInstance()->deselectAll();
}
}
LLSelectMgr::getInstance()->promoteSelectionToRoot();
}
void QToolAlign::handleSelect()
{
// no parts, please
//llwarns << "in select" << llendl;
LLSelectMgr::getInstance()->promoteSelectionToRoot();
LLSelectMgr::getInstance()->updateSelectionCenter();
gFloaterTools->setStatusText("align");
}
void QToolAlign::handleDeselect()
{
}
BOOL QToolAlign::findSelectedManipulator(S32 x, S32 y)
{
mHighlightedAxis = -1;
mHighlightedDirection = 0;
LLMatrix4 transform;
if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
{
LLVector4 translation(mBBox.getCenterAgent());
transform.initRotTrans(mBBox.getRotation(), translation);
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
transform *= cfr;
LLMatrix4 window_scale;
F32 zoom_level = 2.f * gAgent.mHUDCurZoom;
window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f),
LLQuaternion::DEFAULT,
LLVector3::zero);
transform *= window_scale;
}
else
{
transform.initAll(LLVector3(1.f, 1.f, 1.f), mBBox.getRotation(), mBBox.getCenterAgent());
LLMatrix4 projection_matrix = LLViewerCamera::getInstance()->getProjection();
LLMatrix4 model_matrix = LLViewerCamera::getInstance()->getModelview();
transform *= model_matrix;
transform *= projection_matrix;
}
F32 half_width = (F32)gViewerWindow->getWindowWidth() / 2.f;
F32 half_height = (F32)gViewerWindow->getWindowHeight() / 2.f;
LLVector2 manip2d;
LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
LLVector2 delta;
LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal();
for (S32 axis = VX; axis <= VZ; axis++)
{
for (F32 direction = -1.0; direction <= 1.0; direction += 2.0)
{
LLVector3 axis_vector = LLVector3(0,0,0);
axis_vector.mV[axis] = direction * bbox_scale.mV[axis] / 2.0;
LLVector4 manipulator_center = LLVector4(axis_vector);
LLVector4 screen_center = manipulator_center * transform;
screen_center /= screen_center.mV[VW];
manip2d.setVec(screen_center.mV[VX] * half_width, screen_center.mV[VY] * half_height);
delta = manip2d - mousePos;
if (delta.magVecSquared() < MANIPULATOR_SELECT_SIZE * MANIPULATOR_SELECT_SIZE)
{
mHighlightedAxis = axis;
mHighlightedDirection = direction;
return TRUE;
}
}
}
return FALSE;
}
BOOL QToolAlign::handleHover(S32 x, S32 y, MASK mask)
{
if (mask & MASK_SHIFT)
{
mForce = FALSE;
}
else
{
mForce = TRUE;
}
gViewerWindow->setCursor(UI_CURSOR_ARROW);
return findSelectedManipulator(x, y);
}
void setup_transforms_bbox(LLBBox bbox)
{
// translate to center
LLVector3 center = bbox.getCenterAgent();
gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);
// rotate
LLQuaternion rotation = bbox.getRotation();
F32 angle_radians, x, y, z;
rotation.getAngleAxis(&angle_radians, &x, &y, &z);
// gGL has no rotate method (despite having translate and scale) presumably because
// its authors smoke crack. so we hack.
gGL.flush();
glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
// scale
LLVector3 scale = bbox.getMaxLocal() - bbox.getMinLocal();
gGL.scalef(scale.mV[VX], scale.mV[VY], scale.mV[VZ]);
}
void render_bbox(LLBBox bbox)
{
glMatrixMode(GL_MODELVIEW);
gGL.pushMatrix();
setup_transforms_bbox(bbox);
gGL.flush();
gBox.render();
gGL.popMatrix();
}
void render_cone_bbox(LLBBox bbox)
{
glMatrixMode(GL_MODELVIEW);
gGL.pushMatrix();
setup_transforms_bbox(bbox);
gGL.flush();
gCone.render(CONE_LOD_HIGHEST);
gGL.popMatrix();
}
// the selection bbox isn't axis aligned, so we must construct one
// should this be cached in the selection manager? yes.
LLBBox get_selection_axis_aligned_bbox()
{
LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
LLVector3 position = selection_bbox.getPositionAgent();
LLBBox axis_aligned_bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3());
axis_aligned_bbox.addPointLocal(LLVector3());
// cycle over the nodes in selection
for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin();
selection_iter != LLSelectMgr::getInstance()->getSelection()->end();
++selection_iter)
{
LLSelectNode *select_node = *selection_iter;
if (select_node)
{
LLViewerObject* object = select_node->getObject();
if (object)
{
axis_aligned_bbox.addBBoxAgent(object->getBoundingBoxAgent());
}
}
}
return axis_aligned_bbox;
}
void QToolAlign::computeManipulatorSize()
{
if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
{
mManipulatorSize = MANIPULATOR_SIZE / (LLViewerCamera::getInstance()->getViewHeightInPixels() *
gAgent.mHUDCurZoom);
}
else
{
F32 distance = dist_vec(gAgent.getCameraPositionAgent(), mBBox.getCenterAgent());
if (distance > 0.001f)
{
// range != zero
F32 fraction_of_fov = MANIPULATOR_SIZE /LLViewerCamera::getInstance()->getViewHeightInPixels();
F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
mManipulatorSize = MANIPULATOR_SIZE * distance * tan(apparent_angle);
}
else
{
// range == zero
mManipulatorSize = MANIPULATOR_SIZE;
}
}
}
LLColor4 manipulator_color[3] = { LLColor4(0.7f, 0.0f, 0.0f, 0.5f),
LLColor4(0.0f, 0.7f, 0.0f, 0.5f),
LLColor4(0.0f, 0.0f, 0.7f, 0.5f) };
void QToolAlign::renderManipulators()
{
computeManipulatorSize();
LLVector3 bbox_center = mBBox.getCenterAgent();
LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal();
for (S32 axis = VX; axis <= VZ; axis++)
for (F32 direction = -1.0; direction <= 1.0; direction += 2.0)
{
F32 size = mManipulatorSize;
LLColor4 color = manipulator_color[axis];
if ((axis == mHighlightedAxis) && (direction == mHighlightedDirection))
{
size *= 2.0;
color *= 1.5;
}
S32 arrows = 1;
if (mForce)
{
arrows = 2;
}
for (S32 i = 0; i < arrows; i++)
{
LLVector3 axis_vector = LLVector3(0,0,0);
axis_vector.mV[axis] = direction * (bbox_scale.mV[axis] / 2.0 + i * (size/3.0));
LLVector3 manipulator_center = bbox_center + axis_vector;
LLQuaternion manipulator_rotation;
manipulator_rotation.shortestArc(LLVector3(0,0,1), -1.0 * axis_vector);
LLBBox manipulator_bbox = LLBBox(manipulator_center, manipulator_rotation,
LLVector3(), LLVector3());
manipulator_bbox.addPointLocal(LLVector3(-1, -1, -0.75) * size * 0.5);
manipulator_bbox.addPointLocal(LLVector3(1, 1, 0.75) * size * 0.5);
gGL.color4fv(color.mV);
// sadly, gCone doesn't use gGL like gBox does (presumably because its author smokes crack) so we
// also set the raw GL color. hopefully this won't screw-up later rendering.
glColor4fv(color.mV);
render_cone_bbox(manipulator_bbox);
}
}
}
void QToolAlign::render()
{
mBBox = get_selection_axis_aligned_bbox();
// Draw bounding box
LLGLSUIDefault gls_ui;
LLGLEnable gl_blend(GL_BLEND);
LLGLEnable gls_alpha_test(GL_ALPHA_TEST);
LLGLDepthTest gls_depth(GL_FALSE);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// render box
LLColor4 default_normal_color( 0.7f, 0.7f, 0.7f, 0.1f );
gGL.color4fv( default_normal_color.mV );
render_bbox(mBBox);
renderManipulators();
}
// only works for our specialized (AABB, position centered) bboxes
BOOL bbox_overlap(LLBBox bbox1, LLBBox bbox2)
{
const F32 FUDGE = 0.001f; // because of stupid SL precision/rounding
LLVector3 delta = bbox1.getCenterAgent() - bbox2.getCenterAgent();
LLVector3 half_extent = (bbox1.getExtentLocal() + bbox2.getExtentLocal()) / 2.0;
return ((fabs(delta.mV[VX]) < half_extent.mV[VX] - FUDGE) &&
(fabs(delta.mV[VY]) < half_extent.mV[VY] - FUDGE) &&
(fabs(delta.mV[VZ]) < half_extent.mV[VZ] - FUDGE));
}
// used to sort bboxes before packing
class BBoxCompare
{
public:
BBoxCompare(S32 axis, F32 direction, std::map<LLPointer<LLViewerObject>, LLBBox >& bboxes) :
mAxis(axis), mDirection(direction), mBBoxes(bboxes) {}
BOOL operator() (LLViewerObject* object1, LLViewerObject* object2)
{
LLVector3 corner1 = mBBoxes[object1].getCenterAgent() -
mDirection * mBBoxes[object1].getExtentLocal()/2.0;
LLVector3 corner2 = mBBoxes[object2].getCenterAgent() -
mDirection * mBBoxes[object2].getExtentLocal()/2.0;
return mDirection * corner1.mV[mAxis] < mDirection * corner2.mV[mAxis];
}
S32 mAxis;
F32 mDirection;
std::map<LLPointer<LLViewerObject>, LLBBox >& mBBoxes;
};
void QToolAlign::align()
{
// no linkset parts, please
LLSelectMgr::getInstance()->promoteSelectionToRoot();
std::vector<LLPointer<LLViewerObject> > objects;
std::map<LLPointer<LLViewerObject>, LLBBox > original_bboxes;
// cycle over the nodes in selection and collect them into an array
for (LLObjectSelection::root_iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
selection_iter != LLSelectMgr::getInstance()->getSelection()->root_end();
++selection_iter)
{
LLSelectNode *select_node = *selection_iter;
if (select_node)
{
LLViewerObject* object = select_node->getObject();
if (object)
{
LLVector3 position = object->getPositionAgent();
LLBBox bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3());
bbox.addPointLocal(LLVector3());
// add the parent's bbox
bbox.addBBoxAgent(object->getBoundingBoxAgent());
LLViewerObject::const_child_list_t& children = object->getChildren();
for (LLViewerObject::const_child_list_t::const_iterator i = children.begin();
i != children.end(); i++)
{
// add the child's bbox
LLViewerObject* child = *i;
bbox.addBBoxAgent(child->getBoundingBoxAgent());
}
objects.push_back(object);
original_bboxes[object] = bbox;
}
}
}
S32 axis = mHighlightedAxis;
F32 direction = mHighlightedDirection;
// sort them into positional order for proper packing
BBoxCompare compare(axis, direction, original_bboxes);
sort(objects.begin(), objects.end(), compare);
// storage for their new position after alignment - start with original position first
std::map<LLPointer<LLViewerObject>, LLBBox > new_bboxes = original_bboxes;
// find new positions
for (S32 i = 0; i < (S32)objects.size(); i++)
{
LLBBox target_bbox = mBBox;
LLVector3 target_corner = target_bbox.getCenterAgent() -
direction * target_bbox.getExtentLocal() / 2.0;
LLViewerObject* object = objects[i];
LLBBox this_bbox = original_bboxes[object];
LLVector3 this_corner = this_bbox.getCenterAgent() -
direction * this_bbox.getExtentLocal() / 2.0;
// for packing, we cycle over several possible positions, taking the smallest that does not overlap
F32 smallest = direction * 9999999; // 999999 guarenteed not to be the smallest
for (S32 j = 0; j <= i; j++)
{
// how far must it move?
LLVector3 delta = target_corner - this_corner;
// new position moves only on one axis, please
LLVector3 delta_one_axis = LLVector3(0,0,0);
delta_one_axis.mV[axis] = delta.mV[axis];
LLVector3 new_position = this_bbox.getCenterAgent() + delta_one_axis;
// construct the new bbox
LLBBox new_bbox = LLBBox(new_position, LLQuaternion(), LLVector3(), LLVector3());
new_bbox.addPointLocal(this_bbox.getExtentLocal() / 2.0);
new_bbox.addPointLocal(-1.0 * this_bbox.getExtentLocal() / 2.0);
// check to see if it overlaps the previously placed objects
BOOL overlap = FALSE;
llwarns << "i=" << i << " j=" << j << llendl;
if (!mForce) // well, don't check if in force mode
{
for (S32 k = 0; k < i; k++)
{
LLViewerObject* other_object = objects[k];
LLBBox other_bbox = new_bboxes[other_object];
BOOL overlaps_this = bbox_overlap(other_bbox, new_bbox);
if (overlaps_this)
{
llwarns << "overlap" << new_bbox.getCenterAgent() << other_bbox.getCenterAgent() << llendl;
llwarns << "extent" << new_bbox.getExtentLocal() << other_bbox.getExtentLocal() << llendl;
}
overlap = (overlap || overlaps_this);
}
}
if (!overlap)
{
F32 this_value = (new_bbox.getCenterAgent() -
direction * new_bbox.getExtentLocal() / 2.0).mV[axis];
if (direction * this_value < direction * smallest)
{
smallest = this_value;
// store it
new_bboxes[object] = new_bbox;
}
}
// update target for next time through the loop
if (j < (S32)objects.size())
{
LLBBox next_bbox = new_bboxes[objects[j]];
target_corner = next_bbox.getCenterAgent() +
direction * next_bbox.getExtentLocal() / 2.0;
}
}
}
// now move them
for (S32 i = 0; i < (S32)objects.size(); i++)
{
LLViewerObject* object = objects[i];
LLBBox original_bbox = original_bboxes[object];
LLBBox new_bbox = new_bboxes[object];
LLVector3 delta = new_bbox.getCenterAgent() - original_bbox.getCenterAgent();
LLVector3 original_position = object->getPositionAgent();
LLVector3 new_position = original_position + delta;
object->setPosition(new_position);
}
LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
}

View File

@@ -0,0 +1,49 @@
/**
* @file qtoolalign.h
* @brief A tool to align objects
*/
#ifndef Q_QTOOLALIGN_H
#define Q_QTOOLALIGN_H
#include "lltool.h"
#include "llbbox.h"
#include "lltoolcomp.h"
class LLViewerObject;
class LLPickInfo;
class LLToolSelectRect;
class QToolAlign
: public LLToolComposite, public LLSingleton<QToolAlign>
{
public:
QToolAlign();
virtual ~QToolAlign();
virtual void handleSelect();
virtual void handleDeselect();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual void render();
virtual LLTool* getOverrideTool(MASK mask);
static void pickCallback(const LLPickInfo& pick_info);
private:
void align();
void computeManipulatorSize();
void renderManipulators();
BOOL findSelectedManipulator(S32 x, S32 y);
LLBBox mBBox;
F32 mManipulatorSize;
S32 mHighlightedAxis;
F32 mHighlightedDirection;
BOOL mForce;
};
#endif // Q_QTOOLALIGN_H

View File

@@ -73,12 +73,15 @@
<check_box bottom_delta="-15" follows="left|top" font="SansSerifSmall" height="16"
initial_value="false" label="Select Texture" left="4" mouse_opaque="true"
name="radio select face" radio_style="true" width="114" />
<check_box bottom_delta="-19" control_name="EditLinkedParts" follows="left|top"
<check_box bottom_delta="-15" follows="left|top" font="SansSerifSmall" height="16"
initial_value="false" label="Align (Ctrl-A)" left="4" mouse_opaque="true"
name="radio align" radio_style="true" width="114" />
<check_box bottom_delta="-15" control_name="EditLinkedParts" follows="left|top"
font="SansSerifSmall" height="16" initial_value="false"
label="Edit linked parts" left="4" mouse_opaque="true"
name="checkbox edit linked parts" width="114" />
<text bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
bottom_delta="-20" drop_shadow_visible="true" follows="left|top"
bottom_delta="-17" drop_shadow_visible="true" follows="left|top"
font="SansSerifSmall" h_pad="0" halign="left" height="14" left="6"
mouse_opaque="true" name="text ruler mode" v_pad="0" width="68">
Ruler:
@@ -1388,6 +1391,9 @@
<string name="status_move">
Drag to move, shift-drag to copy
</string>
<string name="status_align">
Click an arrow to align objects in that direction
</string>
<string name="status_modifyland">
Click and hold to modify land
</string>