diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5803c59809..2a83c30224 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -731,14 +731,14 @@ set(viewer_SOURCE_FILES noise.cpp pipeline.cpp rlvactions.cpp - rlvhandler.cpp - rlvhelper.cpp rlvcommon.cpp - rlvlocks.cpp - rlvinventory.cpp + rlveffects.cpp rlvextensions.cpp rlvfloaters.cpp - rlvmodifiers.cpp + rlvhandler.cpp + rlvhelper.cpp + rlvinventory.cpp + rlvlocks.cpp rlvui.cpp ) @@ -1366,14 +1366,15 @@ set(viewer_HEADER_FILES noise.h pipeline.h rlvactions.h - rlvdefines.h - rlvhandler.h - rlvhelper.h rlvcommon.h - rlvlocks.h - rlvinventory.h + rlvdefines.h + rlveffects.h rlvextensions.h rlvfloaters.h + rlvhandler.h + rlvhelper.h + rlvinventory.h + rlvlocks.h rlvmodifiers.h rlvui.h roles_constants.h diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index be2fd55d7a..817ff4ee53 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -79,7 +79,8 @@ #include "llpostprocess.h" #include "llscenemonitor.h" // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) -#include "rlvhandler.h" +#include "llvisualeffect.h" +#include "rlvactions.h" #include "rlvlocks.h" // [/RLVa:KB] @@ -1310,9 +1311,9 @@ void render_ui(F32 zoom_factor, int subfield) LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD); render_hud_elements(); // [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay) - if (gRlvHandler.isEnabled()) + if (RlvActions::hasBehaviour(RLV_BHVR_SETOVERLAY)) { - gRlvHandler.renderOverlay(); + LLVfxManager::instance().runEffect(EVisualEffect::RlvOverlay); } // [/RLVa:KB] render_hud_attachments(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index adc56a8622..6052d34f9a 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -214,6 +214,8 @@ #include "llcleanup.h" // [RLVa:KB] - Checked: 2010-03-31 (RLVa-1.2.0c) +#include "rlvactions.h" +#include "rlveffects.h" #include "rlvhandler.h" // [/RLVa:KB] @@ -5663,11 +5665,12 @@ void LLPickInfo::fetchResults() mPickPt = mMousePt; // [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay) - if ( (gRlvHandler.isEnabled()) && (hit_object) && (!hit_object->isHUDAttachment()) ) + if ( (RlvActions::hasBehaviour(RLV_BHVR_SETOVERLAY)) && (hit_object) && (!hit_object->isHUDAttachment()) ) { - if (gRlvHandler.hitTestOverlay(mMousePt)) + if (auto* pOverlayEffect = LLVfxManager::instance().getEffect(EVisualEffect::RlvOverlay)) { - hit_object = nullptr; + if (pOverlayEffect->hitTest(mMousePt)) + hit_object = nullptr; } } // [/RLVa:KB] diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 1b97316143..d5e684b2e6 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -240,7 +240,7 @@ enum ERlvBehaviour { // Camera (force) RLV_BHVR_SETCAM_MODE, // Switch the user's camera into the specified mode (e.g. mouselook or thirdview) - // Effect: "vision spheres" + // Effects RLV_BHVR_SETSPHERE, // Gives an object exclusive control of the 'vision spheres' effect RLV_BHVR_SETSPHERE_COLOR, RLV_BHVR_SETSPHERE_DENSITY, @@ -249,12 +249,7 @@ enum ERlvBehaviour { RLV_BHVR_SETSPHERE_MINALPHA, RLV_BHVR_SETSPHERE_MINDIST, - // Overlay RLV_BHVR_SETOVERLAY, // Gives an object exclusive control of the overlay - RLV_BHVR_SETOVERLAY_ALPHA, // Changes the overlay texture's transparency level - RLV_BHVR_SETOVERLAY_TEXTURE, // Changes the overlay texture - RLV_BHVR_SETOVERLAY_TINT, // Changes the tint that's applied to the overlay texture - RLV_BHVR_SETOVERLAY_TOUCH, // Block world interaction (=touching) based on the alpha channel of the overlay texture RLV_BHVR_SETOVERLAY_TWEEN, // Animate between the current overlay settings and the supplied values RLV_BHVR_COUNT, @@ -273,10 +268,6 @@ enum ERlvBehaviourModifier RLV_MODIFIER_FARTOUCHDIST, // Radius of a sphere around the user in which they can interact with the world - RLV_MODIFIER_OVERLAY_ALPHA, // Transparency level of the overlay texture (in addition to the texture's own alpha channel) - RLV_MODIFIER_OVERLAY_TEXTURE, // Specifies the UUID of the overlay texture - RLV_MODIFIER_OVERLAY_TINT, // The tint that's applied to the overlay texture - RLV_MODIFIER_OVERLAY_TOUCH, // Determines whether the overlay texture's alpha channel will be used to allow/block world interaction RLV_MODIFIER_RECVIMDISTMIN, // Minimum distance to receive an IM from an otherwise restricted sender (squared value) RLV_MODIFIER_RECVIMDISTMAX, // Maximum distance to receive an IM from an otherwise restricted sender (squared value) @@ -304,6 +295,16 @@ enum ERlvBehaviourModifier RLV_MODIFIER_UNKNOWN }; +enum class ERlvLocalBhvrModifier +{ + OverlayAlpha, // Transparency level of the overlay texture (in addition to the texture's own alpha channel) + OverlayTexture, // Specifies the UUID of the overlay texture + OverlayTint, // The tint that's applied to the overlay texture + OverlayTouch, // Determines whether the overlay texture's alpha channel will be used to allow/block world interaction + + Unknown, +}; + enum ERlvBehaviourOptionType { RLV_OPTION_NONE, // Behaviour takes no parameters diff --git a/indra/newview/rlveffects.cpp b/indra/newview/rlveffects.cpp new file mode 100644 index 0000000000..4750442089 --- /dev/null +++ b/indra/newview/rlveffects.cpp @@ -0,0 +1,175 @@ +/** + * + * Copyright (c) 2021, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#include "llviewerprecompiledheaders.h" + +#include "llglslshader.h" +#include "llrender2dutils.h" +#include "llviewertexturelist.h" +#include "llviewerwindow.h" + +#include "rlveffects.h" +#include "rlvhandler.h" + +// ==================================================================================== +// RlvOverlayEffect class +// + +const float c_DefaultAlpha = 1.0f; +const float c_DefaultColor[3] = { 1.0f, 1.0f, 1.0f }; + +RlvOverlayEffect::RlvOverlayEffect(const LLUUID& idRlvObj) + : LLVisualEffect(idRlvObj, EVisualEffect::RlvOverlay, EVisualEffectType::Custom) + , m_nAlpha(c_DefaultAlpha) + , m_fBlockTouch(false) + , m_Color(LLColor3(c_DefaultColor)) +{ + if (RlvObject* pRlvObj = gRlvHandler.getObject(idRlvObj)) + { + float nAlpha; + if (pRlvObj->getModifierValue(ERlvLocalBhvrModifier::OverlayAlpha, nAlpha)) + m_nAlpha = nAlpha; + + pRlvObj->getModifierValue(ERlvLocalBhvrModifier::OverlayTouch, m_fBlockTouch); + + LLVector3 vecColor; + if (pRlvObj->getModifierValue(ERlvLocalBhvrModifier::OverlayTint, vecColor)) + m_Color = LLColor3(vecColor.mV); + + LLUUID idTexture; + if ( (pRlvObj) && (pRlvObj->getModifierValue(ERlvLocalBhvrModifier::OverlayTexture, idTexture)) ) + setImage(idTexture); + } +} + +RlvOverlayEffect::~RlvOverlayEffect() +{ + clearImage(); +} + +// static +ERlvCmdRet RlvOverlayEffect::onAlphaValueChanged(const LLUUID& idRlvObj, const boost::optional newValue) +{ + if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + { + pEffect->m_nAlpha = (newValue) ? boost::get(newValue.value()) : c_DefaultAlpha; + } + return RLV_RET_SUCCESS; +} + +// static +ERlvCmdRet RlvOverlayEffect::onBlockTouchValueChanged(const LLUUID& idRlvObj, const boost::optional newValue) +{ + if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + { + pEffect->m_fBlockTouch = (newValue) ? boost::get(newValue.value()) : false; + } + return RLV_RET_SUCCESS; +} +// static +ERlvCmdRet RlvOverlayEffect::onColorValueChanged(const LLUUID& idRlvObj, const boost::optional newValue) +{ + if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + { + pEffect->m_Color = LLColor3( (newValue) ? boost::get(newValue.value()).mV : c_DefaultColor); + } + return RLV_RET_SUCCESS; +} + +// static +ERlvCmdRet RlvOverlayEffect::onTextureChanged(const LLUUID& idRlvObj, const boost::optional newValue) +{ + if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + { + if (newValue) + pEffect->setImage(boost::get(newValue.value())); + else + pEffect->clearImage(); + } + return RLV_RET_SUCCESS; +} + +void RlvOverlayEffect::clearImage() +{ + if (m_pImage) + { + m_pImage->setBoostLevel(m_nImageOrigBoost); + m_pImage = nullptr; + } +} + +bool RlvOverlayEffect::hitTest(const LLCoordGL& ptMouse) const +{ + if (!m_pImage) + return false; + + return (m_fBlockTouch) && (m_pImage->getMask(LLVector2((float)ptMouse.mX / gViewerWindow->getWorldViewWidthScaled(), (float)ptMouse.mY / gViewerWindow->getWorldViewHeightScaled()))); +} + +void RlvOverlayEffect::setImage(const LLUUID& idTexture) +{ + if ( (m_pImage) && (m_pImage->getID() == idTexture) ) + return; + + clearImage(); + m_pImage = LLViewerTextureManager::getFetchedTexture(idTexture, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + m_nImageOrigBoost = m_pImage->getBoostLevel(); + m_pImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + m_pImage->forceToSaveRawImage(0); +} + +void RlvOverlayEffect::run() +{ + if (m_pImage) + { + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + + int nWidth = gViewerWindow->getWorldViewWidthScaled(); + int nHeight = gViewerWindow->getWorldViewHeightScaled(); + + m_pImage->addTextureStats(nWidth * nHeight); + m_pImage->setKnownDrawSize(nWidth, nHeight); + + gGL.pushMatrix(); + LLGLSUIDefault glsUI; + gViewerWindow->setup2DRender(); + + const LLVector2& displayScale = gViewerWindow->getDisplayScale(); + gGL.scalef(displayScale.mV[VX], displayScale.mV[VY], 1.f); + + gGL.getTexUnit(0)->bind(m_pImage); + const LLColor3 col = m_Color.get(); + gGL.color4f(col.mV[0], col.mV[1], col.mV[2], llclamp(m_nAlpha.get(), 0.0f, 1.0f)); + + gl_rect_2d_simple_tex(nWidth, nHeight); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.popMatrix(); + gGL.flush(); + gViewerWindow->setup3DRender(); + + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } + } +} + +// ==================================================================================== diff --git a/indra/newview/rlveffects.h b/indra/newview/rlveffects.h new file mode 100644 index 0000000000..181187fe9d --- /dev/null +++ b/indra/newview/rlveffects.h @@ -0,0 +1,64 @@ +/** + * + * Copyright (c) 2021, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#pragma once + +#include "llvisualeffect.h" +#include "rlvhelper.h" + +// ============================================================================ +// Forward declarations +// + +class LLViewerFetchedTexture; + +// ==================================================================================== +// RlvOverlayEffect class +// + +class RlvOverlayEffect : public LLVisualEffect +{ +public: + RlvOverlayEffect(const LLUUID& idRlvObj); + ~RlvOverlayEffect(); + +public: + void tweenAlpha(float endAlpha, double duration) { m_nAlpha.start(endAlpha, duration); } + void tweenColor(LLColor3 endColor, double duration) { m_Color.start(endColor, duration); } + bool hitTest(const LLCoordGL& ptMouse) const; + static ERlvCmdRet onAlphaValueChanged(const LLUUID& idRlvObj, const boost::optional newValue); + static ERlvCmdRet onBlockTouchValueChanged(const LLUUID& idRlvObj, const boost::optional newValue); + static ERlvCmdRet onColorValueChanged(const LLUUID& idRlvObj, const boost::optional newValue); + static ERlvCmdRet onTextureChanged(const LLUUID& idRlvObj, const boost::optional newValue); +protected: + void clearImage(); + void setImage(const LLUUID& idTexture); + + void run() override; + + /* + * Member variables + */ +protected: + LLTweenableValueLerp m_nAlpha; + bool m_fBlockTouch; + LLTweenableValueLerp m_Color; + + LLPointer m_pImage = nullptr; + int m_nImageOrigBoost = 0; +}; + +// ==================================================================================== diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 72dd6e4c7d..a89338d5f9 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -53,12 +53,12 @@ #include "llviewercamera.h" // @setcam and related #include "llworldmapmessage.h" // @tpto #include "llviewertexturelist.h" // @setcam_texture -#include "llviewerwindow.h" // @setoverlay // RLVa includes #include "rlvactions.h" #include "rlvfloaters.h" #include "rlvactions.h" +#include "rlveffects.h" #include "rlvhandler.h" #include "rlvhelper.h" #include "rlvinventory.h" @@ -178,7 +178,6 @@ void RlvHandler::cleanup() RLV_ASSERT(std::all_of(m_Behaviours, m_Behaviours + RLV_BHVR_COUNT, [](S16 cnt) { return !cnt; })); RLV_ASSERT(m_CurCommandStack.empty()); RLV_ASSERT(m_CurObjectStack.empty()); - RLV_ASSERT(m_pOverlayImage.isNull()); // // Clean up what's left @@ -1782,7 +1781,7 @@ ERlvCmdRet RlvBehaviourGenericHandler::onCommand(const RlvC // 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)) ) + if ( (!rlvCmd.hasOption()) || (!pBhvrModifier) || (!pBhvrModifier->convertOptionValue(rlvCmd.getOption(), pBhvrModifier->getType(), modValue)) ) return RLV_RET_FAILED_OPTION; // HACK-RLVa: reference counting doesn't happen until control returns to our caller but the modifier callbacks will happen now so we need to adjust the reference counts here @@ -1803,15 +1802,22 @@ ERlvCmdRet RlvBehaviourGenericHandler::onCommand(const RlvC return RLV_RET_SUCCESS; } -// Handles: @bhvr[:]=n|y +// Handles: @bhvr=n, @bhvr:=n|y and @bhvr:=force template<> ERlvCmdRet RlvBehaviourGenericHandler::onCommand(const RlvCommand& rlvCmd, bool& fRefCount) { - // If there is an option then it should specify a valid modifier (and reference count) - if (rlvCmd.hasOption()) + if ( (rlvCmd.getParamType() & RLV_TYPE_ADDREM) && (rlvCmd.hasOption()) ) + { + // @bhvr:=n|y : if there is an option then it should specify a valid global modifier and if so we reference count return RlvBehaviourGenericHandler::onCommand(rlvCmd, fRefCount); + } + else if (rlvCmd.getParamType() == RLV_TYPE_FORCE) + { + // @bhvr:=force : local modifiers hide behind their primary behaviour which knows how to handle them + return rlvCmd.getBehaviourInfo()->processModifier(rlvCmd); + } - // Add the default option on an empty modifier if needed + // @bhvr=n : add the default option on an empty modifier if needed RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifierFromBehaviour(rlvCmd.getBehaviourType()); if ( (pBhvrModifier) && (pBhvrModifier->getAddDefault()) ) { @@ -2047,36 +2053,10 @@ void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour eBhv template<> template<> void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr) { - // Once an object has exclusive control over the overlay only its behaviours should be active. This affects: - // - behaviour modifiers => handled for us once we set the primary object - - LLUUID idRlvObject; if (fHasBhvr) - { - // Get the UUID of the primary object (there should only be one) - std::list lObjects; - gRlvHandler.findBehaviour(RLV_BHVR_SETOVERLAY, lObjects); - RLV_ASSERT(lObjects.size() == 1); - idRlvObject = lObjects.front()->getObjectID(); - } - - RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_ALPHA)->setPrimaryObject(idRlvObject); - RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_TINT)->setPrimaryObject(idRlvObject); - RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_TEXTURE)->setPrimaryObject(idRlvObject); - RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_TOUCH)->setPrimaryObject(idRlvObject); -} - -// Handles: @setoverlay_texture:=n|y changes -template<> -void RlvBehaviourModifierHandler::onValueChange() const -{ - if (RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_TEXTURE)) - { - if (pBhvrModifier->hasValue()) - gRlvHandler.setOverlayImage(pBhvrModifier->getValue()); - else - gRlvHandler.clearOverlayImage(); - } + LLVfxManager::instance().addEffect(new RlvOverlayEffect(gRlvHandler.getCurrentObject())); + else + LLVfxManager::instance().removeEffect(gRlvHandler.getCurrentObject()); } // Handles: @sendchannel[:]=n|y and @sendchannel_except[:]=n|y @@ -2622,7 +2602,7 @@ ERlvCmdRet RlvForceGenericHandler::onCommand(const RlvComma // 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)) ) + if ( (!rlvCmd.hasOption()) || (!pBhvrModifier) || (!pBhvrModifier->convertOptionValue(rlvCmd.getOption(), pBhvrModifier->getType(), modValue)) ) return RLV_RET_FAILED_OPTION; pBhvrModifier->setValue(modValue, rlvCmd.getObjectID()); @@ -2977,6 +2957,14 @@ ERlvCmdRet RlvForceHandler::onCommand(const RlvCommand& rl template<> template<> ERlvCmdRet RlvForceHandler::onCommand(const RlvCommand& rlvCmd) { + RlvObject* pRlvObj = gRlvHandler.getObject(rlvCmd.getObjectID()); + if (!pRlvObj) + return RLV_RET_FAILED_NOBEHAVIOUR; + + RlvOverlayEffect* pOverlayEffect = LLVfxManager::instance().getEffect(rlvCmd.getObjectID()); + if (!pOverlayEffect) + return RLV_RET_FAILED_LOCK; + std::vector optionList; if ( (!RlvCommandOptionHelper::parseStringList(rlvCmd.getOption(), optionList)) || (3 != optionList.size()) ) return RLV_RET_FAILED_OPTION; @@ -2989,12 +2977,18 @@ ERlvCmdRet RlvForceHandler::onCommand(const RlvComman // Process the overlay alpha tween (if there is one and it is a valid value) float overlayAlpha = .0f; if (RlvCommandOptionHelper::parseOption(optionList[0], overlayAlpha)) - RlvBehaviourModifierAnimator::instance().addTween(rlvCmd.getObjectID(), RLV_MODIFIER_OVERLAY_ALPHA, RlvBehaviourModifierAnimationType::Lerp, overlayAlpha, tweenDuration); + { + pOverlayEffect->tweenAlpha(overlayAlpha, tweenDuration); + pRlvObj->setModifierValue(ERlvLocalBhvrModifier::OverlayAlpha, overlayAlpha); + } // Process the overlay tint tween (if there is one and it is a valid value) LLVector3 overlayColor; if (RlvCommandOptionHelper::parseOption(optionList[1], overlayColor)) - RlvBehaviourModifierAnimator::instance().addTween(rlvCmd.getObjectID(), RLV_MODIFIER_OVERLAY_TINT, RlvBehaviourModifierAnimationType::Lerp, overlayColor, tweenDuration); + { + pOverlayEffect->tweenColor(LLColor3(overlayColor.mV), tweenDuration); + pRlvObj->setModifierValue(ERlvLocalBhvrModifier::OverlayTint, overlayColor); + } return RLV_RET_SUCCESS; } @@ -3776,76 +3770,4 @@ ERlvCmdRet RlvHandler::onGetPath(const RlvCommand& rlvCmd, std::string& strReply // Command specific helper functions - @setoverlay // -void RlvHandler::clearOverlayImage() -{ - if (m_pOverlayImage) - { - m_pOverlayImage->setBoostLevel(m_nOverlayOrigBoost); - m_pOverlayImage = nullptr; - } -} - -bool RlvHandler::hitTestOverlay(const LLCoordGL& ptMouse) const -{ - if (!m_pOverlayImage) - return false; - - RlvBehaviourModifier* pTouchModifier = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_TOUCH); - return (pTouchModifier) && (pTouchModifier->hasValue()) && (pTouchModifier->getValue()) && - (m_pOverlayImage->getMask(LLVector2((float)ptMouse.mX / gViewerWindow->getWorldViewWidthScaled(), (float)ptMouse.mY / gViewerWindow->getWorldViewHeightScaled()))); -} - -void RlvHandler::renderOverlay() -{ - if ( (hasBehaviour(RLV_BHVR_SETOVERLAY)) && (m_pOverlayImage) ) - { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - - int nWidth = gViewerWindow->getWorldViewWidthScaled(); - int nHeight = gViewerWindow->getWorldViewHeightScaled(); - - m_pOverlayImage->addTextureStats(nWidth * nHeight); - m_pOverlayImage->setKnownDrawSize(nWidth, nHeight); - - gGL.pushMatrix(); - LLGLSUIDefault glsUI; - gViewerWindow->setup2DRender(); - - const LLVector2& displayScale = gViewerWindow->getDisplayScale(); - gGL.scalef(displayScale.mV[VX], displayScale.mV[VY], 1.f); - - gGL.getTexUnit(0)->bind(m_pOverlayImage); - const LLVector3 overlayTint = RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_TINT)->getValue(); - gGL.color4f(overlayTint.mV[0], overlayTint.mV[1], overlayTint.mV[2], llclamp(RlvBehaviourDictionary::instance().getModifier(RLV_MODIFIER_OVERLAY_ALPHA)->getValue(), 0.0f, 1.0f)); - - gl_rect_2d_simple_tex(nWidth, nHeight); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.popMatrix(); - gGL.flush(); - gViewerWindow->setup3DRender(); - - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } - } -} - -void RlvHandler::setOverlayImage(const LLUUID& idTexture) -{ - if ( (m_pOverlayImage) && (m_pOverlayImage->getID() == idTexture) ) - return; - - clearOverlayImage(); - m_pOverlayImage = LLViewerTextureManager::getFetchedTexture(idTexture, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - m_nOverlayOrigBoost = m_pOverlayImage->getBoostLevel(); - m_pOverlayImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); - m_pOverlayImage->forceToSaveRawImage(0); -} - // ============================================================================ diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h index 32eda85137..2aaea60c19 100644 --- a/indra/newview/rlvhandler.h +++ b/indra/newview/rlvhandler.h @@ -23,13 +23,9 @@ #include "rlvcommon.h" #include "rlvhelper.h" - // ============================================================================ - // Forward declarations - // - -class LLViewerFetchedTexture; - // ============================================================================ +// RlvHandler class +// class RlvHandler : public LLOldEvents::LLSimpleListener, public LLParticularGroupObserver { @@ -56,6 +52,8 @@ public: public: // Returns a list of all objects containing the specified behaviour bool findBehaviour(ERlvBehaviour eBhvr, std::list& lObjects) const; + // Returns a pointer to an RLV object instance (DO NOT STORE THIS!) + RlvObject* getObject(const LLUUID& idRlvObj) const; // 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; @@ -123,9 +121,7 @@ public: // Command specific helper functions bool filterChat(std::string& strUTF8Text, bool fFilterEmote) const; // @sendchat, @recvchat and @redirchat - bool hitTestOverlay(const LLCoordGL& ptMouse) const; // @setoverlay bool redirectChatOrEmote(const std::string& strUTF8Test) const; // @redirchat and @rediremote - void renderOverlay(); // @setoverlay // Command processing helper functions ERlvCmdRet processCommand(const LLUUID& idObj, const std::string& strCommand, bool fFromObj); @@ -144,11 +140,9 @@ public: protected: // Command specific helper functions (NOTE: these generally do not perform safety checks) bool checkActiveGroupThrottle(const LLUUID& idRlvObj); // @setgroup=force - void clearOverlayImage(); // @setoverlay=n void setActiveGroup(const LLUUID& idGroup); // @setgroup=force void setActiveGroupRole(const LLUUID& idGroup, const std::string& strRole); // @setgroup=force void setCameraOverride(bool fOverride); // @setcam family - void setOverlayImage(const LLUUID& idTexture); // @setoverlay=n void onIMQueryListResponse(const LLSD& sdNotification, const LLSD sdResponse); @@ -263,8 +257,6 @@ protected: mutable LLUUID m_idAgentGroup; // @setgroup=n std::pair m_PendingGroupChange; // @setgroup=force std::pair m_GroupChangeExpiration; // @setgroup=force - LLPointer m_pOverlayImage = nullptr; // @setoverlay=n - int m_nOverlayOrigBoost = 0; // @setoverlay=n std::string m_strCameraPresetRestore; // @setcam_eyeoffset, @setcam_eyeoffsetscale and @setcam_focusoffset @@ -301,6 +293,12 @@ inline RlvHandler* RlvHandler::getInstance() return &gRlvHandler; } +inline RlvObject* RlvHandler::getObject(const LLUUID& idRlvObj) const +{ + auto itObj = m_Objects.find(idRlvObj); + return (m_Objects.end() != itObj) ? const_cast(&itObj->second) : nullptr; +} + inline bool RlvHandler::hasBehaviour(ERlvBehaviour eBhvr, const std::string& strOption) const { return hasBehaviourExcept(eBhvr, strOption, LLUUID::null); diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index a57bc03b68..21c5c164be 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -22,6 +22,7 @@ #include "llviewerobjectlist.h" #include "rlvcommon.h" +#include "rlveffects.h" #include "rlvhelper.h" #include "rlvhandler.h" #include "rlvinventory.h" @@ -228,15 +229,12 @@ RlvBehaviourDictionary::RlvBehaviourDictionary() RLV_MODIFIER_EFFECT_SPHERE_MINALPHA, new RlvBehaviourModifier("Effect: Vision spheres - Min distance alpha", 1.0f, false, new RlvBehaviourModifierCompMax())); // Overlay - addEntry(new RlvBehaviourGenericToggleProcessor("setoverlay", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); - addModifier(new RlvForceGenericProcessor("setoverlay_alpha", RLV_BHVR_SETOVERLAY_ALPHA, RlvBehaviourInfo::BHVR_EXPERIMENTAL), - RLV_MODIFIER_OVERLAY_ALPHA, new RlvBehaviourModifier("Overlay - Alpha", 1.0f, false, new RlvBehaviourModifierComp())); - addModifier(new RlvForceGenericProcessor("setoverlay_texture", RLV_BHVR_SETOVERLAY_TEXTURE, RlvBehaviourInfo::BHVR_EXPERIMENTAL), - RLV_MODIFIER_OVERLAY_TEXTURE, new RlvBehaviourModifierHandler("Overlay - Texture", LLUUID::null, false, new RlvBehaviourModifierComp())); - addModifier(new RlvForceGenericProcessor("setoverlay_tint", RLV_BHVR_SETOVERLAY_TINT, RlvBehaviourInfo::BHVR_EXPERIMENTAL), - RLV_MODIFIER_OVERLAY_TINT, new RlvBehaviourModifier("Overlay - Tint", LLVector3(1.0f, 1.0f, 1.0f), false, new RlvBehaviourModifierComp())); - addModifier(new RlvBehaviourGenericProcessor("setoverlay_touch", RLV_BHVR_SETOVERLAY_TOUCH, RlvBehaviourInfo::BHVR_EXPERIMENTAL), - RLV_MODIFIER_OVERLAY_TOUCH, new RlvBehaviourModifier("Overlay - Touch", true, true, new RlvBehaviourModifierComp())); + RlvBehaviourInfo* pSetOverlayBhvr = new RlvBehaviourGenericToggleProcessor("setoverlay"); + pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayAlpha, typeid(float), "alpha", &RlvOverlayEffect::onAlphaValueChanged); + pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTexture, typeid(LLUUID), "texture", &RlvOverlayEffect::onTextureChanged); + pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTint, typeid(LLVector3), "tint", &RlvOverlayEffect::onColorValueChanged); + pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTouch, typeid(LLVector3), "touch", &RlvOverlayEffect::onBlockTouchValueChanged); + addEntry(pSetOverlayBhvr); addEntry(new RlvForceProcessor("setoverlay_tween", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); // @@ -407,20 +405,36 @@ void RlvBehaviourDictionary::clearModifiers(const LLUUID& idRlvObj) } } -const RlvBehaviourInfo* RlvBehaviourDictionary::getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const +const RlvBehaviourInfo* RlvBehaviourDictionary::getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict, ERlvLocalBhvrModifier* peBhvrModifier) const { - bool fStrict = boost::algorithm::ends_with(strBhvr, "_sec"); + size_t idxBhvrLastPart = strBhvr.find_last_of('_'); + std::string strBhvrLastPart((std::string::npos != idxBhvrLastPart) && (idxBhvrLastPart < strBhvr.size()) ? strBhvr.substr(idxBhvrLastPart + 1) : LLStringUtil::null); + + bool fStrict = (strBhvrLastPart.compare("sec") == 0); if (pfStrict) *pfStrict = fStrict; + ERlvLocalBhvrModifier eBhvrModifier = ERlvLocalBhvrModifier::Unknown; rlv_string2info_map_t::const_iterator itBhvr = m_String2InfoMap.find(std::make_pair( (!fStrict) ? strBhvr : strBhvr.substr(0, strBhvr.size() - 4), (eParamType & RLV_TYPE_ADDREM) ? RLV_TYPE_ADDREM : eParamType)); - return ( (itBhvr != m_String2InfoMap.end()) && ((!fStrict) || (itBhvr->second->hasStrict())) ) ? itBhvr->second : NULL; + if ( (m_String2InfoMap.end() == itBhvr) && (!fStrict) && (!strBhvrLastPart.empty()) && (RLV_TYPE_FORCE == eParamType) ) + { + // No match found but it could still be a local scope modifier + auto itBhvrMod = m_String2InfoMap.find(std::make_pair(strBhvr.substr(0, idxBhvrLastPart), RLV_TYPE_ADDREM)); + if ( (m_String2InfoMap.end() != itBhvrMod) && (eBhvrModifier = itBhvrMod->second->lookupBehaviourModifier(strBhvrLastPart)) != ERlvLocalBhvrModifier::Unknown) + itBhvr = itBhvrMod; + } + + if (peBhvrModifier) + *peBhvrModifier = eBhvrModifier; + return ( (itBhvr != m_String2InfoMap.end()) && ((!fStrict) || (itBhvr->second->hasStrict())) ) ? itBhvr->second : nullptr; } ERlvBehaviour RlvBehaviourDictionary::getBehaviourFromString(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const { - const RlvBehaviourInfo* pBhvrInfo = getBehaviourInfo(strBhvr, eParamType, pfStrict); - return (pBhvrInfo) ? pBhvrInfo->getBehaviourType() : RLV_BHVR_UNKNOWN; + ERlvLocalBhvrModifier eBhvrModifier; + const RlvBehaviourInfo* pBhvrInfo = getBehaviourInfo(strBhvr, eParamType, pfStrict, &eBhvrModifier); + // Filter out locally scoped modifier commands since they don't actually have a unique behaviour value of their own + return (pBhvrInfo && ERlvLocalBhvrModifier::Unknown != eBhvrModifier) ? pBhvrInfo->getBehaviourType() : RLV_BHVR_UNKNOWN; } bool RlvBehaviourDictionary::getCommands(const std::string& strMatch, ERlvParamType eParamType, std::list& cmdList) const @@ -469,6 +483,42 @@ void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERl } } +// ============================================================================ +// RlvBehaviourInfo +// + +// virtual +ERlvCmdRet RlvBehaviourInfo::processModifier(const RlvCommand& rlvCmd) const +{ + // The object should be holding at least one active behaviour + if (!gRlvHandler.hasBehaviour(rlvCmd.getObjectID())) + return RLV_RET_FAILED_NOBEHAVIOUR; + + auto itBhvrModifier = std::find_if(m_BhvrModifiers.begin(), m_BhvrModifiers.end(), [&rlvCmd](const modifier_lookup_t::value_type& entry) { return std::get<0>(entry.second) == rlvCmd.getBehaviourModifier(); }); + if (m_BhvrModifiers.end() == itBhvrModifier) + return RLV_RET_FAILED_UNKNOWN; + + ERlvCmdRet eCmdRet; const modifier_handler_func_t& fnHandler = std::get<2>(itBhvrModifier->second); + if (rlvCmd.hasOption()) + { + // If there's an option parse it (and perform type checking) + RlvBehaviourModifierValue modValue; + if ( (rlvCmd.hasOption()) && (!RlvBehaviourModifier::convertOptionValue(rlvCmd.getOption(), std::get<1>(itBhvrModifier->second), modValue)) ) + return RLV_RET_FAILED_OPTION; + eCmdRet = (fnHandler) ? fnHandler(rlvCmd.getObjectID(), modValue) : RLV_RET_SUCCESS; + if (RLV_RET_SUCCESS == eCmdRet) + gRlvHandler.getObject(rlvCmd.getObjectID())->setModifierValue(rlvCmd.getBehaviourModifier(), modValue); + } + else + { + eCmdRet = (fnHandler) ? fnHandler(rlvCmd.getObjectID(), boost::none) : RLV_RET_SUCCESS; + if (RLV_RET_SUCCESS == eCmdRet) + gRlvHandler.getObject(rlvCmd.getObjectID())->clearModifierValue(rlvCmd.getBehaviourModifier()); + } + + return eCmdRet; +} + // ============================================================================ // RlvBehaviourModifier // @@ -508,7 +558,6 @@ void RlvBehaviourModifier::clearValues(const LLUUID& idRlvObj) [&idRlvObj](const RlvBehaviourModifierValueTuple& modValue) { return (std::get<1>(modValue) == idRlvObj) && (std::get<2>(modValue) == RLV_BHVR_UNKNOWN); }), m_Values.end()); - RlvBehaviourModifierAnimator::instance().clearTweens(idRlvObj); if (origCount != m_Values.size()) { onValueChange(); @@ -583,21 +632,22 @@ void RlvBehaviourModifier::setValue(const RlvBehaviourModifierValue& modValue, c } } -bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const +// static +bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, const std::type_index& modType, RlvBehaviourModifierValue& modValue) { try { - if (typeid(float) == m_DefaultValue.type()) + if (modType == typeid(float)) { modValue = std::stof(optionValue); return true; } - else if (typeid(int) == m_DefaultValue.type()) + else if (modType == typeid(int)) { modValue = std::stoi(optionValue); return true; } - else if (typeid(LLVector3) == m_DefaultValue.type()) + else if (modType == typeid(LLVector3)) { LLVector3 vecOption; if (3 == sscanf(optionValue.c_str(), "%f/%f/%f", vecOption.mV + 0, vecOption.mV + 1, vecOption.mV + 2)) @@ -606,7 +656,7 @@ bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, Rl return true; } } - else if (typeid(LLUUID) == m_DefaultValue.type()) + else if (modType == typeid(LLUUID)) { LLUUID idOption; if (LLUUID::parseUUID(optionValue, &idOption)) @@ -628,7 +678,7 @@ bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, Rl // RlvCommand::RlvCommand(const LLUUID& idObj, const std::string& strCommand) - : m_fValid(false), m_idObj(idObj), m_pBhvrInfo(NULL), m_eParamType(RLV_TYPE_UNKNOWN), m_fStrict(false), m_fRefCounted(false) + : m_idObj(idObj) { if (m_fValid = parseCommand(strCommand, m_strBehaviour, m_strOption, m_strParam)) { @@ -656,7 +706,7 @@ RlvCommand::RlvCommand(const LLUUID& idObj, const std::string& strCommand) return; } - m_pBhvrInfo = RlvBehaviourDictionary::instance().getBehaviourInfo(m_strBehaviour, m_eParamType, &m_fStrict); + m_pBhvrInfo = RlvBehaviourDictionary::instance().getBehaviourInfo(m_strBehaviour, m_eParamType, &m_fStrict, &m_eBhvrModifier); } RlvCommand::RlvCommand(const RlvCommand& rlvCmd, ERlvParamType eParamType) @@ -1087,6 +1137,20 @@ std::string RlvObject::getStatusString(const std::string& strFilter, const std:: return strStatus; } +void RlvObject::clearModifierValue(ERlvLocalBhvrModifier eBhvrModifier) +{ + m_Modifiers.erase(eBhvrModifier); +} + +void RlvObject::setModifierValue(ERlvLocalBhvrModifier eBhvrModifier, const RlvBehaviourModifierValue& newValue) +{ + auto itBhvrModifierValue = m_Modifiers.find(eBhvrModifier); + if (m_Modifiers.end() != itBhvrModifierValue) + itBhvrModifierValue->second = newValue; + else + m_Modifiers.insert(std::make_pair(eBhvrModifier, newValue)); +} + // ============================================================================ // RlvForceWear // diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index cbe79ec57a..f5e9c7c6d2 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -38,6 +38,7 @@ struct RlvBehaviourModifierComp; class RlvBehaviourInfo { + typedef std::function)> modifier_handler_func_t; public: enum EBehaviourFlags { @@ -65,24 +66,29 @@ public: : m_strBhvr(strBhvr), m_eBhvr(eBhvr), m_maskParamType(maskParamType), m_nBhvrFlags(nBhvrFlags) {} virtual ~RlvBehaviourInfo() {} - const std::string& getBehaviour() const { return m_strBhvr; } - ERlvBehaviour getBehaviourType() const { return m_eBhvr; } - U32 getBehaviourFlags() const { return m_nBhvrFlags; } - U32 getParamTypeMask() const { return m_maskParamType; } - bool hasStrict() const { return m_nBhvrFlags & BHVR_STRICT; } - bool isBlocked() const { return m_nBhvrFlags & BHVR_BLOCKED; } - bool isExperimental() const { return m_nBhvrFlags & BHVR_EXPERIMENTAL; } - bool isExtended() const { return m_nBhvrFlags & BHVR_EXTENDED; } - bool isSynonym() const { return m_nBhvrFlags & BHVR_SYNONYM; } - void toggleBehaviourFlag(EBehaviourFlags eBhvrFlag, bool fEnable); + void addModifier(ERlvLocalBhvrModifier eBhvrMod, const std::type_info& valueType, const std::string& strBhvrMod, modifier_handler_func_t fnHandler = nullptr); + const std::string& getBehaviour() const { return m_strBhvr; } + ERlvBehaviour getBehaviourType() const { return m_eBhvr; } + U32 getBehaviourFlags() const { return m_nBhvrFlags; } + U32 getParamTypeMask() const { return m_maskParamType; } + bool hasStrict() const { return m_nBhvrFlags & BHVR_STRICT; } + bool isBlocked() const { return m_nBhvrFlags & BHVR_BLOCKED; } + bool isExperimental() const { return m_nBhvrFlags & BHVR_EXPERIMENTAL; } + bool isExtended() const { return m_nBhvrFlags & BHVR_EXTENDED; } + bool isSynonym() const { return m_nBhvrFlags & BHVR_SYNONYM; } + ERlvLocalBhvrModifier lookupBehaviourModifier(const std::string& strBhvrMod) const; + void toggleBehaviourFlag(EBehaviourFlags eBhvrFlag, bool fEnable); virtual ERlvCmdRet processCommand(const RlvCommand& rlvCmd) const { return RLV_RET_NO_PROCESSOR; } + virtual ERlvCmdRet processModifier(const RlvCommand& rlvCmd) const; protected: std::string m_strBhvr; ERlvBehaviour m_eBhvr; U32 m_nBhvrFlags; U32 m_maskParamType; + typedef std::map> modifier_lookup_t; + modifier_lookup_t m_BhvrModifiers; }; // ============================================================================ @@ -106,7 +112,7 @@ public: 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; + const RlvBehaviourInfo* getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict = nullptr, ERlvLocalBhvrModifier* peBhvrModifier = nullptr) const; bool getCommands(const std::string& strMatch, ERlvParamType eParamType, std::list& cmdList) const; bool getHasStrict(ERlvBehaviour eBhvr) const; RlvBehaviourModifier* getModifier(ERlvBehaviourModifier eBhvrMod) const { return (eBhvrMod < RLV_MODIFIER_COUNT) ? m_BehaviourModifiers[eBhvrMod] : nullptr; } @@ -244,12 +250,13 @@ protected: virtual void onValueChange() const {} public: bool addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idRlvObj, ERlvBehaviour eBhvr = RLV_BHVR_UNKNOWN); - bool convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const; + static bool convertOptionValue(const std::string& optionValue, const std::type_index& modType, RlvBehaviourModifierValue& modValue); 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 std::type_info& getType() const { return m_DefaultValue.type(); } 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; @@ -289,14 +296,17 @@ public: public: std::string asString() const; const std::string& getBehaviour() const { return m_strBehaviour; } + const RlvBehaviourInfo* getBehaviourInfo() const { return m_pBhvrInfo; } ERlvBehaviour getBehaviourType() const { return (m_pBhvrInfo) ? m_pBhvrInfo->getBehaviourType() : RLV_BHVR_UNKNOWN; } U32 getBehaviourFlags() const{ return (m_pBhvrInfo) ? m_pBhvrInfo->getBehaviourFlags() : 0; } + ERlvLocalBhvrModifier getBehaviourModifier() const { return m_eBhvrModifier; } const LLUUID& getObjectID() const { return m_idObj; } const std::string& getOption() const { return m_strOption; } const std::string& getParam() const { return m_strParam; } ERlvParamType getParamType() const { return m_eParamType; } bool hasOption() const { return !m_strOption.empty(); } bool isBlocked() const { return (m_pBhvrInfo) ? m_pBhvrInfo->isBlocked() : false; } + bool isModifier() const { return ERlvLocalBhvrModifier::Unknown != m_eBhvrModifier; } bool isRefCounted() const { return m_fRefCounted; } bool isStrict() const { return m_fStrict; } bool isValid() const { return m_fValid; } @@ -316,15 +326,16 @@ public: * Member variables */ protected: - bool m_fValid; + bool m_fValid = false; LLUUID m_idObj; std::string m_strBehaviour; - const RlvBehaviourInfo* m_pBhvrInfo; - ERlvParamType m_eParamType; - bool m_fStrict; + const RlvBehaviourInfo* m_pBhvrInfo = nullptr; + ERlvParamType m_eParamType = RLV_TYPE_UNKNOWN; + ERlvLocalBhvrModifier m_eBhvrModifier = ERlvLocalBhvrModifier::Unknown; + bool m_fStrict = false; std::string m_strOption; std::string m_strParam; - mutable bool m_fRefCounted; + mutable bool m_fRefCounted = false; friend class RlvHandler; friend class RlvObject; @@ -452,6 +463,14 @@ public: bool hasLookup() const { return m_fLookup; } const rlv_command_list_t& getCommandList() const { return m_Commands; } + /* + * Local-scope modifiers + */ +public: + void clearModifierValue(ERlvLocalBhvrModifier eBhvrMod); + template bool getModifierValue(ERlvLocalBhvrModifier eBhvrModifier, T& value) const; + void setModifierValue(ERlvLocalBhvrModifier eBhvrMod, const RlvBehaviourModifierValue& modValue); + /* * Member variables */ @@ -462,6 +481,8 @@ protected: bool m_fLookup; // TRUE if the object existed in gObjectList at one point in time S16 m_nLookupMisses; // Count of unsuccessful lookups in gObjectList by the GC rlv_command_list_t m_Commands; // List of behaviours held by this object (in the order they were received) + typedef std::map bhvr_modifier_map_t; + bhvr_modifier_map_t m_Modifiers; // List of (local scope) modifiers set on this object friend class RlvHandler; }; @@ -686,6 +707,19 @@ std::string rlvGetLastParenthesisedText(const std::string& strText, std::string: // Inlined class member functions // +inline void RlvBehaviourInfo::addModifier(ERlvLocalBhvrModifier eBhvrMod, const std::type_info& valueType, const std::string& strBhvrMod, modifier_handler_func_t fnHandler) +{ + RLV_ASSERT_DBG(m_BhvrModifiers.find(strBhvrMod) == m_BhvrModifiers.end()); + + m_BhvrModifiers.insert(std::make_pair(strBhvrMod, std::make_tuple(eBhvrMod, std::type_index(valueType), fnHandler))); +} + +inline ERlvLocalBhvrModifier RlvBehaviourInfo::lookupBehaviourModifier(const std::string& strBhvrMod) const +{ + auto itBhvrModifier = m_BhvrModifiers.find(strBhvrMod); + return (m_BhvrModifiers.end() != itBhvrModifier) ? std::get<0>(itBhvrModifier->second) : ERlvLocalBhvrModifier::Unknown; +} + inline void RlvBehaviourInfo::toggleBehaviourFlag(EBehaviourFlags eBhvrFlag, bool fEnable) { if (fEnable) @@ -710,6 +744,18 @@ inline bool RlvCommand::operator ==(const RlvCommand& rhs) const ( (RLV_TYPE_UNKNOWN != m_eParamType) ? (m_eParamType == rhs.m_eParamType) : (m_strParam == rhs.m_strParam) ); } +template +inline bool RlvObject::getModifierValue(ERlvLocalBhvrModifier eBhvrModifier, T& value) const +{ + auto itBhvrModifierValue = m_Modifiers.find(eBhvrModifier); + if (m_Modifiers.end() != itBhvrModifierValue) + { + value = boost::get(itBhvrModifierValue->second); + return true; + } + return false; +} + // Checked: 2010-04-05 (RLVa-1.2.0d) | Modified: RLVa-1.2.0d inline bool RlvForceWear::isWearableItem(const LLInventoryItem* pItem) { diff --git a/indra/newview/rlvmodifiers.cpp b/indra/newview/rlvmodifiers.cpp deleted file mode 100644 index ce082254f2..0000000000 --- a/indra/newview/rlvmodifiers.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/** - * - * Copyright (c) 2009-2018, Kitty Barnett - * - * The source code in this file is provided to you under the terms of the - * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt - * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt - * - * By copying, modifying or distributing this software, you acknowledge that - * you have read and understood your obligations described above, and agree to - * abide by those obligations. - * - */ - -#include "llviewerprecompiledheaders.h" - -#include "rlvmodifiers.h" - -// ==================================================================================== -// RlvBehaviourModifierAnimator -// - -RlvBehaviourModifierAnimator::~RlvBehaviourModifierAnimator() -{ - if (!m_TimerHandle.isDead()) - m_TimerHandle.markDead(); -} - -void RlvBehaviourModifierAnimator::addTween(const LLUUID& idObject, ERlvBehaviourModifier eBhvrMod, RlvBehaviourModifierAnimationType eAnimType, const RlvBehaviourModifierValue& endValue, float nDuration) -{ - // Make sure we don't run two animations on the same modifier for the same object - const auto itTween = std::find_if(m_Tweens.begin(), m_Tweens.end(), [&idObject, eBhvrMod](const RlvBehaviourModifierTween& t) { return t.idObject == idObject && t.eBhvrMod == eBhvrMod; }); - if (m_Tweens.end() != itTween) - m_Tweens.erase(itTween); - - if (const RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(eBhvrMod)) - { - RlvBehaviourModifierTween newTween; - newTween.idObject = idObject; - newTween.eBhvrMod = eBhvrMod; - newTween.eAnimType = RlvBehaviourModifierAnimationType::Lerp; - newTween.nStartTime = LLTimer::getElapsedSeconds(); - newTween.nDuration = nDuration; - newTween.startValue = pBhvrModifier->getValue(); - newTween.endValue = endValue; - if (newTween.startValue.which() == newTween.endValue.which()) - { - if (m_TimerHandle.isDead()) - m_TimerHandle = (new AnimationTimer())->getHandle(); - m_Tweens.emplace_back(std::move(newTween)); - } - } -} - -void RlvBehaviourModifierAnimator::clearTweens(const LLUUID& idObject, ERlvBehaviourModifier eBhvrMod) -{ - m_Tweens.erase(std::remove_if(m_Tweens.begin(), m_Tweens.end(), - [&idObject, eBhvrMod](const RlvBehaviourModifierTween& cmpTween) - { - return cmpTween.idObject == idObject && ((cmpTween.eBhvrMod == eBhvrMod) || (RLV_MODIFIER_UNKNOWN == eBhvrMod)); - }), m_Tweens.end()); -} - -// ==================================================================================== -// RlvBehaviourModifierAnimator timer -// - -RlvBehaviourModifierAnimator::AnimationTimer::AnimationTimer() - : LLEventTimer(1.f / RLV_MODIFIER_ANIMATION_FREQUENCY) -{ -} - - -BOOL RlvBehaviourModifierAnimator::AnimationTimer::tick() -{ - RlvBehaviourModifierAnimator& modAnimatior = RlvBehaviourModifierAnimator::instance(); - const double curTime = LLTimer::getElapsedSeconds(); - - const auto activeTweens = modAnimatior.m_Tweens; - for (const auto& curTween : activeTweens) - { - if (RlvBehaviourModifier* pBhvrModifier = RlvBehaviourDictionary::instance().getModifier(curTween.eBhvrMod)) - { - // Update the modifier's value - float curFactor = (curTime - curTween.nStartTime) / curTween.nDuration; - if (curFactor < 1.0) - { - const auto& valueType = curTween.startValue.type(); - if (typeid(float) == valueType) - pBhvrModifier->setValue(lerp(boost::get(curTween.startValue), boost::get(curTween.endValue), curFactor), curTween.idObject); - else if (typeid(int) == valueType) - pBhvrModifier->setValue(lerp(boost::get(curTween.startValue), boost::get(curTween.endValue), curFactor), curTween.idObject); - else if (typeid(LLVector3) == valueType) - pBhvrModifier->setValue(lerp(boost::get(curTween.startValue), boost::get(curTween.endValue), curFactor), curTween.idObject); - } - else - { - pBhvrModifier->setValue(curTween.endValue, curTween.idObject); - auto itTween = std::find_if(modAnimatior.m_Tweens.begin(), modAnimatior.m_Tweens.end(), - [&curTween](const RlvBehaviourModifierTween& t) - { - // NOTE: implementation leak - taking advantage of the fact that we know there can only be one active tween per object/modifier/type combination - return t.idObject == curTween.idObject && t.eBhvrMod == curTween.eBhvrMod && t.eAnimType == curTween.eAnimType; - }); - modAnimatior.m_Tweens.erase(itTween); - } - } - } - - return modAnimatior.m_Tweens.empty(); -} - - // ==================================================================================== diff --git a/indra/newview/rlvmodifiers.h b/indra/newview/rlvmodifiers.h index 3ccec3e71c..374ef58567 100644 --- a/indra/newview/rlvmodifiers.h +++ b/indra/newview/rlvmodifiers.h @@ -73,56 +73,6 @@ struct RlvBehaviourModifierCompMax : public RlvBehaviourModifierComp } }; -// ==================================================================================== -// RlvBehaviourModifierAnimator - A class to animate behaviour modifiers -// - -enum class RlvBehaviourModifierAnimationType { Lerp }; - -struct RlvBehaviourModifierTween -{ - LLUUID idObject; - ERlvBehaviourModifier eBhvrMod; - RlvBehaviourModifierAnimationType eAnimType; - double nStartTime; - float nDuration; - RlvBehaviourModifierValue startValue; - RlvBehaviourModifierValue endValue; -}; - -class RlvBehaviourModifierAnimator : public LLSingleton -{ - LLSINGLETON_EMPTY_CTOR(RlvBehaviourModifierAnimator); -public: - ~RlvBehaviourModifierAnimator() override; - - /* - * Member functions - */ -public: - void addTween(const LLUUID& idObject, ERlvBehaviourModifier eBhvrMod, RlvBehaviourModifierAnimationType eAnimType, const RlvBehaviourModifierValue& endValue, float nDuration); - void clearTweens(const LLUUID& idObject) { clearTweens(idObject, RLV_MODIFIER_UNKNOWN); } - void clearTweens(const LLUUID& idObject, ERlvBehaviourModifier eBhvrMod); - - /* - * Animation timer - */ -protected: - class AnimationTimer : public LLEventTimer, public LLHandleProvider - { - public: - AnimationTimer(); - BOOL tick() override; - }; - - /* - * Member variables - */ -protected: - LLHandle m_TimerHandle; - std::list< RlvBehaviourModifierTween> m_Tweens; -}; - // ==================================================================================== // RlvCachedBehaviourModifier - Provides an optimized way to access a modifier that's frequently accessed and rarely updated //