Preload magic effect visuals of the player's selected weapon/spell

pull/151/head
scrawl 8 years ago
parent e46fb1770c
commit 57b585570a

@ -215,7 +215,9 @@ namespace MWBase
virtual std::string getSelectedSpell() = 0;
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0;
virtual const MWWorld::Ptr& getSelectedEnchantItem() const = 0;
virtual void setSelectedWeapon(const MWWorld::Ptr& item) = 0;
virtual const MWWorld::Ptr& getSelectedWeapon() const = 0;
virtual void unsetSelectedSpell() = 0;
virtual void unsetSelectedWeapon() = 0;

@ -569,6 +569,9 @@ namespace MWBase
/// Export scene graph to a file and return the filename.
/// \param ptr object to export scene graph for (if empty, export entire scene graph)
virtual std::string exportSceneGraph(const MWWorld::Ptr& ptr) = 0;
/// Preload VFX associated with this effect list
virtual void preloadEffects(const ESM::EffectList* effectList) = 0;
};
}

@ -39,6 +39,7 @@ namespace MWGui
void setSelectedSpell(const std::string& spellId, int successChancePercent);
void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent);
const MWWorld::Ptr& getSelectedEnchantItem();
void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent);
void unsetSelectedSpell();
void unsetSelectedWeapon();

@ -1282,6 +1282,7 @@ namespace MWGui
void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent)
{
mSelectedSpell = spellId;
mSelectedEnchantItem = MWWorld::Ptr();
mHud->setSelectedSpell(spellId, successChancePercent);
const ESM::Spell* spell = mStore->get<ESM::Spell>().find(spellId);
@ -1291,6 +1292,7 @@ namespace MWGui
void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item)
{
mSelectedEnchantItem = item;
mSelectedSpell = "";
const ESM::Enchantment* ench = mStore->get<ESM::Enchantment>()
.find(item.getClass().getEnchantment(item));
@ -1301,17 +1303,29 @@ namespace MWGui
mSpellWindow->setTitle(item.getClass().getName(item));
}
const MWWorld::Ptr &WindowManager::getSelectedEnchantItem() const
{
return mSelectedEnchantItem;
}
void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item)
{
mSelectedWeapon = item;
int durabilityPercent =
static_cast<int>(item.getClass().getItemHealth(item) / static_cast<float>(item.getClass().getItemMaxHealth(item)) * 100);
mHud->setSelectedWeapon(item, durabilityPercent);
mInventoryWindow->setTitle(item.getClass().getName(item));
}
const MWWorld::Ptr &WindowManager::getSelectedWeapon() const
{
return mSelectedWeapon;
}
void WindowManager::unsetSelectedSpell()
{
mSelectedSpell = "";
mSelectedEnchantItem = MWWorld::Ptr();
mHud->unsetSelectedSpell();
MWWorld::Player* player = &MWBase::Environment::get().getWorld()->getPlayer();
@ -1323,6 +1337,7 @@ namespace MWGui
void WindowManager::unsetSelectedWeapon()
{
mSelectedWeapon = MWWorld::Ptr();
mHud->unsetSelectedWeapon();
mInventoryWindow->setTitle("#{sSkillHandtohand}");
}

@ -13,6 +13,8 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/ptr.hpp"
#include <components/settings/settings.hpp>
#include <components/to_utf8/to_utf8.hpp>
@ -244,7 +246,9 @@ namespace MWGui
virtual std::string getSelectedSpell() { return mSelectedSpell; }
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item);
virtual const MWWorld::Ptr& getSelectedEnchantItem() const;
virtual void setSelectedWeapon(const MWWorld::Ptr& item);
virtual const MWWorld::Ptr& getSelectedWeapon() const;
virtual void unsetSelectedSpell();
virtual void unsetSelectedWeapon();
@ -403,6 +407,8 @@ namespace MWGui
void onWindowChangeCoord(MyGUI::Window* _sender);
std::string mSelectedSpell;
MWWorld::Ptr mSelectedEnchantItem;
MWWorld::Ptr mSelectedWeapon;
std::stack<WindowModal*> mCurrentModals;

@ -7,6 +7,7 @@
#include <components/misc/resourcehelpers.hpp>
#include <components/settings/settings.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -652,6 +653,35 @@ namespace MWWorld
return Ptr();
}
class PreloadMeshItem : public SceneUtil::WorkItem
{
public:
PreloadMeshItem(const std::string& mesh, Resource::SceneManager* sceneManager)
: mMesh(mesh), mSceneManager(sceneManager)
{
}
virtual void doWork()
{
try
{
mSceneManager->getTemplate(mMesh);
}
catch (std::exception& e)
{
}
}
private:
std::string mMesh;
Resource::SceneManager* mSceneManager;
};
void Scene::preload(const std::string &mesh)
{
if (!mRendering.getResourceSystem()->getSceneManager()->checkLoaded(mesh, mRendering.getReferenceTime()))
mRendering.getWorkQueue()->addWorkItem(new PreloadMeshItem(mesh, mRendering.getResourceSystem()->getSceneManager()));
}
void Scene::preloadCells(float dt)
{
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();

@ -132,6 +132,8 @@ namespace MWWorld
bool isCellActive(const CellStore &cell);
Ptr searchPtrViaActorId (int actorId);
void preload(const std::string& mesh);
};
}

@ -152,7 +152,7 @@ namespace MWWorld
mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), mUserDataPath(userDataPath),
mActivationDistanceOverride (activationDistanceOverride), mStartupScript(startupScript),
mStartCell (startCell), mDistanceToFacedObject(-1), mTeleportEnabled(true),
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0), mSpellPreloadTimer(0.f)
{
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath);
@ -1627,6 +1627,13 @@ namespace MWWorld
updateSoundListener();
updatePlayer(paused);
mSpellPreloadTimer -= duration;
if (mSpellPreloadTimer <= 0.f)
{
mSpellPreloadTimer = 0.1f;
preloadSpells();
}
}
void World::updatePlayer(bool paused)
@ -1683,7 +1690,39 @@ namespace MWWorld
if (result.mHit)
mRendering->getCamera()->setCameraDistance((result.mHitPos - focal).length() - radius, false, false);
}
}
void World::preloadSpells()
{
std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
if (!selectedSpell.empty())
{
const ESM::Spell* spell = mStore.get<ESM::Spell>().search(selectedSpell);
if (spell)
preloadEffects(&spell->mEffects);
}
const MWWorld::Ptr& selectedEnchantItem = MWBase::Environment::get().getWindowManager()->getSelectedEnchantItem();
if (!selectedEnchantItem.isEmpty())
{
std::string enchantId = selectedEnchantItem.getClass().getEnchantment(selectedEnchantItem);
if (!enchantId.empty())
{
const ESM::Enchantment* ench = mStore.get<ESM::Enchantment>().search(selectedEnchantItem.getClass().getEnchantment(selectedEnchantItem));
if (ench)
preloadEffects(&ench->mEffects);
}
}
const MWWorld::Ptr& selectedWeapon = MWBase::Environment::get().getWindowManager()->getSelectedWeapon();
if (!selectedWeapon.isEmpty())
{
std::string enchantId = selectedWeapon.getClass().getEnchantment(selectedWeapon);
if (!enchantId.empty())
{
const ESM::Enchantment* ench = mStore.get<ESM::Enchantment>().search(enchantId);
if (ench && ench->mData.mType == ESM::Enchantment::WhenStrikes)
preloadEffects(&ench->mEffects);
}
}
}
void World::updateSoundListener()
@ -2720,7 +2759,6 @@ namespace MWWorld
if (!selectedSpell.empty())
{
const ESM::Spell* spell = getStore().get<ESM::Spell>().find(selectedSpell);
cast.cast(spell);
}
else if (actor.getClass().hasInventoryStore(actor))
@ -3356,4 +3394,30 @@ namespace MWWorld
return mPhysics->getHitDistance(weaponPos, target) - halfExtents.y();
}
void preload(MWWorld::Scene* scene, const ESMStore& store, const std::string& obj)
{
if (obj.empty())
return;
MWWorld::ManualRef ref(store, obj);
std::string model = ref.getPtr().getClass().getModel(ref.getPtr());
if (!model.empty())
scene->preload(model);
}
void World::preloadEffects(const ESM::EffectList *effectList)
{
for (std::vector<ESM::ENAMstruct>::const_iterator it = effectList->mList.begin(); it != effectList->mList.end(); ++it)
{
const ESM::MagicEffect *effect = mStore.get<ESM::MagicEffect>().find(it->mEffectID);
preload(mWorldScene, mStore, effect->mCasting);
preload(mWorldScene, mStore, effect->mHit);
if (it->mArea > 0)
preload(mWorldScene, mStore, effect->mArea);
if (it->mRange == ESM::RT_Target)
preload(mWorldScene, mStore, effect->mBolt);
}
}
}

@ -135,6 +135,8 @@ namespace MWWorld
void updateWindowManager ();
void updatePlayer(bool paused);
void preloadSpells();
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
public: // FIXME
@ -174,6 +176,8 @@ namespace MWWorld
bool mGoToJail;
int mDaysInPrison;
float mSpellPreloadTimer;
float feetToGameUnits(float feet);
float getActivationDistancePlusTelekinesis();
@ -677,6 +681,9 @@ namespace MWWorld
/// Export scene graph to a file and return the filename.
/// \param ptr object to export scene graph for (if empty, export entire scene graph)
virtual std::string exportSceneGraph(const MWWorld::Ptr& ptr);
/// Preload VFX associated with this effect list
virtual void preloadEffects(const ESM::EffectList* effectList);
};
}

@ -49,6 +49,18 @@ osg::ref_ptr<osg::Object> ObjectCache::getRefFromObjectCache(const std::string&
else return 0;
}
bool ObjectCache::checkInObjectCache(const std::string &fileName, double timeStamp)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
ObjectCacheMap::iterator itr = _objectCache.find(fileName);
if (itr!=_objectCache.end())
{
itr->second.second = timeStamp;
return true;
}
else return false;
}
void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

@ -64,6 +64,9 @@ class ObjectCache : public osg::Referenced
/** Get an ref_ptr<Object> from the object cache*/
osg::ref_ptr<osg::Object> getRefFromObjectCache(const std::string& fileName);
/** Check if an object is in the cache, and if it is, update its usage time stamp. */
bool checkInObjectCache(const std::string& fileName, double timeStamp);
/** call releaseGLObjects on all objects attached to the object cache.*/
void releaseGLObjects(osg::State* state);

@ -272,6 +272,14 @@ namespace Resource
mShaderManager->setShaderPath(path);
}
bool SceneManager::checkLoaded(const std::string &name, double timeStamp)
{
std::string normalized = name;
mVFS->normalizeFilename(normalized);
return mCache->checkInObjectCache(normalized, timeStamp);
}
/// @brief Callback to read image files from the VFS.
class ImageReadCallback : public osgDB::ReadFileCallback
{

@ -77,6 +77,9 @@ namespace Resource
void setShaderPath(const std::string& path);
/// Check if a given scene is loaded and if so, update its usage timestamp to prevent it from being unloaded
bool checkLoaded(const std::string& name, double referenceTime);
/// Get a read-only copy of this scene "template"
/// @note If the given filename does not exist or fails to load, an error marker mesh will be used instead.
/// If even the error marker mesh can not be found, an exception is thrown.

Loading…
Cancel
Save