summaryrefslogtreecommitdiff
path: root/indra/newview/llmoveview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmoveview.cpp')
-rw-r--r--indra/newview/llmoveview.cpp730
1 files changed, 635 insertions, 95 deletions
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index eea729393c..6658e1d7e8 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -2,30 +2,25 @@
* @file llmoveview.cpp
* @brief Container for movement buttons like forward, left, fly
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * 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://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * 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.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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$
*/
@@ -35,14 +30,26 @@
// Library includes
#include "indra_constants.h"
+#include "llparcel.h"
// Viewer includes
+
#include "llagent.h"
-#include "llviewercontrol.h"
+#include "llagentcamera.h"
+#include "llvoavatarself.h" // to check gAgentAvatarp->isSitting()
+#include "llbottomtray.h"
#include "llbutton.h"
-#include "llviewerwindow.h"
+#include "llfirstuse.h"
+#include "llfloaterreg.h"
+#include "llhints.h"
#include "lljoystickbutton.h"
-#include "llvieweruictrlfactory.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+#include "llviewercontrol.h"
+#include "llselectmgr.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "lltooltip.h"
//
// Constants
@@ -52,155 +59,688 @@ 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
-//
-// Global statics
-//
-
-LLFloaterMove* LLFloaterMove::sInstance = NULL;
-
+const std::string BOTTOM_TRAY_BUTTON_NAME = "movement_btn";
//
// Member functions
//
// protected
-LLFloaterMove::LLFloaterMove()
-: LLFloater("move floater")
+LLFloaterMove::LLFloaterMove(const LLSD& key)
+: LLTransientDockableFloater(NULL, true, 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()
{
setIsChrome(TRUE);
- gUICtrlFactory->buildFloater(this,"floater_moveview.xml");
+ setTitleVisible(TRUE); // restore title visibility after chrome applying
+
+ LLDockableFloater::postBuild();
+
+ // Code that implements floater buttons toggling when user moves via keyboard is located in LLAgent::propagate()
- mForwardButton = LLViewerUICtrlFactory::getJoystickAgentTurnByName(this, "forward btn");
+ mForwardButton = getChild<LLJoystickAgentTurn>("forward btn");
mForwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mBackwardButton = LLViewerUICtrlFactory::getJoystickAgentTurnByName(this, "backward btn");
+ mBackwardButton = getChild<LLJoystickAgentTurn>("backward btn");
mBackwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mSlideLeftButton = LLViewerUICtrlFactory::getJoystickAgentSlideByName(this, "slide left btn");
+ mSlideLeftButton = getChild<LLJoystickAgentSlide>("move left btn");
mSlideLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mSlideRightButton = LLViewerUICtrlFactory::getJoystickAgentSlideByName(this, "slide right btn");
+ mSlideRightButton = getChild<LLJoystickAgentSlide>("move right btn");
mSlideRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnLeftButton = LLUICtrlFactory::getButtonByName(this, "turn left btn");
+ mTurnLeftButton = getChild<LLButton>("turn left btn");
mTurnLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnLeftButton->setHeldDownCallback( turnLeft );
-
- mTurnRightButton = LLUICtrlFactory::getButtonByName(this, "turn right btn");
+ mTurnLeftButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnLeft, this));
+ mTurnRightButton = getChild<LLButton>("turn right btn");
mTurnRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnRightButton->setHeldDownCallback( turnRight );
+ mTurnRightButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnRight, this));
- mMoveUpButton = LLUICtrlFactory::getButtonByName(this, "move up btn");
- childSetAction("move up btn",moveUp,NULL);
+ mMoveUpButton = getChild<LLButton>("move up btn");
mMoveUpButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mMoveUpButton->setHeldDownCallback( moveUp );
+ mMoveUpButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveUp, this));
- mMoveDownButton = LLUICtrlFactory::getButtonByName(this, "move down btn");
- childSetAction("move down btn",moveDown,NULL);
+ mMoveDownButton = getChild<LLButton>("move down btn");
mMoveDownButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mMoveDownButton->setHeldDownCallback( moveDown );
+ mMoveDownButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveDown, this));
- sInstance = this;
-}
-// protected
-LLFloaterMove::~LLFloaterMove()
-{
- // children all deleted by LLView destructor
- sInstance = NULL;
+ 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();
+
+ LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(LLFloaterMove::sUpdateFlyingStatus);
+
+ return TRUE;
}
+// *NOTE: we assume that setVisible() is called on floater close.
// virtual
-void LLFloaterMove::onClose(bool app_quitting)
+void LLFloaterMove::setVisible(BOOL visible)
{
- LLFloater::onClose(app_quitting);
-
- if (!app_quitting)
+ // Do nothing with Stand/Stop Flying panel in excessive calls of this method (from LLTransientFloaterMgr?).
+ if (getVisible() == visible)
{
- gSavedSettings.setBOOL("ShowMovementControls", FALSE);
+ LLTransientDockableFloater::setVisible(visible);
+ return;
}
-}
-//
-// Static member functions
-//
+ 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);
+ }
-// static
-void LLFloaterMove::show(void*)
+ LLTransientDockableFloater::setVisible(visible);
+}
+
+// static
+F32 LLFloaterMove::getYawRate( F32 time )
{
- if (sInstance)
+ if( time < NUDGE_TIME )
{
- sInstance->open(); /*Flawfinder: ignore*/
+ F32 rate = YAW_NUDGE_RATE + time * (1 - YAW_NUDGE_RATE)/ NUDGE_TIME;
+ return rate;
}
else
{
- LLFloaterMove* f = new LLFloaterMove();
- f->open(); /*Flawfinder: ignore*/
+ return 1.f;
}
-
- gSavedSettings.setBOOL("ShowMovementControls", TRUE);
}
-// static
-void LLFloaterMove::toggle(void*)
+
+// static
+void LLFloaterMove::setFlyingMode(BOOL fly)
{
- if (sInstance)
+ 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)
{
- sInstance->close();
+ LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
}
else
{
- show(NULL);
+ LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
+ }
+}
+//static
+void LLFloaterMove::setAlwaysRunMode(bool run)
+{
+ LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
+ if (instance)
+ {
+ instance->setAlwaysRunModeImpl(run);
}
}
-// static
-BOOL LLFloaterMove::visible(void*)
+void LLFloaterMove::setFlyingModeImpl(BOOL fly)
{
- return (sInstance != NULL);
+ updateButtonsWithMovementMode(fly ? MM_FLY : (gAgent.getAlwaysRun() ? MM_RUN : MM_WALK));
}
+void LLFloaterMove::setAlwaysRunModeImpl(bool run)
+{
+ if (!gAgent.getFlying())
+ {
+ updateButtonsWithMovementMode(run ? MM_RUN : MM_WALK);
+ }
+}
-// protected static
-F32 LLFloaterMove::getYawRate( F32 time )
+//static
+void LLFloaterMove::setSittingMode(BOOL bSitting)
{
- if( time < NUDGE_TIME )
+ if (bSitting)
{
- F32 rate = YAW_NUDGE_RATE + time * (1 - YAW_NUDGE_RATE)/ NUDGE_TIME;
- return rate;
+ LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND);
}
else
{
- return 1.f;
+ LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND);
+
+ // show "Stop Flying" button if needed. EXT-871
+ if (gAgent.getFlying())
+ {
+ LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
+ }
}
+ enableInstance(!bSitting);
}
-// protected static
-void LLFloaterMove::turnLeft(void *)
+// protected
+void LLFloaterMove::turnLeft()
{
- F32 time = sInstance->mTurnLeftButton->getHeldDownTime();
+ F32 time = mTurnLeftButton->getHeldDownTime();
gAgent.moveYaw( getYawRate( time ) );
}
-// protected static
-void LLFloaterMove::turnRight(void *)
+// protected
+void LLFloaterMove::turnRight()
{
- F32 time = sInstance->mTurnRightButton->getHeldDownTime();
+ F32 time = mTurnRightButton->getHeldDownTime();
gAgent.moveYaw( -getYawRate( time ) );
}
-// protected static
-void LLFloaterMove::moveUp(void *)
+// protected
+void LLFloaterMove::moveUp()
{
// Jumps or flys up, depending on fly state
gAgent.moveUp(1);
}
-// protected static
-void LLFloaterMove::moveDown(void *)
+// 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;
+ gAgent.setFlying(MM_FLY == mode);
+
+ // 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;
+ }
+ setMovementMode(initMovementMode);
+
+ if (isAgentAvatarValid())
+ {
+ showModeButtons(!gAgentAvatarp->isSitting());
+ }
+}
+
+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);
+}
+
+/**
+ * Updates position of the floater to be center aligned with Move button.
+ */
+void LLFloaterMove::updatePosition()
+{
+ LLBottomTray* tray = LLBottomTray::getInstance();
+ if (!tray) return;
+
+ LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
+
+ //align centers of a button and a floater
+ S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+
+ S32 y = 0;
+ if (!mModeActionsPanel->getVisible())
+ {
+ y = mModeActionsPanel->getRect().getHeight();
+ }
+ setOrigin(x, y);
+}
+
+//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(BOOL bEnable)
+{
+ LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
+ if (instance)
+ {
+ if (gAgent.getFlying())
+ {
+ instance->showModeButtons(FALSE);
+ }
+ else
+ {
+ instance->showModeButtons(bEnable);
+ }
+ }
+}
+
+void LLFloaterMove::onOpen(const LLSD& key)
+{
+ LLButton *anchor_panel = LLBottomTray::getInstance()->getChild<LLButton>("movement_btn");
+
+ if (gAgent.getFlying())
+ {
+ setFlyingMode(TRUE);
+ showModeButtons(FALSE);
+ }
+
+ if (isAgentAvatarValid() && gAgentAvatarp->isSitting())
+ {
+ setSittingMode(TRUE);
+ showModeButtons(FALSE);
+ }
+
+ setDockControl(new LLDockControl(
+ anchor_panel, this,
+ getDockTongue(), LLDockControl::TOP));
+
+ sUpdateFlyingStatus();
+}
+
+//virtual
+void LLFloaterMove::setDocked(bool docked, bool pop_on_undock/* = true*/)
+{
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
+}
+
+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
+inline 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:
+ llerrs << "Unexpected EStandStopFlyingMode is passed: " << mode << llendl;
+ }
+
+}
+
+BOOL LLPanelStandStopFlying::postBuild()
+{
+ mStandButton = getChild<LLButton>("stand_btn");
+ mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this));
+ mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE));
+ mStandButton->setVisible(FALSE);
+ LLHints::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);
+
+ 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)
+ {
+ llwarns << "Stand/stop flying panel parent is unset, already attached?: " << mAttached << ", new parent: " << (move_view == NULL ? "NULL" : "Move Floater") << llendl;
+ 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())
+ {
+ llwarns << "Original parent of the stand / stop flying panel not found" << llendl;
+ 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::getRootView()->addChild(panel);
+
+ llinfos << "Build LLPanelStandStopFlying panel" << llendl;
+
+ panel->updatePosition();
+ return panel;
+}
+
+void LLPanelStandStopFlying::onStandButtonClick()
+{
+ LLFirstUse::sit(false);
+
+ LLSelectMgr::getInstance()->deselectAllForStandingUp();
+ gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+
+ setFocus(FALSE); // EXT-482
+ mStandButton->setVisible(FALSE); // force visibility changing to avoid seeing Stand & Move buttons at once.
+}
+
+void LLPanelStandStopFlying::onStopFlyingButtonClick()
+{
+ gAgent.setFlying(FALSE);
+
+ setFocus(FALSE); // EXT-482
+ setVisible(FALSE);
+}
+
+/**
+ * Updates position of the Stand & Stop Flying panel to be center aligned with Move button.
+ */
+void LLPanelStandStopFlying::updatePosition()
+{
+ LLBottomTray* tray = LLBottomTray::getInstance();
+ if (!tray || mAttached) return;
+
+ LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
+
+ // Align centers of the button and the panel.
+ S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+ setOrigin(x, 0);
+}
+
+
// EOF