539 lines
17 KiB
C++
539 lines
17 KiB
C++
/**
|
|
* @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;
|
|
|
|
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 *) { };
|
|
|
|
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),
|
|
mTimeDeltaThreshold(0.0f),
|
|
mTimeDeltaPassed(0.0f),
|
|
mIgnoreTimeDelta(false),
|
|
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);
|
|
mTimeDeltaPassed = LLSettingsBase::Seconds(0.0f);
|
|
mLastBlendF = LLSettingsBase::BlendFactor(-1.0f);
|
|
}
|
|
|
|
virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) SETTINGS_OVERRIDE;
|
|
|
|
inline void setTimeDeltaThreshold(const LLSettingsBase::Seconds time)
|
|
{
|
|
mTimeDeltaThreshold = time;
|
|
mTimeDeltaPassed = time + LLSettingsBase::Seconds(1.0); // take the next update call.
|
|
}
|
|
|
|
inline LLSettingsBase::Seconds getTimeDeltaThreshold() const
|
|
{
|
|
return mTimeDeltaThreshold;
|
|
}
|
|
|
|
inline void setIgnoreTimeDeltaThreshold(bool val) { mIgnoreTimeDelta = val; }
|
|
inline bool getIgnoreTimeDeltaThreshold() const { return mIgnoreTimeDelta; }
|
|
|
|
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::Seconds mTimeDeltaThreshold;
|
|
LLSettingsBase::Seconds mTimeDeltaPassed;
|
|
bool mIgnoreTimeDelta;
|
|
LLSettingsBase::BlendFactor mBlendFMinDelta;
|
|
LLSettingsBase::BlendFactor mLastBlendF;
|
|
};
|
|
|
|
|
|
#endif
|