Daytime node switch support (feature #4836)

pull/2153/head
Andrei Kortunov 6 years ago
parent a12f7702ad
commit 9e4a339ad3

@ -31,6 +31,7 @@
Feature #4673: Weapon sheathing
Feature #4730: Native animated containers support
Feature #4812: Support NiSwitchNode
Feature #4836: Daytime node switch
Task #4686: Upgrade media decoder to a more current FFmpeg API
0.45.0

@ -1,5 +1,38 @@
#include "lighting.hpp"
#include <osg/LightSource>
#include <osg/NodeVisitor>
#include <osg/Switch>
#include <components/misc/constants.hpp>
class DayNightSwitchVisitor : public osg::NodeVisitor
{
public:
DayNightSwitchVisitor(int index)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mIndex(index)
{ }
virtual void apply(osg::Switch &switchNode)
{
if (switchNode.getName() == Constants::NightDayLabel)
switchNode.setSingleChildOn(mIndex);
traverse(switchNode);
}
private:
int mIndex;
};
CSVRender::Lighting::~Lighting() {}
void CSVRender::Lighting::updateDayNightMode(int index)
{
if (mRootNode == nullptr)
return;
DayNightSwitchVisitor visitor(index);
mRootNode->accept(visitor);
}

@ -19,7 +19,7 @@ namespace CSVRender
Lighting() : mRootNode(0) {}
virtual ~Lighting();
virtual void activate (osg::Group* rootNode) = 0;
virtual void activate (osg::Group* rootNode, bool isExterior) = 0;
virtual void deactivate() = 0;
@ -27,6 +27,8 @@ namespace CSVRender
protected:
void updateDayNightMode(int index);
osg::ref_ptr<osg::LightSource> mLightSource;
osg::Group* mRootNode;
};

@ -4,7 +4,7 @@
CSVRender::LightingBright::LightingBright() {}
void CSVRender::LightingBright::activate (osg::Group* rootNode)
void CSVRender::LightingBright::activate (osg::Group* rootNode, bool /*isExterior*/)
{
mRootNode = rootNode;
@ -20,6 +20,8 @@ void CSVRender::LightingBright::activate (osg::Group* rootNode)
mLightSource->setLight(light);
mRootNode->addChild(mLightSource);
updateDayNightMode(0);
}
void CSVRender::LightingBright::deactivate()

@ -17,7 +17,7 @@ namespace CSVRender
LightingBright();
virtual void activate (osg::Group* rootNode);
virtual void activate (osg::Group* rootNode, bool /*isExterior*/);
virtual void deactivate();

@ -4,7 +4,7 @@
CSVRender::LightingDay::LightingDay(){}
void CSVRender::LightingDay::activate (osg::Group* rootNode)
void CSVRender::LightingDay::activate (osg::Group* rootNode, bool /*isExterior*/)
{
mRootNode = rootNode;
@ -19,6 +19,8 @@ void CSVRender::LightingDay::activate (osg::Group* rootNode)
mLightSource->setLight(light);
mRootNode->addChild(mLightSource);
updateDayNightMode(0);
}
void CSVRender::LightingDay::deactivate()

@ -11,7 +11,7 @@ namespace CSVRender
LightingDay();
virtual void activate (osg::Group* rootNode);
virtual void activate (osg::Group* rootNode, bool /*isExterior*/);
virtual void deactivate();

@ -4,7 +4,7 @@
CSVRender::LightingNight::LightingNight() {}
void CSVRender::LightingNight::activate (osg::Group* rootNode)
void CSVRender::LightingNight::activate (osg::Group* rootNode, bool isExterior)
{
mRootNode = rootNode;
@ -20,6 +20,8 @@ void CSVRender::LightingNight::activate (osg::Group* rootNode)
mLightSource->setLight(light);
mRootNode->addChild(mLightSource);
updateDayNightMode(isExterior ? 1 : 0);
}
void CSVRender::LightingNight::deactivate()

@ -11,7 +11,7 @@ namespace CSVRender
LightingNight();
virtual void activate (osg::Group* rootNode);
virtual void activate (osg::Group* rootNode, bool isExterior);
virtual void deactivate();
virtual osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient);

@ -20,6 +20,8 @@ CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
connect (&mData, SIGNAL (assetTablesChanged ()),
this, SLOT (assetTablesChanged ()));
setExterior(false);
if (!referenceable)
{
QAbstractItemModel *references =

@ -195,6 +195,7 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
, mResourceSystem(resourceSystem)
, mLighting(nullptr)
, mHasDefaultAmbient(false)
, mIsExterior(true)
, mPrevMouseX(0)
, mPrevMouseY(0)
, mCamPositionSet(false)
@ -250,7 +251,7 @@ void SceneWidget::setLighting(Lighting *lighting)
mLighting->deactivate();
mLighting = lighting;
mLighting->activate (mRootNode);
mLighting->activate (mRootNode, mIsExterior);
osg::Vec4f ambient = mLighting->getAmbientColour(mHasDefaultAmbient ? &mDefaultAmbient : 0);
setAmbient(ambient);
@ -315,6 +316,11 @@ void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour)
setAmbient(mLighting->getAmbientColour(&mDefaultAmbient));
}
void SceneWidget::setExterior (bool isExterior)
{
mIsExterior = isExterior;
}
void SceneWidget::mouseMoveEvent (QMouseEvent *event)
{
mCurrentCamControl->handleMouseMoveEvent(event->x() - mPrevMouseX, event->y() - mPrevMouseY);

@ -89,6 +89,8 @@ namespace CSVRender
void setDefaultAmbient (const osg::Vec4f& colour);
///< \note The actual ambient colour may differ based on lighting settings.
void setExterior (bool isExterior);
protected:
void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this.
@ -104,6 +106,7 @@ namespace CSVRender
osg::Vec4f mDefaultAmbient;
bool mHasDefaultAmbient;
bool mIsExterior;
LightingDay mLightingDay;
LightingNight mLightingNight;
LightingBright mLightingBright;

@ -28,6 +28,11 @@ void CSVRender::UnpagedWorldspaceWidget::update()
setDefaultAmbient (colour);
bool isInterior = (record.get().mData.mFlags & ESM::Cell::Interior) != 0;
bool behaveLikeExterior = (record.get().mData.mFlags & ESM::Cell::QuasiEx) != 0;
setExterior(behaveLikeExterior || !isInterior);
/// \todo deal with mSunlight and mFog/mForDensity
flagAsModified();

@ -226,6 +226,8 @@ namespace MWBase
virtual int getCurrentWeather() const = 0;
virtual unsigned int getNightDayMode() const = 0;
virtual int getMasserPhase() const = 0;
virtual int getSecundaPhase() const = 0;

@ -9,6 +9,7 @@
#include <osg/BlendFunc>
#include <osg/Material>
#include <osg/PositionAttitudeTransform>
#include <osg/Switch>
#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleProcessor>
@ -33,6 +34,7 @@
#include <components/sceneutil/lightutil.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/util.hpp>
#include <components/settings/settings.hpp>
@ -91,6 +93,47 @@ namespace
std::vector<osg::ref_ptr<osg::Node> > mToRemove;
};
class DayNightCallback : public osg::NodeCallback
{
public:
DayNightCallback() : mCurrentState(0)
{
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
unsigned int state = MWBase::Environment::get().getWorld()->getNightDayMode();
const unsigned int newState = node->asGroup()->getNumChildren() > state ? state : 0;
if (newState != mCurrentState)
{
mCurrentState = newState;
node->asSwitch()->setSingleChildOn(mCurrentState);
}
traverse(node, nv);
}
private:
unsigned int mCurrentState;
};
class AddSwitchCallbacksVisitor : public osg::NodeVisitor
{
public:
AddSwitchCallbacksVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{ }
virtual void apply(osg::Switch &switchNode)
{
if (switchNode.getName() == Constants::NightDayLabel)
switchNode.addUpdateCallback(new DayNightCallback());
traverse(switchNode);
}
};
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
{
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
@ -1934,6 +1977,12 @@ namespace MWRender
mObjectRoot->accept(visitor);
visitor.remove();
}
if (SceneUtil::hasUserDescription(mObjectRoot, Constants::NightDayLabel))
{
AddSwitchCallbacksVisitor visitor;
mObjectRoot->accept(visitor);
}
}
Animation::AnimState::~AnimState()

@ -547,6 +547,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall
, mFastForward(false)
, mWeatherUpdateTime(mHoursBetweenWeatherChanges)
, mTransitionFactor(0)
, mNightDayMode(Default)
, mCurrentWeather(0)
, mNextWeather(0)
, mQueuedWeather(0)
@ -683,6 +684,14 @@ void WeatherManager::update(float duration, bool paused, const TimeStamp& time,
updateWeatherTransitions(duration);
}
bool isDay = time.getHour() >= mSunriseTime && time.getHour() <= mTimeSettings.mNightStart;
if (isExterior && !isDay)
mNightDayMode = ExteriorNight;
else if (!isExterior && isDay && mWeatherSettings[mCurrentWeather].mGlareView >= 0.5f)
mNightDayMode = InteriorDay;
else
mNightDayMode = Default;
if(!isExterior)
{
mRendering.setSkyEnabled(false);
@ -823,6 +832,11 @@ unsigned int WeatherManager::getWeatherID() const
return mCurrentWeather;
}
NightDayMode WeatherManager::getNightDayMode() const
{
return mNightDayMode;
}
bool WeatherManager::useTorches(float hour) const
{
bool isDark = hour < mSunriseTime || hour > mTimeSettings.mNightStart;

@ -40,6 +40,13 @@ namespace MWWorld
{
class TimeStamp;
enum NightDayMode
{
Default = 0,
ExteriorNight = 1,
InteriorDay = 2
};
struct WeatherSetting
{
float mPreSunriseTime;
@ -277,6 +284,7 @@ namespace MWWorld
void stopSounds();
float getWindSpeed() const;
NightDayMode getNightDayMode() const;
/// Are we in an ash or blight storm?
bool isInStorm() const;
@ -329,6 +337,7 @@ namespace MWWorld
bool mFastForward;
float mWeatherUpdateTime;
float mTransitionFactor;
NightDayMode mNightDayMode;
int mCurrentWeather;
int mNextWeather;
int mQueuedWeather;

@ -2024,6 +2024,11 @@ namespace MWWorld
return mWeatherManager->getWeatherID();
}
unsigned int World::getNightDayMode() const
{
return mWeatherManager->getNightDayMode();
}
void World::changeWeather(const std::string& region, const unsigned int id)
{
mWeatherManager->changeWeather(region, id);

@ -337,6 +337,8 @@ namespace MWWorld
int getCurrentWeather() const override;
unsigned int getNightDayMode() const override;
int getMasserPhase() const override;
int getSecundaPhase() const override;

@ -1,6 +1,8 @@
#ifndef OPENMW_CONSTANTS_H
#define OPENMW_CONSTANTS_H
#include <string>
namespace Constants
{
@ -22,6 +24,9 @@ const float GravityConst = 8.96f;
// Size of one exterior cell in game units
const int CellSizeInUnits = 8192;
// A label to mark night/day visual switches
const std::string NightDayLabel = "NightDaySwitch";
}
#endif

@ -11,9 +11,11 @@
// resource
#include <components/debug/debuglog.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/stringops.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/sceneutil/util.hpp>
// particle
#include <osgParticle/ParticleSystem>
@ -608,6 +610,10 @@ namespace NifOsg
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
osg::ref_ptr<osg::Switch> switchNode = handleSwitchNode(niSwitchNode);
node->addChild(switchNode);
if (niSwitchNode->name == Constants::NightDayLabel && !SceneUtil::hasUserDescription(rootNode, Constants::NightDayLabel))
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::NightDayLabel);
const Nif::NodeList &children = niSwitchNode->children;
for(size_t i = 0;i < children.length();++i)
{

@ -1,5 +1,7 @@
#include "util.hpp"
#include <osg/Node>
namespace SceneUtil
{
@ -53,4 +55,22 @@ float makeOsgColorComponent(unsigned int value, unsigned int shift)
return float((value >> shift) & 0xFFu) / 255.0f;
}
bool hasUserDescription(const osg::Node* node, const std::string pattern)
{
if (node == nullptr)
return false;
const osg::UserDataContainer* udc = node->getUserDataContainer();
if (udc && udc->getNumDescriptions() > 0)
{
for (auto& descr : udc->getDescriptions())
{
if (descr == pattern)
return true;
}
}
return false;
}
}

@ -19,6 +19,7 @@ namespace SceneUtil
float makeOsgColorComponent (unsigned int value, unsigned int shift);
bool hasUserDescription(const osg::Node* node, const std::string pattern);
}
#endif

Loading…
Cancel
Save