mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 21:45:32 +00:00
Set alpha value of character animations according to Invisibility / Chameleon effects.
This commit is contained in:
parent
9fcb4fad5c
commit
37a7ee8fcd
9 changed files with 125 additions and 39 deletions
|
@ -727,6 +727,8 @@ void CharacterController::update(float duration)
|
|||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
Ogre::Vector3 movement(0.0f);
|
||||
|
||||
updateVisibility();
|
||||
|
||||
if(!cls.isActor())
|
||||
{
|
||||
if(mAnimQueue.size() > 1)
|
||||
|
@ -1130,4 +1132,25 @@ void CharacterController::updateContinuousVfx()
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterController::updateVisibility()
|
||||
{
|
||||
if (!mPtr.getClass().isActor())
|
||||
return;
|
||||
float alpha = 1.f;
|
||||
if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
|
||||
{
|
||||
if (mPtr.getRefData().getHandle() == "player")
|
||||
alpha = 0.4f;
|
||||
else
|
||||
alpha = 0.f;
|
||||
}
|
||||
float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude;
|
||||
if (chameleon)
|
||||
{
|
||||
alpha *= std::max(0.2f, (100.f - chameleon)/100.f);
|
||||
}
|
||||
|
||||
mAnimation->setAlpha(alpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -173,6 +173,8 @@ class CharacterController
|
|||
|
||||
bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak);
|
||||
|
||||
void updateVisibility();
|
||||
|
||||
public:
|
||||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||
virtual ~CharacterController();
|
||||
|
|
|
@ -215,6 +215,8 @@ public:
|
|||
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", std::string texture = "");
|
||||
void removeEffect (int effectId);
|
||||
void getLoopingEffects (std::vector<int>& out);
|
||||
|
||||
virtual void setAlpha(float alpha) {}
|
||||
private:
|
||||
void updateEffects(float duration);
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <OgreParticleSystem.h>
|
||||
#include <OgreSubEntity.h>
|
||||
|
||||
#include <extern/shiny/Main/Factory.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -116,7 +118,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v
|
|||
mViewMode(viewMode),
|
||||
mShowWeapons(false),
|
||||
mShowShield(true),
|
||||
mFirstPersonOffset(0.f, 0.f, 0.f)
|
||||
mFirstPersonOffset(0.f, 0.f, 0.f),
|
||||
mAlpha(1.f)
|
||||
{
|
||||
mNpc = mPtr.get<ESM::NPC>()->mBase;
|
||||
|
||||
|
@ -219,6 +222,7 @@ void NpcAnimation::updateNpcBase()
|
|||
|
||||
void NpcAnimation::updateParts()
|
||||
{
|
||||
mAlpha = 1.f;
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
|
||||
|
||||
|
@ -647,6 +651,7 @@ void NpcAnimation::showWeapons(bool showWeapon)
|
|||
{
|
||||
removeIndividualPart(ESM::PRT_Weapon);
|
||||
}
|
||||
mAlpha = 1.f;
|
||||
}
|
||||
|
||||
void NpcAnimation::showShield(bool show)
|
||||
|
@ -705,4 +710,56 @@ void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, boo
|
|||
}
|
||||
}
|
||||
|
||||
void NpcAnimation::setAlpha(float alpha)
|
||||
{
|
||||
if (alpha == mAlpha)
|
||||
return;
|
||||
mAlpha = alpha;
|
||||
|
||||
for (int i=0; i<ESM::PRT_Count; ++i)
|
||||
{
|
||||
if (mObjectParts[i].isNull())
|
||||
continue;
|
||||
|
||||
for (unsigned int j=0; j<mObjectParts[i]->mEntities.size(); ++j)
|
||||
{
|
||||
Ogre::Entity* ent = mObjectParts[i]->mEntities[j];
|
||||
if (ent != mObjectParts[i]->mSkelBase)
|
||||
applyAlpha(alpha, ent, mObjectParts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectScenePtr scene)
|
||||
{
|
||||
ent->getSubEntity(0)->setRenderQueueGroup(alpha != 1.f || ent->getSubEntity(0)->getMaterial()->isTransparent()
|
||||
? RQG_Alpha : RQG_Main);
|
||||
|
||||
|
||||
Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(ent);
|
||||
if (mAlpha == 1.f)
|
||||
{
|
||||
// Don't bother remembering what the original values were. Just remove the techniques and let the factory restore them.
|
||||
mat->removeAllTechniques();
|
||||
sh::Factory::getInstance()._ensureMaterial(mat->getName(), "Default");
|
||||
return;
|
||||
}
|
||||
|
||||
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
|
||||
while(techs.hasMoreElements())
|
||||
{
|
||||
Ogre::Technique *tech = techs.getNext();
|
||||
Ogre::Technique::PassIterator passes = tech->getPassIterator();
|
||||
while(passes.hasMoreElements())
|
||||
{
|
||||
Ogre::Pass *pass = passes.getNext();
|
||||
pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
|
||||
Ogre::ColourValue diffuse = pass->getDiffuse();
|
||||
diffuse.a = alpha;
|
||||
pass->setDiffuse(diffuse);
|
||||
pass->setVertexColourTracking(pass->getVertexColourTracking() &~Ogre::TVC_DIFFUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ private:
|
|||
|
||||
Ogre::SharedPtr<SayAnimationValue> mSayAnimationValue;
|
||||
|
||||
float mAlpha;
|
||||
|
||||
void updateNpcBase();
|
||||
|
||||
NifOgre::ObjectScenePtr insertBoundedPart(const std::string &model, int group, const std::string &bonename,
|
||||
|
@ -78,6 +80,8 @@ private:
|
|||
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
|
||||
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
|
||||
|
||||
void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param ptr
|
||||
|
@ -109,6 +113,9 @@ public:
|
|||
|
||||
/// Rebuilds the NPC, updating their root model, animation sources, and equipment.
|
||||
void rebuild();
|
||||
|
||||
/// Make the NPC only partially visible
|
||||
virtual void setAlpha(float alpha);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -60,14 +60,14 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
|
|||
MWWorld::Fallback* fallback)
|
||||
: mRendering(_rend)
|
||||
, mFallback(fallback)
|
||||
, mObjects(mRendering)
|
||||
, mActors(mRendering, this)
|
||||
, mPlayerAnimation(NULL)
|
||||
, mAmbientMode(0)
|
||||
, mSunEnabled(0)
|
||||
, mPhysicsEngine(engine)
|
||||
, mTerrain(NULL)
|
||||
{
|
||||
mActors = new MWRender::Actors(mRendering, this);
|
||||
mObjects = new MWRender::Objects(mRendering);
|
||||
// select best shader mode
|
||||
bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos);
|
||||
bool glES = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL ES") != std::string::npos);
|
||||
|
@ -162,8 +162,8 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
|
|||
mRootNode = mRendering.getScene()->getRootSceneNode();
|
||||
mRootNode->createChildSceneNode("player");
|
||||
|
||||
mObjects.setRootNode(mRootNode);
|
||||
mActors.setRootNode(mRootNode);
|
||||
mObjects->setRootNode(mRootNode);
|
||||
mActors->setRootNode(mRootNode);
|
||||
|
||||
mCamera = new MWRender::Camera(mRendering.getCamera());
|
||||
|
||||
|
@ -201,6 +201,8 @@ RenderingManager::~RenderingManager ()
|
|||
delete mCompositors;
|
||||
delete mWater;
|
||||
delete mVideoPlayer;
|
||||
delete mActors;
|
||||
delete mObjects;
|
||||
delete mFactory;
|
||||
}
|
||||
|
||||
|
@ -210,10 +212,10 @@ MWRender::SkyManager* RenderingManager::getSkyManager()
|
|||
}
|
||||
|
||||
MWRender::Objects& RenderingManager::getObjects(){
|
||||
return mObjects;
|
||||
return *mObjects;
|
||||
}
|
||||
MWRender::Actors& RenderingManager::getActors(){
|
||||
return mActors;
|
||||
return *mActors;
|
||||
}
|
||||
|
||||
OEngine::Render::Fader* RenderingManager::getFader()
|
||||
|
@ -223,8 +225,8 @@ OEngine::Render::Fader* RenderingManager::getFader()
|
|||
|
||||
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store)
|
||||
{
|
||||
mObjects.removeCell(store);
|
||||
mActors.removeCell(store);
|
||||
mObjects->removeCell(store);
|
||||
mActors->removeCell(store);
|
||||
mDebugging->cellRemoved(store);
|
||||
}
|
||||
|
||||
|
@ -240,7 +242,7 @@ void RenderingManager::toggleWater()
|
|||
|
||||
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
|
||||
{
|
||||
mObjects.buildStaticGeometry (*store);
|
||||
mObjects->buildStaticGeometry (*store);
|
||||
sh::Factory::getInstance().unloadUnreferencedMaterials();
|
||||
mDebugging->cellAdded(store);
|
||||
waterAdded(store);
|
||||
|
@ -254,8 +256,8 @@ void RenderingManager::addObject (const MWWorld::Ptr& ptr){
|
|||
|
||||
void RenderingManager::removeObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
if (!mObjects.deleteObject (ptr))
|
||||
mActors.deleteObject (ptr);
|
||||
if (!mObjects->deleteObject (ptr))
|
||||
mActors->deleteObject (ptr);
|
||||
}
|
||||
|
||||
void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position)
|
||||
|
@ -295,9 +297,9 @@ RenderingManager::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &
|
|||
parent->removeChild(child);
|
||||
|
||||
if (MWWorld::Class::get(old).isActor()) {
|
||||
mActors.updateObjectCell(old, cur);
|
||||
mActors->updateObjectCell(old, cur);
|
||||
} else {
|
||||
mObjects.updateObjectCell(old, cur);
|
||||
mObjects->updateObjectCell(old, cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +317,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
|
|||
if(ptr.getRefData().getHandle() == "player")
|
||||
anim = mPlayerAnimation;
|
||||
else if(MWWorld::Class::get(ptr).isActor())
|
||||
anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr));
|
||||
anim = dynamic_cast<NpcAnimation*>(mActors->getAnimation(ptr));
|
||||
if(anim)
|
||||
{
|
||||
anim->rebuild();
|
||||
|
@ -380,8 +382,8 @@ void RenderingManager::update (float duration, bool paused)
|
|||
if(paused)
|
||||
return;
|
||||
|
||||
mActors.update (duration);
|
||||
mObjects.update (duration);
|
||||
mActors->update (duration);
|
||||
mObjects->update (duration);
|
||||
|
||||
|
||||
mSkyManager->update(duration);
|
||||
|
@ -657,7 +659,7 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
|
|||
{
|
||||
assert(mTerrain);
|
||||
|
||||
Ogre::AxisAlignedBox dims = mObjects.getDimensions(cell);
|
||||
Ogre::AxisAlignedBox dims = mObjects->getDimensions(cell);
|
||||
Ogre::Vector2 center(cell->mCell->getGridX() + 0.5, cell->mCell->getGridY() + 0.5);
|
||||
dims.merge(mTerrain->getWorldBoundingBox(center));
|
||||
|
||||
|
@ -667,7 +669,7 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
|
|||
mLocalMap->requestMap(cell, dims.getMinimum().z, dims.getMaximum().z);
|
||||
}
|
||||
else
|
||||
mLocalMap->requestMap(cell, mObjects.getDimensions(cell));
|
||||
mLocalMap->requestMap(cell, mObjects->getDimensions(cell));
|
||||
}
|
||||
|
||||
void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
|
||||
|
@ -677,13 +679,13 @@ void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
|
|||
|
||||
void RenderingManager::disableLights(bool sun)
|
||||
{
|
||||
mObjects.disableLights();
|
||||
mObjects->disableLights();
|
||||
sunDisable(sun);
|
||||
}
|
||||
|
||||
void RenderingManager::enableLights(bool sun)
|
||||
{
|
||||
mObjects.enableLights();
|
||||
mObjects->enableLights();
|
||||
sunEnable(sun);
|
||||
}
|
||||
|
||||
|
@ -859,7 +861,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
|
|||
|
||||
if (rebuild)
|
||||
{
|
||||
mObjects.rebuildStaticGeometry();
|
||||
mObjects->rebuildStaticGeometry();
|
||||
if (mTerrain)
|
||||
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
|
||||
Settings::Manager::getBool("split", "Shadows"));
|
||||
|
@ -976,13 +978,13 @@ void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rend
|
|||
|
||||
Animation* RenderingManager::getAnimation(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
Animation *anim = mActors.getAnimation(ptr);
|
||||
Animation *anim = mActors->getAnimation(ptr);
|
||||
|
||||
if(!anim && ptr.getRefData().getHandle() == "player")
|
||||
anim = mPlayerAnimation;
|
||||
|
||||
if (!anim)
|
||||
anim = mObjects.getAnimation(ptr);
|
||||
anim = mObjects->getAnimation(ptr);
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
|
|
@ -242,8 +242,8 @@ private:
|
|||
|
||||
OEngine::Render::OgreRenderer &mRendering;
|
||||
|
||||
MWRender::Objects mObjects;
|
||||
MWRender::Actors mActors;
|
||||
MWRender::Objects* mObjects;
|
||||
MWRender::Actors* mActors;
|
||||
|
||||
MWRender::NpcAnimation *mPlayerAnimation;
|
||||
|
||||
|
|
|
@ -63,11 +63,12 @@ Ogre::MaterialPtr MaterialControllerManager::getWritableMaterial(Ogre::MovableOb
|
|||
else if (Ogre::ParticleSystem* partSys = dynamic_cast<Ogre::ParticleSystem*>(movable))
|
||||
mat = Ogre::MaterialManager::getSingleton().getByName(partSys->getMaterialName());
|
||||
|
||||
// Make sure techniques are created
|
||||
sh::Factory::getInstance()._ensureMaterial(mat->getName(), "Default");
|
||||
|
||||
static int count=0;
|
||||
mat = mat->clone(mat->getName() + Ogre::StringConverter::toString(count++));
|
||||
Ogre::String newName = mat->getName() + Ogre::StringConverter::toString(count++);
|
||||
sh::Factory::getInstance().createMaterialInstance(newName, mat->getName());
|
||||
// Make sure techniques are created
|
||||
sh::Factory::getInstance()._ensureMaterial(newName, "Default");
|
||||
mat = Ogre::MaterialManager::getSingleton().getByName(newName);
|
||||
|
||||
mClonedMaterials[movable] = mat;
|
||||
|
||||
|
@ -84,7 +85,7 @@ MaterialControllerManager::~MaterialControllerManager()
|
|||
{
|
||||
for (std::map<Ogre::MovableObject*, Ogre::MaterialPtr>::iterator it = mClonedMaterials.begin(); it != mClonedMaterials.end(); ++it)
|
||||
{
|
||||
Ogre::MaterialManager::getSingleton().remove(it->second->getName());
|
||||
sh::Factory::getInstance().destroyMaterialInstance(it->second->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,9 +98,7 @@
|
|||
#if VERTEXCOLOR_MODE != 2
|
||||
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
|
||||
#endif
|
||||
#if VERTEXCOLOR_MODE != 2
|
||||
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
|
||||
#endif
|
||||
#if VERTEXCOLOR_MODE != 1
|
||||
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
|
||||
#endif
|
||||
|
@ -234,9 +232,7 @@
|
|||
lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz;
|
||||
#endif
|
||||
|
||||
#if VERTEXCOLOR_MODE != 2
|
||||
lightResult.a *= materialDiffuse.a;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -339,9 +335,7 @@
|
|||
#if VERTEXCOLOR_MODE != 2
|
||||
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
|
||||
#endif
|
||||
#if VERTEXCOLOR_MODE != 2
|
||||
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
|
||||
#endif
|
||||
#if VERTEXCOLOR_MODE != 1
|
||||
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
|
||||
#endif
|
||||
|
@ -434,9 +428,7 @@
|
|||
lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz;
|
||||
#endif
|
||||
|
||||
#if VERTEXCOLOR_MODE != 2
|
||||
lightResult.a *= materialDiffuse.a;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// shadows only for the first (directional) light
|
||||
|
|
Loading…
Reference in a new issue