mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-23 16:09:45 +00:00
Merge pull request #1001 from Allofich/traps
Make non-actors play spell cast visuals and sounds
This commit is contained in:
commit
6b45a757a9
7 changed files with 231 additions and 79 deletions
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
#include "../mwrender/renderinginterface.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
@ -112,6 +113,20 @@ namespace MWClass
|
||||||
bool hasKey = false;
|
bool hasKey = false;
|
||||||
std::string keyName;
|
std::string keyName;
|
||||||
|
|
||||||
|
// make door glow if player activates it with telekinesis
|
||||||
|
if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr() &&
|
||||||
|
MWBase::Environment::get().getWorld()->getDistanceToFacedObject() >
|
||||||
|
MWBase::Environment::get().getWorld()->getMaxActivationDistance())
|
||||||
|
{
|
||||||
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
|
||||||
|
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis");
|
||||||
|
const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().find(index);
|
||||||
|
|
||||||
|
animation->addSpellCastGlow(effect); // TODO: Telekinesis glow should only be as long as the door animation
|
||||||
|
}
|
||||||
|
|
||||||
// make key id lowercase
|
// make key id lowercase
|
||||||
std::string keyId = ptr.getCellRef().getKey();
|
std::string keyId = ptr.getCellRef().getKey();
|
||||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
Misc::StringUtils::lowerCaseInPlace(keyId);
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
#include "security.hpp"
|
#include "security.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -961,34 +962,6 @@ void CharacterController::updateIdleStormState(bool inwater)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::castSpell(const std::string &spellid)
|
|
||||||
{
|
|
||||||
static const std::string schools[] = {
|
|
||||||
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
|
||||||
};
|
|
||||||
|
|
||||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
|
||||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
|
||||||
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
|
|
||||||
|
|
||||||
const ESM::MagicEffect *effect;
|
|
||||||
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID);
|
|
||||||
|
|
||||||
const ESM::Static* castStatic;
|
|
||||||
if (!effect->mCasting.empty())
|
|
||||||
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
|
||||||
else
|
|
||||||
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
|
||||||
|
|
||||||
mAnimation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex);
|
|
||||||
|
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
|
||||||
if(!effect->mCastSound.empty())
|
|
||||||
sndMgr->playSound3D(mPtr, effect->mCastSound, 1.0f, 1.0f);
|
|
||||||
else
|
|
||||||
sndMgr->playSound3D(mPtr, schools[effect->mData.mSchool]+" cast", 1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CharacterController::updateCreatureState()
|
bool CharacterController::updateCreatureState()
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = mPtr.getClass();
|
const MWWorld::Class &cls = mPtr.getClass();
|
||||||
|
@ -1020,7 +993,8 @@ bool CharacterController::updateCreatureState()
|
||||||
const std::string spellid = stats.getSpells().getSelectedSpell();
|
const std::string spellid = stats.getSpells().getSelectedSpell();
|
||||||
if (!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
|
if (!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
|
||||||
{
|
{
|
||||||
castSpell(spellid);
|
MWMechanics::CastSpell cast(mPtr, NULL);
|
||||||
|
cast.playSpellCastingEffects(spellid);
|
||||||
|
|
||||||
if (!mAnimation->hasAnimation("spellcast"))
|
if (!mAnimation->hasAnimation("spellcast"))
|
||||||
MWBase::Environment::get().getWorld()->castSpell(mPtr); // No "release" text key to use, so cast immediately
|
MWBase::Environment::get().getWorld()->castSpell(mPtr); // No "release" text key to use, so cast immediately
|
||||||
|
@ -1248,7 +1222,8 @@ bool CharacterController::updateWeaponState()
|
||||||
|
|
||||||
if(!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
|
if(!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
|
||||||
{
|
{
|
||||||
castSpell(spellid);
|
MWMechanics::CastSpell cast(mPtr, NULL);
|
||||||
|
cast.playSpellCastingEffects(spellid);
|
||||||
|
|
||||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||||
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
|
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
|
||||||
|
|
|
@ -214,8 +214,6 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
||||||
|
|
||||||
void updateHeadTracking(float duration);
|
void updateHeadTracking(float duration);
|
||||||
|
|
||||||
void castSpell(const std::string& spellid);
|
|
||||||
|
|
||||||
void updateMagicEffects();
|
void updateMagicEffects();
|
||||||
|
|
||||||
void playDeath(float startpoint, CharacterState death);
|
void playDeath(float startpoint, CharacterState death);
|
||||||
|
|
|
@ -574,6 +574,10 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (effectId == ESM::MagicEffect::Lock)
|
if (effectId == ESM::MagicEffect::Lock)
|
||||||
{
|
{
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
const ESM::MagicEffect *magiceffect = store.get<ESM::MagicEffect>().find(effectId);
|
||||||
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||||
|
animation->addSpellCastGlow(magiceffect);
|
||||||
if (target.getCellRef().getLockLevel() < magnitude) //If the door is not already locked to a higher value, lock it to spell magnitude
|
if (target.getCellRef().getLockLevel() < magnitude) //If the door is not already locked to a higher value, lock it to spell magnitude
|
||||||
{
|
{
|
||||||
if (caster == getPlayer())
|
if (caster == getPlayer())
|
||||||
|
@ -584,6 +588,10 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else if (effectId == ESM::MagicEffect::Open)
|
else if (effectId == ESM::MagicEffect::Open)
|
||||||
{
|
{
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
const ESM::MagicEffect *magiceffect = store.get<ESM::MagicEffect>().find(effectId);
|
||||||
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||||
|
animation->addSpellCastGlow(magiceffect);
|
||||||
if (target.getCellRef().getLockLevel() <= magnitude)
|
if (target.getCellRef().getLockLevel() <= magnitude)
|
||||||
{
|
{
|
||||||
if (target.getCellRef().getLockLevel() > 0)
|
if (target.getCellRef().getLockLevel() > 0)
|
||||||
|
@ -837,6 +845,10 @@ namespace MWMechanics
|
||||||
mCaster.getClass().skillUsageSucceeded(mCaster,
|
mCaster.getClass().skillUsageSucceeded(mCaster,
|
||||||
spellSchoolToSkill(school), 0);
|
spellSchoolToSkill(school), 0);
|
||||||
|
|
||||||
|
// A non-actor doesn't play its spell cast effects from a character controller, so play them here
|
||||||
|
if (!mCaster.getClass().isActor())
|
||||||
|
playSpellCastingEffects(mId);
|
||||||
|
|
||||||
inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self);
|
inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self);
|
||||||
|
|
||||||
if (!mTarget.isEmpty())
|
if (!mTarget.isEmpty())
|
||||||
|
@ -930,6 +942,42 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CastSpell::playSpellCastingEffects(const std::string &spellid){
|
||||||
|
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||||
|
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
|
||||||
|
|
||||||
|
const ESM::MagicEffect *effect;
|
||||||
|
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID);
|
||||||
|
|
||||||
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
||||||
|
|
||||||
|
if (mCaster.getClass().isActor()) // TODO: Non-actors (except for large statics?) should also create a spell cast vfx
|
||||||
|
{
|
||||||
|
const ESM::Static* castStatic;
|
||||||
|
if (!effect->mCasting.empty())
|
||||||
|
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
||||||
|
else
|
||||||
|
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
||||||
|
|
||||||
|
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mCaster.getClass().isActor())
|
||||||
|
animation->addSpellCastGlow(effect);
|
||||||
|
|
||||||
|
static const std::string schools[] = {
|
||||||
|
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
||||||
|
};
|
||||||
|
|
||||||
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
if(!effect->mCastSound.empty())
|
||||||
|
sndMgr->playSound3D(mCaster, effect->mCastSound, 1.0f, 1.0f);
|
||||||
|
else
|
||||||
|
sndMgr->playSound3D(mCaster, schools[effect->mData.mSchool]+" cast", 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
int getEffectiveEnchantmentCastCost(float castCost, const MWWorld::Ptr &actor)
|
int getEffectiveEnchantmentCastCost(float castCost, const MWWorld::Ptr &actor)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -92,6 +92,8 @@ namespace MWMechanics
|
||||||
/// @note Auto detects if spell, ingredient or potion
|
/// @note Auto detects if spell, ingredient or potion
|
||||||
bool cast (const std::string& id);
|
bool cast (const std::string& id);
|
||||||
|
|
||||||
|
void playSpellCastingEffects(const std::string &spellid);
|
||||||
|
|
||||||
/// @note \a target can be any type of object, not just actors.
|
/// @note \a target can be any type of object, not just actors.
|
||||||
/// @note \a caster can be any type of object, or even an empty object.
|
/// @note \a caster can be any type of object, or even an empty object.
|
||||||
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
||||||
|
|
|
@ -86,48 +86,6 @@ namespace
|
||||||
std::vector<osg::ref_ptr<osg::Node> > mToRemove;
|
std::vector<osg::ref_ptr<osg::Node> > mToRemove;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlowUpdater : public SceneUtil::StateSetUpdater
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GlowUpdater(int texUnit, osg::Vec4f color, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures)
|
|
||||||
: mTexUnit(texUnit)
|
|
||||||
, mColor(color)
|
|
||||||
, mTextures(textures)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setDefaults(osg::StateSet *stateset)
|
|
||||||
{
|
|
||||||
stateset->setTextureMode(mTexUnit, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
|
||||||
|
|
||||||
osg::TexGen* texGen = new osg::TexGen;
|
|
||||||
texGen->setMode(osg::TexGen::SPHERE_MAP);
|
|
||||||
|
|
||||||
stateset->setTextureAttributeAndModes(mTexUnit, texGen, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
|
||||||
|
|
||||||
osg::TexEnvCombine* texEnv = new osg::TexEnvCombine;
|
|
||||||
texEnv->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
|
|
||||||
texEnv->setConstantColor(mColor);
|
|
||||||
texEnv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
|
|
||||||
texEnv->setSource2_RGB(osg::TexEnvCombine::TEXTURE);
|
|
||||||
texEnv->setOperand2_RGB(osg::TexEnvCombine::SRC_COLOR);
|
|
||||||
|
|
||||||
stateset->setTextureAttributeAndModes(mTexUnit, texEnv, osg::StateAttribute::ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
|
||||||
{
|
|
||||||
float time = nv->getFrameStamp()->getSimulationTime();
|
|
||||||
int index = (int)(time*16) % mTextures.size();
|
|
||||||
stateset->setTextureAttribute(mTexUnit, mTextures[index], osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int mTexUnit;
|
|
||||||
osg::Vec4f mColor;
|
|
||||||
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NodeMapVisitor : public osg::NodeVisitor
|
class NodeMapVisitor : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -289,6 +247,134 @@ namespace
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
class GlowUpdater : public SceneUtil::StateSetUpdater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GlowUpdater(int texUnit, osg::Vec4f color, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
|
||||||
|
osg::Node* node, float duration, Resource::ResourceSystem* resourcesystem)
|
||||||
|
: mTexUnit(texUnit)
|
||||||
|
, mColor(color)
|
||||||
|
, mOriginalColor(color)
|
||||||
|
, mTextures(textures)
|
||||||
|
, mNode(node)
|
||||||
|
, mDuration(duration)
|
||||||
|
, mOriginalDuration(duration)
|
||||||
|
, mStartingTime(0)
|
||||||
|
, mResourceSystem(resourcesystem)
|
||||||
|
, mColorChanged(false)
|
||||||
|
, mDone(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setDefaults(osg::StateSet *stateset)
|
||||||
|
{
|
||||||
|
if (mDone)
|
||||||
|
removeTexture(stateset);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stateset->setTextureMode(mTexUnit, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||||
|
osg::TexGen* texGen = new osg::TexGen;
|
||||||
|
texGen->setMode(osg::TexGen::SPHERE_MAP);
|
||||||
|
|
||||||
|
stateset->setTextureAttributeAndModes(mTexUnit, texGen, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||||
|
|
||||||
|
osg::TexEnvCombine* texEnv = new osg::TexEnvCombine;
|
||||||
|
texEnv->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
|
||||||
|
texEnv->setConstantColor(mColor);
|
||||||
|
texEnv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
|
||||||
|
texEnv->setSource2_RGB(osg::TexEnvCombine::TEXTURE);
|
||||||
|
texEnv->setOperand2_RGB(osg::TexEnvCombine::SRC_COLOR);
|
||||||
|
|
||||||
|
stateset->setTextureAttributeAndModes(mTexUnit, texEnv, osg::StateAttribute::ON);
|
||||||
|
stateset->addUniform(new osg::Uniform("envMapColor", mColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeTexture(osg::StateSet* stateset)
|
||||||
|
{
|
||||||
|
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXTURE);
|
||||||
|
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXGEN);
|
||||||
|
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXENV);
|
||||||
|
stateset->removeTextureMode(mTexUnit, GL_TEXTURE_2D);
|
||||||
|
stateset->removeUniform("envMapColor");
|
||||||
|
|
||||||
|
osg::StateSet::TextureAttributeList& list = stateset->getTextureAttributeList();
|
||||||
|
while (list.size() && list.rbegin()->empty())
|
||||||
|
list.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
|
{
|
||||||
|
if (mColorChanged){
|
||||||
|
this->reset();
|
||||||
|
setDefaults(stateset);
|
||||||
|
mColorChanged = false;
|
||||||
|
}
|
||||||
|
if (mDone)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set the starting time to measure glow duration from if this is a temporary glow
|
||||||
|
if ((mDuration >= 0) && mStartingTime == 0)
|
||||||
|
mStartingTime = nv->getFrameStamp()->getSimulationTime();
|
||||||
|
|
||||||
|
float time = nv->getFrameStamp()->getSimulationTime();
|
||||||
|
int index = (int)(time*16) % mTextures.size();
|
||||||
|
stateset->setTextureAttribute(mTexUnit, mTextures[index], osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||||
|
|
||||||
|
if ((mDuration >= 0) && (time - mStartingTime > mDuration)) // If this is a temporary glow and it has finished its duration
|
||||||
|
{
|
||||||
|
if (mOriginalDuration >= 0) // if this glowupdater was a temporary glow since its creation
|
||||||
|
{
|
||||||
|
removeTexture(stateset);
|
||||||
|
this->reset();
|
||||||
|
mDone = true;
|
||||||
|
mResourceSystem->getSceneManager()->recreateShaders(mNode);
|
||||||
|
}
|
||||||
|
if (mOriginalDuration < 0) // if this glowupdater was originally a permanent glow
|
||||||
|
{
|
||||||
|
mDuration = mOriginalDuration;
|
||||||
|
mStartingTime = 0;
|
||||||
|
mColor = mOriginalColor;
|
||||||
|
this->reset();
|
||||||
|
setDefaults(stateset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPermanentGlowUpdater()
|
||||||
|
{
|
||||||
|
return (mDuration < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDone()
|
||||||
|
{
|
||||||
|
return mDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setColor(osg::Vec4f color)
|
||||||
|
{
|
||||||
|
mColor = color;
|
||||||
|
mColorChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDuration(float duration)
|
||||||
|
{
|
||||||
|
mDuration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mTexUnit;
|
||||||
|
osg::Vec4f mColor;
|
||||||
|
osg::Vec4f mOriginalColor; // for restoring the color of a permanent glow after a temporary glow on the object finishes
|
||||||
|
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
||||||
|
osg::Node* mNode;
|
||||||
|
float mDuration;
|
||||||
|
float mOriginalDuration; // for recording that this is originally a permanent glow if it is changed to a temporary one
|
||||||
|
float mStartingTime;
|
||||||
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
bool mColorChanged;
|
||||||
|
bool mDone;
|
||||||
|
};
|
||||||
|
|
||||||
struct Animation::AnimSource
|
struct Animation::AnimSource
|
||||||
{
|
{
|
||||||
|
@ -1106,7 +1192,29 @@ namespace MWRender
|
||||||
int mLowestUnusedTexUnit;
|
int mLowestUnusedTexUnit;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Animation::addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor)
|
void Animation::addSpellCastGlow(const ESM::MagicEffect *effect)
|
||||||
|
{
|
||||||
|
osg::Vec4f glowColor(1,1,1,1);
|
||||||
|
glowColor.x() = effect->mData.mRed / 255.f;
|
||||||
|
glowColor.y() = effect->mData.mGreen / 255.f;
|
||||||
|
glowColor.z() = effect->mData.mBlue / 255.f;
|
||||||
|
|
||||||
|
if (!mGlowUpdater || (mGlowUpdater->isDone() || (mGlowUpdater->isPermanentGlowUpdater() == true)))
|
||||||
|
{
|
||||||
|
if (mGlowUpdater && mGlowUpdater->isDone())
|
||||||
|
mObjectRoot->removeUpdateCallback(mGlowUpdater);
|
||||||
|
|
||||||
|
if (mGlowUpdater && mGlowUpdater->isPermanentGlowUpdater())
|
||||||
|
{
|
||||||
|
mGlowUpdater->setColor(glowColor);
|
||||||
|
mGlowUpdater->setDuration(1.5); // Glow length measured from original engine as about 1.5 seconds
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addGlow(mObjectRoot, glowColor, 1.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor, float glowDuration)
|
||||||
{
|
{
|
||||||
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||||
for (int i=0; i<32; ++i)
|
for (int i=0; i<32; ++i)
|
||||||
|
@ -1130,8 +1238,10 @@ namespace MWRender
|
||||||
FindLowestUnusedTexUnitVisitor findLowestUnusedTexUnitVisitor;
|
FindLowestUnusedTexUnitVisitor findLowestUnusedTexUnitVisitor;
|
||||||
node->accept(findLowestUnusedTexUnitVisitor);
|
node->accept(findLowestUnusedTexUnitVisitor);
|
||||||
int texUnit = findLowestUnusedTexUnitVisitor.mLowestUnusedTexUnit;
|
int texUnit = findLowestUnusedTexUnitVisitor.mLowestUnusedTexUnit;
|
||||||
osg::ref_ptr<GlowUpdater> glowupdater (new GlowUpdater(texUnit, glowColor, textures));
|
|
||||||
node->addUpdateCallback(glowupdater);
|
osg::ref_ptr<GlowUpdater> glowUpdater = new GlowUpdater(texUnit, glowColor, textures, node, glowDuration, mResourceSystem);
|
||||||
|
mGlowUpdater = glowUpdater;
|
||||||
|
node->addUpdateCallback(glowUpdater);
|
||||||
|
|
||||||
// set a texture now so that the ShaderVisitor can find it
|
// set a texture now so that the ShaderVisitor can find it
|
||||||
osg::ref_ptr<osg::StateSet> writableStateSet = NULL;
|
osg::ref_ptr<osg::StateSet> writableStateSet = NULL;
|
||||||
|
@ -1144,7 +1254,6 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
|
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
|
||||||
writableStateSet->addUniform(new osg::Uniform("envMapColor", glowColor));
|
writableStateSet->addUniform(new osg::Uniform("envMapColor", glowColor));
|
||||||
|
|
||||||
mResourceSystem->getSceneManager()->recreateShaders(node);
|
mResourceSystem->getSceneManager()->recreateShaders(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct Light;
|
struct Light;
|
||||||
|
struct MagicEffect;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
|
@ -32,6 +33,7 @@ namespace MWRender
|
||||||
|
|
||||||
class ResetAccumRootCallback;
|
class ResetAccumRootCallback;
|
||||||
class RotateController;
|
class RotateController;
|
||||||
|
class GlowUpdater;
|
||||||
|
|
||||||
class EffectAnimationTime : public SceneUtil::ControllerSource
|
class EffectAnimationTime : public SceneUtil::ControllerSource
|
||||||
{
|
{
|
||||||
|
@ -261,6 +263,7 @@ protected:
|
||||||
float mHeadPitchRadians;
|
float mHeadPitchRadians;
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
|
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
|
||||||
|
osg::ref_ptr<GlowUpdater> mGlowUpdater;
|
||||||
|
|
||||||
float mAlpha;
|
float mAlpha;
|
||||||
|
|
||||||
|
@ -317,7 +320,7 @@ protected:
|
||||||
|
|
||||||
osg::Vec4f getEnchantmentColor(const MWWorld::ConstPtr& item) const;
|
osg::Vec4f getEnchantmentColor(const MWWorld::ConstPtr& item) const;
|
||||||
|
|
||||||
void addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor);
|
void addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor, float glowDuration = -1);
|
||||||
|
|
||||||
/// Set the render bin for this animation's object root. May be customized by subclasses.
|
/// Set the render bin for this animation's object root. May be customized by subclasses.
|
||||||
virtual void setRenderBin();
|
virtual void setRenderBin();
|
||||||
|
@ -351,6 +354,8 @@ public:
|
||||||
void removeEffect (int effectId);
|
void removeEffect (int effectId);
|
||||||
void getLoopingEffects (std::vector<int>& out) const;
|
void getLoopingEffects (std::vector<int>& out) const;
|
||||||
|
|
||||||
|
void addSpellCastGlow(const ESM::MagicEffect *effect);
|
||||||
|
|
||||||
virtual void updatePtr(const MWWorld::Ptr &ptr);
|
virtual void updatePtr(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
bool hasAnimation(const std::string &anim) const;
|
bool hasAnimation(const std::string &anim) const;
|
||||||
|
|
Loading…
Reference in a new issue