mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 04:45:34 +00:00
Fixed race.cpp
This commit is contained in:
commit
1dff1fabdb
50 changed files with 1007 additions and 252 deletions
|
@ -439,7 +439,7 @@ void Record<ESM::Apparatus>::print()
|
|||
template<>
|
||||
void Record<ESM::BodyPart>::print()
|
||||
{
|
||||
std::cout << " Name: " << mData.mName << std::endl;
|
||||
std::cout << " Race: " << mData.mRace << std::endl;
|
||||
std::cout << " Model: " << mData.mModel << std::endl;
|
||||
std::cout << " Type: " << meshTypeLabel(mData.mData.mType)
|
||||
<< " (" << (int)mData.mData.mType << ")" << std::endl;
|
||||
|
|
|
@ -102,3 +102,9 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||
add_definitions (--coverage)
|
||||
target_link_libraries(omwlauncher gcov)
|
||||
endif()
|
||||
|
||||
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(omwlauncher dl Xt)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ opencs_units (model/world
|
|||
|
||||
|
||||
opencs_units_noqt (model/world
|
||||
universalid data record idcollection commands columnbase scriptcontext
|
||||
universalid data record idcollection commands columnbase scriptcontext cell
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/world
|
||||
|
|
20
apps/opencs/model/world/cell.cpp
Normal file
20
apps/opencs/model/world/cell.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
#include "cell.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
void CSMWorld::Cell::load (ESM::ESMReader &esm)
|
||||
{
|
||||
mName = mId;
|
||||
|
||||
ESM::Cell::load (esm, true); /// \todo set this to false, once the bug in ESM::Cell::load is fixed
|
||||
|
||||
if (!(mData.mFlags & Interior))
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "#" << mData.mX << " " << mData.mY;
|
||||
|
||||
mId = stream.str();
|
||||
}
|
||||
}
|
17
apps/opencs/model/world/cell.hpp
Normal file
17
apps/opencs/model/world/cell.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef CSM_WOLRD_CELL_H
|
||||
#define CSM_WOLRD_CELL_H
|
||||
|
||||
#include <components/esm/loadcell.hpp>
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
/// \brief Wrapper for Cell record
|
||||
struct Cell : public ESM::Cell
|
||||
{
|
||||
std::string mId;
|
||||
|
||||
void load (ESM::ESMReader &esm);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -748,6 +748,31 @@ namespace CSMWorld
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct RegionColumn : public Column<ESXRecordT>
|
||||
{
|
||||
RegionColumn() : Column<ESXRecordT> ("Region", ColumnBase::Display_String) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return QString::fromUtf8 (record.get().mRegion.c_str());
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mRegion = data.toString().toUtf8().constData();
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -119,6 +119,15 @@ CSMWorld::Data::Data()
|
|||
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Starter Spell", 0x2));
|
||||
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Always Succeeds", 0x4));
|
||||
|
||||
mCells.addColumn (new StringIdColumn<Cell>);
|
||||
mCells.addColumn (new RecordStateColumn<Cell>);
|
||||
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
|
||||
mCells.addColumn (new NameColumn<Cell>);
|
||||
mCells.addColumn (new FlagColumn<Cell> ("Sleep forbidden", ESM::Cell::NoSleep));
|
||||
mCells.addColumn (new FlagColumn<Cell> ("Interior Water", ESM::Cell::HasWater));
|
||||
mCells.addColumn (new FlagColumn<Cell> ("Interior Sky", ESM::Cell::QuasiEx));
|
||||
mCells.addColumn (new RegionColumn<Cell>);
|
||||
|
||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
|
||||
|
@ -130,6 +139,7 @@ CSMWorld::Data::Data()
|
|||
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
||||
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
||||
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
||||
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
||||
}
|
||||
|
||||
CSMWorld::Data::~Data()
|
||||
|
@ -248,6 +258,16 @@ CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
|
|||
return mSpells;
|
||||
}
|
||||
|
||||
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
|
||||
{
|
||||
return mCells;
|
||||
}
|
||||
|
||||
CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells()
|
||||
{
|
||||
return mCells;
|
||||
}
|
||||
|
||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
|
||||
{
|
||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||
|
@ -293,6 +313,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
|||
case ESM::REC_REGN: mRegions.load (reader, base); break;
|
||||
case ESM::REC_BSGN: mBirthsigns.load (reader, base); break;
|
||||
case ESM::REC_SPEL: mSpells.load (reader, base); break;
|
||||
case ESM::REC_CELL: mCells.load (reader, base); break;
|
||||
|
||||
default:
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "idcollection.hpp"
|
||||
#include "universalid.hpp"
|
||||
#include "cell.hpp"
|
||||
|
||||
class QAbstractItemModel;
|
||||
|
||||
|
@ -38,6 +39,7 @@ namespace CSMWorld
|
|||
IdCollection<ESM::Region> mRegions;
|
||||
IdCollection<ESM::BirthSign> mBirthsigns;
|
||||
IdCollection<ESM::Spell> mSpells;
|
||||
IdCollection<Cell> mCells;
|
||||
std::vector<QAbstractItemModel *> mModels;
|
||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||
|
||||
|
@ -98,6 +100,10 @@ namespace CSMWorld
|
|||
|
||||
IdCollection<ESM::Spell>& getSpells();
|
||||
|
||||
const IdCollection<Cell>& getCells() const;
|
||||
|
||||
IdCollection<Cell>& getCells();
|
||||
|
||||
QAbstractItemModel *getTableModel (const UniversalId& id);
|
||||
///< If no table model is available for \a id, an exception is thrown.
|
||||
///
|
||||
|
|
|
@ -325,10 +325,10 @@ namespace CSMWorld
|
|||
{
|
||||
std::string id = reader.getHNOString ("NAME");
|
||||
|
||||
int index = searchId (id);
|
||||
|
||||
if (reader.isNextSub ("DELE"))
|
||||
{
|
||||
int index = searchId (id);
|
||||
|
||||
reader.skipRecord();
|
||||
|
||||
if (index==-1)
|
||||
|
@ -354,6 +354,8 @@ namespace CSMWorld
|
|||
record.mId = id;
|
||||
record.load (reader);
|
||||
|
||||
int index = searchId (record.mId);
|
||||
|
||||
if (index==-1)
|
||||
{
|
||||
// new record
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace
|
|||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells" },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
};
|
||||
|
@ -45,6 +46,7 @@ namespace
|
|||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell" },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
};
|
||||
|
|
|
@ -55,7 +55,9 @@ namespace CSMWorld
|
|||
Type_Birthsigns,
|
||||
Type_Birthsign,
|
||||
Type_Spells,
|
||||
Type_Spell
|
||||
Type_Spell,
|
||||
Type_Cells,
|
||||
Type_Cell
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -125,6 +125,10 @@ void CSVDoc::View::setupWorldMenu()
|
|||
QAction *spells = new QAction (tr ("Spells"), this);
|
||||
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
|
||||
world->addAction (spells);
|
||||
|
||||
QAction *cells = new QAction (tr ("Cells"), this);
|
||||
connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView()));
|
||||
world->addAction (cells);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupUi()
|
||||
|
@ -325,6 +329,11 @@ void CSVDoc::View::addSpellsSubView()
|
|||
addSubView (CSMWorld::UniversalId::Type_Spells);
|
||||
}
|
||||
|
||||
void CSVDoc::View::addCellsSubView()
|
||||
{
|
||||
addSubView (CSMWorld::UniversalId::Type_Cells);
|
||||
}
|
||||
|
||||
void CSVDoc::View::abortOperation (int type)
|
||||
{
|
||||
mDocument->abortOperation (type);
|
||||
|
|
|
@ -133,6 +133,8 @@ namespace CSVDoc
|
|||
void addBirthsignsSubView();
|
||||
|
||||
void addSpellsSubView();
|
||||
|
||||
void addCellsSubView();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
CSMWorld::UniversalId::Type_Regions,
|
||||
CSMWorld::UniversalId::Type_Birthsigns,
|
||||
CSMWorld::UniversalId::Type_Spells,
|
||||
CSMWorld::UniversalId::Type_Cells,
|
||||
|
||||
CSMWorld::UniversalId::Type_None // end marker
|
||||
};
|
||||
|
|
|
@ -122,6 +122,12 @@ if (UNIX AND NOT APPLE)
|
|||
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(openmw dl Xt)
|
||||
endif()
|
||||
|
||||
|
||||
if(APPLE)
|
||||
find_library(CARBON_FRAMEWORK Carbon)
|
||||
find_library(COCOA_FRAMEWORK Cocoa)
|
||||
|
|
|
@ -161,7 +161,7 @@ void OMW::Engine::loadBSA()
|
|||
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||
{
|
||||
// Last data dir has the highest priority
|
||||
std::string groupName = "Data" + Ogre::StringConverter::toString(dataDirs.size()-i);
|
||||
std::string groupName = "Data" + Ogre::StringConverter::toString(dataDirs.size()-i, 8, '0');
|
||||
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
|
||||
|
||||
std::string dataDirectory = iter->string();
|
||||
|
@ -176,7 +176,7 @@ void OMW::Engine::loadBSA()
|
|||
if (mFileCollections.doesExist(*archive))
|
||||
{
|
||||
// Last BSA has the highest priority
|
||||
std::string groupName = "DataBSA" + Ogre::StringConverter::toString(dataDirs.size()-i);
|
||||
std::string groupName = "DataBSA" + Ogre::StringConverter::toString(mArchives.size()-i, 8, '0');
|
||||
|
||||
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
|
||||
|
||||
|
@ -368,6 +368,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
|
||||
mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoder, mFallbackMap,
|
||||
mActivationDistanceOverride));
|
||||
MWBase::Environment::get().getWorld()->setupPlayer(mNewGame);
|
||||
|
||||
//Load translation data
|
||||
mTranslationDataStorage.setEncoder(mEncoder);
|
||||
|
|
|
@ -321,6 +321,7 @@ namespace MWBase
|
|||
virtual void changeVanityModeScale(float factor) = 0;
|
||||
virtual bool vanityRotateCamera(float * rot) = 0;
|
||||
|
||||
virtual void setupPlayer(bool newGame) = 0;
|
||||
virtual void renderPlayer() = 0;
|
||||
|
||||
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
|
||||
|
|
|
@ -292,7 +292,7 @@ namespace MWClass
|
|||
ref->mBase = record;
|
||||
}
|
||||
|
||||
int Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
std::pair<int, std::string> Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
||||
|
||||
|
@ -317,10 +317,7 @@ namespace MWClass
|
|||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
{
|
||||
if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() )
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}");
|
||||
|
||||
return 0;
|
||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,9 +328,7 @@ namespace MWClass
|
|||
{
|
||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||
{
|
||||
if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() )
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}");
|
||||
return 0;
|
||||
return std::make_pair(0, "#{sNotifyMessage14}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +339,7 @@ namespace MWClass
|
|||
MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
|
||||
if(weapon == invStore.end())
|
||||
return 1;
|
||||
return std::make_pair(1,"");
|
||||
|
||||
if(weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
|
||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
|
||||
|
@ -354,12 +349,12 @@ namespace MWClass
|
|||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
|
||||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
|
||||
{
|
||||
return 3;
|
||||
return std::make_pair(3,"");
|
||||
}
|
||||
return 1;
|
||||
return std::make_pair(1,"");
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return std::make_pair(1,"");
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -67,8 +67,9 @@ namespace MWClass
|
|||
|
||||
virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
|
||||
|
||||
virtual int canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
|
||||
virtual std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. \n
|
||||
/// Second item in the pair specifies the error message
|
||||
|
||||
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
||||
const;
|
||||
|
|
|
@ -238,7 +238,7 @@ namespace MWClass
|
|||
ref->mBase = record;
|
||||
}
|
||||
|
||||
int Clothing::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
std::pair<int, std::string> Clothing::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
{
|
||||
// slots that this item can be equipped in
|
||||
std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
@ -260,12 +260,7 @@ namespace MWClass
|
|||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
{
|
||||
if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() )
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,19 +269,12 @@ namespace MWClass
|
|||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||
{
|
||||
if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() )
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return std::make_pair(0, "#{sNotifyMessage15}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return std::make_pair (1, "");
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -61,8 +61,9 @@ namespace MWClass
|
|||
|
||||
virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
|
||||
|
||||
virtual int canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
virtual std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
|
||||
/// Second item in the pair specifies the error message
|
||||
|
||||
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
||||
const;
|
||||
|
|
|
@ -384,7 +384,7 @@ namespace MWClass
|
|||
ref->mBase = record;
|
||||
}
|
||||
|
||||
int Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
{
|
||||
std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
|
@ -402,12 +402,12 @@ namespace MWClass
|
|||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
|
||||
{
|
||||
return 2;
|
||||
return std::make_pair (2, "");
|
||||
}
|
||||
return 1;
|
||||
return std::make_pair (1, "");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return std::make_pair (0, "");
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -67,8 +67,9 @@ namespace MWClass
|
|||
|
||||
virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
|
||||
|
||||
virtual int canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
virtual std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
|
||||
/// Second item in the pair specifies the error message
|
||||
|
||||
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
||||
const;
|
||||
|
|
|
@ -21,36 +21,6 @@ namespace
|
|||
else
|
||||
return index;
|
||||
}
|
||||
|
||||
int countParts(const std::string &part, const std::string &race, bool male)
|
||||
{
|
||||
/// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs
|
||||
const MWWorld::Store<ESM::BodyPart> &store =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
std::string prefix =
|
||||
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
|
||||
|
||||
std::string suffix;
|
||||
suffix.reserve(prefix.size() + 3);
|
||||
|
||||
int count = -1;
|
||||
do {
|
||||
++count;
|
||||
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
|
||||
}
|
||||
while (store.search(prefix + suffix) != 0);
|
||||
|
||||
if (count == 0 && part == "hair") {
|
||||
count = -1;
|
||||
do {
|
||||
++count;
|
||||
suffix = (boost::format("%02d") % (count + 1)).str();
|
||||
}
|
||||
while (store.search(prefix + suffix) != 0);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
|
@ -61,8 +31,6 @@ namespace MWGui
|
|||
, mGenderIndex(0)
|
||||
, mFaceIndex(0)
|
||||
, mHairIndex(0)
|
||||
, mFaceCount(10)
|
||||
, mHairCount(14)
|
||||
, mCurrentAngle(0)
|
||||
{
|
||||
// Centre dialog
|
||||
|
@ -227,67 +195,28 @@ namespace MWGui
|
|||
|
||||
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
|
||||
{
|
||||
do
|
||||
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
|
||||
while (!isFacePlayable());
|
||||
mFaceIndex = wrap(mFaceIndex - 1, mAvailableHeads.size());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectNextFace(MyGUI::Widget*)
|
||||
{
|
||||
do
|
||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||
while (!isFacePlayable());
|
||||
mFaceIndex = wrap(mFaceIndex + 1, mAvailableHeads.size());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
|
||||
{
|
||||
do
|
||||
mHairIndex = wrap(mHairIndex - 1, mHairCount);
|
||||
while (!isHairPlayable());
|
||||
mHairIndex = wrap(mHairIndex - 1, mAvailableHairs.size());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
||||
{
|
||||
do
|
||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||
while (!isHairPlayable());
|
||||
mHairIndex = wrap(mHairIndex + 1, mAvailableHairs.size());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
bool RaceDialog::isFacePlayable()
|
||||
{
|
||||
std::string prefix =
|
||||
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
||||
|
||||
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
|
||||
|
||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
if (parts.search(prefix + "head_" + headIndex) == 0)
|
||||
return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
else
|
||||
return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
}
|
||||
|
||||
bool RaceDialog::isHairPlayable()
|
||||
{
|
||||
std::string prefix =
|
||||
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
||||
|
||||
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
|
||||
|
||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
if (parts.search(prefix + "hair_" + hairIndex) == 0)
|
||||
return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
else
|
||||
return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
||||
{
|
||||
if (_index == MyGUI::ITEM_NONE)
|
||||
|
@ -308,18 +237,41 @@ namespace MWGui
|
|||
updateSpellPowers();
|
||||
}
|
||||
|
||||
void RaceDialog::getBodyParts (int part, std::vector<std::string>& out)
|
||||
{
|
||||
out.clear();
|
||||
const MWWorld::Store<ESM::BodyPart> &store =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
for (MWWorld::Store<ESM::BodyPart>::iterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
const ESM::BodyPart& bodypart = *it;
|
||||
if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable)
|
||||
continue;
|
||||
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
|
||||
continue;
|
||||
if (bodypart.mData.mPart != static_cast<ESM::BodyPart::MeshPart>(part))
|
||||
continue;
|
||||
if (mGenderIndex != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
|
||||
continue;
|
||||
bool firstPerson = (bodypart.mId.size() >= 3)
|
||||
&& bodypart.mId[bodypart.mId.size()-3] == '1'
|
||||
&& bodypart.mId[bodypart.mId.size()-2] == 's'
|
||||
&& bodypart.mId[bodypart.mId.size()-1] == 't';
|
||||
if (firstPerson)
|
||||
continue;
|
||||
if (Misc::StringUtils::ciEqual(bodypart.mRace, mCurrentRaceId))
|
||||
out.push_back(bodypart.mId);
|
||||
}
|
||||
}
|
||||
|
||||
void RaceDialog::recountParts()
|
||||
{
|
||||
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0);
|
||||
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0);
|
||||
getBodyParts(ESM::BodyPart::MP_Hair, mAvailableHairs);
|
||||
getBodyParts(ESM::BodyPart::MP_Head, mAvailableHeads);
|
||||
|
||||
mFaceIndex = 0;
|
||||
mHairIndex = 0;
|
||||
|
||||
while (!isHairPlayable())
|
||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||
while (!isFacePlayable())
|
||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||
}
|
||||
|
||||
// update widget content
|
||||
|
@ -330,21 +282,9 @@ namespace MWGui
|
|||
record.mRace = mCurrentRaceId;
|
||||
record.setIsMale(mGenderIndex == 0);
|
||||
|
||||
std::string prefix =
|
||||
"b_n_" + mCurrentRaceId + ((record.isMale()) ? "_m_" : "_f_");
|
||||
record.mHead = mAvailableHeads[mFaceIndex];
|
||||
record.mHair = mAvailableHairs[mHairIndex];
|
||||
|
||||
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
|
||||
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
|
||||
|
||||
record.mHead = prefix + "head_" + headIndex;
|
||||
record.mHair = prefix + "hair_" + hairIndex;
|
||||
|
||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
if (parts.search(record.mHair) == 0) {
|
||||
record.mHair = prefix + "hair" + hairIndex;
|
||||
}
|
||||
mPreview->setPrototype(record);
|
||||
}
|
||||
|
||||
|
@ -442,5 +382,4 @@ namespace MWGui
|
|||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -76,8 +76,10 @@ namespace MWGui
|
|||
void updatePreview();
|
||||
void recountParts();
|
||||
|
||||
bool isHairPlayable();
|
||||
bool isFacePlayable();
|
||||
void getBodyParts (int part, std::vector<std::string>& out);
|
||||
|
||||
std::vector<std::string> mAvailableHeads;
|
||||
std::vector<std::string> mAvailableHairs;
|
||||
|
||||
MyGUI::ImageBox* mPreviewImage;
|
||||
MyGUI::ListBox* mRaceList;
|
||||
|
@ -90,7 +92,6 @@ namespace MWGui
|
|||
std::vector<MyGUI::Widget*> mSpellPowerItems;
|
||||
|
||||
int mGenderIndex, mFaceIndex, mHairIndex;
|
||||
int mFaceCount, mHairCount;
|
||||
|
||||
std::string mCurrentRaceId;
|
||||
|
||||
|
|
|
@ -134,21 +134,22 @@ namespace MWGui
|
|||
int x,y;
|
||||
bool interior = _sender->getUserString("interior") == "y";
|
||||
MWBase::Environment::get().getWorld()->positionToIndex(pos.pos[0],pos.pos[1],x,y);
|
||||
MWWorld::CellStore* cell;
|
||||
if(interior) cell = MWBase::Environment::get().getWorld()->getInterior(cellname);
|
||||
if(interior)
|
||||
MWBase::Environment::get().getWorld()->changeToInteriorCell(cellname, pos);
|
||||
else
|
||||
{
|
||||
cell = MWBase::Environment::get().getWorld()->getExterior(x,y);
|
||||
ESM::Position PlayerPos = player.getRefData().getPosition();
|
||||
float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) );
|
||||
int time = int(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->getFloat());
|
||||
for(int i = 0;i < time;i++)
|
||||
ESM::Position playerPos = player.getRefData().getPosition();
|
||||
float d = Ogre::Vector3(pos.pos[0], pos.pos[1], 0).distance(
|
||||
Ogre::Vector3(playerPos.pos[0], playerPos.pos[1], 0));
|
||||
int hours = static_cast<int>(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->getFloat());
|
||||
for(int i = 0;i < hours;i++)
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager ()->restoreDynamicStats ();
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->advanceTime(time);
|
||||
MWBase::Environment::get().getWorld()->advanceTime(hours);
|
||||
|
||||
MWBase::Environment::get().getWorld()->changeToExteriorCell(pos);
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->moveObject(player,*cell,pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||
|
||||
MWWorld::Class::get(player).adjustPosition(player);
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel);
|
||||
|
|
|
@ -155,6 +155,18 @@ namespace MWMechanics
|
|||
stat.setCurrent (stat.getModified());
|
||||
creatureStats.setDynamic (i, stat);
|
||||
}
|
||||
|
||||
// unequip any items that may not be equipped. we need this for when the race is changed to a beast race
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore(ptr);
|
||||
for (int i=0; i<MWWorld::InventoryStore::Slots; ++i)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator it = invStore.getSlot(i);
|
||||
if (it != invStore.end())
|
||||
{
|
||||
if (!MWWorld::Class::get(*it).canBeEquipped(*it, ptr).first)
|
||||
invStore.equip(i, invStore.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MechanicsManager::MechanicsManager()
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace MWMechanics
|
|||
const ESM::Spell *spell =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (iter->first);
|
||||
|
||||
if (spell->mData.mFlags & ESM::Spell::ST_Disease)
|
||||
if (spell->mData.mType == ESM::Spell::ST_Disease)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ namespace MWMechanics
|
|||
const ESM::Spell *spell =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (iter->first);
|
||||
|
||||
if (spell->mData.mFlags & ESM::Spell::ST_Blight)
|
||||
if (spell->mData.mType == ESM::Spell::ST_Blight)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,9 @@ void Actors::insertActivator (const MWWorld::Ptr& ptr)
|
|||
|
||||
bool Actors::deleteObject (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
if (mAllActors.find(ptr) == mAllActors.end())
|
||||
return false;
|
||||
|
||||
mRendering->removeWaterRippleEmitter (ptr);
|
||||
|
||||
delete mAllActors[ptr];
|
||||
|
@ -139,6 +142,7 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store)
|
|||
Ogre::SceneNode *base = celliter->second;
|
||||
base->removeAndDestroyAllChildren();
|
||||
mRend.getScene()->destroySceneNode(base);
|
||||
|
||||
mCellSceneNodes.erase(celliter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -305,56 +305,83 @@ void NpcAnimation::updateParts(bool forceupdate)
|
|||
if(mViewMode == VM_HeadOnly)
|
||||
return;
|
||||
|
||||
static const struct {
|
||||
ESM::PartReferenceType type;
|
||||
const char name[2][12];
|
||||
} PartTypeList[] = {
|
||||
{ ESM::PRT_Neck, { "neck", "" } },
|
||||
{ ESM::PRT_Cuirass, { "chest", "" } },
|
||||
{ ESM::PRT_Groin, { "groin", "" } },
|
||||
{ ESM::PRT_RHand, { "hand", "hands" } },
|
||||
{ ESM::PRT_LHand, { "hand", "hands" } },
|
||||
{ ESM::PRT_RWrist, { "wrist", "" } },
|
||||
{ ESM::PRT_LWrist, { "wrist", "" } },
|
||||
{ ESM::PRT_RForearm, { "forearm", "" } },
|
||||
{ ESM::PRT_LForearm, { "forearm", "" } },
|
||||
{ ESM::PRT_RUpperarm, { "upper arm", "" } },
|
||||
{ ESM::PRT_LUpperarm, { "upper arm", "" } },
|
||||
{ ESM::PRT_RFoot, { "foot", "feet" } },
|
||||
{ ESM::PRT_LFoot, { "foot", "feet" } },
|
||||
{ ESM::PRT_RAnkle, { "ankle", "" } },
|
||||
{ ESM::PRT_LAnkle, { "ankle", "" } },
|
||||
{ ESM::PRT_RKnee, { "knee", "" } },
|
||||
{ ESM::PRT_LKnee, { "knee", "" } },
|
||||
{ ESM::PRT_RLeg, { "upper leg", "" } },
|
||||
{ ESM::PRT_LLeg, { "upper leg", "" } },
|
||||
{ ESM::PRT_Tail, { "tail", "" } }
|
||||
};
|
||||
std::map<int, int> bodypartMap;
|
||||
bodypartMap[ESM::PRT_Neck] = ESM::BodyPart::MP_Neck;
|
||||
bodypartMap[ESM::PRT_Cuirass] = ESM::BodyPart::MP_Chest;
|
||||
bodypartMap[ESM::PRT_Groin] = ESM::BodyPart::MP_Groin;
|
||||
bodypartMap[ESM::PRT_RHand] = ESM::BodyPart::MP_Hand;
|
||||
bodypartMap[ESM::PRT_LHand] = ESM::BodyPart::MP_Hand;
|
||||
bodypartMap[ESM::PRT_RWrist] = ESM::BodyPart::MP_Wrist;
|
||||
bodypartMap[ESM::PRT_LWrist] = ESM::BodyPart::MP_Wrist;
|
||||
bodypartMap[ESM::PRT_RForearm] = ESM::BodyPart::MP_Forearm;
|
||||
bodypartMap[ESM::PRT_LForearm] = ESM::BodyPart::MP_Forearm;
|
||||
bodypartMap[ESM::PRT_RUpperarm] = ESM::BodyPart::MP_Upperarm;
|
||||
bodypartMap[ESM::PRT_LUpperarm] = ESM::BodyPart::MP_Upperarm;
|
||||
bodypartMap[ESM::PRT_RFoot] = ESM::BodyPart::MP_Foot;
|
||||
bodypartMap[ESM::PRT_LFoot] = ESM::BodyPart::MP_Foot;
|
||||
bodypartMap[ESM::PRT_RAnkle] = ESM::BodyPart::MP_Ankle;
|
||||
bodypartMap[ESM::PRT_LAnkle] = ESM::BodyPart::MP_Ankle;
|
||||
bodypartMap[ESM::PRT_RKnee] = ESM::BodyPart::MP_Knee;
|
||||
bodypartMap[ESM::PRT_LKnee] = ESM::BodyPart::MP_Knee;
|
||||
bodypartMap[ESM::PRT_RLeg] = ESM::BodyPart::MP_Upperleg;
|
||||
bodypartMap[ESM::PRT_LLeg] = ESM::BodyPart::MP_Upperleg;
|
||||
bodypartMap[ESM::PRT_Tail] = ESM::BodyPart::MP_Tail;
|
||||
|
||||
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++)
|
||||
|
||||
const int Flag_Female = 0x01;
|
||||
const int Flag_FirstPerson = 0x02;
|
||||
|
||||
int flags = 0;
|
||||
if (!mNpc->isMale())
|
||||
flags |= Flag_Female;
|
||||
if (mViewMode == VM_FirstPerson)
|
||||
flags |= Flag_FirstPerson;
|
||||
|
||||
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
|
||||
static std::map< std::pair<std::string, int> , std::vector<const ESM::BodyPart*> > sRaceMapping;
|
||||
std::string race = Misc::StringUtils::lowerCase(mNpc->mRace);
|
||||
std::pair<std::string, int> thisCombination = std::make_pair(race, flags);
|
||||
if (sRaceMapping.find(thisCombination) == sRaceMapping.end())
|
||||
{
|
||||
if(mPartPriorities[PartTypeList[i].type] < 1)
|
||||
sRaceMapping[thisCombination].resize(ESM::PRT_Count);
|
||||
for (int i=0; i<ESM::PRT_Count; ++i)
|
||||
sRaceMapping[thisCombination][i] = NULL;
|
||||
|
||||
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
||||
|
||||
for (MWWorld::Store<ESM::BodyPart>::iterator it = partStore.begin(); it != partStore.end(); ++it)
|
||||
{
|
||||
const ESM::BodyPart *part = NULL;
|
||||
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
||||
|
||||
if(!mNpc->isMale())
|
||||
const ESM::BodyPart& bodypart = *it;
|
||||
if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable)
|
||||
continue;
|
||||
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
|
||||
{
|
||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]+ext);
|
||||
if(part == 0)
|
||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]+ext);
|
||||
continue;
|
||||
}
|
||||
if(part == 0)
|
||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]+ext);
|
||||
if(part == 0)
|
||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]+ext);
|
||||
if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
|
||||
continue;
|
||||
if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace))
|
||||
continue;
|
||||
|
||||
if(part)
|
||||
addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel);
|
||||
bool firstPerson = (bodypart.mId.size() >= 3)
|
||||
&& bodypart.mId[bodypart.mId.size()-3] == '1'
|
||||
&& bodypart.mId[bodypart.mId.size()-2] == 's'
|
||||
&& bodypart.mId[bodypart.mId.size()-1] == 't';
|
||||
if (firstPerson != (mViewMode == VM_FirstPerson))
|
||||
continue;
|
||||
for (std::map<int, int>::iterator bIt = bodypartMap.begin(); bIt != bodypartMap.end(); ++bIt )
|
||||
if (bIt->second == bodypart.mData.mPart)
|
||||
sRaceMapping[thisCombination][bIt->first] = &*it;
|
||||
}
|
||||
}
|
||||
|
||||
for (int part = ESM::PRT_Neck; part < ESM::PRT_Count; ++part)
|
||||
{
|
||||
const ESM::BodyPart* bodypart = sRaceMapping[thisCombination][part];
|
||||
if (mPartPriorities[part] < 1 && bodypart)
|
||||
addOrReplaceIndividualPart(part, -1,1, "meshes\\"+bodypart->mModel);
|
||||
}
|
||||
}
|
||||
|
||||
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename)
|
||||
|
|
|
@ -788,8 +788,8 @@ void VideoState::decode_thread_loop(VideoState *self)
|
|||
// main decode loop
|
||||
while(!self->quit)
|
||||
{
|
||||
if((self->audio_st >= 0 && self->audioq.size > MAX_AUDIOQ_SIZE) ||
|
||||
(self->video_st >= 0 && self->videoq.size > MAX_VIDEOQ_SIZE))
|
||||
if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) ||
|
||||
(self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE))
|
||||
{
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
|
||||
continue;
|
||||
|
|
|
@ -21,7 +21,13 @@ namespace MWWorld
|
|||
MWWorld::Ptr object = getTarget();
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor);
|
||||
|
||||
switch(MWWorld::Class::get (object).canBeEquipped (object, actor))
|
||||
std::pair <int, std::string> result = MWWorld::Class::get (object).canBeEquipped (object, actor);
|
||||
|
||||
// display error message if the player tried to equip something
|
||||
if (!result.second.empty() && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer())
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(result.second);
|
||||
|
||||
switch(result.first)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
|
@ -48,8 +54,6 @@ namespace MWWorld
|
|||
|
||||
assert(it != invStore.end());
|
||||
|
||||
std::string npcRace = actor.get<ESM::NPC>()->mBase->mRace;
|
||||
|
||||
bool equipped = false;
|
||||
|
||||
// equip the item in the first free slot
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace ESM
|
|||
|
||||
namespace MWWorld
|
||||
{
|
||||
/// List all (Ogre-)handles.
|
||||
struct ListHandles
|
||||
/// List all (Ogre-)handles, then reset RefData::mBaseNode to 0.
|
||||
struct ListAndResetHandles
|
||||
{
|
||||
std::vector<Ogre::SceneNode*> mHandles;
|
||||
|
||||
|
@ -23,6 +23,8 @@ namespace MWWorld
|
|||
Ogre::SceneNode* handle = data.getBaseNode();
|
||||
if (handle)
|
||||
mHandles.push_back (handle);
|
||||
|
||||
data.setBaseNode(0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -165,6 +165,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
|
|||
else
|
||||
return Ptr();
|
||||
}
|
||||
|
||||
MWWorld::Ptr ptr;
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Activator> *ref = cell.mActivators.find (name))
|
||||
|
@ -246,16 +247,16 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
|||
}
|
||||
|
||||
// Then check cells that are already listed
|
||||
for (std::map<std::string, Ptr::CellStore>::iterator iter = mInteriors.begin();
|
||||
iter!=mInteriors.end(); ++iter)
|
||||
for (std::map<std::pair<int, int>, Ptr::CellStore>::iterator iter = mExteriors.begin();
|
||||
iter!=mExteriors.end(); ++iter)
|
||||
{
|
||||
Ptr ptr = getPtrAndCache (name, iter->second);
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
for (std::map<std::pair<int, int>, Ptr::CellStore>::iterator iter = mExteriors.begin();
|
||||
iter!=mExteriors.end(); ++iter)
|
||||
for (std::map<std::string, Ptr::CellStore>::iterator iter = mInteriors.begin();
|
||||
iter!=mInteriors.end(); ++iter)
|
||||
{
|
||||
Ptr ptr = getPtrAndCache (name, iter->second);
|
||||
if (!ptr.isEmpty())
|
||||
|
@ -266,7 +267,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
|||
const MWWorld::Store<ESM::Cell> &cells = mStore.get<ESM::Cell>();
|
||||
MWWorld::Store<ESM::Cell>::iterator iter;
|
||||
|
||||
for (iter = cells.intBegin(); iter != cells.intEnd(); ++iter)
|
||||
for (iter = cells.extBegin(); iter != cells.extEnd(); ++iter)
|
||||
{
|
||||
Ptr::CellStore *cellStore = getCellStore (&(*iter));
|
||||
|
||||
|
@ -276,7 +277,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
for (iter = cells.extBegin(); iter != cells.extEnd(); ++iter)
|
||||
for (iter = cells.intBegin(); iter != cells.intEnd(); ++iter)
|
||||
{
|
||||
Ptr::CellStore *cellStore = getCellStore (&(*iter));
|
||||
|
||||
|
|
|
@ -264,9 +264,9 @@ namespace MWWorld
|
|||
throw std::runtime_error ("class can't be enchanted");
|
||||
}
|
||||
|
||||
int Class::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
std::pair<int, std::string> Class::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
{
|
||||
return 1;
|
||||
return std::make_pair (1, "");
|
||||
}
|
||||
|
||||
void Class::adjustPosition(const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -245,8 +245,9 @@ namespace MWWorld
|
|||
|
||||
virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
|
||||
|
||||
virtual int canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
virtual std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
|
||||
/// Second item in the pair specifies the error message
|
||||
|
||||
virtual Ptr
|
||||
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
||||
|
|
|
@ -186,7 +186,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
|
|||
}
|
||||
}
|
||||
|
||||
switch(MWWorld::Class::get (test).canBeEquipped (test, npc))
|
||||
switch(MWWorld::Class::get (test).canBeEquipped (test, npc).first)
|
||||
{
|
||||
case 0:
|
||||
continue;
|
||||
|
|
|
@ -76,27 +76,28 @@ namespace MWWorld
|
|||
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
||||
{
|
||||
std::cout << "Unloading cell\n";
|
||||
ListHandles functor;
|
||||
ListAndResetHandles functor;
|
||||
|
||||
(*iter)->forEach<ListHandles>(functor);
|
||||
(*iter)->forEach<ListAndResetHandles>(functor);
|
||||
{
|
||||
// silence annoying g++ warning
|
||||
for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin());
|
||||
iter2!=functor.mHandles.end(); ++iter2){
|
||||
Ogre::SceneNode* node = *iter2;
|
||||
iter2!=functor.mHandles.end(); ++iter2)
|
||||
{
|
||||
Ogre::SceneNode* node = *iter2;
|
||||
mPhysics->removeObject (node->getName());
|
||||
}
|
||||
}
|
||||
|
||||
if ((*iter)->mCell->isExterior())
|
||||
{
|
||||
ESM::Land* land =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(
|
||||
(*iter)->mCell->getGridX(),
|
||||
(*iter)->mCell->getGridY()
|
||||
);
|
||||
if (land)
|
||||
mPhysics->removeHeightField( (*iter)->mCell->getGridX(), (*iter)->mCell->getGridY() );
|
||||
}
|
||||
if ((*iter)->mCell->isExterior())
|
||||
{
|
||||
ESM::Land* land =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(
|
||||
(*iter)->mCell->getGridX(),
|
||||
(*iter)->mCell->getGridY()
|
||||
);
|
||||
if (land)
|
||||
mPhysics->removeHeightField( (*iter)->mCell->getGridX(), (*iter)->mCell->getGridY() );
|
||||
}
|
||||
|
||||
mRendering.removeCell(*iter);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "manualref.hpp"
|
||||
#include "cellfunctors.hpp"
|
||||
#include "containerstore.hpp"
|
||||
#include "inventorystore.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
|
||||
|
@ -210,9 +211,6 @@ namespace MWWorld
|
|||
|
||||
mStore.setUp();
|
||||
|
||||
mPlayer = new MWWorld::Player (mStore.get<ESM::NPC>().find ("player"), *this);
|
||||
mRendering->attachCameraTo(mPlayer->getPlayer());
|
||||
|
||||
// global variables
|
||||
mGlobalVariables = new Globals (mStore);
|
||||
|
||||
|
@ -801,8 +799,8 @@ namespace MWWorld
|
|||
|
||||
void World::scaleObject (const Ptr& ptr, float scale)
|
||||
{
|
||||
MWWorld::Class::get(ptr).adjustScale(ptr,scale);
|
||||
ptr.getCellRef().mScale = scale;
|
||||
MWWorld::Class::get(ptr).adjustScale(ptr,scale);
|
||||
|
||||
if(ptr.getRefData().getBaseNode() == 0)
|
||||
return;
|
||||
|
@ -1369,6 +1367,18 @@ namespace MWWorld
|
|||
return mRendering->vanityRotateCamera(rot);
|
||||
}
|
||||
|
||||
void World::setupPlayer(bool newGame)
|
||||
{
|
||||
const ESM::NPC* player = mStore.get<ESM::NPC>().find ("player");
|
||||
mPlayer = new MWWorld::Player (player, *this);
|
||||
mRendering->attachCameraTo(mPlayer->getPlayer());
|
||||
if (newGame)
|
||||
{
|
||||
MWWorld::Class::get(mPlayer->getPlayer()).getContainerStore(mPlayer->getPlayer()).fill(player->mInventory, "", mStore);
|
||||
MWWorld::Class::get(mPlayer->getPlayer()).getInventoryStore(mPlayer->getPlayer()).autoEquip (mPlayer->getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
void World::renderPlayer()
|
||||
{
|
||||
mRendering->renderPlayer(mPlayer->getPlayer());
|
||||
|
|
|
@ -363,6 +363,7 @@ namespace MWWorld
|
|||
|
||||
virtual bool vanityRotateCamera(float * rot);
|
||||
|
||||
virtual void setupPlayer(bool newGame);
|
||||
virtual void renderPlayer();
|
||||
|
||||
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
|
||||
|
|
|
@ -38,7 +38,9 @@ enum PartReferenceType
|
|||
PRT_RPauldron = 23,
|
||||
PRT_LPauldron = 24,
|
||||
PRT_Weapon = 25,
|
||||
PRT_Tail = 26
|
||||
PRT_Tail = 26,
|
||||
|
||||
PRT_Count = 27
|
||||
};
|
||||
|
||||
// Reference to body parts
|
||||
|
|
|
@ -9,13 +9,13 @@ namespace ESM
|
|||
void BodyPart::load(ESMReader &esm)
|
||||
{
|
||||
mModel = esm.getHNString("MODL");
|
||||
mName = esm.getHNString("FNAM");
|
||||
mRace = esm.getHNString("FNAM");
|
||||
esm.getHNT(mData, "BYDT", 4);
|
||||
}
|
||||
void BodyPart::save(ESMWriter &esm)
|
||||
{
|
||||
esm.writeHNCString("MODL", mModel);
|
||||
esm.writeHNCString("FNAM", mName);
|
||||
esm.writeHNCString("FNAM", mRace);
|
||||
esm.writeHNT("BYDT", mData, 4);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,9 @@ struct BodyPart
|
|||
MP_Knee = 11,
|
||||
MP_Upperleg = 12,
|
||||
MP_Clavicle = 13,
|
||||
MP_Tail = 14
|
||||
MP_Tail = 14,
|
||||
|
||||
MP_Count = 15
|
||||
};
|
||||
|
||||
enum Flags
|
||||
|
@ -52,7 +54,7 @@ struct BodyPart
|
|||
};
|
||||
|
||||
BYDTstruct mData;
|
||||
std::string mId, mModel, mName;
|
||||
std::string mId, mModel, mRace;
|
||||
|
||||
void load(ESMReader &esm);
|
||||
void save(ESMWriter &esm);
|
||||
|
|
|
@ -356,4 +356,22 @@ bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Cell::blank()
|
||||
{
|
||||
mName.clear();
|
||||
mRegion.clear();
|
||||
mWater = 0;
|
||||
mWaterInt = false;
|
||||
mMapColor = 0;
|
||||
mNAM0 = 0;
|
||||
|
||||
mData.mFlags = 0;
|
||||
mData.mX = 0;
|
||||
mData.mY = 0;
|
||||
|
||||
mAmbi.mAmbient = 0;
|
||||
mAmbi.mSunlight = 0;
|
||||
mAmbi.mFog = 0;
|
||||
mAmbi.mFogDensity = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,9 @@ struct Cell
|
|||
* Since they are comparably rare, we use a separate method for this.
|
||||
*/
|
||||
static bool getNextMVRF(ESMReader &esm, MovedCellRef &mref);
|
||||
|
||||
void blank();
|
||||
///< Set record to default state (does not touch the ID/index).
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -351,14 +351,19 @@ class NIFObjectLoader
|
|||
|
||||
static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl)
|
||||
{
|
||||
Ogre::ParticleEmitter *emitter = partsys->addEmitter("Point");
|
||||
emitter->setDirection(Ogre::Vector3(0.0f, 0.0f, std::cos(partctrl->verticalDir)));
|
||||
emitter->setAngle(Ogre::Radian(partctrl->verticalAngle));
|
||||
Ogre::ParticleEmitter *emitter = partsys->addEmitter("Nif");
|
||||
emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom,
|
||||
partctrl->velocity+partctrl->velocityRandom);
|
||||
emitter->setEmissionRate(partctrl->emitRate);
|
||||
emitter->setTimeToLive(partctrl->lifetime-partctrl->lifetimeRandom,
|
||||
partctrl->lifetime+partctrl->lifetimeRandom);
|
||||
emitter->setParameter("width", Ogre::StringConverter::toString(partctrl->offsetRandom.x));
|
||||
emitter->setParameter("height", Ogre::StringConverter::toString(partctrl->offsetRandom.y));
|
||||
emitter->setParameter("depth", Ogre::StringConverter::toString(partctrl->offsetRandom.z));
|
||||
emitter->setParameter("vertical_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalDir).valueDegrees()));
|
||||
emitter->setParameter("vertical_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalAngle).valueDegrees()));
|
||||
emitter->setParameter("horizontal_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalDir).valueDegrees()));
|
||||
emitter->setParameter("horizontal_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalAngle).valueDegrees()));
|
||||
|
||||
Nif::ExtraPtr e = partctrl->extra;
|
||||
while(!e.empty())
|
||||
|
@ -366,21 +371,44 @@ class NIFObjectLoader
|
|||
if(e->recType == Nif::RC_NiParticleGrowFade)
|
||||
{
|
||||
const Nif::NiParticleGrowFade *gf = static_cast<const Nif::NiParticleGrowFade*>(e.getPtr());
|
||||
|
||||
Ogre::ParticleAffector *affector = partsys->addAffector("GrowFade");
|
||||
affector->setParameter("grow_time", Ogre::StringConverter::toString(gf->growTime));
|
||||
affector->setParameter("fade_time", Ogre::StringConverter::toString(gf->fadeTime));
|
||||
}
|
||||
else if(e->recType == Nif::RC_NiParticleRotation)
|
||||
else if(e->recType == Nif::RC_NiGravity)
|
||||
{
|
||||
// TODO: Implement (Ogre::RotationAffector?)
|
||||
const Nif::NiGravity *gr = static_cast<const Nif::NiGravity*>(e.getPtr());
|
||||
|
||||
Ogre::ParticleAffector *affector = partsys->addAffector("Gravity");
|
||||
affector->setParameter("force", Ogre::StringConverter::toString(gr->mForce));
|
||||
affector->setParameter("force_type", (gr->mType==0) ? "wind" : "point");
|
||||
affector->setParameter("direction", Ogre::StringConverter::toString(gr->mDirection));
|
||||
affector->setParameter("position", Ogre::StringConverter::toString(gr->mPosition));
|
||||
}
|
||||
else if(e->recType == Nif::RC_NiParticleColorModifier)
|
||||
{
|
||||
// TODO: Implement (Ogre::ColourInterpolatorAffector?)
|
||||
const Nif::NiParticleColorModifier *cl = static_cast<const Nif::NiParticleColorModifier*>(e.getPtr());
|
||||
const Nif::NiColorData *clrdata = cl->data.getPtr();
|
||||
|
||||
Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator");
|
||||
size_t num_colors = std::min<size_t>(6, clrdata->mKeyList.mKeys.size());
|
||||
for(size_t i = 0;i < num_colors;i++)
|
||||
{
|
||||
Ogre::ColourValue color;
|
||||
color.r = clrdata->mKeyList.mKeys[i].mValue[0];
|
||||
color.g = clrdata->mKeyList.mKeys[i].mValue[1];
|
||||
color.b = clrdata->mKeyList.mKeys[i].mValue[2];
|
||||
color.a = clrdata->mKeyList.mKeys[i].mValue[3];
|
||||
affector->setParameter("colour"+Ogre::StringConverter::toString(i),
|
||||
Ogre::StringConverter::toString(color));
|
||||
affector->setParameter("time"+Ogre::StringConverter::toString(i),
|
||||
Ogre::StringConverter::toString(clrdata->mKeyList.mKeys[i].mTime));
|
||||
}
|
||||
}
|
||||
else if(e->recType == Nif::RC_NiGravity)
|
||||
else if(e->recType == Nif::RC_NiParticleRotation)
|
||||
{
|
||||
// TODO: Implement
|
||||
// TODO: Implement (Ogre::RotationAffector?)
|
||||
}
|
||||
else
|
||||
warn("Unhandled particle modifier "+e->recName);
|
||||
|
@ -424,6 +452,9 @@ class NIFObjectLoader
|
|||
particledata->particleRadius*2.0f);
|
||||
partsys->setCullIndividually(false);
|
||||
partsys->setParticleQuota(particledata->numParticles);
|
||||
// TODO: There is probably a field or flag to specify this, as some
|
||||
// particle effects have it and some don't.
|
||||
partsys->setKeepParticlesInLocalSpace(true);
|
||||
|
||||
Nif::ControllerPtr ctrl = partnode->controller;
|
||||
while(!ctrl.empty())
|
||||
|
@ -461,7 +492,7 @@ class NIFObjectLoader
|
|||
|
||||
static void createObjects(const std::string &name, const std::string &group,
|
||||
Ogre::SceneManager *sceneMgr, const Nif::Node *node,
|
||||
ObjectList &objectlist, int flags=0)
|
||||
ObjectList &objectlist, int flags)
|
||||
{
|
||||
// Do not create objects for the collision shape (includes all children)
|
||||
if(node->recType == Nif::RC_RootCollisionNode)
|
||||
|
@ -578,8 +609,8 @@ class NIFObjectLoader
|
|||
}
|
||||
}
|
||||
|
||||
if(node->recType == Nif::RC_NiAutoNormalParticles ||
|
||||
node->recType == Nif::RC_NiRotatingParticles)
|
||||
if((node->recType == Nif::RC_NiAutoNormalParticles ||
|
||||
node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x40000000))
|
||||
{
|
||||
Ogre::ParticleSystem *partsys = createParticleSystem(name, group, sceneMgr, objectlist.mSkelBase, node);
|
||||
if(partsys != NULL)
|
||||
|
@ -607,8 +638,7 @@ class NIFObjectLoader
|
|||
{
|
||||
/* This creates an empty mesh to which a skeleton gets attached. This
|
||||
* is to ensure we have an entity with a skeleton instance, even if all
|
||||
* other meshes are hidden or entities attached to a specific node
|
||||
* instead of skinned. */
|
||||
* other entities are attached to bones and not skinned. */
|
||||
Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton();
|
||||
if(meshMgr.getByName(name).isNull())
|
||||
NIFMeshLoader::createMesh(name, name, group, ~(size_t)0);
|
||||
|
@ -618,7 +648,7 @@ class NIFObjectLoader
|
|||
}
|
||||
|
||||
public:
|
||||
static void load(Ogre::SceneManager *sceneMgr, ObjectList &objectlist, const std::string &name, const std::string &group)
|
||||
static void load(Ogre::SceneManager *sceneMgr, ObjectList &objectlist, const std::string &name, const std::string &group, int flags=0)
|
||||
{
|
||||
Nif::NIFFile::ptr nif = Nif::NIFFile::create(name);
|
||||
if(nif->numRoots() < 1)
|
||||
|
@ -644,7 +674,7 @@ public:
|
|||
// Create a base skeleton entity if this NIF needs one
|
||||
createSkelBase(name, group, sceneMgr, node, objectlist);
|
||||
}
|
||||
createObjects(name, group, sceneMgr, node, objectlist);
|
||||
createObjects(name, group, sceneMgr, node, objectlist, flags);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -732,7 +762,7 @@ ObjectList Loader::createObjectBase(Ogre::SceneManager *sceneMgr, std::string na
|
|||
ObjectList objectlist;
|
||||
|
||||
Misc::StringUtils::toLower(name);
|
||||
NIFObjectLoader::load(sceneMgr, objectlist, name, group);
|
||||
NIFObjectLoader::load(sceneMgr, objectlist, name, group, 0xC0000000);
|
||||
|
||||
return objectlist;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,347 @@
|
|||
|
||||
#include <OgreStringConverter.h>
|
||||
#include <OgreParticleSystem.h>
|
||||
#include <OgreParticleEmitter.h>
|
||||
#include <OgreParticleAffector.h>
|
||||
#include <OgreParticle.h>
|
||||
|
||||
/* FIXME: "Nif" isn't really an appropriate emitter name. */
|
||||
class NifEmitter : public Ogre::ParticleEmitter
|
||||
{
|
||||
public:
|
||||
/** Command object for the emitter width (see Ogre::ParamCommand).*/
|
||||
class CmdWidth : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
return Ogre::StringConverter::toString(static_cast<const NifEmitter*>(target)->getWidth());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
static_cast<NifEmitter*>(target)->setWidth(Ogre::StringConverter::parseReal(val));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for the emitter height (see Ogre::ParamCommand).*/
|
||||
class CmdHeight : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
return Ogre::StringConverter::toString(static_cast<const NifEmitter*>(target)->getHeight());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
static_cast<NifEmitter*>(target)->setHeight(Ogre::StringConverter::parseReal(val));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for the emitter depth (see Ogre::ParamCommand).*/
|
||||
class CmdDepth : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
return Ogre::StringConverter::toString(static_cast<const NifEmitter*>(target)->getDepth());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
static_cast<NifEmitter*>(target)->setDepth(Ogre::StringConverter::parseReal(val));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for the emitter vertical_direction (see Ogre::ParamCommand).*/
|
||||
class CmdVerticalDir : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||
return Ogre::StringConverter::toString(self->getVerticalDirection().valueDegrees());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||
self->setVerticalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for the emitter vertical_angle (see Ogre::ParamCommand).*/
|
||||
class CmdVerticalAngle : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||
return Ogre::StringConverter::toString(self->getVerticalAngle().valueDegrees());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||
self->setVerticalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for the emitter horizontal_direction (see Ogre::ParamCommand).*/
|
||||
class CmdHorizontalDir : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||
return Ogre::StringConverter::toString(self->getHorizontalDirection().valueDegrees());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||
self->setHorizontalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for the emitter horizontal_angle (see Ogre::ParamCommand).*/
|
||||
class CmdHorizontalAngle : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||
return Ogre::StringConverter::toString(self->getHorizontalAngle().valueDegrees());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||
self->setHorizontalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
NifEmitter(Ogre::ParticleSystem *psys)
|
||||
: Ogre::ParticleEmitter(psys)
|
||||
{
|
||||
initDefaults("Nif");
|
||||
}
|
||||
|
||||
/** See Ogre::ParticleEmitter. */
|
||||
unsigned short _getEmissionCount(Ogre::Real timeElapsed)
|
||||
{
|
||||
// Use basic constant emission
|
||||
return genConstantEmissionCount(timeElapsed);
|
||||
}
|
||||
|
||||
/** See Ogre::ParticleEmitter. */
|
||||
void _initParticle(Ogre::Particle *particle)
|
||||
{
|
||||
Ogre::Vector3 xOff, yOff, zOff;
|
||||
|
||||
// Call superclass
|
||||
ParticleEmitter::_initParticle(particle);
|
||||
|
||||
xOff = Ogre::Math::SymmetricRandom() * mXRange;
|
||||
yOff = Ogre::Math::SymmetricRandom() * mYRange;
|
||||
zOff = Ogre::Math::SymmetricRandom() * mZRange;
|
||||
|
||||
particle->position = mPosition + xOff + yOff + zOff;
|
||||
|
||||
// Generate complex data by reference
|
||||
genEmissionColour(particle->colour);
|
||||
|
||||
// NOTE: We do not use mDirection/mAngle for the initial direction.
|
||||
Ogre::Radian hdir = mHorizontalDir + mHorizontalAngle*Ogre::Math::SymmetricRandom();
|
||||
Ogre::Radian vdir = mVerticalDir + mVerticalAngle*Ogre::Math::SymmetricRandom();
|
||||
particle->direction = (Ogre::Quaternion(hdir, Ogre::Vector3::UNIT_Z) *
|
||||
Ogre::Quaternion(vdir, Ogre::Vector3::UNIT_X)) *
|
||||
Ogre::Vector3::UNIT_Z;
|
||||
|
||||
genEmissionVelocity(particle->direction);
|
||||
|
||||
// Generate simpler data
|
||||
particle->timeToLive = particle->totalTimeToLive = genEmissionTTL();
|
||||
}
|
||||
|
||||
/** Overloaded to update the trans. matrix */
|
||||
void setDirection(const Ogre::Vector3 &dir)
|
||||
{
|
||||
ParticleEmitter::setDirection(dir);
|
||||
genAreaAxes();
|
||||
}
|
||||
|
||||
/** Sets the size of the area from which particles are emitted.
|
||||
@param
|
||||
size Vector describing the size of the area. The area extends
|
||||
around the center point by half the x, y and z components of
|
||||
this vector. The box is aligned such that it's local Z axis points
|
||||
along it's direction (see setDirection)
|
||||
*/
|
||||
void setSize(const Ogre::Vector3 &size)
|
||||
{
|
||||
mSize = size;
|
||||
genAreaAxes();
|
||||
}
|
||||
|
||||
/** Sets the size of the area from which particles are emitted.
|
||||
@param x,y,z
|
||||
Individual axis lengths describing the size of the area. The area
|
||||
extends around the center point by half the x, y and z components
|
||||
of this vector. The box is aligned such that it's local Z axis
|
||||
points along it's direction (see setDirection)
|
||||
*/
|
||||
void setSize(Ogre::Real x, Ogre::Real y, Ogre::Real z)
|
||||
{
|
||||
mSize.x = x;
|
||||
mSize.y = y;
|
||||
mSize.z = z;
|
||||
genAreaAxes();
|
||||
}
|
||||
|
||||
/** Sets the width (local x size) of the emitter. */
|
||||
void setWidth(Ogre::Real width)
|
||||
{
|
||||
mSize.x = width;
|
||||
genAreaAxes();
|
||||
}
|
||||
/** Gets the width (local x size) of the emitter. */
|
||||
Ogre::Real getWidth(void) const
|
||||
{ return mSize.x; }
|
||||
/** Sets the height (local y size) of the emitter. */
|
||||
void setHeight(Ogre::Real height)
|
||||
{
|
||||
mSize.y = height;
|
||||
genAreaAxes();
|
||||
}
|
||||
/** Gets the height (local y size) of the emitter. */
|
||||
Ogre::Real getHeight(void) const
|
||||
{ return mSize.y; }
|
||||
/** Sets the depth (local y size) of the emitter. */
|
||||
void setDepth(Ogre::Real depth)
|
||||
{
|
||||
mSize.z = depth;
|
||||
genAreaAxes();
|
||||
}
|
||||
/** Gets the depth (local y size) of the emitter. */
|
||||
Ogre::Real getDepth(void) const
|
||||
{ return mSize.z; }
|
||||
|
||||
void setVerticalDirection(Ogre::Radian vdir)
|
||||
{ mVerticalDir = vdir; }
|
||||
Ogre::Radian getVerticalDirection(void) const
|
||||
{ return mVerticalDir; }
|
||||
|
||||
void setVerticalAngle(Ogre::Radian vangle)
|
||||
{ mVerticalAngle = vangle; }
|
||||
Ogre::Radian getVerticalAngle(void) const
|
||||
{ return mVerticalAngle; }
|
||||
|
||||
void setHorizontalDirection(Ogre::Radian hdir)
|
||||
{ mHorizontalDir = hdir; }
|
||||
Ogre::Radian getHorizontalDirection(void) const
|
||||
{ return mHorizontalDir; }
|
||||
|
||||
void setHorizontalAngle(Ogre::Radian hangle)
|
||||
{ mHorizontalAngle = hangle; }
|
||||
Ogre::Radian getHorizontalAngle(void) const
|
||||
{ return mHorizontalAngle; }
|
||||
|
||||
|
||||
protected:
|
||||
/// Size of the area
|
||||
Ogre::Vector3 mSize;
|
||||
|
||||
Ogre::Radian mVerticalDir;
|
||||
Ogre::Radian mVerticalAngle;
|
||||
Ogre::Radian mHorizontalDir;
|
||||
Ogre::Radian mHorizontalAngle;
|
||||
|
||||
/// Local axes, not normalised, their magnitude reflects area size
|
||||
Ogre::Vector3 mXRange, mYRange, mZRange;
|
||||
|
||||
/// Internal method for generating the area axes
|
||||
void genAreaAxes(void)
|
||||
{
|
||||
Ogre::Vector3 mLeft = mUp.crossProduct(mDirection);
|
||||
mXRange = mLeft * (mSize.x * 0.5f);
|
||||
mYRange = mUp * (mSize.y * 0.5f);
|
||||
mZRange = mDirection * (mSize.z * 0.5f);
|
||||
}
|
||||
|
||||
/** Internal for initializing some defaults and parameters
|
||||
@return True if custom parameters need initialising
|
||||
*/
|
||||
bool initDefaults(const Ogre::String &t)
|
||||
{
|
||||
// Defaults
|
||||
mDirection = Ogre::Vector3::UNIT_Z;
|
||||
mUp = Ogre::Vector3::UNIT_Y;
|
||||
setSize(100.0f, 100.0f, 100.0f);
|
||||
mType = t;
|
||||
|
||||
// Set up parameters
|
||||
if(createParamDictionary(mType + "Emitter"))
|
||||
{
|
||||
addBaseParameters();
|
||||
Ogre::ParamDictionary *dict = getParamDictionary();
|
||||
|
||||
// Custom params
|
||||
dict->addParameter(Ogre::ParameterDef("width",
|
||||
"Width of the shape in world coordinates.",
|
||||
Ogre::PT_REAL),
|
||||
&msWidthCmd);
|
||||
dict->addParameter(Ogre::ParameterDef("height",
|
||||
"Height of the shape in world coordinates.",
|
||||
Ogre::PT_REAL),
|
||||
&msHeightCmd);
|
||||
dict->addParameter(Ogre::ParameterDef("depth",
|
||||
"Depth of the shape in world coordinates.",
|
||||
Ogre::PT_REAL),
|
||||
&msDepthCmd);
|
||||
|
||||
dict->addParameter(Ogre::ParameterDef("vertical_direction",
|
||||
"Vertical direction of emitted particles (in degrees).",
|
||||
Ogre::PT_REAL),
|
||||
&msVerticalDirCmd);
|
||||
dict->addParameter(Ogre::ParameterDef("vertical_angle",
|
||||
"Vertical direction variance of emitted particles (in degrees).",
|
||||
Ogre::PT_REAL),
|
||||
&msVerticalAngleCmd);
|
||||
dict->addParameter(Ogre::ParameterDef("horizontal_direction",
|
||||
"Horizontal direction of emitted particles (in degrees).",
|
||||
Ogre::PT_REAL),
|
||||
&msHorizontalDirCmd);
|
||||
dict->addParameter(Ogre::ParameterDef("horizontal_angle",
|
||||
"Horizontal direction variance of emitted particles (in degrees).",
|
||||
Ogre::PT_REAL),
|
||||
&msHorizontalAngleCmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Command objects
|
||||
static CmdWidth msWidthCmd;
|
||||
static CmdHeight msHeightCmd;
|
||||
static CmdDepth msDepthCmd;
|
||||
static CmdVerticalDir msVerticalDirCmd;
|
||||
static CmdVerticalAngle msVerticalAngleCmd;
|
||||
static CmdHorizontalDir msHorizontalDirCmd;
|
||||
static CmdHorizontalAngle msHorizontalAngleCmd;
|
||||
};
|
||||
NifEmitter::CmdWidth NifEmitter::msWidthCmd;
|
||||
NifEmitter::CmdHeight NifEmitter::msHeightCmd;
|
||||
NifEmitter::CmdDepth NifEmitter::msDepthCmd;
|
||||
NifEmitter::CmdVerticalDir NifEmitter::msVerticalDirCmd;
|
||||
NifEmitter::CmdVerticalAngle NifEmitter::msVerticalAngleCmd;
|
||||
NifEmitter::CmdHorizontalDir NifEmitter::msHorizontalDirCmd;
|
||||
NifEmitter::CmdHorizontalAngle NifEmitter::msHorizontalAngleCmd;
|
||||
|
||||
Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys)
|
||||
{
|
||||
Ogre::ParticleEmitter *emit = OGRE_NEW NifEmitter(psys);
|
||||
mEmitters.push_back(emit);
|
||||
return emit;
|
||||
}
|
||||
|
||||
|
||||
class GrowFadeAffector : public Ogre::ParticleAffector
|
||||
{
|
||||
public:
|
||||
|
@ -144,3 +482,212 @@ Ogre::ParticleAffector *GrowFadeAffectorFactory::createAffector(Ogre::ParticleSy
|
|||
mAffectors.push_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
class GravityAffector : public Ogre::ParticleAffector
|
||||
{
|
||||
enum ForceType {
|
||||
Type_Wind,
|
||||
Type_Point
|
||||
};
|
||||
|
||||
public:
|
||||
/** Command object for force (see Ogre::ParamCommand).*/
|
||||
class CmdForce : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const GravityAffector *self = static_cast<const GravityAffector*>(target);
|
||||
return Ogre::StringConverter::toString(self->getForce());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
GravityAffector *self = static_cast<GravityAffector*>(target);
|
||||
self->setForce(Ogre::StringConverter::parseReal(val));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for force_type (see Ogre::ParamCommand).*/
|
||||
class CmdForceType : public Ogre::ParamCommand
|
||||
{
|
||||
static ForceType getTypeFromString(const Ogre::String &type)
|
||||
{
|
||||
if(type == "wind")
|
||||
return Type_Wind;
|
||||
if(type == "point")
|
||||
return Type_Point;
|
||||
OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid force type string: "+type,
|
||||
"CmdForceType::getTypeFromString");
|
||||
}
|
||||
|
||||
static Ogre::String getStringFromType(ForceType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Type_Wind: return "wind";
|
||||
case Type_Point: return "point";
|
||||
}
|
||||
OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid force type enum: "+Ogre::StringConverter::toString(type),
|
||||
"CmdForceType::getStringFromType");
|
||||
}
|
||||
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const GravityAffector *self = static_cast<const GravityAffector*>(target);
|
||||
return getStringFromType(self->getForceType());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
GravityAffector *self = static_cast<GravityAffector*>(target);
|
||||
self->setForceType(getTypeFromString(val));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for direction (see Ogre::ParamCommand).*/
|
||||
class CmdDirection : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const GravityAffector *self = static_cast<const GravityAffector*>(target);
|
||||
return Ogre::StringConverter::toString(self->getDirection());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
GravityAffector *self = static_cast<GravityAffector*>(target);
|
||||
self->setDirection(Ogre::StringConverter::parseVector3(val));
|
||||
}
|
||||
};
|
||||
|
||||
/** Command object for position (see Ogre::ParamCommand).*/
|
||||
class CmdPosition : public Ogre::ParamCommand
|
||||
{
|
||||
public:
|
||||
Ogre::String doGet(const void *target) const
|
||||
{
|
||||
const GravityAffector *self = static_cast<const GravityAffector*>(target);
|
||||
return Ogre::StringConverter::toString(self->getPosition());
|
||||
}
|
||||
void doSet(void *target, const Ogre::String &val)
|
||||
{
|
||||
GravityAffector *self = static_cast<GravityAffector*>(target);
|
||||
self->setPosition(Ogre::StringConverter::parseVector3(val));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Default constructor. */
|
||||
GravityAffector(Ogre::ParticleSystem *psys)
|
||||
: ParticleAffector(psys)
|
||||
, mForce(0.0f)
|
||||
, mForceType(Type_Wind)
|
||||
, mPosition(0.0f)
|
||||
, mDirection(0.0f)
|
||||
{
|
||||
mType = "Gravity";
|
||||
|
||||
// Init parameters
|
||||
if(createParamDictionary("GravityAffector"))
|
||||
{
|
||||
Ogre::ParamDictionary *dict = getParamDictionary();
|
||||
|
||||
Ogre::String force_title("force");
|
||||
Ogre::String force_descr("Amount of force applied to particles.");
|
||||
Ogre::String force_type_title("force_type");
|
||||
Ogre::String force_type_descr("Type of force applied to particles (point or wind).");
|
||||
Ogre::String direction_title("direction");
|
||||
Ogre::String direction_descr("Direction of wind forces.");
|
||||
Ogre::String position_title("position");
|
||||
Ogre::String position_descr("Position of point forces.");
|
||||
|
||||
dict->addParameter(Ogre::ParameterDef(force_title, force_descr, Ogre::PT_REAL), &msForceCmd);
|
||||
dict->addParameter(Ogre::ParameterDef(force_type_title, force_type_descr, Ogre::PT_STRING), &msForceTypeCmd);
|
||||
dict->addParameter(Ogre::ParameterDef(direction_title, direction_descr, Ogre::PT_VECTOR3), &msDirectionCmd);
|
||||
dict->addParameter(Ogre::ParameterDef(position_title, position_descr, Ogre::PT_VECTOR3), &msPositionCmd);
|
||||
}
|
||||
}
|
||||
|
||||
/** See Ogre::ParticleAffector. */
|
||||
void _affectParticles(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
|
||||
{
|
||||
switch(mForceType)
|
||||
{
|
||||
case Type_Wind:
|
||||
applyWindForce(psys, timeElapsed);
|
||||
break;
|
||||
case Type_Point:
|
||||
applyPointForce(psys, timeElapsed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setForce(Ogre::Real force)
|
||||
{ mForce = force; }
|
||||
Ogre::Real getForce() const
|
||||
{ return mForce; }
|
||||
|
||||
void setForceType(ForceType type)
|
||||
{ mForceType = type; }
|
||||
ForceType getForceType() const
|
||||
{ return mForceType; }
|
||||
|
||||
void setDirection(const Ogre::Vector3 &dir)
|
||||
{ mDirection = dir; }
|
||||
const Ogre::Vector3 &getDirection() const
|
||||
{ return mDirection; }
|
||||
|
||||
void setPosition(const Ogre::Vector3 &pos)
|
||||
{ mPosition = pos; }
|
||||
const Ogre::Vector3 &getPosition() const
|
||||
{ return mPosition; }
|
||||
|
||||
static CmdForce msForceCmd;
|
||||
static CmdForceType msForceTypeCmd;
|
||||
static CmdDirection msDirectionCmd;
|
||||
static CmdPosition msPositionCmd;
|
||||
|
||||
protected:
|
||||
void applyWindForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
|
||||
{
|
||||
const Ogre::Vector3 vec = mDirection * mForce * timeElapsed;
|
||||
Ogre::ParticleIterator pi = psys->_getIterator();
|
||||
while (!pi.end())
|
||||
{
|
||||
Ogre::Particle *p = pi.getNext();
|
||||
p->direction += vec;
|
||||
}
|
||||
}
|
||||
|
||||
void applyPointForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
|
||||
{
|
||||
const Ogre::Real force = mForce * timeElapsed;
|
||||
Ogre::ParticleIterator pi = psys->_getIterator();
|
||||
while (!pi.end())
|
||||
{
|
||||
Ogre::Particle *p = pi.getNext();
|
||||
const Ogre::Vector3 vec = (p->position - mPosition).normalisedCopy() * force;
|
||||
p->direction += vec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float mForce;
|
||||
|
||||
ForceType mForceType;
|
||||
|
||||
Ogre::Vector3 mPosition;
|
||||
Ogre::Vector3 mDirection;
|
||||
};
|
||||
GravityAffector::CmdForce GravityAffector::msForceCmd;
|
||||
GravityAffector::CmdForceType GravityAffector::msForceTypeCmd;
|
||||
GravityAffector::CmdDirection GravityAffector::msDirectionCmd;
|
||||
GravityAffector::CmdPosition GravityAffector::msPositionCmd;
|
||||
|
||||
Ogre::ParticleAffector *GravityAffectorFactory::createAffector(Ogre::ParticleSystem *psys)
|
||||
{
|
||||
Ogre::ParticleAffector *p = new GravityAffector(psys);
|
||||
mAffectors.push_back(p);
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
#ifndef OENGINE_OGRE_PARTICLES_H
|
||||
#define OENGINE_OGRE_PARTICLES_H
|
||||
|
||||
#include <OgreParticleEmitterFactory.h>
|
||||
#include <OgreParticleAffectorFactory.h>
|
||||
|
||||
/** Factory class for NifEmitter. */
|
||||
class NifEmitterFactory : public Ogre::ParticleEmitterFactory
|
||||
{
|
||||
public:
|
||||
/** See ParticleEmitterFactory */
|
||||
Ogre::String getName() const
|
||||
{ return "Nif"; }
|
||||
|
||||
/** See ParticleEmitterFactory */
|
||||
Ogre::ParticleEmitter* createEmitter(Ogre::ParticleSystem *psys);
|
||||
};
|
||||
|
||||
/** Factory class for GrowFadeAffector. */
|
||||
class GrowFadeAffectorFactory : public Ogre::ParticleAffectorFactory
|
||||
{
|
||||
|
@ -14,4 +27,15 @@ class GrowFadeAffectorFactory : public Ogre::ParticleAffectorFactory
|
|||
Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys);
|
||||
};
|
||||
|
||||
/** Factory class for GravityAffector. */
|
||||
class GravityAffectorFactory : public Ogre::ParticleAffectorFactory
|
||||
{
|
||||
/** See Ogre::ParticleAffectorFactory */
|
||||
Ogre::String getName() const
|
||||
{ return "Gravity"; }
|
||||
|
||||
/** See Ogre::ParticleAffectorFactory */
|
||||
Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys);
|
||||
};
|
||||
|
||||
#endif /* OENGINE_OGRE_PARTICLES_H */
|
||||
|
|
|
@ -110,6 +110,11 @@ void OgreRenderer::loadPlugins()
|
|||
|
||||
void OgreRenderer::unloadPlugins()
|
||||
{
|
||||
std::vector<Ogre::ParticleEmitterFactory*>::iterator ei;
|
||||
for(ei = mEmitterFactories.begin();ei != mEmitterFactories.end();ei++)
|
||||
OGRE_DELETE (*ei);
|
||||
mEmitterFactories.clear();
|
||||
|
||||
std::vector<Ogre::ParticleAffectorFactory*>::iterator ai;
|
||||
for(ai = mAffectorFactories.begin();ai != mAffectorFactories.end();ai++)
|
||||
OGRE_DELETE (*ai);
|
||||
|
@ -206,11 +211,22 @@ void OgreRenderer::configure(const std::string &logPath,
|
|||
Files::loadOgrePlugin(pluginDir, "Plugin_CgProgramManager", *mRoot);
|
||||
Files::loadOgrePlugin(pluginDir, "Plugin_ParticleFX", *mRoot);
|
||||
|
||||
|
||||
Ogre::ParticleEmitterFactory *emitter;
|
||||
emitter = OGRE_NEW NifEmitterFactory();
|
||||
Ogre::ParticleSystemManager::getSingleton().addEmitterFactory(emitter);
|
||||
mEmitterFactories.push_back(emitter);
|
||||
|
||||
|
||||
Ogre::ParticleAffectorFactory *affector;
|
||||
affector = OGRE_NEW GrowFadeAffectorFactory();
|
||||
Ogre::ParticleSystemManager::getSingleton().addAffectorFactory(affector);
|
||||
mAffectorFactories.push_back(affector);
|
||||
|
||||
affector = OGRE_NEW GravityAffectorFactory();
|
||||
Ogre::ParticleSystemManager::getSingleton().addAffectorFactory(affector);
|
||||
mAffectorFactories.push_back(affector);
|
||||
|
||||
|
||||
RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem);
|
||||
if (rs == 0)
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace Ogre
|
|||
class SceneManager;
|
||||
class Camera;
|
||||
class Viewport;
|
||||
class ParticleEmitterFactory;
|
||||
class ParticleAffectorFactory;
|
||||
}
|
||||
|
||||
|
@ -95,6 +96,7 @@ namespace OEngine
|
|||
Ogre::D3D9Plugin* mD3D9Plugin;
|
||||
#endif
|
||||
Fader* mFader;
|
||||
std::vector<Ogre::ParticleEmitterFactory*> mEmitterFactories;
|
||||
std::vector<Ogre::ParticleAffectorFactory*> mAffectorFactories;
|
||||
bool logging;
|
||||
|
||||
|
|
Loading…
Reference in a new issue