mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-03 16:45:33 +00:00
1893617ec9
The pointer to the LightListCallback is now stored in the Animation, which eliminates the need for dynamic_cast. Also, when the object root is recreated, the previously used LightListCallback will be reused, so we no longer need the objectRootReset() notifier. Finally, there was a bug when saving and reloading the game, the getIgnoredLightSources() were not being set, as the ActorAnimation constructor completes before the NpcAnimation sets the ObjectRoot. This was solved by creating the LightListCallback in advance in the Animation constructor.
130 lines
4.5 KiB
C++
130 lines
4.5 KiB
C++
#include "actoranimation.hpp"
|
|
|
|
#include <utility>
|
|
|
|
#include <osg/Node>
|
|
#include <osg/Group>
|
|
#include <osg/Vec4f>
|
|
|
|
#include <components/esm/loadligh.hpp>
|
|
#include <components/esm/loadcell.hpp>
|
|
|
|
#include <components/sceneutil/lightmanager.hpp>
|
|
#include <components/sceneutil/lightutil.hpp>
|
|
|
|
#include <components/fallback/fallback.hpp>
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
#include "../mwworld/ptr.hpp"
|
|
#include "../mwworld/class.hpp"
|
|
#include "../mwworld/cellstore.hpp"
|
|
|
|
#include "vismask.hpp"
|
|
|
|
namespace MWRender
|
|
{
|
|
|
|
ActorAnimation::ActorAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem,
|
|
bool disableListener)
|
|
: Animation(ptr, parentNode, resourceSystem),
|
|
mListenerDisabled(disableListener)
|
|
{
|
|
MWWorld::ContainerStore& store = mPtr.getClass().getContainerStore(mPtr);
|
|
|
|
for (MWWorld::ContainerStoreIterator iter = store.begin(MWWorld::ContainerStore::Type_Light); iter != store.end(); ++iter)
|
|
{
|
|
const ESM::Light* light = iter->get<ESM::Light>()->mBase;
|
|
if (!(light->mData.mFlags & ESM::Light::Carry))
|
|
{
|
|
addHiddenItemLight(*iter, light);
|
|
}
|
|
}
|
|
|
|
if (!mListenerDisabled)
|
|
store.setContListener(this);
|
|
}
|
|
|
|
ActorAnimation::~ActorAnimation()
|
|
{
|
|
if (!mListenerDisabled && mPtr.getRefData().getCustomData() && mPtr.getClass().getContainerStore(mPtr).getContListener() == this)
|
|
mPtr.getClass().getContainerStore(mPtr).setContListener(NULL);
|
|
|
|
for (ItemLightMap::iterator iter = mItemLights.begin(); iter != mItemLights.end(); ++iter)
|
|
{
|
|
mInsert->removeChild(iter->second);
|
|
}
|
|
}
|
|
|
|
void ActorAnimation::itemAdded(const MWWorld::ConstPtr& item, int /*count*/)
|
|
{
|
|
if (item.getTypeName() == typeid(ESM::Light).name())
|
|
{
|
|
const ESM::Light* light = item.get<ESM::Light>()->mBase;
|
|
if (!(light->mData.mFlags & ESM::Light::Carry))
|
|
{
|
|
addHiddenItemLight(item, light);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActorAnimation::itemRemoved(const MWWorld::ConstPtr& item, int /*count*/)
|
|
{
|
|
if (item.getTypeName() == typeid(ESM::Light).name())
|
|
{
|
|
ItemLightMap::iterator iter = mItemLights.find(item);
|
|
if (iter != mItemLights.end())
|
|
{
|
|
if (!item.getRefData().getCount())
|
|
{
|
|
removeHiddenItemLight(item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActorAnimation::addHiddenItemLight(const MWWorld::ConstPtr& item, const ESM::Light* esmLight)
|
|
{
|
|
if (mItemLights.find(item) != mItemLights.end())
|
|
return;
|
|
|
|
const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
|
static bool outQuadInLin = fallback->getFallbackBool("LightAttenuation_OutQuadInLin");
|
|
static bool useQuadratic = fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
|
static float quadraticValue = fallback->getFallbackFloat("LightAttenuation_QuadraticValue");
|
|
static float quadraticRadiusMult = fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
|
static bool useLinear = fallback->getFallbackBool("LightAttenuation_UseLinear");
|
|
static float linearRadiusMult = fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
|
static float linearValue = fallback->getFallbackFloat("LightAttenuation_LinearValue");
|
|
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
|
|
|
|
osg::Vec4f ambient(1,1,1,1);
|
|
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, outQuadInLin,
|
|
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue, ambient);
|
|
|
|
mInsert->addChild(lightSource);
|
|
|
|
if (SceneUtil::LightListCallback* callback = mLightListCallback)
|
|
callback->getIgnoredLightSources().insert(lightSource.get());
|
|
|
|
mItemLights.insert(std::make_pair(item, lightSource));
|
|
}
|
|
|
|
void ActorAnimation::removeHiddenItemLight(const MWWorld::ConstPtr& item)
|
|
{
|
|
ItemLightMap::iterator iter = mItemLights.find(item);
|
|
if (iter == mItemLights.end())
|
|
return;
|
|
|
|
if (SceneUtil::LightListCallback* callback = mLightListCallback)
|
|
{
|
|
std::set<SceneUtil::LightSource*>::iterator ignoredIter = callback->getIgnoredLightSources().find(iter->second.get());
|
|
if (ignoredIter != callback->getIgnoredLightSources().end())
|
|
callback->getIgnoredLightSources().erase(ignoredIter);
|
|
}
|
|
|
|
mInsert->removeChild(iter->second);
|
|
mItemLights.erase(iter);
|
|
}
|
|
|
|
}
|