Need to test: localassetbrowser preview related floaters hgfloatertexteditor maps media textures! Currently very hacky web browser alpha masks on avatars bumpmaps Are all sky components appearing? LLViewerDynamicTexture (texture baking, browser, animated textures, anim previews, etc) Snapshot related features Customize avatar vfs floater UI textures in general Texture priority issues
883 lines
18 KiB
C++
883 lines
18 KiB
C++
/**
|
|
* @file lljoystickbutton.cpp
|
|
* @brief LLJoystick class implementation
|
|
*
|
|
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2001-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "lljoystickbutton.h"
|
|
|
|
// Library includes
|
|
#include "llcoord.h"
|
|
#include "indra_constants.h"
|
|
#include "llrender.h"
|
|
|
|
// Project includes
|
|
#include "llui.h"
|
|
#include "llagent.h"
|
|
#include "llviewertexturelist.h"
|
|
#include "llviewerwindow.h"
|
|
#include "llmoveview.h"
|
|
|
|
#include "llglheaders.h"
|
|
|
|
static LLRegisterWidget<LLJoystickAgentSlide> r1("joystick_slide");
|
|
static LLRegisterWidget<LLJoystickAgentTurn> r2("joystick_turn");
|
|
|
|
|
|
const F32 NUDGE_TIME = 0.25f; // in seconds
|
|
const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
|
|
|
|
//
|
|
// Public Methods
|
|
//
|
|
LLJoystick::LLJoystick(
|
|
const std::string& name,
|
|
LLRect rect,
|
|
const std::string &default_image,
|
|
const std::string &selected_image,
|
|
EJoystickQuadrant initial_quadrant )
|
|
:
|
|
LLButton(name, rect, default_image, selected_image, LLStringUtil::null, NULL, NULL),
|
|
mInitialQuadrant(initial_quadrant),
|
|
mInitialOffset(0, 0),
|
|
mLastMouse(0, 0),
|
|
mFirstMouse(0, 0),
|
|
mVertSlopNear(0),
|
|
mVertSlopFar(0),
|
|
mHorizSlopNear(0),
|
|
mHorizSlopFar(0),
|
|
mHeldDown(FALSE),
|
|
mHeldDownTimer()
|
|
{
|
|
setHeldDownCallback(&LLJoystick::onHeldDown);
|
|
setCallbackUserData(this);
|
|
}
|
|
|
|
|
|
void LLJoystick::updateSlop()
|
|
{
|
|
mVertSlopNear = getRect().getHeight();
|
|
mVertSlopFar = getRect().getHeight() * 2;
|
|
|
|
mHorizSlopNear = getRect().getWidth();
|
|
mHorizSlopFar = getRect().getWidth() * 2;
|
|
|
|
// Compute initial mouse offset based on initial quadrant.
|
|
// Place the mouse evenly between the near and far zones.
|
|
switch (mInitialQuadrant)
|
|
{
|
|
case JQ_ORIGIN:
|
|
mInitialOffset.set(0, 0);
|
|
break;
|
|
|
|
case JQ_UP:
|
|
mInitialOffset.mX = 0;
|
|
mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2;
|
|
break;
|
|
|
|
case JQ_DOWN:
|
|
mInitialOffset.mX = 0;
|
|
mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2;
|
|
break;
|
|
|
|
case JQ_LEFT:
|
|
mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2;
|
|
mInitialOffset.mY = 0;
|
|
break;
|
|
|
|
case JQ_RIGHT:
|
|
mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2;
|
|
mInitialOffset.mY = 0;
|
|
break;
|
|
|
|
default:
|
|
llerrs << "LLJoystick::LLJoystick() - bad switch case" << llendl;
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL LLJoystick::handleMouseDown(S32 x, S32 y, MASK mask)
|
|
{
|
|
//llinfos << "joystick mouse down " << x << ", " << y << llendl;
|
|
|
|
mLastMouse.set(x, y);
|
|
mFirstMouse.set(x, y);
|
|
|
|
mMouseDownTimer.reset();
|
|
return LLButton::handleMouseDown(x, y, mask);
|
|
}
|
|
|
|
|
|
BOOL LLJoystick::handleMouseUp(S32 x, S32 y, MASK mask)
|
|
{
|
|
// llinfos << "joystick mouse up " << x << ", " << y << llendl;
|
|
|
|
if( hasMouseCapture() )
|
|
{
|
|
mLastMouse.set(x, y);
|
|
mHeldDown = FALSE;
|
|
onMouseUp();
|
|
}
|
|
|
|
return LLButton::handleMouseUp(x, y, mask);
|
|
}
|
|
|
|
|
|
BOOL LLJoystick::handleHover(S32 x, S32 y, MASK mask)
|
|
{
|
|
if( hasMouseCapture() )
|
|
{
|
|
mLastMouse.set(x, y);
|
|
}
|
|
|
|
return LLButton::handleHover(x, y, mask);
|
|
}
|
|
|
|
F32 LLJoystick::getElapsedHeldDownTime()
|
|
{
|
|
if( mHeldDown )
|
|
{
|
|
return getHeldDownTime();
|
|
}
|
|
else
|
|
{
|
|
return 0.f;
|
|
}
|
|
}
|
|
|
|
// static
|
|
void LLJoystick::onHeldDown(void *userdata)
|
|
{
|
|
LLJoystick *self = (LLJoystick *)userdata;
|
|
|
|
// somebody removed this function without checking the
|
|
// build. Removed 2007-03-26.
|
|
//llassert( gViewerWindow->hasMouseCapture( self ) );
|
|
|
|
self->mHeldDown = TRUE;
|
|
self->onHeldDown();
|
|
}
|
|
|
|
EJoystickQuadrant LLJoystick::selectQuadrant(LLXMLNodePtr node)
|
|
{
|
|
|
|
EJoystickQuadrant quadrant = JQ_RIGHT;
|
|
|
|
if (node->hasAttribute("quadrant"))
|
|
{
|
|
std::string quadrant_name;
|
|
node->getAttributeString("quadrant", quadrant_name);
|
|
|
|
quadrant = quadrantFromName(quadrant_name);
|
|
}
|
|
return quadrant;
|
|
}
|
|
|
|
|
|
std::string LLJoystick::nameFromQuadrant(EJoystickQuadrant quadrant)
|
|
{
|
|
if (quadrant == JQ_ORIGIN) return std::string("origin");
|
|
else if (quadrant == JQ_UP) return std::string("up");
|
|
else if (quadrant == JQ_DOWN) return std::string("down");
|
|
else if (quadrant == JQ_LEFT) return std::string("left");
|
|
else if (quadrant == JQ_RIGHT) return std::string("right");
|
|
else return std::string();
|
|
}
|
|
|
|
|
|
EJoystickQuadrant LLJoystick::quadrantFromName(const std::string& sQuadrant)
|
|
{
|
|
EJoystickQuadrant quadrant = JQ_RIGHT;
|
|
|
|
if (sQuadrant == "origin")
|
|
{
|
|
quadrant = JQ_ORIGIN;
|
|
}
|
|
else if (sQuadrant == "up")
|
|
{
|
|
quadrant = JQ_UP;
|
|
}
|
|
else if (sQuadrant == "down")
|
|
{
|
|
quadrant = JQ_DOWN;
|
|
}
|
|
else if (sQuadrant == "left")
|
|
{
|
|
quadrant = JQ_LEFT;
|
|
}
|
|
else if (sQuadrant == "right")
|
|
{
|
|
quadrant = JQ_RIGHT;
|
|
}
|
|
|
|
return quadrant;
|
|
}
|
|
|
|
|
|
LLXMLNodePtr LLJoystick::getXML(bool save_children) const
|
|
{
|
|
LLXMLNodePtr node = LLButton::getXML();
|
|
|
|
node->createChild("quadrant", TRUE)->setStringValue(nameFromQuadrant(mInitialQuadrant));
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// LLJoystickAgentTurn
|
|
//-------------------------------------------------------------------------------
|
|
|
|
void LLJoystickAgentTurn::onHeldDown()
|
|
{
|
|
F32 time = getElapsedHeldDownTime();
|
|
updateSlop();
|
|
|
|
//llinfos << "move forward/backward (and/or turn)" << llendl;
|
|
|
|
S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX;
|
|
S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY;
|
|
|
|
float m = (float) (dx)/abs(dy);
|
|
|
|
if (m > 1) {
|
|
m = 1;
|
|
}
|
|
else if (m < -1) {
|
|
m = -1;
|
|
}
|
|
gAgent.moveYaw(-LLFloaterMove::getYawRate(time)*m);
|
|
|
|
|
|
// handle forward/back movement
|
|
if (dy > mVertSlopFar)
|
|
{
|
|
// ...if mouse is forward of run region run forward
|
|
gAgent.moveAt(1);
|
|
}
|
|
else if (dy > mVertSlopNear)
|
|
{
|
|
if( time < NUDGE_TIME )
|
|
{
|
|
gAgent.moveAtNudge(1);
|
|
}
|
|
else
|
|
{
|
|
// ...else if mouse is forward of walk region walk forward
|
|
// JC 9/5/2002 - Always run / move quickly.
|
|
gAgent.moveAt(1);
|
|
}
|
|
}
|
|
else if (dy < -mVertSlopFar)
|
|
{
|
|
// ...else if mouse is behind run region run backward
|
|
gAgent.moveAt(-1);
|
|
}
|
|
else if (dy < -mVertSlopNear)
|
|
{
|
|
if( time < NUDGE_TIME )
|
|
{
|
|
gAgent.moveAtNudge(-1);
|
|
}
|
|
else
|
|
{
|
|
// ...else if mouse is behind walk region walk backward
|
|
// JC 9/5/2002 - Always run / move quickly.
|
|
gAgent.moveAt(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
LLXMLNodePtr LLJoystickAgentTurn::getXML(bool save_children) const
|
|
{
|
|
LLXMLNodePtr node = LLJoystick::getXML();
|
|
|
|
node->setName(LL_JOYSTICK_TURN);
|
|
|
|
return node;
|
|
}
|
|
|
|
LLView* LLJoystickAgentTurn::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
|
{
|
|
std::string name("button");
|
|
node->getAttributeString("name", name);
|
|
|
|
std::string image_unselected;
|
|
if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
|
|
|
|
std::string image_selected;
|
|
if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
|
|
|
|
EJoystickQuadrant quad = JQ_ORIGIN;
|
|
if (node->hasAttribute("quadrant")) quad = selectQuadrant(node);
|
|
|
|
LLJoystickAgentTurn *button = new LLJoystickAgentTurn(name,
|
|
LLRect(),
|
|
image_unselected,
|
|
image_selected,
|
|
quad);
|
|
|
|
if (node->hasAttribute("halign"))
|
|
{
|
|
LLFontGL::HAlign halign = selectFontHAlign(node);
|
|
button->setHAlign(halign);
|
|
}
|
|
|
|
if (node->hasAttribute("scale_image"))
|
|
{
|
|
BOOL needsScale = FALSE;
|
|
node->getAttributeBOOL("scale_image",needsScale);
|
|
button->setScaleImage( needsScale );
|
|
}
|
|
|
|
button->initFromXML(node, parent);
|
|
|
|
return button;
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// LLJoystickAgentSlide
|
|
//-------------------------------------------------------------------------------
|
|
|
|
void LLJoystickAgentSlide::onMouseUp()
|
|
{
|
|
F32 time = getElapsedHeldDownTime();
|
|
if( time < NUDGE_TIME )
|
|
{
|
|
switch (mInitialQuadrant)
|
|
{
|
|
case JQ_LEFT:
|
|
gAgent.moveLeftNudge(1);
|
|
break;
|
|
|
|
case JQ_RIGHT:
|
|
gAgent.moveLeftNudge(-1);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLJoystickAgentSlide::onHeldDown()
|
|
{
|
|
//llinfos << "slide left/right (and/or move forward/backward)" << llendl;
|
|
|
|
updateSlop();
|
|
|
|
S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX;
|
|
S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY;
|
|
|
|
// handle left-right sliding
|
|
if (dx > mHorizSlopNear)
|
|
{
|
|
gAgent.moveLeft(-1);
|
|
}
|
|
else if (dx < -mHorizSlopNear)
|
|
{
|
|
gAgent.moveLeft(1);
|
|
}
|
|
|
|
// handle forward/back movement
|
|
if (dy > mVertSlopFar)
|
|
{
|
|
// ...if mouse is forward of run region run forward
|
|
gAgent.moveAt(1);
|
|
}
|
|
else if (dy > mVertSlopNear)
|
|
{
|
|
// ...else if mouse is forward of walk region walk forward
|
|
gAgent.moveAtNudge(1);
|
|
}
|
|
else if (dy < -mVertSlopFar)
|
|
{
|
|
// ...else if mouse is behind run region run backward
|
|
gAgent.moveAt(-1);
|
|
}
|
|
else if (dy < -mVertSlopNear)
|
|
{
|
|
// ...else if mouse is behind walk region walk backward
|
|
gAgent.moveAtNudge(-1);
|
|
}
|
|
}
|
|
|
|
|
|
LLXMLNodePtr LLJoystickAgentSlide::getXML(bool save_children) const
|
|
{
|
|
LLXMLNodePtr node = LLJoystick::getXML();
|
|
|
|
node->setName(LL_JOYSTICK_SLIDE);
|
|
|
|
return node;
|
|
}
|
|
|
|
// static
|
|
LLView* LLJoystickAgentSlide::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
|
{
|
|
std::string name("button");
|
|
node->getAttributeString("name", name);
|
|
|
|
std::string image_unselected;
|
|
if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
|
|
|
|
std::string image_selected;
|
|
if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
|
|
|
|
|
|
EJoystickQuadrant quad = JQ_ORIGIN;
|
|
if (node->hasAttribute("quadrant")) quad = selectQuadrant(node);
|
|
|
|
LLJoystickAgentSlide *button = new LLJoystickAgentSlide(name,
|
|
LLRect(),
|
|
image_unselected,
|
|
image_selected,
|
|
quad);
|
|
|
|
if (node->hasAttribute("halign"))
|
|
{
|
|
LLFontGL::HAlign halign = selectFontHAlign(node);
|
|
button->setHAlign(halign);
|
|
}
|
|
|
|
if (node->hasAttribute("scale_image"))
|
|
{
|
|
BOOL needsScale = FALSE;
|
|
node->getAttributeBOOL("scale_image",needsScale);
|
|
button->setScaleImage( needsScale );
|
|
}
|
|
|
|
button->initFromXML(node, parent);
|
|
|
|
return button;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// LLJoystickCameraRotate
|
|
//-------------------------------------------------------------------------------
|
|
|
|
LLJoystickCameraRotate::LLJoystickCameraRotate(const std::string& name, LLRect rect, const std::string &out_img, const std::string &in_img)
|
|
:
|
|
LLJoystick(name, rect, out_img, in_img, JQ_ORIGIN),
|
|
mInLeft( FALSE ),
|
|
mInTop( FALSE ),
|
|
mInRight( FALSE ),
|
|
mInBottom( FALSE )
|
|
{ }
|
|
|
|
|
|
void LLJoystickCameraRotate::updateSlop()
|
|
{
|
|
// do the initial offset calculation based on mousedown location
|
|
|
|
// small fixed slop region
|
|
mVertSlopNear = 16;
|
|
mVertSlopFar = 32;
|
|
|
|
mHorizSlopNear = 16;
|
|
mHorizSlopFar = 32;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL LLJoystickCameraRotate::handleMouseDown(S32 x, S32 y, MASK mask)
|
|
{
|
|
updateSlop();
|
|
|
|
// Set initial offset based on initial click location
|
|
S32 horiz_center = getRect().getWidth() / 2;
|
|
S32 vert_center = getRect().getHeight() / 2;
|
|
|
|
S32 dx = x - horiz_center;
|
|
S32 dy = y - vert_center;
|
|
|
|
if (dy > dx && dy > -dx)
|
|
{
|
|
// top
|
|
mInitialOffset.mX = 0;
|
|
mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2;
|
|
mInitialQuadrant = JQ_UP;
|
|
}
|
|
else if (dy > dx && dy <= -dx)
|
|
{
|
|
// left
|
|
mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2;
|
|
mInitialOffset.mY = 0;
|
|
mInitialQuadrant = JQ_LEFT;
|
|
}
|
|
else if (dy <= dx && dy <= -dx)
|
|
{
|
|
// bottom
|
|
mInitialOffset.mX = 0;
|
|
mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2;
|
|
mInitialQuadrant = JQ_DOWN;
|
|
}
|
|
else
|
|
{
|
|
// right
|
|
mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2;
|
|
mInitialOffset.mY = 0;
|
|
mInitialQuadrant = JQ_RIGHT;
|
|
}
|
|
|
|
return LLJoystick::handleMouseDown(x, y, mask);
|
|
}
|
|
|
|
|
|
void LLJoystickCameraRotate::onHeldDown()
|
|
{
|
|
updateSlop();
|
|
|
|
S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX;
|
|
S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY;
|
|
|
|
// left-right rotation
|
|
if (dx > mHorizSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitLeftKey(getOrbitRate());
|
|
}
|
|
else if (dx < -mHorizSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitRightKey(getOrbitRate());
|
|
}
|
|
|
|
// over/under rotation
|
|
if (dy > mVertSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitUpKey(getOrbitRate());
|
|
}
|
|
else if (dy < -mVertSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitDownKey(getOrbitRate());
|
|
}
|
|
}
|
|
|
|
F32 LLJoystickCameraRotate::getOrbitRate()
|
|
{
|
|
F32 time = getElapsedHeldDownTime();
|
|
if( time < NUDGE_TIME )
|
|
{
|
|
F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
|
|
//llinfos << rate << llendl;
|
|
return rate;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
// Only used for drawing
|
|
void LLJoystickCameraRotate::setToggleState( BOOL left, BOOL top, BOOL right, BOOL bottom )
|
|
{
|
|
mInLeft = left;
|
|
mInTop = top;
|
|
mInRight = right;
|
|
mInBottom = bottom;
|
|
}
|
|
|
|
void LLJoystickCameraRotate::draw()
|
|
{
|
|
LLGLSUIDefault gls_ui;
|
|
|
|
getImageUnselected()->draw( 0, 0 );
|
|
|
|
if( mInTop )
|
|
{
|
|
drawRotatedImage( getImageSelected()->getImage(), 0 );
|
|
}
|
|
|
|
if( mInRight )
|
|
{
|
|
drawRotatedImage( getImageSelected()->getImage(), 1 );
|
|
}
|
|
|
|
if( mInBottom )
|
|
{
|
|
drawRotatedImage( getImageSelected()->getImage(), 2 );
|
|
}
|
|
|
|
if( mInLeft )
|
|
{
|
|
drawRotatedImage( getImageSelected()->getImage(), 3 );
|
|
}
|
|
|
|
if (sDebugRects)
|
|
{
|
|
drawDebugRect();
|
|
}
|
|
}
|
|
|
|
// Draws image rotated by multiples of 90 degrees
|
|
void LLJoystickCameraRotate::drawRotatedImage( LLTexture* image, S32 rotations )
|
|
{
|
|
S32 width = image->getWidth();
|
|
S32 height = image->getHeight();
|
|
|
|
F32 uv[][2] =
|
|
{
|
|
{ 1.f, 1.f },
|
|
{ 0.f, 1.f },
|
|
{ 0.f, 0.f },
|
|
{ 1.f, 0.f }
|
|
};
|
|
|
|
gGL.getTexUnit(0)->bind(image);
|
|
|
|
gGL.color4fv(UI_VERTEX_COLOR.mV);
|
|
|
|
gGL.begin(LLRender::QUADS);
|
|
{
|
|
gGL.texCoord2fv( uv[ (rotations + 0) % 4]);
|
|
gGL.vertex2i(width, height );
|
|
|
|
gGL.texCoord2fv( uv[ (rotations + 1) % 4]);
|
|
gGL.vertex2i(0, height );
|
|
|
|
gGL.texCoord2fv( uv[ (rotations + 2) % 4]);
|
|
gGL.vertex2i(0, 0);
|
|
|
|
gGL.texCoord2fv( uv[ (rotations + 3) % 4]);
|
|
gGL.vertex2i(width, 0);
|
|
}
|
|
gGL.end();
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// LLJoystickCameraTrack
|
|
//-------------------------------------------------------------------------------
|
|
|
|
|
|
void LLJoystickCameraTrack::onHeldDown()
|
|
{
|
|
updateSlop();
|
|
|
|
S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX;
|
|
S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY;
|
|
|
|
if (dx > mVertSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setPanRightKey(getOrbitRate());
|
|
}
|
|
else if (dx < -mVertSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setPanLeftKey(getOrbitRate());
|
|
}
|
|
|
|
// over/under rotation
|
|
if (dy > mVertSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setPanUpKey(getOrbitRate());
|
|
}
|
|
else if (dy < -mVertSlopNear)
|
|
{
|
|
gAgent.unlockView();
|
|
gAgent.setPanDownKey(getOrbitRate());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// LLJoystickCameraZoom
|
|
//-------------------------------------------------------------------------------
|
|
|
|
LLJoystickCameraZoom::LLJoystickCameraZoom(const std::string& name, LLRect rect, const std::string &out_img, const std::string &plus_in_img, const std::string &minus_in_img)
|
|
:
|
|
LLJoystick(name, rect, out_img, LLStringUtil::null, JQ_ORIGIN),
|
|
mInTop( FALSE ),
|
|
mInBottom( FALSE )
|
|
{
|
|
mPlusInImage = LLUI::getUIImage(plus_in_img);
|
|
mMinusInImage = LLUI::getUIImage(minus_in_img);
|
|
}
|
|
|
|
|
|
BOOL LLJoystickCameraZoom::handleMouseDown(S32 x, S32 y, MASK mask)
|
|
{
|
|
BOOL handled = LLJoystick::handleMouseDown(x, y, mask);
|
|
|
|
if( handled )
|
|
{
|
|
if (mFirstMouse.mY > getRect().getHeight() / 2)
|
|
{
|
|
mInitialQuadrant = JQ_UP;
|
|
}
|
|
else
|
|
{
|
|
mInitialQuadrant = JQ_DOWN;
|
|
}
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
|
|
void LLJoystickCameraZoom::onHeldDown()
|
|
{
|
|
updateSlop();
|
|
|
|
const F32 FAST_RATE = 2.5f; // two and a half times the normal rate
|
|
|
|
S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY;
|
|
|
|
if (dy > mVertSlopFar)
|
|
{
|
|
// Zoom in fast
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitInKey(FAST_RATE);
|
|
}
|
|
else if (dy > mVertSlopNear)
|
|
{
|
|
// Zoom in slow
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitInKey(getOrbitRate());
|
|
}
|
|
else if (dy < -mVertSlopFar)
|
|
{
|
|
// Zoom out fast
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitOutKey(FAST_RATE);
|
|
}
|
|
else if (dy < -mVertSlopNear)
|
|
{
|
|
// Zoom out slow
|
|
gAgent.unlockView();
|
|
gAgent.setOrbitOutKey(getOrbitRate());
|
|
}
|
|
}
|
|
|
|
// Only used for drawing
|
|
void LLJoystickCameraZoom::setToggleState( BOOL top, BOOL bottom )
|
|
{
|
|
mInTop = top;
|
|
mInBottom = bottom;
|
|
}
|
|
|
|
void LLJoystickCameraZoom::draw()
|
|
{
|
|
if( mInTop )
|
|
{
|
|
mPlusInImage->draw(0,0);
|
|
}
|
|
else
|
|
if( mInBottom )
|
|
{
|
|
mMinusInImage->draw(0,0);
|
|
}
|
|
else
|
|
{
|
|
getImageUnselected()->draw( 0, 0 );
|
|
}
|
|
|
|
if (sDebugRects)
|
|
{
|
|
drawDebugRect();
|
|
}
|
|
}
|
|
|
|
void LLJoystickCameraZoom::updateSlop()
|
|
{
|
|
mVertSlopNear = getRect().getHeight() / 4;
|
|
mVertSlopFar = getRect().getHeight() / 2;
|
|
|
|
mHorizSlopNear = getRect().getWidth() / 4;
|
|
mHorizSlopFar = getRect().getWidth() / 2;
|
|
|
|
// Compute initial mouse offset based on initial quadrant.
|
|
// Place the mouse evenly between the near and far zones.
|
|
switch (mInitialQuadrant)
|
|
{
|
|
case JQ_ORIGIN:
|
|
mInitialOffset.set(0, 0);
|
|
break;
|
|
|
|
case JQ_UP:
|
|
mInitialOffset.mX = 0;
|
|
mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2;
|
|
break;
|
|
|
|
case JQ_DOWN:
|
|
mInitialOffset.mX = 0;
|
|
mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2;
|
|
break;
|
|
|
|
case JQ_LEFT:
|
|
mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2;
|
|
mInitialOffset.mY = 0;
|
|
break;
|
|
|
|
case JQ_RIGHT:
|
|
mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2;
|
|
mInitialOffset.mY = 0;
|
|
break;
|
|
|
|
default:
|
|
llerrs << "LLJoystick::LLJoystick() - bad switch case" << llendl;
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
F32 LLJoystickCameraZoom::getOrbitRate()
|
|
{
|
|
F32 time = getElapsedHeldDownTime();
|
|
if( time < NUDGE_TIME )
|
|
{
|
|
F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
|
|
// llinfos << "rate " << rate << " time " << time << llendl;
|
|
return rate;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|