1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-06 12:15:36 +00:00

Preload items equipped by NPCs

This commit is contained in:
scrawl 2016-02-07 22:37:52 +01:00
parent a81b10b415
commit c8054424c9
4 changed files with 73 additions and 7 deletions

View file

@ -5,10 +5,14 @@
#include <components/resource/scenemanager.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/bulletshapemanager.hpp>
#include <components/misc/resourcehelpers.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/esmstore.hpp"
#include "cellstore.hpp"
#include "manualref.hpp"
#include "class.hpp"
@ -23,11 +27,54 @@ namespace MWWorld
{
}
virtual bool operator()(const MWWorld::ConstPtr& ptr)
virtual bool operator()(const MWWorld::Ptr& ptr)
{
std::string model = ptr.getClass().getModel(ptr);
if (!model.empty())
mOut.push_back(model);
// TODO: preload NPC body parts (mHead / mHair)
// FIXME: use const version of InventoryStore functions once they are available
if (ptr.getClass().hasInventoryStore(ptr))
{
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr);
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot)
{
MWWorld::ContainerStoreIterator equipped = invStore.getSlot(slot);
if (equipped != invStore.end())
{
std::vector<ESM::PartReference> parts;
if(equipped->getTypeName() == typeid(ESM::Clothing).name())
{
const ESM::Clothing *clothes = equipped->get<ESM::Clothing>()->mBase;
parts = clothes->mParts.mParts;
}
else if(equipped->getTypeName() == typeid(ESM::Armor).name())
{
const ESM::Armor *armor = equipped->get<ESM::Armor>()->mBase;
parts = armor->mParts.mParts;
}
else
{
model = equipped->getClass().getModel(*equipped);
if (!model.empty())
mOut.push_back(model);
}
for (std::vector<ESM::PartReference>::const_iterator it = parts.begin(); it != parts.end(); ++it)
{
const ESM::BodyPart* part = MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>().search(it->mMale);
if (part && !part->mModel.empty())
mOut.push_back("meshes/"+part->mModel);
part = MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>().search(it->mFemale);
if (part && !part->mModel.empty())
mOut.push_back("meshes/"+part->mModel);
}
}
}
}
return true;
}
@ -39,14 +86,15 @@ namespace MWWorld
{
public:
/// Constructor to be called from the main thread.
PreloadItem(const MWWorld::CellStore* cell, Resource::SceneManager* sceneManager, Resource::BulletShapeManager* bulletShapeManager)
PreloadItem(MWWorld::CellStore* cell, Resource::SceneManager* sceneManager, Resource::BulletShapeManager* bulletShapeManager)
: mSceneManager(sceneManager)
, mBulletShapeManager(bulletShapeManager)
{
osg::Timer timer;
ListModelsVisitor visitor (mMeshes);
if (cell->getState() == MWWorld::CellStore::State_Loaded)
{
ListModelsVisitor visitor (mMeshes);
cell->forEachConst(visitor);
cell->forEach(visitor);
}
else
{
@ -61,6 +109,7 @@ namespace MWWorld
mMeshes.push_back(model);
}
}
std::cout << "listed models in " << timer.time_m() << std::endl;
}
/// Preload work to be called from the worker thread.
@ -73,9 +122,16 @@ namespace MWWorld
{
try
{
std::string mesh = *it;
Misc::ResourceHelpers::correctActorModelPath(mesh, mSceneManager->getVFS());
//std::cout << "preloading " << mesh << std::endl;
mPreloadedNodes.push_back(mSceneManager->getTemplate(*it));
mPreloadedShapes.push_back(mBulletShapeManager->getShape(*it));
// TODO: load .kf
// TODO: do a createInstance() and hold on to it since we can make use of it when the cell goes active
}
catch (std::exception& e)
@ -84,7 +140,7 @@ namespace MWWorld
// error will be shown when visiting the cell
}
}
std::cout << "preloaded " << mPreloadedNodes.size() << " nodes in " << preloadTimer.time_m() << std::endl;
//std::cout << "preloaded " << mPreloadedNodes.size() << " nodes in " << preloadTimer.time_m() << std::endl;
}
private:
@ -128,7 +184,7 @@ namespace MWWorld
mWorkQueue = new SceneUtil::WorkQueue;
}
void CellPreloader::preload(const CellStore *cell, double timestamp)
void CellPreloader::preload(CellStore *cell, double timestamp)
{
if (!mWorkQueue)
{

View file

@ -22,7 +22,7 @@ namespace MWWorld
/// Ask a background thread to preload rendering meshes and collision shapes for objects in this cell.
/// @note The cell itself must be in State_Loaded or State_Preloaded.
void preload(const MWWorld::CellStore* cell, double timestamp);
void preload(MWWorld::CellStore* cell, double timestamp);
/// Removes preloaded cells that have not had a preload request for a while.
void updateCache(double timestamp);

View file

@ -2,6 +2,7 @@
#include <limits>
#include <iostream>
#include <osg/Timer>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/resourcehelpers.hpp>
@ -329,6 +330,7 @@ namespace MWWorld
void Scene::changeCellGrid (int X, int Y)
{
osg::Timer timer;
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener);
@ -413,6 +415,8 @@ namespace MWWorld
mPreloader->updateCache(mRendering.getReferenceTime());
mRendering.clearCache();
std::cout << "changeCellGrid took " << timer.time_m() << std::endl;
}
void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos)
@ -477,6 +481,7 @@ namespace MWWorld
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
{
osg::Timer timer;
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
bool loadcell = (mCurrentCell == NULL);
if(!loadcell)
@ -537,6 +542,8 @@ namespace MWWorld
mPreloader->updateCache(mRendering.getReferenceTime());
mRendering.clearCache();
std::cout << "change to interior took " << timer.time_m() << std::endl;
}
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos)

View file

@ -1,5 +1,6 @@
#include "scenemanager.hpp"
#include <iostream>
#include <osg/Node>
#include <osg/Geode>
#include <osg/UserDataContainer>
@ -364,6 +365,8 @@ namespace Resource
if (mIncrementalCompileOperation)
mIncrementalCompileOperation->add(loaded);
//std::cout << "loading " << normalized << std::endl;
mCache->addEntryToObjectCache(normalized, loaded);
return loaded;
}