diff options
Diffstat (limited to 'indra/newview/llmoveview.cpp')
-rw-r--r-- | indra/newview/llmoveview.cpp | 730 |
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 |