/indra/newview/lltoolmgr.cpp
C++ | 477 lines | 343 code | 74 blank | 60 comment | 55 complexity | f2e259a98159174937e4d815515d3afe MD5 | raw file
Possible License(s): LGPL-2.1
1/**
2 * @file lltoolmgr.cpp
3 * @brief LLToolMgr class implementation
4 *
5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
6 * Second Life Viewer Source Code
7 * Copyright (C) 2010, Linden Research, Inc.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation;
12 * version 2.1 of the License only.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
24 * $/LicenseInfo$
25 */
26
27#include "llviewerprecompiledheaders.h"
28
29#include "lltoolmgr.h"
30
31#include "lluictrl.h"
32#include "llmenugl.h"
33#include "llfloaterreg.h"
34
35//#include "llfirstuse.h"
36// tools and manipulators
37#include "lltool.h"
38#include "llmanipscale.h"
39#include "llselectmgr.h"
40#include "lltoolbrush.h"
41#include "lltoolcomp.h"
42#include "lltooldraganddrop.h"
43#include "lltoolface.h"
44#include "lltoolfocus.h"
45#include "lltoolgrab.h"
46#include "lltoolindividual.h"
47#include "lltoolmorph.h"
48#include "lltoolpie.h"
49#include "lltoolselectland.h"
50#include "lltoolobjpicker.h"
51#include "lltoolpipette.h"
52#include "llagent.h"
53#include "llagentcamera.h"
54#include "llviewercontrol.h"
55#include "llviewerjoystick.h"
56#include "llviewermenu.h"
57#include "llviewerparcelmgr.h"
58
59
60// Used when app not active to avoid processing hover.
61LLTool* gToolNull = NULL;
62
63LLToolset* gBasicToolset = NULL;
64LLToolset* gCameraToolset = NULL;
65//LLToolset* gLandToolset = NULL;
66LLToolset* gMouselookToolset = NULL;
67LLToolset* gFaceEditToolset = NULL;
68
69/////////////////////////////////////////////////////
70// LLToolMgr
71
72LLToolMgr::LLToolMgr()
73 :
74 mBaseTool(NULL),
75 mSavedTool(NULL),
76 mTransientTool( NULL ),
77 mOverrideTool( NULL ),
78 mSelectedTool( NULL ),
79 mCurrentToolset( NULL )
80{
81 // Not a panel, register these callbacks globally.
82 LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this));
83 LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this));
84 LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this));
85
86 gToolNull = new LLTool(LLStringUtil::null); // Does nothing
87 setCurrentTool(gToolNull);
88
89 gBasicToolset = new LLToolset();
90 gCameraToolset = new LLToolset();
91// gLandToolset = new LLToolset();
92 gMouselookToolset = new LLToolset();
93 gFaceEditToolset = new LLToolset();
94}
95
96void LLToolMgr::initTools()
97{
98 static BOOL initialized = FALSE;
99 if(initialized)
100 {
101 return;
102 }
103 initialized = TRUE;
104 gBasicToolset->addTool( LLToolPie::getInstance() );
105 gBasicToolset->addTool( LLToolCamera::getInstance() );
106 gCameraToolset->addTool( LLToolCamera::getInstance() );
107 gBasicToolset->addTool( LLToolGrab::getInstance() );
108 gBasicToolset->addTool( LLToolCompTranslate::getInstance() );
109 gBasicToolset->addTool( LLToolCompCreate::getInstance() );
110 gBasicToolset->addTool( LLToolBrushLand::getInstance() );
111 gMouselookToolset->addTool( LLToolCompGun::getInstance() );
112 gBasicToolset->addTool( LLToolCompInspect::getInstance() );
113 gFaceEditToolset->addTool( LLToolCamera::getInstance() );
114
115 // On startup, use "select" tool
116 setCurrentToolset(gBasicToolset);
117
118 gBasicToolset->selectTool( LLToolPie::getInstance() );
119}
120
121LLToolMgr::~LLToolMgr()
122{
123 delete gBasicToolset;
124 gBasicToolset = NULL;
125
126 delete gMouselookToolset;
127 gMouselookToolset = NULL;
128
129 delete gFaceEditToolset;
130 gFaceEditToolset = NULL;
131
132 delete gCameraToolset;
133 gCameraToolset = NULL;
134
135 delete gToolNull;
136 gToolNull = NULL;
137}
138
139BOOL LLToolMgr::usingTransientTool()
140{
141 return mTransientTool ? TRUE : FALSE;
142}
143
144void LLToolMgr::setCurrentToolset(LLToolset* current)
145{
146 if (!current) return;
147
148 // switching toolsets?
149 if (current != mCurrentToolset)
150 {
151 // deselect current tool
152 if (mSelectedTool)
153 {
154 mSelectedTool->handleDeselect();
155 }
156 mCurrentToolset = current;
157 // select first tool of new toolset only if toolset changed
158 mCurrentToolset->selectFirstTool();
159 }
160 // update current tool based on new toolset
161 setCurrentTool( mCurrentToolset->getSelectedTool() );
162}
163
164LLToolset* LLToolMgr::getCurrentToolset()
165{
166 return mCurrentToolset;
167}
168
169void LLToolMgr::setCurrentTool( LLTool* tool )
170{
171 if (mTransientTool)
172 {
173 mTransientTool = NULL;
174 }
175
176 mBaseTool = tool;
177 updateToolStatus();
178
179 mSavedTool = NULL;
180}
181
182LLTool* LLToolMgr::getCurrentTool()
183{
184 MASK override_mask = gKeyboard ? gKeyboard->currentMask(TRUE) : 0;
185
186 LLTool* cur_tool = NULL;
187 // always use transient tools if available
188 if (mTransientTool)
189 {
190 mOverrideTool = NULL;
191 cur_tool = mTransientTool;
192 }
193 // tools currently grabbing mouse input will stay active
194 else if (mSelectedTool && mSelectedTool->hasMouseCapture())
195 {
196 cur_tool = mSelectedTool;
197 }
198 else
199 {
200 mOverrideTool = mBaseTool ? mBaseTool->getOverrideTool(override_mask) : NULL;
201
202 // use override tool if available otherwise drop back to base tool
203 cur_tool = mOverrideTool ? mOverrideTool : mBaseTool;
204 }
205
206 LLTool* prev_tool = mSelectedTool;
207 // Set the selected tool to avoid infinite recursion
208 mSelectedTool = cur_tool;
209
210 //update tool selection status
211 if (prev_tool != cur_tool)
212 {
213 if (prev_tool)
214 {
215 prev_tool->handleDeselect();
216 }
217 if (cur_tool)
218 {
219 cur_tool->handleSelect();
220 }
221 }
222
223 return mSelectedTool;
224}
225
226LLTool* LLToolMgr::getBaseTool()
227{
228 return mBaseTool;
229}
230
231void LLToolMgr::updateToolStatus()
232{
233 // call getcurrenttool() to calculate active tool and call handleSelect() and handleDeselect() immediately
234 // when active tool changes
235 getCurrentTool();
236}
237
238bool LLToolMgr::inEdit()
239{
240 return mBaseTool != LLToolPie::getInstance() && mBaseTool != gToolNull;
241}
242
243bool LLToolMgr::canEdit()
244{
245 return LLViewerParcelMgr::getInstance()->allowAgentBuild();
246}
247
248void LLToolMgr::toggleBuildMode()
249{
250 LLFloaterReg::toggleInstanceOrBringToFront("build");
251
252 bool build_visible = LLFloaterReg::instanceVisible("build");
253 if (build_visible)
254 {
255 ECameraMode camMode = gAgentCamera.getCameraMode();
256 if (CAMERA_MODE_MOUSELOOK == camMode || CAMERA_MODE_CUSTOMIZE_AVATAR == camMode)
257 {
258 // pull the user out of mouselook or appearance mode when entering build mode
259 handle_reset_view();
260 }
261
262 if (gSavedSettings.getBOOL("EditCameraMovement"))
263 {
264 // camera should be set
265 if (LLViewerJoystick::getInstance()->getOverrideCamera())
266 {
267 handle_toggle_flycam();
268 }
269
270 if (gAgentCamera.getFocusOnAvatar())
271 {
272 // zoom in if we're looking at the avatar
273 gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
274 gAgentCamera.setFocusGlobal(gAgent.getPositionGlobal() + 2.0 * LLVector3d(gAgent.getAtAxis()));
275 gAgentCamera.cameraZoomIn(0.666f);
276 gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
277 }
278 }
279
280
281 setCurrentToolset(gBasicToolset);
282 getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
283
284 // Could be first use
285 //LLFirstUse::useBuild();
286
287 gAgentCamera.resetView(false);
288
289 // avoid spurious avatar movements
290 LLViewerJoystick::getInstance()->setNeedsReset();
291
292 }
293 else
294 {
295 if (gSavedSettings.getBOOL("EditCameraMovement"))
296 {
297 // just reset the view, will pull us out of edit mode
298 handle_reset_view();
299 }
300 else
301 {
302 // manually disable edit mode, but do not affect the camera
303 gAgentCamera.resetView(false);
304 LLFloaterReg::hideInstance("build");
305 gViewerWindow->showCursor();
306 }
307 // avoid spurious avatar movements pulling out of edit mode
308 LLViewerJoystick::getInstance()->setNeedsReset();
309 }
310
311}
312
313bool LLToolMgr::inBuildMode()
314{
315 // when entering mouselook inEdit() immediately returns true before
316 // cameraMouselook() actually starts returning true. Also, appearance edit
317 // sets build mode to true, so let's exclude that.
318 bool b=(inEdit()
319 && !gAgentCamera.cameraMouselook()
320 && mCurrentToolset != gFaceEditToolset);
321
322 return b;
323}
324
325void LLToolMgr::setTransientTool(LLTool* tool)
326{
327 if (!tool)
328 {
329 clearTransientTool();
330 }
331 else
332 {
333 if (mTransientTool)
334 {
335 mTransientTool = NULL;
336 }
337
338 mTransientTool = tool;
339 }
340
341 updateToolStatus();
342}
343
344void LLToolMgr::clearTransientTool()
345{
346 if (mTransientTool)
347 {
348 mTransientTool = NULL;
349 if (!mBaseTool)
350 {
351 llwarns << "mBaseTool is NULL" << llendl;
352 }
353 }
354 updateToolStatus();
355}
356
357
358void LLToolMgr::onAppFocusLost()
359{
360 if (mSelectedTool)
361 {
362 mSelectedTool->handleDeselect();
363 }
364 updateToolStatus();
365}
366
367void LLToolMgr::onAppFocusGained()
368{
369 if (mSelectedTool)
370 {
371 mSelectedTool->handleSelect();
372 }
373 updateToolStatus();
374}
375
376void LLToolMgr::clearSavedTool()
377{
378 mSavedTool = NULL;
379}
380
381/////////////////////////////////////////////////////
382// LLToolset
383
384void LLToolset::addTool(LLTool* tool)
385{
386 mToolList.push_back( tool );
387 if( !mSelectedTool )
388 {
389 mSelectedTool = tool;
390 }
391}
392
393
394void LLToolset::selectTool(LLTool* tool)
395{
396 mSelectedTool = tool;
397 LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
398}
399
400
401void LLToolset::selectToolByIndex( S32 index )
402{
403 LLTool *tool = (index >= 0 && index < (S32)mToolList.size()) ? mToolList[index] : NULL;
404 if (tool)
405 {
406 mSelectedTool = tool;
407 LLToolMgr::getInstance()->setCurrentTool( tool );
408 }
409}
410
411BOOL LLToolset::isToolSelected( S32 index )
412{
413 LLTool *tool = (index >= 0 && index < (S32)mToolList.size()) ? mToolList[index] : NULL;
414 return (tool == mSelectedTool);
415}
416
417
418void LLToolset::selectFirstTool()
419{
420 mSelectedTool = (0 < mToolList.size()) ? mToolList[0] : NULL;
421 LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
422}
423
424
425void LLToolset::selectNextTool()
426{
427 LLTool* next = NULL;
428 for( tool_list_t::iterator iter = mToolList.begin();
429 iter != mToolList.end(); )
430 {
431 LLTool* cur = *iter++;
432 if( cur == mSelectedTool && iter != mToolList.end() )
433 {
434 next = *iter;
435 break;
436 }
437 }
438
439 if( next )
440 {
441 mSelectedTool = next;
442 LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
443 }
444 else
445 {
446 selectFirstTool();
447 }
448}
449
450void LLToolset::selectPrevTool()
451{
452 LLTool* prev = NULL;
453 for( tool_list_t::reverse_iterator iter = mToolList.rbegin();
454 iter != mToolList.rend(); )
455 {
456 LLTool* cur = *iter++;
457 if( cur == mSelectedTool && iter != mToolList.rend() )
458 {
459 prev = *iter;
460 break;
461 }
462 }
463
464 if( prev )
465 {
466 mSelectedTool = prev;
467 LLToolMgr::getInstance()->setCurrentTool( mSelectedTool );
468 }
469 else if (mToolList.size() > 0)
470 {
471 selectToolByIndex((S32)mToolList.size()-1);
472 }
473}
474
475////////////////////////////////////////////////////////////////////////////
476
477