PageRenderTime 624ms CodeModel.GetById 202ms app.highlight 204ms RepoModel.GetById 198ms app.codeStats 0ms

/indra/newview/llfloatercamera.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 585 lines | 436 code | 94 blank | 55 comment | 79 complexity | f1096c385d2404045cd04f2a63c4396a MD5 | raw file
  1/** 
  2 * @file llfloatercamera.cpp
  3 * @brief Container for camera control buttons (zoom, pan, orbit)
  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 "llfloatercamera.h"
 30
 31// Library includes
 32#include "llfloaterreg.h"
 33
 34// Viewer includes
 35#include "llagentcamera.h"
 36#include "lljoystickbutton.h"
 37#include "llviewercontrol.h"
 38#include "llviewercamera.h"
 39#include "lltoolmgr.h"
 40#include "lltoolfocus.h"
 41#include "llslider.h"
 42#include "llfirstuse.h"
 43#include "llhints.h"
 44
 45static LLDefaultChildRegistry::Register<LLPanelCameraItem> r("panel_camera_item");
 46
 47const F32 NUDGE_TIME = 0.25f;		// in seconds
 48const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
 49
 50// Constants
 51const F32 CAMERA_BUTTON_DELAY = 0.0f;
 52
 53#define ORBIT "cam_rotate_stick"
 54#define PAN "cam_track_stick"
 55#define ZOOM "zoom"
 56#define PRESETS "preset_views_list"
 57#define CONTROLS "controls"
 58
 59bool LLFloaterCamera::sFreeCamera = false;
 60bool LLFloaterCamera::sAppearanceEditing = false;
 61
 62// Zoom the camera in and out
 63class LLPanelCameraZoom
 64:	public LLPanel
 65{
 66	LOG_CLASS(LLPanelCameraZoom);
 67public:
 68	LLPanelCameraZoom();
 69
 70	/* virtual */ BOOL	postBuild();
 71	/* virtual */ void	draw();
 72
 73protected:
 74	void	onZoomPlusHeldDown();
 75	void	onZoomMinusHeldDown();
 76	void	onSliderValueChanged();
 77	void	onCameraTrack();
 78	void	onCameraRotate();
 79	F32		getOrbitRate(F32 time);
 80
 81private:
 82	LLButton*	mPlusBtn;
 83	LLButton*	mMinusBtn;
 84	LLSlider*	mSlider;
 85};
 86
 87LLPanelCameraItem::Params::Params()
 88:	icon_over("icon_over"),
 89	icon_selected("icon_selected"),
 90	picture("picture"),
 91	text("text"),
 92	selected_picture("selected_picture"),
 93	mousedown_callback("mousedown_callback")
 94{
 95}
 96
 97LLPanelCameraItem::LLPanelCameraItem(const LLPanelCameraItem::Params& p)
 98:	LLPanel(p)
 99{
100	LLIconCtrl::Params icon_params = p.picture;
101	mPicture = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
102	addChild(mPicture);
103
104	icon_params = p.icon_over;
105	mIconOver = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
106	addChild(mIconOver);
107
108	icon_params = p.icon_selected;
109	mIconSelected = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
110	addChild(mIconSelected);
111
112	icon_params = p.selected_picture;
113	mPictureSelected = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
114	addChild(mPictureSelected);
115
116	LLTextBox::Params text_params = p.text;
117	mText = LLUICtrlFactory::create<LLTextBox>(text_params);
118	addChild(mText);
119
120	if (p.mousedown_callback.isProvided())
121	{
122		setCommitCallback(initCommitCallback(p.mousedown_callback));
123	}
124}
125
126void set_view_visible(LLView* parent, const std::string& name, bool visible)
127{
128	parent->getChildView(name)->setVisible(visible);
129}
130
131BOOL LLPanelCameraItem::postBuild()
132{
133	setMouseEnterCallback(boost::bind(set_view_visible, this, "hovered_icon", true));
134	setMouseLeaveCallback(boost::bind(set_view_visible, this, "hovered_icon", false));
135	setMouseDownCallback(boost::bind(&LLPanelCameraItem::onAnyMouseClick, this));
136	setRightMouseDownCallback(boost::bind(&LLPanelCameraItem::onAnyMouseClick, this));
137	return TRUE;
138}
139
140void LLPanelCameraItem::onAnyMouseClick()
141{
142	if (mCommitSignal) (*mCommitSignal)(this, LLSD());
143}
144
145void LLPanelCameraItem::setValue(const LLSD& value)
146{
147	if (!value.isMap()) return;;
148	if (!value.has("selected")) return;
149	getChildView("selected_icon")->setVisible( value["selected"]);
150	getChildView("picture")->setVisible( !value["selected"]);
151	getChildView("selected_picture")->setVisible( value["selected"]);
152}
153
154static LLRegisterPanelClassWrapper<LLPanelCameraZoom> t_camera_zoom_panel("camera_zoom_panel");
155
156//-------------------------------------------------------------------------------
157// LLPanelCameraZoom
158//-------------------------------------------------------------------------------
159
160LLPanelCameraZoom::LLPanelCameraZoom()
161:	mPlusBtn( NULL ),
162	mMinusBtn( NULL ),
163	mSlider( NULL )
164{
165	mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this));
166	mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this));
167	mCommitCallbackRegistrar.add("Slider.value_changed", boost::bind(&LLPanelCameraZoom::onSliderValueChanged, this));
168	mCommitCallbackRegistrar.add("Camera.track", boost::bind(&LLPanelCameraZoom::onCameraTrack, this));
169	mCommitCallbackRegistrar.add("Camera.rotate", boost::bind(&LLPanelCameraZoom::onCameraRotate, this));
170}
171
172BOOL LLPanelCameraZoom::postBuild()
173{
174	mPlusBtn  = getChild <LLButton> ("zoom_plus_btn");
175	mMinusBtn = getChild <LLButton> ("zoom_minus_btn");
176	mSlider   = getChild <LLSlider> ("zoom_slider");
177	return LLPanel::postBuild();
178}
179
180void LLPanelCameraZoom::draw()
181{
182	mSlider->setValue(gAgentCamera.getCameraZoomFraction());
183	LLPanel::draw();
184}
185
186void LLPanelCameraZoom::onZoomPlusHeldDown()
187{
188	F32 val = mSlider->getValueF32();
189	F32 inc = mSlider->getIncrement();
190	mSlider->setValue(val - inc);
191	F32 time = mPlusBtn->getHeldDownTime();
192	gAgentCamera.unlockView();
193	gAgentCamera.setOrbitInKey(getOrbitRate(time));
194}
195
196void LLPanelCameraZoom::onZoomMinusHeldDown()
197{
198	F32 val = mSlider->getValueF32();
199	F32 inc = mSlider->getIncrement();
200	mSlider->setValue(val + inc);
201	F32 time = mMinusBtn->getHeldDownTime();
202	gAgentCamera.unlockView();
203	gAgentCamera.setOrbitOutKey(getOrbitRate(time));
204}
205
206void LLPanelCameraZoom::onCameraTrack()
207{
208	// EXP-202 when camera panning activated, remove the hint
209	LLFirstUse::viewPopup( false );
210}
211
212void LLPanelCameraZoom::onCameraRotate()
213{
214	// EXP-202 when camera rotation activated, remove the hint
215	LLFirstUse::viewPopup( false );
216}
217
218F32 LLPanelCameraZoom::getOrbitRate(F32 time)
219{
220	if( time < NUDGE_TIME )
221	{
222		F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
223		return rate;
224	}
225	else
226	{
227		return 1;
228	}
229}
230
231void  LLPanelCameraZoom::onSliderValueChanged()
232{
233	F32 zoom_level = mSlider->getValueF32();
234	gAgentCamera.setCameraZoomFraction(zoom_level);
235}
236
237void activate_camera_tool()
238{
239	LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
240};
241
242//
243// Member functions
244//
245
246/*static*/ bool LLFloaterCamera::inFreeCameraMode()
247{
248	LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
249	if (floater_camera && floater_camera->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA && gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)
250	{
251		return true;
252	}
253	return false;
254}
255
256void LLFloaterCamera::resetCameraMode()
257{
258	LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
259	if (!floater_camera) return;
260	floater_camera->switchMode(CAMERA_CTRL_MODE_PAN);
261}
262
263void LLFloaterCamera::onAvatarEditingAppearance(bool editing)
264{
265	sAppearanceEditing = editing;
266	LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
267	if (!floater_camera) return;
268	floater_camera->handleAvatarEditingAppearance(editing);
269}
270
271void LLFloaterCamera::handleAvatarEditingAppearance(bool editing)
272{
273	//camera presets (rear, front, etc.)
274	getChildView("preset_views_list")->setEnabled(!editing);
275	getChildView("presets_btn")->setEnabled(!editing);
276
277	//camera modes (object view, mouselook view)
278	getChildView("camera_modes_list")->setEnabled(!editing);
279	getChildView("avatarview_btn")->setEnabled(!editing);
280}
281
282void LLFloaterCamera::update()
283{
284	ECameraControlMode mode = determineMode();
285	if (mode != mCurrMode) setMode(mode);
286}
287
288
289void LLFloaterCamera::toPrevMode()
290{
291	switchMode(mPrevMode);
292}
293
294/*static*/ void LLFloaterCamera::onLeavingMouseLook()
295{
296	LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
297	if (floater_camera)
298	{
299		floater_camera->updateItemsSelection();
300		if(floater_camera->inFreeCameraMode())
301		{
302			activate_camera_tool();
303		}
304	}
305}
306
307LLFloaterCamera* LLFloaterCamera::findInstance()
308{
309	return LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera");
310}
311
312void LLFloaterCamera::onOpen(const LLSD& key)
313{
314	LLFirstUse::viewPopup();
315
316	mZoom->onOpen(key);
317
318	// Returns to previous mode, see EXT-2727(View tool should remember state).
319	// In case floater was just hidden and it isn't reset the mode
320	// just update state to current one. Else go to previous.
321	if ( !mClosed )
322		updateState();
323	else
324		toPrevMode();
325	mClosed = FALSE;
326}
327
328void LLFloaterCamera::onClose(bool app_quitting)
329{
330	//We don't care of camera mode if app is quitting
331	if(app_quitting)
332		return;
333	// When mCurrMode is in CAMERA_CTRL_MODE_PAN
334	// switchMode won't modify mPrevMode, so force it here.
335	// It is needed to correctly return to previous mode on open, see EXT-2727.
336	if (mCurrMode == CAMERA_CTRL_MODE_PAN)
337		mPrevMode = CAMERA_CTRL_MODE_PAN;
338
339	switchMode(CAMERA_CTRL_MODE_PAN);
340	mClosed = TRUE;
341}
342
343LLFloaterCamera::LLFloaterCamera(const LLSD& val)
344:	LLFloater(val),
345	mClosed(FALSE),
346	mCurrMode(CAMERA_CTRL_MODE_PAN),
347	mPrevMode(CAMERA_CTRL_MODE_PAN)
348{
349	LLHints::registerHintTarget("view_popup", getHandle());
350	mCommitCallbackRegistrar.add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2));
351}
352
353// virtual
354BOOL LLFloaterCamera::postBuild()
355{
356	updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
357
358	mRotate = getChild<LLJoystickCameraRotate>(ORBIT);
359	mZoom = findChild<LLPanelCameraZoom>(ZOOM);
360	mTrack = getChild<LLJoystickCameraTrack>(PAN);
361
362	assignButton2Mode(CAMERA_CTRL_MODE_MODES,			"avatarview_btn");
363	assignButton2Mode(CAMERA_CTRL_MODE_PAN,				"pan_btn");
364	assignButton2Mode(CAMERA_CTRL_MODE_PRESETS,		"presets_btn");
365
366	update();
367
368	// ensure that appearance mode is handled while building. See EXT-7796.
369	handleAvatarEditingAppearance(sAppearanceEditing);
370
371	return LLFloater::postBuild();
372}
373
374void LLFloaterCamera::fillFlatlistFromPanel (LLFlatListView* list, LLPanel* panel)
375{
376	// copying child list and then iterating over a copy, because list itself
377	// is changed in process
378	const child_list_t child_list = *panel->getChildList();
379	child_list_t::const_reverse_iterator iter = child_list.rbegin();
380	child_list_t::const_reverse_iterator end = child_list.rend();
381	for ( ; iter != end; ++iter)
382	{
383		LLView* view = *iter;
384		LLPanel* item = dynamic_cast<LLPanel*>(view);
385		if (panel)
386			list->addItem(item);
387	}
388
389}
390
391ECameraControlMode LLFloaterCamera::determineMode()
392{
393	if (sAppearanceEditing)
394	{
395		// this is the only enabled camera mode while editing agent appearance.
396		return CAMERA_CTRL_MODE_PAN;
397	}
398
399	LLTool* curr_tool = LLToolMgr::getInstance()->getCurrentTool();
400	if (curr_tool == LLToolCamera::getInstance())
401	{
402		return CAMERA_CTRL_MODE_FREE_CAMERA;
403	} 
404
405	if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
406	{
407		return CAMERA_CTRL_MODE_PRESETS;
408	}
409
410	return CAMERA_CTRL_MODE_PAN;
411}
412
413
414void clear_camera_tool()
415{
416	LLToolMgr* tool_mgr = LLToolMgr::getInstance();
417	if (tool_mgr->usingTransientTool() && 
418		tool_mgr->getCurrentTool() == LLToolCamera::getInstance())
419	{
420		tool_mgr->clearTransientTool();
421	}
422}
423
424
425void LLFloaterCamera::setMode(ECameraControlMode mode)
426{
427	if (mode != mCurrMode)
428	{
429		mPrevMode = mCurrMode;
430		mCurrMode = mode;
431	}
432	
433	updateState();
434}
435
436void LLFloaterCamera::switchMode(ECameraControlMode mode)
437{
438	setMode(mode);
439
440	switch (mode)
441	{
442	case CAMERA_CTRL_MODE_MODES:
443		if(sFreeCamera)
444		{
445			switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
446		}
447		break;
448
449	case CAMERA_CTRL_MODE_PAN:
450		sFreeCamera = false;
451		clear_camera_tool();
452		break;
453
454	case CAMERA_CTRL_MODE_FREE_CAMERA:
455		sFreeCamera = true;
456		activate_camera_tool();
457		break;
458
459	case CAMERA_CTRL_MODE_PRESETS:
460		if(sFreeCamera)
461		{
462			switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
463		}
464		break;
465
466	default:
467		//normally we won't occur here
468		llassert_always(FALSE);
469	}
470}
471
472
473void LLFloaterCamera::onClickBtn(ECameraControlMode mode)
474{
475	// check for a click on active button
476	if (mCurrMode == mode) mMode2Button[mode]->setToggleState(TRUE);
477	
478	switchMode(mode);
479
480}
481
482void LLFloaterCamera::assignButton2Mode(ECameraControlMode mode, const std::string& button_name)
483{
484	LLButton* button = getChild<LLButton>(button_name);
485	
486	button->setClickedCallback(boost::bind(&LLFloaterCamera::onClickBtn, this, mode));
487	mMode2Button[mode] = button;
488}
489
490void LLFloaterCamera::updateState()
491{
492	getChildView(ZOOM)->setVisible(CAMERA_CTRL_MODE_PAN == mCurrMode);
493	
494	bool show_presets = (CAMERA_CTRL_MODE_PRESETS == mCurrMode) || (CAMERA_CTRL_MODE_FREE_CAMERA == mCurrMode
495																	&& CAMERA_CTRL_MODE_PRESETS == mPrevMode);
496	getChildView(PRESETS)->setVisible(show_presets);
497	
498	bool show_camera_modes = CAMERA_CTRL_MODE_MODES == mCurrMode || (CAMERA_CTRL_MODE_FREE_CAMERA == mCurrMode
499																	&& CAMERA_CTRL_MODE_MODES == mPrevMode);
500	getChildView("camera_modes_list")->setVisible( show_camera_modes);
501
502	updateItemsSelection();
503
504	if (CAMERA_CTRL_MODE_FREE_CAMERA == mCurrMode)
505	{
506		return;
507	}
508
509	//updating buttons
510	std::map<ECameraControlMode, LLButton*>::const_iterator iter = mMode2Button.begin();
511	for (; iter != mMode2Button.end(); ++iter)
512	{
513		iter->second->setToggleState(iter->first == mCurrMode);
514	}
515}
516
517void LLFloaterCamera::updateItemsSelection()
518{
519	ECameraPreset preset = (ECameraPreset) gSavedSettings.getU32("CameraPreset");
520	LLSD argument;
521	argument["selected"] = preset == CAMERA_PRESET_REAR_VIEW;
522	getChild<LLPanelCameraItem>("rear_view")->setValue(argument);
523	argument["selected"] = preset == CAMERA_PRESET_GROUP_VIEW;
524	getChild<LLPanelCameraItem>("group_view")->setValue(argument);
525	argument["selected"] = preset == CAMERA_PRESET_FRONT_VIEW;
526	getChild<LLPanelCameraItem>("front_view")->setValue(argument);
527	argument["selected"] = gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK;
528	getChild<LLPanelCameraItem>("mouselook_view")->setValue(argument);
529	argument["selected"] = mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA;
530	getChild<LLPanelCameraItem>("object_view")->setValue(argument);
531}
532
533void LLFloaterCamera::onClickCameraItem(const LLSD& param)
534{
535	std::string name = param.asString();
536
537	if ("mouselook_view" == name)
538	{
539		gAgentCamera.changeCameraToMouselook();
540	}
541	else if ("object_view" == name)
542	{
543		LLFloaterCamera* camera_floater = LLFloaterCamera::findInstance();
544		if (camera_floater)
545		camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
546	}
547	else
548	{
549		switchToPreset(name);
550	}
551
552	LLFloaterCamera* camera_floater = LLFloaterCamera::findInstance();
553	if (camera_floater)
554	{
555		camera_floater->updateItemsSelection();
556		camera_floater->fromFreeToPresets();
557	}
558}
559
560/*static*/
561void LLFloaterCamera::switchToPreset(const std::string& name)
562{
563	sFreeCamera = false;
564	clear_camera_tool();
565	if ("rear_view" == name)
566	{
567		gAgentCamera.switchCameraPreset(CAMERA_PRESET_REAR_VIEW);
568	}
569	else if ("group_view" == name)
570	{
571		gAgentCamera.switchCameraPreset(CAMERA_PRESET_GROUP_VIEW);
572	}
573	else if ("front_view" == name)
574	{
575		gAgentCamera.switchCameraPreset(CAMERA_PRESET_FRONT_VIEW);
576	}
577}
578
579void LLFloaterCamera::fromFreeToPresets()
580{
581	if (!sFreeCamera && mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA && mPrevMode == CAMERA_CTRL_MODE_PRESETS)
582	{
583		switchMode(CAMERA_CTRL_MODE_PRESETS);
584	}
585}