Use the StateSetUpdater to modify alpha for Animation objects (bug #5001)

pull/2355/head
Andrei Kortunov 5 years ago
parent ed859c41be
commit 5876a417c3

@ -83,6 +83,7 @@
Bug #4989: Object dimension-dependent VFX scaling behavior is inconsistent
Bug #4990: Dead bodies prevent you from hitting
Bug #4999: Drop instruction behaves differently from vanilla
Bug #5001: Possible data race in the Animation::setAlpha()
Bug #5004: Werewolves shield their eyes during storm
Feature #1774: Handle AvoidNode
Feature #2229: Improve pathfinding AI

@ -460,6 +460,46 @@ namespace
namespace MWRender
{
class TransparencyUpdater : public SceneUtil::StateSetUpdater
{
public:
TransparencyUpdater(const float alpha)
: mAlpha(alpha)
{
}
void setAlpha(const float alpha)
{
mAlpha = alpha;
}
protected:
virtual void setDefaults(osg::StateSet* stateset)
{
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
osg::BlendFunc* blendfunc (new osg::BlendFunc);
stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// FIXME: overriding diffuse/ambient/emissive colors
material = new osg::Material;
material->setColorMode(osg::Material::OFF);
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,mAlpha));
material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/)
{
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
material->setAlpha(osg::Material::FRONT_AND_BACK, mAlpha);
}
private:
float mAlpha;
};
class GlowUpdater : public SceneUtil::StateSetUpdater
{
public:
@ -1772,32 +1812,21 @@ namespace MWRender
return;
mAlpha = alpha;
// TODO: we use it to fade actors away too, but it would be nice to have a dithering shader instead.
if (alpha != 1.f)
{
// If we have an existing material for alpha transparency, just override alpha level
osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet();
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
if (material)
if (mTransparencyUpdater == nullptr)
{
material->setAlpha(osg::Material::FRONT_AND_BACK, alpha);
mTransparencyUpdater = new TransparencyUpdater(alpha);
mObjectRoot->addUpdateCallback(mTransparencyUpdater);
}
else
{
osg::BlendFunc* blendfunc (new osg::BlendFunc);
stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// FIXME: overriding diffuse/ambient/emissive colors
material = new osg::Material;
material->setColorMode(osg::Material::OFF);
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,alpha));
material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
mObjectRoot->setStateSet(stateset);
}
mTransparencyUpdater->setAlpha(alpha);
}
else
{
mObjectRoot->removeUpdateCallback(mTransparencyUpdater);
mTransparencyUpdater = nullptr;
mObjectRoot->setStateSet(nullptr);
}

@ -35,6 +35,7 @@ namespace MWRender
class ResetAccumRootCallback;
class RotateController;
class GlowUpdater;
class TransparencyUpdater;
class EffectAnimationTime : public SceneUtil::ControllerSource
{
@ -266,6 +267,7 @@ protected:
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
osg::ref_ptr<GlowUpdater> mGlowUpdater;
osg::ref_ptr<TransparencyUpdater> mTransparencyUpdater;
float mAlpha;

Loading…
Cancel
Save