diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dd3890188ec49959214bada52c55503812e0ac83..ba61c4635769738bdf338362e3a66475a433f619 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -682,6 +682,7 @@ set(viewer_SOURCE_FILES llviewerwearable.cpp llviewerwindow.cpp llviewerwindowlistener.cpp + llvisualeffect.cpp llvlcomposition.cpp llvlmanager.cpp llvoavatar.cpp @@ -1302,6 +1303,7 @@ set(viewer_HEADER_FILES llviewerwearable.h llviewerwindow.h llviewerwindowlistener.h + llvisualeffect.h llvlcomposition.h llvlmanager.h llvoavatar.h diff --git a/indra/newview/llvisualeffect.cpp b/indra/newview/llvisualeffect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23c9065f9623ea08680ad9e362b5820313d8d48d --- /dev/null +++ b/indra/newview/llvisualeffect.cpp @@ -0,0 +1,140 @@ +/** + * + * 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 "llvisualeffect.h" + +#include <boost/iterator/filter_iterator.hpp> +#include <boost/range/iterator_range.hpp> + +// ============================================================================ +// LLTweenableValue class +// + +template<> +float LLTweenableValueLerp<float>::get() +{ + if (!m_CurValue) + { + float curFactor = (LLTimer::getElapsedSeconds() - m_StartTime) / m_Duration; + if (curFactor < 1.0) + return lerp(m_StartValue, m_EndValue, curFactor); + m_CurValue = m_EndValue; + } + return m_CurValue.get(); +} + +template<> +LLColor3 LLTweenableValueLerp<LLColor3>::get() +{ + if (!m_CurValue) + { + float curFactor = (LLTimer::getElapsedSeconds() - m_StartTime) / m_Duration; + if (curFactor < 1.0) + return lerp(m_StartValue, m_EndValue, curFactor); + m_CurValue = m_EndValue; + } + return m_CurValue.get(); +} + +template<> +LLVector4 LLTweenableValueLerp<LLVector4>::get() +{ + if (!m_CurValue) + { + float curFactor = (LLTimer::getElapsedSeconds() - m_StartTime) / m_Duration; + if (curFactor < 1.0) + return lerp(m_StartValue, m_EndValue, curFactor); + m_CurValue = m_EndValue; + } + return m_CurValue.get(); +} + +// ============================================================================ +// LLVfxManager class +// + +LLVfxManager::LLVfxManager() +{ + +} + +bool LLVfxManager::addEffect(LLVisualEffect* pEffectInst) +{ + if (m_Effects.end() != m_Effects.find(pEffectInst)) + return false; + + m_Effects.insert(pEffectInst); + + return true; +} + +LLVisualEffect* LLVfxManager::getEffect(const LLUUID& idEffect) const +{ + auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [&idEffect](const LLVisualEffect* pEffect) { return pEffect->getId() == idEffect; }); + return (m_Effects.end() != itEffect) ? *itEffect : nullptr; +} + +LLVisualEffect* LLVfxManager::getEffect(EVisualEffect eCode) const +{ + // NOTE: returns the first found but there could be more + auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [eCode](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode; }); + return (m_Effects.end() != itEffect) ? *itEffect : nullptr; +} + +bool LLVfxManager::removeEffect(const LLUUID& idEffect) +{ + auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [&idEffect](const LLVisualEffect* pEffect) { return pEffect->getId() == idEffect; }); + if (m_Effects.end() == itEffect) + return false; + + delete *itEffect; + m_Effects.erase(itEffect); + return true; +} + +void LLVfxManager::runEffect(EVisualEffect eCode) +{ + // *TODO-Catz: once we're done, check whether iterating over the entire list still has negliable impact + auto pred = [eCode](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode; }; + + auto beginEffect = boost::make_filter_iterator(pred, m_Effects.begin(), m_Effects.end()), + endEffect = boost::make_filter_iterator(pred, m_Effects.end(), m_Effects.end()); + + auto effectRange = boost::make_iterator_range(beginEffect, endEffect); + for (LLVisualEffect* pEffect : effectRange) + { + pEffect->run(); + } +} + +void LLVfxManager::runEffect(EVisualEffectType eType) +{ + // *TODO-Catz: once we're done, check whether iterating over the entire list still has negliable impact + auto pred = [eType](const LLVisualEffect* pEffect) { return pEffect->getType() == eType; }; + + auto beginEffect = boost::make_filter_iterator(pred, m_Effects.begin(), m_Effects.end()), + endEffect = boost::make_filter_iterator(pred, m_Effects.end(), m_Effects.end()); + + auto effectRange = boost::make_iterator_range(beginEffect, endEffect); + for (LLVisualEffect* pEffect : effectRange) + { + pEffect->run(); + } +} + +// ============================================================================ diff --git a/indra/newview/llvisualeffect.h b/indra/newview/llvisualeffect.h new file mode 100644 index 0000000000000000000000000000000000000000..86f3ab56c7bad2ad1742a06981fc944321209935 --- /dev/null +++ b/indra/newview/llvisualeffect.h @@ -0,0 +1,153 @@ +/** + * + * 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 "llsingleton.h" + +// ============================================================================ +// +// + +enum class EVisualEffect +{ + RlvOverlay, + RlvSphere, +}; + +enum class EVisualEffectType +{ + PostProcessShader, + Custom, +}; + +// ============================================================================ +// +// + +class LLVisualEffect +{ +public: + LLVisualEffect(LLUUID id, EVisualEffect eCode, EVisualEffectType eType) + : m_id(id), m_eCode(eCode), m_eType(eType) + {} + virtual ~LLVisualEffect() {} + + EVisualEffect getCode() const { return m_eCode;} + const LLUUID& getId() const { return m_id;} + U32 getPriority() const { return m_nPriority; } + EVisualEffectType getType() const { return m_eType;} + + virtual void run() = 0; + + /* + * Member variables + */ +protected: + LLUUID m_id; + EVisualEffect m_eCode; + EVisualEffectType m_eType; + U32 m_nPriority; +}; + +// ============================================================================ +// +// + +enum class LLTweenType +{ + None, + Lerp, +}; + +template<typename T> +class LLTweenableValue +{ +public: + LLTweenableValue(const T& defaultValue) : m_CurValue(defaultValue) {} + virtual ~LLTweenableValue() {} + + virtual T get() = 0; + virtual void start(const T& endValue, double duration) = 0; + + T& operator =(const T& value) { m_CurValue = value; } + + /* + * Member variables + */ +protected: + boost::optional<T> m_CurValue; +}; + +template<typename T> +class LLTweenableValueLerp : public LLTweenableValue<T> +{ +public: + LLTweenableValueLerp(const T& defaultValue) : LLTweenableValue(defaultValue) {} + + T get() override; + void start(const T& endValue, double duration) override + { + m_StartValue = get(); + m_CurValue = boost::none; + m_EndValue = endValue; + + m_StartTime = LLTimer::getElapsedSeconds(); + m_Duration = duration; + } + + /* + * Member variables + */ +protected: + double m_StartTime; + double m_Duration; + T m_StartValue; + T m_EndValue; +}; + +// ============================================================================ +// +// + +class LLVfxManager : public LLSingleton<LLVfxManager> +{ + LLSINGLETON(LLVfxManager); +protected: + ~LLVfxManager() {} + + /* + * Member functions + */ +public: + bool addEffect(LLVisualEffect* pEffectInst); + LLVisualEffect* getEffect(const LLUUID& idEffect) const; + template<typename T> T* getEffect(const LLUUID& idEffect) const { return dynamic_cast<T*>(getEffect(idEffect)); } + LLVisualEffect* getEffect(EVisualEffect eCode) const; + template<typename T> T* getEffect(EVisualEffect eCode) const { return dynamic_cast<T*>(getEffect(eCode)); } + bool removeEffect(const LLUUID& idEffect); + void runEffect(EVisualEffect eCode); + void runEffect(EVisualEffectType eType); +protected: + + /* + * Member variables + */ +protected: + std::set<LLVisualEffect*> m_Effects; +}; + +// ============================================================================