forked from mirror/openmw-tes3mp
Merge pull request #151 from OpenMW/master
Add OpenMW commits up to 16 Feb 2017
This commit is contained in:
commit
c32c004516
22 changed files with 257 additions and 30 deletions
|
@ -131,6 +131,8 @@ namespace CSMWorld
|
|||
Display_InfoCondComp,
|
||||
Display_String32,
|
||||
Display_LongString256,
|
||||
Display_BookType,
|
||||
Display_BloodType,
|
||||
|
||||
Display_EffectSkill, // must display at least one, unlike Display_Skill
|
||||
Display_EffectAttribute, // must display at least one, unlike Display_Attribute
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace CSMWorld
|
|||
{ ColumnId_ArmorType, "Armor Type" },
|
||||
{ ColumnId_Health, "Health" },
|
||||
{ ColumnId_ArmorValue, "Armor Value" },
|
||||
{ ColumnId_Scroll, "Scroll" },
|
||||
{ ColumnId_BookType, "Book Type" },
|
||||
{ ColumnId_ClothingType, "Clothing Type" },
|
||||
{ ColumnId_WeightCapacity, "Weight Capacity" },
|
||||
{ ColumnId_OrganicContainer, "Organic Container" },
|
||||
|
@ -112,8 +112,8 @@ namespace CSMWorld
|
|||
{ ColumnId_Flies, "Flies" },
|
||||
{ ColumnId_Walks, "Walks" },
|
||||
{ ColumnId_Essential, "Essential" },
|
||||
{ ColumnId_SkeletonBlood, "Skeleton Blood" },
|
||||
{ ColumnId_MetalBlood, "Metal Blood" },
|
||||
{ ColumnId_BloodType, "Blood Type" },
|
||||
|
||||
{ ColumnId_OpenSound, "Open Sound" },
|
||||
{ ColumnId_CloseSound, "Close Sound" },
|
||||
{ ColumnId_Duration, "Duration" },
|
||||
|
@ -553,6 +553,16 @@ namespace
|
|||
"AI Wander", "AI Travel", "AI Follow", "AI Escort", "AI Activate", 0
|
||||
};
|
||||
|
||||
static const char *sBookType[] =
|
||||
{
|
||||
"Book", "Scroll", 0
|
||||
};
|
||||
|
||||
static const char *sBloodType[] =
|
||||
{
|
||||
"Default (Red)", "Skeleton Blood (White)", "Metal Blood (Golden)", 0
|
||||
};
|
||||
|
||||
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
|
||||
{
|
||||
switch (column)
|
||||
|
@ -582,6 +592,8 @@ namespace
|
|||
case CSMWorld::Columns::ColumnId_AiPackageType: return sAiPackageType;
|
||||
case CSMWorld::Columns::ColumnId_InfoCondFunc: return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings;
|
||||
case CSMWorld::Columns::ColumnId_InfoCondComp: return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings;
|
||||
case CSMWorld::Columns::ColumnId_BookType: return sBookType;
|
||||
case CSMWorld::Columns::ColumnId_BloodType: return sBloodType;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace CSMWorld
|
|||
ColumnId_ArmorType = 77,
|
||||
ColumnId_Health = 78,
|
||||
ColumnId_ArmorValue = 79,
|
||||
ColumnId_Scroll = 80,
|
||||
ColumnId_BookType = 80,
|
||||
ColumnId_ClothingType = 81,
|
||||
ColumnId_WeightCapacity = 82,
|
||||
ColumnId_OrganicContainer = 83,
|
||||
|
@ -107,8 +107,8 @@ namespace CSMWorld
|
|||
ColumnId_Flies = 92,
|
||||
ColumnId_Walks = 93,
|
||||
ColumnId_Essential = 94,
|
||||
ColumnId_SkeletonBlood = 95,
|
||||
ColumnId_MetalBlood = 96,
|
||||
ColumnId_BloodType = 95,
|
||||
// unused
|
||||
ColumnId_OpenSound = 97,
|
||||
ColumnId_CloseSound = 98,
|
||||
ColumnId_Duration = 99,
|
||||
|
|
|
@ -301,9 +301,9 @@ void CSMWorld::ArmorRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
|
|||
}
|
||||
|
||||
CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns,
|
||||
const RefIdColumn *scroll, const RefIdColumn *skill, const RefIdColumn *text)
|
||||
const RefIdColumn *bookType, const RefIdColumn *skill, const RefIdColumn *text)
|
||||
: EnchantableRefIdAdapter<ESM::Book> (UniversalId::Type_Book, columns),
|
||||
mScroll (scroll), mSkill (skill), mText (text)
|
||||
mBookType (bookType), mSkill (skill), mText (text)
|
||||
{}
|
||||
|
||||
QVariant CSMWorld::BookRefIdAdapter::getData (const RefIdColumn *column,
|
||||
|
@ -312,8 +312,8 @@ QVariant CSMWorld::BookRefIdAdapter::getData (const RefIdColumn *column,
|
|||
const Record<ESM::Book>& record = static_cast<const Record<ESM::Book>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
|
||||
|
||||
if (column==mScroll)
|
||||
return record.get().mData.mIsScroll!=0;
|
||||
if (column==mBookType)
|
||||
return record.get().mData.mIsScroll;
|
||||
|
||||
if (column==mSkill)
|
||||
return record.get().mData.mSkillId;
|
||||
|
@ -332,7 +332,7 @@ void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
|
|||
|
||||
ESM::Book book = record.get();
|
||||
|
||||
if (column==mScroll)
|
||||
if (column==mBookType)
|
||||
book.mData.mIsScroll = value.toInt();
|
||||
else if (column==mSkill)
|
||||
book.mData.mSkillId = value.toInt();
|
||||
|
@ -458,7 +458,8 @@ CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
|
|||
mOriginal(NULL),
|
||||
mAttributes(NULL),
|
||||
mAttacks(NULL),
|
||||
mMisc(NULL)
|
||||
mMisc(NULL),
|
||||
mBloodType(NULL)
|
||||
{}
|
||||
|
||||
CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns)
|
||||
|
@ -489,6 +490,19 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con
|
|||
if (column==mColumns.mMisc)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ESM::Creature::Skeleton | ESM::Creature::Metal;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::Creature::Skeleton)
|
||||
return 1;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::Creature::Metal)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
||||
|
@ -512,6 +526,17 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
|
|||
creature.mScale = value.toFloat();
|
||||
else if (column==mColumns.mOriginal)
|
||||
creature.mOriginal = value.toString().toUtf8().constData();
|
||||
else if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ~(ESM::Creature::Skeleton | ESM::Creature::Metal);
|
||||
|
||||
if (value.toInt() == 1)
|
||||
creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Skeleton;
|
||||
else if (value.toInt() == 2)
|
||||
creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Metal;
|
||||
else
|
||||
creature.mFlags = creature.mFlags & mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
|
@ -696,7 +721,8 @@ CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns)
|
|||
mHead(NULL),
|
||||
mAttributes(NULL),
|
||||
mSkills(NULL),
|
||||
mMisc(NULL)
|
||||
mMisc(NULL),
|
||||
mBloodType(NULL)
|
||||
{}
|
||||
|
||||
CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns)
|
||||
|
@ -735,6 +761,19 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re
|
|||
if (column==mColumns.mMisc)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ESM::NPC::Skeleton | ESM::NPC::Metal;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::NPC::Skeleton)
|
||||
return 1;
|
||||
|
||||
if ((record.get().mFlags & mask) == ESM::NPC::Metal)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
||||
|
@ -762,6 +801,17 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d
|
|||
npc.mHair = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mHead)
|
||||
npc.mHead = value.toString().toUtf8().constData();
|
||||
else if (column == mColumns.mBloodType)
|
||||
{
|
||||
int mask = ~(ESM::NPC::Skeleton | ESM::NPC::Metal);
|
||||
|
||||
if (value.toInt() == 1)
|
||||
npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Skeleton;
|
||||
else if (value.toInt() == 2)
|
||||
npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Metal;
|
||||
else
|
||||
npc.mFlags = npc.mFlags & mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
|
|
|
@ -694,13 +694,13 @@ namespace CSMWorld
|
|||
|
||||
class BookRefIdAdapter : public EnchantableRefIdAdapter<ESM::Book>
|
||||
{
|
||||
const RefIdColumn *mScroll;
|
||||
const RefIdColumn *mBookType;
|
||||
const RefIdColumn *mSkill;
|
||||
const RefIdColumn *mText;
|
||||
|
||||
public:
|
||||
|
||||
BookRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *scroll,
|
||||
BookRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *bookType,
|
||||
const RefIdColumn *skill, const RefIdColumn *text);
|
||||
|
||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
||||
|
@ -757,6 +757,7 @@ namespace CSMWorld
|
|||
const RefIdColumn *mAttributes;
|
||||
const RefIdColumn *mAttacks;
|
||||
const RefIdColumn *mMisc;
|
||||
const RefIdColumn *mBloodType;
|
||||
|
||||
CreatureColumns (const ActorColumns& actorColumns);
|
||||
};
|
||||
|
@ -849,6 +850,7 @@ namespace CSMWorld
|
|||
const RefIdColumn *mAttributes; // depends on npc type
|
||||
const RefIdColumn *mSkills; // depends on npc type
|
||||
const RefIdColumn *mMisc; // may depend on npc type, e.g. FactionID
|
||||
const RefIdColumn *mBloodType;
|
||||
|
||||
NpcColumns (const ActorColumns& actorColumns);
|
||||
};
|
||||
|
|
|
@ -291,8 +291,8 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
mColumns.push_back (RefIdColumn (Columns::ColumnId_ArmorValue, ColumnBase::Display_Integer));
|
||||
const RefIdColumn *armor = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Scroll, ColumnBase::Display_Boolean));
|
||||
const RefIdColumn *scroll = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_BookType, ColumnBase::Display_BookType));
|
||||
const RefIdColumn *bookType = &mColumns.back();
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId));
|
||||
const RefIdColumn *skill = &mColumns.back();
|
||||
|
@ -346,15 +346,11 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
{ Columns::ColumnId_Flies, ESM::Creature::Flies },
|
||||
{ Columns::ColumnId_Walks, ESM::Creature::Walks },
|
||||
{ Columns::ColumnId_Essential, ESM::Creature::Essential },
|
||||
{ Columns::ColumnId_SkeletonBlood, ESM::Creature::Skeleton },
|
||||
{ Columns::ColumnId_MetalBlood, ESM::Creature::Metal },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
// for re-use in NPC records
|
||||
const RefIdColumn *essential = 0;
|
||||
const RefIdColumn *skeletonBlood = 0;
|
||||
const RefIdColumn *metalBlood = 0;
|
||||
|
||||
for (int i=0; sCreatureFlagTable[i].mName!=-1; ++i)
|
||||
{
|
||||
|
@ -364,11 +360,14 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
switch (sCreatureFlagTable[i].mFlag)
|
||||
{
|
||||
case ESM::Creature::Essential: essential = &mColumns.back(); break;
|
||||
case ESM::Creature::Skeleton: skeletonBlood = &mColumns.back(); break;
|
||||
case ESM::Creature::Metal: metalBlood = &mColumns.back(); break;
|
||||
}
|
||||
}
|
||||
|
||||
mColumns.push_back(RefIdColumn(Columns::ColumnId_BloodType, ColumnBase::Display_BloodType));
|
||||
// For re-use in NPC records.
|
||||
const RefIdColumn *bloodType = &mColumns.back();
|
||||
creatureColumns.mBloodType = bloodType;
|
||||
|
||||
creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
|
||||
|
||||
// Nested table
|
||||
|
@ -497,9 +496,8 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
|
||||
npcColumns.mFlags.insert (std::make_pair (autoCalc, ESM::NPC::Autocalc));
|
||||
|
||||
npcColumns.mFlags.insert (std::make_pair (skeletonBlood, ESM::NPC::Skeleton));
|
||||
|
||||
npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal));
|
||||
// Re-used from Creature records.
|
||||
npcColumns.mBloodType = bloodType;
|
||||
|
||||
// Need a way to add a table of stats and values (rather than adding a long list of
|
||||
// entries in the dialogue subview) E.g. attributes+stats(health, mana, fatigue), skills
|
||||
|
@ -659,7 +657,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||
mAdapters.insert (std::make_pair (UniversalId::Type_Armor,
|
||||
new ArmorRefIdAdapter (enchantableColumns, armorType, health, armor, partRef)));
|
||||
mAdapters.insert (std::make_pair (UniversalId::Type_Book,
|
||||
new BookRefIdAdapter (enchantableColumns, scroll, skill, text)));
|
||||
new BookRefIdAdapter (enchantableColumns, bookType, skill, text)));
|
||||
mAdapters.insert (std::make_pair (UniversalId::Type_Clothing,
|
||||
new ClothingRefIdAdapter (enchantableColumns, clothingType, partRef)));
|
||||
mAdapters.insert (std::make_pair (UniversalId::Type_Container,
|
||||
|
|
|
@ -107,6 +107,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
|||
{ CSMWorld::ColumnBase::Display_IngredEffectId, CSMWorld::Columns::ColumnId_EffectId, true },
|
||||
{ CSMWorld::ColumnBase::Display_EffectSkill, CSMWorld::Columns::ColumnId_Skill, false },
|
||||
{ CSMWorld::ColumnBase::Display_EffectAttribute, CSMWorld::Columns::ColumnId_Attribute, false },
|
||||
{ CSMWorld::ColumnBase::Display_BookType, CSMWorld::Columns::ColumnId_BookType, false},
|
||||
{ CSMWorld::ColumnBase::Display_BloodType, CSMWorld::Columns::ColumnId_BloodType, false}
|
||||
};
|
||||
|
||||
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -572,6 +572,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();
|
||||
|
|
|
@ -1286,6 +1286,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);
|
||||
|
@ -1295,6 +1296,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));
|
||||
|
@ -1305,17 +1307,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();
|
||||
|
@ -1327,6 +1341,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;
|
||||
|
||||
|
|
|
@ -426,6 +426,9 @@ namespace MWMechanics
|
|||
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
|
||||
inv.setSelectedEnchantItem(inv.end());
|
||||
}
|
||||
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(mSpellId);
|
||||
MWBase::Environment::get().getWorld()->preloadEffects(&spell->mEffects);
|
||||
}
|
||||
|
||||
float ActionSpell::getCombatRange (bool& isRanged) const
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <osg/Light>
|
||||
#include <osg/LightModel>
|
||||
|
@ -202,7 +203,8 @@ namespace MWRender
|
|||
|
||||
mObjects.reset(new Objects(mResourceSystem, sceneRoot, mUnrefQueue.get()));
|
||||
|
||||
mViewer->setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation);
|
||||
if (getenv("OPENMW_DONT_PRECOMPILE") == NULL)
|
||||
mViewer->setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation);
|
||||
|
||||
mResourceSystem->getSceneManager()->setIncrementalCompileOperation(mViewer->getIncrementalCompileOperation());
|
||||
|
||||
|
|
|
@ -10,6 +10,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"
|
||||
|
@ -679,6 +680,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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -159,7 +159,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);
|
||||
|
@ -1653,6 +1653,13 @@ namespace MWWorld
|
|||
updateSoundListener();
|
||||
|
||||
updatePlayer(paused);
|
||||
|
||||
mSpellPreloadTimer -= duration;
|
||||
if (mSpellPreloadTimer <= 0.f)
|
||||
{
|
||||
mSpellPreloadTimer = 0.1f;
|
||||
preloadSpells();
|
||||
}
|
||||
}
|
||||
|
||||
void World::updatePlayer(bool paused)
|
||||
|
@ -1709,7 +1716,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()
|
||||
|
@ -2803,7 +2842,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))
|
||||
|
@ -3439,4 +3477,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();
|
||||
|
||||
|
@ -680,6 +684,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…
Reference in a new issue