aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llmaniptranslate.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llmaniptranslate.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llmaniptranslate.cpp')
-rw-r--r--linden/indra/newview/llmaniptranslate.cpp2145
1 files changed, 2145 insertions, 0 deletions
diff --git a/linden/indra/newview/llmaniptranslate.cpp b/linden/indra/newview/llmaniptranslate.cpp
new file mode 100644
index 0000000..fea6092
--- /dev/null
+++ b/linden/indra/newview/llmaniptranslate.cpp
@@ -0,0 +1,2145 @@
1/**
2 * @file llmaniptranslate.cpp
3 * @brief LLManipTranslate class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28/**
29 * Positioning tool
30 */
31
32#include "llviewerprecompiledheaders.h"
33
34#include "llmaniptranslate.h"
35
36#include "llgl.h"
37
38#include "llagent.h"
39#include "llbbox.h"
40#include "llbox.h"
41#include "llviewercontrol.h"
42#include "llcriticaldamp.h"
43#include "llcylinder.h"
44#include "lldrawable.h"
45#include "llfloatertools.h"
46#include "llfontgl.h"
47#include "llglheaders.h"
48#include "llhudrender.h"
49#include "llresmgr.h"
50#include "llselectmgr.h"
51#include "llsphere.h"
52#include "llstatusbar.h"
53#include "lltoolmgr.h"
54#include "llviewercamera.h"
55#include "llviewerjoint.h"
56#include "llviewerobject.h"
57#include "llviewerwindow.h"
58#include "llvoavatar.h"
59#include "llworld.h"
60#include "viewer.h"
61#include "llui.h"
62
63const S32 NUM_AXES = 3;
64const S32 MOUSE_DRAG_SLOP = 2; // pixels
65const F32 HANDLE_HIDE_ANGLE = 0.15f; // radians
66const F32 SELECTED_ARROW_SCALE = 1.3f;
67const F32 MANIPULATOR_HOTSPOT_START = 0.2f;
68const F32 MANIPULATOR_HOTSPOT_END = 1.2f;
69const F32 SNAP_GUIDE_SCREEN_SIZE = 0.7f;
70const F32 MIN_PLANE_MANIP_DOT_PRODUCT = 0.25f;
71const F32 PLANE_TICK_SIZE = 0.4f;
72const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
73const F32 SNAP_ARROW_SCALE = 0.7f;
74
75static GLuint sGridTex = 0;
76
77const LLManip::EManipPart MANIPULATOR_IDS[9] =
78{
79 LLManip::LL_X_ARROW,
80 LLManip::LL_Y_ARROW,
81 LLManip::LL_Z_ARROW,
82 LLManip::LL_X_ARROW,
83 LLManip::LL_Y_ARROW,
84 LLManip::LL_Z_ARROW,
85 LLManip::LL_YZ_PLANE,
86 LLManip::LL_XZ_PLANE,
87 LLManip::LL_XY_PLANE
88};
89
90const U32 ARROW_TO_AXIS[4] =
91{
92 VX,
93 VX,
94 VY,
95 VZ
96};
97
98BOOL sort_manip_by_end_z(LLManipTranslate::ManipulatorHandle *new_manip, LLManipTranslate::ManipulatorHandle *test_manip)
99{
100 return (new_manip->mEndPosition.mV[VZ] < test_manip->mEndPosition.mV[VZ]);
101}
102
103LLManipTranslate::LLManipTranslate( LLToolComposite* composite )
104: LLManip( "Move", composite ),
105 mLastHoverMouseX(-1),
106 mLastHoverMouseY(-1),
107 mSendUpdateOnMouseUp(FALSE),
108 mMouseOutsideSlop(FALSE),
109 mCopyMadeThisDrag(FALSE),
110 mMouseDownX(-1),
111 mMouseDownY(-1),
112 mAxisArrowLength(50),
113 mConeSize(0),
114 mArrowLengthMeters(0.f),
115 mPlaneManipOffsetMeters(0.f),
116 mManipPart(LL_NO_PART),
117 mUpdateTimer(),
118 mSnapOffsetMeters(0.f),
119 mArrowScales(1.f, 1.f, 1.f),
120 mPlaneScales(1.f, 1.f, 1.f),
121 mPlaneManipPositions(1.f, 1.f, 1.f, 1.f)
122{
123 mProjectedManipulators.setInsertBefore(sort_manip_by_end_z);
124
125 if (sGridTex == 0)
126 {
127 restoreGL();
128 }
129}
130
131//static
132void LLManipTranslate::restoreGL()
133{
134 //generate grid texture
135 U32 rez = 512;
136 U32 mip = 0;
137
138 GLuint* d = new GLuint[rez*rez];
139 LLGLEnable tex2d(GL_TEXTURE_2D);
140 glGenTextures(1, &sGridTex);
141 glBindTexture(GL_TEXTURE_2D, sGridTex);
142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
144
145 while (rez >= 1)
146 {
147 for (U32 i = 0; i < rez*rez; i++)
148 {
149 d[i] = 0x00FFFFFF;
150 }
151
152 U32 subcol = 0xFFFFFFFF;
153 if (rez >= 4)
154 { //large grain grid
155 for (U32 i = 0; i < rez; i++)
156 {
157 if (rez <= 16)
158 {
159 if (rez == 16)
160 {
161 subcol = 0xA0FFFFFF;
162 }
163 else if (rez == 8)
164 {
165 subcol = 0x80FFFFFF;
166 }
167 else
168 {
169 subcol = 0x40FFFFFF;
170 }
171 }
172 else
173 {
174 subcol = 0xFFFFFFFF;
175 }
176 d[i *rez+ 0 ] = subcol;
177 d[0 *rez+ i ] = subcol;
178 if (rez >= 32)
179 {
180 d[i *rez+ (rez-1)] = subcol;
181 d[(rez-1) *rez+ i ] = subcol;
182 }
183
184 if (rez >= 64)
185 {
186 subcol = 0xFFFFFFFF;
187
188 if (i > 0 && i < (rez-1))
189 {
190 d[i *rez+ 1 ] = subcol;
191 d[i *rez+ (rez-2)] = subcol;
192 d[1 *rez+ i ] = subcol;
193 d[(rez-2) *rez+ i ] = subcol;
194 }
195 }
196 }
197 }
198
199 subcol = 0x50A0A0A0;
200 if (rez >= 128)
201 { //small grain grid
202 for (U32 i = 8; i < rez; i+=8)
203 {
204 for (U32 j = 2; j < rez-2; j++)
205 {
206 d[i *rez+ j] = subcol;
207 d[j *rez+ i] = subcol;
208 }
209 }
210 }
211 if (rez >= 64)
212 { //medium grain grid
213 if (rez == 64)
214 {
215 subcol = 0x50A0A0A0;
216 }
217 else
218 {
219 subcol = 0xA0D0D0D0;
220 }
221
222 for (U32 i = 32; i < rez; i+=32)
223 {
224 U32 pi = i-1;
225 for (U32 j = 2; j < rez-2; j++)
226 {
227 d[i *rez+ j] = subcol;
228 d[j *rez+ i] = subcol;
229
230 if (rez > 128)
231 {
232 d[pi *rez+ j] = subcol;
233 d[j *rez+ pi] = subcol;
234 }
235 }
236 }
237 }
238#ifdef LL_WINDOWS
239 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_BYTE, d);
240#else
241 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d);
242#endif
243 rez = rez >> 1;
244 mip++;
245 }
246 delete [] d;
247}
248
249
250LLManipTranslate::~LLManipTranslate()
251{
252 mProjectedManipulators.deleteAllData();
253}
254
255
256void LLManipTranslate::handleSelect()
257{
258 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
259 gFloaterTools->setStatusText("Drag to move, shift-drag to copy");
260}
261
262void LLManipTranslate::handleDeselect()
263{
264 mHighlightedPart = LL_NO_PART;
265 mManipPart = LL_NO_PART;
266 gFloaterTools->setStatusText("");
267}
268
269BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
270{
271 BOOL handled = FALSE;
272
273 // didn't click in any UI object, so must have clicked in the world
274 LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
275 if( hit_obj &&
276 (mHighlightedPart == LL_X_ARROW ||
277 mHighlightedPart == LL_Y_ARROW ||
278 mHighlightedPart == LL_Z_ARROW ||
279 mHighlightedPart == LL_YZ_PLANE ||
280 mHighlightedPart == LL_XZ_PLANE ||
281 mHighlightedPart == LL_XY_PLANE ) )
282 {
283 handled = handleMouseDownOnPart( x, y, mask );
284 }
285
286 return handled;
287}
288
289// Assumes that one of the arrows on an object was hit.
290BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
291{
292 BOOL can_move = gSelectMgr->getObjectCount() != 0;
293 for (LLViewerObject* objectp = gSelectMgr->getFirstObject();
294 objectp;
295 objectp = gSelectMgr->getNextObject())
296 {
297 can_move = can_move && objectp->permMove() && (objectp->permModify() || gSavedSettings.getBOOL("SelectLinkedSet"));
298 }
299
300 if (!can_move)
301 {
302 return FALSE;
303 }
304
305 highlightManipulators(x, y);
306 S32 hit_part = mHighlightedPart;
307
308 if( (hit_part != LL_X_ARROW) &&
309 (hit_part != LL_Y_ARROW) &&
310 (hit_part != LL_Z_ARROW) &&
311 (hit_part != LL_YZ_PLANE) &&
312 (hit_part != LL_XZ_PLANE) &&
313 (hit_part != LL_XY_PLANE) )
314 {
315 return TRUE;
316 }
317
318 mHelpTextTimer.reset();
319 sNumTimesHelpTextShown++;
320
321 gSelectMgr->getGrid(mGridOrigin, mGridRotation, mGridScale);
322
323 gSelectMgr->enableSilhouette(FALSE);
324
325 // we just started a drag, so save initial object positions
326 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE);
327
328 mManipPart = (EManipPart)hit_part;
329 mMouseDownX = x;
330 mMouseDownY = y;
331 mMouseOutsideSlop = FALSE;
332
333 LLVector3 axis;
334
335 LLSelectNode *selectNode = gSelectMgr->getFirstMoveableNode(TRUE);
336
337 if (!selectNode)
338 {
339 // didn't find the object in our selection...oh well
340 llwarns << "Trying to translate an unselected object" << llendl;
341 return TRUE;
342 }
343
344 LLViewerObject *selected_object = selectNode->getObject();
345 if (!selected_object)
346 {
347 // somehow we lost the object!
348 llwarns << "Translate manip lost the object" << llendl;
349 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
350 return TRUE;
351 }
352
353 // Compute unit vectors for arrow hit and a plane through that vector
354 BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis);
355 getManipNormal(selected_object, mManipPart, mManipNormal);
356
357 //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(gSelectMgr->getSelectionCenterGlobal());
358 // TomY: The above should (?) be identical to the below
359 LLVector3 select_center_agent = getPivotPoint();
360 mSubdivisions = llclamp(getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
361
362 // if we clicked on a planar manipulator, recenter mouse cursor
363 if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE)
364 {
365 LLCoordGL mouse_pos;
366 gCamera->projectPosAgentToScreen(select_center_agent, mouse_pos);
367
368 if (gSavedSettings.getBOOL("SnapToMouseCursor"))
369 {
370 LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY);
371 x = mouse_pos.mX;
372 y = mouse_pos.mY;
373 }
374 }
375
376 gSelectMgr->updateSelectionCenter();
377 LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint());
378 getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal);
379 mDragSelectionStartGlobal = object_start_global;
380 mCopyMadeThisDrag = FALSE;
381
382 // Route future Mouse messages here preemptively. (Release on mouse up.)
383 setMouseCapture( TRUE );
384
385 return TRUE;
386}
387
388BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
389{
390 // Translation tool only works if mouse button is down.
391 // Bail out if mouse not down.
392 if( !hasMouseCapture() )
393 {
394 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (inactive)" << llendl;
395 // Always show cursor
396 // gViewerWindow->setCursor(UI_CURSOR_ARROW);
397 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
398
399 highlightManipulators(x, y);
400 return TRUE;
401 }
402
403 // Handle auto-rotation if necessary.
404 const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
405 const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20;
406 const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
407 BOOL rotated = FALSE;
408
409 // ...build mode moves camera about focus point
410 if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
411 {
412 if (x < ROTATE_H_MARGIN)
413 {
414 gAgent.cameraOrbitAround(rotate_angle);
415 rotated = TRUE;
416 }
417 else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
418 {
419 gAgent.cameraOrbitAround(-rotate_angle);
420 rotated = TRUE;
421 }
422 }
423
424 // Suppress processing if mouse hasn't actually moved.
425 // This may cause problems if the camera moves outside of the
426 // rotation above.
427 if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated)
428 {
429 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (mouse unmoved)" << llendl;
430 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
431 return TRUE;
432 }
433 mLastHoverMouseX = x;
434 mLastHoverMouseY = y;
435
436 // Suppress if mouse hasn't moved past the initial slop region
437 // Reset once we start moving
438 if( !mMouseOutsideSlop )
439 {
440 if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP )
441 {
442 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (mouse inside slop)" << llendl;
443 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
444 return TRUE;
445 }
446 else
447 {
448 // ...just went outside the slop region
449 mMouseOutsideSlop = TRUE;
450 // If holding down shift, leave behind a copy.
451 if (mask == MASK_COPY)
452 {
453 // ...we're trying to make a copy
454 gSelectMgr->selectDuplicate(LLVector3::zero, FALSE);
455 mCopyMadeThisDrag = TRUE;
456
457 // When we make the copy, we don't want to do any other processing.
458 // If so, the object will also be moved, and the copy will be offset.
459 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (made copy)" << llendl;
460 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
461 }
462 }
463 }
464
465 // Throttle updates to 10 per second.
466 BOOL send_update = FALSE;
467
468 LLVector3 axis_f;
469 LLVector3d axis_d;
470 LLViewerObject *object;
471
472 // pick the first object to constrain to grid w/ common origin
473 // this is so we don't screw up groups
474 LLSelectNode* selectNode = gSelectMgr->getFirstMoveableNode(TRUE);
475 if (!selectNode)
476 {
477 // somehow we lost the object!
478 llwarns << "Translate manip lost the object" << llendl;
479 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
480 return TRUE;
481 }
482
483 object = selectNode->getObject();
484 if (!object)
485 {
486 // somehow we lost the object!
487 llwarns << "Translate manip lost the object" << llendl;
488 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
489 return TRUE;
490 }
491
492 // Compute unit vectors for arrow hit and a plane through that vector
493 BOOL axis_exists = getManipAxis(object, mManipPart, axis_f); // TODO: move this
494
495 axis_d.setVec(axis_f);
496
497 gSelectMgr->updateSelectionCenter();
498 LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint());
499
500 mSubdivisions = llclamp(getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
501
502 // Project the cursor onto that plane
503 LLVector3d relative_move;
504 getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\
505 relative_move -= mDragCursorStartGlobal;
506
507 // You can't move more than some distance from your original mousedown point.
508 if (gSavedSettings.getBOOL("LimitDragDistance"))
509 {
510 F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance");
511
512 if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance)
513 {
514 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (too far)" << llendl;
515 gViewerWindow->setCursor(UI_CURSOR_NOLOCKED);
516 return TRUE;
517 }
518 }
519
520 F64 axis_magnitude = relative_move * axis_d; // dot product
521 LLVector3d cursor_point_snap_line;
522
523 F64 off_axis_magnitude;
524
525 getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f);
526 off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f;
527
528 if (gSavedSettings.getBOOL("SnapEnabled"))
529 {
530 if (off_axis_magnitude > mSnapOffsetMeters)
531 {
532 mInSnapRegime = TRUE;
533 LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal);
534 LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line);
535 if (!gSavedSettings.getBOOL("SnapToMouseCursor"))
536 {
537 cursor_snap_agent -= mouse_down_offset;
538 }
539
540 F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f;
541
542 F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions);
543 F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions);
544 if (relative_snap_dist < snap_dist * 2.f)
545 {
546 if (cursor_grid_dist > 0.f)
547 {
548 cursor_grid_dist -= relative_snap_dist - snap_dist;
549 }
550 else
551 {
552 cursor_grid_dist += relative_snap_dist - snap_dist;
553 }
554 }
555
556 F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f;
557 axis_magnitude = cursor_grid_dist - object_start_on_axis;
558 }
559 else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE)
560 {
561 // subtract offset from object center
562 LLVector3d cursor_point_global;
563 getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal );
564 cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal);
565
566 // snap to planar grid
567 LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global);
568 LLVector3 camera_plane_projection = gCamera->getAtAxis();
569 camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal);
570 camera_plane_projection.normVec();
571 LLVector3 camera_projected_dir = camera_plane_projection;
572 camera_plane_projection.rotVec(~mGridRotation);
573 camera_plane_projection.scaleVec(mGridScale);
574 camera_plane_projection.abs();
575 F32 max_grid_scale;
576 if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] &&
577 camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ])
578 {
579 max_grid_scale = mGridScale.mV[VX];
580 }
581 else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ])
582 {
583 max_grid_scale = mGridScale.mV[VY];
584 }
585 else
586 {
587 max_grid_scale = mGridScale.mV[VZ];
588 }
589
590 F32 num_subdivisions = llclamp(getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
591
592 F32 grid_scale_a;
593 F32 grid_scale_b;
594 LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation;
595
596 switch (mManipPart)
597 {
598 case LL_YZ_PLANE:
599 grid_scale_a = mGridScale.mV[VY] / num_subdivisions;
600 grid_scale_b = mGridScale.mV[VZ] / num_subdivisions;
601 cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
602 cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
603 break;
604 case LL_XZ_PLANE:
605 grid_scale_a = mGridScale.mV[VX] / num_subdivisions;
606 grid_scale_b = mGridScale.mV[VZ] / num_subdivisions;
607 cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
608 cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
609 break;
610 case LL_XY_PLANE:
611 grid_scale_a = mGridScale.mV[VX] / num_subdivisions;
612 grid_scale_b = mGridScale.mV[VY] / num_subdivisions;
613 cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f;
614 cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f;
615 break;
616 default:
617 break;
618 }
619 cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin;
620 relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal));
621 mInSnapRegime = TRUE;
622 }
623 else
624 {
625 mInSnapRegime = FALSE;
626 }
627 }
628 else
629 {
630 mInSnapRegime = FALSE;
631 }
632
633 // Clamp to arrow direction
634 // *FIX: does this apply anymore?
635 if (!axis_exists)
636 {
637 axis_magnitude = relative_move.normVec();
638 axis_d.setVec(relative_move);
639 axis_d.normVec();
640 axis_f.setVec(axis_d);
641 }
642
643 LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply
644 LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply
645
646 for(selectNode = gSelectMgr->getFirstNode();
647 selectNode;
648 selectNode = gSelectMgr->getNextNode() )
649 {
650 object = selectNode->getObject();
651
652 // Only apply motion to root objects and objects selected
653 // as "individual".
654 if (!object->isRootEdit() && !selectNode->mIndividualSelection)
655 {
656 continue;
657 }
658
659 if (!object->isRootEdit())
660 {
661 // child objects should not update if parent is selected
662 LLViewerObject* editable_root = (LLViewerObject*)object->getParent();
663 if (editable_root->isSelected())
664 {
665 // we will be moved properly by our parent, so skip
666 continue;
667 }
668 }
669
670 if (object->permMove())
671 {
672 // handle attachments in local space
673 if (object->isAttachment() && object->mDrawable.notNull())
674 {
675 // calculate local version of relative move
676 LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation();
677 objWorldRotation.transQuat();
678
679 LLVector3 old_position_local = object->getPosition();
680 LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation);
681
682 // move and clamp root object first, before adjusting children
683 if (new_position_local != old_position_local)
684 {
685 send_update = TRUE;
686 }
687 //RN: I forget, but we need to do this because of snapping which doesn't often result
688 // in position changes even when the mouse moves
689 object->setPosition(new_position_local);
690 rebuild(object);
691 gAgent.getAvatarObject()->clampAttachmentPositions();
692 new_position_local = object->getPosition();
693
694 if (selectNode->mIndividualSelection)
695 {
696 send_update = FALSE;
697 LLVector3 child_offset = (old_position_local - new_position_local) * ~object->getRotation();
698
699 // counter-translate child objects if we are moving the root as an individual
700 for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++)
701 {
702 LLViewerObject* childp = object->mChildList[child_num];
703
704 if (!childp->isSelected())
705 {
706 childp->setPosition(childp->getPosition() + child_offset);
707 rebuild(childp);
708 }
709 }
710 }
711 }
712 else
713 {
714 // compute new position to send to simulators, but don't set it yet.
715 // We need the old position to know which simulator to send the move message to.
716 LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move;
717
718 // Don't let object centers go too far underground
719 F64 min_height = gWorldp->getMinAllowedZ(object);
720 if (new_position_global.mdV[VZ] < min_height)
721 {
722 new_position_global.mdV[VZ] = min_height;
723 }
724
725 // For safety, cap heights where objects can be dragged
726 if (new_position_global.mdV[VZ] > MAX_OBJECT_Z)
727 {
728 new_position_global.mdV[VZ] = MAX_OBJECT_Z;
729 }
730
731 // Grass is always drawn on the ground, so clamp its position to the ground
732 if (object->getPCode() == LL_PCODE_LEGACY_GRASS)
733 {
734 new_position_global.mdV[VZ] = gWorldp->resolveLandHeightGlobal(new_position_global) + 1.f;
735 }
736
737 if (object->isRootEdit())
738 {
739 new_position_global = gWorldp->clipToVisibleRegions(object->getPositionGlobal(), new_position_global);
740 }
741
742 // PR: Only update if changed
743 LLVector3d old_position_global = object->getPositionGlobal();
744 LLVector3 old_position_agent = object->getPositionAgent();
745 LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global);
746 if (object->isRootEdit())
747 {
748 // finally, move parent object after children have calculated new offsets
749 object->setPositionAgent(new_position_agent);
750 rebuild(object);
751 }
752 else
753 {
754 LLViewerObject* root_object = object->getRootEdit();
755 new_position_agent -= root_object->getPositionAgent();
756 new_position_agent = new_position_agent * ~root_object->getRotation();
757 object->setPositionParent(new_position_agent, FALSE);
758 rebuild(object);
759 }
760
761 if (selectNode->mIndividualSelection)
762 {
763 LLVector3 parent_offset = (new_position_agent - old_position_agent) * ~object->getRotation();
764
765 // counter-translate child objects if we are moving the root as an individual
766 for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++)
767 {
768 LLViewerObject* childp = object->mChildList[child_num];
769 if (!childp->isSelected())
770 {
771 childp->setPosition(childp->getPosition() - parent_offset);
772 rebuild(childp);
773 }
774 }
775 send_update = FALSE;
776 }
777 else if (old_position_global != new_position_global)
778 {
779 send_update = TRUE;
780 }
781 }
782 }
783 }
784
785 // Handle throttling to 10 updates per second.
786 F32 elapsed_time = mUpdateTimer.getElapsedTimeF32();
787 const F32 UPDATE_DELAY = 0.1f; // min time between transmitted updates
788 if (send_update && (elapsed_time > UPDATE_DELAY))
789 {
790 gSelectMgr->sendMultipleUpdate(UPD_POSITION);
791 mUpdateTimer.reset();
792 mSendUpdateOnMouseUp = FALSE;
793 }
794 else
795 {
796 // ...suppressed update
797 mSendUpdateOnMouseUp = TRUE;
798 }
799
800 gSelectMgr->updateSelectionCenter();
801 gAgent.clearFocusObject();
802 //gAgent.setObjectTracking(FALSE);
803 dialog_refresh_all(); // ??? is this necessary?
804
805 lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (active)" << llendl;
806 gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE);
807 return TRUE;
808}
809
810void LLManipTranslate::highlightManipulators(S32 x, S32 y)
811{
812 mHighlightedPart = LL_NO_PART;
813
814 if (!gSelectMgr->getObjectCount())
815 {
816 return;
817 }
818
819 //LLBBox bbox = gSelectMgr->getBBoxOfSelection();
820 LLMatrix4 projMatrix = gCamera->getProjection();
821 LLMatrix4 modelView = gCamera->getModelview();
822
823 LLVector3 object_position = getPivotPoint();
824
825 LLVector3 grid_origin;
826 LLVector3 grid_scale;
827 LLQuaternion grid_rotation;
828
829 gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
830
831 LLVector3 relative_camera_dir;
832
833 LLMatrix4 transform;
834
835 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
836 {
837 relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation;
838 LLVector4 translation(object_position);
839 transform.initRotTrans(grid_rotation, translation);
840 LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
841 transform *= cfr;
842 LLMatrix4 window_scale;
843 F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom;
844 window_scale.initAll(LLVector3(zoom_level / gCamera->getAspect(), zoom_level, 0.f),
845 LLQuaternion::DEFAULT,
846 LLVector3::zero);
847 transform *= window_scale;
848 }
849 else
850 {
851 relative_camera_dir = (object_position - gCamera->getOrigin()) * ~grid_rotation;
852 relative_camera_dir.normVec();
853
854 transform.initRotTrans(grid_rotation, LLVector4(object_position));
855 transform *= modelView;
856 transform *= projMatrix;
857 }
858
859 mProjectedManipulators.deleteAllData();
860
861 S32 numManips = 0;
862
863 // edges
864 mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f);
865 mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f);
866
867 mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f);
868 mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f);
869
870 mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f);
871 mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f);
872
873 mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f);
874 mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f);
875
876 mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f);
877 mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f);
878
879 mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f);
880 mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f);
881
882 S32 num_arrow_manips = numManips;
883
884 // planar manipulators
885 BOOL planar_manip_yz_visible = FALSE;
886 BOOL planar_manip_xz_visible = FALSE;
887 BOOL planar_manip_xy_visible = FALSE;
888
889 mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f);
890 mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
891 mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f);
892 mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
893 if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT)
894 {
895 planar_manip_yz_visible = TRUE;
896 }
897
898 mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f);
899 mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
900 mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f);
901 mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
902 if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT)
903 {
904 planar_manip_xz_visible = TRUE;
905 }
906
907 mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f);
908 mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
909 mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f);
910 mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions);
911 if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT)
912 {
913 planar_manip_xy_visible = TRUE;
914 }
915
916 for (S32 i = 0; i < num_arrow_manips; i+= 2)
917 {
918 LLVector4 projected_start = mManipulatorVertices[i] * transform;
919 projected_start = projected_start * (1.f / projected_start.mV[VW]);
920
921 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
922 projected_end = projected_end * (1.f / projected_end.mV[VW]);
923
924 ManipulatorHandle* projManipulator =
925 new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
926 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
927 MANIPULATOR_IDS[i / 2],
928 10.f); // 10 pixel hotspot for arrows
929 mProjectedManipulators.addDataSorted(projManipulator);
930 }
931
932 if (planar_manip_yz_visible)
933 {
934 S32 i = num_arrow_manips;
935 LLVector4 projected_start = mManipulatorVertices[i] * transform;
936 projected_start = projected_start * (1.f / projected_start.mV[VW]);
937
938 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
939 projected_end = projected_end * (1.f / projected_end.mV[VW]);
940
941 ManipulatorHandle* projManipulator =
942 new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
943 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
944 MANIPULATOR_IDS[i / 2],
945 20.f); // 20 pixels for planar manipulators
946 mProjectedManipulators.addDataSorted(projManipulator);
947 }
948
949 if (planar_manip_xz_visible)
950 {
951 S32 i = num_arrow_manips + 2;
952 LLVector4 projected_start = mManipulatorVertices[i] * transform;
953 projected_start = projected_start * (1.f / projected_start.mV[VW]);
954
955 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
956 projected_end = projected_end * (1.f / projected_end.mV[VW]);
957
958 ManipulatorHandle* projManipulator =
959 new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
960 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
961 MANIPULATOR_IDS[i / 2],
962 20.f); // 20 pixels for planar manipulators
963 mProjectedManipulators.addDataSorted(projManipulator);
964 }
965
966 if (planar_manip_xy_visible)
967 {
968 S32 i = num_arrow_manips + 4;
969 LLVector4 projected_start = mManipulatorVertices[i] * transform;
970 projected_start = projected_start * (1.f / projected_start.mV[VW]);
971
972 LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
973 projected_end = projected_end * (1.f / projected_end.mV[VW]);
974
975 ManipulatorHandle* projManipulator =
976 new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
977 LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
978 MANIPULATOR_IDS[i / 2],
979 20.f); // 20 pixels for planar manipulators
980 mProjectedManipulators.addDataSorted(projManipulator);
981 }
982
983 LLVector2 manip_start_2d;
984 LLVector2 manip_end_2d;
985 LLVector2 manip_dir;
986 F32 half_width = gViewerWindow->getWindowWidth() / 2.f;
987 F32 half_height = gViewerWindow->getWindowHeight() / 2.f;
988 LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
989 LLVector2 mouse_delta;
990
991 for (ManipulatorHandle* manipulator = mProjectedManipulators.getFirstData();
992 manipulator;
993 manipulator = mProjectedManipulators.getNextData())
994 {
995 manip_start_2d.setVec(manipulator->mStartPosition.mV[VX] * half_width, manipulator->mStartPosition.mV[VY] * half_height);
996 manip_end_2d.setVec(manipulator->mEndPosition.mV[VX] * half_width, manipulator->mEndPosition.mV[VY] * half_height);
997 manip_dir = manip_end_2d - manip_start_2d;
998
999 mouse_delta = mousePos - manip_start_2d;
1000
1001 F32 manip_length = manip_dir.normVec();
1002
1003 F32 mouse_pos_manip = mouse_delta * manip_dir;
1004 F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip);
1005
1006 if (mouse_pos_manip > 0.f &&
1007 mouse_pos_manip < manip_length &&
1008 mouse_dist_manip_squared < manipulator->mHotSpotRadius * manipulator->mHotSpotRadius)
1009 {
1010 mHighlightedPart = manipulator->mManipID;
1011 break;
1012 }
1013 }
1014}
1015
1016F32 LLManipTranslate::getMinGridScale()
1017{
1018 F32 scale;
1019 switch (mManipPart)
1020 {
1021 case LL_NO_PART:
1022 default:
1023 scale = 1.f;
1024 break;
1025 case LL_X_ARROW:
1026 scale = mGridScale.mV[VX];
1027 break;
1028 case LL_Y_ARROW:
1029 scale = mGridScale.mV[VY];
1030 break;
1031 case LL_Z_ARROW:
1032 scale = mGridScale.mV[VZ];
1033 break;
1034 case LL_YZ_PLANE:
1035 scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]);
1036 break;
1037 case LL_XZ_PLANE:
1038 scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]);
1039 break;
1040 case LL_XY_PLANE:
1041 scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]);
1042 break;
1043 }
1044
1045 return scale;
1046}
1047
1048
1049BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask)
1050{
1051 // first, perform normal processing in case this was a quick-click
1052 handleHover(x, y, mask);
1053
1054 // make sure arrow colors go back to normal
1055 mManipPart = LL_NO_PART;
1056 gSelectMgr->enableSilhouette(TRUE);
1057
1058 // Might have missed last update due to UPDATE_DELAY timing.
1059 if (mSendUpdateOnMouseUp)
1060 {
1061 gSelectMgr->sendMultipleUpdate( UPD_POSITION );
1062 mSendUpdateOnMouseUp = FALSE;
1063 }
1064
1065// if (mCopyMadeThisDrag)
1066// {
1067// gSelectMgr->clearGridObjects();
1068// }
1069
1070 mInSnapRegime = FALSE;
1071 gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
1072 //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject"));
1073
1074 return LLManip::handleMouseUp(x, y, mask);
1075}
1076
1077
1078void LLManipTranslate::render()
1079{
1080 glMatrixMode(GL_MODELVIEW);
1081 glPushMatrix();
1082 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
1083 {
1084 F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
1085 glScalef(zoom, zoom, zoom);
1086 }
1087 {
1088 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
1089 renderGuidelines();
1090 }
1091 {
1092 renderTranslationHandles();
1093 renderSnapGuides();
1094 }
1095 glPopMatrix();
1096
1097 renderText();
1098}
1099
1100void LLManipTranslate::renderSnapGuides()
1101{
1102 if (!gSavedSettings.getBOOL("SnapEnabled"))
1103 {
1104 return;
1105 }
1106
1107 F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision");
1108 F32 line_alpha = gSavedSettings.getF32("GridOpacity");
1109
1110 LLGLSNoTexture gls_no_texture;
1111 LLGLDepthTest gls_depth(GL_TRUE);
1112 LLGLDisable gls_cull(GL_CULL_FACE);
1113 LLVector3 translate_axis;
1114
1115 if (mManipPart == LL_NO_PART)
1116 {
1117 return;
1118 }
1119
1120 LLSelectNode *first_node = gSelectMgr->getFirstMoveableNode(TRUE);
1121 if (!first_node)
1122 {
1123 return;
1124 }
1125
1126 updateGridSettings();
1127
1128 F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions;
1129 LLVector3 grid_origin;
1130 LLVector3 grid_scale;
1131 LLQuaternion grid_rotation;
1132
1133 gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
1134 LLVector3 saved_selection_center = getSavedPivotPoint(); //gSelectMgr->getSavedBBoxOfSelection().getCenterAgent();
1135 LLVector3 selection_center = getPivotPoint();
1136
1137 LLViewerObject *first_object = first_node->getObject();
1138
1139 //pick appropriate projection plane for snap rulers according to relative camera position
1140 if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW)
1141 {
1142 getManipAxis(first_object, mManipPart, translate_axis);
1143
1144 LLVector3 at_axis_abs;
1145 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
1146 {
1147 at_axis_abs = LLVector3::x_axis * ~grid_rotation;
1148 }
1149 else
1150 {
1151 at_axis_abs = saved_selection_center - gCamera->getOrigin();
1152 at_axis_abs.normVec();
1153
1154 at_axis_abs = at_axis_abs * ~grid_rotation;
1155 }
1156 at_axis_abs.abs();
1157
1158 if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ])
1159 {
1160 if (mManipPart == LL_Y_ARROW)
1161 {
1162 mSnapOffsetAxis = LLVector3::z_axis;
1163 }
1164 else if (mManipPart == LL_Z_ARROW)
1165 {
1166 mSnapOffsetAxis = LLVector3::y_axis;
1167 }
1168 else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ])
1169 {
1170 mSnapOffsetAxis = LLVector3::z_axis;
1171 }
1172 else
1173 {
1174 mSnapOffsetAxis = LLVector3::y_axis;
1175 }
1176 }
1177 else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ])
1178 {
1179 if (mManipPart == LL_X_ARROW)
1180 {
1181 mSnapOffsetAxis = LLVector3::z_axis;
1182 }
1183 else if (mManipPart == LL_Z_ARROW)
1184 {
1185 mSnapOffsetAxis = LLVector3::x_axis;
1186 }
1187 else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ])
1188 {
1189 mSnapOffsetAxis = LLVector3::z_axis;
1190 }
1191 else
1192 {
1193 mSnapOffsetAxis = LLVector3::x_axis;
1194 }
1195 }
1196 else
1197 {
1198 if (mManipPart == LL_X_ARROW)
1199 {
1200 mSnapOffsetAxis = LLVector3::y_axis;
1201 }
1202 else if (mManipPart == LL_Y_ARROW)
1203 {
1204 mSnapOffsetAxis = LLVector3::x_axis;
1205 }
1206 else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY])
1207 {
1208 mSnapOffsetAxis = LLVector3::y_axis;
1209 }
1210 else
1211 {
1212 mSnapOffsetAxis = LLVector3::x_axis;
1213 }
1214 }
1215
1216 mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation;
1217
1218 F32 guide_size_meters;
1219
1220 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
1221 {
1222 guide_size_meters = 1.f / gAgent.getAvatarObject()->mHUDCurZoom;
1223 mSnapOffsetMeters = mArrowLengthMeters * 1.5f;
1224 }
1225 else
1226 {
1227 LLVector3 cam_to_selection = getPivotPoint() - gCamera->getOrigin();
1228 F32 current_range = cam_to_selection.normVec();
1229 guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWindowHeight() * current_range / gCamera->getPixelMeterRatio();
1230
1231 F32 fraction_of_fov = mAxisArrowLength / (F32) gCamera->getViewHeightInPixels();
1232 F32 apparent_angle = fraction_of_fov * gCamera->getView(); // radians
1233 F32 offset_at_camera = tan(apparent_angle) * 1.5f;
1234 F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), gCamera->getOrigin());
1235 mSnapOffsetMeters = range * offset_at_camera;
1236 }
1237
1238 LLVector3 tick_start;
1239 LLVector3 tick_end;
1240
1241 // how far away from grid origin is the selection along the axis of translation?
1242 F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis;
1243 // find distance to nearest smallest grid unit
1244 F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale);
1245 // how many smallest grid units are we away from largest grid scale?
1246 S32 sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale);
1247 S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale));
1248
1249 LLGLDepthTest gls_depth(GL_FALSE);
1250
1251 for (S32 pass = 0; pass < 3; pass++)
1252 {
1253 LLColor4 line_color = setupSnapGuideRenderPass(pass);
1254
1255 glBegin(GL_LINES);
1256 {
1257 LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit));
1258 LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit));
1259 LLVector3 line_mid = (line_start + line_end) * 0.5f;
1260
1261 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
1262 glVertex3fv(line_start.mV);
1263 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
1264 glVertex3fv(line_mid.mV);
1265 glVertex3fv(line_mid.mV);
1266 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
1267 glVertex3fv(line_end.mV);
1268
1269 line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f));
1270 line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f));
1271 line_mid = (line_start + line_end) * 0.5f;
1272
1273 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
1274 glVertex3fv(line_start.mV);
1275 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
1276 glVertex3fv(line_mid.mV);
1277 glVertex3fv(line_mid.mV);
1278 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f);
1279 glVertex3fv(line_end.mV);
1280
1281 for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++)
1282 {
1283 tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit));
1284
1285 F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
1286
1287 if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f)
1288 {
1289 continue;
1290 }
1291
1292 // add in off-axis offset
1293 tick_start += (mSnapOffsetAxis * mSnapOffsetMeters);
1294
1295 BOOL is_sub_tick = FALSE;
1296 F32 tick_scale = 1.f;
1297 for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
1298 {
1299 if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f)
1300 {
1301 break;
1302 }
1303 tick_scale *= 0.7f;
1304 is_sub_tick = TRUE;
1305 }
1306
1307// S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side;
1308// F32 alpha = line_alpha * (1.f - (0.8f * ((F32)llabs(i) / (F32)num_ticks_to_fade)));
1309
1310 tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale);
1311
1312 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
1313 glVertex3fv(tick_start.mV);
1314 glVertex3fv(tick_end.mV);
1315
1316 tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) +
1317 (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit));
1318 tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale);
1319
1320 glVertex3fv(tick_start.mV);
1321 glVertex3fv(tick_end.mV);
1322 }
1323 }
1324 glEnd();
1325
1326 if (mInSnapRegime)
1327 {
1328 LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters;
1329 LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters;
1330
1331 glBegin(GL_LINES);
1332 {
1333 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
1334
1335 glVertex3fv(line_start.mV);
1336 glVertex3fv(line_end.mV);
1337 }
1338 glEnd();
1339
1340 // draw snap guide arrow
1341 glBegin(GL_TRIANGLES);
1342 {
1343 glColor4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]);
1344
1345 LLVector3 arrow_dir;
1346 LLVector3 arrow_span = translate_axis;
1347
1348 arrow_dir = -mSnapOffsetAxis;
1349 glVertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV);
1350 glVertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
1351 glVertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
1352
1353 arrow_dir = mSnapOffsetAxis;
1354 glVertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV);
1355 glVertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
1356 glVertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV);
1357 }
1358 glEnd();
1359 }
1360 }
1361
1362 sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale);
1363
1364 LLVector2 screen_translate_axis(llabs(translate_axis * gCamera->getLeftAxis()), llabs(translate_axis * gCamera->getUpAxis()));
1365 screen_translate_axis.normVec();
1366
1367 S32 tick_label_spacing = llround(screen_translate_axis * sTickLabelSpacing);
1368
1369 // render tickmark values
1370 for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++)
1371 {
1372 LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit));
1373 F32 alpha = line_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side)));
1374
1375 F32 tick_scale = 1.f;
1376 for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
1377 {
1378 if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f)
1379 {
1380 break;
1381 }
1382 tick_scale *= 0.7f;
1383 }
1384
1385 if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing)))) == 0.f)
1386 {
1387 F32 snap_offset_meters;
1388
1389 if (mSnapOffsetAxis * gCamera->getUpAxis() > 0.f)
1390 {
1391 snap_offset_meters = mSnapOffsetMeters;
1392 }
1393 else
1394 {
1395 snap_offset_meters = -mSnapOffsetMeters;
1396 }
1397 LLVector3 text_origin = selection_center +
1398 (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) +
1399 (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale));
1400
1401 LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation;
1402 F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale();
1403 EGridMode grid_mode = gSelectMgr->getGridMode();
1404 F32 text_highlight = 0.8f;
1405 if(i - llround(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime)
1406 {
1407 text_highlight = 1.f;
1408 }
1409
1410 if (grid_mode == GRID_MODE_WORLD)
1411 {
1412 // rescale units to meters from multiple of grid scale
1413 offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]];
1414 renderTickValue(text_origin, offset_val, "m", LLColor4(text_highlight, text_highlight, text_highlight, alpha));
1415 }
1416 else
1417 {
1418 renderTickValue(text_origin, offset_val, "x", LLColor4(text_highlight, text_highlight, text_highlight, alpha));
1419 }
1420 }
1421 }
1422 if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
1423 {
1424 // render helpful text
1425 if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText)
1426 {
1427 F32 snap_offset_meters_up;
1428 if (mSnapOffsetAxis * gCamera->getUpAxis() > 0.f)
1429 {
1430 snap_offset_meters_up = mSnapOffsetMeters;
1431 }
1432 else
1433 {
1434 snap_offset_meters_up = -mSnapOffsetMeters;
1435 }
1436
1437 LLVector3 selection_center_start = getSavedPivotPoint();//gSelectMgr->getSavedBBoxOfSelection().getCenterAgent();
1438
1439 LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis);
1440 const LLFontGL* big_fontp = LLFontGL::sSansSerif;
1441
1442 LLGLSTexture gls_texture;
1443 std::string help_text = "Move mouse cursor over ruler to snap";
1444 LLColor4 help_text_color = LLColor4::white;
1445 help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
1446 hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
1447 help_text = "to snap to grid";
1448 help_text_pos -= gCamera->getUpAxis() * mSnapOffsetMeters * 0.2f;
1449 hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
1450 }
1451 }
1452 }
1453 else
1454 {
1455 // render gridlines for planar snapping
1456
1457 F32 u = 0, v = 0;
1458 glPushMatrix();
1459
1460 F32 x,y,z,angle_radians;
1461 grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
1462 glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
1463 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
1464
1465 LLVector3 grid_center = selection_center - grid_origin;
1466 grid_center *= ~grid_rotation;
1467
1468 F32 usc = 1;
1469 F32 vsc = 1;
1470
1471 switch (mManipPart)
1472 {
1473 case LL_YZ_PLANE:
1474 u = grid_center.mV[VY];
1475 v = grid_center.mV[VZ];
1476 usc = grid_scale.mV[VY];
1477 vsc = grid_scale.mV[VZ];
1478 break;
1479 case LL_XZ_PLANE:
1480 u = grid_center.mV[VX];
1481 v = grid_center.mV[VZ];
1482 usc = grid_scale.mV[VX];
1483 vsc = grid_scale.mV[VZ];
1484 break;
1485 case LL_XY_PLANE:
1486 u = grid_center.mV[VX];
1487 v = grid_center.mV[VY];
1488 usc = grid_scale.mV[VX];
1489 vsc = grid_scale.mV[VY];
1490 break;
1491 default:
1492 break;
1493 }
1494
1495 F32 sz = mGridSizeMeters;
1496 F32 tiles = sz;
1497 glMatrixMode(GL_TEXTURE);
1498 glPushMatrix();
1499 usc = 1.0f/usc;
1500 vsc = 1.0f/vsc;
1501
1502 while (usc > vsc*4.0f)
1503 {
1504 usc *= 0.5f;
1505 }
1506 while (vsc > usc * 4.0f)
1507 {
1508 vsc *= 0.5f;
1509 }
1510
1511 glScalef(usc, vsc, 1.0f);
1512 glTranslatef(u, v, 0);
1513
1514 float a = line_alpha;
1515
1516 LLColor4 col = gColors.getColor("SilhouetteChildColor");
1517 {
1518 //draw grid behind objects
1519 LLGLSTexture tex2d;
1520 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
1521
1522 {
1523 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
1524 glBindTexture(GL_TEXTURE_2D, sGridTex);
1525 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
1526 renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f);
1527 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1528 }
1529
1530 {
1531 LLGLDisable alpha_test(GL_ALPHA_TEST);
1532 //draw black overlay
1533 glBindTexture(GL_TEXTURE_2D, 0);
1534 renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f);
1535
1536 //draw grid top
1537 glBindTexture(GL_TEXTURE_2D, sGridTex);
1538 renderGrid(u,v,tiles,1,1,1,a);
1539
1540 glPopMatrix();
1541 glMatrixMode(GL_MODELVIEW);
1542 glPopMatrix();
1543
1544 {
1545 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
1546 renderGuidelines();
1547 }
1548
1549 {
1550 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
1551 LLGLEnable stipple(GL_LINE_STIPPLE);
1552 glLineStipple(1, 0x3333);
1553
1554 switch (mManipPart)
1555 {
1556 case LL_YZ_PLANE:
1557 renderGuidelines(FALSE, TRUE, TRUE);
1558 break;
1559 case LL_XZ_PLANE:
1560 renderGuidelines(TRUE, FALSE, TRUE);
1561 break;
1562 case LL_XY_PLANE:
1563 renderGuidelines(TRUE, TRUE, FALSE);
1564 break;
1565 default:
1566 break;
1567 }
1568 }
1569 }
1570 }
1571 }
1572}
1573
1574void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a)
1575{
1576 F32 d = size*0.5f;
1577
1578 for (F32 xx = -size-d; xx < size+d; xx += d)
1579 {
1580 glBegin(GL_TRIANGLE_STRIP);
1581 for (F32 yy = -size-d; yy < size+d; yy += d)
1582 {
1583 float dx, dy, da;
1584
1585 dx = xx; dy = yy;
1586 da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
1587 glTexCoord2f(dx, dy);
1588 renderGridVert(dx,dy,r,g,b,da);
1589
1590 dx = xx+d; dy = yy;
1591 da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
1592 glTexCoord2f(dx, dy);
1593 renderGridVert(dx,dy,r,g,b,da);
1594
1595 dx = xx; dy = yy+d;
1596 da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
1597 glTexCoord2f(dx, dy);
1598 renderGridVert(dx,dy,r,g,b,da);
1599
1600 dx = xx+d; dy = yy+d;
1601 da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a;
1602 glTexCoord2f(dx, dy);
1603 renderGridVert(dx,dy,r,g,b,da);
1604 }
1605 glEnd();
1606 }
1607
1608
1609}
1610
1611
1612void LLManipTranslate::renderText()
1613{
1614 if (gSelectMgr->getRootObjectCount() && !gSelectMgr->selectionIsAttachment())
1615 {
1616 LLVector3 pos = getPivotPoint();
1617 renderXYZ(pos);
1618 }
1619 else
1620 {
1621 LLViewerObject* objectp = gSelectMgr->getFirstRootObject();
1622 if(!objectp)
1623 {
1624 objectp = gSelectMgr->getFirstObject();
1625 }
1626
1627 if (objectp)
1628 {
1629 renderXYZ(objectp->getPositionEdit());
1630 }
1631 }
1632}
1633
1634void LLManipTranslate::renderTranslationHandles()
1635{
1636 LLVector3 grid_origin;
1637 LLVector3 grid_scale;
1638 LLQuaternion grid_rotation;
1639 LLGLDepthTest gls_depth(GL_FALSE);
1640
1641 gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
1642 LLVector3 at_axis;
1643 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
1644 {
1645 at_axis = LLVector3::x_axis * ~grid_rotation;
1646 }
1647 else
1648 {
1649 at_axis = gCamera->getAtAxis() * ~grid_rotation;
1650 }
1651
1652 if (at_axis.mV[VX] > 0.f)
1653 {
1654 mPlaneManipPositions.mV[VX] = 1.f;
1655 }
1656 else
1657 {
1658 mPlaneManipPositions.mV[VX] = -1.f;
1659 }
1660
1661 if (at_axis.mV[VY] > 0.f)
1662 {
1663 mPlaneManipPositions.mV[VY] = 1.f;
1664 }
1665 else
1666 {
1667 mPlaneManipPositions.mV[VY] = -1.f;
1668 }
1669
1670 if (at_axis.mV[VZ] > 0.f)
1671 {
1672 mPlaneManipPositions.mV[VZ] = 1.f;
1673 }
1674 else
1675 {
1676 mPlaneManipPositions.mV[VZ] = -1.f;
1677 }
1678
1679 LLViewerObject *first_object = gSelectMgr->getFirstMoveableObject(TRUE);
1680 if (!first_object) return;
1681
1682 LLVector3 selection_center = getPivotPoint();
1683
1684 // Drag handles
1685 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
1686 {
1687 mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight();
1688 mArrowLengthMeters /= gAgent.getAvatarObject()->mHUDCurZoom;
1689 }
1690 else
1691 {
1692 LLVector3 camera_pos_agent = gAgent.getCameraPositionAgent();
1693 F32 range = dist_vec(camera_pos_agent, selection_center);
1694 F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center);
1695
1696 // Don't draw handles if you're too far away
1697 if (gSavedSettings.getBOOL("LimitSelectDistance"))
1698 {
1699 if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance"))
1700 {
1701 return;
1702 }
1703 }
1704
1705 if (range > 0.001f)
1706 {
1707 // range != zero
1708 F32 fraction_of_fov = mAxisArrowLength / (F32) gCamera->getViewHeightInPixels();
1709 F32 apparent_angle = fraction_of_fov * gCamera->getView(); // radians
1710 mArrowLengthMeters = range * tan(apparent_angle);
1711 }
1712 else
1713 {
1714 // range == zero
1715 mArrowLengthMeters = 1.0f;
1716 }
1717 }
1718
1719 mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f;
1720 mGridSizeMeters = gSavedSettings.getF32("GridDrawSize");
1721 mConeSize = mArrowLengthMeters / 4.f;
1722
1723 glMatrixMode(GL_MODELVIEW);
1724 glPushMatrix();
1725 {
1726 glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]);
1727
1728 F32 angle_radians, x, y, z;
1729 grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
1730
1731 glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
1732
1733 LLQuaternion invRotation = grid_rotation;
1734 invRotation.conjQuat();
1735
1736 LLVector3 relative_camera_dir;
1737
1738 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
1739 {
1740 relative_camera_dir = LLVector3::x_axis * invRotation;
1741 }
1742 else
1743 {
1744 relative_camera_dir = (selection_center - gCamera->getOrigin()) * invRotation;
1745 }
1746 relative_camera_dir.normVec();
1747
1748 {
1749 LLGLSNoTexture gls_ui_no_texture;
1750 LLGLDisable cull_face(GL_CULL_FACE);
1751
1752 LLColor4 color1;
1753 LLColor4 color2;
1754
1755 // update manipulator sizes
1756 for (S32 index = 0; index < 3; index++)
1757 {
1758 if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW)
1759 {
1760 mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
1761 mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
1762 }
1763 else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE)
1764 {
1765 mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
1766 mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
1767 }
1768 else
1769 {
1770 mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
1771 mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE ));
1772 }
1773 }
1774
1775 if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT)
1776 {
1777 // render YZ plane manipulator
1778 glPushMatrix();
1779 glScalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
1780 glTranslatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters);
1781 glScalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]);
1782 if (mHighlightedPart == LL_YZ_PLANE)
1783 {
1784 color1.setVec(0.f, 1.f, 0.f, 1.f);
1785 color2.setVec(0.f, 0.f, 1.f, 1.f);
1786 }
1787 else
1788 {
1789 color1.setVec(0.f, 1.f, 0.f, 0.6f);
1790 color2.setVec(0.f, 0.f, 1.f, 0.6f);
1791 }
1792 glBegin(GL_TRIANGLES);
1793 {
1794 glColor4fv(color1.mV);
1795 glVertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
1796 glVertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f));
1797 glVertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
1798
1799 glColor4fv(color2.mV);
1800 glVertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
1801 glVertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
1802 glVertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
1803 }
1804 glEnd();
1805
1806 LLUI::setLineWidth(3.0f);
1807 glBegin(GL_LINES);
1808 {
1809 glColor4f(0.f, 0.f, 0.f, 0.3f);
1810 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1811 glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1812 glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1813 glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f);
1814 glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1815 glVertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f);
1816
1817 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1818 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
1819 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
1820 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
1821 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
1822 glVertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
1823 }
1824 glEnd();
1825 LLUI::setLineWidth(1.0f);
1826 glPopMatrix();
1827 }
1828
1829 if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT)
1830 {
1831 // render XZ plane manipulator
1832 glPushMatrix();
1833 glScalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
1834 glTranslatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters);
1835 glScalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]);
1836 if (mHighlightedPart == LL_XZ_PLANE)
1837 {
1838 color1.setVec(0.f, 0.f, 1.f, 1.f);
1839 color2.setVec(1.f, 0.f, 0.f, 1.f);
1840 }
1841 else
1842 {
1843 color1.setVec(0.f, 0.f, 1.f, 0.6f);
1844 color2.setVec(1.f, 0.f, 0.f, 0.6f);
1845 }
1846
1847 glBegin(GL_TRIANGLES);
1848 {
1849 glColor4fv(color1.mV);
1850 glVertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
1851 glVertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
1852 glVertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
1853
1854 glColor4fv(color2.mV);
1855 glVertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f));
1856 glVertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f));
1857 glVertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f));
1858 }
1859 glEnd();
1860
1861 LLUI::setLineWidth(3.0f);
1862 glBegin(GL_LINES);
1863 {
1864 glColor4f(0.f, 0.f, 0.f, 0.3f);
1865 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1866 glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1867 glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1868 glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f);
1869 glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1870 glVertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f);
1871
1872 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f);
1873 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
1874 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
1875 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
1876 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f);
1877 glVertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f);
1878 }
1879 glEnd();
1880 LLUI::setLineWidth(1.0f);
1881
1882 glPopMatrix();
1883 }
1884
1885 if ((mManipPart == LL_NO_PART || mManipPart == LL_XY_PLANE) && llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT)
1886 {
1887 // render XY plane manipulator
1888 glPushMatrix();
1889 glScalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]);
1890
1891/* Y
1892 ^
1893 v1
1894 | \
1895 |<- v0
1896 | /| \
1897 v2__v__v3 > X
1898*/
1899 LLVector3 v0,v1,v2,v3;
1900#if 0
1901 // This should theoretically work but looks off; could be tuned later -SJB
1902 glTranslatef(-mPlaneManipOffsetMeters, -mPlaneManipOffsetMeters, 0.f);
1903 v0 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f);
1904 v1 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), 0.f);
1905 v2 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f);
1906 v3 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f);
1907#else
1908 glTranslatef(mPlaneManipOffsetMeters, mPlaneManipOffsetMeters, 0.f);
1909 v0 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f);
1910 v1 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f);
1911 v2 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f);
1912 v3 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f);
1913#endif
1914 glScalef(mPlaneScales.mV[VZ], mPlaneScales.mV[VZ], mPlaneScales.mV[VZ]);
1915 if (mHighlightedPart == LL_XY_PLANE)
1916 {
1917 color1.setVec(1.f, 0.f, 0.f, 1.f);
1918 color2.setVec(0.f, 1.f, 0.f, 1.f);
1919 }
1920 else
1921 {
1922 color1.setVec(0.8f, 0.f, 0.f, 0.6f);
1923 color2.setVec(0.f, 0.8f, 0.f, 0.6f);
1924 }
1925
1926 glBegin(GL_TRIANGLES);
1927 {
1928 glColor4fv(color1.mV);
1929 glVertex3fv(v0.mV);
1930 glVertex3fv(v1.mV);
1931 glVertex3fv(v2.mV);
1932
1933 glColor4fv(color2.mV);
1934 glVertex3fv(v2.mV);
1935 glVertex3fv(v3.mV);
1936 glVertex3fv(v0.mV);
1937 }
1938 glEnd();
1939
1940 LLUI::setLineWidth(3.0f);
1941 glBegin(GL_LINES);
1942 {
1943 glColor4f(0.f, 0.f, 0.f, 0.3f);
1944 LLVector3 v12 = (v1 + v2) * .5f;
1945 glVertex3fv(v0.mV);
1946 glVertex3fv(v12.mV);
1947 glVertex3fv(v12.mV);
1948 glVertex3fv((v12 + (v0-v12)*.3f + (v2-v12)*.3f).mV);
1949 glVertex3fv(v12.mV);
1950 glVertex3fv((v12 + (v0-v12)*.3f + (v1-v12)*.3f).mV);
1951
1952 LLVector3 v23 = (v2 + v3) * .5f;
1953 glVertex3fv(v0.mV);
1954 glVertex3fv(v23.mV);
1955 glVertex3fv(v23.mV);
1956 glVertex3fv((v23 + (v0-v23)*.3f + (v3-v23)*.3f).mV);
1957 glVertex3fv(v23.mV);
1958 glVertex3fv((v23 + (v0-v23)*.3f + (v2-v23)*.3f).mV);
1959 }
1960 glEnd();
1961 LLUI::setLineWidth(1.0f);
1962
1963 glPopMatrix();
1964 }
1965 }
1966 {
1967 LLGLSNoTexture gls_ui_no_texture;
1968
1969 // Since we draw handles with depth testing off, we need to draw them in the
1970 // proper depth order.
1971
1972 // Copied from LLDrawable::updateGeometry
1973 LLVector3 pos_agent = first_object->getPositionAgent();
1974 LLVector3 camera_agent = gAgent.getCameraPositionAgent();
1975 LLVector3 headPos = pos_agent - camera_agent;
1976
1977 LLVector3 orientWRTHead = headPos * invRotation;
1978
1979 // Find nearest vertex
1980 U32 nearest = (orientWRTHead.mV[0] < 0.0f ? 1 : 0) +
1981 (orientWRTHead.mV[1] < 0.0f ? 2 : 0) +
1982 (orientWRTHead.mV[2] < 0.0f ? 4 : 0);
1983
1984 // opposite faces on Linden cubes:
1985 // 0 & 5
1986 // 1 & 3
1987 // 2 & 4
1988
1989 // Table of order to draw faces, based on nearest vertex
1990 static U32 face_list[8][NUM_AXES*2] = {
1991 { 2,0,1, 4,5,3 }, // v6 F201 F453
1992 { 2,0,3, 4,5,1 }, // v7 F203 F451
1993 { 4,0,1, 2,5,3 }, // v5 F401 F253
1994 { 4,0,3, 2,5,1 }, // v4 F403 F251
1995 { 2,5,1, 4,0,3 }, // v2 F251 F403
1996 { 2,5,3, 4,0,1 }, // v3 F253 F401
1997 { 4,5,1, 2,0,3 }, // v1 F451 F203
1998 { 4,5,3, 2,0,1 }, // v0 F453 F201
1999 };
2000 static const EManipPart which_arrow[6] = {
2001 LL_Z_ARROW,
2002 LL_X_ARROW,
2003 LL_Y_ARROW,
2004 LL_X_ARROW,
2005 LL_Y_ARROW,
2006 LL_Z_ARROW};
2007
2008 // draw arrows for deeper faces first, closer faces last
2009 LLVector3 camera_axis;
2010 if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
2011 {
2012 camera_axis = LLVector3::x_axis;
2013 }
2014 else
2015 {
2016 camera_axis.setVec(gAgent.getCameraPositionAgent() - first_object->getPositionAgent());
2017 }
2018
2019 for (U32 i = 0; i < NUM_AXES*2; i++)
2020 {
2021 U32 face = face_list[nearest][i];
2022
2023 LLVector3 arrow_axis;
2024 getManipAxis(first_object, which_arrow[face], arrow_axis);
2025
2026 if (fabs(angle_between(camera_axis, arrow_axis) - F_PI_BY_TWO) < F_PI_BY_TWO - HANDLE_HIDE_ANGLE)
2027 {
2028 renderArrow(which_arrow[face],
2029 mManipPart,
2030 (face >= 3) ? -mConeSize : mConeSize,
2031 (face >= 3) ? -mArrowLengthMeters : mArrowLengthMeters,
2032 mConeSize,
2033 FALSE);
2034 }
2035 }
2036 }
2037 }
2038 glPopMatrix();
2039}
2040
2041
2042void LLManipTranslate::renderArrow(S32 which_arrow, S32 selected_arrow, F32 box_size, F32 arrow_size, F32 handle_size, BOOL reverse_direction)
2043{
2044 LLGLSNoTexture gls_ui_no_texture;
2045 LLGLEnable gls_blend(GL_BLEND);
2046 LLGLEnable gls_color_material(GL_COLOR_MATERIAL);
2047
2048 for (S32 pass = 1; pass <= 2; pass++)
2049 {
2050 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, pass == 1 ? GL_LEQUAL : GL_GREATER);
2051 glPushMatrix();
2052
2053 S32 index = 0;
2054
2055 index = ARROW_TO_AXIS[which_arrow];
2056
2057 // assign a color for this arrow
2058 LLColor4 color; // black
2059 if (which_arrow == selected_arrow || which_arrow == mHighlightedPart)
2060 {
2061 color.mV[index] = (pass == 1) ? 1.f : 0.5f;
2062 }
2063 else if (selected_arrow != LL_NO_PART)
2064 {
2065 color.mV[VALPHA] = 0.f;
2066 }
2067 else
2068 {
2069 color.mV[index] = pass == 1 ? .8f : .35f ; // red, green, or blue
2070 color.mV[VALPHA] = 0.6f;
2071 }
2072 glColor4fv( color.mV );
2073
2074 LLVector3 vec;
2075
2076 {
2077// Stipple looks OK, but not great - SJB
2078// LLGLEnable stipple(GL_LINE_STIPPLE);
2079// glLineStipple(1, 0x3333);
2080
2081 LLUI::setLineWidth(2.0f);
2082 glBegin(GL_LINES);
2083 vec.mV[index] = box_size;
2084 glVertex3f(vec.mV[0], vec.mV[1], vec.mV[2]);
2085
2086 vec.mV[index] = arrow_size;
2087 glVertex3f(vec.mV[0], vec.mV[1], vec.mV[2]);
2088 glEnd();
2089 LLUI::setLineWidth(1.0f);
2090 }
2091
2092 glTranslatef(vec.mV[0], vec.mV[1], vec.mV[2]);
2093 glScalef(handle_size, handle_size, handle_size);
2094
2095 F32 rot = 0.0f;
2096 LLVector3 axis;
2097
2098 switch(which_arrow)
2099 {
2100 case LL_X_ARROW:
2101 rot = reverse_direction ? -90.0f : 90.0f;
2102 axis.mV[1] = 1.0f;
2103 break;
2104 case LL_Y_ARROW:
2105 rot = reverse_direction ? 90.0f : -90.0f;
2106 axis.mV[0] = 1.0f;
2107 break;
2108 case LL_Z_ARROW:
2109 rot = reverse_direction ? 180.0f : 0.0f;
2110 axis.mV[0] = 1.0f;
2111 break;
2112 default:
2113 llerrs << "renderArrow called with bad arrow " << which_arrow << llendl;
2114 break;
2115 }
2116
2117 glRotatef(rot, axis.mV[0], axis.mV[1], axis.mV[2]);
2118 glScalef(mArrowScales.mV[index], mArrowScales.mV[index], mArrowScales.mV[index] * 1.5f);
2119
2120 gCone.render(CONE_LOD_HIGHEST);
2121
2122 glPopMatrix();
2123 }
2124}
2125
2126void LLManipTranslate::renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha)
2127{
2128 glColor4f(r, g, b, alpha);
2129 switch (mManipPart)
2130 {
2131 case LL_YZ_PLANE:
2132 glVertex3f(0, x_trans, y_trans);
2133 break;
2134 case LL_XZ_PLANE:
2135 glVertex3f(x_trans, 0, y_trans);
2136 break;
2137 case LL_XY_PLANE:
2138 glVertex3f(x_trans, y_trans, 0);
2139 break;
2140 default:
2141 glVertex3f(0,0,0);
2142 break;
2143 }
2144
2145}