1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-06 13:45:34 +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/scenemanager.hpp>
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/resource/bulletshapemanager.hpp> #include <components/resource/bulletshapemanager.hpp>
#include <components/misc/resourcehelpers.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/esmstore.hpp"
#include "cellstore.hpp" #include "cellstore.hpp"
#include "manualref.hpp" #include "manualref.hpp"
#include "class.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); std::string model = ptr.getClass().getModel(ptr);
if (!model.empty()) if (!model.empty())
mOut.push_back(model); 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; return true;
} }
@ -39,14 +86,15 @@ namespace MWWorld
{ {
public: public:
/// Constructor to be called from the main thread. /// 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) : mSceneManager(sceneManager)
, mBulletShapeManager(bulletShapeManager) , mBulletShapeManager(bulletShapeManager)
{ {
osg::Timer timer;
ListModelsVisitor visitor (mMeshes);
if (cell->getState() == MWWorld::CellStore::State_Loaded) if (cell->getState() == MWWorld::CellStore::State_Loaded)
{ {
ListModelsVisitor visitor (mMeshes); cell->forEach(visitor);
cell->forEachConst(visitor);
} }
else else
{ {
@ -61,6 +109,7 @@ namespace MWWorld
mMeshes.push_back(model); mMeshes.push_back(model);
} }
} }
std::cout << "listed models in " << timer.time_m() << std::endl;
} }
/// Preload work to be called from the worker thread. /// Preload work to be called from the worker thread.
@ -73,9 +122,16 @@ namespace MWWorld
{ {
try try
{ {
std::string mesh = *it;
Misc::ResourceHelpers::correctActorModelPath(mesh, mSceneManager->getVFS());
//std::cout << "preloading " << mesh << std::endl;
mPreloadedNodes.push_back(mSceneManager->getTemplate(*it)); mPreloadedNodes.push_back(mSceneManager->getTemplate(*it));
mPreloadedShapes.push_back(mBulletShapeManager->getShape(*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 // 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) catch (std::exception& e)
@ -84,7 +140,7 @@ namespace MWWorld
// error will be shown when visiting the cell // 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: private:
@ -128,7 +184,7 @@ namespace MWWorld
mWorkQueue = new SceneUtil::WorkQueue; mWorkQueue = new SceneUtil::WorkQueue;
} }
void CellPreloader::preload(const CellStore *cell, double timestamp) void CellPreloader::preload(CellStore *cell, double timestamp)
{ {
if (!mWorkQueue) 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. /// 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. /// @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. /// Removes preloaded cells that have not had a preload request for a while.
void updateCache(double timestamp); void updateCache(double timestamp);

View file

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

View file

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