diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lljoystickbutton.cpp | |
parent | README.txt (diff) | |
download | meta-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 '')
-rw-r--r-- | linden/indra/newview/lljoystickbutton.cpp | 866 |
1 files changed, 866 insertions, 0 deletions
diff --git a/linden/indra/newview/lljoystickbutton.cpp b/linden/indra/newview/lljoystickbutton.cpp new file mode 100644 index 0000000..a280ca8 --- /dev/null +++ b/linden/indra/newview/lljoystickbutton.cpp | |||
@@ -0,0 +1,866 @@ | |||
1 | /** | ||
2 | * @file lljoystickbutton.cpp | ||
3 | * @brief LLJoystick class implementation | ||
4 | * | ||
5 | * Copyright (c) 2001-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 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "lljoystickbutton.h" | ||
31 | |||
32 | // Library includes | ||
33 | #include "llcoord.h" | ||
34 | #include "indra_constants.h" | ||
35 | |||
36 | // Project includes | ||
37 | #include "llui.h" | ||
38 | #include "llagent.h" | ||
39 | #include "llviewerimage.h" | ||
40 | #include "llviewerimagelist.h" | ||
41 | #include "llviewerwindow.h" | ||
42 | #include "llmoveview.h" | ||
43 | |||
44 | #include "llglheaders.h" | ||
45 | |||
46 | const F32 NUDGE_TIME = 0.25f; // in seconds | ||
47 | const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed | ||
48 | |||
49 | // | ||
50 | // Public Methods | ||
51 | // | ||
52 | LLJoystick::LLJoystick( | ||
53 | const LLString& name, | ||
54 | LLRect rect, | ||
55 | const LLString &default_image, | ||
56 | const LLString &selected_image, | ||
57 | EJoystickQuadrant initial_quadrant ) | ||
58 | : | ||
59 | LLButton(name, rect, default_image, selected_image, NULL, NULL), | ||
60 | mInitialQuadrant(initial_quadrant), | ||
61 | mInitialOffset(0, 0), | ||
62 | mLastMouse(0, 0), | ||
63 | mFirstMouse(0, 0), | ||
64 | mVertSlopNear(0), | ||
65 | mVertSlopFar(0), | ||
66 | mHorizSlopNear(0), | ||
67 | mHorizSlopFar(0), | ||
68 | mHeldDown(FALSE), | ||
69 | mHeldDownTimer() | ||
70 | { | ||
71 | mHeldDownCallback = &LLJoystick::onHeldDown; | ||
72 | mCallbackUserData = this; | ||
73 | } | ||
74 | |||
75 | |||
76 | void LLJoystick::updateSlop() | ||
77 | { | ||
78 | mVertSlopNear = mRect.getHeight(); | ||
79 | mVertSlopFar = mRect.getHeight() * 2; | ||
80 | |||
81 | mHorizSlopNear = mRect.getWidth(); | ||
82 | mHorizSlopFar = mRect.getWidth() * 2; | ||
83 | |||
84 | // Compute initial mouse offset based on initial quadrant. | ||
85 | // Place the mouse evenly between the near and far zones. | ||
86 | switch (mInitialQuadrant) | ||
87 | { | ||
88 | case JQ_ORIGIN: | ||
89 | mInitialOffset.set(0, 0); | ||
90 | break; | ||
91 | |||
92 | case JQ_UP: | ||
93 | mInitialOffset.mX = 0; | ||
94 | mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2; | ||
95 | break; | ||
96 | |||
97 | case JQ_DOWN: | ||
98 | mInitialOffset.mX = 0; | ||
99 | mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2; | ||
100 | break; | ||
101 | |||
102 | case JQ_LEFT: | ||
103 | mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2; | ||
104 | mInitialOffset.mY = 0; | ||
105 | break; | ||
106 | |||
107 | case JQ_RIGHT: | ||
108 | mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2; | ||
109 | mInitialOffset.mY = 0; | ||
110 | break; | ||
111 | |||
112 | default: | ||
113 | llerrs << "LLJoystick::LLJoystick() - bad switch case" << llendl; | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | return; | ||
118 | } | ||
119 | |||
120 | |||
121 | BOOL LLJoystick::handleMouseDown(S32 x, S32 y, MASK mask) | ||
122 | { | ||
123 | //llinfos << "joystick mouse down " << x << ", " << y << llendl; | ||
124 | |||
125 | mLastMouse.set(x, y); | ||
126 | mFirstMouse.set(x, y); | ||
127 | |||
128 | mMouseDownTimer.reset(); | ||
129 | return LLButton::handleMouseDown(x, y, mask); | ||
130 | } | ||
131 | |||
132 | |||
133 | BOOL LLJoystick::handleMouseUp(S32 x, S32 y, MASK mask) | ||
134 | { | ||
135 | // llinfos << "joystick mouse up " << x << ", " << y << llendl; | ||
136 | |||
137 | if( gViewerWindow->hasMouseCapture( this ) ) | ||
138 | { | ||
139 | mLastMouse.set(x, y); | ||
140 | mHeldDown = FALSE; | ||
141 | onMouseUp(); | ||
142 | } | ||
143 | |||
144 | return LLButton::handleMouseUp(x, y, mask); | ||
145 | } | ||
146 | |||
147 | |||
148 | BOOL LLJoystick::handleHover(S32 x, S32 y, MASK mask) | ||
149 | { | ||
150 | if( gViewerWindow->hasMouseCapture( this ) ) | ||
151 | { | ||
152 | mLastMouse.set(x, y); | ||
153 | } | ||
154 | |||
155 | return LLButton::handleHover(x, y, mask); | ||
156 | } | ||
157 | |||
158 | F32 LLJoystick::getElapsedHeldDownTime() | ||
159 | { | ||
160 | if( mHeldDown ) | ||
161 | { | ||
162 | return mMouseDownTimer.getElapsedTimeF32(); | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | return 0.f; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | // static | ||
171 | void LLJoystick::onHeldDown(void *userdata) | ||
172 | { | ||
173 | LLJoystick *self = (LLJoystick *)userdata; | ||
174 | |||
175 | llassert( gViewerWindow->hasMouseCapture( self ) ); | ||
176 | |||
177 | self->mHeldDown = TRUE; | ||
178 | self->onHeldDown(); | ||
179 | } | ||
180 | |||
181 | EJoystickQuadrant LLJoystick::selectQuadrant(LLXMLNodePtr node) | ||
182 | { | ||
183 | |||
184 | EJoystickQuadrant quadrant = JQ_RIGHT; | ||
185 | |||
186 | if (node->hasAttribute("quadrant")) | ||
187 | { | ||
188 | LLString quadrant_name; | ||
189 | node->getAttributeString("quadrant", quadrant_name); | ||
190 | |||
191 | quadrant = quadrantFromName(quadrant_name.c_str()); | ||
192 | } | ||
193 | return quadrant; | ||
194 | } | ||
195 | |||
196 | |||
197 | LLString LLJoystick::nameFromQuadrant(EJoystickQuadrant quadrant) | ||
198 | { | ||
199 | if (quadrant == JQ_ORIGIN) return LLString("origin"); | ||
200 | else if (quadrant == JQ_UP) return LLString("up"); | ||
201 | else if (quadrant == JQ_DOWN) return LLString("down"); | ||
202 | else if (quadrant == JQ_LEFT) return LLString("left"); | ||
203 | else if (quadrant == JQ_RIGHT) return LLString("right"); | ||
204 | else return LLString(); | ||
205 | } | ||
206 | |||
207 | |||
208 | EJoystickQuadrant LLJoystick::quadrantFromName(const LLString& sQuadrant) | ||
209 | { | ||
210 | EJoystickQuadrant quadrant = JQ_RIGHT; | ||
211 | |||
212 | if (sQuadrant == "origin") | ||
213 | { | ||
214 | quadrant = JQ_ORIGIN; | ||
215 | } | ||
216 | else if (sQuadrant == "up") | ||
217 | { | ||
218 | quadrant = JQ_UP; | ||
219 | } | ||
220 | else if (sQuadrant == "down") | ||
221 | { | ||
222 | quadrant = JQ_DOWN; | ||
223 | } | ||
224 | else if (sQuadrant == "left") | ||
225 | { | ||
226 | quadrant = JQ_LEFT; | ||
227 | } | ||
228 | else if (sQuadrant == "right") | ||
229 | { | ||
230 | quadrant = JQ_RIGHT; | ||
231 | } | ||
232 | |||
233 | return quadrant; | ||
234 | } | ||
235 | |||
236 | |||
237 | LLXMLNodePtr LLJoystick::getXML(bool save_children) const | ||
238 | { | ||
239 | LLXMLNodePtr node = LLUICtrl::getXML(); | ||
240 | |||
241 | node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign)); | ||
242 | node->createChild("quadrant", TRUE)->setStringValue(nameFromQuadrant(mInitialQuadrant)); | ||
243 | |||
244 | addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected"); | ||
245 | addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected"); | ||
246 | |||
247 | node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage); | ||
248 | |||
249 | return node; | ||
250 | } | ||
251 | |||
252 | |||
253 | |||
254 | //------------------------------------------------------------------------------- | ||
255 | // LLJoystickAgentTurn | ||
256 | //------------------------------------------------------------------------------- | ||
257 | |||
258 | void LLJoystickAgentTurn::onHeldDown() | ||
259 | { | ||
260 | F32 time = getElapsedHeldDownTime(); | ||
261 | updateSlop(); | ||
262 | |||
263 | //llinfos << "move forward/backward (and/or turn)" << llendl; | ||
264 | |||
265 | S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX; | ||
266 | S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; | ||
267 | |||
268 | float m = (float) (dx)/abs(dy); | ||
269 | |||
270 | if (m > 1) { | ||
271 | m = 1; | ||
272 | } | ||
273 | else if (m < -1) { | ||
274 | m = -1; | ||
275 | } | ||
276 | gAgent.moveYaw(-LLFloaterMove::getYawRate(time)*m); | ||
277 | |||
278 | |||
279 | // handle forward/back movement | ||
280 | if (dy > mVertSlopFar) | ||
281 | { | ||
282 | // ...if mouse is forward of run region run forward | ||
283 | gAgent.moveAt(1); | ||
284 | } | ||
285 | else if (dy > mVertSlopNear) | ||
286 | { | ||
287 | if( time < NUDGE_TIME ) | ||
288 | { | ||
289 | gAgent.moveAtNudge(1); | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | // ...else if mouse is forward of walk region walk forward | ||
294 | // JC 9/5/2002 - Always run / move quickly. | ||
295 | gAgent.moveAt(1); | ||
296 | } | ||
297 | } | ||
298 | else if (dy < -mVertSlopFar) | ||
299 | { | ||
300 | // ...else if mouse is behind run region run backward | ||
301 | gAgent.moveAt(-1); | ||
302 | } | ||
303 | else if (dy < -mVertSlopNear) | ||
304 | { | ||
305 | if( time < NUDGE_TIME ) | ||
306 | { | ||
307 | gAgent.moveAtNudge(-1); | ||
308 | } | ||
309 | else | ||
310 | { | ||
311 | // ...else if mouse is behind walk region walk backward | ||
312 | // JC 9/5/2002 - Always run / move quickly. | ||
313 | gAgent.moveAt(-1); | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | LLView* LLJoystickAgentTurn::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) | ||
319 | { | ||
320 | LLString name("button"); | ||
321 | node->getAttributeString("name", name); | ||
322 | |||
323 | LLString image_unselected; | ||
324 | if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected); | ||
325 | |||
326 | LLString image_selected; | ||
327 | if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected); | ||
328 | |||
329 | EJoystickQuadrant quad = JQ_ORIGIN; | ||
330 | if (node->hasAttribute("quadrant")) quad = selectQuadrant(node); | ||
331 | |||
332 | LLJoystickAgentTurn *button = new LLJoystickAgentTurn(name, | ||
333 | LLRect(), | ||
334 | image_unselected, | ||
335 | image_selected, | ||
336 | quad); | ||
337 | |||
338 | if (node->hasAttribute("halign")) | ||
339 | { | ||
340 | LLFontGL::HAlign halign = selectFontHAlign(node); | ||
341 | button->setHAlign(halign); | ||
342 | } | ||
343 | |||
344 | if (node->hasAttribute("scale_image")) | ||
345 | { | ||
346 | BOOL needsScale = FALSE; | ||
347 | node->getAttributeBOOL("scale_image",needsScale); | ||
348 | button->setScaleImage( needsScale ); | ||
349 | } | ||
350 | |||
351 | button->initFromXML(node, parent); | ||
352 | |||
353 | return button; | ||
354 | } | ||
355 | |||
356 | |||
357 | |||
358 | //------------------------------------------------------------------------------- | ||
359 | // LLJoystickAgentSlide | ||
360 | //------------------------------------------------------------------------------- | ||
361 | |||
362 | void LLJoystickAgentSlide::onMouseUp() | ||
363 | { | ||
364 | F32 time = getElapsedHeldDownTime(); | ||
365 | if( time < NUDGE_TIME ) | ||
366 | { | ||
367 | switch (mInitialQuadrant) | ||
368 | { | ||
369 | case JQ_LEFT: | ||
370 | gAgent.moveLeftNudge(1); | ||
371 | break; | ||
372 | |||
373 | case JQ_RIGHT: | ||
374 | gAgent.moveLeftNudge(-1); | ||
375 | break; | ||
376 | |||
377 | default: | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | void LLJoystickAgentSlide::onHeldDown() | ||
384 | { | ||
385 | //llinfos << "slide left/right (and/or move forward/backward)" << llendl; | ||
386 | |||
387 | updateSlop(); | ||
388 | |||
389 | S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX; | ||
390 | S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; | ||
391 | |||
392 | // handle left-right sliding | ||
393 | if (dx > mHorizSlopNear) | ||
394 | { | ||
395 | gAgent.moveLeft(-1); | ||
396 | } | ||
397 | else if (dx < -mHorizSlopNear) | ||
398 | { | ||
399 | gAgent.moveLeft(1); | ||
400 | } | ||
401 | |||
402 | // handle forward/back movement | ||
403 | if (dy > mVertSlopFar) | ||
404 | { | ||
405 | // ...if mouse is forward of run region run forward | ||
406 | gAgent.moveAt(1); | ||
407 | } | ||
408 | else if (dy > mVertSlopNear) | ||
409 | { | ||
410 | // ...else if mouse is forward of walk region walk forward | ||
411 | gAgent.moveAtNudge(1); | ||
412 | } | ||
413 | else if (dy < -mVertSlopFar) | ||
414 | { | ||
415 | // ...else if mouse is behind run region run backward | ||
416 | gAgent.moveAt(-1); | ||
417 | } | ||
418 | else if (dy < -mVertSlopNear) | ||
419 | { | ||
420 | // ...else if mouse is behind walk region walk backward | ||
421 | gAgent.moveAtNudge(-1); | ||
422 | } | ||
423 | } | ||
424 | |||
425 | |||
426 | // static | ||
427 | LLView* LLJoystickAgentSlide::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) | ||
428 | { | ||
429 | LLString name("button"); | ||
430 | node->getAttributeString("name", name); | ||
431 | |||
432 | LLString image_unselected; | ||
433 | if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected); | ||
434 | |||
435 | LLString image_selected; | ||
436 | if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected); | ||
437 | |||
438 | |||
439 | EJoystickQuadrant quad = JQ_ORIGIN; | ||
440 | if (node->hasAttribute("quadrant")) quad = selectQuadrant(node); | ||
441 | |||
442 | LLJoystickAgentSlide *button = new LLJoystickAgentSlide(name, | ||
443 | LLRect(), | ||
444 | image_unselected, | ||
445 | image_selected, | ||
446 | quad); | ||
447 | |||
448 | if (node->hasAttribute("halign")) | ||
449 | { | ||
450 | LLFontGL::HAlign halign = selectFontHAlign(node); | ||
451 | button->setHAlign(halign); | ||
452 | } | ||
453 | |||
454 | if (node->hasAttribute("scale_image")) | ||
455 | { | ||
456 | BOOL needsScale = FALSE; | ||
457 | node->getAttributeBOOL("scale_image",needsScale); | ||
458 | button->setScaleImage( needsScale ); | ||
459 | } | ||
460 | |||
461 | button->initFromXML(node, parent); | ||
462 | |||
463 | return button; | ||
464 | } | ||
465 | |||
466 | |||
467 | //------------------------------------------------------------------------------- | ||
468 | // LLJoystickCameraRotate | ||
469 | //------------------------------------------------------------------------------- | ||
470 | |||
471 | LLJoystickCameraRotate::LLJoystickCameraRotate(const LLString& name, LLRect rect, const LLString &out_img, const LLString &in_img) | ||
472 | : | ||
473 | LLJoystick(name, rect, out_img, in_img, JQ_ORIGIN), | ||
474 | mInLeft( FALSE ), | ||
475 | mInTop( FALSE ), | ||
476 | mInRight( FALSE ), | ||
477 | mInBottom( FALSE ) | ||
478 | { } | ||
479 | |||
480 | |||
481 | void LLJoystickCameraRotate::updateSlop() | ||
482 | { | ||
483 | // do the initial offset calculation based on mousedown location | ||
484 | |||
485 | // small fixed slop region | ||
486 | mVertSlopNear = 16; | ||
487 | mVertSlopFar = 32; | ||
488 | |||
489 | mHorizSlopNear = 16; | ||
490 | mHorizSlopFar = 32; | ||
491 | |||
492 | return; | ||
493 | } | ||
494 | |||
495 | |||
496 | BOOL LLJoystickCameraRotate::handleMouseDown(S32 x, S32 y, MASK mask) | ||
497 | { | ||
498 | updateSlop(); | ||
499 | |||
500 | // Set initial offset based on initial click location | ||
501 | S32 horiz_center = mRect.getWidth() / 2; | ||
502 | S32 vert_center = mRect.getHeight() / 2; | ||
503 | |||
504 | S32 dx = x - horiz_center; | ||
505 | S32 dy = y - vert_center; | ||
506 | |||
507 | if (dy > dx && dy > -dx) | ||
508 | { | ||
509 | // top | ||
510 | mInitialOffset.mX = 0; | ||
511 | mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2; | ||
512 | mInitialQuadrant = JQ_UP; | ||
513 | } | ||
514 | else if (dy > dx && dy <= -dx) | ||
515 | { | ||
516 | // left | ||
517 | mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2; | ||
518 | mInitialOffset.mY = 0; | ||
519 | mInitialQuadrant = JQ_LEFT; | ||
520 | } | ||
521 | else if (dy <= dx && dy <= -dx) | ||
522 | { | ||
523 | // bottom | ||
524 | mInitialOffset.mX = 0; | ||
525 | mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2; | ||
526 | mInitialQuadrant = JQ_DOWN; | ||
527 | } | ||
528 | else | ||
529 | { | ||
530 | // right | ||
531 | mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2; | ||
532 | mInitialOffset.mY = 0; | ||
533 | mInitialQuadrant = JQ_RIGHT; | ||
534 | } | ||
535 | |||
536 | return LLJoystick::handleMouseDown(x, y, mask); | ||
537 | } | ||
538 | |||
539 | |||
540 | void LLJoystickCameraRotate::onHeldDown() | ||
541 | { | ||
542 | updateSlop(); | ||
543 | |||
544 | S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX; | ||
545 | S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; | ||
546 | |||
547 | // left-right rotation | ||
548 | if (dx > mHorizSlopNear) | ||
549 | { | ||
550 | gAgent.unlockView(); | ||
551 | gAgent.setOrbitLeftKey(getOrbitRate()); | ||
552 | } | ||
553 | else if (dx < -mHorizSlopNear) | ||
554 | { | ||
555 | gAgent.unlockView(); | ||
556 | gAgent.setOrbitRightKey(getOrbitRate()); | ||
557 | } | ||
558 | |||
559 | // over/under rotation | ||
560 | if (dy > mVertSlopNear) | ||
561 | { | ||
562 | gAgent.unlockView(); | ||
563 | gAgent.setOrbitUpKey(getOrbitRate()); | ||
564 | } | ||
565 | else if (dy < -mVertSlopNear) | ||
566 | { | ||
567 | gAgent.unlockView(); | ||
568 | gAgent.setOrbitDownKey(getOrbitRate()); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | F32 LLJoystickCameraRotate::getOrbitRate() | ||
573 | { | ||
574 | F32 time = getElapsedHeldDownTime(); | ||
575 | if( time < NUDGE_TIME ) | ||
576 | { | ||
577 | F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME; | ||
578 | //llinfos << rate << llendl; | ||
579 | return rate; | ||
580 | } | ||
581 | else | ||
582 | { | ||
583 | return 1; | ||
584 | } | ||
585 | } | ||
586 | |||
587 | |||
588 | // Only used for drawing | ||
589 | void LLJoystickCameraRotate::setToggleState( BOOL left, BOOL top, BOOL right, BOOL bottom ) | ||
590 | { | ||
591 | mInLeft = left; | ||
592 | mInTop = top; | ||
593 | mInRight = right; | ||
594 | mInBottom = bottom; | ||
595 | } | ||
596 | |||
597 | void LLJoystickCameraRotate::draw() | ||
598 | { | ||
599 | |||
600 | if( getVisible() ) | ||
601 | { | ||
602 | LLGLSUIDefault gls_ui; | ||
603 | |||
604 | gl_draw_image( 0, 0, mImageUnselected ); | ||
605 | |||
606 | if( mInTop ) | ||
607 | { | ||
608 | drawRotatedImage( mImageSelected, 0 ); | ||
609 | } | ||
610 | |||
611 | if( mInRight ) | ||
612 | { | ||
613 | drawRotatedImage( mImageSelected, 1 ); | ||
614 | } | ||
615 | |||
616 | if( mInBottom ) | ||
617 | { | ||
618 | drawRotatedImage( mImageSelected, 2 ); | ||
619 | } | ||
620 | |||
621 | if( mInLeft ) | ||
622 | { | ||
623 | drawRotatedImage( mImageSelected, 3 ); | ||
624 | } | ||
625 | |||
626 | if (sDebugRects) | ||
627 | { | ||
628 | drawDebugRect(); | ||
629 | } | ||
630 | } | ||
631 | } | ||
632 | |||
633 | // Draws image rotated by multiples of 90 degrees | ||
634 | void LLJoystickCameraRotate::drawRotatedImage( LLImageGL* image, S32 rotations ) | ||
635 | { | ||
636 | S32 width = image->getWidth(); | ||
637 | S32 height = image->getHeight(); | ||
638 | |||
639 | F32 uv[][2] = | ||
640 | { | ||
641 | { 1.f, 1.f }, | ||
642 | { 0.f, 1.f }, | ||
643 | { 0.f, 0.f }, | ||
644 | { 1.f, 0.f } | ||
645 | }; | ||
646 | |||
647 | image->bind(); | ||
648 | |||
649 | glColor4fv(UI_VERTEX_COLOR.mV); | ||
650 | |||
651 | glBegin(GL_QUADS); | ||
652 | { | ||
653 | glTexCoord2fv( uv[ (rotations + 0) % 4]); | ||
654 | glVertex2i(width, height ); | ||
655 | |||
656 | glTexCoord2fv( uv[ (rotations + 1) % 4]); | ||
657 | glVertex2i(0, height ); | ||
658 | |||
659 | glTexCoord2fv( uv[ (rotations + 2) % 4]); | ||
660 | glVertex2i(0, 0); | ||
661 | |||
662 | glTexCoord2fv( uv[ (rotations + 3) % 4]); | ||
663 | glVertex2i(width, 0); | ||
664 | } | ||
665 | glEnd(); | ||
666 | } | ||
667 | |||
668 | |||
669 | |||
670 | //------------------------------------------------------------------------------- | ||
671 | // LLJoystickCameraTrack | ||
672 | //------------------------------------------------------------------------------- | ||
673 | |||
674 | |||
675 | void LLJoystickCameraTrack::onHeldDown() | ||
676 | { | ||
677 | updateSlop(); | ||
678 | |||
679 | S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX; | ||
680 | S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; | ||
681 | |||
682 | if (dx > mVertSlopNear) | ||
683 | { | ||
684 | gAgent.unlockView(); | ||
685 | gAgent.setPanRightKey(getOrbitRate()); | ||
686 | } | ||
687 | else if (dx < -mVertSlopNear) | ||
688 | { | ||
689 | gAgent.unlockView(); | ||
690 | gAgent.setPanLeftKey(getOrbitRate()); | ||
691 | } | ||
692 | |||
693 | // over/under rotation | ||
694 | if (dy > mVertSlopNear) | ||
695 | { | ||
696 | gAgent.unlockView(); | ||
697 | gAgent.setPanUpKey(getOrbitRate()); | ||
698 | } | ||
699 | else if (dy < -mVertSlopNear) | ||
700 | { | ||
701 | gAgent.unlockView(); | ||
702 | gAgent.setPanDownKey(getOrbitRate()); | ||
703 | } | ||
704 | } | ||
705 | |||
706 | |||
707 | |||
708 | //------------------------------------------------------------------------------- | ||
709 | // LLJoystickCameraZoom | ||
710 | //------------------------------------------------------------------------------- | ||
711 | |||
712 | LLJoystickCameraZoom::LLJoystickCameraZoom(const LLString& name, LLRect rect, const LLString &out_img, const LLString &plus_in_img, const LLString &minus_in_img) | ||
713 | : | ||
714 | LLJoystick(name, rect, out_img, "", JQ_ORIGIN), | ||
715 | mInTop( FALSE ), | ||
716 | mInBottom( FALSE ) | ||
717 | { | ||
718 | mPlusInImage = gImageList.getImage(LLUI::findAssetUUIDByName(plus_in_img), MIPMAP_FALSE, TRUE); | ||
719 | mMinusInImage = gImageList.getImage(LLUI::findAssetUUIDByName(minus_in_img), MIPMAP_FALSE, TRUE); | ||
720 | } | ||
721 | |||
722 | |||
723 | BOOL LLJoystickCameraZoom::handleMouseDown(S32 x, S32 y, MASK mask) | ||
724 | { | ||
725 | BOOL handled = LLJoystick::handleMouseDown(x, y, mask); | ||
726 | |||
727 | if( handled ) | ||
728 | { | ||
729 | if (mFirstMouse.mY > mRect.getHeight() / 2) | ||
730 | { | ||
731 | mInitialQuadrant = JQ_UP; | ||
732 | } | ||
733 | else | ||
734 | { | ||
735 | mInitialQuadrant = JQ_DOWN; | ||
736 | } | ||
737 | } | ||
738 | return handled; | ||
739 | } | ||
740 | |||
741 | |||
742 | void LLJoystickCameraZoom::onHeldDown() | ||
743 | { | ||
744 | updateSlop(); | ||
745 | |||
746 | const F32 FAST_RATE = 2.5f; // two and a half times the normal rate | ||
747 | |||
748 | S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; | ||
749 | |||
750 | if (dy > mVertSlopFar) | ||
751 | { | ||
752 | // Zoom in fast | ||
753 | gAgent.unlockView(); | ||
754 | gAgent.setOrbitInKey(FAST_RATE); | ||
755 | } | ||
756 | else if (dy > mVertSlopNear) | ||
757 | { | ||
758 | // Zoom in slow | ||
759 | gAgent.unlockView(); | ||
760 | gAgent.setOrbitInKey(getOrbitRate()); | ||
761 | } | ||
762 | else if (dy < -mVertSlopFar) | ||
763 | { | ||
764 | // Zoom out fast | ||
765 | gAgent.unlockView(); | ||
766 | gAgent.setOrbitOutKey(FAST_RATE); | ||
767 | } | ||
768 | else if (dy < -mVertSlopNear) | ||
769 | { | ||
770 | // Zoom out slow | ||
771 | gAgent.unlockView(); | ||
772 | gAgent.setOrbitOutKey(getOrbitRate()); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | // Only used for drawing | ||
777 | void LLJoystickCameraZoom::setToggleState( BOOL top, BOOL bottom ) | ||
778 | { | ||
779 | mInTop = top; | ||
780 | mInBottom = bottom; | ||
781 | } | ||
782 | |||
783 | void LLJoystickCameraZoom::draw() | ||
784 | { | ||
785 | if( getVisible() ) | ||
786 | { | ||
787 | if( mInTop ) | ||
788 | { | ||
789 | gl_draw_image( 0, 0, mPlusInImage ); | ||
790 | } | ||
791 | else | ||
792 | if( mInBottom ) | ||
793 | { | ||
794 | gl_draw_image( 0, 0, mMinusInImage ); | ||
795 | } | ||
796 | else | ||
797 | { | ||
798 | gl_draw_image( 0, 0, mImageUnselected ); | ||
799 | } | ||
800 | |||
801 | if (sDebugRects) | ||
802 | { | ||
803 | drawDebugRect(); | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | void LLJoystickCameraZoom::updateSlop() | ||
809 | { | ||
810 | mVertSlopNear = mRect.getHeight() / 4; | ||
811 | mVertSlopFar = mRect.getHeight() / 2; | ||
812 | |||
813 | mHorizSlopNear = mRect.getWidth() / 4; | ||
814 | mHorizSlopFar = mRect.getWidth() / 2; | ||
815 | |||
816 | // Compute initial mouse offset based on initial quadrant. | ||
817 | // Place the mouse evenly between the near and far zones. | ||
818 | switch (mInitialQuadrant) | ||
819 | { | ||
820 | case JQ_ORIGIN: | ||
821 | mInitialOffset.set(0, 0); | ||
822 | break; | ||
823 | |||
824 | case JQ_UP: | ||
825 | mInitialOffset.mX = 0; | ||
826 | mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2; | ||
827 | break; | ||
828 | |||
829 | case JQ_DOWN: | ||
830 | mInitialOffset.mX = 0; | ||
831 | mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2; | ||
832 | break; | ||
833 | |||
834 | case JQ_LEFT: | ||
835 | mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2; | ||
836 | mInitialOffset.mY = 0; | ||
837 | break; | ||
838 | |||
839 | case JQ_RIGHT: | ||
840 | mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2; | ||
841 | mInitialOffset.mY = 0; | ||
842 | break; | ||
843 | |||
844 | default: | ||
845 | llerrs << "LLJoystick::LLJoystick() - bad switch case" << llendl; | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | return; | ||
850 | } | ||
851 | |||
852 | |||
853 | F32 LLJoystickCameraZoom::getOrbitRate() | ||
854 | { | ||
855 | F32 time = getElapsedHeldDownTime(); | ||
856 | if( time < NUDGE_TIME ) | ||
857 | { | ||
858 | F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME; | ||
859 | // llinfos << "rate " << rate << " time " << time << llendl; | ||
860 | return rate; | ||
861 | } | ||
862 | else | ||
863 | { | ||
864 | return 1; | ||
865 | } | ||
866 | } | ||