Added behaviour modifiers as a prelude to camera restrictions and other fun goodies
--HG-- branch : RLVamaster
parent
8b6b3be823
commit
68025f9e1d
|
|
@ -56,6 +56,7 @@ class RlvObject;
|
|||
|
||||
struct RlvException;
|
||||
typedef boost::variant<std::string, LLUUID, S32, ERlvBehaviour> RlvExceptionOption;
|
||||
typedef boost::variant<int, float> RlvBehaviourModifierValue;
|
||||
|
||||
class RlvGCTimer;
|
||||
|
||||
|
|
|
|||
|
|
@ -192,11 +192,19 @@ enum ERlvBehaviour {
|
|||
RLV_BHVR_UNKNOWN
|
||||
};
|
||||
|
||||
enum RlvBehaviourOptionType
|
||||
enum ERlvBehaviourModifier
|
||||
{
|
||||
RLV_MODIFIER_COUNT,
|
||||
RLV_MODIFIER_UNKNOWN
|
||||
};
|
||||
|
||||
enum ERlvBehaviourOptionType
|
||||
{
|
||||
RLV_OPTION_NONE,
|
||||
RLV_OPTION_EXCEPTION,
|
||||
RLV_OPTION_NONE_OR_EXCEPTION
|
||||
RLV_OPTION_NONE_OR_EXCEPTION,
|
||||
RLV_OPTION_MODIFIER,
|
||||
RLV_OPTION_NONE_OR_MODIFIER
|
||||
};
|
||||
|
||||
enum ERlvParamType {
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ RlvHandler::RlvHandler() : m_fCanCancelTp(true), m_posSitSource(), m_pGCTimer(NU
|
|||
{
|
||||
gAgent.addListener(this, "new group");
|
||||
|
||||
// Array auto-initialization to 0 is non-standard? (Compiler warning in VC-8.0)
|
||||
// Array auto-initialization to 0 is still not supported in VS2013
|
||||
memset(m_Behaviours, 0, sizeof(S16) * RLV_BHVR_COUNT);
|
||||
}
|
||||
|
||||
|
|
@ -1360,6 +1360,45 @@ ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_NONE_OR_EXCEPTION>::onCommand(c
|
|||
return RlvBehaviourGenericHandler<RLV_OPTION_NONE>::onCommand(rlvCmd, fRefCount);
|
||||
}
|
||||
|
||||
// Handles: @bhvr:<modifier>=n|y
|
||||
ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_MODIFIER>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
|
||||
{
|
||||
// There should be an option and it should specify a valid modifier (RlvBehaviourModifier performs the appropriate type checks)
|
||||
RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifierFromBehaviour(rlvCmd.getBehaviourType());
|
||||
RlvBehaviourModifierValue modValue;
|
||||
if ( (!rlvCmd.hasOption()) || (!pBhvrModifier) || (!pBhvrModifier->convertOptionValue(rlvCmd.getOption(), modValue)) )
|
||||
return RLV_RET_FAILED_OPTION;
|
||||
|
||||
if (RLV_TYPE_ADD == rlvCmd.getParamType())
|
||||
pBhvrModifier->addValue(modValue);
|
||||
else
|
||||
pBhvrModifier->removeValue(modValue);
|
||||
|
||||
fRefCount = true;
|
||||
return RLV_RET_SUCCESS;
|
||||
}
|
||||
|
||||
// Handles: @bhvr[:<modifier>]=n|y
|
||||
ERlvCmdRet RlvBehaviourGenericHandler<RLV_OPTION_NONE_OR_MODIFIER>::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
|
||||
{
|
||||
// If there is an option then it should specify a valid modifier (and reference count)
|
||||
if (rlvCmd.hasOption())
|
||||
return RlvBehaviourGenericHandler<RLV_OPTION_MODIFIER>::onCommand(rlvCmd, fRefCount);
|
||||
|
||||
// Add the default option on an empty modifier if needed
|
||||
RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifierFromBehaviour(rlvCmd.getBehaviourType());
|
||||
if ( (pBhvrModifier) && (pBhvrModifier->getAddDefault()) )
|
||||
{
|
||||
if (RLV_TYPE_ADD == rlvCmd.getParamType())
|
||||
pBhvrModifier->addValue(pBhvrModifier->getDefaultValue());
|
||||
else
|
||||
pBhvrModifier->removeValue(pBhvrModifier->getDefaultValue());
|
||||
}
|
||||
|
||||
fRefCount = true;
|
||||
return RLV_RET_SUCCESS;
|
||||
}
|
||||
|
||||
// Handles: @addattach[:<attachpt>]=n|y and @remattach[:<attachpt>]=n|y
|
||||
template<> template<>
|
||||
ERlvCmdRet RlvBehaviourAddRemAttachHandler::onCommand(const RlvCommand& rlvCmd, bool& fRefCount)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,14 @@
|
|||
// RlvBehaviourDictionary
|
||||
//
|
||||
|
||||
static RlvBehaviourModifier_CompMin s_RlvBehaviourModifier_CompMin;
|
||||
static RlvBehaviourModifier_CompMax s_RlvBehaviourModifier_CompMax;
|
||||
|
||||
RlvBehaviourDictionary::RlvBehaviourDictionary()
|
||||
{
|
||||
// Array auto-initialization to 0 is still not supported in VS2013
|
||||
memset(m_BehaviourModifiers, 0, sizeof(RlvBehaviourModifier*) * RLV_MODIFIER_COUNT);
|
||||
|
||||
//
|
||||
// Restrictions
|
||||
//
|
||||
|
|
@ -219,6 +225,12 @@ RlvBehaviourDictionary::~RlvBehaviourDictionary()
|
|||
for (const RlvBehaviourInfo* pBhvrInfo : m_BhvrInfoList)
|
||||
delete pBhvrInfo;
|
||||
m_BhvrInfoList.clear();
|
||||
|
||||
for (int idxBhvrMod = 0; idxBhvrMod < RLV_MODIFIER_COUNT; idxBhvrMod++)
|
||||
{
|
||||
delete m_BehaviourModifiers[idxBhvrMod];
|
||||
m_BehaviourModifiers[idxBhvrMod] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RlvBehaviourDictionary::addEntry(const RlvBehaviourInfo* pEntry)
|
||||
|
|
@ -241,6 +253,15 @@ void RlvBehaviourDictionary::addEntry(const RlvBehaviourInfo* pEntry)
|
|||
m_BhvrInfoList.push_back(pEntry);
|
||||
}
|
||||
|
||||
void RlvBehaviourDictionary::addModifier(ERlvBehaviour eBhvr, ERlvBehaviourModifier eModifier, RlvBehaviourModifier* pModifierEntry)
|
||||
{
|
||||
if (eModifier < RLV_MODIFIER_COUNT)
|
||||
{
|
||||
m_BehaviourModifiers[eModifier] = pModifierEntry;
|
||||
m_Bhvr2ModifierMap.insert(std::make_pair(eBhvr, eModifier));
|
||||
}
|
||||
}
|
||||
|
||||
const RlvBehaviourInfo* RlvBehaviourDictionary::getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const
|
||||
{
|
||||
bool fStrict = boost::algorithm::ends_with(strBhvr, "_sec");
|
||||
|
|
@ -287,6 +308,13 @@ bool RlvBehaviourDictionary::getHasStrict(ERlvBehaviour eBhvr) const
|
|||
return false;
|
||||
}
|
||||
|
||||
RlvBehaviourModifier* RlvBehaviourDictionary::getModifierFromBehaviour(ERlvBehaviour eBhvr) const
|
||||
{
|
||||
rlv_bhvr2mod_map_t::const_iterator itMod = m_Bhvr2ModifierMap.find(eBhvr);
|
||||
ERlvBehaviourModifier eBhvrMod = (m_Bhvr2ModifierMap.end() != itMod) ? itMod->second : RLV_MODIFIER_UNKNOWN;
|
||||
return (eBhvrMod < RLV_MODIFIER_UNKNOWN) ? m_BehaviourModifiers[eBhvrMod] : nullptr;
|
||||
}
|
||||
|
||||
void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERlvParamType eParamType, RlvBehaviourInfo::EBehaviourFlags eBhvrFlag, bool fEnable)
|
||||
{
|
||||
rlv_string2info_map_t::const_iterator itBhvr = m_String2InfoMap.find(std::make_pair(strBhvr, (eParamType & RLV_TYPE_ADDREM) ? RLV_TYPE_ADDREM : eParamType));
|
||||
|
|
@ -296,6 +324,61 @@ void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERl
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RlvBehaviourModifier
|
||||
//
|
||||
|
||||
RlvBehaviourModifier::RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator)
|
||||
: m_DefaultValue(defaultValue), m_fAddDefaultOnEmpty(fAddDefaultOnEmpty), m_pValueComparator(pValueComparator)
|
||||
{
|
||||
}
|
||||
|
||||
bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue)
|
||||
{
|
||||
if (modValue.which() == m_DefaultValue.which())
|
||||
{
|
||||
m_Values.insert((m_pValueComparator) ? std::lower_bound(m_Values.begin(), m_Values.end(), modValue, boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)) : m_Values.end(), modValue);
|
||||
m_ChangeSignal(getValue());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RlvBehaviourModifier::removeValue(const RlvBehaviourModifierValue& modValue)
|
||||
{
|
||||
if ( (modValue.which() == m_DefaultValue.which()) )
|
||||
{
|
||||
auto itValue = std::find(m_Values.begin(), m_Values.end(), modValue);
|
||||
if (m_Values.end() != itValue)
|
||||
{
|
||||
m_Values.erase(itValue);
|
||||
m_ChangeSignal(getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const
|
||||
{
|
||||
try
|
||||
{
|
||||
if (typeid(float) == m_DefaultValue.type())
|
||||
{
|
||||
modValue = std::stof(optionValue.c_str());
|
||||
return true;
|
||||
}
|
||||
else if (typeid(int) == m_DefaultValue.type())
|
||||
{
|
||||
modValue = std::stoi(optionValue.c_str());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (const std::invalid_argument&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RlvCommmand
|
||||
//
|
||||
|
|
|
|||
|
|
@ -141,14 +141,14 @@ template<ERlvBehaviour eBhvr, typename handlerImpl = RlvCommandHandler<RLV_TYPE_
|
|||
template<ERlvBehaviour eBhvr, typename handlerImpl = RlvCommandHandler<RLV_TYPE_REPLY, eBhvr>> using RlvReplyProcessor = RlvCommandProcessor<RLV_TYPE_REPLY, eBhvr, handlerImpl>;
|
||||
|
||||
// Provides pre-defined generic implementations of basic behaviours (template voodoo - see original commit for something that still made sense)
|
||||
template<RlvBehaviourOptionType optionType> struct RlvBehaviourGenericHandler { static ERlvCmdRet onCommand(const RlvCommand& rlvCmd, bool& fRefCount); };
|
||||
template<RlvBehaviourOptionType optionType> using RlvBehaviourGenericProcessor = RlvBehaviourProcessor<RLV_BHVR_UNKNOWN, RlvBehaviourGenericHandler<optionType>>;
|
||||
template<ERlvBehaviourOptionType optionType> struct RlvBehaviourGenericHandler { static ERlvCmdRet onCommand(const RlvCommand& rlvCmd, bool& fRefCount); };
|
||||
template<ERlvBehaviourOptionType optionType> using RlvBehaviourGenericProcessor = RlvBehaviourProcessor<RLV_BHVR_UNKNOWN, RlvBehaviourGenericHandler<optionType>>;
|
||||
|
||||
// ============================================================================
|
||||
// RlvBehaviourProcessor and related classes - Handles add/rem comamnds aka "restrictions)
|
||||
//
|
||||
|
||||
template <ERlvBehaviour eBhvr, RlvBehaviourOptionType optionType, typename toggleHandlerImpl = RlvBehaviourToggleHandler<eBhvr>>
|
||||
template <ERlvBehaviour eBhvr, ERlvBehaviourOptionType optionType, typename toggleHandlerImpl = RlvBehaviourToggleHandler<eBhvr>>
|
||||
class RlvBehaviourToggleProcessor : public RlvBehaviourInfo
|
||||
{
|
||||
public:
|
||||
|
|
@ -156,6 +156,107 @@ public:
|
|||
ERlvCmdRet processCommand(const RlvCommand& rlvCmd) const override { return RlvCommandHandlerBaseImpl<RLV_TYPE_ADDREM>::processCommand(rlvCmd, &RlvBehaviourGenericHandler<optionType>::onCommand, &toggleHandlerImpl::onCommandToggle); }
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// RlvBehaviourModifier - stores behaviour modifiers in an - optionally - sorted list and returns the first element (or default value if there are no modifiers)
|
||||
//
|
||||
|
||||
struct RlvBehaviourModifier_Comp { virtual bool operator()(const RlvBehaviourModifierValue& lhs, const RlvBehaviourModifierValue& rhs) = 0; };
|
||||
struct RlvBehaviourModifier_CompMin : public RlvBehaviourModifier_Comp { bool operator()(const RlvBehaviourModifierValue& lhs, const RlvBehaviourModifierValue& rhs) override { return lhs < rhs; } };
|
||||
struct RlvBehaviourModifier_CompMax : public RlvBehaviourModifier_Comp { bool operator()(const RlvBehaviourModifierValue& lhs, const RlvBehaviourModifierValue& rhs) override { return rhs < lhs; } };
|
||||
|
||||
class RlvBehaviourModifier
|
||||
{
|
||||
public:
|
||||
RlvBehaviourModifier(const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator);
|
||||
|
||||
/*
|
||||
* Member functions
|
||||
*/
|
||||
public:
|
||||
bool addValue(const RlvBehaviourModifierValue& modValue);
|
||||
bool convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const;
|
||||
bool getAddDefault() const { return m_fAddDefaultOnEmpty; }
|
||||
const RlvBehaviourModifierValue& getDefaultValue() const { return m_DefaultValue; }
|
||||
const RlvBehaviourModifierValue& getValue() const { return (!m_Values.empty()) ? m_Values.front() : m_DefaultValue; }
|
||||
template<typename T> const T& getValue() const { return boost::get<T>(getValue()); }
|
||||
void removeValue(const RlvBehaviourModifierValue& modValue);
|
||||
|
||||
typedef boost::signals2::signal<void(const RlvBehaviourModifierValue& newValue)> change_signal_t;
|
||||
change_signal_t& getSignal() { return m_ChangeSignal; }
|
||||
|
||||
/*
|
||||
* Member variables
|
||||
*/
|
||||
protected:
|
||||
RlvBehaviourModifierValue m_DefaultValue;
|
||||
bool m_fAddDefaultOnEmpty;
|
||||
std::list<RlvBehaviourModifierValue> m_Values;
|
||||
change_signal_t m_ChangeSignal;
|
||||
RlvBehaviourModifier_Comp* m_pValueComparator;
|
||||
};
|
||||
|
||||
// Inspired by LLControlCache<T>
|
||||
template<typename T>
|
||||
class RlvBehaviourModifierCache : public LLRefCount, public LLInstanceTracker<RlvBehaviourModifierCache<T>, ERlvBehaviourModifier>
|
||||
{
|
||||
public:
|
||||
RlvBehaviourModifierCache(ERlvBehaviourModifier eModifier)
|
||||
: LLInstanceTracker<RlvBehaviourModifierCache<T>, ERlvBehaviourModifier>(eModifier)
|
||||
{
|
||||
RlvBehaviourModifier* pBhvrModifier = (eModifier < RLV_MODIFIER_COUNT) ? RlvBehaviourDictionary::instance().getModifier(eModifier) : nullptr;
|
||||
if (pBhvrModifier)
|
||||
{
|
||||
mConnection = pBhvrModifier->getSignal().connect(boost::bind(&RlvBehaviourModifierCache<T>::handleValueChange, this, _1));
|
||||
mCachedValue = pBhvrModifier->getValue<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCachedValue = {};
|
||||
}
|
||||
}
|
||||
~RlvBehaviourModifierCache() {}
|
||||
|
||||
/*
|
||||
* Member functions
|
||||
*/
|
||||
public:
|
||||
const T& getValue() const { return mCachedValue; }
|
||||
protected:
|
||||
void handleValueChange(const RlvBehaviourModifierValue& newValue) { mCachedValue = boost::get<T>(newValue); }
|
||||
|
||||
/*
|
||||
* Member variables
|
||||
*/
|
||||
protected:
|
||||
T mCachedValue;
|
||||
boost::signals2::scoped_connection mConnection;
|
||||
};
|
||||
|
||||
// Inspired by LLCachedControl<T>
|
||||
template <typename T>
|
||||
class RlvCachedBehaviourModifier
|
||||
{
|
||||
public:
|
||||
RlvCachedBehaviourModifier(ERlvBehaviourModifier eModifier)
|
||||
{
|
||||
if ((mCachedModifierPtr = RlvBehaviourModifierCache<T>::getInstance(eModifier)) == nullptr)
|
||||
mCachedModifierPtr = new RlvBehaviourModifierCache<T>(eModifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* Operators
|
||||
*/
|
||||
public:
|
||||
operator const T&() const { return mCachedModifierPtr->getValue(); }
|
||||
const T& operator()() { return mCachedModifierPtr->getValue(); }
|
||||
|
||||
/*
|
||||
* Member variables
|
||||
*/
|
||||
protected:
|
||||
LLPointer<RlvBehaviourModifierCache<T>> mCachedModifierPtr;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// RlvBehaviourDictionary and related classes
|
||||
//
|
||||
|
|
@ -168,6 +269,7 @@ protected:
|
|||
~RlvBehaviourDictionary();
|
||||
public:
|
||||
void addEntry(const RlvBehaviourInfo* pEntry);
|
||||
void addModifier(ERlvBehaviour eBhvr, ERlvBehaviourModifier eModifier, RlvBehaviourModifier* pModifierEntry);
|
||||
|
||||
/*
|
||||
* General helper functions
|
||||
|
|
@ -177,7 +279,8 @@ public:
|
|||
const RlvBehaviourInfo* getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict = NULL) const;
|
||||
bool getCommands(const std::string& strMatch, ERlvParamType eParamType, std::list<std::string>& cmdList) const;
|
||||
bool getHasStrict(ERlvBehaviour eBhvr) const;
|
||||
const std::string& getStringFromBehaviour(ERlvBehaviour eBhvr, ERlvParamType eParamType, bool fStrict = false) const;
|
||||
RlvBehaviourModifier* getModifier(ERlvBehaviourModifier eBhvrMod) const { return (eBhvrMod < RLV_MODIFIER_COUNT) ? m_BehaviourModifiers[eBhvrMod] : nullptr; }
|
||||
RlvBehaviourModifier* getModifierFromBehaviour(ERlvBehaviour eBhvr) const;
|
||||
void toggleBehaviourFlag(const std::string& strBhvr, ERlvParamType eParamType, RlvBehaviourInfo::EBehaviourFlags eBvhrFlag, bool fEnable);
|
||||
|
||||
/*
|
||||
|
|
@ -187,10 +290,13 @@ protected:
|
|||
typedef std::list<const RlvBehaviourInfo*> rlv_bhvrinfo_list_t;
|
||||
typedef std::map<std::pair<std::string, ERlvParamType>, const RlvBehaviourInfo*> rlv_string2info_map_t;
|
||||
typedef std::multimap<ERlvBehaviour, const RlvBehaviourInfo*> rlv_bhvr2info_map_t;
|
||||
typedef std::map<ERlvBehaviour, ERlvBehaviourModifier> rlv_bhvr2mod_map_t;
|
||||
|
||||
rlv_bhvrinfo_list_t m_BhvrInfoList;
|
||||
rlv_string2info_map_t m_String2InfoMap;
|
||||
rlv_bhvr2info_map_t m_Bhvr2InfoMap;
|
||||
rlv_bhvr2mod_map_t m_Bhvr2ModifierMap;
|
||||
RlvBehaviourModifier* m_BehaviourModifiers[RLV_MODIFIER_COUNT];
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue