diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index bce3ce0cc9..1c3f03181b 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -305,6 +305,7 @@ enum ERlvCmdRet { RLV_RET_FAILED_UNKNOWN, // Command failed (unknown command) RLV_RET_FAILED_NOSHAREDROOT, // Command failed (missing #RLV) RLV_RET_FAILED_DEPRECATED, // Command failed (deprecated and no longer supported) + RLV_RET_FAILED_NOBEHAVIOUR, // Command failed (force modifier on an object with no active restrictions) RLV_RET_NO_PROCESSOR // Command doesn't have a template processor define (legacy code) }; #define RLV_RET_SUCCEEDED(eCmdRet) (((eCmdRet) & RLV_RET_SUCCESS) == RLV_RET_SUCCESS) diff --git a/indra/newview/rlvfloaters.cpp b/indra/newview/rlvfloaters.cpp index eb643373c2..ed531eb93b 100644 --- a/indra/newview/rlvfloaters.cpp +++ b/indra/newview/rlvfloaters.cpp @@ -750,6 +750,7 @@ BOOL RlvFloaterConsole::postBuild() void RlvFloaterConsole::onClose(bool fQuitting) { + RlvBehaviourDictionary::instance().clearModifiers(gAgent.getID()); gRlvHandler.processCommand(gAgent.getID(), "clear", true); } diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 6fd5a35d63..1441aa57e4 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -387,6 +387,7 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj) if (0 == itObj->second.m_Commands.size()) { RLV_DEBUGS << "\t- command list empty => removing " << idCurObj << RLV_ENDL; + RlvBehaviourDictionary::instance().clearModifiers(idCurObj); m_Objects.erase(itObj); } } @@ -1519,13 +1520,13 @@ ERlvCmdRet RlvBehaviourGenericHandler::onCommand(const RlvC if (RLV_TYPE_ADD == rlvCmd.getParamType()) { gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++; - pBhvrModifier->addValue(modValue, rlvCmd.getObjectID()); + pBhvrModifier->addValue(modValue, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--; } else { gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--; - pBhvrModifier->removeValue(modValue, rlvCmd.getObjectID()); + pBhvrModifier->removeValue(modValue, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++; } @@ -1549,13 +1550,13 @@ ERlvCmdRet RlvBehaviourGenericHandler::onCommand(co if (RLV_TYPE_ADD == rlvCmd.getParamType()) { gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++; - pBhvrModifier->addValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID()); + pBhvrModifier->addValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--; } else { gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]--; - pBhvrModifier->removeValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID()); + pBhvrModifier->removeValue(pBhvrModifier->getDefaultValue(), rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); gRlvHandler.m_Behaviours[rlvCmd.getBehaviourType()]++; } } @@ -1828,15 +1829,15 @@ ERlvCmdRet RlvBehaviourRecvSendStartIMHandler::onCommand(const RlvCommand& rlvCm RlvBehaviourModifier *pBhvrModDistMin = RlvBehaviourDictionary::instance().getModifier(eModDistMin), *pBhvrModDistMax = RlvBehaviourDictionary::instance().getModifier(eModDistMax); if (RLV_TYPE_ADD == rlvCmd.getParamType()) { - pBhvrModDistMin->addValue(nDistMin * nDistMin, rlvCmd.getObjectID()); + pBhvrModDistMin->addValue(nDistMin * nDistMin, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); if (optionList.size() >= 2) - pBhvrModDistMax->addValue(nDistMax * nDistMax, rlvCmd.getObjectID()); + pBhvrModDistMax->addValue(nDistMax * nDistMax, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); } else { - pBhvrModDistMin->removeValue(nDistMin * nDistMin, rlvCmd.getObjectID()); + pBhvrModDistMin->removeValue(nDistMin * nDistMin, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); if (optionList.size() >= 2) - pBhvrModDistMax->removeValue(nDistMax * nDistMax, rlvCmd.getObjectID()); + pBhvrModDistMax->removeValue(nDistMax * nDistMax, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); } fRefCount = true; @@ -2279,6 +2280,24 @@ ERlvCmdRet RlvCommandHandlerBaseImpl::processCommand(const RlvCo return (*pHandler)(rlvCmd); } +// Handles: @bhvr:=force +template<> +ERlvCmdRet RlvForceGenericHandler::onCommand(const RlvCommand& rlvCmd) +{ + // The object should be holding at least one active behaviour + if (!gRlvHandler.hasBehaviour(rlvCmd.getObjectID())) + return RLV_RET_FAILED_NOBEHAVIOUR; + + // 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; + + pBhvrModifier->setValue(modValue, rlvCmd.getObjectID()); + return RLV_RET_SUCCESS; +} + // Checked: 2010-04-07 (RLVa-1.2.0d) | Modified: RLVa-1.1.0j ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const { @@ -3048,12 +3067,12 @@ ERlvCmdRet RlvBehaviourCamZoomMinMaxHandler::onCommand(const RlvCommand& rlvCmd, if (RLV_TYPE_ADD == rlvCmd.getParamType()) { gRlvHandler.m_Behaviours[(RLV_BHVR_CAMZOOMMIN == rlvCmd.getBehaviourType()) ? RLV_BHVR_SETCAM_FOVMIN : RLV_BHVR_SETCAM_FOVMAX]++; - pBhvrModifier->addValue(DEFAULT_FIELD_OF_VIEW / nMult, rlvCmd.getObjectID()); + pBhvrModifier->addValue(DEFAULT_FIELD_OF_VIEW / nMult, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); } else { gRlvHandler.m_Behaviours[(RLV_BHVR_CAMZOOMMIN == rlvCmd.getBehaviourType()) ? RLV_BHVR_SETCAM_FOVMIN : RLV_BHVR_SETCAM_FOVMAX]--; - pBhvrModifier->removeValue(DEFAULT_FIELD_OF_VIEW / nMult, rlvCmd.getObjectID()); + pBhvrModifier->removeValue(DEFAULT_FIELD_OF_VIEW / nMult, rlvCmd.getObjectID(), rlvCmd.getBehaviourType()); } } @@ -3352,7 +3371,7 @@ bool RlvHandler::hitTestOverlay(const LLCoordGL& ptMouse) const void RlvHandler::renderOverlay() { - if (m_pOverlayImage) + if ( (hasBehaviour(RLV_BHVR_SETOVERLAY)) && (m_pOverlayImage) ) { if (LLGLSLShader::sNoFixedFunction) { diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h index 7b01a210e5..7c48d0c276 100644 --- a/indra/newview/rlvhandler.h +++ b/indra/newview/rlvhandler.h @@ -59,6 +59,8 @@ public: // Returns TRUE is at least one object contains the specified behaviour (and optional option) bool hasBehaviour(ERlvBehaviour eBhvr) const { return (eBhvr < RLV_BHVR_COUNT) ? (0 != m_Behaviours[eBhvr]) : false; } bool hasBehaviour(ERlvBehaviour eBhvr, const std::string& strOption) const; + // Returns TRUE if the specified object has at least one active behaviour + bool hasBehaviour(const LLUUID& idObj) { return m_Objects.end() != m_Objects.find(idObj); } // Returns TRUE if the specified object contains the specified behaviour (and optional option) bool hasBehaviour(const LLUUID& idObj, ERlvBehaviour eBhvr, const std::string& strOption = LLStringUtil::null) const; // Returns TRUE if at least one object (except the specified one) contains the specified behaviour (and optional option) diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 68cb4238f8..f62da48c5f 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -369,6 +369,16 @@ void RlvBehaviourDictionary::addModifier(const RlvBehaviourInfo* pBhvrEntry, ERl addModifier(pBhvrEntry->getBehaviourType(), eModifier, pModifierEntry); } +// TODO: this shouldn't be in this class - find a better spot for it +void RlvBehaviourDictionary::clearModifiers(const LLUUID& idRlvObj) +{ + for (int idxModifier = 0; idxModifier < RLV_MODIFIER_COUNT; idxModifier++) + { + if (m_BehaviourModifiers[idxModifier]) + m_BehaviourModifiers[idxModifier]->clearValues(idRlvObj); + } +} + const RlvBehaviourInfo* RlvBehaviourDictionary::getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const { bool fStrict = boost::algorithm::ends_with(strBhvr, "_sec"); @@ -450,11 +460,11 @@ RlvBehaviourModifier::~RlvBehaviourModifier() } } -bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject) +bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj, ERlvBehaviour eBhvr) { if (modValue.which() == m_DefaultValue.which()) { - m_Values.insert((m_pValueComparator) ? std::lower_bound(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject), boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)) : m_Values.end(), std::make_pair(modValue, idObject)); + m_Values.insert((m_pValueComparator) ? std::lower_bound(m_Values.begin(), m_Values.end(), std::make_tuple(modValue, idRlvObj, eBhvr), boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)) : m_Values.end(), std::make_tuple(modValue, idRlvObj, eBhvr)); // NOTE: change signal needs to trigger before modifier handlers so cached values have a chance to update properly m_ChangeSignal(getValue()); onValueChange(); @@ -463,6 +473,20 @@ bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, c return false; } +void RlvBehaviourModifier::clearValues(const LLUUID& idRlvObj) +{ + size_t origCount = m_Values.size(); + m_Values.erase(std::remove_if(m_Values.begin(), m_Values.end(), + [&idRlvObj](const RlvBehaviourModifierValueTuple& modValue) { + return (std::get<1>(modValue) == idRlvObj) && (std::get<2>(modValue) == RLV_BHVR_UNKNOWN); + }), m_Values.end()); + if (origCount != m_Values.size()) + { + onValueChange(); + m_ChangeSignal(getValue()); + } +} + const LLUUID& RlvBehaviourModifier::getPrimaryObject() const { return (m_pValueComparator) ? m_pValueComparator->m_idPrimaryObject : LLUUID::null; @@ -472,14 +496,14 @@ bool RlvBehaviourModifier::hasValue() const { // If no primary object is set this returns "any value set"; otherwise it returns "any value set by the primary object" if ( (!m_pValueComparator) || (m_pValueComparator->m_idPrimaryObject.isNull()) ) return !m_Values.empty(); - return (!m_Values.empty()) ? m_Values.front().second == m_pValueComparator->m_idPrimaryObject : false; + return (!m_Values.empty()) ? std::get<1>(m_Values.front()) == m_pValueComparator->m_idPrimaryObject : false; } -void RlvBehaviourModifier::removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject) +void RlvBehaviourModifier::removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj, ERlvBehaviour eBhvr) { if ( (modValue.which() == m_DefaultValue.which()) ) { - auto itValue = std::find(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject)); + auto itValue = std::find(m_Values.begin(), m_Values.end(), std::make_tuple(modValue, idRlvObj, eBhvr)); if (m_Values.end() != itValue) { m_Values.erase(itValue); @@ -500,6 +524,31 @@ void RlvBehaviourModifier::setPrimaryObject(const LLUUID& idPrimaryObject) } } +void RlvBehaviourModifier::setValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj) +{ + if ( (modValue.which() == m_DefaultValue.which()) ) + { + auto itValue = std::find_if(m_Values.begin(), m_Values.end(), + [&idRlvObj](const RlvBehaviourModifierValueTuple& cmpValue) { + return (std::get<1>(cmpValue) == idRlvObj) && (std::get<2>(cmpValue) == RLV_BHVR_UNKNOWN); + }); + if (m_Values.end() != itValue) + { + // The object already has a modifier value set => change it + std::get<0>(*itValue) = modValue; + if (m_pValueComparator) + m_Values.sort(boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)); + onValueChange(); + m_ChangeSignal(getValue()); + } + else + { + // The command doesn't have a modifier value yet => add it + addValue(modValue, idRlvObj, RLV_BHVR_UNKNOWN); + } + } +} + bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const { try diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 8dba8e639e..67165de11b 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -103,6 +103,7 @@ public: * General helper functions */ public: + void clearModifiers(const LLUUID& idRlvObj); ERlvBehaviour getBehaviourFromString(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict = NULL) const; const RlvBehaviourInfo* getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict = NULL) const; bool getCommands(const std::string& strMatch, ERlvParamType eParamType, std::list& cmdList) const; @@ -207,6 +208,8 @@ template struct RlvBehaviourGenericHandler { static ERlvCmdRet onCommand(const RlvCommand& rlvCmd, bool& fRefCount); }; template using RlvBehaviourGenericProcessor = RlvBehaviourProcessor>; +template struct RlvForceGenericHandler { static ERlvCmdRet onCommand(const RlvCommand& rlvCmd); }; +template using RlvForceGenericProcessor = RlvForceProcessor>; // ============================================================================ // RlvBehaviourProcessor and related classes - Handles add/rem comamnds aka "restrictions) @@ -225,7 +228,7 @@ template RlvBehaviourModifierValueTuple; +typedef std::tuple RlvBehaviourModifierValueTuple; struct RlvBehaviourModifier_Comp { @@ -233,7 +236,7 @@ struct RlvBehaviourModifier_Comp virtual bool operator()(const RlvBehaviourModifierValueTuple& lhs, const RlvBehaviourModifierValueTuple& rhs) { // Values that match the primary object take precedence (otherwise maintain relative ordering) - if ( (rhs.second == m_idPrimaryObject) && (lhs.second != m_idPrimaryObject) ) + if ( (std::get<1>(rhs) == m_idPrimaryObject) && (std::get<1>(lhs) != m_idPrimaryObject) ) return false; return true; } @@ -244,8 +247,8 @@ struct RlvBehaviourModifier_CompMin : public RlvBehaviourModifier_Comp { bool operator()(const RlvBehaviourModifierValueTuple& lhs, const RlvBehaviourModifierValueTuple& rhs) override { - if ( (m_idPrimaryObject.isNull()) || ((lhs.second == m_idPrimaryObject) && (rhs.second == m_idPrimaryObject)) ) - return lhs.first < rhs.first; + if ( (m_idPrimaryObject.isNull()) || ((std::get<1>(lhs) == m_idPrimaryObject) && (std::get<1>(rhs) == m_idPrimaryObject)) ) + return std::get<0>(lhs) < std::get<0>(rhs); return RlvBehaviourModifier_Comp::operator()(lhs, rhs); } }; @@ -253,8 +256,8 @@ struct RlvBehaviourModifier_CompMax : public RlvBehaviourModifier_Comp { bool operator()(const RlvBehaviourModifierValueTuple& lhs, const RlvBehaviourModifierValueTuple& rhs) override { - if ( (m_idPrimaryObject.isNull()) || ((lhs.second == m_idPrimaryObject) && (rhs.second == m_idPrimaryObject)) ) - return rhs.first < lhs.first; + if ( (m_idPrimaryObject.isNull()) || ((std::get<1>(lhs) == m_idPrimaryObject) && (std::get<1>(rhs) == m_idPrimaryObject)) ) + return std::get<0>(rhs) < std::get<0>(lhs); return RlvBehaviourModifier_Comp::operator()(lhs, rhs); } }; @@ -271,16 +274,18 @@ public: protected: virtual void onValueChange() const {} public: - bool addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject); + bool addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj, ERlvBehaviour eBhvr = RLV_BHVR_UNKNOWN); bool convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const; + void clearValues(const LLUUID& idRlvObj); bool getAddDefault() const { return m_fAddDefaultOnEmpty; } const RlvBehaviourModifierValue& getDefaultValue() const { return m_DefaultValue; } const LLUUID& getPrimaryObject() const; const std::string& getName() const { return m_strName; } - const RlvBehaviourModifierValue& getValue() const { return (hasValue()) ? m_Values.front().first : m_DefaultValue; } + const RlvBehaviourModifierValue& getValue() const { return (hasValue()) ? std::get<0>(m_Values.front()) : m_DefaultValue; } template const T& getValue() const { return boost::get(getValue()); } bool hasValue() const; - void removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject); + void removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj, ERlvBehaviour eBhvr = RLV_BHVR_UNKNOWN); + void setValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj); void setPrimaryObject(const LLUUID& idPrimaryObject); typedef boost::signals2::signal change_signal_t;