summaryrefslogtreecommitdiff
path: root/indra/newview/llenvmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llenvmanager.cpp')
-rw-r--r--indra/newview/llenvmanager.cpp684
1 files changed, 684 insertions, 0 deletions
diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp
new file mode 100644
index 0000000000..c2720eaf28
--- /dev/null
+++ b/indra/newview/llenvmanager.cpp
@@ -0,0 +1,684 @@
+/**
+ * @file llenvmanager.cpp
+ * @brief Implementation of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llenvmanager.h"
+
+#include "llagent.h"
+#include "lldaycyclemanager.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewerregion.h"
+#include "llwaterparammanager.h"
+#include "llwlhandlers.h"
+#include "llwlparammanager.h"
+
+std::string LLEnvPrefs::getWaterPresetName() const
+{
+ if (mWaterPresetName.empty())
+ {
+ llwarns << "Water preset name is empty" << llendl;
+ }
+
+ return mWaterPresetName;
+}
+
+std::string LLEnvPrefs::getSkyPresetName() const
+{
+ if (mSkyPresetName.empty())
+ {
+ llwarns << "Sky preset name is empty" << llendl;
+ }
+
+ return mSkyPresetName;
+}
+
+std::string LLEnvPrefs::getDayCycleName() const
+{
+ if (mDayCycleName.empty())
+ {
+ llwarns << "Day cycle name is empty" << llendl;
+ }
+
+ return mDayCycleName;
+}
+
+void LLEnvPrefs::setUseRegionSettings(bool val)
+{
+ mUseRegionSettings = val;
+}
+
+void LLEnvPrefs::setUseWaterPreset(const std::string& name)
+{
+ mUseRegionSettings = false;
+ mWaterPresetName = name;
+}
+
+void LLEnvPrefs::setUseSkyPreset(const std::string& name)
+{
+ mUseRegionSettings = false;
+ mUseDayCycle = false;
+ mSkyPresetName = name;
+}
+
+void LLEnvPrefs::setUseDayCycle(const std::string& name)
+{
+ mUseRegionSettings = false;
+ mUseDayCycle = true;
+ mDayCycleName = name;
+}
+
+//=============================================================================
+LLEnvManagerNew::LLEnvManagerNew()
+{
+ mInterpNextChangeMessage = true;
+
+ // Set default environment settings.
+ mUserPrefs.mUseRegionSettings = true;
+ mUserPrefs.mUseDayCycle = true;
+ mUserPrefs.mWaterPresetName = "Default";
+ mUserPrefs.mSkyPresetName = "Default";
+ mUserPrefs.mDayCycleName = "Default";
+}
+
+bool LLEnvManagerNew::getUseRegionSettings() const
+{
+ return mUserPrefs.getUseRegionSettings();
+}
+
+bool LLEnvManagerNew::getUseDayCycle() const
+{
+ return mUserPrefs.getUseDayCycle();
+}
+
+bool LLEnvManagerNew::getUseFixedSky() const
+{
+ return mUserPrefs.getUseFixedSky();
+}
+
+std::string LLEnvManagerNew::getWaterPresetName() const
+{
+ return mUserPrefs.getWaterPresetName();
+}
+
+std::string LLEnvManagerNew::getSkyPresetName() const
+{
+ return mUserPrefs.getSkyPresetName();
+}
+
+std::string LLEnvManagerNew::getDayCycleName() const
+{
+ return mUserPrefs.getDayCycleName();
+}
+
+const LLEnvironmentSettings& LLEnvManagerNew::getRegionSettings() const
+{
+ return !mNewRegionPrefs.isEmpty() ? mNewRegionPrefs : mCachedRegionPrefs;
+}
+
+void LLEnvManagerNew::setRegionSettings(const LLEnvironmentSettings& new_settings)
+{
+ // Set region settings override that will be used locally
+ // until user either uploads the changes or goes to another region.
+ mNewRegionPrefs = new_settings;
+}
+
+bool LLEnvManagerNew::usePrefs()
+{
+ LL_DEBUGS("Windlight") << "Displaying preferred environment" << LL_ENDL;
+ updateManagersFromPrefs(false);
+ return true;
+}
+
+bool LLEnvManagerNew::useDefaults()
+{
+ bool rslt;
+
+ rslt = useDefaultWater();
+ rslt &= useDefaultSky();
+
+ return rslt;
+}
+
+bool LLEnvManagerNew::useRegionSettings()
+{
+ bool rslt;
+
+ rslt = useRegionSky();
+ rslt &= useRegionWater();
+
+ return rslt;
+}
+
+bool LLEnvManagerNew::useWaterPreset(const std::string& name)
+{
+ LL_DEBUGS("Windlight") << "Displaying water preset " << name << LL_ENDL;
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+ bool rslt = water_mgr.getParamSet(name, water_mgr.mCurParams);
+ llassert(rslt == true);
+ return rslt;
+}
+
+bool LLEnvManagerNew::useWaterParams(const LLSD& params)
+{
+ LL_DEBUGS("Windlight") << "Displaying water params" << LL_ENDL;
+ LLWaterParamManager::instance().mCurParams.setAll(params);
+ return true;
+}
+
+bool LLEnvManagerNew::useSkyPreset(const std::string& name)
+{
+ LLWLParamManager& sky_mgr = LLWLParamManager::instance();
+ LLWLParamSet param_set;
+
+ if (!sky_mgr.getParamSet(LLWLParamKey(name, LLEnvKey::SCOPE_LOCAL), param_set))
+ {
+ llwarns << "No sky preset named " << name << llendl;
+ return false;
+ }
+
+ LL_DEBUGS("Windlight") << "Displaying sky preset " << name << LL_ENDL;
+ sky_mgr.applySkyParams(param_set.getAll());
+ return true;
+}
+
+bool LLEnvManagerNew::useSkyParams(const LLSD& params)
+{
+ LL_DEBUGS("Windlight") << "Displaying sky params" << LL_ENDL;
+ LLWLParamManager::instance().applySkyParams(params);
+ return true;
+}
+
+bool LLEnvManagerNew::useDayCycle(const std::string& name, LLEnvKey::EScope scope)
+{
+ LLSD params;
+
+ if (scope == LLEnvKey::SCOPE_REGION)
+ {
+ LL_DEBUGS("Windlight") << "Displaying region day cycle " << name << LL_ENDL;
+ params = getRegionSettings().getWLDayCycle();
+ }
+ else
+ {
+ LL_DEBUGS("Windlight") << "Displaying local day cycle " << name << LL_ENDL;
+
+ if (!LLDayCycleManager::instance().getPreset(name, params))
+ {
+ llwarns << "No day cycle named " << name << llendl;
+ return false;
+ }
+ }
+
+ bool rslt = LLWLParamManager::instance().applyDayCycleParams(params, scope);
+ llassert(rslt == true);
+ return rslt;
+}
+
+bool LLEnvManagerNew::useDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time /* = 0.5*/)
+{
+ LL_DEBUGS("Windlight") << "Displaying day cycle params" << LL_ENDL;
+ return LLWLParamManager::instance().applyDayCycleParams(params, scope);
+}
+
+void LLEnvManagerNew::setUseRegionSettings(bool val)
+{
+ mUserPrefs.setUseRegionSettings(val);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::setUseWaterPreset(const std::string& name)
+{
+ // *TODO: make sure the preset exists.
+ if (name.empty())
+ {
+ llwarns << "Empty water preset name passed" << llendl;
+ return;
+ }
+
+ mUserPrefs.setUseWaterPreset(name);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::setUseSkyPreset(const std::string& name)
+{
+ // *TODO: make sure the preset exists.
+ if (name.empty())
+ {
+ llwarns << "Empty sky preset name passed" << llendl;
+ return;
+ }
+
+ mUserPrefs.setUseSkyPreset(name);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::setUseDayCycle(const std::string& name)
+{
+ if (!LLDayCycleManager::instance().presetExists(name))
+ {
+ llwarns << "Invalid day cycle name passed" << llendl;
+ return;
+ }
+
+ mUserPrefs.setUseDayCycle(name);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::loadUserPrefs()
+{
+ // operate on members directly to avoid side effects
+ mUserPrefs.mWaterPresetName = gSavedSettings.getString("WaterPresetName");
+ mUserPrefs.mSkyPresetName = gSavedSettings.getString("SkyPresetName");
+ mUserPrefs.mDayCycleName = gSavedSettings.getString("DayCycleName");
+
+ mUserPrefs.mUseRegionSettings = gSavedSettings.getBOOL("UseEnvironmentFromRegion");
+ mUserPrefs.mUseDayCycle = gSavedSettings.getBOOL("UseDayCycle");
+}
+
+void LLEnvManagerNew::saveUserPrefs()
+{
+ gSavedSettings.setString("WaterPresetName", getWaterPresetName());
+ gSavedSettings.setString("SkyPresetName", getSkyPresetName());
+ gSavedSettings.setString("DayCycleName", getDayCycleName());
+
+ gSavedSettings.setBOOL("UseEnvironmentFromRegion", getUseRegionSettings());
+ gSavedSettings.setBOOL("UseDayCycle", getUseDayCycle());
+
+ mUsePrefsChangeSignal();
+}
+
+void LLEnvManagerNew::setUserPrefs(
+ const std::string& water_preset,
+ const std::string& sky_preset,
+ const std::string& day_cycle_preset,
+ bool use_fixed_sky,
+ bool use_region_settings)
+{
+ // operate on members directly to avoid side effects
+ mUserPrefs.mWaterPresetName = water_preset;
+ mUserPrefs.mSkyPresetName = sky_preset;
+ mUserPrefs.mDayCycleName = day_cycle_preset;
+
+ mUserPrefs.mUseRegionSettings = use_region_settings;
+ mUserPrefs.mUseDayCycle = !use_fixed_sky;
+
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::dumpUserPrefs()
+{
+ LL_DEBUGS("Windlight") << "WaterPresetName: " << gSavedSettings.getString("WaterPresetName") << LL_ENDL;
+ LL_DEBUGS("Windlight") << "SkyPresetName: " << gSavedSettings.getString("SkyPresetName") << LL_ENDL;
+ LL_DEBUGS("Windlight") << "DayCycleName: " << gSavedSettings.getString("DayCycleName") << LL_ENDL;
+
+ LL_DEBUGS("Windlight") << "UseEnvironmentFromRegion: " << gSavedSettings.getBOOL("UseEnvironmentFromRegion") << LL_ENDL;
+ LL_DEBUGS("Windlight") << "UseDayCycle: " << gSavedSettings.getBOOL("UseDayCycle") << LL_ENDL;
+}
+
+void LLEnvManagerNew::dumpPresets()
+{
+ const LLEnvironmentSettings& region_settings = getRegionSettings();
+ std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : "Unknown region";
+
+ // Dump water presets.
+ LL_DEBUGS("Windlight") << "Waters:" << LL_ENDL;
+ if (region_settings.getWaterParams().size() != 0)
+ {
+ LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
+ }
+ LLWaterParamManager::preset_name_list_t water_presets;
+ LLWaterParamManager::instance().getPresetNames(water_presets);
+ for (LLWaterParamManager::preset_name_list_t::const_iterator it = water_presets.begin(); it != water_presets.end(); ++it)
+ {
+ LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
+ }
+
+ // Dump sky presets.
+ LL_DEBUGS("Windlight") << "Skies:" << LL_ENDL;
+ LLWLParamManager::preset_key_list_t sky_preset_keys;
+ LLWLParamManager::instance().getPresetKeys(sky_preset_keys);
+ for (LLWLParamManager::preset_key_list_t::const_iterator it = sky_preset_keys.begin(); it != sky_preset_keys.end(); ++it)
+ {
+ std::string preset_name = it->name;
+ std::string item_title;
+
+ if (it->scope == LLEnvKey::SCOPE_LOCAL) // local preset
+ {
+ item_title = preset_name;
+ }
+ else // region preset
+ {
+ item_title = preset_name + " (" + region_name + ")";
+ }
+ LL_DEBUGS("Windlight") << " - " << item_title << LL_ENDL;
+ }
+
+ // Dump day cycles.
+ LL_DEBUGS("Windlight") << "Days:" << LL_ENDL;
+ const LLSD& cur_region_dc = region_settings.getWLDayCycle();
+ if (cur_region_dc.size() != 0)
+ {
+ LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
+ }
+ LLDayCycleManager::preset_name_list_t days;
+ LLDayCycleManager::instance().getPresetNames(days);
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = days.begin(); it != days.end(); ++it)
+ {
+ LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
+ }
+}
+
+void LLEnvManagerNew::requestRegionSettings()
+{
+ LLEnvironmentRequest::initiate();
+}
+
+bool LLEnvManagerNew::sendRegionSettings(const LLEnvironmentSettings& new_settings)
+{
+ LLSD metadata;
+
+ metadata["regionID"] = gAgent.getRegion()->getRegionID();
+ // add last received update ID to outbound message so simulator can handle concurrent updates
+ metadata["messageID"] = mLastReceivedID;
+
+ return LLEnvironmentApply::initiateRequest(new_settings.makePacket(metadata));
+}
+
+boost::signals2::connection LLEnvManagerNew::setPreferencesChangeCallback(const prefs_change_signal_t::slot_type& cb)
+{
+ return mUsePrefsChangeSignal.connect(cb);
+}
+
+boost::signals2::connection LLEnvManagerNew::setRegionSettingsChangeCallback(const region_settings_change_signal_t::slot_type& cb)
+{
+ return mRegionSettingsChangeSignal.connect(cb);
+}
+
+boost::signals2::connection LLEnvManagerNew::setRegionChangeCallback(const region_change_signal_t::slot_type& cb)
+{
+ return mRegionChangeSignal.connect(cb);
+}
+
+boost::signals2::connection LLEnvManagerNew::setRegionSettingsAppliedCallback(const region_settings_applied_signal_t::slot_type& cb)
+{
+ return mRegionSettingsAppliedSignal.connect(cb);
+}
+
+// static
+bool LLEnvManagerNew::canEditRegionSettings()
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ BOOL owner_or_god = gAgent.isGodlike() || (region && region->getOwner() == gAgent.getID());
+ BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
+
+ LL_DEBUGS("Windlight") << "Can edit region settings: " << (bool) owner_or_god_or_manager << LL_ENDL;
+ return owner_or_god_or_manager;
+}
+
+// static
+const std::string LLEnvManagerNew::getScopeString(LLEnvKey::EScope scope)
+{
+ switch(scope)
+ {
+ case LLEnvKey::SCOPE_LOCAL:
+ return LLTrans::getString("LocalSettings");
+ case LLEnvKey::SCOPE_REGION:
+ return LLTrans::getString("RegionSettings");
+ default:
+ return " (?)";
+ }
+}
+
+void LLEnvManagerNew::onRegionCrossing()
+{
+ LL_DEBUGS("Windlight") << "Crossed region" << LL_ENDL;
+ onRegionChange(true);
+}
+
+void LLEnvManagerNew::onTeleport()
+{
+ LL_DEBUGS("Windlight") << "Teleported" << LL_ENDL;
+ onRegionChange(false);
+}
+
+void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content)
+{
+ // If the message was valid, grab the UUID from it and save it for next outbound update message.
+ mLastReceivedID = content[0]["messageID"].asUUID();
+
+ // Refresh cached region settings.
+ LL_DEBUGS("Windlight") << "Caching region environment settings: " << content << LL_ENDL;
+ F32 sun_hour = 0; // *TODO
+ LLEnvironmentSettings new_settings(content[1], content[2], content[3], sun_hour);
+ mCachedRegionPrefs = new_settings;
+
+ // Load region sky presets.
+ LLWLParamManager::instance().refreshRegionPresets();
+
+ // If using server settings, update managers.
+ if (getUseRegionSettings())
+ {
+ updateManagersFromPrefs(mInterpNextChangeMessage);
+ }
+
+ // Let interested parties know about the region settings update.
+ mRegionSettingsChangeSignal();
+
+ // reset
+ mInterpNextChangeMessage = false;
+}
+
+void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok)
+{
+ LL_DEBUGS("Windlight") << "Applying region settings " << (ok ? "succeeded" : "failed") << LL_ENDL;
+
+ // Clear locally modified region settings because they have just been uploaded.
+ mNewRegionPrefs.clear();
+
+ mRegionSettingsAppliedSignal(ok);
+}
+
+//-- private methods ----------------------------------------------------------
+
+// virtual
+void LLEnvManagerNew::initSingleton()
+{
+ LL_DEBUGS("Windlight") << "Initializing LLEnvManagerNew" << LL_ENDL;
+
+ loadUserPrefs();
+}
+
+void LLEnvManagerNew::updateSkyFromPrefs()
+{
+ bool success = true;
+
+ // Sync sky with user prefs.
+ if (getUseRegionSettings()) // apply region-wide settings
+ {
+ success = useRegionSky();
+ }
+ else // apply user-specified settings
+ {
+ if (getUseDayCycle())
+ {
+ success = useDayCycle(getDayCycleName(), LLEnvKey::SCOPE_LOCAL);
+ }
+ else
+ {
+ success = useSkyPreset(getSkyPresetName());
+ }
+ }
+
+ // If something went wrong, fall back to defaults.
+ if (!success)
+ {
+ // *TODO: fix user prefs
+ useDefaultSky();
+ }
+}
+
+void LLEnvManagerNew::updateWaterFromPrefs(bool interpolate)
+{
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+ LLSD target_water_params;
+
+ // Determine new water settings based on user prefs.
+
+ {
+ // Fall back to default water.
+ LLWaterParamSet default_water;
+ water_mgr.getParamSet("Default", default_water);
+ target_water_params = default_water.getAll();
+ }
+
+ if (getUseRegionSettings())
+ {
+ // *TODO: make sure whether region settings belong to the current region?
+ const LLSD& region_water_params = getRegionSettings().getWaterParams();
+ if (region_water_params.size() != 0) // region has no water settings
+ {
+ LL_DEBUGS("Windlight") << "Applying region water" << LL_ENDL;
+ target_water_params = region_water_params;
+ }
+ else
+ {
+ LL_DEBUGS("Windlight") << "Applying default water" << LL_ENDL;
+ }
+ }
+ else
+ {
+ std::string water = getWaterPresetName();
+ LL_DEBUGS("Windlight") << "Applying water preset [" << water << "]" << LL_ENDL;
+ LLWaterParamSet params;
+ if (!water_mgr.getParamSet(water, params))
+ {
+ llwarns << "No water preset named " << water << ", falling back to defaults" << llendl;
+ water_mgr.getParamSet("Default", params);
+
+ // *TODO: Fix user preferences accordingly.
+ }
+ target_water_params = params.getAll();
+ }
+
+ // Sync water with user prefs.
+ water_mgr.applyParams(target_water_params, interpolate);
+}
+
+void LLEnvManagerNew::updateManagersFromPrefs(bool interpolate)
+{
+ // Apply water settings.
+ updateWaterFromPrefs(interpolate);
+
+ // Apply sky settings.
+ updateSkyFromPrefs();
+}
+
+bool LLEnvManagerNew::useRegionSky()
+{
+ const LLEnvironmentSettings& region_settings = getRegionSettings();
+
+ // If region is set to defaults,
+ if (region_settings.getSkyMap().size() == 0)
+ {
+ // well... apply the default sky settings.
+ useDefaultSky();
+ return true;
+ }
+
+ // *TODO: Support fixed sky from region.
+
+ // Otherwise apply region day cycle.
+ LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
+ return useDayCycleParams(
+ region_settings.getWLDayCycle(),
+ LLEnvKey::SCOPE_REGION,
+ region_settings.getDayTime());
+}
+
+bool LLEnvManagerNew::useRegionWater()
+{
+ const LLEnvironmentSettings& region_settings = getRegionSettings();
+ const LLSD& region_water = region_settings.getWaterParams();
+
+ // If region is set to defaults,
+ if (region_water.size() == 0)
+ {
+ // well... apply the default water settings.
+ return useDefaultWater();
+ }
+
+ // Otherwise apply region water.
+ LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
+ return useWaterParams(region_water);
+}
+
+bool LLEnvManagerNew::useDefaultSky()
+{
+ return useDayCycle("Default", LLEnvKey::SCOPE_LOCAL);
+}
+
+bool LLEnvManagerNew::useDefaultWater()
+{
+ return useWaterPreset("Default");
+}
+
+
+void LLEnvManagerNew::onRegionChange(bool interpolate)
+{
+ // Avoid duplicating region setting requests
+ // by checking whether the region is actually changing.
+ LLViewerRegion* regionp = gAgent.getRegion();
+ LLUUID region_uuid = regionp ? regionp->getRegionID() : LLUUID::null;
+ if (region_uuid == mCurRegionUUID)
+ {
+ return;
+ }
+
+ // Clear locally modified region settings.
+ mNewRegionPrefs.clear();
+
+ // *TODO: clear environment settings of the previous region?
+
+ // Request environment settings of the new region.
+ LL_DEBUGS("Windlight") << "New viewer region: " << region_uuid << LL_ENDL;
+ mCurRegionUUID = region_uuid;
+ mInterpNextChangeMessage = interpolate;
+ requestRegionSettings();
+
+ // Let interested parties know agent region has been changed.
+ mRegionChangeSignal();
+}