/** * @file lltoolmgr.cpp * @brief LLToolMgr class implementation * * $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 "lltoolmgr.h" #include "lluictrl.h" #include "llmenugl.h" #include "llfloaterreg.h" //#include "llfirstuse.h" // tools and manipulators #include "llfloaterinspect.h" #include "lltool.h" #include "llmanipscale.h" #include "llmarketplacefunctions.h" #include "llselectmgr.h" #include "lltoolbrush.h" #include "lltoolcomp.h" #include "lltooldraganddrop.h" #include "lltoolface.h" #include "lltoolfocus.h" #include "lltoolgrab.h" #include "lltoolindividual.h" #include "lltoolmorph.h" #include "lltoolpie.h" #include "lltoolselectland.h" #include "lltoolobjpicker.h" #include "lltoolpipette.h" #include "llagent.h" #include "llagentcamera.h" #include "llviewercontrol.h" #include "llviewerjoystick.h" #include "llviewermenu.h" #include "llviewerparcelmgr.h" // Used when app not active to avoid processing hover. LLTool* gToolNull = NULL; LLToolset* gBasicToolset = NULL; LLToolset* gCameraToolset = NULL; //LLToolset* gLandToolset = NULL; LLToolset* gMouselookToolset = NULL; LLToolset* gFaceEditToolset = NULL; ///////////////////////////////////////////////////// // LLToolMgr LLToolMgr::LLToolMgr() : mBaseTool(NULL), mSavedTool(NULL), mTransientTool( NULL ), mOverrideTool( NULL ), mSelectedTool( NULL ), mCurrentToolset( NULL ) { // Not a panel, register these callbacks globally. LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.EnabledOrActive", boost::bind(&LLToolMgr::buildEnabledOrActive, this)); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", { boost::bind(&LLToolMgr::toggleBuildMode, this, _2) }); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Marketplace.Enabled", boost::bind(&LLToolMgr::canAccessMarketplace, this)); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Marketplace.Toggle", { boost::bind(&LLToolMgr::toggleMarketplace, this, _2) }); gToolNull = new LLTool(LLStringUtil::null); // Does nothing setCurrentTool(gToolNull); gBasicToolset = new LLToolset(); gCameraToolset = new LLToolset(); // gLandToolset = new LLToolset(); gMouselookToolset = new LLToolset(); gFaceEditToolset = new LLToolset(); gMouselookToolset->setShowFloaterTools(false); gFaceEditToolset->setShowFloaterTools(false); } void LLToolMgr::initTools() { static bool initialized = false; if(initialized) { return; } initialized = true; gBasicToolset->addTool( LLToolPie::getInstance() ); gBasicToolset->addTool( LLToolCamera::getInstance() ); gCameraToolset->addTool( LLToolCamera::getInstance() ); gBasicToolset->addTool( LLToolGrab::getInstance() ); gBasicToolset->addTool( LLToolCompTranslate::getInstance() ); gBasicToolset->addTool( LLToolCompCreate::getInstance() ); gBasicToolset->addTool( LLToolBrushLand::getInstance() ); gMouselookToolset->addTool( LLToolCompGun::getInstance() ); gBasicToolset->addTool( LLToolCompInspect::getInstance() ); gFaceEditToolset->addTool( LLToolCamera::getInstance() ); // On startup, use "select" tool setCurrentToolset(gBasicToolset); gBasicToolset->selectTool( LLToolPie::getInstance() ); } LLToolMgr::~LLToolMgr() { delete gBasicToolset; gBasicToolset = NULL; delete gMouselookToolset; gMouselookToolset = NULL; delete gFaceEditToolset; gFaceEditToolset = NULL; delete gCameraToolset; gCameraToolset = NULL; delete gToolNull; gToolNull = NULL; } bool LLToolMgr::usingTransientTool() { return mTransientTool != nullptr; } void LLToolMgr::setCurrentToolset(LLToolset* current) { if (!current) return; // switching toolsets? if (current != mCurrentToolset) { // deselect current tool if (mSelectedTool) { mSelectedTool->handleDeselect(); } mCurrentToolset = current; // select first tool of new toolset only if toolset changed mCurrentToolset->selectFirstTool(); } // update current tool based on new toolset setCurrentTool( mCurrentToolset->getSelectedTool() ); } LLToolset* LLToolMgr::getCurrentToolset() { return mCurrentToolset; } void LLToolMgr::setCurrentTool( LLTool* tool ) { if (mTransientTool) { mTransientTool = NULL; } mBaseTool = tool; updateToolStatus(); mSavedTool = NULL; } LLTool* LLToolMgr::getCurrentTool() { MASK override_mask = gKeyboard ? gKeyboard->currentMask(true) : 0; LLTool* cur_tool = NULL; // always use transient tools if available if (mTransientTool) { mOverrideTool = NULL; cur_tool = mTransientTool; } // tools currently grabbing mouse input will stay active else if (mSelectedTool && mSelectedTool->hasMouseCapture()) { cur_tool = mSelectedTool; } else { mOverrideTool = mBaseTool ? mBaseTool->getOverrideTool(override_mask) : NULL; // use override tool if available otherwise drop back to base tool cur_tool = mOverrideTool ? mOverrideTool : mBaseTool; } LLTool* prev_tool = mSelectedTool; // Set the selected tool to avoid infinite recursion mSelectedTool = cur_tool; //update tool selection status if (prev_tool != cur_tool) { if (prev_tool) { prev_tool->handleDeselect(); } if (cur_tool) { if ( LLToolCompInspect::getInstance()->isToolCameraActive() && prev_tool == LLToolCamera::getInstance() && cur_tool == LLToolPie::getInstance() ) { LLFloaterInspect * inspect_instance = LLFloaterReg::getTypedInstance("inspect"); if(inspect_instance && inspect_instance->getVisible()) { setTransientTool(LLToolCompInspect::getInstance()); } } else { cur_tool->handleSelect(); } } } return mSelectedTool; } LLTool* LLToolMgr::getBaseTool() { return mBaseTool; } void LLToolMgr::updateToolStatus() { // call getcurrenttool() to calculate active tool and call handleSelect() and handleDeselect() immediately // when active tool changes getCurrentTool(); } bool LLToolMgr::inEdit() { return mBaseTool != LLToolPie::getInstance() && mBaseTool != gToolNull; } bool LLToolMgr::canEdit() { return LLViewerParcelMgr::getInstance()->allowAgentBuild(); } bool LLToolMgr::buildEnabledOrActive() { return LLFloaterReg::instanceVisible("build") || canEdit(); } void LLToolMgr::toggleBuildMode(const LLSD& sdname) { const std::string& param = sdname.asString(); LLFloaterReg::toggleInstanceOrBringToFront("build"); if (param == "build" && !canEdit()) { return; } bool build_visible = LLFloaterReg::instanceVisible("build"); if (build_visible) { ECameraMode camMode = gAgentCamera.getCameraMode(); if (CAMERA_MODE_MOUSELOOK == camMode || CAMERA_MODE_CUSTOMIZE_AVATAR == camMode) { // pull the user out of mouselook or appearance mode when entering build mode handle_reset_view(); } if (gSavedSettings.getBOOL("EditCameraMovement")) { // camera should be set if (LLViewerJoystick::getInstance()->getOverrideCamera()) { handle_toggle_flycam(); } if (gAgentCamera.getFocusOnAvatar()) { // zoom in if we're looking at the avatar gAgentCamera.setFocusOnAvatar(false, ANIMATE); gAgentCamera.setFocusGlobal(gAgent.getPositionGlobal() + 2.0 * LLVector3d(gAgent.getAtAxis())); gAgentCamera.cameraZoomIn(0.666f); gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); } } setCurrentToolset(gBasicToolset); getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); // Could be first use //LLFirstUse::useBuild(); gAgentCamera.resetView(false); // avoid spurious avatar movements LLViewerJoystick::getInstance()->setNeedsReset(); } else { if (gSavedSettings.getBOOL("EditCameraMovement")) { // just reset the view, will pull us out of edit mode handle_reset_view(); } else { // manually disable edit mode, but do not affect the camera gAgentCamera.resetView(false); LLFloaterReg::hideInstance("build"); gViewerWindow->showCursor(); } // avoid spurious avatar movements pulling out of edit mode LLViewerJoystick::getInstance()->setNeedsReset(); } } bool LLToolMgr::inBuildMode() { // when entering mouselook inEdit() immediately returns true before // cameraMouselook() actually starts returning true. Also, appearance edit // sets build mode to true, so let's exclude that. bool b=(inEdit() && !gAgentCamera.cameraMouselook() && mCurrentToolset != gFaceEditToolset); return b; } bool LLToolMgr::canAccessMarketplace() { return (LLMarketplaceData::instance().getSLMStatus() != MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT); } void LLToolMgr::toggleMarketplace(const LLSD& sdname) { const std::string& param = sdname.asString(); if ((param != "marketplace") || !canAccessMarketplace()) { return; } LLFloaterReg::toggleInstanceOrBringToFront("marketplace_listings"); } void LLToolMgr::setTransientTool(LLTool* tool) { if (!tool) { clearTransientTool(); } else { if (mTransientTool) { mTransientTool = NULL; } mTransientTool = tool; } updateToolStatus(); } void LLToolMgr::clearTransientTool() { if (mTransientTool) { mTransientTool = NULL; if (!mBaseTool) { LL_WARNS() << "mBaseTool is NULL" << LL_ENDL; } } updateToolStatus(); } void LLToolMgr::onAppFocusLost() { if (LLApp::isExiting()) return; if (mSelectedTool) { mSelectedTool->handleDeselect(); } updateToolStatus(); } void LLToolMgr::onAppFocusGained() { if (mSelectedTool) { mSelectedTool->handleSelect(); } updateToolStatus(); } void LLToolMgr::clearSavedTool() { mSavedTool = NULL; } ///////////////////////////////////////////////////// // LLToolset void LLToolset::addTool(LLTool* tool) { mToolList.push_back( tool ); if( !mSelectedTool ) { mSelectedTool = tool; } } void LLToolset::selectTool(LLTool* tool) { mSelectedTool = tool; LLToolMgr::getInstance()->setCurrentTool( mSelectedTool ); } void LLToolset::selectToolByIndex( S32 index ) { LLTool *tool = (index >= 0 && index < (S32)mToolList.size()) ? mToolList[index] : NULL; if (tool) { mSelectedTool = tool; LLToolMgr::getInstance()->setCurrentTool( tool ); } } bool LLToolset::isToolSelected( S32 index ) { LLTool *tool = (index >= 0 && index < (S32)mToolList.size()) ? mToolList[index] : NULL; return (tool == mSelectedTool); } void LLToolset::selectFirstTool() { mSelectedTool = (0 < mToolList.size()) ? mToolList[0] : NULL; LLToolMgr::getInstance()->setCurrentTool( mSelectedTool ); } void LLToolset::selectNextTool() { LLTool* next = NULL; for( tool_list_t::iterator iter = mToolList.begin(); iter != mToolList.end(); ) { LLTool* cur = *iter++; if( cur == mSelectedTool && iter != mToolList.end() ) { next = *iter; break; } } if( next ) { mSelectedTool = next; LLToolMgr::getInstance()->setCurrentTool( mSelectedTool ); } else { selectFirstTool(); } } void LLToolset::selectPrevTool() { LLTool* prev = NULL; for( tool_list_t::reverse_iterator iter = mToolList.rbegin(); iter != mToolList.rend(); ) { LLTool* cur = *iter++; if( cur == mSelectedTool && iter != mToolList.rend() ) { prev = *iter; break; } } if( prev ) { mSelectedTool = prev; LLToolMgr::getInstance()->setCurrentTool( mSelectedTool ); } else if (mToolList.size() > 0) { selectToolByIndex((S32)mToolList.size()-1); } } ////////////////////////////////////////////////////////////////////////////