1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 18:35:20 +00:00

Add particle and sound fading for weather transitions (Fixes #2130)

This commit is contained in:
scrawl 2014-12-01 20:31:33 +01:00
parent b9d0552166
commit fadbb5ad21
3 changed files with 94 additions and 44 deletions

View File

@ -34,6 +34,41 @@
using namespace MWRender; using namespace MWRender;
using namespace Ogre; using namespace Ogre;
namespace
{
void setAlpha (NifOgre::ObjectScenePtr scene, Ogre::MovableObject* movable, float alpha)
{
Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(movable);
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
Ogre::ColourValue diffuse = pass->getDiffuse();
diffuse.a = alpha;
pass->setDiffuse(diffuse);
}
}
}
void setAlpha (NifOgre::ObjectScenePtr scene, float alpha)
{
for(size_t i = 0; i < scene->mParticles.size(); ++i)
setAlpha(scene, scene->mParticles[i], alpha);
for(size_t i = 0; i < scene->mEntities.size(); ++i)
{
if (scene->mEntities[i] != scene->mSkelBase)
setAlpha(scene, scene->mEntities[i], alpha);
}
}
}
BillboardObject::BillboardObject( const String& textureName, BillboardObject::BillboardObject( const String& textureName,
const float initialSize, const float initialSize,
const Vector3& position, const Vector3& position,
@ -660,6 +695,11 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
mSun->setVisibility(weather.mGlareView * strength); mSun->setVisibility(weather.mGlareView * strength);
mAtmosphereNight->setVisible(weather.mNight && mEnabled); mAtmosphereNight->setVisible(weather.mNight && mEnabled);
if (mParticle.get())
setAlpha(mParticle, weather.mEffectFade);
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end(); ++it)
setAlpha(it->second, weather.mEffectFade);
} }
void SkyManager::setGlare(const float glare) void SkyManager::setGlare(const float glare)

View File

@ -6,6 +6,8 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwsound/sound.hpp"
#include "../mwrender/renderingmanager.hpp" #include "../mwrender/renderingmanager.hpp"
#include "player.hpp" #include "player.hpp"
@ -152,12 +154,12 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa
setFallbackWeather(foggy,"foggy"); setFallbackWeather(foggy,"foggy");
Weather thunderstorm; Weather thunderstorm;
thunderstorm.mRainLoopSoundID = "rain heavy"; thunderstorm.mAmbientLoopSoundID = "rain heavy";
thunderstorm.mRainEffect = "meshes\\raindrop.nif"; thunderstorm.mRainEffect = "meshes\\raindrop.nif";
setFallbackWeather(thunderstorm,"thunderstorm"); setFallbackWeather(thunderstorm,"thunderstorm");
Weather rain; Weather rain;
rain.mRainLoopSoundID = "rain"; rain.mAmbientLoopSoundID = "rain";
rain.mRainEffect = "meshes\\raindrop.nif"; rain.mRainEffect = "meshes\\raindrop.nif";
setFallbackWeather(rain,"rain"); setFallbackWeather(rain,"rain");
@ -186,7 +188,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa
WeatherManager::~WeatherManager() WeatherManager::~WeatherManager()
{ {
stopSounds(true); stopSounds();
} }
void WeatherManager::setWeather(const String& weather, bool instant) void WeatherManager::setWeather(const String& weather, bool instant)
@ -228,6 +230,8 @@ void WeatherManager::setResult(const String& weatherType)
mResult.mCloudSpeed = current.mCloudSpeed; mResult.mCloudSpeed = current.mCloudSpeed;
mResult.mGlareView = current.mGlareView; mResult.mGlareView = current.mGlareView;
mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
mResult.mAmbientSoundVolume = 1.f;
mResult.mEffectFade = 1.f;
mResult.mSunColor = current.mSunDiscSunsetColor; mResult.mSunColor = current.mSunDiscSunsetColor;
mResult.mIsStorm = current.mIsStorm; mResult.mIsStorm = current.mIsStorm;
@ -341,11 +345,30 @@ void WeatherManager::transition(float factor)
mResult.mNight = current.mNight; mResult.mNight = current.mNight;
mResult.mIsStorm = current.mIsStorm; if (factor < 0.5)
mResult.mParticleEffect = current.mParticleEffect; {
mResult.mRainEffect = current.mRainEffect; mResult.mIsStorm = current.mIsStorm;
mResult.mRainSpeed = current.mRainSpeed; mResult.mParticleEffect = current.mParticleEffect;
mResult.mRainFrequency = current.mRainFrequency; mResult.mRainEffect = current.mRainEffect;
mResult.mParticleEffect = current.mParticleEffect;
mResult.mRainSpeed = current.mRainSpeed;
mResult.mRainFrequency = current.mRainFrequency;
mResult.mAmbientSoundVolume = 1-(factor*2);
mResult.mEffectFade = mResult.mAmbientSoundVolume;
mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
}
else
{
mResult.mIsStorm = other.mIsStorm;
mResult.mParticleEffect = other.mParticleEffect;
mResult.mRainEffect = other.mRainEffect;
mResult.mParticleEffect = other.mParticleEffect;
mResult.mRainSpeed = other.mRainSpeed;
mResult.mRainFrequency = other.mRainFrequency;
mResult.mAmbientSoundVolume = 2*(factor-0.5);
mResult.mEffectFade = mResult.mAmbientSoundVolume;
mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID;
}
} }
void WeatherManager::update(float duration, bool paused) void WeatherManager::update(float duration, bool paused)
@ -361,7 +384,7 @@ void WeatherManager::update(float duration, bool paused)
{ {
mRendering->skyDisable(); mRendering->skyDisable();
mRendering->getSkyManager()->setLightningStrength(0.f); mRendering->getSkyManager()->setLightningStrength(0.f);
stopSounds(true); stopSounds();
return; return;
} }
@ -541,40 +564,25 @@ void WeatherManager::update(float duration, bool paused)
mRendering->getSkyManager()->setWeather(mResult); mRendering->getSkyManager()->setWeather(mResult);
// Play sounds // Play sounds
if (mNextWeather == "") if (mPlayingSoundID != mResult.mAmbientLoopSoundID)
{ {
std::string ambientSnd = mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID; stopSounds();
if (!ambientSnd.empty() && std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), ambientSnd) == mSoundsPlaying.end()) if (!mResult.mAmbientLoopSoundID.empty())
{ mAmbientSound = MWBase::Environment::get().getSoundManager()->playSound(mResult.mAmbientLoopSoundID, 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
mSoundsPlaying.push_back(ambientSnd);
MWBase::Environment::get().getSoundManager()->playSound(ambientSnd, 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
}
std::string rainSnd = mWeatherSettings[mCurrentWeather].mRainLoopSoundID; mPlayingSoundID = mResult.mAmbientLoopSoundID;
if (!rainSnd.empty() && std::find(mSoundsPlaying.begin(), mSoundsPlaying.end(), rainSnd) == mSoundsPlaying.end())
{
mSoundsPlaying.push_back(rainSnd);
MWBase::Environment::get().getSoundManager()->playSound(rainSnd, 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
}
} }
if (mAmbientSound.get())
stopSounds(false); mAmbientSound->setVolume(mResult.mAmbientSoundVolume);
} }
void WeatherManager::stopSounds(bool stopAll) void WeatherManager::stopSounds()
{ {
std::vector<std::string>::iterator it = mSoundsPlaying.begin(); if (mAmbientSound.get())
while (it!=mSoundsPlaying.end())
{ {
if (stopAll || MWBase::Environment::get().getSoundManager()->stopSound(mAmbientSound);
!((*it == mWeatherSettings[mCurrentWeather].mAmbientLoopSoundID) || mAmbientSound.reset();
(*it == mWeatherSettings[mCurrentWeather].mRainLoopSoundID))) mPlayingSoundID.clear();
{
MWBase::Environment::get().getSoundManager()->stopSound(*it);
it = mSoundsPlaying.erase(it);
}
else
++it;
} }
} }
@ -764,7 +772,7 @@ bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type)
state.load(reader); state.load(reader);
// reset other temporary state, now that we loaded successfully // reset other temporary state, now that we loaded successfully
stopSounds(true); // let's hope this never throws stopSounds(); // let's hope this never throws
mRegionOverrides.clear(); mRegionOverrides.clear();
mRegionMods.clear(); mRegionMods.clear();
mThunderFlash = 0.0; mThunderFlash = 0.0;

View File

@ -7,6 +7,8 @@
#include <OgreColourValue.h> #include <OgreColourValue.h>
#include <OgreVector3.h> #include <OgreVector3.h>
#include "../mwbase/soundmanager.hpp"
namespace ESM namespace ESM
{ {
struct Region; struct Region;
@ -61,10 +63,12 @@ namespace MWWorld
bool mIsStorm; bool mIsStorm;
std::string mAmbientLoopSoundID; std::string mAmbientLoopSoundID;
float mAmbientSoundVolume;
std::string mParticleEffect; std::string mParticleEffect;
std::string mRainEffect; std::string mRainEffect;
float mEffectFade;
float mRainSpeed; float mRainSpeed;
float mRainFrequency; float mRainFrequency;
}; };
@ -125,9 +129,6 @@ namespace MWWorld
// This is used for Blight, Ashstorm and Blizzard (Bloodmoon) // This is used for Blight, Ashstorm and Blizzard (Bloodmoon)
std::string mAmbientLoopSoundID; std::string mAmbientLoopSoundID;
// Rain sound effect
std::string mRainLoopSoundID;
// Is this an ash storm / blight storm? If so, the following will happen: // Is this an ash storm / blight storm? If so, the following will happen:
// - The particles and clouds will be oriented so they appear to come from the Red Mountain. // - The particles and clouds will be oriented so they appear to come from the Red Mountain.
// - Characters will animate their hand to protect eyes from the storm when looking in its direction (idlestorm animation) // - Characters will animate their hand to protect eyes from the storm when looking in its direction (idlestorm animation)
@ -173,7 +174,7 @@ namespace MWWorld
*/ */
void update(float duration, bool paused = false); void update(float duration, bool paused = false);
void stopSounds(bool stopAll); void stopSounds();
void setHour(const float hour); void setHour(const float hour);
@ -206,6 +207,9 @@ namespace MWWorld
bool mIsStorm; bool mIsStorm;
Ogre::Vector3 mStormDirection; Ogre::Vector3 mStormDirection;
MWBase::SoundPtr mAmbientSound;
std::string mPlayingSoundID;
MWWorld::Fallback* mFallback; MWWorld::Fallback* mFallback;
void setFallbackWeather(Weather& weather,const std::string& name); void setFallbackWeather(Weather& weather,const std::string& name);
MWRender::RenderingManager* mRendering; MWRender::RenderingManager* mRendering;
@ -214,8 +218,6 @@ namespace MWWorld
std::map<std::string, std::string> mRegionOverrides; std::map<std::string, std::string> mRegionOverrides;
std::vector<std::string> mSoundsPlaying;
std::string mCurrentWeather; std::string mCurrentWeather;
std::string mNextWeather; std::string mNextWeather;