diff options
Diffstat (limited to 'indra/newview/llmoveview.cpp')
-rw-r--r-- | indra/newview/llmoveview.cpp | 1462 |
1 files changed, 731 insertions, 731 deletions
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 33ee99a9d9..a8ceaffde8 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -1,731 +1,731 @@ -/**
- * @file llmoveview.cpp
- * @brief Container for movement buttons like forward, left, fly
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llmoveview.h"
-
-// Library includes
-#include "indra_constants.h"
-#include "llparcel.h"
-
-// Viewer includes
-
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llvoavatarself.h" // to check gAgentAvatarp->isSitting()
-#include "llbutton.h"
-#include "llfirstuse.h"
-#include "llfloaterreg.h"
-#include "llhints.h"
-#include "lljoystickbutton.h"
-#include "lluictrlfactory.h"
-#include "llviewerwindow.h"
-#include "llviewercontrol.h"
-#include "llselectmgr.h"
-#include "lltoolbarview.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h"
-#include "lltooltip.h"
-
-//
-// Constants
-//
-
-const F32 MOVE_BUTTON_DELAY = 0.0f;
-const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed
-const F32 NUDGE_TIME = 0.25f; // in seconds
-
-//
-// Member functions
-//
-
-// protected
-LLFloaterMove::LLFloaterMove(const LLSD& key)
-: LLFloater(key),
- mForwardButton(NULL),
- mBackwardButton(NULL),
- mTurnLeftButton(NULL),
- mTurnRightButton(NULL),
- mMoveUpButton(NULL),
- mMoveDownButton(NULL),
- mModeActionsPanel(NULL),
- mCurrentMode(MM_WALK)
-{
-}
-
-LLFloaterMove::~LLFloaterMove()
-{
- // Ensure LLPanelStandStopFlying panel is not among floater's children. See EXT-8458.
- setVisible(false);
-
- // Otherwise it can be destroyed and static pointer in LLPanelStandStopFlying::getInstance() will become invalid.
- // Such situation was possible when LLFloaterReg returns "dead" instance of floater.
- // Should not happen after LLFloater::destroy was modified to remove "dead" instances from LLFloaterReg.
-}
-
-// virtual
-bool LLFloaterMove::postBuild()
-{
- updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
-
- // Code that implements floater buttons toggling when user moves via keyboard is located in LLAgent::propagate()
-
- mForwardButton = getChild<LLJoystickAgentTurn>("forward btn");
- mForwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
-
- mBackwardButton = getChild<LLJoystickAgentTurn>("backward btn");
- mBackwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
-
- mSlideLeftButton = getChild<LLJoystickAgentSlide>("move left btn");
- mSlideLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
-
- mSlideRightButton = getChild<LLJoystickAgentSlide>("move right btn");
- mSlideRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
-
- mTurnLeftButton = getChild<LLButton>("turn left btn");
- mTurnLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnLeftButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnLeft, this));
- mTurnRightButton = getChild<LLButton>("turn right btn");
- mTurnRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnRightButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnRight, this));
-
- mMoveUpButton = getChild<LLButton>("move up btn");
- mMoveUpButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mMoveUpButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveUp, this));
-
- mMoveDownButton = getChild<LLButton>("move down btn");
- mMoveDownButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mMoveDownButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveDown, this));
-
-
- mModeActionsPanel = getChild<LLPanel>("panel_modes");
-
- LLButton* btn;
- btn = getChild<LLButton>("mode_walk_btn");
- btn->setCommitCallback(boost::bind(&LLFloaterMove::onWalkButtonClick, this));
-
- btn = getChild<LLButton>("mode_run_btn");
- btn->setCommitCallback(boost::bind(&LLFloaterMove::onRunButtonClick, this));
-
- btn = getChild<LLButton>("mode_fly_btn");
- btn->setCommitCallback(boost::bind(&LLFloaterMove::onFlyButtonClick, this));
-
- initModeTooltips();
-
- initModeButtonMap();
-
- initMovementMode();
-
- gAgent.addParcelChangedCallback(LLFloaterMove::sUpdateFlyingStatus);
-
- return true;
-}
-
-// *NOTE: we assume that setVisible() is called on floater close.
-// virtual
-void LLFloaterMove::setVisible(bool visible)
-{
- // Do nothing with Stand/Stop Flying panel in excessive calls of this method.
- if (getVisible() == visible)
- {
- LLFloater::setVisible(visible);
- return;
- }
-
- if (visible)
- {
- LLFirstUse::notMoving(false);
- // Attach the Stand/Stop Flying panel.
- LLPanelStandStopFlying* ssf_panel = LLPanelStandStopFlying::getInstance();
- ssf_panel->reparent(this);
- const LLRect& mode_actions_rect = mModeActionsPanel->getRect();
- ssf_panel->setOrigin(mode_actions_rect.mLeft, mode_actions_rect.mBottom);
- }
- else
- {
- // Detach the Stand/Stop Flying panel.
- LLPanelStandStopFlying::getInstance()->reparent(NULL);
- }
-
- LLFloater::setVisible(visible);
-}
-
-// static
-F32 LLFloaterMove::getYawRate( F32 time )
-{
- if( time < NUDGE_TIME )
- {
- F32 rate = YAW_NUDGE_RATE + time * (1 - YAW_NUDGE_RATE)/ NUDGE_TIME;
- return rate;
- }
- else
- {
- return 1.f;
- }
-}
-
-
-// static
-void LLFloaterMove::setFlyingMode(bool fly)
-{
- LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
- if (instance)
- {
- instance->setFlyingModeImpl(fly);
- LLVOAvatarSelf* avatar_object = gAgentAvatarp;
- bool is_sitting = avatar_object
- && (avatar_object->getRegion() != NULL)
- && (!avatar_object->isDead())
- && avatar_object->isSitting();
- instance->showModeButtons(!fly && !is_sitting);
- }
- if (fly)
- {
- LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
- }
- else
- {
- LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
- }
-}
-//static
-void LLFloaterMove::setAlwaysRunMode(bool run)
-{
- LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
- if (instance)
- {
- instance->setAlwaysRunModeImpl(run);
- }
-}
-
-void LLFloaterMove::setFlyingModeImpl(bool fly)
-{
- updateButtonsWithMovementMode(fly ? MM_FLY : (gAgent.getAlwaysRun() ? MM_RUN : MM_WALK));
-}
-
-void LLFloaterMove::setAlwaysRunModeImpl(bool run)
-{
- if (!gAgent.getFlying())
- {
- updateButtonsWithMovementMode(run ? MM_RUN : MM_WALK);
- }
-}
-
-//static
-void LLFloaterMove::setSittingMode(bool bSitting)
-{
- if (bSitting)
- {
- LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND);
- }
- else
- {
- LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND);
-
- // show "Stop Flying" button if needed. EXT-871
- if (gAgent.getFlying())
- {
- LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
- }
- }
- enableInstance();
-}
-
-// protected
-void LLFloaterMove::turnLeft()
-{
- F32 time = mTurnLeftButton->getHeldDownTime();
- gAgent.moveYaw( getYawRate( time ) );
-}
-
-// protected
-void LLFloaterMove::turnRight()
-{
- F32 time = mTurnRightButton->getHeldDownTime();
- gAgent.moveYaw( -getYawRate( time ) );
-}
-
-// protected
-void LLFloaterMove::moveUp()
-{
- // Jumps or flys up, depending on fly state
- gAgent.moveUp(1);
-}
-
-// protected
-void LLFloaterMove::moveDown()
-{
- // Crouches or flys down, depending on fly state
- gAgent.moveUp(-1);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Private Section:
-//////////////////////////////////////////////////////////////////////////
-
-void LLFloaterMove::onWalkButtonClick()
-{
- setMovementMode(MM_WALK);
-}
-void LLFloaterMove::onRunButtonClick()
-{
- setMovementMode(MM_RUN);
-}
-void LLFloaterMove::onFlyButtonClick()
-{
- setMovementMode(MM_FLY);
-}
-
-void LLFloaterMove::setMovementMode(const EMovementMode mode)
-{
- mCurrentMode = mode;
-
- if(MM_FLY == mode)
- {
- LLAgent::toggleFlying();
- }
- else
- {
- gAgent.setFlying(false);
- }
-
- // attempts to set avatar flying can not set it real flying in some cases.
- // For ex. when avatar fell down & is standing up.
- // So, no need to continue processing FLY mode. See EXT-1079
- if (MM_FLY == mode && !gAgent.getFlying())
- {
- return;
- }
-
- switch (mode)
- {
- case MM_RUN:
- gAgent.setAlwaysRun();
- gAgent.setRunning();
- break;
- case MM_WALK:
- gAgent.clearAlwaysRun();
- gAgent.clearRunning();
- break;
- default:
- //do nothing for other modes (MM_FLY)
- break;
- }
- // tell the simulator.
- gAgent.sendWalkRun(gAgent.getAlwaysRun());
-
- updateButtonsWithMovementMode(mode);
-
- bool bHideModeButtons = MM_FLY == mode
- || (isAgentAvatarValid() && gAgentAvatarp->isSitting());
-
- showModeButtons(!bHideModeButtons);
-
-}
-
-void LLFloaterMove::updateButtonsWithMovementMode(const EMovementMode newMode)
-{
- setModeTooltip(newMode);
- setModeButtonToggleState(newMode);
- setModeTitle(newMode);
-}
-
-void LLFloaterMove::initModeTooltips()
-{
- control_tooltip_map_t walkTipMap;
- walkTipMap.insert(std::make_pair(mForwardButton, getString("walk_forward_tooltip")));
- walkTipMap.insert(std::make_pair(mBackwardButton, getString("walk_back_tooltip")));
- walkTipMap.insert(std::make_pair(mSlideLeftButton, getString("walk_left_tooltip")));
- walkTipMap.insert(std::make_pair(mSlideRightButton, getString("walk_right_tooltip")));
- walkTipMap.insert(std::make_pair(mMoveUpButton, getString("jump_tooltip")));
- walkTipMap.insert(std::make_pair(mMoveDownButton, getString("crouch_tooltip")));
- mModeControlTooltipsMap[MM_WALK] = walkTipMap;
-
- control_tooltip_map_t runTipMap;
- runTipMap.insert(std::make_pair(mForwardButton, getString("run_forward_tooltip")));
- runTipMap.insert(std::make_pair(mBackwardButton, getString("run_back_tooltip")));
- runTipMap.insert(std::make_pair(mSlideLeftButton, getString("run_left_tooltip")));
- runTipMap.insert(std::make_pair(mSlideRightButton, getString("run_right_tooltip")));
- runTipMap.insert(std::make_pair(mMoveUpButton, getString("jump_tooltip")));
- runTipMap.insert(std::make_pair(mMoveDownButton, getString("crouch_tooltip")));
- mModeControlTooltipsMap[MM_RUN] = runTipMap;
-
- control_tooltip_map_t flyTipMap;
- flyTipMap.insert(std::make_pair(mForwardButton, getString("fly_forward_tooltip")));
- flyTipMap.insert(std::make_pair(mBackwardButton, getString("fly_back_tooltip")));
- flyTipMap.insert(std::make_pair(mSlideLeftButton, getString("fly_left_tooltip")));
- flyTipMap.insert(std::make_pair(mSlideRightButton, getString("fly_right_tooltip")));
- flyTipMap.insert(std::make_pair(mMoveUpButton, getString("fly_up_tooltip")));
- flyTipMap.insert(std::make_pair(mMoveDownButton, getString("fly_down_tooltip")));
- mModeControlTooltipsMap[MM_FLY] = flyTipMap;
-
- setModeTooltip(MM_WALK);
-}
-
-void LLFloaterMove::initModeButtonMap()
-{
- mModeControlButtonMap[MM_WALK] = getChild<LLButton>("mode_walk_btn");
- mModeControlButtonMap[MM_RUN] = getChild<LLButton>("mode_run_btn");
- mModeControlButtonMap[MM_FLY] = getChild<LLButton>("mode_fly_btn");
-}
-
-void LLFloaterMove::initMovementMode()
-{
- EMovementMode initMovementMode = gAgent.getAlwaysRun() ? MM_RUN : MM_WALK;
- if (gAgent.getFlying())
- {
- initMovementMode = MM_FLY;
- }
-
- mCurrentMode = initMovementMode;
- bool hide_mode_buttons = (MM_FLY == mCurrentMode) || (isAgentAvatarValid() && gAgentAvatarp->isSitting());
-
- updateButtonsWithMovementMode(mCurrentMode);
- showModeButtons(!hide_mode_buttons);
-}
-
-void LLFloaterMove::setModeTooltip(const EMovementMode mode)
-{
- llassert_always(mModeControlTooltipsMap.end() != mModeControlTooltipsMap.find(mode));
- control_tooltip_map_t controlsTipMap = mModeControlTooltipsMap[mode];
- control_tooltip_map_t::const_iterator it = controlsTipMap.begin();
- for (; it != controlsTipMap.end(); ++it)
- {
- LLView* ctrl = it->first;
- std::string tooltip = it->second;
- ctrl->setToolTip(tooltip);
- }
-}
-
-void LLFloaterMove::setModeTitle(const EMovementMode mode)
-{
- std::string title;
- switch(mode)
- {
- case MM_WALK:
- title = getString("walk_title");
- break;
- case MM_RUN:
- title = getString("run_title");
- break;
- case MM_FLY:
- title = getString("fly_title");
- break;
- default:
- // title should be provided for all modes
- llassert(false);
- break;
- }
- setTitle(title);
-}
-
-//static
-void LLFloaterMove::sUpdateFlyingStatus()
-{
- LLFloaterMove *floater = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
- if (floater) floater->mModeControlButtonMap[MM_FLY]->setEnabled(gAgent.canFly());
-
-}
-
-void LLFloaterMove::showModeButtons(bool bShow)
-{
- if (mModeActionsPanel->getVisible() == bShow)
- return;
- mModeActionsPanel->setVisible(bShow);
-}
-
-//static
-void LLFloaterMove::enableInstance()
-{
- LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
- if (instance)
- {
- if (gAgent.getFlying())
- {
- instance->showModeButtons(false);
- }
- else
- {
- instance->showModeButtons(isAgentAvatarValid() && !gAgentAvatarp->isSitting());
- }
- }
-}
-
-void LLFloaterMove::onOpen(const LLSD& key)
-{
- if (gAgent.getFlying())
- {
- setFlyingMode(true);
- showModeButtons(false);
- }
-
- if (isAgentAvatarValid() && gAgentAvatarp->isSitting())
- {
- setSittingMode(true);
- showModeButtons(false);
- }
-
- sUpdateFlyingStatus();
-}
-
-void LLFloaterMove::setModeButtonToggleState(const EMovementMode mode)
-{
- llassert_always(mModeControlButtonMap.end() != mModeControlButtonMap.find(mode));
-
- mode_control_button_map_t::const_iterator it = mModeControlButtonMap.begin();
- for (; it != mModeControlButtonMap.end(); ++it)
- {
- it->second->setToggleState(false);
- }
-
- mModeControlButtonMap[mode]->setToggleState(true);
-}
-
-
-
-/************************************************************************/
-/* LLPanelStandStopFlying */
-/************************************************************************/
-LLPanelStandStopFlying::LLPanelStandStopFlying() :
- mStandButton(NULL),
- mStopFlyingButton(NULL),
- mAttached(false)
-{
- // make sure we have the only instance of this class
- static bool b = true;
- llassert_always(b);
- b=false;
-}
-
-// static
-LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
-{
- static LLPanelStandStopFlying* panel = getStandStopFlyingPanel();
- return panel;
-}
-
-//static
-void LLPanelStandStopFlying::setStandStopFlyingMode(EStandStopFlyingMode mode)
-{
- LLPanelStandStopFlying* panel = getInstance();
-
- if (mode == SSFM_STAND)
- {
- LLFirstUse::sit();
- LLFirstUse::notMoving(false);
- }
- panel->mStandButton->setVisible(SSFM_STAND == mode);
- panel->mStopFlyingButton->setVisible(SSFM_STOP_FLYING == mode);
-
- //visibility of it should be updated after updating visibility of the buttons
- panel->setVisible(true);
-}
-
-//static
-void LLPanelStandStopFlying::clearStandStopFlyingMode(EStandStopFlyingMode mode)
-{
- LLPanelStandStopFlying* panel = getInstance();
- switch(mode) {
- case SSFM_STAND:
- panel->mStandButton->setVisible(false);
- break;
- case SSFM_STOP_FLYING:
- panel->mStopFlyingButton->setVisible(false);
- break;
- default:
- LL_ERRS() << "Unexpected EStandStopFlyingMode is passed: " << mode << LL_ENDL;
- }
-
-}
-
-bool LLPanelStandStopFlying::postBuild()
-{
- mStandButton = getChild<LLButton>("stand_btn");
- mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this));
- mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance));
- mStandButton->setVisible(false);
- LLHints::getInstance()->registerHintTarget("stand_btn", mStandButton->getHandle());
-
- mStopFlyingButton = getChild<LLButton>("stop_fly_btn");
- //mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, false));
- mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));
- mStopFlyingButton->setVisible(false);
-
- gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelStandStopFlying::updatePosition, this));
-
- return true;
-}
-
-//virtual
-void LLPanelStandStopFlying::setVisible(bool visible)
-{
- //we dont need to show the panel if these buttons are not activated
- if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) visible = false;
-
- if (visible)
- {
- updatePosition();
- }
-
- // do not change parent visibility in case panel is attached into Move Floater: EXT-3632, EXT-4646
- if (!mAttached)
- {
- //change visibility of parent layout_panel to animate in/out. EXT-2504
- if (getParent()) getParent()->setVisible(visible);
- }
-
- // also change own visibility to avoid displaying the panel in mouselook (broken when EXT-2504 was implemented).
- // See EXT-4718.
- LLPanel::setVisible(visible);
-}
-
-bool LLPanelStandStopFlying::handleToolTip(S32 x, S32 y, MASK mask)
-{
- LLToolTipMgr::instance().unblockToolTips();
-
- if (mStandButton->getVisible())
- {
- LLToolTipMgr::instance().show(mStandButton->getToolTip());
- }
- else if (mStopFlyingButton->getVisible())
- {
- LLToolTipMgr::instance().show(mStopFlyingButton->getToolTip());
- }
-
- return LLPanel::handleToolTip(x, y, mask);
-}
-
-void LLPanelStandStopFlying::reparent(LLFloaterMove* move_view)
-{
- LLPanel* parent = dynamic_cast<LLPanel*>(getParent());
- if (!parent)
- {
- LL_WARNS() << "Stand/stop flying panel parent is unset, already attached?: " << mAttached << ", new parent: " << (move_view == NULL ? "NULL" : "Move Floater") << LL_ENDL;
- return;
- }
-
- if (move_view != NULL)
- {
- llassert(move_view != parent); // sanity check
-
- // Save our original container.
- if (!mOriginalParent.get())
- mOriginalParent = parent->getHandle();
-
- // Attach to movement controls.
- parent->removeChild(this);
- move_view->addChild(this);
- // Origin must be set by movement controls.
- mAttached = true;
- }
- else
- {
- if (!mOriginalParent.get())
- {
- LL_WARNS() << "Original parent of the stand / stop flying panel not found" << LL_ENDL;
- return;
- }
-
- // Detach from movement controls.
- parent->removeChild(this);
- mOriginalParent.get()->addChild(this);
- // update parent with self visibility (it is changed in setVisible()). EXT-4743
- mOriginalParent.get()->setVisible(getVisible());
-
- mAttached = false;
- updatePosition(); // don't defer until next draw() to avoid flicker
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Private Section
-//////////////////////////////////////////////////////////////////////////
-
-//static
-LLPanelStandStopFlying* LLPanelStandStopFlying::getStandStopFlyingPanel()
-{
- LLPanelStandStopFlying* panel = new LLPanelStandStopFlying();
- panel->buildFromFile("panel_stand_stop_flying.xml");
-
- panel->setVisible(false);
- //LLUI::getInstance()->getRootView()->addChild(panel);
-
- LL_INFOS() << "Build LLPanelStandStopFlying panel" << LL_ENDL;
-
- panel->updatePosition();
- return panel;
-}
-
-void LLPanelStandStopFlying::onStandButtonClick()
-{
- LLFirstUse::sit(false);
-
- LLSelectMgr::getInstance()->deselectAllForStandingUp();
- gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
-
- setFocus(false);
-}
-
-void LLPanelStandStopFlying::onStopFlyingButtonClick()
-{
- gAgent.setFlying(false);
-
- setFocus(false); // EXT-482
-}
-
-/**
- * Updates position of the Stand & Stop Flying panel to be center aligned with Move button.
- */
-void LLPanelStandStopFlying::updatePosition()
-{
- if (mAttached) return;
-
- S32 bottom_tb_center = 0;
- if (LLToolBar* toolbar_bottom = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_BOTTOM))
- {
- bottom_tb_center = toolbar_bottom->getRect().getCenterX();
- }
-
- S32 left_tb_width = 0;
- if (LLToolBar* toolbar_left = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT))
- {
- left_tb_width = toolbar_left->getRect().getWidth();
- }
-
- if (gToolBarView != NULL && gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)->hasButtons())
- {
- S32 x_pos = bottom_tb_center - getRect().getWidth() / 2 - left_tb_width;
- setOrigin( x_pos, 0);
- }
- else
- {
- S32 x_pos = bottom_tb_center - getRect().getWidth() / 2;
- setOrigin( x_pos, 0);
- }
-}
-
-// EOF
+/** + * @file llmoveview.cpp + * @brief Container for movement buttons like forward, left, fly + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmoveview.h" + +// Library includes +#include "indra_constants.h" +#include "llparcel.h" + +// Viewer includes + +#include "llagent.h" +#include "llagentcamera.h" +#include "llvoavatarself.h" // to check gAgentAvatarp->isSitting() +#include "llbutton.h" +#include "llfirstuse.h" +#include "llfloaterreg.h" +#include "llhints.h" +#include "lljoystickbutton.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" +#include "llviewercontrol.h" +#include "llselectmgr.h" +#include "lltoolbarview.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "lltooltip.h" + +// +// Constants +// + +const F32 MOVE_BUTTON_DELAY = 0.0f; +const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed +const F32 NUDGE_TIME = 0.25f; // in seconds + +// +// Member functions +// + +// protected +LLFloaterMove::LLFloaterMove(const LLSD& key) +: LLFloater(key), + mForwardButton(NULL), + mBackwardButton(NULL), + mTurnLeftButton(NULL), + mTurnRightButton(NULL), + mMoveUpButton(NULL), + mMoveDownButton(NULL), + mModeActionsPanel(NULL), + mCurrentMode(MM_WALK) +{ +} + +LLFloaterMove::~LLFloaterMove() +{ + // Ensure LLPanelStandStopFlying panel is not among floater's children. See EXT-8458. + setVisible(false); + + // Otherwise it can be destroyed and static pointer in LLPanelStandStopFlying::getInstance() will become invalid. + // Such situation was possible when LLFloaterReg returns "dead" instance of floater. + // Should not happen after LLFloater::destroy was modified to remove "dead" instances from LLFloaterReg. +} + +// virtual +bool LLFloaterMove::postBuild() +{ + updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730) + + // Code that implements floater buttons toggling when user moves via keyboard is located in LLAgent::propagate() + + mForwardButton = getChild<LLJoystickAgentTurn>("forward btn"); + mForwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + + mBackwardButton = getChild<LLJoystickAgentTurn>("backward btn"); + mBackwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + + mSlideLeftButton = getChild<LLJoystickAgentSlide>("move left btn"); + mSlideLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + + mSlideRightButton = getChild<LLJoystickAgentSlide>("move right btn"); + mSlideRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + + mTurnLeftButton = getChild<LLButton>("turn left btn"); + mTurnLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + mTurnLeftButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnLeft, this)); + mTurnRightButton = getChild<LLButton>("turn right btn"); + mTurnRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + mTurnRightButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnRight, this)); + + mMoveUpButton = getChild<LLButton>("move up btn"); + mMoveUpButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + mMoveUpButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveUp, this)); + + mMoveDownButton = getChild<LLButton>("move down btn"); + mMoveDownButton->setHeldDownDelay(MOVE_BUTTON_DELAY); + mMoveDownButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveDown, this)); + + + mModeActionsPanel = getChild<LLPanel>("panel_modes"); + + LLButton* btn; + btn = getChild<LLButton>("mode_walk_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onWalkButtonClick, this)); + + btn = getChild<LLButton>("mode_run_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onRunButtonClick, this)); + + btn = getChild<LLButton>("mode_fly_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onFlyButtonClick, this)); + + initModeTooltips(); + + initModeButtonMap(); + + initMovementMode(); + + gAgent.addParcelChangedCallback(LLFloaterMove::sUpdateFlyingStatus); + + return true; +} + +// *NOTE: we assume that setVisible() is called on floater close. +// virtual +void LLFloaterMove::setVisible(bool visible) +{ + // Do nothing with Stand/Stop Flying panel in excessive calls of this method. + if (getVisible() == visible) + { + LLFloater::setVisible(visible); + return; + } + + if (visible) + { + LLFirstUse::notMoving(false); + // Attach the Stand/Stop Flying panel. + LLPanelStandStopFlying* ssf_panel = LLPanelStandStopFlying::getInstance(); + ssf_panel->reparent(this); + const LLRect& mode_actions_rect = mModeActionsPanel->getRect(); + ssf_panel->setOrigin(mode_actions_rect.mLeft, mode_actions_rect.mBottom); + } + else + { + // Detach the Stand/Stop Flying panel. + LLPanelStandStopFlying::getInstance()->reparent(NULL); + } + + LLFloater::setVisible(visible); +} + +// static +F32 LLFloaterMove::getYawRate( F32 time ) +{ + if( time < NUDGE_TIME ) + { + F32 rate = YAW_NUDGE_RATE + time * (1 - YAW_NUDGE_RATE)/ NUDGE_TIME; + return rate; + } + else + { + return 1.f; + } +} + + +// static +void LLFloaterMove::setFlyingMode(bool fly) +{ + LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (instance) + { + instance->setFlyingModeImpl(fly); + LLVOAvatarSelf* avatar_object = gAgentAvatarp; + bool is_sitting = avatar_object + && (avatar_object->getRegion() != NULL) + && (!avatar_object->isDead()) + && avatar_object->isSitting(); + instance->showModeButtons(!fly && !is_sitting); + } + if (fly) + { + LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING); + } + else + { + LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING); + } +} +//static +void LLFloaterMove::setAlwaysRunMode(bool run) +{ + LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (instance) + { + instance->setAlwaysRunModeImpl(run); + } +} + +void LLFloaterMove::setFlyingModeImpl(bool fly) +{ + updateButtonsWithMovementMode(fly ? MM_FLY : (gAgent.getAlwaysRun() ? MM_RUN : MM_WALK)); +} + +void LLFloaterMove::setAlwaysRunModeImpl(bool run) +{ + if (!gAgent.getFlying()) + { + updateButtonsWithMovementMode(run ? MM_RUN : MM_WALK); + } +} + +//static +void LLFloaterMove::setSittingMode(bool bSitting) +{ + if (bSitting) + { + LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND); + } + else + { + LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND); + + // show "Stop Flying" button if needed. EXT-871 + if (gAgent.getFlying()) + { + LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING); + } + } + enableInstance(); +} + +// protected +void LLFloaterMove::turnLeft() +{ + F32 time = mTurnLeftButton->getHeldDownTime(); + gAgent.moveYaw( getYawRate( time ) ); +} + +// protected +void LLFloaterMove::turnRight() +{ + F32 time = mTurnRightButton->getHeldDownTime(); + gAgent.moveYaw( -getYawRate( time ) ); +} + +// protected +void LLFloaterMove::moveUp() +{ + // Jumps or flys up, depending on fly state + gAgent.moveUp(1); +} + +// protected +void LLFloaterMove::moveDown() +{ + // Crouches or flys down, depending on fly state + gAgent.moveUp(-1); +} + +////////////////////////////////////////////////////////////////////////// +// Private Section: +////////////////////////////////////////////////////////////////////////// + +void LLFloaterMove::onWalkButtonClick() +{ + setMovementMode(MM_WALK); +} +void LLFloaterMove::onRunButtonClick() +{ + setMovementMode(MM_RUN); +} +void LLFloaterMove::onFlyButtonClick() +{ + setMovementMode(MM_FLY); +} + +void LLFloaterMove::setMovementMode(const EMovementMode mode) +{ + mCurrentMode = mode; + + if(MM_FLY == mode) + { + LLAgent::toggleFlying(); + } + else + { + gAgent.setFlying(false); + } + + // attempts to set avatar flying can not set it real flying in some cases. + // For ex. when avatar fell down & is standing up. + // So, no need to continue processing FLY mode. See EXT-1079 + if (MM_FLY == mode && !gAgent.getFlying()) + { + return; + } + + switch (mode) + { + case MM_RUN: + gAgent.setAlwaysRun(); + gAgent.setRunning(); + break; + case MM_WALK: + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + break; + default: + //do nothing for other modes (MM_FLY) + break; + } + // tell the simulator. + gAgent.sendWalkRun(gAgent.getAlwaysRun()); + + updateButtonsWithMovementMode(mode); + + bool bHideModeButtons = MM_FLY == mode + || (isAgentAvatarValid() && gAgentAvatarp->isSitting()); + + showModeButtons(!bHideModeButtons); + +} + +void LLFloaterMove::updateButtonsWithMovementMode(const EMovementMode newMode) +{ + setModeTooltip(newMode); + setModeButtonToggleState(newMode); + setModeTitle(newMode); +} + +void LLFloaterMove::initModeTooltips() +{ + control_tooltip_map_t walkTipMap; + walkTipMap.insert(std::make_pair(mForwardButton, getString("walk_forward_tooltip"))); + walkTipMap.insert(std::make_pair(mBackwardButton, getString("walk_back_tooltip"))); + walkTipMap.insert(std::make_pair(mSlideLeftButton, getString("walk_left_tooltip"))); + walkTipMap.insert(std::make_pair(mSlideRightButton, getString("walk_right_tooltip"))); + walkTipMap.insert(std::make_pair(mMoveUpButton, getString("jump_tooltip"))); + walkTipMap.insert(std::make_pair(mMoveDownButton, getString("crouch_tooltip"))); + mModeControlTooltipsMap[MM_WALK] = walkTipMap; + + control_tooltip_map_t runTipMap; + runTipMap.insert(std::make_pair(mForwardButton, getString("run_forward_tooltip"))); + runTipMap.insert(std::make_pair(mBackwardButton, getString("run_back_tooltip"))); + runTipMap.insert(std::make_pair(mSlideLeftButton, getString("run_left_tooltip"))); + runTipMap.insert(std::make_pair(mSlideRightButton, getString("run_right_tooltip"))); + runTipMap.insert(std::make_pair(mMoveUpButton, getString("jump_tooltip"))); + runTipMap.insert(std::make_pair(mMoveDownButton, getString("crouch_tooltip"))); + mModeControlTooltipsMap[MM_RUN] = runTipMap; + + control_tooltip_map_t flyTipMap; + flyTipMap.insert(std::make_pair(mForwardButton, getString("fly_forward_tooltip"))); + flyTipMap.insert(std::make_pair(mBackwardButton, getString("fly_back_tooltip"))); + flyTipMap.insert(std::make_pair(mSlideLeftButton, getString("fly_left_tooltip"))); + flyTipMap.insert(std::make_pair(mSlideRightButton, getString("fly_right_tooltip"))); + flyTipMap.insert(std::make_pair(mMoveUpButton, getString("fly_up_tooltip"))); + flyTipMap.insert(std::make_pair(mMoveDownButton, getString("fly_down_tooltip"))); + mModeControlTooltipsMap[MM_FLY] = flyTipMap; + + setModeTooltip(MM_WALK); +} + +void LLFloaterMove::initModeButtonMap() +{ + mModeControlButtonMap[MM_WALK] = getChild<LLButton>("mode_walk_btn"); + mModeControlButtonMap[MM_RUN] = getChild<LLButton>("mode_run_btn"); + mModeControlButtonMap[MM_FLY] = getChild<LLButton>("mode_fly_btn"); +} + +void LLFloaterMove::initMovementMode() +{ + EMovementMode initMovementMode = gAgent.getAlwaysRun() ? MM_RUN : MM_WALK; + if (gAgent.getFlying()) + { + initMovementMode = MM_FLY; + } + + mCurrentMode = initMovementMode; + bool hide_mode_buttons = (MM_FLY == mCurrentMode) || (isAgentAvatarValid() && gAgentAvatarp->isSitting()); + + updateButtonsWithMovementMode(mCurrentMode); + showModeButtons(!hide_mode_buttons); +} + +void LLFloaterMove::setModeTooltip(const EMovementMode mode) +{ + llassert_always(mModeControlTooltipsMap.end() != mModeControlTooltipsMap.find(mode)); + control_tooltip_map_t controlsTipMap = mModeControlTooltipsMap[mode]; + control_tooltip_map_t::const_iterator it = controlsTipMap.begin(); + for (; it != controlsTipMap.end(); ++it) + { + LLView* ctrl = it->first; + std::string tooltip = it->second; + ctrl->setToolTip(tooltip); + } +} + +void LLFloaterMove::setModeTitle(const EMovementMode mode) +{ + std::string title; + switch(mode) + { + case MM_WALK: + title = getString("walk_title"); + break; + case MM_RUN: + title = getString("run_title"); + break; + case MM_FLY: + title = getString("fly_title"); + break; + default: + // title should be provided for all modes + llassert(false); + break; + } + setTitle(title); +} + +//static +void LLFloaterMove::sUpdateFlyingStatus() +{ + LLFloaterMove *floater = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (floater) floater->mModeControlButtonMap[MM_FLY]->setEnabled(gAgent.canFly()); + +} + +void LLFloaterMove::showModeButtons(bool bShow) +{ + if (mModeActionsPanel->getVisible() == bShow) + return; + mModeActionsPanel->setVisible(bShow); +} + +//static +void LLFloaterMove::enableInstance() +{ + LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (instance) + { + if (gAgent.getFlying()) + { + instance->showModeButtons(false); + } + else + { + instance->showModeButtons(isAgentAvatarValid() && !gAgentAvatarp->isSitting()); + } + } +} + +void LLFloaterMove::onOpen(const LLSD& key) +{ + if (gAgent.getFlying()) + { + setFlyingMode(true); + showModeButtons(false); + } + + if (isAgentAvatarValid() && gAgentAvatarp->isSitting()) + { + setSittingMode(true); + showModeButtons(false); + } + + sUpdateFlyingStatus(); +} + +void LLFloaterMove::setModeButtonToggleState(const EMovementMode mode) +{ + llassert_always(mModeControlButtonMap.end() != mModeControlButtonMap.find(mode)); + + mode_control_button_map_t::const_iterator it = mModeControlButtonMap.begin(); + for (; it != mModeControlButtonMap.end(); ++it) + { + it->second->setToggleState(false); + } + + mModeControlButtonMap[mode]->setToggleState(true); +} + + + +/************************************************************************/ +/* LLPanelStandStopFlying */ +/************************************************************************/ +LLPanelStandStopFlying::LLPanelStandStopFlying() : + mStandButton(NULL), + mStopFlyingButton(NULL), + mAttached(false) +{ + // make sure we have the only instance of this class + static bool b = true; + llassert_always(b); + b=false; +} + +// static +LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance() +{ + static LLPanelStandStopFlying* panel = getStandStopFlyingPanel(); + return panel; +} + +//static +void LLPanelStandStopFlying::setStandStopFlyingMode(EStandStopFlyingMode mode) +{ + LLPanelStandStopFlying* panel = getInstance(); + + if (mode == SSFM_STAND) + { + LLFirstUse::sit(); + LLFirstUse::notMoving(false); + } + panel->mStandButton->setVisible(SSFM_STAND == mode); + panel->mStopFlyingButton->setVisible(SSFM_STOP_FLYING == mode); + + //visibility of it should be updated after updating visibility of the buttons + panel->setVisible(true); +} + +//static +void LLPanelStandStopFlying::clearStandStopFlyingMode(EStandStopFlyingMode mode) +{ + LLPanelStandStopFlying* panel = getInstance(); + switch(mode) { + case SSFM_STAND: + panel->mStandButton->setVisible(false); + break; + case SSFM_STOP_FLYING: + panel->mStopFlyingButton->setVisible(false); + break; + default: + LL_ERRS() << "Unexpected EStandStopFlyingMode is passed: " << mode << LL_ENDL; + } + +} + +bool LLPanelStandStopFlying::postBuild() +{ + mStandButton = getChild<LLButton>("stand_btn"); + mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this)); + mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance)); + mStandButton->setVisible(false); + LLHints::getInstance()->registerHintTarget("stand_btn", mStandButton->getHandle()); + + mStopFlyingButton = getChild<LLButton>("stop_fly_btn"); + //mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, false)); + mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this)); + mStopFlyingButton->setVisible(false); + + gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelStandStopFlying::updatePosition, this)); + + return true; +} + +//virtual +void LLPanelStandStopFlying::setVisible(bool visible) +{ + //we dont need to show the panel if these buttons are not activated + if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) visible = false; + + if (visible) + { + updatePosition(); + } + + // do not change parent visibility in case panel is attached into Move Floater: EXT-3632, EXT-4646 + if (!mAttached) + { + //change visibility of parent layout_panel to animate in/out. EXT-2504 + if (getParent()) getParent()->setVisible(visible); + } + + // also change own visibility to avoid displaying the panel in mouselook (broken when EXT-2504 was implemented). + // See EXT-4718. + LLPanel::setVisible(visible); +} + +bool LLPanelStandStopFlying::handleToolTip(S32 x, S32 y, MASK mask) +{ + LLToolTipMgr::instance().unblockToolTips(); + + if (mStandButton->getVisible()) + { + LLToolTipMgr::instance().show(mStandButton->getToolTip()); + } + else if (mStopFlyingButton->getVisible()) + { + LLToolTipMgr::instance().show(mStopFlyingButton->getToolTip()); + } + + return LLPanel::handleToolTip(x, y, mask); +} + +void LLPanelStandStopFlying::reparent(LLFloaterMove* move_view) +{ + LLPanel* parent = dynamic_cast<LLPanel*>(getParent()); + if (!parent) + { + LL_WARNS() << "Stand/stop flying panel parent is unset, already attached?: " << mAttached << ", new parent: " << (move_view == NULL ? "NULL" : "Move Floater") << LL_ENDL; + return; + } + + if (move_view != NULL) + { + llassert(move_view != parent); // sanity check + + // Save our original container. + if (!mOriginalParent.get()) + mOriginalParent = parent->getHandle(); + + // Attach to movement controls. + parent->removeChild(this); + move_view->addChild(this); + // Origin must be set by movement controls. + mAttached = true; + } + else + { + if (!mOriginalParent.get()) + { + LL_WARNS() << "Original parent of the stand / stop flying panel not found" << LL_ENDL; + return; + } + + // Detach from movement controls. + parent->removeChild(this); + mOriginalParent.get()->addChild(this); + // update parent with self visibility (it is changed in setVisible()). EXT-4743 + mOriginalParent.get()->setVisible(getVisible()); + + mAttached = false; + updatePosition(); // don't defer until next draw() to avoid flicker + } +} + +////////////////////////////////////////////////////////////////////////// +// Private Section +////////////////////////////////////////////////////////////////////////// + +//static +LLPanelStandStopFlying* LLPanelStandStopFlying::getStandStopFlyingPanel() +{ + LLPanelStandStopFlying* panel = new LLPanelStandStopFlying(); + panel->buildFromFile("panel_stand_stop_flying.xml"); + + panel->setVisible(false); + //LLUI::getInstance()->getRootView()->addChild(panel); + + LL_INFOS() << "Build LLPanelStandStopFlying panel" << LL_ENDL; + + panel->updatePosition(); + return panel; +} + +void LLPanelStandStopFlying::onStandButtonClick() +{ + LLFirstUse::sit(false); + + LLSelectMgr::getInstance()->deselectAllForStandingUp(); + gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + + setFocus(false); +} + +void LLPanelStandStopFlying::onStopFlyingButtonClick() +{ + gAgent.setFlying(false); + + setFocus(false); // EXT-482 +} + +/** + * Updates position of the Stand & Stop Flying panel to be center aligned with Move button. + */ +void LLPanelStandStopFlying::updatePosition() +{ + if (mAttached) return; + + S32 bottom_tb_center = 0; + if (LLToolBar* toolbar_bottom = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_BOTTOM)) + { + bottom_tb_center = toolbar_bottom->getRect().getCenterX(); + } + + S32 left_tb_width = 0; + if (LLToolBar* toolbar_left = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)) + { + left_tb_width = toolbar_left->getRect().getWidth(); + } + + if (gToolBarView != NULL && gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)->hasButtons()) + { + S32 x_pos = bottom_tb_center - getRect().getWidth() / 2 - left_tb_width; + setOrigin( x_pos, 0); + } + else + { + S32 x_pos = bottom_tb_center - getRect().getWidth() / 2; + setOrigin( x_pos, 0); + } +} + +// EOF |