Override spell textures by NiTexturingProperty

pull/1051/head
Allofich 8 years ago
parent 368828b217
commit a033ba3bd2

@ -1235,10 +1235,8 @@ bool CharacterController::updateWeaponState()
MWMechanics::CastSpell cast(mPtr, NULL);
cast.playSpellCastingEffects(spellid);
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.at(spell->mEffects.mList.size() - 1);
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
const ESM::MagicEffect *effect;
effect = store.get<ESM::MagicEffect>().find(lastEffect.mEffectID); // use last effect of list for color of VFX_Hands

@ -541,12 +541,7 @@ namespace MWMechanics
else
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_DefaultHit");
std::string texture = "";
// TODO: Applying the override texture should depend on texture properties in the .NIF file and not use special cases.
if (magicEffect->mHit.empty() || magicEffect->mHit == "VFX_DefaultHit" || magicEffect->mHit == "VFX_MysticismHit"
|| magicEffect->mHit == "VFX_SoulTrapHit")
texture = magicEffect->mParticle;
std::string texture = magicEffect->mParticle;
// TODO: VFX are no longer active after saving/reloading the game
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
@ -940,16 +935,13 @@ namespace MWMechanics
if (mCaster.getClass().isActor()) // TODO: Non-actors should also create a spell cast vfx
{
const ESM::Static* castStatic;
std::string texture = "";
if (!effect->mCasting.empty())
castStatic = store.get<ESM::Static>().find (effect->mCasting);
else
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
// TODO: Applying the override texture should depend on texture properties in the .NIF file and not use special cases.
if (effect->mCasting.empty() || effect->mCasting == "VFX_DefaultCast" || effect->mCasting == "VFX_ShieldCast")
texture = effect->mParticle;
std::string texture = effect->mParticle;
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture);
}

@ -1342,7 +1342,7 @@ namespace MWRender
SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
node->accept(assignVisitor);
overrideTexture(texture, mResourceSystem, node);
overrideFirstRootTexture(texture, mResourceSystem, node);
// TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box.

@ -46,7 +46,7 @@ void EffectManager::addEffect(const std::string &model, const std::string& textu
SceneUtil::AssignControllerSourcesVisitor assignVisitor(effect.mAnimTime);
node->accept(assignVisitor);
overrideTexture(textureOverride, mResourceSystem, node);
overrideFirstRootTexture(textureOverride, mResourceSystem, node);
mParentNode->addChild(trans);
mResourceSystem->getSceneManager()->notifyAttached(node);

@ -1,14 +1,53 @@
#include "util.hpp"
#include <osg/Node>
#include <osg/ValueObject>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/sceneutil/visitor.hpp>
namespace MWRender
{
class TextureOverrideVisitor : public osg::NodeVisitor
{
public:
TextureOverrideVisitor(size_t refID, std::string texture, Resource::ResourceSystem* resourcesystem)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mRefID(refID)
, mTexture(texture)
, mResourcesystem(resourcesystem)
{
}
virtual void apply(osg::Node& node)
{
int index;
osg::ref_ptr<osg::Node> nodePtr(&node);
if (node.getUserValue("NiTexturingPropertyIndex", index))
{
if (mRefID == index)
overrideTexture(mTexture, mResourcesystem, nodePtr);
}
traverse(node);
}
int mRefID;
std::string mTexture;
Resource::ResourceSystem* mResourcesystem;
};
void overrideFirstRootTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node)
{
int index;
if (node->getUserValue("overrideIndex", index))
{
TextureOverrideVisitor overrideVisitor(index, texture, resourceSystem);
node->accept(overrideVisitor);
}
}
void overrideTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node)
{
if (texture.empty())
@ -26,7 +65,7 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
else
stateset = new osg::StateSet;
stateset->setTextureAttribute(0, tex, osg::StateAttribute::OVERRIDE);
stateset->setTextureAttribute(0, tex, osg::StateAttribute::PROTECTED);
node->setStateSet(stateset);
}

@ -17,6 +17,8 @@ namespace Resource
namespace MWRender
{
void overrideFirstRootTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node);
void overrideTexture(const std::string& texture, Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Node> node);
// Node callback to entirely skip the traversal.

@ -74,15 +74,12 @@ namespace
if (count != 0)
speed /= count;
// in the original engine, the particle texture is only used if there is only one projectile
// the particle texture is only used if there is only one projectile
if (projectileEffects.mList.size() == 1)
{
const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
effects.mList.begin()->mEffectID);
// TODO: Applying the override texture should depend on texture properties in the .NIF file and not use special cases.
if (magicEffect->mBolt.empty() || magicEffect->mBolt == "VFX_DefaultBolt" || magicEffect->mBolt == "VFX_DestructBolt")
texture = magicEffect->mParticle;
texture = magicEffect->mParticle;
}
if (projectileEffects.mList.size() > 1) // insert a VFX_Multiple projectile if there are multiple projectile effects
@ -155,7 +152,7 @@ namespace MWWorld
attachTo = rotateNode;
}
mResourceSystem->getSceneManager()->getInstance(model, attachTo);
osg::ref_ptr<osg::Node> projectile = mResourceSystem->getSceneManager()->getInstance(model, attachTo);
if (state.mIdMagic.size() > 1)
for (size_t iter = 1; iter != state.mIdMagic.size(); ++iter)
@ -180,7 +177,8 @@ namespace MWWorld
SceneUtil::AssignControllerSourcesVisitor assignVisitor (state.mEffectAnimationTime);
state.mNode->accept(assignVisitor);
MWRender::overrideTexture(texture, mResourceSystem, state.mNode);
MWRender::overrideFirstRootTexture(texture, mResourceSystem, projectile);
}
void ProjectileManager::update(State& state, float duration)
@ -500,8 +498,8 @@ namespace MWWorld
state.mSpellId = esm.mSpellId;
state.mActorId = esm.mActorId;
state.mStack = esm.mStack;
std::string color = "";
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, color, esm.mEffects);
std::string texture = "";
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, texture, esm.mEffects);
state.mSpeed = esm.mSpeed; // speed is derived from non-projectile effects as well as
// projectile effects, so we can't calculate it from the save
// file's effect list, which is already trimmed of non-projectile
@ -519,7 +517,7 @@ namespace MWWorld
return true;
}
createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, color);
createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, texture);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();

@ -3172,11 +3172,7 @@ namespace MWWorld
else
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
std::string texture = "";
// TODO: Applying the override texture should depend on texture properties in the .NIF file and not use special cases.
if (effect->mArea.empty() || effect->mArea == "VFX_DefaultArea")
texture = effect->mParticle;
std::string texture = effect->mParticle;
if (effectIt->mArea <= 0)
{

@ -6,6 +6,7 @@
#include <osg/Array>
#include <osg/LOD>
#include <osg/TexGen>
#include <osg/ValueObject>
// resource
#include <components/misc/stringops.hpp>
@ -368,13 +369,32 @@ namespace NifOsg
return created;
}
void applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager, std::vector<int>& boundTextures, int animflags)
void applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager, std::vector<int>& boundTextures, int animflags, bool isRootNode)
{
const Nif::PropertyList& props = nifNode->props;
for (size_t i = 0; i <props.length();++i)
bool foundFirstRootTexturingProperty = false;
for (size_t i = 0; i <props.length(); ++i)
{
if (!props[i].empty())
{
// store the recIndex of the NiTexturingProperty. Used for spells when overriding textures.
// Get the lowest numbered one for the root node. This is what is overridden when a spell
// effect "particle texture" is used. For non-root nodes we keep setting until we have the highest
// numbered one, which is the one that displays in the game and can be overridden if it matches the
// lowest one on the root.
if (!foundFirstRootTexturingProperty && isRootNode && props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
{
int index = props[i].getPtr()->recIndex;
applyTo->setUserValue("overrideIndex", index);
foundFirstRootTexturingProperty = true;
}
else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
{
int index = props[i].getPtr()->recIndex;
applyTo->setUserValue("NiTexturingPropertyIndex", index);
}
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags);
}
}
}
@ -631,7 +651,7 @@ namespace NifOsg
osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags);
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags, node == rootNode);
if (nifNode->recType == Nif::RC_NiTriShape && !skipMeshes)
{

Loading…
Cancel
Save