Skip to content
Snippets Groups Projects
lltoolmgr.cpp 11 KiB
Newer Older
James Cook's avatar
James Cook committed
/** 
 * @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$
James Cook's avatar
James Cook committed
 */

#include "llviewerprecompiledheaders.h"

#include "lltoolmgr.h"

#include "lluictrl.h"
#include "llmenugl.h"
#include "llfloaterreg.h"

James Cook's avatar
James Cook committed
// tools and manipulators
James Cook's avatar
James Cook committed
#include "llmanipscale.h"
#include "llselectmgr.h"
James Cook's avatar
James Cook committed
#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"
Steven Bennetts's avatar
Steven Bennetts committed
#include "llagent.h"
Steven Bennetts's avatar
Steven Bennetts committed
#include "llviewercontrol.h"
#include "llviewerjoystick.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e)
#include "rlvhandler.h"
// [/RLVa:KB]
James Cook's avatar
James Cook committed

// 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()
	:
James Cook's avatar
James Cook committed
	mSavedTool(NULL),
	mTransientTool( NULL ),
	mOverrideTool( NULL ),
	mSelectedTool( NULL ),
	mCurrentToolset( NULL )
James Cook's avatar
James Cook committed
{
	// 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));
// [RLVa:KB] - Checked: 2010-09-11 (RLVa-1.2.1d) | Added: RLVa-1.2.1d
	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&RlvUIEnabler::isBuildEnabled));
// [/RLVa:KB]
	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this));
	
	gToolNull = new LLTool(LLStringUtil::null);  // Does nothing
James Cook's avatar
James Cook committed
	setCurrentTool(gToolNull);

	gBasicToolset		= new LLToolset();
	gCameraToolset		= new LLToolset();
//	gLandToolset		= new LLToolset();
	gMouselookToolset	= new LLToolset();
	gFaceEditToolset	= new LLToolset();
}

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() );
James Cook's avatar
James Cook committed

	// On startup, use "select" tool
	setCurrentToolset(gBasicToolset);

	gBasicToolset->selectTool( LLToolPie::getInstance() );
James Cook's avatar
James Cook committed
}

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 ? TRUE : FALSE;
}

void LLToolMgr::setCurrentToolset(LLToolset* current)
James Cook's avatar
James Cook committed
{
	if (!current) return;

	// switching toolsets?
	if (current != mCurrentToolset)
James Cook's avatar
James Cook committed
	{
		// deselect current tool
		if (mSelectedTool)
		{
			mSelectedTool->handleDeselect();
		}
		mCurrentToolset = current;
		// select first tool of new toolset only if toolset changed
		mCurrentToolset->selectFirstTool();
James Cook's avatar
James Cook committed
	}
	// update current tool based on new toolset
	setCurrentTool( mCurrentToolset->getSelectedTool() );
}

LLToolset* LLToolMgr::getCurrentToolset()
{
	return mCurrentToolset;
}
James Cook's avatar
James Cook committed

void LLToolMgr::setCurrentTool( LLTool* tool )
{
James Cook's avatar
James Cook committed
	if (mTransientTool)
	{
		mTransientTool = NULL;
	}

	mBaseTool = tool;
	updateToolStatus();
LLTool* LLToolMgr::getCurrentTool()
James Cook's avatar
James Cook committed
{
	MASK override_mask = gKeyboard ? gKeyboard->currentMask(TRUE) : 0;
James Cook's avatar
James Cook committed

	LLTool* cur_tool = NULL;
	// always use transient tools if available
James Cook's avatar
James Cook committed
	if (mTransientTool)
	{
		mOverrideTool = NULL;
		cur_tool = mTransientTool;
James Cook's avatar
James Cook committed
	}
	// tools currently grabbing mouse input will stay active
	else if (mSelectedTool && mSelectedTool->hasMouseCapture())
James Cook's avatar
James Cook committed
	{
		cur_tool = mSelectedTool;
James Cook's avatar
James Cook committed
	}
James Cook's avatar
James Cook committed
	{
		mOverrideTool = mBaseTool ? mBaseTool->getOverrideTool(override_mask) : NULL;
James Cook's avatar
James Cook committed

		// use override tool if available otherwise drop back to base tool
		cur_tool = mOverrideTool ? mOverrideTool : mBaseTool;
James Cook's avatar
James Cook committed
	}
	LLTool* prev_tool = mSelectedTool;
	// Set the selected tool to avoid infinite recursion
	mSelectedTool = cur_tool;
	
	//update tool selection status
James Cook's avatar
James Cook committed
	{
James Cook's avatar
James Cook committed
		{
James Cook's avatar
James Cook committed
		}
James Cook's avatar
James Cook committed
		{
			cur_tool->handleSelect();
James Cook's avatar
James Cook committed
		}
	}

	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();
James Cook's avatar
James Cook committed
{
	return mBaseTool != LLToolPie::getInstance() && mBaseTool != gToolNull;
	return LLViewerParcelMgr::getInstance()->allowAgentBuild();
}

void LLToolMgr::toggleBuildMode()
{
	if (inBuildMode())
	{
		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();
	}
	else
	{
		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 );
// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b
		// TODO-RLVa: [RLVa-1.2.1] Does this code actually still ever trigger?
		if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
		{
			LLSelectMgr::getInstance()->deselectAll();
		}
// [/RLVa:KB]

		setCurrentToolset(gBasicToolset);
		getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );

		// Could be first use
		gAgentCamera.resetView(false);

		// avoid spurious avatar movements
		LLViewerJoystick::getInstance()->setNeedsReset();

	}
}

Steven Bennetts's avatar
Steven Bennetts committed
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()
Steven Bennetts's avatar
Steven Bennetts committed
			&& mCurrentToolset != gFaceEditToolset);
	
	return b;
}

James Cook's avatar
James Cook committed
void LLToolMgr::setTransientTool(LLTool* tool)
{
	if (!tool)
	{
		clearTransientTool();
	}
	else
	{
		if (mTransientTool)
		{
			mTransientTool = NULL;
		}

		mTransientTool = tool;
	}
James Cook's avatar
James Cook committed
}

void LLToolMgr::clearTransientTool()
{
	if (mTransientTool)
	{
		mTransientTool = NULL;
James Cook's avatar
James Cook committed
		{
			llwarns << "mBaseTool is NULL" << llendl;
James Cook's avatar
James Cook committed
		}
	}
James Cook's avatar
James Cook committed
}


void LLToolMgr::onAppFocusLost()
{
	if (mSelectedTool)
	{
		mSelectedTool->handleDeselect();
	}
James Cook's avatar
James Cook committed
}

void LLToolMgr::onAppFocusGained()
{
	if (mSelectedTool)
James Cook's avatar
James Cook committed
	{
		mSelectedTool->handleSelect();
James Cook's avatar
James Cook committed
	}
void LLToolMgr::clearSavedTool()
{
	mSavedTool = NULL;
}

James Cook's avatar
James Cook committed
/////////////////////////////////////////////////////
// LLToolset

void LLToolset::addTool(LLTool* tool)
{
	mToolList.push_back( tool );
James Cook's avatar
James Cook committed
	if( !mSelectedTool )
	{
		mSelectedTool = tool;
	}
}


void LLToolset::selectTool(LLTool* tool)
{
	mSelectedTool = tool;
	LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
James Cook's avatar
James Cook committed
}


void LLToolset::selectToolByIndex( S32 index )
{
	LLTool *tool = (index >= 0 && index < (S32)mToolList.size()) ? mToolList[index] : NULL;
James Cook's avatar
James Cook committed
	if (tool)
	{
		mSelectedTool = tool;
		LLToolMgr::getInstance()->setCurrentTool( tool );
James Cook's avatar
James Cook committed
	}
}

BOOL LLToolset::isToolSelected( S32 index )
{
	LLTool *tool = (index >= 0 && index < (S32)mToolList.size()) ? mToolList[index] : NULL;
	return (tool == mSelectedTool);
James Cook's avatar
James Cook committed
}


void LLToolset::selectFirstTool()
{
	mSelectedTool = (0 < mToolList.size()) ? mToolList[0] : NULL;
	LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
James Cook's avatar
James Cook committed
}


void LLToolset::selectNextTool()
{
	LLTool* next = NULL;
	for( tool_list_t::iterator iter = mToolList.begin();
		 iter != mToolList.end(); )
James Cook's avatar
James Cook committed
	{
		LLTool* cur = *iter++;
		if( cur == mSelectedTool && iter != mToolList.end() )
James Cook's avatar
James Cook committed
		{
James Cook's avatar
James Cook committed
	{
		LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
James Cook's avatar
James Cook committed
	}
}

void LLToolset::selectPrevTool()
{
	LLTool* prev = NULL;
	for( tool_list_t::reverse_iterator iter = mToolList.rbegin();
		 iter != mToolList.rend(); )
James Cook's avatar
James Cook committed
	{
		LLTool* cur = *iter++;
		if( cur == mSelectedTool && iter != mToolList.rend() )
James Cook's avatar
James Cook committed
		{
James Cook's avatar
James Cook committed
	{
		LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
	}
	else if (mToolList.size() > 0)
	{
		selectToolByIndex((S32)mToolList.size()-1);
////////////////////////////////////////////////////////////////////////////