PageRenderTime 77ms CodeModel.GetById 9ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llenvmanager.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 678 lines | 493 code | 114 blank | 71 comment | 45 complexity | bc5820634dc5a28f8a383e00ba3da9f2 MD5 | raw file
  1/**
  2 * @file llenvmanager.cpp
  3 * @brief Implementation of classes managing WindLight and water settings.
  4 *
  5 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2011, 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 "llenvmanager.h"
 30
 31#include "llagent.h"
 32#include "lldaycyclemanager.h"
 33#include "llviewercontrol.h" // for gSavedSettings
 34#include "llviewerregion.h"
 35#include "llwaterparammanager.h"
 36#include "llwlhandlers.h"
 37#include "llwlparammanager.h"
 38
 39std::string LLEnvPrefs::getWaterPresetName() const
 40{
 41	if (mWaterPresetName.empty())
 42	{
 43		llwarns << "Water preset name is empty" << llendl;
 44	}
 45
 46	return mWaterPresetName;
 47}
 48
 49std::string LLEnvPrefs::getSkyPresetName() const
 50{
 51	if (mSkyPresetName.empty())
 52	{
 53		llwarns << "Sky preset name is empty" << llendl;
 54	}
 55
 56	return mSkyPresetName;
 57}
 58
 59std::string LLEnvPrefs::getDayCycleName() const
 60{
 61	if (mDayCycleName.empty())
 62	{
 63		llwarns << "Day cycle name is empty" << llendl;
 64	}
 65
 66	return mDayCycleName;
 67}
 68
 69void LLEnvPrefs::setUseRegionSettings(bool val)
 70{
 71	mUseRegionSettings = val;
 72}
 73
 74void LLEnvPrefs::setUseWaterPreset(const std::string& name)
 75{
 76	mUseRegionSettings = false;
 77	mWaterPresetName = name;
 78}
 79
 80void LLEnvPrefs::setUseSkyPreset(const std::string& name)
 81{
 82	mUseRegionSettings = false;
 83	mUseDayCycle = false;
 84	mSkyPresetName = name;
 85}
 86
 87void LLEnvPrefs::setUseDayCycle(const std::string& name)
 88{
 89	mUseRegionSettings = false;
 90	mUseDayCycle = true;
 91	mDayCycleName = name;
 92}
 93
 94//=============================================================================
 95LLEnvManagerNew::LLEnvManagerNew()
 96{
 97	mInterpNextChangeMessage = true;
 98
 99	// Set default environment settings.
100	mUserPrefs.mUseRegionSettings = true;
101	mUserPrefs.mUseDayCycle = true;
102	mUserPrefs.mWaterPresetName = "Default";
103	mUserPrefs.mSkyPresetName = "Default";
104	mUserPrefs.mDayCycleName = "Default";
105}
106
107bool LLEnvManagerNew::getUseRegionSettings() const
108{
109	return mUserPrefs.getUseRegionSettings();
110}
111
112bool LLEnvManagerNew::getUseDayCycle() const
113{
114	return mUserPrefs.getUseDayCycle();
115}
116
117bool LLEnvManagerNew::getUseFixedSky() const
118{
119	return mUserPrefs.getUseFixedSky();
120}
121
122std::string LLEnvManagerNew::getWaterPresetName() const
123{
124	return mUserPrefs.getWaterPresetName();
125}
126
127std::string LLEnvManagerNew::getSkyPresetName() const
128{
129	return mUserPrefs.getSkyPresetName();
130}
131
132std::string LLEnvManagerNew::getDayCycleName() const
133{
134	return mUserPrefs.getDayCycleName();
135}
136
137const LLEnvironmentSettings& LLEnvManagerNew::getRegionSettings() const
138{
139	return !mNewRegionPrefs.isEmpty() ? mNewRegionPrefs : mCachedRegionPrefs;
140}
141
142void LLEnvManagerNew::setRegionSettings(const LLEnvironmentSettings& new_settings)
143{
144	// Set region settings override that will be used locally
145	// until user either uploads the changes or goes to another region.
146	mNewRegionPrefs = new_settings;
147}
148
149bool LLEnvManagerNew::usePrefs()
150{
151	LL_DEBUGS("Windlight") << "Displaying preferred environment" << LL_ENDL;
152	updateManagersFromPrefs(false);
153	return true;
154}
155
156bool LLEnvManagerNew::useDefaults()
157{
158	bool rslt;
159
160	rslt  = useDefaultWater();
161	rslt &= useDefaultSky();
162
163	return rslt;
164}
165
166bool LLEnvManagerNew::useRegionSettings()
167{
168	bool rslt;
169
170	rslt  = useRegionSky();
171	rslt &= useRegionWater();
172
173	return rslt;
174}
175
176bool LLEnvManagerNew::useWaterPreset(const std::string& name)
177{
178	LL_DEBUGS("Windlight") << "Displaying water preset " << name << LL_ENDL;
179	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
180	bool rslt = water_mgr.getParamSet(name, water_mgr.mCurParams);
181	llassert(rslt == true);
182	return rslt;
183}
184
185bool LLEnvManagerNew::useWaterParams(const LLSD& params)
186{
187	LL_DEBUGS("Windlight") << "Displaying water params" << LL_ENDL;
188	LLWaterParamManager::instance().mCurParams.setAll(params);
189	return true;
190}
191
192bool LLEnvManagerNew::useSkyPreset(const std::string& name)
193{
194	LLWLParamManager& sky_mgr = LLWLParamManager::instance();
195	LLWLParamSet param_set;
196
197	if (!sky_mgr.getParamSet(LLWLParamKey(name, LLEnvKey::SCOPE_LOCAL), param_set))
198	{
199		llwarns << "No sky preset named " << name << llendl;
200		return false;
201	}
202
203	LL_DEBUGS("Windlight") << "Displaying sky preset " << name << LL_ENDL;
204	sky_mgr.applySkyParams(param_set.getAll());
205	return true;
206}
207
208bool LLEnvManagerNew::useSkyParams(const LLSD& params)
209{
210	LL_DEBUGS("Windlight") << "Displaying sky params" << LL_ENDL;
211	LLWLParamManager::instance().applySkyParams(params);
212	return true;
213}
214
215bool LLEnvManagerNew::useDayCycle(const std::string& name, LLEnvKey::EScope scope)
216{
217	LLSD params;
218
219	if (scope == LLEnvKey::SCOPE_REGION)
220	{
221		LL_DEBUGS("Windlight") << "Displaying region day cycle " << name << LL_ENDL;
222		params = getRegionSettings().getWLDayCycle();
223	}
224	else
225	{
226		LL_DEBUGS("Windlight") << "Displaying local day cycle " << name << LL_ENDL;
227
228		if (!LLDayCycleManager::instance().getPreset(name, params))
229		{
230			llwarns << "No day cycle named " << name << llendl;
231			return false;
232		}
233	}
234
235	bool rslt = LLWLParamManager::instance().applyDayCycleParams(params, scope);
236	llassert(rslt == true);
237	return rslt;
238}
239
240bool LLEnvManagerNew::useDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time /* = 0.5*/)
241{
242	LL_DEBUGS("Windlight") << "Displaying day cycle params" << LL_ENDL;
243	return LLWLParamManager::instance().applyDayCycleParams(params, scope);
244}
245
246void LLEnvManagerNew::setUseRegionSettings(bool val)
247{
248	mUserPrefs.setUseRegionSettings(val);
249	saveUserPrefs();
250	updateManagersFromPrefs(false);
251}
252
253void LLEnvManagerNew::setUseWaterPreset(const std::string& name)
254{
255	// *TODO: make sure the preset exists.
256	if (name.empty())
257	{
258		llwarns << "Empty water preset name passed" << llendl;
259		return;
260	}
261
262	mUserPrefs.setUseWaterPreset(name);
263	saveUserPrefs();
264	updateManagersFromPrefs(false);
265}
266
267void LLEnvManagerNew::setUseSkyPreset(const std::string& name)
268{
269	// *TODO: make sure the preset exists.
270	if (name.empty())
271	{
272		llwarns << "Empty sky preset name passed" << llendl;
273		return;
274	}
275
276	mUserPrefs.setUseSkyPreset(name);
277	saveUserPrefs();
278	updateManagersFromPrefs(false);
279}
280
281void LLEnvManagerNew::setUseDayCycle(const std::string& name)
282{
283	if (!LLDayCycleManager::instance().presetExists(name))
284	{
285		llwarns << "Invalid day cycle name passed" << llendl;
286		return;
287	}
288
289	mUserPrefs.setUseDayCycle(name);
290	saveUserPrefs();
291	updateManagersFromPrefs(false);
292}
293
294void LLEnvManagerNew::loadUserPrefs()
295{
296	// operate on members directly to avoid side effects
297	mUserPrefs.mWaterPresetName	= gSavedSettings.getString("WaterPresetName");
298	mUserPrefs.mSkyPresetName	= gSavedSettings.getString("SkyPresetName");
299	mUserPrefs.mDayCycleName	= gSavedSettings.getString("DayCycleName");
300
301	mUserPrefs.mUseRegionSettings	= gSavedSettings.getBOOL("UseEnvironmentFromRegion");
302	mUserPrefs.mUseDayCycle			= gSavedSettings.getBOOL("UseDayCycle");
303}
304
305void LLEnvManagerNew::saveUserPrefs()
306{
307	gSavedSettings.setString("WaterPresetName",			getWaterPresetName());
308	gSavedSettings.setString("SkyPresetName",			getSkyPresetName());
309	gSavedSettings.setString("DayCycleName",			getDayCycleName());
310
311	gSavedSettings.setBOOL("UseEnvironmentFromRegion",	getUseRegionSettings());
312	gSavedSettings.setBOOL("UseDayCycle",				getUseDayCycle());
313
314	mUsePrefsChangeSignal();
315}
316
317void LLEnvManagerNew::setUserPrefs(
318	const std::string& water_preset,
319	const std::string& sky_preset,
320	const std::string& day_cycle_preset,
321	bool use_fixed_sky,
322	bool use_region_settings)
323{
324	// operate on members directly to avoid side effects
325	mUserPrefs.mWaterPresetName	= water_preset;
326	mUserPrefs.mSkyPresetName	= sky_preset;
327	mUserPrefs.mDayCycleName	= day_cycle_preset;
328
329	mUserPrefs.mUseRegionSettings	= use_region_settings;
330	mUserPrefs.mUseDayCycle			= !use_fixed_sky;
331
332	saveUserPrefs();
333	updateManagersFromPrefs(false);
334}
335
336void LLEnvManagerNew::dumpUserPrefs()
337{
338	LL_DEBUGS("Windlight") << "WaterPresetName: "	<< gSavedSettings.getString("WaterPresetName") << LL_ENDL;
339	LL_DEBUGS("Windlight") << "SkyPresetName: "		<< gSavedSettings.getString("SkyPresetName") << LL_ENDL;
340	LL_DEBUGS("Windlight") << "DayCycleName: "		<< gSavedSettings.getString("DayCycleName") << LL_ENDL;
341
342	LL_DEBUGS("Windlight") << "UseEnvironmentFromRegion: "	<< gSavedSettings.getBOOL("UseEnvironmentFromRegion") << LL_ENDL;
343	LL_DEBUGS("Windlight") << "UseDayCycle: "				<< gSavedSettings.getBOOL("UseDayCycle") << LL_ENDL;
344}
345
346void LLEnvManagerNew::dumpPresets()
347{
348	const LLEnvironmentSettings& region_settings = getRegionSettings();
349	std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : "Unknown region";
350
351	// Dump water presets.
352	LL_DEBUGS("Windlight") << "Waters:" << LL_ENDL;
353	if (region_settings.getWaterParams().size() != 0)
354	{
355		LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
356	}
357	LLWaterParamManager::preset_name_list_t water_presets;
358	LLWaterParamManager::instance().getPresetNames(water_presets);
359	for (LLWaterParamManager::preset_name_list_t::const_iterator it = water_presets.begin(); it != water_presets.end(); ++it)
360	{
361		LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
362	}
363
364	// Dump sky presets.
365	LL_DEBUGS("Windlight") << "Skies:" << LL_ENDL;
366	LLWLParamManager::preset_key_list_t sky_preset_keys;
367	LLWLParamManager::instance().getPresetKeys(sky_preset_keys);
368	for (LLWLParamManager::preset_key_list_t::const_iterator it = sky_preset_keys.begin(); it != sky_preset_keys.end(); ++it)
369	{
370		std::string preset_name = it->name;
371		std::string item_title;
372
373		if (it->scope == LLEnvKey::SCOPE_LOCAL) // local preset
374		{
375			item_title = preset_name;
376		}
377		else // region preset
378		{
379			item_title = preset_name + " (" + region_name + ")";
380		}
381		LL_DEBUGS("Windlight") << " - " << item_title << LL_ENDL;
382	}
383
384	// Dump day cycles.
385	LL_DEBUGS("Windlight") << "Days:" << LL_ENDL;
386	const LLSD& cur_region_dc = region_settings.getWLDayCycle();
387	if (cur_region_dc.size() != 0)
388	{
389		LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
390	}
391	LLDayCycleManager::preset_name_list_t days;
392	LLDayCycleManager::instance().getPresetNames(days);
393	for (LLDayCycleManager::preset_name_list_t::const_iterator it = days.begin(); it != days.end(); ++it)
394	{
395		LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
396	}
397}
398
399void LLEnvManagerNew::requestRegionSettings()
400{
401	LLEnvironmentRequest::initiate();
402}
403
404bool LLEnvManagerNew::sendRegionSettings(const LLEnvironmentSettings& new_settings)
405{
406	LLSD metadata;
407
408	metadata["regionID"] = gAgent.getRegion()->getRegionID();
409	// add last received update ID to outbound message so simulator can handle concurrent updates
410	metadata["messageID"] = mLastReceivedID;
411
412	return LLEnvironmentApply::initiateRequest(new_settings.makePacket(metadata));
413}
414
415boost::signals2::connection LLEnvManagerNew::setPreferencesChangeCallback(const prefs_change_signal_t::slot_type& cb)
416{
417	return mUsePrefsChangeSignal.connect(cb);
418}
419
420boost::signals2::connection LLEnvManagerNew::setRegionSettingsChangeCallback(const region_settings_change_signal_t::slot_type& cb)
421{
422	return mRegionSettingsChangeSignal.connect(cb);
423}
424
425boost::signals2::connection LLEnvManagerNew::setRegionChangeCallback(const region_change_signal_t::slot_type& cb)
426{
427	return mRegionChangeSignal.connect(cb);
428}
429
430boost::signals2::connection LLEnvManagerNew::setRegionSettingsAppliedCallback(const region_settings_applied_signal_t::slot_type& cb)
431{
432	return mRegionSettingsAppliedSignal.connect(cb);
433}
434
435// static
436bool LLEnvManagerNew::canEditRegionSettings()
437{
438	LLViewerRegion* region = gAgent.getRegion();
439	BOOL owner_or_god = gAgent.isGodlike() || (region && region->getOwner() == gAgent.getID());
440	BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
441
442	LL_DEBUGS("Windlight") << "Can edit region settings: " << (bool) owner_or_god_or_manager << LL_ENDL;
443	return owner_or_god_or_manager;
444}
445
446// static
447const std::string LLEnvManagerNew::getScopeString(LLEnvKey::EScope scope)
448{
449	switch(scope)
450	{
451		case LLEnvKey::SCOPE_LOCAL:
452			return LLTrans::getString("LocalSettings");
453		case LLEnvKey::SCOPE_REGION:
454			return LLTrans::getString("RegionSettings");
455		default:
456			return " (?)";
457	}
458}
459
460void LLEnvManagerNew::onRegionCrossing()
461{
462	LL_DEBUGS("Windlight") << "Crossed region" << LL_ENDL;
463	onRegionChange(true);
464}
465
466void LLEnvManagerNew::onTeleport()
467{
468	LL_DEBUGS("Windlight") << "Teleported" << LL_ENDL;
469	onRegionChange(false);
470}
471
472void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content)
473{
474	// If the message was valid, grab the UUID from it and save it for next outbound update message.
475	mLastReceivedID = content[0]["messageID"].asUUID();
476
477	// Refresh cached region settings.
478	LL_DEBUGS("Windlight") << "Caching region environment settings: " << content << LL_ENDL;
479	F32 sun_hour = 0; // *TODO
480	LLEnvironmentSettings new_settings(content[1], content[2], content[3], sun_hour);
481	mCachedRegionPrefs = new_settings;
482
483	// Load region sky presets.
484	LLWLParamManager::instance().refreshRegionPresets();
485
486	// If using server settings, update managers.
487	if (getUseRegionSettings())
488	{
489		updateManagersFromPrefs(mInterpNextChangeMessage);
490	}
491
492	// Let interested parties know about the region settings update.
493	mRegionSettingsChangeSignal();
494
495	// reset
496	mInterpNextChangeMessage = false;
497}
498
499void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok)
500{
501	LL_DEBUGS("Windlight") << "Applying region settings " << (ok ? "succeeded" : "failed") << LL_ENDL;
502
503	// Clear locally modified region settings because they have just been uploaded.
504	mNewRegionPrefs.clear();
505
506	mRegionSettingsAppliedSignal(ok);
507}
508
509//-- private methods ----------------------------------------------------------
510
511// virtual
512void LLEnvManagerNew::initSingleton()
513{
514	LL_DEBUGS("Windlight") << "Initializing LLEnvManagerNew" << LL_ENDL;
515
516	loadUserPrefs();
517}
518
519void LLEnvManagerNew::updateSkyFromPrefs()
520{
521	bool success = true;
522
523	// Sync sky with user prefs.
524	if (getUseRegionSettings()) // apply region-wide settings
525	{
526		success = useRegionSky();
527	}
528	else // apply user-specified settings
529	{
530		if (getUseDayCycle())
531		{
532			success = useDayCycle(getDayCycleName(), LLEnvKey::SCOPE_LOCAL);
533		}
534		else
535		{
536			success = useSkyPreset(getSkyPresetName());
537		}
538	}
539
540	// If something went wrong, fall back to defaults.
541	if (!success)
542	{
543		// *TODO: fix user prefs
544		useDefaultSky();
545	}
546}
547
548void LLEnvManagerNew::updateWaterFromPrefs(bool interpolate)
549{
550	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
551	LLSD target_water_params;
552
553	// Determine new water settings based on user prefs.
554
555	{
556		// Fall back to default water.
557		LLWaterParamSet default_water;
558		water_mgr.getParamSet("Default", default_water);
559		target_water_params = default_water.getAll();
560	}
561
562	if (getUseRegionSettings())
563	{
564		// *TODO: make sure whether region settings belong to the current region?
565		const LLSD& region_water_params = getRegionSettings().getWaterParams();
566		if (region_water_params.size() != 0) // region has no water settings
567		{
568			LL_DEBUGS("Windlight") << "Applying region water" << LL_ENDL;
569			target_water_params = region_water_params;
570		}
571		else
572		{
573			LL_DEBUGS("Windlight") << "Applying default water" << LL_ENDL;
574		}
575	}
576	else
577	{
578		std::string water = getWaterPresetName();
579		LL_DEBUGS("Windlight") << "Applying water preset [" << water << "]" << LL_ENDL;
580		LLWaterParamSet params;
581		if (!water_mgr.getParamSet(water, params))
582		{
583			llwarns << "No water preset named " << water << ", falling back to defaults" << llendl;
584			water_mgr.getParamSet("Default", params);
585
586			// *TODO: Fix user preferences accordingly.
587		}
588		target_water_params = params.getAll();
589	}
590
591	// Sync water with user prefs.
592	water_mgr.applyParams(target_water_params, interpolate);
593}
594
595void LLEnvManagerNew::updateManagersFromPrefs(bool interpolate)
596{
597	// Apply water settings.
598	updateWaterFromPrefs(interpolate);
599
600	// Apply sky settings.
601	updateSkyFromPrefs();
602}
603
604bool LLEnvManagerNew::useRegionSky()
605{
606	const LLEnvironmentSettings& region_settings = getRegionSettings();
607
608	// If region is set to defaults,
609	if (region_settings.getSkyMap().size() == 0)
610	{
611		// well... apply the default sky settings.
612		useDefaultSky();
613		return true;
614	}
615
616	// *TODO: Support fixed sky from region.
617
618	// Otherwise apply region day cycle.
619	LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
620	return useDayCycleParams(
621		region_settings.getWLDayCycle(),
622		LLEnvKey::SCOPE_REGION,
623		region_settings.getDayTime());
624}
625
626bool LLEnvManagerNew::useRegionWater()
627{
628	const LLEnvironmentSettings& region_settings = getRegionSettings();
629	const LLSD& region_water = region_settings.getWaterParams();
630
631	// If region is set to defaults,
632	if (region_water.size() == 0)
633	{
634		// well... apply the default water settings.
635		return useDefaultWater();
636	}
637
638	// Otherwise apply region water.
639	LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
640	return useWaterParams(region_water);
641}
642
643bool LLEnvManagerNew::useDefaultSky()
644{
645	return useDayCycle("Default", LLEnvKey::SCOPE_LOCAL);
646}
647
648bool LLEnvManagerNew::useDefaultWater()
649{
650	return useWaterPreset("Default");
651}
652
653
654void LLEnvManagerNew::onRegionChange(bool interpolate)
655{
656	// Avoid duplicating region setting requests
657	// by checking whether the region is actually changing.
658	LLViewerRegion* regionp = gAgent.getRegion();
659	LLUUID region_uuid = regionp ? regionp->getRegionID() : LLUUID::null;
660	if (region_uuid == mCurRegionUUID)
661	{
662		return;
663	}
664
665	// Clear locally modified region settings.
666	mNewRegionPrefs.clear();
667
668	// *TODO: clear environment settings of the previous region?
669
670	// Request environment settings of the new region.
671	LL_DEBUGS("Windlight") << "New viewer region: " << region_uuid << LL_ENDL;
672	mCurRegionUUID = region_uuid;
673	mInterpNextChangeMessage = interpolate;
674	requestRegionSettings();
675
676	// Let interested parties know agent region has been changed.
677	mRegionChangeSignal();
678}