summaryrefslogtreecommitdiff
path: root/indra/newview/llenvironment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llenvironment.cpp')
-rw-r--r--indra/newview/llenvironment.cpp862
1 files changed, 673 insertions, 189 deletions
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 9179c545df..4bf7a630a5 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -350,15 +350,25 @@ namespace
LLSettingsInjected(typename SETTINGT::ptr_t source) :
SETTINGT(),
- mSource(source)
+ mSource(source),
+ mLastSourceHash(0),
+ mLastHash(0)
{}
virtual ~LLSettingsInjected() {};
-// typename SETTINGT::ptr_t buildClone() const override;
-
typename SETTINGT::ptr_t getSource() const { return this->mSource; }
- void setSource(const typename SETTINGT::ptr_t &source) { this->mSource = source; this->setDirtyFlag(true); }
+ void setSource(const typename SETTINGT::ptr_t &source)
+ {
+ if (source.get() == this) // do not set a source to itself.
+ return;
+ this->mSource = source;
+ this->setDirtyFlag(true);
+ this->mLastSourceHash = 0;
+ }
+
+ virtual bool isDirty() const override { return SETTINGT::isDirty() || (this->mSource->isDirty()); }
+ virtual bool isVeryDirty() const override { return SETTINGT::isVeryDirty() || (this->mSource->isVeryDirty()); }
void injectSetting(const std::string keyname, LLSD value, LLUUID experience_id, F32Seconds transition)
{
@@ -377,32 +387,46 @@ namespace
}
}
- void removeInjection(const std::string keyname, LLUUID experience)
+ void removeInjection(const std::string keyname, LLUUID experience, LLSettingsBase::Seconds transition)
{
auto it = mInjections.begin();
while (it != mInjections.end())
{
- if (((*it)->mKeyName == keyname) &&
+ if ((keyname.empty() || ((*it)->mKeyName == keyname)) &&
(experience.isNull() || (experience == (*it)->mExperience)))
{
+ if (transition != LLEnvironment::TRANSITION_INSTANT)
+ {
+ typename Injection::ptr_t injection = std::make_shared<Injection>(transition, keyname, (*it)->mLastValue, false, LLUUID::null);
+ mInjections.push_front(injection); // push them in at the front so we don't check them again.
+ }
mInjections.erase(it++);
}
else
- {
++it;
- }
}
for (auto itexp = mOverrideExps.begin(); itexp != mOverrideExps.end();)
{
if (experience.isNull() || ((*itexp).second == experience))
{
+ if (transition != LLEnvironment::TRANSITION_INSTANT)
+ {
+ typename Injection::ptr_t injection = std::make_shared<Injection>(transition, (*itexp).first, mOverrideValues[(*itexp).first], false, LLUUID::null);
+ mInjections.push_front(injection);
+ }
mOverrideValues.erase((*itexp).first);
mOverrideExps.erase(itexp++);
}
else
++itexp;
}
+ std::stable_sort(mInjections.begin(), mInjections.end(), [](const typename Injection::ptr_t &a, const typename Injection::ptr_t &b) { return a->mTimeRemaining < b->mTimeRemaining; });
+ }
+
+ void removeInjections(LLUUID experience_id, LLSettingsBase::Seconds transition)
+ {
+ removeInjection(std::string(), experience_id, transition);
}
void injectExperienceValues(LLSD values, LLUUID experience_id, typename LLSettingsBase::Seconds transition)
@@ -414,47 +438,9 @@ namespace
this->setDirtyFlag(true);
}
- protected:
- struct Injection
- {
- Injection(typename LLSettingsBase::Seconds transition, const std::string &keyname, LLSD value, bool blendin, LLUUID experince, S32 index = -1) :
- mTransition(transition),
- mTimeRemaining(transition),
- mKeyName(keyname),
- mValue(value),
- mExperience(experince),
- mIndex(index),
- mBlendIn(blendin),
- mFirstTime(true)
- {}
-
- typename LLSettingsBase::Seconds mTransition;
- typename LLSettingsBase::Seconds mTimeRemaining;
- std::string mKeyName;
- LLSD mValue;
- LLUUID mExperience;
- S32 mIndex;
- bool mBlendIn;
- bool mFirstTime;
-
- typedef std::shared_ptr<Injection> ptr_t;
- };
-
-
- virtual void updateSettings() override
+ void applyInjections(LLSettingsBase::Seconds delta)
{
- static LLFrameTimer timer;
-
- typename LLSettingsBase::Seconds delta(timer.getElapsedTimeAndResetF32());
-
- resetSpecial();
-
- if (mSource && mSource->isDirty())
- {
- mSource->updateSettings();
- }
-
- this->mSettings = mSource->getSettings();
+ this->mSettings = this->mSource->getSettings();
for (auto ito = mOverrideValues.beginMap(); ito != mOverrideValues.endMap(); ++ito)
{
@@ -484,7 +470,7 @@ namespace
{
if ((*it)->mBlendIn)
{
- LL_WARNS("LAPRAS") << "Done blending '" << key_name << "' after " << (*it)->mTransition.value() - (*it)->mTimeRemaining.value() << " value now=" << target << LL_ENDL;
+ //_WARNS("LAPRAS") << "Done blending '" << key_name << "' after " << (*it)->mTransition.value() - (*it)->mTimeRemaining.value() << " value now=" << target << LL_ENDL;
mOverrideValues[key_name] = target;
mOverrideExps[key_name] = (*it)->mExperience;
this->mSettings[key_name] = target;
@@ -500,20 +486,85 @@ namespace
}
else if (skips.find(key_name) == skips.end())
{
- this->mSettings[key_name] = this->interpolateSDValue(key_name, value, target, this->getParameterMap(), mix, slerps);
-// LL_WARNS("LAPRAS") << "...blending '" << key_name << "' by " << mix << "% now=" << mSettings[key_name] << LL_ENDL;
+ if (!(*it)->mBlendIn)
+ mix = 1.0 - mix;
+ (*it)->mLastValue = this->interpolateSDValue(key_name, value, target, this->getParameterMap(), mix, slerps);
+ this->mSettings[key_name] = (*it)->mLastValue;
}
}
+ size_t hash = this->getHash();
+
+ if (hash != mLastHash)
+ {
+ this->setDirtyFlag(true);
+ mLastHash = hash;
+ }
+
it = mInjections.begin();
it = std::find_if(mInjections.begin(), mInjections.end(), [](const typename Injection::ptr_t &a) { return a->mTimeRemaining > 0.0f; });
if (it != mInjections.begin())
{
-
mInjections.erase(mInjections.begin(), mInjections.end());
}
+ }
+
+ bool hasInjections() const
+ {
+ return (!mInjections.empty() || (mOverrideValues.size() > 0));
+ }
+
+ protected:
+ struct Injection
+ {
+ Injection(typename LLSettingsBase::Seconds transition, const std::string &keyname, LLSD value, bool blendin, LLUUID experince, S32 index = -1) :
+ mTransition(transition),
+ mTimeRemaining(transition),
+ mKeyName(keyname),
+ mValue(value),
+ mExperience(experince),
+ mIndex(index),
+ mBlendIn(blendin),
+ mFirstTime(true)
+ {}
+
+ typename LLSettingsBase::Seconds mTransition;
+ typename LLSettingsBase::Seconds mTimeRemaining;
+ std::string mKeyName;
+ LLSD mValue;
+ LLSD mLastValue;
+ LLUUID mExperience;
+ S32 mIndex;
+ bool mBlendIn;
+ bool mFirstTime;
+
+ typedef std::shared_ptr<Injection> ptr_t;
+ };
+
+
+ virtual void updateSettings() override
+ {
+ static LLFrameTimer timer;
+
+ if (!this->mSource)
+ return;
+
+ // clears the dirty flag on this object. Need to prevent triggering
+ // more calls into this updateSettings
+ LLSettingsBase::updateSettings();
+
+ resetSpecial();
+
+ if (this->mSource->isDirty())
+ {
+ this->mSource->updateSettings();
+ }
+
+ typename LLSettingsBase::Seconds delta(timer.getElapsedTimeAndResetF32());
+
+
SETTINGT::updateSettings();
if (!mInjections.empty())
@@ -528,6 +579,8 @@ namespace
typedef std::map<std::string, LLUUID> key_to_expid_t;
typedef std::deque<typename Injection::ptr_t> injections_t;
+ size_t mLastSourceHash;
+ size_t mLastHash;
typename SETTINGT::ptr_t mSource;
injections_t mInjections;
LLSD mOverrideValues;
@@ -636,30 +689,87 @@ namespace
{
setBlendFactor(mix);
}
-
}
typedef LLSettingsInjected<LLSettingsVOSky> LLSettingsInjectedSky;
typedef LLSettingsInjected<LLSettingsVOWater> LLSettingsInjectedWater;
-#if 0
//=====================================================================
class DayInjection : public LLEnvironment::DayInstance
{
+ friend class InjectedTransition;
+
public:
typedef std::shared_ptr<DayInjection> ptr_t;
+ typedef std::weak_ptr<DayInjection> wptr_t;
- DayInjection(LLEnvironment::EnvSelection_t env) :
- LLEnvironment::DayInstance(env)
- {
- }
+ DayInjection(LLEnvironment::EnvSelection_t env);
+ virtual ~DayInjection();
- virtual ~DayInjection() { };
+ virtual bool applyTimeDelta(const LLSettingsBase::Seconds& delta) override;
- protected:
+ void setInjectedDay(const LLSettingsDay::ptr_t &pday, LLUUID experience_id, LLSettingsBase::Seconds transition);
+ void setInjectedSky(const LLSettingsSky::ptr_t &psky, LLUUID experience_id, LLSettingsBase::Seconds transition);
+ void setInjectedWater(const LLSettingsWater::ptr_t &pwater, LLUUID experience_id, LLSettingsBase::Seconds transition);
+
+ void injectSkySettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition);
+ void injectWaterSettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition);
+
+ void clearInjections(LLUUID experience_id, LLSettingsBase::Seconds transition_time);
+
+ virtual void animate() override;
+
+ LLEnvironment::DayInstance::ptr_t getBaseDayInstance() const { return mBaseDayInstance; }
+ void setBaseDayInstance(const LLEnvironment::DayInstance::ptr_t &baseday);
+
+ S32 countExperiencesActive() const { return mActiveExperiences.size(); }
+
+ bool isOverriddenSky() const { return !mSkyExperience.isNull(); }
+ bool isOverriddenWater() const { return !mWaterExperience.isNull(); }
+
+ bool hasInjections() const;
+
+ void testExperiencesOnParcel(S32 parcel_id);
private:
+ static void testExperiencesOnParcelCoro(wptr_t that, S32 parcel_id);
+
+
+ void animateSkyChange(LLSettingsSky::ptr_t psky, LLSettingsBase::Seconds transition);
+ void animateWaterChange(LLSettingsWater::ptr_t pwater, LLSettingsBase::Seconds transition);
+
+ void onEnvironmentChanged(LLEnvironment::EnvSelection_t env);
+ void onParcelChange();
+
+ void checkExperience();
+
+
+ LLEnvironment::DayInstance::ptr_t mBaseDayInstance;
+
+ LLSettingsInjectedSky::ptr_t mInjectedSky;
+ LLSettingsInjectedWater::ptr_t mInjectedWater;
+ std::set<LLUUID> mActiveExperiences;
+ LLUUID mDayExperience;
+ LLUUID mSkyExperience;
+ LLUUID mWaterExperience;
+ LLEnvironment::connection_t mEnvChangeConnection;
+ boost::signals2::connection mParcelChangeConnection;
};
-#endif
+
+ class InjectedTransition : public LLEnvironment::DayTransition
+ {
+ public:
+ InjectedTransition(const DayInjection::ptr_t &injection, const LLSettingsSky::ptr_t &skystart, const LLSettingsWater::ptr_t &waterstart, DayInstance::ptr_t &end, LLSettingsDay::Seconds time):
+ LLEnvironment::DayTransition(skystart, waterstart, end, time),
+ mInjection(injection)
+ { }
+ virtual ~InjectedTransition() { };
+
+ virtual void animate() override;
+
+ protected:
+ DayInjection::ptr_t mInjection;
+ };
+
}
//=========================================================================
@@ -871,7 +981,11 @@ bool LLEnvironment::isInventoryEnabled() const
void LLEnvironment::onRegionChange()
{
+// if (gAgent.getRegionCapability("ExperienceQuery").empty())
+// {
+// // for now environmental experiences do not survive region crossings
clearExperienceEnvironment(LLUUID::null, TRANSITION_DEFAULT);
+// }
LLViewerRegion* cur_region = gAgent.getRegion();
if (!cur_region)
@@ -950,7 +1064,10 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getEnvironmentInstance(LLEnviro
environment = environment->clone();
else
{
- environment = std::make_shared<DayInstance>(env);
+ if (env == ENV_PUSH)
+ environment = std::make_shared<DayInjection>(env);
+ else
+ environment = std::make_shared<DayInstance>(env);
}
mEnvironments[env] = environment;
}
@@ -1048,19 +1165,11 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe
else if (settings->getSettingsType() == "sky")
{
fixedEnvironment_t fixedenv(std::static_pointer_cast<LLSettingsSky>(settings), LLSettingsWater::ptr_t());
-// if (environment)
-// {
-// fixedenv.second = environment->getWater();
-// }
setEnvironment(env, fixedenv);
}
else if (settings->getSettingsType() == "water")
{
fixedEnvironment_t fixedenv(LLSettingsSky::ptr_t(), std::static_pointer_cast<LLSettingsWater>(settings));
-// if (environment)
-// {
-// fixedenv.first = environment->getSky();
-// }
setEnvironment(env, fixedenv);
}
}
@@ -1240,12 +1349,19 @@ void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool f
if ((mCurrentEnvironment != pinstance) || forced)
{
- DayInstance::ptr_t trans = std::make_shared<DayTransition>(
- mCurrentEnvironment->getSky(), mCurrentEnvironment->getWater(), pinstance, transition);
-
- trans->animate();
-
- mCurrentEnvironment = trans;
+ if (transition != TRANSITION_INSTANT)
+ {
+ DayInstance::ptr_t trans = std::make_shared<DayTransition>(
+ mCurrentEnvironment->getSky(), mCurrentEnvironment->getWater(), pinstance, transition);
+
+ trans->animate();
+
+ mCurrentEnvironment = trans;
+ }
+ else
+ {
+ mCurrentEnvironment = pinstance;
+ }
}
}
@@ -1358,8 +1474,12 @@ void LLEnvironment::update(const LLViewerCamera * cam)
F32Seconds delta(timer.getElapsedTimeAndResetF32());
- mCurrentEnvironment->applyTimeDelta(delta);
+ {
+ DayInstance::ptr_t keeper = mCurrentEnvironment;
+ // make sure the current environment does not go away until applyTimeDelta is done.
+ mCurrentEnvironment->applyTimeDelta(delta);
+ }
// update clouds, sun, and general
updateCloudScroll();
@@ -2174,7 +2294,7 @@ void LLEnvironment::handleEnvironmentPush(LLSD &message)
void LLEnvironment::handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition)
{
- clearExperienceEnvironment(experience_id, transition);
+ clearExperienceEnvironment(experience_id, LLSettingsBase::Seconds(transition));
}
void LLEnvironment::handleEnvironmentPushFull(LLUUID experience_id, LLSD &message, F32 transition)
@@ -2194,12 +2314,12 @@ void LLEnvironment::handleEnvironmentPushPartial(LLUUID experience_id, LLSD &mes
setExperienceEnvironment(experience_id, settings, LLSettingsBase::Seconds(transition));
}
-void LLEnvironment::clearExperienceEnvironment(LLUUID experience_id, F32 transition_time)
+void LLEnvironment::clearExperienceEnvironment(LLUUID experience_id, LLSettingsBase::Seconds transition_time)
{
- if (hasEnvironment(ENV_PUSH))
+ DayInjection::ptr_t injection = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH));
+ if (injection)
{
- clearEnvironment(ENV_PUSH);
- updateEnvironment(LLSettingsBase::Seconds(transition_time));
+ injection->clearInjections(experience_id, transition_time);
}
}
@@ -2216,15 +2336,49 @@ void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLUUID asset_
LLSettingsVOBase::getSettingsAsset(asset_id,
[this, experience_id, transition_time](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
{
- // individual settings will be overridden by the settings. No need to keep injections.
- onSetEnvAssetLoaded(ENV_PUSH, asset_id, settings,
- LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET,
- LLSettingsBase::Seconds(transition_time), status, NO_VERSION);
+ onSetExperienceEnvAssetLoaded(experience_id, settings, transition_time, status);
});
}
+void LLEnvironment::onSetExperienceEnvAssetLoaded(LLUUID experience_id, LLSettingsBase::ptr_t settings, F32 transition_time, S32 status)
+{
+ DayInjection::ptr_t environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH));
+ bool updateenvironment(false);
+
+ if (!settings || status)
+ {
+ LLSD args;
+ args["DESC"] = experience_id.asString();
+ LLNotificationsUtil::add("FailedToFindSettings", args);
+ return;
+ }
+
+ if (!environment)
+ {
+ environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH, true));
+ updateenvironment = true;
+ }
+
+ if (settings->getSettingsType() == "daycycle")
+ {
+ environment->setInjectedDay(std::static_pointer_cast<LLSettingsDay>(settings), experience_id, LLSettingsBase::Seconds(transition_time));
+ }
+ else if (settings->getSettingsType() == "sky")
+ {
+ environment->setInjectedSky(std::static_pointer_cast<LLSettingsSky>(settings), experience_id, LLSettingsBase::Seconds(transition_time));
+ }
+ else if (settings->getSettingsType() == "water")
+ {
+ environment->setInjectedWater(std::static_pointer_cast<LLSettingsWater>(settings), experience_id, LLSettingsBase::Seconds(transition_time));
+ }
+
+ if (updateenvironment)
+ updateEnvironment(TRANSITION_INSTANT, true);
+}
+
+
void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLSD data, F32 transition_time)
{
LLSD sky(data["sky"]);
@@ -2232,57 +2386,31 @@ void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLSD data, F3
if (sky.isUndefined() && water.isUndefined())
{
- clearExperienceEnvironment(experience_id, transition_time);
+ clearExperienceEnvironment(experience_id, LLSettingsBase::Seconds(transition_time));
return;
}
- LLSettingsInjectedSky::ptr_t pinjectedsky;
- LLSettingsInjectedWater::ptr_t pinjectedwater;
+ DayInjection::ptr_t environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH));
+ bool updateenvironment(false);
- fixedEnvironment_t pushenv = getEnvironmentFixed(ENV_PUSH, true);
+ if (!environment)
+ {
+ environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH, true));
+ updateenvironment = true;
+ }
if (!sky.isUndefined())
{
- bool newsky(false);
-
- if (pushenv.first)
- {
- pinjectedsky = std::dynamic_pointer_cast<LLSettingsInjectedSky>(pushenv.first);
- }
- if (!pinjectedsky)
- {
- pinjectedsky = std::make_shared<LLSettingsInjectedSky>(pushenv.first);
- newsky = true;
- }
-
- pinjectedsky->injectExperienceValues(sky, experience_id, F32Seconds(transition_time));
- if (!newsky)
- pinjectedsky.reset();
+ environment->injectSkySettings(sky, experience_id, LLSettingsBase::Seconds(transition_time));
}
if (!water.isUndefined())
{
- bool newwater(false);
- if (pushenv.second)
- {
- pinjectedwater = std::dynamic_pointer_cast<LLSettingsInjectedWater>(pushenv.second);
- }
- if (!pinjectedwater)
- {
- pinjectedwater = std::make_shared<LLSettingsInjectedWater>(pushenv.second);
- newwater = true;
- }
-
- pinjectedwater->injectExperienceValues(water, experience_id, F32Seconds(transition_time));
- if (!newwater)
- pinjectedwater.reset();
+ environment->injectWaterSettings(sky, experience_id, LLSettingsBase::Seconds(transition_time));
}
- if (pinjectedsky || pinjectedwater)
- {
- setEnvironment(ENV_PUSH, pinjectedsky, pinjectedwater);
- updateEnvironment(TRANSITION_INSTANT);
- }
+ if (updateenvironment)
+ updateEnvironment(TRANSITION_INSTANT, true);
}
@@ -2312,8 +2440,7 @@ LLEnvironment::DayInstance::DayInstance(EnvSelection_t env) :
mInitialized(false),
mType(TYPE_INVALID),
mSkyTrack(1),
- mEnv(env),
- mBackup(false)
+ mEnv(env)
{ }
@@ -2335,8 +2462,10 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::DayInstance::clone() const
return environment;
}
-void LLEnvironment::DayInstance::applyTimeDelta(const LLSettingsBase::Seconds& delta)
+bool LLEnvironment::DayInstance::applyTimeDelta(const LLSettingsBase::Seconds& delta)
{
+ ptr_t keeper(shared_from_this()); // makes sure that this does not go away while it is being worked on.
+
bool changed(false);
if (!mInitialized)
initialize();
@@ -2345,14 +2474,11 @@ void LLEnvironment::DayInstance::applyTimeDelta(const LLSettingsBase::Seconds& d
changed |= mBlenderSky->applyTimeDelta(delta);
if (mBlenderWater)
changed |= mBlenderWater->applyTimeDelta(delta);
- if (mBackup && changed)
- backup();
+ return changed;
}
void LLEnvironment::DayInstance::setDay(const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset)
{
- if (mType == TYPE_FIXED)
- LL_WARNS("ENVIRONMENT") << "Fixed day instance changed to Cycled" << LL_ENDL;
mType = TYPE_CYCLED;
mInitialized = false;
@@ -2372,8 +2498,6 @@ void LLEnvironment::DayInstance::setDay(const LLSettingsDay::ptr_t &pday, LLSett
void LLEnvironment::DayInstance::setSky(const LLSettingsSky::ptr_t &psky)
{
- if (mType == TYPE_CYCLED)
- LL_WARNS("ENVIRONMENT") << "Cycled day instance changed to FIXED" << LL_ENDL;
mType = TYPE_FIXED;
mInitialized = false;
@@ -2383,8 +2507,6 @@ void LLEnvironment::DayInstance::setSky(const LLSettingsSky::ptr_t &psky)
mSky->mReplaced |= different_sky;
mSky->update();
mBlenderSky.reset();
- if (mBackup)
- backup();
if (gAtmosphere)
{
@@ -2396,16 +2518,12 @@ void LLEnvironment::DayInstance::setSky(const LLSettingsSky::ptr_t &psky)
void LLEnvironment::DayInstance::setWater(const LLSettingsWater::ptr_t &pwater)
{
- if (mType == TYPE_CYCLED)
- LL_WARNS("ENVIRONMENT") << "Cycled day instance changed to FIXED" << LL_ENDL;
mType = TYPE_FIXED;
mInitialized = false;
mWater = pwater;
mWater->update();
mBlenderWater.reset();
- if (mBackup)
- backup();
}
void LLEnvironment::DayInstance::initialize()
@@ -2440,7 +2558,6 @@ void LLEnvironment::DayInstance::setSkyTrack(S32 trackno)
}
}
-
void LLEnvironment::DayInstance::setBlenders(const LLSettingsBlender::ptr_t &skyblend, const LLSettingsBlender::ptr_t &waterblend)
{
mBlenderSky = skyblend;
@@ -2448,52 +2565,6 @@ void LLEnvironment::DayInstance::setBlenders(const LLSettingsBlender::ptr_t &sky
}
-void LLEnvironment::DayInstance::setBackup(bool backupval)
-{
- if (backupval == mBackup)
- return;
-
- mBackup = backupval;
- LLSettingsSky::ptr_t psky = getSky();
- if (mBackup)
- {
- backup();
- }
- else
- {
- restore();
- mBackupSky = LLSD();
- mBackupWater = LLSD();
- }
-}
-
-void LLEnvironment::DayInstance::backup()
-{
- if (!mBackup)
- return;
-
- if (mSky)
- {
- mBackupSky = mSky->cloneSettings();
- }
- if (mWater)
- {
- mBackupWater = mWater->cloneSettings();
- }
-}
-
-void LLEnvironment::DayInstance::restore()
-{
- if (!mBackupSky.isUndefined() && mSky)
- {
- mSky->replaceSettings(mBackupSky);
- }
- if (!mBackupWater.isUndefined() && mWater)
- {
- mWater->replaceSettings(mBackupWater);
- }
-}
-
LLSettingsBase::TrackPosition LLEnvironment::DayInstance::secondsToKeyframe(LLSettingsDay::Seconds seconds)
{
return convert_time_to_position(seconds, mDayLength);
@@ -2551,10 +2622,13 @@ LLEnvironment::DayTransition::DayTransition(const LLSettingsSky::ptr_t &skystart
}
-void LLEnvironment::DayTransition::applyTimeDelta(const LLSettingsBase::Seconds& delta)
+bool LLEnvironment::DayTransition::applyTimeDelta(const LLSettingsBase::Seconds& delta)
{
- mNextInstance->applyTimeDelta(delta);
- DayInstance::applyTimeDelta(delta);
+ bool changed(false);
+
+ changed = mNextInstance->applyTimeDelta(delta);
+ changed |= DayInstance::applyTimeDelta(delta);
+ return changed;
}
void LLEnvironment::DayTransition::animate()
@@ -2659,3 +2733,413 @@ F64 LLTrackBlenderLoopingManual::getSpanLength(const LLSettingsDay::TrackBound_t
}
//=========================================================================
+namespace
+{
+ DayInjection::DayInjection(LLEnvironment::EnvSelection_t env):
+ LLEnvironment::DayInstance(env),
+ mBaseDayInstance(),
+ mInjectedSky(),
+ mInjectedWater(),
+ mActiveExperiences(),
+ mDayExperience(),
+ mSkyExperience(),
+ mWaterExperience(),
+ mEnvChangeConnection(),
+ mParcelChangeConnection()
+ {
+ mInjectedSky = std::make_shared<LLSettingsInjectedSky>(LLEnvironment::instance().getCurrentSky());
+ mInjectedWater = std::make_shared<LLSettingsInjectedWater>(LLEnvironment::instance().getCurrentWater());
+ mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance();
+ mSky = mInjectedSky;
+ mWater = mInjectedWater;
+
+ mEnvChangeConnection = LLEnvironment::instance().setEnvironmentChanged([this](LLEnvironment::EnvSelection_t env, S32) { onEnvironmentChanged(env); });
+ mParcelChangeConnection = gAgent.addParcelChangedCallback([this]() { onParcelChange(); });
+ }
+
+ DayInjection::~DayInjection()
+ {
+ if (mEnvChangeConnection.connected())
+ mEnvChangeConnection.disconnect();
+ if (mParcelChangeConnection.connected())
+ mParcelChangeConnection.disconnect();
+ }
+
+
+ bool DayInjection::applyTimeDelta(const LLSettingsBase::Seconds& delta)
+ {
+ bool changed(false);
+
+ if (mBaseDayInstance)
+ changed |= mBaseDayInstance->applyTimeDelta(delta);
+ mInjectedSky->applyInjections(delta);
+ mInjectedWater->applyInjections(delta);
+ changed |= LLEnvironment::DayInstance::applyTimeDelta(delta);
+ if (changed)
+ {
+ mInjectedSky->setDirtyFlag(true);
+ mInjectedWater->setDirtyFlag(true);
+ }
+ mInjectedSky->update();
+ mInjectedWater->update();
+
+ if (!hasInjections())
+ { // There are no injections being managed. This should really go away.
+ LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+ LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+ }
+
+ return changed;
+ }
+
+ void DayInjection::setBaseDayInstance(const LLEnvironment::DayInstance::ptr_t &baseday)
+ {
+ mBaseDayInstance = baseday;
+
+ if (mSkyExperience.isNull())
+ mInjectedSky->setSource(mBaseDayInstance->getSky());
+ if (mWaterExperience.isNull())
+ mInjectedWater->setSource(mBaseDayInstance->getWater());
+ }
+
+
+ bool DayInjection::hasInjections() const
+ {
+ return (!mSkyExperience.isNull() || !mWaterExperience.isNull() || !mDayExperience.isNull() ||
+ mBlenderSky || mBlenderWater || mInjectedSky->hasInjections() || mInjectedWater->hasInjections());
+ }
+
+
+ void DayInjection::testExperiencesOnParcel(S32 parcel_id)
+ {
+ LLCoros::instance().launch("DayInjection::testExperiencesOnParcel",
+ [this, parcel_id]() { DayInjection::testExperiencesOnParcelCoro(std::static_pointer_cast<DayInjection>(this->shared_from_this()), parcel_id); });
+
+ }
+
+ void DayInjection::setInjectedDay(const LLSettingsDay::ptr_t &pday, LLUUID experience_id, LLSettingsBase::Seconds transition)
+ {
+ mSkyExperience = experience_id;
+ mWaterExperience = experience_id;
+ mDayExperience = experience_id;
+
+ mBaseDayInstance = mBaseDayInstance->clone();
+ mBaseDayInstance->setEnvironmentSelection(LLEnvironment::ENV_NONE);
+ mBaseDayInstance->setDay(pday, mBaseDayInstance->getDayLength(), mBaseDayInstance->getDayOffset());
+ animateSkyChange(mBaseDayInstance->getSky(), transition);
+ animateWaterChange(mBaseDayInstance->getWater(), transition);
+
+ mActiveExperiences.insert(experience_id);
+ }
+
+ void DayInjection::setInjectedSky(const LLSettingsSky::ptr_t &psky, LLUUID experience_id, LLSettingsBase::Seconds transition)
+ {
+ mSkyExperience = experience_id;
+ mActiveExperiences.insert(experience_id);
+ checkExperience();
+ animateSkyChange(psky, transition);
+ }
+
+ void DayInjection::setInjectedWater(const LLSettingsWater::ptr_t &pwater, LLUUID experience_id, LLSettingsBase::Seconds transition)
+ {
+ mWaterExperience = experience_id;
+ mActiveExperiences.insert(experience_id);
+ checkExperience();
+ animateWaterChange(pwater, transition);
+ }
+
+ void DayInjection::injectSkySettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition)
+ {
+ mInjectedSky->injectExperienceValues(settings, experience_id, transition);
+ mActiveExperiences.insert(experience_id);
+ }
+
+ void DayInjection::injectWaterSettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition)
+ {
+ mInjectedWater->injectExperienceValues(settings, experience_id, transition);
+ mActiveExperiences.insert(experience_id);
+ }
+
+ void DayInjection::clearInjections(LLUUID experience_id, LLSettingsBase::Seconds transition_time)
+ {
+ if ((experience_id.isNull() && !mDayExperience.isNull()) || (experience_id == mDayExperience))
+ {
+ mDayExperience.setNull();
+ if (mSkyExperience == experience_id)
+ mSkyExperience.setNull();
+ if (mWaterExperience == experience_id)
+ mWaterExperience.setNull();
+
+ mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance();
+
+ if (mSkyExperience.isNull())
+ animateSkyChange(mBaseDayInstance->getSky(), transition_time);
+ if (mWaterExperience.isNull())
+ animateWaterChange(mBaseDayInstance->getWater(), transition_time);
+ }
+
+ if ((experience_id.isNull() && !mSkyExperience.isNull()) || (experience_id == mSkyExperience))
+ {
+ mSkyExperience.setNull();
+ animateSkyChange(mBaseDayInstance->getSky(), transition_time);
+ }
+ if ((experience_id.isNull() && !mWaterExperience.isNull()) || (experience_id == mWaterExperience))
+ {
+ mWaterExperience.setNull();
+ animateWaterChange(mBaseDayInstance->getWater(), transition_time);
+ }
+
+ mInjectedSky->removeInjections(experience_id, transition_time);
+ mInjectedWater->removeInjections(experience_id, transition_time);
+
+ if (experience_id.isNull())
+ mActiveExperiences.clear();
+ else
+ mActiveExperiences.erase(experience_id);
+
+ if ((transition_time == LLEnvironment::TRANSITION_INSTANT) && (countExperiencesActive() == 0))
+ { // Only do this if instant and there are no other experiences injecting values.
+ // (otherwise will be handled after transition)
+ LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+ LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+ }
+ }
+
+
+ void DayInjection::testExperiencesOnParcelCoro(wptr_t that, S32 parcel_id)
+ {
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("testExperiencesOnParcelCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ std::string url = gAgent.getRegionCapability("ExperienceQuery");
+
+ if (url.empty())
+ {
+ LL_WARNS("ENVIRONMENT") << "No experience query cap." << LL_ENDL;
+ return; // no checking in this region.
+ }
+
+ {
+ ptr_t thatlock(that);
+ std::stringstream fullurl;
+
+ if (!thatlock)
+ return;
+
+ fullurl << url << "?";
+ fullurl << "parcelid=" << parcel_id;
+
+ for (auto it = thatlock->mActiveExperiences.begin(); it != thatlock->mActiveExperiences.end(); ++it)
+ {
+ if (it != thatlock->mActiveExperiences.begin())
+ fullurl << ",";
+ else
+ fullurl << "&experiences=";
+ fullurl << (*it).asString();
+ }
+ url = fullurl.str();
+ }
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ LL_WARNS() << "Unable to retrieve experience status for parcel." << LL_ENDL;
+ return;
+ }
+
+ {
+ LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel();
+ if (!parcel)
+ return;
+
+ if (parcel_id != parcel->getLocalID())
+ {
+ // Agent no longer on queried parcel.
+ return;
+ }
+ }
+
+
+ LLSD experiences = result["experiences"];
+ {
+ ptr_t thatlock(that);
+ if (!thatlock)
+ return;
+
+ for (LLSD::map_iterator itr = experiences.beginMap(); itr != experiences.endMap(); ++itr)
+ {
+ if (!((*itr).second.asBoolean()))
+ thatlock->clearInjections(LLUUID((*itr).first), LLEnvironment::TRANSITION_FAST);
+
+ }
+ }
+ }
+
+ void DayInjection::animateSkyChange(LLSettingsSky::ptr_t psky, LLSettingsBase::Seconds transition)
+ {
+ if (mInjectedSky.get() == psky.get())
+ { // An attempt to animate to itself... don't do it.
+ return;
+ }
+ if (transition == LLEnvironment::TRANSITION_INSTANT)
+ {
+ mBlenderSky.reset();
+ mInjectedSky->setSource(psky);
+ }
+ else
+ {
+ LLSettingsSky::ptr_t start_sky(mInjectedSky->getSource()->buildClone());
+ LLSettingsSky::ptr_t target_sky(start_sky->buildClone());
+ mInjectedSky->setSource(target_sky);
+
+ mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(target_sky, start_sky, psky, transition);
+ mBlenderSky->setOnFinished(
+ [this, psky](LLSettingsBlender::ptr_t blender)
+ {
+ mBlenderSky.reset();
+ mInjectedSky->setSource(psky);
+ setSky(mInjectedSky);
+ if (!mBlenderWater && (countExperiencesActive() == 0))
+ {
+ LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+ LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+ }
+ });
+ }
+ }
+
+ void DayInjection::animateWaterChange(LLSettingsWater::ptr_t pwater, LLSettingsBase::Seconds transition)
+ {
+ if (mInjectedWater.get() == pwater.get())
+ { // An attempt to animate to itself. Bad idea.
+ return;
+ }
+ if (transition == LLEnvironment::TRANSITION_INSTANT)
+ {
+ mBlenderWater.reset();
+ mInjectedWater->setSource(pwater);
+ }
+ else
+ {
+ LLSettingsWater::ptr_t start_Water(mInjectedWater->getSource()->buildClone());
+ LLSettingsWater::ptr_t scratch_Water(start_Water->buildClone());
+ mInjectedWater->setSource(scratch_Water);
+
+ mBlenderWater = std::make_shared<LLSettingsBlenderTimeDelta>(scratch_Water, start_Water, pwater, transition);
+ mBlenderWater->setOnFinished(
+ [this, pwater](LLSettingsBlender::ptr_t blender)
+ {
+ mBlenderWater.reset();
+ mInjectedWater->setSource(pwater);
+ setWater(mInjectedWater);
+ if (!mBlenderSky && (countExperiencesActive() == 0))
+ {
+ LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+ LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+ }
+ });
+ }
+ }
+
+ void DayInjection::onEnvironmentChanged(LLEnvironment::EnvSelection_t env)
+ {
+ if (env >= LLEnvironment::ENV_PARCEL)
+ {
+ LLEnvironment::EnvSelection_t base_env(mBaseDayInstance->getEnvironmentSelection());
+ LLEnvironment::DayInstance::ptr_t nextbase = LLEnvironment::instance().getSharedEnvironmentInstance();
+
+ if ((base_env == LLEnvironment::ENV_NONE) || (nextbase == mBaseDayInstance) ||
+ (!mSkyExperience.isNull() && !mWaterExperience.isNull()))
+ { // base instance completely overridden, or not changed no transition will happen
+ return;
+ }
+
+ LL_WARNS("PUSHENV") << "Underlying environment has changed (" << env << ")! Base env is type " << base_env << LL_ENDL;
+
+ LLEnvironment::DayInstance::ptr_t trans = std::make_shared<InjectedTransition>(std::static_pointer_cast<DayInjection>(shared_from_this()),
+ mBaseDayInstance->getSky(), mBaseDayInstance->getWater(), nextbase, LLEnvironment::TRANSITION_DEFAULT);
+
+ trans->animate();
+ setBaseDayInstance(trans);
+ }
+ }
+
+ void DayInjection::onParcelChange()
+ {
+ S32 parcel_id(INVALID_PARCEL_ID);
+ LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel();
+
+ if (!parcel)
+ return;
+
+ parcel_id = parcel->getLocalID();
+
+ testExperiencesOnParcel(parcel_id);
+ }
+
+ void DayInjection::checkExperience()
+ {
+ if ((!mDayExperience.isNull()) && (mSkyExperience != mDayExperience) && (mWaterExperience != mDayExperience))
+ { // There was a day experience but we've replaced it with a water and a sky experience.
+ mDayExperience.setNull();
+ mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance();
+ }
+ }
+
+ void DayInjection::animate()
+ {
+
+ }
+
+ void InjectedTransition::animate()
+ {
+ mNextInstance->animate();
+
+ if (!mInjection->isOverriddenSky())
+ {
+ mSky = mStartSky->buildClone();
+ mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(mSky, mStartSky, mNextInstance->getSky(), mTransitionTime);
+ mBlenderSky->setOnFinished(
+ [this](LLSettingsBlender::ptr_t blender) {
+ mBlenderSky.reset();
+
+ if (!mBlenderSky && !mBlenderSky)
+ mInjection->setBaseDayInstance(mNextInstance);
+ else
+ mInjection->mInjectedSky->setSource(mNextInstance->getSky());
+ });
+ }
+ else
+ {
+ mSky = mInjection->getSky();
+ mBlenderSky.reset();
+ }
+
+ if (!mInjection->isOverriddenWater())
+ {
+ mWater = mStartWater->buildClone();
+ mBlenderWater = std::make_shared<LLSettingsBlenderTimeDelta>(mWater, mStartWater, mNextInstance->getWater(), mTransitionTime);
+ mBlenderWater->setOnFinished(
+ [this](LLSettingsBlender::ptr_t blender) {
+ mBlenderWater.reset();
+
+ if (!mBlenderSky && !mBlenderWater)
+ mInjection->setBaseDayInstance(mNextInstance);
+ else
+ mInjection->mInjectedWater->setSource(mNextInstance->getWater());
+ });
+ }
+ else
+ {
+ mWater = mInjection->getWater();
+ mBlenderWater.reset();
+ }
+
+ }
+
+}
+