mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
9ae69447d3
13 changed files with 176 additions and 191 deletions
|
@ -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;
|
||||
typedef std::map<std::string, ESM::Pathgrid> Interior;
|
||||
typedef std::map<std::pair<int, int>, ESM::Pathgrid> Exterior;
|
||||
|
||||
std::vector<ESM::Pathgrid>::iterator mIntBegin, mIntEnd, mExtBegin, mExtEnd;
|
||||
|
||||
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…
Reference in a new issue