Merge remote-tracking branch 'scrawl/master'

moveref
Marc Zinnschlag 10 years ago
commit 9ae69447d3

@ -7,6 +7,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/failedaction.hpp"
@ -21,7 +22,7 @@
#include "../mwgui/tooltips.hpp"
#include "../mwrender/objects.hpp"
#include "../mwrender/actors.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -87,7 +88,8 @@ namespace MWClass
{
const std::string model = getModel(ptr);
if (!model.empty()) {
renderingInterface.getObjects().insertModel(ptr, model);
MWRender::Actors& actors = renderingInterface.getActors();
actors.insertActivator(ptr);
}
}
@ -96,6 +98,7 @@ namespace MWClass
const std::string model = getModel(ptr);
if(!model.empty())
physics.addObject(ptr);
MWBase::Environment::get().getMechanicsManager()->add(ptr);
}
std::string Container::getModel(const MWWorld::Ptr &ptr) const

@ -633,8 +633,8 @@ namespace MWGui
MWWorld::Store<ESM::Skill>::iterator it = skills.begin();
for (; it != skills.end(); ++it)
{
if (it->mData.mSpecialization == specId)
specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->mIndex] + "}";
if (it->second.mData.mSpecialization == specId)
specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->first] + "}";
}
widget->setUserString("Caption_CenteredCaptionText", specText);
widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip");

@ -1072,7 +1072,8 @@ bool CharacterController::updateWeaponState()
}
else if (mHitState == CharState_KnockDown)
{
mUpperBodyState = UpperCharState_WeapEquiped;
if (mUpperBodyState > UpperCharState_WeapEquiped)
mUpperBodyState = UpperCharState_WeapEquiped;
mAnimation->disable(mCurrentWeapon);
}
}

@ -143,9 +143,9 @@ namespace MWMechanics
MWWorld::Store<ESM::Skill>::iterator iter = skills.begin();
for (; iter != skills.end(); ++iter)
{
if (iter->mData.mSpecialization==class_->mData.mSpecialization)
if (iter->second.mData.mSpecialization==class_->mData.mSpecialization)
{
int index = iter->mIndex;
int index = iter->first;
if (index>=0 && index<27)
{

@ -4,6 +4,8 @@
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
#include "renderconst.hpp"
namespace MWRender
@ -16,17 +18,14 @@ ActivatorAnimation::~ActivatorAnimation()
ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
: Animation(ptr, ptr.getRefData().getBaseNode())
{
MWWorld::LiveCellRef<ESM::Activator> *ref = mPtr.get<ESM::Activator>();
const std::string& model = mPtr.getClass().getModel(mPtr);
assert(ref->mBase != NULL);
if(!ref->mBase->mModel.empty())
if(!model.empty())
{
const std::string name = "meshes\\"+ref->mBase->mModel;
setObjectRoot(name, false);
setObjectRoot(model, false);
setRenderProperties(mObjectRoot, RV_Misc, RQG_Main, RQG_Alpha);
addAnimSource(name);
addAnimSource(model);
}
}

@ -114,10 +114,6 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, mdlname) :
NifOgre::Loader::createObjectBase(mInsert, mdlname));
// Fast forward auto-play particles, which will have been set up as Emitting by the loader.
for (unsigned int i=0; i<mObjectRoot->mParticles.size(); ++i)
mObjectRoot->mParticles[i]->fastForward(1, 0.1);
if(mObjectRoot->mSkelBase)
{
mSkelBase = mObjectRoot->mSkelBase;

@ -571,10 +571,6 @@ NifOgre::ObjectScenePtr NpcAnimation::insertBoundedPart(const std::string &model
std::for_each(objects->mEntities.begin(), objects->mEntities.end(), SetObjectGroup(group));
std::for_each(objects->mParticles.begin(), objects->mParticles.end(), SetObjectGroup(group));
// Fast forward auto-play particles, which will have been set up as Emitting by the loader.
for (unsigned int i=0; i<objects->mParticles.size(); ++i)
objects->mParticles[i]->fastForward(1, 0.1);
if(objects->mSkelBase)
{
Ogre::AnimationStateSet *aset = objects->mSkelBase->getAllAnimationStates();

@ -842,36 +842,12 @@ namespace MWWorld
template <>
class Store<ESM::Pathgrid> : public StoreBase
{
public:
typedef std::vector<ESM::Pathgrid>::const_iterator iterator;
private:
std::vector<ESM::Pathgrid> mStatic;
std::vector<ESM::Pathgrid>::iterator mIntBegin, mIntEnd, mExtBegin, mExtEnd;
typedef std::map<std::string, ESM::Pathgrid> Interior;
typedef std::map<std::pair<int, int>, ESM::Pathgrid> Exterior;
struct IntExtOrdering
{
bool operator()(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const {
// interior pathgrids precedes exterior ones (x < y)
if ((x.mData.mX == 0 && x.mData.mY == 0) &&
(y.mData.mX != 0 || y.mData.mY != 0))
{
return true;
}
return false;
}
};
struct ExtCompare
{
bool operator()(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const {
if (x.mData.mX == y.mData.mX) {
return x.mData.mY < y.mData.mY;
}
return x.mData.mX < y.mData.mX;
}
};
Interior mInt;
Exterior mExt;
public:
@ -881,65 +857,33 @@ namespace MWWorld
pathgrid.load(esm);
// Try to overwrite existing record
// Can't use search() because we aren't sorted yet
if (!pathgrid.mCell.empty())
{
for (std::vector<ESM::Pathgrid>::iterator it = mStatic.begin(); it != mStatic.end(); ++it)
{
if ((*it).mCell == pathgrid.mCell)
{
(*it) = pathgrid;
return;
}
}
std::pair<Interior::iterator, bool> found = mInt.insert(std::make_pair(pathgrid.mCell, pathgrid));
if (found.second)
found.first->second = pathgrid;
}
else
{
for (std::vector<ESM::Pathgrid>::iterator it = mStatic.begin(); it != mStatic.end(); ++it)
{
if ((*it).mData.mX == pathgrid.mData.mX && (*it).mData.mY == pathgrid.mData.mY)
{
(*it) = pathgrid;
return;
}
}
std::pair<Exterior::iterator, bool> found = mExt.insert(std::make_pair(std::make_pair(pathgrid.mData.mX, pathgrid.mData.mY),
pathgrid));
if (found.second)
found.first->second = pathgrid;
}
mStatic.push_back(pathgrid);
}
size_t getSize() const {
return mStatic.size();
return mInt.size() + mExt.size();
}
void setUp() {
IntExtOrdering cmp;
std::sort(mStatic.begin(), mStatic.end(), cmp);
ESM::Pathgrid pg;
pg.mData.mX = pg.mData.mY = 1;
mExtBegin =
std::lower_bound(mStatic.begin(), mStatic.end(), pg, cmp);
mExtEnd = mStatic.end();
mIntBegin = mStatic.begin();
mIntEnd = mExtBegin;
std::sort(mIntBegin, mIntEnd, RecordCmp());
std::sort(mExtBegin, mExtEnd, ExtCompare());
}
const ESM::Pathgrid *search(int x, int y) const {
ESM::Pathgrid pg;
pg.mData.mX = x;
pg.mData.mY = y;
iterator it =
std::lower_bound(mExtBegin, mExtEnd, pg, ExtCompare());
if (it != mExtEnd && it->mData.mX == x && it->mData.mY == y) {
return &(*it);
}
return 0;
Exterior::const_iterator it = mExt.find(std::make_pair(x,y));
if (it != mExt.end())
return &(it->second);
return NULL;
}
const ESM::Pathgrid *find(int x, int y) const {
@ -953,14 +897,10 @@ namespace MWWorld
}
const ESM::Pathgrid *search(const std::string &name) const {
ESM::Pathgrid pg;
pg.mCell = name;
iterator it = std::lower_bound(mIntBegin, mIntEnd, pg, RecordCmp());
if (it != mIntEnd && Misc::StringUtils::ciEqual(it->mCell, name)) {
return &(*it);
}
return 0;
Interior::const_iterator it = mInt.find(name);
if (it != mInt.end())
return &(it->second);
return NULL;
}
const ESM::Pathgrid *find(const std::string &name) const {
@ -986,53 +926,20 @@ namespace MWWorld
}
return find(cell.mData.mX, cell.mData.mY);
}
iterator begin() const {
return mStatic.begin();
}
iterator end() const {
return mStatic.end();
}
iterator interiorPathsBegin() const {
return mIntBegin;
}
iterator interiorPathsEnd() const {
return mIntEnd;
}
iterator exteriorPathsBegin() const {
return mExtBegin;
}
iterator exteriorPathsEnd() const {
return mExtEnd;
}
};
template <class T>
class IndexedStore
{
struct Compare
{
bool operator()(const T &x, const T &y) const {
return x.mIndex < y.mIndex;
}
};
protected:
std::vector<T> mStatic;
typedef typename std::map<int, T> Static;
Static mStatic;
public:
typedef typename std::vector<T>::const_iterator iterator;
typedef typename std::map<int, T>::const_iterator iterator;
IndexedStore() {}
IndexedStore(unsigned int size) {
mStatic.reserve(size);
}
iterator begin() const {
return mStatic.begin();
}
@ -1041,10 +948,14 @@ namespace MWWorld
return mStatic.end();
}
/// \todo refine loading order
void load(ESM::ESMReader &esm) {
mStatic.push_back(T());
mStatic.back().load(esm);
T record;
record.load(esm);
// Try to overwrite existing record
std::pair<typename Static::iterator, bool> found = mStatic.insert(std::make_pair(record.mIndex, record));
if (found.second)
found.first->second = record;
}
int getSize() const {
@ -1052,40 +963,13 @@ namespace MWWorld
}
void setUp() {
/// \note This method sorts indexed values for further
/// searches. Every loaded item is present in storage, but
/// latest loaded shadows any previous while searching.
/// If memory cost will be too high, it is possible to remove
/// unused values.
Compare cmp;
std::stable_sort(mStatic.begin(), mStatic.end(), cmp);
typename std::vector<T>::iterator first, next;
next = first = mStatic.begin();
while (first != mStatic.end() && ++next != mStatic.end()) {
while (next != mStatic.end() && !cmp(*first, *next)) {
++next;
}
if (first != --next) {
std::swap(*first, *next);
}
first = ++next;
}
}
const T *search(int index) const {
T item;
item.mIndex = index;
iterator it =
std::lower_bound(mStatic.begin(), mStatic.end(), item, Compare());
if (it != mStatic.end() && it->mIndex == index) {
return &(*it);
}
return 0;
typename Static::const_iterator it = mStatic.find(index);
if (it != mStatic.end())
return &(it->second);
return NULL;
}
const T *find(int index) const {
@ -1103,18 +987,12 @@ namespace MWWorld
struct Store<ESM::Skill> : public IndexedStore<ESM::Skill>
{
Store() {}
Store(unsigned int size)
: IndexedStore<ESM::Skill>(size)
{}
};
template <>
struct Store<ESM::MagicEffect> : public IndexedStore<ESM::MagicEffect>
{
Store() {}
Store(unsigned int size)
: IndexedStore<ESM::MagicEffect>(size)
{}
};
template <>

@ -30,7 +30,14 @@ void Script::load(ESMReader &esm)
int s = mData.mStringTableSize;
std::vector<char> tmp (s);
esm.getHExact (&tmp[0], s);
// not using getHExact, vanilla doesn't seem to mind unused bytes at the end
esm.getSubHeader();
int left = esm.getSubSize();
if (left < s)
esm.fail("SCVR string list is smaller than specified");
esm.getExact(&tmp[0], s);
if (left > s)
esm.skip(left-s); // skip the leftover junk
// Set up the list of variable names
mVarNames.resize(mData.mNumShorts + mData.mNumLongs + mData.mNumFloats);

@ -350,8 +350,11 @@ struct NiMorphData : public Record
struct NiKeyframeData : public Record
{
QuaternionKeyMap mRotations;
//\FIXME mXYZ_Keys are read, but not used.
FloatKeyMap mXYZ_Keys;
FloatKeyMap mXRotations;
FloatKeyMap mYRotations;
FloatKeyMap mZRotations;
Vector3KeyMap mTranslations;
FloatKeyMap mScales;
@ -362,12 +365,9 @@ struct NiKeyframeData : public Record
{
//Chomp unused float
nif->getFloat();
for(size_t i=0;i<3;++i)
{
//Read concatenates items together.
mXYZ_Keys.read(nif,true);
}
nif->file->warn("XYZ_ROTATION_KEY read, but not used!");
mXRotations.read(nif, true);
mYRotations.read(nif, true);
mZRotations.read(nif, true);
}
mTranslations.read(nif);
mScales.read(nif);

@ -49,9 +49,7 @@ struct KeyMapT {
if(count == 0 && !force)
return;
//If we aren't forcing things, make sure that read clears any previous keys
if(!force)
mKeys.clear();
mKeys.clear();
mInterpolationType = nif->getUInt();
@ -88,7 +86,7 @@ struct KeyMapT {
//XYZ keys aren't actually read here.
//data.hpp sees that the last type read was sXYZInterpolation and:
// Eats a floating point number, then
// Re-runs the read function 3 more times, with force enabled so that the previous values aren't cleared.
// Re-runs the read function 3 more times.
// When it does that it's reading in a bunch of sLinearInterpolation keys, not sXYZInterpolation.
else if(mInterpolationType == sXYZInterpolation)
{

@ -161,6 +161,38 @@ void ObjectScene::rotateBillboardNodes(Ogre::Camera *camera)
}
}
void ObjectScene::_notifyAttached()
{
// convert initial particle positions to world space for world-space particle systems
// this can't be done on creation because the particle system is not in its correct world space position yet
for (std::vector<Ogre::ParticleSystem*>::iterator it = mParticles.begin(); it != mParticles.end(); ++it)
{
Ogre::ParticleSystem* psys = *it;
if (psys->getKeepParticlesInLocalSpace())
continue;
Ogre::ParticleIterator pi = psys->_getIterator();
while (!pi.end())
{
Ogre::Particle *p = pi.getNext();
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
Ogre::Vector3& position = p->mPosition;
Ogre::Vector3& direction = p->mDirection;
#else
Ogre::Vector3& position = p->position;
Ogre::Vector3& direction = p->direction;
#endif
position =
(psys->getParentNode()->_getDerivedOrientation() *
(psys->getParentNode()->_getDerivedScale() * position))
+ psys->getParentNode()->_getDerivedPosition();
direction =
(psys->getParentNode()->_getDerivedOrientation() * direction);
}
}
}
// Animates a texture
class FlipController
{
@ -410,6 +442,9 @@ public:
{
private:
const Nif::QuaternionKeyMap* mRotations;
const Nif::FloatKeyMap* mXRotations;
const Nif::FloatKeyMap* mYRotations;
const Nif::FloatKeyMap* mZRotations;
const Nif::Vector3KeyMap* mTranslations;
const Nif::FloatKeyMap* mScales;
Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid
@ -440,11 +475,25 @@ public:
return keys.rbegin()->second.mValue;
}
Ogre::Quaternion getXYZRotation(float time) const
{
float xrot = interpKey(mXRotations->mKeys, time);
float yrot = interpKey(mYRotations->mKeys, time);
float zrot = interpKey(mZRotations->mKeys, time);
Ogre::Quaternion xr(Ogre::Radian(xrot), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr(Ogre::Radian(yrot), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr(Ogre::Radian(zrot), Ogre::Vector3::UNIT_Z);
return (xr*yr*zr);
}
public:
/// @note The NiKeyFrameData must be valid as long as this KeyframeController exists.
Value(Ogre::Node *target, const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data)
: NodeTargetValue<Ogre::Real>(target)
, mRotations(&data->mRotations)
, mXRotations(&data->mXRotations)
, mYRotations(&data->mYRotations)
, mZRotations(&data->mZRotations)
, mTranslations(&data->mTranslations)
, mScales(&data->mScales)
, mNif(nif)
@ -454,6 +503,8 @@ public:
{
if(mRotations->mKeys.size() > 0)
return interpKey(mRotations->mKeys, time);
else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty())
return getXYZRotation(time);
return mNode->getOrientation();
}
@ -481,6 +532,8 @@ public:
{
if(mRotations->mKeys.size() > 0)
mNode->setOrientation(interpKey(mRotations->mKeys, time));
else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty())
mNode->setOrientation(getXYZRotation(time));
if(mTranslations->mKeys.size() > 0)
mNode->setPosition(interpKey(mTranslations->mKeys, time));
if(mScales->mKeys.size() > 0)
@ -949,6 +1002,8 @@ class NIFObjectLoader
createParticleEmitterAffectors(partsys, partctrl, trgtbone, scene->mSkelBase->getName());
}
createParticleInitialState(partsys, particledata, partctrl);
Ogre::ControllerValueRealPtr srcval((partflags&Nif::NiNode::ParticleFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
@ -975,6 +1030,50 @@ class NIFObjectLoader
createMaterialControllers(partnode, partsys, animflags, scene);
}
static void createParticleInitialState(Ogre::ParticleSystem* partsys, const Nif::NiAutoNormalParticlesData* particledata,
const Nif::NiParticleSystemController* partctrl)
{
partsys->_update(0.f); // seems to be required to allocate mFreeParticles
int i=0;
for (std::vector<Nif::NiParticleSystemController::Particle>::const_iterator it = partctrl->particles.begin();
i<particledata->activeCount && it != partctrl->particles.end(); ++it, ++i)
{
const Nif::NiParticleSystemController::Particle& particle = *it;
Ogre::Particle* created = partsys->createParticle();
if (!created)
break;
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
Ogre::Vector3& position = created->mPosition;
Ogre::Vector3& direction = created->mDirection;
Ogre::ColourValue& colour = created->mColour;
float& totalTimeToLive = created->mTotalTimeToLive;
float& timeToLive = created->mTimeToLive;
#else
Ogre::Vector3& position = created->position;
Ogre::Vector3& direction = created->direction;
Ogre::ColourValue& colour = created->colour;
float& totalTimeToLive = created->totalTimeToLive;
float& timeToLive = created->timeToLive;
#endif
direction = particle.velocity;
position = particledata->vertices.at(particle.vertex);
if (particle.vertex < int(particledata->colors.size()))
{
Ogre::Vector4 partcolour = particledata->colors.at(particle.vertex);
colour = Ogre::ColourValue(partcolour.x, partcolour.y, partcolour.z, partcolour.w);
}
else
colour = Ogre::ColourValue(1.f, 1.f, 1.f, 1.f);
float size = particledata->sizes.at(particle.vertex);
created->setDimensions(size, size);
totalTimeToLive = std::max(0.f, particle.lifespan);
timeToLive = std::max(0.f, particle.lifespan - particle.lifetime);
}
}
static void createNodeControllers(const Nif::NIFFilePtr& nif, const std::string &name, Nif::ControllerPtr ctrl, ObjectScenePtr scene, int animflags)
{
@ -1275,6 +1374,8 @@ ObjectScenePtr Loader::createObjects(Ogre::SceneNode *parentNode, std::string na
parentNode->attachObject(entity);
}
scene->_notifyAttached();
return scene;
}
@ -1342,6 +1443,8 @@ ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bo
}
}
scene->_notifyAttached();
return scene;
}

@ -84,6 +84,10 @@ struct ObjectScene {
void rotateBillboardNodes(Ogre::Camera* camera);
void setVisibilityFlags (unsigned int flags);
// This is called internally by the OgreNifLoader once all elements of the
// scene have been attached to their respective nodes.
void _notifyAttached();
};
typedef Ogre::SharedPtr<ObjectScene> ObjectScenePtr;

Loading…
Cancel
Save