diff options
Diffstat (limited to 'indra/llinventory')
-rw-r--r-- | indra/llinventory/llsettingsbase.cpp | 192 | ||||
-rw-r--r-- | indra/llinventory/llsettingsbase.h | 26 | ||||
-rw-r--r-- | indra/llinventory/llsettingssky.cpp | 10 | ||||
-rw-r--r-- | indra/llinventory/llsettingswater.cpp | 2 |
4 files changed, 154 insertions, 76 deletions
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp index 2adbb213e6..80680948b5 100644 --- a/indra/llinventory/llsettingsbase.cpp +++ b/indra/llinventory/llsettingsbase.cpp @@ -80,7 +80,7 @@ LLSettingsBase::LLSettingsBase(const LLSD setting) : //========================================================================= void LLSettingsBase::lerpSettings(const LLSettingsBase &other, F64 mix) { - mSettings = interpolateSDMap(mSettings, other.mSettings, mix); + mSettings = interpolateSDMap(mSettings, other.mSettings, other.getParameterMap(), mix); setDirtyFlag(true); } @@ -158,7 +158,7 @@ LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) cons return newSettings; } -LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, F64 mix) const +LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, F64 mix) const { LLSD newSettings; @@ -173,81 +173,33 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, F if (skip.find(key_name) != skip.end()) continue; - if (!other.has(key_name)) - { // The other does not contain this setting, keep the original value - // TODO: Should I blend this out instead? - newSettings[key_name] = value; - continue; - } - LLSD::Type setting_type = value.type(); - LLSD other_value = other[key_name]; - - if (other_value.type() != setting_type) - { - // The data type mismatched between this and other. Hard switch when we pass the break point - // but issue a warning. - LL_WARNS("SETTINGS") << "Setting lerp between mismatched types for '" << key_name << "'." << LL_ENDL; - newSettings[key_name] = (mix > BREAK_POINT) ? other_value : value; - continue; + LLSD other_value; + if (other.has(key_name)) + { + other_value = other[key_name]; } - - switch (setting_type) + else { - case LLSD::TypeInteger: - // lerp between the two values rounding the result to the nearest integer. - newSettings[key_name] = LLSD::Integer(llroundf(lerp(value.asReal(), other_value.asReal(), mix))); - break; - case LLSD::TypeReal: - // lerp between the two values. - newSettings[key_name] = LLSD::Real(lerp(value.asReal(), other_value.asReal(), mix)); - break; - case LLSD::TypeMap: - // deep copy. - newSettings[key_name] = interpolateSDMap(value, other_value, mix); - break; - - case LLSD::TypeArray: + parammapping_t::const_iterator def_iter = defaults.find(key_name); + if (def_iter != defaults.end()) { - LLSD newvalue(LLSD::emptyArray()); - - if (slerps.find(key_name) != slerps.end()) - { - LLQuaternion a(value); - LLQuaternion b(other_value); - LLQuaternion q = slerp(mix, a, b); - newvalue = q.getValue(); - } - else - { // TODO: We could expand this to inspect the type and do a deep lerp based on type. - // for now assume a heterogeneous array of reals. - size_t len = std::max(value.size(), other_value.size()); - - for (size_t i = 0; i < len; ++i) - { - - newvalue[i] = lerp(value[i].asReal(), other_value[i].asReal(), mix); - } - } - - newSettings[key_name] = newvalue; + other_value = def_iter->second.getDefaultValue(); + } + else if (value.type() == LLSD::TypeMap) + { + // interpolate in case there are defaults inside (part of legacy) + other_value = LLSDMap(); + } + else + { + // The other or defaults does not contain this setting, keep the original value + // TODO: Should I blend this out instead? + newSettings[key_name] = value; + continue; } - - break; - - case LLSD::TypeUUID: - newSettings[key_name] = value.asUUID(); - break; - -// case LLSD::TypeBoolean: -// case LLSD::TypeString: -// case LLSD::TypeURI: -// case LLSD::TypeBinary: -// case LLSD::TypeDate: - default: - // atomic or unknown data types. Lerping between them does not make sense so switch at the break. - newSettings[key_name] = (mix > BREAK_POINT) ? other_value : value; - break; } + + newSettings[key_name] = interpolateSDValue(key_name, value, other_value, defaults, mix, slerps); } // Special handling cases @@ -264,6 +216,27 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, F // Now add anything that is in other but not in the settings for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it) { + std::string key_name = (*it).first; + + if (skip.find(key_name) != skip.end()) + continue; + + if (settings.has(key_name)) + continue; + + parammapping_t::const_iterator def_iter = defaults.find(key_name); + if (def_iter != defaults.end()) + { + // Blend against default value + newSettings[key_name] = interpolateSDValue(key_name, def_iter->second.getDefaultValue(), (*it).second, defaults, mix, slerps); + } + // else do nothing when no known defaults + // TODO: Should I blend this out instead? + } + + // Note: writes variables from skip list, bug? + for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it) + { // TODO: Should I blend this in instead? if (skip.find((*it).first) == skip.end()) continue; @@ -277,6 +250,81 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, F return newSettings; } +LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD &value, const LLSD &other_value, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const +{ + LLSD new_value; + + LLSD::Type setting_type = value.type(); + + if (other_value.type() != setting_type) + { + // The data type mismatched between this and other. Hard switch when we pass the break point + // but issue a warning. + LL_WARNS("SETTINGS") << "Setting lerp between mismatched types for '" << key_name << "'." << LL_ENDL; + new_value = (mix > BREAK_POINT) ? other_value : value; + } + + switch (setting_type) + { + case LLSD::TypeInteger: + // lerp between the two values rounding the result to the nearest integer. + new_value = LLSD::Integer(llroundf(lerp(value.asReal(), other_value.asReal(), mix))); + break; + case LLSD::TypeReal: + // lerp between the two values. + new_value = LLSD::Real(lerp(value.asReal(), other_value.asReal(), mix)); + break; + case LLSD::TypeMap: + // deep copy. + new_value = interpolateSDMap(value, other_value, defaults, mix); + break; + + case LLSD::TypeArray: + { + LLSD new_array(LLSD::emptyArray()); + + if (slerps.find(key_name) != slerps.end()) + { + LLQuaternion a(value); + LLQuaternion b(other_value); + LLQuaternion q = slerp(mix, a, b); + new_array = q.getValue(); + } + else + { // TODO: We could expand this to inspect the type and do a deep lerp based on type. + // for now assume a heterogeneous array of reals. + size_t len = std::max(value.size(), other_value.size()); + + for (size_t i = 0; i < len; ++i) + { + + new_array[i] = lerp(value[i].asReal(), other_value[i].asReal(), mix); + } + } + + new_value = new_array; + } + + break; + + case LLSD::TypeUUID: + new_value = value.asUUID(); + break; + + // case LLSD::TypeBoolean: + // case LLSD::TypeString: + // case LLSD::TypeURI: + // case LLSD::TypeBinary: + // case LLSD::TypeDate: + default: + // atomic or unknown data types. Lerping between them does not make sense so switch at the break. + new_value = (mix > BREAK_POINT) ? other_value : value; + break; + } + + return new_value; +} + LLSettingsBase::stringset_t LLSettingsBase::getSkipInterpolateKeys() const { static stringset_t skipSet; diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h index aea1bc3fde..c7b685c6d5 100644 --- a/indra/llinventory/llsettingsbase.h +++ b/indra/llinventory/llsettingsbase.h @@ -76,7 +76,21 @@ public: static const U32 FLAG_NOMOD; static const U32 FLAG_NOTRANS; - typedef std::map<std::string, S32> parammapping_t; + class DefaultParam + { + public: + DefaultParam(S32 key, const LLSD& value) : mShaderKey(key), mDefaultValue(value) {} + DefaultParam() : mShaderKey(-1) {} + S32 getShaderKey() const { return mShaderKey; } + const LLSD getDefaultValue() const { return mDefaultValue; } + + private: + S32 mShaderKey; + LLSD mDefaultValue; + }; + // Contains settings' names (map key), related shader id-key and default + // value for revert in case we need to reset shader (no need to search each time) + typedef std::map<std::string, DefaultParam> parammapping_t; typedef PTR_NAMESPACE::shared_ptr<LLSettingsBase> ptr_t; @@ -312,7 +326,15 @@ protected: // combining settings objects. Customize for specific setting types virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix); - LLSD interpolateSDMap(const LLSD &settings, const LLSD &other, BlendFactor mix) const; + + // combining settings maps where it can based on mix rate + // @settings initial value (mix==0) + // @other target value (mix==1) + // @defaults list of default values for legacy fields and (re)setting shaders + // @mix from 0 to 1, ratio or rate of transition from initial 'settings' to 'other' + // return interpolated and combined LLSD map + LLSD interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, BlendFactor mix) const; + LLSD interpolateSDValue(const std::string& name, const LLSD &value, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const; /// when lerping between settings, some may require special handling. /// Get a list of these key to be skipped by the default settings lerp. diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 8a1e74d7ea..cf6bc45080 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -438,7 +438,14 @@ void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) LLSettingsSky::ptr_t other = PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsSky>(end); if (other) { - LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, blendf); + if (!mSettings.has(SETTING_LEGACY_HAZE) && !mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT)) + { + // Special case since SETTING_AMBIENT is both in outer and legacy maps, we prioritize legacy one + // see getAmbientColor() + setAmbientColor(getAmbientColor()); + } + + LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf); replaceSettings(blenddata); mNextSunTextureId = other->getSunTextureId(); mNextMoonTextureId = other->getMoonTextureId(); @@ -924,6 +931,7 @@ LLVector3 LLSettingsSky::getLightDirection() const LLColor3 LLSettingsSky::getAmbientColor() const { + // Todo: this causes complications, preferably to get rid of this duality if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT)) { return LLColor3(mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT]); diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp index 87744453ed..7cfff954a0 100644 --- a/indra/llinventory/llsettingswater.cpp +++ b/indra/llinventory/llsettingswater.cpp @@ -178,7 +178,7 @@ void LLSettingsWater::blend(const LLSettingsBase::ptr_t &end, F64 blendf) LLSettingsWater::ptr_t other = PTR_NAMESPACE::static_pointer_cast<LLSettingsWater>(end); if (other) { - LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, blendf); + LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf); replaceSettings(blenddata); mNextNormalMapID = other->getNormalMapID(); mNextTransparentTextureID = other->getTransparentTextureID(); |