forked from teamnwah/openmw-tes3coop
Override spell textures by NiTexturingProperty
This commit is contained in:
parent
368828b217
commit
a033ba3bd2
9 changed files with 80 additions and 35 deletions
|
@ -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…
Reference in a new issue