diff options
Diffstat (limited to 'indra/llinventory/llsettingsbase.h')
-rw-r--r-- | indra/llinventory/llsettingsbase.h | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h new file mode 100644 index 0000000000..26e2901968 --- /dev/null +++ b/indra/llinventory/llsettingsbase.h @@ -0,0 +1,518 @@ +/** +* @file llsettingsbase.h +* @author optional +* @brief A base class for asset based settings groups. +* +* $LicenseInfo:2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2017, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_SETTINGS_BASE_H +#define LL_SETTINGS_BASE_H + +#include <string> +#include <map> +#include <vector> +#include <boost/signals2.hpp> + +#include "llsd.h" +#include "llsdutil.h" +#include "v2math.h" +#include "v3math.h" +#include "v4math.h" +#include "llquaternion.h" +#include "v4color.h" +#include "v3color.h" +#include "llunits.h" + +#include "llinventorysettings.h" + +#define PTR_NAMESPACE std +#define SETTINGS_OVERRIDE override + +class LLSettingsBase : + public PTR_NAMESPACE::enable_shared_from_this<LLSettingsBase>, + private boost::noncopyable +{ + friend class LLEnvironment; + friend class LLSettingsDay; + + friend std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings); + +protected: + LOG_CLASS(LLSettingsBase); +public: + typedef F64Seconds Seconds; + typedef F64 BlendFactor; + typedef F32 TrackPosition; // 32-bit as these are stored in LLSD as such + static const TrackPosition INVALID_TRACKPOS; + + static const std::string SETTING_ID; + static const std::string SETTING_NAME; + static const std::string SETTING_HASH; + static const std::string SETTING_TYPE; + static const std::string SETTING_ASSETID; + static const std::string SETTING_FLAGS; + + static const U32 FLAG_NOCOPY; + static const U32 FLAG_NOMOD; + static const U32 FLAG_NOTRANS; + static const U32 FLAG_NOSAVE; + + 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; + + virtual ~LLSettingsBase() { }; + + //--------------------------------------------------------------------- + virtual std::string getSettingsType() const = 0; + + virtual LLSettingsType::type_e getSettingsTypeValue() const = 0; + + //--------------------------------------------------------------------- + // Settings status + inline bool hasSetting(const std::string ¶m) const { return mSettings.has(param); } + virtual bool isDirty() const { return mDirty; } + virtual bool isVeryDirty() const { return mReplaced; } + inline void setDirtyFlag(bool dirty) { mDirty = dirty; clearAssetId(); } + + size_t getHash() const; // Hash will not include Name, ID or a previously stored Hash + + inline LLUUID getId() const + { + return getValue(SETTING_ID).asUUID(); + } + + inline std::string getName() const + { + return getValue(SETTING_NAME).asString(); + } + + inline void setName(std::string val) + { + setValue(SETTING_NAME, val); + } + + inline LLUUID getAssetId() const + { + if (mSettings.has(SETTING_ASSETID)) + return mSettings[SETTING_ASSETID].asUUID(); + return LLUUID(); + } + + inline U32 getFlags() const + { + if (mSettings.has(SETTING_FLAGS)) + return static_cast<U32>(mSettings[SETTING_FLAGS].asInteger()); + return 0; + } + + inline void setFlags(U32 value) + { + setLLSD(SETTING_FLAGS, LLSD::Integer(value)); + } + + inline bool getFlag(U32 flag) const + { + if (mSettings.has(SETTING_FLAGS)) + return ((U32)mSettings[SETTING_FLAGS].asInteger() & flag) == flag; + return false; + } + + inline void setFlag(U32 flag) + { + U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0); + + flags |= flag; + + if (flags) + mSettings[SETTING_FLAGS] = LLSD::Integer(flags); + else + mSettings.erase(SETTING_FLAGS); + } + + inline void clearFlag(U32 flag) + { + U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0); + + flags &= ~flag; + + if (flags) + mSettings[SETTING_FLAGS] = LLSD::Integer(flags); + else + mSettings.erase(SETTING_FLAGS); + } + + virtual void replaceSettings(LLSD settings) + { + mBlendedFactor = 0.0; + setDirtyFlag(true); + mReplaced = true; + mSettings = settings; + } + + virtual LLSD getSettings() const; + + //--------------------------------------------------------------------- + // + inline void setLLSD(const std::string &name, const LLSD &value) + { + mSettings[name] = value; + mDirty = true; + if (name != SETTING_ASSETID) + clearAssetId(); + } + + inline void setValue(const std::string &name, const LLSD &value) + { + setLLSD(name, value); + } + + inline LLSD getValue(const std::string &name, const LLSD &deflt = LLSD()) const + { + if (!mSettings.has(name)) + return deflt; + return mSettings[name]; + } + + inline void setValue(const std::string &name, F32 v) + { + setLLSD(name, LLSD::Real(v)); + } + + inline void setValue(const std::string &name, const LLVector2 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLVector3 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLVector4 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLQuaternion &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLColor3 &value) + { + setValue(name, value.getValue()); + } + + inline void setValue(const std::string &name, const LLColor4 &value) + { + setValue(name, value.getValue()); + } + + inline BlendFactor getBlendFactor() const + { + return mBlendedFactor; + } + + // Note this method is marked const but may modify the settings object. + // (note the internal const cast). This is so that it may be called without + // special consideration from getters. + inline void update() const + { + if ((!mDirty) && (!mReplaced)) + return; + (const_cast<LLSettingsBase *>(this))->updateSettings(); + } + + virtual void blend(const ptr_t &end, BlendFactor blendf) = 0; + + virtual bool validate(); + + virtual ptr_t buildDerivedClone() const = 0; + + class Validator + { + public: + static const U32 VALIDATION_PARTIAL; + + typedef boost::function<bool(LLSD &)> verify_pr; + + Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD()) : + mName(name), + mRequired(required), + mType(type), + mVerify(verify), + mDefault(defval) + { } + + std::string getName() const { return mName; } + bool isRequired() const { return mRequired; } + LLSD::Type getType() const { return mType; } + + bool verify(LLSD &data, U32 flags); + + // Some basic verifications + static bool verifyColor(LLSD &value); + static bool verifyVector(LLSD &value, S32 length); + static bool verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals); + static bool verifyVectorNormalized(LLSD &value, S32 length); + static bool verifyQuaternion(LLSD &value); + static bool verifyQuaternionNormal(LLSD &value); + static bool verifyFloatRange(LLSD &value, LLSD range); + static bool verifyIntegerRange(LLSD &value, LLSD range); + static bool verifyStringLength(LLSD &value, S32 length); + + private: + std::string mName; + bool mRequired; + LLSD::Type mType; + verify_pr mVerify; + LLSD mDefault; + }; + typedef std::vector<Validator> validation_list_t; + + static LLSD settingValidation(LLSD &settings, validation_list_t &validations, bool partial = false); + + inline void setAssetId(LLUUID value) + { // note that this skips setLLSD + mSettings[SETTING_ASSETID] = value; + } + + inline void clearAssetId() + { + if (mSettings.has(SETTING_ASSETID)) + mSettings.erase(SETTING_ASSETID); + } + + // Calculate any custom settings that may need to be cached. + virtual void updateSettings() { mDirty = false; mReplaced = false; } +protected: + + LLSettingsBase(); + LLSettingsBase(const LLSD setting); + + static LLSD settingValidation(LLSD settings); + + typedef std::set<std::string> stringset_t; + + // combining settings objects. Customize for specific setting types + virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix); + + // 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. + /// (handling should be performed in the override of lerpSettings. + virtual stringset_t getSkipInterpolateKeys() const; + + // A list of settings that represent quaternions and should be slerped + // rather than lerped. + virtual stringset_t getSlerpKeys() const { return stringset_t(); } + + virtual validation_list_t getValidationList() const = 0; + + // Apply any settings that need special handling. + virtual void applySpecial(void *, bool force = false) { }; + + virtual parammapping_t getParameterMap() const { return parammapping_t(); } + + LLSD mSettings; + bool mIsValid; + LLAssetID mAssetID; + + LLSD cloneSettings() const; + + inline void setBlendFactor(BlendFactor blendfactor) + { + mBlendedFactor = blendfactor; + } + + void replaceWith(LLSettingsBase::ptr_t other) + { + replaceSettings(other->cloneSettings()); + setBlendFactor(other->getBlendFactor()); + } + +private: + bool mDirty; + bool mReplaced; // super dirty! + + LLSD combineSDMaps(const LLSD &first, const LLSD &other) const; + + BlendFactor mBlendedFactor; +}; + + +class LLSettingsBlender : public PTR_NAMESPACE::enable_shared_from_this<LLSettingsBlender> +{ + LOG_CLASS(LLSettingsBlender); +public: + typedef PTR_NAMESPACE::shared_ptr<LLSettingsBlender> ptr_t; + typedef boost::signals2::signal<void(const ptr_t )> finish_signal_t; + typedef boost::signals2::connection connection_t; + + LLSettingsBlender(const LLSettingsBase::ptr_t &target, + const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting) : + mOnFinished(), + mTarget(target), + mInitial(initsetting), + mFinal(endsetting) + { + if (mInitial && mTarget) + mTarget->replaceSettings(mInitial->getSettings()); + + if (!mFinal) + mFinal = mInitial; + } + + virtual ~LLSettingsBlender() {} + + virtual void reset( LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition&) + { + // note: the 'span' reset parameter is unused by the base class. + if (!mInitial) + LL_WARNS("BLENDER") << "Reseting blender with empty initial setting. Expect badness in the future." << LL_ENDL; + + mInitial = initsetting; + mFinal = endsetting; + + if (!mFinal) + mFinal = mInitial; + + if (mTarget) + mTarget->replaceSettings(mInitial->getSettings()); + } + + LLSettingsBase::ptr_t getTarget() const + { + return mTarget; + } + + LLSettingsBase::ptr_t getInitial() const + { + return mInitial; + } + + LLSettingsBase::ptr_t getFinal() const + { + return mFinal; + } + + connection_t setOnFinished(const finish_signal_t::slot_type &onfinished) + { + return mOnFinished.connect(onfinished); + } + + virtual void update(const LLSettingsBase::BlendFactor& blendf); + virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) + { + llassert(false); + // your derived class needs to implement an override of this func + return false; + } + + virtual F64 setBlendFactor(const LLSettingsBase::BlendFactor& position); + + virtual void switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position) { /*NoOp*/ } + +protected: + void triggerComplete(); + + finish_signal_t mOnFinished; + + LLSettingsBase::ptr_t mTarget; + LLSettingsBase::ptr_t mInitial; + LLSettingsBase::ptr_t mFinal; +}; + +class LLSettingsBlenderTimeDelta : public LLSettingsBlender +{ + LOG_CLASS(LLSettingsBlenderTimeDelta); +public: + static const LLSettingsBase::BlendFactor MIN_BLEND_DELTA; + + LLSettingsBlenderTimeDelta(const LLSettingsBase::ptr_t &target, + const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::Seconds& blend_span) : + LLSettingsBlender(target, initsetting, endsetting), + mBlendSpan(blend_span), + mLastUpdate(0.0f), + mTimeSpent(0.0f), + mBlendFMinDelta(MIN_BLEND_DELTA), + mLastBlendF(-1.0f) + { + mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch()); + mLastUpdate = mTimeStart; + } + + virtual ~LLSettingsBlenderTimeDelta() + { + } + + virtual void reset(LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition& blend_span) SETTINGS_OVERRIDE + { + LLSettingsBlender::reset(initsetting, endsetting, blend_span); + + mBlendSpan = blend_span; + mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch()); + mLastUpdate = mTimeStart; + mTimeSpent = LLSettingsBase::Seconds(0.0f); + mLastBlendF = LLSettingsBase::BlendFactor(-1.0f); + } + + virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) SETTINGS_OVERRIDE; + + inline void setTimeSpent(LLSettingsBase::Seconds time) { mTimeSpent = time; } +protected: + LLSettingsBase::BlendFactor calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const; + + LLSettingsBase::TrackPosition mBlendSpan; + LLSettingsBase::Seconds mLastUpdate; + LLSettingsBase::Seconds mTimeSpent; + LLSettingsBase::Seconds mTimeStart; + LLSettingsBase::BlendFactor mBlendFMinDelta; + LLSettingsBase::BlendFactor mLastBlendF; +}; + + +#endif |