mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-06 17:15:35 +00:00
Merge pull request #2153 from akortunov/glowing_windows
Native glowing windows support
This commit is contained in:
commit
f4313c02e1
23 changed files with 179 additions and 8 deletions
|
@ -32,6 +32,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());
|
||||
|
@ -1933,6 +1976,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…
Reference in a new issue