mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 10:36:42 +00:00
Issue #777: Add CreatureAnimation variant for creatures with weapons/shields
This commit is contained in:
parent
589fbbd871
commit
198bb0de60
5 changed files with 156 additions and 12 deletions
|
@ -148,8 +148,10 @@ namespace MWClass
|
||||||
|
|
||||||
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
{
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
MWRender::Actors& actors = renderingInterface.getActors();
|
MWRender::Actors& actors = renderingInterface.getActors();
|
||||||
actors.insertCreature(ptr);
|
actors.insertCreature(ptr, ref->mBase->mFlags & ESM::Creature::Weapon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
|
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
|
||||||
|
|
|
@ -76,10 +76,14 @@ void Actors::insertNPC(const MWWorld::Ptr& ptr)
|
||||||
mAllActors[ptr] = anim;
|
mAllActors[ptr] = anim;
|
||||||
mRendering->addWaterRippleEmitter (ptr);
|
mRendering->addWaterRippleEmitter (ptr);
|
||||||
}
|
}
|
||||||
void Actors::insertCreature (const MWWorld::Ptr& ptr)
|
void Actors::insertCreature (const MWWorld::Ptr& ptr, bool weaponsShields)
|
||||||
{
|
{
|
||||||
insertBegin(ptr);
|
insertBegin(ptr);
|
||||||
CreatureAnimation* anim = new CreatureAnimation(ptr);
|
Animation* anim = NULL;
|
||||||
|
if (weaponsShields)
|
||||||
|
anim = new CreatureWeaponAnimation(ptr);
|
||||||
|
else
|
||||||
|
anim = new CreatureAnimation(ptr);
|
||||||
delete mAllActors[ptr];
|
delete mAllActors[ptr];
|
||||||
mAllActors[ptr] = anim;
|
mAllActors[ptr] = anim;
|
||||||
mRendering->addWaterRippleEmitter (ptr);
|
mRendering->addWaterRippleEmitter (ptr);
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace MWRender
|
||||||
void setRootNode(Ogre::SceneNode* root);
|
void setRootNode(Ogre::SceneNode* root);
|
||||||
|
|
||||||
void insertNPC(const MWWorld::Ptr& ptr);
|
void insertNPC(const MWWorld::Ptr& ptr);
|
||||||
void insertCreature (const MWWorld::Ptr& ptr);
|
void insertCreature (const MWWorld::Ptr& ptr, bool weaponsShields);
|
||||||
void insertActivator (const MWWorld::Ptr& ptr);
|
void insertActivator (const MWWorld::Ptr& ptr);
|
||||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||||
///< \return found?
|
///< \return found?
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
#include "creatureanimation.hpp"
|
#include "creatureanimation.hpp"
|
||||||
|
|
||||||
|
#include <OgreEntity.h>
|
||||||
|
#include <OgreSkeletonInstance.h>
|
||||||
|
#include <OgreBone.h>
|
||||||
|
|
||||||
#include "renderconst.hpp"
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
CreatureAnimation::~CreatureAnimation()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
||||||
: Animation(ptr, ptr.getRefData().getBaseNode())
|
: Animation(ptr, ptr.getRefData().getBaseNode())
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
||||||
|
|
||||||
assert (ref->mBase != NULL);
|
std::string model = ptr.getClass().getModel(ptr);
|
||||||
if(!ref->mBase->mModel.empty())
|
if(!model.empty())
|
||||||
{
|
{
|
||||||
std::string model = "meshes\\"+ref->mBase->mModel;
|
|
||||||
|
|
||||||
setObjectRoot(model, false);
|
setObjectRoot(model, false);
|
||||||
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
||||||
|
|
||||||
|
@ -30,4 +31,115 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr)
|
||||||
|
: Animation(ptr, ptr.getRefData().getBaseNode())
|
||||||
|
, mShowWeapons(true) // TODO: change to false, once charactercontroller handles creature weapons
|
||||||
|
, mShowCarriedLeft(true) // TODO: change to false, once charactercontroller handles creature weapons
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
std::string model = ptr.getClass().getModel(ptr);
|
||||||
|
if(!model.empty())
|
||||||
|
{
|
||||||
|
setObjectRoot(model, false);
|
||||||
|
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
||||||
|
|
||||||
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||||
|
addAnimSource("meshes\\base_anim.nif");
|
||||||
|
addAnimSource(model);
|
||||||
|
|
||||||
|
mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr);
|
||||||
|
|
||||||
|
updateParts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureWeaponAnimation::showWeapons(bool showWeapon)
|
||||||
|
{
|
||||||
|
if (showWeapon != mShowWeapons)
|
||||||
|
{
|
||||||
|
mShowWeapons = showWeapon;
|
||||||
|
updateParts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureWeaponAnimation::showCarriedLeft(bool show)
|
||||||
|
{
|
||||||
|
if (show != mShowCarriedLeft)
|
||||||
|
{
|
||||||
|
mShowCarriedLeft = show;
|
||||||
|
updateParts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureWeaponAnimation::updateParts()
|
||||||
|
{
|
||||||
|
mWeapon.setNull();
|
||||||
|
mShield.setNull();
|
||||||
|
|
||||||
|
if (mShowWeapons)
|
||||||
|
updatePart(mWeapon, MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
if (mShowCarriedLeft)
|
||||||
|
updatePart(mShield, MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureWeaponAnimation::updatePart(NifOgre::ObjectScenePtr& scene, int slot)
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
|
||||||
|
MWWorld::ContainerStoreIterator it = inv.getSlot(slot);
|
||||||
|
|
||||||
|
if (it == inv.end())
|
||||||
|
{
|
||||||
|
scene.setNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MWWorld::Ptr item = *it;
|
||||||
|
|
||||||
|
std::string bonename;
|
||||||
|
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
||||||
|
bonename = "Weapon Bone";
|
||||||
|
else
|
||||||
|
bonename = "Shield Bone";
|
||||||
|
|
||||||
|
scene = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, item.getClass().getModel(item));
|
||||||
|
Ogre::Vector3 glowColor = getEnchantmentColor(item);
|
||||||
|
|
||||||
|
setRenderProperties(scene, RV_Actors, RQG_Main, RQG_Alpha, 0,
|
||||||
|
!item.getClass().getEnchantment(item).empty(), &glowColor);
|
||||||
|
|
||||||
|
if(scene->mSkelBase)
|
||||||
|
{
|
||||||
|
Ogre::SkeletonInstance *skel = scene->mSkelBase->getSkeleton();
|
||||||
|
if(scene->mSkelBase->isParentTagPoint())
|
||||||
|
{
|
||||||
|
Ogre::Node *root = scene->mSkelBase->getParentNode();
|
||||||
|
if(skel->hasBone("BoneOffset"))
|
||||||
|
{
|
||||||
|
Ogre::Bone *offset = skel->getBone("BoneOffset");
|
||||||
|
|
||||||
|
root->translate(offset->getPosition());
|
||||||
|
|
||||||
|
// It appears that the BoneOffset rotation is completely bogus, at least for light models.
|
||||||
|
//root->rotate(offset->getOrientation());
|
||||||
|
root->pitch(Ogre::Degree(-90.0f));
|
||||||
|
|
||||||
|
root->scale(offset->getScale());
|
||||||
|
root->setInitialState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateSkeletonInstance(mSkelBase->getSkeleton(), skel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// type == ESM::PRT_Weapon should get an animation source based on the current offset
|
||||||
|
// of the weapon attack animation (from its beginning, or start marker?)
|
||||||
|
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(scene->mControllers.begin());
|
||||||
|
for(;ctrl != scene->mControllers.end();ctrl++)
|
||||||
|
{
|
||||||
|
if(ctrl->getSource().isNull())
|
||||||
|
ctrl->setSource(Ogre::SharedPtr<NullAnimationTime>(new NullAnimationTime()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_RENDER_CREATUREANIMATION_H
|
#define GAME_RENDER_CREATUREANIMATION_H
|
||||||
|
|
||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,32 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CreatureAnimation(const MWWorld::Ptr& ptr);
|
CreatureAnimation(const MWWorld::Ptr& ptr);
|
||||||
virtual ~CreatureAnimation();
|
virtual ~CreatureAnimation() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// For creatures with weapons and shields
|
||||||
|
// Animation is already virtual anyway, so might as well make a separate class.
|
||||||
|
// Most creatures don't need weapons/shields, so this will save some memory.
|
||||||
|
class CreatureWeaponAnimation : public Animation, public MWWorld::InventoryStoreListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreatureWeaponAnimation(const MWWorld::Ptr& ptr);
|
||||||
|
virtual ~CreatureWeaponAnimation() {}
|
||||||
|
|
||||||
|
virtual void equipmentChanged() { updateParts(); }
|
||||||
|
|
||||||
|
virtual void showWeapons(bool showWeapon);
|
||||||
|
virtual void showCarriedLeft(bool show);
|
||||||
|
|
||||||
|
void updateParts();
|
||||||
|
|
||||||
|
void updatePart(NifOgre::ObjectScenePtr& scene, int slot);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NifOgre::ObjectScenePtr mWeapon;
|
||||||
|
NifOgre::ObjectScenePtr mShield;
|
||||||
|
bool mShowWeapons;
|
||||||
|
bool mShowCarriedLeft;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue