From 7dbc779c3aa4b40e4efabe918cc285c587b5d522 Mon Sep 17 00:00:00 2001 From: Glorf Date: Sat, 30 Mar 2013 19:08:42 +0100 Subject: [PATCH 001/198] Self-enchanting mechanics --- apps/openmw/mwgui/enchantingdialog.cpp | 22 +++++++++-- apps/openmw/mwmechanics/enchanting.cpp | 55 ++++++++++++++++++++++++-- apps/openmw/mwmechanics/enchanting.hpp | 9 ++++- 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index ef124bb430..7d5d1411f9 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -19,7 +19,6 @@ namespace MWGui : WindowBase("openmw_enchanting_dialog.layout", parWindowManager) , EffectEditorBase(parWindowManager) , mItemSelectionDialog(NULL) - , mEnchanting(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) { getWidget(mName, "NameEdit"); getWidget(mCancelButton, "CancelButton"); @@ -87,6 +86,9 @@ namespace MWGui void EnchantingDialog::startEnchanting (MWWorld::Ptr actor) { + mEnchanting.setSelfEnchanting(false); + mEnchanting.setEnchanter(actor); + mPtr = actor; startEditing (); @@ -94,7 +96,14 @@ namespace MWGui void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem) { - /// \todo + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + mEnchanting.setSelfEnchanting(true); + mEnchanting.setEnchanter(player); + + mPtr = player; + + startEditing(); } void EnchantingDialog::onReferenceUnavailable () @@ -264,8 +273,13 @@ namespace MWGui mEnchanting.setNewItemName(mName->getCaption()); mEnchanting.setEffect(mEffectList); - mEnchanting.create(); - mWindowManager.messageBox ("#{sEnchantmentMenu12}"); + int result = mEnchanting.create(); + + if(result==1) + mWindowManager.messageBox ("#{sEnchantmentMenu12}"); + else + mWindowManager.messageBox ("#{sNotifyMessage34}"); + mWindowManager.removeGuiMode (GM_Enchanting); } } diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 4ef20a5e52..3590ae0f3f 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -3,10 +3,13 @@ #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" + +#include "creaturestats.hpp" +#include "npcstats.hpp" + namespace MWMechanics { - Enchanting::Enchanting(MWWorld::Ptr enchanter): - mEnchanter(enchanter), + Enchanting::Enchanting(): mEnchantType(0) {} @@ -45,11 +48,20 @@ namespace MWMechanics mSoulGemPtr=soulGem; } - void Enchanting::create() + int Enchanting::create() { - mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1); + if(mSelfEnchanting) + { + if(getEnchantChance() (RAND_MAX)*100) + return 0; + + MWWorld::Class::get (mEnchanter).skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 1); + } + + mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); + mEnchantment.mData.mCharge = getGemCharge(); if(mEnchantType==3) { @@ -67,6 +79,7 @@ namespace MWMechanics MWWorld::Ptr result = mOldItemPtr; result.mPtr = newobjPtr.mPtr; MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (result); + return 1; } void Enchanting::nextEnchantType() @@ -110,6 +123,10 @@ namespace MWMechanics float cost = 0; std::vector mEffects = mEffectList.mList; int i=mEffects.size(); + + /* + Formula from http://www.uesp.net/wiki/Morrowind:Enchant + */ for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) { const ESM::MagicEffect* effect = store.get().find(it->mEffectID); @@ -164,4 +181,34 @@ namespace MWMechanics return true; return false; } + + void Enchanting::setSelfEnchanting(bool selfEnchanting) + { + mSelfEnchanting = selfEnchanting; + } + + void Enchanting::setEnchanter(MWWorld::Ptr enchanter) + { + mEnchanter = enchanter; + } + + float Enchanting::getEnchantChance() + { + /* + Formula from http://www.uesp.net/wiki/Morrowind:Enchant + */ + const CreatureStats& creatureStats = MWWorld::Class::get (mEnchanter).getCreatureStats (mEnchanter); + const NpcStats& npcStats = MWWorld::Class::get (mEnchanter).getNpcStats (mEnchanter); + + float chance1 = (npcStats.getSkill (ESM::Skill::Enchant).getModified() + + (0.25 * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified()) + + (0.125 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified())); + + float chance2 = 2.5 * getEnchantCost(); + if(mEnchantType==3) + { + chance2 *= 2; + } + return (chance1-chance2); + } } diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp index 1daf34c6d1..fffa2c5b20 100644 --- a/apps/openmw/mwmechanics/enchanting.hpp +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -16,6 +16,8 @@ namespace MWMechanics const MWWorld::Ptr *mNewItemPtr; int mEnchantType; + bool mSelfEnchanting; + ESM::EffectList mEffectList; ESM::Enchantment mEnchantment; @@ -23,17 +25,20 @@ namespace MWMechanics std::string mObjectType; std::string mOldItemId; public: - Enchanting(MWWorld::Ptr enchanter); + Enchanting(); + void setEnchanter(MWWorld::Ptr enchanter); + void setSelfEnchanting(bool selfEnchanting); void setOldItem(MWWorld::Ptr oldItem); void setNewItemName(std::string s); void setEffect(ESM::EffectList effectList); void setSoulGem(MWWorld::Ptr soulGem); - void create(); + int create(); void nextEnchantType(); int getEnchantType(); int getEnchantCost(); int getMaxEnchantValue(); int getGemCharge(); + float getEnchantChance(); bool soulEmpty(); bool itemEmpty(); }; From d29a42dcbe37b968827b7648eab6ce8f345bbf66 Mon Sep 17 00:00:00 2001 From: Glorf Date: Sun, 31 Mar 2013 23:18:23 +0200 Subject: [PATCH 002/198] Fixed enchanting mechanics --- apps/openmw/mwclass/armor.cpp | 4 ++-- apps/openmw/mwclass/armor.hpp | 2 +- apps/openmw/mwclass/book.cpp | 4 ++-- apps/openmw/mwclass/book.hpp | 2 +- apps/openmw/mwclass/clothing.cpp | 4 ++-- apps/openmw/mwclass/clothing.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 4 ++-- apps/openmw/mwclass/weapon.hpp | 2 +- apps/openmw/mwgui/enchantingdialog.cpp | 12 +++++++++--- apps/openmw/mwmechanics/enchanting.cpp | 21 +++++++++++---------- apps/openmw/mwmechanics/enchanting.hpp | 4 +++- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- 13 files changed, 37 insertions(+), 28 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 281dd1f42c..b94c270d56 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -274,7 +274,7 @@ namespace MWClass return ref->mBase->mEnchant; } - std::string Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + void Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -285,7 +285,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - return record->mId; + ref->mBase = record; } boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 0c32015a35..65f49abb7d 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -65,7 +65,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 644561e52b..85b006160b 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -147,7 +147,7 @@ namespace MWClass return ref->mBase->mEnchant; } - std::string Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + void Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -159,7 +159,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - return record->mId; + ref->mBase = record; } boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index c17d4255b1..29e3de0361 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -51,7 +51,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 8f29a2084d..d65376898e 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -221,7 +221,7 @@ namespace MWClass return ref->mBase->mEnchant; } - std::string Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + void Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -232,7 +232,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - return record->mId; + ref->mBase = record; } boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 4457e79fb6..c3ef22f113 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -59,7 +59,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 894b38acc9..ed2a095e37 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -367,7 +367,7 @@ namespace MWClass return ref->mBase->mEnchant; } - std::string Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + void Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -378,7 +378,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - return record->mId; + ref->mBase = record; } boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 533f32f592..4774bb50be 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -65,7 +65,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 7d5d1411f9..0f3b8b7cb0 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -86,10 +86,16 @@ namespace MWGui void EnchantingDialog::startEnchanting (MWWorld::Ptr actor) { - mEnchanting.setSelfEnchanting(false); - mEnchanting.setEnchanter(actor); - mPtr = actor; + /*Now there's no need to use other enchanters, player is the enchanter here, + even if the enchanted object is created by NPC. Could be changed later, probably + with some price formulas */ + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + + mEnchanting.setSelfEnchanting(false); + mEnchanting.setEnchanter(player); + + mPtr = player; startEditing (); } diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 3590ae0f3f..ba4e46de79 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -20,6 +20,7 @@ namespace MWMechanics { mObjectType = mOldItemPtr.getTypeName(); mOldItemId = mOldItemPtr.getCellRef().mRefID; + mOldItemCount = mOldItemPtr.getRefData().getCount(); } else { @@ -50,7 +51,8 @@ namespace MWMechanics int Enchanting::create() { - mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1); + mEnchantment.mData.mCharge = getGemCharge(); + mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); if(mSelfEnchanting) { @@ -60,9 +62,6 @@ namespace MWMechanics MWWorld::Class::get (mEnchanter).skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 1); } - mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); - - mEnchantment.mData.mCharge = getGemCharge(); if(mEnchantType==3) { mEnchantment.mData.mCharge=0; @@ -70,15 +69,17 @@ namespace MWMechanics mEnchantment.mData.mType = mEnchantType; mEnchantment.mData.mCost = getEnchantCost(); mEnchantment.mEffects = mEffectList; + const ESM::Enchantment *enchantment = MWBase::Environment::get().getWorld()->createRecord (mEnchantment); - std::string newobjId = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); + MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); + + mOldItemPtr.getRefData().setCount(1); + + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId); + ref.getPtr().getRefData().setCount (mOldItemCount-1); + MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobjId); - MWWorld::Ptr newobjPtr = ref.getPtr(); - MWWorld::Ptr result = mOldItemPtr; - result.mPtr = newobjPtr.mPtr; - MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (result); return 1; } diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp index fffa2c5b20..1a7dde708c 100644 --- a/apps/openmw/mwmechanics/enchanting.hpp +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -13,7 +13,7 @@ namespace MWMechanics MWWorld::Ptr mOldItemPtr; MWWorld::Ptr mSoulGemPtr; MWWorld::Ptr mEnchanter; - const MWWorld::Ptr *mNewItemPtr; + int mEnchantType; bool mSelfEnchanting; @@ -24,6 +24,8 @@ namespace MWMechanics std::string mNewItemName; std::string mObjectType; std::string mOldItemId; + int mOldItemCount; + public: Enchanting(); void setEnchanter(MWWorld::Ptr enchanter); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 876328641a..9a83063c03 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -246,7 +246,7 @@ namespace MWWorld return ""; } - std::string Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + void Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { throw std::runtime_error ("class can't be enchanted"); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 012a03bf62..2f010eb3d7 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -234,7 +234,7 @@ namespace MWWorld virtual std::string getModel(const MWWorld::Ptr &ptr) const; - virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell) const; From 1bff6ed872f9deb860682fae7e398c8778433292 Mon Sep 17 00:00:00 2001 From: Glorf Date: Mon, 1 Apr 2013 17:12:47 +0200 Subject: [PATCH 003/198] Enchaning values import, fixed constness --- apps/openmw/mwmechanics/enchanting.cpp | 46 ++++++++++++++------------ apps/openmw/mwmechanics/enchanting.hpp | 22 ++++++------ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index ba4e46de79..d86f7c1511 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -29,7 +29,7 @@ namespace MWMechanics } } - void Enchanting::setNewItemName(std::string s) + void Enchanting::setNewItemName(const std::string& s) { mNewItemName=s; } @@ -39,7 +39,7 @@ namespace MWMechanics mEffectList=effectList; } - int Enchanting::getEnchantType() + int Enchanting::getEnchantType() const { return mEnchantType; } @@ -49,30 +49,31 @@ namespace MWMechanics mSoulGemPtr=soulGem; } - int Enchanting::create() + bool Enchanting::create() { - mEnchantment.mData.mCharge = getGemCharge(); + ESM::Enchantment enchantment; + enchantment.mData.mCharge = getGemCharge(); mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); if(mSelfEnchanting) { if(getEnchantChance() (RAND_MAX)*100) - return 0; + return false; MWWorld::Class::get (mEnchanter).skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 1); } if(mEnchantType==3) { - mEnchantment.mData.mCharge=0; + enchantment.mData.mCharge=0; } - mEnchantment.mData.mType = mEnchantType; - mEnchantment.mData.mCost = getEnchantCost(); - mEnchantment.mEffects = mEffectList; + enchantment.mData.mType = mEnchantType; + enchantment.mData.mCost = getEnchantCost(); + enchantment.mEffects = mEffectList; - const ESM::Enchantment *enchantment = MWBase::Environment::get().getWorld()->createRecord (mEnchantment); + const ESM::Enchantment *enchantmentPtr = MWBase::Environment::get().getWorld()->createRecord (enchantment); - MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); + MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName); mOldItemPtr.getRefData().setCount(1); @@ -80,7 +81,7 @@ namespace MWMechanics ref.getPtr().getRefData().setCount (mOldItemCount-1); MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); - return 1; + return true; } void Enchanting::nextEnchantType() @@ -93,12 +94,13 @@ namespace MWMechanics } if ((mObjectType == typeid(ESM::Armor).name())||(mObjectType == typeid(ESM::Clothing).name())) { + int soulConstAmount = MWBase::Environment::get().getWorld()->getStore().get().find ("iSoulAmountForConstantEffect")->getInt(); switch(mEnchantType) { case 1: mEnchantType = 2; case 3: - if(getGemCharge()<400) + if(getGemCharge()getStore(); float cost = 0; @@ -138,7 +140,8 @@ namespace MWMechanics if(mEnchantType==3) { - cost1 *= 100; + int constDurationMultipler = MWBase::Environment::get().getWorld()->getStore().get().find ("fEnchantmentConstantDurationMult")->getFloat(); + cost1 *= constDurationMultipler; cost2 *= 2; } if(effect->mData.mFlags & ESM::MagicEffect::CastTarget) @@ -152,7 +155,7 @@ namespace MWMechanics } return cost; } - int Enchanting::getGemCharge() + int Enchanting::getGemCharge() const { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); if(soulEmpty()) @@ -163,20 +166,20 @@ namespace MWMechanics return soul->mData.mSoul; } - int Enchanting::getMaxEnchantValue() + int Enchanting::getMaxEnchantValue() const { if (itemEmpty()) return 0; return MWWorld::Class::get(mOldItemPtr).getEnchantmentPoints(mOldItemPtr); } - bool Enchanting::soulEmpty() + bool Enchanting::soulEmpty() const { if (mSoulGemPtr.isEmpty()) return true; return false; } - bool Enchanting::itemEmpty() + bool Enchanting::itemEmpty() const { if(mOldItemPtr.isEmpty()) return true; @@ -193,7 +196,7 @@ namespace MWMechanics mEnchanter = enchanter; } - float Enchanting::getEnchantChance() + float Enchanting::getEnchantChance() const { /* Formula from http://www.uesp.net/wiki/Morrowind:Enchant @@ -208,7 +211,8 @@ namespace MWMechanics float chance2 = 2.5 * getEnchantCost(); if(mEnchantType==3) { - chance2 *= 2; + float constantChance = MWBase::Environment::get().getWorld()->getStore().get().find ("fEnchantmentConstantChanceMult")->getFloat(); + chance2 /= constantChance; } return (chance1-chance2); } diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp index 1a7dde708c..c951ae8256 100644 --- a/apps/openmw/mwmechanics/enchanting.hpp +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -9,7 +9,6 @@ namespace MWMechanics { class Enchanting { - MWWorld::Ptr mOldItemPtr; MWWorld::Ptr mSoulGemPtr; MWWorld::Ptr mEnchanter; @@ -19,7 +18,6 @@ namespace MWMechanics bool mSelfEnchanting; ESM::EffectList mEffectList; - ESM::Enchantment mEnchantment; std::string mNewItemName; std::string mObjectType; @@ -31,18 +29,18 @@ namespace MWMechanics void setEnchanter(MWWorld::Ptr enchanter); void setSelfEnchanting(bool selfEnchanting); void setOldItem(MWWorld::Ptr oldItem); - void setNewItemName(std::string s); + void setNewItemName(const std::string& s); void setEffect(ESM::EffectList effectList); void setSoulGem(MWWorld::Ptr soulGem); - int create(); - void nextEnchantType(); - int getEnchantType(); - int getEnchantCost(); - int getMaxEnchantValue(); - int getGemCharge(); - float getEnchantChance(); - bool soulEmpty(); - bool itemEmpty(); + bool create(); //Return true if created, false if failed. + void nextEnchantType(); //Set enchant type to next possible type (for mOldItemPtr object) + int getEnchantType() const; + int getEnchantCost() const; + int getMaxEnchantValue() const; + int getGemCharge() const; + float getEnchantChance() const; + bool soulEmpty() const; //Return true if empty + bool itemEmpty() const; //Return true if empty }; } #endif From 9dbd024076efabe5e3a109e359495bb9f7c75cee Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 1 Apr 2013 17:30:54 +0200 Subject: [PATCH 004/198] another minor fix --- apps/openmw/mwmechanics/objects.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/objects.hpp b/apps/openmw/mwmechanics/objects.hpp index 3a2e51644e..7b1185a29a 100644 --- a/apps/openmw/mwmechanics/objects.hpp +++ b/apps/openmw/mwmechanics/objects.hpp @@ -1,5 +1,5 @@ #ifndef GAME_MWMECHANICS_ACTIVATORS_H -#define GAME_MWMECHANICS_ACTOVATORS_H +#define GAME_MWMECHANICS_ACTIVATORS_H #include #include From d25c838e1d3c5f9aabfc4c41e1482e835c6c034e Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 2 Apr 2013 11:42:29 +0200 Subject: [PATCH 005/198] Bugfix #646 --- apps/openmw/mwworld/actionequip.cpp | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index afbb505f22..513182a2dc 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -108,6 +108,46 @@ namespace MWWorld } + //Disable twohanded when shield equipped, shield when twohanded equipped + if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) + { + invStore.equip(*slot, it); + + if (it.getType() == MWWorld::ContainerStore::Type_Weapon) + { + if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + it->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + it->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + it->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + it->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + { + //unequip lefthand item + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + } + } + } + if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft) + { + ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + + if (weapon.getType() == MWWorld::ContainerStore::Type_Weapon) + { + if(weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + weapon->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + weapon->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + { + //unequip twohanded item + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + } + } + } + // if all slots are occupied, replace the last slot if (slot == --slots.first.end()) { From c71edb613d12e3b46bd4d0e998e054bbcf4cc330 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Apr 2013 12:00:45 +0200 Subject: [PATCH 006/198] added faction table --- apps/opencs/model/world/data.cpp | 16 ++++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 3 +++ components/esm/loadfact.cpp | 25 +++++++++++++++++++++++-- components/esm/loadfact.hpp | 3 +++ 9 files changed, 67 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 7b3e667715..825e29a232 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -57,10 +57,15 @@ CSMWorld::Data::Data() mClasses.addColumn (new PlayableColumn); mClasses.addColumn (new DescriptionColumn); + mFactions.addColumn (new StringIdColumn); + mFactions.addColumn (new RecordStateColumn); + mFactions.addColumn (new NameColumn); + 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); addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); + addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); } CSMWorld::Data::~Data() @@ -99,6 +104,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getSkills() return mSkills; } +const CSMWorld::IdCollection& CSMWorld::Data::getFactions() const +{ + return mFactions; +} + +CSMWorld::IdCollection& CSMWorld::Data::getFactions() +{ + return mFactions; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -137,6 +152,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_GMST: mGmsts.load (reader, base); break; case ESM::REC_SKIL: mSkills.load (reader, base); break; case ESM::REC_CLAS: mClasses.load (reader, base); break; + case ESM::REC_FACT: mFactions.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 7baf03259e..1e2894774a 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -24,6 +25,7 @@ namespace CSMWorld IdCollection mGmsts; IdCollection mSkills; IdCollection mClasses; + IdCollection mFactions; std::vector mModels; std::map mModelIndex; @@ -52,6 +54,10 @@ namespace CSMWorld IdCollection& getSkills(); + const IdCollection& getFactions() const; + + IdCollection& getFactions(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index a85b30c2a8..985cab0d4c 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -21,6 +21,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -31,6 +32,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 4c4d95654b..0190467c4b 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -41,7 +41,9 @@ namespace CSMWorld Type_Skills, Type_Skill, Type_Classes, - Type_Class + Type_Class, + Type_Factions, + Type_Faction }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 2ef66593f7..3c4bc3b047 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -94,6 +94,10 @@ void CSVDoc::View::setupWorldMenu() connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView())); world->addAction (classes); + QAction *factions = new QAction (tr ("Factions"), this); + connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView())); + world->addAction (factions); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); world->addAction (mVerify); @@ -262,6 +266,11 @@ void CSVDoc::View::addClassesSubView() addSubView (CSMWorld::UniversalId::Type_Classes); } +void CSVDoc::View::addFactionsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Factions); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index bc8e8fc26d..03905430a8 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -119,6 +119,8 @@ namespace CSVDoc void addSkillsSubView(); void addClassesSubView(); + + void addFactionsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 5d715ea21e..cbfbf6b464 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -20,6 +20,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Classes, new CSVDoc::SubViewFactoryWithCreateFlag (true)); + manager.add (CSMWorld::UniversalId::Type_Factions, + new CSVDoc::SubViewFactoryWithCreateFlag (true)); + // manager.add (CSMWorld::UniversalId::Type_Global, // new CSVDoc::SubViewFactoryWithCreateFlag (true)); } \ No newline at end of file diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index 6ea66977d5..50fb94bbb7 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -33,7 +33,7 @@ void Faction::load(ESMReader &esm) void Faction::save(ESMWriter &esm) { esm.writeHNCString("FNAM", mName); - + for (int i = 0; i < 10; i++) { if (mRanks[i].empty()) @@ -43,7 +43,7 @@ void Faction::save(ESMWriter &esm) } esm.writeHNT("FADT", mData, 240); - + for (std::vector::iterator it = mReactions.begin(); it != mReactions.end(); ++it) { esm.writeHNString("ANAM", it->mFaction); @@ -51,4 +51,25 @@ void Faction::save(ESMWriter &esm) } } + void Faction::blank() + { + mName.clear(); + mData.mAttribute1 = mData.mAttribute2 = 0; + mData.mUnknown = -1; + mData.mIsHidden = 0; + + for (int i=0; i<10; ++i) + { + mData.mRankData[i].mAttribute1 = mData.mRankData[i].mAttribute2 = 0; + mData.mRankData[i].mSkill1 = mData.mRankData[i].mSkill2 = 0; + mData.mRankData[i].mFactReaction = 0; + + mRanks[i].clear(); + } + + for (int i=0; i<6; ++i) + mData.mSkillID[i] = 0; + + mReactions.clear(); + } } diff --git a/components/esm/loadfact.hpp b/components/esm/loadfact.hpp index 49898b1cf2..a2ba688c01 100644 --- a/components/esm/loadfact.hpp +++ b/components/esm/loadfact.hpp @@ -58,6 +58,9 @@ struct Faction void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } #endif From f9f520df34373dc585d7bf695362564a6b7fe3b7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Apr 2013 13:59:45 +0200 Subject: [PATCH 007/198] adjusted faction record to increase consistency with other records --- apps/esmtool/record.cpp | 14 +++++++------- apps/openmw/mwdialogue/filter.cpp | 4 ++-- apps/openmw/mwgui/stats_window.cpp | 6 +++--- apps/openmw/mwmechanics/npcstats.cpp | 2 +- components/esm/loadclas.cpp | 19 +++++++++++++++++++ components/esm/loadclas.hpp | 6 ++++++ components/esm/loadfact.cpp | 21 +++++++++++++++++++-- components/esm/loadfact.hpp | 10 ++++++++-- 8 files changed, 65 insertions(+), 17 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index de3a175106..8f77e4b445 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -679,14 +679,14 @@ void Record::print() std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl; if (mData.mData.mUnknown != -1) std::cout << " Unknown: " << mData.mData.mUnknown << std::endl; - std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute1) - << " (" << mData.mData.mAttribute1 << ")" << std::endl; - std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute2) - << " (" << mData.mData.mAttribute2 << ")" << std::endl; + std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttributes[0]) + << " (" << mData.mData.mAttributes[0] << ")" << std::endl; + std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttributes[1]) + << " (" << mData.mData.mAttributes[1] << ")" << std::endl; for (int i = 0; i != 6; i++) - if (mData.mData.mSkillID[i] != -1) - std::cout << " Skill: " << skillLabel(mData.mData.mSkillID[i]) - << " (" << mData.mData.mSkillID[i] << ")" << std::endl; + if (mData.mData.mSkills[i] != -1) + std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i]) + << " (" << mData.mData.mSkills[i] << ")" << std::endl; for (int i = 0; i != 10; i++) if (mData.mRanks[i] != "") { diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index f7e9529568..ddb15d423d 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -569,8 +569,8 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements (const MWWorld::Ptr& ac MWMechanics::CreatureStats& stats = MWWorld::Class::get (actor).getCreatureStats (actor); - return stats.getAttribute (faction.mData.mAttribute1).getBase()>=faction.mData.mRankData[rank].mAttribute1 && - stats.getAttribute (faction.mData.mAttribute2).getBase()>=faction.mData.mRankData[rank].mAttribute2; + return stats.getAttribute (faction.mData.mAttributes[0]).getBase()>=faction.mData.mRankData[rank].mAttribute1 && + stats.getAttribute (faction.mData.mAttributes[1]).getBase()>=faction.mData.mRankData[rank].mAttribute2; } bool MWDialogue::Filter::hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 0fa4127b55..86019fa28d 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -500,8 +500,8 @@ void StatsWindow::updateSkillArea() text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; ESM::RankData rankData = faction->mData.mRankData[it->second+1]; - const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute1); - const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute2); + const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttributes[0]); + const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttributes[1]); assert(attr1 && attr2); text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) @@ -511,7 +511,7 @@ void StatsWindow::updateSkillArea() text += "\n#BF9959"; for (int i=0; i<6; ++i) { - text += "#{"+ESM::Skill::sSkillNameIds[faction->mData.mSkillID[i]]+"}"; + text += "#{"+ESM::Skill::sSkillNameIds[faction->mData.mSkills[i]]+"}"; if (i<5) text += ", "; } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index b9aee6abf3..7216e8fe0e 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -334,7 +334,7 @@ bool MWMechanics::NpcStats::hasSkillsForRank (const std::string& factionId, int std::vector skills; for (int i=0; i<6; ++i) - skills.push_back (static_cast (getSkill (faction.mData.mSkillID[i]).getModified())); + skills.push_back (static_cast (getSkill (faction.mData.mSkills[i]).getModified())); std::sort (skills.begin(), skills.end()); diff --git a/components/esm/loadclas.cpp b/components/esm/loadclas.cpp index d9f367fd63..bdc4614625 100644 --- a/components/esm/loadclas.cpp +++ b/components/esm/loadclas.cpp @@ -1,5 +1,7 @@ #include "loadclas.hpp" +#include + #include "esmreader.hpp" #include "esmwriter.hpp" @@ -18,6 +20,23 @@ const char *Class::sGmstSpecializationIds[3] = { "sSpecializationStealth" }; + + int& Class::CLDTstruct::getSkill (int index, bool major) + { + if (index<0 || index>=5) + throw std::logic_error ("skill index out of range"); + + return mSkills[index][major ? 1 : 0]; + } + + int Class::CLDTstruct::getSkill (int index, bool major) const + { + if (index<0 || index>=5) + throw std::logic_error ("skill index out of range"); + + return mSkills[index][major ? 1 : 0]; + } + void Class::load(ESMReader &esm) { mName = esm.getHNString("FNAM"); diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index ac596af32c..4f85e6ee8b 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -58,6 +58,12 @@ struct Class // I have no idea how to autocalculate these items... int mCalc; + + int& getSkill (int index, bool major); + ///< Throws an exception for invalid values of \a index. + + int getSkill (int index, bool major) const; + ///< Throws an exception for invalid values of \a index. }; // 60 bytes std::string mId, mName, mDescription; diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index 50fb94bbb7..12a76f1ade 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -1,10 +1,27 @@ #include "loadfact.hpp" +#include + #include "esmreader.hpp" #include "esmwriter.hpp" namespace ESM { + int& Faction::FADTstruct::getSkill (int index, bool ignored) + { + if (index<0 || index>=6) + throw std::logic_error ("skill index out of range"); + + return mSkills[index]; + } + + int Faction::FADTstruct::getSkill (int index, bool ignored) const + { + if (index<0 || index>=6) + throw std::logic_error ("skill index out of range"); + + return mSkills[index]; + } void Faction::load(ESMReader &esm) { @@ -54,7 +71,7 @@ void Faction::save(ESMWriter &esm) void Faction::blank() { mName.clear(); - mData.mAttribute1 = mData.mAttribute2 = 0; + mData.mAttributes[0] = mData.mAttributes[1] = 0; mData.mUnknown = -1; mData.mIsHidden = 0; @@ -68,7 +85,7 @@ void Faction::save(ESMWriter &esm) } for (int i=0; i<6; ++i) - mData.mSkillID[i] = 0; + mData.mSkills[i] = 0; mReactions.clear(); } diff --git a/components/esm/loadfact.hpp b/components/esm/loadfact.hpp index a2ba688c01..edc4640bb1 100644 --- a/components/esm/loadfact.hpp +++ b/components/esm/loadfact.hpp @@ -34,13 +34,19 @@ struct Faction struct FADTstruct { // Which attributes we like - int mAttribute1, mAttribute2; + int mAttributes[2]; RankData mRankData[10]; - int mSkillID[6]; // IDs of skills this faction require + int mSkills[6]; // IDs of skills this faction require int mUnknown; // Always -1? int mIsHidden; // 1 - hidden from player + + int& getSkill (int index, bool ignored = false); + ///< Throws an exception for invalid values of \a index. + + int getSkill (int index, bool ignored = false) const; + ///< Throws an exception for invalid values of \a index. }; // 240 bytes FADTstruct mData; From ec6bdbeb40dd3641233ac5e22b4557ee795affe0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Apr 2013 14:04:13 +0200 Subject: [PATCH 008/198] added skill columns to faction table --- apps/opencs/model/world/columns.hpp | 8 ++++---- apps/opencs/model/world/data.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index cbcddd972d..9345df0d20 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -347,15 +347,15 @@ namespace CSMWorld int mIndex; bool mMajor; - SkillsColumn (int index, bool major) - : Column ((major ? "Major Skill #" : "Minor Skill #")+ + SkillsColumn (int index, bool typePrefix = false, bool major = false) + : Column ((typePrefix ? (major ? "Major Skill #" : "Minor Skill #") : "Skill #")+ boost::lexical_cast (index), ColumnBase::Display_String), mIndex (index), mMajor (major) {} virtual QVariant get (const Record& record) const { - int skill = record.get().mData.mSkills[mIndex][mMajor ? 1 : 0]; + int skill = record.get().mData.getSkill (mIndex, mMajor); return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str()); } @@ -373,7 +373,7 @@ namespace CSMWorld { ESXRecordT record2 = record.get(); - record2.mData.mSkills[mIndex][mMajor ? 1 : 0] = index; + record2.mData.getSkill (mIndex, mMajor) = index; record.setModified (record2); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 825e29a232..23a1eb91b9 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -51,15 +51,17 @@ CSMWorld::Data::Data() mClasses.addColumn (new AttributesColumn (1)); mClasses.addColumn (new SpecialisationColumn); for (int i=0; i<5; ++i) - mClasses.addColumn (new SkillsColumn (i, true)); + mClasses.addColumn (new SkillsColumn (i, true, true)); for (int i=0; i<5; ++i) - mClasses.addColumn (new SkillsColumn (i, false)); + mClasses.addColumn (new SkillsColumn (i, true, false)); mClasses.addColumn (new PlayableColumn); mClasses.addColumn (new DescriptionColumn); mFactions.addColumn (new StringIdColumn); mFactions.addColumn (new RecordStateColumn); mFactions.addColumn (new NameColumn); + for (int i=0; i<6; ++i) + mFactions.addColumn (new SkillsColumn (i)); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From 900c2cfa81b629a74fcb3ce112fbbf1578217c3a Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 2 Apr 2013 14:08:59 +0200 Subject: [PATCH 009/198] Minor bugfix #646 change --- apps/openmw/mwworld/actionequip.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 513182a2dc..9a44a99791 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -111,8 +111,6 @@ namespace MWWorld //Disable twohanded when shield equipped, shield when twohanded equipped if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) { - invStore.equip(*slot, it); - if (it.getType() == MWWorld::ContainerStore::Type_Weapon) { if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || From 384c88182dfa5ab54e215bafa99edc8cfed6a867 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Apr 2013 14:15:22 +0200 Subject: [PATCH 010/198] dealing with unset attribute fields --- apps/opencs/view/doc/viewmanager.cpp | 2 +- apps/opencs/view/world/enumdelegate.cpp | 5 ++++- apps/opencs/view/world/enumdelegate.hpp | 3 ++- components/esm/loadskil.cpp | 15 +++++++++------ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index bc87728945..3be7228b31 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -61,7 +61,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) new CSVWorld::EnumDelegateFactory (sSpecialisations)); mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute, - new CSVWorld::EnumDelegateFactory (sAttributes)); + new CSVWorld::EnumDelegateFactory (sAttributes, true)); } CSVDoc::ViewManager::~ViewManager() diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 0dd0a1d594..b1e9f72865 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -92,10 +92,13 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {} -CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names) +CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names, bool allowNone) { assert (names); + if (allowNone) + add (-1, ""); + for (int i=0; names[i]; ++i) add (i, names[i]); } diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index 752ed5be72..58f19ff782 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -47,8 +47,9 @@ namespace CSVWorld EnumDelegateFactory(); - EnumDelegateFactory (const char **names); + EnumDelegateFactory (const char **names, bool allowNone = false); ///< \param names Array of char pointer with a 0-pointer as end mark + /// \param allowNone Use value of -1 for "none selected" (empty string) virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index b7259db94e..b57645f3b8 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -127,15 +127,18 @@ void Skill::save(ESMWriter &esm) { std::ostringstream stream; - stream << "#"; + if (index!=-1) + { + stream << "#"; - if (index<10) - stream << "0"; + if (index<10) + stream << "0"; - stream << index; + stream << index; - if (index>=0 && index=0 && index Date: Tue, 2 Apr 2013 14:20:51 +0200 Subject: [PATCH 011/198] added hidden flag column to faction table --- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 26 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 9345df0d20..dfabaaf2cf 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -409,6 +409,31 @@ namespace CSMWorld return true; } }; + + template + struct HiddenColumn : public Column + { + HiddenColumn() : Column ("Hidden", ColumnBase::Display_Boolean) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mIsHidden!=0; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mIsHidden = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 23a1eb91b9..13fff7f096 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -60,6 +60,7 @@ CSMWorld::Data::Data() mFactions.addColumn (new StringIdColumn); mFactions.addColumn (new RecordStateColumn); mFactions.addColumn (new NameColumn); + mFactions.addColumn (new HiddenColumn); for (int i=0; i<6; ++i) mFactions.addColumn (new SkillsColumn (i)); From 9d009af2a132823795dc949ed9b030e4a95e7a1e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Apr 2013 15:33:28 +0200 Subject: [PATCH 012/198] simplified code for sub view factory creation --- apps/opencs/view/world/subviews.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index cbfbf6b464..de36594a58 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -8,20 +8,24 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { - manager.add (CSMWorld::UniversalId::Type_Globals, - new CSVDoc::SubViewFactoryWithCreateFlag (true)); - manager.add (CSMWorld::UniversalId::Type_Gmsts, new CSVDoc::SubViewFactoryWithCreateFlag (false)); manager.add (CSMWorld::UniversalId::Type_Skills, new CSVDoc::SubViewFactoryWithCreateFlag (false)); - manager.add (CSMWorld::UniversalId::Type_Classes, - new CSVDoc::SubViewFactoryWithCreateFlag (true)); + static const CSMWorld::UniversalId::Type sTableTypes[] = + { + CSMWorld::UniversalId::Type_Globals, + CSMWorld::UniversalId::Type_Classes, + CSMWorld::UniversalId::Type_Factions, + + CSMWorld::UniversalId::Type_None // end marker + }; + + for (int i=0; sTableTypes[i]!=CSMWorld::UniversalId::Type_None; ++i) + manager.add (sTableTypes[i], new CSVDoc::SubViewFactoryWithCreateFlag (true)); - manager.add (CSMWorld::UniversalId::Type_Factions, - new CSVDoc::SubViewFactoryWithCreateFlag (true)); // manager.add (CSMWorld::UniversalId::Type_Global, // new CSVDoc::SubViewFactoryWithCreateFlag (true)); From 676a92e2e0157abe29fd898531b0c63610db0466 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Apr 2013 15:47:25 +0200 Subject: [PATCH 013/198] moved Verify function from World menu to File menu --- apps/opencs/view/doc/view.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 3c4bc3b047..83b333c04e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -41,6 +41,10 @@ void CSVDoc::View::setupFileMenu() connect (mSave, SIGNAL (triggered()), this, SLOT (save())); file->addAction (mSave); + mVerify = new QAction (tr ("&Verify"), this); + connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); + file->addAction (mVerify); + QAction *close = new QAction (tr ("&Close"), this); connect (close, SIGNAL (triggered()), this, SLOT (close())); file->addAction(close); @@ -97,10 +101,6 @@ void CSVDoc::View::setupWorldMenu() QAction *factions = new QAction (tr ("Factions"), this); connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView())); world->addAction (factions); - - mVerify = new QAction (tr ("&Verify"), this); - connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); - world->addAction (mVerify); } void CSVDoc::View::setupUi() From 369cf0b4cafac002e0a0338163b95a29630f2b51 Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 2 Apr 2013 20:46:48 +0200 Subject: [PATCH 014/198] Enchanting price mechanics --- apps/openmw/mwgui/enchantingdialog.cpp | 27 ++++++++---------- apps/openmw/mwmechanics/enchanting.cpp | 38 +++++++++++++++++++++++++- apps/openmw/mwmechanics/enchanting.hpp | 2 ++ 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 0f3b8b7cb0..1ed80127d4 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -63,6 +63,8 @@ namespace MWGui mCastCost->setCaption(boost::lexical_cast(mEnchanting.getEnchantCost())); + mPrice->setCaption(boost::lexical_cast(mEnchanting.getEnchantPrice())); + switch(mEnchanting.getEnchantType()) { case 0: @@ -86,16 +88,10 @@ namespace MWGui void EnchantingDialog::startEnchanting (MWWorld::Ptr actor) { - - /*Now there's no need to use other enchanters, player is the enchanter here, - even if the enchanted object is created by NPC. Could be changed later, probably - with some price formulas */ - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - mEnchanting.setSelfEnchanting(false); - mEnchanting.setEnchanter(player); + mEnchanting.setEnchanter(actor); - mPtr = player; + mPtr = actor; startEditing (); } @@ -103,13 +99,14 @@ namespace MWGui void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Ptr gem = soulgem; mEnchanting.setSelfEnchanting(true); mEnchanting.setEnchanter(player); mPtr = player; - startEditing(); + mEnchanting.setSoulGem(gem); } void EnchantingDialog::onReferenceUnavailable () @@ -252,12 +249,6 @@ namespace MWGui return; } - if (boost::lexical_cast(mPrice->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) - { - mWindowManager.messageBox ("#{sNotifyMessage18}"); - return; - } - if (mEnchanting.soulEmpty()) { mWindowManager.messageBox ("#{sNotifyMessage52}"); @@ -279,6 +270,12 @@ namespace MWGui mEnchanting.setNewItemName(mName->getCaption()); mEnchanting.setEffect(mEffectList); + if (mEnchanting.getEnchantPrice() > mWindowManager.getInventoryWindow()->getPlayerGold()) + { + mWindowManager.messageBox ("#{sNotifyMessage18}"); + return; + } + int result = mEnchanting.create(); if(result==1) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index d86f7c1511..a2f85fb0c4 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -3,6 +3,7 @@ #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwbase/mechanicsmanager.hpp" #include "creaturestats.hpp" #include "npcstats.hpp" @@ -79,7 +80,10 @@ namespace MWMechanics MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId); ref.getPtr().getRefData().setCount (mOldItemCount-1); - MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::Class::get (player).getContainerStore (player).add (ref.getPtr()); + payForEnchantment(); return true; } @@ -126,6 +130,8 @@ namespace MWMechanics float cost = 0; std::vector mEffects = mEffectList.mList; int i=mEffects.size(); + if(i<=0) + return 0; /* Formula from http://www.uesp.net/wiki/Morrowind:Enchant @@ -155,6 +161,17 @@ namespace MWMechanics } return cost; } + + int Enchanting::getEnchantPrice() const + { + if(mEnchanter.isEmpty()) + return 0; + + float priceMultipler = MWBase::Environment::get().getWorld()->getStore().get().find ("fEnchantmentValueMult")->getFloat(); + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mEnchanter, (getEnchantCost() * priceMultipler), true); + return price; + } + int Enchanting::getGemCharge() const { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -216,4 +233,23 @@ namespace MWMechanics } return (chance1-chance2); } + + void Enchanting::payForEnchantment() const + { + MWWorld::Ptr gold; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + + for (MWWorld::ContainerStoreIterator it = store.begin(); + it != store.end(); ++it) + { + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001")) + { + gold = *it; + } + } + + gold.getRefData().setCount(gold.getRefData().getCount() - getEnchantPrice()); + } } diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp index c951ae8256..d8a6342ac9 100644 --- a/apps/openmw/mwmechanics/enchanting.hpp +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -36,11 +36,13 @@ namespace MWMechanics void nextEnchantType(); //Set enchant type to next possible type (for mOldItemPtr object) int getEnchantType() const; int getEnchantCost() const; + int getEnchantPrice() const; int getMaxEnchantValue() const; int getGemCharge() const; float getEnchantChance() const; bool soulEmpty() const; //Return true if empty bool itemEmpty() const; //Return true if empty + void payForEnchantment() const; }; } #endif From 98727d2fb6c6ec26a5f8dabe370d9714b23d71dd Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 2 Apr 2013 21:32:23 +0200 Subject: [PATCH 015/198] Workaround for launcher compilation problems due to bug in Qt MOC compiler. For details please see: https://forum.openmw.org/viewtopic.php?f=7&t=1451 https://bugreports.qt-project.org/browse/QTBUG-22829 Signed-off-by: Lukasz Gromanowski --- apps/launcher/maindialog.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 7e818a74ab..824dff6e82 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -2,9 +2,9 @@ #define MAINDIALOG_H #include - +#ifndef Q_MOC_RUN #include - +#endif #include "settings/gamesettings.hpp" #include "settings/graphicssettings.hpp" #include "settings/launchersettings.hpp" From 7b7d3353a66fc30e6282c6d3931d012abbfa029e Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 2 Apr 2013 22:23:38 +0200 Subject: [PATCH 016/198] Exception for enchanting with Azura Star --- apps/openmw/mwmechanics/enchanting.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index a2f85fb0c4..45db667d26 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -54,7 +54,12 @@ namespace MWMechanics { ESM::Enchantment enchantment; enchantment.mData.mCharge = getGemCharge(); - mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); + + //Exception for Azura Star, it's not destroyed after enchanting + if(mSoulGemPtr.get()->mBase->mId=="Misc_SoulGem_Azura") + mSoulGemPtr.getCellRef().mSoul=""; + else + mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); if(mSelfEnchanting) { From 061fb4c482353633d2610166646a981998307a24 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 2 Apr 2013 23:15:22 +0200 Subject: [PATCH 017/198] Added simple Travis CI cfg file. Added simple Travis CI configuration file for testing. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..94cf749245 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: cpp +compiler: + - clang + - gcc +before_script: + - mkdir build + - cd build + - cmake .. +branches: + only: + - master + - travis_ci_test +notifications: + recipients: + - lgromanowski+travis.ci@gmail.com + email: + on_success: change + on_failure: always From df8da0486da56835f55ab31e2aa87bfda82a50e0 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 2 Apr 2013 23:20:59 +0200 Subject: [PATCH 018/198] Small changes in .travis.yml file. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 94cf749245..f2a9179f59 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ before_script: - mkdir build - cd build - cmake .. +before_install: + - git submodule update --init --recursive +script: make branches: only: - master From cb18cf1eee9ab28ced4347aa880403972ed18dde Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 2 Apr 2013 23:30:44 +0200 Subject: [PATCH 019/198] Added OpenMW dependencies into .travis.yml file. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f2a9179f59..6e3748056c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,10 @@ before_script: - cd build - cmake .. before_install: - - git submodule update --init --recursive + - git submodule update --init --recursive + - sudo apt-add-repository ppa:openmw/deps + - sudo apt-get update -qq + - sudo apt-get install -qq ffmpeg-dev boost-dev libbullet libogre-static mygui-static script: make branches: only: From 4f19fb0cdbfa5ac3815f83133cb1d864f371274a Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 2 Apr 2013 23:38:23 +0200 Subject: [PATCH 020/198] Changes in apt-add-repository line - added echo. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6e3748056c..cdbabb1a1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_script: - cmake .. before_install: - git submodule update --init --recursive - - sudo apt-add-repository ppa:openmw/deps + - echo -e "\n" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get install -qq ffmpeg-dev boost-dev libbullet libogre-static mygui-static script: make From f8497895149469720e56c25fc0b9b25e08e3c058 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 2 Apr 2013 23:41:24 +0200 Subject: [PATCH 021/198] Changes in apt-add-repository line. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cdbabb1a1e..3d3ad404c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_script: - cmake .. before_install: - git submodule update --init --recursive - - echo -e "\n" | sudo apt-add-repository ppa:openmw/deps + - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get install -qq ffmpeg-dev boost-dev libbullet libogre-static mygui-static script: make From df0ee82a3c9f27700ee39ac5175a01fc77912b7a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 2 Apr 2013 23:45:32 +0200 Subject: [PATCH 022/198] Loose files should have priority over BSA resources. This makes texture replacers work. --- apps/openmw/engine.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ce84b8dfe1..dad024c98e 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -153,20 +153,6 @@ OMW::Engine::~Engine() void OMW::Engine::loadBSA() { - for (std::vector::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive) - { - if (mFileCollections.doesExist(*archive)) - { - const std::string archivePath = mFileCollections.getPath(*archive).string(); - std::cout << "Adding BSA archive " << archivePath << std::endl; - Bsa::addBSA(archivePath); - } - else - { - std::cout << "Archive " << *archive << " not found" << std::endl; - } - } - const Files::PathContainer& dataDirs = mFileCollections.getPaths(); std::string dataDirectory; for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) @@ -175,6 +161,24 @@ void OMW::Engine::loadBSA() std::cout << "Data dir " << dataDirectory << std::endl; Bsa::addDir(dataDirectory, mFSStrict); } + + // BSA resources are put into a separate group. We want loose files to have priority over BSA resources, and this seems + // to be the only way to get Ogre to do just that. + Ogre::ResourceGroupManager::getSingleton ().createResourceGroup ("GroupBSA"); + + for (std::vector::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive) + { + if (mFileCollections.doesExist(*archive)) + { + const std::string archivePath = mFileCollections.getPath(*archive).string(); + std::cout << "Adding BSA archive " << archivePath << std::endl; + Bsa::addBSA(archivePath, "GroupBSA"); + } + else + { + std::cout << "Archive " << *archive << " not found" << std::endl; + } + } } // add resources directory From 73b984cc2d01ccca61cd5efeaa51f324060e69d9 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:08:24 +0200 Subject: [PATCH 023/198] Corrected packages names in .travis.yml file. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3d3ad404c5..75fe322990 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg-dev boost-dev libbullet libogre-static mygui-static + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev mygui-static-dev script: make branches: only: From c32f4d853e6ca6b9f5f06367ad526f911c034bfb Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:14:26 +0200 Subject: [PATCH 024/198] Another change in packages names in .travis.yml file. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 75fe322990..a29140b256 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev mygui-static-dev + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev script: make branches: only: From c73209c049b4ba2776fb8c11ae91132dba8515a8 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:21:42 +0200 Subject: [PATCH 025/198] Added another part of dependencies, enabled building with static ogre and mygui. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a29140b256..1239f1ed0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,12 @@ compiler: before_script: - mkdir build - cd build - - cmake .. + - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev zziplib-bin libmpg123-dev script: make branches: only: From 05a5cb3ae48e00d82488d2d4056a5fd906cde571 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 00:27:29 +0200 Subject: [PATCH 026/198] Improved responsiveness of the inventory window when resizing. --- apps/openmw/engine.cpp | 1 + apps/openmw/mwbase/windowmanager.hpp | 2 ++ apps/openmw/mwgui/inventorywindow.cpp | 20 +++++++++++++++----- apps/openmw/mwgui/inventorywindow.hpp | 4 ++++ apps/openmw/mwgui/windowmanagerimp.cpp | 5 +++++ apps/openmw/mwgui/windowmanagerimp.hpp | 2 ++ 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index dad024c98e..948a06d471 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -66,6 +66,7 @@ bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt) { if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) MWBase::Environment::get().getWorld()->frameStarted(evt.timeSinceLastFrame); + MWBase::Environment::get().getWindowManager ()->frameStarted(evt.timeSinceLastFrame); return true; } diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 4d66a77423..b271aed182 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -246,6 +246,8 @@ namespace MWBase virtual void showSoulgemDialog (MWWorld::Ptr item) = 0; + virtual void frameStarted(float dt) = 0; + virtual void changePointer (const std::string& name) = 0; virtual const Translation::Storage& getTranslationDataStorage() const = 0; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 1943ff773a..aeab5f94aa 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -37,6 +37,7 @@ namespace MWGui , mLastXSize(0) , mLastYSize(0) , mPreview(MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()) + , mPreviewDirty(true) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); @@ -268,6 +269,19 @@ namespace MWGui mTrading = true; } + void InventoryWindow::doRenderUpdate () + { + if (mPreviewDirty) + { + mPreviewDirty = false; + MyGUI::IntSize size = mAvatar->getSize(); + + mPreview.update (size.width, size.height); + mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024))); + mAvatarImage->setImageTexture("CharacterPreview"); + } + } + void InventoryWindow::notifyContentChanged() { // update the spell window just in case new enchanted items were added to inventory @@ -282,11 +296,7 @@ namespace MWGui else mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability - MyGUI::IntSize size = mAvatar->getSize(); - - mPreview.update (size.width, size.height); - mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024))); - mAvatarImage->setImageTexture("CharacterPreview"); + mPreviewDirty = true; mArmorRating->setCaptionWithReplacing ("#{sArmor}: " + boost::lexical_cast(static_cast(MWWorld::Class::get(mPtr).getArmorRating(mPtr)))); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 95657672d3..fceb7ecef1 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -16,6 +16,8 @@ namespace MWGui virtual void open(); + void doRenderUpdate(); + /// start trading, disables item drag&drop void startTrade(); @@ -34,6 +36,8 @@ namespace MWGui } protected: + bool mPreviewDirty; + MyGUI::Widget* mAvatar; MyGUI::ImageBox* mAvatarImage; MyGUI::TextBox* mArmorRating; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index cf14c1f514..c975b2cdba 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1190,3 +1190,8 @@ void WindowManager::showSoulgemDialog(MWWorld::Ptr item) { mSoulgemDialog->show(item); } + +void WindowManager::frameStarted (float dt) +{ + mInventoryWindow->doRenderUpdate (); +} diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 7a7adec27d..c14c6b2fe4 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -238,6 +238,8 @@ namespace MWGui virtual void startRepair(MWWorld::Ptr actor); virtual void startRepairItem(MWWorld::Ptr item); + virtual void frameStarted(float dt); + virtual void showSoulgemDialog (MWWorld::Ptr item); virtual void changePointer (const std::string& name); From 5a1bb21b23b1c68a1ea597ac339396a0a2704aee Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:30:43 +0200 Subject: [PATCH 027/198] Build dependecies. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1239f1ed0e..80c3a46537 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev zziplib-bin libmpg123-dev + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev zziplib-bin libmpg123-dev libcg libav-tools script: make branches: only: From 74d519d4057fe9d06c4b3b0fe3d6d1cafb074390 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:35:18 +0200 Subject: [PATCH 028/198] Added libois into build dependencies in .travis.yml file. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 80c3a46537..51fa23e8e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev zziplib-bin libmpg123-dev libcg libav-tools + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev zziplib-bin libmpg123-dev libcg libav-tools libois-dev script: make branches: only: From 798ed642030dc059e0ab4d4963061bffb07131b6 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:40:01 +0200 Subject: [PATCH 029/198] Added google-mock and libopenal into build dependencies. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 51fa23e8e6..003a4d8013 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev zziplib-bin libmpg123-dev libcg libav-tools libois-dev + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev script: make branches: only: From 5957a9e037942934b30202b572ed9d8bb0cb4876 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:44:03 +0200 Subject: [PATCH 030/198] Added libxaw7 into dependencies. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 003a4d8013..4939ad0ec7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev libxaw7-dev script: make branches: only: From e7bb3743cc491d00e036791d6f74ccf512d92286 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 00:58:59 +0200 Subject: [PATCH 031/198] Trying to build with Ogre shared lib . Signed-off-by: Lukasz Gromanowski --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4939ad0ec7..d31e4afc8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,12 @@ compiler: before_script: - mkdir build - cd build - - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 + - cmake .. -DMYGUI_STATIC=1 before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-static-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev libxaw7-dev + - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev libxaw7-dev script: make branches: only: From f6f165852dda10d098f2f8daa2ee9081291329fd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 2 Apr 2013 21:08:21 -0700 Subject: [PATCH 032/198] Better handle material texture layers --- components/nifogre/ogrenifloader.cpp | 110 ++++++++++++++++----------- 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 5aa5ff80cb..b3ab4c0160 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -538,16 +538,51 @@ static std::map MaterialMap; static void warn(const std::string &msg) { - std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; + std::cerr << "NIFMaterialLoader: Warn: " << msg << std::endl; } static void fail(const std::string &msg) { - std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; + std::cerr << "NIFMaterialLoader: Fail: "<< msg << std::endl; abort(); } +static std::string findTextureName(const std::string &filename) +{ + /* Bethesda at some point converted all their BSA + * textures from tga to dds for increased load speed, but all + * texture file name references were kept as .tga. + */ + static const char path[] = "textures\\"; + + std::string texname = filename; + Misc::StringUtils::toLower(texname); + + if(texname.compare(0, sizeof(path)-1, path) != 0) + texname = path + texname; + + Ogre::String::size_type pos = texname.rfind('.'); + if(pos != Ogre::String::npos && texname.compare(pos, texname.length() - pos, ".dds") != 0) + { + // since we know all (GOTY edition or less) textures end + // in .dds, we change the extension + texname.replace(pos, texname.length(), ".dds"); + + // if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods) + // verify, and revert if false (this call succeeds quickly, but fails slowly) + if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texname)) + { + texname = filename; + Misc::StringUtils::toLower(texname); + if(texname.compare(0, sizeof(path)-1, path) != 0) + texname = path + texname; + } + } + + return texname; +} + public: static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group, const Nif::NiTexturingProperty *texprop, @@ -575,47 +610,29 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String int depthFlags = 3; // Default should be 1, but Bloodmoon's models are broken int specFlags = 0; - Ogre::String texName; + Ogre::String texName[7]; bool vertexColour = (shape->data->colors.size() != 0); // Texture - if(texprop && texprop->textures[0].inUse) + if(texprop) { - const Nif::NiSourceTexture *st = texprop->textures[0].texture.getPtr(); - if(st->external) + for(int i = 0;i < 7;i++) { - /* Bethesda at some point converted all their BSA - * textures from tga to dds for increased load speed, but all - * texture file name references were kept as .tga. - */ - static const char path[] = "textures\\"; - - texName = st->filename; - Misc::StringUtils::toLower(texName); - - if(texName.compare(0, sizeof(path)-1, path) != 0) - texName = path + texName; - - Ogre::String::size_type pos = texName.rfind('.'); - if(pos != Ogre::String::npos && texName.compare(pos, texName.length() - pos, ".dds") != 0) + if(!texprop->textures[i].inUse) + continue; + if(texprop->textures[i].texture.empty()) { - // since we know all (GOTY edition or less) textures end - // in .dds, we change the extension - texName.replace(pos, texName.length(), ".dds"); - - // if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods) - // verify, and revert if false (this call succeeds quickly, but fails slowly) - if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName)) - { - texName = st->filename; - Misc::StringUtils::toLower(texName); - if(texName.compare(0, sizeof(path)-1, path) != 0) - texName = path + texName; - } + warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name+"\n"); + continue; } + + const Nif::NiSourceTexture *st = texprop->textures[0].texture.getPtr(); + if(st->external) + texName[i] = findTextureName(st->filename); + else + warn("Found internal texture, ignoring."); } - else warn("Found internal texture, ignoring."); } // Alpha modifiers @@ -655,8 +672,6 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String alpha = matprop->data.alpha; } - Ogre::String matname = name; - if(matprop || !texName.empty()) { // Generate a hash out of all properties that can affect the material. size_t h = 0; @@ -672,7 +687,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String boost::hash_combine(h, emissive.x); boost::hash_combine(h, emissive.y); boost::hash_combine(h, emissive.z); - boost::hash_combine(h, texName); + for(int i = 0;i < 7;i++) + { + if(!texName[i].empty()) + boost::hash_combine(h, texName[i]); + } boost::hash_combine(h, vertexColour); boost::hash_combine(h, alphaFlags); boost::hash_combine(h, alphaTest); @@ -687,11 +706,11 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String return itr->second; } // not found, create a new one - MaterialMap.insert(std::make_pair(h, matname)); + MaterialMap.insert(std::make_pair(h, name)); } // No existing material like this. Create a new one. - sh::MaterialInstance* instance = sh::Factory::getInstance ().createMaterialInstance (matname, "openmw_objects_base"); + sh::MaterialInstance *instance = sh::Factory::getInstance().createMaterialInstance(name, "openmw_objects_base"); if(vertMode == 0 || !vertexColour) { instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); @@ -722,13 +741,18 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); } - instance->setProperty("diffuseMap", sh::makeProperty(texName)); + instance->setProperty("diffuseMap", sh::makeProperty(texName[0])); + for(int i = 1;i < 7;i++) + { + if(!texName[i].empty()) + warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)+"\n"); + } if (vertexColour) instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); // Add transparency if NiAlphaProperty was present - NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName); + NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName[0]); if (result.first) { alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */ @@ -763,8 +787,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue(((depthFlags>>1)&1) ? "on" : "off"))); // depth_func??? - sh::Factory::getInstance()._ensureMaterial(matname, "Default"); - return matname; + sh::Factory::getInstance()._ensureMaterial(name, "Default"); + return name; } }; From 512534be11a670c0102299bad95fa61264d3e604 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 2 Apr 2013 22:58:07 -0700 Subject: [PATCH 033/198] Read the correct texture resource for other layers --- components/nifogre/ogrenifloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index b3ab4c0160..d1ce7ae318 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -627,7 +627,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String continue; } - const Nif::NiSourceTexture *st = texprop->textures[0].texture.getPtr(); + const Nif::NiSourceTexture *st = texprop->textures[i].texture.getPtr(); if(st->external) texName[i] = findTextureName(st->filename); else From aac2ba1d5fff2e3b4ebfe22125343ac7aa027b62 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 12:24:13 +0200 Subject: [PATCH 034/198] Fix loading screen looking for wallpapers in a fixed group. --- apps/openmw/mwgui/loadingscreen.cpp | 20 +++++++++++++------- apps/openmw/mwgui/loadingscreen.hpp | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index e7c7acb533..86f196d9f5 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -217,15 +217,21 @@ namespace MWGui void LoadingScreen::changeWallpaper () { - if (mResources.isNull ()) - mResources = Ogre::ResourceGroupManager::getSingleton ().findResourceNames ("General", "Splash_*.tga"); - - - if (mResources->size()) + if (mResources.empty()) { - std::string const & randomSplash = mResources->at (rand() % mResources->size()); + Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups (); + for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it) + { + Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "Splash_*.tga"); + mResources.insert(mResources.end(), resourcesInThisGroup->begin(), resourcesInThisGroup->end()); + } + } - Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General"); + if (!mResources.empty()) + { + std::string const & randomSplash = mResources.at (rand() % mResources.size()); + + Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); mBackgroundImage->setImageTexture (randomSplash); } diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 24b3850710..176fc0f5d5 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -44,7 +44,7 @@ namespace MWGui Ogre::Rectangle2D* mRectangle; Ogre::MaterialPtr mBackgroundMaterial; - Ogre::StringVectorPtr mResources; + Ogre::StringVector mResources; bool mLoadingOn; From 095daca058e980471af9391b027e0f83f28c494b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 Apr 2013 03:26:21 -0700 Subject: [PATCH 035/198] Create entities when iterating through the NIF --- components/nifogre/ogrenifloader.cpp | 185 ++++++++++++--------------- components/nifogre/ogrenifloader.hpp | 14 -- 2 files changed, 79 insertions(+), 120 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index d1ce7ae318..89f55fbd4e 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1088,9 +1088,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader typedef std::map LoaderMap; static LoaderMap sLoaders; -public: - NIFMeshLoader() - { } + NIFMeshLoader(const std::string &name, const std::string &group) : mName(name), mGroup(group), mShapeIndex(~(size_t)0) { } @@ -1113,25 +1111,25 @@ public: findTriShape(mesh, node, NULL, NULL, NULL, NULL, NULL, NULL); } - void createMeshes(const Nif::Node *node, MeshInfoList &meshes, int flags=0) + void createEntities(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities, int flags=0) { // Do not create meshes for the collision shape (includes all children) if(node->recType == Nif::RC_RootCollisionNode) return; - flags |= node->flags; - // Marker objects: just skip the entire node /// \todo don't do this in the editor if (node->name.find("marker") != std::string::npos) return; + flags |= node->flags; + Nif::ExtraPtr e = node->extra; while(!e.empty()) { - Nif::NiStringExtraData *sd; - if((sd=dynamic_cast(e.getPtr())) != NULL) + if(e->recType == Nif::RC_NiStringExtraData) { + const Nif::NiStringExtraData *sd = static_cast(e.getPtr()); // String markers may contain important information // affecting the entire subtree of this obj if(sd->string == "MRK") @@ -1146,7 +1144,7 @@ public: if(node->recType == Nif::RC_NiTriShape && !(flags&0x01)) // Not hidden { - const Nif::NiTriShape *shape = dynamic_cast(node); + const Nif::NiTriShape *shape = static_cast(node); Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); std::string fullname = mName+"@index="+Ogre::StringConverter::toString(shape->recIndex); @@ -1165,7 +1163,15 @@ public: mesh->setAutoBuildEdgeLists(false); } - meshes.push_back(MeshInfo(mesh->getName(), shape->name)); + entities.mEntities.push_back(sceneMgr->createEntity(mesh)); + if(entities.mSkelBase) + { + Ogre::Entity *entity = entities.mEntities.back(); + if(entity->hasSkeleton()) + entity->shareSkeletonInstanceWith(entities.mSkelBase); + else + entities.mSkelBase->attachObjectToBone(shape->name, entity); + } } const Nif::NiNode *ninode = dynamic_cast(node); @@ -1175,12 +1181,12 @@ public: for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - createMeshes(children[i].getPtr(), meshes, flags); + createEntities(sceneMgr, children[i].getPtr(), entities, flags); } } } - void createEmptyMesh(const Nif::Node *node, MeshInfoList &meshes) + void createSkelBase(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities) { /* 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 @@ -1199,91 +1205,61 @@ public: mesh = meshMgr.createManual(fullname, mGroup, loader); mesh->setAutoBuildEdgeLists(false); } - meshes.push_back(MeshInfo(mesh->getName(), node->name)); + entities.mSkelBase = sceneMgr->createEntity(mesh); + entities.mEntities.push_back(entities.mSkelBase); + } + +public: + NIFMeshLoader() : mShapeIndex(~(size_t)0) + { } + + static void load(Ogre::SceneManager *sceneMgr, EntityList &entities, const std::string &name, const std::string &group) + { + Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name); + Nif::NIFFile &nif = *pnif.get(); + if(nif.numRecords() < 1) + { + nif.warn("Found no NIF records in "+name+"."); + return; + } + + // The first record is assumed to be the root node + const Nif::Record *r = nif.getRecord(0); + assert(r != NULL); + + const Nif::Node *node = dynamic_cast(r); + if(node == NULL) + { + nif.warn("First record in "+name+" was not a node, but a "+ + r->recName+"."); + return; + } + + bool hasSkel = Ogre::SkeletonManager::getSingleton().resourceExists(name); + if(!hasSkel) + hasSkel = !NIFSkeletonLoader::createSkeleton(name, group, node).isNull(); + + NIFMeshLoader meshldr(name, group); + if(hasSkel) + meshldr.createSkelBase(sceneMgr, node, entities); + meshldr.createEntities(sceneMgr, node, entities); } }; NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; -typedef std::map MeshInfoMap; -static MeshInfoMap sMeshInfoMap; - -MeshInfoList Loader::load(const std::string &name, const std::string &group) -{ - MeshInfoMap::const_iterator meshiter = sMeshInfoMap.find(name); - if(meshiter != sMeshInfoMap.end()) - return meshiter->second; - - MeshInfoList &meshes = sMeshInfoMap[name]; - Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name); - Nif::NIFFile &nif = *pnif.get(); - if(nif.numRecords() < 1) - { - nif.warn("Found no NIF records in "+name+"."); - return meshes; - } - - // The first record is assumed to be the root node - Nif::Record const *r = nif.getRecord(0); - assert(r != NULL); - - Nif::Node const *node = dynamic_cast(r); - if(node == NULL) - { - nif.warn("First record in "+name+" was not a node, but a "+ - r->recName+"."); - return meshes; - } - - bool hasSkel = Ogre::SkeletonManager::getSingleton().resourceExists(name); - if(!hasSkel) - hasSkel = !NIFSkeletonLoader::createSkeleton(name, group, node).isNull(); - - NIFMeshLoader meshldr(name, group); - if(hasSkel) - meshldr.createEmptyMesh(node, meshes); - meshldr.createMeshes(node, meshes, 0); - - return meshes; -} - EntityList Loader::createEntities(Ogre::SceneNode *parentNode, std::string name, const std::string &group) { EntityList entitylist; Misc::StringUtils::toLower(name); - MeshInfoList meshes = load(name, group); - if(meshes.size() == 0) - return entitylist; + NIFMeshLoader::load(parentNode->getCreator(), entitylist, name, group); - Ogre::SceneManager *sceneMgr = parentNode->getCreator(); - for(size_t i = 0;i < meshes.size();i++) + for(size_t i = 0;i < entitylist.mEntities.size();i++) { - entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].mMeshName)); - Ogre::Entity *entity = entitylist.mEntities.back(); - if(!entitylist.mSkelBase && entity->hasSkeleton()) - entitylist.mSkelBase = entity; - } - - if(entitylist.mSkelBase) - { - parentNode->attachObject(entitylist.mSkelBase); - for(size_t i = 0;i < entitylist.mEntities.size();i++) - { - Ogre::Entity *entity = entitylist.mEntities[i]; - if(entity != entitylist.mSkelBase && entity->hasSkeleton()) - { - entity->shareSkeletonInstanceWith(entitylist.mSkelBase); - parentNode->attachObject(entity); - } - else if(entity != entitylist.mSkelBase) - entitylist.mSkelBase->attachObjectToBone(meshes[i].mTargetNode, entity); - } - } - else - { - for(size_t i = 0;i < entitylist.mEntities.size();i++) - parentNode->attachObject(entitylist.mEntities[i]); + Ogre::Entity *entity = entitylist.mEntities[i]; + if(!entity->isAttached()) + parentNode->attachObject(entity); } return entitylist; @@ -1296,25 +1272,17 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen EntityList entitylist; Misc::StringUtils::toLower(name); - MeshInfoList meshes = load(name, group); - if(meshes.size() == 0) - return entitylist; + NIFMeshLoader::load(parentNode->getCreator(), entitylist, name, group); bool isskinned = false; - Ogre::SceneManager *sceneMgr = parentNode->getCreator(); - std::string filter = "@shape=tri "+bonename; - Misc::StringUtils::toLower(filter); - for(size_t i = 0;i < meshes.size();i++) + for(size_t i = 0;i < entitylist.mEntities.size();i++) { - Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].mMeshName); - if(!entitylist.mSkelBase) + Ogre::Entity *ent = entitylist.mEntities[i]; + if(entitylist.mSkelBase != ent && ent->hasSkeleton()) { - if(ent->hasSkeleton()) - entitylist.mSkelBase = ent; - } - else if(!isskinned && ent->hasSkeleton()) isskinned = true; - entitylist.mEntities.push_back(ent); + break; + } } Ogre::Vector3 scale(1.0f); @@ -1323,20 +1291,21 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen if(isskinned) { + std::string filter = "@shape=tri "+bonename; + Misc::StringUtils::toLower(filter); for(size_t i = 0;i < entitylist.mEntities.size();i++) { Ogre::Entity *entity = entitylist.mEntities[i]; if(entity->hasSkeleton()) { - if(entity != entitylist.mSkelBase) - entity->shareSkeletonInstanceWith(entitylist.mSkelBase); - if(entity->getMesh()->getName().find(filter) != std::string::npos) + if(entity == entitylist.mSkelBase || + entity->getMesh()->getName().find(filter) != std::string::npos) parentNode->attachObject(entity); } else { - if(entity->getMesh()->getName().find(filter) != std::string::npos) - entitylist.mSkelBase->attachObjectToBone(meshes[i].mTargetNode, entity); + if(entity->getMesh()->getName().find(filter) == std::string::npos) + entity->detachFromParent(); } } } @@ -1344,8 +1313,12 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen { for(size_t i = 0;i < entitylist.mEntities.size();i++) { - Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entitylist.mEntities[i]); - tag->setScale(scale); + Ogre::Entity *entity = entitylist.mEntities[i]; + if(!entity->isAttached()) + { + Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entity); + tag->setScale(scale); + } } } diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index b8b2e3c007..92b153468a 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -48,22 +48,8 @@ struct EntityList { }; -/* This holds a list of mesh names, the names of their parent nodes, and the offset - * from their parent nodes. */ -struct MeshInfo { - std::string mMeshName; - std::string mTargetNode; - - MeshInfo(const std::string &name, const std::string &target) - : mMeshName(name), mTargetNode(target) - { } -}; -typedef std::vector MeshInfoList; - class Loader { - static MeshInfoList load(const std::string &name, const std::string &group); - public: static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, Ogre::SceneNode *parentNode, From f0d49fdbd06f99a297bb39c80b0b14317aade26e Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 12:28:57 +0200 Subject: [PATCH 036/198] Create separate groups for each data dir / BSA file. --- apps/openmw/engine.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 948a06d471..17610e479f 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -154,26 +154,36 @@ OMW::Engine::~Engine() void OMW::Engine::loadBSA() { + // We use separate resource groups to handle location priority. const Files::PathContainer& dataDirs = mFileCollections.getPaths(); - std::string dataDirectory; + + int i=0; for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) { - dataDirectory = iter->string(); + // Last data dir has the highest priority + std::string groupName = "Data" + Ogre::StringConverter::toString(dataDirs.size()-i); + Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName); + + std::string dataDirectory = iter->string(); std::cout << "Data dir " << dataDirectory << std::endl; - Bsa::addDir(dataDirectory, mFSStrict); + Bsa::addDir(dataDirectory, mFSStrict, groupName); + ++i; } - // BSA resources are put into a separate group. We want loose files to have priority over BSA resources, and this seems - // to be the only way to get Ogre to do just that. - Ogre::ResourceGroupManager::getSingleton ().createResourceGroup ("GroupBSA"); - + i=0; for (std::vector::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive) { if (mFileCollections.doesExist(*archive)) { + // Last BSA has the highest priority + std::string groupName = "DataBSA" + Ogre::StringConverter::toString(dataDirs.size()-i); + + Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName); + const std::string archivePath = mFileCollections.getPath(*archive).string(); std::cout << "Adding BSA archive " << archivePath << std::endl; - Bsa::addBSA(archivePath, "GroupBSA"); + Bsa::addBSA(archivePath, groupName); + ++i; } else { From 5625d73d84488a2c4eb2ff51270329a972733285 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 17:16:34 +0200 Subject: [PATCH 037/198] Bump texture support --- components/nif/property.hpp | 11 ++ components/nifogre/ogrenifloader.cpp | 26 ++++- extern/shiny/Docs/Macros.dox | 23 ++++- extern/shiny/Main/MaterialInstance.hpp | 1 + extern/shiny/Main/ShaderInstance.cpp | 15 +-- extern/shiny/Main/ShaderSet.cpp | 16 +++ extern/shiny/Main/ShaderSet.hpp | 4 + files/materials/objects.mat | 7 ++ files/materials/objects.shader | 134 +++++++++++++++++++++++-- 9 files changed, 211 insertions(+), 26 deletions(-) diff --git a/components/nif/property.hpp b/components/nif/property.hpp index cd1e0a5d11..00cdc0e008 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -109,6 +109,17 @@ public: * 5 - Bump map texture * 6 - Decal texture */ + enum TextureType + { + BaseTexture = 0, + DarkTexture = 1, + DetailTexture = 2, + GlossTexture = 3, + GlowTexture = 4, + BumpTexture = 5, + DecalTexture = 6 + }; + Texture textures[7]; void read(NIFStream *nif) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 89f55fbd4e..c5dc7fbb98 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -555,11 +555,14 @@ static std::string findTextureName(const std::string &filename) * texture file name references were kept as .tga. */ static const char path[] = "textures\\"; + static const char path2[] = "textures/"; + std::string texname = filename; Misc::StringUtils::toLower(texname); - if(texname.compare(0, sizeof(path)-1, path) != 0) + if(texname.compare(0, sizeof(path)-1, path) != 0 + && texname.compare(0, sizeof(path2)-1, path2) != 0) texname = path + texname; Ogre::String::size_type pos = texname.rfind('.'); @@ -575,7 +578,8 @@ static std::string findTextureName(const std::string &filename) { texname = filename; Misc::StringUtils::toLower(texname); - if(texname.compare(0, sizeof(path)-1, path) != 0) + if(texname.compare(0, sizeof(path)-1, path) != 0 + && texname.compare(0, sizeof(path2)-1, path2) != 0) texname = path + texname; } } @@ -590,7 +594,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String const Nif::NiAlphaProperty *alphaprop, const Nif::NiVertexColorProperty *vertprop, const Nif::NiZBufferProperty *zprop, - const Nif::NiSpecularProperty *specprop) + const Nif::NiSpecularProperty *specprop, + bool &needTangents) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); @@ -634,6 +639,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String warn("Found internal texture, ignoring."); } } + needTangents = !texName[Nif::NiTexturingProperty::BumpTexture].empty(); // Alpha modifiers if(alphaprop) @@ -741,7 +747,8 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); } - instance->setProperty("diffuseMap", sh::makeProperty(texName[0])); + instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); + instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); for(int i = 1;i < 7;i++) { if(!texName[i].empty()) @@ -1022,11 +1029,20 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } + bool needTangents=false; std::string matname = NIFMaterialLoader::getMaterial(shape, mesh->getName(), mGroup, texprop, matprop, alphaprop, - vertprop, zprop, specprop); + vertprop, zprop, specprop, needTangents); if(matname.length() > 0) sub->setMaterialName(matname); + + // build tangents if the material needs them + if (needTangents) + { + unsigned short src,dest; + if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest)) + mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest); + } } bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node, diff --git a/extern/shiny/Docs/Macros.dox b/extern/shiny/Docs/Macros.dox index 0578c447f3..c04ebd3747 100644 --- a/extern/shiny/Docs/Macros.dox +++ b/extern/shiny/Docs/Macros.dox @@ -107,6 +107,23 @@ \section properties Property retrieval / binding + \subsection shPropertyHasValue shPropertyHasValue + + Usage: \@shPropertyHasValue(property) + + Gets replaced by 1 if the property's value is not empty, or 0 if it is empty. + Useful for checking whether an optional texture is present or not. + + Example: + \code + #if @shPropertyHasValue(specularMap) + // specular mapping code + #endif + #if @shPropertyHasValue(normalMap) + // normal mapping code + #endif + \endcode + \subsection shUniformProperty shUniformProperty Usage: \@shUniformProperty<4f|3f|2f|1f|int> (uniformName, property) @@ -130,15 +147,11 @@ Example: \code - #if @shPropertyBool(has_normal_map) + #if @shPropertyBool(has_vertex_colors) ... #endif \endcode - \subsection shPropertyNotBool shPropertyNotBool - - Same as shPropertyBool, but inverts the result (i.e. when shPropertyBool would return 0, this returns 1 and vice versa) - \subsection shPropertyString shPropertyString Retrieve a string property of the pass that this shader belongs to diff --git a/extern/shiny/Main/MaterialInstance.hpp b/extern/shiny/Main/MaterialInstance.hpp index 000f9d60c9..36ba37ddba 100644 --- a/extern/shiny/Main/MaterialInstance.hpp +++ b/extern/shiny/Main/MaterialInstance.hpp @@ -25,6 +25,7 @@ namespace sh public: virtual void requestedConfiguration (MaterialInstance* m, const std::string& configuration) = 0; ///< called before creating virtual void createdConfiguration (MaterialInstance* m, const std::string& configuration) = 0; ///< called after creating + virtual ~MaterialInstanceListener(){} }; /** diff --git a/extern/shiny/Main/ShaderInstance.cpp b/extern/shiny/Main/ShaderInstance.cpp index 1539128aba..b44c63c322 100644 --- a/extern/shiny/Main/ShaderInstance.cpp +++ b/extern/shiny/Main/ShaderInstance.cpp @@ -194,13 +194,6 @@ namespace sh bool val = retrieveValue(value, properties->getContext()).get(); replaceValue = val ? "1" : "0"; } - else if (cmd == "shPropertyNotBool") // same as above, but inverts the result - { - std::string propertyName = args[0]; - PropertyValuePtr value = properties->getProperty(propertyName); - bool val = retrieveValue(value, properties->getContext()).get(); - replaceValue = val ? "0" : "1"; - } else if (cmd == "shPropertyString") { std::string propertyName = args[0]; @@ -214,6 +207,14 @@ namespace sh std::string value = retrieveValue(properties->getProperty(propertyName), properties->getContext()).get(); replaceValue = (value == comparedAgainst) ? "1" : "0"; } + else if (isCmd(source, pos, "@shPropertyHasValue")) + { + assert(args.size() == 1); + std::string propertyName = args[0]; + PropertyValuePtr value = properties->getProperty(propertyName); + std::string val = retrieveValue(value, properties->getContext()).get(); + replaceValue = (val.empty() ? "0" : "1"); + } else throw std::runtime_error ("unknown command \"" + cmd + "\""); source.replace(pos, (end+1)-pos, replaceValue); diff --git a/extern/shiny/Main/ShaderSet.cpp b/extern/shiny/Main/ShaderSet.cpp index 413d7d1a26..628e0acee7 100644 --- a/extern/shiny/Main/ShaderSet.cpp +++ b/extern/shiny/Main/ShaderSet.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "Factory.hpp" @@ -26,6 +27,10 @@ namespace sh std::ifstream stream(sourceFile.c_str(), std::ifstream::in); std::stringstream buffer; + boost::filesystem::path p (sourceFile); + p = p.branch_path(); + mBasePath = p.string(); + buffer << stream.rdbuf(); stream.close(); mSource = buffer.str(); @@ -52,6 +57,12 @@ namespace sh size_t start = currentToken.find('(')+1; mGlobalSettings.push_back(currentToken.substr(start, currentToken.find(')')-start)); } + else if (boost::starts_with(currentToken, "@shPropertyHasValue")) + { + assert ((currentToken.find('(') != std::string::npos) && (currentToken.find(')') != std::string::npos)); + size_t start = currentToken.find('(')+1; + mPropertiesToExist.push_back(currentToken.substr(start, currentToken.find(')')-start)); + } else if (boost::starts_with(currentToken, "@shPropertyEqual")) { assert ((currentToken.find('(') != std::string::npos) && (currentToken.find(')') != std::string::npos) @@ -135,6 +146,11 @@ namespace sh { boost::hash_combine(seed, retrieveValue(currentGlobalSettings->getProperty(*it), NULL).get()); } + for (std::vector::iterator it = mPropertiesToExist.begin(); it != mPropertiesToExist.end(); ++it) + { + std::string v = retrieveValue(properties->getProperty(*it), properties->getContext()).get(); + boost::hash_combine(seed, static_cast(v != "")); + } boost::hash_combine(seed, static_cast(Factory::getInstance().getCurrentLanguage())); return seed; } diff --git a/extern/shiny/Main/ShaderSet.hpp b/extern/shiny/Main/ShaderSet.hpp index a423b6779f..b21278ac99 100644 --- a/extern/shiny/Main/ShaderSet.hpp +++ b/extern/shiny/Main/ShaderSet.hpp @@ -53,6 +53,10 @@ namespace sh std::vector mGlobalSettings; ///< names of the global settings that affect the shader source std::vector mProperties; ///< names of the per-material properties that affect the shader source + std::vector mPropertiesToExist; + ///< same as mProperties, however in this case, it is only relevant if the property is empty or not + /// (we don't care about the value) + ShaderInstanceMap mInstances; ///< maps permutation ID (generated from the properties) to \a ShaderInstance void parse(); ///< find out which properties and global settings affect the shader source diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 5e18a666a7..00b43a9d0d 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -6,6 +6,7 @@ material openmw_objects_base emissive 0.0 0.0 0.0 vertmode 0 diffuseMap black.png + normalMap is_transparent false // real transparency, alpha rejection doesn't count here scene_blend default @@ -22,6 +23,7 @@ material openmw_objects_base { vertexcolor_mode $vertmode is_transparent $is_transparent + normalMap $normalMap } diffuse $diffuse @@ -38,6 +40,11 @@ material openmw_objects_base direct_texture $diffuseMap create_in_ffp true } + + texture_unit normalMap + { + direct_texture $normalMap + } texture_unit shadowMap0 { diff --git a/files/materials/objects.shader b/files/materials/objects.shader index c8616e9d1e..73968a6b3e 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -14,13 +14,15 @@ #define NEED_DEPTH #endif +#define NORMAL_MAP @shPropertyHasValue(normalMap) + +// if normal mapping is enabled, we force pixel lighting +#define VERTEX_LIGHTING (!@shPropertyHasValue(normalMap)) #define UNDERWATER @shGlobalSettingBool(render_refraction) #define VERTEXCOLOR_MODE @shPropertyString(vertexcolor_mode) -#define VERTEX_LIGHTING 1 - #define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) #ifdef SH_VERTEX_SHADER @@ -42,6 +44,16 @@ shVertexInput(float2, uv0) shOutput(float2, UV) shNormalInput(float4) + +#if NORMAL_MAP + shTangentInput(float4) + shOutput(float3, tangentPassthrough) +#endif + +#if !VERTEX_LIGHTING + shOutput(float3, normalPassthrough) +#endif + #ifdef NEED_DEPTH shOutput(float, depthPassthrough) #endif @@ -52,6 +64,10 @@ shColourInput(float4) #endif +#if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING + shOutput(float4, colourPassthrough) +#endif + #if VERTEX_LIGHTING shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_view_space_array, @shGlobalSettingString(num_lights)) @@ -94,6 +110,15 @@ { shOutputPosition = shMatrixMult(wvp, shInputPosition); UV = uv0; +#if NORMAL_MAP + tangentPassthrough = tangent.xyz; +#endif +#if !VERTEX_LIGHTING + normalPassthrough = normal.xyz; +#endif +#if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING + colourPassthrough = colour; +#endif #ifdef NEED_DEPTH @@ -188,15 +213,31 @@ #endif SH_BEGIN_PROGRAM - shSampler2D(diffuseMap) - shInput(float2, UV) + shSampler2D(diffuseMap) + +#if NORMAL_MAP + shSampler2D(normalMap) +#endif + + shInput(float2, UV) + +#if NORMAL_MAP + shInput(float3, tangentPassthrough) +#endif +#if !VERTEX_LIGHTING + shInput(float3, normalPassthrough) +#endif #ifdef NEED_DEPTH shInput(float, depthPassthrough) #endif shInput(float3, objSpacePositionPassthrough) - + +#if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING + shInput(float4, colourPassthrough) +#endif + #if FOG shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour) shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) @@ -222,23 +263,98 @@ #if (UNDERWATER) || (FOG) shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) - shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) + shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) #endif #if UNDERWATER - shUniform(float, waterLevel) @shSharedParameter(waterLevel) + shUniform(float, waterLevel) @shSharedParameter(waterLevel) shUniform(float, waterEnabled) @shSharedParameter(waterEnabled) #endif #if VERTEX_LIGHTING shInput(float4, lightResult) shInput(float3, directionalResult) +#else + shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) + shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_view_space_array, @shGlobalSettingString(num_lights)) + shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights)) + shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights)) + shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) + shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix) + #if VERTEXCOLOR_MODE != 2 + shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) + #endif + #if VERTEXCOLOR_MODE != 2 + shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) + #endif + #if VERTEXCOLOR_MODE != 1 + shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) + #endif #endif SH_START_PROGRAM { shOutputColour(0) = shSample(diffuseMap, UV); - + +#if NORMAL_MAP + float3 normal = normalPassthrough; + float3 binormal = cross(tangentPassthrough.xyz, normal.xyz); + float3x3 tbn = float3x3(tangentPassthrough.xyz, binormal, normal.xyz); + + #if SH_GLSL + tbn = transpose(tbn); + #endif + + float3 TSnormal = shSample(normalMap, UV.xy).xyz * 2 - 1; + + normal = normalize (shMatrixMult( transpose(tbn), TSnormal )); +#endif + +#if !VERTEX_LIGHTING + float3 viewPos = shMatrixMult(worldView, float4(objSpacePositionPassthrough,1)).xyz; + float3 viewNormal = normalize(shMatrixMult(worldView, float4(normal.xyz, 0)).xyz); + + float3 lightDir; + float d; + float4 lightResult = float4(0,0,0,1); + @shForeach(@shGlobalSettingString(num_lights)) + lightDir = lightPosition[@shIterator].xyz - (viewPos * lightPosition[@shIterator].w); + d = length(lightDir); + lightDir = normalize(lightDir); + +#if VERTEXCOLOR_MODE == 2 + lightResult.xyz += colourPassthrough.xyz * lightDiffuse[@shIterator].xyz + * shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) + * max(dot(viewNormal.xyz, lightDir), 0); +#else + lightResult.xyz += materialDiffuse.xyz * lightDiffuse[@shIterator].xyz + * shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) + * max(dot(viewNormal.xyz, lightDir), 0); +#endif + +#if @shIterator == 0 + float3 directionalResult = lightResult.xyz; +#endif + + @shEndForeach + + +#if VERTEXCOLOR_MODE == 2 + lightResult.xyz += lightAmbient.xyz * colourPassthrough.xyz + materialEmissive.xyz; + lightResult.a *= colourPassthrough.a; +#endif +#if VERTEXCOLOR_MODE == 1 + lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + colourPassthrough.xyz; +#endif +#if VERTEXCOLOR_MODE == 0 + lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz; +#endif + +#if VERTEXCOLOR_MODE != 2 + lightResult.a *= materialDiffuse.a; +#endif +#endif + // shadows only for the first (directional) light #if SHADOWS float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0); @@ -275,7 +391,7 @@ #if FOG float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); - + #if UNDERWATER shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, UNDERWATER_COLOUR, shSaturate(length(waterEyePos-worldPos) / VISIBILITY)); From ae3e4ecf8b7598a021970ab2c3f1a75650822781 Mon Sep 17 00:00:00 2001 From: Glorf Date: Wed, 3 Apr 2013 18:02:30 +0200 Subject: [PATCH 038/198] Finished enchanting --- apps/openmw/mwgui/enchantingdialog.cpp | 20 ++++++++++++++++++-- apps/openmw/mwgui/enchantingdialog.hpp | 1 + apps/openmw/mwmechanics/enchanting.cpp | 3 ++- files/mygui/openmw_enchanting_dialog.layout | 4 ++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 1ed80127d4..23e400c367 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -32,6 +32,7 @@ namespace MWGui getWidget(mTypeButton, "TypeButton"); getWidget(mBuyButton, "BuyButton"); getWidget(mPrice, "PriceLabel"); + getWidget(mPriceText, "PriceTextLabel"); setWidgets(mAvailableEffectsList, mUsedEffectsView); @@ -94,19 +95,34 @@ namespace MWGui mPtr = actor; startEditing (); + + mPrice->setVisible(true); } void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - MWWorld::Ptr gem = soulgem; mEnchanting.setSelfEnchanting(true); mEnchanting.setEnchanter(player); mPtr = player; startEditing(); - mEnchanting.setSoulGem(gem); + mEnchanting.setSoulGem(soulgem); + + MyGUI::ImageBox* image = mSoulBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(soulgem).getInventoryIcon(soulgem); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture (path); + image->setUserString ("ToolTipType", "ItemPtr"); + image->setUserData(soulgem); + image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul); + + mPrice->setVisible(false); + mPriceText->setVisible(false); } void EnchantingDialog::onReferenceUnavailable () diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 347b37e908..a7861c422d 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -56,6 +56,7 @@ namespace MWGui MyGUI::TextBox* mCastCost; MyGUI::TextBox* mCharge; MyGUI::TextBox* mPrice; + MyGUI::TextBox* mPriceText; MWMechanics::Enchanting mEnchanting; ESM::EffectList mEffectList; diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 45db667d26..884c4d8963 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -88,7 +88,8 @@ namespace MWMechanics MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Class::get (player).getContainerStore (player).add (ref.getPtr()); - payForEnchantment(); + if(!mSelfEnchanting) + payForEnchantment(); return true; } diff --git a/files/mygui/openmw_enchanting_dialog.layout b/files/mygui/openmw_enchanting_dialog.layout index 41b8ffa938..f64d21deaa 100644 --- a/files/mygui/openmw_enchanting_dialog.layout +++ b/files/mygui/openmw_enchanting_dialog.layout @@ -97,11 +97,11 @@ - + - + From 21796197217e50a3cffe24f95008a46edd42da62 Mon Sep 17 00:00:00 2001 From: Glorf Date: Wed, 3 Apr 2013 18:06:11 +0200 Subject: [PATCH 039/198] Small enchanting fix --- apps/openmw/mwgui/enchantingdialog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 23e400c367..276e7a9047 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -95,8 +95,6 @@ namespace MWGui mPtr = actor; startEditing (); - - mPrice->setVisible(true); } void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem) @@ -123,6 +121,7 @@ namespace MWGui mPrice->setVisible(false); mPriceText->setVisible(false); + updateLabels(); } void EnchantingDialog::onReferenceUnavailable () From 30654a1faa0d9181e4beb28babfd09fd801b809b Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 18:11:57 +0200 Subject: [PATCH 040/198] Added removing of ogre static. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d31e4afc8d..f517a4da83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq + - sudo apt-get remove -qq libogre-static-dev - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev libxaw7-dev script: make branches: From 4bf87948a03e6073c2c527c25f7ee45d7ba47c18 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 18:19:46 +0200 Subject: [PATCH 041/198] Removed clang compilation target. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f517a4da83..4852efb810 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: cpp compiler: - - clang - gcc before_script: - mkdir build From 08e9bb0236447d7a952f13791180ba122a5fad4a Mon Sep 17 00:00:00 2001 From: Glorf Date: Wed, 3 Apr 2013 18:25:40 +0200 Subject: [PATCH 042/198] Another small enchanting fix --- apps/openmw/mwmechanics/enchanting.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 884c4d8963..d92acdafc0 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -7,6 +7,7 @@ #include "creaturestats.hpp" #include "npcstats.hpp" +#include namespace MWMechanics { @@ -56,7 +57,7 @@ namespace MWMechanics enchantment.mData.mCharge = getGemCharge(); //Exception for Azura Star, it's not destroyed after enchanting - if(mSoulGemPtr.get()->mBase->mId=="Misc_SoulGem_Azura") + if(boost::iequals(mSoulGemPtr.get()->mBase->mId, "Misc_SoulGem_Azura")) mSoulGemPtr.getCellRef().mSoul=""; else mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); From 71b4319a0ce170b9815c480ee5e5a1cb2b1f0d6f Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 18:31:38 +0200 Subject: [PATCH 043/198] Yet another change in build dependencies. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4852efb810..a9c47aa4e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get remove -qq libogre-static-dev - - sudo apt-get install -qq ffmpeg libboost-all-dev libbullet-dev libogre-dev libmygui-static-dev libqt4-dev libgtest-dev google-mock zziplib-bin libmpg123-dev libcg libav-tools libois-dev libopenal-dev libxaw7-dev + - sudo apt-get install -qq libois-dev libopenal-dev libpng-dev libogre-dev libmpg123-dev libsndfile1-dev libblkid-dev libfreeimage-dev libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev libboost-program-options-dev libboost-system-dev libboost-wave-dev uuid-dev libqt4-opengl libqt4-dev libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev ffmpeg libbullet-dev libmygui-dev libqt4-dev libgtest-dev google-mock zziplib-bin libcg libav-tools libois-dev libopenal-dev libxaw7-dev script: make branches: only: From a9b56eedc3c220a108915d3caf9234a60129c99e Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 18:51:40 +0200 Subject: [PATCH 044/198] Support NIF "glow maps", which are basically an emissive channel. --- components/nif/property.hpp | 4 ++-- components/nifogre/ogrenifloader.cpp | 7 ++++++ files/materials/objects.mat | 14 ++++++++++++ files/materials/objects.shader | 33 ++++++++++++++++++++++++---- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 00cdc0e008..fd96ad0481 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -64,7 +64,7 @@ public: bool inUse; NiSourceTexturePtr texture; - int clamp, set, filter; + int clamp, uvSet, filter; short unknown2; void read(NIFStream *nif) @@ -75,7 +75,7 @@ public: texture.read(nif); clamp = nif->getInt(); filter = nif->getInt(); - set = nif->getInt(); + uvSet = nif->getInt(); // I have no idea, but I think these are actually two // PS2-specific shorts (ps2L and ps2K), followed by an unknown diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index c5dc7fbb98..f8eca821ff 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -749,6 +749,13 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); + instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); + if (!texName[Nif::NiTexturingProperty::GlowTexture].empty()) + { + instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true))); + instance->setProperty("emissiveMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::GlowTexture].uvSet))); + } + for(int i = 1;i < 7;i++) { if(!texName[i].empty()) diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 00b43a9d0d..8740c82c34 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -7,6 +7,9 @@ material openmw_objects_base vertmode 0 diffuseMap black.png normalMap + emissiveMap + use_emissive_map false + emissiveMapUVSet 0 is_transparent false // real transparency, alpha rejection doesn't count here scene_blend default @@ -24,6 +27,8 @@ material openmw_objects_base vertexcolor_mode $vertmode is_transparent $is_transparent normalMap $normalMap + emissiveMapUVSet $emissiveMapUVSet + emissiveMap $emissiveMap } diffuse $diffuse @@ -39,12 +44,21 @@ material openmw_objects_base { direct_texture $diffuseMap create_in_ffp true + tex_coord_set $emissiveMapUVSet } texture_unit normalMap { direct_texture $normalMap } + + texture_unit emissiveMap + { + create_in_ffp $use_emissive_map + colour_op add + direct_texture $emissiveMap + tex_coord_set $emissiveMapUVSet + } texture_unit shadowMap0 { diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 73968a6b3e..d0e8173733 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -15,6 +15,10 @@ #endif #define NORMAL_MAP @shPropertyHasValue(normalMap) +#define EMISSIVE_MAP @shPropertyHasValue(emissiveMap) + +// right now we support 2 UV sets max. implementing them is tedious, and we're probably not going to need more +#define SECOND_UV_SET @shPropertyString(emissiveMapUVSet) // if normal mapping is enabled, we force pixel lighting #define VERTEX_LIGHTING (!@shPropertyHasValue(normalMap)) @@ -42,7 +46,11 @@ #endif shVertexInput(float2, uv0) - shOutput(float2, UV) +#if SECOND_UV_SET + shVertexInput(float2, uv1) +#endif + shOutput(float4, UV) + shNormalInput(float4) #if NORMAL_MAP @@ -109,7 +117,12 @@ SH_START_PROGRAM { shOutputPosition = shMatrixMult(wvp, shInputPosition); - UV = uv0; + + UV.xy = uv0; +#if SECOND_UV_SET + UV.zw = uv1; +#endif + #if NORMAL_MAP tangentPassthrough = tangent.xyz; #endif @@ -219,7 +232,11 @@ shSampler2D(normalMap) #endif - shInput(float2, UV) +#if EMISSIVE_MAP + shSampler2D(emissiveMap) +#endif + + shInput(float4, UV) #if NORMAL_MAP shInput(float3, tangentPassthrough) @@ -294,7 +311,7 @@ SH_START_PROGRAM { - shOutputColour(0) = shSample(diffuseMap, UV); + shOutputColour(0) = shSample(diffuseMap, UV.xy); #if NORMAL_MAP float3 normal = normalPassthrough; @@ -399,6 +416,14 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); #endif +#endif + +#if EMISSIVE_MAP + #if SECOND_UV_SET + shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz; + #else + shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz; + #endif #endif // prevent negative colour output (for example with negative lights) From 2a5fc7cd822e9a204b63bfdf858cec1c7eefba53 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 19:02:21 +0200 Subject: [PATCH 045/198] Change in build dependencies. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a9c47aa4e2..4d1257d2bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,8 @@ before_install: - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get remove -qq libogre-static-dev - - sudo apt-get install -qq libois-dev libopenal-dev libpng-dev libogre-dev libmpg123-dev libsndfile1-dev libblkid-dev libfreeimage-dev libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev libboost-program-options-dev libboost-system-dev libboost-wave-dev uuid-dev libqt4-opengl libqt4-dev libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev ffmpeg libbullet-dev libmygui-dev libqt4-dev libgtest-dev google-mock zziplib-bin libcg libav-tools libois-dev libopenal-dev libxaw7-dev -script: make + - sudo apt-get install -qq libois-dev libopenal-dev libpng-dev libogre-static-dev libmpg123-dev libsndfile1-dev libblkid-dev libfreeimage-dev libboost-all-dev uuid-dev libqt4-opengl libqt4-dev libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev 0ibpostproc-dev ffmpeg libbullet-dev libmygui-static-dev libgtest-dev google-mock zziplib-bin libcg libav-tools libois-dev libopenal-dev libxaw7-dev +script: "make -j`grep -c processor /proc/cpuinfo`" branches: only: - master From f655b9997cc4e04f606f726452ad241eabe57c5c Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 19:10:57 +0200 Subject: [PATCH 046/198] Added printing CMakeCache.txt file For debug purposes, should be removed if compilation succeed. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4d1257d2bf..d99809590e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ before_script: - mkdir build - cd build - cmake .. -DMYGUI_STATIC=1 + - cat CMakeCache.txt before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps From d070860f0943c2fa5ac22762128554b5fcf623be Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 19:14:13 +0200 Subject: [PATCH 047/198] Fixed typo. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d99809590e..7f361f5d40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ before_install: - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get remove -qq libogre-static-dev - - sudo apt-get install -qq libois-dev libopenal-dev libpng-dev libogre-static-dev libmpg123-dev libsndfile1-dev libblkid-dev libfreeimage-dev libboost-all-dev uuid-dev libqt4-opengl libqt4-dev libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev 0ibpostproc-dev ffmpeg libbullet-dev libmygui-static-dev libgtest-dev google-mock zziplib-bin libcg libav-tools libois-dev libopenal-dev libxaw7-dev + - sudo apt-get install -qq libois-dev libopenal-dev libpng-dev libogre-static-dev libmpg123-dev libsndfile1-dev libblkid-dev libfreeimage-dev libboost-all-dev uuid-dev libqt4-opengl libqt4-dev libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev ffmpeg libbullet-dev libmygui-static-dev libgtest-dev google-mock zziplib-bin libcg libav-tools libois-dev libopenal-dev libxaw7-dev script: "make -j`grep -c processor /proc/cpuinfo`" branches: only: From af509ce016ee85094fcd75f69eadf29109c2757f Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Wed, 3 Apr 2013 19:19:25 +0200 Subject: [PATCH 048/198] Restored building with static ogre. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7f361f5d40..db0a47d844 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ compiler: before_script: - mkdir build - cd build - - cmake .. -DMYGUI_STATIC=1 + - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 - cat CMakeCache.txt before_install: - git submodule update --init --recursive From 8ca88d1a708b05741240eb1e1b04d63449f2f2ab Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 21:13:01 +0200 Subject: [PATCH 049/198] Fix merchant repair menu allowing repair of repair items --- apps/openmw/mwgui/merchantrepair.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 0a65326050..1c9056748b 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -40,7 +40,8 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); - for (MWWorld::ContainerStoreIterator iter (store.begin()); + int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor; + for (MWWorld::ContainerStoreIterator iter (store.begin(categories)); iter!=store.end(); ++iter) { if (MWWorld::Class::get(*iter).hasItemHealth(*iter)) From 43cdbd033d690dd904bf6f98dd39423f3182443f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 21:14:49 +0200 Subject: [PATCH 050/198] Display remaining item health / enchantment charge in HUD icons, display remaining enchanment charge in tooltips --- apps/openmw/mwbase/windowmanager.hpp | 4 ++-- apps/openmw/mwclass/armor.cpp | 2 ++ apps/openmw/mwclass/clothing.cpp | 2 ++ apps/openmw/mwclass/weapon.cpp | 3 +++ apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/quickkeysmenu.cpp | 2 +- apps/openmw/mwgui/spellwindow.cpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 4 ++-- apps/openmw/mwgui/tooltips.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 9 +++++++-- apps/openmw/mwgui/windowmanagerimp.hpp | 4 ++-- 11 files changed, 25 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index b271aed182..976d7d84c1 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -182,8 +182,8 @@ namespace MWBase virtual void activateQuickKey (int index) = 0; virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0; - virtual void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) = 0; - virtual void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) = 0; + virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0; + virtual void setSelectedWeapon(const MWWorld::Ptr& item) = 0; virtual void unsetSelectedSpell() = 0; virtual void unsetSelectedWeapon() = 0; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index b94c270d56..320944d3ce 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -260,6 +260,8 @@ namespace MWClass } info.enchant = ref->mBase->mEnchant; + if (!info.enchant.empty()) + info.remainingEnchantCharge = ptr.getCellRef().mEnchantmentCharge; info.text = text; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index d65376898e..abad267675 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -207,6 +207,8 @@ namespace MWClass } info.enchant = ref->mBase->mEnchant; + if (!info.enchant.empty()) + info.remainingEnchantCharge = ptr.getCellRef().mEnchantmentCharge; info.text = text; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index ed2a095e37..0a527262f8 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -349,6 +349,9 @@ namespace MWClass info.enchant = ref->mBase->mEnchant; + if (!info.enchant.empty()) + info.remainingEnchantCharge = ptr.getCellRef().mEnchantmentCharge; + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner"); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index aeab5f94aa..001f42bd11 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -294,7 +294,7 @@ namespace MWGui if (weaponSlot == invStore.end()) mWindowManager.unsetSelectedWeapon(); else - mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability + mWindowManager.setSelectedWeapon(*weaponSlot); /// \todo track weapon durability mPreviewDirty = true; diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 5ea13fb0d7..2e4bf9100b 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -346,7 +346,7 @@ namespace MWGui store.setSelectedEnchantItem(it); spells.setSelectedSpell(""); - mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge % + mWindowManager.setSelectedEnchantItem(item); } } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index d7fb0e1bcd..021a849a08 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -382,7 +382,7 @@ namespace MWGui store.setSelectedEnchantItem(it); spells.setSelectedSpell(""); - mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge % + mWindowManager.setSelectedEnchantItem(item); updateSpells(); } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index af3e146bba..9292e60e5c 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -456,8 +456,8 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) if (enchant->mData.mType == ESM::Enchantment::WhenStrikes || enchant->mData.mType == ESM::Enchantment::WhenUsed) { - /// \todo store the current enchantment charge somewhere - int charge = enchant->mData.mCharge; + int maxCharge = enchant->mData.mCharge; + int charge = (info.remainingEnchantCharge == -1) ? maxCharge : info.remainingEnchantCharge; const int chargeWidth = 204; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index ba94915cc7..da5a35221c 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -17,6 +17,7 @@ namespace MWGui : isPotion(false) , imageSize(32) , wordWrap(true) + , remainingEnchantCharge(-1) {} std::string caption; @@ -26,6 +27,7 @@ namespace MWGui // enchantment (for cloth, armor, weapons) std::string enchant; + int remainingEnchantCharge; // effects (for potions, ingredients) Widgets::SpellEffectList effects; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index c975b2cdba..f994683a66 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -933,14 +933,19 @@ void WindowManager::setSelectedSpell(const std::string& spellId, int successChan mSpellWindow->setTitle(spell->mName); } -void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) +void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item) { + const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get() + .find(MWWorld::Class::get(item).getEnchantment(item)); + + int chargePercent = item.getCellRef().mEnchantmentCharge / static_cast(ench->mData.mCharge) * 100; mHud->setSelectedEnchantItem(item, chargePercent); mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item)); } -void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) +void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) { + int durabilityPercent = item.getCellRef().mCharge / static_cast(MWWorld::Class::get(item).getItemMaxHealth(item)) * 100; mHud->setSelectedWeapon(item, durabilityPercent); mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item)); } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index c14c6b2fe4..3c9fc586a3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -179,8 +179,8 @@ namespace MWGui virtual void activateQuickKey (int index); virtual void setSelectedSpell(const std::string& spellId, int successChancePercent); - virtual void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent); - virtual void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent); + virtual void setSelectedEnchantItem(const MWWorld::Ptr& item); + virtual void setSelectedWeapon(const MWWorld::Ptr& item); virtual void unsetSelectedSpell(); virtual void unsetSelectedWeapon(); From ebaf80d53921e51aa9b3c8cd823ef191b2490d9a Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 3 Apr 2013 23:55:57 +0200 Subject: [PATCH 051/198] Trace actors onto the ground after load, when moved to a different cell by the console or on player cell change. --- apps/openmw/mwbase/world.hpp | 3 ++ apps/openmw/mwclass/creature.cpp | 6 +++ apps/openmw/mwclass/creature.hpp | 2 + apps/openmw/mwclass/npc.cpp | 5 ++ apps/openmw/mwclass/npc.hpp | 2 + apps/openmw/mwrender/renderingmanager.cpp | 27 +++++----- apps/openmw/mwrender/renderingmanager.hpp | 2 + apps/openmw/mwrender/terrain.cpp | 11 ++++ apps/openmw/mwrender/terrain.hpp | 3 ++ .../mwscript/transformationextensions.cpp | 3 ++ apps/openmw/mwworld/class.cpp | 4 ++ apps/openmw/mwworld/class.hpp | 3 ++ apps/openmw/mwworld/physicssystem.cpp | 50 ++++++++++++++++++- apps/openmw/mwworld/physicssystem.hpp | 1 + apps/openmw/mwworld/scene.cpp | 6 ++- apps/openmw/mwworld/worldimp.cpp | 19 +++++++ apps/openmw/mwworld/worldimp.hpp | 3 ++ libs/openengine/bullet/physic.cpp | 3 +- 18 files changed, 138 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 8eea383eb4..040dc703c0 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -216,6 +216,9 @@ namespace MWBase virtual MWWorld::Ptr getFacedObject() = 0; ///< Return pointer to the object the player is looking at, if it is within activation range + virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0; + ///< Adjust position after load to be on ground. Must be called after model load. + virtual void deleteObject (const MWWorld::Ptr& ptr) = 0; virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0; diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 1097f8f29c..04889360f3 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -9,6 +9,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" @@ -86,6 +87,11 @@ namespace MWClass return ref->mBase->mId; } + void Creature::adjustPosition(const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getWorld()->adjustPosition(ptr); + } + void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { MWRender::Actors& actors = renderingInterface.getActors(); diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index ea356165eb..297c2ea61b 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -22,6 +22,8 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; + virtual void adjustPosition(const MWWorld::Ptr& ptr) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index cd6b0def11..7cda87bb15 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -160,6 +160,11 @@ namespace MWClass return ref->mBase->mId; } + void Npc::adjustPosition(const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getWorld()->adjustPosition(ptr); + } + void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr)); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 1a10bce6c1..d1a9158fdf 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -44,6 +44,8 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; + virtual void adjustPosition(const MWWorld::Ptr& ptr) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7c442c6868..2f49a40316 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -529,25 +529,28 @@ void RenderingManager::applyFog (bool underwater) void RenderingManager::setAmbientMode() { - switch (mAmbientMode) - { + switch (mAmbientMode) + { case 0: - - setAmbientColour(mAmbientColor); - break; + setAmbientColour(mAmbientColor); + break; case 1: - - setAmbientColour(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1)); - break; + setAmbientColour(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1)); + break; case 2: - - setAmbientColour(ColourValue(1,1,1)); - break; - } + setAmbientColour(ColourValue(1,1,1)); + break; + } } +float RenderingManager::getTerrainHeightAt(Ogre::Vector3 worldPos) +{ + return mTerrainManager->getTerrainHeightAt(worldPos); +} + + void RenderingManager::configureAmbient(MWWorld::Ptr::CellStore &mCell) { mAmbientColor.setAsABGR (mCell.mCell->mAmbi.mAmbient); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index fd43438ca5..b343a60bdb 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -158,6 +158,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches); + float getTerrainHeightAt (Ogre::Vector3 worldPos); + void setGlare(bool glare); void skyEnable (); void skyDisable (); diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 438366873c..c27dce6cad 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -71,6 +71,17 @@ namespace MWRender //---------------------------------------------------------------------------------------------- + float TerrainManager::getTerrainHeightAt(Vector3 worldPos) + { + Ogre::Terrain* terrain = NULL; + float height = mTerrainGroup.getHeightAtWorldPosition(worldPos, &terrain); + if (terrain == NULL) + return std::numeric_limits().min(); + return height; + } + + //---------------------------------------------------------------------------------------------- + TerrainManager::~TerrainManager() { OGRE_DELETE mTerrainGlobals; diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index 484a0dbe3a..45c56390e8 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -40,6 +40,9 @@ namespace MWRender{ void cellAdded(MWWorld::CellStore* store); void cellRemoved(MWWorld::CellStore* store); + + float getTerrainHeightAt (Ogre::Vector3 worldPos); + private: Ogre::TerrainGlobalOptions* mTerrainGlobals; Ogre::TerrainGroup mTerrainGroup; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index d86a6e3486..000cc545db 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -303,6 +303,8 @@ namespace MWScript zRot = zRot/60.; } MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); + + MWBase::Environment::get().getWorld()->adjustPosition(ptr); } else { @@ -341,6 +343,7 @@ namespace MWScript zRot = zRot/60.; } MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); + MWBase::Environment::get().getWorld()->adjustPosition(ptr); } }; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 98579797c7..2dfa241b3b 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -259,6 +259,10 @@ namespace MWWorld throw std::runtime_error ("class can't be enchanted"); } + void Class::adjustPosition(const MWWorld::Ptr& ptr) const + { + } + MWWorld::Ptr Class::copyToCellImpl(const Ptr &ptr, CellStore &cell) const { diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index e34ebdde77..de4741e38b 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -81,6 +81,9 @@ namespace MWWorld ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void adjustPosition(const MWWorld::Ptr& ptr) const; + ///< Adjust position to stand on ground. Must be called post model load + virtual MWMechanics::CreatureStats& getCreatureStats (const Ptr& ptr) const; ///< Return creature stats or throw an exception, if class does not have creature stats /// (default implementation: throw an exceoption) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 28f3317065..19ee2e517b 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -88,6 +88,50 @@ namespace MWWorld } public: + static Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr, OEngine::Physic::PhysicEngine *engine) + { + const ESM::Position &refpos = ptr.getRefData().getPosition(); + Ogre::Vector3 position(refpos.pos); + + bool hit=false; + bool isInterior = !ptr.getCell()->isExterior(); + + OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle()); + if (!physicActor) + return position; + + bool wasCollisionMode = physicActor->getCollisionMode(); + + physicActor->enableCollisions(false); + + Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); + + Ogre::Vector3 newPosition = position; + + traceResults trace; //no initialization needed + + int maxHeight = 400.f; + int steps = 100; + for (int i=0; isetOnGround(hit); + physicActor->enableCollisions(wasCollisionMode); + + if (hit) + return newPosition; + else + return position; + } + + static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity, OEngine::Physic::PhysicEngine *engine) { @@ -318,7 +362,7 @@ namespace MWWorld btVector3 btTo = btVector3(to.x, to.y, to.z); std::pair test = mEngine->rayTest(btFrom, btTo); - if (test.first == "") { + if (test.second == -1) { return std::make_pair(false, Ogre::Vector3()); } return std::make_pair(true, ray.getPoint(len * test.second)); @@ -351,6 +395,10 @@ namespace MWWorld return MovementSolver::move(ptr, movement, time, gravity, mEngine); } + Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr) + { + return MovementSolver::traceDown(ptr, mEngine); + } void PhysicsSystem::addHeightField (float* heights, int x, int y, float yoffset, diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 2e48be4079..4eec9367cb 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -51,6 +51,7 @@ namespace MWWorld bool toggleCollisionMode(); Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity); + Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr); std::pair getFacedHandle (MWWorld::World& world, float queryDistance); std::vector < std::pair > getFacedHandles (float queryDistance); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 339026ca60..c8853f4842 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -51,6 +51,7 @@ namespace class_.insertObject(ptr, physics); MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true); MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale); + class_.adjustPosition(ptr); } catch (const std::exception& e) { @@ -99,7 +100,6 @@ namespace MWWorld } mRendering.removeCell(*iter); - //mPhysics->removeObject("Unnamed_43"); MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter); MWBase::Environment::get().getMechanicsManager()->drop (*iter); @@ -165,6 +165,8 @@ namespace MWWorld float y = Ogre::Radian(pos.rot[1]).valueDegrees(); float z = Ogre::Radian(pos.rot[2]).valueDegrees(); world->rotateObject(player, x, y, z); + + world->adjustPosition(player); } MWBase::MechanicsManager *mechMgr = @@ -355,6 +357,8 @@ namespace MWWorld float y = Ogre::Radian(position.rot[1]).valueDegrees(); float z = Ogre::Radian(position.rot[2]).valueDegrees(); world->rotateObject(world->getPlayer().getPlayer(), x, y, z); + + world->adjustPosition(world->getPlayer().getPlayer()); return; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ae0e02c8c9..2ce753b816 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -709,6 +709,7 @@ namespace MWWorld pos.pos[0] = x; pos.pos[1] = y; pos.pos[2] = z; + Ogre::Vector3 vec(x, y, z); CellStore *currCell = ptr.getCell(); @@ -822,6 +823,24 @@ namespace MWWorld } } + void World::adjustPosition(const Ptr &ptr) + { + Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]); + + if (!isFlying(ptr)) + { + Ogre::Vector3 traced = mPhysics->traceDown(ptr); + if (traced.z < pos.z) + pos.z = traced.z; + } + + float terrainHeight = mRendering->getTerrainHeightAt(pos); + if (pos.z < terrainHeight) + pos.z = terrainHeight; + + moveObject(ptr, pos.x, pos.y, pos.z); + } + void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) { rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(), diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 8cff50bd16..5ae87a1ff7 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -188,6 +188,9 @@ namespace MWWorld virtual Ptr searchPtrViaHandle (const std::string& handle); ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual void adjustPosition (const Ptr& ptr); + ///< Adjust position after load to be on ground. Must be called after model load. + virtual void enable (const Ptr& ptr); virtual void disable (const Ptr& ptr); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 7b831d32c5..f71fa4320b 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -323,7 +323,8 @@ namespace Physic mHeightFieldMap [name] = hf; - dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal); + dynamicsWorld->addRigidBody(body,CollisionType_World|CollisionType_Raycasting, + CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal|CollisionType_Raycasting); } void PhysicEngine::removeHeightField(int x, int y) From fea44c05d4a337ffe4f5543c94c2a9ec3ab724bc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 10:10:26 +0200 Subject: [PATCH 052/198] added class record verifier --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/classcheck.cpp | 63 ++++++++++++++++++++++++++ apps/opencs/model/tools/classcheck.hpp | 29 ++++++++++++ apps/opencs/model/tools/tools.cpp | 3 ++ apps/opencs/model/world/data.cpp | 10 ++++ apps/opencs/model/world/data.hpp | 4 ++ 6 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/classcheck.cpp create mode 100644 apps/opencs/model/tools/classcheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index a305d90d93..adfc5f4aeb 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,7 +35,7 @@ opencs_units (model/tools ) opencs_units_noqt (model/tools - stage verifier mandatoryid skillcheck + stage verifier mandatoryid skillcheck classcheck ) diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp new file mode 100644 index 0000000000..302af6b9db --- /dev/null +++ b/apps/opencs/model/tools/classcheck.cpp @@ -0,0 +1,63 @@ + +#include "classcheck.hpp" + +#include +#include + +#include +#include + +#include "../world/universalid.hpp" + +CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection& classes) +: mClasses (classes) +{} + +int CSMTools::ClassCheckStage::setup() +{ + return mClasses.getSize(); +} + +void CSMTools::ClassCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Class& class_= mClasses.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId); + + // test for empty name and description + if (class_.mName.empty()) + messages.push_back (id.toString() + "|" + class_.mId + " has an empty name"); + + if (class_.mDescription.empty()) + messages.push_back (id.toString() + "|" + class_.mId + " has an empty description"); + + // test for invalid attributes + for (int i=0; i<2; ++i) + if (class_.mData.mAttribute[i]==-1) + { + std::ostringstream stream; + + stream << id.toString() << "|Attribute #" << i << " of " << class_.mId << " is not set"; + + messages.push_back (stream.str()); + } + + // test for non-unique skill + std::map skills; // ID, number of occurrences + + for (int i=0; i<5; ++i) + for (int i2=0; i2<2; ++i2) + ++skills[class_.mData.mSkills[i][i2]]; + + for (std::map::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) + if (iter->second>1) + { + std::ostringstream stream; + + stream + << id.toString() << "|" + << ESM::Skill::indexToId (iter->first) << " is listed more than once"; + + messages.push_back (stream.str()); + } +} \ No newline at end of file diff --git a/apps/opencs/model/tools/classcheck.hpp b/apps/opencs/model/tools/classcheck.hpp new file mode 100644 index 0000000000..a29d7c8b78 --- /dev/null +++ b/apps/opencs/model/tools/classcheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_CLASSCHECK_H +#define CSM_TOOLS_CLASSCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that class records are internally consistent + class ClassCheckStage : public Stage + { + const CSMWorld::IdCollection& mClasses; + + public: + + ClassCheckStage (const CSMWorld::IdCollection& classes); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 33cc3cc61b..84a6910ecc 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -13,6 +13,7 @@ #include "reportmodel.hpp" #include "mandatoryid.hpp" #include "skillcheck.hpp" +#include "classcheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -54,6 +55,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); mVerifier->appendStage (new SkillCheckStage (mData.getSkills())); + + mVerifier->appendStage (new ClassCheckStage (mData.getClasses())); } return mVerifier; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 13fff7f096..fc6cc01220 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -107,6 +107,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getSkills() return mSkills; } +const CSMWorld::IdCollection& CSMWorld::Data::getClasses() const +{ + return mClasses; +} + +CSMWorld::IdCollection& CSMWorld::Data::getClasses() +{ + return mClasses; +} + const CSMWorld::IdCollection& CSMWorld::Data::getFactions() const { return mFactions; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 1e2894774a..16a9685a53 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -54,6 +54,10 @@ namespace CSMWorld IdCollection& getSkills(); + const IdCollection& getClasses() const; + + IdCollection& getClasses(); + const IdCollection& getFactions() const; IdCollection& getFactions(); From 06533b8d71a10139816996a3f68042b7f4aff14e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 10:31:10 +0200 Subject: [PATCH 053/198] additional check for using the same attribute twice in a class --- apps/opencs/model/tools/classcheck.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index 302af6b9db..da2e9f19a6 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -42,6 +42,15 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me messages.push_back (stream.str()); } + if (class_.mData.mAttribute[0]==class_.mData.mAttribute[1] && class_.mData.mAttribute[0]!=-1) + { + std::ostringstream stream; + + stream << id.toString() << "|Class lists same attribute twice"; + + messages.push_back (stream.str()); + } + // test for non-unique skill std::map skills; // ID, number of occurrences From b5eaa464ad8cb840437a9280f278f25813e18930 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 10:39:43 +0200 Subject: [PATCH 054/198] added faction record verifier --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/factioncheck.cpp | 61 ++++++++++++++++++++++++ apps/opencs/model/tools/factioncheck.hpp | 29 +++++++++++ apps/opencs/model/tools/tools.cpp | 3 ++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/factioncheck.cpp create mode 100644 apps/opencs/model/tools/factioncheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index adfc5f4aeb..07766507f7 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,7 +35,7 @@ opencs_units (model/tools ) opencs_units_noqt (model/tools - stage verifier mandatoryid skillcheck classcheck + stage verifier mandatoryid skillcheck classcheck factioncheck ) diff --git a/apps/opencs/model/tools/factioncheck.cpp b/apps/opencs/model/tools/factioncheck.cpp new file mode 100644 index 0000000000..ea4a87eec8 --- /dev/null +++ b/apps/opencs/model/tools/factioncheck.cpp @@ -0,0 +1,61 @@ + +#include "factioncheck.hpp" + +#include +#include + +#include +#include + +#include "../world/universalid.hpp" + +CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection& factions) +: mFactions (factions) +{} + +int CSMTools::FactionCheckStage::setup() +{ + return mFactions.getSize(); +} + +void CSMTools::FactionCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Faction& faction = mFactions.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Faction, faction.mId); + + // test for empty name + if (faction.mName.empty()) + messages.push_back (id.toString() + "|" + faction.mId + " has an empty name"); + + // test for invalid attributes + if (faction.mData.mAttributes[0]==faction.mData.mAttributes[1] && faction.mData.mAttributes[0]!=-1) + { + std::ostringstream stream; + + stream << id.toString() << "|Faction lists same attribute twice"; + + messages.push_back (stream.str()); + } + + // test for non-unique skill + std::map skills; // ID, number of occurrences + + for (int i=0; i<6; ++i) + if (faction.mData.mSkills[i]!=-1) + ++skills[faction.mData.mSkills[i]]; + + for (std::map::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) + if (iter->second>1) + { + std::ostringstream stream; + + stream + << id.toString() << "|" + << ESM::Skill::indexToId (iter->first) << " is listed more than once"; + + messages.push_back (stream.str()); + } + + /// \todo check data members that can't be edited in the table view +} \ No newline at end of file diff --git a/apps/opencs/model/tools/factioncheck.hpp b/apps/opencs/model/tools/factioncheck.hpp new file mode 100644 index 0000000000..8686505727 --- /dev/null +++ b/apps/opencs/model/tools/factioncheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_FACTIONCHECK_H +#define CSM_TOOLS_FACTIONCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that faction records are internally consistent + class FactionCheckStage : public Stage + { + const CSMWorld::IdCollection& mFactions; + + public: + + FactionCheckStage (const CSMWorld::IdCollection& factions); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 84a6910ecc..db45de43e5 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -14,6 +14,7 @@ #include "mandatoryid.hpp" #include "skillcheck.hpp" #include "classcheck.hpp" +#include "factioncheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -57,6 +58,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new SkillCheckStage (mData.getSkills())); mVerifier->appendStage (new ClassCheckStage (mData.getClasses())); + + mVerifier->appendStage (new FactionCheckStage (mData.getFactions())); } return mVerifier; From 7136ac0079ed293752202416e6a1f1c9478f0a90 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 10:58:53 +0200 Subject: [PATCH 055/198] added missing attribute columns to faction table --- apps/esmtool/record.cpp | 8 ++++---- apps/opencs/model/tools/factioncheck.cpp | 2 +- apps/opencs/model/world/data.cpp | 2 ++ apps/openmw/mwdialogue/filter.cpp | 4 ++-- apps/openmw/mwgui/stats_window.cpp | 4 ++-- components/esm/loadfact.cpp | 2 +- components/esm/loadfact.hpp | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 8f77e4b445..d15e7f2b0b 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -679,10 +679,10 @@ void Record::print() std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl; if (mData.mData.mUnknown != -1) std::cout << " Unknown: " << mData.mData.mUnknown << std::endl; - std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttributes[0]) - << " (" << mData.mData.mAttributes[0] << ")" << std::endl; - std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttributes[1]) - << " (" << mData.mData.mAttributes[1] << ")" << std::endl; + std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0]) + << " (" << mData.mData.mAttribute[0] << ")" << std::endl; + std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1]) + << " (" << mData.mData.mAttribute[1] << ")" << std::endl; for (int i = 0; i != 6; i++) if (mData.mData.mSkills[i] != -1) std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i]) diff --git a/apps/opencs/model/tools/factioncheck.cpp b/apps/opencs/model/tools/factioncheck.cpp index ea4a87eec8..af26904efa 100644 --- a/apps/opencs/model/tools/factioncheck.cpp +++ b/apps/opencs/model/tools/factioncheck.cpp @@ -29,7 +29,7 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector& messages.push_back (id.toString() + "|" + faction.mId + " has an empty name"); // test for invalid attributes - if (faction.mData.mAttributes[0]==faction.mData.mAttributes[1] && faction.mData.mAttributes[0]!=-1) + if (faction.mData.mAttribute[0]==faction.mData.mAttribute[1] && faction.mData.mAttribute[0]!=-1) { std::ostringstream stream; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index fc6cc01220..d62fd7267b 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -60,6 +60,8 @@ CSMWorld::Data::Data() mFactions.addColumn (new StringIdColumn); mFactions.addColumn (new RecordStateColumn); mFactions.addColumn (new NameColumn); + mFactions.addColumn (new AttributesColumn (0)); + mFactions.addColumn (new AttributesColumn (1)); mFactions.addColumn (new HiddenColumn); for (int i=0; i<6; ++i) mFactions.addColumn (new SkillsColumn (i)); diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index ddb15d423d..78969ffd0b 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -569,8 +569,8 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements (const MWWorld::Ptr& ac MWMechanics::CreatureStats& stats = MWWorld::Class::get (actor).getCreatureStats (actor); - return stats.getAttribute (faction.mData.mAttributes[0]).getBase()>=faction.mData.mRankData[rank].mAttribute1 && - stats.getAttribute (faction.mData.mAttributes[1]).getBase()>=faction.mData.mRankData[rank].mAttribute2; + return stats.getAttribute (faction.mData.mAttribute[0]).getBase()>=faction.mData.mRankData[rank].mAttribute1 && + stats.getAttribute (faction.mData.mAttribute[1]).getBase()>=faction.mData.mRankData[rank].mAttribute2; } bool MWDialogue::Filter::hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 86019fa28d..0678e98919 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -500,8 +500,8 @@ void StatsWindow::updateSkillArea() text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; ESM::RankData rankData = faction->mData.mRankData[it->second+1]; - const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttributes[0]); - const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttributes[1]); + const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute[0]); + const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute[1]); assert(attr1 && attr2); text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index 12a76f1ade..e2712d462d 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -71,7 +71,7 @@ void Faction::save(ESMWriter &esm) void Faction::blank() { mName.clear(); - mData.mAttributes[0] = mData.mAttributes[1] = 0; + mData.mAttribute[0] = mData.mAttribute[1] = 0; mData.mUnknown = -1; mData.mIsHidden = 0; diff --git a/components/esm/loadfact.hpp b/components/esm/loadfact.hpp index edc4640bb1..891b996473 100644 --- a/components/esm/loadfact.hpp +++ b/components/esm/loadfact.hpp @@ -34,7 +34,7 @@ struct Faction struct FADTstruct { // Which attributes we like - int mAttributes[2]; + int mAttribute[2]; RankData mRankData[10]; From e8c32d0c3db7a77ed27db957e5b1d718bb2fd961 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 11:23:17 +0200 Subject: [PATCH 056/198] MWWorld::Player cleanup --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwscript/controlextensions.cpp | 1 + apps/openmw/mwworld/cellstore.hpp | 35 +---------------- apps/openmw/mwworld/livecellref.hpp | 45 ++++++++++++++++++++++ apps/openmw/mwworld/player.cpp | 31 +++++++++++++-- apps/openmw/mwworld/player.hpp | 33 ++++++---------- 6 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 apps/openmw/mwworld/livecellref.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index beb0b9aadf..8a0030be42 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -54,7 +54,7 @@ add_openmw_dir (mwworld containerstore actiontalk actiontake manualref player cellfunctors failedaction cells localscripts customdata weather inventorystore ptr actionopen actionread actionequip timestamp actionalchemy cellstore actionapply actioneat - esmstore store recordcmp fallback actionrepair actionsoulgem + esmstore store recordcmp fallback actionrepair actionsoulgem livecellref ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 8d65dfdd5b..ac53b8ee25 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -12,6 +12,7 @@ #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/ptr.hpp" #include "../mwmechanics/npcstats.hpp" diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 2e6b45bb7e..0cc111cde3 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -6,45 +6,12 @@ #include #include -#include "refdata.hpp" +#include "livecellref.hpp" #include "esmstore.hpp" struct C; namespace MWWorld { - class Ptr; - class ESMStore; - - /// A reference to one object (of any type) in a cell. - /// - /// Constructing this with a CellRef instance in the constructor means that - /// in practice (where D is RefData) the possibly mutable data is copied - /// across to mData. If later adding data (such as position) to CellRef - /// this would have to be manually copied across. - template - struct LiveCellRef - { - LiveCellRef(const ESM::CellRef& cref, const X* b = NULL) - : mBase(b), mRef(cref), mData(mRef) - {} - - LiveCellRef(const X* b = NULL) - : mBase(b), mData(mRef) - {} - - // The object that this instance is based on. - const X* mBase; - - /* Information about this instance, such as 3D location and - rotation and individual type-dependent data. - */ - ESM::CellRef mRef; - - /// runtime-data - RefData mData; - }; - - template bool operator==(const LiveCellRef& ref, int pRefnum); /// A list of cell references template diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp new file mode 100644 index 0000000000..4c5efb861f --- /dev/null +++ b/apps/openmw/mwworld/livecellref.hpp @@ -0,0 +1,45 @@ +#ifndef GAME_MWWORLD_LIVECELLREF_H +#define GAME_MWWORLD_LIVECELLREF_H + +#include + +#include "refdata.hpp" + +namespace MWWorld +{ + class Ptr; + class ESMStore; + + /// A reference to one object (of any type) in a cell. + /// + /// Constructing this with a CellRef instance in the constructor means that + /// in practice (where D is RefData) the possibly mutable data is copied + /// across to mData. If later adding data (such as position) to CellRef + /// this would have to be manually copied across. + template + struct LiveCellRef + { + LiveCellRef(const ESM::CellRef& cref, const X* b = NULL) + : mBase(b), mRef(cref), mData(mRef) + {} + + LiveCellRef(const X* b = NULL) + : mBase(b), mData(mRef) + {} + + // The object that this instance is based on. + const X* mBase; + + /* Information about this instance, such as 3D location and + rotation and individual type-dependent data. + */ + ESM::CellRef mRef; + + /// runtime-data + RefData mData; + }; + + template bool operator==(const LiveCellRef& ref, int pRefnum); +} + +#endif diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index ea8a02dee9..3338f08edf 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -1,14 +1,13 @@ #include "player.hpp" - #include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" + +#include "../mwworld/ptr.hpp" #include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" -#include "esmstore.hpp" #include "class.hpp" namespace MWWorld @@ -25,12 +24,38 @@ namespace MWWorld playerPos[0] = playerPos[1] = playerPos[2] = 0; } + void Player::setCell (MWWorld::CellStore *cellStore) + { + mCellStore = cellStore; + } + + MWWorld::Ptr Player::getPlayer() + { + MWWorld::Ptr ptr (&mPlayer, mCellStore); + return ptr; + } + + void Player::setBirthSign (const std::string &sign) + { + mSign = sign; + } + + const std::string& Player::getBirthSign() const + { + return mSign; + } + void Player::setDrawState (MWMechanics::DrawState_ state) { MWWorld::Ptr ptr = getPlayer(); MWWorld::Class::get(ptr).getNpcStats(ptr).setDrawState (state); } + bool Player::getAutoMove() const + { + return mAutoMove; + } + void Player::setAutoMove (bool enable) { MWWorld::Ptr ptr = getPlayer(); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index c985510917..dfaddf66a9 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -1,15 +1,20 @@ #ifndef GAME_MWWORLD_PLAYER_H #define GAME_MWWORLD_PLAYER_H -#include "../mwworld/cellstore.hpp" #include "../mwworld/refdata.hpp" -#include "../mwworld/ptr.hpp" +#include "../mwworld/livecellref.hpp" #include "../mwmechanics/drawstate.hpp" +namespace ESM +{ + struct NPC; +} + namespace MWBase { class World; + class Ptr; } namespace MWWorld @@ -30,31 +35,17 @@ namespace MWWorld Player(const ESM::NPC *player, const MWBase::World& world); - void setCell (MWWorld::CellStore *cellStore) - { - mCellStore = cellStore; - } + void setCell (MWWorld::CellStore *cellStore); - MWWorld::Ptr getPlayer() - { - MWWorld::Ptr ptr (&mPlayer, mCellStore); - return ptr; - } + MWWorld::Ptr getPlayer(); - void setBirthSign(const std::string &sign) { - mSign = sign; - } + void setBirthSign(const std::string &sign); - const std::string &getBirthSign() const { - return mSign; - } + const std::string &getBirthSign() const; void setDrawState (MWMechanics::DrawState_ state); - bool getAutoMove() const - { - return mAutoMove; - } + bool getAutoMove() const; MWMechanics::DrawState_ getDrawState(); /// \todo constness From 8c7d578ddcf9a8d91e80c98618a19045252d1959 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 12:13:15 +0200 Subject: [PATCH 057/198] moved the CellRef struct to its own header --- apps/openmw/mwworld/livecellref.hpp | 2 +- components/CMakeLists.txt | 2 +- components/esm/cellref.hpp | 90 +++++++++++++++++++++++++++++ components/esm/loadcell.hpp | 78 +------------------------ 4 files changed, 93 insertions(+), 79 deletions(-) create mode 100644 components/esm/cellref.hpp diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 4c5efb861f..8f419b626f 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -1,7 +1,7 @@ #ifndef GAME_MWWORLD_LIVECELLREF_H #define GAME_MWWORLD_LIVECELLREF_H -#include +#include #include "refdata.hpp" diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 88bf764445..a2f416fcca 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -39,7 +39,7 @@ add_component_dir (esm loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat - loadweap records aipackage effectlist spelllist variant variantimp loadtes3 + loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref ) add_component_dir (misc diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp new file mode 100644 index 0000000000..fb03a90844 --- /dev/null +++ b/components/esm/cellref.hpp @@ -0,0 +1,90 @@ +#ifndef OPENMW_ESM_CELLREF_H +#define OPENMW_ESM_CELLREF_H + +#include + +#include "defs.hpp" + +namespace ESM +{ + class ESMWriter; + + /* Cell reference. This represents ONE object (of many) inside the + cell. The cell references are not loaded as part of the normal + loading process, but are rather loaded later on demand when we are + setting up a specific cell. + */ + + class CellRef + { + public: + + int mRefnum; // Reference number + std::string mRefID; // ID of object being referenced + + float mScale; // Scale applied to mesh + + // The NPC that owns this object (and will get angry if you steal + // it) + std::string mOwner; + + // I have no idea, looks like a link to a global variable? + std::string mGlob; + + // ID of creature trapped in this soul gem (?) + std::string mSoul; + + // ?? CNAM has a faction name, might be for objects/beds etc + // belonging to a faction. + std::string mFaction; + + // INDX might be PC faction rank required to use the item? Sometimes + // is -1, which I assume means "any rank". + int mFactIndex; + + // For weapon or armor, this is the remaining item health. + // For tools (lockpicks, probes, repair hammer) it is the remaining uses. + int mCharge; + + // Remaining enchantment charge + float mEnchantmentCharge; + + // This is 5 for Gold_005 references, 100 for Gold_100 and so on. + int mGoldValue; + + // For doors - true if this door teleports to somewhere else, false + // if it should open through animation. + bool mTeleport; + + // Teleport location for the door, if this is a teleporting door. + Position mDoorDest; + + // Destination cell for doors (optional) + std::string mDestCell; + + // Lock level for doors and containers + int mLockLevel; + std::string mKey, mTrap; // Key and trap ID names, if any + + // This corresponds to the "Reference Blocked" checkbox in the construction set, + // which prevents editing that reference. + // -1 is not blocked, otherwise it is blocked. + signed char mReferenceBlocked; + + // Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn. + int mDeleted; + + // Occurs in Tribunal.esm, eg. in the cell "Mournhold, Plaza + // Brindisi Dorom", where it has the value 100. Also only for + // activators. + int mFltv; + int mNam0; + + // Position and rotation of this object within the cell + Position mPos; + + void save(ESMWriter &esm); + }; +} + +#endif \ No newline at end of file diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index afc953f54c..44412b5eb9 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -7,95 +7,19 @@ #include "esmcommon.hpp" #include "defs.hpp" - +#include "cellref.hpp" namespace MWWorld { class ESMStore; } - namespace ESM { class ESMReader; class ESMWriter; -/* Cell reference. This represents ONE object (of many) inside the - cell. The cell references are not loaded as part of the normal - loading process, but are rather loaded later on demand when we are - setting up a specific cell. - */ -class CellRef -{ -public: - int mRefnum; // Reference number - std::string mRefID; // ID of object being referenced - - float mScale; // Scale applied to mesh - - // The NPC that owns this object (and will get angry if you steal - // it) - std::string mOwner; - - // I have no idea, looks like a link to a global variable? - std::string mGlob; - - // ID of creature trapped in this soul gem (?) - std::string mSoul; - - // ?? CNAM has a faction name, might be for objects/beds etc - // belonging to a faction. - std::string mFaction; - - // INDX might be PC faction rank required to use the item? Sometimes - // is -1, which I assume means "any rank". - int mFactIndex; - - // For weapon or armor, this is the remaining item health. - // For tools (lockpicks, probes, repair hammer) it is the remaining uses. - int mCharge; - - // Remaining enchantment charge - float mEnchantmentCharge; - - // This is 5 for Gold_005 references, 100 for Gold_100 and so on. - int mGoldValue; - - // For doors - true if this door teleports to somewhere else, false - // if it should open through animation. - bool mTeleport; - - // Teleport location for the door, if this is a teleporting door. - Position mDoorDest; - - // Destination cell for doors (optional) - std::string mDestCell; - - // Lock level for doors and containers - int mLockLevel; - std::string mKey, mTrap; // Key and trap ID names, if any - - // This corresponds to the "Reference Blocked" checkbox in the construction set, - // which prevents editing that reference. - // -1 is not blocked, otherwise it is blocked. - signed char mReferenceBlocked; - - // Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn. - int mDeleted; - - // Occurs in Tribunal.esm, eg. in the cell "Mournhold, Plaza - // Brindisi Dorom", where it has the value 100. Also only for - // activators. - int mFltv; - int mNam0; - - // Position and rotation of this object within the cell - Position mPos; - - void save(ESMWriter &esm); -}; - /* Moved cell reference tracking object. This mainly stores the target cell of the reference, so we can easily know where it has been moved when another plugin tries to move it independently. From 5244362fba72d6e47e54a75b9d6a5e890d8bb266 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 12:23:06 +0200 Subject: [PATCH 058/198] some cleanup --- apps/openmw/mwworld/cellstore.hpp | 1 - apps/openmw/mwworld/livecellref.hpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 0cc111cde3..7e4fc407d4 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -9,7 +9,6 @@ #include "livecellref.hpp" #include "esmstore.hpp" -struct C; namespace MWWorld { diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 8f419b626f..28c1bb5c27 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -39,7 +39,7 @@ namespace MWWorld RefData mData; }; - template bool operator==(const LiveCellRef& ref, int pRefnum); +// template bool operator==(const LiveCellRef& ref, int pRefnum); } #endif From 111ebf84bb352072e60cc94e7e7427872b66aa91 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 12:27:57 +0200 Subject: [PATCH 059/198] replaced an include with a forward declaration --- apps/openmw/mwscript/locals.cpp | 13 ++++++++----- apps/openmw/mwscript/locals.hpp | 10 +++++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp index 2cf2a97c1d..180a2791bc 100644 --- a/apps/openmw/mwscript/locals.cpp +++ b/apps/openmw/mwscript/locals.cpp @@ -1,8 +1,11 @@ #include "locals.hpp" +#include + +#include + #include "../mwbase/environment.hpp" #include "../mwbase/scriptmanager.hpp" -#include namespace MWScript { @@ -39,9 +42,9 @@ namespace MWScript } return 0; } - + bool Locals::setVarByInt(const std::string& script, const std::string& var, int val) - { + { Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); int index = locals.getIndex(var); char type = locals.getType(var); @@ -51,10 +54,10 @@ namespace MWScript { case 's': mShorts.at (index) = val; break; - + case 'l': mLongs.at (index) = val; break; - + case 'f': mFloats.at (index) = val; break; } diff --git a/apps/openmw/mwscript/locals.hpp b/apps/openmw/mwscript/locals.hpp index 1d9b9c3e4f..deae0d44ea 100644 --- a/apps/openmw/mwscript/locals.hpp +++ b/apps/openmw/mwscript/locals.hpp @@ -3,9 +3,13 @@ #include -#include #include +namespace ESM +{ + struct Script; +} + namespace MWScript { class Locals @@ -14,11 +18,11 @@ namespace MWScript std::vector mShorts; std::vector mLongs; std::vector mFloats; - + void configure (const ESM::Script& script); bool setVarByInt(const std::string& script, const std::string& var, int val); int getIntVar (const std::string& script, const std::string& var); ///< if var does not exist, returns 0 - + }; } From 62d70f17c859977ac631378595cdf09b18022258 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 12:42:38 +0200 Subject: [PATCH 060/198] removed another redundant include --- apps/openmw/mwworld/cellstore.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 7e4fc407d4..f8467c84f6 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -1,8 +1,6 @@ #ifndef GAME_MWWORLD_CELLSTORE_H #define GAME_MWWORLD_CELLSTORE_H -#include - #include #include From 18e046e6285f41b588fba796da123a44faffeae0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 13:50:36 +0200 Subject: [PATCH 061/198] cleaned up race record struct --- apps/esmtool/record.cpp | 60 ++++++------------- .../mwmechanics/mechanicsmanagerimp.cpp | 16 +---- components/esm/loadrace.cpp | 9 +++ components/esm/loadrace.hpp | 13 ++-- 4 files changed, 34 insertions(+), 64 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index d15e7f2b0b..a6f77862ef 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -1099,53 +1099,29 @@ void Record::print() template<> void Record::print() { + static const char *sAttributeNames[8] = + { + "Strength", "Intelligence", "Willpower", "Agility", + "Speed", "Endurance", "Personality", "Luck" + }; + std::cout << " Name: " << mData.mName << std::endl; std::cout << " Description: " << mData.mDescription << std::endl; std::cout << " Flags: " << raceFlags(mData.mData.mFlags) << std::endl; - std::cout << " Male:" << std::endl; - std::cout << " Strength: " - << mData.mData.mStrength.mMale << std::endl; - std::cout << " Intelligence: " - << mData.mData.mIntelligence.mMale << std::endl; - std::cout << " Willpower: " - << mData.mData.mWillpower.mMale << std::endl; - std::cout << " Agility: " - << mData.mData.mAgility.mMale << std::endl; - std::cout << " Speed: " - << mData.mData.mSpeed.mMale << std::endl; - std::cout << " Endurance: " - << mData.mData.mEndurance.mMale << std::endl; - std::cout << " Personality: " - << mData.mData.mPersonality.mMale << std::endl; - std::cout << " Luck: " - << mData.mData.mLuck.mMale << std::endl; - std::cout << " Height: " - << mData.mData.mHeight.mMale << std::endl; - std::cout << " Weight: " - << mData.mData.mWeight.mMale << std::endl; + for (int i=0; i<2; ++i) + { + bool male = i==0; - std::cout << " Female:" << std::endl; - std::cout << " Strength: " - << mData.mData.mStrength.mFemale << std::endl; - std::cout << " Intelligence: " - << mData.mData.mIntelligence.mFemale << std::endl; - std::cout << " Willpower: " - << mData.mData.mWillpower.mFemale << std::endl; - std::cout << " Agility: " - << mData.mData.mAgility.mFemale << std::endl; - std::cout << " Speed: " - << mData.mData.mSpeed.mFemale << std::endl; - std::cout << " Endurance: " - << mData.mData.mEndurance.mFemale << std::endl; - std::cout << " Personality: " - << mData.mData.mPersonality.mFemale << std::endl; - std::cout << " Luck: " - << mData.mData.mLuck.mFemale << std::endl; - std::cout << " Height: " - << mData.mData.mHeight.mFemale << std::endl; - std::cout << " Weight: " - << mData.mData.mWeight.mFemale << std::endl; + std::cout << (male ? " Male:" : " Female:") << std::endl; + + for (int i=0; i<8; ++i) + std::cout << " " << sAttributeNames[i] << ": " + << mData.mData.mAttributeValues[i].getValue (male) << std::endl; + + std::cout << " Height: " << mData.mData.mHeight.getValue (male) << std::endl; + std::cout << " Weight: " << mData.mData.mWeight.getValue (male) << std::endl; + } for (int i = 0; i != 7; i++) // Not all races have 7 skills. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index c8d8279210..8757213e99 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -53,21 +53,9 @@ namespace MWMechanics for (int i=0; i<8; ++i) { - const ESM::Race::MaleFemale *attribute = 0; - switch (i) - { - case 0: attribute = &race->mData.mStrength; break; - case 1: attribute = &race->mData.mIntelligence; break; - case 2: attribute = &race->mData.mWillpower; break; - case 3: attribute = &race->mData.mAgility; break; - case 4: attribute = &race->mData.mSpeed; break; - case 5: attribute = &race->mData.mEndurance; break; - case 6: attribute = &race->mData.mPersonality; break; - case 7: attribute = &race->mData.mLuck; break; - } + const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i]; - creatureStats.getAttribute(i).setBase ( - static_cast (male ? attribute->mMale : attribute->mFemale)); + creatureStats.getAttribute(i).setBase (male ? attribute.mMale : attribute.mFemale); } for (int i=0; i<27; ++i) diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index 139ef081c0..94aa792bc6 100644 --- a/components/esm/loadrace.cpp +++ b/components/esm/loadrace.cpp @@ -5,6 +5,15 @@ namespace ESM { + int Race::MaleFemale::getValue (bool male) const + { + return male ? mMale : mFemale; + } + + int Race::MaleFemaleF::getValue (bool male) const + { + return male ? mMale : mFemale; + } void Race::load(ESMReader &esm) { diff --git a/components/esm/loadrace.hpp b/components/esm/loadrace.hpp index 91a424c10b..845956686c 100644 --- a/components/esm/loadrace.hpp +++ b/components/esm/loadrace.hpp @@ -26,11 +26,15 @@ struct Race struct MaleFemale { int mMale, mFemale; + + int getValue (bool male) const; }; struct MaleFemaleF { float mMale, mFemale; + + int getValue (bool male) const; }; enum Flags @@ -45,14 +49,7 @@ struct Race SkillBonus mBonus[7]; // Attribute values for male/female - MaleFemale mStrength, - mIntelligence, - mWillpower, - mAgility, - mSpeed, - mEndurance, - mPersonality, - mLuck; + MaleFemale mAttributeValues[8]; // The actual eye level height (in game units) is (probably) given // as 'height' times 128. This has not been tested yet. From 97d617d43f0bb88d680ddab826ee158d6f73c5e6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 Apr 2013 04:33:56 -0700 Subject: [PATCH 062/198] Use more appropriate VBO settings Unskinned meshes don't need dynamic VBOs; they aren't rewritten since their transformations are handled by the modelview matrix. They also don't need the local RAM copy (the "shadow buffer") since it's really only useful for skinning purposes (though this means the VBO has to be readable for static geometry to work). --- components/nifogre/ogrenifloader.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index f8eca821ff..6083238808 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -845,8 +845,13 @@ class NIFMeshLoader : Ogre::ManualResourceLoader const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); std::vector srcVerts = data->vertices; std::vector srcNorms = data->normals; + Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC; + bool vertShadowBuffer = false; if(skin != NULL) { + vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; + vertShadowBuffer = true; + // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be // explicitly attached later. mesh->setSkeletonName(mName); @@ -948,8 +953,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader if(srcVerts.size()) { vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - srcVerts.size(), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, - true); + srcVerts.size(), vertUsage, vertShadowBuffer); vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true); decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); @@ -960,8 +964,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader if(srcNorms.size()) { vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - srcNorms.size(), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, - true); + srcNorms.size(), vertUsage, vertShadowBuffer); vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true); decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); @@ -980,8 +983,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader rs->convertColourValue(clr, &colorsRGB[i]); } vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), - colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, - true); + colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC); vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true); decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); bind->setBinding(nextBuf++, vbuf); @@ -993,7 +995,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size()*numUVs, - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); + Ogre::HardwareBuffer::HBU_STATIC); for(size_t i = 0;i < numUVs;i++) { const std::vector &uvlist = data->uvlist[i]; @@ -1009,7 +1011,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader if(srcIdx.size()) { ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(), - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); + Ogre::HardwareBuffer::HBU_STATIC); ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true); sub->indexData->indexBuffer = ibuf; sub->indexData->indexCount = srcIdx.size(); From ee0a20f9ce30cd885a3110df97b6e911095d5d7f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 Apr 2013 07:00:24 -0700 Subject: [PATCH 063/198] Read some missing particle data from NIFs --- components/nif/data.hpp | 13 +++++++++---- components/nif/nifstream.hpp | 6 ++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 9bdba63961..68ffd19b8f 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -167,6 +167,10 @@ class NiAutoNormalParticlesData : public ShapeData public: int activeCount; + float activeRadius; + + std::vector sizes; + void read(NIFStream *nif) { ShapeData::read(nif); @@ -174,14 +178,13 @@ public: // Should always match the number of vertices activeCount = nif->getUShort(); - // Skip all the info, we don't support particles yet - nif->getFloat(); // Active radius ? + activeRadius = nif->getFloat(); nif->getUShort(); // Number of valid entries in the following arrays ? if(nif->getInt()) { // Particle sizes - nif->skip(activeCount * sizeof(float)); + nif->getFloats(sizes, activeCount); } } }; @@ -189,6 +192,8 @@ public: class NiRotatingParticlesData : public NiAutoNormalParticlesData { public: + std::vector rotations; + void read(NIFStream *nif) { NiAutoNormalParticlesData::read(nif); @@ -198,7 +203,7 @@ public: // Rotation quaternions. I THINK activeCount is correct here, // but verts (vertex number) might also be correct, if there is // any case where the two don't match. - nif->skip(activeCount * 4*sizeof(float)); + nif->getQuaternions(rotations, activeCount); } } }; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 02b931b7ed..a2595d17b8 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -168,6 +168,12 @@ public: for(size_t i = 0;i < vec.size();i++) vec[i] = getVector4(); } + void getQuaternions(std::vector &quat, size_t size) + { + quat.resize(size); + for(size_t i = 0;i < quat.size();i++) + quat[i] = getQuaternion(); + } }; } From 2f6ae4a915e1a26f75afd6993dd0b06ab40a211b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 Apr 2013 20:56:35 -0700 Subject: [PATCH 064/198] Read more particle information --- components/nif/controller.hpp | 79 ++++++++++++++++++++++++++++++++--- components/nif/data.hpp | 18 ++++---- components/nif/recordptr.hpp | 1 + 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 8331b93b7d..2ff25a274b 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -62,20 +62,87 @@ public: } }; -class NiBSPArrayController : public Controller +class NiParticleSystemController : public Controller { public: + float velocity; + float velocityRandom; + + float verticalDir; // 0=up, pi/2=horizontal, pi=down + float verticalAngle; + float horizontalDir; + float horizontalAngle; + + float size; + float startTime; + float stopTime; + + float emitRate; + float lifetime; + float lifetimeRandom; + + int emitFlags; // Bit 0: Emit Rate toggle bit (0 = auto adjust, 1 = use Emit Rate value) + Ogre::Vector3 offsetRandom; + + NodePtr emitter; + + int numParticles; + int activeCount; + //std::vector particles; /*numParticles*/ + + RecordPtr modifier; + void read(NIFStream *nif) { Controller::read(nif); - // At the moment, just skip it all - nif->skip(111); - int s = nif->getUShort(); - nif->skip(15 + s*40); + velocity = nif->getFloat(); + velocityRandom = nif->getFloat(); + verticalDir = nif->getFloat(); + verticalAngle = nif->getFloat(); + horizontalDir = nif->getFloat(); + horizontalAngle = nif->getFloat(); + /*normal?*/ nif->getVector3(); + /*color?*/ nif->getVector4(); + size = nif->getFloat(); + startTime = nif->getFloat(); + stopTime = nif->getFloat(); + nif->getChar(); + emitRate = nif->getFloat(); + lifetime = nif->getFloat(); + lifetimeRandom = nif->getFloat(); + + emitFlags = nif->getUShort(); + offsetRandom = nif->getVector3(); + + emitter.read(nif); + + /* Unknown Short, 0? + * Unknown Float, 1.0? + * Unknown Int, 1? + * Unknown Int, 0? + * Unknown Short, 0? + */ + nif->skip(16); + + numParticles = nif->getUShort(); + activeCount = nif->getUShort(); + nif->skip(numParticles*40); + + nif->getUInt(); /* -1? */ + modifier.read(nif); + nif->getUInt(); /* -1? */ + nif->getChar(); + } + + void post(NIFFile *nif) + { + Controller::post(nif); + emitter.post(nif); + modifier.post(nif); } }; -typedef NiBSPArrayController NiParticleSystemController; +typedef NiParticleSystemController NiBSPArrayController; class NiMaterialColorController : public Controller { diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 68ffd19b8f..a2c9bb56db 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -165,9 +165,9 @@ public: class NiAutoNormalParticlesData : public ShapeData { public: - int activeCount; + float particleSize; - float activeRadius; + int activeCount; std::vector sizes; @@ -176,15 +176,15 @@ public: ShapeData::read(nif); // Should always match the number of vertices - activeCount = nif->getUShort(); + nif->getUShort(); - activeRadius = nif->getFloat(); - nif->getUShort(); // Number of valid entries in the following arrays ? + particleSize = nif->getFloat(); + activeCount = nif->getUShort(); if(nif->getInt()) { // Particle sizes - nif->getFloats(sizes, activeCount); + nif->getFloats(sizes, vertices.size()); } } }; @@ -200,10 +200,8 @@ public: if(nif->getInt()) { - // Rotation quaternions. I THINK activeCount is correct here, - // but verts (vertex number) might also be correct, if there is - // any case where the two don't match. - nif->getQuaternions(rotations, activeCount); + // Rotation quaternions. + nif->getQuaternions(rotations, vertices.size()); } } }; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index c5bafea124..b7cd122bcb 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -142,6 +142,7 @@ class NiSourceTexture; class NiRotatingParticlesData; class NiAutoNormalParticlesData; +typedef RecordPtrT RecordPtr; typedef RecordPtrT NodePtr; typedef RecordPtrT ExtraPtr; typedef RecordPtrT NiUVDataPtr; From ac10c5f05cd94034d3ee6b4a0ed97dc9518a8fc9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 Apr 2013 01:26:57 -0700 Subject: [PATCH 065/198] Even more particle information --- components/nif/controlled.hpp | 8 +++++--- components/nif/controller.hpp | 29 ++++++++++++++++++++++++----- components/nif/recordptr.hpp | 1 - 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 36c9a82ace..08c47defee 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -66,12 +66,14 @@ typedef Named NiSequenceStreamHelper; class NiParticleGrowFade : public Controlled { public: + float growTime; + float fadeTime; + void read(NIFStream *nif) { Controlled::read(nif); - - // Two floats. - nif->skip(8); + growTime = nif->getFloat(); + fadeTime = nif->getFloat(); } }; diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 2ff25a274b..aa6a9ef4ff 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -65,6 +65,14 @@ public: class NiParticleSystemController : public Controller { public: + struct Particle { + Ogre::Vector3 velocity; + float lifetime; + float lifespan; + float timestamp; + int vertex; + }; + float velocity; float velocityRandom; @@ -88,9 +96,9 @@ public: int numParticles; int activeCount; - //std::vector particles; /*numParticles*/ + std::vector particles; - RecordPtr modifier; + ExtraPtr extra; void read(NIFStream *nif) { @@ -127,10 +135,21 @@ public: numParticles = nif->getUShort(); activeCount = nif->getUShort(); - nif->skip(numParticles*40); + + particles.resize(numParticles); + for(size_t i = 0;i < particles.size();i++) + { + particles[i].velocity = nif->getVector3(); + nif->getVector3(); /* unknown */ + particles[i].lifetime = nif->getFloat(); + particles[i].lifespan = nif->getFloat(); + particles[i].timestamp = nif->getFloat(); + nif->getUShort(); /* unknown */ + particles[i].vertex = nif->getUShort(); + } nif->getUInt(); /* -1? */ - modifier.read(nif); + extra.read(nif); nif->getUInt(); /* -1? */ nif->getChar(); } @@ -139,7 +158,7 @@ public: { Controller::post(nif); emitter.post(nif); - modifier.post(nif); + extra.post(nif); } }; typedef NiParticleSystemController NiBSPArrayController; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index b7cd122bcb..c5bafea124 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -142,7 +142,6 @@ class NiSourceTexture; class NiRotatingParticlesData; class NiAutoNormalParticlesData; -typedef RecordPtrT RecordPtr; typedef RecordPtrT NodePtr; typedef RecordPtrT ExtraPtr; typedef RecordPtrT NiUVDataPtr; From 77ba0fbe730ff6d9e7a20126df177054d183eed2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 Apr 2013 01:31:05 -0700 Subject: [PATCH 066/198] Prepare for creating particles This adds a vector of ParticleSystems to the EntityList, and modifies corresponding code to handle it. It also loads the ParticleFX plugin so particles can be created (although they aren't yet). --- apps/openmw/mwrender/animation.cpp | 3 +++ apps/openmw/mwrender/npcanimation.cpp | 6 +++--- apps/openmw/mwrender/objects.cpp | 13 ++++++++++++- components/nifogre/ogrenifloader.hpp | 4 +++- libs/openengine/ogre/renderer.cpp | 1 + 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index cc926e685d..fd575f9183 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -40,9 +40,12 @@ Animation::~Animation() if(mInsert) { Ogre::SceneManager *sceneMgr = mInsert->getCreator(); + for(size_t i = 0;i < mEntityList.mParticles.size();i++) + sceneMgr->destroyParticleSystem(mEntityList.mParticles[i]); for(size_t i = 0;i < mEntityList.mEntities.size();i++) sceneMgr->destroyEntity(mEntityList.mEntities[i]); } + mEntityList.mParticles.clear(); mEntityList.mEntities.clear(); mEntityList.mSkelBase = NULL; } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index b76a38c469..f1af6a7d3c 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -363,11 +363,11 @@ void NpcAnimation::removeEntities(NifOgre::EntityList &entities) assert(&entities != &mEntityList); Ogre::SceneManager *sceneMgr = mInsert->getCreator(); + for(size_t i = 0;i < entities.mParticles.size();i++) + sceneMgr->destroyParticleSystem(entities.mParticles[i]); for(size_t i = 0;i < entities.mEntities.size();i++) - { - entities.mEntities[i]->detachFromParent(); sceneMgr->destroyEntity(entities.mEntities[i]); - } + entities.mParticles.clear(); entities.mEntities.clear(); entities.mSkelBase = NULL; } diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 50c0210649..8c5d4cad3a 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -156,7 +158,8 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool } } - if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || anyTransparency) + if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || + anyTransparency || entities.mParticles.size() > 0) { for(size_t i = 0;i < entities.mEntities.size();i++) { @@ -169,6 +172,14 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); } + for(size_t i = 0;i < entities.mParticles.size();i++) + { + Ogre::ParticleSystem *part = entities.mParticles[i]; + // TODO: Check the particle system's material for actual transparency + part->setRenderQueueGroup(RQG_Alpha); + part->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); + part->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); + } } else { diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index 92b153468a..e6672541bd 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -40,8 +40,10 @@ namespace NifOgre typedef std::multimap TextKeyMap; static const char sTextKeyExtraDataID[] = "TextKeyExtraData"; struct EntityList { - std::vector mEntities; Ogre::Entity *mSkelBase; + std::vector mEntities; + + std::vector mParticles; EntityList() : mSkelBase(0) { } diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 309ba8a060..05760ffa98 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -195,6 +195,7 @@ void OgreRenderer::configure(const std::string &logPath, Files::loadOgrePlugin(pluginDir, "RenderSystem_GL3Plus", *mRoot); Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mRoot); Files::loadOgrePlugin(pluginDir, "Plugin_CgProgramManager", *mRoot); + Files::loadOgrePlugin(pluginDir, "Plugin_ParticleFX", *mRoot); RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem); if (rs == 0) From b5719e0ec7051d139de32023577c630124842c9f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 Apr 2013 05:08:12 -0700 Subject: [PATCH 067/198] Create particle systems for NiAutoNormalParticles and NiRotatingParticles nodes Very incomplete, but it's something to work with. --- components/nifogre/ogrenifloader.cpp | 171 +++++++++++++++++++++++++-- 1 file changed, 163 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 6083238808..6d08d4ffcc 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include @@ -317,7 +319,9 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */ - node->recType == Nif::RC_NiTriShape /* Handled in the mesh loader */ + node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */ + node->recType == Nif::RC_NiAutoNormalParticles || + node->recType == Nif::RC_NiRotatingParticles )) warn("Unhandled "+node->recName+" "+node->name+" in "+skel->getName()); @@ -326,7 +330,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro { if(ctrl->recType == Nif::RC_NiKeyframeController) ctrls.push_back(static_cast(ctrl.getPtr())); - else + else if(!(ctrl->recType == Nif::RC_NiParticleSystemController + )) warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); ctrl = ctrl->next; } @@ -588,7 +593,8 @@ static std::string findTextureName(const std::string &filename) } public: -static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group, +static Ogre::String getMaterial(const Nif::ShapeData *shapedata, + const Ogre::String &name, const Ogre::String &group, const Nif::NiTexturingProperty *texprop, const Nif::NiMaterialProperty *matprop, const Nif::NiAlphaProperty *alphaprop, @@ -617,7 +623,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String int specFlags = 0; Ogre::String texName[7]; - bool vertexColour = (shape->data->colors.size() != 0); + bool vertexColour = (shapedata->colors.size() != 0); // Texture if(texprop) @@ -819,12 +825,12 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::string mGroup; size_t mShapeIndex; - void warn(const std::string &msg) + static void warn(const std::string &msg) { std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; } - void fail(const std::string &msg) + static void fail(const std::string &msg) { std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; abort(); @@ -1039,9 +1045,10 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } bool needTangents=false; - std::string matname = NIFMaterialLoader::getMaterial(shape, mesh->getName(), mGroup, + std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, texprop, matprop, alphaprop, - vertprop, zprop, specprop, needTangents); + vertprop, zprop, specprop, + needTangents); if(matname.length() > 0) sub->setMaterialName(matname); @@ -1114,6 +1121,146 @@ class NIFMeshLoader : Ogre::ManualResourceLoader static LoaderMap sLoaders; + static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl) + { + Ogre::ParticleEmitter *emitter = partsys->addEmitter("Point"); + emitter->setDirection(Ogre::Vector3::UNIT_Z); + emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom, + partctrl->velocity+partctrl->velocityRandom); + emitter->setEmissionRate(partctrl->emitRate); + emitter->setTimeToLive(partctrl->lifetime-partctrl->lifetimeRandom, + partctrl->lifetime+partctrl->lifetimeRandom); + + Nif::ExtraPtr e = partctrl->extra; + while(!e.empty()) + { + if(e->recType == Nif::RC_NiParticleGrowFade) + { + // TODO: Implement + } + else if(e->recType == Nif::RC_NiParticleColorModifier) + { + // TODO: Implement (Ogre::ColourInterpolatorAffector?) + } + else if(e->recType == Nif::RC_NiGravity) + { + // TODO: Implement (Ogre::LinearForceAffector?) + } + else + warn("Unhandled particle modifier "+e->recName); + e = e->extra; + } + } + + Ogre::ParticleSystem *createParticleSystem(Ogre::SceneManager *sceneMgr, Ogre::Entity *entitybase, + const Nif::Node *partnode) + { + const Nif::NiAutoNormalParticlesData *particledata = NULL; + if(partnode->recType == Nif::RC_NiAutoNormalParticles) + particledata = static_cast(partnode)->data.getPtr(); + else if(partnode->recType == Nif::RC_NiRotatingParticles) + particledata = static_cast(partnode)->data.getPtr(); + + Ogre::ParticleSystem *partsys = sceneMgr->createParticleSystem(); + try { + const Nif::NiTexturingProperty *texprop = NULL; + const Nif::NiMaterialProperty *matprop = NULL; + const Nif::NiAlphaProperty *alphaprop = NULL; + const Nif::NiVertexColorProperty *vertprop = NULL; + const Nif::NiZBufferProperty *zprop = NULL; + const Nif::NiSpecularProperty *specprop = NULL; + if(partnode->parent) + { + // FIXME: We should probably search down the whole tree instead of just the parent + const Nif::PropertyList &proplist = partnode->parent->props; + for(size_t i = 0;i < proplist.length();i++) + { + // Entries may be empty + if(proplist[i].empty()) + continue; + + const Nif::Property *pr = proplist[i].getPtr(); + if(pr->recType == Nif::RC_NiTexturingProperty) + texprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiMaterialProperty) + matprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiAlphaProperty) + alphaprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiVertexColorProperty) + vertprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiZBufferProperty) + zprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiSpecularProperty) + specprop = static_cast(pr); + else + warn("Unhandled property type: "+pr->recName); + } + } + const Nif::PropertyList &proplist = partnode->props; + for(size_t i = 0;i < proplist.length();i++) + { + // Entries may be empty + if(proplist[i].empty()) + continue; + + const Nif::Property *pr = proplist[i].getPtr(); + if(pr->recType == Nif::RC_NiTexturingProperty) + texprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiMaterialProperty) + matprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiAlphaProperty) + alphaprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiVertexColorProperty) + vertprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiZBufferProperty) + zprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiSpecularProperty) + specprop = static_cast(pr); + else + warn("Unhandled property type: "+pr->recName); + } + + std::string fullname = mName+"@index="+Ogre::StringConverter::toString(partnode->recIndex); + if(partnode->name.length() > 0) + fullname += "@type="+partnode->name; + Misc::StringUtils::toLower(fullname); + + bool needTangents; + partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, mGroup, + texprop, matprop, alphaprop, + vertprop, zprop, specprop, + needTangents)); + + partsys->setDefaultDimensions(particledata->particleSize, particledata->particleSize); + partsys->setCullIndividually(false); + partsys->setParticleQuota(particledata->activeCount); + + Nif::ControllerPtr ctrl = partnode->controller; + while(!ctrl.empty()) + { + if(ctrl->recType == Nif::RC_NiParticleSystemController) + { + const Nif::NiParticleSystemController *partctrl = static_cast(ctrl.getPtr()); + + createParticleEmitterAffectors(partsys, partctrl); + if(!partctrl->emitter.empty() && !partsys->isAttached()) + entitybase->attachObjectToBone(partctrl->emitter->name, partsys); + } + ctrl = ctrl->next; + } + + if(!partsys->isAttached()) + entitybase->attachObjectToBone(partnode->name, partsys); + } + catch(std::exception &e) { + std::cerr<< "Particles exception: "<destroyParticleSystem(partsys); + partsys = NULL; + }; + return partsys; + } + + NIFMeshLoader(const std::string &name, const std::string &group) : mName(name), mGroup(group), mShapeIndex(~(size_t)0) { } @@ -1199,6 +1346,14 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } + if((node->recType == Nif::RC_NiAutoNormalParticles || + node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x01)) + { + Ogre::ParticleSystem *partsys = createParticleSystem(sceneMgr, entities.mSkelBase, node); + if(partsys != NULL) + entities.mParticles.push_back(partsys); + } + const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { From 73da794d77c8d2552bf478478f43b54e4c45d028 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 4 Apr 2013 14:34:39 +0200 Subject: [PATCH 068/198] added basic race table --- apps/opencs/model/world/data.cpp | 17 +++++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 1 + components/esm/loadrace.cpp | 21 +++++++++++++++++++++ components/esm/loadrace.hpp | 3 +++ 9 files changed, 64 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d62fd7267b..c596bb162d 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -66,11 +66,17 @@ CSMWorld::Data::Data() for (int i=0; i<6; ++i) mFactions.addColumn (new SkillsColumn (i)); + mRaces.addColumn (new StringIdColumn); + mRaces.addColumn (new RecordStateColumn); + mRaces.addColumn (new NameColumn); + mRaces.addColumn (new DescriptionColumn); + 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); addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); + addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); } CSMWorld::Data::~Data() @@ -129,6 +135,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getFactions() return mFactions; } +const CSMWorld::IdCollection& CSMWorld::Data::getRaces() const +{ + return mRaces; +} + +CSMWorld::IdCollection& CSMWorld::Data::getRaces() +{ + return mRaces; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -168,6 +184,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_SKIL: mSkills.load (reader, base); break; case ESM::REC_CLAS: mClasses.load (reader, base); break; case ESM::REC_FACT: mFactions.load (reader, base); break; + case ESM::REC_RACE: mRaces.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 16a9685a53..6b729728f5 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -26,6 +27,7 @@ namespace CSMWorld IdCollection mSkills; IdCollection mClasses; IdCollection mFactions; + IdCollection mRaces; std::vector mModels; std::map mModelIndex; @@ -62,6 +64,10 @@ namespace CSMWorld IdCollection& getFactions(); + const IdCollection& getRaces() const; + + IdCollection& getRaces(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 985cab0d4c..2e5e6a0a0a 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -22,6 +22,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -33,6 +34,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 0190467c4b..2213e15f31 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -43,7 +43,9 @@ namespace CSMWorld Type_Classes, Type_Class, Type_Factions, - Type_Faction + Type_Faction, + Type_Races, + Type_Race }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 83b333c04e..e12929cf2e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -101,6 +101,10 @@ void CSVDoc::View::setupWorldMenu() QAction *factions = new QAction (tr ("Factions"), this); connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView())); world->addAction (factions); + + QAction *races = new QAction (tr ("Races"), this); + connect (races, SIGNAL (triggered()), this, SLOT (addRacesSubView())); + world->addAction (races); } void CSVDoc::View::setupUi() @@ -271,6 +275,11 @@ void CSVDoc::View::addFactionsSubView() addSubView (CSMWorld::UniversalId::Type_Factions); } +void CSVDoc::View::addRacesSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Races); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 03905430a8..4132d73b20 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -121,6 +121,8 @@ namespace CSVDoc void addClassesSubView(); void addFactionsSubView(); + + void addRacesSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index de36594a58..d5ba273776 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -19,6 +19,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Globals, CSMWorld::UniversalId::Type_Classes, CSMWorld::UniversalId::Type_Factions, + CSMWorld::UniversalId::Type_Races, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index 94aa792bc6..955424e2b9 100644 --- a/components/esm/loadrace.cpp +++ b/components/esm/loadrace.cpp @@ -30,4 +30,25 @@ void Race::save(ESMWriter &esm) esm.writeHNOString("DESC", mDescription); } + void Race::blank() + { + mName.clear(); + mDescription.clear(); + + mPowers.mList.clear(); + + for (int i=0; i<7; ++i) + { + mData.mBonus[i].mSkill = -1; + mData.mBonus[i].mBonus = 0; + } + + for (int i=0; i<8; ++i) + mData.mAttributeValues[i].mMale = mData.mAttributeValues[i].mFemale = 1; + + mData.mHeight.mMale = mData.mHeight.mFemale = 1; + mData.mWeight.mMale = mData.mWeight.mFemale = 1; + + mData.mFlags = 0; + } } diff --git a/components/esm/loadrace.hpp b/components/esm/loadrace.hpp index 845956686c..6ecec8ebb9 100644 --- a/components/esm/loadrace.hpp +++ b/components/esm/loadrace.hpp @@ -66,6 +66,9 @@ struct Race void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } From 48a88f1917d00eccb9c2e490f13f3dc335c240be Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 4 Apr 2013 15:10:27 +0200 Subject: [PATCH 069/198] Fix startRandomTitle --- apps/openmw/mwsound/soundmanagerimp.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 1b07dfe627..69e3016767 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -208,14 +208,21 @@ namespace MWSound void SoundManager::startRandomTitle() { - Ogre::StringVectorPtr filelist; - filelist = mResourceMgr.findResourceNames(Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "Music/"+mCurrentPlaylist+"/*"); - if(!filelist->size()) + Ogre::StringVector filelist; + + Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups (); + for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it) + { + Ogre::StringVectorPtr resourcesInThisGroup = mResourceMgr.findResourceNames(*it, + "Music/"+mCurrentPlaylist+"/*"); + filelist.insert(filelist.end(), resourcesInThisGroup->begin(), resourcesInThisGroup->end()); + } + + if(!filelist.size()) return; - int i = rand()%filelist->size(); - streamMusicFull((*filelist)[i]); + int i = rand()%filelist.size(); + streamMusicFull(filelist[i]); } bool SoundManager::isMusicPlaying() From 2e7d5377f40b257186f21e939e370e298c5b51f9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 4 Apr 2013 16:51:22 +0200 Subject: [PATCH 070/198] Fix crash when moving npcs to an inactive cell --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- .../mwscript/transformationextensions.cpp | 4 ++-- apps/openmw/mwworld/scene.cpp | 14 +++++------ apps/openmw/mwworld/worldimp.cpp | 24 ++++++++++++++----- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 2f49a40316..cd5ab19b9d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -235,7 +235,7 @@ void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store) mObjects.buildStaticGeometry (*store); mDebugging->cellAdded(store); if (store->mCell->isExterior()) - mTerrainManager->cellAdded(store); + mTerrainManager->cellAdded(store); waterAdded(store); } diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 000cc545db..97dc6d7188 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -304,7 +304,7 @@ namespace MWScript } MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); - MWBase::Environment::get().getWorld()->adjustPosition(ptr); + MWWorld::Class::get(ptr).adjustPosition(ptr); } else { @@ -343,7 +343,7 @@ namespace MWScript zRot = zRot/60.; } MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); - MWBase::Environment::get().getWorld()->adjustPosition(ptr); + MWWorld::Class::get(ptr).adjustPosition(ptr); } }; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index c8853f4842..2244a4fc64 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -115,11 +115,6 @@ namespace MWWorld if(result.second) { - /// \todo rescale depending on the state of a new GMST - insertCell (*cell, true); - - mRendering.cellAdded (cell); - float verts = ESM::Land::LAND_SIZE; float worldsize = ESM::Land::REAL_SIZE; @@ -142,6 +137,11 @@ namespace MWWorld } } + /// \todo rescale depending on the state of a new GMST + insertCell (*cell, true); + + mRendering.cellAdded (cell); + mRendering.configureAmbient(*cell); mRendering.requestMap(cell); mRendering.configureAmbient(*cell); @@ -166,7 +166,7 @@ namespace MWWorld float z = Ogre::Radian(pos.rot[2]).valueDegrees(); world->rotateObject(player, x, y, z); - world->adjustPosition(player); + MWWorld::Class::get(player).adjustPosition(player); } MWBase::MechanicsManager *mechMgr = @@ -358,7 +358,7 @@ namespace MWWorld float z = Ogre::Radian(position.rot[2]).valueDegrees(); world->rotateObject(world->getPlayer().getPlayer(), x, y, z); - world->adjustPosition(world->getPlayer().getPlayer()); + MWWorld::Class::get(world->getPlayer().getPlayer()).adjustPosition(world->getPlayer().getPlayer()); return; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 2ce753b816..ae9b7a06b7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -706,6 +706,7 @@ namespace MWWorld void World::moveObject(const Ptr &ptr, CellStore &newCell, float x, float y, float z) { ESM::Position &pos = ptr.getRefData().getPosition(); + pos.pos[0] = x; pos.pos[1] = y; pos.pos[2] = z; @@ -718,7 +719,7 @@ namespace MWWorld if (*currCell != newCell) { - removeContainerScripts(ptr); + removeContainerScripts(ptr); if (isPlayer) { @@ -750,7 +751,7 @@ namespace MWWorld else { MWWorld::Ptr copy = - MWWorld::Class::get(ptr).copyToCell(ptr, newCell); + MWWorld::Class::get(ptr).copyToCell(ptr, newCell, pos); mRendering->updateObjectCell(ptr, copy); @@ -780,12 +781,14 @@ namespace MWWorld bool World::moveObjectImp(const Ptr& ptr, float x, float y, float z) { CellStore *cell = ptr.getCell(); + if (cell->isExterior()) { int cellX, cellY; positionToIndex(x, y, cellX, cellY); cell = getExterior(cellX, cellY); } + moveObject(ptr, *cell, x, y, z); return cell != ptr.getCell(); @@ -827,6 +830,19 @@ namespace MWWorld { Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]); + if(!ptr.getRefData().getBaseNode()) + { + // will be adjusted when Ptr's cell becomes active + return; + } + + float terrainHeight = mRendering->getTerrainHeightAt(pos); + + if (pos.z < terrainHeight) + pos.z = terrainHeight+400; // place slightly above. will snap down to ground with code below + + ptr.getRefData().getPosition().pos[2] = pos.z; + if (!isFlying(ptr)) { Ogre::Vector3 traced = mPhysics->traceDown(ptr); @@ -834,10 +850,6 @@ namespace MWWorld pos.z = traced.z; } - float terrainHeight = mRendering->getTerrainHeightAt(pos); - if (pos.z < terrainHeight) - pos.z = terrainHeight; - moveObject(ptr, pos.x, pos.y, pos.z); } From 076831c9cc5dc0bf9b9bc864eff82a4715856b7b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 5 Apr 2013 12:48:05 +0200 Subject: [PATCH 071/198] added flag columns to race table --- apps/opencs/model/world/columns.hpp | 34 +++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 2 ++ 2 files changed, 36 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index dfabaaf2cf..ad6916ae2b 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -434,6 +434,40 @@ namespace CSMWorld return true; } }; + + template + struct FlagColumn : public Column + { + int mMask; + + FlagColumn (const std::string& name, int mask) + : Column (name, ColumnBase::Display_Boolean), mMask (mask) + {} + + virtual QVariant get (const Record& record) const + { + return (record.get().mData.mFlags & mMask)!=0; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + int flags = record.get().mData.mFlags & ~mMask; + + if (data.toInt()) + flags |= mMask; + + record2.mData.mFlags = flags; + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c596bb162d..18ff5aac1a 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -70,6 +70,8 @@ CSMWorld::Data::Data() mRaces.addColumn (new RecordStateColumn); mRaces.addColumn (new NameColumn); mRaces.addColumn (new DescriptionColumn); + mRaces.addColumn (new FlagColumn ("Playable", 0x1)); + mRaces.addColumn (new FlagColumn ("Beast Race", 0x2)); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From 35fe828108a2ab9b8f71071e3a9e1ec693e39d78 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 5 Apr 2013 13:46:48 +0200 Subject: [PATCH 072/198] added race table weight/height columns --- apps/opencs/model/world/columns.hpp | 40 ++++++++++++++++++++++++++++- apps/opencs/model/world/data.cpp | 4 +++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index ad6916ae2b..f65f212da1 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -453,7 +453,7 @@ namespace CSMWorld { ESXRecordT record2 = record.get(); - int flags = record.get().mData.mFlags & ~mMask; + int flags = record2.mData.mFlags & ~mMask; if (data.toInt()) flags |= mMask; @@ -468,6 +468,44 @@ namespace CSMWorld return true; } }; + + template + struct WeightHeightColumn : public Column + { + bool mMale; + bool mWeight; + + WeightHeightColumn (bool male, bool weight) + : Column (male ? (weight ? "Male Weight" : "Male Height") : + (weight ? "Female Weight" : "Female Height"), ColumnBase::Display_Float), + mMale (male), mWeight (weight) + {} + + virtual QVariant get (const Record& record) const + { + const ESM::Race::MaleFemaleF& value = + mWeight ? record.get().mData.mWeight : record.get().mData.mHeight; + + return mMale ? value.mMale : value.mFemale; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + ESM::Race::MaleFemaleF& value = + mWeight ? record2.mData.mWeight : record2.mData.mHeight; + + (mMale ? value.mMale : value.mFemale) = data.toFloat(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 18ff5aac1a..fb835b986a 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -72,6 +72,10 @@ CSMWorld::Data::Data() mRaces.addColumn (new DescriptionColumn); mRaces.addColumn (new FlagColumn ("Playable", 0x1)); mRaces.addColumn (new FlagColumn ("Beast Race", 0x2)); + mRaces.addColumn (new WeightHeightColumn (true, true)); + mRaces.addColumn (new WeightHeightColumn (true, false)); + mRaces.addColumn (new WeightHeightColumn (false, true)); + mRaces.addColumn (new WeightHeightColumn (false, false)); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From dc9f5f93e74567acf0b3975e7328ba702bbd4003 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 Apr 2013 05:14:24 -0700 Subject: [PATCH 073/198] Use a helper function to get node properties --- components/nifogre/ogrenifloader.cpp | 155 ++++++++++----------------- 1 file changed, 56 insertions(+), 99 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 6d08d4ffcc..4b0f9ce3dc 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -836,15 +836,44 @@ class NIFMeshLoader : Ogre::ManualResourceLoader abort(); } + static void getNodeProperties(const Nif::Node *node, + const Nif::NiTexturingProperty *&texprop, + const Nif::NiMaterialProperty *&matprop, + const Nif::NiAlphaProperty *&alphaprop, + const Nif::NiVertexColorProperty *&vertprop, + const Nif::NiZBufferProperty *&zprop, + const Nif::NiSpecularProperty *&specprop) + { + if(node->parent) + getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop); + + const Nif::PropertyList &proplist = node->props; + for(size_t i = 0;i < proplist.length();i++) + { + // Entries may be empty + if(proplist[i].empty()) + continue; + + const Nif::Property *pr = proplist[i].getPtr(); + if(pr->recType == Nif::RC_NiTexturingProperty) + texprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiMaterialProperty) + matprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiAlphaProperty) + alphaprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiVertexColorProperty) + vertprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiZBufferProperty) + zprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiSpecularProperty) + specprop = static_cast(pr); + else + warn("Unhandled property type: "+pr->recName); + } + } // Convert NiTriShape to Ogre::SubMesh - void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape, - const Nif::NiTexturingProperty *texprop, - const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop, - const Nif::NiSpecularProperty *specprop) + void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -1044,7 +1073,15 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } - bool needTangents=false; + const Nif::NiTexturingProperty *texprop = NULL; + const Nif::NiMaterialProperty *matprop = NULL; + const Nif::NiAlphaProperty *alphaprop = NULL; + const Nif::NiVertexColorProperty *vertprop = NULL; + const Nif::NiZBufferProperty *zprop = NULL; + const Nif::NiSpecularProperty *specprop = NULL; + bool needTangents = false; + + getNodeProperties(shape, texprop, matprop, alphaprop, vertprop, zprop, specprop); std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop, @@ -1061,42 +1098,11 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } - bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node, - const Nif::NiTexturingProperty *texprop, - const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop, - const Nif::NiSpecularProperty *specprop) + bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node) { - // Scan the property list for material information - const Nif::PropertyList &proplist = node->props; - for(size_t i = 0;i < proplist.length();i++) - { - // Entries may be empty - if(proplist[i].empty()) - continue; - - const Nif::Property *pr = proplist[i].getPtr(); - if(pr->recType == Nif::RC_NiTexturingProperty) - texprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiMaterialProperty) - matprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiAlphaProperty) - alphaprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiVertexColorProperty) - vertprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiZBufferProperty) - zprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiSpecularProperty) - specprop = static_cast(pr); - else - warn("Unhandled property type: "+pr->recName); - } - if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) { - handleNiTriShape(mesh, dynamic_cast(node), texprop, matprop, alphaprop, vertprop, zprop, specprop); + handleNiTriShape(mesh, dynamic_cast(node)); return true; } @@ -1108,7 +1114,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { if(!children[i].empty()) { - if(findTriShape(mesh, children[i].getPtr(), texprop, matprop, alphaprop, vertprop, zprop, specprop)) + if(findTriShape(mesh, children[i].getPtr())) return true; } } @@ -1163,69 +1169,20 @@ class NIFMeshLoader : Ogre::ManualResourceLoader Ogre::ParticleSystem *partsys = sceneMgr->createParticleSystem(); try { + std::string fullname = mName+"@index="+Ogre::StringConverter::toString(partnode->recIndex); + if(partnode->name.length() > 0) + fullname += "@type="+partnode->name; + Misc::StringUtils::toLower(fullname); + const Nif::NiTexturingProperty *texprop = NULL; const Nif::NiMaterialProperty *matprop = NULL; const Nif::NiAlphaProperty *alphaprop = NULL; const Nif::NiVertexColorProperty *vertprop = NULL; const Nif::NiZBufferProperty *zprop = NULL; const Nif::NiSpecularProperty *specprop = NULL; - if(partnode->parent) - { - // FIXME: We should probably search down the whole tree instead of just the parent - const Nif::PropertyList &proplist = partnode->parent->props; - for(size_t i = 0;i < proplist.length();i++) - { - // Entries may be empty - if(proplist[i].empty()) - continue; + bool needTangents = false; - const Nif::Property *pr = proplist[i].getPtr(); - if(pr->recType == Nif::RC_NiTexturingProperty) - texprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiMaterialProperty) - matprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiAlphaProperty) - alphaprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiVertexColorProperty) - vertprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiZBufferProperty) - zprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiSpecularProperty) - specprop = static_cast(pr); - else - warn("Unhandled property type: "+pr->recName); - } - } - const Nif::PropertyList &proplist = partnode->props; - for(size_t i = 0;i < proplist.length();i++) - { - // Entries may be empty - if(proplist[i].empty()) - continue; - - const Nif::Property *pr = proplist[i].getPtr(); - if(pr->recType == Nif::RC_NiTexturingProperty) - texprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiMaterialProperty) - matprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiAlphaProperty) - alphaprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiVertexColorProperty) - vertprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiZBufferProperty) - zprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiSpecularProperty) - specprop = static_cast(pr); - else - warn("Unhandled property type: "+pr->recName); - } - - std::string fullname = mName+"@index="+Ogre::StringConverter::toString(partnode->recIndex); - if(partnode->name.length() > 0) - fullname += "@type="+partnode->name; - Misc::StringUtils::toLower(fullname); - - bool needTangents; + getNodeProperties(partnode, texprop, matprop, alphaprop, vertprop, zprop, specprop); partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop, @@ -1280,7 +1237,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } const Nif::Node *node = dynamic_cast(nif->getRecord(0)); - findTriShape(mesh, node, NULL, NULL, NULL, NULL, NULL, NULL); + findTriShape(mesh, node); } void createEntities(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities, int flags=0) From 12fada28622c329b1119b6e5b6d0fae10e207eb7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 Apr 2013 05:34:59 -0700 Subject: [PATCH 074/198] Don't offset the animation time to 0 --- components/nifogre/ogrenifloader.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 4b0f9ce3dc..f663cdf145 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -167,7 +167,7 @@ static void fail(const std::string &msg) static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime) { - Ogre::Animation *anim = skel->createAnimation(name, stopTime-startTime); + Ogre::Animation *anim = skel->createAnimation(name, stopTime); for(size_t i = 0;i < ctrls.size();i++) { @@ -246,7 +246,7 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const } Ogre::TransformKeyFrame *kframe; - kframe = nodetrack->createNodeKeyFrame(curtime-startTime); + kframe = nodetrack->createNodeKeyFrame(curtime); if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin()) kframe->setRotation(curquat); else @@ -441,16 +441,15 @@ void loadResource(Ogre::Resource *resource) buildAnimation(skel, currentgroup, ctrls, targets, keyiter->first, lastkeyiter->first); - TextKeyMap::const_iterator insiter = keyiter; + TextKeyMap::const_iterator insiter(keyiter); TextKeyMap groupkeys; do { sep = insiter->second.find(':'); if(sep == currentgroup.length() && insiter->second.compare(0, sep, currentgroup) == 0) - groupkeys.insert(std::make_pair(insiter->first - keyiter->first, - insiter->second.substr(sep+2))); + groupkeys.insert(std::make_pair(insiter->first, insiter->second.substr(sep+2))); else if((sep == sizeof("soundgen")-1 && insiter->second.compare(0, sep, "soundgen") == 0) || (sep == sizeof("sound")-1 && insiter->second.compare(0, sep, "sound") == 0)) - groupkeys.insert(std::make_pair(insiter->first - keyiter->first, insiter->second)); + groupkeys.insert(std::make_pair(insiter->first, insiter->second)); } while(insiter++ != lastkeyiter); bindings.setUserAny(std::string(sTextKeyExtraDataID)+"@"+currentgroup, Ogre::Any(groupkeys)); From bf0ae3ae72bb5f0d291d037b41f326707f65b21c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 Apr 2013 06:29:14 -0700 Subject: [PATCH 075/198] Read NiVisData info --- components/nif/data.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index a2c9bb56db..c13495ff8b 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -297,13 +297,17 @@ public: float time; char isSet; }; + std::vector mVis; void read(NIFStream *nif) { int count = nif->getInt(); - - /* Skip VisData */ - nif->skip(count*5); + mVis.resize(count); + for(size_t i = 0;i < mVis.size();i++) + { + mVis[i].time = nif->getFloat(); + mVis[i].isSet = nif->getChar(); + } } }; From 48d9885554cdddb7c813035f9d226228f91ac310 Mon Sep 17 00:00:00 2001 From: Glorf Date: Fri, 5 Apr 2013 15:42:05 +0200 Subject: [PATCH 076/198] Started bugfix #691 --- apps/openmw/mwclass/armor.cpp | 87 +++++++++++++++++++++ apps/openmw/mwclass/armor.hpp | 2 + apps/openmw/mwclass/clothing.cpp | 61 +++++++++++++++ apps/openmw/mwclass/clothing.hpp | 2 + apps/openmw/mwclass/weapon.cpp | 66 ++++++++++++++++ apps/openmw/mwclass/weapon.hpp | 2 + apps/openmw/mwmechanics/actors.cpp | 3 +- apps/openmw/mwworld/actionequip.cpp | 104 +------------------------ apps/openmw/mwworld/class.cpp | 5 ++ apps/openmw/mwworld/class.hpp | 3 + apps/openmw/mwworld/inventorystore.cpp | 6 +- apps/openmw/mwworld/inventorystore.hpp | 2 +- 12 files changed, 237 insertions(+), 106 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 320944d3ce..496e695450 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -16,6 +16,8 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/player.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -290,6 +292,91 @@ namespace MWClass ref->mBase = record; } + bool Armor::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + { + MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); + + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = invStore.begin(); + for (; it != invStore.end(); ++it) + { + if (*it == item) + { + break; + } + } + + assert(it != invStore.end()); + + std::string npcRace = npc.get()->mBase->mRace; + + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + + // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); + if(race->mData.mFlags & ESM::Race::Beast) + { + if(*slot == MWWorld::InventoryStore::Slot_Helmet) + { + std::vector parts; + if(it.getType() == MWWorld::ContainerStore::Type_Clothing) + parts = it->get()->mBase->mParts.mParts; + else + parts = it->get()->mBase->mParts.mParts; + + bool allow = true; + for(std::vector::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}"); + + allow = false; + break; + } + } + + if(!allow) + break; + } + + if (*slot == MWWorld::InventoryStore::Slot_Boots) + { + bool allow = true; + std::vector parts; + if(it.getType() == MWWorld::ContainerStore::Type_Clothing) + parts = it->get()->mBase->mParts.mParts; + else + parts = it->get()->mBase->mParts.mParts; + for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) + { + if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) + { + allow = false; + // Only notify the player, not npcs + if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) + { + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}"); + } + break; + } + } + + if(!allow) + return false; + } + + } + } + return true; + } + boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 65f49abb7d..bb07e42b03 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -67,6 +67,8 @@ namespace MWClass virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index abad267675..77a7557bf6 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -14,6 +14,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/player.hpp" #include "../mwgui/tooltips.hpp" @@ -237,6 +238,66 @@ namespace MWClass ref->mBase = record; } + bool Clothing::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + { + MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); + + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = invStore.begin(); + for (; it != invStore.end(); ++it) + { + if (*it == item) + { + break; + } + } + + assert(it != invStore.end()); + + std::string npcRace = npc.get()->mBase->mRace; + + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + + // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); + if(race->mData.mFlags & ESM::Race::Beast) + { + if (*slot == MWWorld::InventoryStore::Slot_Boots) + { + bool allow = true; + std::vector parts; + if(it.getType() == MWWorld::ContainerStore::Type_Clothing) + parts = it->get()->mBase->mParts.mParts; + else + parts = it->get()->mBase->mParts.mParts; + for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) + { + if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) + { + allow = false; + // Only notify the player, not npcs + if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) + { + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}"); + } + break; + } + } + + if(!allow) + return false; + } + + } + } + return true; + } + boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index c3ef22f113..4978fa2288 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -61,6 +61,8 @@ namespace MWClass virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 0a527262f8..51e8130039 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -384,6 +384,72 @@ namespace MWClass ref->mBase = record; } + bool Weapon::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + { + MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); + + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = invStore.begin(); + for (; it != invStore.end(); ++it) + { + if (*it == item) + { + break; + } + } + + assert(it != invStore.end()); + + std::string npcRace = npc.get()->mBase->mRace; + + // equip the item in the first free slot + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) + { + if (it.getType() == MWWorld::ContainerStore::Type_Weapon) + { + if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + it->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + it->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + it->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + it->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + { + //unequip lefthand item + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + } + } + } + if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft) + { + MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + + if (weapon.getType() == MWWorld::ContainerStore::Type_Weapon) + { + if(weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + weapon->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + weapon->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + { + //unequip twohanded item + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + } + } + } + return true; + } + return false; + } + boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 4774bb50be..922cd165f2 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -67,6 +67,8 @@ namespace MWClass virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index f60567c6c4..89671ee086 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -36,8 +36,7 @@ namespace MWMechanics void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) { if (!paused && ptr.getRefData().getHandle()!="player") - MWWorld::Class::get (ptr).getInventoryStore (ptr).autoEquip ( - MWWorld::Class::get (ptr).getNpcStats (ptr)); + MWWorld::Class::get (ptr).getInventoryStore (ptr).autoEquip (ptr); } void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 9a44a99791..c147113fc6 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -43,108 +43,8 @@ namespace MWWorld for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) { - - // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) - const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); - if(race->mData.mFlags & ESM::Race::Beast) - { - if(*slot == MWWorld::InventoryStore::Slot_Helmet) - { - std::vector parts; - if(it.getType() == MWWorld::ContainerStore::Type_Clothing) - parts = it->get()->mBase->mParts.mParts; - else - parts = it->get()->mBase->mParts.mParts; - - bool allow = true; - for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) - { - if((*itr).mPart == ESM::PRT_Head) - { - if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) - MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}"); - - allow = false; - break; - } - } - - if(!allow) - break; - } - - if (*slot == MWWorld::InventoryStore::Slot_Boots) - { - bool allow = true; - std::vector parts; - if(it.getType() == MWWorld::ContainerStore::Type_Clothing) - parts = it->get()->mBase->mParts.mParts; - else - parts = it->get()->mBase->mParts.mParts; - for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) - { - if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) - { - allow = false; - // Only notify the player, not npcs - if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) - { - if(it.getType() == MWWorld::ContainerStore::Type_Clothing){ // It's shoes - MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}"); - } - - else // It's boots - { - MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}"); - } - } - break; - } - } - - if(!allow) - break; - } - - } - - //Disable twohanded when shield equipped, shield when twohanded equipped - if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) - { - if (it.getType() == MWWorld::ContainerStore::Type_Weapon) - { - if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - it->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - it->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - it->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - it->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) - { - //unequip lefthand item - invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); - } - } - } - if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft) - { - ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - - if (weapon.getType() == MWWorld::ContainerStore::Type_Weapon) - { - if(weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - weapon->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - weapon->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) - { - //unequip twohanded item - invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); - } - } - } + if(!MWWorld::Class::get(getTarget()).canEquip(actor,getTarget())) + break; // if all slots are occupied, replace the last slot if (slot == --slots.first.end()) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 2dfa241b3b..ee2072cf09 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -259,6 +259,11 @@ namespace MWWorld throw std::runtime_error ("class can't be enchanted"); } + bool Class::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + { + return true; + } + void Class::adjustPosition(const MWWorld::Ptr& ptr) const { } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index de4741e38b..4931da7a86 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -242,6 +242,9 @@ namespace MWWorld virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + ///< Return 0 if player cannot equip item. Unequip twohanded item if neccesary + virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell) const; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index dd518ff6a4..7a5ae38d0e 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -128,8 +128,9 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot) return mSlots[slot]; } -void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) +void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc) { + const MWMechanics::NpcStats& stats = MWWorld::Class::get(npc).getNpcStats(npc); TSlots slots; initSlots (slots); @@ -183,6 +184,9 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) } } + if(!MWWorld::Class::get (test).canEquip (npc, test)) + continue; + if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { // unstack item pointed to by iterator if required diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index e55eca0ae7..cc28a0a0c0 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -78,7 +78,7 @@ namespace MWWorld ContainerStoreIterator getSlot (int slot); - void autoEquip (const MWMechanics::NpcStats& stats); + void autoEquip (const MWWorld::Ptr& npc); ///< Auto equip items according to stats and item value. const MWMechanics::MagicEffects& getMagicEffects(); From af2a38db3854ecae1c6cdf056ed80b93146fe036 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 Apr 2013 08:27:26 -0700 Subject: [PATCH 077/198] Fix looping anims that dont have "loop start" --- apps/openmw/mwrender/animation.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index fd575f9183..8dbd8d8073 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -307,7 +307,15 @@ void Animation::reset(const std::string &start, const std::string &stop) else { mNextKey = mCurrentKeys->begin(); - mCurrentTime = 0.0f; + while(mNextKey != mCurrentKeys->end() && mNextKey->second != "start") + mNextKey++; + if(mNextKey != mCurrentKeys->end()) + mCurrentTime = mNextKey->first; + else + { + mNextKey = mCurrentKeys->begin(); + mCurrentTime = 0.0f; + } } if(stop.length() > 0) From 75b462b9744f1660af0374bc43c984e796008c24 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 5 Apr 2013 18:23:22 +0200 Subject: [PATCH 078/198] If alpha rejection was forced, we also need to force depth_write and depth_check --- components/nifogre/ogrenifloader.cpp | 1 + files/materials/objects.mat | 2 ++ 2 files changed, 3 insertions(+) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index f8eca821ff..8f9d69f6e2 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -771,6 +771,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String { alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */ alphaTest = result.second; + depthFlags = (1<<0) | (1<<1); // depth_write on, depth_check on } if((alphaFlags&1)) diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 8740c82c34..49df4e3949 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -14,6 +14,7 @@ material openmw_objects_base is_transparent false // real transparency, alpha rejection doesn't count here scene_blend default depth_write default + depth_check default alpha_rejection default transparent_sorting default @@ -38,6 +39,7 @@ material openmw_objects_base scene_blend $scene_blend alpha_rejection $alpha_rejection depth_write $depth_write + depth_check $depth_check transparent_sorting $transparent_sorting texture_unit diffuseMap From 0631b28646c5cfe12360be1356980db93e3ff050 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 Apr 2013 10:13:54 -0700 Subject: [PATCH 079/198] Prepare for supporting controller objects --- apps/openmw/mwrender/animation.cpp | 7 +++++++ apps/openmw/mwrender/animation.hpp | 20 ++++++++++++++++++++ apps/openmw/mwrender/npcanimation.cpp | 1 + components/nifogre/ogrenifloader.hpp | 2 ++ 4 files changed, 30 insertions(+) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 8dbd8d8073..00196c9d47 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -45,6 +45,7 @@ Animation::~Animation() for(size_t i = 0;i < mEntityList.mEntities.size();i++) sceneMgr->destroyEntity(mEntityList.mEntities[i]); } + mEntityList.mControllers.clear(); mEntityList.mParticles.clear(); mEntityList.mEntities.clear(); mEntityList.mSkelBase = NULL; @@ -129,6 +130,10 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); } + + Ogre::SharedPtr > ctrlval(OGRE_NEW AnimationValue(this)); + for(size_t i = 0;i < mEntityList.mControllers.size();i++) + mEntityList.mControllers[i].setSource(ctrlval); } @@ -457,6 +462,8 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) if(!handleEvent(time, evt)) break; } + for(size_t i = 0;i < mEntityList.mControllers.size();i++) + mEntityList.mControllers[i].update(); return movement; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 7caf351694..3e7dee6db2 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -16,6 +16,26 @@ namespace MWRender class Animation { protected: + class AnimationValue : public Ogre::ControllerValue + { + private: + Animation *mAnimation; + + public: + AnimationValue(Animation *anim) : mAnimation(anim) + { } + + virtual Ogre::Real getValue() const + { + return mAnimation->mCurrentTime; + } + + virtual void setValue(Ogre::Real value) + { + mAnimation->mCurrentTime = value; + } + }; + MWWorld::Ptr mPtr; MWMechanics::CharacterController *mController; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index f1af6a7d3c..b7bcad5995 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -367,6 +367,7 @@ void NpcAnimation::removeEntities(NifOgre::EntityList &entities) sceneMgr->destroyParticleSystem(entities.mParticles[i]); for(size_t i = 0;i < entities.mEntities.size();i++) sceneMgr->destroyEntity(entities.mEntities[i]); + entities.mControllers.clear(); entities.mParticles.clear(); entities.mEntities.clear(); entities.mSkelBase = NULL; diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index e6672541bd..819b4d8806 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -45,6 +45,8 @@ struct EntityList { std::vector mParticles; + std::vector > mControllers; + EntityList() : mSkelBase(0) { } }; From aa9df818a52574984406733edb7c916c7183b1c6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 Apr 2013 10:38:27 -0700 Subject: [PATCH 080/198] Add support for NiVisController --- components/nifogre/ogrenifloader.cpp | 103 ++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index f663cdf145..443b207103 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -62,6 +62,83 @@ ostream& operator<<(ostream &o, const NifOgre::TextKeyMap&) namespace NifOgre { + +// FIXME: Should not be here. +class VisController +{ +public: + class Value : public Ogre::ControllerValue + { + private: + Ogre::Bone *mTarget; + + // FIXME: We are not getting all objects here. Skinned meshes get + // attached to the object's root node, and won't be connected via a + // TagPoint. + static void setVisible(Ogre::Node *node, int vis) + { + Ogre::Node::ChildNodeIterator iter = node->getChildIterator(); + while(iter.hasMoreElements()) + { + node = iter.getNext(); + setVisible(node, vis); + + Ogre::TagPoint *tag = dynamic_cast(node); + if(tag != NULL) + { + Ogre::MovableObject *obj = tag->getChildObject(); + if(obj != NULL) + obj->setVisible(vis); + } + } + } + + public: + Value(Ogre::Bone *target) : mTarget(target) + { } + + virtual Ogre::Real getValue() const + { + // Should not be called + return 1.0f; + } + + virtual void setValue(Ogre::Real value) + { + int vis = static_cast(value); + setVisible(mTarget, vis); + } + }; + + class Function : public Ogre::ControllerFunction + { + private: + std::vector mData; + + public: + Function(const Nif::NiVisData *data) + : Ogre::ControllerFunction(false), + mData(data->mVis) + { } + + virtual Ogre::Real calculate(Ogre::Real value) + { + if(mData.size() == 0) + return 1.0f; + + if(mData[0].time >= value) + return mData[0].isSet; + for(size_t i = 1;i < mData.size();i++) + { + if(mData[i].time > value) + return mData[i-1].isSet; + } + return mData.back().isSet; + } + }; +}; + + // Helper class that computes the bounding box and of a mesh class BoundsFinder { @@ -330,7 +407,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro { if(ctrl->recType == Nif::RC_NiKeyframeController) ctrls.push_back(static_cast(ctrl.getPtr())); - else if(!(ctrl->recType == Nif::RC_NiParticleSystemController + else if(!(ctrl->recType == Nif::RC_NiParticleSystemController || + ctrl->recType == Nif::RC_NiVisController )) warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); ctrl = ctrl->next; @@ -1129,7 +1207,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl) { Ogre::ParticleEmitter *emitter = partsys->addEmitter("Point"); - emitter->setDirection(Ogre::Vector3::UNIT_Z); + emitter->setDirection(Ogre::Vector3(0.0f, 0.0f, std::cos(partctrl->verticalDir))); + emitter->setAngle(Ogre::Radian(partctrl->verticalAngle)); emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom, partctrl->velocity+partctrl->velocityRandom); emitter->setEmissionRate(partctrl->emitRate); @@ -1270,6 +1349,26 @@ class NIFMeshLoader : Ogre::ManualResourceLoader e = e->extra; } + Nif::ControllerPtr ctrl = node->controller; + while(!ctrl.empty()) + { + if(ctrl->recType == Nif::RC_NiVisController) + { + const Nif::NiVisController *vis = static_cast(ctrl.getPtr()); + + const Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); + if(!target) target = node; + + Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(target->name); + Ogre::SharedPtr > srcval; /* Filled in later */ + Ogre::SharedPtr > dstval(OGRE_NEW VisController::Value(trgtbone)); + Ogre::SharedPtr > func(OGRE_NEW VisController::Function(vis->data.getPtr())); + + entities.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + } + ctrl = ctrl->next; + } + if(node->recType == Nif::RC_NiTriShape && !(flags&0x01)) // Not hidden { const Nif::NiTriShape *shape = static_cast(node); From b1257620d90904571a49fb75ac2a2080051311ff Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 5 Apr 2013 22:58:21 +0200 Subject: [PATCH 081/198] Some cleanup in build dependencies. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index db0a47d844..35fb3a598b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,16 @@ before_script: - mkdir build - cd build - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 - - cat CMakeCache.txt before_install: - git submodule update --init --recursive - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - - sudo apt-get remove -qq libogre-static-dev - - sudo apt-get install -qq libois-dev libopenal-dev libpng-dev libogre-static-dev libmpg123-dev libsndfile1-dev libblkid-dev libfreeimage-dev libboost-all-dev uuid-dev libqt4-opengl libqt4-dev libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev ffmpeg libbullet-dev libmygui-static-dev libgtest-dev google-mock zziplib-bin libcg libav-tools libois-dev libopenal-dev libxaw7-dev + - sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev + - sudo apt-get install -qq libqt4-dev libxaw7-dev libxrand-dev libfreeimage-dev libpng-dev + - sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev + - sudo apt-get install -qq libcg nvidia-cg-dev + - sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev + - sudo apt-get install -qq libois-dev libbullet-dev libogre-static-dev libmygui-static-dev script: "make -j`grep -c processor /proc/cpuinfo`" branches: only: From 07d5d26b4a2f724553feb8ecacc9fe58ed15d9d2 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 5 Apr 2013 23:02:44 +0200 Subject: [PATCH 082/198] Corrected typo. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 35fb3a598b..b8ebe6275c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev - - sudo apt-get install -qq libqt4-dev libxaw7-dev libxrand-dev libfreeimage-dev libpng-dev + - sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev - sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev - sudo apt-get install -qq libcg nvidia-cg-dev - sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev From d999c0a91c692289b4a3aba805c72ae41e4adf15 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 5 Apr 2013 23:18:10 +0200 Subject: [PATCH 083/198] Enabled addtional Ubuntu repositories. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b8ebe6275c..f383d82721 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ before_script: - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 before_install: - git submodule update --init --recursive + - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse partner" - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev From fb4f50ce8f577081bfdc796c9f6cbc998debcec9 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 5 Apr 2013 23:28:44 +0200 Subject: [PATCH 084/198] Removed 'partner' repository. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f383d82721..61d5fa551c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ before_script: - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 before_install: - git submodule update --init --recursive - - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse partner" + - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" - echo "yes" | sudo apt-add-repository ppa:openmw/deps - sudo apt-get update -qq - sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev From a48d60b5e34ed1d6dcfe6396392ec40120bf5412 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 5 Apr 2013 23:34:23 +0200 Subject: [PATCH 085/198] Changed packet name from nvidia-cg-dev to nvidia-cg-toolkit. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 61d5fa551c..c574572490 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ before_install: - sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev - sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev - sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev - - sudo apt-get install -qq libcg nvidia-cg-dev + - sudo apt-get install -qq libcg nvidia-cg-toolkit - sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev - sudo apt-get install -qq libois-dev libbullet-dev libogre-static-dev libmygui-static-dev script: "make -j`grep -c processor /proc/cpuinfo`" From 99ff89d668b8d51a3f6b46af35a94bc26ef1d256 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 5 Apr 2013 23:41:15 +0200 Subject: [PATCH 086/198] Lowered number of used CPUs for compilation. Enabled building of unit tests. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c574572490..ee26fd5c1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ compiler: before_script: - mkdir build - cd build - - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 + - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 before_install: - git submodule update --init --recursive - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" @@ -16,7 +16,7 @@ before_install: - sudo apt-get install -qq libcg nvidia-cg-toolkit - sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev - sudo apt-get install -qq libois-dev libbullet-dev libogre-static-dev libmygui-static-dev -script: "make -j`grep -c processor /proc/cpuinfo`" +script: "make -j4" branches: only: - master From 6529919102bde1d126121a5669cbb802949162dc Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 6 Apr 2013 00:01:44 +0200 Subject: [PATCH 087/198] Enabled building of Gtest libary. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index ee26fd5c1b..96ce6d7eb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ language: cpp compiler: - - gcc -before_script: - - mkdir build - - cd build - - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 + - gcc before_install: - git submodule update --init --recursive - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" @@ -15,7 +11,17 @@ before_install: - sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev - sudo apt-get install -qq libcg nvidia-cg-toolkit - sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev - - sudo apt-get install -qq libois-dev libbullet-dev libogre-static-dev libmygui-static-dev + - sudo apt-get install -qq libois-dev libbullet-dev libogre-static-dev libmygui-static-dev + - sudo mkdir /usr/src/gtest/build + - cd /usr/src/gtest/build + - sudo cmake .. -DBUILD_SHARED_LIBS=1 + - sudo make -j4 + - sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so + - sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so +before_script: + - mkdir build + - cd build + - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 script: "make -j4" branches: only: From 977da3eeb80d09d3eccc0d0f7cd19308e2e71472 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 6 Apr 2013 00:18:14 +0200 Subject: [PATCH 088/198] Change back directory to the one where OpenMW is downloaded. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 96ce6d7eb2..8df94ca488 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: cpp compiler: - gcc before_install: + - pwd - git submodule update --init --recursive - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" - echo "yes" | sudo apt-add-repository ppa:openmw/deps @@ -19,6 +20,7 @@ before_install: - sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so - sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so before_script: + - cd - - mkdir build - cd build - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 From 86457ce488b233141091b04487d1ed5d89ac4338 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 6 Apr 2013 00:45:04 +0200 Subject: [PATCH 089/198] Enabled running of openmw test suite. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8df94ca488..9ed8b7526c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,10 @@ language: cpp compiler: - gcc +branches: + only: + - master + - travis_ci_test before_install: - pwd - git submodule update --init --recursive @@ -24,11 +28,10 @@ before_script: - mkdir build - cd build - cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -script: "make -j4" -branches: - only: - - master - - travis_ci_test +script: + - make -j4 +after_script: + - openmw_test_suite notifications: recipients: - lgromanowski+travis.ci@gmail.com From 05e7cfeb70c80ebb3fcaa0d9f984366e65988a7f Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 6 Apr 2013 01:04:41 +0200 Subject: [PATCH 090/198] Corrected path to the openmw test suite. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9ed8b7526c..54fff44e2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ compiler: branches: only: - master + - next - travis_ci_test before_install: - pwd @@ -31,7 +32,7 @@ before_script: script: - make -j4 after_script: - - openmw_test_suite + - ./openmw_test_suite notifications: recipients: - lgromanowski+travis.ci@gmail.com From 9ac56ce60e2d03761be32a3e83e947cdfc9f1f4e Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 6 Apr 2013 01:24:38 +0200 Subject: [PATCH 091/198] Removed travis_ci_test branch from checked branches list. Signed-off-by: Lukasz Gromanowski --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 54fff44e2e..374b38ce08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ branches: only: - master - next - - travis_ci_test before_install: - pwd - git submodule update --init --recursive From 81615c1ae5ac4055ffbe8c6239ebdf6b8b7fb029 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 00:18:36 -0700 Subject: [PATCH 092/198] Add a custom GrowFade particle affector --- CMakeLists.txt | 1 + libs/openengine/ogre/particles.cpp | 146 +++++++++++++++++++++++++++++ libs/openengine/ogre/particles.hpp | 17 ++++ libs/openengine/ogre/renderer.cpp | 15 +++ libs/openengine/ogre/renderer.hpp | 2 + 5 files changed, 181 insertions(+) create mode 100644 libs/openengine/ogre/particles.cpp create mode 100644 libs/openengine/ogre/particles.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e1b8e32e5e..b6a1017906 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ set(LIBDIR ${CMAKE_SOURCE_DIR}/libs) set(OENGINE_OGRE ${LIBDIR}/openengine/ogre/renderer.cpp ${LIBDIR}/openengine/ogre/fader.cpp + ${LIBDIR}/openengine/ogre/particles.cpp ${LIBDIR}/openengine/ogre/selectionbuffer.cpp ) set(OENGINE_GUI diff --git a/libs/openengine/ogre/particles.cpp b/libs/openengine/ogre/particles.cpp new file mode 100644 index 0000000000..3453b7f3d7 --- /dev/null +++ b/libs/openengine/ogre/particles.cpp @@ -0,0 +1,146 @@ +#include "particles.hpp" + +#include +#include +#include +#include + +class GrowFadeAffector : public Ogre::ParticleAffector +{ +public: + /** Command object for grow_time (see Ogre::ParamCommand).*/ + class CmdGrowTime : public Ogre::ParamCommand + { + public: + Ogre::String doGet(const void *target) const + { + const GrowFadeAffector *self = static_cast(target); + return Ogre::StringConverter::toString(self->getGrowTime()); + } + void doSet(void *target, const Ogre::String &val) + { + GrowFadeAffector *self = static_cast(target); + self->setGrowTime(Ogre::StringConverter::parseReal(val)); + } + }; + + /** Command object for fade_time (see Ogre::ParamCommand).*/ + class CmdFadeTime : public Ogre::ParamCommand + { + public: + Ogre::String doGet(const void *target) const + { + const GrowFadeAffector *self = static_cast(target); + return Ogre::StringConverter::toString(self->getFadeTime()); + } + void doSet(void *target, const Ogre::String &val) + { + GrowFadeAffector *self = static_cast(target); + self->setFadeTime(Ogre::StringConverter::parseReal(val)); + } + }; + + /** Default constructor. */ + GrowFadeAffector(Ogre::ParticleSystem *psys) : ParticleAffector(psys) + { + mGrowTime = 0.0f; + mFadeTime = 0.0f; + + mType = "GrowFade"; + + // Init parameters + if(createParamDictionary("GrowFadeAffector")) + { + Ogre::ParamDictionary *dict = getParamDictionary(); + + Ogre::String grow_title("grow_time"); + Ogre::String fade_title("fade_time"); + Ogre::String grow_descr("Time from begin to reach full size."); + Ogre::String fade_descr("Time from end to shrink."); + + dict->addParameter(Ogre::ParameterDef(grow_title, grow_descr, Ogre::PT_REAL), &msGrowCmd); + dict->addParameter(Ogre::ParameterDef(fade_title, fade_descr, Ogre::PT_REAL), &msFadeCmd); + } + } + + /** See Ogre::ParticleAffector. */ + void _initParticle(Ogre::Particle *particle) + { + const Ogre::Real life_time = particle->totalTimeToLive; + Ogre::Real particle_time = particle->timeToLive; + + Ogre::Real width = mParent->getDefaultWidth(); + Ogre::Real height = mParent->getDefaultHeight(); + if(life_time-particle_time < mGrowTime) + { + Ogre::Real scale = (life_time-particle_time) / mGrowTime; + width *= scale; + height *= scale; + } + if(particle_time < mFadeTime) + { + Ogre::Real scale = particle_time / mFadeTime; + width *= scale; + height *= scale; + } + particle->setDimensions(width, height); + } + + /** See Ogre::ParticleAffector. */ + void _affectParticles(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed) + { + Ogre::ParticleIterator pi = psys->_getIterator(); + while (!pi.end()) + { + Ogre::Particle *p = pi.getNext(); + const Ogre::Real life_time = p->totalTimeToLive; + Ogre::Real particle_time = p->timeToLive; + + Ogre::Real width = mParent->getDefaultWidth(); + Ogre::Real height = mParent->getDefaultHeight(); + if(life_time-particle_time < mGrowTime) + { + Ogre::Real scale = (life_time-particle_time) / mGrowTime; + width *= scale; + height *= scale; + } + if(particle_time < mFadeTime) + { + Ogre::Real scale = particle_time / mFadeTime; + width *= scale; + height *= scale; + } + p->setDimensions(width, height); + } + } + + void setGrowTime(Ogre::Real time) + { + mGrowTime = time; + } + Ogre::Real getGrowTime() const + { return mGrowTime; } + + void setFadeTime(Ogre::Real time) + { + mFadeTime = time; + } + Ogre::Real getFadeTime() const + { return mFadeTime; } + + static CmdGrowTime msGrowCmd; + static CmdFadeTime msFadeCmd; + +protected: + Ogre::Real mGrowTime; + Ogre::Real mFadeTime; +}; +GrowFadeAffector::CmdGrowTime GrowFadeAffector::msGrowCmd; +GrowFadeAffector::CmdFadeTime GrowFadeAffector::msFadeCmd; + +Ogre::ParticleAffector *GrowFadeAffectorFactory::createAffector(Ogre::ParticleSystem *psys) +{ + Ogre::ParticleAffector *p = new GrowFadeAffector(psys); + mAffectors.push_back(p); + return p; +} diff --git a/libs/openengine/ogre/particles.hpp b/libs/openengine/ogre/particles.hpp new file mode 100644 index 0000000000..d466bb0308 --- /dev/null +++ b/libs/openengine/ogre/particles.hpp @@ -0,0 +1,17 @@ +#ifndef OENGINE_OGRE_PARTICLES_H +#define OENGINE_OGRE_PARTICLES_H + +#include + +/** Factory class for GrowFadeAffector. */ +class GrowFadeAffectorFactory : public Ogre::ParticleAffectorFactory +{ + /** See Ogre::ParticleAffectorFactory */ + Ogre::String getName() const + { return "GrowFade"; } + + /** See Ogre::ParticleAffectorFactory */ + Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys); +}; + +#endif /* OENGINE_OGRE_PARTICLES_H */ diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 05760ffa98..c9e91968f5 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -1,5 +1,6 @@ #include "renderer.hpp" #include "fader.hpp" +#include "particles.hpp" #include "OgreRoot.h" #include "OgreRenderWindow.h" @@ -8,6 +9,8 @@ #include "OgreTextureManager.h" #include "OgreTexture.h" #include "OgreHardwarePixelBuffer.h" +#include +#include "OgreParticleAffectorFactory.h" #include @@ -24,6 +27,7 @@ using namespace Ogre; using namespace OEngine::Render; + #if defined(__APPLE__) && !defined(__LP64__) CustomRoot::CustomRoot(const Ogre::String& pluginFileName, @@ -106,6 +110,11 @@ void OgreRenderer::loadPlugins() void OgreRenderer::unloadPlugins() { + std::vector::iterator ai; + for(ai = mAffectorFactories.begin();ai != mAffectorFactories.end();ai++) + OGRE_DELETE (*ai); + mAffectorFactories.clear(); + #ifdef ENABLE_PLUGIN_GL delete mGLPlugin; mGLPlugin = NULL; @@ -197,6 +206,12 @@ void OgreRenderer::configure(const std::string &logPath, Files::loadOgrePlugin(pluginDir, "Plugin_CgProgramManager", *mRoot); Files::loadOgrePlugin(pluginDir, "Plugin_ParticleFX", *mRoot); + Ogre::ParticleAffectorFactory *affector; + affector = OGRE_NEW GrowFadeAffectorFactory(); + Ogre::ParticleSystemManager::getSingleton().addAffectorFactory(affector); + mAffectorFactories.push_back(affector); + + RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem); if (rs == 0) throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 251dc9c54d..ea46f5ae62 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -40,6 +40,7 @@ namespace Ogre class SceneManager; class Camera; class Viewport; + class ParticleAffectorFactory; } namespace OEngine @@ -94,6 +95,7 @@ namespace OEngine Ogre::D3D9Plugin* mD3D9Plugin; #endif Fader* mFader; + std::vector mAffectorFactories; bool logging; public: From b5017e054309cbd77517d6256fb6ca50b92bf9d7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 00:19:05 -0700 Subject: [PATCH 093/198] Implement NiParticleGrowFade --- components/nifogre/ogrenifloader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 443b207103..4a388bf553 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -1220,7 +1221,10 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { if(e->recType == Nif::RC_NiParticleGrowFade) { - // TODO: Implement + const Nif::NiParticleGrowFade *gf = static_cast(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_NiParticleColorModifier) { From 99b915e652c27bfe1bc0e53e2d5cec9d12796e75 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 00:54:53 -0700 Subject: [PATCH 094/198] Fix some material warnings --- components/nifogre/ogrenifloader.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 54d2c8cf16..215462bac5 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -712,7 +712,7 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, continue; if(texprop->textures[i].texture.empty()) { - warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name+"\n"); + warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name); continue; } @@ -840,10 +840,14 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, instance->setProperty("emissiveMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::GlowTexture].uvSet))); } - for(int i = 1;i < 7;i++) + for(int i = 0;i < 7;i++) { + if(i == Nif::NiTexturingProperty::BaseTexture || + i == Nif::NiTexturingProperty::BumpTexture || + i == Nif::NiTexturingProperty::GlowTexture) + continue; if(!texName[i].empty()) - warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)+"\n"); + warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)); } if (vertexColour) From 1d934e3112423306ac3ae58ffb30412e88274b24 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 04:46:28 -0700 Subject: [PATCH 095/198] Reduce some stdout spam --- apps/openmw/mwmechanics/aiwander.cpp | 2 +- apps/openmw/mwscript/aiextensions.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index e9db6d212a..3cd78a9338 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -13,7 +13,7 @@ MWMechanics::AiPackage * MWMechanics::AiWander::clone() const bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor) { - std::cout << "AiWadner completed.\n"; + // Return completed return true; } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 8402a5b4cd..1ff6fbbf1f 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -196,8 +196,6 @@ namespace MWScript MWMechanics::AiWander wanderPackage(range, duration, time, idleList); MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSequence().stack(wanderPackage); - - std::cout << "AiWander" << std::endl; } }; From 41ce5464c9088e8c79a6c91fdbb741cec1e51bb9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 05:00:19 -0700 Subject: [PATCH 096/198] Recognize NiBSAnimationNode as a record type And don't warn about animated nodes without textkeys --- components/nif/niffile.cpp | 2 +- components/nif/record.hpp | 1 + components/nifogre/ogrenifloader.cpp | 11 ++++------- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index bf05e7576a..f97c506806 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -209,7 +209,7 @@ static const RecordFactoryEntry recordFactories [] = { { "NiNode", &construct , RC_NiNode }, { "AvoidNode", &construct , RC_NiNode }, { "NiBSParticleNode", &construct , RC_NiNode }, - { "NiBSAnimationNode", &construct , RC_NiNode }, + { "NiBSAnimationNode", &construct , RC_NiBSAnimationNode }, { "NiBillboardNode", &construct , RC_NiNode }, { "NiTriShape", &construct , RC_NiTriShape }, { "NiRotatingParticles", &construct , RC_NiRotatingParticles }, diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 3a3cd9b84a..361af3f64c 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -59,6 +59,7 @@ enum RecordType RC_NiMaterialColorController, RC_NiBSPArrayController, RC_NiParticleSystemController, + RC_NiBSAnimationNode, RC_NiLight, RC_NiTextureEffect, RC_NiVertWeightsExtraData, diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 215462bac5..377fa94188 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -464,6 +464,10 @@ void loadResource(Ogre::Resource *resource) return; } + /* Animations without textkeys don't get Ogre::Animation objects. */ + if(!animroot) + return; + std::vector targets; // TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file if(ctrls.size() == 0) // No animations? Then we're done. @@ -486,13 +490,6 @@ void loadResource(Ogre::Resource *resource) return; } - if(!animroot) - { - warn(Ogre::StringConverter::toString(ctrls.size())+" animated node(s) in "+ - skel->getName()+", but no text keys."); - return; - } - Ogre::UserObjectBindings &bindings = animroot->getUserObjectBindings(); bindings.setUserAny(sTextKeyExtraDataID, Ogre::Any(true)); From f764f243d2e42ac5e63a9f44e49deee641a69226 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 06:44:34 -0700 Subject: [PATCH 097/198] Fix the particle quota --- components/nif/data.hpp | 4 +++- components/nifogre/ogrenifloader.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index c13495ff8b..0804b53ae2 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -165,6 +165,8 @@ public: class NiAutoNormalParticlesData : public ShapeData { public: + int numParticles; + float particleSize; int activeCount; @@ -176,7 +178,7 @@ public: ShapeData::read(nif); // Should always match the number of vertices - nif->getUShort(); + numParticles = nif->getUShort(); particleSize = nif->getFloat(); activeCount = nif->getUShort(); diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 377fa94188..cadedbd709 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1274,7 +1274,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader partsys->setDefaultDimensions(particledata->particleSize, particledata->particleSize); partsys->setCullIndividually(false); - partsys->setParticleQuota(particledata->activeCount); + partsys->setParticleQuota(particledata->numParticles); Nif::ControllerPtr ctrl = partnode->controller; while(!ctrl.empty()) From 95730cc127149317583a6051df4eea7b331f3628 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 06:53:08 -0700 Subject: [PATCH 098/198] Create entities and particle systems for hidden objects They're set as (in)visible as appropriate. --- components/nifogre/ogrenifloader.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index cadedbd709..3f20fbab30 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1375,7 +1375,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader ctrl = ctrl->next; } - if(node->recType == Nif::RC_NiTriShape && !(flags&0x01)) // Not hidden + if(node->recType == Nif::RC_NiTriShape) { const Nif::NiTriShape *shape = static_cast(node); @@ -1396,10 +1396,12 @@ class NIFMeshLoader : Ogre::ManualResourceLoader mesh->setAutoBuildEdgeLists(false); } - entities.mEntities.push_back(sceneMgr->createEntity(mesh)); + Ogre::Entity *entity = sceneMgr->createEntity(mesh); + entity->setVisible(!(flags&0x01)); + + entities.mEntities.push_back(entity); if(entities.mSkelBase) { - Ogre::Entity *entity = entities.mEntities.back(); if(entity->hasSkeleton()) entity->shareSkeletonInstanceWith(entities.mSkelBase); else @@ -1407,12 +1409,15 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } - if((node->recType == Nif::RC_NiAutoNormalParticles || - node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x01)) + if(node->recType == Nif::RC_NiAutoNormalParticles || + node->recType == Nif::RC_NiRotatingParticles) { Ogre::ParticleSystem *partsys = createParticleSystem(sceneMgr, entities.mSkelBase, node); if(partsys != NULL) + { + partsys->setVisible(!(flags&0x01)); entities.mParticles.push_back(partsys); + } } const Nif::NiNode *ninode = dynamic_cast(node); From e0da2659729727481f7984983dc59551a27b076d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 08:15:12 -0700 Subject: [PATCH 099/198] Use accurate bone lookups for attaching objects NIFs don't requires nodes to have unique names, which means looking up a bone by name may get the wrong one. Instead, use a NifIndex:BoneHandle map to make sure we can get the proper bone from a given Nif::Node. --- components/nifogre/ogrenifloader.cpp | 36 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 3f20fbab30..06296ddeec 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -380,7 +380,6 @@ static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk) return textkeys; } - void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector &ctrls, Ogre::Bone *parent=NULL) { Ogre::Bone *bone; @@ -389,6 +388,7 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro else bone = skel->createBone(); if(parent) parent->addChild(bone); + mNifToOgreHandleMap[node->recIndex] = bone->getHandle(); bone->setOrientation(node->trafo.rotation); bone->setPosition(node->trafo.pos); @@ -439,6 +439,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro } } +// Lookup to retrieve an Ogre bone handle for a given Nif record index +std::map mNifToOgreHandleMap; typedef std::map LoaderMap; static LoaderMap sLoaders; @@ -569,6 +571,20 @@ static Ogre::SkeletonPtr createSkeleton(const std::string &name, const std::stri return skelMgr.create(name, group, true, &sLoaders[name]); } +// Looks up an Ogre Bone handle ID from a NIF's record index. Should only be +// used when the bone name is insufficient as this is a relatively slow lookup +static int lookupOgreBoneHandle(const std::string &nifname, int idx) +{ + LoaderMap::const_iterator loader = sLoaders.find(nifname); + if(loader != sLoaders.end()) + { + std::map::const_iterator entry = loader->second.mNifToOgreHandleMap.find(idx); + if(entry != loader->second.mNifToOgreHandleMap.end()) + return entry->second; + } + throw std::runtime_error("Invalid NIF record lookup ("+nifname+", index "+Ogre::StringConverter::toString(idx)+")"); +} + }; NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders; @@ -1285,7 +1301,11 @@ class NIFMeshLoader : Ogre::ManualResourceLoader createParticleEmitterAffectors(partsys, partctrl); if(!partctrl->emitter.empty() && !partsys->isAttached()) - entitybase->attachObjectToBone(partctrl->emitter->name, partsys); + { + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, partctrl->emitter->recIndex); + Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid); + entitybase->attachObjectToBone(trgtbone->getName(), partsys); + } } ctrl = ctrl->next; } @@ -1362,10 +1382,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { const Nif::NiVisController *vis = static_cast(ctrl.getPtr()); - const Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); - if(!target) target = node; - - Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(target->name); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); + Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(trgtid); Ogre::SharedPtr > srcval; /* Filled in later */ Ogre::SharedPtr > dstval(OGRE_NEW VisController::Value(trgtbone)); Ogre::SharedPtr > func(OGRE_NEW VisController::Function(vis->data.getPtr())); @@ -1405,7 +1423,11 @@ class NIFMeshLoader : Ogre::ManualResourceLoader if(entity->hasSkeleton()) entity->shareSkeletonInstanceWith(entities.mSkelBase); else - entities.mSkelBase->attachObjectToBone(shape->name, entity); + { + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, shape->recIndex); + Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(trgtid); + entities.mSkelBase->attachObjectToBone(trgtbone->getName(), entity); + } } } From 0fb583e0659847a55d198cc5ecd07594bbc7768d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 17:35:36 +0200 Subject: [PATCH 100/198] added verifier for race record --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/racecheck.cpp | 47 +++++++++++++++++++++++++++ apps/opencs/model/tools/racecheck.hpp | 29 +++++++++++++++++ apps/opencs/model/tools/tools.cpp | 3 ++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/racecheck.cpp create mode 100644 apps/opencs/model/tools/racecheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 07766507f7..0cf72b24c8 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,7 +35,7 @@ opencs_units (model/tools ) opencs_units_noqt (model/tools - stage verifier mandatoryid skillcheck classcheck factioncheck + stage verifier mandatoryid skillcheck classcheck factioncheck racecheck ) diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp new file mode 100644 index 0000000000..50bb08a7c6 --- /dev/null +++ b/apps/opencs/model/tools/racecheck.cpp @@ -0,0 +1,47 @@ + +#include "racecheck.hpp" + +#include + +#include + +#include "../world/universalid.hpp" + +CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection& races) +: mRaces (races) +{} + +int CSMTools::RaceCheckStage::setup() +{ + return mRaces.getSize(); +} + +void CSMTools::RaceCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Race& race = mRaces.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId); + + // test for empty name and description + if (race.mName.empty()) + messages.push_back (id.toString() + "|" + race.mId + " has an empty name"); + + if (race.mDescription.empty()) + messages.push_back (id.toString() + "|" + race.mId + " has an empty description"); + + // test for positive height + if (race.mData.mHeight.mMale<=0) + messages.push_back (id.toString() + "|male " + race.mId + " has non-positive height"); + + if (race.mData.mHeight.mFemale<=0) + messages.push_back (id.toString() + "|female " + race.mId + " has non-positive height"); + + // test for non-negative weight + if (race.mData.mWeight.mMale<0) + messages.push_back (id.toString() + "|male " + race.mId + " has negative weight"); + + if (race.mData.mWeight.mFemale<0) + messages.push_back (id.toString() + "|female " + race.mId + " has negative weight"); + + /// \todo check data members that can't be edited in the table view +} \ No newline at end of file diff --git a/apps/opencs/model/tools/racecheck.hpp b/apps/opencs/model/tools/racecheck.hpp new file mode 100644 index 0000000000..e3f12599ba --- /dev/null +++ b/apps/opencs/model/tools/racecheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_RACECHECK_H +#define CSM_TOOLS_RACECHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that race records are internally consistent + class RaceCheckStage : public Stage + { + const CSMWorld::IdCollection& mRaces; + + public: + + RaceCheckStage (const CSMWorld::IdCollection& races); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index db45de43e5..5fb37514f0 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -15,6 +15,7 @@ #include "skillcheck.hpp" #include "classcheck.hpp" #include "factioncheck.hpp" +#include "racecheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -60,6 +61,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new ClassCheckStage (mData.getClasses())); mVerifier->appendStage (new FactionCheckStage (mData.getFactions())); + + mVerifier->appendStage (new RaceCheckStage (mData.getRaces())); } return mVerifier; From 59f1d4b0476579146f358b827d4ca060f4b0a76f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 09:44:10 -0700 Subject: [PATCH 101/198] Add support for NiUVController on meshes --- apps/openmw/mwrender/animation.cpp | 5 +- components/nifogre/ogrenifloader.cpp | 120 ++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 00196c9d47..2b980320da 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -133,7 +133,10 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model Ogre::SharedPtr > ctrlval(OGRE_NEW AnimationValue(this)); for(size_t i = 0;i < mEntityList.mControllers.size();i++) - mEntityList.mControllers[i].setSource(ctrlval); + { + if(mEntityList.mControllers[i].getSource().isNull()) + mEntityList.mControllers[i].setSource(ctrlval); + } } diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 06296ddeec..1e42fed37f 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -139,6 +140,105 @@ public: }; }; +class UVController +{ +public: + class Value : public Ogre::ControllerValue + { + private: + Ogre::MaterialPtr mMaterial; + Nif::FloatKeyList mUTrans; + Nif::FloatKeyList mVTrans; + Nif::FloatKeyList mUScale; + Nif::FloatKeyList mVScale; + + static float lookupValue(float time, const Nif::FloatKeyList &keys) + { + Nif::FloatKeyList::VecType::const_iterator iter(keys.mKeys.begin()); + for(;iter != keys.mKeys.end();iter++) + { + if(iter->mTime > time) + continue; + Nif::FloatKeyList::VecType::const_iterator next(iter+1); + if(next == keys.mKeys.end()) + return iter->mValue; + float a = (time-iter->mTime) / (next->mTime-iter->mTime); + return iter->mValue + ((next->mValue - iter->mValue)*a); + } + return 0.0f; + } + + public: + Value(const Ogre::MaterialPtr &material, Nif::NiUVData *data) + : mMaterial(material) + , mUTrans(data->mKeyList[0]) + , mVTrans(data->mKeyList[1]) + , mUScale(data->mKeyList[2]) + , mVScale(data->mKeyList[3]) + { } + + virtual Ogre::Real getValue() const + { + // Should not be called + return 1.0f; + } + + virtual void setValue(Ogre::Real value) + { + float uTrans = lookupValue(value, mUTrans); + float vTrans = lookupValue(value, mVTrans); + float uScale = lookupValue(value, mUScale); + float vScale = lookupValue(value, mVScale); + if(uScale == 0.0f) uScale = 1.0f; + if(vScale == 0.0f) vScale = 1.0f; + + Ogre::Material::TechniqueIterator techs = mMaterial->getTechniqueIterator(); + while(techs.hasMoreElements()) + { + Ogre::Technique *tech = techs.getNext(); + Ogre::Technique::PassIterator passes = tech->getPassIterator(); + while(passes.hasMoreElements()) + { + Ogre::Pass *pass = passes.getNext(); + Ogre::TextureUnitState *tex = pass->getTextureUnitState(0); + tex->setTextureScroll(uTrans, vTrans); + tex->setTextureScale(uScale, vScale); + } + } + } + }; + + class Function : public Ogre::ControllerFunction + { + private: + float mFrequency; + float mPhase; + float mStartTime; + float mStopTime; + + public: + Function(const Nif::NiUVController *ctrl) + : Ogre::ControllerFunction(false) + , mFrequency(ctrl->frequency) + , mPhase(ctrl->phase) + , mStartTime(ctrl->timeStart) + , mStopTime(ctrl->timeStop) + { + mDeltaCount = mPhase; + while(mDeltaCount < mStartTime) + mDeltaCount += (mStopTime-mStartTime); + } + + virtual Ogre::Real calculate(Ogre::Real value) + { + mDeltaCount += value; + mDeltaCount = std::fmod(mDeltaCount+(value*mFrequency) - mStartTime, + mStopTime - mStartTime) + mStartTime; + return mDeltaCount; + } + }; +}; + // Helper class that computes the bounding box and of a mesh class BoundsFinder @@ -409,7 +509,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro if(ctrl->recType == Nif::RC_NiKeyframeController) ctrls.push_back(static_cast(ctrl.getPtr())); else if(!(ctrl->recType == Nif::RC_NiParticleSystemController || - ctrl->recType == Nif::RC_NiVisController + ctrl->recType == Nif::RC_NiVisController || + ctrl->recType == Nif::RC_NiUVController )) warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); ctrl = ctrl->next; @@ -1429,6 +1530,23 @@ class NIFMeshLoader : Ogre::ManualResourceLoader entities.mSkelBase->attachObjectToBone(trgtbone->getName(), entity); } } + + Nif::ControllerPtr ctrl = node->controller; + while(!ctrl.empty()) + { + if(ctrl->recType == Nif::RC_NiUVController) + { + const Nif::NiUVController *uv = static_cast(ctrl.getPtr()); + + const Ogre::MaterialPtr &material = entity->getSubEntity(0)->getMaterial(); + Ogre::ControllerValueRealPtr srcval(Ogre::ControllerManager::getSingleton().getFrameTimeSource()); + Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr())); + Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv)); + + entities.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + } + ctrl = ctrl->next; + } } if(node->recType == Nif::RC_NiAutoNormalParticles || From e50b6b1cfe9f3738909e8857b8f67bb7b282ddd4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 09:45:26 -0700 Subject: [PATCH 102/198] Apply texture matrix 0 in the object shader --- files/materials/objects.shader | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index d0e8173733..4868cf98d1 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -36,6 +36,8 @@ SH_BEGIN_PROGRAM shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shUniform(float4x4, textureMatrix0) @shAutoConstant(textureMatrix0, texture_matrix, 0) + #if (VIEWPROJ_FIX) || (SHADOWS) shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) #endif @@ -118,7 +120,7 @@ { shOutputPosition = shMatrixMult(wvp, shInputPosition); - UV.xy = uv0; + UV.xy = shMatrixMult (textureMatrix0, float4(uv0,0,1)).xy; #if SECOND_UV_SET UV.zw = uv1; #endif From ebcb4c66c3adc94217bb912f48789ccde6682668 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 10:17:09 -0700 Subject: [PATCH 103/198] Properly read and use the NIF root record list --- components/nif/niffile.cpp | 18 +++++++++++------- components/nif/niffile.hpp | 14 +++++++++++++- components/nifbullet/bulletnifloader.cpp | 11 +++++------ components/nifogre/ogrenifloader.cpp | 20 ++++++++++---------- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index f97c506806..44eae2953d 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -345,14 +345,18 @@ void NIFFile::parse() } } - /* After the data, the nif contains an int N and then a list of N - ints following it. This might be a list of the root nodes in the - tree, but for the moment we ignore it. - */ + size_t rootNum = nif.getUInt(); + roots.resize(rootNum); - // Once parsing is done, do post-processing. - for(size_t i=0; ipost(this); + for(size_t i = 0;i < rootNum;i++) + { + intptr_t idx = nif.getInt(); + roots[i] = ((idx >= 0) ? records.at(idx) : NULL); + } + + // Once parsing is done, do post-processing. + for(size_t i=0; ipost(this); } /// \todo move to the write cpp file diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index ed11bdd7cb..6e629772e6 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -66,6 +66,9 @@ class NIFFile /// Record list std::vector records; + /// Root list + std::vector roots; + /// Parse the file void parse(); @@ -115,9 +118,18 @@ public: assert(res != NULL); return res; } - /// Number of records size_t numRecords() { return records.size(); } + + /// Get a given root + Record *getRoot(size_t index=0) + { + Record *res = roots.at(index); + assert(res != NULL); + return res; + } + /// Number of roots + size_t numRoots() { return roots.size(); } }; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 08625ee9cb..6bd43f6e35 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -91,21 +91,20 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) // likely a sign of incomplete code rather than faulty input. Nif::NIFFile::ptr pnif (Nif::NIFFile::create (resourceName.substr(0, resourceName.length()-7))); Nif::NIFFile & nif = *pnif.get (); - if (nif.numRecords() < 1) + if (nif.numRoots() < 1) { - warn("Found no records in NIF."); + warn("Found no root nodes in NIF."); return; } - // The first record is assumed to be the root node - Nif::Record *r = nif.getRecord(0); + Nif::Record *r = nif.getRoot(0); assert(r != NULL); Nif::Node *node = dynamic_cast(r); if (node == NULL) { - warn("First record in file was not a node, but a " + - r->recName + ". Skipping file."); + warn("First root in file was not a node, but a " + + r->recName + ". Skipping file."); return; } diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 1e42fed37f..830e85cdef 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -553,7 +553,7 @@ void loadResource(Ogre::Resource *resource) OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); Nif::NIFFile::ptr nif(Nif::NIFFile::create(skel->getName())); - const Nif::Node *node = static_cast(nif->getRecord(0)); + const Nif::Node *node = static_cast(nif->getRoot(0)); std::vector ctrls; Ogre::Bone *animroot = NULL; @@ -1441,7 +1441,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader return; } - const Nif::Node *node = dynamic_cast(nif->getRecord(0)); + const Nif::Node *node = dynamic_cast(nif->getRecord(mShapeIndex)); findTriShape(mesh, node); } @@ -1603,21 +1603,21 @@ public: { Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name); Nif::NIFFile &nif = *pnif.get(); - if(nif.numRecords() < 1) + if(nif.numRoots() < 1) { - nif.warn("Found no NIF records in "+name+"."); + nif.warn("Found no root nodes in "+name+"."); return; } // The first record is assumed to be the root node - const Nif::Record *r = nif.getRecord(0); + const Nif::Record *r = nif.getRoot(0); assert(r != NULL); const Nif::Node *node = dynamic_cast(r); if(node == NULL) { - nif.warn("First record in "+name+" was not a node, but a "+ - r->recName+"."); + nif.warn("First root in "+name+" was not a node, but a "+ + r->recName+"."); return; } @@ -1722,14 +1722,14 @@ Ogre::SkeletonPtr Loader::getSkeleton(std::string name, const std::string &group return skel; Nif::NIFFile::ptr nif = Nif::NIFFile::create(name); - if(nif->numRecords() < 1) + if(nif->numRoots() < 1) { - nif->warn("Found no NIF records in "+name+"."); + nif->warn("Found no root nodes in "+name+"."); return skel; } // The first record is assumed to be the root node - const Nif::Record *r = nif->getRecord(0); + const Nif::Record *r = nif->getRoot(0); assert(r != NULL); const Nif::Node *node = dynamic_cast(r); From 9bc3945f406f3cd252d3a05cf00dc175c7fea17e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 19:20:46 +0200 Subject: [PATCH 104/198] multiple fixes to UniversalId constructor --- apps/opencs/model/world/universalid.cpp | 69 ++++++++++++------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 2e5e6a0a0a..5c7547d71d 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -55,44 +55,41 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId) { std::string type = universalId.substr (0, index); - if (index==std::string::npos) - { - for (int i=0; sNoArg[i].mName; ++i) - if (type==sNoArg[i].mName) - { - mArgumentType = ArgumentType_None; - mType = sNoArg[i].mType; - mClass = sNoArg[i].mClass; + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mName) + { + mArgumentType = ArgumentType_Id; + mType = sIdArg[i].mType; + mClass = sIdArg[i].mClass; + mId = universalId.substr (index+2); + return; + } + + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mName) + { + mArgumentType = ArgumentType_Index; + mType = sIndexArg[i].mType; + mClass = sIndexArg[i].mClass; + + std::istringstream stream (universalId.substr (index+2)); + + if (stream >> mIndex) return; - } - } - else - { - for (int i=0; sIdArg[i].mName; ++i) - if (type==sIdArg[i].mName) - { - mArgumentType = ArgumentType_Id; - mType = sIdArg[i].mType; - mClass = sIdArg[i].mClass; - mId = universalId.substr (0, index); - return; - } - for (int i=0; sIndexArg[i].mName; ++i) - if (type==sIndexArg[i].mName) - { - mArgumentType = ArgumentType_Index; - mType = sIndexArg[i].mType; - mClass = sIndexArg[i].mClass; - - std::istringstream stream (universalId.substr (0, index)); - - if (stream >> mIndex) - return; - - break; - } - } + break; + } + } + else + { + for (int i=0; sNoArg[i].mName; ++i) + if (universalId==sNoArg[i].mName) + { + mArgumentType = ArgumentType_None; + mType = sNoArg[i].mType; + mClass = sNoArg[i].mClass; + return; + } } throw std::runtime_error ("invalid UniversalId: " + universalId); From 98e7b3fd938edbe334de7bfc36aa2d721f6a3b50 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 19:20:59 +0200 Subject: [PATCH 105/198] check for at least one playable race --- apps/opencs/model/tools/racecheck.cpp | 41 ++++++++++++++++++++------- apps/opencs/model/tools/racecheck.hpp | 5 ++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp index 50bb08a7c6..1e7a4cab45 100644 --- a/apps/opencs/model/tools/racecheck.cpp +++ b/apps/opencs/model/tools/racecheck.cpp @@ -7,16 +7,7 @@ #include "../world/universalid.hpp" -CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection& races) -: mRaces (races) -{} - -int CSMTools::RaceCheckStage::setup() -{ - return mRaces.getSize(); -} - -void CSMTools::RaceCheckStage::perform (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector& messages) { const ESM::Race& race = mRaces.getRecord (stage).get(); @@ -43,5 +34,35 @@ void CSMTools::RaceCheckStage::perform (int stage, std::vector& mes if (race.mData.mWeight.mFemale<0) messages.push_back (id.toString() + "|female " + race.mId + " has negative weight"); + // remember playable flag + if (race.mData.mFlags & 0x1) + mPlayable = true; + /// \todo check data members that can't be edited in the table view +} + +void CSMTools::RaceCheckStage::performFinal (std::vector& messages) +{ + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Races); + + if (!mPlayable) + messages.push_back (id.toString() + "|No playable race"); +} + +CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection& races) +: mRaces (races), mPlayable (false) +{} + +int CSMTools::RaceCheckStage::setup() +{ + mPlayable = false; + return mRaces.getSize()+1; +} + +void CSMTools::RaceCheckStage::perform (int stage, std::vector& messages) +{ + if (stage==mRaces.getSize()) + performFinal (messages); + else + performPerRecord (stage, messages); } \ No newline at end of file diff --git a/apps/opencs/model/tools/racecheck.hpp b/apps/opencs/model/tools/racecheck.hpp index e3f12599ba..155f799021 100644 --- a/apps/opencs/model/tools/racecheck.hpp +++ b/apps/opencs/model/tools/racecheck.hpp @@ -13,6 +13,11 @@ namespace CSMTools class RaceCheckStage : public Stage { const CSMWorld::IdCollection& mRaces; + bool mPlayable; + + void performPerRecord (int stage, std::vector& messages); + + void performFinal (std::vector& messages); public: From 1f3df4df0f9ccbdb452ea7e88de4b7f02c417a59 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 6 Apr 2013 19:25:29 +0200 Subject: [PATCH 106/198] Perform a sanity check on count arguments --- apps/openmw/mwscript/miscextensions.cpp | 7 +++++++ apps/openmw/mwscript/transformationextensions.cpp | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index f329e30d90..489f6bd3db 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -399,6 +399,13 @@ namespace MWScript Interpreter::Type_Integer amount = runtime[0].mInteger; runtime.pop(); + if (amount<0) + throw std::runtime_error ("amount must be non-negative"); + + // no-op + if (amount == 0) + return; + MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 97dc6d7188..49688efb5d 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -460,6 +460,13 @@ namespace MWScript Interpreter::Type_Integer direction = runtime[0].mInteger; runtime.pop(); + if (count<0) + throw std::runtime_error ("count must be non-negative"); + + // no-op + if (count == 0) + return; + ESM::Position ipos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition(); Ogre::Vector3 pos(ipos.pos[0],ipos.pos[1],ipos.pos[2]); Ogre::Quaternion rot(Ogre::Radian(-ipos.rot[2]), Ogre::Vector3::UNIT_Z); @@ -503,6 +510,13 @@ namespace MWScript Interpreter::Type_Integer direction = runtime[0].mInteger; runtime.pop(); + if (count<0) + throw std::runtime_error ("count must be non-negative"); + + // no-op + if (count == 0) + return; + ESM::Position ipos = me.getRefData().getPosition(); Ogre::Vector3 pos(ipos.pos[0],ipos.pos[1],ipos.pos[2]); Ogre::Quaternion rot(Ogre::Radian(-ipos.rot[2]), Ogre::Vector3::UNIT_Z); From c28399112637417ddf66a9b65ebec4409227d16e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 10:33:07 -0700 Subject: [PATCH 107/198] Remove an unneeded method --- components/nifogre/ogrenifloader.cpp | 30 +++------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 830e85cdef..5206ef8344 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1070,7 +1070,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } // Convert NiTriShape to Ogre::SubMesh - void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape const *shape) + void createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape) { Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); @@ -1295,30 +1295,6 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } } - bool findTriShape(Ogre::Mesh *mesh, const Nif::Node *node) - { - if(node->recType == Nif::RC_NiTriShape && mShapeIndex == node->recIndex) - { - handleNiTriShape(mesh, dynamic_cast(node)); - return true; - } - - const Nif::NiNode *ninode = dynamic_cast(node); - if(ninode) - { - const Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) - { - if(!children[i].empty()) - { - if(findTriShape(mesh, children[i].getPtr())) - return true; - } - } - } - return false; - } - typedef std::map LoaderMap; static LoaderMap sLoaders; @@ -1441,8 +1417,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader return; } - const Nif::Node *node = dynamic_cast(nif->getRecord(mShapeIndex)); - findTriShape(mesh, node); + const Nif::Record *record = nif->getRecord(mShapeIndex); + createSubMesh(mesh, dynamic_cast(record)); } void createEntities(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities, int flags=0) From 6b151be3f427ea361e03e9830236642b41721aac Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 11:26:51 -0700 Subject: [PATCH 108/198] Create particle systems even when MRK was specified --- components/nifogre/ogrenifloader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 5206ef8344..6a7c3c6dbf 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1444,9 +1444,9 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // affecting the entire subtree of this obj if(sd->string == "MRK") { - // Marker objects. These are only visible in the + // Marker objects. These meshes are only visible in the // editor. - return; + flags |= 0x80000000; } } e = e->extra; @@ -1470,7 +1470,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader ctrl = ctrl->next; } - if(node->recType == Nif::RC_NiTriShape) + if(node->recType == Nif::RC_NiTriShape && !(flags&0x80000000)) { const Nif::NiTriShape *shape = static_cast(node); From 8bf569d58ab00c1ef804b802e3bec5bc358032f0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 21:21:10 +0200 Subject: [PATCH 109/198] added basic sound table --- apps/opencs/model/world/data.cpp | 15 +++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 1 + components/esm/loadsoun.cpp | 8 ++++++++ components/esm/loadsoun.hpp | 3 +++ 9 files changed, 49 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index fb835b986a..b6fb437695 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -77,12 +77,16 @@ CSMWorld::Data::Data() mRaces.addColumn (new WeightHeightColumn (false, true)); mRaces.addColumn (new WeightHeightColumn (false, false)); + mSounds.addColumn (new StringIdColumn); + mSounds.addColumn (new RecordStateColumn); + 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); addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); + addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound); } CSMWorld::Data::~Data() @@ -151,6 +155,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getRaces() return mRaces; } +const CSMWorld::IdCollection& CSMWorld::Data::getSounds() const +{ + return mSounds; +} + +CSMWorld::IdCollection& CSMWorld::Data::getSounds() +{ + return mSounds; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -191,6 +205,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_CLAS: mClasses.load (reader, base); break; case ESM::REC_FACT: mFactions.load (reader, base); break; case ESM::REC_RACE: mRaces.load (reader, base); break; + case ESM::REC_SOUN: mSounds.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 6b729728f5..320480e639 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -28,6 +29,7 @@ namespace CSMWorld IdCollection mClasses; IdCollection mFactions; IdCollection mRaces; + IdCollection mSounds; std::vector mModels; std::map mModelIndex; @@ -68,6 +70,10 @@ namespace CSMWorld IdCollection& getRaces(); + const IdCollection& getSounds() const; + + IdCollection& getSounds(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 5c7547d71d..7bdc15c8c7 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -23,6 +23,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -35,6 +36,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 2213e15f31..a21d67fcd8 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -45,7 +45,9 @@ namespace CSMWorld Type_Factions, Type_Faction, Type_Races, - Type_Race + Type_Race, + Type_Sounds, + Type_Sound }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index e12929cf2e..611690ca65 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -105,6 +105,10 @@ void CSVDoc::View::setupWorldMenu() QAction *races = new QAction (tr ("Races"), this); connect (races, SIGNAL (triggered()), this, SLOT (addRacesSubView())); world->addAction (races); + + QAction *sounds = new QAction (tr ("Sounds"), this); + connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView())); + world->addAction (sounds); } void CSVDoc::View::setupUi() @@ -280,6 +284,11 @@ void CSVDoc::View::addRacesSubView() addSubView (CSMWorld::UniversalId::Type_Races); } +void CSVDoc::View::addSoundsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Sounds); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 4132d73b20..e8e716b706 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -123,6 +123,8 @@ namespace CSVDoc void addFactionsSubView(); void addRacesSubView(); + + void addSoundsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index d5ba273776..3ba950f879 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -20,6 +20,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Classes, CSMWorld::UniversalId::Type_Factions, CSMWorld::UniversalId::Type_Races, + CSMWorld::UniversalId::Type_Sounds, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadsoun.cpp b/components/esm/loadsoun.cpp index 87a08d2d3a..75d4bc8de6 100644 --- a/components/esm/loadsoun.cpp +++ b/components/esm/loadsoun.cpp @@ -23,4 +23,12 @@ void Sound::save(ESMWriter &esm) esm.writeHNT("DATA", mData, 3); } + void Sound::blank() + { + mSound.clear(); + + mData.mVolume = 128; + mData.mMinRange = 0; + mData.mMaxRange = 256; + } } diff --git a/components/esm/loadsoun.hpp b/components/esm/loadsoun.hpp index 8f59f690a1..f8e38ac092 100644 --- a/components/esm/loadsoun.hpp +++ b/components/esm/loadsoun.hpp @@ -21,6 +21,9 @@ struct Sound void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } #endif From ca289a317c579c44b83132cf2bb5b471a8d5b979 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 12:26:58 -0700 Subject: [PATCH 110/198] Separate the UVController function out and make it generic Also fix a timing bug in it. --- components/nifogre/ogrenifloader.cpp | 60 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 6a7c3c6dbf..dfdec0bfa6 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -66,6 +66,36 @@ namespace NifOgre { // FIXME: Should not be here. +class DefaultFunction : public Ogre::ControllerFunction +{ +private: + float mFrequency; + float mPhase; + float mStartTime; + float mStopTime; + +public: + DefaultFunction(const Nif::Controller *ctrl) + : Ogre::ControllerFunction(false) + , mFrequency(ctrl->frequency) + , mPhase(ctrl->phase) + , mStartTime(ctrl->timeStart) + , mStopTime(ctrl->timeStop) + { + mDeltaCount = mPhase; + while(mDeltaCount < mStartTime) + mDeltaCount += (mStopTime-mStartTime); + } + + virtual Ogre::Real calculate(Ogre::Real value) + { + mDeltaCount += value*mFrequency; + mDeltaCount = std::fmod(mDeltaCount - mStartTime, + mStopTime - mStartTime) + mStartTime; + return mDeltaCount; + } +}; + class VisController { public: @@ -208,35 +238,7 @@ public: } }; - class Function : public Ogre::ControllerFunction - { - private: - float mFrequency; - float mPhase; - float mStartTime; - float mStopTime; - - public: - Function(const Nif::NiUVController *ctrl) - : Ogre::ControllerFunction(false) - , mFrequency(ctrl->frequency) - , mPhase(ctrl->phase) - , mStartTime(ctrl->timeStart) - , mStopTime(ctrl->timeStop) - { - mDeltaCount = mPhase; - while(mDeltaCount < mStartTime) - mDeltaCount += (mStopTime-mStartTime); - } - - virtual Ogre::Real calculate(Ogre::Real value) - { - mDeltaCount += value; - mDeltaCount = std::fmod(mDeltaCount+(value*mFrequency) - mStartTime, - mStopTime - mStartTime) + mStartTime; - return mDeltaCount; - } - }; + typedef DefaultFunction Function; }; From dd5940b395a5439aa08cd080a0afb3f585fd99ae Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 21:40:03 +0200 Subject: [PATCH 111/198] added sound parameter columns to sonud table --- apps/opencs/model/world/columns.hpp | 60 +++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 3 ++ 2 files changed, 63 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index f65f212da1..0416287ba0 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -506,6 +506,66 @@ namespace CSMWorld return true; } }; + + template + struct SoundParamColumn : public Column + { + enum Type + { + Type_Volume, + Type_MinRange, + Type_MaxRange + }; + + Type mType; + + SoundParamColumn (Type type) + : Column ( + type==Type_Volume ? "Volume" : (type==Type_MinRange ? "Min Range" : "Max Range"), + ColumnBase::Display_Integer), + mType (type) + {} + + virtual QVariant get (const Record& record) const + { + int value = 0; + + switch (mType) + { + case Type_Volume: value = record.get().mData.mVolume; break; + case Type_MinRange: value = record.get().mData.mMinRange; break; + case Type_MaxRange: value = record.get().mData.mMaxRange; break; + } + + return value; + } + + virtual void set (Record& record, const QVariant& data) + { + int value = data.toInt(); + + if (value<0) + value = 0; + else if (value>255) + value = 255; + + ESXRecordT record2 = record.get(); + + switch (mType) + { + case Type_Volume: record2.mData.mVolume = static_cast (value); break; + case Type_MinRange: record2.mData.mMinRange = static_cast (value); break; + case Type_MaxRange: record2.mData.mMaxRange = static_cast (value); break; + } + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b6fb437695..afa70cdc17 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -79,6 +79,9 @@ CSMWorld::Data::Data() mSounds.addColumn (new StringIdColumn); mSounds.addColumn (new RecordStateColumn); + mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_Volume)); + mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MinRange)); + mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MaxRange)); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From 63cbf7ddeb3a00d89dc43850219bfa7e86dcbd6e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 Apr 2013 12:41:40 -0700 Subject: [PATCH 112/198] Specify a default return for failed lookups --- components/nifogre/ogrenifloader.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index dfdec0bfa6..d89d0d30a5 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -182,7 +182,7 @@ public: Nif::FloatKeyList mUScale; Nif::FloatKeyList mVScale; - static float lookupValue(float time, const Nif::FloatKeyList &keys) + static float lookupValue(const Nif::FloatKeyList &keys, float time, float def) { Nif::FloatKeyList::VecType::const_iterator iter(keys.mKeys.begin()); for(;iter != keys.mKeys.end();iter++) @@ -195,7 +195,7 @@ public: float a = (time-iter->mTime) / (next->mTime-iter->mTime); return iter->mValue + ((next->mValue - iter->mValue)*a); } - return 0.0f; + return def; } public: @@ -215,12 +215,10 @@ public: virtual void setValue(Ogre::Real value) { - float uTrans = lookupValue(value, mUTrans); - float vTrans = lookupValue(value, mVTrans); - float uScale = lookupValue(value, mUScale); - float vScale = lookupValue(value, mVScale); - if(uScale == 0.0f) uScale = 1.0f; - if(vScale == 0.0f) vScale = 1.0f; + float uTrans = lookupValue(mUTrans, value, 0.0f); + float vTrans = lookupValue(mVTrans, value, 0.0f); + float uScale = lookupValue(mUScale, value, 1.0f); + float vScale = lookupValue(mVScale, value, 1.0f); Ogre::Material::TechniqueIterator techs = mMaterial->getTechniqueIterator(); while(techs.hasMoreElements()) From 50b58b2ead2ae4b4db3ad9936f9a781592f55823 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 21:43:05 +0200 Subject: [PATCH 113/198] added sound file column to sound table --- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 26 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 0416287ba0..75dfe15c27 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -566,6 +566,31 @@ namespace CSMWorld return true; } }; + + template + struct SoundFileColumn : public Column + { + SoundFileColumn() : Column ("Sound File", ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mSound.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mSound = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index afa70cdc17..69109bd743 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -82,6 +82,7 @@ CSMWorld::Data::Data() mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_Volume)); mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MinRange)); mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MaxRange)); + mSounds.addColumn (new SoundFileColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From e2c6458adb3509388c178f421d08b73787119619 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 21:48:52 +0200 Subject: [PATCH 114/198] added verifier for sound records --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/soundcheck.cpp | 29 ++++++++++++++++++++++++++ apps/opencs/model/tools/soundcheck.hpp | 29 ++++++++++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 3 +++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/soundcheck.cpp create mode 100644 apps/opencs/model/tools/soundcheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 0cf72b24c8..ffd4c7f1ea 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,7 +35,7 @@ opencs_units (model/tools ) opencs_units_noqt (model/tools - stage verifier mandatoryid skillcheck classcheck factioncheck racecheck + stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck ) diff --git a/apps/opencs/model/tools/soundcheck.cpp b/apps/opencs/model/tools/soundcheck.cpp new file mode 100644 index 0000000000..52834e6594 --- /dev/null +++ b/apps/opencs/model/tools/soundcheck.cpp @@ -0,0 +1,29 @@ + +#include "soundcheck.hpp" + +#include + +#include + +#include "../world/universalid.hpp" + +CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection& sounds) +: mSounds (sounds) +{} + +int CSMTools::SoundCheckStage::setup() +{ + return mSounds.getSize(); +} + +void CSMTools::SoundCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Sound& sound = mSounds.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId); + + if (sound.mData.mMinRange>sound.mData.mMaxRange) + messages.push_back (id.toString() + "|Maximum range larger than minimum range"); + + /// \todo check, if the sound file exists +} \ No newline at end of file diff --git a/apps/opencs/model/tools/soundcheck.hpp b/apps/opencs/model/tools/soundcheck.hpp new file mode 100644 index 0000000000..a309763a12 --- /dev/null +++ b/apps/opencs/model/tools/soundcheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_SOUNDCHECK_H +#define CSM_TOOLS_SOUNDCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that sound records are internally consistent + class SoundCheckStage : public Stage + { + const CSMWorld::IdCollection& mSounds; + + public: + + SoundCheckStage (const CSMWorld::IdCollection& sounds); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 5fb37514f0..4003bc8840 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -16,6 +16,7 @@ #include "classcheck.hpp" #include "factioncheck.hpp" #include "racecheck.hpp" +#include "soundcheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -63,6 +64,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new FactionCheckStage (mData.getFactions())); mVerifier->appendStage (new RaceCheckStage (mData.getRaces())); + + mVerifier->appendStage (new SoundCheckStage (mData.getSounds())); } return mVerifier; From ec7a8f1add42914684290b4e99bbc8d8f054d586 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 6 Apr 2013 21:58:28 +0200 Subject: [PATCH 115/198] small fix --- components/esm/loadsoun.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/loadsoun.cpp b/components/esm/loadsoun.cpp index 75d4bc8de6..07af2b5e91 100644 --- a/components/esm/loadsoun.cpp +++ b/components/esm/loadsoun.cpp @@ -29,6 +29,6 @@ void Sound::save(ESMWriter &esm) mData.mVolume = 128; mData.mMinRange = 0; - mData.mMaxRange = 256; + mData.mMaxRange = 255; } } From 4daaa4030d7434b50a2f835f44329a217e9be357 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 00:12:04 +0200 Subject: [PATCH 116/198] Added shader based MyGUI render manager to allow using Ogre's next generation render systems. --- files/CMakeLists.txt | 3 + files/materials/mygui.mat | 25 ++ files/materials/mygui.shader | 45 +++ files/materials/mygui.shaderset | 15 + libs/openengine/gui/manager.cpp | 537 +++++++++++++++++++++++++++++++- libs/openengine/gui/manager.hpp | 4 +- 6 files changed, 625 insertions(+), 4 deletions(-) create mode 100644 files/materials/mygui.mat create mode 100644 files/materials/mygui.shader create mode 100644 files/materials/mygui.shaderset diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt index 9e65b516b7..9b2325744e 100644 --- a/files/CMakeLists.txt +++ b/files/CMakeLists.txt @@ -44,6 +44,9 @@ set(MATERIAL_FILES watersim_common.h watersim.mat watersim.shaderset + mygui.mat + mygui.shader + mygui.shaderset ) copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}") diff --git a/files/materials/mygui.mat b/files/materials/mygui.mat new file mode 100644 index 0000000000..78cba3f897 --- /dev/null +++ b/files/materials/mygui.mat @@ -0,0 +1,25 @@ +material MyGUI/NoTexture +{ + pass + { + vertex_program mygui_vertex + fragment_program mygui_fragment + shader_properties + { + has_texture false + } + } +} + +material MyGUI/OneTexture +{ + pass + { + vertex_program mygui_vertex + fragment_program mygui_fragment + shader_properties + { + has_texture true + } + } +} diff --git a/files/materials/mygui.shader b/files/materials/mygui.shader new file mode 100644 index 0000000000..014558d972 --- /dev/null +++ b/files/materials/mygui.shader @@ -0,0 +1,45 @@ +#include "core.h" + +#define TEXTURE @shPropertyBool(has_texture) + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM +#if TEXTURE + shVertexInput(float2, uv0) + shOutput(float2, UV) +#endif + shColourInput(float4) + shOutput(float4, colourPassthrough) + + SH_START_PROGRAM + { + shOutputPosition = float4(shInputPosition.xyz, 1.f); +#if TEXTURE + UV.xy = uv0; +#endif + colourPassthrough = colour; + } + +#else + + + SH_BEGIN_PROGRAM + +#if TEXTURE + shSampler2D(diffuseMap) + shInput(float2, UV) +#endif + + shInput(float4, colourPassthrough) + + SH_START_PROGRAM + { +#if TEXTURE + shOutputColour(0) = shSample(diffuseMap, UV.xy) * colourPassthrough; +#else + shOutputColour(0) = colourPassthrough; +#endif + } + +#endif diff --git a/files/materials/mygui.shaderset b/files/materials/mygui.shaderset new file mode 100644 index 0000000000..980cd4caf4 --- /dev/null +++ b/files/materials/mygui.shaderset @@ -0,0 +1,15 @@ +shader_set mygui_vertex +{ + source mygui.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_3_0 vs_2_0 +} + +shader_set mygui_fragment +{ + source mygui.shader + type fragment + profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1 + profiles_hlsl ps_3_0 ps_2_0 +} diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index c9b5614008..f9117586fe 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -2,11 +2,18 @@ #include #include +#include #include +#include +#include + using namespace OEngine::GUI; +namespace MyGUI +{ + /* * As of MyGUI 3.2.0, MyGUI::OgreDataManager::isDataExist is unnecessarily complex * this override fixes the resulting performance issue. @@ -20,6 +27,532 @@ public: } }; + +/* + * As of MyGUI 3.2.0, rendering with shaders is not supported. + * We definitely need this though to run in GL3 core / DX11 at all. + * To make matters worse, subclassing OgreRenderManager doesn't seem to be possible here. :/ + */ +class ShaderBasedRenderManager : public RenderManager, + public IRenderTarget, + public Ogre::WindowEventListener, + public Ogre::RenderQueueListener, + public Ogre::RenderSystem::Listener +{ + // флаг для обновления всех и вся + bool mUpdate; + + IntSize mViewSize; + + Ogre::SceneManager* mSceneManager; + + VertexColourType mVertexFormat; + + // окно, на которое мы подписываемся для изменения размеров + Ogre::RenderWindow* mWindow; + + // вьюпорт, с которым работает система + unsigned short mActiveViewport; + + Ogre::RenderSystem* mRenderSystem; + Ogre::TextureUnitState::UVWAddressingMode mTextureAddressMode; + Ogre::LayerBlendModeEx mColorBlendMode, mAlphaBlendMode; + + RenderTargetInfo mInfo; + + typedef std::map MapTexture; + MapTexture mTextures; + + bool mIsInitialise; + bool mManualRender; + size_t mCountBatch; + + // ADDED + Ogre::GpuProgram* mVertexProgramNoTexture; + Ogre::GpuProgram* mVertexProgramOneTexture; + Ogre::GpuProgram* mFragmentProgramNoTexture; + Ogre::GpuProgram* mFragmentProgramOneTexture; + +public: + ShaderBasedRenderManager& getInstance() + { + return *getInstancePtr(); + } + ShaderBasedRenderManager* getInstancePtr() + { + return static_cast(RenderManager::getInstancePtr()); + } + + ShaderBasedRenderManager() : + mUpdate(false), + mSceneManager(nullptr), + mWindow(nullptr), + mActiveViewport(0), + mRenderSystem(nullptr), + mIsInitialise(false), + mManualRender(false), + mCountBatch(0) + { + } + + void initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene) + { + MYGUI_PLATFORM_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice"); + MYGUI_PLATFORM_LOG(Info, "* Initialise: " << getClassTypeName()); + + mColorBlendMode.blendType = Ogre::LBT_COLOUR; + mColorBlendMode.source1 = Ogre::LBS_TEXTURE; + mColorBlendMode.source2 = Ogre::LBS_DIFFUSE; + mColorBlendMode.operation = Ogre::LBX_MODULATE; + + mAlphaBlendMode.blendType = Ogre::LBT_ALPHA; + mAlphaBlendMode.source1 = Ogre::LBS_TEXTURE; + mAlphaBlendMode.source2 = Ogre::LBS_DIFFUSE; + mAlphaBlendMode.operation = Ogre::LBX_MODULATE; + + mTextureAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP; + mTextureAddressMode.v = Ogre::TextureUnitState::TAM_CLAMP; + mTextureAddressMode.w = Ogre::TextureUnitState::TAM_CLAMP; + + mSceneManager = nullptr; + mWindow = nullptr; + mUpdate = false; + mRenderSystem = nullptr; + mActiveViewport = 0; + + Ogre::Root* root = Ogre::Root::getSingletonPtr(); + if (root != nullptr) + setRenderSystem(root->getRenderSystem()); + setRenderWindow(_window); + setSceneManager(_scene); + + // ADDED + sh::MaterialInstance* mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/NoTexture"); + sh::Factory::getInstance()._ensureMaterial("MyGUI/NoTexture", "Default"); + mVertexProgramNoTexture = static_cast(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0) + ->getVertexProgram()->_getBindingDelegate(); + + mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/OneTexture"); + sh::Factory::getInstance()._ensureMaterial("MyGUI/OneTexture", "Default"); + mVertexProgramOneTexture = static_cast(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0) + ->getVertexProgram()->_getBindingDelegate(); + + mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/NoTexture"); + sh::Factory::getInstance()._ensureMaterial("MyGUI/NoTexture", "Default"); + mFragmentProgramNoTexture = static_cast(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0) + ->getFragmentProgram()->_getBindingDelegate(); + + mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/OneTexture"); + sh::Factory::getInstance()._ensureMaterial("MyGUI/OneTexture", "Default"); + mFragmentProgramOneTexture = static_cast(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0) + ->getFragmentProgram()->_getBindingDelegate(); + + + + MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully initialized"); + mIsInitialise = true; + } + + void shutdown() + { + MYGUI_PLATFORM_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised"); + MYGUI_PLATFORM_LOG(Info, "* Shutdown: " << getClassTypeName()); + + destroyAllResources(); + + setSceneManager(nullptr); + setRenderWindow(nullptr); + setRenderSystem(nullptr); + + MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully shutdown"); + mIsInitialise = false; + } + + void setRenderSystem(Ogre::RenderSystem* _render) + { + // отписываемся + if (mRenderSystem != nullptr) + { + mRenderSystem->removeListener(this); + mRenderSystem = nullptr; + } + + mRenderSystem = _render; + + // подписываемся на рендер евент + if (mRenderSystem != nullptr) + { + mRenderSystem->addListener(this); + + // формат цвета в вершинах + Ogre::VertexElementType vertex_type = mRenderSystem->getColourVertexElementType(); + if (vertex_type == Ogre::VET_COLOUR_ARGB) + mVertexFormat = VertexColourType::ColourARGB; + else if (vertex_type == Ogre::VET_COLOUR_ABGR) + mVertexFormat = VertexColourType::ColourABGR; + + updateRenderInfo(); + } + } + + Ogre::RenderSystem* getRenderSystem() + { + return mRenderSystem; + } + + void setRenderWindow(Ogre::RenderWindow* _window) + { + // отписываемся + if (mWindow != nullptr) + { + Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this); + mWindow = nullptr; + } + + mWindow = _window; + + if (mWindow != nullptr) + { + Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this); + windowResized(mWindow); + } + } + + void setSceneManager(Ogre::SceneManager* _scene) + { + if (nullptr != mSceneManager) + { + mSceneManager->removeRenderQueueListener(this); + mSceneManager = nullptr; + } + + mSceneManager = _scene; + + if (nullptr != mSceneManager) + { + mSceneManager->addRenderQueueListener(this); + } + } + + void setActiveViewport(unsigned short _num) + { + mActiveViewport = _num; + + if (mWindow != nullptr) + { + Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this); + Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this); + + // рассылка обновлений + windowResized(mWindow); + } + } + + void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation) + { + Gui* gui = Gui::getInstancePtr(); + if (gui == nullptr) + return; + + if (Ogre::RENDER_QUEUE_OVERLAY != queueGroupId) + return; + + Ogre::Viewport* viewport = mSceneManager->getCurrentViewport(); + if (nullptr == viewport + || !viewport->getOverlaysEnabled()) + return; + + if (mWindow->getNumViewports() <= mActiveViewport + || viewport != mWindow->getViewport(mActiveViewport)) + return; + + mCountBatch = 0; + + static Timer timer; + static unsigned long last_time = timer.getMilliseconds(); + unsigned long now_time = timer.getMilliseconds(); + unsigned long time = now_time - last_time; + + onFrameEvent((float)((double)(time) / (double)1000)); + + last_time = now_time; + + //begin(); + setManualRender(true); + onRenderToTarget(this, mUpdate); + //end(); + + // сбрасываем флаг + mUpdate = false; + } + + void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation) + { + } + + void eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters) + { + if (eventName == "DeviceLost") + { + } + else if (eventName == "DeviceRestored") + { + // обновить всех + mUpdate = true; + } + } + + IVertexBuffer* createVertexBuffer() + { + return new OgreVertexBuffer(); + } + + void destroyVertexBuffer(IVertexBuffer* _buffer) + { + delete _buffer; + } + + // для оповещений об изменении окна рендера + void windowResized(Ogre::RenderWindow* _window) + { + if (_window->getNumViewports() > mActiveViewport) + { + Ogre::Viewport* port = _window->getViewport(mActiveViewport); +#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0 + Ogre::OrientationMode orient = port->getOrientationMode(); + if (orient == Ogre::OR_DEGREE_90 || orient == Ogre::OR_DEGREE_270) + mViewSize.set(port->getActualHeight(), port->getActualWidth()); + else + mViewSize.set(port->getActualWidth(), port->getActualHeight()); +#else + mViewSize.set(port->getActualWidth(), port->getActualHeight()); +#endif + + // обновить всех + mUpdate = true; + + updateRenderInfo(); + + onResizeView(mViewSize); + } + } + + void updateRenderInfo() + { + if (mRenderSystem != nullptr) + { + mInfo.maximumDepth = mRenderSystem->getMaximumDepthInputValue(); + mInfo.hOffset = mRenderSystem->getHorizontalTexelOffset() / float(mViewSize.width); + mInfo.vOffset = mRenderSystem->getVerticalTexelOffset() / float(mViewSize.height); + mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width); + mInfo.pixScaleX = 1.0f / float(mViewSize.width); + mInfo.pixScaleY = 1.0f / float(mViewSize.height); + } + } + + void doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count) + { + if (getManualRender()) + { + begin(); + setManualRender(false); + } + + // ADDED + + if (_texture) + { + Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mVertexProgramOneTexture); + Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mFragmentProgramOneTexture); + } + else + { + Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mVertexProgramNoTexture); + Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mFragmentProgramNoTexture); + } + + if (_texture) + { + OgreTexture* texture = static_cast(_texture); + Ogre::TexturePtr texture_ptr = texture->getOgreTexture(); + if (!texture_ptr.isNull()) + { + mRenderSystem->_setTexture(0, true, texture_ptr); + mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); + } + } + + OgreVertexBuffer* buffer = static_cast(_buffer); + Ogre::RenderOperation* operation = buffer->getRenderOperation(); + operation->vertexData->vertexCount = _count; + + mRenderSystem->_render(*operation); + + ++ mCountBatch; + } + + void begin() + { + // set-up matrices + mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY); + mRenderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY); + +#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0 + Ogre::OrientationMode orient = mWindow->getViewport(mActiveViewport)->getOrientationMode(); + mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY * Ogre::Quaternion(Ogre::Degree(orient * 90.f), Ogre::Vector3::UNIT_Z)); +#else + mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY); +#endif + + // initialise render settings + mRenderSystem->setLightingEnabled(false); + mRenderSystem->_setDepthBufferParams(false, false); + mRenderSystem->_setDepthBias(0, 0); + mRenderSystem->_setCullingMode(Ogre::CULL_NONE); + mRenderSystem->_setFog(Ogre::FOG_NONE); + mRenderSystem->_setColourBufferWriteEnabled(true, true, true, true); + mRenderSystem->unbindGpuProgram(Ogre::GPT_FRAGMENT_PROGRAM); + mRenderSystem->unbindGpuProgram(Ogre::GPT_VERTEX_PROGRAM); + mRenderSystem->setShadingType(Ogre::SO_GOURAUD); + + // initialise texture settings + mRenderSystem->_setTextureCoordCalculation(0, Ogre::TEXCALC_NONE); + mRenderSystem->_setTextureCoordSet(0, 0); + mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); + mRenderSystem->_setTextureAddressingMode(0, mTextureAddressMode); + mRenderSystem->_setTextureMatrix(0, Ogre::Matrix4::IDENTITY); +#if OGRE_VERSION < MYGUI_DEFINE_VERSION(1, 6, 0) + mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0); +#else + mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0, false); +#endif + mRenderSystem->_setTextureBlendMode(0, mColorBlendMode); + mRenderSystem->_setTextureBlendMode(0, mAlphaBlendMode); + mRenderSystem->_disableTextureUnitsFrom(1); + + // enable alpha blending + mRenderSystem->_setSceneBlending(Ogre::SBF_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA); + + // always use wireframe + // TODO: add option to enable wireframe mode in platform + mRenderSystem->_setPolygonMode(Ogre::PM_SOLID); + } + + void end() + { + } + + ITexture* createTexture(const std::string& _name) + { + MapTexture::const_iterator item = mTextures.find(_name); + MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist"); + + OgreTexture* texture = new OgreTexture(_name, OgreDataManager::getInstance().getGroup()); + mTextures[_name] = texture; + return texture; + } + + void destroyTexture(ITexture* _texture) + { + if (_texture == nullptr) return; + + MapTexture::iterator item = mTextures.find(_texture->getName()); + MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found"); + + mTextures.erase(item); + delete _texture; + } + + ITexture* getTexture(const std::string& _name) + { + MapTexture::const_iterator item = mTextures.find(_name); + if (item == mTextures.end()) + { + Ogre::TexturePtr texture = (Ogre::TexturePtr)Ogre::TextureManager::getSingleton().getByName(_name); + if (!texture.isNull()) + { + ITexture* result = createTexture(_name); + static_cast(result)->setOgreTexture(texture); + return result; + } + return nullptr; + } + return item->second; + } + + bool isFormatSupported(PixelFormat _format, TextureUsage _usage) + { + return Ogre::TextureManager::getSingleton().isFormatSupported( + Ogre::TEX_TYPE_2D, + OgreTexture::convertFormat(_format), + OgreTexture::convertUsage(_usage)); + } + + void destroyAllResources() + { + for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item) + { + delete item->second; + } + mTextures.clear(); + } + +#if MYGUI_DEBUG_MODE == 1 + bool checkTexture(ITexture* _texture) + { + for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item) + { + if (item->second == _texture) + return true; + } + return false; + } +#endif + + const IntSize& getViewSize() const + { + return mViewSize; + } + + VertexColourType getVertexFormat() + { + return mVertexFormat; + } + + const RenderTargetInfo& getInfo() + { + return mInfo; + } + + size_t getActiveViewport() + { + return mActiveViewport; + } + + Ogre::RenderWindow* getRenderWindow() + { + return mWindow; + } + + bool getManualRender() + { + return mManualRender; + } + + void setManualRender(bool _value) + { + mManualRender = _value; + } + + size_t getBatchCount() const + { + return mCountBatch; + } +}; + +} + + void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging, const std::string& logDir) { assert(wnd); @@ -41,8 +574,8 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool // Set up OGRE platform (bypassing OgrePlatform). We might make this more generic later. mLogManager = new LogManager(); - mRenderManager = new OgreRenderManager(); - mDataManager = new FixedOgreDataManager(); + mRenderManager = new MyGUI::ShaderBasedRenderManager(); + mDataManager = new MyGUI::FixedOgreDataManager(); LogManager::getInstance().setSTDOutputEnabled(logging); diff --git a/libs/openengine/gui/manager.hpp b/libs/openengine/gui/manager.hpp index 16673ef980..eec867ff8b 100644 --- a/libs/openengine/gui/manager.hpp +++ b/libs/openengine/gui/manager.hpp @@ -8,7 +8,7 @@ namespace MyGUI class Gui; class LogManager; class OgreDataManager; - class OgreRenderManager; + class ShaderBasedRenderManager; } namespace Ogre @@ -25,7 +25,7 @@ namespace GUI MyGUI::Gui *mGui; MyGUI::LogManager* mLogManager; MyGUI::OgreDataManager* mDataManager; - MyGUI::OgreRenderManager* mRenderManager; + MyGUI::ShaderBasedRenderManager* mRenderManager; Ogre::SceneManager* mSceneMgr; From d97b341dc6de0b640e55e14a5f467c5d75344b38 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 01:02:21 -0700 Subject: [PATCH 117/198] Rename NIFMeshLoader to NIFObjectLoader --- components/nifogre/ogrenifloader.cpp | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index d89d0d30a5..130e940208 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1012,11 +1012,11 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, std::map NIFMaterialLoader::MaterialMap; -/** Manual resource loader for NIF meshes. This is the main class - responsible for translating the internal NIF mesh structure into - something Ogre can use. +/** Manual resource loader for NIF objects (meshes, particle systems, etc). + * This is the main class responsible for translating the internal NIF + * structures into something Ogre can use. */ -class NIFMeshLoader : Ogre::ManualResourceLoader +class NIFObjectLoader : Ogre::ManualResourceLoader { std::string mName; std::string mGroup; @@ -1296,7 +1296,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } - typedef std::map LoaderMap; + typedef std::map LoaderMap; static LoaderMap sLoaders; @@ -1399,7 +1399,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } - NIFMeshLoader(const std::string &name, const std::string &group) + NIFObjectLoader(const std::string &name, const std::string &group) : mName(name), mGroup(group), mShapeIndex(~(size_t)0) { } @@ -1421,13 +1421,13 @@ class NIFMeshLoader : Ogre::ManualResourceLoader createSubMesh(mesh, dynamic_cast(record)); } - void createEntities(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities, int flags=0) + void createObjects(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities, int flags=0) { - // Do not create meshes for the collision shape (includes all children) + // Do not create objects for the collision shape (includes all children) if(node->recType == Nif::RC_RootCollisionNode) return; - // Marker objects: just skip the entire node + // Marker objects: just skip the entire node branch /// \todo don't do this in the editor if (node->name.find("marker") != std::string::npos) return; @@ -1483,7 +1483,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader Ogre::MeshPtr mesh = meshMgr.getByName(fullname); if(mesh.isNull()) { - NIFMeshLoader *loader = &sLoaders[fullname]; + NIFObjectLoader *loader = &sLoaders[fullname]; *loader = *this; loader->mShapeIndex = shape->recIndex; @@ -1543,7 +1543,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - createEntities(sceneMgr, children[i].getPtr(), entities, flags); + createObjects(sceneMgr, children[i].getPtr(), entities, flags); } } } @@ -1561,7 +1561,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader Ogre::MeshPtr mesh = meshMgr.getByName(fullname); if(mesh.isNull()) { - NIFMeshLoader *loader = &sLoaders[fullname]; + NIFObjectLoader *loader = &sLoaders[fullname]; *loader = *this; mesh = meshMgr.createManual(fullname, mGroup, loader); @@ -1572,7 +1572,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } public: - NIFMeshLoader() : mShapeIndex(~(size_t)0) + NIFObjectLoader() : mShapeIndex(~(size_t)0) { } static void load(Ogre::SceneManager *sceneMgr, EntityList &entities, const std::string &name, const std::string &group) @@ -1601,13 +1601,13 @@ public: if(!hasSkel) hasSkel = !NIFSkeletonLoader::createSkeleton(name, group, node).isNull(); - NIFMeshLoader meshldr(name, group); + NIFObjectLoader meshldr(name, group); if(hasSkel) meshldr.createSkelBase(sceneMgr, node, entities); - meshldr.createEntities(sceneMgr, node, entities); + meshldr.createObjects(sceneMgr, node, entities); } }; -NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; +NIFObjectLoader::LoaderMap NIFObjectLoader::sLoaders; EntityList Loader::createEntities(Ogre::SceneNode *parentNode, std::string name, const std::string &group) @@ -1615,7 +1615,7 @@ EntityList Loader::createEntities(Ogre::SceneNode *parentNode, std::string name, EntityList entitylist; Misc::StringUtils::toLower(name); - NIFMeshLoader::load(parentNode->getCreator(), entitylist, name, group); + NIFObjectLoader::load(parentNode->getCreator(), entitylist, name, group); for(size_t i = 0;i < entitylist.mEntities.size();i++) { @@ -1634,7 +1634,7 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen EntityList entitylist; Misc::StringUtils::toLower(name); - NIFMeshLoader::load(parentNode->getCreator(), entitylist, name, group); + NIFObjectLoader::load(parentNode->getCreator(), entitylist, name, group); bool isskinned = false; for(size_t i = 0;i < entitylist.mEntities.size();i++) From 834a6a1f009c2741465a99605f0b1a06661b0c58 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 01:14:26 -0700 Subject: [PATCH 118/198] Remove old, unused code --- components/nifogre/ogrenifloader.cpp | 44 +--------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 130e940208..99c6a65dcf 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1719,46 +1719,4 @@ Ogre::SkeletonPtr Loader::getSkeleton(std::string name, const std::string &group return NIFSkeletonLoader::createSkeleton(name, group, node); } - -/* More code currently not in use, from the old D source. This was - used in the first attempt at loading NIF meshes, where each submesh - in the file was given a separate bone in a skeleton. Unfortunately - the OGRE skeletons can't hold more than 256 bones, and some NIFs go - way beyond that. The code might be of use if we implement animated - submeshes like this (the part of the NIF that is animated is - usually much less than the entire file, but the method might still - not be water tight.) - -// Insert a raw RGBA image into the texture system. -extern "C" void ogre_insertTexture(char* name, uint32_t width, uint32_t height, void *data) -{ - TexturePtr texture = TextureManager::getSingleton().createManual( - name, // name - "General", // group - TEX_TYPE_2D, // type - width, height, // width & height - 0, // number of mipmaps - PF_BYTE_RGBA, // pixel format - TU_DEFAULT); // usage; should be TU_DYNAMIC_WRITE_ONLY_DISCARDABLE for - // textures updated very often (e.g. each frame) - - // Get the pixel buffer - HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer(); - - // Lock the pixel buffer and get a pixel box - pixelBuffer->lock(HardwareBuffer::HBL_NORMAL); // for best performance use HBL_DISCARD! - const PixelBox& pixelBox = pixelBuffer->getCurrentLock(); - - void *dest = pixelBox.data; - - // Copy the data - memcpy(dest, data, width*height*4); - - // Unlock the pixel buffer - pixelBuffer->unlock(); -} - - -*/ - -} // nsmaepace NifOgre +} // namespace NifOgre From 2db72ae607926627e95032f7e7d8f177b7da2478 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 01:52:35 -0700 Subject: [PATCH 119/198] Rename EntityList to ObjectList --- apps/openmw/mwrender/activatoranimation.cpp | 6 +- apps/openmw/mwrender/animation.cpp | 44 ++++++------ apps/openmw/mwrender/animation.hpp | 4 +- apps/openmw/mwrender/creatureanimation.cpp | 6 +- apps/openmw/mwrender/npcanimation.cpp | 54 +++++++-------- apps/openmw/mwrender/npcanimation.hpp | 6 +- apps/openmw/mwrender/objects.cpp | 26 +++---- apps/openmw/mwrender/sky.cpp | 18 ++--- components/nifogre/ogrenifloader.cpp | 76 ++++++++++----------- components/nifogre/ogrenifloader.hpp | 18 ++--- 10 files changed, 129 insertions(+), 129 deletions(-) diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index 961c070038..b1b820915d 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -25,10 +25,10 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) { std::string mesh = "meshes\\" + ref->mBase->mModel; - createEntityList(mPtr.getRefData().getBaseNode(), mesh); - for(size_t i = 0;i < mEntityList.mEntities.size();i++) + createObjectList(mPtr.getRefData().getBaseNode(), mesh); + for(size_t i = 0;i < mObjectList.mEntities.size();i++) { - Ogre::Entity *ent = mEntityList.mEntities[i]; + Ogre::Entity *ent = mObjectList.mEntities[i]; for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) { diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 2b980320da..1d983acfc5 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -40,21 +40,21 @@ Animation::~Animation() if(mInsert) { Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < mEntityList.mParticles.size();i++) - sceneMgr->destroyParticleSystem(mEntityList.mParticles[i]); - for(size_t i = 0;i < mEntityList.mEntities.size();i++) - sceneMgr->destroyEntity(mEntityList.mEntities[i]); + for(size_t i = 0;i < mObjectList.mParticles.size();i++) + sceneMgr->destroyParticleSystem(mObjectList.mParticles[i]); + for(size_t i = 0;i < mObjectList.mEntities.size();i++) + sceneMgr->destroyEntity(mObjectList.mEntities[i]); } - mEntityList.mControllers.clear(); - mEntityList.mParticles.clear(); - mEntityList.mEntities.clear(); - mEntityList.mSkelBase = NULL; + mObjectList.mControllers.clear(); + mObjectList.mParticles.clear(); + mObjectList.mEntities.clear(); + mObjectList.mSkelBase = NULL; } void Animation::setAnimationSources(const std::vector &names) { - if(!mEntityList.mSkelBase) + if(!mObjectList.mSkelBase) return; mCurrentAnim = NULL; @@ -87,7 +87,7 @@ void Animation::setAnimationSources(const std::vector &names) if(!mNonAccumRoot) { mAccumRoot = mInsert; - mNonAccumRoot = mEntityList.mSkelBase->getSkeleton()->getBone(bone->getName()); + mNonAccumRoot = mObjectList.mSkelBase->getSkeleton()->getBone(bone->getName()); } mSkeletonSources.push_back(skel); @@ -105,15 +105,15 @@ void Animation::setAnimationSources(const std::vector &names) } } -void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model) +void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model) { mInsert = node->createChildSceneNode(); assert(mInsert); - mEntityList = NifOgre::Loader::createEntities(mInsert, model); - if(mEntityList.mSkelBase) + mObjectList = NifOgre::Loader::createObjects(mInsert, model); + if(mObjectList.mSkelBase) { - Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateSet *aset = mObjectList.mSkelBase->getAllAnimationStates(); Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); while(asiter.hasMoreElements()) { @@ -125,17 +125,17 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model // Set the bones as manually controlled since we're applying the // transformations manually (needed if we want to apply an animation // from one skeleton onto another). - Ogre::SkeletonInstance *skelinst = mEntityList.mSkelBase->getSkeleton(); + Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton(); Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); } Ogre::SharedPtr > ctrlval(OGRE_NEW AnimationValue(this)); - for(size_t i = 0;i < mEntityList.mControllers.size();i++) + for(size_t i = 0;i < mObjectList.mControllers.size();i++) { - if(mEntityList.mControllers[i].getSource().isNull()) - mEntityList.mControllers[i].setSource(ctrlval); + if(mObjectList.mControllers[i].getSource().isNull()) + mObjectList.mControllers[i].setSource(ctrlval); } } @@ -242,7 +242,7 @@ void Animation::applyAnimation(const Ogre::Animation *anim, float time, Ogre::Sk // HACK: Dirty the animation state set so that Ogre will apply the // transformations to entities this skeleton instance is shared with. - mEntityList.mSkelBase->getAllAnimationStates()->_notifyDirty(); + mObjectList.mSkelBase->getAllAnimationStates()->_notifyDirty(); } static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone) @@ -289,7 +289,7 @@ Ogre::Vector3 Animation::updatePosition(float time) mCurrentTime = std::fmod(std::max(time, 0.0f), mCurrentAnim->getLength()); else mCurrentTime = std::min(mCurrentAnim->getLength(), std::max(time, 0.0f)); - applyAnimation(mCurrentAnim, mCurrentTime, mEntityList.mSkelBase->getSkeleton()); + applyAnimation(mCurrentAnim, mCurrentTime, mObjectList.mSkelBase->getSkeleton()); Ogre::Vector3 posdiff = Ogre::Vector3::ZERO; if(mNonAccumRoot) @@ -465,8 +465,8 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) if(!handleEvent(time, evt)) break; } - for(size_t i = 0;i < mEntityList.mControllers.size();i++) - mEntityList.mControllers[i].update(); + for(size_t i = 0;i < mObjectList.mControllers.size();i++) + mObjectList.mControllers[i].update(); return movement; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 3e7dee6db2..55aaca427c 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -40,7 +40,7 @@ protected: MWMechanics::CharacterController *mController; Ogre::SceneNode* mInsert; - NifOgre::EntityList mEntityList; + NifOgre::ObjectList mObjectList; std::map mTextKeys; Ogre::Node *mAccumRoot; Ogre::Bone *mNonAccumRoot; @@ -91,7 +91,7 @@ protected: setAnimationSources(names); } - void createEntityList(Ogre::SceneNode *node, const std::string &model); + void createObjectList(Ogre::SceneNode *node, const std::string &model); public: Animation(const MWWorld::Ptr &ptr); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 22f84ee018..a8c4afc4e8 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -25,10 +25,10 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) { std::string model = "meshes\\"+ref->mBase->mModel; - createEntityList(mPtr.getRefData().getBaseNode(), model); - for(size_t i = 0;i < mEntityList.mEntities.size();i++) + createObjectList(mPtr.getRefData().getBaseNode(), model); + for(size_t i = 0;i < mObjectList.mEntities.size();i++) { - Ogre::Entity *ent = mEntityList.mEntities[i]; + Ogre::Entity *ent = mObjectList.mEntities[i]; ent->setVisibilityFlags(RV_Actors); for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index b7bcad5995..5d14440e75 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -50,7 +50,7 @@ const NpcAnimation::PartInfo NpcAnimation::sPartList[NpcAnimation::sPartListSize NpcAnimation::~NpcAnimation() { for(size_t i = 0;i < sPartListSize;i++) - removeEntities(mEntityParts[i]); + removeObjects(mObjectParts[i]); } @@ -94,10 +94,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - createEntityList(node, smodel); - for(size_t i = 0;i < mEntityList.mEntities.size();i++) + createObjectList(node, smodel); + for(size_t i = 0;i < mObjectList.mEntities.size();i++) { - Ogre::Entity *base = mEntityList.mEntities[i]; + Ogre::Entity *base = mObjectList.mEntities[i]; base->getUserObjectBindings().setUserAny(Ogre::Any(-1)); if (mVisibilityFlags != 0) @@ -302,11 +302,11 @@ void NpcAnimation::updateParts(bool forceupdate) } } -NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int group, const std::string &bonename) +NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename) { - NifOgre::EntityList entities = NifOgre::Loader::createEntities(mEntityList.mSkelBase, bonename, - mInsert, mesh); - std::vector &parts = entities.mEntities; + NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mObjectList.mSkelBase, bonename, + mInsert, model); + const std::vector &parts = objects.mEntities; for(size_t i = 0;i < parts.size();i++) { parts[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); @@ -319,9 +319,9 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } - if(entities.mSkelBase) + if(objects.mSkelBase) { - Ogre::AnimationStateSet *aset = entities.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateSet *aset = objects.mSkelBase->getAllAnimationStates(); Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); while(asiter.hasMoreElements()) { @@ -329,12 +329,12 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int state->setEnabled(false); state->setLoop(false); } - Ogre::SkeletonInstance *skelinst = entities.mSkelBase->getSkeleton(); + Ogre::SkeletonInstance *skelinst = objects.mSkelBase->getSkeleton(); Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); } - return entities; + return objects; } Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) @@ -347,10 +347,10 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) mTimeToChange -= timepassed; Ogre::Vector3 ret = Animation::runAnimation(timepassed); - const Ogre::SkeletonInstance *skelsrc = mEntityList.mSkelBase->getSkeleton(); + const Ogre::SkeletonInstance *skelsrc = mObjectList.mSkelBase->getSkeleton(); for(size_t i = 0;i < sPartListSize;i++) { - Ogre::Entity *ent = mEntityParts[i].mSkelBase; + Ogre::Entity *ent = mObjectParts[i].mSkelBase; if(!ent) continue; updateSkeletonInstance(skelsrc, ent->getSkeleton()); ent->getAllAnimationStates()->_notifyDirty(); @@ -358,19 +358,19 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) return ret; } -void NpcAnimation::removeEntities(NifOgre::EntityList &entities) +void NpcAnimation::removeObjects(NifOgre::ObjectList &objects) { - assert(&entities != &mEntityList); + assert(&objects != &mObjectList); Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < entities.mParticles.size();i++) - sceneMgr->destroyParticleSystem(entities.mParticles[i]); - for(size_t i = 0;i < entities.mEntities.size();i++) - sceneMgr->destroyEntity(entities.mEntities[i]); - entities.mControllers.clear(); - entities.mParticles.clear(); - entities.mEntities.clear(); - entities.mSkelBase = NULL; + for(size_t i = 0;i < objects.mParticles.size();i++) + sceneMgr->destroyParticleSystem(objects.mParticles[i]); + for(size_t i = 0;i < objects.mEntities.size();i++) + sceneMgr->destroyEntity(objects.mEntities[i]); + objects.mControllers.clear(); + objects.mParticles.clear(); + objects.mEntities.clear(); + objects.mSkelBase = NULL; } void NpcAnimation::removeIndividualPart(int type) @@ -382,7 +382,7 @@ void NpcAnimation::removeIndividualPart(int type) { if(type == sPartList[i].type) { - removeEntities(mEntityParts[i]); + removeObjects(mObjectParts[i]); break; } } @@ -420,7 +420,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, { if(type == sPartList[i].type) { - mEntityParts[i] = insertBoundedPart(mesh, group, sPartList[i].name); + mObjectParts[i] = insertBoundedPart(mesh, group, sPartList[i].name); break; } } @@ -451,7 +451,7 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vectorgetSkeleton()->getBone("Bip01 Head"); + return mObjectList.mSkelBase->getSkeleton()->getBone("Bip01 Head"); } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 5da4afef8a..41c29f7638 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -33,7 +33,7 @@ private: int mStateID; // Bounded Parts - NifOgre::EntityList mEntityParts[sPartListSize]; + NifOgre::ObjectList mObjectParts[sPartListSize]; const ESM::NPC *mNpc; std::string mHeadModel; @@ -60,11 +60,11 @@ private: int mPartslots[sPartListSize]; //Each part slot is taken by clothing, armor, or is empty int mPartPriorities[sPartListSize]; - NifOgre::EntityList insertBoundedPart(const std::string &mesh, int group, const std::string &bonename); + NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename); void updateParts(bool forceupdate = false); - void removeEntities(NifOgre::EntityList &entities); + void removeObjects(NifOgre::ObjectList &objects); void removeIndividualPart(int type); void reserveIndividualPart(int type, int group, int priority); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 8c5d4cad3a..3456e1c16a 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -130,9 +130,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; - NifOgre::EntityList entities = NifOgre::Loader::createEntities(insert, mesh); - for(size_t i = 0;i < entities.mEntities.size();i++) - bounds.merge(entities.mEntities[i]->getWorldBoundingBox(true)); + NifOgre::ObjectList objects = NifOgre::Loader::createObjects(insert, mesh); + for(size_t i = 0;i < objects.mEntities.size();i++) + bounds.merge(objects.mEntities[i]->getWorldBoundingBox(true)); Ogre::Vector3 extents = bounds.getSize(); extents *= insert->getScale(); @@ -149,9 +149,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool mBounds[ptr.getCell()].merge(bounds); bool anyTransparency = false; - for(size_t i = 0;!anyTransparency && i < entities.mEntities.size();i++) + for(size_t i = 0;!anyTransparency && i < objects.mEntities.size();i++) { - Ogre::Entity *ent = entities.mEntities[i]; + Ogre::Entity *ent = objects.mEntities[i]; for(unsigned int i=0;!anyTransparency && i < ent->getNumSubEntities(); ++i) { anyTransparency = ent->getSubEntity(i)->getMaterial()->isTransparent(); @@ -159,11 +159,11 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool } if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || - anyTransparency || entities.mParticles.size() > 0) + anyTransparency || objects.mParticles.size() > 0) { - for(size_t i = 0;i < entities.mEntities.size();i++) + for(size_t i = 0;i < objects.mEntities.size();i++) { - Ogre::Entity *ent = entities.mEntities[i]; + Ogre::Entity *ent = objects.mEntities[i]; for(unsigned int i=0; i < ent->getNumSubEntities(); ++i) { Ogre::SubEntity* subEnt = ent->getSubEntity(i); @@ -172,9 +172,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); } - for(size_t i = 0;i < entities.mParticles.size();i++) + for(size_t i = 0;i < objects.mParticles.size();i++) { - Ogre::ParticleSystem *part = entities.mParticles[i]; + Ogre::ParticleSystem *part = objects.mParticles[i]; // TODO: Check the particle system's material for actual transparency part->setRenderQueueGroup(RQG_Alpha); part->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); @@ -225,8 +225,8 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool sg->setRenderQueueGroup(RQG_Main); - std::vector::reverse_iterator iter = entities.mEntities.rbegin(); - while(iter != entities.mEntities.rend()) + std::vector::reverse_iterator iter = objects.mEntities.rbegin(); + while(iter != objects.mEntities.rend()) { Ogre::Node *node = (*iter)->getParentNode(); sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale()); @@ -239,7 +239,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool if (light) { - insertLight(ptr, entities.mSkelBase, bounds.getCenter() - insert->_getDerivedPosition()); + insertLight(ptr, objects.mSkelBase, bounds.getCenter() - insert->_getDerivedPosition()); } } diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 94af3521b3..7f3abce701 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -288,10 +288,10 @@ void SkyManager::create() // Stars mAtmosphereNight = mRootNode->createChildSceneNode(); - NifOgre::EntityList entities = NifOgre::Loader::createEntities(mAtmosphereNight, "meshes\\sky_night_01.nif"); - for(size_t i = 0, matidx = 0;i < entities.mEntities.size();i++) + NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_01.nif"); + for(size_t i = 0, matidx = 0;i < objects.mEntities.size();i++) { - Entity* night1_ent = entities.mEntities[i]; + Entity* night1_ent = objects.mEntities[i]; night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); night1_ent->setVisibilityFlags(RV_Sky); night1_ent->setCastShadows(false); @@ -314,10 +314,10 @@ void SkyManager::create() // Atmosphere (day) mAtmosphereDay = mRootNode->createChildSceneNode(); - entities = NifOgre::Loader::createEntities(mAtmosphereDay, "meshes\\sky_atmosphere.nif"); - for(size_t i = 0;i < entities.mEntities.size();i++) + objects = NifOgre::Loader::createObjects(mAtmosphereDay, "meshes\\sky_atmosphere.nif"); + for(size_t i = 0;i < objects.mEntities.size();i++) { - Entity* atmosphere_ent = entities.mEntities[i]; + Entity* atmosphere_ent = objects.mEntities[i]; atmosphere_ent->setCastShadows(false); atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly); atmosphere_ent->setVisibilityFlags(RV_Sky); @@ -332,10 +332,10 @@ void SkyManager::create() // Clouds SceneNode* clouds_node = mRootNode->createChildSceneNode(); - entities = NifOgre::Loader::createEntities(clouds_node, "meshes\\sky_clouds_01.nif"); - for(size_t i = 0;i < entities.mEntities.size();i++) + objects = NifOgre::Loader::createObjects(clouds_node, "meshes\\sky_clouds_01.nif"); + for(size_t i = 0;i < objects.mEntities.size();i++) { - Entity* clouds_ent = entities.mEntities[i]; + Entity* clouds_ent = objects.mEntities[i]; clouds_ent->setVisibilityFlags(RV_Sky); clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); for(unsigned int j = 0;j < clouds_ent->getNumSubEntities();j++) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 99c6a65dcf..e7d1a88d1c 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1421,7 +1421,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader createSubMesh(mesh, dynamic_cast(record)); } - void createObjects(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities, int flags=0) + void createObjects(Ogre::SceneManager *sceneMgr, const Nif::Node *node, ObjectList &objectlist, int flags=0) { // Do not create objects for the collision shape (includes all children) if(node->recType == Nif::RC_RootCollisionNode) @@ -1460,12 +1460,12 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Nif::NiVisController *vis = static_cast(ctrl.getPtr()); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); - Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(trgtid); + Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); Ogre::SharedPtr > srcval; /* Filled in later */ Ogre::SharedPtr > dstval(OGRE_NEW VisController::Value(trgtbone)); Ogre::SharedPtr > func(OGRE_NEW VisController::Function(vis->data.getPtr())); - entities.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); } ctrl = ctrl->next; } @@ -1494,16 +1494,16 @@ class NIFObjectLoader : Ogre::ManualResourceLoader Ogre::Entity *entity = sceneMgr->createEntity(mesh); entity->setVisible(!(flags&0x01)); - entities.mEntities.push_back(entity); - if(entities.mSkelBase) + objectlist.mEntities.push_back(entity); + if(objectlist.mSkelBase) { if(entity->hasSkeleton()) - entity->shareSkeletonInstanceWith(entities.mSkelBase); + entity->shareSkeletonInstanceWith(objectlist.mSkelBase); else { int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, shape->recIndex); - Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(trgtid); - entities.mSkelBase->attachObjectToBone(trgtbone->getName(), entity); + Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); + objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), entity); } } @@ -1519,7 +1519,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr())); Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv)); - entities.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); } ctrl = ctrl->next; } @@ -1528,11 +1528,11 @@ class NIFObjectLoader : Ogre::ManualResourceLoader if(node->recType == Nif::RC_NiAutoNormalParticles || node->recType == Nif::RC_NiRotatingParticles) { - Ogre::ParticleSystem *partsys = createParticleSystem(sceneMgr, entities.mSkelBase, node); + Ogre::ParticleSystem *partsys = createParticleSystem(sceneMgr, objectlist.mSkelBase, node); if(partsys != NULL) { partsys->setVisible(!(flags&0x01)); - entities.mParticles.push_back(partsys); + objectlist.mParticles.push_back(partsys); } } @@ -1543,12 +1543,12 @@ class NIFObjectLoader : Ogre::ManualResourceLoader for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - createObjects(sceneMgr, children[i].getPtr(), entities, flags); + createObjects(sceneMgr, children[i].getPtr(), objectlist, flags); } } } - void createSkelBase(Ogre::SceneManager *sceneMgr, const Nif::Node *node, EntityList &entities) + void createSkelBase(Ogre::SceneManager *sceneMgr, const Nif::Node *node, ObjectList &objectlist) { /* 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 @@ -1567,15 +1567,15 @@ class NIFObjectLoader : Ogre::ManualResourceLoader mesh = meshMgr.createManual(fullname, mGroup, loader); mesh->setAutoBuildEdgeLists(false); } - entities.mSkelBase = sceneMgr->createEntity(mesh); - entities.mEntities.push_back(entities.mSkelBase); + objectlist.mSkelBase = sceneMgr->createEntity(mesh); + objectlist.mEntities.push_back(objectlist.mSkelBase); } public: NIFObjectLoader() : mShapeIndex(~(size_t)0) { } - static void load(Ogre::SceneManager *sceneMgr, EntityList &entities, const std::string &name, const std::string &group) + static void load(Ogre::SceneManager *sceneMgr, ObjectList &objectlist, const std::string &name, const std::string &group) { Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name); Nif::NIFFile &nif = *pnif.get(); @@ -1603,44 +1603,44 @@ public: NIFObjectLoader meshldr(name, group); if(hasSkel) - meshldr.createSkelBase(sceneMgr, node, entities); - meshldr.createObjects(sceneMgr, node, entities); + meshldr.createSkelBase(sceneMgr, node, objectlist); + meshldr.createObjects(sceneMgr, node, objectlist); } }; NIFObjectLoader::LoaderMap NIFObjectLoader::sLoaders; -EntityList Loader::createEntities(Ogre::SceneNode *parentNode, std::string name, const std::string &group) +ObjectList Loader::createObjects(Ogre::SceneNode *parentNode, std::string name, const std::string &group) { - EntityList entitylist; + ObjectList objectlist; Misc::StringUtils::toLower(name); - NIFObjectLoader::load(parentNode->getCreator(), entitylist, name, group); + NIFObjectLoader::load(parentNode->getCreator(), objectlist, name, group); - for(size_t i = 0;i < entitylist.mEntities.size();i++) + for(size_t i = 0;i < objectlist.mEntities.size();i++) { - Ogre::Entity *entity = entitylist.mEntities[i]; + Ogre::Entity *entity = objectlist.mEntities[i]; if(!entity->isAttached()) parentNode->attachObject(entity); } - return entitylist; + return objectlist; } -EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonename, - Ogre::SceneNode *parentNode, - std::string name, const std::string &group) +ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonename, + Ogre::SceneNode *parentNode, + std::string name, const std::string &group) { - EntityList entitylist; + ObjectList objectlist; Misc::StringUtils::toLower(name); - NIFObjectLoader::load(parentNode->getCreator(), entitylist, name, group); + NIFObjectLoader::load(parentNode->getCreator(), objectlist, name, group); bool isskinned = false; - for(size_t i = 0;i < entitylist.mEntities.size();i++) + for(size_t i = 0;i < objectlist.mEntities.size();i++) { - Ogre::Entity *ent = entitylist.mEntities[i]; - if(entitylist.mSkelBase != ent && ent->hasSkeleton()) + Ogre::Entity *ent = objectlist.mEntities[i]; + if(objectlist.mSkelBase != ent && ent->hasSkeleton()) { isskinned = true; break; @@ -1655,12 +1655,12 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen { std::string filter = "@shape=tri "+bonename; Misc::StringUtils::toLower(filter); - for(size_t i = 0;i < entitylist.mEntities.size();i++) + for(size_t i = 0;i < objectlist.mEntities.size();i++) { - Ogre::Entity *entity = entitylist.mEntities[i]; + Ogre::Entity *entity = objectlist.mEntities[i]; if(entity->hasSkeleton()) { - if(entity == entitylist.mSkelBase || + if(entity == objectlist.mSkelBase || entity->getMesh()->getName().find(filter) != std::string::npos) parentNode->attachObject(entity); } @@ -1673,9 +1673,9 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen } else { - for(size_t i = 0;i < entitylist.mEntities.size();i++) + for(size_t i = 0;i < objectlist.mEntities.size();i++) { - Ogre::Entity *entity = entitylist.mEntities[i]; + Ogre::Entity *entity = objectlist.mEntities[i]; if(!entity->isAttached()) { Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entity); @@ -1684,7 +1684,7 @@ EntityList Loader::createEntities(Ogre::Entity *parent, const std::string &bonen } } - return entitylist; + return objectlist; } diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index 819b4d8806..ee50aa86e5 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -39,7 +39,7 @@ namespace NifOgre typedef std::multimap TextKeyMap; static const char sTextKeyExtraDataID[] = "TextKeyExtraData"; -struct EntityList { +struct ObjectList { Ogre::Entity *mSkelBase; std::vector mEntities; @@ -47,7 +47,7 @@ struct EntityList { std::vector > mControllers; - EntityList() : mSkelBase(0) + ObjectList() : mSkelBase(0) { } }; @@ -55,14 +55,14 @@ struct EntityList { class Loader { public: - static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, - Ogre::SceneNode *parentNode, - std::string name, - const std::string &group="General"); + static ObjectList createObjects(Ogre::Entity *parent, const std::string &bonename, + Ogre::SceneNode *parentNode, + std::string name, + const std::string &group="General"); - static EntityList createEntities(Ogre::SceneNode *parentNode, - std::string name, - const std::string &group="General"); + static ObjectList createObjects(Ogre::SceneNode *parentNode, + std::string name, + const std::string &group="General"); static Ogre::SkeletonPtr getSkeleton(std::string name, const std::string &group="General"); }; From 878b4c15c5631fa3daa75a80d1fd44cb7e917a36 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 02:08:33 -0700 Subject: [PATCH 120/198] Set visibility flags and the render queue group for particles --- apps/openmw/mwrender/activatoranimation.cpp | 9 ++++++- apps/openmw/mwrender/creatureanimation.cpp | 8 ++++++ apps/openmw/mwrender/npcanimation.cpp | 30 ++++++++++++++++----- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/activatoranimation.cpp b/apps/openmw/mwrender/activatoranimation.cpp index b1b820915d..4630208b4b 100644 --- a/apps/openmw/mwrender/activatoranimation.cpp +++ b/apps/openmw/mwrender/activatoranimation.cpp @@ -1,6 +1,7 @@ #include "activatoranimation.hpp" #include +#include #include #include @@ -29,14 +30,20 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) for(size_t i = 0;i < mObjectList.mEntities.size();i++) { Ogre::Entity *ent = mObjectList.mEntities[i]; + ent->setVisibilityFlags(RV_Misc); for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) { Ogre::SubEntity* subEnt = ent->getSubEntity(j); subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } + } + for(size_t i = 0;i < mObjectList.mParticles.size();i++) + { + Ogre::ParticleSystem *part = mObjectList.mParticles[i]; + part->setVisibilityFlags(RV_Misc); - ent->setVisibilityFlags(RV_Misc); + part->setRenderQueueGroup(RQG_Alpha); } setAnimationSource(mesh); } diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index a8c4afc4e8..c714a2372a 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -1,6 +1,7 @@ #include "creatureanimation.hpp" #include +#include #include #include @@ -37,6 +38,13 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } + for(size_t i = 0;i < mObjectList.mParticles.size();i++) + { + Ogre::ParticleSystem *part = mObjectList.mParticles[i]; + part->setVisibilityFlags(RV_Actors); + + part->setRenderQueueGroup(RQG_Alpha); + } std::vector names; if((ref->mBase->mFlags&ESM::Creature::Biped)) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 5d14440e75..28c78fd2f7 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "../mwworld/esmstore.hpp" @@ -109,6 +110,15 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } + for(size_t i = 0;i < mObjectList.mParticles.size();i++) + { + Ogre::ParticleSystem *part = mObjectList.mParticles[i]; + + part->getUserObjectBindings().setUserAny(Ogre::Any(-1)); + if(mVisibilityFlags != 0) + part->setVisibilityFlags(mVisibilityFlags); + part->setRenderQueueGroup(RQG_Alpha); + } std::vector skelnames(1, smodel); if(!mNpc->isMale() && !isBeast) @@ -306,19 +316,25 @@ NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, in { NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mObjectList.mSkelBase, bonename, mInsert, model); - const std::vector &parts = objects.mEntities; - for(size_t i = 0;i < parts.size();i++) + for(size_t i = 0;i < objects.mEntities.size();i++) { - parts[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); - if (mVisibilityFlags != 0) - parts[i]->setVisibilityFlags(mVisibilityFlags); + objects.mEntities[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); + if(mVisibilityFlags != 0) + objects.mEntities[i]->setVisibilityFlags(mVisibilityFlags); - for(unsigned int j=0; j < parts[i]->getNumSubEntities(); ++j) + for(unsigned int j=0; j < objects.mEntities[i]->getNumSubEntities(); ++j) { - Ogre::SubEntity* subEnt = parts[i]->getSubEntity(j); + Ogre::SubEntity* subEnt = objects.mEntities[i]->getSubEntity(j); subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } + for(size_t i = 0;i < objects.mParticles.size();i++) + { + objects.mParticles[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); + if(mVisibilityFlags != 0) + objects.mParticles[i]->setVisibilityFlags(mVisibilityFlags); + objects.mParticles[i]->setRenderQueueGroup(RQG_Alpha); + } if(objects.mSkelBase) { Ogre::AnimationStateSet *aset = objects.mSkelBase->getAllAnimationStates(); From be419bc89185c74be619d08054e94e8aad0cec71 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 02:28:15 -0700 Subject: [PATCH 121/198] Handle NiCamera nodes --- apps/openmw/mwrender/animation.cpp | 1 + apps/openmw/mwrender/npcanimation.cpp | 1 + components/nifogre/ogrenifloader.cpp | 8 ++++++++ components/nifogre/ogrenifloader.hpp | 7 ++++++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 1d983acfc5..23d2d9e1b6 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -46,6 +46,7 @@ Animation::~Animation() sceneMgr->destroyEntity(mObjectList.mEntities[i]); } mObjectList.mControllers.clear(); + mObjectList.mCameras.clear(); mObjectList.mParticles.clear(); mObjectList.mEntities.clear(); mObjectList.mSkelBase = NULL; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 28c78fd2f7..931b8ef83d 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -384,6 +384,7 @@ void NpcAnimation::removeObjects(NifOgre::ObjectList &objects) for(size_t i = 0;i < objects.mEntities.size();i++) sceneMgr->destroyEntity(objects.mEntities[i]); objects.mControllers.clear(); + objects.mCameras.clear(); objects.mParticles.clear(); objects.mEntities.clear(); objects.mSkelBase = NULL; diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index e7d1a88d1c..7dd616e4ee 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -498,6 +498,7 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */ node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */ + node->recType == Nif::RC_NiCamera || node->recType == Nif::RC_NiAutoNormalParticles || node->recType == Nif::RC_NiRotatingParticles )) @@ -1452,6 +1453,13 @@ class NIFObjectLoader : Ogre::ManualResourceLoader e = e->extra; } + if(node->recType == Nif::RC_NiCamera) + { + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, node->recIndex); + Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); + objectlist.mCameras.push_back(trgtbone); + } + Nif::ControllerPtr ctrl = node->controller; while(!ctrl.empty()) { diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index ee50aa86e5..88cbaf6910 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -42,9 +42,14 @@ static const char sTextKeyExtraDataID[] = "TextKeyExtraData"; struct ObjectList { Ogre::Entity *mSkelBase; std::vector mEntities; - std::vector mParticles; + // We could actually have Ogre::Camera objects, but that means more + // maintenance when switching cameras. The information in the NiCamera node + // is pretty much useless too anyway. So instead, this is just a list of + // bones in the mSkelBase which are NiCamera nodes. + std::vector mCameras; + std::vector > mControllers; ObjectList() : mSkelBase(0) From ff1d908af416d8301dda9f1f82d8947c1213d4f4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 15:17:35 +0200 Subject: [PATCH 122/198] added script table --- apps/esmtool/record.cpp | 2 +- apps/opencs/model/world/data.cpp | 15 +++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 1 + components/esm/loadscpt.cpp | 15 +++++++++++++-- components/esm/loadscpt.hpp | 5 ++++- 10 files changed, 56 insertions(+), 5 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index a6f77862ef..e16ade6e24 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -1182,7 +1182,7 @@ void Record::print() std::cout << " Variable: " << *vit << std::endl; std::cout << " ByteCode: "; - std::vector::iterator cit; + std::vector::iterator cit; for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++) std::cout << boost::format("%02X") % (int)(*cit); std::cout << std::endl; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 69109bd743..c29cdaccfb 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -84,6 +84,9 @@ CSMWorld::Data::Data() mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MaxRange)); mSounds.addColumn (new SoundFileColumn); + mScripts.addColumn (new StringIdColumn); + mScripts.addColumn (new RecordStateColumn); + 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); @@ -91,6 +94,7 @@ CSMWorld::Data::Data() addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound); + addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script); } CSMWorld::Data::~Data() @@ -169,6 +173,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getSounds() return mSounds; } +const CSMWorld::IdCollection& CSMWorld::Data::getScripts() const +{ + return mScripts; +} + +CSMWorld::IdCollection& CSMWorld::Data::getScripts() +{ + return mScripts; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -210,6 +224,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_FACT: mFactions.load (reader, base); break; case ESM::REC_RACE: mRaces.load (reader, base); break; case ESM::REC_SOUN: mSounds.load (reader, base); break; + case ESM::REC_SCPT: mScripts.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 320480e639..7daf5d4baa 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -30,6 +31,7 @@ namespace CSMWorld IdCollection mFactions; IdCollection mRaces; IdCollection mSounds; + IdCollection mScripts; std::vector mModels; std::map mModelIndex; @@ -74,6 +76,10 @@ namespace CSMWorld IdCollection& getSounds(); + const IdCollection& getScripts() const; + + IdCollection& getScripts(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 7bdc15c8c7..816681a133 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -24,6 +24,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -37,6 +38,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index a21d67fcd8..06db75d7f4 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -47,7 +47,9 @@ namespace CSMWorld Type_Races, Type_Race, Type_Sounds, - Type_Sound + Type_Sound, + Type_Scripts, + Type_Script }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 611690ca65..27cf78b3ce 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -109,6 +109,10 @@ void CSVDoc::View::setupWorldMenu() QAction *sounds = new QAction (tr ("Sounds"), this); connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView())); world->addAction (sounds); + + QAction *scripts = new QAction (tr ("Scripts"), this); + connect (scripts, SIGNAL (triggered()), this, SLOT (addScriptsSubView())); + world->addAction (scripts); } void CSVDoc::View::setupUi() @@ -289,6 +293,11 @@ void CSVDoc::View::addSoundsSubView() addSubView (CSMWorld::UniversalId::Type_Sounds); } +void CSVDoc::View::addScriptsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Scripts); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index e8e716b706..4822db3e4f 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -125,6 +125,8 @@ namespace CSVDoc void addRacesSubView(); void addSoundsSubView(); + + void addScriptsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 3ba950f879..7cdf18bce6 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -21,6 +21,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Factions, CSMWorld::UniversalId::Type_Races, CSMWorld::UniversalId::Type_Sounds, + CSMWorld::UniversalId::Type_Scripts, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadscpt.cpp b/components/esm/loadscpt.cpp index d9b6497d98..2c1b018d97 100644 --- a/components/esm/loadscpt.cpp +++ b/components/esm/loadscpt.cpp @@ -64,7 +64,7 @@ void Script::save(ESMWriter &esm) memcpy(data.mName.name, mId.c_str(), mId.size()); esm.writeHNT("SCHD", data, 52); - + if (!mVarNames.empty()) { esm.startSubRecord("SCVR"); @@ -76,10 +76,21 @@ void Script::save(ESMWriter &esm) } esm.startSubRecord("SCDT"); - esm.write(&mScriptData[0], mData.mScriptDataSize); + esm.write(reinterpret_cast(&mScriptData[0]), mData.mScriptDataSize); esm.endRecord("SCDT"); esm.writeHNOString("SCTX", mScriptText); } + void Script::blank() + { + mData.mNumShorts = mData.mNumLongs = mData.mNumFloats = 0; + mData.mScriptDataSize = 0; + mData.mStringTableSize = 0; + + mVarNames.clear(); + mScriptData.clear(); + mScriptText = "Begin " + mId + "\n\nEnd " + mId + "\n"; + } + } diff --git a/components/esm/loadscpt.hpp b/components/esm/loadscpt.hpp index 10a6d24b10..be7e839002 100644 --- a/components/esm/loadscpt.hpp +++ b/components/esm/loadscpt.hpp @@ -52,11 +52,14 @@ public: SCHDstruct mData; std::vector mVarNames; // Variable names - std::vector mScriptData; // Compiled bytecode + std::vector mScriptData; // Compiled bytecode std::string mScriptText; // Uncompiled script void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } #endif From 755a80a522963f6d6b26f39134bd6696c917756c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 15:52:43 +0200 Subject: [PATCH 123/198] Fix camera shaking when near the pitch limit. --- apps/openmw/mwrender/player.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 63396378d0..55fda326fa 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -242,14 +242,15 @@ namespace MWRender void Player::setPitch(float angle) { - float limit = Ogre::Math::HALF_PI; + const float epsilon = 0.000001; + float limit = Ogre::Math::HALF_PI - epsilon; if (mVanity.forced || mPreviewMode) { limit /= 2; } if (angle > limit) { - angle = limit - 0.01; + angle = limit; } else if (angle < -limit) { - angle = -limit + 0.01; + angle = -limit; } if (mVanity.enabled || mPreviewMode) { mPreviewCam.pitch = angle; From ebff64a7a4b297c2b9a34a808c19d4b57ee8dee9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 06:56:12 -0700 Subject: [PATCH 124/198] Fix UVController and add warn about unhandled material controllers --- components/nifogre/ogrenifloader.cpp | 63 ++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 7dd616e4ee..8924056e03 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -184,18 +184,23 @@ public: static float lookupValue(const Nif::FloatKeyList &keys, float time, float def) { - Nif::FloatKeyList::VecType::const_iterator iter(keys.mKeys.begin()); + if(keys.mKeys.size() == 0) + return def; + + if(time <= keys.mKeys.front().mTime) + return keys.mKeys.front().mValue; + + Nif::FloatKeyList::VecType::const_iterator iter(keys.mKeys.begin()+1); for(;iter != keys.mKeys.end();iter++) { - if(iter->mTime > time) + if(iter->mTime < time) continue; - Nif::FloatKeyList::VecType::const_iterator next(iter+1); - if(next == keys.mKeys.end()) - return iter->mValue; - float a = (time-iter->mTime) / (next->mTime-iter->mTime); - return iter->mValue + ((next->mValue - iter->mValue)*a); + + Nif::FloatKeyList::VecType::const_iterator last(iter-1); + float a = (time-last->mTime) / (iter->mTime-last->mTime); + return last->mValue + ((iter->mValue - last->mValue)*a); } - return def; + return keys.mKeys.back().mValue; } public: @@ -837,6 +842,13 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, else warn("Found internal texture, ignoring."); } + + Nif::ControllerPtr ctrls = texprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled texture controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } } needTangents = !texName[Nif::NiTexturingProperty::BumpTexture].empty(); @@ -845,6 +857,13 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, { alphaFlags = alphaprop->flags; alphaTest = alphaprop->data.threshold; + + Nif::ControllerPtr ctrls = alphaprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled alpha controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } } // Vertex color handling @@ -853,17 +872,38 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, vertMode = vertprop->data.vertmode; // FIXME: Handle lightmode? //lightMode = vertprop->data.lightmode; + + Nif::ControllerPtr ctrls = vertprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled vertex color controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } } if(zprop) { depthFlags = zprop->flags; // Depth function??? + + Nif::ControllerPtr ctrls = zprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled depth controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } } if(specprop) { specFlags = specprop->flags; + + Nif::ControllerPtr ctrls = specprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled specular controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } } // Material @@ -875,6 +915,13 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, emissive = matprop->data.emissive; glossiness = matprop->data.glossiness; alpha = matprop->data.alpha; + + Nif::ControllerPtr ctrls = matprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled material controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } } { From 2e067e95a9a63bbb25d12ecbe6fb969a4e638317 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 07:12:52 -0700 Subject: [PATCH 125/198] Handle NiWireframeProperty --- components/nifogre/ogrenifloader.cpp | 37 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 8924056e03..94cb14b588 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -799,6 +799,7 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, const Nif::NiVertexColorProperty *vertprop, const Nif::NiZBufferProperty *zprop, const Nif::NiSpecularProperty *specprop, + const Nif::NiWireframeProperty *wireprop, bool &needTangents) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); @@ -819,6 +820,7 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, int depthFlags = 3; // Default should be 1, but Bloodmoon's models are broken int specFlags = 0; + int wireFlags = 0; Ogre::String texName[7]; bool vertexColour = (shapedata->colors.size() != 0); @@ -906,6 +908,18 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, } } + if(wireprop) + { + wireFlags = wireprop->flags; + + Nif::ControllerPtr ctrls = wireprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled wireframe controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + // Material if(matprop) { @@ -950,6 +964,7 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, boost::hash_combine(h, vertMode); boost::hash_combine(h, depthFlags); boost::hash_combine(h, specFlags); + boost::hash_combine(h, wireFlags); std::map::iterator itr = MaterialMap.find(h); if (itr != MaterialMap.end()) @@ -993,6 +1008,11 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); } + if(wireFlags) + { + instance->setProperty("polygon_mode", sh::makeProperty(new sh::StringValue("wireframe"))); + } + instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); @@ -1087,10 +1107,11 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Nif::NiAlphaProperty *&alphaprop, const Nif::NiVertexColorProperty *&vertprop, const Nif::NiZBufferProperty *&zprop, - const Nif::NiSpecularProperty *&specprop) + const Nif::NiSpecularProperty *&specprop, + const Nif::NiWireframeProperty *wireprop) { if(node->parent) - getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop); + getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); const Nif::PropertyList &proplist = node->props; for(size_t i = 0;i < proplist.length();i++) @@ -1112,6 +1133,8 @@ class NIFObjectLoader : Ogre::ManualResourceLoader zprop = static_cast(pr); else if(pr->recType == Nif::RC_NiSpecularProperty) specprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiWireframeProperty) + wireprop = static_cast(pr); else warn("Unhandled property type: "+pr->recName); } @@ -1324,13 +1347,14 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Nif::NiVertexColorProperty *vertprop = NULL; const Nif::NiZBufferProperty *zprop = NULL; const Nif::NiSpecularProperty *specprop = NULL; + const Nif::NiWireframeProperty *wireprop = NULL; bool needTangents = false; - getNodeProperties(shape, texprop, matprop, alphaprop, vertprop, zprop, specprop); + getNodeProperties(shape, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop, - needTangents); + wireprop, needTangents); if(matname.length() > 0) sub->setMaterialName(matname); @@ -1405,13 +1429,14 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Nif::NiVertexColorProperty *vertprop = NULL; const Nif::NiZBufferProperty *zprop = NULL; const Nif::NiSpecularProperty *specprop = NULL; + const Nif::NiWireframeProperty *wireprop = NULL; bool needTangents = false; - getNodeProperties(partnode, texprop, matprop, alphaprop, vertprop, zprop, specprop); + getNodeProperties(partnode, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop, - needTangents)); + wireprop, needTangents)); partsys->setDefaultDimensions(particledata->particleSize, particledata->particleSize); partsys->setCullIndividually(false); From 8bbfba3f43afa56d62c63b310700384d50fcfaa4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 16:18:40 +0200 Subject: [PATCH 126/198] Fix fatigue not being set to its maximum value when player is rebuilt --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 8757213e99..4a2a2ecc69 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -149,7 +149,7 @@ namespace MWMechanics // forced update and current value adjustments mActors.updateActor (ptr, 0); - for (int i=0; i<2; ++i) + for (int i=0; i<3; ++i) { DynamicStat stat = creatureStats.getDynamic (i); stat.setCurrent (stat.getModified()); From e25f5c6dfe71b5c076ccd01dce5048f575ac5aa5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 16:32:06 +0200 Subject: [PATCH 127/198] added basic region table --- apps/opencs/model/world/data.cpp | 16 ++++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 1 + components/esm/loadregn.cpp | 19 ++++++++++++++++--- components/esm/loadregn.hpp | 3 +++ 9 files changed, 58 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c29cdaccfb..0c6f2b4ada 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -87,6 +87,10 @@ CSMWorld::Data::Data() mScripts.addColumn (new StringIdColumn); mScripts.addColumn (new RecordStateColumn); + mRegions.addColumn (new StringIdColumn); + mRegions.addColumn (new RecordStateColumn); + mRegions.addColumn (new NameColumn); + 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); @@ -95,6 +99,7 @@ CSMWorld::Data::Data() addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound); addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script); + addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region); } CSMWorld::Data::~Data() @@ -183,6 +188,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getScripts() return mScripts; } +const CSMWorld::IdCollection& CSMWorld::Data::getRegions() const +{ + return mRegions; +} + +CSMWorld::IdCollection& CSMWorld::Data::getRegions() +{ + return mRegions; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -225,6 +240,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_RACE: mRaces.load (reader, base); break; case ESM::REC_SOUN: mSounds.load (reader, base); break; case ESM::REC_SCPT: mScripts.load (reader, base); break; + case ESM::REC_REGN: mRegions.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 7daf5d4baa..d9432aa3e3 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -32,6 +33,7 @@ namespace CSMWorld IdCollection mRaces; IdCollection mSounds; IdCollection mScripts; + IdCollection mRegions; std::vector mModels; std::map mModelIndex; @@ -80,6 +82,10 @@ namespace CSMWorld IdCollection& getScripts(); + const IdCollection& getRegions() const; + + IdCollection& getRegions(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 816681a133..4a81ee01b5 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -25,6 +25,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -39,6 +40,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 06db75d7f4..507febba44 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -49,7 +49,9 @@ namespace CSMWorld Type_Sounds, Type_Sound, Type_Scripts, - Type_Script + Type_Script, + Type_Regions, + Type_Region }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 27cf78b3ce..8e51ba9dcb 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -113,6 +113,10 @@ void CSVDoc::View::setupWorldMenu() QAction *scripts = new QAction (tr ("Scripts"), this); connect (scripts, SIGNAL (triggered()), this, SLOT (addScriptsSubView())); world->addAction (scripts); + + QAction *regions = new QAction (tr ("Regions"), this); + connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView())); + world->addAction (regions); } void CSVDoc::View::setupUi() @@ -298,6 +302,11 @@ void CSVDoc::View::addScriptsSubView() addSubView (CSMWorld::UniversalId::Type_Scripts); } +void CSVDoc::View::addRegionsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Regions); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 4822db3e4f..a5190dedc6 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -127,6 +127,8 @@ namespace CSVDoc void addSoundsSubView(); void addScriptsSubView(); + + void addRegionsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 7cdf18bce6..30812f8f58 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -22,6 +22,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Races, CSMWorld::UniversalId::Type_Sounds, CSMWorld::UniversalId::Type_Scripts, + CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadregn.cpp b/components/esm/loadregn.cpp index d39a294547..41c7f507ae 100644 --- a/components/esm/loadregn.cpp +++ b/components/esm/loadregn.cpp @@ -31,14 +31,14 @@ void Region::load(ESMReader &esm) void Region::save(ESMWriter &esm) { esm.writeHNCString("FNAM", mName); - + if (esm.getVersion() == VER_12) esm.writeHNT("WEAT", mData, sizeof(mData) - 2); else esm.writeHNT("WEAT", mData); - + esm.writeHNOCString("BNAM", mSleepList); - + esm.writeHNT("CNAM", mMapColor); for (std::vector::iterator it = mSoundList.begin(); it != mSoundList.end(); ++it) { @@ -46,4 +46,17 @@ void Region::save(ESMWriter &esm) } } + void Region::blank() + { + mName.clear(); + + mData.mClear = mData.mCloudy = mData.mFoggy = mData.mOvercast = mData.mRain = + mData.mThunder = mData.mAsh, mData.mBlight = mData.mA = mData.mB = 0; + + mMapColor = 0; + + mName.clear(); + mSleepList.clear(); + mSoundList.clear(); + } } diff --git a/components/esm/loadregn.hpp b/components/esm/loadregn.hpp index 0496ef5af2..f2a3d9a108 100644 --- a/components/esm/loadregn.hpp +++ b/components/esm/loadregn.hpp @@ -48,6 +48,9 @@ struct Region void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } #endif From 88c81bfb243164d185723dfbe8e266bf58611034 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 07:38:43 -0700 Subject: [PATCH 128/198] Apply polygon_mode to objects --- files/materials/objects.mat | 2 ++ 1 file changed, 2 insertions(+) diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 49df4e3949..957d75db56 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -17,6 +17,7 @@ material openmw_objects_base depth_check default alpha_rejection default transparent_sorting default + polygon_mode default pass { @@ -41,6 +42,7 @@ material openmw_objects_base depth_write $depth_write depth_check $depth_check transparent_sorting $transparent_sorting + polygon_mode $polygon_mode texture_unit diffuseMap { From fe9a7f12b6c21bc6dc4ebc8ac22fb5fc767a0b81 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 07:53:01 -0700 Subject: [PATCH 129/198] Material fixes --- components/nifogre/ogrenifloader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 94cb14b588..3bd8b95e58 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -947,9 +947,11 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata, boost::hash_combine(h, diffuse.x); boost::hash_combine(h, diffuse.y); boost::hash_combine(h, diffuse.z); + boost::hash_combine(h, alpha); boost::hash_combine(h, specular.x); boost::hash_combine(h, specular.y); boost::hash_combine(h, specular.z); + boost::hash_combine(h, glossiness); boost::hash_combine(h, emissive.x); boost::hash_combine(h, emissive.y); boost::hash_combine(h, emissive.z); @@ -1108,7 +1110,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Nif::NiVertexColorProperty *&vertprop, const Nif::NiZBufferProperty *&zprop, const Nif::NiSpecularProperty *&specprop, - const Nif::NiWireframeProperty *wireprop) + const Nif::NiWireframeProperty *&wireprop) { if(node->parent) getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); From f49a2a97c5f09a30703448b28cadbe17adf963ce Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 16:56:21 +0200 Subject: [PATCH 130/198] added map colour column to region table --- apps/opencs/model/world/columns.hpp | 34 +++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 35 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 75dfe15c27..b09c931b28 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -5,6 +5,8 @@ #include +#include + #include "columnbase.hpp" namespace CSMWorld @@ -591,6 +593,38 @@ namespace CSMWorld return true; } }; + + /// \todo QColor is a GUI class and should not be in model. Need to think of an alternative + /// solution. + template + struct MapColourColumn : public Column + { + /// \todo Replace Display_Integer with something that displays the colour value more directly. + MapColourColumn() : Column ("Map Colour", ColumnBase::Display_Integer) {} + + virtual QVariant get (const Record& record) const + { + int colour = record.get().mMapColor; + + return QColor (colour & 0xff, (colour>>8) & 0xff, (colour>>16) & 0xff); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + QColor colour = data.value(); + + record2.mMapColor = colour.rgb() & 0xffffff; + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 0c6f2b4ada..f451656875 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -90,6 +90,7 @@ CSMWorld::Data::Data() mRegions.addColumn (new StringIdColumn); mRegions.addColumn (new RecordStateColumn); mRegions.addColumn (new NameColumn); + mRegions.addColumn (new MapColourColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From ab5980ae187b8e8e71167353368c0598a83bc26f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 08:29:56 -0700 Subject: [PATCH 131/198] Let the default controller function use absolute input And convert the VisController to use it. --- components/nifogre/ogrenifloader.cpp | 84 ++++++++++++++-------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 3bd8b95e58..e5e072620e 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -75,24 +75,33 @@ private: float mStopTime; public: - DefaultFunction(const Nif::Controller *ctrl) - : Ogre::ControllerFunction(false) + DefaultFunction(const Nif::Controller *ctrl, bool deltaInput) + : Ogre::ControllerFunction(deltaInput) , mFrequency(ctrl->frequency) , mPhase(ctrl->phase) , mStartTime(ctrl->timeStart) , mStopTime(ctrl->timeStop) { - mDeltaCount = mPhase; - while(mDeltaCount < mStartTime) - mDeltaCount += (mStopTime-mStartTime); + if(mDeltaInput) + { + mDeltaCount = mPhase; + while(mDeltaCount < mStartTime) + mDeltaCount += (mStopTime-mStartTime); + } } virtual Ogre::Real calculate(Ogre::Real value) { - mDeltaCount += value*mFrequency; - mDeltaCount = std::fmod(mDeltaCount - mStartTime, - mStopTime - mStartTime) + mStartTime; - return mDeltaCount; + if(mDeltaInput) + { + mDeltaCount += value*mFrequency; + mDeltaCount = std::fmod(mDeltaCount - mStartTime, + mStopTime - mStartTime) + mStartTime; + return mDeltaCount; + } + + value = std::min(mStopTime, std::max(mStartTime, value+mPhase)); + return value; } }; @@ -103,6 +112,20 @@ public: { private: Ogre::Bone *mTarget; + std::vector mData; + + virtual bool calculate(Ogre::Real time) + { + if(mData.size() == 0) + return true; + + for(size_t i = 1;i < mData.size();i++) + { + if(mData[i].time > time) + return mData[i-1].isSet; + } + return mData.back().isSet; + } // FIXME: We are not getting all objects here. Skinned meshes get // attached to the object's root node, and won't be connected via a @@ -126,7 +149,9 @@ public: } public: - Value(Ogre::Bone *target) : mTarget(target) + Value(Ogre::Bone *target, const Nif::NiVisData *data) + : mTarget(target) + , mData(data->mVis) { } virtual Ogre::Real getValue() const @@ -135,39 +160,14 @@ public: return 1.0f; } - virtual void setValue(Ogre::Real value) + virtual void setValue(Ogre::Real time) { - int vis = static_cast(value); + bool vis = calculate(time); setVisible(mTarget, vis); } }; - class Function : public Ogre::ControllerFunction - { - private: - std::vector mData; - - public: - Function(const Nif::NiVisData *data) - : Ogre::ControllerFunction(false), - mData(data->mVis) - { } - - virtual Ogre::Real calculate(Ogre::Real value) - { - if(mData.size() == 0) - return 1.0f; - - if(mData[0].time >= value) - return mData[0].isSet; - for(size_t i = 1;i < mData.size();i++) - { - if(mData[i].time > value) - return mData[i-1].isSet; - } - return mData.back().isSet; - } - }; + typedef DefaultFunction Function; }; class UVController @@ -1543,9 +1543,9 @@ class NIFObjectLoader : Ogre::ManualResourceLoader int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); - Ogre::SharedPtr > srcval; /* Filled in later */ - Ogre::SharedPtr > dstval(OGRE_NEW VisController::Value(trgtbone)); - Ogre::SharedPtr > func(OGRE_NEW VisController::Function(vis->data.getPtr())); + Ogre::ControllerValueRealPtr srcval; /* Filled in later */ + Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr())); + Ogre::ControllerFunctionRealPtr func(OGRE_NEW VisController::Function(vis, false)); objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); } @@ -1599,7 +1599,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Ogre::MaterialPtr &material = entity->getSubEntity(0)->getMaterial(); Ogre::ControllerValueRealPtr srcval(Ogre::ControllerManager::getSingleton().getFrameTimeSource()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr())); - Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv)); + Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv, true)); objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); } From 399394ff103ec1f2779cdb8244caccff6da5621e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 10:03:13 -0700 Subject: [PATCH 132/198] Don't restrict animations to the keyframe time limits --- components/nifogre/ogrenifloader.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index e5e072620e..90139c9f02 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -384,10 +384,8 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const lasttrans = curtrans = traniter->mValue; if(scaleiter != scalekeys.mKeys.end()) lastscale = curscale = Ogre::Vector3(scaleiter->mValue); - float begTime = std::max(kfc->timeStart, startTime); - float endTime = std::min(kfc->timeStop, stopTime); - bool didlast = false; + bool didlast = false; while(!didlast) { float curtime = std::numeric_limits::max(); @@ -400,11 +398,11 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const if(scaleiter != scalekeys.mKeys.end()) curtime = std::min(curtime, scaleiter->mTime); - curtime = std::max(curtime, begTime); - if(curtime >= endTime) + curtime = std::max(curtime, startTime); + if(curtime >= stopTime) { didlast = true; - curtime = endTime; + curtime = stopTime; } // Get the latest quaternions, translations, and scales for the From 822866b5ae325a8a6a1bf29d1c09f4c8860f9104 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sun, 7 Apr 2013 18:04:30 +0100 Subject: [PATCH 133/198] fixed autorun --- apps/openmw/mwinput/inputmanagerimp.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 74d581b811..0ed49cd7f7 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -301,6 +301,12 @@ namespace MWInput mPlayer.setForwardBackward (-1); } + else if(mPlayer.getAutoMove()) + { + triedToMove = true; + mPlayer.setForwardBackward (1); + } + mPlayer.setSneak(actionIsActive(A_Sneak)); if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"]) @@ -321,6 +327,7 @@ namespace MWInput mOverencumberedMessageDelay -= dt; if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player)) { + mPlayer.setAutoMove (false); if (mOverencumberedMessageDelay <= 0) { MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}"); From c9424f577f15a35a6f1fe22d6681db39a48269fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 19:29:15 +0200 Subject: [PATCH 134/198] added sleeplist column to region table --- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 26 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index b09c931b28..aa097dac65 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -625,6 +625,31 @@ namespace CSMWorld return true; } }; + + template + struct SleepListColumn : public Column + { + SleepListColumn() : Column ("Sleep Encounter", ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mSleepList.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mSleepList = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index f451656875..fc93675e42 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -91,6 +91,7 @@ CSMWorld::Data::Data() mRegions.addColumn (new RecordStateColumn); mRegions.addColumn (new NameColumn); mRegions.addColumn (new MapColourColumn); + mRegions.addColumn (new SleepListColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); From 593646436ea4fe3dcabdb01b40c2fd5d45b0a279 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 19:39:13 +0200 Subject: [PATCH 135/198] added verifier for region record --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/regioncheck.cpp | 33 +++++++++++++++++++++++++ apps/opencs/model/tools/regioncheck.hpp | 29 ++++++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 3 +++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/regioncheck.cpp create mode 100644 apps/opencs/model/tools/regioncheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ffd4c7f1ea..301febfc49 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,7 +35,7 @@ opencs_units (model/tools ) opencs_units_noqt (model/tools - stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck + stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck ) diff --git a/apps/opencs/model/tools/regioncheck.cpp b/apps/opencs/model/tools/regioncheck.cpp new file mode 100644 index 0000000000..ac64ac0271 --- /dev/null +++ b/apps/opencs/model/tools/regioncheck.cpp @@ -0,0 +1,33 @@ + +#include "regioncheck.hpp" + +#include +#include + +#include + +#include "../world/universalid.hpp" + +CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection& regions) +: mRegions (regions) +{} + +int CSMTools::RegionCheckStage::setup() +{ + return mRegions.getSize(); +} + +void CSMTools::RegionCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Region& region = mRegions.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Region, region.mId); + + // test for empty name + if (region.mName.empty()) + messages.push_back (id.toString() + "|" + region.mId + " has an empty name"); + + /// \todo test that the ID in mSleeplist exists + + /// \todo check data members that can't be edited in the table view +} \ No newline at end of file diff --git a/apps/opencs/model/tools/regioncheck.hpp b/apps/opencs/model/tools/regioncheck.hpp new file mode 100644 index 0000000000..b421356514 --- /dev/null +++ b/apps/opencs/model/tools/regioncheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_REGIONCHECK_H +#define CSM_TOOLS_REGIONCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that region records are internally consistent + class RegionCheckStage : public Stage + { + const CSMWorld::IdCollection& mRegions; + + public: + + RegionCheckStage (const CSMWorld::IdCollection& regions); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 4003bc8840..45adcf5e49 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -17,6 +17,7 @@ #include "factioncheck.hpp" #include "racecheck.hpp" #include "soundcheck.hpp" +#include "regioncheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -66,6 +67,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new RaceCheckStage (mData.getRaces())); mVerifier->appendStage (new SoundCheckStage (mData.getSounds())); + + mVerifier->appendStage (new RegionCheckStage (mData.getRegions())); } return mVerifier; From 80a1abd48ad5bc37e604c820249d8d7d250cd91c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 11:09:55 -0700 Subject: [PATCH 136/198] Clear the old text keys when setting new animation sources --- apps/openmw/mwrender/animation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 23d2d9e1b6..8ecebc7070 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -63,6 +63,7 @@ void Animation::setAnimationSources(const std::vector &names) mAnimVelocity = 0.0f; mAccumRoot = NULL; mNonAccumRoot = NULL; + mTextKeys.clear(); mSkeletonSources.clear(); std::vector::const_iterator nameiter; @@ -96,7 +97,7 @@ void Animation::setAnimationSources(const std::vector &names) { Ogre::Animation *anim = skel->getAnimation(i); const Ogre::Any &groupdata = bindings.getUserAny(std::string(NifOgre::sTextKeyExtraDataID)+ - "@"+anim->getName()); + "@"+anim->getName()); if(!groupdata.isEmpty()) mTextKeys[anim->getName()] = Ogre::any_cast(groupdata); } From 60cc95305d101c820856684186b7fb3beabf1e8f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 20:26:39 +0200 Subject: [PATCH 137/198] added basic birthsign table --- apps/opencs/model/world/data.cpp | 17 +++++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 1 + components/esm/loadbsgn.cpp | 8 ++++++++ components/esm/loadbsgn.hpp | 3 +++ 9 files changed, 51 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index fc93675e42..70162ba758 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -93,6 +93,11 @@ CSMWorld::Data::Data() mRegions.addColumn (new MapColourColumn); mRegions.addColumn (new SleepListColumn); + mBirthsigns.addColumn (new StringIdColumn); + mBirthsigns.addColumn (new RecordStateColumn); + mBirthsigns.addColumn (new NameColumn); + mBirthsigns.addColumn (new DescriptionColumn); + 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); @@ -102,6 +107,7 @@ CSMWorld::Data::Data() addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound); addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script); addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region); + addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign); } CSMWorld::Data::~Data() @@ -200,6 +206,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getRegions() return mRegions; } +const CSMWorld::IdCollection& CSMWorld::Data::getBirthsigns() const +{ + return mBirthsigns; +} + +CSMWorld::IdCollection& CSMWorld::Data::getBirthsigns() +{ + return mBirthsigns; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -243,6 +259,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_SOUN: mSounds.load (reader, base); break; case ESM::REC_SCPT: mScripts.load (reader, base); break; case ESM::REC_REGN: mRegions.load (reader, base); break; + case ESM::REC_BSGN: mBirthsigns.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index d9432aa3e3..122e855d86 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -34,6 +35,7 @@ namespace CSMWorld IdCollection mSounds; IdCollection mScripts; IdCollection mRegions; + IdCollection mBirthsigns; std::vector mModels; std::map mModelIndex; @@ -86,6 +88,10 @@ namespace CSMWorld IdCollection& getRegions(); + const IdCollection& getBirthsigns() const; + + IdCollection& getBirthsigns(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 4a81ee01b5..6d305d6c0f 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -26,6 +26,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -41,6 +42,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 507febba44..0586719f14 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -51,7 +51,9 @@ namespace CSMWorld Type_Scripts, Type_Script, Type_Regions, - Type_Region + Type_Region, + Type_Birthsigns, + Type_Birthsign }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 8e51ba9dcb..af9b814203 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -117,6 +117,10 @@ void CSVDoc::View::setupWorldMenu() QAction *regions = new QAction (tr ("Regions"), this); connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView())); world->addAction (regions); + + QAction *birthsigns = new QAction (tr ("Birthsigns"), this); + connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView())); + world->addAction (birthsigns); } void CSVDoc::View::setupUi() @@ -307,6 +311,11 @@ void CSVDoc::View::addRegionsSubView() addSubView (CSMWorld::UniversalId::Type_Regions); } +void CSVDoc::View::addBirthsignsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Birthsigns); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index a5190dedc6..12944e5693 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -129,6 +129,8 @@ namespace CSVDoc void addScriptsSubView(); void addRegionsSubView(); + + void addBirthsignsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 30812f8f58..23c66319c6 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -23,6 +23,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Sounds, CSMWorld::UniversalId::Type_Scripts, CSMWorld::UniversalId::Type_Regions, + CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadbsgn.cpp b/components/esm/loadbsgn.cpp index b58071644c..cb500f6748 100644 --- a/components/esm/loadbsgn.cpp +++ b/components/esm/loadbsgn.cpp @@ -24,4 +24,12 @@ void BirthSign::save(ESMWriter &esm) mPowers.save(esm); } + void BirthSign::blank() + { + mName.clear(); + mDescription.clear(); + mTexture.clear(); + mPowers.mList.clear(); + } + } diff --git a/components/esm/loadbsgn.hpp b/components/esm/loadbsgn.hpp index b0bc28be48..434ddf68ea 100644 --- a/components/esm/loadbsgn.hpp +++ b/components/esm/loadbsgn.hpp @@ -20,6 +20,9 @@ struct BirthSign void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } #endif From baf8eaecb82f75168eaac998c9795faa18c3b72e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 20:46:04 +0200 Subject: [PATCH 138/198] added texture column to birthsign table --- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 26 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index aa097dac65..fbc533779a 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -650,6 +650,31 @@ namespace CSMWorld return true; } }; + + template + struct TextureColumn : public Column + { + TextureColumn() : Column ("Texture", ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mTexture.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mTexture = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 70162ba758..b385c5b4c2 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -96,6 +96,7 @@ CSMWorld::Data::Data() mBirthsigns.addColumn (new StringIdColumn); mBirthsigns.addColumn (new RecordStateColumn); mBirthsigns.addColumn (new NameColumn); + mBirthsigns.addColumn (new TextureColumn); mBirthsigns.addColumn (new DescriptionColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); From 2d2196b0d60d4b874af143e370547e72d14ef3ca Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 21:01:02 +0200 Subject: [PATCH 139/198] Implemented levelled items --- apps/openmw/mwworld/containerstore.cpp | 73 ++++++++++++++++++++++---- apps/openmw/mwworld/containerstore.hpp | 1 + components/esm/loadlevlist.hpp | 15 +++--- 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index a377f2bbbf..8a5662986e 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -14,6 +14,8 @@ #include "../mwbase/world.hpp" #include "../mwbase/scriptmanager.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "manualref.hpp" #include "refdata.hpp" #include "class.hpp" @@ -180,21 +182,72 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const MWWor for (std::vector::const_iterator iter (items.mList.begin()); iter!=items.mList.end(); ++iter) { - ManualRef ref (store, iter->mItem.toString()); - - if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) - { - /// \todo implement leveled item lists - continue; - } - - ref.getPtr().getRefData().setCount (std::abs(iter->mCount)); /// \todo implement item restocking (indicated by negative count) - addImp (ref.getPtr()); + std::string id = iter->mItem.toString(); + addInitialItem(id, iter->mCount); } flagAsModified(); } +void MWWorld::ContainerStore::addInitialItem (const std::string& id, int count, unsigned char failChance, bool topLevel) +{ + count = std::abs(count); /// \todo implement item restocking (indicated by negative count) + + ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id); + + if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) + { + const ESM::ItemLevList* levItem = ref.getPtr().get()->mBase; + const std::vector& items = levItem->mList; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + int playerLevel = MWWorld::Class::get(player).getCreatureStats(player).getLevel(); + + failChance += levItem->mChanceNone; + + if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each) + { + for (int i=0; i (std::rand()) / RAND_MAX; + if (random >= failChance/100.f) + { + std::vector candidates; + int highestLevel = 0; + for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + { + if (it->mLevel > highestLevel) + highestLevel = it->mLevel; + } + + std::pair highest = std::make_pair(-1, ""); + for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + { + if (playerLevel >= it->mLevel + && (levItem->mFlags & ESM::ItemLevList::AllLevels || it->mLevel == highestLevel)) + { + candidates.push_back(it->mId); + if (it->mLevel >= highest.first) + highest = std::make_pair(it->mLevel, it->mId); + } + + } + if (!candidates.size()) + return; + std::string item = candidates[std::rand()%candidates.size()]; + addInitialItem(item, count, failChance, false); + } + } + else + { + ref.getPtr().getRefData().setCount (count); + addImp (ref.getPtr()); + } +} + void MWWorld::ContainerStore::clear() { for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 9d315d27f0..a466c3c2a9 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -53,6 +53,7 @@ namespace MWWorld mutable float mCachedWeight; mutable bool mWeightUpToDate; ContainerStoreIterator addImp (const Ptr& ptr); + void addInitialItem (const std::string& id, int count, unsigned char failChance=0, bool topLevel=true); public: diff --git a/components/esm/loadlevlist.hpp b/components/esm/loadlevlist.hpp index b7db5db360..aa9656d724 100644 --- a/components/esm/loadlevlist.hpp +++ b/components/esm/loadlevlist.hpp @@ -22,17 +22,20 @@ struct LeveledListBase { enum Flags { - AllLevels = 0x01, // Calculate from all levels <= player - // level, not just the closest below - // player. - Each = 0x02 // Select a new item each time this + + Each = 0x01, // Select a new item each time this // list is instantiated, instead of // giving several identical items - }; // (used when a container has more + // (used when a container has more // than one instance of one leveled // list.) + AllLevels = 0x02 // Calculate from all levels <= player + // level, not just the closest below + // player. + }; + int mFlags; - unsigned char mChanceNone; // Chance that none are selected (0-255?) + unsigned char mChanceNone; // Chance that none are selected (0-100) std::string mId; // Record name used to read references. Must be set before load() is From f3c8cd2065ee3f781d3259464e7b1b2943f1f842 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 21:38:53 +0200 Subject: [PATCH 140/198] Don't buy/sell keys which are set to open a lock --- apps/openmw/mwclass/apparatus.cpp | 5 +++++ apps/openmw/mwclass/apparatus.hpp | 2 ++ apps/openmw/mwclass/armor.cpp | 5 +++++ apps/openmw/mwclass/armor.hpp | 2 ++ apps/openmw/mwclass/book.cpp | 5 +++++ apps/openmw/mwclass/book.hpp | 2 ++ apps/openmw/mwclass/clothing.cpp | 5 +++++ apps/openmw/mwclass/clothing.hpp | 2 ++ apps/openmw/mwclass/ingredient.cpp | 5 +++++ apps/openmw/mwclass/ingredient.hpp | 2 ++ apps/openmw/mwclass/light.cpp | 5 +++++ apps/openmw/mwclass/light.hpp | 2 ++ apps/openmw/mwclass/lockpick.cpp | 5 +++++ apps/openmw/mwclass/lockpick.hpp | 2 ++ apps/openmw/mwclass/misc.cpp | 8 ++++++++ apps/openmw/mwclass/misc.hpp | 2 ++ apps/openmw/mwclass/potion.cpp | 5 +++++ apps/openmw/mwclass/potion.hpp | 2 ++ apps/openmw/mwclass/probe.cpp | 5 +++++ apps/openmw/mwclass/probe.hpp | 2 ++ apps/openmw/mwclass/repair.cpp | 5 +++++ apps/openmw/mwclass/repair.hpp | 2 ++ apps/openmw/mwclass/weapon.cpp | 5 +++++ apps/openmw/mwclass/weapon.hpp | 2 ++ apps/openmw/mwgui/tradewindow.cpp | 27 +-------------------------- apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 3 +++ components/esm/loadnpc.hpp | 2 +- 28 files changed, 97 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 851a5ae360..32c1277318 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -159,4 +159,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mAppas.insert(*ref), &cell); } + + bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Apparatus; + } } diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 7045f62d6f..d4917c6186 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -54,6 +54,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 320944d3ce..e62985d3dc 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -315,4 +315,9 @@ namespace MWClass return ref->mBase->mData.mEnchant; } + + bool Armor::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Armor; + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 65f49abb7d..16905d65cc 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -74,6 +74,8 @@ namespace MWClass virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 85b006160b..b658295f85 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -183,4 +183,9 @@ namespace MWClass return ref->mBase->mData.mEnchant; } + + bool Book::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Books; + } } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 29e3de0361..3f083f5525 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -59,6 +59,8 @@ namespace MWClass virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index abad267675..98480f06f2 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -262,4 +262,9 @@ namespace MWClass return ref->mBase->mData.mEnchant; } + + bool Clothing::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Clothing; + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index c3ef22f113..2e5bb424fb 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -68,6 +68,8 @@ namespace MWClass virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 14cf6ff6f9..0afe60e0e2 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -197,4 +197,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mIngreds.insert(*ref), &cell); } + + bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Ingredients; + } } diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 0afd202fb4..d27a7cbb0e 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -56,6 +56,8 @@ namespace MWClass ///< Return name of inventory icon. virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 7466657725..306c6bbb6a 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -203,4 +203,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell); } + + bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Lights; + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 640e1705bd..7d919f75df 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -57,6 +57,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 2015726968..bfbf107565 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -176,4 +176,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell); } + + bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Picks; + } } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 0961b55b24..edd884a3e0 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -57,6 +57,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 8cfac1a686..02307cc021 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -246,4 +246,12 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionSoulgem(ptr)); } + bool Miscellaneous::canSell (const MWWorld::Ptr& item, int npcServices) const + { + MWWorld::LiveCellRef *ref = + item.get(); + + return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc); + } + } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 12a50af19d..ba00900bd0 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -53,6 +53,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 37461ed905..ad2826ea83 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -194,4 +194,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mPotions.insert(*ref), &cell); } + + bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Potions; + } } diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index d595f7e694..845795d0e8 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -52,6 +52,8 @@ namespace MWClass ///< Return name of inventory icon. virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index e4533af655..4ec6a8340b 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -175,4 +175,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mProbes.insert(*ref), &cell); } + + bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Probes; + } } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index d9f90baf6d..75ebaa01cb 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -57,6 +57,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index bafedee88b..36e7068252 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -175,4 +175,9 @@ namespace MWClass { return boost::shared_ptr(new MWWorld::ActionRepair(ptr)); } + + bool Repair::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::RepairItem; + } } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 3083c97e35..a545cf4d60 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -61,6 +61,8 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health /// (default implementation: throw an exceoption) + + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 0a527262f8..3df1ced7df 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -409,4 +409,9 @@ namespace MWClass return ref->mBase->mData.mEnchant; } + + bool Weapon::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return npcServices & ESM::NPC::Weapon; + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 4774bb50be..084ceeca2b 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -73,6 +73,8 @@ namespace MWClass virtual std::string getModel(const MWWorld::Ptr &ptr) const; + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; + virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 81a29e69bd..73904371ed 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -356,32 +356,7 @@ namespace MWGui services = ref->mBase->mAiData.mServices; } - /// \todo what about potions, there doesn't seem to be a flag for them?? - - if (item.getTypeName() == typeid(ESM::Weapon).name()) - return services & ESM::NPC::Weapon; - else if (item.getTypeName() == typeid(ESM::Armor).name()) - return services & ESM::NPC::Armor; - else if (item.getTypeName() == typeid(ESM::Clothing).name()) - return services & ESM::NPC::Clothing; - else if (item.getTypeName() == typeid(ESM::Book).name()) - return services & ESM::NPC::Books; - else if (item.getTypeName() == typeid(ESM::Ingredient).name()) - return services & ESM::NPC::Ingredients; - else if (item.getTypeName() == typeid(ESM::Lockpick).name()) - return services & ESM::NPC::Picks; - else if (item.getTypeName() == typeid(ESM::Probe).name()) - return services & ESM::NPC::Probes; - else if (item.getTypeName() == typeid(ESM::Light).name()) - return services & ESM::NPC::Lights; - else if (item.getTypeName() == typeid(ESM::Apparatus).name()) - return services & ESM::NPC::Apparatus; - else if (item.getTypeName() == typeid(ESM::Repair).name()) - return services & ESM::NPC::RepairItem; - else if (item.getTypeName() == typeid(ESM::Miscellaneous).name()) - return services & ESM::NPC::Misc; - - return false; + return MWWorld::Class::get(item).canSell(item, services); } std::vector TradeWindow::itemsToIgnore() diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 2dfa241b3b..0f8d40e931 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -47,6 +47,11 @@ namespace MWWorld throw std::runtime_error ("class does not represent an actor"); } + bool Class::canSell (const MWWorld::Ptr& item, int npcServices) const + { + return false; + } + MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const { throw std::runtime_error ("class does not have creature stats"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index de4741e38b..49e0ff0032 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -238,6 +238,9 @@ namespace MWWorld virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; + virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; + ///< Determine whether or not \a item can be sold to an npc with the given \a npcServices + virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 46be29961d..b30077f23c 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -35,11 +35,11 @@ struct NPC Apparatus = 0x00100, RepairItem = 0x00200, Misc = 0x00400, + Potions = 0x02000, // Other services Spells = 0x00800, MagicItems = 0x01000, - Potions = 0x02000, Training = 0x04000, // What skills? Spellmaking = 0x08000, Enchanting = 0x10000, From 2362e920f309b272994cd1763f7e668fc7033de8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 12:41:27 -0700 Subject: [PATCH 141/198] Use an unconnected object list for animation sources We'll want the controllers, as the plan is to use their keyframe controllers to animate the actual skeleton used for the meshes. --- apps/openmw/mwrender/animation.cpp | 52 ++++++++++++++++++---------- apps/openmw/mwrender/animation.hpp | 3 +- components/nifogre/ogrenifloader.cpp | 29 +++------------- components/nifogre/ogrenifloader.hpp | 4 ++- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 8ecebc7070..686fbbb848 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -16,6 +16,19 @@ namespace MWRender { +void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects) +{ + for(size_t i = 0;i < objects.mParticles.size();i++) + sceneMgr->destroyParticleSystem(objects.mParticles[i]); + for(size_t i = 0;i < objects.mEntities.size();i++) + sceneMgr->destroyEntity(objects.mEntities[i]); + objects.mControllers.clear(); + objects.mCameras.clear(); + objects.mParticles.clear(); + objects.mEntities.clear(); + objects.mSkelBase = NULL; +} + Animation::Animation(const MWWorld::Ptr &ptr) : mPtr(ptr) , mController(NULL) @@ -40,16 +53,12 @@ Animation::~Animation() if(mInsert) { Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < mObjectList.mParticles.size();i++) - sceneMgr->destroyParticleSystem(mObjectList.mParticles[i]); - for(size_t i = 0;i < mObjectList.mEntities.size();i++) - sceneMgr->destroyEntity(mObjectList.mEntities[i]); + destroyObjectList(sceneMgr, mObjectList); + + for(size_t i = 0;i < mAnimationSources.size();i++) + destroyObjectList(sceneMgr, mAnimationSources[i]); + mAnimationSources.clear(); } - mObjectList.mControllers.clear(); - mObjectList.mCameras.clear(); - mObjectList.mParticles.clear(); - mObjectList.mEntities.clear(); - mObjectList.mSkelBase = NULL; } @@ -57,6 +66,7 @@ void Animation::setAnimationSources(const std::vector &names) { if(!mObjectList.mSkelBase) return; + Ogre::SceneManager *sceneMgr = mInsert->getCreator(); mCurrentAnim = NULL; mCurrentKeys = NULL; @@ -64,19 +74,24 @@ void Animation::setAnimationSources(const std::vector &names) mAccumRoot = NULL; mNonAccumRoot = NULL; mTextKeys.clear(); - mSkeletonSources.clear(); + for(size_t i = 0;i < mAnimationSources.size();i++) + destroyObjectList(sceneMgr, mAnimationSources[i]); + mAnimationSources.clear(); std::vector::const_iterator nameiter; for(nameiter = names.begin();nameiter != names.end();nameiter++) { - Ogre::SkeletonPtr skel = NifOgre::Loader::getSkeleton(*nameiter); - if(skel.isNull()) + mAnimationSources.push_back(NifOgre::Loader::createObjectBase(sceneMgr, *nameiter)); + if(!mAnimationSources.back().mSkelBase) { std::cerr<< "Failed to get skeleton source "<<*nameiter <touch(); + Ogre::Entity *ent = mAnimationSources.back().mSkelBase; + Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName()); Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); while(boneiter.hasMoreElements()) { @@ -92,7 +107,6 @@ void Animation::setAnimationSources(const std::vector &names) mNonAccumRoot = mObjectList.mSkelBase->getSkeleton()->getBone(bone->getName()); } - mSkeletonSources.push_back(skel); for(int i = 0;i < skel->getNumAnimations();i++) { Ogre::Animation *anim = skel->getAnimation(i); @@ -144,9 +158,9 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model bool Animation::hasAnimation(const std::string &anim) { - for(std::vector::const_iterator iter(mSkeletonSources.begin());iter != mSkeletonSources.end();iter++) + for(std::vector::const_iterator iter(mAnimationSources.begin());iter != mAnimationSources.end();iter++) { - if((*iter)->hasAnimation(anim)) + if(iter->mSkelBase->hasAnimationState(anim)) return true; } return false; @@ -413,11 +427,11 @@ void Animation::play(const std::string &groupname, const std::string &start, con try { bool found = false; /* Look in reverse; last-inserted source has priority. */ - for(std::vector::const_reverse_iterator iter(mSkeletonSources.rbegin());iter != mSkeletonSources.rend();iter++) + for(std::vector::const_reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) { - if((*iter)->hasAnimation(groupname)) + if(iter->mSkelBase->hasAnimationState(groupname)) { - mCurrentAnim = (*iter)->getAnimation(groupname); + mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname); mCurrentKeys = &mTextKeys[groupname]; mAnimVelocity = 0.0f; diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 55aaca427c..22ab9fc7eb 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -47,7 +47,7 @@ protected: Ogre::Vector3 mAccumulate; Ogre::Vector3 mLastPosition; - std::vector mSkeletonSources; + std::vector mAnimationSources; NifOgre::TextKeyMap *mCurrentKeys; NifOgre::TextKeyMap::const_iterator mNextKey; @@ -92,6 +92,7 @@ protected: } void createObjectList(Ogre::SceneNode *node, const std::string &model); + static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects); public: Animation(const MWWorld::Ptr &ptr); diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 90139c9f02..d3da77e41e 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1768,35 +1768,14 @@ ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonena } -Ogre::SkeletonPtr Loader::getSkeleton(std::string name, const std::string &group) +ObjectList Loader::createObjectBase(Ogre::SceneManager *sceneMgr, std::string name, const std::string &group) { - Ogre::SkeletonPtr skel; + ObjectList objectlist; Misc::StringUtils::toLower(name); - skel = Ogre::SkeletonManager::getSingleton().getByName(name); - if(!skel.isNull()) - return skel; + NIFObjectLoader::load(sceneMgr, objectlist, name, group); - Nif::NIFFile::ptr nif = Nif::NIFFile::create(name); - if(nif->numRoots() < 1) - { - nif->warn("Found no root nodes in "+name+"."); - return skel; - } - - // The first record is assumed to be the root node - const Nif::Record *r = nif->getRoot(0); - assert(r != NULL); - - const Nif::Node *node = dynamic_cast(r); - if(node == NULL) - { - nif->warn("First record in "+name+" was not a node, but a "+ - r->recName+"."); - return skel; - } - - return NIFSkeletonLoader::createSkeleton(name, group, node); + return objectlist; } } // namespace NifOgre diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index 88cbaf6910..3a7a22f8b1 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -69,7 +69,9 @@ public: std::string name, const std::string &group="General"); - static Ogre::SkeletonPtr getSkeleton(std::string name, const std::string &group="General"); + static ObjectList createObjectBase(Ogre::SceneManager *sceneMgr, + std::string name, + const std::string &group="General"); }; } From 480467b6ebf693004cbc3df2232ff981465a086f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 21:53:11 +0200 Subject: [PATCH 142/198] Reset the 'owner' field for items that were legitimately bought from an NPC. --- apps/openmw/mwgui/tradewindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 73904371ed..7756484fa5 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -257,6 +257,12 @@ namespace MWGui MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition); // success! make the item transfer. + MWWorld::ContainerStore& playerBoughtItems = mWindowManager.getInventoryWindow()->getBoughtItems(); + for (MWWorld::ContainerStoreIterator it = playerBoughtItems.begin(); it != playerBoughtItems.end(); ++it) + { + if (Misc::StringUtils::ciEqual(it->getCellRef().mOwner, MWWorld::Class::get(mPtr).getId(mPtr))) + it->getCellRef().mOwner = ""; + } transferBoughtItems(); mWindowManager.getInventoryWindow()->transferBoughtItems(); From 7494f90301bcf35a6d3560b495b4f61455b05c9c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 13:02:46 -0700 Subject: [PATCH 143/198] Remove an unneeded function --- apps/openmw/mwrender/npcanimation.cpp | 21 +++------------------ apps/openmw/mwrender/npcanimation.hpp | 1 - 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 931b8ef83d..253dbb0ff7 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -50,8 +50,9 @@ const NpcAnimation::PartInfo NpcAnimation::sPartList[NpcAnimation::sPartListSize NpcAnimation::~NpcAnimation() { + Ogre::SceneManager *sceneMgr = mInsert->getCreator(); for(size_t i = 0;i < sPartListSize;i++) - removeObjects(mObjectParts[i]); + destroyObjectList(sceneMgr, mObjectParts[i]); } @@ -374,22 +375,6 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) return ret; } -void NpcAnimation::removeObjects(NifOgre::ObjectList &objects) -{ - assert(&objects != &mObjectList); - - Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < objects.mParticles.size();i++) - sceneMgr->destroyParticleSystem(objects.mParticles[i]); - for(size_t i = 0;i < objects.mEntities.size();i++) - sceneMgr->destroyEntity(objects.mEntities[i]); - objects.mControllers.clear(); - objects.mCameras.clear(); - objects.mParticles.clear(); - objects.mEntities.clear(); - objects.mSkelBase = NULL; -} - void NpcAnimation::removeIndividualPart(int type) { mPartPriorities[type] = 0; @@ -399,7 +384,7 @@ void NpcAnimation::removeIndividualPart(int type) { if(type == sPartList[i].type) { - removeObjects(mObjectParts[i]); + destroyObjectList(mInsert->getCreator(), mObjectParts[i]); break; } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 41c29f7638..b59051a8d6 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -64,7 +64,6 @@ private: void updateParts(bool forceupdate = false); - void removeObjects(NifOgre::ObjectList &objects); void removeIndividualPart(int type); void reserveIndividualPart(int type, int group, int priority); From 44a59e1b87805627390d44d8ba02710476445d7a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 13:03:41 -0700 Subject: [PATCH 144/198] Fix a couple messages --- components/nifogre/ogrenifloader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index d3da77e41e..d02c0816e3 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1092,12 +1092,12 @@ class NIFObjectLoader : Ogre::ManualResourceLoader static void warn(const std::string &msg) { - std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; + std::cerr << "NIFObjectLoader: Warn: " << msg << std::endl; } static void fail(const std::string &msg) { - std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; + std::cerr << "NIFObjectLoader: Fail: "<< msg << std::endl; abort(); } From 9e08497f0200b8ea42ad3e6116b868ebca7adbf6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 7 Apr 2013 22:07:04 +0200 Subject: [PATCH 145/198] Initial container content should inherit the owner of its container --- apps/openmw/mwworld/cells.cpp | 6 +++--- apps/openmw/mwworld/containerstore.cpp | 11 ++++++----- apps/openmw/mwworld/containerstore.hpp | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 5f771be475..4838cfefa5 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -45,7 +45,7 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) Ptr container (&*iter, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->mBase->mInventory, mStore); + iter->mBase->mInventory, container.getCellRef().mOwner, mStore); } for (CellRefList::List::iterator iter ( @@ -55,7 +55,7 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) Ptr container (&*iter, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->mBase->mInventory, mStore); + iter->mBase->mInventory, Class::get(container).getId(container), mStore); } for (CellRefList::List::iterator iter ( @@ -65,7 +65,7 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) Ptr container (&*iter, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->mBase->mInventory, mStore); + iter->mBase->mInventory, Class::get(container).getId(container), mStore); } } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 8a5662986e..05026a98ba 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -177,19 +177,19 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr return it; } -void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const MWWorld::ESMStore& store) +void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, const MWWorld::ESMStore& store) { for (std::vector::const_iterator iter (items.mList.begin()); iter!=items.mList.end(); ++iter) { std::string id = iter->mItem.toString(); - addInitialItem(id, iter->mCount); + addInitialItem(id, owner, iter->mCount); } flagAsModified(); } -void MWWorld::ContainerStore::addInitialItem (const std::string& id, int count, unsigned char failChance, bool topLevel) +void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, unsigned char failChance, bool topLevel) { count = std::abs(count); /// \todo implement item restocking (indicated by negative count) @@ -208,7 +208,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, int count, if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each) { for (int i=0; i Date: Sun, 7 Apr 2013 13:46:29 -0700 Subject: [PATCH 146/198] Update animation source controller targets --- apps/openmw/mwrender/animation.cpp | 14 ++++++++++++++ components/nifogre/ogrenifloader.cpp | 9 ++++----- components/nifogre/ogrenifloader.hpp | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 686fbbb848..f3ecbd6a51 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -78,6 +78,7 @@ void Animation::setAnimationSources(const std::vector &names) destroyObjectList(sceneMgr, mAnimationSources[i]); mAnimationSources.clear(); + Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton(); std::vector::const_iterator nameiter; for(nameiter = names.begin();nameiter != names.end();nameiter++) { @@ -89,6 +90,19 @@ void Animation::setAnimationSources(const std::vector &names) mAnimationSources.pop_back(); continue; } + const NifOgre::ObjectList &objects = mAnimationSources.back(); + + for(size_t i = 0;i < objects.mControllers.size();i++) + { + NifOgre::NodeTargetValue *dstval = dynamic_cast*>(objects.mControllers[i].getDestination().getPointer()); + if(!dstval) continue; + + const Ogre::String &trgtname = dstval->getNode()->getName(); + if(!skelinst->hasBone(trgtname)) continue; + + Ogre::Bone *bone = skelinst->getBone(trgtname); + dstval->setNode(bone); + } Ogre::Entity *ent = mAnimationSources.back().mSkelBase; Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName()); diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index d02c0816e3..a0aefaccc9 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -108,10 +108,9 @@ public: class VisController { public: - class Value : public Ogre::ControllerValue + class Value : public NodeTargetValue { private: - Ogre::Bone *mTarget; std::vector mData; virtual bool calculate(Ogre::Real time) @@ -149,8 +148,8 @@ public: } public: - Value(Ogre::Bone *target, const Nif::NiVisData *data) - : mTarget(target) + Value(Ogre::Node *target, const Nif::NiVisData *data) + : NodeTargetValue(target) , mData(data->mVis) { } @@ -163,7 +162,7 @@ public: virtual void setValue(Ogre::Real time) { bool vis = calculate(time); - setVisible(mTarget, vis); + setVisible(mNode, vis); } }; diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index 3a7a22f8b1..18bbf0200f 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -74,6 +74,24 @@ public: const std::string &group="General"); }; +// FIXME: Should be with other general Ogre extensions. +template +class NodeTargetValue : public Ogre::ControllerValue +{ +protected: + Ogre::Node *mNode; + +public: + NodeTargetValue(Ogre::Node *target) : mNode(target) + { } + + void setNode(Ogre::Node *target) + { mNode = target; } + Ogre::Node *getNode() const + { return mNode; } +}; +typedef Ogre::SharedPtr > NodeTargetValueRealPtr; + } namespace std From 43a501369080f633f829a4b3e64e87b960d738ec Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 7 Apr 2013 23:25:35 +0200 Subject: [PATCH 147/198] added verifier for birthsign record --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/model/tools/birthsigncheck.cpp | 39 ++++++++++++++++++++++ apps/opencs/model/tools/birthsigncheck.hpp | 29 ++++++++++++++++ apps/opencs/model/tools/tools.cpp | 3 ++ 4 files changed, 72 insertions(+) create mode 100644 apps/opencs/model/tools/birthsigncheck.cpp create mode 100644 apps/opencs/model/tools/birthsigncheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 301febfc49..87221d7af5 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -36,6 +36,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck + birthsigncheck ) diff --git a/apps/opencs/model/tools/birthsigncheck.cpp b/apps/opencs/model/tools/birthsigncheck.cpp new file mode 100644 index 0000000000..b673c93ded --- /dev/null +++ b/apps/opencs/model/tools/birthsigncheck.cpp @@ -0,0 +1,39 @@ + +#include "birthsigncheck.hpp" + +#include +#include + +#include + +#include "../world/universalid.hpp" + +CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection& birthsigns) +: mBirthsigns (birthsigns) +{} + +int CSMTools::BirthsignCheckStage::setup() +{ + return mBirthsigns.getSize(); +} + +void CSMTools::BirthsignCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::BirthSign& birthsign = mBirthsigns.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Birthsign, birthsign.mId); + + // test for empty name, description and texture + if (birthsign.mName.empty()) + messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty name"); + + if (birthsign.mDescription.empty()) + messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty description"); + + if (birthsign.mTexture.empty()) + messages.push_back (id.toString() + "|" + birthsign.mId + " is missing a texture"); + + /// \todo test if the texture exists + + /// \todo check data members that can't be edited in the table view +} \ No newline at end of file diff --git a/apps/opencs/model/tools/birthsigncheck.hpp b/apps/opencs/model/tools/birthsigncheck.hpp new file mode 100644 index 0000000000..42b5a6b244 --- /dev/null +++ b/apps/opencs/model/tools/birthsigncheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_BIRTHSIGNCHECK_H +#define CSM_TOOLS_BIRTHSIGNCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that birthsign records are internally consistent + class BirthsignCheckStage : public Stage + { + const CSMWorld::IdCollection& mBirthsigns; + + public: + + BirthsignCheckStage (const CSMWorld::IdCollection& birthsigns); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 45adcf5e49..78796de418 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -18,6 +18,7 @@ #include "racecheck.hpp" #include "soundcheck.hpp" #include "regioncheck.hpp" +#include "birthsigncheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -69,6 +70,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new SoundCheckStage (mData.getSounds())); mVerifier->appendStage (new RegionCheckStage (mData.getRegions())); + + mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns())); } return mVerifier; From 261ea1fe5e137386e4b859bcbae6b519d4fa3b1f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 14:56:23 -0700 Subject: [PATCH 148/198] Implement a KeyframeController --- apps/openmw/mwrender/animation.cpp | 21 ++++-- apps/openmw/mwrender/animation.hpp | 1 + components/nifogre/ogrenifloader.cpp | 107 +++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index f3ecbd6a51..fd7aeac1d0 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -37,6 +37,7 @@ Animation::Animation(const MWWorld::Ptr &ptr) , mNonAccumRoot(NULL) , mAccumulate(Ogre::Vector3::ZERO) , mLastPosition(0.0f) + , mCurrentControllers(NULL) , mCurrentKeys(NULL) , mCurrentAnim(NULL) , mCurrentTime(0.0f) @@ -68,6 +69,7 @@ void Animation::setAnimationSources(const std::vector &names) return; Ogre::SceneManager *sceneMgr = mInsert->getCreator(); + mCurrentControllers = &mObjectList.mControllers; mCurrentAnim = NULL; mCurrentKeys = NULL; mAnimVelocity = 0.0f; @@ -78,6 +80,7 @@ void Animation::setAnimationSources(const std::vector &names) destroyObjectList(sceneMgr, mAnimationSources[i]); mAnimationSources.clear(); + Ogre::SharedPtr > ctrlval(OGRE_NEW AnimationValue(this)); Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton(); std::vector::const_iterator nameiter; for(nameiter = names.begin();nameiter != names.end();nameiter++) @@ -90,7 +93,7 @@ void Animation::setAnimationSources(const std::vector &names) mAnimationSources.pop_back(); continue; } - const NifOgre::ObjectList &objects = mAnimationSources.back(); + NifOgre::ObjectList &objects = mAnimationSources.back(); for(size_t i = 0;i < objects.mControllers.size();i++) { @@ -104,7 +107,13 @@ void Animation::setAnimationSources(const std::vector &names) dstval->setNode(bone); } - Ogre::Entity *ent = mAnimationSources.back().mSkelBase; + for(size_t i = 0;i < objects.mControllers.size();i++) + { + if(objects.mControllers[i].getSource().isNull()) + objects.mControllers[i].setSource(ctrlval); + } + + Ogre::Entity *ent = objects.mSkelBase; Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName()); Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); while(boneiter.hasMoreElements()) @@ -167,6 +176,7 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model if(mObjectList.mControllers[i].getSource().isNull()) mObjectList.mControllers[i].setSource(ctrlval); } + mCurrentControllers = &mObjectList.mControllers; } @@ -441,12 +451,13 @@ void Animation::play(const std::string &groupname, const std::string &start, con try { bool found = false; /* Look in reverse; last-inserted source has priority. */ - for(std::vector::const_reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) + for(std::vector::reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) { if(iter->mSkelBase->hasAnimationState(groupname)) { mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname); mCurrentKeys = &mTextKeys[groupname]; + mCurrentControllers = &iter->mControllers; mAnimVelocity = 0.0f; if(mNonAccumRoot) @@ -495,8 +506,8 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) if(!handleEvent(time, evt)) break; } - for(size_t i = 0;i < mObjectList.mControllers.size();i++) - mObjectList.mControllers[i].update(); + for(size_t i = 0;i < mCurrentControllers->size();i++) + (*mCurrentControllers)[i].update(); return movement; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 22ab9fc7eb..aee139bd67 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -49,6 +49,7 @@ protected: std::vector mAnimationSources; + std::vector > *mCurrentControllers; NifOgre::TextKeyMap *mCurrentKeys; NifOgre::TextKeyMap::const_iterator mNextKey; Ogre::Animation *mCurrentAnim; diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index a0aefaccc9..e7bf820b8e 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -169,6 +169,101 @@ public: typedef DefaultFunction Function; }; +class KeyframeController +{ +public: + class Value : public NodeTargetValue + { + private: + Nif::QuaternionKeyList mRotations; + Nif::Vector3KeyList mTranslations; + Nif::FloatKeyList mScales; + + public: + Value(Ogre::Node *target, const Nif::NiKeyframeData *data) + : NodeTargetValue(target) + , mRotations(data->mRotations) + , mTranslations(data->mTranslations) + , mScales(data->mScales) + { } + + virtual Ogre::Real getValue() const + { + // Should not be called + return 0.0f; + } + + virtual void setValue(Ogre::Real time) + { + if(mRotations.mKeys.size() > 0) + { + if(time <= mRotations.mKeys.front().mTime) + mNode->setOrientation(mRotations.mKeys.front().mValue); + else if(time >= mRotations.mKeys.back().mTime) + mNode->setOrientation(mRotations.mKeys.back().mValue); + else + { + Nif::QuaternionKeyList::VecType::const_iterator iter(mRotations.mKeys.begin()+1); + for(;iter != mRotations.mKeys.end();iter++) + { + if(iter->mTime < time) + continue; + + Nif::QuaternionKeyList::VecType::const_iterator last(iter-1); + float a = (time-last->mTime) / (iter->mTime-last->mTime); + mNode->setOrientation(Ogre::Quaternion::nlerp(a, last->mValue, iter->mValue)); + break; + } + } + } + if(mTranslations.mKeys.size() > 0) + { + if(time <= mTranslations.mKeys.front().mTime) + mNode->setPosition(mTranslations.mKeys.front().mValue); + else if(time >= mTranslations.mKeys.back().mTime) + mNode->setPosition(mTranslations.mKeys.back().mValue); + else + { + Nif::Vector3KeyList::VecType::const_iterator iter(mTranslations.mKeys.begin()+1); + for(;iter != mTranslations.mKeys.end();iter++) + { + if(iter->mTime < time) + continue; + + Nif::Vector3KeyList::VecType::const_iterator last(iter-1); + float a = (time-last->mTime) / (iter->mTime-last->mTime); + mNode->setPosition(last->mValue + ((iter->mValue - last->mValue)*a)); + break; + } + } + } + if(mScales.mKeys.size() > 0) + { + if(time <= mScales.mKeys.front().mTime) + mNode->setScale(Ogre::Vector3(mScales.mKeys.front().mValue)); + else if(time >= mScales.mKeys.back().mTime) + mNode->setScale(Ogre::Vector3(mScales.mKeys.back().mValue)); + else + { + Nif::FloatKeyList::VecType::const_iterator iter(mScales.mKeys.begin()+1); + for(;iter != mScales.mKeys.end();iter++) + { + if(iter->mTime < time) + continue; + + Nif::FloatKeyList::VecType::const_iterator last(iter-1); + float a = (time-last->mTime) / (iter->mTime-last->mTime); + mNode->setScale(Ogre::Vector3(last->mValue + ((iter->mValue - last->mValue)*a))); + break; + } + } + } + } + }; + + typedef DefaultFunction Function; +}; + class UVController { public: @@ -1546,6 +1641,18 @@ class NIFObjectLoader : Ogre::ManualResourceLoader objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); } + else if(ctrl->recType == Nif::RC_NiKeyframeController) + { + const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); + + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); + Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); + Ogre::ControllerValueRealPtr srcval; /* Filled in later */ + Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr())); + Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, false)); + + objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + } ctrl = ctrl->next; } From 3c633e275e99852ea48e8b8e1e49f3145c63e640 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 15:42:07 -0700 Subject: [PATCH 149/198] Don't create a controller for empty keyframe data --- components/nifogre/ogrenifloader.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index e7bf820b8e..e06a23b5b9 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1644,14 +1644,16 @@ class NIFObjectLoader : Ogre::ManualResourceLoader else if(ctrl->recType == Nif::RC_NiKeyframeController) { const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); + if(!key->data.empty()) + { + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); + Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); + Ogre::ControllerValueRealPtr srcval; /* Filled in later */ + Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr())); + Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, false)); - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); - Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); - Ogre::ControllerValueRealPtr srcval; /* Filled in later */ - Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr())); - Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, false)); - - objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + objectlist.mControllers.push_back(Ogre::Controller(srcval, dstval, func)); + } } ctrl = ctrl->next; } From 7baca30a1d10bd0cef7b49e59be39e7df92692e2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 16:21:45 -0700 Subject: [PATCH 150/198] Only get the non-accum root's keyframe when updating positions The actual animation pose is now handled by the controllers, based on the current animation time. --- apps/openmw/mwrender/animation.cpp | 80 ++++++++++++++---------------- apps/openmw/mwrender/animation.hpp | 9 ++-- 2 files changed, 40 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index fd7aeac1d0..72f7ebaf2e 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -263,28 +263,6 @@ void Animation::calcAnimVelocity() } } -void Animation::applyAnimation(const Ogre::Animation *anim, float time, Ogre::SkeletonInstance *skel) -{ - Ogre::TimeIndex timeindex = anim->_getTimeIndex(time); - Ogre::Animation::NodeTrackIterator tracks = anim->getNodeTrackIterator(); - while(tracks.hasMoreElements()) - { - Ogre::NodeAnimationTrack *track = tracks.getNext(); - const Ogre::String &targetname = track->getAssociatedNode()->getName(); - if(!skel->hasBone(targetname)) - continue; - Ogre::Bone *bone = skel->getBone(targetname); - bone->setOrientation(Ogre::Quaternion::IDENTITY); - bone->setPosition(Ogre::Vector3::ZERO); - bone->setScale(Ogre::Vector3::UNIT_SCALE); - track->applyToNode(bone, timeindex); - } - - // HACK: Dirty the animation state set so that Ogre will apply the - // transformations to entities this skeleton instance is shared with. - mObjectList.mSkelBase->getAllAnimationStates()->_notifyDirty(); -} - static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone) { if(skelsrc->hasBone(bone->getName())) @@ -323,24 +301,29 @@ void Animation::updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Og } -Ogre::Vector3 Animation::updatePosition(float time) +Ogre::Vector3 Animation::updatePosition() { - if(mLooping) - mCurrentTime = std::fmod(std::max(time, 0.0f), mCurrentAnim->getLength()); - else - mCurrentTime = std::min(mCurrentAnim->getLength(), std::max(time, 0.0f)); - applyAnimation(mCurrentAnim, mCurrentTime, mObjectList.mSkelBase->getSkeleton()); + Ogre::Vector3 posdiff; - Ogre::Vector3 posdiff = Ogre::Vector3::ZERO; - if(mNonAccumRoot) + Ogre::TransformKeyFrame kf(0, mCurrentTime); + Ogre::Animation::NodeTrackIterator trackiter = mCurrentAnim->getNodeTrackIterator(); + while(trackiter.hasMoreElements()) { - /* Get the non-accumulation root's difference from the last update. */ - posdiff = (mNonAccumRoot->getPosition() - mLastPosition) * mAccumulate; - - /* Translate the accumulation root back to compensate for the move. */ - mLastPosition += posdiff; - mAccumRoot->setPosition(-mLastPosition); + const Ogre::NodeAnimationTrack *track = trackiter.getNext(); + if(track->getAssociatedNode()->getName() == mNonAccumRoot->getName()) + { + track->getInterpolatedKeyFrame(mCurrentAnim->_getTimeIndex(mCurrentTime), &kf); + break; + } } + + /* Get the non-accumulation root's difference from the last update. */ + posdiff = (kf.getTranslate() - mLastPosition) * mAccumulate; + + /* Translate the accumulation root back to compensate for the move. */ + mLastPosition += posdiff; + mAccumRoot->setPosition(-mLastPosition); + return posdiff; } @@ -486,11 +469,14 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) timepassed *= mAnimSpeedMult; while(mCurrentAnim && mPlaying) { - float targetTime = std::min(mStopTime, mCurrentTime+timepassed); + float targetTime = mCurrentTime + timepassed; if(mNextKey == mCurrentKeys->end() || mNextKey->first > targetTime) { - movement += updatePosition(targetTime); - mPlaying = (mLooping || mStopTime > targetTime); + mCurrentTime = std::min(mStopTime, targetTime); + if(mNonAccumRoot) + movement += updatePosition(); + mPlaying = (mLooping || mStopTime > mCurrentTime); + timepassed = targetTime - mCurrentTime; break; } @@ -498,10 +484,11 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) const std::string &evt = mNextKey->second; mNextKey++; - movement += updatePosition(time); - mPlaying = (mLooping || mStopTime > time); - - timepassed = targetTime - time; + mCurrentTime = time; + if(mNonAccumRoot) + movement += updatePosition(); + mPlaying = (mLooping || mStopTime > mCurrentTime); + timepassed = targetTime - mCurrentTime; if(!handleEvent(time, evt)) break; @@ -509,6 +496,13 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) for(size_t i = 0;i < mCurrentControllers->size();i++) (*mCurrentControllers)[i].update(); + if(mObjectList.mSkelBase) + { + // HACK: Dirty the animation state set so that Ogre will apply the + // transformations to entities this skeleton instance is shared with. + mObjectList.mSkelBase->getAllAnimationStates()->_notifyDirty(); + } + return movement; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index aee139bd67..2fcc1e8f70 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -63,16 +63,13 @@ protected: void calcAnimVelocity(); - /* Applies the given animation to the given skeleton instance, using the specified time. */ - void applyAnimation(const Ogre::Animation *anim, float time, Ogre::SkeletonInstance *skel); - /* Updates a skeleton instance so that all bones matching the source skeleton (based on * bone names) are positioned identically. */ void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel); - /* Updates the animation to the specified time, and returns the movement - * vector since the last update or reset. */ - Ogre::Vector3 updatePosition(float time); + /* Updates the position of the accum root node for the current time, and + * returns the wanted movement vector from the previous update. */ + Ogre::Vector3 updatePosition(); /* Resets the animation to the time of the specified start marker, without * moving anything, and set the end time to the specified stop marker. If From dba7308248ef270a5a138c2f0470b9412e13e414 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 17:16:49 -0700 Subject: [PATCH 151/198] Recognize NiParticleRotation --- components/nifogre/ogrenifloader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index e06a23b5b9..ac1e8e056e 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1487,13 +1487,17 @@ class NIFObjectLoader : Ogre::ManualResourceLoader 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) + { + // TODO: Implement (Ogre::RotationAffector?) + } else if(e->recType == Nif::RC_NiParticleColorModifier) { // TODO: Implement (Ogre::ColourInterpolatorAffector?) } else if(e->recType == Nif::RC_NiGravity) { - // TODO: Implement (Ogre::LinearForceAffector?) + // TODO: Implement } else warn("Unhandled particle modifier "+e->recName); From c6c67a1bb49d22d93f6c9f6bf5859ddc4c5629f2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 7 Apr 2013 18:15:23 -0700 Subject: [PATCH 152/198] Read NiGravity fields --- components/nif/controlled.hpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 08c47defee..6acb8ff201 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -98,12 +98,23 @@ public: class NiGravity : public Controlled { public: + float mForce; + /* 0 - Wind (fixed direction) + * 1 - Point (fixed origin) + */ + int mType; + Ogre::Vector3 mPosition; + Ogre::Vector3 mDirection; + void read(NIFStream *nif) { Controlled::read(nif); - // two floats, one int, six floats - nif->skip(9*4); + /*unknown*/nif->getFloat(); + mForce = nif->getFloat(); + mType = nif->getUInt(); + mPosition = nif->getVector3(); + mDirection = nif->getVector3(); } }; From 08d43fe21787501b5a572c946268e8e2874b2410 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 Apr 2013 05:48:52 -0700 Subject: [PATCH 153/198] Make the getHeadNode method more general --- apps/openmw/mwrender/animation.cpp | 12 ++++++++++++ apps/openmw/mwrender/animation.hpp | 2 ++ apps/openmw/mwrender/characterpreview.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 5 ----- apps/openmw/mwrender/npcanimation.hpp | 2 -- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 72f7ebaf2e..067e856720 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -180,6 +180,18 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model } +Ogre::Node *Animation::getNode(const std::string &name) +{ + if(mObjectList.mSkelBase) + { + Ogre::SkeletonInstance *skel = mObjectList.mSkelBase->getSkeleton(); + if(skel->hasBone(name)) + return skel->getBone(name); + } + return NULL; +} + + bool Animation::hasAnimation(const std::string &anim) { for(std::vector::const_iterator iter(mAnimationSources.begin());iter != mAnimationSources.end();iter++) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 2fcc1e8f70..cfef28f16c 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -113,6 +113,8 @@ public: void play(const std::string &groupname, const std::string &start, const std::string &stop, bool loop); virtual Ogre::Vector3 runAnimation(float timepassed); + + Ogre::Node *getNode(const std::string &name); }; } diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 843bcf007b..616543a7d4 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -201,7 +201,7 @@ namespace MWRender void RaceSelectionPreview::updateCamera() { Ogre::Vector3 scale = mNode->getScale(); - Ogre::Vector3 headOffset = mAnimation->getHeadNode()->_getDerivedPosition(); + Ogre::Vector3 headOffset = mAnimation->getNode("Bip01 Head")->_getDerivedPosition(); headOffset = mNode->convertLocalToWorldPosition(headOffset); mCamera->setPosition(headOffset + mPosition * scale); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 253dbb0ff7..d7620a8de5 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -451,9 +451,4 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vectorgetSkeleton()->getBone("Bip01 Head"); -} - } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index b59051a8d6..224d174f43 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -78,8 +78,6 @@ public: virtual Ogre::Vector3 runAnimation(float timepassed); - Ogre::Node* getHeadNode(); - void forceUpdate() { updateParts(true); } }; From a5c868c9f58c26210da7f818fd4449acb7a9a7e4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 8 Apr 2013 14:54:19 +0200 Subject: [PATCH 154/198] Create a separate vertex buffer for each UV set --- components/nifogre/ogrenifloader.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 8f9d69f6e2..a94f469010 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -992,17 +992,19 @@ class NIFMeshLoader : Ogre::ManualResourceLoader size_t numUVs = data->uvlist.size(); if(numUVs) { - size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); - vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size()*numUVs, - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); for(size_t i = 0;i < numUVs;i++) { + size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); + vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size(), + Ogre::HardwareBuffer::HBU_STATIC); + const std::vector &uvlist = data->uvlist[i]; - vbuf->writeData(i*srcVerts.size()*elemSize, elemSize*srcVerts.size(), &uvlist[0], true); - decl->addElement(nextBuf, i*srcVerts.size()*elemSize, Ogre::VET_FLOAT2, + + vbuf->writeData(0, elemSize*srcVerts.size(), &uvlist[0], true); + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i); + bind->setBinding(nextBuf++, vbuf); } - bind->setBinding(nextBuf++, vbuf); } // Triangle faces From 343e2027af0797db178967ca36765d26373ac138 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 8 Apr 2013 15:17:30 +0200 Subject: [PATCH 155/198] Support NIF detail maps --- components/nifogre/ogrenifloader.cpp | 15 ++++++++++++++- files/materials/objects.mat | 16 +++++++++++++--- files/materials/objects.shader | 17 +++++++++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index a94f469010..9244ac6ccc 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -749,16 +749,29 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); + instance->setProperty("detailMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DetailTexture])); instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); if (!texName[Nif::NiTexturingProperty::GlowTexture].empty()) { instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true))); instance->setProperty("emissiveMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::GlowTexture].uvSet))); } + if (!texName[Nif::NiTexturingProperty::DetailTexture].empty()) + { + instance->setProperty("use_detail_map", sh::makeProperty(new sh::BooleanValue(true))); + instance->setProperty("detailMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::DetailTexture].uvSet))); + } + if (!texName[Nif::NiTexturingProperty::BumpTexture].empty()) + { + // force automips on normal maps for now + instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture] + " 4")); + } + for(int i = 1;i < 7;i++) { - if(!texName[i].empty()) + if(!texName[i].empty() && (i == Nif::NiTexturingProperty::DarkTexture || i == Nif::NiTexturingProperty::DecalTexture + || i == Nif::NiTexturingProperty::GlossTexture)) warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)+"\n"); } diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 49df4e3949..994a18ea94 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -9,9 +9,10 @@ material openmw_objects_base normalMap emissiveMap use_emissive_map false + use_detail_map false emissiveMapUVSet 0 + detailMapUVSet 0 - is_transparent false // real transparency, alpha rejection doesn't count here scene_blend default depth_write default depth_check default @@ -26,10 +27,11 @@ material openmw_objects_base shader_properties { vertexcolor_mode $vertmode - is_transparent $is_transparent normalMap $normalMap emissiveMapUVSet $emissiveMapUVSet + detailMapUVSet $detailMapUVSet emissiveMap $emissiveMap + detailMap $detailMap } diffuse $diffuse @@ -51,7 +53,7 @@ material openmw_objects_base texture_unit normalMap { - direct_texture $normalMap + texture $normalMap } texture_unit emissiveMap @@ -61,6 +63,14 @@ material openmw_objects_base direct_texture $emissiveMap tex_coord_set $emissiveMapUVSet } + + texture_unit detailMap + { + create_in_ffp $use_detail_map + colour_op_ex modulate_x2 src_current src_texture + direct_texture $detailMap + tex_coord_set $detailMapUVSet + } texture_unit shadowMap0 { diff --git a/files/materials/objects.shader b/files/materials/objects.shader index d0e8173733..aa7f006a22 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -16,9 +16,10 @@ #define NORMAL_MAP @shPropertyHasValue(normalMap) #define EMISSIVE_MAP @shPropertyHasValue(emissiveMap) +#define DETAIL_MAP @shPropertyHasValue(detailMap) // right now we support 2 UV sets max. implementing them is tedious, and we're probably not going to need more -#define SECOND_UV_SET @shPropertyString(emissiveMapUVSet) +#define SECOND_UV_SET (@shPropertyString(emissiveMapUVSet) || @shPropertyString(detailMapUVSet)) // if normal mapping is enabled, we force pixel lighting #define VERTEX_LIGHTING (!@shPropertyHasValue(normalMap)) @@ -236,6 +237,10 @@ shSampler2D(emissiveMap) #endif +#if DETAIL_MAP + shSampler2D(detailMap) +#endif + shInput(float4, UV) #if NORMAL_MAP @@ -313,6 +318,14 @@ { shOutputColour(0) = shSample(diffuseMap, UV.xy); +#if DETAIL_MAP +#if @shPropertyString(detailMapUVSet) + shOutputColour(0) *= shSample(detailMap, UV.zw)*2; +#else + shOutputColour(0) *= shSample(detailMap, UV.xy)*2; +#endif +#endif + #if NORMAL_MAP float3 normal = normalPassthrough; float3 binormal = cross(tangentPassthrough.xyz, normal.xyz); @@ -419,7 +432,7 @@ #endif #if EMISSIVE_MAP - #if SECOND_UV_SET + #if @shPropertyString(emissiveMapUVSet) shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz; #else shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz; From a7de870a443bb602ea45515f312ed730f46045b3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 8 Apr 2013 16:21:18 +0200 Subject: [PATCH 156/198] Fix mercenary not updating its profit when item was dragged onto the player avatar --- apps/openmw/mwgui/inventorywindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 001f42bd11..c744fcf6d9 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -150,6 +150,7 @@ namespace MWGui it = invStore.add(ptr); (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); ptr = *it; + mDragAndDrop->mDraggedFrom->notifyItemDragged(ptr, -mDragAndDrop->mDraggedCount); } /// \todo scripts From d0bcf830919ec034f40f213404be618bc588fefc Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 8 Apr 2013 16:30:18 +0200 Subject: [PATCH 157/198] Adjust player position to ground after using travel services --- apps/openmw/mwgui/travelwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 465f588b8a..2508498fa0 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -156,6 +156,7 @@ namespace MWGui MWBase::Environment::get().getWorld()->advanceTime(time); } MWBase::Environment::get().getWorld()->moveObject(player,*cell,pos.pos[0],pos.pos[1],pos.pos[2]); + MWWorld::Class::get(player).adjustPosition(player); mWindowManager.removeGuiMode(GM_Travel); mWindowManager.removeGuiMode(GM_Dialogue); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0); From 50932a7a6bf52281aaa37242e53d0d84739a80ac Mon Sep 17 00:00:00 2001 From: Glorf Date: Mon, 8 Apr 2013 17:50:03 +0200 Subject: [PATCH 158/198] Finished bugfix #691 --- apps/openmw/mwclass/armor.cpp | 47 ++++++++++++++------------------ apps/openmw/mwclass/clothing.cpp | 31 ++++++++++++--------- apps/openmw/mwclass/weapon.cpp | 42 +++++++--------------------- 3 files changed, 49 insertions(+), 71 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 496e695450..f6392941d6 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -321,15 +321,10 @@ namespace MWClass const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { + std::vector parts = it->get()->mBase->mParts.mParts; + if(*slot == MWWorld::InventoryStore::Slot_Helmet) { - std::vector parts; - if(it.getType() == MWWorld::ContainerStore::Type_Clothing) - parts = it->get()->mBase->mParts.mParts; - else - parts = it->get()->mBase->mParts.mParts; - - bool allow = true; for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) { if((*itr).mPart == ESM::PRT_Head) @@ -337,41 +332,41 @@ namespace MWClass if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}"); - allow = false; - break; + return false; } } - - if(!allow) - break; } if (*slot == MWWorld::InventoryStore::Slot_Boots) { - bool allow = true; - std::vector parts; - if(it.getType() == MWWorld::ContainerStore::Type_Clothing) - parts = it->get()->mBase->mParts.mParts; - else - parts = it->get()->mBase->mParts.mParts; for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) { if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) { - allow = false; - // Only notify the player, not npcs if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) - { MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}"); - } - break; + return false; } } - - if(!allow) - return false; } + } + if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft) + { + MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + + if(weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + weapon->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + weapon->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + { + //unequip twohanded item + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + } + return true; } } return true; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 77a7557bf6..318515a7b1 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -267,32 +267,37 @@ namespace MWClass const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { + std::vector parts = it->get()->mBase->mParts.mParts; + + if(*slot == MWWorld::InventoryStore::Slot_Helmet) + { + for(std::vector::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 false; + } + } + } + if (*slot == MWWorld::InventoryStore::Slot_Boots) { - bool allow = true; - std::vector parts; - if(it.getType() == MWWorld::ContainerStore::Type_Clothing) - parts = it->get()->mBase->mParts.mParts; - else - parts = it->get()->mBase->mParts.mParts; for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) { if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) { - allow = false; - // Only notify the player, not npcs if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) { MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}"); } - break; + + return false; } } - - if(!allow) - return false; } - } } return true; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 51e8130039..a0a8b7e874 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -411,41 +411,19 @@ namespace MWClass { if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) { - if (it.getType() == MWWorld::ContainerStore::Type_Weapon) + if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + it->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + it->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + it->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + it->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) { - if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - it->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - it->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - it->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - it->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) - { - //unequip lefthand item - invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); - } - } - } - if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft) - { - MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - - if (weapon.getType() == MWWorld::ContainerStore::Type_Weapon) - { - if(weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - weapon->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - weapon->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) - { - //unequip twohanded item - invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); - } + //unequip lefthand item + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); } + return true; } - return true; } return false; } From 194ca2584dfced9e807c1c5865eb3b5600a723e0 Mon Sep 17 00:00:00 2001 From: Glorf Date: Mon, 8 Apr 2013 17:53:41 +0200 Subject: [PATCH 159/198] Small azura's star fix --- apps/openmw/mwmechanics/enchanting.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index d92acdafc0..a38cb0037b 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -53,14 +53,18 @@ namespace MWMechanics bool Enchanting::create() { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); ESM::Enchantment enchantment; enchantment.mData.mCharge = getGemCharge(); - //Exception for Azura Star, it's not destroyed after enchanting + mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); + + //Exception for Azura Star, new one will be added after enchanting if(boost::iequals(mSoulGemPtr.get()->mBase->mId, "Misc_SoulGem_Azura")) - mSoulGemPtr.getCellRef().mSoul=""; - else - mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1); + { + MWWorld::ManualRef azura (MWBase::Environment::get().getWorld()->getStore(), "Misc_SoulGem_Azura"); + MWWorld::Class::get (player).getContainerStore (player).add (azura.getPtr()); + } if(mSelfEnchanting) { @@ -87,7 +91,6 @@ namespace MWMechanics MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId); ref.getPtr().getRefData().setCount (mOldItemCount-1); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Class::get (player).getContainerStore (player).add (ref.getPtr()); if(!mSelfEnchanting) payForEnchantment(); From 23097ac9dc3b0046471bb1ebce1238dc5a97af61 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 Apr 2013 09:47:03 -0700 Subject: [PATCH 160/198] Minor cleanup of NiMorphData --- components/nif/data.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 0804b53ae2..bd109041f1 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -398,16 +398,13 @@ struct NiMorphData : public Record { int morphCount = nif->getInt(); int vertCount = nif->getInt(); - nif->getChar(); + /*relative targets?*/nif->getChar(); mMorphs.resize(morphCount); for(int i = 0;i < morphCount;i++) { mMorphs[i].mData.read(nif, true); - - mMorphs[i].mVertices.resize(vertCount); - for(int j = 0;j < vertCount;j++) - mMorphs[i].mVertices[j] = nif->getVector3(); + nif->getVector3s(mMorphs[i].mVertices, vertCount); } } }; From 2f52df22cea1558074457146f67b8e22516e5976 Mon Sep 17 00:00:00 2001 From: Glorf Date: Mon, 8 Apr 2013 19:00:38 +0200 Subject: [PATCH 161/198] Bugfix #553 --- apps/openmw/mwgui/journalwindow.cpp | 6 ------ apps/openmw/mwgui/journalwindow.hpp | 1 - apps/openmw/mwinput/inputmanagerimp.cpp | 6 ++++++ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index ba39b01012..f33cfd353f 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -114,15 +114,9 @@ MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) //displayLeftText(list.front()); } -void MWGui::JournalWindow::close() -{ - MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); -} - void MWGui::JournalWindow::open() { mPageNumber = 0; - MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); if(MWBase::Environment::get().getJournal()->begin()!=MWBase::Environment::get().getJournal()->end()) { book journal; diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index cd1ff7ebbd..f68cca46e9 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -16,7 +16,6 @@ namespace MWGui public: JournalWindow(MWBase::WindowManager& parWindowManager); virtual void open(); - virtual void close(); private: void displayLeftText(std::string text); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 0ed49cd7f7..c23106be1a 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -656,9 +656,15 @@ namespace MWInput bool gameMode = !mWindows.isGuiMode(); if(gameMode) + { + MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); mWindows.pushGuiMode(MWGui::GM_Journal); + } else if(mWindows.getMode() == MWGui::GM_Journal) + { + MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); mWindows.popGuiMode(); + } // .. but don't touch any other mode. } From 7c22e123f4c6fb37f27f874749096a4b9a8b4558 Mon Sep 17 00:00:00 2001 From: Glorf Date: Mon, 8 Apr 2013 22:10:55 +0200 Subject: [PATCH 162/198] Bugfix #691 changes --- apps/openmw/mwclass/armor.cpp | 27 +++++------------ apps/openmw/mwclass/armor.hpp | 3 +- apps/openmw/mwclass/clothing.cpp | 24 ++++------------ apps/openmw/mwclass/clothing.hpp | 3 +- apps/openmw/mwclass/weapon.cpp | 40 +++++++------------------- apps/openmw/mwclass/weapon.hpp | 3 +- apps/openmw/mwworld/actionequip.cpp | 11 +++++-- apps/openmw/mwworld/class.cpp | 4 +-- apps/openmw/mwworld/class.hpp | 4 +-- apps/openmw/mwworld/inventorystore.cpp | 13 +++++++-- 10 files changed, 53 insertions(+), 79 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index f6392941d6..ddab6f7548 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -292,25 +292,13 @@ namespace MWClass ref->mBase = record; } - bool Armor::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Armor::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const { MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); // slots that this item can be equipped in std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); - // retrieve ContainerStoreIterator to the item - MWWorld::ContainerStoreIterator it = invStore.begin(); - for (; it != invStore.end(); ++it) - { - if (*it == item) - { - break; - } - } - - assert(it != invStore.end()); - std::string npcRace = npc.get()->mBase->mRace; for (std::vector::const_iterator slot=slots.first.begin(); @@ -321,7 +309,7 @@ namespace MWClass const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { - std::vector parts = it->get()->mBase->mParts.mParts; + std::vector parts = item.get()->mBase->mParts.mParts; if(*slot == MWWorld::InventoryStore::Slot_Helmet) { @@ -332,7 +320,7 @@ namespace MWClass if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}"); - return false; + return 0; } } } @@ -345,7 +333,7 @@ namespace MWClass { if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}"); - return false; + return 0; } } } @@ -363,13 +351,12 @@ namespace MWClass weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) { - //unequip twohanded item - invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + return 3; } - return true; + return 1; } } - return true; + return 1; } boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index bb07e42b03..96c72848cc 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -67,7 +67,8 @@ namespace MWClass virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; - virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + virtual int canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) 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 boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 318515a7b1..58c4a2c5c6 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -238,25 +238,11 @@ namespace MWClass ref->mBase = record; } - bool Clothing::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Clothing::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); - // slots that this item can be equipped in std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); - // retrieve ContainerStoreIterator to the item - MWWorld::ContainerStoreIterator it = invStore.begin(); - for (; it != invStore.end(); ++it) - { - if (*it == item) - { - break; - } - } - - assert(it != invStore.end()); - std::string npcRace = npc.get()->mBase->mRace; for (std::vector::const_iterator slot=slots.first.begin(); @@ -267,7 +253,7 @@ namespace MWClass const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { - std::vector parts = it->get()->mBase->mParts.mParts; + std::vector parts = item.get()->mBase->mParts.mParts; if(*slot == MWWorld::InventoryStore::Slot_Helmet) { @@ -278,7 +264,7 @@ namespace MWClass if(npc == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}"); - return false; + return 0; } } } @@ -294,13 +280,13 @@ namespace MWClass MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}"); } - return false; + return 0; } } } } } - return true; + return 1; } boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 4978fa2288..eb8d801996 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -61,7 +61,8 @@ namespace MWClass virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; - virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + virtual int canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) 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 boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index a0a8b7e874..a0cacaf6bd 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -384,48 +384,30 @@ namespace MWClass ref->mBase = record; } - bool Weapon::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Weapon::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); - - // slots that this item can be equipped in std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); - // retrieve ContainerStoreIterator to the item - MWWorld::ContainerStoreIterator it = invStore.begin(); - for (; it != invStore.end(); ++it) - { - if (*it == item) - { - break; - } - } - - assert(it != invStore.end()); - - std::string npcRace = npc.get()->mBase->mRace; - // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) { if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) { - if(it->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - it->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - it->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - it->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - it->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - it->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + if(item.get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + item.get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + item.get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + item.get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + item.get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + item.get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + item.get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) { - //unequip lefthand item - invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + return 2; } - return true; + return 1; } } - return false; + return 0; } boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 922cd165f2..01686b09cc 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -67,7 +67,8 @@ namespace MWClass virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; - virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; + virtual int canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) 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 boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index c147113fc6..51d0de6fe8 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -43,8 +43,15 @@ namespace MWWorld for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) { - if(!MWWorld::Class::get(getTarget()).canEquip(actor,getTarget())) - break; + switch(MWWorld::Class::get (*it).canBeEquipped (actor, *it)) + { + case 0: + return; + case 2: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + case 3: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + } // if all slots are occupied, replace the last slot if (slot == --slots.first.end()) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index ee2072cf09..a0067f5d2e 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -259,9 +259,9 @@ namespace MWWorld throw std::runtime_error ("class can't be enchanted"); } - bool Class::canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Class::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const { - return true; + return 1; } void Class::adjustPosition(const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 4931da7a86..362a8bc9ca 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -242,8 +242,8 @@ namespace MWWorld virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; - virtual bool canEquip(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const; - ///< Return 0 if player cannot equip item. Unequip twohanded item if neccesary + virtual int canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) 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 Ptr copyToCell(const Ptr &ptr, CellStore &cell) const; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 7a5ae38d0e..9f51db3534 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -131,6 +131,8 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot) void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc) { const MWMechanics::NpcStats& stats = MWWorld::Class::get(npc).getNpcStats(npc); + MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); + TSlots slots; initSlots (slots); @@ -184,8 +186,15 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc) } } - if(!MWWorld::Class::get (test).canEquip (npc, test)) - continue; + switch(MWWorld::Class::get (test).canBeEquipped (npc, test)) + { + case 0: + continue; + case 2: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + case 3: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { From e7c0f2a211b4854b6ce6198c5245a6071483b0da Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 Apr 2013 14:54:13 -0700 Subject: [PATCH 163/198] Minor cleanup to loading texture UV coords --- components/nifogre/ogrenifloader.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index aa28a30dd2..bf4621e6f0 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1400,21 +1400,14 @@ class NIFObjectLoader : Ogre::ManualResourceLoader // Texture UV coordinates size_t numUVs = data->uvlist.size(); - if(numUVs) + for(size_t i = 0;i < numUVs;i++) { - for(size_t i = 0;i < numUVs;i++) - { - size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); - vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size(), - Ogre::HardwareBuffer::HBU_STATIC); + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2), + srcVerts.size(), Ogre::HardwareBuffer::HBU_STATIC); + vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[i][0], true); - const std::vector &uvlist = data->uvlist[i]; - - vbuf->writeData(0, elemSize*srcVerts.size(), &uvlist[0], true); - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, - Ogre::VES_TEXTURE_COORDINATES, i); - bind->setBinding(nextBuf++, vbuf); - } + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i); + bind->setBinding(nextBuf++, vbuf); } // Triangle faces From 973fdeb2e01be028de7e5fa0b3df473c72fce397 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 Apr 2013 15:21:28 -0700 Subject: [PATCH 164/198] Improve particle system placement when no emitters are specified --- components/nifogre/ogrenifloader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index bf4621e6f0..3c876283e1 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1566,7 +1566,11 @@ class NIFObjectLoader : Ogre::ManualResourceLoader } if(!partsys->isAttached()) - entitybase->attachObjectToBone(partnode->name, partsys); + { + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, partnode->recIndex); + Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid); + entitybase->attachObjectToBone(trgtbone->getName(), partsys); + } } catch(std::exception &e) { std::cerr<< "Particles exception: "< Date: Tue, 9 Apr 2013 01:24:17 +0200 Subject: [PATCH 165/198] Fix several NPCs spawning in the ground --- apps/openmw/mwworld/scene.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 2244a4fc64..439f761311 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -118,6 +118,7 @@ namespace MWWorld float verts = ESM::Land::LAND_SIZE; float worldsize = ESM::Land::REAL_SIZE; + // Load terrain physics first... if (cell->mCell->isExterior()) { ESM::Land* land = @@ -137,6 +138,7 @@ namespace MWWorld } } + // ... then references. This is important for adjustPosition to work correctly. /// \todo rescale depending on the state of a new GMST insertCell (*cell, true); @@ -439,7 +441,6 @@ namespace MWWorld insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale); @@ -447,11 +448,13 @@ namespace MWWorld insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale); insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale); + // Load NPCs and creatures _after_ everything else (important for adjustPosition to work correctly) + insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale); + insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale); } void Scene::addObjectToScene (const Ptr& ptr) From 623c2c8201c80857bbaefe4278b04e88cdda269b Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 9 Apr 2013 07:45:07 +0200 Subject: [PATCH 166/198] Minor fix --- apps/openmw/mwworld/actionequip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 51d0de6fe8..d5927b6c55 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -43,7 +43,7 @@ namespace MWWorld for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) { - switch(MWWorld::Class::get (*it).canBeEquipped (actor, *it)) + switch(MWWorld::Class::get (getTarget()).canBeEquipped (actor, getTarget())) { case 0: return; From ec6dff38b187691b809c4b90ac15c27a972d4da2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 9 Apr 2013 11:40:36 +0200 Subject: [PATCH 167/198] added basic spell table --- apps/opencs/model/world/data.cpp | 19 +++++++++++++++++++ apps/opencs/model/world/data.hpp | 6 ++++++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 1 + components/esm/loadspel.cpp | 10 ++++++++++ components/esm/loadspel.hpp | 3 +++ 9 files changed, 55 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b385c5b4c2..af2b17bd96 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -99,6 +99,13 @@ CSMWorld::Data::Data() mBirthsigns.addColumn (new TextureColumn); mBirthsigns.addColumn (new DescriptionColumn); + mSpells.addColumn (new StringIdColumn); + mSpells.addColumn (new RecordStateColumn); + mSpells.addColumn (new NameColumn); + mSpells.addColumn (new FlagColumn ("Autocalc", 0x1)); + mSpells.addColumn (new FlagColumn ("Starter Spell", 0x2)); + mSpells.addColumn (new FlagColumn ("Always Succeeds", 0x4)); + 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); @@ -109,6 +116,7 @@ CSMWorld::Data::Data() addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script); 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); } CSMWorld::Data::~Data() @@ -217,6 +225,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getBirthsigns() return mBirthsigns; } +const CSMWorld::IdCollection& CSMWorld::Data::getSpells() const +{ + return mSpells; +} + +CSMWorld::IdCollection& CSMWorld::Data::getSpells() +{ + return mSpells; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -261,6 +279,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_SCPT: mScripts.load (reader, base); break; 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; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 122e855d86..d7b69ba5e3 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -36,6 +37,7 @@ namespace CSMWorld IdCollection mScripts; IdCollection mRegions; IdCollection mBirthsigns; + IdCollection mSpells; std::vector mModels; std::map mModelIndex; @@ -92,6 +94,10 @@ namespace CSMWorld IdCollection& getBirthsigns(); + const IdCollection& getSpells() const; + + IdCollection& getSpells(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 6d305d6c0f..11f4877886 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -27,6 +27,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" }, { 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_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -43,6 +44,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" }, { 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_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 0586719f14..5586b22e79 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -53,7 +53,9 @@ namespace CSMWorld Type_Regions, Type_Region, Type_Birthsigns, - Type_Birthsign + Type_Birthsign, + Type_Spells, + Type_Spell }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index af9b814203..dfdcb10365 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -121,6 +121,10 @@ void CSVDoc::View::setupWorldMenu() QAction *birthsigns = new QAction (tr ("Birthsigns"), this); connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView())); world->addAction (birthsigns); + + QAction *spells = new QAction (tr ("Spells"), this); + connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView())); + world->addAction (spells); } void CSVDoc::View::setupUi() @@ -316,6 +320,11 @@ void CSVDoc::View::addBirthsignsSubView() addSubView (CSMWorld::UniversalId::Type_Birthsigns); } +void CSVDoc::View::addSpellsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Spells); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 12944e5693..9241efbb9a 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -131,6 +131,8 @@ namespace CSVDoc void addRegionsSubView(); void addBirthsignsSubView(); + + void addSpellsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 23c66319c6..c9ef4df8db 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -24,6 +24,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Scripts, CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_Birthsigns, + CSMWorld::UniversalId::Type_Spells, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadspel.cpp b/components/esm/loadspel.cpp index b0f1ca64b9..8149fe4cef 100644 --- a/components/esm/loadspel.cpp +++ b/components/esm/loadspel.cpp @@ -20,4 +20,14 @@ void Spell::save(ESMWriter &esm) mEffects.save(esm); } + void Spell::blank() + { + mData.mType = 0; + mData.mCost = 0; + mData.mFlags = 0; + + mName.clear(); + + mEffects.mList.clear(); + } } diff --git a/components/esm/loadspel.hpp b/components/esm/loadspel.hpp index 0d5e0be522..3a620962d1 100644 --- a/components/esm/loadspel.hpp +++ b/components/esm/loadspel.hpp @@ -43,6 +43,9 @@ struct Spell void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). }; } #endif From ae0a7d5bcde2e15b228b388f9e693b1453378a36 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 9 Apr 2013 11:53:47 +0200 Subject: [PATCH 168/198] added cost and type columns to spell table --- apps/opencs/model/world/columnbase.hpp | 3 +- apps/opencs/model/world/columns.hpp | 48 ++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 2 ++ apps/opencs/view/doc/viewmanager.cpp | 8 +++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 5c2ce8a676..23049164f8 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -34,7 +34,8 @@ namespace CSMWorld Display_GlobalVarType, Display_Specialisation, Display_Attribute, - Display_Boolean + Display_Boolean, + Display_SpellType }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index fbc533779a..6d6d1b1ef0 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -675,6 +675,54 @@ namespace CSMWorld return true; } }; + + template + struct SpellTypeColumn : public Column + { + SpellTypeColumn() : Column ("Type", ColumnBase::Display_SpellType) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mType; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mType = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct CostColumn : public Column + { + CostColumn() : Column ("Cost", ColumnBase::Display_Integer) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mCost; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + record2.mData.mCost = data.toInt(); + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index af2b17bd96..84b49b6bcd 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -102,6 +102,8 @@ CSMWorld::Data::Data() mSpells.addColumn (new StringIdColumn); mSpells.addColumn (new RecordStateColumn); mSpells.addColumn (new NameColumn); + mSpells.addColumn (new SpellTypeColumn); + mSpells.addColumn (new CostColumn); mSpells.addColumn (new FlagColumn ("Autocalc", 0x1)); mSpells.addColumn (new FlagColumn ("Starter Spell", 0x2)); mSpells.addColumn (new FlagColumn ("Always Succeeds", 0x4)); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 3be7228b31..050bd51fe2 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -49,6 +49,11 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) "Luck", 0 }; + static const char *sSpellTypes[] = + { + "Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0 + }; + mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType, @@ -62,6 +67,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute, new CSVWorld::EnumDelegateFactory (sAttributes, true)); + + mDelegateFactories->add (CSMWorld::ColumnBase::Display_SpellType, + new CSVWorld::EnumDelegateFactory (sSpellTypes)); } CSVDoc::ViewManager::~ViewManager() From 40bb772e34aedf01c472aad93147c3a81a5a983d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 9 Apr 2013 12:44:49 +0200 Subject: [PATCH 169/198] added verifier for spell record --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/spellcheck.cpp | 35 ++++++++++++++++++++++++++ apps/opencs/model/tools/spellcheck.hpp | 29 +++++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 3 +++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/spellcheck.cpp create mode 100644 apps/opencs/model/tools/spellcheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 87221d7af5..76d4280c8f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -36,7 +36,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck - birthsigncheck + birthsigncheck spellcheck ) diff --git a/apps/opencs/model/tools/spellcheck.cpp b/apps/opencs/model/tools/spellcheck.cpp new file mode 100644 index 0000000000..3adee0a4ef --- /dev/null +++ b/apps/opencs/model/tools/spellcheck.cpp @@ -0,0 +1,35 @@ + +#include "spellcheck.hpp" + +#include +#include + +#include + +#include "../world/universalid.hpp" + +CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection& spells) +: mSpells (spells) +{} + +int CSMTools::SpellCheckStage::setup() +{ + return mSpells.getSize(); +} + +void CSMTools::SpellCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Spell& spell = mSpells.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Spell, spell.mId); + + // test for empty name and description + if (spell.mName.empty()) + messages.push_back (id.toString() + "|" + spell.mId + " has an empty name"); + + // test for invalid cost values + if (spell.mData.mCost<0) + messages.push_back (id.toString() + "|" + spell.mId + " has a negative spell costs"); + + /// \todo check data members that can't be edited in the table view +} \ No newline at end of file diff --git a/apps/opencs/model/tools/spellcheck.hpp b/apps/opencs/model/tools/spellcheck.hpp new file mode 100644 index 0000000000..0566392193 --- /dev/null +++ b/apps/opencs/model/tools/spellcheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_SPELLCHECK_H +#define CSM_TOOLS_SPELLCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that spell records are internally consistent + class SpellCheckStage : public Stage + { + const CSMWorld::IdCollection& mSpells; + + public: + + SpellCheckStage (const CSMWorld::IdCollection& spells); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 78796de418..803861203c 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -19,6 +19,7 @@ #include "soundcheck.hpp" #include "regioncheck.hpp" #include "birthsigncheck.hpp" +#include "spellcheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -72,6 +73,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new RegionCheckStage (mData.getRegions())); mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns())); + + mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); } return mVerifier; From be4a01bdb4edf99ca9618ea477f31f44366fc85e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 9 Apr 2013 14:27:32 +0200 Subject: [PATCH 170/198] added missing recrod type columns --- apps/opencs/model/world/data.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 84b49b6bcd..14aff47e89 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -33,11 +33,13 @@ CSMWorld::Data::Data() mGmsts.addColumn (new StringIdColumn); mGmsts.addColumn (new RecordStateColumn); mGmsts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Gmst)); + mGmsts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Gmst)); mGmsts.addColumn (new VarTypeColumn (ColumnBase::Display_GmstVarType)); mGmsts.addColumn (new VarValueColumn); mSkills.addColumn (new StringIdColumn); mSkills.addColumn (new RecordStateColumn); + mSkills.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Skill)); mSkills.addColumn (new AttributeColumn); mSkills.addColumn (new SpecialisationColumn); for (int i=0; i<4; ++i) @@ -46,6 +48,7 @@ CSMWorld::Data::Data() mClasses.addColumn (new StringIdColumn); mClasses.addColumn (new RecordStateColumn); + mClasses.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Class)); mClasses.addColumn (new NameColumn); mClasses.addColumn (new AttributesColumn (0)); mClasses.addColumn (new AttributesColumn (1)); @@ -59,6 +62,7 @@ CSMWorld::Data::Data() mFactions.addColumn (new StringIdColumn); mFactions.addColumn (new RecordStateColumn); + mFactions.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Faction)); mFactions.addColumn (new NameColumn); mFactions.addColumn (new AttributesColumn (0)); mFactions.addColumn (new AttributesColumn (1)); @@ -68,6 +72,7 @@ CSMWorld::Data::Data() mRaces.addColumn (new StringIdColumn); mRaces.addColumn (new RecordStateColumn); + mRaces.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Race)); mRaces.addColumn (new NameColumn); mRaces.addColumn (new DescriptionColumn); mRaces.addColumn (new FlagColumn ("Playable", 0x1)); @@ -79,6 +84,7 @@ CSMWorld::Data::Data() mSounds.addColumn (new StringIdColumn); mSounds.addColumn (new RecordStateColumn); + mSounds.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Sound)); mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_Volume)); mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MinRange)); mSounds.addColumn (new SoundParamColumn (SoundParamColumn::Type_MaxRange)); @@ -86,21 +92,25 @@ CSMWorld::Data::Data() mScripts.addColumn (new StringIdColumn); mScripts.addColumn (new RecordStateColumn); + mScripts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Script)); mRegions.addColumn (new StringIdColumn); mRegions.addColumn (new RecordStateColumn); + mRegions.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Region)); mRegions.addColumn (new NameColumn); mRegions.addColumn (new MapColourColumn); mRegions.addColumn (new SleepListColumn); mBirthsigns.addColumn (new StringIdColumn); mBirthsigns.addColumn (new RecordStateColumn); + mBirthsigns.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Birthsign)); mBirthsigns.addColumn (new NameColumn); mBirthsigns.addColumn (new TextureColumn); mBirthsigns.addColumn (new DescriptionColumn); mSpells.addColumn (new StringIdColumn); mSpells.addColumn (new RecordStateColumn); + mSpells.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Spell)); mSpells.addColumn (new NameColumn); mSpells.addColumn (new SpellTypeColumn); mSpells.addColumn (new CostColumn); From cd33f40c8fb1497b3db6eae569a45a9c334cf9d4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 9 Apr 2013 14:28:31 +0200 Subject: [PATCH 171/198] re-enabled opening of record subviews via double click in table --- apps/opencs/view/world/tablesubview.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index f4deceb490..bb4bb76c61 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -21,6 +21,5 @@ void CSVWorld::TableSubView::setEditLock (bool locked) void CSVWorld::TableSubView::rowActivated (const QModelIndex& index) { - /// \todo re-enable, after dialogue sub views have been fixed up -// focusId (mTable->getUniversalId (index.row())); + focusId (mTable->getUniversalId (index.row())); } \ No newline at end of file From 46925e93a6f79402f0838eabab30f02c4352a828 Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 9 Apr 2013 16:14:08 +0200 Subject: [PATCH 172/198] Second minor fix --- apps/openmw/mwclass/armor.cpp | 3 +++ apps/openmw/mwworld/actionequip.cpp | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index ddab6f7548..a14b2667e1 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -343,6 +343,9 @@ namespace MWClass { MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if(weapon == invStore.end()) + return 1; + if(weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index d5927b6c55..82431ac8f3 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -18,6 +18,7 @@ namespace MWWorld void ActionEquip::executeImp (const Ptr& actor) { + MWWorld::Ptr object = getTarget(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor); // slots that this item can be equipped in @@ -27,7 +28,7 @@ namespace MWWorld MWWorld::ContainerStoreIterator it = invStore.begin(); for (; it != invStore.end(); ++it) { - if (*it == getTarget()) + if (*it == object) { break; } @@ -43,7 +44,7 @@ namespace MWWorld for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) { - switch(MWWorld::Class::get (getTarget()).canBeEquipped (actor, getTarget())) + switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) { case 0: return; @@ -70,10 +71,10 @@ namespace MWWorld } } - std::string script = MWWorld::Class::get(*it).getScript(*it); + std::string script = MWWorld::Class::get(object).getScript(object); /* Set OnPCEquip Variable on item's script, if the player is equipping it, and it has a script with that variable declared */ if(equipped && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && script != "") - (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 1); + (object).mRefData->getLocals().setVarByInt(script, "onpcequip", 1); } } From 9f9d978b0f1020777403f2b5f2e67b7ed0a03cd7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 9 Apr 2013 09:07:05 -0700 Subject: [PATCH 173/198] Use an enum to specify the NPC's view mode (normal, head only) --- apps/openmw/mwrender/characterpreview.cpp | 8 ++++---- apps/openmw/mwrender/npcanimation.cpp | 8 ++++---- apps/openmw/mwrender/npcanimation.hpp | 10 ++++++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 616543a7d4..0da20f3daf 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -59,8 +59,8 @@ namespace MWRender mNode = renderRoot->createChildSceneNode(); - mAnimation = new NpcAnimation(mCharacter, mNode, - MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0, renderHeadOnly()); + mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter), + 0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); mNode->setVisible (false); @@ -101,8 +101,8 @@ namespace MWRender assert(mAnimation); delete mAnimation; - mAnimation = new NpcAnimation(mCharacter, mNode, - MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0, renderHeadOnly()); + mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter), + 0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); float scale=1.f; MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index d7620a8de5..685edb68c8 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -56,7 +56,7 @@ NpcAnimation::~NpcAnimation() } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& inv, int visibilityFlags, bool headOnly) +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& inv, int visibilityFlags, ViewMode viewMode) : Animation(ptr), mStateID(-1), mTimeToChange(0), @@ -73,7 +73,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mGloveL(inv.end()), mGloveR(inv.end()), mSkirtIter(inv.end()), - mHeadOnly(headOnly) + mViewMode(viewMode) { mNpc = mPtr.get()->mBase; @@ -222,7 +222,7 @@ void NpcAnimation::updateParts(bool forceupdate) if(!forceupdate) return; - for(size_t i = 0;i < slotlistsize && !mHeadOnly;i++) + for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) { MWWorld::ContainerStoreIterator iter = inv.getSlot(slotlist[i].slot); @@ -259,7 +259,7 @@ void NpcAnimation::updateParts(bool forceupdate) if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1) addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel); - if (mHeadOnly) + if(mViewMode == VM_HeadOnly) return; static const struct { diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 224d174f43..44639e94ab 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -26,6 +26,11 @@ struct PartInfo { const char name[32]; }; +enum ViewMode { + VM_Normal, + VM_HeadOnly +}; + private: static const size_t sPartListSize = 27; static const PartInfo sPartList[sPartListSize]; @@ -39,7 +44,7 @@ private: std::string mHeadModel; std::string mHairModel; std::string mBodyPrefix; - bool mHeadOnly; + ViewMode mViewMode; float mTimeToChange; MWWorld::ContainerStoreIterator mRobe; @@ -73,7 +78,8 @@ private: public: NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, - MWWorld::InventoryStore& inv, int visibilityFlags, bool headOnly=false); + MWWorld::InventoryStore& inv, int visibilityFlags, + ViewMode viewMode=VM_Normal); virtual ~NpcAnimation(); virtual Ogre::Vector3 runAnimation(float timepassed); From 029d56572777fcccf01639166af528b63c2837e3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 9 Apr 2013 09:23:07 -0700 Subject: [PATCH 174/198] Avoid calling setVisible for character previews --- apps/openmw/mwrender/characterpreview.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 0da20f3daf..8396acaea8 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -62,8 +62,6 @@ namespace MWRender mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter), 0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); - mNode->setVisible (false); - Ogre::Vector3 scale = mNode->getScale(); mCamera->setPosition(mPosition * scale); mCamera->lookAt(mLookAt * scale); @@ -108,8 +106,6 @@ namespace MWRender MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale); mNode->setScale(Ogre::Vector3(scale)); - mNode->setVisible (false); - mCamera->setPosition(mPosition * mNode->getScale()); mCamera->lookAt(mLookAt * mNode->getScale()); @@ -139,12 +135,8 @@ namespace MWRender mNode->setOrientation (Ogre::Quaternion::IDENTITY); - mNode->setVisible (true); - mRenderTarget->update(); mSelectionBuffer->update(); - - mNode->setVisible (false); } int InventoryPreview::getSlotSelected (int posX, int posY) @@ -178,9 +170,7 @@ namespace MWRender updateCamera(); - mNode->setVisible (true); mRenderTarget->update(); - mNode->setVisible (false); } void RaceSelectionPreview::setPrototype(const ESM::NPC &proto) From 44ef02eb99c2cf7f4cab6d60320e155fe5183579 Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 9 Apr 2013 19:04:59 +0200 Subject: [PATCH 175/198] Third minor fix --- apps/openmw/mwworld/actionequip.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 82431ac8f3..2877a2c5ae 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -40,19 +40,20 @@ namespace MWWorld bool equipped = false; + switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) + { + case 0: + return; //Item cannot be equipped, so function breaks. + case 2: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + case 3: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + } + // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) { - switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) - { - case 0: - return; - case 2: - invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); - case 3: - invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); - } // if all slots are occupied, replace the last slot if (slot == --slots.first.end()) From 248fff6eb7323b7c7cf4f56afff53c1b820e6fb3 Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 9 Apr 2013 19:41:03 +0200 Subject: [PATCH 176/198] Fourth minor fix --- apps/openmw/mwworld/actionequip.cpp | 4 +++- apps/openmw/mwworld/inventorystore.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 2877a2c5ae..39c5abe345 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -43,11 +43,13 @@ namespace MWWorld switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) { case 0: - return; //Item cannot be equipped, so function breaks. + return; case 2: invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + break; case 3: invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + break; } // equip the item in the first free slot diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 9f51db3534..782e3f920f 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -192,8 +192,10 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc) continue; case 2: invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + break; case 3: invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + break; } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped From bd93e63150dc69c0e3caf27231dfbede99772baf Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 9 Apr 2013 19:46:27 +0200 Subject: [PATCH 177/198] Fifth minor fix --- apps/openmw/mwworld/actionequip.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 39c5abe345..fd35d0dd3c 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -21,6 +21,18 @@ namespace MWWorld MWWorld::Ptr object = getTarget(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor); + switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) + { + case 0: + return; + case 2: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); + break; + case 3: + invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); + break; + } + // slots that this item can be equipped in std::pair, bool> slots = MWWorld::Class::get(getTarget()).getEquipmentSlots(getTarget()); @@ -40,18 +52,6 @@ namespace MWWorld bool equipped = false; - switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) - { - case 0: - return; - case 2: - invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end()); - break; - case 3: - invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end()); - break; - } - // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) From 6ca2b1af743b659e44b9601f99c985a92a66e99a Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Tue, 9 Apr 2013 19:24:41 +0100 Subject: [PATCH 178/198] fix for turning animations playing when in vanity mode --- apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwinput/inputmanagerimp.cpp | 13 +++++++++++-- apps/openmw/mwrender/renderingmanager.cpp | 10 ++++++++++ apps/openmw/mwrender/renderingmanager.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 5 +++++ apps/openmw/mwworld/worldimp.hpp | 2 ++ 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 040dc703c0..39e985890a 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -319,6 +319,7 @@ namespace MWBase virtual void allowVanityMode(bool allow) = 0; virtual void togglePlayerLooking(bool enable) = 0; virtual void changeVanityModeScale(float factor) = 0; + virtual bool vanityRotateCamera(float * rot) = 0; virtual void renderPlayer() = 0; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index c23106be1a..6a34161e08 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -533,8 +533,17 @@ namespace MWInput float scale = MWBase::Environment::get().getFrameDuration(); if(scale <= 0.0f) scale = 1.0f; - mPlayer.setYaw(x/scale); - mPlayer.setPitch(-y/scale); + float rot[3]; + rot[0] = -y; + rot[1] = 0.0f; + rot[2] = x; + + // Only actually turn player when we're not in vanity mode + if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot)) + { + mPlayer.setYaw(x/scale); + mPlayer.setPitch(-y/scale); + } if (arg.state.Z.rel) MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.state.Z.rel); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index cd5ab19b9d..029cf394b4 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -891,6 +891,16 @@ void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float mPlayer->getSightAngles(pitch, yaw); } +bool RenderingManager::vanityRotateCamera(float* rot) +{ + if(!mPlayer->isVanityOrPreviewModeEnabled()) + return false; + + Ogre::Vector3 vRot(rot); + mPlayer->rotateCamera(vRot, true); + return true; +} + void RenderingManager::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) { return mLocalMap->getInteriorMapPosition (position, nX, nY, x, y); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index b343a60bdb..cece7a95f0 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -88,6 +88,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList mPlayer->setCameraDistance(-factor/120.f*10, true, true); } + bool vanityRotateCamera(float* rot); + void getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw); void attachCameraTo(const MWWorld::Ptr &ptr); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ae9b7a06b7..11ccd8f2fc 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1364,6 +1364,11 @@ namespace MWWorld return physactor && physactor->getOnGround(); } + bool World::vanityRotateCamera(float * rot) + { + return mRendering->vanityRotateCamera(rot); + } + void World::renderPlayer() { mRendering->renderPlayer(mPlayer->getPlayer()); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 5ae87a1ff7..7b12babee9 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -361,6 +361,8 @@ namespace MWWorld mRendering->changeVanityModeScale(factor); } + virtual bool vanityRotateCamera(float * rot); + virtual void renderPlayer(); virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); From 0e7d555cdf5ebd475792ffe13c0ad7d653288267 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 9 Apr 2013 20:31:00 +0200 Subject: [PATCH 179/198] Terrain material now uses multiple passes if required, which means it can support an arbitrary number of layers. Also re-enables PSSM. --- apps/openmw/mwgui/settingswindow.cpp | 4 +- apps/openmw/mwrender/shadows.cpp | 5 +- apps/openmw/mwrender/terrainmaterial.cpp | 161 ++++++++++++++++------- apps/openmw/mwrender/terrainmaterial.hpp | 3 + files/materials/shadowcaster.shader | 3 +- files/materials/terrain.shader | 33 ++++- 6 files changed, 148 insertions(+), 61 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 58754472dd..5fb6e5000b 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -236,9 +236,7 @@ namespace MWGui mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows")); - //mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); - mShadowsLargeDistance->setCaptionWithReplacing("#{sOff}"); - mShadowsLargeDistance->setEnabled (false); + mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); mShadowsEnabledButton->setCaptionWithReplacing(Settings::Manager::getBool("enabled", "Shadows") ? "#{sOn}" : "#{sOff}"); mActorShadows->setCaptionWithReplacing(Settings::Manager::getBool("actor shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index 595a82294b..0d066a0ecb 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -28,10 +28,7 @@ void Shadows::recreate() { bool enabled = Settings::Manager::getBool("enabled", "Shadows"); - // Split shadow maps are currently disabled because the terrain cannot cope with them - // (Too many texture units) Solution would be a multi-pass terrain material - //bool split = Settings::Manager::getBool("split", "Shadows"); - const bool split = false; + bool split = Settings::Manager::getBool("split", "Shadows"); sh::Factory::getInstance ().setGlobalSetting ("shadows", enabled && !split ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("shadows_pssm", enabled && split ? "true" : "false"); diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index 8a568883df..dd74254be6 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -68,59 +68,113 @@ namespace MWRender Ogre::MaterialManager::getSingleton().remove(matName); mMaterial = sh::Factory::getInstance().createMaterialInstance (matName); - mMaterial->setProperty ("allow_fixed_function", sh::makeProperty(new sh::BooleanValue(false))); - sh::MaterialInstancePass* p = mMaterial->createPass (); + int numPasses = getRequiredPasses(terrain); + int maxLayersInOnePass = getMaxLayersPerPass(terrain); - p->setProperty ("vertex_program", sh::makeProperty(new sh::StringValue("terrain_vertex"))); - p->setProperty ("fragment_program", sh::makeProperty(new sh::StringValue("terrain_fragment"))); - - p->mShaderProperties.setProperty ("colour_map", sh::makeProperty(new sh::BooleanValue(mGlobalColourMap))); - - // global colour map - sh::MaterialInstanceTextureUnit* colourMap = p->createTextureUnit ("colourMap"); - colourMap->setProperty ("texture_alias", sh::makeProperty (new sh::StringValue(mMaterial->getName() + "_colourMap"))); - colourMap->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); - - // global normal map - sh::MaterialInstanceTextureUnit* normalMap = p->createTextureUnit ("normalMap"); - normalMap->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getTerrainNormalMap ()->getName()))); - normalMap->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); - - Ogre::uint maxLayers = getMaxLayers(terrain); - Ogre::uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); - Ogre::uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - - p->mShaderProperties.setProperty ("num_layers", sh::makeProperty(new sh::StringValue(Ogre::StringConverter::toString(numLayers)))); - p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty(new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures)))); - - // blend maps - for (Ogre::uint i = 0; i < numBlendTextures; ++i) + for (int pass=0; passcreateTextureUnit ("blendMap" + Ogre::StringConverter::toString(i)); - blendTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getBlendTextureName(i)))); - blendTex->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); - } + int layerOffset = maxLayersInOnePass * pass; + int blendmapOffset = (pass == 0) ? 1 : 0; // the first layer of the first pass is the base layer and does not need a blend map - // layer maps - for (Ogre::uint i = 0; i < numLayers; ++i) - { - sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i)); - diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getLayerTextureName(i, 0)))); - p->mShaderProperties.setProperty ("blendmap_component_" + Ogre::StringConverter::toString(i), - sh::makeProperty(new sh::StringValue(Ogre::StringConverter::toString(int((i-1) / 4)) + "." + getComponent(int((i-1) % 4))))); - } + sh::MaterialInstancePass* p = mMaterial->createPass (); - // shadow - for (Ogre::uint i = 0; i < 3; ++i) - { - sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); - shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); - } + p->setProperty ("vertex_program", sh::makeProperty(new sh::StringValue("terrain_vertex"))); + p->setProperty ("fragment_program", sh::makeProperty(new sh::StringValue("terrain_fragment"))); + if (pass != 0) + { + p->setProperty ("scene_blend", sh::makeProperty(new sh::StringValue("alpha_blend"))); + // Only write if depth is equal to the depth value written by the previous pass. + p->setProperty ("depth_func", sh::makeProperty(new sh::StringValue("equal"))); + } - p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty(new sh::StringValue( - Ogre::StringConverter::toString(numBlendTextures + numLayers + 2)))); + p->mShaderProperties.setProperty ("colour_map", sh::makeProperty(new sh::BooleanValue(mGlobalColourMap))); + p->mShaderProperties.setProperty ("is_first_pass", sh::makeProperty(new sh::BooleanValue(pass == 0))); + + // global colour map + sh::MaterialInstanceTextureUnit* colourMap = p->createTextureUnit ("colourMap"); + colourMap->setProperty ("texture_alias", sh::makeProperty (new sh::StringValue(mMaterial->getName() + "_colourMap"))); + colourMap->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); + + // global normal map + sh::MaterialInstanceTextureUnit* normalMap = p->createTextureUnit ("normalMap"); + normalMap->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getTerrainNormalMap ()->getName()))); + normalMap->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); + + Ogre::uint numLayersInThisPass = std::min(maxLayersInOnePass, terrain->getLayerCount()-layerOffset); + + // HACK: Terrain::getLayerBlendTextureIndex should be const, but it is not. + // Remove this once ogre got fixed. + Ogre::Terrain* nonconstTerrain = const_cast(terrain); + + // a blend map might be shared between two passes + // so we can't just use terrain->getBlendTextureCount() + Ogre::uint numBlendTextures=0; + std::vector blendTextures; + for (unsigned int layer=blendmapOffset; layergetBlendTextureName(nonconstTerrain->getLayerBlendTextureIndex( + static_cast(layerOffset+layer)).first); + if (std::find(blendTextures.begin(), blendTextures.end(), blendTextureName) == blendTextures.end()) + { + blendTextures.push_back(blendTextureName); + ++numBlendTextures; + } + } + + p->mShaderProperties.setProperty ("num_layers", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numLayersInThisPass)))); + p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures)))); + + // blend maps + // the index of the first blend map used in this pass + int blendmapStart; + if (terrain->getLayerCount() == 1) // special case. if there's only one layer, we don't need blend maps at all + blendmapStart = 0; + else + blendmapStart = nonconstTerrain->getLayerBlendTextureIndex(static_cast(layerOffset+blendmapOffset)).first; + for (Ogre::uint i = 0; i < numBlendTextures; ++i) + { + sh::MaterialInstanceTextureUnit* blendTex = p->createTextureUnit ("blendMap" + Ogre::StringConverter::toString(i)); + blendTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getBlendTextureName(blendmapStart+i)))); + blendTex->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); + } + + // layer maps + for (Ogre::uint i = 0; i < numLayersInThisPass; ++i) + { + sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i)); + diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getLayerTextureName(layerOffset+i, 0)))); + + if (i+layerOffset > 0) + { + int blendTextureIndex = nonconstTerrain->getLayerBlendTextureIndex(static_cast(layerOffset+i)).first; + int blendTextureComponent = nonconstTerrain->getLayerBlendTextureIndex(static_cast(layerOffset+i)).second; + p->mShaderProperties.setProperty ("blendmap_component_" + Ogre::StringConverter::toString(i), + sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(blendTextureIndex-blendmapStart) + "." + getComponent(blendTextureComponent)))); + } + else + { + // just to make it shut up about blendmap_component_0 not existing in the first pass. + // it might be retrieved, but will never survive the preprocessing step. + p->mShaderProperties.setProperty ("blendmap_component_" + Ogre::StringConverter::toString(i), + sh::makeProperty (new sh::StringValue(""))); + } + } + + // shadow + for (Ogre::uint i = 0; i < 3; ++i) + { + sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); + shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); + } + + p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty (new sh::StringValue( + Ogre::StringConverter::toString(numBlendTextures + numLayersInThisPass + 2)))); + + // make sure the pass index is fed to the permutation handler, because blendmap components may be different + p->mShaderProperties.setProperty ("pass_index", sh::makeProperty(new sh::IntValue(pass))); + } return Ogre::MaterialManager::getSingleton().getByName(matName); } @@ -142,6 +196,11 @@ namespace MWRender } Ogre::uint8 TerrainMaterial::Profile::getMaxLayers(const Ogre::Terrain* terrain) const + { + return 255; + } + + int TerrainMaterial::Profile::getMaxLayersPerPass (const Ogre::Terrain* terrain) { // count the texture units free Ogre::uint8 freeTextureUnits = 16; @@ -151,11 +210,21 @@ namespace MWRender --freeTextureUnits; // shadow --freeTextureUnits; + --freeTextureUnits; + --freeTextureUnits; // each layer needs 1.25 units (1xdiffusespec, 0.25xblend) return static_cast(freeTextureUnits / (1.25f)); } + int TerrainMaterial::Profile::getRequiredPasses (const Ogre::Terrain* terrain) + { + int maxLayersPerPass = getMaxLayersPerPass(terrain); + assert(terrain->getLayerCount()); + assert(maxLayersPerPass); + return std::ceil(static_cast(terrain->getLayerCount()) / maxLayersPerPass); + } + void TerrainMaterial::Profile::updateParams(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) { } diff --git a/apps/openmw/mwrender/terrainmaterial.hpp b/apps/openmw/mwrender/terrainmaterial.hpp index fe1214cf5e..c90499baeb 100644 --- a/apps/openmw/mwrender/terrainmaterial.hpp +++ b/apps/openmw/mwrender/terrainmaterial.hpp @@ -72,6 +72,9 @@ namespace MWRender private: sh::MaterialInstance* mMaterial; + int getRequiredPasses (const Ogre::Terrain* terrain); + int getMaxLayersPerPass (const Ogre::Terrain* terrain); + bool mGlobalColourMap; }; diff --git a/files/materials/shadowcaster.shader b/files/materials/shadowcaster.shader index b312d414c5..b992366a7e 100644 --- a/files/materials/shadowcaster.shader +++ b/files/materials/shadowcaster.shader @@ -45,8 +45,7 @@ // use alpha channel of the first texture float alpha = shSample(texture1, UV).a; - // discard if alpha is less than 0.5 - if (alpha < 1.0) + if (alpha < 0.5) discard; #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index c73b582f8d..de90a6cf61 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -1,6 +1,6 @@ #include "core.h" -#define IS_FIRST_PASS 1 +#define IS_FIRST_PASS (@shPropertyString(pass_index) == 0) #define FOG @shGlobalSettingBool(fog) @@ -23,6 +23,9 @@ #define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) +#if !IS_FIRST_PASS +// This is not the first pass. +#endif #if NEED_DEPTH @shAllocatePassthrough(1, depth) @@ -222,7 +225,11 @@ float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); #endif - + +#if !IS_FIRST_PASS +float combinedAlpha = 0.f; +#endif + // Layer calculations @shForeach(@shPropertyString(num_blendmaps)) float4 blendValues@shIterator = shSample(blendMap@shIterator, UV); @@ -232,12 +239,20 @@ @shForeach(@shPropertyString(num_layers)) -#if IS_FIRST_PASS == 1 && @shIterator == 0 - // first layer of first pass doesn't need a blend map +#if IS_FIRST_PASS + #if @shIterator == 0 + // first layer of first pass is the base layer and doesn't need a blend map albedo = shSample(diffuseMap0, UV * 10).rgb; -#else + #else albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); - + #endif +#else + #if @shIterator == 0 + albedo = shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator); + #else + albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); + #endif + combinedAlpha += blendValues@shPropertyString(blendmap_component_@shIterator); #endif @shEndForeach @@ -325,6 +340,12 @@ // prevent negative colour output (for example with negative lights) shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); + +#if IS_FIRST_PASS + shOutputColour(0).a = 1; +#else + shOutputColour(0).a = min(combinedAlpha, 1.f); +#endif } #endif From a700c50e84e06586e3a766940e43f33e156d67ee Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 9 Apr 2013 15:10:14 -0700 Subject: [PATCH 180/198] Add a first-person view mode to NpcAnimation And use it instead of showing/hiding the player. --- apps/openmw/mwrender/animation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 64 ++++++++++++++++++++++----- apps/openmw/mwrender/npcanimation.hpp | 3 ++ apps/openmw/mwrender/player.cpp | 12 +++-- 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 067e856720..a849b20efe 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -476,7 +476,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con Ogre::Vector3 Animation::runAnimation(float timepassed) { - Ogre::Vector3 movement = Ogre::Vector3::ZERO; + Ogre::Vector3 movement(0.0f); timepassed *= mAnimSpeedMult; while(mCurrentAnim && mPlaying) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 685edb68c8..7e59f8f6c9 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -130,7 +130,40 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); setAnimationSources(skelnames); - updateParts(true); + forceUpdate(); +} + +void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) +{ + assert(viewMode != VM_HeadOnly); + mViewMode = viewMode; + + /* FIXME: Enable this once first-person animations work. */ +#if 0 + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Race *race = store.get().find(mNpc->mRace); + + bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; + std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); + + std::vector skelnames(1, smodel); + if(!mNpc->isMale() && !isBeast) + skelnames.push_back("meshes\\base_anim_female.nif"); + else if(mBodyPrefix.find("argonian") != std::string::npos) + skelnames.push_back("meshes\\argonian_swimkna.nif"); + if(mNpc->mModel.length() > 0) + skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); + if(mViewMode == VM_FirstPerson) + { + smodel = (!isBeast ? "meshes\\base_anim.1st.nif" : "meshes\\base_animkna.1st.nif"); + skelnames.push_back(smodel); + } + setAnimationSources(skelnames); +#endif + + for(size_t i = 0;i < sPartListSize;i++) + removeIndividualPart(i); + forceUpdate(); } void NpcAnimation::updateParts(bool forceupdate) @@ -254,13 +287,18 @@ void NpcAnimation::updateParts(bool forceupdate) reserveIndividualPart(slotlist[i].reserveParts[res], slotlist[i].slot, prio); } - if(mPartPriorities[ESM::PRT_Head] < 1) - addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel); - if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1) - addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel); - + if(mViewMode != VM_FirstPerson) + { + if(mPartPriorities[ESM::PRT_Head] < 1) + addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel); + if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1) + addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel); + } if(mViewMode == VM_HeadOnly) return; + /* FIXME: Remove this once we figure out how to show what in first-person */ + if(mViewMode == VM_FirstPerson) + return; static const struct { ESM::PartReferenceType type; @@ -288,6 +326,7 @@ void NpcAnimation::updateParts(bool forceupdate) { ESM::PRT_Tail, { "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++) { @@ -298,14 +337,14 @@ void NpcAnimation::updateParts(bool forceupdate) if(!mNpc->isMale()) { - part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]); + part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]+ext); if(part == 0) - part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]); + part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]+ext); } if(part == 0) - part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]); + part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]+ext); if(part == 0) - part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]); + part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]+ext); if(part) addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel); @@ -431,6 +470,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, void NpcAnimation::addPartGroup(int group, int priority, const std::vector &parts) { + const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : ""; for(std::size_t i = 0; i < parts.size(); i++) { const ESM::PartReference &part = parts[i]; @@ -440,9 +480,9 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vectorisMale()) - bodypart = partStore.search(part.mFemale); + bodypart = partStore.search(part.mFemale+ext); if(!bodypart) - bodypart = partStore.search(part.mMale); + bodypart = partStore.search(part.mMale+ext); if(bodypart) addOrReplaceIndividualPart(part.mPart, group, priority, "meshes\\"+bodypart->mModel); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 44639e94ab..f2f4c66697 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -28,6 +28,7 @@ struct PartInfo { enum ViewMode { VM_Normal, + VM_FirstPerson, VM_HeadOnly }; @@ -84,6 +85,8 @@ public: virtual Ogre::Vector3 runAnimation(float timepassed); + void setViewMode(ViewMode viewMode); + void forceUpdate() { updateParts(true); } }; diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 55fda326fa..439264f3af 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -124,8 +124,6 @@ namespace MWRender MWBase::Environment::get().getWindowManager ()->showCrosshair (!MWBase::Environment::get().getWindowManager ()->isGuiMode () && (mFirstPersonView && !mVanity.enabled && !mPreviewMode)); - /// \fixme We shouldn't hide the whole model, just certain components of the character (head, chest, feet, etc) - mPlayerNode->setVisible(mVanity.enabled || mPreviewMode || !mFirstPersonView); if (mFirstPersonView && !mVanity.enabled) { return; } @@ -139,6 +137,8 @@ namespace MWRender void Player::toggleViewMode() { mFirstPersonView = !mFirstPersonView; + mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? + NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); if (mFirstPersonView) { mCamera->setPosition(0.f, 0.f, 0.f); setLowHeight(false); @@ -168,6 +168,9 @@ namespace MWRender mVanity.enabled = enable; mVanity.forced = force && enable; + mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? + NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); + float offset = mPreviewCam.offset; Ogre::Vector3 rot(0.f, 0.f, 0.f); if (mVanity.enabled) { @@ -194,6 +197,8 @@ namespace MWRender return; } mPreviewMode = enable; + mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? + NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); float offset = mCamera->getPosition().z; if (mPreviewMode) { mMainCam.offset = offset; @@ -305,7 +310,8 @@ namespace MWRender delete mAnimation; mAnimation = anim; - mPlayerNode->setVisible(mVanity.enabled || mPreviewMode || !mFirstPersonView); + mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ? + NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson); } void Player::setHeight(float height) From 50d8353a8db9bdeb5f577449e7ae784a3f15bd70 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 9 Apr 2013 16:51:04 -0700 Subject: [PATCH 181/198] Fix a hack so arms dont show in first-person --- apps/openmw/mwrender/npcanimation.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 7e59f8f6c9..96220f47d0 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -255,6 +255,14 @@ void NpcAnimation::updateParts(bool forceupdate) if(!forceupdate) return; + /* FIXME: Remove this once we figure out how to show what in first-person */ + if(mViewMode == VM_FirstPerson) + { + for(size_t i = 0;i < slotlistsize;i++) + this->*slotlist[i].part = inv.getSlot(slotlist[i].slot); + return; + } + for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) { MWWorld::ContainerStoreIterator iter = inv.getSlot(slotlist[i].slot); @@ -296,9 +304,6 @@ void NpcAnimation::updateParts(bool forceupdate) } if(mViewMode == VM_HeadOnly) return; - /* FIXME: Remove this once we figure out how to show what in first-person */ - if(mViewMode == VM_FirstPerson) - return; static const struct { ESM::PartReferenceType type; From ce9bc6d9bae9d03b8c614e781b420789eb9531d4 Mon Sep 17 00:00:00 2001 From: Britt Mathis Date: Wed, 10 Apr 2013 00:32:05 -0400 Subject: [PATCH 182/198] MwGui windowManager calls fixed to use MWBase::Environment::get().getWindowManager, filenames in MwGui now comply with naming conventions --- apps/openmw/mwgui/alchemywindow.cpp | 17 +- apps/openmw/mwgui/alchemywindow.hpp | 4 +- apps/openmw/mwgui/birth.cpp | 9 +- apps/openmw/mwgui/birth.hpp | 2 +- apps/openmw/mwgui/bookwindow.cpp | 4 +- apps/openmw/mwgui/bookwindow.hpp | 2 +- apps/openmw/mwgui/charactercreation.cpp | 2 +- apps/openmw/mwgui/class.cpp | 93 ++-- apps/openmw/mwgui/class.hpp | 2 +- apps/openmw/mwgui/confirmationdialog.hpp | 2 +- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/countdialog.hpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 46 +- apps/openmw/mwgui/dialogue.hpp | 2 +- apps/openmw/mwgui/dialoguehistory.cpp | 76 +++ apps/openmw/mwgui/dialoguehistory.hpp | 19 + apps/openmw/mwgui/enchantingdialog.cpp | 42 +- apps/openmw/mwgui/enchantingdialog.hpp | 2 +- apps/openmw/mwgui/hud.hpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 20 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/journalwindow.hpp | 2 +- apps/openmw/mwgui/levelupdialog.cpp | 2 +- apps/openmw/mwgui/levelupdialog.hpp | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 8 +- apps/openmw/mwgui/loadingscreen.hpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 446 +++++++++++++++++ apps/openmw/mwgui/mapwindow.hpp | 107 ++++ apps/openmw/mwgui/merchantrepair.cpp | 10 +- apps/openmw/mwgui/merchantrepair.hpp | 2 +- apps/openmw/mwgui/messagebox.cpp | 5 +- apps/openmw/mwgui/messagebox.hpp | 8 +- apps/openmw/mwgui/quickkeysmenu.cpp | 20 +- apps/openmw/mwgui/quickkeysmenu.hpp | 2 +- apps/openmw/mwgui/race.cpp | 26 +- apps/openmw/mwgui/race.hpp | 2 +- apps/openmw/mwgui/repair.cpp | 2 +- apps/openmw/mwgui/repair.hpp | 2 +- apps/openmw/mwgui/review.cpp | 11 +- apps/openmw/mwgui/review.hpp | 2 +- apps/openmw/mwgui/scrollwindow.cpp | 4 +- apps/openmw/mwgui/scrollwindow.hpp | 2 +- apps/openmw/mwgui/settingswindow.cpp | 14 +- apps/openmw/mwgui/settingswindow.hpp | 2 +- apps/openmw/mwgui/spellbuyingwindow.cpp | 14 +- apps/openmw/mwgui/spellbuyingwindow.hpp | 2 +- apps/openmw/mwgui/spellcreationdialog.cpp | 21 +- apps/openmw/mwgui/spellcreationdialog.hpp | 2 +- apps/openmw/mwgui/spellwindow.cpp | 18 +- apps/openmw/mwgui/spellwindow.hpp | 2 +- apps/openmw/mwgui/statswindow.cpp | 580 ++++++++++++++++++++++ apps/openmw/mwgui/statswindow.hpp | 83 ++++ apps/openmw/mwgui/textinput.cpp | 70 +++ apps/openmw/mwgui/textinput.hpp | 33 ++ apps/openmw/mwgui/tooltips.cpp | 29 +- apps/openmw/mwgui/tooltips.hpp | 6 +- apps/openmw/mwgui/tradewindow.cpp | 24 +- apps/openmw/mwgui/tradewindow.hpp | 2 +- apps/openmw/mwgui/trainingwindow.cpp | 18 +- apps/openmw/mwgui/trainingwindow.hpp | 2 +- apps/openmw/mwgui/travelwindow.cpp | 18 +- apps/openmw/mwgui/travelwindow.hpp | 2 +- apps/openmw/mwgui/waitdialog.cpp | 14 +- apps/openmw/mwgui/waitdialog.hpp | 2 +- apps/openmw/mwgui/widgets.cpp | 39 +- apps/openmw/mwgui/widgets.hpp | 8 - apps/openmw/mwgui/windowbase.cpp | 54 ++ apps/openmw/mwgui/windowbase.hpp | 47 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 8 +- apps/openmw/mwgui/windowpinnablebase.cpp | 28 ++ apps/openmw/mwgui/windowpinnablebase.hpp | 28 ++ 72 files changed, 1863 insertions(+), 328 deletions(-) create mode 100644 apps/openmw/mwgui/dialoguehistory.cpp create mode 100644 apps/openmw/mwgui/dialoguehistory.hpp create mode 100644 apps/openmw/mwgui/mapwindow.cpp create mode 100644 apps/openmw/mwgui/mapwindow.hpp create mode 100644 apps/openmw/mwgui/statswindow.cpp create mode 100644 apps/openmw/mwgui/statswindow.hpp create mode 100644 apps/openmw/mwgui/textinput.cpp create mode 100644 apps/openmw/mwgui/textinput.hpp create mode 100644 apps/openmw/mwgui/windowbase.cpp create mode 100644 apps/openmw/mwgui/windowbase.hpp create mode 100644 apps/openmw/mwgui/windowpinnablebase.cpp create mode 100644 apps/openmw/mwgui/windowpinnablebase.hpp diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index ca7f1b913a..1ae534797d 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -64,8 +64,8 @@ namespace MWGui { mAlchemy.clear(); - mWindowManager.removeGuiMode(GM_Alchemy); - mWindowManager.removeGuiMode(GM_Inventory); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Alchemy); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Inventory); } void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) @@ -77,40 +77,40 @@ namespace MWGui if (result == MWMechanics::Alchemy::Result_NoName) { - mWindowManager.messageBox("#{sNotifyMessage37}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage37}"); return; } // check if mortar & pestle is available (always needed) if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle) { - mWindowManager.messageBox("#{sNotifyMessage45}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage45}"); return; } // make sure 2 or more ingredients were selected if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients) { - mWindowManager.messageBox("#{sNotifyMessage6a}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage6a}"); return; } if (result == MWMechanics::Alchemy::Result_NoEffects) { - mWindowManager.messageBox("#{sNotifyMessage8}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage8}"); MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); return; } if (result == MWMechanics::Alchemy::Result_Success) { - mWindowManager.messageBox("#{sPotionSuccess}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sPotionSuccess}"); MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f); } else if (result == MWMechanics::Alchemy::Result_RandomFailure) { // potion failed - mWindowManager.messageBox("#{sNotifyMessage8}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage8}"); MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); } @@ -232,7 +232,6 @@ namespace MWGui MyGUI::IntCoord coord(0, 0, mEffectsBox->getWidth(), 24); Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget ("MW_StatName", coord, MyGUI::Align::Left | MyGUI::Align::Top); - effectsWidget->setWindowManager(&mWindowManager); Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list); effectsWidget->setEffectList(_list); diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 5f84e73e9b..933975f0c8 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -5,7 +5,7 @@ #include "../mwmechanics/alchemy.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" #include "container.hpp" #include "widgets.hpp" @@ -38,7 +38,7 @@ namespace MWGui virtual void onReferenceUnavailable() { ; } void update(); - + private: MWMechanics::Alchemy mAlchemy; diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 4b07dd698c..d899ab00b1 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -46,7 +46,7 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager) MyGUI::Button* okButton; getWidget(okButton, "OKButton"); - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); updateBirths(); @@ -59,9 +59,9 @@ void BirthDialog::setNextButtonShow(bool shown) getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); else - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); } void BirthDialog::open() @@ -221,7 +221,7 @@ void BirthDialog::updateSpells() if (!categories[category].spells.empty()) { MyGUI::TextBox* label = mSpellArea->createWidget("SandBrightText", coord, MyGUI::Align::Default, std::string("Label")); - label->setCaption(mWindowManager.getGameSettingString(categories[category].label, "")); + label->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString(categories[category].label, "")); mSpellItems.push_back(label); coord.top += lineHeight; @@ -230,7 +230,6 @@ void BirthDialog::updateSpells() { const std::string &spellId = *it; spellWidget = mSpellArea->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("Spell") + boost::lexical_cast(i)); - spellWidget->setWindowManager(&mWindowManager); spellWidget->setSpellId(spellId); mSpellItems.push_back(spellWidget); diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index d3f82dace4..033501f22f 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_BIRTH_H #define MWGUI_BIRTH_H -#include "window_base.hpp" +#include "windowbase.hpp" /* This file contains the dialog for choosing a birth sign. diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 777751069b..d57953d07d 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -102,7 +102,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender) // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - mWindowManager.removeGuiMode(GM_Book); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender) @@ -112,7 +112,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender) MWWorld::ActionTake take(mBook); take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - mWindowManager.removeGuiMode(GM_Book); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book); } void BookWindow::onNextPageButtonClicked (MyGUI::Widget* sender) diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index a509f131fe..c2a9dca893 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_BOOKWINDOW_H #define MWGUI_BOOKWINDOW_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index bcf3c335d3..27de7cee98 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -1,6 +1,6 @@ #include "charactercreation.hpp" -#include "text_input.hpp" +#include "textinput.hpp" #include "race.hpp" #include "class.hpp" #include "birth.hpp" diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index a2f09096a1..8c352d5080 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -26,7 +26,7 @@ GenerateClassResultDialog::GenerateClassResultDialog(MWBase::WindowManager& parW // Centre dialog center(); - setText("ReflectT", mWindowManager.getGameSettingString("sMessageQuestionAnswer1", "")); + setText("ReflectT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sMessageQuestionAnswer1", "")); getWidget(mClassImage, "ClassImage"); getWidget(mClassName, "ClassName"); @@ -37,7 +37,7 @@ GenerateClassResultDialog::GenerateClassResultDialog(MWBase::WindowManager& parW MyGUI::Button* okButton; getWidget(okButton, "OKButton"); - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked); } @@ -77,16 +77,12 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager) getWidget(mFavoriteAttribute[0], "FavoriteAttribute0"); getWidget(mFavoriteAttribute[1], "FavoriteAttribute1"); - mFavoriteAttribute[0]->setWindowManager(&mWindowManager); - mFavoriteAttribute[1]->setWindowManager(&mWindowManager); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; getWidget(mMajorSkill[i], std::string("MajorSkill").append(1, theIndex)); getWidget(mMinorSkill[i], std::string("MinorSkill").append(1, theIndex)); - mMajorSkill[i]->setWindowManager(&mWindowManager); - mMinorSkill[i]->setWindowManager(&mWindowManager); } getWidget(mClassList, "ClassList"); @@ -115,9 +111,9 @@ void PickClassDialog::setNextButtonShow(bool shown) getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); else - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); } void PickClassDialog::open() @@ -224,7 +220,7 @@ void PickClassDialog::updateStats() "sSpecializationMagic", "sSpecializationStealth" }; - std::string specName = mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization]); + std::string specName = MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[specialization], specIds[specialization]); mSpecializationName->setCaption(specName); ToolTips::createSpecializationToolTip(mSpecializationName, specName, specialization); @@ -365,10 +361,10 @@ ClassChoiceDialog::ClassChoiceDialog(MWBase::WindowManager& parWindowManager) { setText(""); ButtonList buttons; - buttons.push_back(mWindowManager.getGameSettingString("sClassChoiceMenu1", "")); - buttons.push_back(mWindowManager.getGameSettingString("sClassChoiceMenu2", "")); - buttons.push_back(mWindowManager.getGameSettingString("sClassChoiceMenu3", "")); - buttons.push_back(mWindowManager.getGameSettingString("sBack", "")); + buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu1", "")); + buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu2", "")); + buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu3", "")); + buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBack", "")); setButtons(buttons); } @@ -384,20 +380,18 @@ CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager) // Centre dialog center(); - setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); + setText("SpecializationT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sChooseClassMenu1", "Specialization")); getWidget(mSpecializationName, "SpecializationName"); mSpecializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked); - setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); + setText("FavoriteAttributesT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); getWidget(mFavoriteAttribute0, "FavoriteAttribute0"); getWidget(mFavoriteAttribute1, "FavoriteAttribute1"); - mFavoriteAttribute0->setWindowManager(&mWindowManager); - mFavoriteAttribute1->setWindowManager(&mWindowManager); mFavoriteAttribute0->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked); mFavoriteAttribute1->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeClicked); - setText("MajorSkillT", mWindowManager.getGameSettingString("sSkillClassMajor", "")); - setText("MinorSkillT", mWindowManager.getGameSettingString("sSkillClassMinor", "")); + setText("MajorSkillT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillClassMajor", "")); + setText("MinorSkillT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillClassMinor", "")); for(int i = 0; i < 5; i++) { char theIndex = '0'+i; @@ -410,11 +404,10 @@ CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager) std::vector::const_iterator end = mSkills.end(); for (std::vector::const_iterator it = mSkills.begin(); it != end; ++it) { - (*it)->setWindowManager(&mWindowManager); (*it)->eventClicked += MyGUI::newDelegate(this, &CreateClassDialog::onSkillClicked); } - setText("LabelT", mWindowManager.getGameSettingString("sName", "")); + setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "")); getWidget(mEditName, "EditName"); // Make sure the edit box has focus @@ -522,32 +515,32 @@ void CreateClassDialog::setNextButtonShow(bool shown) getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); else - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); } // widget controls void CreateClassDialog::onDialogCancel() { - mWindowManager.removeDialog(mSpecDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mSpecDialog); mSpecDialog = 0; - mWindowManager.removeDialog(mAttribDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mAttribDialog); mAttribDialog = 0; - mWindowManager.removeDialog(mSkillDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mSkillDialog); mSkillDialog = 0; - mWindowManager.removeDialog(mDescDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mDescDialog); mDescDialog = 0; } void CreateClassDialog::onSpecializationClicked(MyGUI::Widget* _sender) { delete mSpecDialog; - mSpecDialog = new SelectSpecializationDialog(mWindowManager); + mSpecDialog = new SelectSpecializationDialog(*MWBase::Environment::get().getWindowManager()); mSpecDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mSpecDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected); mSpecDialog->setVisible(true); @@ -558,7 +551,7 @@ void CreateClassDialog::onSpecializationSelected() mSpecializationId = mSpecDialog->getSpecializationId(); setSpecialization(mSpecializationId); - mWindowManager.removeDialog(mSpecDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mSpecDialog); mSpecDialog = 0; } @@ -570,7 +563,7 @@ void CreateClassDialog::setSpecialization(int id) "sSpecializationMagic", "sSpecializationStealth" }; - std::string specName = mWindowManager.getGameSettingString(specIds[mSpecializationId], specIds[mSpecializationId]); + std::string specName = MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[mSpecializationId], specIds[mSpecializationId]); mSpecializationName->setCaption(specName); ToolTips::createSpecializationToolTip(mSpecializationName, specName, mSpecializationId); } @@ -578,7 +571,7 @@ void CreateClassDialog::setSpecialization(int id) void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) { delete mAttribDialog; - mAttribDialog = new SelectAttributeDialog(mWindowManager); + mAttribDialog = new SelectAttributeDialog(*MWBase::Environment::get().getWindowManager()); mAffectedAttribute = _sender; mAttribDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mAttribDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected); @@ -599,7 +592,7 @@ void CreateClassDialog::onAttributeSelected() mFavoriteAttribute0->setAttributeId(mFavoriteAttribute1->getAttributeId()); } mAffectedAttribute->setAttributeId(id); - mWindowManager.removeDialog(mAttribDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mAttribDialog); mAttribDialog = 0; update(); @@ -608,7 +601,7 @@ void CreateClassDialog::onAttributeSelected() void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) { delete mSkillDialog; - mSkillDialog = new SelectSkillDialog(mWindowManager); + mSkillDialog = new SelectSkillDialog(*MWBase::Environment::get().getWindowManager()); mAffectedSkill = _sender; mSkillDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mSkillDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected); @@ -633,14 +626,14 @@ void CreateClassDialog::onSkillSelected() } mAffectedSkill->setSkillId(mSkillDialog->getSkillId()); - mWindowManager.removeDialog(mSkillDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mSkillDialog); mSkillDialog = 0; update(); } void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) { - mDescDialog = new DescriptionDialog(mWindowManager); + mDescDialog = new DescriptionDialog(*MWBase::Environment::get().getWindowManager()); mDescDialog->setTextInput(mDescription); mDescDialog->eventDone += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered); mDescDialog->setVisible(true); @@ -649,7 +642,7 @@ void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow) { mDescription = mDescDialog->getTextInput(); - mWindowManager.removeDialog(mDescDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mDescDialog); mDescDialog = 0; } @@ -673,14 +666,14 @@ SelectSpecializationDialog::SelectSpecializationDialog(MWBase::WindowManager& pa // Centre dialog center(); - setText("LabelT", mWindowManager.getGameSettingString("sSpecializationMenu1", "")); + setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationMenu1", "")); getWidget(mSpecialization0, "Specialization0"); getWidget(mSpecialization1, "Specialization1"); getWidget(mSpecialization2, "Specialization2"); - std::string combat = mWindowManager.getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Combat], ""); - std::string magic = mWindowManager.getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Magic], ""); - std::string stealth = mWindowManager.getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Stealth], ""); + std::string combat = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Combat], ""); + std::string magic = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Magic], ""); + std::string stealth = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Class::sGmstSpecializationIds[ESM::Class::Stealth], ""); mSpecialization0->setCaption(combat); mSpecialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); @@ -696,7 +689,7 @@ SelectSpecializationDialog::SelectSpecializationDialog(MWBase::WindowManager& pa MyGUI::Button* cancelButton; getWidget(cancelButton, "CancelButton"); - cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); + cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); } @@ -733,7 +726,7 @@ SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowMan // Centre dialog center(); - setText("LabelT", mWindowManager.getGameSettingString("sAttributesMenu1", "")); + setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sAttributesMenu1", "")); for (int i = 0; i < 8; ++i) { @@ -741,7 +734,6 @@ SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowMan char theIndex = '0'+i; getWidget(attribute, std::string("Attribute").append(1, theIndex)); - attribute->setWindowManager(&parWindowManager); attribute->setAttributeId(ESM::Attribute::sAttributeIds[i]); attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId()); @@ -749,7 +741,7 @@ SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowMan MyGUI::Button* cancelButton; getWidget(cancelButton, "CancelButton"); - cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); + cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); } @@ -780,10 +772,10 @@ SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager) // Centre dialog center(); - setText("LabelT", mWindowManager.getGameSettingString("sSkillsMenu1", "")); - setText("CombatLabelT", mWindowManager.getGameSettingString("sSpecializationCombat", "")); - setText("MagicLabelT", mWindowManager.getGameSettingString("sSpecializationMagic", "")); - setText("StealthLabelT", mWindowManager.getGameSettingString("sSpecializationStealth", "")); + setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillsMenu1", "")); + setText("CombatLabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationCombat", "")); + setText("MagicLabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationMagic", "")); + setText("StealthLabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationStealth", "")); for(int i = 0; i < 9; i++) { @@ -833,7 +825,6 @@ SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager) { for (int i = 0; i < 9; ++i) { - mSkills[spec][i].widget->setWindowManager(&mWindowManager); mSkills[spec][i].widget->setSkillId(mSkills[spec][i].skillId); mSkills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); ToolTips::createSkillToolTip(mSkills[spec][i].widget, mSkills[spec][i].widget->getSkillId()); @@ -842,7 +833,7 @@ SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager) MyGUI::Button* cancelButton; getWidget(cancelButton, "CancelButton"); - cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); + cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", "")); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); } @@ -876,7 +867,7 @@ DescriptionDialog::DescriptionDialog(MWBase::WindowManager& parWindowManager) MyGUI::Button* okButton; getWidget(okButton, "OKButton"); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DescriptionDialog::onOkClicked); - okButton->setCaption(mWindowManager.getGameSettingString("sInputMenu1", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sInputMenu1", "")); // Make sure the edit box has focus MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 8c60331d87..11da1a7913 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -3,7 +3,7 @@ #include "widgets.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" /* This file contains the dialogs for choosing a class. diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index 45941f2ad0..a925cad550 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_CONFIRMATIONDIALOG_H #define MWGUI_CONFIRMATIONDIALOG_H -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 7e6a0b0885..f7846e70ec 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -751,7 +751,7 @@ void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender) /// \todo I don't think this is the correct flag to check if (MWWorld::Class::get(mPtr).isEssential(mPtr)) - mWindowManager.messageBox("#{sDisposeCorpseFail}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}"); else MWBase::Environment::get().getWorld()->deleteObject(mPtr); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 03bd519f7d..7a3e804e5d 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -3,7 +3,7 @@ #include "../mwworld/esmstore.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" #include "referenceinterface.hpp" #include "../mwclass/container.hpp" diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp index 80da6eea01..d5155839d8 100644 --- a/apps/openmw/mwgui/countdialog.hpp +++ b/apps/openmw/mwgui/countdialog.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_COUNTDIALOG_H #define MWGUI_COUNTDIALOG_H -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index b3aa27617c..0939da1b17 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -18,7 +18,7 @@ #include "../mwdialogue/dialoguemanagerimp.hpp" -#include "dialogue_history.hpp" +#include "dialoguehistory.hpp" #include "widgets.hpp" #include "list.hpp" #include "tradewindow.hpp" @@ -89,17 +89,17 @@ void PersuasionDialog::onPersuade(MyGUI::Widget *sender) else if (sender == mTauntButton) type = MWBase::MechanicsManager::PT_Taunt; else if (sender == mBribe10Button) { - mWindowManager.getTradeWindow()->addOrRemoveGold(-10); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-10); type = MWBase::MechanicsManager::PT_Bribe10; } else if (sender == mBribe100Button) { - mWindowManager.getTradeWindow()->addOrRemoveGold(-100); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-100); type = MWBase::MechanicsManager::PT_Bribe100; } else /*if (sender == mBribe1000Button)*/ { - mWindowManager.getTradeWindow()->addOrRemoveGold(-1000); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-1000); type = MWBase::MechanicsManager::PT_Bribe1000; } @@ -113,7 +113,7 @@ void PersuasionDialog::open() WindowModal::open(); center(); - int playerGold = mWindowManager.getInventoryWindow()->getPlayerGold(); + int playerGold = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold(); mBribe10Button->setEnabled (playerGold >= 10); mBribe100Button->setEnabled (playerGold >= 100); @@ -251,45 +251,45 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id) } else if (topic == gmst.find("sCompanionShare")->getString()) { - mWindowManager.pushGuiMode(GM_Companion); - mWindowManager.showCompanionWindow(mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion); + MWBase::Environment::get().getWindowManager()->showCompanionWindow(mPtr); } else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused()) { if (topic == gmst.find("sBarter")->getString()) { - mWindowManager.pushGuiMode(GM_Barter); - mWindowManager.getTradeWindow()->startTrade(mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->startTrade(mPtr); } else if (topic == gmst.find("sSpells")->getString()) { - mWindowManager.pushGuiMode(GM_SpellBuying); - mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying); + MWBase::Environment::get().getWindowManager()->getSpellBuyingWindow()->startSpellBuying(mPtr); } else if (topic == gmst.find("sTravel")->getString()) { - mWindowManager.pushGuiMode(GM_Travel); - mWindowManager.getTravelWindow()->startTravel(mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel); + MWBase::Environment::get().getWindowManager()->getTravelWindow()->startTravel(mPtr); } else if (topic == gmst.find("sSpellMakingMenuTitle")->getString()) { - mWindowManager.pushGuiMode(GM_SpellCreation); - mWindowManager.startSpellMaking (mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation); + MWBase::Environment::get().getWindowManager()->startSpellMaking (mPtr); } else if (topic == gmst.find("sEnchanting")->getString()) { - mWindowManager.pushGuiMode(GM_Enchanting); - mWindowManager.startEnchanting (mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting); + MWBase::Environment::get().getWindowManager()->startEnchanting (mPtr); } else if (topic == gmst.find("sServiceTrainingTitle")->getString()) { - mWindowManager.pushGuiMode(GM_Training); - mWindowManager.startTraining (mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training); + MWBase::Environment::get().getWindowManager()->startTraining (mPtr); } else if (topic == gmst.find("sRepair")->getString()) { - mWindowManager.pushGuiMode(GM_MerchantRepair); - mWindowManager.startRepair (mPtr); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair); + MWBase::Environment::get().getWindowManager()->startRepair (mPtr); } } } @@ -456,7 +456,7 @@ std::string DialogueWindow::parseText(const std::string& text) } else { - if( !mWindowManager.getTranslationDataStorage().hasTranslation() ) + if( !MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation() ) { for(std::vector::const_iterator it = topics.begin(); it != topics.end(); ++it) { @@ -528,7 +528,7 @@ void DialogueWindow::goodbye() void DialogueWindow::onReferenceUnavailable() { - mWindowManager.removeGuiMode(GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); } void DialogueWindow::onFrame() diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 187731fc77..e78856c951 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_DIALOGE_H #define MWGUI_DIALOGE_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "referenceinterface.hpp" #include diff --git a/apps/openmw/mwgui/dialoguehistory.cpp b/apps/openmw/mwgui/dialoguehistory.cpp new file mode 100644 index 0000000000..a122a78916 --- /dev/null +++ b/apps/openmw/mwgui/dialoguehistory.cpp @@ -0,0 +1,76 @@ +#include "dialoguehistory.hpp" + +#include "../mwbase/windowmanager.hpp" + +#include "widgets.hpp" + +#include "../mwworld/esmstore.hpp" + +#include +#include + +#include +#include + +using namespace MWGui; +using namespace Widgets; + +MyGUI::UString DialogueHistory::getColorAtPos(size_t _pos) +{ + MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour()); + MyGUI::TextIterator iterator(getCaption()); + while(iterator.moveNext()) + { + size_t pos = iterator.getPosition(); + iterator.getTagColour(colour); + if (pos < _pos) + continue; + else if (pos == _pos) + break; + } + return colour; +} + +MyGUI::UString DialogueHistory::getColorTextAt(size_t _pos) +{ + bool breakOnNext = false; + MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour()); + MyGUI::UString colour2 = colour; + MyGUI::TextIterator iterator(getCaption()); + MyGUI::TextIterator col_start = iterator; + while(iterator.moveNext()) + { + size_t pos = iterator.getPosition(); + iterator.getTagColour(colour); + if(colour != colour2) + { + if(breakOnNext) + { + return getOnlyText().substr(col_start.getPosition(), iterator.getPosition()-col_start.getPosition()); + } + col_start = iterator; + colour2 = colour; + } + if (pos < _pos) + continue; + else if (pos == _pos) + { + breakOnNext = true; + } + } + return ""; +} + +void DialogueHistory::addDialogHeading(const MyGUI::UString& parText) +{ + MyGUI::UString head("\n#D8C09A"); + head.append(parText); + head.append("#B29154\n"); + addText(head); +} + +void DialogueHistory::addDialogText(const MyGUI::UString& parText) +{ + addText(parText); + addText("\n"); +} diff --git a/apps/openmw/mwgui/dialoguehistory.hpp b/apps/openmw/mwgui/dialoguehistory.hpp new file mode 100644 index 0000000000..c37504af77 --- /dev/null +++ b/apps/openmw/mwgui/dialoguehistory.hpp @@ -0,0 +1,19 @@ +#ifndef MWGUI_DIALOGE_HISTORY_H +#define MWGUI_DIALOGE_HISTORY_H +#include + +namespace MWGui +{ + class DialogueHistory : public MyGUI::EditBox + { + MYGUI_RTTI_DERIVED( DialogueHistory ) + public: + Widget* getClient() { return mClient; } + MyGUI::UString getColorAtPos(size_t _pos); + MyGUI::UString getColorTextAt(size_t _pos); + void addDialogHeading(const MyGUI::UString& parText); + void addDialogText(const MyGUI::UString& parText); + }; +} +#endif + diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 276e7a9047..02d847d1a8 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -69,19 +69,19 @@ namespace MWGui switch(mEnchanting.getEnchantType()) { case 0: - mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastOnce","Cast Once")); + mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastOnce","Cast Once")); mAddEffectDialog.constantEffect=false; break; case 1: - mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastWhenStrikes", "When Strikes")); + mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastWhenStrikes", "When Strikes")); mAddEffectDialog.constantEffect=false; break; case 2: - mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastWhenUsed", "When Used")); + mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastWhenUsed", "When Used")); mAddEffectDialog.constantEffect=false; break; case 3: - mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastConstant", "Cast Constant")); + mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastConstant", "Cast Constant")); mAddEffectDialog.constantEffect=true; break; } @@ -126,20 +126,20 @@ namespace MWGui void EnchantingDialog::onReferenceUnavailable () { - mWindowManager.removeGuiMode (GM_Dialogue); - mWindowManager.removeGuiMode (GM_Enchanting); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting); } void EnchantingDialog::onCancelButtonClicked(MyGUI::Widget* sender) { - mWindowManager.removeGuiMode (GM_Enchanting); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting); } void EnchantingDialog::onSelectItem(MyGUI::Widget *sender) { delete mItemSelectionDialog; mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}", - ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic, mWindowManager); + ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic, *MWBase::Environment::get().getWindowManager()); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); mItemSelectionDialog->setVisible(true); @@ -190,7 +190,7 @@ namespace MWGui if(mEnchanting.getGemCharge()==0) { - mWindowManager.messageBox ("#{sNotifyMessage32}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage32}"); return; } @@ -227,14 +227,14 @@ namespace MWGui { delete mItemSelectionDialog; mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}", - ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones, mWindowManager); + ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones, *MWBase::Environment::get().getWindowManager()); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); mItemSelectionDialog->setVisible(true); mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); mItemSelectionDialog->drawItems (); - //mWindowManager.messageBox("#{sInventorySelectNoSoul}"); + //MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}"); } void EnchantingDialog::notifyEffectsChanged () @@ -254,50 +254,50 @@ namespace MWGui { if (mEffects.size() <= 0) { - mWindowManager.messageBox ("#{sNotifyMessage30}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage30}"); return; } if (mName->getCaption ().empty()) { - mWindowManager.messageBox ("#{sNotifyMessage10}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage10}"); return; } if (mEnchanting.soulEmpty()) { - mWindowManager.messageBox ("#{sNotifyMessage52}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage52}"); return; } if (mEnchanting.itemEmpty()) { - mWindowManager.messageBox ("#{sNotifyMessage11}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage11}"); return; } if (mEnchanting.getEnchantCost() > mEnchanting.getMaxEnchantValue()) { - mWindowManager.messageBox ("#{sNotifyMessage29}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage29}"); return; } mEnchanting.setNewItemName(mName->getCaption()); mEnchanting.setEffect(mEffectList); - if (mEnchanting.getEnchantPrice() > mWindowManager.getInventoryWindow()->getPlayerGold()) + if (mEnchanting.getEnchantPrice() > MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) { - mWindowManager.messageBox ("#{sNotifyMessage18}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage18}"); return; } int result = mEnchanting.create(); if(result==1) - mWindowManager.messageBox ("#{sEnchantmentMenu12}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu12}"); else - mWindowManager.messageBox ("#{sNotifyMessage34}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage34}"); - mWindowManager.removeGuiMode (GM_Enchanting); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting); } } diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index a7861c422d..822199ac67 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_ENCHANTINGDIALOG_H #define MWGUI_ENCHANTINGDIALOG_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "referenceinterface.hpp" #include "spellcreationdialog.hpp" diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index aab9e62a4f..c65566ce3e 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -1,4 +1,4 @@ -#include "map_window.hpp" +#include "mapwindow.hpp" #include diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 001f42bd11..393f03a541 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -130,7 +130,7 @@ namespace MWGui void InventoryWindow::onPinToggled() { - mWindowManager.setWeaponVisibility(!mPinned); + MWBase::Environment::get().getWindowManager()->setWeaponVisibility(!mPinned); } void InventoryWindow::onAvatarClicked(MyGUI::Widget* _sender) @@ -162,13 +162,13 @@ namespace MWGui // the "Take" button should not be visible. // NOTE: the take button is "reset" when the window opens, so we can safely do the following // without screwing up future book windows - mWindowManager.getBookWindow()->setTakeButtonShow(false); - mWindowManager.getScrollWindow()->setTakeButtonShow(false); + MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false); + MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false); mDragAndDrop->mIsOnDragAndDrop = false; MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget); - mWindowManager.setDragDrop(false); + MWBase::Environment::get().getWindowManager()->setDragDrop(false); drawItems(); @@ -224,11 +224,11 @@ namespace MWGui { invStore.equip(slot, invStore.end()); std::string script = MWWorld::Class::get(*it).getScript(*it); - + // Unset OnPCEquip Variable on item's script, if it has a script with that variable declared if(script != "") (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 0); - + return; } } @@ -285,16 +285,16 @@ namespace MWGui void InventoryWindow::notifyContentChanged() { // update the spell window just in case new enchanted items were added to inventory - if (mWindowManager.getSpellWindow()) - mWindowManager.getSpellWindow()->updateSpells(); + if (MWBase::Environment::get().getWindowManager()->getSpellWindow()) + MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells(); // update selected weapon icon MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if (weaponSlot == invStore.end()) - mWindowManager.unsetSelectedWeapon(); + MWBase::Environment::get().getWindowManager()->unsetSelectedWeapon(); else - mWindowManager.setSelectedWeapon(*weaponSlot); /// \todo track weapon durability + MWBase::Environment::get().getWindowManager()->setSelectedWeapon(*weaponSlot); /// \todo track weapon durability mPreviewDirty = true; diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index fceb7ecef1..61ee17ef93 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -4,7 +4,7 @@ #include "../mwrender/characterpreview.hpp" #include "container.hpp" -#include "window_pinnable_base.hpp" +#include "windowpinnablebase.hpp" #include "widgets.hpp" namespace MWGui diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index cd1ff7ebbd..73a2dca2ec 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -6,7 +6,7 @@ #include #include -#include "window_base.hpp" +#include "windowbase.hpp" #include "imagebutton.hpp" namespace MWGui diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index 67620d49da..dcecdccc1b 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -183,7 +183,7 @@ namespace MWGui creatureStats.setLevel (creatureStats.getLevel()+1); pcStats.levelUp (); - mWindowManager.removeGuiMode (GM_Levelup); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Levelup); } } diff --git a/apps/openmw/mwgui/levelupdialog.hpp b/apps/openmw/mwgui/levelupdialog.hpp index 3c8b74800b..a54948e2a0 100644 --- a/apps/openmw/mwgui/levelupdialog.hpp +++ b/apps/openmw/mwgui/levelupdialog.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_LEVELUPDIALOG_H #define MWGUI_LEVELUPDIALOG_H -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 86f196d9f5..3066705124 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -195,12 +195,12 @@ namespace MWGui { changeWallpaper(); - mWindowManager.pushGuiMode(GM_LoadingWallpaper); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_LoadingWallpaper); } else { mBackgroundImage->setImageTexture(""); - mWindowManager.pushGuiMode(GM_Loading); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Loading); } } @@ -211,8 +211,8 @@ namespace MWGui mLoadingOn = false; mFirstLoad = false; - mWindowManager.removeGuiMode(GM_Loading); - mWindowManager.removeGuiMode(GM_LoadingWallpaper); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper); } void LoadingScreen::changeWallpaper () diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 176fc0f5d5..cb33975ae3 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -4,7 +4,7 @@ #include #include -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp new file mode 100644 index 0000000000..029974d2b3 --- /dev/null +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -0,0 +1,446 @@ +#include "mapwindow.hpp" + +#include + +#include +#include +#include + +#include + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/player.hpp" + +#include "../mwrender/globalmap.hpp" + +#include "widgets.hpp" + +using namespace MWGui; + +LocalMapBase::LocalMapBase() + : mCurX(0) + , mCurY(0) + , mInterior(false) + , mFogOfWar(true) + , mLocalMap(NULL) + , mMapDragAndDrop(false) + , mPrefix() + , mChanged(true) + , mLayout(NULL) + , mLastPositionX(0.0f) + , mLastPositionY(0.0f) + , mLastDirectionX(0.0f) + , mLastDirectionY(0.0f) + , mCompass(NULL) +{ +} + +void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop) +{ + mLocalMap = widget; + mLayout = layout; + mMapDragAndDrop = mapDragAndDrop; + mCompass = compass; + + // create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each + const int widgetSize = 512; + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + MyGUI::ImageBox* map = mLocalMap->createWidget("ImageBox", + MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), + MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my)); + + MyGUI::ImageBox* fog = map->createWidget("ImageBox", + MyGUI::IntCoord(0, 0, widgetSize, widgetSize), + MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my) + "_fog"); + + if (!mMapDragAndDrop) + { + map->setNeedMouseFocus(false); + fog->setNeedMouseFocus(false); + } + + mMapWidgets.push_back(map); + mFogWidgets.push_back(fog); + } + } +} + +void LocalMapBase::setCellPrefix(const std::string& prefix) +{ + mPrefix = prefix; + mChanged = true; +} + +void LocalMapBase::toggleFogOfWar() +{ + mFogOfWar = !mFogOfWar; + applyFogOfWar(); +} + +void LocalMapBase::applyFogOfWar() +{ + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + std::string name = "Map_" + boost::lexical_cast(mx) + "_" + + boost::lexical_cast(my); + + std::string image = mPrefix+"_"+ boost::lexical_cast(mCurX + (mx-1)) + "_" + + boost::lexical_cast(mCurY + (-1*(my-1))); + MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx]; + fog->setImageTexture(mFogOfWar ? + ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" + : "black.png" ) + : ""); + } + } + notifyMapChanged (); +} + +void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2) +{ + applyFogOfWar (); +} + +void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2) +{ + applyFogOfWar (); +} + +void LocalMapBase::setActiveCell(const int x, const int y, bool interior) +{ + if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell + + // clear all previous markers + for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i) + { + if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker") + { + MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i)); + } + } + + for (int mx=0; mx<3; ++mx) + { + for (int my=0; my<3; ++my) + { + // map + std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" + + boost::lexical_cast(y + (-1*(my-1))); + + std::string name = "Map_" + boost::lexical_cast(mx) + "_" + + boost::lexical_cast(my); + + MyGUI::ImageBox* box = mMapWidgets[my + 3*mx]; + + if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) + box->setImageTexture(image); + else + box->setImageTexture("black.png"); + + + // door markers + + // interior map only consists of one cell, so handle the markers only once + if (interior && (mx != 2 || my != 2)) + continue; + + MWWorld::CellStore* cell; + if (interior) + cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix); + else + cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1)); + + std::vector doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell); + + for (std::vector::iterator it = doors.begin(); it != doors.end(); ++it) + { + MWBase::World::DoorMarker marker = *it; + + // convert world coordinates to normalized cell coordinates + MyGUI::IntCoord widgetCoord; + float nX,nY; + int cellDx, cellDy; + if (!interior) + { + const int cellSize = 8192; + + nX = (marker.x - cellSize * (x+mx-1)) / cellSize; + nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize; + + widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8); + } + else + { + Ogre::Vector2 position (marker.x, marker.y); + MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy); + + widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8); + } + + static int counter = 0; + ++counter; + MyGUI::Button* markerWidget = mLocalMap->createWidget("ButtonImage", + widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast(counter)); + markerWidget->setImageResource("DoorMarker"); + markerWidget->setUserString("ToolTipType", "Layout"); + markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); + markerWidget->setUserString("Caption_TextOneLine", marker.name); + markerWidget->setUserString("IsMarker", "true"); + markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused); + markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused); + + MarkerPosition markerPos; + markerPos.interior = interior; + markerPos.cellX = interior ? cellDx : x + mx - 1; + markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1); + markerPos.nX = nX; + markerPos.nY = nY; + + markerWidget->setUserData(markerPos); + } + + + } + } + mInterior = interior; + mCurX = x; + mCurY = y; + mChanged = false; + + // fog of war + applyFogOfWar(); + + // set the compass texture again, because MyGUI determines sorting of ImageBox widgets + // based on the last setImageTexture call + std::string tex = "textures\\compass.dds"; + mCompass->setImageTexture(""); + mCompass->setImageTexture(tex); +} + + +void LocalMapBase::setPlayerPos(const float x, const float y) +{ + if (x == mLastPositionX && y == mLastPositionY) + return; + + notifyPlayerUpdate (); + + MyGUI::IntSize size = mLocalMap->getCanvasSize(); + MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); + MyGUI::IntCoord viewsize = mLocalMap->getCoord(); + MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); + mLocalMap->setViewOffset(pos); + + mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16)); + mLastPositionX = x; + mLastPositionY = y; +} + +void LocalMapBase::setPlayerDir(const float x, const float y) +{ + if (x == mLastDirectionX && y == mLastDirectionY) + return; + + notifyPlayerUpdate (); + + MyGUI::ISubWidget* main = mCompass->getSubWidgetMain(); + MyGUI::RotatingSkin* rotatingSubskin = main->castType(); + rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); + float angle = std::atan2(x,y); + rotatingSubskin->setAngle(angle); + + mLastDirectionX = x; + mLastDirectionY = y; +} + +// ------------------------------------------------------------------------------------------ + +MapWindow::MapWindow(MWBase::WindowManager& parWindowManager, const std::string& cacheDir) + : MWGui::WindowPinnableBase("openmw_map_window.layout", parWindowManager) + , mGlobal(false) +{ + setCoord(500,0,320,300); + + mGlobalMapRender = new MWRender::GlobalMap(cacheDir); + mGlobalMapRender->render(); + + getWidget(mLocalMap, "LocalMap"); + getWidget(mGlobalMap, "GlobalMap"); + getWidget(mGlobalMapImage, "GlobalMapImage"); + getWidget(mGlobalMapOverlay, "GlobalMapOverlay"); + getWidget(mPlayerArrowLocal, "CompassLocal"); + getWidget(mPlayerArrowGlobal, "CompassGlobal"); + + mGlobalMapImage->setImageTexture("GlobalMap.png"); + mGlobalMapOverlay->setImageTexture("GlobalMapOverlay"); + + mGlobalMap->setVisible (false); + + getWidget(mButton, "WorldButton"); + mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); + mButton->setCaptionWithReplacing("#{sWorld}"); + + getWidget(mEventBoxGlobal, "EventBoxGlobal"); + mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); + mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); + getWidget(mEventBoxLocal, "EventBoxLocal"); + mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); + mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); + + LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this); +} + +MapWindow::~MapWindow() +{ + delete mGlobalMapRender; +} + +void MapWindow::setCellName(const std::string& cellName) +{ + setTitle("#{sCell=" + cellName + "}"); +} + +void MapWindow::addVisitedLocation(const std::string& name, int x, int y) +{ + float worldX, worldY; + mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY); + + MyGUI::IntCoord widgetCoord( + worldX * mGlobalMapRender->getWidth()+6, + worldY * mGlobalMapRender->getHeight()+6, + 12, 12); + + + static int _counter=0; + MyGUI::Button* markerWidget = mGlobalMapImage->createWidget("ButtonImage", + widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast(_counter)); + markerWidget->setImageResource("DoorMarker"); + markerWidget->setUserString("ToolTipType", "Layout"); + markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); + markerWidget->setUserString("Caption_TextOneLine", name); + ++_counter; + + markerWidget = mEventBoxGlobal->createWidget("", + widgetCoord, MyGUI::Align::Default); + markerWidget->setNeedMouseFocus (true); + markerWidget->setUserString("ToolTipType", "Layout"); + markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); + markerWidget->setUserString("Caption_TextOneLine", name); +} + +void MapWindow::cellExplored(int x, int y) +{ + mGlobalMapRender->exploreCell(x,y); +} + +void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) +{ + if (_id!=MyGUI::MouseButton::Left) return; + mLastDragPos = MyGUI::IntPoint(_left, _top); +} + +void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) +{ + if (_id!=MyGUI::MouseButton::Left) return; + + MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos; + + if (!mGlobal) + mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff ); + else + mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff ); + + + mLastDragPos = MyGUI::IntPoint(_left, _top); +} + +void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) +{ + mGlobal = !mGlobal; + mGlobalMap->setVisible(mGlobal); + mLocalMap->setVisible(!mGlobal); + + mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : + "#{sWorld}"); + + if (mGlobal) + globalMapUpdatePlayer (); +} + +void MapWindow::onPinToggled() +{ + MWBase::Environment::get().getWindowManager()->setMinimapVisibility(!mPinned); +} + +void MapWindow::open() +{ + mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); + mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); + + for (unsigned int i=0; igetChildCount (); ++i) + { + if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker") + mGlobalMapImage->getChildAt (i)->castType()->setImageResource("DoorMarker"); + } + + globalMapUpdatePlayer(); + + mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds"); +} + +void MapWindow::globalMapUpdatePlayer () +{ + Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition (); + Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation (); + Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y); + + float worldX, worldY; + mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY); + worldX *= mGlobalMapRender->getWidth(); + worldY *= mGlobalMapRender->getHeight(); + + + // for interiors, we have no choice other than using the last position & direction. + /// \todo save this last position in the savegame? + if (MWBase::Environment::get().getWorld ()->isCellExterior ()) + { + mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16)); + + MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain(); + MyGUI::RotatingSkin* rotatingSubskin = main->castType(); + rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); + float angle = std::atan2(dir.x, dir.y); + rotatingSubskin->setAngle(angle); + + // set the view offset so that player is in the center + MyGUI::IntSize viewsize = mGlobalMap->getSize(); + MyGUI::IntPoint viewoffs(0.5*viewsize.width - worldX, 0.5*viewsize.height - worldY); + mGlobalMap->setViewOffset(viewoffs); + } +} + +void MapWindow::notifyPlayerUpdate () +{ + globalMapUpdatePlayer (); +} + +void MapWindow::notifyMapChanged () +{ + // workaround to prevent the map from drawing on top of the button + MyGUI::IntCoord oldCoord = mButton->getCoord (); + MyGUI::Gui::getInstance().destroyWidget (mButton); + mButton = mMainWidget->createWidget("MW_Button", + oldCoord, MyGUI::Align::Bottom | MyGUI::Align::Right); + mButton->setProperty ("ExpandDirection", "Left"); + + mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); + mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : + "#{sWorld}"); +} diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp new file mode 100644 index 0000000000..329854e182 --- /dev/null +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -0,0 +1,107 @@ +#ifndef MWGUI_MAPWINDOW_H +#define MWGUI_MAPWINDOW_H + +#include "windowpinnablebase.hpp" + +namespace MWRender +{ + class GlobalMap; +} + +namespace MWGui +{ + class LocalMapBase + { + public: + LocalMapBase(); + void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop=false); + + void setCellPrefix(const std::string& prefix); + void setActiveCell(const int x, const int y, bool interior=false); + void setPlayerDir(const float x, const float y); + void setPlayerPos(const float x, const float y); + + void toggleFogOfWar(); + + struct MarkerPosition + { + bool interior; + int cellX; + int cellY; + float nX; + float nY; + }; + + protected: + int mCurX, mCurY; + bool mInterior; + MyGUI::ScrollView* mLocalMap; + MyGUI::ImageBox* mCompass; + std::string mPrefix; + bool mChanged; + bool mFogOfWar; + + std::vector mMapWidgets; + std::vector mFogWidgets; + + void applyFogOfWar(); + + void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2); + void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2); + + virtual void notifyPlayerUpdate() {} + virtual void notifyMapChanged() {} + + OEngine::GUI::Layout* mLayout; + + bool mMapDragAndDrop; + + float mLastPositionX; + float mLastPositionY; + float mLastDirectionX; + float mLastDirectionY; + }; + + class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase + { + public: + MapWindow(MWBase::WindowManager& parWindowManager, const std::string& cacheDir); + virtual ~MapWindow(); + + void setCellName(const std::string& cellName); + + void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map + void cellExplored(int x, int y); + + virtual void open(); + + private: + void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); + void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); + void onWorldButtonClicked(MyGUI::Widget* _sender); + + void globalMapUpdatePlayer(); + + MyGUI::ScrollView* mGlobalMap; + MyGUI::ImageBox* mGlobalMapImage; + MyGUI::ImageBox* mGlobalMapOverlay; + MyGUI::ImageBox* mPlayerArrowLocal; + MyGUI::ImageBox* mPlayerArrowGlobal; + MyGUI::Button* mButton; + MyGUI::IntPoint mLastDragPos; + bool mGlobal; + + MyGUI::Button* mEventBoxGlobal; + MyGUI::Button* mEventBoxLocal; + + MWRender::GlobalMap* mGlobalMapRender; + + protected: + virtual void onPinToggled(); + + virtual void notifyPlayerUpdate(); + virtual void notifyMapChanged(); + + }; +} +#endif diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 1c9056748b..f24d2d4177 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -72,7 +72,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) MyGUI::Button* button = mList->createWidget( - (price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", + (price>MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, currentY, 0, @@ -82,7 +82,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) currentY += 18; - button->setEnabled(price<=mWindowManager.getInventoryWindow()->getPlayerGold()); + button->setEnabled(price<=MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()); button->setUserString("Price", boost::lexical_cast(price)); button->setUserData(*iter); button->setCaptionWithReplacing(name); @@ -95,7 +95,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY))); mGoldLabel->setCaptionWithReplacing("#{sGold}: " - + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); + + boost::lexical_cast(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())); } void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel) @@ -120,14 +120,14 @@ void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); int price = boost::lexical_cast(sender->getUserString("Price")); - mWindowManager.getTradeWindow()->addOrRemoveGold(-price); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-price); startRepair(mActor); } void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender) { - mWindowManager.removeGuiMode(GM_MerchantRepair); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_MerchantRepair); } } diff --git a/apps/openmw/mwgui/merchantrepair.hpp b/apps/openmw/mwgui/merchantrepair.hpp index 4b7e2b8fbd..2cd6c486a9 100644 --- a/apps/openmw/mwgui/merchantrepair.hpp +++ b/apps/openmw/mwgui/merchantrepair.hpp @@ -1,7 +1,7 @@ #ifndef OPENMW_MWGUI_MERCHANTREPAIR_H #define OPENMW_MWGUI_MERCHANTREPAIR_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 46663b67a5..58bbc3c3ab 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -7,9 +7,8 @@ using namespace MWGui; -MessageBoxManager::MessageBoxManager (MWBase::WindowManager *windowManager) +MessageBoxManager::MessageBoxManager (MWBase::WindowManager* windowManager) { - mWindowManager = windowManager; // defines mMessageBoxSpeed = 0.1; mInterMessageBoxe = NULL; @@ -371,7 +370,7 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan void InteractiveMessageBox::enterPressed() { - + std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); std::vector::const_iterator button; for(button = mButtons.begin(); button != mButtons.end(); ++button) diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 859e1806a7..c64953b665 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -3,7 +3,7 @@ #include -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwbase/windowmanager.hpp" @@ -40,7 +40,7 @@ namespace MWGui void removeMessageBox (float time, MessageBox *msgbox); bool removeMessageBox (MessageBox *msgbox); void setMessageBoxSpeed (int speed); - + void enterPressed(); int readPressedButton (); @@ -51,8 +51,6 @@ namespace MWGui void onButtonPressed(int button) { eventButtonPressed(button); eventButtonPressed.clear(); } - MWBase::WindowManager *mWindowManager; - private: std::vector mMessageBoxes; InteractiveMessageBox* mInterMessageBoxe; @@ -92,7 +90,7 @@ namespace MWGui private: void buttonActivated (MyGUI::Widget* _widget); - + MessageBoxManager& mMessageBoxManager; MyGUI::EditBox* mMessageWidget; MyGUI::Widget* mButtonsWidget; diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 2e4bf9100b..82835a8058 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -109,14 +109,14 @@ namespace MWGui { // open assign dialog if (!mAssignDialog) - mAssignDialog = new QuickKeysMenuAssign(mWindowManager, this); + mAssignDialog = new QuickKeysMenuAssign(*MWBase::Environment::get().getWindowManager(), this); mAssignDialog->setVisible (true); } } void QuickKeysMenu::onOkButtonClicked (MyGUI::Widget *sender) { - mWindowManager.removeGuiMode(GM_QuickKeysMenu); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_QuickKeysMenu); } @@ -124,7 +124,7 @@ namespace MWGui { if (!mItemSelectionDialog ) { - mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}", ContainerBase::Filter_All, mWindowManager); + mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}", ContainerBase::Filter_All, *MWBase::Environment::get().getWindowManager()); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItemCancel); } @@ -139,7 +139,7 @@ namespace MWGui { if (!mMagicSelectionDialog ) { - mMagicSelectionDialog = new MagicSelectionDialog(mWindowManager, this); + mMagicSelectionDialog = new MagicSelectionDialog(*MWBase::Environment::get().getWindowManager(), this); } mMagicSelectionDialog->setVisible(true); @@ -281,7 +281,7 @@ namespace MWGui std::string spellId = button->getChildAt(0)->getUserString("Spell"); spells.setSelectedSpell(spellId); store.setSelectedEnchantItem(store.end()); - mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); + MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); } else if (type == Type_Item) { @@ -303,11 +303,11 @@ namespace MWGui // the "Take" button should not be visible. // NOTE: the take button is "reset" when the window opens, so we can safely do the following // without screwing up future book windows - mWindowManager.getBookWindow()->setTakeButtonShow(false); - mWindowManager.getScrollWindow()->setTakeButtonShow(false); + MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false); + MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false); // since we changed equipping status, update the inventory window - mWindowManager.getInventoryWindow()->drawItems(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } else if (type == Type_MagicItem) { @@ -341,12 +341,12 @@ namespace MWGui action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()); // since we changed equipping status, update the inventory window - mWindowManager.getInventoryWindow()->drawItems(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } store.setSelectedEnchantItem(it); spells.setSelectedSpell(""); - mWindowManager.setSelectedEnchantItem(item); + MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); } } diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 345ffa0c87..d5b6e6cd85 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -4,7 +4,7 @@ #include "../mwworld/ptr.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index be693eb2ba..167ad573a0 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -74,7 +74,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) // Centre dialog center(); - setText("AppearanceT", mWindowManager.getGameSettingString("sRaceMenu1", "Appearance")); + setText("AppearanceT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu1", "Appearance")); getWidget(mPreviewImage, "PreviewImage"); getWidget(mHeadRotate, "HeadRotate"); @@ -86,34 +86,34 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) // Set up next/previous buttons MyGUI::Button *prevButton, *nextButton; - setText("GenderChoiceT", mWindowManager.getGameSettingString("sRaceMenu2", "Change Sex")); + setText("GenderChoiceT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu2", "Change Sex")); getWidget(prevButton, "PrevGenderButton"); getWidget(nextButton, "NextGenderButton"); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousGender); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextGender); - setText("FaceChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Face")); + setText("FaceChoiceT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu3", "Change Face")); getWidget(prevButton, "PrevFaceButton"); getWidget(nextButton, "NextFaceButton"); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace); - setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu4", "Change Hair")); + setText("HairChoiceT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu4", "Change Hair")); getWidget(prevButton, "PrevHairButton"); getWidget(nextButton, "NextHairButton"); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextHair); - setText("RaceT", mWindowManager.getGameSettingString("sRaceMenu5", "Race")); + setText("RaceT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu5", "Race")); getWidget(mRaceList, "RaceList"); mRaceList->setScrollVisible(true); mRaceList->eventListSelectAccept += MyGUI::newDelegate(this, &RaceDialog::onSelectRace); mRaceList->eventListMouseItemActivate += MyGUI::newDelegate(this, &RaceDialog::onSelectRace); mRaceList->eventListChangePosition += MyGUI::newDelegate(this, &RaceDialog::onSelectRace); - setText("SkillsT", mWindowManager.getGameSettingString("sBonusSkillTitle", "Skill Bonus")); + setText("SkillsT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sBonusSkillTitle", "Skill Bonus")); getWidget(mSkillList, "SkillList"); - setText("SpellPowerT", mWindowManager.getGameSettingString("sRaceMenu7", "Specials")); + setText("SpellPowerT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu7", "Specials")); getWidget(mSpellPowerList, "SpellPowerList"); MyGUI::Button* backButton; @@ -122,7 +122,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) MyGUI::Button* okButton; getWidget(okButton, "OKButton"); - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); updateRaces(); @@ -136,9 +136,9 @@ void RaceDialog::setNextButtonShow(bool shown) getWidget(okButton, "OKButton"); if (shown) - okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); else - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); } void RaceDialog::open() @@ -156,7 +156,7 @@ void RaceDialog::open() const ESM::NPC proto = mPreview->getPrototype(); setRaceId(proto.mRace); recountParts(); - + std::string index = proto.mHead.substr(proto.mHead.size() - 2, 2); mFaceIndex = boost::lexical_cast(index) - 1; @@ -361,7 +361,7 @@ void RaceDialog::updateRaces() const MWWorld::Store &races = MWBase::Environment::get().getWorld()->getStore().get(); - + int index = 0; MWWorld::Store::iterator it = races.begin(); for (; it != races.end(); ++it) @@ -403,7 +403,6 @@ void RaceDialog::updateSkills() skillWidget = mSkillList->createWidget("MW_StatNameValue", coord1, MyGUI::Align::Default, std::string("Skill") + boost::lexical_cast(i)); - skillWidget->setWindowManager(&mWindowManager); skillWidget->setSkillNumber(skillId); skillWidget->setSkillValue(MWSkill::SkillValue(race->mData.mBonus[i].mBonus)); ToolTips::createSkillToolTip(skillWidget, skillId); @@ -439,7 +438,6 @@ void RaceDialog::updateSpellPowers() { const std::string &spellpower = *it; spellPowerWidget = mSpellPowerList->createWidget("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast(i)); - spellPowerWidget->setWindowManager(&mWindowManager); spellPowerWidget->setSpellId(spellpower); spellPowerWidget->setUserString("ToolTipType", "Spell"); spellPowerWidget->setUserString("Spell", spellpower); diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 0ca440ad53..4a4acd0112 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -8,7 +8,7 @@ #include "../mwrender/characterpreview.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index f53ddc4305..43c262ad85 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -133,7 +133,7 @@ void Repair::updateRepairView() void Repair::onCancel(MyGUI::Widget *sender) { - mWindowManager.removeGuiMode(GM_Repair); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Repair); } void Repair::onRepairItem(MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index c14b1955bd..824e0b6d2a 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -1,7 +1,7 @@ #ifndef OPENMW_MWGUI_REPAIR_H #define OPENMW_MWGUI_REPAIR_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwworld/ptr.hpp" #include "../mwmechanics/repair.hpp" diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 50508cc5f0..74b1893456 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -53,15 +53,15 @@ ReviewDialog::ReviewDialog(MWBase::WindowManager& parWindowManager) // Setup dynamic stats getWidget(mHealth, "Health"); - mHealth->setTitle(mWindowManager.getGameSettingString("sHealth", "")); + mHealth->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sHealth", "")); mHealth->setValue(45, 45); getWidget(mMagicka, "Magicka"); - mMagicka->setTitle(mWindowManager.getGameSettingString("sMagic", "")); + mMagicka->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sMagic", "")); mMagicka->setValue(50, 50); getWidget(mFatigue, "Fatigue"); - mFatigue->setTitle(mWindowManager.getGameSettingString("sFatigue", "")); + mFatigue->setTitle(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFatigue", "")); mFatigue->setValue(160, 160); // Setup attributes @@ -71,7 +71,6 @@ ReviewDialog::ReviewDialog(MWBase::WindowManager& parWindowManager) { getWidget(attribute, std::string("Attribute") + boost::lexical_cast(idx)); mAttributeWidgets.insert(std::make_pair(static_cast(ESM::Attribute::sAttributeIds[idx]), attribute)); - attribute->setWindowManager(&mWindowManager); attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]); attribute->setAttributeValue(MWAttribute::AttributeValue(0, 0)); } @@ -277,7 +276,7 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId addSeparator(coord1, coord2); } - addGroup(mWindowManager.getGameSettingString(titleId, titleDefault), coord1, coord2); + addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString(titleId, titleDefault), coord1, coord2); SkillList::const_iterator end = skills.end(); for (SkillList::const_iterator it = skills.begin(); it != end; ++it) @@ -296,7 +295,7 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId state = "increased"; else if (modified < base) state = "decreased"; - MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); + MyGUI::TextBox* widget = addValueItem(MWBase::Environment::get().getWindowManager()->getGameSettingString(skillNameId, skillNameId), boost::lexical_cast(static_cast(modified)), state, coord1, coord2); for (int i=0; i<2; ++i) { diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 4f41ec42d6..9775a52de4 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_REVIEW_H #define MWGUI_REVIEW_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwmechanics/stat.hpp" #include "widgets.hpp" diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 3bd3a47439..22884bfe6d 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -66,7 +66,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); - mWindowManager.removeGuiMode(GM_Scroll); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -76,5 +76,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mScroll); take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - mWindowManager.removeGuiMode(GM_Scroll); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll); } diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index 42b6395a9a..59b39cab38 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_SCROLLWINDOW_H #define MWGUI_SCROLLWINDOW_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "imagebutton.hpp" #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 58754472dd..e21d4f5894 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -274,7 +274,7 @@ namespace MWGui void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.removeGuiMode(GM_Settings); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Settings); } void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) @@ -282,7 +282,7 @@ namespace MWGui if (index == MyGUI::ITEM_NONE) return; - ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); dialog->open("#{sNotifyMessage67}"); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); @@ -329,8 +329,8 @@ namespace MWGui void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) { - std::string on = mWindowManager.getGameSettingString("sOn", "On"); - std::string off = mWindowManager.getGameSettingString("sOff", "On"); + std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On"); + std::string off = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOff", "On"); bool newState; if (_sender->castType()->getCaption() == on) { @@ -437,8 +437,8 @@ namespace MWGui void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender) { - std::string on = mWindowManager.getGameSettingString("sOn", "On"); - std::string off = mWindowManager.getGameSettingString("sOff", "On"); + std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On"); + std::string off = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOff", "On"); std::string val = static_cast(_sender)->getCaption(); if (val == off) @@ -610,7 +610,7 @@ namespace MWGui void SettingsWindow::onResetDefaultBindings(MyGUI::Widget* _sender) { - ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); + ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); dialog->open("#{sNotifyMessage66}"); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResetDefaultBindingsAccept); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index fc1ec9e365..292c1233de 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_SETTINGS_H #define MWGUI_SETTINGS_H -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index d39ad6a5ae..9aa8074a24 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -48,7 +48,7 @@ namespace MWGui MyGUI::Button* toAdd = mSpellsView->createWidget( - (price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", + (price>MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, mCurrentY, 200, @@ -120,13 +120,13 @@ namespace MWGui { int price = *_sender->getUserData(); - if (mWindowManager.getInventoryWindow()->getPlayerGold()>=price) + if (MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()>=price) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); spells.add (mSpellsWidgetMap.find(_sender)->second); - mWindowManager.getTradeWindow()->addOrRemoveGold(-price); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-price); startSpellBuying(mPtr); MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); @@ -135,12 +135,12 @@ namespace MWGui void SpellBuyingWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.removeGuiMode(GM_SpellBuying); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_SpellBuying); } void SpellBuyingWindow::updateLabels() { - mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); + mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())); mPlayerGold->setCoord(8, mPlayerGold->getTop(), mPlayerGold->getTextSize().width, @@ -150,8 +150,8 @@ namespace MWGui void SpellBuyingWindow::onReferenceUnavailable() { // remove both Spells and Dialogue (since you always trade with the NPC/creature that you have previously talked to) - mWindowManager.removeGuiMode(GM_SpellBuying); - mWindowManager.removeGuiMode(GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_SpellBuying); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); } void SpellBuyingWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index f9cda35df0..1418a9db52 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_SpellBuyingWINDOW_H #define MWGUI_SpellBuyingWINDOW_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "referenceinterface.hpp" namespace MyGUI diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 592063a761..6fef91457f 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -303,38 +303,38 @@ namespace MWGui void SpellCreationDialog::onCancelButtonClicked (MyGUI::Widget* sender) { - mWindowManager.removeGuiMode (MWGui::GM_SpellCreation); + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_SpellCreation); } void SpellCreationDialog::onBuyButtonClicked (MyGUI::Widget* sender) { if (mEffects.size() <= 0) { - mWindowManager.messageBox ("#{sNotifyMessage30}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage30}"); return; } if (mNameEdit->getCaption () == "") { - mWindowManager.messageBox ("#{sNotifyMessage10}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage10}"); return; } if (mMagickaCost->getCaption() == "0") { - mWindowManager.messageBox ("#{sEnchantmentMenu8}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu8}"); return; } - if (boost::lexical_cast(mPriceLabel->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) + if (boost::lexical_cast(mPriceLabel->getCaption()) > MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) { - mWindowManager.messageBox ("#{sNotifyMessage18}"); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage18}"); return; } mSpell.mName = mNameEdit->getCaption(); - mWindowManager.getTradeWindow()->addOrRemoveGold(-boost::lexical_cast(mPriceLabel->getCaption())); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-boost::lexical_cast(mPriceLabel->getCaption())); MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); @@ -347,7 +347,7 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); - mWindowManager.removeGuiMode (GM_SpellCreation); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_SpellCreation); } void SpellCreationDialog::open() @@ -357,8 +357,8 @@ namespace MWGui void SpellCreationDialog::onReferenceUnavailable () { - mWindowManager.removeGuiMode (GM_Dialogue); - mWindowManager.removeGuiMode (GM_SpellCreation); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_SpellCreation); } void SpellCreationDialog::notifyEffectsChanged () @@ -601,7 +601,6 @@ namespace MWGui Widgets::MWSpellEffectPtr effect = button->createWidget("MW_EffectImage", MyGUI::IntCoord(0,0,0,24), MyGUI::Align::Default); effect->setNeedMouseFocus (false); - effect->setWindowManager (MWBase::Environment::get().getWindowManager ()); effect->setSpellEffect (params); effect->setSize(effect->getRequestedWidth (), 24); diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index 8f1c071804..facbdf5304 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_SPELLCREATION_H #define MWGUI_SPELLCREATION_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "referenceinterface.hpp" #include "list.hpp" #include "widgets.hpp" diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 021a849a08..257fab89d4 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -71,7 +71,7 @@ namespace MWGui void SpellWindow::onPinToggled() { - mWindowManager.setSpellVisibility(!mPinned); + MWBase::Environment::get().getWindowManager()->setSpellVisibility(!mPinned); } void SpellWindow::open() @@ -140,7 +140,7 @@ namespace MWGui { store.setSelectedEnchantItem(store.end()); spells.setSelectedSpell(""); - mWindowManager.unsetSelectedSpell(); + MWBase::Environment::get().getWindowManager()->unsetSelectedSpell(); selectedItem = MWWorld::Ptr(); } } @@ -377,12 +377,12 @@ namespace MWGui action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ()); // since we changed equipping status, update the inventory window - mWindowManager.getInventoryWindow()->drawItems(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } store.setSelectedEnchantItem(it); spells.setSelectedSpell(""); - mWindowManager.setSelectedEnchantItem(item); + MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); updateSpells(); } @@ -404,14 +404,14 @@ namespace MWGui if (spell->mData.mFlags & ESM::Spell::F_Always || spell->mData.mType == ESM::Spell::ST_Power) { - mWindowManager.messageBox("#{sDeleteSpellError}"); + MWBase::Environment::get().getWindowManager()->messageBox("#{sDeleteSpellError}"); } else { // ask for confirmation mSpellToDelete = spellId; - ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog(); - std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); + ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); + std::string question = MWBase::Environment::get().getWindowManager()->getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); question = boost::str(boost::format(question) % spell->mName); dialog->open(question); dialog->eventOkClicked.clear(); @@ -423,7 +423,7 @@ namespace MWGui { spells.setSelectedSpell(spellId); store.setSelectedEnchantItem(store.end()); - mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); + MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); } updateSpells(); @@ -454,7 +454,7 @@ namespace MWGui if (spells.getSelectedSpell() == mSpellToDelete) { spells.setSelectedSpell(""); - mWindowManager.unsetSelectedSpell(); + MWBase::Environment::get().getWindowManager()->unsetSelectedSpell(); } spells.remove(mSpellToDelete); diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 1963d43463..b0994c5901 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_SPELLWINDOW_H #define MWGUI_SPELLWINDOW_H -#include "window_pinnable_base.hpp" +#include "windowpinnablebase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp new file mode 100644 index 0000000000..0e0676c2fb --- /dev/null +++ b/apps/openmw/mwgui/statswindow.cpp @@ -0,0 +1,580 @@ +#include "statswindow.hpp" + +#include +#include +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/class.hpp" + +#include "../mwmechanics/npcstats.hpp" + +#include "tooltips.hpp" + + +using namespace MWGui; +const int StatsWindow::sLineHeight = 18; + +StatsWindow::StatsWindow (MWBase::WindowManager& parWindowManager) + : WindowPinnableBase("openmw_stats_window.layout", parWindowManager) + , mSkillView(NULL) + , mClientHeight(0) + , mMajorSkills() + , mMinorSkills() + , mMiscSkills() + , mSkillValues() + , mSkillWidgetMap() + , mFactionWidgetMap() + , mFactions() + , mBirthSignId() + , mReputation(0) + , mBounty(0) + , mSkillWidgets() + , mChanged(true) +{ + setCoord(0,0,498, 342); + + const char *names[][2] = + { + { "Attrib1", "sAttributeStrength" }, + { "Attrib2", "sAttributeIntelligence" }, + { "Attrib3", "sAttributeWillpower" }, + { "Attrib4", "sAttributeAgility" }, + { "Attrib5", "sAttributeSpeed" }, + { "Attrib6", "sAttributeEndurance" }, + { "Attrib7", "sAttributePersonality" }, + { "Attrib8", "sAttributeLuck" }, + { 0, 0 } + }; + + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + for (int i=0; names[i][0]; ++i) + { + setText (names[i][0], store.get().find (names[i][1])->getString()); + } + + getWidget(mSkillView, "SkillView"); + getWidget(mLeftPane, "LeftPane"); + getWidget(mRightPane, "RightPane"); + + for (int i = 0; i < ESM::Skill::Length; ++i) + { + mSkillValues.insert(std::pair >(i, MWMechanics::Stat())); + mSkillWidgetMap.insert(std::pair(i, (MyGUI::TextBox*)NULL)); + } + + MyGUI::WindowPtr t = static_cast(mMainWidget); + t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); +} + +void StatsWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (mSkillView->getViewOffset().top + _rel*0.3 > 0) + mSkillView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3)); +} + +void StatsWindow::onWindowResize(MyGUI::Window* window) +{ + mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) ); + mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) ); + mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); +} + +void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max) +{ + MyGUI::ProgressPtr pt; + getWidget(pt, name); + pt->setProgressRange(max); + pt->setProgressPosition(val); + + std::stringstream out; + out << val << "/" << max; + setText(tname, out.str().c_str()); +} + +void StatsWindow::setPlayerName(const std::string& playerName) +{ + static_cast(mMainWidget)->setCaption(playerName); + adjustWindowCaption(); +} + +void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) +{ + static const char *ids[] = + { + "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", + "AttribVal6", "AttribVal7", "AttribVal8", + 0 + }; + + for (int i=0; ids[i]; ++i) + if (ids[i]==id) + { + std::ostringstream valueString; + valueString << value.getModified(); + setText (id, valueString.str()); + + MyGUI::TextBox* box; + getWidget(box, id); + + if (value.getModified()>value.getBase()) + box->_setWidgetState("increased"); + else if (value.getModified()_setWidgetState("decreased"); + else + box->_setWidgetState("normal"); + + break; + } +} + +void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat& value) +{ + static const char *ids[] = + { + "HBar", "MBar", "FBar", + 0 + }; + + for (int i=0; ids[i]; ++i) + { + if (ids[i]==id) + { + std::string id (ids[i]); + setBar (id, id + "T", static_cast(value.getCurrent()), static_cast(value.getModified())); + + // health, magicka, fatigue tooltip + MyGUI::Widget* w; + std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); + if (i==0) + { + getWidget(w, "Health"); + w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); + } + else if (i==1) + { + getWidget(w, "Magicka"); + w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); + } + else if (i==2) + { + getWidget(w, "Fatigue"); + w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); + } + } + } +} + +void StatsWindow::setValue (const std::string& id, const std::string& value) +{ + if (id=="name") + setPlayerName (value); + else if (id=="race") + setText ("RaceText", value); + else if (id=="class") + setText ("ClassText", value); +} + +void StatsWindow::setValue (const std::string& id, int value) +{ + if (id=="level") + { + std::ostringstream text; + text << value; + setText("LevelText", text.str()); + } +} + +void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value) +{ + mSkillValues[parSkill] = value; + MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill]; + if (widget) + { + float modified = value.getModified(), base = value.getBase(); + std::string text = boost::lexical_cast(std::floor(modified)); + std::string state = "normal"; + if (modified > base) + state = "increased"; + else if (modified < base) + state = "decreased"; + + widget->setCaption(text); + widget->_setWidgetState(state); + } +} + +void StatsWindow::configureSkills (const std::vector& major, const std::vector& minor) +{ + mMajorSkills = major; + mMinorSkills = minor; + + // Update misc skills with the remaining skills not in major or minor + std::set skillSet; + std::copy(major.begin(), major.end(), std::inserter(skillSet, skillSet.begin())); + std::copy(minor.begin(), minor.end(), std::inserter(skillSet, skillSet.begin())); + boost::array::const_iterator end = ESM::Skill::sSkillIds.end(); + mMiscSkills.clear(); + for (boost::array::const_iterator it = ESM::Skill::sSkillIds.begin(); it != end; ++it) + { + int skill = *it; + if (skillSet.find(skill) == skillSet.end()) + mMiscSkills.push_back(skill); + } + + updateSkillArea(); +} + +void StatsWindow::onFrame () +{ + if (!mMainWidget->getVisible()) + return; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); + + // level progress + MyGUI::Widget* levelWidget; + for (int i=0; i<2; ++i) + { + getWidget(levelWidget, i==0 ? "Level_str" : "LevelText"); + levelWidget->setUserString("RangePosition_LevelProgress", boost::lexical_cast(PCstats.getLevelProgress())); + levelWidget->setUserString("Caption_LevelProgressText", boost::lexical_cast(PCstats.getLevelProgress()) + "/10"); + } + + setFactions(PCstats.getFactionRanks()); + setExpelled(PCstats.getExpelled ()); + + const std::string &signId = + MWBase::Environment::get().getWorld()->getPlayer().getBirthSign(); + + setBirthSign(signId); + setReputation (PCstats.getReputation ()); + setBounty (PCstats.getBounty ()); + + if (mChanged) + updateSkillArea(); +} + +void StatsWindow::setFactions (const FactionList& factions) +{ + if (mFactions != factions) + { + mFactions = factions; + mChanged = true; + } +} + +void StatsWindow::setExpelled (const std::set& expelled) +{ + if (mExpelled != expelled) + { + mExpelled = expelled; + mChanged = true; + } +} + +void StatsWindow::setBirthSign (const std::string& signId) +{ + if (signId != mBirthSignId) + { + mBirthSignId = signId; + mChanged = true; + } +} + +void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::ImageBox* separator = mSkillView->createWidget("MW_HLine", + MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), + MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + separator->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); + mSkillWidgets.push_back(separator); + + coord1.top += separator->getHeight(); + coord2.top += separator->getHeight(); +} + +void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::TextBox* groupWidget = mSkillView->createWidget("SandBrightText", + MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), + MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + groupWidget->setCaption(label); + groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); + mSkillWidgets.push_back(groupWidget); + + coord1.top += sLineHeight; + coord2.top += sLineHeight; +} + +MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::TextBox *skillNameWidget, *skillValueWidget; + + skillNameWidget = mSkillView->createWidget("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); + skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); + + skillValueWidget = mSkillView->createWidget("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top); + skillValueWidget->setCaption(value); + skillValueWidget->_setWidgetState(state); + skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); + + mSkillWidgets.push_back(skillNameWidget); + mSkillWidgets.push_back(skillValueWidget); + + coord1.top += sLineHeight; + coord2.top += sLineHeight; + + return skillValueWidget; +} + +MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + MyGUI::TextBox* skillNameWidget; + + skillNameWidget = mSkillView->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); + skillNameWidget->setCaption(text); + skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); + + mSkillWidgets.push_back(skillNameWidget); + + coord1.top += sLineHeight; + coord2.top += sLineHeight; + + return skillNameWidget; +} + +void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) +{ + // Add a line separator if there are items above + if (!mSkillWidgets.empty()) + { + addSeparator(coord1, coord2); + } + + addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString(titleId, titleDefault), coord1, coord2); + + SkillList::const_iterator end = skills.end(); + for (SkillList::const_iterator it = skills.begin(); it != end; ++it) + { + int skillId = *it; + if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes + continue; + assert(skillId >= 0 && skillId < ESM::Skill::Length); + const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId]; + const MWMechanics::Stat &stat = mSkillValues.find(skillId)->second; + float base = stat.getBase(); + float modified = stat.getModified(); + int progressPercent = (modified - float(static_cast(modified))) * 100; + + const MWWorld::ESMStore &esmStore = + MWBase::Environment::get().getWorld()->getStore(); + + const ESM::Skill* skill = esmStore.get().find(skillId); + assert(skill); + + std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; + + const ESM::Attribute* attr = + esmStore.get().find(skill->mData.mAttribute); + assert(attr); + + std::string state = "normal"; + if (modified > base) + state = "increased"; + else if (modified < base) + state = "decreased"; + MyGUI::TextBox* widget = addValueItem(MWBase::Environment::get().getWindowManager()->getGameSettingString(skillNameId, skillNameId), + boost::lexical_cast(static_cast(modified)), state, coord1, coord2); + + for (int i=0; i<2; ++i) + { + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipLayout", "SkillToolTip"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillName", "#{"+skillNameId+"}"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillDescription", skill->mDescription); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillAttribute", "#{sGoverningAttribute}: #{" + attr->mName + "}"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ImageTexture_SkillImage", icon); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", boost::lexical_cast(progressPercent)+"/100"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Range_SkillProgress", "100"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("RangePosition_SkillProgress", boost::lexical_cast(progressPercent)); + } + + mSkillWidgetMap[skillId] = widget; + } +} + +void StatsWindow::updateSkillArea() +{ + mChanged = false; + + for (std::vector::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) + { + MyGUI::Gui::getInstance().destroyWidget(*it); + } + mSkillWidgets.clear(); + + mSkillView->setViewOffset (MyGUI::IntPoint(0,0)); + mClientHeight = 0; + + const int valueSize = 40; + MyGUI::IntCoord coord1(10, 0, mSkillView->getWidth() - (10 + valueSize) - 24, 18); + MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height); + + if (!mMajorSkills.empty()) + addSkills(mMajorSkills, "sSkillClassMajor", "Major Skills", coord1, coord2); + + if (!mMinorSkills.empty()) + addSkills(mMinorSkills, "sSkillClassMinor", "Minor Skills", coord1, coord2); + + if (!mMiscSkills.empty()) + addSkills(mMiscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); + + MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::ESMStore &store = world->getStore(); + const ESM::NPC *player = + world->getPlayer().getPlayer().get()->mBase; + + // race tooltip + const ESM::Race* playerRace = store.get().find(player->mRace); + + MyGUI::Widget* raceWidget; + getWidget(raceWidget, "RaceText"); + ToolTips::createRaceToolTip(raceWidget, playerRace); + getWidget(raceWidget, "Race_str"); + ToolTips::createRaceToolTip(raceWidget, playerRace); + + // class tooltip + MyGUI::Widget* classWidget; + + const ESM::Class *playerClass = + store.get().find(player->mClass); + + getWidget(classWidget, "ClassText"); + ToolTips::createClassToolTip(classWidget, *playerClass); + getWidget(classWidget, "Class_str"); + ToolTips::createClassToolTip(classWidget, *playerClass); + + if (!mFactions.empty()) + { + // Add a line separator if there are items above + if (!mSkillWidgets.empty()) + addSeparator(coord1, coord2); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); + std::set& expelled = PCstats.getExpelled (); + + addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFaction", "Faction"), coord1, coord2); + FactionList::const_iterator end = mFactions.end(); + for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) + { + const ESM::Faction *faction = + store.get().find(it->first); + MyGUI::Widget* w = addItem(faction->mName, coord1, coord2); + + std::string text; + + text += std::string("#DDC79E") + faction->mName; + + if (expelled.find(it->first) != expelled.end()) + text += "\n#{sExpelled}"; + else + { + text += std::string("\n#BF9959") + faction->mRanks[it->second]; + + if (it->second < 9) + { + // player doesn't have max rank yet + text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; + + ESM::RankData rankData = faction->mData.mRankData[it->second+1]; + const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute[0]); + const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute[1]); + assert(attr1 && attr2); + + text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) + + ", #{" + attr2->mName + "}: " + boost::lexical_cast(rankData.mAttribute2); + + text += "\n\n#DDC79E#{sFavoriteSkills}"; + text += "\n#BF9959"; + for (int i=0; i<6; ++i) + { + text += "#{"+ESM::Skill::sSkillNameIds[faction->mData.mSkills[i]]+"}"; + if (i<5) + text += ", "; + } + + text += "\n"; + + if (rankData.mSkill1 > 0) + text += "\n#{sNeedOneSkill} " + boost::lexical_cast(rankData.mSkill1); + if (rankData.mSkill2 > 0) + text += "\n#{sNeedTwoSkills} " + boost::lexical_cast(rankData.mSkill2); + } + } + + w->setUserString("ToolTipType", "Layout"); + w->setUserString("ToolTipLayout", "TextToolTip"); + w->setUserString("Caption_Text", text); + } + } + + if (!mBirthSignId.empty()) + { + // Add a line separator if there are items above + if (!mSkillWidgets.empty()) + addSeparator(coord1, coord2); + + addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBirthSign", "Sign"), coord1, coord2); + const ESM::BirthSign *sign = + store.get().find(mBirthSignId); + MyGUI::Widget* w = addItem(sign->mName, coord1, coord2); + + ToolTips::createBirthsignToolTip(w, mBirthSignId); + } + + // Add a line separator if there are items above + if (!mSkillWidgets.empty()) + addSeparator(coord1, coord2); + + addValueItem(MWBase::Environment::get().getWindowManager()->getGameSettingString("sReputation", "Reputation"), + boost::lexical_cast(static_cast(mReputation)), "normal", coord1, coord2); + + for (int i=0; i<2; ++i) + { + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sSkillsMenuReputationHelp}"); + } + + addValueItem(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBounty", "Bounty"), + boost::lexical_cast(static_cast(mBounty)), "normal", coord1, coord2); + + for (int i=0; i<2; ++i) + { + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip"); + mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sCrimeHelp}"); + } + + mClientHeight = coord1.top; + + mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); +} + +void StatsWindow::onPinToggled() +{ + MWBase::Environment::get().getWindowManager()->setHMSVisibility(!mPinned); +} diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp new file mode 100644 index 0000000000..93e26e063d --- /dev/null +++ b/apps/openmw/mwgui/statswindow.hpp @@ -0,0 +1,83 @@ +#ifndef MWGUI_STATS_WINDOW_H +#define MWGUI_STATS_WINDOW_H + +#include "../mwworld/esmstore.hpp" + +#include +#include +#include +#include + +#include "../mwmechanics/stat.hpp" +#include "windowpinnablebase.hpp" + +namespace MWGui +{ + class WindowManager; + + class StatsWindow : public WindowPinnableBase + { + public: + typedef std::map FactionList; + + typedef std::vector SkillList; + + StatsWindow(MWBase::WindowManager& parWindowManager); + + /// automatically updates all the data in the stats window, but only if it has changed. + void onFrame(); + + void setBar(const std::string& name, const std::string& tname, int val, int max); + void setPlayerName(const std::string& playerName); + + /// Set value for the given ID. + void setValue (const std::string& id, const MWMechanics::Stat& value); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setValue (const std::string& id, const std::string& value); + void setValue (const std::string& id, int value); + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); + + void configureSkills (const SkillList& major, const SkillList& minor); + void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; } + void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } + void updateSkillArea(); + + private: + void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); + + void setFactions (const FactionList& factions); + void setExpelled (const std::set& expelled); + void setBirthSign (const std::string &signId); + + void onWindowResize(MyGUI::Window* window); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + + static const int sLineHeight; + + MyGUI::Widget* mLeftPane; + MyGUI::Widget* mRightPane; + + MyGUI::ScrollView* mSkillView; + int mLastPos, mClientHeight; + + SkillList mMajorSkills, mMinorSkills, mMiscSkills; + std::map > mSkillValues; + std::map mSkillWidgetMap; + std::map mFactionWidgetMap; + FactionList mFactions; ///< Stores a list of factions and the current rank + std::string mBirthSignId; + int mReputation, mBounty; + std::vector mSkillWidgets; //< Skills and other information + std::set mExpelled; + + bool mChanged; + + protected: + virtual void onPinToggled(); + }; +} +#endif diff --git a/apps/openmw/mwgui/textinput.cpp b/apps/openmw/mwgui/textinput.cpp new file mode 100644 index 0000000000..071971befb --- /dev/null +++ b/apps/openmw/mwgui/textinput.cpp @@ -0,0 +1,70 @@ +#include "textinput.hpp" + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/environment.hpp" + +using namespace MWGui; + +TextInputDialog::TextInputDialog(MWBase::WindowManager& parWindowManager) + : WindowModal("openmw_text_input.layout", parWindowManager) +{ + // Centre dialog + center(); + + getWidget(mTextEdit, "TextEdit"); + mTextEdit->eventEditSelectAccept += newDelegate(this, &TextInputDialog::onTextAccepted); + + MyGUI::Button* okButton; + getWidget(okButton, "OKButton"); + okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); + + // Make sure the edit box has focus + MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); +} + +void TextInputDialog::setNextButtonShow(bool shown) +{ + MyGUI::Button* okButton; + getWidget(okButton, "OKButton"); + + if (shown) + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); + else + okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); +} + +void TextInputDialog::setTextLabel(const std::string &label) +{ + setText("LabelT", label); +} + +void TextInputDialog::open() +{ + WindowModal::open(); + // Make sure the edit box has focus + MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); +} + +// widget controls + +void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) +{ + if (mTextEdit->getCaption() == "") + { + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); + MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); + } + else + eventDone(this); +} + +void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) +{ + if (mTextEdit->getCaption() == "") + { + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); + MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); + } + else + eventDone(this); +} diff --git a/apps/openmw/mwgui/textinput.hpp b/apps/openmw/mwgui/textinput.hpp new file mode 100644 index 0000000000..6b371bae74 --- /dev/null +++ b/apps/openmw/mwgui/textinput.hpp @@ -0,0 +1,33 @@ +#ifndef MWGUI_TEXT_INPUT_H +#define MWGUI_TEXT_INPUT_H + +#include "windowbase.hpp" + +namespace MWGui +{ + class WindowManager; +} + +namespace MWGui +{ + class TextInputDialog : public WindowModal + { + public: + TextInputDialog(MWBase::WindowManager& parWindowManager); + + std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; } + void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); } + + void setNextButtonShow(bool shown); + void setTextLabel(const std::string &label); + virtual void open(); + + protected: + void onOkClicked(MyGUI::Widget* _sender); + void onTextAccepted(MyGUI::Edit* _sender); + + private: + MyGUI::EditBox* mTextEdit; + }; +} +#endif diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 9292e60e5c..7730019e83 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -12,7 +12,7 @@ #include "../mwworld/class.hpp" -#include "map_window.hpp" +#include "mapwindow.hpp" #include "widgets.hpp" #include "inventorywindow.hpp" @@ -22,7 +22,6 @@ using namespace MyGUI; ToolTips::ToolTips(MWBase::WindowManager* windowManager) : Layout("openmw_tooltips.layout") , mGameMode(true) - , mWindowManager(windowManager) , mFullHelp(false) , mEnabled(true) , mFocusToolTipX(0.0) @@ -81,9 +80,9 @@ void ToolTips::onFrame(float frameDuration) { const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); - if (mWindowManager->getWorldMouseOver() && ((mWindowManager->getMode() == GM_Console) - || (mWindowManager->getMode() == GM_Container) - || (mWindowManager->getMode() == GM_Inventory))) + if (MWBase::Environment::get().getWindowManager()->getWorldMouseOver() && ((MWBase::Environment::get().getWindowManager()->getMode() == GM_Console) + || (MWBase::Environment::get().getWindowManager()->getMode() == GM_Container) + || (MWBase::Environment::get().getWindowManager()->getMode() == GM_Inventory))) { mFocusObject = MWBase::Environment::get().getWorld()->getFacedObject(); @@ -93,7 +92,7 @@ void ToolTips::onFrame(float frameDuration) const MWWorld::Class& objectclass = MWWorld::Class::get (mFocusObject); IntSize tooltipSize; - if ((!objectclass.hasToolTip(mFocusObject))&&(mWindowManager->getMode() == GM_Console)) + if ((!objectclass.hasToolTip(mFocusObject))&&(MWBase::Environment::get().getWindowManager()->getMode() == GM_Console)) { setCoord(0, 0, 300, 300); mDynamicToolTipBox->setVisible(true); @@ -139,7 +138,7 @@ void ToolTips::onFrame(float frameDuration) mLastMouseX = mousePos.left; mLastMouseY = mousePos.top; - + if (mRemainingDelay > 0) return; @@ -167,8 +166,8 @@ void ToolTips::onFrame(float frameDuration) { return; } - - + + // special handling for markers on the local map: the tooltip should only be visible // if the marker is not hidden due to the fog of war. if (focus->getUserString ("IsMarker") == "true") @@ -190,11 +189,11 @@ void ToolTips::onFrame(float frameDuration) } else if (type == "AvatarItemSelection") { - MyGUI::IntCoord avatarPos = mWindowManager->getInventoryWindow ()->getAvatarScreenCoord (); + MyGUI::IntCoord avatarPos = MWBase::Environment::get().getWindowManager()->getInventoryWindow ()->getAvatarScreenCoord (); MyGUI::IntPoint relMousePos = MyGUI::InputManager::getInstance ().getMousePosition () - MyGUI::IntPoint(avatarPos.left, avatarPos.top); int realX = int(float(relMousePos.left) / float(avatarPos.width) * 512.f ); int realY = int(float(relMousePos.top) / float(avatarPos.height) * 1024.f ); - MWWorld::Ptr item = mWindowManager->getInventoryWindow ()->getAvatarSelectedItem (realX, realY); + MWWorld::Ptr item = MWBase::Environment::get().getWindowManager()->getInventoryWindow ()->getAvatarSelectedItem (realX, realY); mFocusObject = item; if (!mFocusObject.isEmpty ()) @@ -346,7 +345,7 @@ void ToolTips::findImageExtension(std::string& image) } IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) -{ +{ mDynamicToolTipBox->setVisible(true); std::string caption = info.caption; @@ -380,7 +379,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) setCoord(0, 0, 300, 300); const IntPoint padding(8, 8); - + const int maximumWidth = 500; const int imageCaptionHPadding = (caption != "" ? 8 : 0); @@ -424,7 +423,6 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) Widgets::MWEffectListPtr effectsWidget = effectArea->createWidget ("MW_StatName", coord, Align::Default, "ToolTipEffectsWidget"); - effectsWidget->setWindowManager(mWindowManager); effectsWidget->setEffectList(info.effects); std::vector effectItems; @@ -444,7 +442,6 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget"); - enchantWidget->setWindowManager(mWindowManager); enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->mEffects)); std::vector enchantEffectItems; @@ -493,7 +490,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) (captionHeight-captionSize.height)/2, captionSize.width-imageSize, captionSize.height); - + //if its too long we do hscroll with the caption if (captionSize.width > maximumWidth) { diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index da5a35221c..e4fcb310c8 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -82,8 +82,6 @@ namespace MWGui private: MyGUI::Widget* mDynamicToolTipBox; - MWBase::WindowManager* mWindowManager; - MWWorld::Ptr mFocusObject; void findImageExtension(std::string& image); @@ -96,9 +94,9 @@ namespace MWGui float mFocusToolTipX; float mFocusToolTipY; - + int mHorizontalScrollIndex; - + float mDelay; float mRemainingDelay; // remaining time until tooltip will show diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 81a29e69bd..718e6378bb 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -85,7 +85,7 @@ namespace MWGui mCurrentBalance = 0; mCurrentMerchantOffer = 0; - mWindowManager.getInventoryWindow()->startTrade(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->startTrade(); mBoughtItems.clear(); @@ -127,7 +127,7 @@ namespace MWGui { bool goldFound = false; MWWorld::Ptr gold; - MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore(); + MWWorld::ContainerStore& playerStore = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getContainerStore(); for (MWWorld::ContainerStoreIterator it = playerStore.begin(); it != playerStore.end(); ++it) @@ -172,7 +172,7 @@ namespace MWGui MWBase::Environment::get().getWorld()->getStore().get(); // were there any items traded at all? - MWWorld::ContainerStore& playerBought = mWindowManager.getInventoryWindow()->getBoughtItems(); + MWWorld::ContainerStore& playerBought = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getBoughtItems(); MWWorld::ContainerStore& merchantBought = getBoughtItems(); if (playerBought.begin() == playerBought.end() && merchantBought.begin() == merchantBought.end()) { @@ -183,7 +183,7 @@ namespace MWGui } // check if the player can afford this - if (mCurrentBalance < 0 && mWindowManager.getInventoryWindow()->getPlayerGold() < std::abs(mCurrentBalance)) + if (mCurrentBalance < 0 && MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold() < std::abs(mCurrentBalance)) { // user notification MWBase::Environment::get().getWindowManager()-> @@ -258,7 +258,7 @@ namespace MWGui // success! make the item transfer. transferBoughtItems(); - mWindowManager.getInventoryWindow()->transferBoughtItems(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->transferBoughtItems(); // add or remove gold from the player. if (mCurrentBalance != 0) @@ -267,17 +267,17 @@ namespace MWGui std::string sound = "Item Gold Up"; MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mWindowManager.removeGuiMode(GM_Barter); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); } void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { // i give you back your stuff! - returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore()); + returnBoughtItems(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getContainerStore()); // now gimme back my stuff! - mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); - mWindowManager.removeGuiMode(GM_Barter); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); } void TradeWindow::onMaxSaleButtonClicked(MyGUI::Widget* _sender) @@ -321,7 +321,7 @@ namespace MWGui void TradeWindow::updateLabels() { - mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); + mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())); if (mCurrentBalance > 0) { @@ -422,8 +422,8 @@ namespace MWGui void TradeWindow::onReferenceUnavailable() { // remove both Trade and Dialogue (since you always trade with the NPC/creature that you have previously talked to) - mWindowManager.removeGuiMode(GM_Barter); - mWindowManager.removeGuiMode(GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); } int TradeWindow::getMerchantGold() diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 2e05d03d51..111c0935fe 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -2,7 +2,7 @@ #define MWGUI_TRADEWINDOW_H #include "container.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 601b44d6c9..c2b543a4fd 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -40,7 +40,7 @@ namespace MWGui { mPtr = actor; - mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); + mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())); MWMechanics::NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats (actor); @@ -82,7 +82,7 @@ namespace MWGui int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer (mPtr,pcStats.getSkill (bestSkills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true); - std::string skin = (price > mWindowManager.getInventoryWindow ()->getPlayerGold ()) ? "SandTextGreyedOut" : "SandTextButton"; + std::string skin = (price > MWBase::Environment::get().getWindowManager()->getInventoryWindow ()->getPlayerGold ()) ? "SandTextGreyedOut" : "SandTextButton"; MyGUI::Button* button = mTrainingOptions->createWidget(skin, MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default); @@ -102,12 +102,12 @@ namespace MWGui void TrainingWindow::onReferenceUnavailable () { - mWindowManager.removeGuiMode(GM_Training); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Training); } void TrainingWindow::onCancelButtonClicked (MyGUI::Widget *sender) { - mWindowManager.removeGuiMode (GM_Training); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training); } void TrainingWindow::onTrainingSelected (MyGUI::Widget *sender) @@ -123,13 +123,13 @@ namespace MWGui int price = pcStats.getSkill (skillId).getBase() * store.get().find("iTrainingMod")->getInt (); price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); - if (mWindowManager.getInventoryWindow()->getPlayerGold()getInventoryWindow()->getPlayerGold()messageBox ("#{sServiceTrainingWords}"); return; } @@ -141,11 +141,11 @@ namespace MWGui pcStats.increaseSkill (skillId, *class_, true); // remove gold - mWindowManager.getTradeWindow()->addOrRemoveGold(-price); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->addOrRemoveGold(-price); // go back to game mode - mWindowManager.removeGuiMode (GM_Training); - mWindowManager.removeGuiMode (GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue); // advance time MWBase::Environment::get().getWorld ()->advanceTime (2); diff --git a/apps/openmw/mwgui/trainingwindow.hpp b/apps/openmw/mwgui/trainingwindow.hpp index f2ef1714ee..d6be60ae67 100644 --- a/apps/openmw/mwgui/trainingwindow.hpp +++ b/apps/openmw/mwgui/trainingwindow.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_TRAININGWINDOW_H #define MWGUI_TRAININGWINDOW_H -#include "window_base.hpp" +#include "windowbase.hpp" #include "referenceinterface.hpp" namespace MWGui diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 465f588b8a..b710171669 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -71,7 +71,7 @@ namespace MWGui price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); - MyGUI::Button* toAdd = mDestinationsView->createWidget((price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default); + MyGUI::Button* toAdd = mDestinationsView->createWidget((price>MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default); mCurrentY += sLineHeight; if(interior) toAdd->setUserString("interior","y"); @@ -129,10 +129,10 @@ namespace MWGui int price; iss >> price; - if (mWindowManager.getInventoryWindow()->getPlayerGold()getInventoryWindow()->getPlayerGold()addOrRemoveGold (-price); + MWBase::Environment::get().getWindowManager()->getTradeWindow ()->addOrRemoveGold (-price); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); @@ -156,20 +156,20 @@ namespace MWGui MWBase::Environment::get().getWorld()->advanceTime(time); } MWBase::Environment::get().getWorld()->moveObject(player,*cell,pos.pos[0],pos.pos[1],pos.pos[2]); - mWindowManager.removeGuiMode(GM_Travel); - mWindowManager.removeGuiMode(GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0); MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(1); } void TravelWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.removeGuiMode(GM_Travel); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); } void TravelWindow::updateLabels() { - mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); + mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())); mPlayerGold->setCoord(8, mPlayerGold->getTop(), mPlayerGold->getTextSize().width, @@ -178,8 +178,8 @@ namespace MWGui void TravelWindow::onReferenceUnavailable() { - mWindowManager.removeGuiMode(GM_Travel); - mWindowManager.removeGuiMode(GM_Dialogue); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); } void TravelWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) diff --git a/apps/openmw/mwgui/travelwindow.hpp b/apps/openmw/mwgui/travelwindow.hpp index cc3d6a31f7..61b724910c 100644 --- a/apps/openmw/mwgui/travelwindow.hpp +++ b/apps/openmw/mwgui/travelwindow.hpp @@ -2,7 +2,7 @@ #define MWGUI_TravelWINDOW_H #include "container.hpp" -#include "window_base.hpp" +#include "windowbase.hpp" #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 09eb5c914e..69dfa10b4d 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -75,7 +75,7 @@ namespace MWGui { if (!MWBase::Environment::get().getWindowManager ()->getRestEnabled ()) { - mWindowManager.popGuiMode (); + MWBase::Environment::get().getWindowManager()->popGuiMode (); } int canRest = MWBase::Environment::get().getWorld ()->canRest (); @@ -83,8 +83,8 @@ namespace MWGui if (canRest == 2) { // resting underwater or mid-air not allowed - mWindowManager.messageBox ("#{sNotifyMessage1}"); - mWindowManager.popGuiMode (); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}"); + MWBase::Environment::get().getWindowManager()->popGuiMode (); } setCanRest(canRest == 0); @@ -212,7 +212,7 @@ namespace MWGui void WaitDialog::onCancelButtonClicked(MyGUI::Widget* sender) { - mWindowManager.popGuiMode (); + MWBase::Environment::get().getWindowManager()->popGuiMode (); } void WaitDialog::onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position) @@ -263,8 +263,8 @@ namespace MWGui { MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.2); mProgressBar.setVisible (false); - mWindowManager.removeGuiMode (GM_Rest); - mWindowManager.removeGuiMode (GM_RestBed); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Rest); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_RestBed); mWaiting = false; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); @@ -273,7 +273,7 @@ namespace MWGui // trigger levelup if possible if (mSleeping && pcstats.getLevelProgress () >= 10) { - mWindowManager.pushGuiMode (GM_Levelup); + MWBase::Environment::get().getWindowManager()->pushGuiMode (GM_Levelup); } } diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index c102d0fc67..4510e665b3 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -1,7 +1,7 @@ #ifndef MWGUI_WAIT_DIALOG_H #define MWGUI_WAIT_DIALOG_H -#include "window_base.hpp" +#include "windowbase.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index e822e047ea..3801ae6f7a 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -218,8 +218,7 @@ void MWAttribute::initialiseOverride() /* MWSpell */ MWSpell::MWSpell() - : mWindowManager(NULL) - , mSpellNameWidget(NULL) + : mSpellNameWidget(NULL) { } @@ -242,7 +241,6 @@ void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::W for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != end; ++it) { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); - effect->setWindowManager(mWindowManager); SpellEffectParams params; params.mEffectID = it->mEffectID; params.mSkill = it->mSkill; @@ -262,7 +260,7 @@ void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::W void MWSpell::updateWidgets() { - if (mSpellNameWidget && mWindowManager) + if (mSpellNameWidget && MWBase::Environment::get().getWindowManager()) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -289,8 +287,7 @@ MWSpell::~MWSpell() /* MWEffectList */ MWEffectList::MWEffectList() - : mWindowManager(NULL) - , mEffectList(0) + : mEffectList(0) { } @@ -311,7 +308,6 @@ void MWEffectList::createEffectWidgets(std::vector &effects, MyG it != mEffectList.end(); ++it) { effect = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); - effect->setWindowManager(mWindowManager); it->mIsConstant = (flags & EF_Constant) || it->mIsConstant; it->mNoTarget = (flags & EF_NoTarget) || it->mNoTarget; effect->setSpellEffect(*it); @@ -378,8 +374,7 @@ SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects) /* MWSpellEffect */ MWSpellEffect::MWSpellEffect() - : mWindowManager(NULL) - , mImageWidget(NULL) + : mImageWidget(NULL) , mTextWidget(NULL) , mRequestedWidth(0) { @@ -409,22 +404,22 @@ void MWSpellEffect::updateWidgets() assert(magicEffect); - std::string pt = mWindowManager->getGameSettingString("spoint", ""); - std::string pts = mWindowManager->getGameSettingString("spoints", ""); - std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " "; - std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); - std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); + std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); + std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); + std::string to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " "; + std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", ""); + std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", ""); std::string effectIDStr = ESM::MagicEffect::effectIdToString(mEffectParams.mEffectID); - std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); + std::string spellLine = MWBase::Environment::get().getWindowManager()->getGameSettingString(effectIDStr, ""); if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill) { - spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], ""); + spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], ""); } if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute) { - spellLine += " " + mWindowManager->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], ""); + spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], ""); } if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) @@ -442,7 +437,7 @@ void MWSpellEffect::updateWidgets() { if (mEffectParams.mDuration >= 0 && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) { - spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs); + spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfor", "") + " " + boost::lexical_cast(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs); } if (mEffectParams.mArea > 0) @@ -453,13 +448,13 @@ void MWSpellEffect::updateWidgets() // potions have no target if (!mEffectParams.mNoTarget) { - std::string on = mWindowManager->getGameSettingString("sonword", ""); + std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sonword", ""); if (mEffectParams.mRange == ESM::RT_Self) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); + spellLine += " " + on + " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeSelf", ""); else if (mEffectParams.mRange == ESM::RT_Touch) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); + spellLine += " " + on + " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeTouch", ""); else if (mEffectParams.mRange == ESM::RT_Target) - spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); + spellLine += " " + on + " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sRangeTarget", ""); } } diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 784537c42a..26ca750667 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -94,7 +94,6 @@ namespace MWGui typedef MWMechanics::Stat SkillValue; - void setWindowManager(MWBase::WindowManager *m) { mManager = m; } /// \todo remove void setSkillId(ESM::Skill::SkillEnum skillId); void setSkillNumber(int skillId); void setSkillValue(const SkillValue& value); @@ -138,7 +137,6 @@ namespace MWGui typedef MWMechanics::Stat AttributeValue; - void setWindowManager(MWBase::WindowManager *m) { mManager = m; } void setAttributeId(int attributeId); void setAttributeValue(const AttributeValue& value); @@ -185,7 +183,6 @@ namespace MWGui typedef MWMechanics::Stat SpellValue; - void setWindowManager(MWBase::WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setSpellId(const std::string &id); /** @@ -207,7 +204,6 @@ namespace MWGui private: void updateWidgets(); - MWBase::WindowManager* mWindowManager; std::string mId; MyGUI::TextBox* mSpellNameWidget; }; @@ -227,7 +223,6 @@ namespace MWGui EF_Constant = 0x02 // constant effect means that duration will not be displayed }; - void setWindowManager(MWBase::WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setEffectList(const SpellEffectList& list); static SpellEffectList effectListFromESM(const ESM::EffectList* effects); @@ -249,7 +244,6 @@ namespace MWGui private: void updateWidgets(); - MWBase::WindowManager* mWindowManager; SpellEffectList mEffectList; }; typedef MWEffectList* MWEffectListPtr; @@ -262,7 +256,6 @@ namespace MWGui typedef ESM::ENAMstruct SpellEffectValue; - void setWindowManager(MWBase::WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setSpellEffect(const SpellEffectParams& params); int getRequestedWidth() const { return mRequestedWidth; } @@ -276,7 +269,6 @@ namespace MWGui void updateWidgets(); - MWBase::WindowManager* mWindowManager; SpellEffectParams mEffectParams; MyGUI::ImageBox* mImageWidget; MyGUI::TextBox* mTextWidget; diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp new file mode 100644 index 0000000000..cb3d4ea8c8 --- /dev/null +++ b/apps/openmw/mwgui/windowbase.cpp @@ -0,0 +1,54 @@ +#include "windowbase.hpp" + +#include + +#include "../mwbase/windowmanager.hpp" + +using namespace MWGui; + +WindowBase::WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) + : Layout(parLayout) +{ +} + +void WindowBase::setVisible(bool visible) +{ + bool wasVisible = mMainWidget->getVisible(); + mMainWidget->setVisible(visible); + + if (visible) + open(); + else if (wasVisible && !visible) + close(); +} + +void WindowBase::center() +{ + // Centre dialog + + // MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); + // Note by scrawl: The following works more reliably in the case when the window was _just_ + // resized and MyGUI RenderManager doesn't know about the new size yet + MyGUI::IntSize gameWindowSize = MyGUI::IntSize(Settings::Manager::getInt("resolution x", "Video"), + Settings::Manager::getInt("resolution y", "Video")); + + MyGUI::IntCoord coord = mMainWidget->getCoord(); + coord.left = (gameWindowSize.width - coord.width)/2; + coord.top = (gameWindowSize.height - coord.height)/2; + mMainWidget->setCoord(coord); +} + +WindowModal::WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager) + : WindowBase(parLayout, parWindowManager) +{ +} + +void WindowModal::open() +{ + MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget); +} + +void WindowModal::close() +{ + MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget); +} diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp new file mode 100644 index 0000000000..a2cb731fee --- /dev/null +++ b/apps/openmw/mwgui/windowbase.hpp @@ -0,0 +1,47 @@ +#ifndef MWGUI_WINDOW_BASE_H +#define MWGUI_WINDOW_BASE_H + +#include + +namespace MWBase +{ + class WindowManager; +} + +namespace MWGui +{ + class WindowManager; + + class WindowBase: public OEngine::GUI::Layout + { + public: + WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + + // Events + typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; + + virtual void open() {} + virtual void close () {} + virtual void setVisible(bool visible); + void center(); + + /** Event : Dialog finished, OK button clicked.\n + signature : void method()\n + */ + EventHandle_WindowBase eventDone; + }; + + + /* + * "Modal" windows cause the rest of the interface to be unaccessible while they are visible + */ + class WindowModal : public WindowBase + { + public: + WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + virtual void open(); + virtual void close(); + }; +} + +#endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index f994683a66..bcde82e966 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -21,12 +21,12 @@ #include "console.hpp" #include "journalwindow.hpp" #include "charactercreation.hpp" -#include "text_input.hpp" +#include "textinput.hpp" #include "review.hpp" #include "dialogue.hpp" -#include "dialogue_history.hpp" -#include "map_window.hpp" -#include "stats_window.hpp" +#include "dialoguehistory.hpp" +#include "mapwindow.hpp" +#include "statswindow.hpp" #include "messagebox.hpp" #include "container.hpp" #include "inventorywindow.hpp" diff --git a/apps/openmw/mwgui/windowpinnablebase.cpp b/apps/openmw/mwgui/windowpinnablebase.cpp new file mode 100644 index 0000000000..54ed082cf9 --- /dev/null +++ b/apps/openmw/mwgui/windowpinnablebase.cpp @@ -0,0 +1,28 @@ +#include "windowpinnablebase.hpp" + +#include "../mwbase/windowmanager.hpp" + +#include "exposedwindow.hpp" + +using namespace MWGui; + +WindowPinnableBase::WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) + : WindowBase(parLayout, parWindowManager), mPinned(false), mVisible(false) +{ + ExposedWindow* window = static_cast(mMainWidget); + mPinButton = window->getSkinWidget ("Button"); + + mPinButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonClicked); +} + +void WindowPinnableBase::onPinButtonClicked(MyGUI::Widget* _sender) +{ + mPinned = !mPinned; + + if (mPinned) + mPinButton->changeWidgetSkin ("PinDown"); + else + mPinButton->changeWidgetSkin ("PinUp"); + + onPinToggled(); +} diff --git a/apps/openmw/mwgui/windowpinnablebase.hpp b/apps/openmw/mwgui/windowpinnablebase.hpp new file mode 100644 index 0000000000..657e8142f1 --- /dev/null +++ b/apps/openmw/mwgui/windowpinnablebase.hpp @@ -0,0 +1,28 @@ +#ifndef MWGUI_WINDOW_PINNABLE_BASE_H +#define MWGUI_WINDOW_PINNABLE_BASE_H + +#include "windowbase.hpp" + +namespace MWGui +{ + class WindowManager; + + class WindowPinnableBase: public WindowBase + { + public: + WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + bool pinned() { return mPinned; } + + private: + void onPinButtonClicked(MyGUI::Widget* _sender); + + protected: + virtual void onPinToggled() = 0; + + MyGUI::Widget* mPinButton; + bool mPinned; + bool mVisible; + }; +} + +#endif From ad49d1ecab8be0fdd863a5f747f5a680bf1fdc5a Mon Sep 17 00:00:00 2001 From: Glorf Date: Wed, 10 Apr 2013 15:24:20 +0200 Subject: [PATCH 183/198] Sixth minor fix --- apps/openmw/mwclass/armor.cpp | 6 +++--- apps/openmw/mwclass/armor.hpp | 2 +- apps/openmw/mwclass/clothing.cpp | 6 +++--- apps/openmw/mwclass/clothing.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 18 +++++++++--------- apps/openmw/mwclass/weapon.hpp | 2 +- apps/openmw/mwworld/actionequip.cpp | 2 +- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index a14b2667e1..d257c87619 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -292,12 +292,12 @@ namespace MWClass ref->mBase = record; } - int Armor::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); // slots that this item can be equipped in - std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); std::string npcRace = npc.get()->mBase->mRace; @@ -309,7 +309,7 @@ namespace MWClass const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { - std::vector parts = item.get()->mBase->mParts.mParts; + std::vector parts = ptr.get()->mBase->mParts.mParts; if(*slot == MWWorld::InventoryStore::Slot_Helmet) { diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 96c72848cc..1b99e51331 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -67,7 +67,7 @@ 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 &npc, const MWWorld::Ptr &item) 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 boost::shared_ptr use (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 58c4a2c5c6..b4e6e61f65 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -238,10 +238,10 @@ namespace MWClass ref->mBase = record; } - int Clothing::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Clothing::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { // slots that this item can be equipped in - std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); std::string npcRace = npc.get()->mBase->mRace; @@ -253,7 +253,7 @@ namespace MWClass const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { - std::vector parts = item.get()->mBase->mParts.mParts; + std::vector parts = ptr.get()->mBase->mParts.mParts; if(*slot == MWWorld::InventoryStore::Slot_Helmet) { diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index eb8d801996..71e01e8187 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -61,7 +61,7 @@ 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 &npc, const MWWorld::Ptr &item) 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 boost::shared_ptr use (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index a0cacaf6bd..e534a65c2a 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -384,9 +384,9 @@ namespace MWClass ref->mBase = record; } - int Weapon::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { - std::pair, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item); + std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); @@ -394,13 +394,13 @@ namespace MWClass { if(*slot == MWWorld::InventoryStore::Slot_CarriedRight) { - if(item.get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - item.get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - item.get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - item.get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - item.get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - item.get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - item.get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) + if(ptr.get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || + ptr.get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || + ptr.get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || + ptr.get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || + ptr.get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || + ptr.get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || + ptr.get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) { return 2; } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 01686b09cc..6c3f32abef 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -67,7 +67,7 @@ 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 &npc, const MWWorld::Ptr &item) 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 boost::shared_ptr use (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index fd35d0dd3c..84d1a3d158 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -21,7 +21,7 @@ namespace MWWorld MWWorld::Ptr object = getTarget(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor); - switch(MWWorld::Class::get (object).canBeEquipped (actor, object)) + switch(MWWorld::Class::get (object).canBeEquipped (object, actor)) { case 0: return; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index a0067f5d2e..d7ff350141 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -259,7 +259,7 @@ namespace MWWorld throw std::runtime_error ("class can't be enchanted"); } - int Class::canBeEquipped(const MWWorld::Ptr &npc, const MWWorld::Ptr &item) const + int Class::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { return 1; } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 362a8bc9ca..484004aca5 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -242,7 +242,7 @@ 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 &npc, const MWWorld::Ptr &item) 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 Ptr diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 782e3f920f..5495d6a021 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -186,7 +186,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc) } } - switch(MWWorld::Class::get (test).canBeEquipped (npc, test)) + switch(MWWorld::Class::get (test).canBeEquipped (test, npc)) { case 0: continue; From d768f6b57e2e4b992861a18dedf9e39c6e79b702 Mon Sep 17 00:00:00 2001 From: Britt Mathis Date: Wed, 10 Apr 2013 13:05:15 -0400 Subject: [PATCH 184/198] Deleted *_* files in MwGui, builds. --- apps/openmw/CMakeLists.txt | 6 +- apps/openmw/mwgui/dialogue_history.cpp | 76 --- apps/openmw/mwgui/dialogue_history.hpp | 19 - apps/openmw/mwgui/map_window.cpp | 446 ---------------- apps/openmw/mwgui/map_window.hpp | 107 ---- apps/openmw/mwgui/stats_window.cpp | 580 --------------------- apps/openmw/mwgui/stats_window.hpp | 83 --- apps/openmw/mwgui/text_input.cpp | 69 --- apps/openmw/mwgui/text_input.hpp | 36 -- apps/openmw/mwgui/window_base.cpp | 55 -- apps/openmw/mwgui/window_base.hpp | 51 -- apps/openmw/mwgui/window_pinnable_base.cpp | 28 - apps/openmw/mwgui/window_pinnable_base.hpp | 28 - 13 files changed, 3 insertions(+), 1581 deletions(-) delete mode 100644 apps/openmw/mwgui/dialogue_history.cpp delete mode 100644 apps/openmw/mwgui/dialogue_history.hpp delete mode 100644 apps/openmw/mwgui/map_window.cpp delete mode 100644 apps/openmw/mwgui/map_window.hpp delete mode 100644 apps/openmw/mwgui/stats_window.cpp delete mode 100644 apps/openmw/mwgui/stats_window.hpp delete mode 100644 apps/openmw/mwgui/text_input.cpp delete mode 100644 apps/openmw/mwgui/text_input.hpp delete mode 100644 apps/openmw/mwgui/window_base.cpp delete mode 100644 apps/openmw/mwgui/window_base.hpp delete mode 100644 apps/openmw/mwgui/window_pinnable_base.cpp delete mode 100644 apps/openmw/mwgui/window_pinnable_base.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8a0030be42..b3c3f4134c 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -24,9 +24,9 @@ add_openmw_dir (mwinput ) add_openmw_dir (mwgui - text_input widgets race class birth review windowmanagerimp console dialogue - dialogue_history window_base stats_window messagebox journalwindow charactercreation - map_window window_pinnable_base tooltips scrollwindow bookwindow list + textinput widgets race class birth review windowmanagerimp console dialogue + dialoguehistory windowbase statswindow messagebox journalwindow charactercreation + mapwindow windowpinnablebase tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog diff --git a/apps/openmw/mwgui/dialogue_history.cpp b/apps/openmw/mwgui/dialogue_history.cpp deleted file mode 100644 index 13f72545e2..0000000000 --- a/apps/openmw/mwgui/dialogue_history.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "dialogue_history.hpp" - -#include "../mwbase/windowmanager.hpp" - -#include "widgets.hpp" - -#include "../mwworld/esmstore.hpp" - -#include -#include - -#include -#include - -using namespace MWGui; -using namespace Widgets; - -MyGUI::UString DialogueHistory::getColorAtPos(size_t _pos) -{ - MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour()); - MyGUI::TextIterator iterator(getCaption()); - while(iterator.moveNext()) - { - size_t pos = iterator.getPosition(); - iterator.getTagColour(colour); - if (pos < _pos) - continue; - else if (pos == _pos) - break; - } - return colour; -} - -MyGUI::UString DialogueHistory::getColorTextAt(size_t _pos) -{ - bool breakOnNext = false; - MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour()); - MyGUI::UString colour2 = colour; - MyGUI::TextIterator iterator(getCaption()); - MyGUI::TextIterator col_start = iterator; - while(iterator.moveNext()) - { - size_t pos = iterator.getPosition(); - iterator.getTagColour(colour); - if(colour != colour2) - { - if(breakOnNext) - { - return getOnlyText().substr(col_start.getPosition(), iterator.getPosition()-col_start.getPosition()); - } - col_start = iterator; - colour2 = colour; - } - if (pos < _pos) - continue; - else if (pos == _pos) - { - breakOnNext = true; - } - } - return ""; -} - -void DialogueHistory::addDialogHeading(const MyGUI::UString& parText) -{ - MyGUI::UString head("\n#D8C09A"); - head.append(parText); - head.append("#B29154\n"); - addText(head); -} - -void DialogueHistory::addDialogText(const MyGUI::UString& parText) -{ - addText(parText); - addText("\n"); -} diff --git a/apps/openmw/mwgui/dialogue_history.hpp b/apps/openmw/mwgui/dialogue_history.hpp deleted file mode 100644 index c37504af77..0000000000 --- a/apps/openmw/mwgui/dialogue_history.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MWGUI_DIALOGE_HISTORY_H -#define MWGUI_DIALOGE_HISTORY_H -#include - -namespace MWGui -{ - class DialogueHistory : public MyGUI::EditBox - { - MYGUI_RTTI_DERIVED( DialogueHistory ) - public: - Widget* getClient() { return mClient; } - MyGUI::UString getColorAtPos(size_t _pos); - MyGUI::UString getColorTextAt(size_t _pos); - void addDialogHeading(const MyGUI::UString& parText); - void addDialogText(const MyGUI::UString& parText); - }; -} -#endif - diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp deleted file mode 100644 index d0f3f921e5..0000000000 --- a/apps/openmw/mwgui/map_window.cpp +++ /dev/null @@ -1,446 +0,0 @@ -#include "map_window.hpp" - -#include - -#include -#include -#include - -#include - -#include "../mwbase/windowmanager.hpp" -#include "../mwbase/world.hpp" -#include "../mwbase/environment.hpp" -#include "../mwworld/player.hpp" - -#include "../mwrender/globalmap.hpp" - -#include "widgets.hpp" - -using namespace MWGui; - -LocalMapBase::LocalMapBase() - : mCurX(0) - , mCurY(0) - , mInterior(false) - , mFogOfWar(true) - , mLocalMap(NULL) - , mMapDragAndDrop(false) - , mPrefix() - , mChanged(true) - , mLayout(NULL) - , mLastPositionX(0.0f) - , mLastPositionY(0.0f) - , mLastDirectionX(0.0f) - , mLastDirectionY(0.0f) - , mCompass(NULL) -{ -} - -void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop) -{ - mLocalMap = widget; - mLayout = layout; - mMapDragAndDrop = mapDragAndDrop; - mCompass = compass; - - // create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each - const int widgetSize = 512; - for (int mx=0; mx<3; ++mx) - { - for (int my=0; my<3; ++my) - { - MyGUI::ImageBox* map = mLocalMap->createWidget("ImageBox", - MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), - MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my)); - - MyGUI::ImageBox* fog = map->createWidget("ImageBox", - MyGUI::IntCoord(0, 0, widgetSize, widgetSize), - MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast(mx) + "_" + boost::lexical_cast(my) + "_fog"); - - if (!mMapDragAndDrop) - { - map->setNeedMouseFocus(false); - fog->setNeedMouseFocus(false); - } - - mMapWidgets.push_back(map); - mFogWidgets.push_back(fog); - } - } -} - -void LocalMapBase::setCellPrefix(const std::string& prefix) -{ - mPrefix = prefix; - mChanged = true; -} - -void LocalMapBase::toggleFogOfWar() -{ - mFogOfWar = !mFogOfWar; - applyFogOfWar(); -} - -void LocalMapBase::applyFogOfWar() -{ - for (int mx=0; mx<3; ++mx) - { - for (int my=0; my<3; ++my) - { - std::string name = "Map_" + boost::lexical_cast(mx) + "_" - + boost::lexical_cast(my); - - std::string image = mPrefix+"_"+ boost::lexical_cast(mCurX + (mx-1)) + "_" - + boost::lexical_cast(mCurY + (-1*(my-1))); - MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx]; - fog->setImageTexture(mFogOfWar ? - ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" - : "black.png" ) - : ""); - } - } - notifyMapChanged (); -} - -void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2) -{ - applyFogOfWar (); -} - -void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2) -{ - applyFogOfWar (); -} - -void LocalMapBase::setActiveCell(const int x, const int y, bool interior) -{ - if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell - - // clear all previous markers - for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i) - { - if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker") - { - MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i)); - } - } - - for (int mx=0; mx<3; ++mx) - { - for (int my=0; my<3; ++my) - { - // map - std::string image = mPrefix+"_"+ boost::lexical_cast(x + (mx-1)) + "_" - + boost::lexical_cast(y + (-1*(my-1))); - - std::string name = "Map_" + boost::lexical_cast(mx) + "_" - + boost::lexical_cast(my); - - MyGUI::ImageBox* box = mMapWidgets[my + 3*mx]; - - if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) - box->setImageTexture(image); - else - box->setImageTexture("black.png"); - - - // door markers - - // interior map only consists of one cell, so handle the markers only once - if (interior && (mx != 2 || my != 2)) - continue; - - MWWorld::CellStore* cell; - if (interior) - cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix); - else - cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1)); - - std::vector doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell); - - for (std::vector::iterator it = doors.begin(); it != doors.end(); ++it) - { - MWBase::World::DoorMarker marker = *it; - - // convert world coordinates to normalized cell coordinates - MyGUI::IntCoord widgetCoord; - float nX,nY; - int cellDx, cellDy; - if (!interior) - { - const int cellSize = 8192; - - nX = (marker.x - cellSize * (x+mx-1)) / cellSize; - nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize; - - widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8); - } - else - { - Ogre::Vector2 position (marker.x, marker.y); - MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy); - - widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8); - } - - static int counter = 0; - ++counter; - MyGUI::Button* markerWidget = mLocalMap->createWidget("ButtonImage", - widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast(counter)); - markerWidget->setImageResource("DoorMarker"); - markerWidget->setUserString("ToolTipType", "Layout"); - markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); - markerWidget->setUserString("Caption_TextOneLine", marker.name); - markerWidget->setUserString("IsMarker", "true"); - markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused); - markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused); - - MarkerPosition markerPos; - markerPos.interior = interior; - markerPos.cellX = interior ? cellDx : x + mx - 1; - markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1); - markerPos.nX = nX; - markerPos.nY = nY; - - markerWidget->setUserData(markerPos); - } - - - } - } - mInterior = interior; - mCurX = x; - mCurY = y; - mChanged = false; - - // fog of war - applyFogOfWar(); - - // set the compass texture again, because MyGUI determines sorting of ImageBox widgets - // based on the last setImageTexture call - std::string tex = "textures\\compass.dds"; - mCompass->setImageTexture(""); - mCompass->setImageTexture(tex); -} - - -void LocalMapBase::setPlayerPos(const float x, const float y) -{ - if (x == mLastPositionX && y == mLastPositionY) - return; - - notifyPlayerUpdate (); - - MyGUI::IntSize size = mLocalMap->getCanvasSize(); - MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height); - MyGUI::IntCoord viewsize = mLocalMap->getCoord(); - MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); - mLocalMap->setViewOffset(pos); - - mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16)); - mLastPositionX = x; - mLastPositionY = y; -} - -void LocalMapBase::setPlayerDir(const float x, const float y) -{ - if (x == mLastDirectionX && y == mLastDirectionY) - return; - - notifyPlayerUpdate (); - - MyGUI::ISubWidget* main = mCompass->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); - float angle = std::atan2(x,y); - rotatingSubskin->setAngle(angle); - - mLastDirectionX = x; - mLastDirectionY = y; -} - -// ------------------------------------------------------------------------------------------ - -MapWindow::MapWindow(MWBase::WindowManager& parWindowManager, const std::string& cacheDir) - : MWGui::WindowPinnableBase("openmw_map_window.layout", parWindowManager) - , mGlobal(false) -{ - setCoord(500,0,320,300); - - mGlobalMapRender = new MWRender::GlobalMap(cacheDir); - mGlobalMapRender->render(); - - getWidget(mLocalMap, "LocalMap"); - getWidget(mGlobalMap, "GlobalMap"); - getWidget(mGlobalMapImage, "GlobalMapImage"); - getWidget(mGlobalMapOverlay, "GlobalMapOverlay"); - getWidget(mPlayerArrowLocal, "CompassLocal"); - getWidget(mPlayerArrowGlobal, "CompassGlobal"); - - mGlobalMapImage->setImageTexture("GlobalMap.png"); - mGlobalMapOverlay->setImageTexture("GlobalMapOverlay"); - - mGlobalMap->setVisible (false); - - getWidget(mButton, "WorldButton"); - mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); - mButton->setCaptionWithReplacing("#{sWorld}"); - - getWidget(mEventBoxGlobal, "EventBoxGlobal"); - mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); - mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); - getWidget(mEventBoxLocal, "EventBoxLocal"); - mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); - mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); - - LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this); -} - -MapWindow::~MapWindow() -{ - delete mGlobalMapRender; -} - -void MapWindow::setCellName(const std::string& cellName) -{ - setTitle("#{sCell=" + cellName + "}"); -} - -void MapWindow::addVisitedLocation(const std::string& name, int x, int y) -{ - float worldX, worldY; - mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY); - - MyGUI::IntCoord widgetCoord( - worldX * mGlobalMapRender->getWidth()+6, - worldY * mGlobalMapRender->getHeight()+6, - 12, 12); - - - static int _counter=0; - MyGUI::Button* markerWidget = mGlobalMapImage->createWidget("ButtonImage", - widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast(_counter)); - markerWidget->setImageResource("DoorMarker"); - markerWidget->setUserString("ToolTipType", "Layout"); - markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); - markerWidget->setUserString("Caption_TextOneLine", name); - ++_counter; - - markerWidget = mEventBoxGlobal->createWidget("", - widgetCoord, MyGUI::Align::Default); - markerWidget->setNeedMouseFocus (true); - markerWidget->setUserString("ToolTipType", "Layout"); - markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); - markerWidget->setUserString("Caption_TextOneLine", name); -} - -void MapWindow::cellExplored(int x, int y) -{ - mGlobalMapRender->exploreCell(x,y); -} - -void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) -{ - if (_id!=MyGUI::MouseButton::Left) return; - mLastDragPos = MyGUI::IntPoint(_left, _top); -} - -void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) -{ - if (_id!=MyGUI::MouseButton::Left) return; - - MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos; - - if (!mGlobal) - mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff ); - else - mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff ); - - - mLastDragPos = MyGUI::IntPoint(_left, _top); -} - -void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) -{ - mGlobal = !mGlobal; - mGlobalMap->setVisible(mGlobal); - mLocalMap->setVisible(!mGlobal); - - mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : - "#{sWorld}"); - - if (mGlobal) - globalMapUpdatePlayer (); -} - -void MapWindow::onPinToggled() -{ - mWindowManager.setMinimapVisibility(!mPinned); -} - -void MapWindow::open() -{ - mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); - mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); - - for (unsigned int i=0; igetChildCount (); ++i) - { - if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker") - mGlobalMapImage->getChildAt (i)->castType()->setImageResource("DoorMarker"); - } - - globalMapUpdatePlayer(); - - mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds"); -} - -void MapWindow::globalMapUpdatePlayer () -{ - Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition (); - Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation (); - Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y); - - float worldX, worldY; - mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY); - worldX *= mGlobalMapRender->getWidth(); - worldY *= mGlobalMapRender->getHeight(); - - - // for interiors, we have no choice other than using the last position & direction. - /// \todo save this last position in the savegame? - if (MWBase::Environment::get().getWorld ()->isCellExterior ()) - { - mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16)); - - MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(16,16)); - float angle = std::atan2(dir.x, dir.y); - rotatingSubskin->setAngle(angle); - - // set the view offset so that player is in the center - MyGUI::IntSize viewsize = mGlobalMap->getSize(); - MyGUI::IntPoint viewoffs(0.5*viewsize.width - worldX, 0.5*viewsize.height - worldY); - mGlobalMap->setViewOffset(viewoffs); - } -} - -void MapWindow::notifyPlayerUpdate () -{ - globalMapUpdatePlayer (); -} - -void MapWindow::notifyMapChanged () -{ - // workaround to prevent the map from drawing on top of the button - MyGUI::IntCoord oldCoord = mButton->getCoord (); - MyGUI::Gui::getInstance().destroyWidget (mButton); - mButton = mMainWidget->createWidget("MW_Button", - oldCoord, MyGUI::Align::Bottom | MyGUI::Align::Right); - mButton->setProperty ("ExpandDirection", "Left"); - - mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); - mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : - "#{sWorld}"); -} diff --git a/apps/openmw/mwgui/map_window.hpp b/apps/openmw/mwgui/map_window.hpp deleted file mode 100644 index 39770a7a26..0000000000 --- a/apps/openmw/mwgui/map_window.hpp +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef MWGUI_MAPWINDOW_H -#define MWGUI_MAPWINDOW_H - -#include "window_pinnable_base.hpp" - -namespace MWRender -{ - class GlobalMap; -} - -namespace MWGui -{ - class LocalMapBase - { - public: - LocalMapBase(); - void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop=false); - - void setCellPrefix(const std::string& prefix); - void setActiveCell(const int x, const int y, bool interior=false); - void setPlayerDir(const float x, const float y); - void setPlayerPos(const float x, const float y); - - void toggleFogOfWar(); - - struct MarkerPosition - { - bool interior; - int cellX; - int cellY; - float nX; - float nY; - }; - - protected: - int mCurX, mCurY; - bool mInterior; - MyGUI::ScrollView* mLocalMap; - MyGUI::ImageBox* mCompass; - std::string mPrefix; - bool mChanged; - bool mFogOfWar; - - std::vector mMapWidgets; - std::vector mFogWidgets; - - void applyFogOfWar(); - - void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2); - void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2); - - virtual void notifyPlayerUpdate() {} - virtual void notifyMapChanged() {} - - OEngine::GUI::Layout* mLayout; - - bool mMapDragAndDrop; - - float mLastPositionX; - float mLastPositionY; - float mLastDirectionX; - float mLastDirectionY; - }; - - class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase - { - public: - MapWindow(MWBase::WindowManager& parWindowManager, const std::string& cacheDir); - virtual ~MapWindow(); - - void setCellName(const std::string& cellName); - - void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map - void cellExplored(int x, int y); - - virtual void open(); - - private: - void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); - void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); - void onWorldButtonClicked(MyGUI::Widget* _sender); - - void globalMapUpdatePlayer(); - - MyGUI::ScrollView* mGlobalMap; - MyGUI::ImageBox* mGlobalMapImage; - MyGUI::ImageBox* mGlobalMapOverlay; - MyGUI::ImageBox* mPlayerArrowLocal; - MyGUI::ImageBox* mPlayerArrowGlobal; - MyGUI::Button* mButton; - MyGUI::IntPoint mLastDragPos; - bool mGlobal; - - MyGUI::Button* mEventBoxGlobal; - MyGUI::Button* mEventBoxLocal; - - MWRender::GlobalMap* mGlobalMapRender; - - protected: - virtual void onPinToggled(); - - virtual void notifyPlayerUpdate(); - virtual void notifyMapChanged(); - - }; -} -#endif diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp deleted file mode 100644 index 0678e98919..0000000000 --- a/apps/openmw/mwgui/stats_window.cpp +++ /dev/null @@ -1,580 +0,0 @@ -#include "stats_window.hpp" - -#include -#include -#include - -#include - -#include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" -#include "../mwbase/mechanicsmanager.hpp" -#include "../mwbase/windowmanager.hpp" - -#include "../mwworld/player.hpp" -#include "../mwworld/class.hpp" - -#include "../mwmechanics/npcstats.hpp" - -#include "tooltips.hpp" - - -using namespace MWGui; -const int StatsWindow::sLineHeight = 18; - -StatsWindow::StatsWindow (MWBase::WindowManager& parWindowManager) - : WindowPinnableBase("openmw_stats_window.layout", parWindowManager) - , mSkillView(NULL) - , mClientHeight(0) - , mMajorSkills() - , mMinorSkills() - , mMiscSkills() - , mSkillValues() - , mSkillWidgetMap() - , mFactionWidgetMap() - , mFactions() - , mBirthSignId() - , mReputation(0) - , mBounty(0) - , mSkillWidgets() - , mChanged(true) -{ - setCoord(0,0,498, 342); - - const char *names[][2] = - { - { "Attrib1", "sAttributeStrength" }, - { "Attrib2", "sAttributeIntelligence" }, - { "Attrib3", "sAttributeWillpower" }, - { "Attrib4", "sAttributeAgility" }, - { "Attrib5", "sAttributeSpeed" }, - { "Attrib6", "sAttributeEndurance" }, - { "Attrib7", "sAttributePersonality" }, - { "Attrib8", "sAttributeLuck" }, - { 0, 0 } - }; - - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - for (int i=0; names[i][0]; ++i) - { - setText (names[i][0], store.get().find (names[i][1])->getString()); - } - - getWidget(mSkillView, "SkillView"); - getWidget(mLeftPane, "LeftPane"); - getWidget(mRightPane, "RightPane"); - - for (int i = 0; i < ESM::Skill::Length; ++i) - { - mSkillValues.insert(std::pair >(i, MWMechanics::Stat())); - mSkillWidgetMap.insert(std::pair(i, (MyGUI::TextBox*)NULL)); - } - - MyGUI::WindowPtr t = static_cast(mMainWidget); - t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); -} - -void StatsWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) -{ - if (mSkillView->getViewOffset().top + _rel*0.3 > 0) - mSkillView->setViewOffset(MyGUI::IntPoint(0, 0)); - else - mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3)); -} - -void StatsWindow::onWindowResize(MyGUI::Window* window) -{ - mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) ); - mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) ); - mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); -} - -void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max) -{ - MyGUI::ProgressPtr pt; - getWidget(pt, name); - pt->setProgressRange(max); - pt->setProgressPosition(val); - - std::stringstream out; - out << val << "/" << max; - setText(tname, out.str().c_str()); -} - -void StatsWindow::setPlayerName(const std::string& playerName) -{ - static_cast(mMainWidget)->setCaption(playerName); - adjustWindowCaption(); -} - -void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) -{ - static const char *ids[] = - { - "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", - "AttribVal6", "AttribVal7", "AttribVal8", - 0 - }; - - for (int i=0; ids[i]; ++i) - if (ids[i]==id) - { - std::ostringstream valueString; - valueString << value.getModified(); - setText (id, valueString.str()); - - MyGUI::TextBox* box; - getWidget(box, id); - - if (value.getModified()>value.getBase()) - box->_setWidgetState("increased"); - else if (value.getModified()_setWidgetState("decreased"); - else - box->_setWidgetState("normal"); - - break; - } -} - -void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat& value) -{ - static const char *ids[] = - { - "HBar", "MBar", "FBar", - 0 - }; - - for (int i=0; ids[i]; ++i) - { - if (ids[i]==id) - { - std::string id (ids[i]); - setBar (id, id + "T", static_cast(value.getCurrent()), static_cast(value.getModified())); - - // health, magicka, fatigue tooltip - MyGUI::Widget* w; - std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); - if (i==0) - { - getWidget(w, "Health"); - w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); - } - else if (i==1) - { - getWidget(w, "Magicka"); - w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); - } - else if (i==2) - { - getWidget(w, "Fatigue"); - w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); - } - } - } -} - -void StatsWindow::setValue (const std::string& id, const std::string& value) -{ - if (id=="name") - setPlayerName (value); - else if (id=="race") - setText ("RaceText", value); - else if (id=="class") - setText ("ClassText", value); -} - -void StatsWindow::setValue (const std::string& id, int value) -{ - if (id=="level") - { - std::ostringstream text; - text << value; - setText("LevelText", text.str()); - } -} - -void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value) -{ - mSkillValues[parSkill] = value; - MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill]; - if (widget) - { - float modified = value.getModified(), base = value.getBase(); - std::string text = boost::lexical_cast(std::floor(modified)); - std::string state = "normal"; - if (modified > base) - state = "increased"; - else if (modified < base) - state = "decreased"; - - widget->setCaption(text); - widget->_setWidgetState(state); - } -} - -void StatsWindow::configureSkills (const std::vector& major, const std::vector& minor) -{ - mMajorSkills = major; - mMinorSkills = minor; - - // Update misc skills with the remaining skills not in major or minor - std::set skillSet; - std::copy(major.begin(), major.end(), std::inserter(skillSet, skillSet.begin())); - std::copy(minor.begin(), minor.end(), std::inserter(skillSet, skillSet.begin())); - boost::array::const_iterator end = ESM::Skill::sSkillIds.end(); - mMiscSkills.clear(); - for (boost::array::const_iterator it = ESM::Skill::sSkillIds.begin(); it != end; ++it) - { - int skill = *it; - if (skillSet.find(skill) == skillSet.end()) - mMiscSkills.push_back(skill); - } - - updateSkillArea(); -} - -void StatsWindow::onFrame () -{ - if (!mMainWidget->getVisible()) - return; - - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); - - // level progress - MyGUI::Widget* levelWidget; - for (int i=0; i<2; ++i) - { - getWidget(levelWidget, i==0 ? "Level_str" : "LevelText"); - levelWidget->setUserString("RangePosition_LevelProgress", boost::lexical_cast(PCstats.getLevelProgress())); - levelWidget->setUserString("Caption_LevelProgressText", boost::lexical_cast(PCstats.getLevelProgress()) + "/10"); - } - - setFactions(PCstats.getFactionRanks()); - setExpelled(PCstats.getExpelled ()); - - const std::string &signId = - MWBase::Environment::get().getWorld()->getPlayer().getBirthSign(); - - setBirthSign(signId); - setReputation (PCstats.getReputation ()); - setBounty (PCstats.getBounty ()); - - if (mChanged) - updateSkillArea(); -} - -void StatsWindow::setFactions (const FactionList& factions) -{ - if (mFactions != factions) - { - mFactions = factions; - mChanged = true; - } -} - -void StatsWindow::setExpelled (const std::set& expelled) -{ - if (mExpelled != expelled) - { - mExpelled = expelled; - mChanged = true; - } -} - -void StatsWindow::setBirthSign (const std::string& signId) -{ - if (signId != mBirthSignId) - { - mBirthSignId = signId; - mChanged = true; - } -} - -void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::ImageBox* separator = mSkillView->createWidget("MW_HLine", - MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), - MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); - separator->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); - mSkillWidgets.push_back(separator); - - coord1.top += separator->getHeight(); - coord2.top += separator->getHeight(); -} - -void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::TextBox* groupWidget = mSkillView->createWidget("SandBrightText", - MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), - MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); - groupWidget->setCaption(label); - groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); - mSkillWidgets.push_back(groupWidget); - - coord1.top += sLineHeight; - coord2.top += sLineHeight; -} - -MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::TextBox *skillNameWidget, *skillValueWidget; - - skillNameWidget = mSkillView->createWidget("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); - skillNameWidget->setCaption(text); - skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); - - skillValueWidget = mSkillView->createWidget("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top); - skillValueWidget->setCaption(value); - skillValueWidget->_setWidgetState(state); - skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); - - mSkillWidgets.push_back(skillNameWidget); - mSkillWidgets.push_back(skillValueWidget); - - coord1.top += sLineHeight; - coord2.top += sLineHeight; - - return skillValueWidget; -} - -MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - MyGUI::TextBox* skillNameWidget; - - skillNameWidget = mSkillView->createWidget("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); - skillNameWidget->setCaption(text); - skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel); - - mSkillWidgets.push_back(skillNameWidget); - - coord1.top += sLineHeight; - coord2.top += sLineHeight; - - return skillNameWidget; -} - -void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) -{ - // Add a line separator if there are items above - if (!mSkillWidgets.empty()) - { - addSeparator(coord1, coord2); - } - - addGroup(mWindowManager.getGameSettingString(titleId, titleDefault), coord1, coord2); - - SkillList::const_iterator end = skills.end(); - for (SkillList::const_iterator it = skills.begin(); it != end; ++it) - { - int skillId = *it; - if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes - continue; - assert(skillId >= 0 && skillId < ESM::Skill::Length); - const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId]; - const MWMechanics::Stat &stat = mSkillValues.find(skillId)->second; - float base = stat.getBase(); - float modified = stat.getModified(); - int progressPercent = (modified - float(static_cast(modified))) * 100; - - const MWWorld::ESMStore &esmStore = - MWBase::Environment::get().getWorld()->getStore(); - - const ESM::Skill* skill = esmStore.get().find(skillId); - assert(skill); - - std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId]; - - const ESM::Attribute* attr = - esmStore.get().find(skill->mData.mAttribute); - assert(attr); - - std::string state = "normal"; - if (modified > base) - state = "increased"; - else if (modified < base) - state = "decreased"; - MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), - boost::lexical_cast(static_cast(modified)), state, coord1, coord2); - - for (int i=0; i<2; ++i) - { - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipLayout", "SkillToolTip"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillName", "#{"+skillNameId+"}"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillDescription", skill->mDescription); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillAttribute", "#{sGoverningAttribute}: #{" + attr->mName + "}"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ImageTexture_SkillImage", icon); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", boost::lexical_cast(progressPercent)+"/100"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Range_SkillProgress", "100"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("RangePosition_SkillProgress", boost::lexical_cast(progressPercent)); - } - - mSkillWidgetMap[skillId] = widget; - } -} - -void StatsWindow::updateSkillArea() -{ - mChanged = false; - - for (std::vector::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) - { - MyGUI::Gui::getInstance().destroyWidget(*it); - } - mSkillWidgets.clear(); - - mSkillView->setViewOffset (MyGUI::IntPoint(0,0)); - mClientHeight = 0; - - const int valueSize = 40; - MyGUI::IntCoord coord1(10, 0, mSkillView->getWidth() - (10 + valueSize) - 24, 18); - MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height); - - if (!mMajorSkills.empty()) - addSkills(mMajorSkills, "sSkillClassMajor", "Major Skills", coord1, coord2); - - if (!mMinorSkills.empty()) - addSkills(mMinorSkills, "sSkillClassMinor", "Minor Skills", coord1, coord2); - - if (!mMiscSkills.empty()) - addSkills(mMiscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); - - MWBase::World *world = MWBase::Environment::get().getWorld(); - const MWWorld::ESMStore &store = world->getStore(); - const ESM::NPC *player = - world->getPlayer().getPlayer().get()->mBase; - - // race tooltip - const ESM::Race* playerRace = store.get().find(player->mRace); - - MyGUI::Widget* raceWidget; - getWidget(raceWidget, "RaceText"); - ToolTips::createRaceToolTip(raceWidget, playerRace); - getWidget(raceWidget, "Race_str"); - ToolTips::createRaceToolTip(raceWidget, playerRace); - - // class tooltip - MyGUI::Widget* classWidget; - - const ESM::Class *playerClass = - store.get().find(player->mClass); - - getWidget(classWidget, "ClassText"); - ToolTips::createClassToolTip(classWidget, *playerClass); - getWidget(classWidget, "Class_str"); - ToolTips::createClassToolTip(classWidget, *playerClass); - - if (!mFactions.empty()) - { - // Add a line separator if there are items above - if (!mSkillWidgets.empty()) - addSeparator(coord1, coord2); - - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); - std::set& expelled = PCstats.getExpelled (); - - addGroup(mWindowManager.getGameSettingString("sFaction", "Faction"), coord1, coord2); - FactionList::const_iterator end = mFactions.end(); - for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) - { - const ESM::Faction *faction = - store.get().find(it->first); - MyGUI::Widget* w = addItem(faction->mName, coord1, coord2); - - std::string text; - - text += std::string("#DDC79E") + faction->mName; - - if (expelled.find(it->first) != expelled.end()) - text += "\n#{sExpelled}"; - else - { - text += std::string("\n#BF9959") + faction->mRanks[it->second]; - - if (it->second < 9) - { - // player doesn't have max rank yet - text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->mRanks[it->second+1]; - - ESM::RankData rankData = faction->mData.mRankData[it->second+1]; - const ESM::Attribute* attr1 = store.get().find(faction->mData.mAttribute[0]); - const ESM::Attribute* attr2 = store.get().find(faction->mData.mAttribute[1]); - assert(attr1 && attr2); - - text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast(rankData.mAttribute1) - + ", #{" + attr2->mName + "}: " + boost::lexical_cast(rankData.mAttribute2); - - text += "\n\n#DDC79E#{sFavoriteSkills}"; - text += "\n#BF9959"; - for (int i=0; i<6; ++i) - { - text += "#{"+ESM::Skill::sSkillNameIds[faction->mData.mSkills[i]]+"}"; - if (i<5) - text += ", "; - } - - text += "\n"; - - if (rankData.mSkill1 > 0) - text += "\n#{sNeedOneSkill} " + boost::lexical_cast(rankData.mSkill1); - if (rankData.mSkill2 > 0) - text += "\n#{sNeedTwoSkills} " + boost::lexical_cast(rankData.mSkill2); - } - } - - w->setUserString("ToolTipType", "Layout"); - w->setUserString("ToolTipLayout", "TextToolTip"); - w->setUserString("Caption_Text", text); - } - } - - if (!mBirthSignId.empty()) - { - // Add a line separator if there are items above - if (!mSkillWidgets.empty()) - addSeparator(coord1, coord2); - - addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); - const ESM::BirthSign *sign = - store.get().find(mBirthSignId); - MyGUI::Widget* w = addItem(sign->mName, coord1, coord2); - - ToolTips::createBirthsignToolTip(w, mBirthSignId); - } - - // Add a line separator if there are items above - if (!mSkillWidgets.empty()) - addSeparator(coord1, coord2); - - addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"), - boost::lexical_cast(static_cast(mReputation)), "normal", coord1, coord2); - - for (int i=0; i<2; ++i) - { - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sSkillsMenuReputationHelp}"); - } - - addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"), - boost::lexical_cast(static_cast(mBounty)), "normal", coord1, coord2); - - for (int i=0; i<2; ++i) - { - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip"); - mSkillWidgets[mSkillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sCrimeHelp}"); - } - - mClientHeight = coord1.top; - - mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); -} - -void StatsWindow::onPinToggled() -{ - mWindowManager.setHMSVisibility(!mPinned); -} diff --git a/apps/openmw/mwgui/stats_window.hpp b/apps/openmw/mwgui/stats_window.hpp deleted file mode 100644 index 3befc1f002..0000000000 --- a/apps/openmw/mwgui/stats_window.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef MWGUI_STATS_WINDOW_H -#define MWGUI_STATS_WINDOW_H - -#include "../mwworld/esmstore.hpp" - -#include -#include -#include -#include - -#include "../mwmechanics/stat.hpp" -#include "window_pinnable_base.hpp" - -namespace MWGui -{ - class WindowManager; - - class StatsWindow : public WindowPinnableBase - { - public: - typedef std::map FactionList; - - typedef std::vector SkillList; - - StatsWindow(MWBase::WindowManager& parWindowManager); - - /// automatically updates all the data in the stats window, but only if it has changed. - void onFrame(); - - void setBar(const std::string& name, const std::string& tname, int val, int max); - void setPlayerName(const std::string& playerName); - - /// Set value for the given ID. - void setValue (const std::string& id, const MWMechanics::Stat& value); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setValue (const std::string& id, const std::string& value); - void setValue (const std::string& id, int value); - void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat& value); - - void configureSkills (const SkillList& major, const SkillList& minor); - void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; } - void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } - void updateSkillArea(); - - private: - void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); - - void setFactions (const FactionList& factions); - void setExpelled (const std::set& expelled); - void setBirthSign (const std::string &signId); - - void onWindowResize(MyGUI::Window* window); - void onMouseWheel(MyGUI::Widget* _sender, int _rel); - - static const int sLineHeight; - - MyGUI::Widget* mLeftPane; - MyGUI::Widget* mRightPane; - - MyGUI::ScrollView* mSkillView; - int mLastPos, mClientHeight; - - SkillList mMajorSkills, mMinorSkills, mMiscSkills; - std::map > mSkillValues; - std::map mSkillWidgetMap; - std::map mFactionWidgetMap; - FactionList mFactions; ///< Stores a list of factions and the current rank - std::string mBirthSignId; - int mReputation, mBounty; - std::vector mSkillWidgets; //< Skills and other information - std::set mExpelled; - - bool mChanged; - - protected: - virtual void onPinToggled(); - }; -} -#endif diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp deleted file mode 100644 index ee9144be68..0000000000 --- a/apps/openmw/mwgui/text_input.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "text_input.hpp" - -#include "../mwbase/windowmanager.hpp" - -using namespace MWGui; - -TextInputDialog::TextInputDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_text_input.layout", parWindowManager) -{ - // Centre dialog - center(); - - getWidget(mTextEdit, "TextEdit"); - mTextEdit->eventEditSelectAccept += newDelegate(this, &TextInputDialog::onTextAccepted); - - MyGUI::Button* okButton; - getWidget(okButton, "OKButton"); - okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); - - // Make sure the edit box has focus - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); -} - -void TextInputDialog::setNextButtonShow(bool shown) -{ - MyGUI::Button* okButton; - getWidget(okButton, "OKButton"); - - if (shown) - okButton->setCaption(mWindowManager.getGameSettingString("sNext", "")); - else - okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); -} - -void TextInputDialog::setTextLabel(const std::string &label) -{ - setText("LabelT", label); -} - -void TextInputDialog::open() -{ - WindowModal::open(); - // Make sure the edit box has focus - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); -} - -// widget controls - -void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) -{ - if (mTextEdit->getCaption() == "") - { - mWindowManager.messageBox ("#{sNotifyMessage37}"); - MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); - } - else - eventDone(this); -} - -void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) -{ - if (mTextEdit->getCaption() == "") - { - mWindowManager.messageBox ("#{sNotifyMessage37}"); - MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); - } - else - eventDone(this); -} diff --git a/apps/openmw/mwgui/text_input.hpp b/apps/openmw/mwgui/text_input.hpp deleted file mode 100644 index 29de7388b2..0000000000 --- a/apps/openmw/mwgui/text_input.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MWGUI_TEXT_INPUT_H -#define MWGUI_TEXT_INPUT_H - -#include "window_base.hpp" - -namespace MWGui -{ - class WindowManager; -} - -/* - */ - -namespace MWGui -{ - class TextInputDialog : public WindowModal - { - public: - TextInputDialog(MWBase::WindowManager& parWindowManager); - - std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; } - void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); } - - void setNextButtonShow(bool shown); - void setTextLabel(const std::string &label); - virtual void open(); - - protected: - void onOkClicked(MyGUI::Widget* _sender); - void onTextAccepted(MyGUI::Edit* _sender); - - private: - MyGUI::EditBox* mTextEdit; - }; -} -#endif diff --git a/apps/openmw/mwgui/window_base.cpp b/apps/openmw/mwgui/window_base.cpp deleted file mode 100644 index 38bee9ea30..0000000000 --- a/apps/openmw/mwgui/window_base.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "window_base.hpp" - -#include - -#include "../mwbase/windowmanager.hpp" - -using namespace MWGui; - -WindowBase::WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) - : Layout(parLayout) - , mWindowManager(parWindowManager) -{ -} - -void WindowBase::setVisible(bool visible) -{ - bool wasVisible = mMainWidget->getVisible(); - mMainWidget->setVisible(visible); - - if (visible) - open(); - else if (wasVisible && !visible) - close(); -} - -void WindowBase::center() -{ - // Centre dialog - - // MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); - // Note by scrawl: The following works more reliably in the case when the window was _just_ - // resized and MyGUI RenderManager doesn't know about the new size yet - MyGUI::IntSize gameWindowSize = MyGUI::IntSize(Settings::Manager::getInt("resolution x", "Video"), - Settings::Manager::getInt("resolution y", "Video")); - - MyGUI::IntCoord coord = mMainWidget->getCoord(); - coord.left = (gameWindowSize.width - coord.width)/2; - coord.top = (gameWindowSize.height - coord.height)/2; - mMainWidget->setCoord(coord); -} - -WindowModal::WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager) - : WindowBase(parLayout, parWindowManager) -{ -} - -void WindowModal::open() -{ - MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget); -} - -void WindowModal::close() -{ - MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget); -} diff --git a/apps/openmw/mwgui/window_base.hpp b/apps/openmw/mwgui/window_base.hpp deleted file mode 100644 index afdf4d065b..0000000000 --- a/apps/openmw/mwgui/window_base.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef MWGUI_WINDOW_BASE_H -#define MWGUI_WINDOW_BASE_H - -#include - -namespace MWBase -{ - class WindowManager; -} - -namespace MWGui -{ - class WindowManager; - - class WindowBase: public OEngine::GUI::Layout - { - public: - WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); - - // Events - typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; - - virtual void open() {} - virtual void close () {} - virtual void setVisible(bool visible); - void center(); - - /** Event : Dialog finished, OK button clicked.\n - signature : void method()\n - */ - EventHandle_WindowBase eventDone; - - protected: - /// \todo remove - MWBase::WindowManager& mWindowManager; - }; - - - /* - * "Modal" windows cause the rest of the interface to be unaccessible while they are visible - */ - class WindowModal : public WindowBase - { - public: - WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager); - virtual void open(); - virtual void close(); - }; -} - -#endif diff --git a/apps/openmw/mwgui/window_pinnable_base.cpp b/apps/openmw/mwgui/window_pinnable_base.cpp deleted file mode 100644 index 651b3a1e98..0000000000 --- a/apps/openmw/mwgui/window_pinnable_base.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "window_pinnable_base.hpp" - -#include "../mwbase/windowmanager.hpp" - -#include "exposedwindow.hpp" - -using namespace MWGui; - -WindowPinnableBase::WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) - : WindowBase(parLayout, parWindowManager), mPinned(false), mVisible(false) -{ - ExposedWindow* window = static_cast(mMainWidget); - mPinButton = window->getSkinWidget ("Button"); - - mPinButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonClicked); -} - -void WindowPinnableBase::onPinButtonClicked(MyGUI::Widget* _sender) -{ - mPinned = !mPinned; - - if (mPinned) - mPinButton->changeWidgetSkin ("PinDown"); - else - mPinButton->changeWidgetSkin ("PinUp"); - - onPinToggled(); -} diff --git a/apps/openmw/mwgui/window_pinnable_base.hpp b/apps/openmw/mwgui/window_pinnable_base.hpp deleted file mode 100644 index 50259858e2..0000000000 --- a/apps/openmw/mwgui/window_pinnable_base.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef MWGUI_WINDOW_PINNABLE_BASE_H -#define MWGUI_WINDOW_PINNABLE_BASE_H - -#include "window_base.hpp" - -namespace MWGui -{ - class WindowManager; - - class WindowPinnableBase: public WindowBase - { - public: - WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); - bool pinned() { return mPinned; } - - private: - void onPinButtonClicked(MyGUI::Widget* _sender); - - protected: - virtual void onPinToggled() = 0; - - MyGUI::Widget* mPinButton; - bool mPinned; - bool mVisible; - }; -} - -#endif From d61ec1063e7c008ea2a1b6a1d90b60d94de85624 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 10 Apr 2013 20:14:10 +0200 Subject: [PATCH 185/198] added script editor --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/columnbase.hpp | 3 +- apps/opencs/model/world/columns.hpp | 25 +++++++ apps/opencs/model/world/data.cpp | 1 + apps/opencs/view/world/scriptsubview.cpp | 92 ++++++++++++++++++++++++ apps/opencs/view/world/scriptsubview.hpp | 62 ++++++++++++++++ apps/opencs/view/world/subviews.cpp | 2 + 7 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 apps/opencs/view/world/scriptsubview.cpp create mode 100644 apps/opencs/view/world/scriptsubview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 76d4280c8f..bd882892fd 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -55,7 +55,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world - table tablesubview + table tablesubview scriptsubview ) opencs_units_noqt (view/world diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 23049164f8..fea618037c 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -35,7 +35,8 @@ namespace CSMWorld Display_Specialisation, Display_Attribute, Display_Boolean, - Display_SpellType + Display_SpellType, + Display_Script }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 6d6d1b1ef0..9242e8a23b 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -723,6 +723,31 @@ namespace CSMWorld return true; } }; + + template + struct ScriptColumn : public Column + { + ScriptColumn() : Column ("Script", ColumnBase::Display_Script, 0) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mScriptText.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mScriptText = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 14aff47e89..9f6b186c0c 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -93,6 +93,7 @@ CSMWorld::Data::Data() mScripts.addColumn (new StringIdColumn); mScripts.addColumn (new RecordStateColumn); mScripts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Script)); + mScripts.addColumn (new ScriptColumn); mRegions.addColumn (new StringIdColumn); mRegions.addColumn (new RecordStateColumn); diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp new file mode 100644 index 0000000000..2fdb44aec3 --- /dev/null +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -0,0 +1,92 @@ + +#include "scriptsubview.hpp" + +#include + +#include + +#include "../../model/doc/document.hpp" +#include "../../model/world/universalid.hpp" +#include "../../model/world/data.hpp" +#include "../../model/world/columnbase.hpp" +#include "../../model/world/commands.hpp" +#include "../../model/world/idtable.hpp" + +CSVWorld::ScriptSubView::ChangeLock::ChangeLock (ScriptSubView& view) : mView (view) +{ + ++mView.mChangeLocked; +} + +CSVWorld::ScriptSubView::ChangeLock::~ChangeLock() +{ + --mView.mChangeLocked; +} + +CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) +: SubView (id), mDocument (document), mColumn (-1), mChangeLocked (0) +{ + setWidget (mEditor = new QTextEdit (this)); + + mEditor->setAcceptRichText (false); + mEditor->setLineWrapMode (QTextEdit::NoWrap); + mEditor->setTabStopWidth (4); + mEditor->setUndoRedoEnabled (false); // we use OpenCS-wide undo/redo instead + + mModel = &dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Scripts)); + + for (int i=0; icolumnCount(); ++i) + if (mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display)== + CSMWorld::ColumnBase::Display_Script) + { + mColumn = i; + break; + } + + if (mColumn==-1) + throw std::logic_error ("Can't find script column"); + + mEditor->setPlainText (mModel->data (mModel->getModelIndex (id.getId(), mColumn)).toString()); + + connect (mEditor, SIGNAL (textChanged()), this, SLOT (textChanged())); + + connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), + this, SLOT (dataChanged (const QModelIndex&, const QModelIndex&))); + +// connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int start, int end)), +// this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int start, int end))); +} + +void CSVWorld::ScriptSubView::setEditLock (bool locked) +{ + mEditor->setReadOnly (locked); +} + +void CSVWorld::ScriptSubView::textChanged() +{ + ChangeLock lock (*this); + + mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel, + mModel->getModelIndex (getUniversalId().getId(), mColumn), mEditor->toPlainText())); +} + +void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) +{ + if (mChangeLocked) + return; + + QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); + + if (index.row()>=topLeft.row() && index.row()<=bottomRight.row() && + index.column()>=topLeft.column() && index.column()<=bottomRight.column()) + { + QTextCursor cursor = mEditor->textCursor(); + mEditor->setPlainText (mModel->data (index).toString()); + mEditor->setTextCursor (cursor); + } +} + +void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end) +{ + +} \ No newline at end of file diff --git a/apps/opencs/view/world/scriptsubview.hpp b/apps/opencs/view/world/scriptsubview.hpp new file mode 100644 index 0000000000..07d87d9476 --- /dev/null +++ b/apps/opencs/view/world/scriptsubview.hpp @@ -0,0 +1,62 @@ +#ifndef CSV_WORLD_SCRIPTSUBVIEW_H +#define CSV_WORLD_SCRIPTSUBVIEW_H + +#include "../doc/subview.hpp" + +class QTextEdit; +class QModelIndex; + +namespace CSMDoc +{ + class Document; +} + +namespace CSMWorld +{ + class IdTable; +} + +namespace CSVWorld +{ + class ScriptSubView : public CSVDoc::SubView + { + Q_OBJECT + + QTextEdit *mEditor; + CSMDoc::Document& mDocument; + CSMWorld::IdTable *mModel; + int mColumn; + int mChangeLocked; + + class ChangeLock + { + ScriptSubView& mView; + + ChangeLock (const ChangeLock&); + ChangeLock& operator= (const ChangeLock&); + + public: + + ChangeLock (ScriptSubView& view); + ~ChangeLock(); + }; + + friend class ChangeLock; + + public: + + ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + + virtual void setEditLock (bool locked); + + private slots: + + void textChanged(); + + void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + + void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index c9ef4df8db..8f7887f3b9 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -5,6 +5,7 @@ #include "tablesubview.hpp" #include "dialoguesubview.hpp" +#include "scriptsubview.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { @@ -32,6 +33,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) for (int i=0; sTableTypes[i]!=CSMWorld::UniversalId::Type_None; ++i) manager.add (sTableTypes[i], new CSVDoc::SubViewFactoryWithCreateFlag (true)); + manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory); // manager.add (CSMWorld::UniversalId::Type_Global, // new CSVDoc::SubViewFactoryWithCreateFlag (true)); From f7383905b7ca21a6aae6dd438ce0cc948eedf2be Mon Sep 17 00:00:00 2001 From: Britt Mathis Date: Wed, 10 Apr 2013 14:46:21 -0400 Subject: [PATCH 186/198] Finally eliminated calls to MWBase::WindowManager in constructors --- apps/openmw/mwgui/alchemywindow.cpp | 4 +- apps/openmw/mwgui/alchemywindow.hpp | 2 +- apps/openmw/mwgui/birth.cpp | 4 +- apps/openmw/mwgui/birth.hpp | 2 +- apps/openmw/mwgui/bookwindow.cpp | 4 +- apps/openmw/mwgui/bookwindow.hpp | 2 +- apps/openmw/mwgui/charactercreation.cpp | 197 +++++++++++----------- apps/openmw/mwgui/charactercreation.hpp | 4 +- apps/openmw/mwgui/class.cpp | 44 ++--- apps/openmw/mwgui/class.hpp | 18 +- apps/openmw/mwgui/companionwindow.cpp | 4 +- apps/openmw/mwgui/companionwindow.hpp | 2 +- apps/openmw/mwgui/confirmationdialog.cpp | 4 +- apps/openmw/mwgui/confirmationdialog.hpp | 2 +- apps/openmw/mwgui/container.cpp | 4 +- apps/openmw/mwgui/container.hpp | 2 +- apps/openmw/mwgui/countdialog.cpp | 4 +- apps/openmw/mwgui/countdialog.hpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 10 +- apps/openmw/mwgui/dialogue.hpp | 4 +- apps/openmw/mwgui/enchantingdialog.cpp | 10 +- apps/openmw/mwgui/enchantingdialog.hpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 4 +- apps/openmw/mwgui/inventorywindow.hpp | 2 +- apps/openmw/mwgui/itemselection.cpp | 4 +- apps/openmw/mwgui/itemselection.hpp | 2 +- apps/openmw/mwgui/journalwindow.cpp | 4 +- apps/openmw/mwgui/journalwindow.hpp | 2 +- apps/openmw/mwgui/levelupdialog.cpp | 4 +- apps/openmw/mwgui/levelupdialog.hpp | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 4 +- apps/openmw/mwgui/loadingscreen.hpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 4 +- apps/openmw/mwgui/mapwindow.hpp | 2 +- apps/openmw/mwgui/merchantrepair.cpp | 4 +- apps/openmw/mwgui/merchantrepair.hpp | 2 +- apps/openmw/mwgui/messagebox.cpp | 4 +- apps/openmw/mwgui/messagebox.hpp | 2 +- apps/openmw/mwgui/quickkeysmenu.cpp | 18 +- apps/openmw/mwgui/quickkeysmenu.hpp | 6 +- apps/openmw/mwgui/race.cpp | 4 +- apps/openmw/mwgui/race.hpp | 2 +- apps/openmw/mwgui/repair.cpp | 4 +- apps/openmw/mwgui/repair.hpp | 2 +- apps/openmw/mwgui/review.cpp | 4 +- apps/openmw/mwgui/review.hpp | 2 +- apps/openmw/mwgui/scrollwindow.cpp | 4 +- apps/openmw/mwgui/scrollwindow.hpp | 2 +- apps/openmw/mwgui/settingswindow.cpp | 4 +- apps/openmw/mwgui/settingswindow.hpp | 2 +- apps/openmw/mwgui/spellbuyingwindow.cpp | 4 +- apps/openmw/mwgui/spellbuyingwindow.hpp | 2 +- apps/openmw/mwgui/spellcreationdialog.cpp | 18 +- apps/openmw/mwgui/spellcreationdialog.hpp | 6 +- apps/openmw/mwgui/spellwindow.cpp | 4 +- apps/openmw/mwgui/spellwindow.hpp | 2 +- apps/openmw/mwgui/statswindow.cpp | 4 +- apps/openmw/mwgui/statswindow.hpp | 2 +- apps/openmw/mwgui/textinput.cpp | 4 +- apps/openmw/mwgui/textinput.hpp | 2 +- apps/openmw/mwgui/tooltips.cpp | 2 +- apps/openmw/mwgui/tooltips.hpp | 2 +- apps/openmw/mwgui/tradewindow.cpp | 4 +- apps/openmw/mwgui/tradewindow.hpp | 2 +- apps/openmw/mwgui/trainingwindow.cpp | 4 +- apps/openmw/mwgui/trainingwindow.hpp | 2 +- apps/openmw/mwgui/travelwindow.cpp | 4 +- apps/openmw/mwgui/travelwindow.hpp | 2 +- apps/openmw/mwgui/waitdialog.cpp | 10 +- apps/openmw/mwgui/waitdialog.hpp | 4 +- apps/openmw/mwgui/widgets.cpp | 14 +- apps/openmw/mwgui/widgets.hpp | 4 - apps/openmw/mwgui/windowbase.cpp | 6 +- apps/openmw/mwgui/windowbase.hpp | 4 +- apps/openmw/mwgui/windowmanagerimp.cpp | 58 +++---- apps/openmw/mwgui/windowpinnablebase.cpp | 4 +- apps/openmw/mwgui/windowpinnablebase.hpp | 2 +- 77 files changed, 300 insertions(+), 309 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 1ae534797d..a6121c234c 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -26,8 +26,8 @@ namespace namespace MWGui { - AlchemyWindow::AlchemyWindow(MWBase::WindowManager& parWindowManager) - : WindowBase("openmw_alchemy_window.layout", parWindowManager) + AlchemyWindow::AlchemyWindow() + : WindowBase("openmw_alchemy_window.layout") , ContainerBase(0), mApparatus (4), mIngredients (4) { getWidget(mCreateButton, "CreateButton"); diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 933975f0c8..c61d2f92b3 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -14,7 +14,7 @@ namespace MWGui class AlchemyWindow : public WindowBase, public ContainerBase { public: - AlchemyWindow(MWBase::WindowManager& parWindowManager); + AlchemyWindow(); virtual void open(); diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index d899ab00b1..133bbd32fb 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -24,8 +24,8 @@ bool sortBirthSigns(const std::pair& left, c } -BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_birth.layout", parWindowManager) +BirthDialog::BirthDialog() + : WindowModal("openmw_chargen_birth.layout") { // Centre dialog center(); diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index 033501f22f..cc958ddcaa 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -13,7 +13,7 @@ namespace MWGui class BirthDialog : public WindowModal { public: - BirthDialog(MWBase::WindowManager& parWindowManager); + BirthDialog(); enum Gender { diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index d57953d07d..ce74c48593 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -14,8 +14,8 @@ using namespace MWGui; -BookWindow::BookWindow (MWBase::WindowManager& parWindowManager) - : WindowBase("openmw_book.layout", parWindowManager) +BookWindow::BookWindow () + : WindowBase("openmw_book.layout") , mTakeButtonShow(true) , mTakeButtonAllowed(true) { diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index c2a9dca893..9123969e09 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -12,7 +12,7 @@ namespace MWGui class BookWindow : public WindowBase { public: - BookWindow(MWBase::WindowManager& parWindowManager); + BookWindow(); void open(MWWorld::Ptr book); void setTakeButtonShow(bool show); diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 27de7cee98..0dd6502c6c 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -47,7 +47,7 @@ namespace using namespace MWGui; -CharacterCreation::CharacterCreation(MWBase::WindowManager* _wm) +CharacterCreation::CharacterCreation() : mNameDialog(0) , mRaceDialog(0) , mClassChoiceDialog(0) @@ -58,7 +58,6 @@ CharacterCreation::CharacterCreation(MWBase::WindowManager* _wm) , mBirthSignDialog(0) , mReviewDialog(0) , mGenerateClassStep(0) - , mWM(_wm) { mCreationStage = CSE_NotStarted; } @@ -118,10 +117,10 @@ void CharacterCreation::spawnDialog(const char id) switch (id) { case GM_Name: - mWM->removeDialog(mNameDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog); mNameDialog = 0; - mNameDialog = new TextInputDialog(*mWM); - mNameDialog->setTextLabel(mWM->getGameSettingString("sName", "Name")); + mNameDialog = new TextInputDialog(); + mNameDialog->setTextLabel(MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "Name")); mNameDialog->setTextInput(mPlayerName); mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen); mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone); @@ -129,9 +128,9 @@ void CharacterCreation::spawnDialog(const char id) break; case GM_Race: - mWM->removeDialog(mRaceDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog); mRaceDialog = 0; - mRaceDialog = new RaceDialog(*mWM); + mRaceDialog = new RaceDialog(); mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen); mRaceDialog->setRaceId(mPlayerRaceId); mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone); @@ -142,9 +141,9 @@ void CharacterCreation::spawnDialog(const char id) break; case GM_Class: - mWM->removeDialog(mClassChoiceDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog); mClassChoiceDialog = 0; - mClassChoiceDialog = new ClassChoiceDialog(*mWM); + mClassChoiceDialog = new ClassChoiceDialog(); mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice); mClassChoiceDialog->setVisible(true); if (mCreationStage < CSE_RaceChosen) @@ -152,9 +151,9 @@ void CharacterCreation::spawnDialog(const char id) break; case GM_ClassPick: - mWM->removeDialog(mPickClassDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog); mPickClassDialog = 0; - mPickClassDialog = new PickClassDialog(*mWM); + mPickClassDialog = new PickClassDialog(); mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); mPickClassDialog->setClassId(mPlayerClass.mName); mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone); @@ -165,9 +164,9 @@ void CharacterCreation::spawnDialog(const char id) break; case GM_Birth: - mWM->removeDialog(mBirthSignDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog); mBirthSignDialog = 0; - mBirthSignDialog = new BirthDialog(*mWM); + mBirthSignDialog = new BirthDialog(); mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen); mBirthSignDialog->setBirthId(mPlayerBirthSignId); mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone); @@ -178,9 +177,9 @@ void CharacterCreation::spawnDialog(const char id) break; case GM_ClassCreate: - mWM->removeDialog(mCreateClassDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); mCreateClassDialog = 0; - mCreateClassDialog = new CreateClassDialog(*mWM); + mCreateClassDialog = new CreateClassDialog(); mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone); mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack); @@ -199,9 +198,9 @@ void CharacterCreation::spawnDialog(const char id) mCreationStage = CSE_RaceChosen; break; case GM_Review: - mWM->removeDialog(mReviewDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); mReviewDialog = 0; - mReviewDialog = new ReviewDialog(*mWM); + mReviewDialog = new ReviewDialog(); mReviewDialog->setPlayerName(mPlayerName); mReviewDialog->setRace(mPlayerRaceId); mReviewDialog->setClass(mPlayerClass); @@ -212,7 +211,7 @@ void CharacterCreation::spawnDialog(const char id) mReviewDialog->setFatigue(mPlayerFatigue); { - std::map > attributes = mWM->getPlayerAttributeValues(); + std::map > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues(); for (std::map >::iterator it = attributes.begin(); it != attributes.end(); ++it) { @@ -221,13 +220,13 @@ void CharacterCreation::spawnDialog(const char id) } { - std::map > skills = mWM->getPlayerSkillValues(); + std::map > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues(); for (std::map >::iterator it = skills.begin(); it != skills.end(); ++it) { mReviewDialog->setSkillValue(static_cast (it->first), it->second); } - mReviewDialog->configureSkills(mWM->getPlayerMajorSkills(), mWM->getPlayerMinorSkills()); + mReviewDialog->configureSkills(MWBase::Environment::get().getWindowManager()->getPlayerMajorSkills(), MWBase::Environment::get().getWindowManager()->getPlayerMinorSkills()); } mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); @@ -257,41 +256,41 @@ void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat& void CharacterCreation::onReviewDialogDone(WindowBase* parWindow) { - mWM->removeDialog(mReviewDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); mReviewDialog = 0; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } void CharacterCreation::onReviewDialogBack() { - mWM->removeDialog(mReviewDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); mReviewDialog = 0; - mWM->pushGuiMode(GM_Birth); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); } void CharacterCreation::onReviewActivateDialog(int parDialog) { - mWM->removeDialog(mReviewDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); mReviewDialog = 0; mCreationStage = CSE_ReviewNext; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); switch(parDialog) { case ReviewDialog::NAME_DIALOG: - mWM->pushGuiMode(GM_Name); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name); break; case ReviewDialog::RACE_DIALOG: - mWM->pushGuiMode(GM_Race); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race); break; case ReviewDialog::CLASS_DIALOG: - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); break; case ReviewDialog::BIRTHSIGN_DIALOG: - mWM->pushGuiMode(GM_Birth); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); }; } @@ -308,27 +307,27 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) if (klass) { mPlayerClass = *klass; - mWM->setPlayerClass(mPlayerClass); + MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass); } - mWM->removeDialog(mPickClassDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog); mPickClassDialog = 0; } //TODO This bit gets repeated a few times; wrap it in a function if (mCreationStage == CSE_ReviewNext) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Review); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); } else if (mCreationStage >= CSE_ClassChosen) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Birth); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); } else { mCreationStage = CSE_ClassChosen; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } @@ -339,34 +338,34 @@ void CharacterCreation::onPickClassDialogBack() const std::string classId = mPickClassDialog->getClassId(); if (!classId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId); - mWM->removeDialog(mPickClassDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog); mPickClassDialog = 0; } - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); } void CharacterCreation::onClassChoice(int _index) { - mWM->removeDialog(mClassChoiceDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog); mClassChoiceDialog = 0; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); switch(_index) { case ClassChoiceDialog::Class_Generate: - mWM->pushGuiMode(GM_ClassGenerate); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_ClassGenerate); break; case ClassChoiceDialog::Class_Pick: - mWM->pushGuiMode(GM_ClassPick); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_ClassPick); break; case ClassChoiceDialog::Class_Create: - mWM->pushGuiMode(GM_ClassCreate); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_ClassCreate); break; case ClassChoiceDialog::Class_Back: - mWM->pushGuiMode(GM_Race); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race); break; }; @@ -377,26 +376,26 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow) if (mNameDialog) { mPlayerName = mNameDialog->getTextInput(); - mWM->setValue("name", mPlayerName); + MWBase::Environment::get().getWindowManager()->setValue("name", mPlayerName); MWBase::Environment::get().getMechanicsManager()->setPlayerName(mPlayerName); - mWM->removeDialog(mNameDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog); mNameDialog = 0; } if (mCreationStage == CSE_ReviewNext) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Review); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); } else if (mCreationStage >= CSE_NameChosen) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Race); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race); } else { mCreationStage = CSE_NameChosen; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } @@ -414,12 +413,12 @@ void CharacterCreation::onRaceDialogBack() data.mHair ); } - mWM->removeDialog(mRaceDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog); mRaceDialog = 0; } - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Name); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name); } void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) @@ -436,26 +435,26 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) data.mHair ); } - mWM->getInventoryWindow()->rebuildAvatar(); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar(); - mWM->removeDialog(mRaceDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog); mRaceDialog = 0; } if (mCreationStage == CSE_ReviewNext) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Review); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); } else if (mCreationStage >= CSE_RaceChosen) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); } else { mCreationStage = CSE_RaceChosen; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } @@ -466,19 +465,19 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) mPlayerBirthSignId = mBirthSignDialog->getBirthId(); if (!mPlayerBirthSignId.empty()) MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId); - mWM->removeDialog(mBirthSignDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog); mBirthSignDialog = 0; } if (mCreationStage >= CSE_BirthSignChosen) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Review); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); } else { mCreationStage = CSE_BirthSignChosen; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } @@ -487,12 +486,12 @@ void CharacterCreation::onBirthSignDialogBack() if (mBirthSignDialog) { MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId()); - mWM->removeDialog(mBirthSignDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog); mBirthSignDialog = 0; } - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); } void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) @@ -522,49 +521,49 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) MWBase::Environment::get().getMechanicsManager()->setPlayerClass(klass); mPlayerClass = klass; - mWM->setPlayerClass(klass); + MWBase::Environment::get().getWindowManager()->setPlayerClass(klass); - mWM->removeDialog(mCreateClassDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); mCreateClassDialog = 0; } if (mCreationStage == CSE_ReviewNext) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Review); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); } else if (mCreationStage >= CSE_ClassChosen) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Birth); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); } else { mCreationStage = CSE_ClassChosen; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } void CharacterCreation::onCreateClassDialogBack() { - mWM->removeDialog(mCreateClassDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); mCreateClassDialog = 0; - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); } void CharacterCreation::onClassQuestionChosen(int _index) { MWBase::Environment::get().getSoundManager()->stopSay(); - mWM->removeDialog(mGenerateClassQuestionDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog); mGenerateClassQuestionDialog = 0; if (_index < 0 || _index >= 3) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); return; } @@ -637,10 +636,10 @@ void CharacterCreation::showClassQuestionDialog() } } - mWM->removeDialog(mGenerateClassResultDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog); mGenerateClassResultDialog = 0; - mGenerateClassResultDialog = new GenerateClassResultDialog(*mWM); + mGenerateClassResultDialog = new GenerateClassResultDialog(); mGenerateClassResultDialog->setClassId(mGenerateClass); mGenerateClassResultDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassBack); mGenerateClassResultDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onGenerateClassDone); @@ -650,15 +649,15 @@ void CharacterCreation::showClassQuestionDialog() if (mGenerateClassStep > 10) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); return; } - mWM->removeDialog(mGenerateClassQuestionDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog); mGenerateClassQuestionDialog = 0; - mGenerateClassQuestionDialog = new InfoBoxDialog(*mWM); + mGenerateClassQuestionDialog = new InfoBoxDialog(); InfoBoxDialog::ButtonList buttons; mGenerateClassQuestionDialog->setText(sGenerateClassSteps(mGenerateClassStep).mText); @@ -674,18 +673,18 @@ void CharacterCreation::showClassQuestionDialog() void CharacterCreation::onGenerateClassBack() { - mWM->removeDialog(mGenerateClassResultDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog); mGenerateClassResultDialog = 0; MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Class); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); } void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) { - mWM->removeDialog(mGenerateClassResultDialog); + MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog); mGenerateClassResultDialog = 0; MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); @@ -694,22 +693,22 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) MWBase::Environment::get().getWorld()->getStore().get().find(mGenerateClass); mPlayerClass = *klass; - mWM->setPlayerClass(mPlayerClass); + MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass); if (mCreationStage == CSE_ReviewNext) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Review); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); } else if (mCreationStage >= CSE_ClassChosen) { - mWM->popGuiMode(); - mWM->pushGuiMode(GM_Birth); + MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); } else { mCreationStage = CSE_ClassChosen; - mWM->popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } } diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index 9653aeede5..fed77e889f 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -29,7 +29,7 @@ namespace MWGui public: typedef std::vector SkillList; - CharacterCreation(MWBase::WindowManager* _wm); + CharacterCreation(); ~CharacterCreation(); //Show a dialog @@ -58,8 +58,6 @@ namespace MWGui BirthDialog* mBirthSignDialog; ReviewDialog* mReviewDialog; - MWBase::WindowManager* mWM; - //Player data std::string mPlayerName; std::string mPlayerRaceId; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 8c352d5080..6edad9e83b 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -20,8 +20,8 @@ using namespace MWGui; /* GenerateClassResultDialog */ -GenerateClassResultDialog::GenerateClassResultDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_generate_class_result.layout", parWindowManager) +GenerateClassResultDialog::GenerateClassResultDialog() + : WindowModal("openmw_chargen_generate_class_result.layout") { // Centre dialog center(); @@ -67,8 +67,8 @@ void GenerateClassResultDialog::onBackClicked(MyGUI::Widget* _sender) /* PickClassDialog */ -PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_class.layout", parWindowManager) +PickClassDialog::PickClassDialog() + : WindowModal("openmw_chargen_class.layout") { // Centre dialog center(); @@ -272,8 +272,8 @@ void InfoBoxDialog::layoutVertically(MyGUI::Widget* widget, int margin) widget->setSize(width, pos); } -InfoBoxDialog::InfoBoxDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_infobox.layout", parWindowManager) +InfoBoxDialog::InfoBoxDialog() + : WindowModal("openmw_infobox.layout") , mCurrentButton(-1) { getWidget(mTextBox, "TextBox"); @@ -356,8 +356,8 @@ void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender) /* ClassChoiceDialog */ -ClassChoiceDialog::ClassChoiceDialog(MWBase::WindowManager& parWindowManager) - : InfoBoxDialog(parWindowManager) +ClassChoiceDialog::ClassChoiceDialog() + : InfoBoxDialog() { setText(""); ButtonList buttons; @@ -370,8 +370,8 @@ ClassChoiceDialog::ClassChoiceDialog(MWBase::WindowManager& parWindowManager) /* CreateClassDialog */ -CreateClassDialog::CreateClassDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_create_class.layout", parWindowManager) +CreateClassDialog::CreateClassDialog() + : WindowModal("openmw_chargen_create_class.layout") , mSpecDialog(NULL) , mAttribDialog(NULL) , mSkillDialog(NULL) @@ -540,7 +540,7 @@ void CreateClassDialog::onDialogCancel() void CreateClassDialog::onSpecializationClicked(MyGUI::Widget* _sender) { delete mSpecDialog; - mSpecDialog = new SelectSpecializationDialog(*MWBase::Environment::get().getWindowManager()); + mSpecDialog = new SelectSpecializationDialog(); mSpecDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mSpecDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected); mSpecDialog->setVisible(true); @@ -571,7 +571,7 @@ void CreateClassDialog::setSpecialization(int id) void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) { delete mAttribDialog; - mAttribDialog = new SelectAttributeDialog(*MWBase::Environment::get().getWindowManager()); + mAttribDialog = new SelectAttributeDialog(); mAffectedAttribute = _sender; mAttribDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mAttribDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected); @@ -601,7 +601,7 @@ void CreateClassDialog::onAttributeSelected() void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) { delete mSkillDialog; - mSkillDialog = new SelectSkillDialog(*MWBase::Environment::get().getWindowManager()); + mSkillDialog = new SelectSkillDialog(); mAffectedSkill = _sender; mSkillDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mSkillDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected); @@ -633,7 +633,7 @@ void CreateClassDialog::onSkillSelected() void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) { - mDescDialog = new DescriptionDialog(*MWBase::Environment::get().getWindowManager()); + mDescDialog = new DescriptionDialog(); mDescDialog->setTextInput(mDescription); mDescDialog->eventDone += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered); mDescDialog->setVisible(true); @@ -660,8 +660,8 @@ void CreateClassDialog::onBackClicked(MyGUI::Widget* _sender) /* SelectSpecializationDialog */ -SelectSpecializationDialog::SelectSpecializationDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_select_specialization.layout", parWindowManager) +SelectSpecializationDialog::SelectSpecializationDialog() + : WindowModal("openmw_chargen_select_specialization.layout") { // Centre dialog center(); @@ -720,8 +720,8 @@ void SelectSpecializationDialog::onCancelClicked(MyGUI::Widget* _sender) /* SelectAttributeDialog */ -SelectAttributeDialog::SelectAttributeDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_select_attribute.layout", parWindowManager) +SelectAttributeDialog::SelectAttributeDialog() + : WindowModal("openmw_chargen_select_attribute.layout") { // Centre dialog center(); @@ -766,8 +766,8 @@ void SelectAttributeDialog::onCancelClicked(MyGUI::Widget* _sender) /* SelectSkillDialog */ -SelectSkillDialog::SelectSkillDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_select_skill.layout", parWindowManager) +SelectSkillDialog::SelectSkillDialog() + : WindowModal("openmw_chargen_select_skill.layout") { // Centre dialog center(); @@ -856,8 +856,8 @@ void SelectSkillDialog::onCancelClicked(MyGUI::Widget* _sender) /* DescriptionDialog */ -DescriptionDialog::DescriptionDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_class_description.layout", parWindowManager) +DescriptionDialog::DescriptionDialog() + : WindowModal("openmw_chargen_class_description.layout") { // Centre dialog center(); diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 11da1a7913..15fc89658f 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -15,7 +15,7 @@ namespace MWGui class InfoBoxDialog : public WindowModal { public: - InfoBoxDialog(MWBase::WindowManager& parWindowManager); + InfoBoxDialog(); typedef std::vector ButtonList; @@ -60,13 +60,13 @@ namespace MWGui Class_Create = 2, Class_Back = 3 }; - ClassChoiceDialog(MWBase::WindowManager& parWindowManager); + ClassChoiceDialog(); }; class GenerateClassResultDialog : public WindowModal { public: - GenerateClassResultDialog(MWBase::WindowManager& parWindowManager); + GenerateClassResultDialog(); std::string getClassId() const; void setClassId(const std::string &classId); @@ -93,7 +93,7 @@ namespace MWGui class PickClassDialog : public WindowModal { public: - PickClassDialog(MWBase::WindowManager& parWindowManager); + PickClassDialog(); const std::string &getClassId() const { return mCurrentClassId; } void setClassId(const std::string &classId); @@ -132,7 +132,7 @@ namespace MWGui class SelectSpecializationDialog : public WindowModal { public: - SelectSpecializationDialog(MWBase::WindowManager& parWindowManager); + SelectSpecializationDialog(); ~SelectSpecializationDialog(); ESM::Class::Specialization getSpecializationId() const { return mSpecializationId; } @@ -163,7 +163,7 @@ namespace MWGui class SelectAttributeDialog : public WindowModal { public: - SelectAttributeDialog(MWBase::WindowManager& parWindowManager); + SelectAttributeDialog(); ~SelectAttributeDialog(); ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; } @@ -192,7 +192,7 @@ namespace MWGui class SelectSkillDialog : public WindowModal { public: - SelectSkillDialog(MWBase::WindowManager& parWindowManager); + SelectSkillDialog(); ~SelectSkillDialog(); ESM::Skill::SkillEnum getSkillId() const { return mSkillId; } @@ -225,7 +225,7 @@ namespace MWGui class DescriptionDialog : public WindowModal { public: - DescriptionDialog(MWBase::WindowManager& parWindowManager); + DescriptionDialog(); ~DescriptionDialog(); std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; } @@ -241,7 +241,7 @@ namespace MWGui class CreateClassDialog : public WindowModal { public: - CreateClassDialog(MWBase::WindowManager& parWindowManager); + CreateClassDialog(); virtual ~CreateClassDialog(); std::string getName() const; diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 643cdf4c65..0a20c471ab 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -13,9 +13,9 @@ namespace MWGui { -CompanionWindow::CompanionWindow(MWBase::WindowManager &parWindowManager, DragAndDrop *dragAndDrop, MessageBoxManager* manager) +CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* manager) : ContainerBase(dragAndDrop) - , WindowBase("openmw_companion_window.layout", parWindowManager) + , WindowBase("openmw_companion_window.layout") , mMessageBoxManager(manager) { MyGUI::ScrollView* itemView; diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 1b64a34d50..073a77a916 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -11,7 +11,7 @@ namespace MWGui class CompanionWindow : public ContainerBase, public WindowBase { public: - CompanionWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop, MessageBoxManager* manager); + CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager); virtual ~CompanionWindow() {} void open(MWWorld::Ptr npc); diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp index 31f4989e07..904468f886 100644 --- a/apps/openmw/mwgui/confirmationdialog.cpp +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -7,8 +7,8 @@ namespace MWGui { - ConfirmationDialog::ConfirmationDialog(MWBase::WindowManager& parWindowManager) : - WindowModal("openmw_confirmation_dialog.layout", parWindowManager) + ConfirmationDialog::ConfirmationDialog() : + WindowModal("openmw_confirmation_dialog.layout") { getWidget(mMessage, "Message"); getWidget(mOkButton, "OkButton"); diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index a925cad550..47b256017f 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -8,7 +8,7 @@ namespace MWGui class ConfirmationDialog : public WindowModal { public: - ConfirmationDialog(MWBase::WindowManager& parWindowManager); + ConfirmationDialog(); void open(const std::string& message); typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index f7846e70ec..8ee4754a32 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -649,9 +649,9 @@ MWWorld::ContainerStore& ContainerBase::getContainerStore() // ------------------------------------------------------------------------------------------------ -ContainerWindow::ContainerWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop) +ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) : ContainerBase(dragAndDrop) - , WindowBase("openmw_container_window.layout", parWindowManager) + , WindowBase("openmw_container_window.layout") { getWidget(mDisposeCorpseButton, "DisposeCorpseButton"); getWidget(mTakeButton, "TakeButton"); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 7a3e804e5d..521ac8cc35 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -134,7 +134,7 @@ namespace MWGui class ContainerWindow : public ContainerBase, public WindowBase { public: - ContainerWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop); + ContainerWindow(DragAndDrop* dragAndDrop); virtual ~ContainerWindow(); diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 61c3c358a2..d017cc1986 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -7,8 +7,8 @@ namespace MWGui { - CountDialog::CountDialog(MWBase::WindowManager& parWindowManager) : - WindowModal("openmw_count_window.layout", parWindowManager) + CountDialog::CountDialog() : + WindowModal("openmw_count_window.layout") { getWidget(mSlider, "CountSlider"); getWidget(mItemEdit, "ItemEdit"); diff --git a/apps/openmw/mwgui/countdialog.hpp b/apps/openmw/mwgui/countdialog.hpp index d5155839d8..9d6d8b263f 100644 --- a/apps/openmw/mwgui/countdialog.hpp +++ b/apps/openmw/mwgui/countdialog.hpp @@ -8,7 +8,7 @@ namespace MWGui class CountDialog : public WindowModal { public: - CountDialog(MWBase::WindowManager& parWindowManager); + CountDialog(); void open(const std::string& item, const std::string& message, const int maxCount); typedef MyGUI::delegates::CMultiDelegate2 EventHandle_WidgetInt; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 0939da1b17..f3c11752e8 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -55,8 +55,8 @@ bool sortByLength (const std::string& left, const std::string& right) -PersuasionDialog::PersuasionDialog(MWBase::WindowManager &parWindowManager) - : WindowModal("openmw_persuasion_dialog.layout", parWindowManager) +PersuasionDialog::PersuasionDialog() + : WindowModal("openmw_persuasion_dialog.layout") { getWidget(mCancelButton, "CancelButton"); getWidget(mAdmireButton, "AdmireButton"); @@ -124,9 +124,9 @@ void PersuasionDialog::open() // -------------------------------------------------------------------------------------------------- -DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager) - : WindowBase("openmw_dialogue_window.layout", parWindowManager) - , mPersuasionDialog(parWindowManager) +DialogueWindow::DialogueWindow() + : WindowBase("openmw_dialogue_window.layout") + , mPersuasionDialog() , mEnabled(false) , mServices(0) { diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index e78856c951..a1bbee02c7 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -29,7 +29,7 @@ namespace MWGui class PersuasionDialog : public WindowModal { public: - PersuasionDialog(MWBase::WindowManager& parWindowManager); + PersuasionDialog(); virtual void open(); @@ -50,7 +50,7 @@ namespace MWGui class DialogueWindow: public WindowBase, public ReferenceInterface { public: - DialogueWindow(MWBase::WindowManager& parWindowManager); + DialogueWindow(); // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 02d847d1a8..2ae98f358f 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -15,9 +15,9 @@ namespace MWGui { - EnchantingDialog::EnchantingDialog(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_enchanting_dialog.layout", parWindowManager) - , EffectEditorBase(parWindowManager) + EnchantingDialog::EnchantingDialog() + : WindowBase("openmw_enchanting_dialog.layout") + , EffectEditorBase() , mItemSelectionDialog(NULL) { getWidget(mName, "NameEdit"); @@ -139,7 +139,7 @@ namespace MWGui { delete mItemSelectionDialog; mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}", - ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic, *MWBase::Environment::get().getWindowManager()); + ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); mItemSelectionDialog->setVisible(true); @@ -227,7 +227,7 @@ namespace MWGui { delete mItemSelectionDialog; mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}", - ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones, *MWBase::Environment::get().getWindowManager()); + ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); mItemSelectionDialog->setVisible(true); diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 822199ac67..c727a09749 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -17,7 +17,7 @@ namespace MWGui class EnchantingDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase { public: - EnchantingDialog(MWBase::WindowManager& parWindowManager); + EnchantingDialog(); virtual ~EnchantingDialog(); virtual void open(); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 393f03a541..dc7ef77ff8 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -30,9 +30,9 @@ namespace MWGui { - InventoryWindow::InventoryWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop) + InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop) : ContainerBase(dragAndDrop) - , WindowPinnableBase("openmw_inventory_window.layout", parWindowManager) + , WindowPinnableBase("openmw_inventory_window.layout") , mTrading(false) , mLastXSize(0) , mLastYSize(0) diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 61ee17ef93..a4ed89d401 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -12,7 +12,7 @@ namespace MWGui class InventoryWindow : public ContainerBase, public WindowPinnableBase { public: - InventoryWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop); + InventoryWindow(DragAndDrop* dragAndDrop); virtual void open(); diff --git a/apps/openmw/mwgui/itemselection.cpp b/apps/openmw/mwgui/itemselection.cpp index 4b8adcef4f..ed8b47b086 100644 --- a/apps/openmw/mwgui/itemselection.cpp +++ b/apps/openmw/mwgui/itemselection.cpp @@ -3,9 +3,9 @@ namespace MWGui { - ItemSelectionDialog::ItemSelectionDialog(const std::string &label, int filter, MWBase::WindowManager& parWindowManager) + ItemSelectionDialog::ItemSelectionDialog(const std::string &label, int filter) : ContainerBase(NULL) - , WindowModal("openmw_itemselection_dialog.layout", parWindowManager) + , WindowModal("openmw_itemselection_dialog.layout") { mFilter = filter; diff --git a/apps/openmw/mwgui/itemselection.hpp b/apps/openmw/mwgui/itemselection.hpp index 733daa91ae..3e812d26c5 100644 --- a/apps/openmw/mwgui/itemselection.hpp +++ b/apps/openmw/mwgui/itemselection.hpp @@ -8,7 +8,7 @@ namespace MWGui class ItemSelectionDialog : public ContainerBase, public WindowModal { public: - ItemSelectionDialog(const std::string& label, int filter, MWBase::WindowManager& parWindowManager); + ItemSelectionDialog(const std::string& label, int filter); typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Item; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index ba39b01012..a3198d6bcd 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -81,8 +81,8 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) } -MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) - : WindowBase("openmw_journal.layout", parWindowManager) +MWGui::JournalWindow::JournalWindow () + : WindowBase("openmw_journal.layout") , mPageNumber(0) { mMainWidget->setVisible(false); diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 73a2dca2ec..7670b65f55 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -14,7 +14,7 @@ namespace MWGui class JournalWindow : public WindowBase { public: - JournalWindow(MWBase::WindowManager& parWindowManager); + JournalWindow(); virtual void open(); virtual void close(); diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index dcecdccc1b..fc1317e908 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -18,8 +18,8 @@ namespace MWGui { - LevelupDialog::LevelupDialog(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_levelup_dialog.layout", parWindowManager) + LevelupDialog::LevelupDialog() + : WindowBase("openmw_levelup_dialog.layout") { getWidget(mOkButton, "OkButton"); getWidget(mClassImage, "ClassImage"); diff --git a/apps/openmw/mwgui/levelupdialog.hpp b/apps/openmw/mwgui/levelupdialog.hpp index a54948e2a0..69afbf0897 100644 --- a/apps/openmw/mwgui/levelupdialog.hpp +++ b/apps/openmw/mwgui/levelupdialog.hpp @@ -9,7 +9,7 @@ namespace MWGui class LevelupDialog : public WindowBase { public: - LevelupDialog(MWBase::WindowManager& parWindowManager); + LevelupDialog(); virtual void open(); diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 3066705124..858c3f36ec 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -23,10 +23,10 @@ namespace MWGui { - LoadingScreen::LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw, MWBase::WindowManager& parWindowManager) + LoadingScreen::LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw) : mSceneMgr(sceneMgr) , mWindow(rw) - , WindowBase("openmw_loading_screen.layout", parWindowManager) + , WindowBase("openmw_loading_screen.layout") , mLoadingOn(false) , mLastRenderTime(0.f) , mLastWallpaperChangeTime(0.f) diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index cb33975ae3..12e6504bca 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -11,7 +11,7 @@ namespace MWGui class LoadingScreen : public WindowBase { public: - LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw, MWBase::WindowManager& parWindowManager); + LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw); virtual ~LoadingScreen(); void setLoadingProgress (const std::string& stage, int depth, int current, int total); diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 029974d2b3..17834be937 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -262,8 +262,8 @@ void LocalMapBase::setPlayerDir(const float x, const float y) // ------------------------------------------------------------------------------------------ -MapWindow::MapWindow(MWBase::WindowManager& parWindowManager, const std::string& cacheDir) - : MWGui::WindowPinnableBase("openmw_map_window.layout", parWindowManager) +MapWindow::MapWindow(const std::string& cacheDir) + : MWGui::WindowPinnableBase("openmw_map_window.layout") , mGlobal(false) { setCoord(500,0,320,300); diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 329854e182..18c81a0608 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -65,7 +65,7 @@ namespace MWGui class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase { public: - MapWindow(MWBase::WindowManager& parWindowManager, const std::string& cacheDir); + MapWindow(const std::string& cacheDir); virtual ~MapWindow(); void setCellName(const std::string& cellName); diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index f24d2d4177..53148cb3f0 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -19,8 +19,8 @@ namespace MWGui { -MerchantRepair::MerchantRepair(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_merchantrepair.layout", parWindowManager) +MerchantRepair::MerchantRepair() + : WindowBase("openmw_merchantrepair.layout") { getWidget(mList, "RepairView"); getWidget(mOkButton, "OkButton"); diff --git a/apps/openmw/mwgui/merchantrepair.hpp b/apps/openmw/mwgui/merchantrepair.hpp index 2cd6c486a9..4cb39fe012 100644 --- a/apps/openmw/mwgui/merchantrepair.hpp +++ b/apps/openmw/mwgui/merchantrepair.hpp @@ -12,7 +12,7 @@ namespace MWGui class MerchantRepair : public WindowBase { public: - MerchantRepair(MWBase::WindowManager &parWindowManager); + MerchantRepair(); virtual void open(); diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 58bbc3c3ab..8e53380bde 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -7,7 +7,7 @@ using namespace MWGui; -MessageBoxManager::MessageBoxManager (MWBase::WindowManager* windowManager) +MessageBoxManager::MessageBoxManager () { // defines mMessageBoxSpeed = 0.1; @@ -212,7 +212,7 @@ int MessageBox::getHeight () InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector& buttons) - : WindowModal("openmw_interactive_messagebox.layout", *MWBase::Environment::get().getWindowManager()) + : WindowModal("openmw_interactive_messagebox.layout") , mMessageBoxManager(parMessageBoxManager) , mButtonPressed(-1) { diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index c64953b665..cb40739023 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -31,7 +31,7 @@ namespace MWGui class MessageBoxManager { public: - MessageBoxManager (MWBase::WindowManager* windowManager); + MessageBoxManager (); void onFrame (float frameDuration); void createMessageBox (const std::string& message); bool createInteractiveMessageBox (const std::string& message, const std::vector& buttons); diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 82835a8058..2deb37d301 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -43,8 +43,8 @@ namespace namespace MWGui { - QuickKeysMenu::QuickKeysMenu(MWBase::WindowManager& parWindowManager) - : WindowBase("openmw_quickkeys_menu.layout", parWindowManager) + QuickKeysMenu::QuickKeysMenu() + : WindowBase("openmw_quickkeys_menu.layout") , mAssignDialog(0) , mItemSelectionDialog(0) , mMagicSelectionDialog(0) @@ -109,7 +109,7 @@ namespace MWGui { // open assign dialog if (!mAssignDialog) - mAssignDialog = new QuickKeysMenuAssign(*MWBase::Environment::get().getWindowManager(), this); + mAssignDialog = new QuickKeysMenuAssign(this); mAssignDialog->setVisible (true); } } @@ -124,7 +124,7 @@ namespace MWGui { if (!mItemSelectionDialog ) { - mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}", ContainerBase::Filter_All, *MWBase::Environment::get().getWindowManager()); + mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}", ContainerBase::Filter_All); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItemCancel); } @@ -139,7 +139,7 @@ namespace MWGui { if (!mMagicSelectionDialog ) { - mMagicSelectionDialog = new MagicSelectionDialog(*MWBase::Environment::get().getWindowManager(), this); + mMagicSelectionDialog = new MagicSelectionDialog(this); } mMagicSelectionDialog->setVisible(true); @@ -352,8 +352,8 @@ namespace MWGui // --------------------------------------------------------------------------------------------------------- - QuickKeysMenuAssign::QuickKeysMenuAssign (MWBase::WindowManager &parWindowManager, QuickKeysMenu* parent) - : WindowModal("openmw_quickkeys_menu_assign.layout", parWindowManager) + QuickKeysMenuAssign::QuickKeysMenuAssign (QuickKeysMenu* parent) + : WindowModal("openmw_quickkeys_menu_assign.layout") , mParent(parent) { getWidget(mLabel, "Label"); @@ -399,8 +399,8 @@ namespace MWGui // --------------------------------------------------------------------------------------------------------- - MagicSelectionDialog::MagicSelectionDialog(MWBase::WindowManager &parWindowManager, QuickKeysMenu* parent) - : WindowModal("openmw_magicselection_dialog.layout", parWindowManager) + MagicSelectionDialog::MagicSelectionDialog(QuickKeysMenu* parent) + : WindowModal("openmw_magicselection_dialog.layout") , mParent(parent) , mWidth(0) , mHeight(0) diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index d5b6e6cd85..646ec2aa45 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -16,7 +16,7 @@ namespace MWGui class QuickKeysMenu : public WindowBase { public: - QuickKeysMenu(MWBase::WindowManager& parWindowManager); + QuickKeysMenu(); ~QuickKeysMenu(); @@ -64,7 +64,7 @@ namespace MWGui class QuickKeysMenuAssign : public WindowModal { public: - QuickKeysMenuAssign(MWBase::WindowManager& parWindowManager, QuickKeysMenu* parent); + QuickKeysMenuAssign(QuickKeysMenu* parent); private: MyGUI::TextBox* mLabel; @@ -79,7 +79,7 @@ namespace MWGui class MagicSelectionDialog : public WindowModal { public: - MagicSelectionDialog(MWBase::WindowManager& parWindowManager, QuickKeysMenu* parent); + MagicSelectionDialog(QuickKeysMenu* parent); virtual void open(); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 167ad573a0..9a0d8a029f 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -62,8 +62,8 @@ int countParts(const std::string &part, const std::string &race, bool male) } } -RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_race.layout", parWindowManager) +RaceDialog::RaceDialog() + : WindowModal("openmw_chargen_race.layout") , mGenderIndex(0) , mFaceIndex(0) , mHairIndex(0) diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 4a4acd0112..f3adce4447 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -26,7 +26,7 @@ namespace MWGui class RaceDialog : public WindowModal { public: - RaceDialog(MWBase::WindowManager& parWindowManager); + RaceDialog(); enum Gender { diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index 43c262ad85..0bd4b0995f 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -15,8 +15,8 @@ namespace MWGui { -Repair::Repair(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_repair.layout", parWindowManager) +Repair::Repair() + : WindowBase("openmw_repair.layout") { getWidget(mRepairBox, "RepairBox"); getWidget(mRepairView, "RepairView"); diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index 824e0b6d2a..5d9a487199 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -12,7 +12,7 @@ namespace MWGui class Repair : public WindowBase { public: - Repair(MWBase::WindowManager &parWindowManager); + Repair(); virtual void open(); diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 74b1893456..562bf97748 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -22,8 +22,8 @@ using namespace Widgets; const int ReviewDialog::sLineHeight = 18; -ReviewDialog::ReviewDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_chargen_review.layout", parWindowManager) +ReviewDialog::ReviewDialog() + : WindowModal("openmw_chargen_review.layout") , mLastPos(0) { // Centre dialog diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index 9775a52de4..d5df94e285 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -28,7 +28,7 @@ namespace MWGui }; typedef std::vector SkillList; - ReviewDialog(MWBase::WindowManager& parWindowManager); + ReviewDialog(); void setPlayerName(const std::string &name); void setRace(const std::string &raceId); diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index 22884bfe6d..1935f7a9b6 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -12,8 +12,8 @@ using namespace MWGui; -ScrollWindow::ScrollWindow (MWBase::WindowManager& parWindowManager) - : WindowBase("openmw_scroll.layout", parWindowManager) +ScrollWindow::ScrollWindow () + : WindowBase("openmw_scroll.layout") , mTakeButtonShow(true) , mTakeButtonAllowed(true) { diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index 59b39cab38..5feaff7bf8 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -11,7 +11,7 @@ namespace MWGui class ScrollWindow : public WindowBase { public: - ScrollWindow (MWBase::WindowManager& parWindowManager); + ScrollWindow (); void open (MWWorld::Ptr scroll); void setTakeButtonShow(bool show); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index e21d4f5894..c3718c2607 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -93,8 +93,8 @@ namespace namespace MWGui { - SettingsWindow::SettingsWindow(MWBase::WindowManager& parWindowManager) : - WindowBase("openmw_settings_window.layout", parWindowManager) + SettingsWindow::SettingsWindow() : + WindowBase("openmw_settings_window.layout") { getWidget(mOkButton, "OkButton"); getWidget(mSubtitlesButton, "SubtitlesButton"); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 292c1233de..6dcef2422e 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -13,7 +13,7 @@ namespace MWGui class SettingsWindow : public WindowBase { public: - SettingsWindow(MWBase::WindowManager& parWindowManager); + SettingsWindow(); virtual void open(); diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 9aa8074a24..7d634df8d6 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -23,8 +23,8 @@ namespace MWGui { const int SpellBuyingWindow::sLineHeight = 18; - SpellBuyingWindow::SpellBuyingWindow(MWBase::WindowManager& parWindowManager) : - WindowBase("openmw_spell_buying_window.layout", parWindowManager) + SpellBuyingWindow::SpellBuyingWindow() : + WindowBase("openmw_spell_buying_window.layout") , mCurrentY(0) , mLastPos(0) { diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index 1418a9db52..f7ea54c89c 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -21,7 +21,7 @@ namespace MWGui class SpellBuyingWindow : public ReferenceInterface, public WindowBase { public: - SpellBuyingWindow(MWBase::WindowManager& parWindowManager); + SpellBuyingWindow(); void startSpellBuying(const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 6fef91457f..e1df9f9cd1 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -40,8 +40,8 @@ namespace namespace MWGui { - EditEffectDialog::EditEffectDialog(MWBase::WindowManager &parWindowManager) - : WindowModal("openmw_edit_effect.layout", parWindowManager) + EditEffectDialog::EditEffectDialog() + : WindowModal("openmw_edit_effect.layout") , mEditing(false) { getWidget(mCancelButton, "CancelButton"); @@ -274,9 +274,9 @@ namespace MWGui // ------------------------------------------------------------------------------------------------ - SpellCreationDialog::SpellCreationDialog(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_spellcreation_dialog.layout", parWindowManager) - , EffectEditorBase(parWindowManager) + SpellCreationDialog::SpellCreationDialog() + : WindowBase("openmw_spellcreation_dialog.layout") + , EffectEditorBase() { getWidget(mNameEdit, "NameEdit"); getWidget(mMagickaCost, "MagickaCost"); @@ -412,8 +412,8 @@ namespace MWGui // ------------------------------------------------------------------------------------------------ - EffectEditorBase::EffectEditorBase(MWBase::WindowManager& parWindowManager) - : mAddEffectDialog(parWindowManager) + EffectEditorBase::EffectEditorBase() + : mAddEffectDialog() , mSelectAttributeDialog(NULL) , mSelectSkillDialog(NULL) { @@ -541,7 +541,7 @@ namespace MWGui if (effect->mData.mFlags & ESM::MagicEffect::TargetSkill) { delete mSelectSkillDialog; - mSelectSkillDialog = new SelectSkillDialog(*MWBase::Environment::get().getWindowManager ()); + mSelectSkillDialog = new SelectSkillDialog(); mSelectSkillDialog->eventCancel += MyGUI::newDelegate(this, &SpellCreationDialog::onAttributeOrSkillCancel); mSelectSkillDialog->eventItemSelected += MyGUI::newDelegate(this, &SpellCreationDialog::onSelectSkill); mSelectSkillDialog->setVisible (true); @@ -549,7 +549,7 @@ namespace MWGui else if (effect->mData.mFlags & ESM::MagicEffect::TargetAttribute) { delete mSelectAttributeDialog; - mSelectAttributeDialog = new SelectAttributeDialog(*MWBase::Environment::get().getWindowManager ()); + mSelectAttributeDialog = new SelectAttributeDialog(); mSelectAttributeDialog->eventCancel += MyGUI::newDelegate(this, &SpellCreationDialog::onAttributeOrSkillCancel); mSelectAttributeDialog->eventItemSelected += MyGUI::newDelegate(this, &SpellCreationDialog::onSelectAttribute); mSelectAttributeDialog->setVisible (true); diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index facbdf5304..5ad306fbea 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -15,7 +15,7 @@ namespace MWGui class EditEffectDialog : public WindowModal { public: - EditEffectDialog(MWBase::WindowManager& parWindowManager); + EditEffectDialog(); virtual void open(); @@ -83,7 +83,7 @@ namespace MWGui class EffectEditorBase { public: - EffectEditorBase(MWBase::WindowManager& parWindowManager); + EffectEditorBase(); protected: @@ -123,7 +123,7 @@ namespace MWGui class SpellCreationDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase { public: - SpellCreationDialog(MWBase::WindowManager& parWindowManager); + SpellCreationDialog(); virtual void open(); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 257fab89d4..d07f9ca542 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -47,8 +47,8 @@ namespace namespace MWGui { - SpellWindow::SpellWindow(MWBase::WindowManager& parWindowManager) - : WindowPinnableBase("openmw_spell_window.layout", parWindowManager) + SpellWindow::SpellWindow() + : WindowPinnableBase("openmw_spell_window.layout") , mHeight(0) , mWidth(0) { diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index b0994c5901..521e73d767 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -10,7 +10,7 @@ namespace MWGui class SpellWindow : public WindowPinnableBase { public: - SpellWindow(MWBase::WindowManager& parWindowManager); + SpellWindow(); virtual ~SpellWindow(); void updateSpells(); diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 0e0676c2fb..a00ec167da 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -22,8 +22,8 @@ using namespace MWGui; const int StatsWindow::sLineHeight = 18; -StatsWindow::StatsWindow (MWBase::WindowManager& parWindowManager) - : WindowPinnableBase("openmw_stats_window.layout", parWindowManager) +StatsWindow::StatsWindow () + : WindowPinnableBase("openmw_stats_window.layout") , mSkillView(NULL) , mClientHeight(0) , mMajorSkills() diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index 93e26e063d..4b723048cc 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -22,7 +22,7 @@ namespace MWGui typedef std::vector SkillList; - StatsWindow(MWBase::WindowManager& parWindowManager); + StatsWindow(); /// automatically updates all the data in the stats window, but only if it has changed. void onFrame(); diff --git a/apps/openmw/mwgui/textinput.cpp b/apps/openmw/mwgui/textinput.cpp index 071971befb..ab2936cfce 100644 --- a/apps/openmw/mwgui/textinput.cpp +++ b/apps/openmw/mwgui/textinput.cpp @@ -5,8 +5,8 @@ using namespace MWGui; -TextInputDialog::TextInputDialog(MWBase::WindowManager& parWindowManager) - : WindowModal("openmw_text_input.layout", parWindowManager) +TextInputDialog::TextInputDialog() + : WindowModal("openmw_text_input.layout") { // Centre dialog center(); diff --git a/apps/openmw/mwgui/textinput.hpp b/apps/openmw/mwgui/textinput.hpp index 6b371bae74..1f53263ecd 100644 --- a/apps/openmw/mwgui/textinput.hpp +++ b/apps/openmw/mwgui/textinput.hpp @@ -13,7 +13,7 @@ namespace MWGui class TextInputDialog : public WindowModal { public: - TextInputDialog(MWBase::WindowManager& parWindowManager); + TextInputDialog(); std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; } void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 7730019e83..2250ffd0b5 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -19,7 +19,7 @@ using namespace MWGui; using namespace MyGUI; -ToolTips::ToolTips(MWBase::WindowManager* windowManager) : +ToolTips::ToolTips() : Layout("openmw_tooltips.layout") , mGameMode(true) , mFullHelp(false) diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index e4fcb310c8..f8f256167b 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -39,7 +39,7 @@ namespace MWGui class ToolTips : public OEngine::GUI::Layout { public: - ToolTips(MWBase::WindowManager* windowManager); + ToolTips(); void onFrame(float frameDuration); diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 718e6378bb..718f40c785 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -24,8 +24,8 @@ namespace MWGui const float TradeWindow::sBalanceChangeInitialPause = 0.5; const float TradeWindow::sBalanceChangeInterval = 0.1; - TradeWindow::TradeWindow(MWBase::WindowManager& parWindowManager) : - WindowBase("openmw_trade_window.layout", parWindowManager) + TradeWindow::TradeWindow() : + WindowBase("openmw_trade_window.layout") , ContainerBase(NULL) // no drag&drop , mCurrentBalance(0) , mBalanceButtonsState(BBS_None) diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 111c0935fe..e526a42ca5 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -23,7 +23,7 @@ namespace MWGui class TradeWindow : public ContainerBase, public WindowBase { public: - TradeWindow(MWBase::WindowManager& parWindowManager); + TradeWindow(); void startTrade(MWWorld::Ptr actor); diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index c2b543a4fd..f85a8be594 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -20,8 +20,8 @@ namespace MWGui { - TrainingWindow::TrainingWindow(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_trainingwindow.layout", parWindowManager) + TrainingWindow::TrainingWindow() + : WindowBase("openmw_trainingwindow.layout") , mFadeTimeRemaining(0) { getWidget(mTrainingOptions, "TrainingOptions"); diff --git a/apps/openmw/mwgui/trainingwindow.hpp b/apps/openmw/mwgui/trainingwindow.hpp index d6be60ae67..740115cdfc 100644 --- a/apps/openmw/mwgui/trainingwindow.hpp +++ b/apps/openmw/mwgui/trainingwindow.hpp @@ -10,7 +10,7 @@ namespace MWGui class TrainingWindow : public WindowBase, public ReferenceInterface { public: - TrainingWindow(MWBase::WindowManager& parWindowManager); + TrainingWindow(); virtual void open(); diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index b710171669..0a74c921af 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -25,8 +25,8 @@ namespace MWGui { const int TravelWindow::sLineHeight = 18; - TravelWindow::TravelWindow(MWBase::WindowManager& parWindowManager) : - WindowBase("openmw_travel_window.layout", parWindowManager) + TravelWindow::TravelWindow() : + WindowBase("openmw_travel_window.layout") , mCurrentY(0) , mLastPos(0) { diff --git a/apps/openmw/mwgui/travelwindow.hpp b/apps/openmw/mwgui/travelwindow.hpp index 61b724910c..a814d04785 100644 --- a/apps/openmw/mwgui/travelwindow.hpp +++ b/apps/openmw/mwgui/travelwindow.hpp @@ -23,7 +23,7 @@ namespace MWGui class TravelWindow : public ReferenceInterface, public WindowBase { public: - TravelWindow(MWBase::WindowManager& parWindowManager); + TravelWindow(); void startTravel(const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 69dfa10b4d..a84b9203a9 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -25,8 +25,8 @@ namespace MWGui { - WaitDialogProgressBar::WaitDialogProgressBar(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_wait_dialog_progressbar.layout", parWindowManager) + WaitDialogProgressBar::WaitDialogProgressBar() + : WindowBase("openmw_wait_dialog_progressbar.layout") { getWidget(mProgressBar, "ProgressBar"); getWidget(mProgressText, "ProgressText"); @@ -46,9 +46,9 @@ namespace MWGui // --------------------------------------------------------------------------------------------------------- - WaitDialog::WaitDialog(MWBase::WindowManager &parWindowManager) - : WindowBase("openmw_wait_dialog.layout", parWindowManager) - , mProgressBar(parWindowManager) + WaitDialog::WaitDialog() + : WindowBase("openmw_wait_dialog.layout") + , mProgressBar() , mWaiting(false) , mSleeping(false) , mHours(1) diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index 4510e665b3..d06d7d1128 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -9,7 +9,7 @@ namespace MWGui class WaitDialogProgressBar : public WindowBase { public: - WaitDialogProgressBar(MWBase::WindowManager& parWindowManager); + WaitDialogProgressBar(); virtual void open(); @@ -23,7 +23,7 @@ namespace MWGui class WaitDialog : public WindowBase { public: - WaitDialog(MWBase::WindowManager& parWindowManager); + WaitDialog(); virtual void open(); diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 3801ae6f7a..dd3206ed65 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -34,8 +34,7 @@ void MWGui::Widgets::fixTexturePath(std::string &path) /* MWSkill */ MWSkill::MWSkill() - : mManager(NULL) - , mSkillId(ESM::Skill::Length) + : mSkillId(ESM::Skill::Length) , mSkillNameWidget(NULL) , mSkillValueWidget(NULL) { @@ -65,7 +64,7 @@ void MWSkill::setSkillValue(const SkillValue& value) void MWSkill::updateWidgets() { - if (mSkillNameWidget && mManager) + if (mSkillNameWidget) { if (mSkillId == ESM::Skill::Length) { @@ -73,7 +72,7 @@ void MWSkill::updateWidgets() } else { - const std::string &name = mManager->getGameSettingString(ESM::Skill::sSkillNameIds[mSkillId], ""); + const std::string &name = MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Skill::sSkillNameIds[mSkillId], ""); static_cast(mSkillNameWidget)->setCaption(name); } } @@ -126,8 +125,7 @@ void MWSkill::initialiseOverride() /* MWAttribute */ MWAttribute::MWAttribute() - : mManager(NULL) - , mId(-1) + : mId(-1) , mAttributeNameWidget(NULL) , mAttributeValueWidget(NULL) { @@ -152,7 +150,7 @@ void MWAttribute::onClicked(MyGUI::Widget* _sender) void MWAttribute::updateWidgets() { - if (mAttributeNameWidget && mManager) + if (mAttributeNameWidget) { if (mId < 0 || mId >= 8) { @@ -170,7 +168,7 @@ void MWAttribute::updateWidgets() "sAttributePersonality", "sAttributeLuck" }; - const std::string &name = mManager->getGameSettingString(attributes[mId], ""); + const std::string &name = MWBase::Environment::get().getWindowManager()->getGameSettingString(attributes[mId], ""); static_cast(mAttributeNameWidget)->setCaption(name); } } diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 26ca750667..038ce3f86f 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -98,7 +98,6 @@ namespace MWGui void setSkillNumber(int skillId); void setSkillValue(const SkillValue& value); - MWBase::WindowManager *getWindowManager() const { return mManager; } ESM::Skill::SkillEnum getSkillId() const { return mSkillId; } const SkillValue& getSkillValue() const { return mValue; } @@ -121,7 +120,6 @@ namespace MWGui void updateWidgets(); - MWBase::WindowManager *mManager; ESM::Skill::SkillEnum mSkillId; SkillValue mValue; MyGUI::Widget* mSkillNameWidget; @@ -140,7 +138,6 @@ namespace MWGui void setAttributeId(int attributeId); void setAttributeValue(const AttributeValue& value); - MWBase::WindowManager *getWindowManager() const { return mManager; } int getAttributeId() const { return mId; } const AttributeValue& getAttributeValue() const { return mValue; } @@ -163,7 +160,6 @@ namespace MWGui void updateWidgets(); - MWBase::WindowManager *mManager; int mId; AttributeValue mValue; MyGUI::Widget* mAttributeNameWidget; diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index cb3d4ea8c8..c41bcb7ce6 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -6,7 +6,7 @@ using namespace MWGui; -WindowBase::WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) +WindowBase::WindowBase(const std::string& parLayout) : Layout(parLayout) { } @@ -38,8 +38,8 @@ void WindowBase::center() mMainWidget->setCoord(coord); } -WindowModal::WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager) - : WindowBase(parLayout, parWindowManager) +WindowModal::WindowModal(const std::string& parLayout) + : WindowBase(parLayout) { } diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index a2cb731fee..2c014baf0b 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -15,7 +15,7 @@ namespace MWGui class WindowBase: public OEngine::GUI::Layout { public: - WindowBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + WindowBase(const std::string& parLayout); // Events typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; @@ -38,7 +38,7 @@ namespace MWGui class WindowModal : public WindowBase { public: - WindowModal(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + WindowModal(const std::string& parLayout); virtual void open(); virtual void close(); }; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index bcde82e966..f2ded8813e 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -162,38 +162,38 @@ WindowManager::WindowManager( mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; mMenu = new MainMenu(w,h); - mMap = new MapWindow(*this, cacheDir); - mStatsWindow = new StatsWindow(*this); + mMap = new MapWindow(cacheDir); + mStatsWindow = new StatsWindow(); mConsole = new Console(w,h, consoleOnlyScripts); - mJournal = new JournalWindow(*this); - mMessageBoxManager = new MessageBoxManager(this); - mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); - mTradeWindow = new TradeWindow(*this); - mSpellBuyingWindow = new SpellBuyingWindow(*this); - mTravelWindow = new TravelWindow(*this); - mDialogueWindow = new DialogueWindow(*this); - mContainerWindow = new ContainerWindow(*this,mDragAndDrop); + mJournal = new JournalWindow(); + mMessageBoxManager = new MessageBoxManager(); + mInventoryWindow = new InventoryWindow(mDragAndDrop); + mTradeWindow = new TradeWindow(); + mSpellBuyingWindow = new SpellBuyingWindow(); + mTravelWindow = new TravelWindow(); + mDialogueWindow = new DialogueWindow(); + mContainerWindow = new ContainerWindow(mDragAndDrop); mHud = new HUD(w,h, mShowFPSLevel, mDragAndDrop); - mToolTips = new ToolTips(this); - mScrollWindow = new ScrollWindow(*this); - mBookWindow = new BookWindow(*this); - mCountDialog = new CountDialog(*this); - mSettingsWindow = new SettingsWindow(*this); - mConfirmationDialog = new ConfirmationDialog(*this); - mAlchemyWindow = new AlchemyWindow(*this); - mSpellWindow = new SpellWindow(*this); - mQuickKeysMenu = new QuickKeysMenu(*this); - mLevelupDialog = new LevelupDialog(*this); - mWaitDialog = new WaitDialog(*this); - mSpellCreationDialog = new SpellCreationDialog(*this); - mEnchantingDialog = new EnchantingDialog(*this); - mTrainingWindow = new TrainingWindow(*this); - mMerchantRepair = new MerchantRepair(*this); - mRepair = new Repair(*this); + mToolTips = new ToolTips(); + mScrollWindow = new ScrollWindow(); + mBookWindow = new BookWindow(); + mCountDialog = new CountDialog(); + mSettingsWindow = new SettingsWindow(); + mConfirmationDialog = new ConfirmationDialog(); + mAlchemyWindow = new AlchemyWindow(); + mSpellWindow = new SpellWindow(); + mQuickKeysMenu = new QuickKeysMenu(); + mLevelupDialog = new LevelupDialog(); + mWaitDialog = new WaitDialog(); + mSpellCreationDialog = new SpellCreationDialog(); + mEnchantingDialog = new EnchantingDialog(); + mTrainingWindow = new TrainingWindow(); + mMerchantRepair = new MerchantRepair(); + mRepair = new Repair(); mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); - mCompanionWindow = new CompanionWindow(*this, mDragAndDrop, mMessageBoxManager); + mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); - mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); + mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ()); mLoadingScreen->onResChange (w,h); mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); @@ -202,7 +202,7 @@ WindowManager::WindowManager( mHud->setVisible(mHudEnabled); - mCharGen = new CharacterCreation(this); + mCharGen = new CharacterCreation(); // Setup player stats for (int i = 0; i < ESM::Attribute::Length; ++i) diff --git a/apps/openmw/mwgui/windowpinnablebase.cpp b/apps/openmw/mwgui/windowpinnablebase.cpp index 54ed082cf9..56868306ac 100644 --- a/apps/openmw/mwgui/windowpinnablebase.cpp +++ b/apps/openmw/mwgui/windowpinnablebase.cpp @@ -6,8 +6,8 @@ using namespace MWGui; -WindowPinnableBase::WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager) - : WindowBase(parLayout, parWindowManager), mPinned(false), mVisible(false) +WindowPinnableBase::WindowPinnableBase(const std::string& parLayout) + : WindowBase(parLayout), mPinned(false), mVisible(false) { ExposedWindow* window = static_cast(mMainWidget); mPinButton = window->getSkinWidget ("Button"); diff --git a/apps/openmw/mwgui/windowpinnablebase.hpp b/apps/openmw/mwgui/windowpinnablebase.hpp index 657e8142f1..1ab6294328 100644 --- a/apps/openmw/mwgui/windowpinnablebase.hpp +++ b/apps/openmw/mwgui/windowpinnablebase.hpp @@ -10,7 +10,7 @@ namespace MWGui class WindowPinnableBase: public WindowBase { public: - WindowPinnableBase(const std::string& parLayout, MWBase::WindowManager& parWindowManager); + WindowPinnableBase(const std::string& parLayout); bool pinned() { return mPinned; } private: From 3a87b12bafefd6b7f97c9a2ddac43fddc496d549 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 10 Apr 2013 21:31:14 +0200 Subject: [PATCH 187/198] delete script subview on script deletion --- apps/opencs/view/world/scriptsubview.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 2fdb44aec3..0319033b00 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -53,8 +53,8 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT (dataChanged (const QModelIndex&, const QModelIndex&))); -// connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int start, int end)), -// this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int start, int end))); + connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), + this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int))); } void CSVWorld::ScriptSubView::setEditLock (bool locked) @@ -88,5 +88,8 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end) { + QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); + if (!parent.isValid() && index.row()>=start && index.row()<=end) + deleteLater(); } \ No newline at end of file From 6c6750342c321b537fcc7cc14246050fc4bf2580 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 10 Apr 2013 13:37:20 -0700 Subject: [PATCH 188/198] Specified particle size is actually the radius --- components/nif/data.hpp | 4 ++-- components/nifogre/ogrenifloader.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index bd109041f1..f1f34184ba 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -167,7 +167,7 @@ class NiAutoNormalParticlesData : public ShapeData public: int numParticles; - float particleSize; + float particleRadius; int activeCount; @@ -180,7 +180,7 @@ public: // Should always match the number of vertices numParticles = nif->getUShort(); - particleSize = nif->getFloat(); + particleRadius = nif->getFloat(); activeCount = nif->getUShort(); if(nif->getInt()) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 3c876283e1..62732d387d 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -1543,7 +1543,8 @@ class NIFObjectLoader : Ogre::ManualResourceLoader vertprop, zprop, specprop, wireprop, needTangents)); - partsys->setDefaultDimensions(particledata->particleSize, particledata->particleSize); + partsys->setDefaultDimensions(particledata->particleRadius*2.0f, + particledata->particleRadius*2.0f); partsys->setCullIndividually(false); partsys->setParticleQuota(particledata->numParticles); From 74145410f24d6c60b6cdca81aa14e40564691cda Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 10 Apr 2013 22:49:22 +0200 Subject: [PATCH 189/198] basic syntax highlighting in script subview --- apps/opencs/CMakeLists.txt | 4 +- apps/opencs/model/world/scriptcontext.cpp | 22 ++++ apps/opencs/model/world/scriptcontext.hpp | 26 +++++ apps/opencs/view/world/scripthighlighter.cpp | 105 +++++++++++++++++++ apps/opencs/view/world/scripthighlighter.hpp | 77 ++++++++++++++ apps/opencs/view/world/scriptsubview.cpp | 4 + components/CMakeLists.txt | 2 +- components/compiler/nullerrorhandler.cpp | 6 ++ components/compiler/nullerrorhandler.hpp | 21 ++++ 9 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 apps/opencs/model/world/scriptcontext.cpp create mode 100644 apps/opencs/model/world/scriptcontext.hpp create mode 100644 apps/opencs/view/world/scripthighlighter.cpp create mode 100644 apps/opencs/view/world/scripthighlighter.hpp create mode 100644 components/compiler/nullerrorhandler.cpp create mode 100644 components/compiler/nullerrorhandler.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index bd882892fd..5c15938bda 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -22,7 +22,7 @@ opencs_units (model/world opencs_units_noqt (model/world - universalid data record idcollection commands columnbase + universalid data record idcollection commands columnbase scriptcontext ) opencs_hdrs_noqt (model/world @@ -59,7 +59,7 @@ opencs_units (view/world ) opencs_units_noqt (view/world - dialoguesubview util subviews enumdelegate vartypedelegate + dialoguesubview util subviews enumdelegate vartypedelegate scripthighlighter ) diff --git a/apps/opencs/model/world/scriptcontext.cpp b/apps/opencs/model/world/scriptcontext.cpp new file mode 100644 index 0000000000..69b72abf26 --- /dev/null +++ b/apps/opencs/model/world/scriptcontext.cpp @@ -0,0 +1,22 @@ + +#include "scriptcontext.hpp" + +bool CSMWorld::ScriptContext::canDeclareLocals() const +{ + return false; +} + +char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const +{ + return ' '; +} + +char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std::string& id) const +{ + return ' '; +} + +bool CSMWorld::ScriptContext::isId (const std::string& name) const +{ + return false; +} \ No newline at end of file diff --git a/apps/opencs/model/world/scriptcontext.hpp b/apps/opencs/model/world/scriptcontext.hpp new file mode 100644 index 0000000000..1231aea649 --- /dev/null +++ b/apps/opencs/model/world/scriptcontext.hpp @@ -0,0 +1,26 @@ +#ifndef CSM_WORLD_SCRIPTCONTEXT_H +#define CSM_WORLD_SCRIPTCONTEXT_H + +#include + +namespace CSMWorld +{ + class ScriptContext : public Compiler::Context + { + public: + + virtual bool canDeclareLocals() const; + ///< Is the compiler allowed to declare local variables? + + virtual char getGlobalType (const std::string& name) const; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + + virtual char getMemberType (const std::string& name, const std::string& id) const; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + + virtual bool isId (const std::string& name) const; + ///< Does \a name match an ID, that can be referenced? + }; +} + +#endif diff --git a/apps/opencs/view/world/scripthighlighter.cpp b/apps/opencs/view/world/scripthighlighter.cpp new file mode 100644 index 0000000000..1e93ac26b7 --- /dev/null +++ b/apps/opencs/view/world/scripthighlighter.cpp @@ -0,0 +1,105 @@ + +#include "scripthighlighter.hpp" + +#include + +#include + +bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) +{ + highlight (loc, Type_Int); + return true; +} + +bool CSVWorld::ScriptHighlighter::parseFloat (float value, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) +{ + highlight (loc, Type_Float); + return true; +} + +bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) +{ + highlight (loc, Type_Name); + return true; +} + +bool CSVWorld::ScriptHighlighter::parseKeyword (int keyword, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) +{ + highlight (loc, Type_Keyword); + return true; +} + +bool CSVWorld::ScriptHighlighter::parseSpecial (int code, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) +{ + highlight (loc, Type_Special); + return true; +} + +void CSVWorld::ScriptHighlighter::parseEOF (Compiler::Scanner& scanner) +{} + +void CSVWorld::ScriptHighlighter::highlight (const Compiler::TokenLoc& loc, Type type) +{ + int length = static_cast (loc.mLiteral.size()); + + int index = loc.mColumn; + + // compensate for bug in Compiler::Scanner (position of token is the character after the token) + index -= length; + + setFormat (index, length, mScheme[type]); +} + +CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent) +: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext) +{ + /// \ŧodo replace this with user settings + { + QTextCharFormat format; + format.setForeground (Qt::darkMagenta); + mScheme.insert (std::make_pair (Type_Int, format)); + } + + { + QTextCharFormat format; + format.setForeground (Qt::green); + mScheme.insert (std::make_pair (Type_Float, format)); + } + + { + QTextCharFormat format; + format.setForeground (Qt::gray); + mScheme.insert (std::make_pair (Type_Name, format)); + } + + { + QTextCharFormat format; + format.setForeground (Qt::red); + mScheme.insert (std::make_pair (Type_Keyword, format)); + } + + { + QTextCharFormat format; + format.setForeground (Qt::darkYellow); + mScheme.insert (std::make_pair (Type_Special, format)); + } +} + +void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text) +{ + std::istringstream stream (text.toUtf8().constData()); + + Compiler::Scanner scanner (mErrorHandler, stream, mContext.getExtensions()); + + try + { + scanner.scan (*this); + } + catch (...) {} // ignore syntax errors + +} \ No newline at end of file diff --git a/apps/opencs/view/world/scripthighlighter.hpp b/apps/opencs/view/world/scripthighlighter.hpp new file mode 100644 index 0000000000..e9918f99b7 --- /dev/null +++ b/apps/opencs/view/world/scripthighlighter.hpp @@ -0,0 +1,77 @@ +#ifndef CSV_WORLD_SCRIPTHIGHLIGHTER_H +#define CSV_WORLD_SCRIPTHIGHLIGHTER_H + +#include + +#include + +#include +#include + +#include "../../model/world/scriptcontext.hpp" + +namespace CSVWorld +{ + class ScriptHighlighter : public QSyntaxHighlighter, private Compiler::Parser + { + public: + + enum Type + { + Type_Int, + Type_Float, + Type_Name, + Type_Keyword, + Type_Special + }; + + private: + + Compiler::NullErrorHandler mErrorHandler; + CSMWorld::ScriptContext mContext; + std::map mScheme; + + private: + + virtual bool parseInt (int value, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner); + ///< Handle an int token. + /// \return fetch another token? + + virtual bool parseFloat (float value, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner); + ///< Handle a float token. + /// \return fetch another token? + + virtual bool parseName (const std::string& name, + const Compiler::TokenLoc& loc, Compiler::Scanner& scanner); + ///< Handle a name token. + /// \return fetch another token? + + virtual bool parseKeyword (int keyword, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner); + ///< Handle a keyword token. + /// \return fetch another token? + + virtual bool parseSpecial (int code, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner); + ///< Handle a special character token. + /// \return fetch another token? + + ///< Handle a special character token. + /// \return fetch another token? + + virtual void parseEOF (Compiler::Scanner& scanner); + ///< Handle EOF token. + + void highlight (const Compiler::TokenLoc& loc, Type type); + + public: + + ScriptHighlighter (QTextDocument *parent); + + virtual void highlightBlock (const QString& text); + }; +} + +#endif diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 0319033b00..ab1c2d57c6 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -12,6 +12,8 @@ #include "../../model/world/commands.hpp" #include "../../model/world/idtable.hpp" +#include "scripthighlighter.hpp" + CSVWorld::ScriptSubView::ChangeLock::ChangeLock (ScriptSubView& view) : mView (view) { ++mView.mChangeLocked; @@ -55,6 +57,8 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int))); + + new ScriptHighlighter (mEditor->document()); } void CSVWorld::ScriptSubView::setEditLock (bool locked) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a2f416fcca..ed12ff2f0e 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -54,7 +54,7 @@ add_component_dir (files add_component_dir (compiler context controlparser errorhandler exception exprparser extensions fileparser generator lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler - stringparser tokenloc + stringparser tokenloc nullerrorhandler ) add_component_dir (interpreter diff --git a/components/compiler/nullerrorhandler.cpp b/components/compiler/nullerrorhandler.cpp new file mode 100644 index 0000000000..3071701e8a --- /dev/null +++ b/components/compiler/nullerrorhandler.cpp @@ -0,0 +1,6 @@ + +#include "nullerrorhandler.hpp" + +void Compiler::NullErrorHandler::report (const std::string& message, const TokenLoc& loc, Type type) {} + +void Compiler::NullErrorHandler::report (const std::string& message, Type type) {} \ No newline at end of file diff --git a/components/compiler/nullerrorhandler.hpp b/components/compiler/nullerrorhandler.hpp new file mode 100644 index 0000000000..bb4db99a28 --- /dev/null +++ b/components/compiler/nullerrorhandler.hpp @@ -0,0 +1,21 @@ + +#ifndef COMPILER_NULLERRORHANDLER_H_INCLUDED +#define COMPILER_NULLERRORHANDLER_H_INCLUDED + +#include "errorhandler.hpp" + +namespace Compiler +{ + /// \brief Error handler implementation: Ignore all error messages + + class NullErrorHandler : public ErrorHandler + { + virtual void report (const std::string& message, const TokenLoc& loc, Type type); + ///< Report error to the user. + + virtual void report (const std::string& message, Type type); + ///< Report a file related error + }; +} + +#endif From caff28e20acb914997143e51ac503835f3a8fb4d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 10 Apr 2013 19:58:17 -0700 Subject: [PATCH 190/198] Move NIFSkeletonLoader to a separate file --- apps/openmw/mwrender/animation.hpp | 3 + components/CMakeLists.txt | 2 +- components/nifogre/ogrenifloader.cpp | 366 +-------------------------- components/nifogre/ogrenifloader.hpp | 4 +- components/nifogre/skeleton.cpp | 351 +++++++++++++++++++++++++ components/nifogre/skeleton.hpp | 63 +++++ 6 files changed, 421 insertions(+), 368 deletions(-) create mode 100644 components/nifogre/skeleton.cpp create mode 100644 components/nifogre/skeleton.hpp diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index cfef28f16c..029c56523d 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -1,6 +1,9 @@ #ifndef _GAME_RENDER_ANIMATION_H #define _GAME_RENDER_ANIMATION_H +#include +#include + #include #include "../mwworld/ptr.hpp" diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a2f416fcca..d43725ee08 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -19,7 +19,7 @@ add_component_dir (nif ) add_component_dir (nifogre - ogrenifloader + ogrenifloader skeleton ) add_component_dir (nifbullet diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 62732d387d..0a30f38bd1 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -51,7 +51,7 @@ #include #include -typedef unsigned char ubyte; +#include "skeleton.hpp" namespace std { @@ -424,370 +424,6 @@ public: }; -/** Manual resource loader for NIF skeletons. This is the main class - responsible for translating the internal NIF skeleton structure into - something Ogre can use (includes animations and node TextKeyData). - */ -class NIFSkeletonLoader : public Ogre::ManualResourceLoader -{ -static void warn(const std::string &msg) -{ - std::cerr << "NIFSkeletonLoader: Warn: " << msg << std::endl; -} - -static void fail(const std::string &msg) -{ - std::cerr << "NIFSkeletonLoader: Fail: "<< msg << std::endl; - abort(); -} - - -static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime) -{ - Ogre::Animation *anim = skel->createAnimation(name, stopTime); - - for(size_t i = 0;i < ctrls.size();i++) - { - const Nif::NiKeyframeController *kfc = ctrls[i]; - if(kfc->data.empty()) - continue; - const Nif::NiKeyframeData *kf = kfc->data.getPtr(); - - /* Get the keyframes and make sure they're sorted first to last */ - const Nif::QuaternionKeyList &quatkeys = kf->mRotations; - const Nif::Vector3KeyList &trankeys = kf->mTranslations; - const Nif::FloatKeyList &scalekeys = kf->mScales; - - Nif::QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin(); - Nif::Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin(); - Nif::FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin(); - - Ogre::Bone *bone = skel->getBone(targets[i]); - // NOTE: For some reason, Ogre doesn't like the node track ID being different from - // the bone ID - Ogre::NodeAnimationTrack *nodetrack = anim->hasNodeTrack(bone->getHandle()) ? - anim->getNodeTrack(bone->getHandle()) : - anim->createNodeTrack(bone->getHandle(), bone); - - Ogre::Quaternion lastquat, curquat; - Ogre::Vector3 lasttrans(0.0f), curtrans(0.0f); - Ogre::Vector3 lastscale(1.0f), curscale(1.0f); - if(quatiter != quatkeys.mKeys.end()) - lastquat = curquat = quatiter->mValue; - if(traniter != trankeys.mKeys.end()) - lasttrans = curtrans = traniter->mValue; - if(scaleiter != scalekeys.mKeys.end()) - lastscale = curscale = Ogre::Vector3(scaleiter->mValue); - - bool didlast = false; - while(!didlast) - { - float curtime = std::numeric_limits::max(); - - //Get latest time - if(quatiter != quatkeys.mKeys.end()) - curtime = std::min(curtime, quatiter->mTime); - if(traniter != trankeys.mKeys.end()) - curtime = std::min(curtime, traniter->mTime); - if(scaleiter != scalekeys.mKeys.end()) - curtime = std::min(curtime, scaleiter->mTime); - - curtime = std::max(curtime, startTime); - if(curtime >= stopTime) - { - didlast = true; - curtime = stopTime; - } - - // Get the latest quaternions, translations, and scales for the - // current time - while(quatiter != quatkeys.mKeys.end() && curtime >= quatiter->mTime) - { - lastquat = curquat; - if(++quatiter != quatkeys.mKeys.end()) - curquat = quatiter->mValue; - } - while(traniter != trankeys.mKeys.end() && curtime >= traniter->mTime) - { - lasttrans = curtrans; - if(++traniter != trankeys.mKeys.end()) - curtrans = traniter->mValue; - } - while(scaleiter != scalekeys.mKeys.end() && curtime >= scaleiter->mTime) - { - lastscale = curscale; - if(++scaleiter != scalekeys.mKeys.end()) - curscale = Ogre::Vector3(scaleiter->mValue); - } - - Ogre::TransformKeyFrame *kframe; - kframe = nodetrack->createNodeKeyFrame(curtime); - if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin()) - kframe->setRotation(curquat); - else - { - Nif::QuaternionKeyList::VecType::const_iterator last = quatiter-1; - float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime); - kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat)); - } - if(traniter == trankeys.mKeys.end() || traniter == trankeys.mKeys.begin()) - kframe->setTranslate(curtrans); - else - { - Nif::Vector3KeyList::VecType::const_iterator last = traniter-1; - float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime); - kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff)); - } - if(scaleiter == scalekeys.mKeys.end() || scaleiter == scalekeys.mKeys.begin()) - kframe->setScale(curscale); - else - { - Nif::FloatKeyList::VecType::const_iterator last = scaleiter-1; - float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime); - kframe->setScale(lastscale + ((curscale-lastscale)*diff)); - } - } - } - anim->optimise(); -} - - -static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk) -{ - TextKeyMap textkeys; - for(size_t i = 0;i < tk->list.size();i++) - { - const std::string &str = tk->list[i].text; - std::string::size_type pos = 0; - while(pos < str.length()) - { - if(::isspace(str[pos])) - { - pos++; - continue; - } - - std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos)); - std::string result = str.substr(pos, nextpos-pos); - textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result))); - - pos = nextpos; - } - } - return textkeys; -} - -void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector &ctrls, Ogre::Bone *parent=NULL) -{ - Ogre::Bone *bone; - if(!skel->hasBone(node->name)) - bone = skel->createBone(node->name); - else - bone = skel->createBone(); - if(parent) parent->addChild(bone); - mNifToOgreHandleMap[node->recIndex] = bone->getHandle(); - - bone->setOrientation(node->trafo.rotation); - bone->setPosition(node->trafo.pos); - bone->setScale(Ogre::Vector3(node->trafo.scale)); - bone->setBindingPose(); - - if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ - node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */ - node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */ - node->recType == Nif::RC_NiCamera || - node->recType == Nif::RC_NiAutoNormalParticles || - node->recType == Nif::RC_NiRotatingParticles - )) - warn("Unhandled "+node->recName+" "+node->name+" in "+skel->getName()); - - Nif::ControllerPtr ctrl = node->controller; - while(!ctrl.empty()) - { - if(ctrl->recType == Nif::RC_NiKeyframeController) - ctrls.push_back(static_cast(ctrl.getPtr())); - else if(!(ctrl->recType == Nif::RC_NiParticleSystemController || - ctrl->recType == Nif::RC_NiVisController || - ctrl->recType == Nif::RC_NiUVController - )) - warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); - ctrl = ctrl->next; - } - - Nif::ExtraPtr e = node->extra; - while(!e.empty()) - { - if(e->recType == Nif::RC_NiTextKeyExtraData && !animroot) - { - const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); - textkeys = extractTextKeys(tk); - animroot = bone; - } - e = e->extra; - } - - const Nif::NiNode *ninode = dynamic_cast(node); - if(ninode) - { - const Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) - { - if(!children[i].empty()) - buildBones(skel, children[i].getPtr(), animroot, textkeys, ctrls, bone); - } - } -} - -// Lookup to retrieve an Ogre bone handle for a given Nif record index -std::map mNifToOgreHandleMap; - -typedef std::map LoaderMap; -static LoaderMap sLoaders; - -public: -void loadResource(Ogre::Resource *resource) -{ - Ogre::Skeleton *skel = dynamic_cast(resource); - OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); - - Nif::NIFFile::ptr nif(Nif::NIFFile::create(skel->getName())); - const Nif::Node *node = static_cast(nif->getRoot(0)); - - std::vector ctrls; - Ogre::Bone *animroot = NULL; - TextKeyMap textkeys; - try { - buildBones(skel, node, animroot, textkeys, ctrls); - } - catch(std::exception &e) { - std::cerr<< "Exception while loading "<getName() < targets; - // TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file - if(ctrls.size() == 0) // No animations? Then we're done. - return; - - float maxtime = 0.0f; - for(size_t i = 0;i < ctrls.size();i++) - { - const Nif::NiKeyframeController *ctrl = ctrls[i]; - maxtime = std::max(maxtime, ctrl->timeStop); - Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); - if(target != NULL) - targets.push_back(target->name); - } - - if(targets.size() != ctrls.size()) - { - warn("Target size mismatch ("+Ogre::StringConverter::toString(targets.size())+" targets, "+ - Ogre::StringConverter::toString(ctrls.size())+" controllers)"); - return; - } - - Ogre::UserObjectBindings &bindings = animroot->getUserObjectBindings(); - bindings.setUserAny(sTextKeyExtraDataID, Ogre::Any(true)); - - std::string currentgroup; - TextKeyMap::const_iterator keyiter = textkeys.begin(); - for(keyiter = textkeys.begin();keyiter != textkeys.end();keyiter++) - { - std::string::size_type sep = keyiter->second.find(':'); - if((sep == currentgroup.length() && keyiter->second.compare(0, sep, currentgroup) == 0) || - (sep == sizeof("soundgen")-1 && keyiter->second.compare(0, sep, "soundgen") == 0) || - (sep == sizeof("sound")-1 && keyiter->second.compare(0, sep, "sound") == 0)) - continue; - currentgroup = keyiter->second.substr(0, sep); - - if(skel->hasAnimation(currentgroup)) - continue; - - TextKeyMap::const_iterator lastkeyiter = textkeys.end(); - while((--lastkeyiter)->first > keyiter->first) - { - if(lastkeyiter->second.find(':') == currentgroup.length() && - lastkeyiter->second.compare(0, currentgroup.length(), currentgroup) == 0) - break; - } - - buildAnimation(skel, currentgroup, ctrls, targets, keyiter->first, lastkeyiter->first); - - TextKeyMap::const_iterator insiter(keyiter); - TextKeyMap groupkeys; - do { - sep = insiter->second.find(':'); - if(sep == currentgroup.length() && insiter->second.compare(0, sep, currentgroup) == 0) - groupkeys.insert(std::make_pair(insiter->first, insiter->second.substr(sep+2))); - else if((sep == sizeof("soundgen")-1 && insiter->second.compare(0, sep, "soundgen") == 0) || - (sep == sizeof("sound")-1 && insiter->second.compare(0, sep, "sound") == 0)) - groupkeys.insert(std::make_pair(insiter->first, insiter->second)); - } while(insiter++ != lastkeyiter); - - bindings.setUserAny(std::string(sTextKeyExtraDataID)+"@"+currentgroup, Ogre::Any(groupkeys)); - } -} - - -static Ogre::SkeletonPtr createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node) -{ - /* We need to be a little aggressive here, since some NIFs have a crap-ton - * of nodes and Ogre only supports 256 bones. We will skip a skeleton if: - * There are no bones used for skinning, there are no controllers on non- - * NiTriShape nodes, there are no nodes named "AttachLight", and the tree - * consists of NiNode, NiTriShape, and RootCollisionNode types only. - */ - if(!node->boneTrafo) - { - if(node->recType == Nif::RC_NiTriShape) - return Ogre::SkeletonPtr(); - if(node->controller.empty() && node->name != "AttachLight") - { - if(node->recType == Nif::RC_NiNode || node->recType == Nif::RC_RootCollisionNode) - { - const Nif::NiNode *ninode = static_cast(node); - const Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) - { - if(!children[i].empty()) - { - Ogre::SkeletonPtr skel = createSkeleton(name, group, children[i].getPtr()); - if(!skel.isNull()) - return skel; - } - } - return Ogre::SkeletonPtr(); - } - } - } - - Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); - return skelMgr.create(name, group, true, &sLoaders[name]); -} - -// Looks up an Ogre Bone handle ID from a NIF's record index. Should only be -// used when the bone name is insufficient as this is a relatively slow lookup -static int lookupOgreBoneHandle(const std::string &nifname, int idx) -{ - LoaderMap::const_iterator loader = sLoaders.find(nifname); - if(loader != sLoaders.end()) - { - std::map::const_iterator entry = loader->second.mNifToOgreHandleMap.find(idx); - if(entry != loader->second.mNifToOgreHandleMap.end()) - return entry->second; - } - throw std::runtime_error("Invalid NIF record lookup ("+nifname+", index "+Ogre::StringConverter::toString(idx)+")"); -} - -}; -NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders; - - // Conversion of blend / test mode from NIF static const char *getBlendFactor(int mode) { diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index 18bbf0200f..fa5182aeaa 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -25,11 +25,11 @@ #define OPENMW_COMPONENTS_NIFOGRE_OGRENIFLOADER_HPP #include -#include -#include +#include #include #include +#include // FIXME: This namespace really doesn't do anything Nif-specific. Any supportable diff --git a/components/nifogre/skeleton.cpp b/components/nifogre/skeleton.cpp new file mode 100644 index 0000000000..e97e91ef03 --- /dev/null +++ b/components/nifogre/skeleton.cpp @@ -0,0 +1,351 @@ +#include "skeleton.hpp" + +#include +#include +#include +#include + +#include +#include + +namespace NifOgre +{ + +void NIFSkeletonLoader::buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime) +{ + Ogre::Animation *anim = skel->createAnimation(name, stopTime); + + for(size_t i = 0;i < ctrls.size();i++) + { + const Nif::NiKeyframeController *kfc = ctrls[i]; + if(kfc->data.empty()) + continue; + const Nif::NiKeyframeData *kf = kfc->data.getPtr(); + + /* Get the keyframes and make sure they're sorted first to last */ + const Nif::QuaternionKeyList &quatkeys = kf->mRotations; + const Nif::Vector3KeyList &trankeys = kf->mTranslations; + const Nif::FloatKeyList &scalekeys = kf->mScales; + + Nif::QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin(); + Nif::Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin(); + Nif::FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin(); + + Ogre::Bone *bone = skel->getBone(targets[i]); + // NOTE: For some reason, Ogre doesn't like the node track ID being different from + // the bone ID + Ogre::NodeAnimationTrack *nodetrack = anim->hasNodeTrack(bone->getHandle()) ? + anim->getNodeTrack(bone->getHandle()) : + anim->createNodeTrack(bone->getHandle(), bone); + + Ogre::Quaternion lastquat, curquat; + Ogre::Vector3 lasttrans(0.0f), curtrans(0.0f); + Ogre::Vector3 lastscale(1.0f), curscale(1.0f); + if(quatiter != quatkeys.mKeys.end()) + lastquat = curquat = quatiter->mValue; + if(traniter != trankeys.mKeys.end()) + lasttrans = curtrans = traniter->mValue; + if(scaleiter != scalekeys.mKeys.end()) + lastscale = curscale = Ogre::Vector3(scaleiter->mValue); + + bool didlast = false; + while(!didlast) + { + float curtime = std::numeric_limits::max(); + + //Get latest time + if(quatiter != quatkeys.mKeys.end()) + curtime = std::min(curtime, quatiter->mTime); + if(traniter != trankeys.mKeys.end()) + curtime = std::min(curtime, traniter->mTime); + if(scaleiter != scalekeys.mKeys.end()) + curtime = std::min(curtime, scaleiter->mTime); + + curtime = std::max(curtime, startTime); + if(curtime >= stopTime) + { + didlast = true; + curtime = stopTime; + } + + // Get the latest quaternions, translations, and scales for the + // current time + while(quatiter != quatkeys.mKeys.end() && curtime >= quatiter->mTime) + { + lastquat = curquat; + if(++quatiter != quatkeys.mKeys.end()) + curquat = quatiter->mValue; + } + while(traniter != trankeys.mKeys.end() && curtime >= traniter->mTime) + { + lasttrans = curtrans; + if(++traniter != trankeys.mKeys.end()) + curtrans = traniter->mValue; + } + while(scaleiter != scalekeys.mKeys.end() && curtime >= scaleiter->mTime) + { + lastscale = curscale; + if(++scaleiter != scalekeys.mKeys.end()) + curscale = Ogre::Vector3(scaleiter->mValue); + } + + Ogre::TransformKeyFrame *kframe; + kframe = nodetrack->createNodeKeyFrame(curtime); + if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin()) + kframe->setRotation(curquat); + else + { + Nif::QuaternionKeyList::VecType::const_iterator last = quatiter-1; + float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime); + kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat)); + } + if(traniter == trankeys.mKeys.end() || traniter == trankeys.mKeys.begin()) + kframe->setTranslate(curtrans); + else + { + Nif::Vector3KeyList::VecType::const_iterator last = traniter-1; + float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime); + kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff)); + } + if(scaleiter == scalekeys.mKeys.end() || scaleiter == scalekeys.mKeys.begin()) + kframe->setScale(curscale); + else + { + Nif::FloatKeyList::VecType::const_iterator last = scaleiter-1; + float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime); + kframe->setScale(lastscale + ((curscale-lastscale)*diff)); + } + } + } + anim->optimise(); +} + + +TextKeyMap NIFSkeletonLoader::extractTextKeys(const Nif::NiTextKeyExtraData *tk) +{ + TextKeyMap textkeys; + for(size_t i = 0;i < tk->list.size();i++) + { + const std::string &str = tk->list[i].text; + std::string::size_type pos = 0; + while(pos < str.length()) + { + if(::isspace(str[pos])) + { + pos++; + continue; + } + + std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos)); + std::string result = str.substr(pos, nextpos-pos); + textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result))); + + pos = nextpos; + } + } + return textkeys; +} + +void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector &ctrls, Ogre::Bone *parent) +{ + Ogre::Bone *bone; + if(!skel->hasBone(node->name)) + bone = skel->createBone(node->name); + else + bone = skel->createBone(); + if(parent) parent->addChild(bone); + mNifToOgreHandleMap[node->recIndex] = bone->getHandle(); + + bone->setOrientation(node->trafo.rotation); + bone->setPosition(node->trafo.pos); + bone->setScale(Ogre::Vector3(node->trafo.scale)); + bone->setBindingPose(); + + if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ + node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */ + node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */ + node->recType == Nif::RC_NiCamera || + node->recType == Nif::RC_NiAutoNormalParticles || + node->recType == Nif::RC_NiRotatingParticles + )) + warn("Unhandled "+node->recName+" "+node->name+" in "+skel->getName()); + + Nif::ControllerPtr ctrl = node->controller; + while(!ctrl.empty()) + { + if(ctrl->recType == Nif::RC_NiKeyframeController) + ctrls.push_back(static_cast(ctrl.getPtr())); + else if(!(ctrl->recType == Nif::RC_NiParticleSystemController || + ctrl->recType == Nif::RC_NiVisController || + ctrl->recType == Nif::RC_NiUVController + )) + warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); + ctrl = ctrl->next; + } + + Nif::ExtraPtr e = node->extra; + while(!e.empty()) + { + if(e->recType == Nif::RC_NiTextKeyExtraData && !animroot) + { + const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); + textkeys = extractTextKeys(tk); + animroot = bone; + } + e = e->extra; + } + + const Nif::NiNode *ninode = dynamic_cast(node); + if(ninode) + { + const Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + buildBones(skel, children[i].getPtr(), animroot, textkeys, ctrls, bone); + } + } +} + +void NIFSkeletonLoader::loadResource(Ogre::Resource *resource) +{ + Ogre::Skeleton *skel = dynamic_cast(resource); + OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); + + Nif::NIFFile::ptr nif(Nif::NIFFile::create(skel->getName())); + const Nif::Node *node = static_cast(nif->getRoot(0)); + + std::vector ctrls; + Ogre::Bone *animroot = NULL; + TextKeyMap textkeys; + try { + buildBones(skel, node, animroot, textkeys, ctrls); + } + catch(std::exception &e) { + std::cerr<< "Exception while loading "<getName() < targets; + // TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file + if(ctrls.size() == 0) // No animations? Then we're done. + return; + + float maxtime = 0.0f; + for(size_t i = 0;i < ctrls.size();i++) + { + const Nif::NiKeyframeController *ctrl = ctrls[i]; + maxtime = std::max(maxtime, ctrl->timeStop); + Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); + if(target != NULL) + targets.push_back(target->name); + } + + if(targets.size() != ctrls.size()) + { + warn("Target size mismatch ("+Ogre::StringConverter::toString(targets.size())+" targets, "+ + Ogre::StringConverter::toString(ctrls.size())+" controllers)"); + return; + } + + Ogre::UserObjectBindings &bindings = animroot->getUserObjectBindings(); + bindings.setUserAny(sTextKeyExtraDataID, Ogre::Any(true)); + + std::string currentgroup; + TextKeyMap::const_iterator keyiter = textkeys.begin(); + for(keyiter = textkeys.begin();keyiter != textkeys.end();keyiter++) + { + std::string::size_type sep = keyiter->second.find(':'); + if((sep == currentgroup.length() && keyiter->second.compare(0, sep, currentgroup) == 0) || + (sep == sizeof("soundgen")-1 && keyiter->second.compare(0, sep, "soundgen") == 0) || + (sep == sizeof("sound")-1 && keyiter->second.compare(0, sep, "sound") == 0)) + continue; + currentgroup = keyiter->second.substr(0, sep); + + if(skel->hasAnimation(currentgroup)) + continue; + + TextKeyMap::const_iterator lastkeyiter = textkeys.end(); + while((--lastkeyiter)->first > keyiter->first) + { + if(lastkeyiter->second.find(':') == currentgroup.length() && + lastkeyiter->second.compare(0, currentgroup.length(), currentgroup) == 0) + break; + } + + buildAnimation(skel, currentgroup, ctrls, targets, keyiter->first, lastkeyiter->first); + + TextKeyMap::const_iterator insiter(keyiter); + TextKeyMap groupkeys; + do { + sep = insiter->second.find(':'); + if(sep == currentgroup.length() && insiter->second.compare(0, sep, currentgroup) == 0) + groupkeys.insert(std::make_pair(insiter->first, insiter->second.substr(sep+2))); + else if((sep == sizeof("soundgen")-1 && insiter->second.compare(0, sep, "soundgen") == 0) || + (sep == sizeof("sound")-1 && insiter->second.compare(0, sep, "sound") == 0)) + groupkeys.insert(std::make_pair(insiter->first, insiter->second)); + } while(insiter++ != lastkeyiter); + + bindings.setUserAny(std::string(sTextKeyExtraDataID)+"@"+currentgroup, Ogre::Any(groupkeys)); + } +} + + +Ogre::SkeletonPtr NIFSkeletonLoader::createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node) +{ + /* We need to be a little aggressive here, since some NIFs have a crap-ton + * of nodes and Ogre only supports 256 bones. We will skip a skeleton if: + * There are no bones used for skinning, there are no controllers on non- + * NiTriShape nodes, there are no nodes named "AttachLight", and the tree + * consists of NiNode, NiTriShape, and RootCollisionNode types only. + */ + if(!node->boneTrafo) + { + if(node->recType == Nif::RC_NiTriShape) + return Ogre::SkeletonPtr(); + if(node->controller.empty() && node->name != "AttachLight") + { + if(node->recType == Nif::RC_NiNode || node->recType == Nif::RC_RootCollisionNode) + { + const Nif::NiNode *ninode = static_cast(node); + const Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + { + Ogre::SkeletonPtr skel = createSkeleton(name, group, children[i].getPtr()); + if(!skel.isNull()) + return skel; + } + } + return Ogre::SkeletonPtr(); + } + } + } + + Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); + return skelMgr.create(name, group, true, &sLoaders[name]); +} + +// Looks up an Ogre Bone handle ID from a NIF's record index. Should only be +// used when the bone name is insufficient as this is a relatively slow lookup +int NIFSkeletonLoader::lookupOgreBoneHandle(const std::string &nifname, int idx) +{ + LoaderMap::const_iterator loader = sLoaders.find(nifname); + if(loader != sLoaders.end()) + { + std::map::const_iterator entry = loader->second.mNifToOgreHandleMap.find(idx); + if(entry != loader->second.mNifToOgreHandleMap.end()) + return entry->second; + } + throw std::runtime_error("Invalid NIF record lookup ("+nifname+", index "+Ogre::StringConverter::toString(idx)+")"); +} + +NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders; + +} diff --git a/components/nifogre/skeleton.hpp b/components/nifogre/skeleton.hpp new file mode 100644 index 0000000000..c69c2a12fe --- /dev/null +++ b/components/nifogre/skeleton.hpp @@ -0,0 +1,63 @@ +#ifndef COMPONENTS_NIFOGRE_SKELETON_HPP +#define COMPONENTS_NIFOGRE_SKELETON_HPP + +#include +#include +#include + +#include + +#include "ogrenifloader.hpp" + +namespace Nif +{ + class NiTextKeyExtraData; + class Node; + class NiKeyframeController; +} + +namespace NifOgre +{ + +/** Manual resource loader for NIF skeletons. This is the main class + responsible for translating the internal NIF skeleton structure into + something Ogre can use (includes animations and node TextKeyData). + */ +class NIFSkeletonLoader : public Ogre::ManualResourceLoader +{ + static void warn(const std::string &msg) + { + std::cerr << "NIFSkeletonLoader: Warn: " << msg << std::endl; + } + + static void fail(const std::string &msg) + { + std::cerr << "NIFSkeletonLoader: Fail: "<< msg << std::endl; + abort(); + } + + static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime); + + static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk); + void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector &ctrls, Ogre::Bone *parent=NULL); + + // Lookup to retrieve an Ogre bone handle for a given Nif record index + std::map mNifToOgreHandleMap; + + typedef std::map LoaderMap; + static LoaderMap sLoaders; + +public: + void loadResource(Ogre::Resource *resource); + + static Ogre::SkeletonPtr createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node); + + // Looks up an Ogre Bone handle ID from a NIF's record index. Should only + // be used when the bone name is insufficient as this is a relatively slow + // lookup + static int lookupOgreBoneHandle(const std::string &nifname, int idx); +}; + +} + +#endif From 39704077722ec64120d6764b8a7e0480cac051be Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 10 Apr 2013 20:22:13 -0700 Subject: [PATCH 191/198] Use actual classes for properties --- components/nif/property.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/components/nif/property.hpp b/components/nif/property.hpp index fd96ad0481..06c8260ce5 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -156,11 +156,11 @@ public: }; // These contain no other data than the 'flags' field in Property -typedef Property NiShadeProperty; -typedef Property NiDitherProperty; -typedef Property NiZBufferProperty; -typedef Property NiSpecularProperty; -typedef Property NiWireframeProperty; +class NiShadeProperty : public Property { }; +class NiDitherProperty : public Property { }; +class NiZBufferProperty : public Property { }; +class NiSpecularProperty : public Property { }; +class NiWireframeProperty : public Property { }; // The rest are all struct-based template @@ -324,10 +324,10 @@ struct S_StencilProperty } }; -typedef StructPropT NiAlphaProperty; -typedef StructPropT NiMaterialProperty; -typedef StructPropT NiVertexColorProperty; -typedef StructPropT NiStencilProperty; +class NiAlphaProperty : public StructPropT { }; +class NiMaterialProperty : public StructPropT { }; +class NiVertexColorProperty : public StructPropT { }; +class NiStencilProperty : public StructPropT { }; } // Namespace #endif From 75489b1e9d583da765dc3da4aedea0f9e8e7fa9b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 10 Apr 2013 20:24:44 -0700 Subject: [PATCH 192/198] Move NIFMaterialLoader to a separate file --- components/CMakeLists.txt | 2 +- components/nifogre/material.cpp | 399 ++++++++++++++++++++++++++ components/nifogre/material.hpp | 57 ++++ components/nifogre/ogrenifloader.cpp | 407 +-------------------------- 4 files changed, 458 insertions(+), 407 deletions(-) create mode 100644 components/nifogre/material.cpp create mode 100644 components/nifogre/material.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index d43725ee08..aa422b49e7 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -19,7 +19,7 @@ add_component_dir (nif ) add_component_dir (nifogre - ogrenifloader skeleton + ogrenifloader skeleton material ) add_component_dir (nifbullet diff --git a/components/nifogre/material.cpp b/components/nifogre/material.cpp new file mode 100644 index 0000000000..431b8219a9 --- /dev/null +++ b/components/nifogre/material.cpp @@ -0,0 +1,399 @@ +#include "material.hpp" + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + + +namespace NifOgre +{ + +// Conversion of blend / test mode from NIF +static const char *getBlendFactor(int mode) +{ + switch(mode) + { + case 0: return "one"; + case 1: return "zero"; + case 2: return "src_colour"; + case 3: return "one_minus_src_colour"; + case 4: return "dest_colour"; + case 5: return "one_minus_dest_colour"; + case 6: return "src_alpha"; + case 7: return "one_minus_src_alpha"; + case 8: return "dest_alpha"; + case 9: return "one_minus_dest_alpha"; + case 10: return "src_alpha_saturate"; + } + std::cerr<< "Unexpected blend mode: "<colors.size() != 0); + + // Texture + if(texprop) + { + for(int i = 0;i < 7;i++) + { + if(!texprop->textures[i].inUse) + continue; + if(texprop->textures[i].texture.empty()) + { + warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name); + continue; + } + + const Nif::NiSourceTexture *st = texprop->textures[i].texture.getPtr(); + if(st->external) + texName[i] = findTextureName(st->filename); + else + warn("Found internal texture, ignoring."); + } + + Nif::ControllerPtr ctrls = texprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled texture controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + needTangents = !texName[Nif::NiTexturingProperty::BumpTexture].empty(); + + // Alpha modifiers + if(alphaprop) + { + alphaFlags = alphaprop->flags; + alphaTest = alphaprop->data.threshold; + + Nif::ControllerPtr ctrls = alphaprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled alpha controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + + // Vertex color handling + if(vertprop) + { + vertMode = vertprop->data.vertmode; + // FIXME: Handle lightmode? + //lightMode = vertprop->data.lightmode; + + Nif::ControllerPtr ctrls = vertprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled vertex color controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + + if(zprop) + { + depthFlags = zprop->flags; + // Depth function??? + + Nif::ControllerPtr ctrls = zprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled depth controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + + if(specprop) + { + specFlags = specprop->flags; + + Nif::ControllerPtr ctrls = specprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled specular controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + + if(wireprop) + { + wireFlags = wireprop->flags; + + Nif::ControllerPtr ctrls = wireprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled wireframe controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + + // Material + if(matprop) + { + ambient = matprop->data.ambient; + diffuse = matprop->data.diffuse; + specular = matprop->data.specular; + emissive = matprop->data.emissive; + glossiness = matprop->data.glossiness; + alpha = matprop->data.alpha; + + Nif::ControllerPtr ctrls = matprop->controller; + while(!ctrls.empty()) + { + warn("Unhandled material controller "+ctrls->recName+" in "+name); + ctrls = ctrls->next; + } + } + + { + // Generate a hash out of all properties that can affect the material. + size_t h = 0; + boost::hash_combine(h, ambient.x); + boost::hash_combine(h, ambient.y); + boost::hash_combine(h, ambient.z); + boost::hash_combine(h, diffuse.x); + boost::hash_combine(h, diffuse.y); + boost::hash_combine(h, diffuse.z); + boost::hash_combine(h, alpha); + boost::hash_combine(h, specular.x); + boost::hash_combine(h, specular.y); + boost::hash_combine(h, specular.z); + boost::hash_combine(h, glossiness); + boost::hash_combine(h, emissive.x); + boost::hash_combine(h, emissive.y); + boost::hash_combine(h, emissive.z); + for(int i = 0;i < 7;i++) + { + if(!texName[i].empty()) + boost::hash_combine(h, texName[i]); + } + boost::hash_combine(h, vertexColour); + boost::hash_combine(h, alphaFlags); + boost::hash_combine(h, alphaTest); + boost::hash_combine(h, vertMode); + boost::hash_combine(h, depthFlags); + boost::hash_combine(h, specFlags); + boost::hash_combine(h, wireFlags); + + std::map::iterator itr = sMaterialMap.find(h); + if (itr != sMaterialMap.end()) + { + // a suitable material exists already - use it + return itr->second; + } + // not found, create a new one + sMaterialMap.insert(std::make_pair(h, name)); + } + + // No existing material like this. Create a new one. + sh::MaterialInstance *instance = sh::Factory::getInstance().createMaterialInstance(name, "openmw_objects_base"); + if(vertMode == 0 || !vertexColour) + { + instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); + instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); + instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); + instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("0"))); + } + else if(vertMode == 1) + { + instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); + instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); + instance->setProperty("emissive", sh::makeProperty(new sh::StringValue("vertexcolour"))); + instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("1"))); + } + else if(vertMode == 2) + { + instance->setProperty("ambient", sh::makeProperty(new sh::StringValue("vertexcolour"))); + instance->setProperty("diffuse", sh::makeProperty(new sh::StringValue("vertexcolour"))); + instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); + instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("2"))); + } + else + std::cerr<< "Unhandled vertex mode: "<setProperty("specular", sh::makeProperty( + new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); + } + + if(wireFlags) + { + instance->setProperty("polygon_mode", sh::makeProperty(new sh::StringValue("wireframe"))); + } + + instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); + instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); + instance->setProperty("detailMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DetailTexture])); + instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); + if (!texName[Nif::NiTexturingProperty::GlowTexture].empty()) + { + instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true))); + instance->setProperty("emissiveMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::GlowTexture].uvSet))); + } + if (!texName[Nif::NiTexturingProperty::DetailTexture].empty()) + { + instance->setProperty("use_detail_map", sh::makeProperty(new sh::BooleanValue(true))); + instance->setProperty("detailMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::DetailTexture].uvSet))); + } + if (!texName[Nif::NiTexturingProperty::BumpTexture].empty()) + { + // force automips on normal maps for now + instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture] + " 4")); + } + + for(int i = 0;i < 7;i++) + { + if(i == Nif::NiTexturingProperty::BaseTexture || + i == Nif::NiTexturingProperty::DetailTexture || + i == Nif::NiTexturingProperty::BumpTexture || + i == Nif::NiTexturingProperty::GlowTexture) + continue; + if(!texName[i].empty()) + warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)); + } + + if (vertexColour) + instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); + + // Add transparency if NiAlphaProperty was present + NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName[0]); + if (result.first) + { + alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */ + alphaTest = result.second; + depthFlags = (1<<0) | (1<<1); // depth_write on, depth_check on + } + + if((alphaFlags&1)) + { + std::string blend_mode; + blend_mode += getBlendFactor((alphaFlags>>1)&0xf); + blend_mode += " "; + blend_mode += getBlendFactor((alphaFlags>>5)&0xf); + instance->setProperty("scene_blend", sh::makeProperty(new sh::StringValue(blend_mode))); + } + + if((alphaFlags>>9)&1) + { + std::string reject; + reject += getTestMode((alphaFlags>>10)&0x7); + reject += " "; + reject += Ogre::StringConverter::toString(alphaTest); + instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); + } + else + instance->getMaterial()->setShadowCasterMaterial("openmw_shadowcaster_noalpha"); + + // Ogre usually only sorts if depth write is disabled, so we want "force" instead of "on" + instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue( + ((alphaFlags&1) && !((alphaFlags>>13)&1)) ? "force" : "off"))); + + instance->setProperty("depth_check", sh::makeProperty(new sh::StringValue((depthFlags&1) ? "on" : "off"))); + instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue(((depthFlags>>1)&1) ? "on" : "off"))); + // depth_func??? + + sh::Factory::getInstance()._ensureMaterial(name, "Default"); + return name; +} + +std::map NIFMaterialLoader::sMaterialMap; + +} diff --git a/components/nifogre/material.hpp b/components/nifogre/material.hpp new file mode 100644 index 0000000000..8843ac6c6c --- /dev/null +++ b/components/nifogre/material.hpp @@ -0,0 +1,57 @@ +#ifndef COMPONENTS_NIFOGRE_MATERIAL_HPP +#define COMPONENTS_NIFOGRE_MATERIAL_HPP + +#include +#include +#include +#include + +#include + +namespace Nif +{ + class ShapeData; + class NiTexturingProperty; + class NiMaterialProperty; + class NiAlphaProperty; + class NiVertexColorProperty; + class NiZBufferProperty; + class NiSpecularProperty; + class NiWireframeProperty; +} + +namespace NifOgre +{ + +class NIFMaterialLoader { + static void warn(const std::string &msg) + { + std::cerr << "NIFMaterialLoader: Warn: " << msg << std::endl; + } + + static void fail(const std::string &msg) + { + std::cerr << "NIFMaterialLoader: Fail: "<< msg << std::endl; + abort(); + } + + static std::map sMaterialMap; + + static std::string findTextureName(const std::string &filename); + +public: + static Ogre::String getMaterial(const Nif::ShapeData *shapedata, + const Ogre::String &name, const Ogre::String &group, + const Nif::NiTexturingProperty *texprop, + const Nif::NiMaterialProperty *matprop, + const Nif::NiAlphaProperty *alphaprop, + const Nif::NiVertexColorProperty *vertprop, + const Nif::NiZBufferProperty *zprop, + const Nif::NiSpecularProperty *specprop, + const Nif::NiWireframeProperty *wireprop, + bool &needTangents); +}; + +} + +#endif diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 0a30f38bd1..3bd93a1b9f 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -40,18 +40,11 @@ #include #include -#include -#include -#include - -#include - #include #include -#include -#include #include "skeleton.hpp" +#include "material.hpp" namespace std { @@ -424,404 +417,6 @@ public: }; -// Conversion of blend / test mode from NIF -static const char *getBlendFactor(int mode) -{ - switch(mode) - { - case 0: return "one"; - case 1: return "zero"; - case 2: return "src_colour"; - case 3: return "one_minus_src_colour"; - case 4: return "dest_colour"; - case 5: return "one_minus_dest_colour"; - case 6: return "src_alpha"; - case 7: return "one_minus_src_alpha"; - case 8: return "dest_alpha"; - case 9: return "one_minus_dest_alpha"; - case 10: return "src_alpha_saturate"; - } - std::cerr<< "Unexpected blend mode: "< MaterialMap; - -static void warn(const std::string &msg) -{ - std::cerr << "NIFMaterialLoader: Warn: " << msg << std::endl; -} - -static void fail(const std::string &msg) -{ - std::cerr << "NIFMaterialLoader: Fail: "<< msg << std::endl; - abort(); -} - - -static std::string findTextureName(const std::string &filename) -{ - /* Bethesda at some point converted all their BSA - * textures from tga to dds for increased load speed, but all - * texture file name references were kept as .tga. - */ - static const char path[] = "textures\\"; - static const char path2[] = "textures/"; - - - std::string texname = filename; - Misc::StringUtils::toLower(texname); - - if(texname.compare(0, sizeof(path)-1, path) != 0 - && texname.compare(0, sizeof(path2)-1, path2) != 0) - texname = path + texname; - - Ogre::String::size_type pos = texname.rfind('.'); - if(pos != Ogre::String::npos && texname.compare(pos, texname.length() - pos, ".dds") != 0) - { - // since we know all (GOTY edition or less) textures end - // in .dds, we change the extension - texname.replace(pos, texname.length(), ".dds"); - - // if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods) - // verify, and revert if false (this call succeeds quickly, but fails slowly) - if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texname)) - { - texname = filename; - Misc::StringUtils::toLower(texname); - if(texname.compare(0, sizeof(path)-1, path) != 0 - && texname.compare(0, sizeof(path2)-1, path2) != 0) - texname = path + texname; - } - } - - return texname; -} - -public: -static Ogre::String getMaterial(const Nif::ShapeData *shapedata, - const Ogre::String &name, const Ogre::String &group, - const Nif::NiTexturingProperty *texprop, - const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop, - const Nif::NiSpecularProperty *specprop, - const Nif::NiWireframeProperty *wireprop, - bool &needTangents) -{ - Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); - Ogre::MaterialPtr material = matMgr.getByName(name); - if(!material.isNull()) - return name; - - Ogre::Vector3 ambient(1.0f); - Ogre::Vector3 diffuse(1.0f); - Ogre::Vector3 specular(0.0f); - Ogre::Vector3 emissive(0.0f); - float glossiness = 0.0f; - float alpha = 1.0f; - int alphaFlags = 0; - int alphaTest = 0; - int vertMode = 2; - //int lightMode = 1; - int depthFlags = 3; - // Default should be 1, but Bloodmoon's models are broken - int specFlags = 0; - int wireFlags = 0; - Ogre::String texName[7]; - - bool vertexColour = (shapedata->colors.size() != 0); - - // Texture - if(texprop) - { - for(int i = 0;i < 7;i++) - { - if(!texprop->textures[i].inUse) - continue; - if(texprop->textures[i].texture.empty()) - { - warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name); - continue; - } - - const Nif::NiSourceTexture *st = texprop->textures[i].texture.getPtr(); - if(st->external) - texName[i] = findTextureName(st->filename); - else - warn("Found internal texture, ignoring."); - } - - Nif::ControllerPtr ctrls = texprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled texture controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - needTangents = !texName[Nif::NiTexturingProperty::BumpTexture].empty(); - - // Alpha modifiers - if(alphaprop) - { - alphaFlags = alphaprop->flags; - alphaTest = alphaprop->data.threshold; - - Nif::ControllerPtr ctrls = alphaprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled alpha controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - // Vertex color handling - if(vertprop) - { - vertMode = vertprop->data.vertmode; - // FIXME: Handle lightmode? - //lightMode = vertprop->data.lightmode; - - Nif::ControllerPtr ctrls = vertprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled vertex color controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(zprop) - { - depthFlags = zprop->flags; - // Depth function??? - - Nif::ControllerPtr ctrls = zprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled depth controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(specprop) - { - specFlags = specprop->flags; - - Nif::ControllerPtr ctrls = specprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled specular controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(wireprop) - { - wireFlags = wireprop->flags; - - Nif::ControllerPtr ctrls = wireprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled wireframe controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - // Material - if(matprop) - { - ambient = matprop->data.ambient; - diffuse = matprop->data.diffuse; - specular = matprop->data.specular; - emissive = matprop->data.emissive; - glossiness = matprop->data.glossiness; - alpha = matprop->data.alpha; - - Nif::ControllerPtr ctrls = matprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled material controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - { - // Generate a hash out of all properties that can affect the material. - size_t h = 0; - boost::hash_combine(h, ambient.x); - boost::hash_combine(h, ambient.y); - boost::hash_combine(h, ambient.z); - boost::hash_combine(h, diffuse.x); - boost::hash_combine(h, diffuse.y); - boost::hash_combine(h, diffuse.z); - boost::hash_combine(h, alpha); - boost::hash_combine(h, specular.x); - boost::hash_combine(h, specular.y); - boost::hash_combine(h, specular.z); - boost::hash_combine(h, glossiness); - boost::hash_combine(h, emissive.x); - boost::hash_combine(h, emissive.y); - boost::hash_combine(h, emissive.z); - for(int i = 0;i < 7;i++) - { - if(!texName[i].empty()) - boost::hash_combine(h, texName[i]); - } - boost::hash_combine(h, vertexColour); - boost::hash_combine(h, alphaFlags); - boost::hash_combine(h, alphaTest); - boost::hash_combine(h, vertMode); - boost::hash_combine(h, depthFlags); - boost::hash_combine(h, specFlags); - boost::hash_combine(h, wireFlags); - - std::map::iterator itr = MaterialMap.find(h); - if (itr != MaterialMap.end()) - { - // a suitable material exists already - use it - return itr->second; - } - // not found, create a new one - MaterialMap.insert(std::make_pair(h, name)); - } - - // No existing material like this. Create a new one. - sh::MaterialInstance *instance = sh::Factory::getInstance().createMaterialInstance(name, "openmw_objects_base"); - if(vertMode == 0 || !vertexColour) - { - instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); - instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); - instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("0"))); - } - else if(vertMode == 1) - { - instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); - instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - instance->setProperty("emissive", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("1"))); - } - else if(vertMode == 2) - { - instance->setProperty("ambient", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("diffuse", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); - instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("2"))); - } - else - std::cerr<< "Unhandled vertex mode: "<setProperty("specular", sh::makeProperty( - new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); - } - - if(wireFlags) - { - instance->setProperty("polygon_mode", sh::makeProperty(new sh::StringValue("wireframe"))); - } - - instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); - instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); - instance->setProperty("detailMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DetailTexture])); - instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); - if (!texName[Nif::NiTexturingProperty::GlowTexture].empty()) - { - instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true))); - instance->setProperty("emissiveMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::GlowTexture].uvSet))); - } - if (!texName[Nif::NiTexturingProperty::DetailTexture].empty()) - { - instance->setProperty("use_detail_map", sh::makeProperty(new sh::BooleanValue(true))); - instance->setProperty("detailMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::DetailTexture].uvSet))); - } - if (!texName[Nif::NiTexturingProperty::BumpTexture].empty()) - { - // force automips on normal maps for now - instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture] + " 4")); - } - - for(int i = 0;i < 7;i++) - { - if(i == Nif::NiTexturingProperty::BaseTexture || - i == Nif::NiTexturingProperty::DetailTexture || - i == Nif::NiTexturingProperty::BumpTexture || - i == Nif::NiTexturingProperty::GlowTexture) - continue; - if(!texName[i].empty()) - warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i)); - } - - if (vertexColour) - instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); - - // Add transparency if NiAlphaProperty was present - NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName[0]); - if (result.first) - { - alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */ - alphaTest = result.second; - depthFlags = (1<<0) | (1<<1); // depth_write on, depth_check on - } - - if((alphaFlags&1)) - { - std::string blend_mode; - blend_mode += getBlendFactor((alphaFlags>>1)&0xf); - blend_mode += " "; - blend_mode += getBlendFactor((alphaFlags>>5)&0xf); - instance->setProperty("scene_blend", sh::makeProperty(new sh::StringValue(blend_mode))); - } - - if((alphaFlags>>9)&1) - { - std::string reject; - reject += getTestMode((alphaFlags>>10)&0x7); - reject += " "; - reject += Ogre::StringConverter::toString(alphaTest); - instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); - } - else - instance->getMaterial()->setShadowCasterMaterial("openmw_shadowcaster_noalpha"); - - // Ogre usually only sorts if depth write is disabled, so we want "force" instead of "on" - instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue( - ((alphaFlags&1) && !((alphaFlags>>13)&1)) ? "force" : "off"))); - - instance->setProperty("depth_check", sh::makeProperty(new sh::StringValue((depthFlags&1) ? "on" : "off"))); - instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue(((depthFlags>>1)&1) ? "on" : "off"))); - // depth_func??? - - sh::Factory::getInstance()._ensureMaterial(name, "Default"); - return name; -} - -}; -std::map NIFMaterialLoader::MaterialMap; - - /** Manual resource loader for NIF objects (meshes, particle systems, etc). * This is the main class responsible for translating the internal NIF * structures into something Ogre can use. From 6128b9276f35d75c6fccb5a05e458fc8537ac5bc Mon Sep 17 00:00:00 2001 From: Britt Mathis Date: Thu, 11 Apr 2013 00:21:56 -0400 Subject: [PATCH 193/198] Removed non-essential includes from all MWGui header files. --- apps/openmw/mwgui/alchemywindow.hpp | 2 +- apps/openmw/mwgui/charactercreation.hpp | 4 ---- apps/openmw/mwgui/container.hpp | 3 --- apps/openmw/mwgui/cursor.hpp | 1 - apps/openmw/mwgui/dialogue.hpp | 3 --- apps/openmw/mwgui/dialoguehistory.hpp | 1 + apps/openmw/mwgui/enchantingdialog.hpp | 2 -- apps/openmw/mwgui/hud.hpp | 2 -- apps/openmw/mwgui/itemselection.hpp | 2 -- apps/openmw/mwgui/journalwindow.hpp | 3 --- apps/openmw/mwgui/list.hpp | 1 - apps/openmw/mwgui/loadingscreen.hpp | 1 - apps/openmw/mwgui/messagebox.hpp | 2 -- apps/openmw/mwgui/quickkeysmenu.hpp | 1 - apps/openmw/mwgui/race.hpp | 5 ----- apps/openmw/mwgui/repair.hpp | 1 - apps/openmw/mwgui/review.hpp | 1 - apps/openmw/mwgui/statswindow.hpp | 5 ----- apps/openmw/mwgui/tradewindow.hpp | 3 --- apps/openmw/mwgui/travelwindow.hpp | 3 --- apps/openmw/mwgui/widgets.hpp | 2 -- apps/openmw/mwgui/windowmanagerimp.hpp | 5 ----- 22 files changed, 2 insertions(+), 51 deletions(-) diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index c61d2f92b3..655a832c17 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -5,12 +5,12 @@ #include "../mwmechanics/alchemy.hpp" -#include "windowbase.hpp" #include "container.hpp" #include "widgets.hpp" namespace MWGui { + class AlchemyWindow : public WindowBase, public ContainerBase { public: diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index fed77e889f..586faf966e 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -1,13 +1,9 @@ #ifndef CHARACTER_CREATION_HPP #define CHARACTER_CREATION_HPP -#include "../mwworld/esmstore.hpp" - #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwmechanics/stat.hpp" - namespace MWGui { class WindowBase; diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 521ac8cc35..8440c6444e 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -1,13 +1,10 @@ #ifndef MGUI_CONTAINER_H #define MGUI_CONTAINER_H -#include "../mwworld/esmstore.hpp" - #include "windowbase.hpp" #include "referenceinterface.hpp" #include "../mwclass/container.hpp" -#include "../mwworld/ptr.hpp" #include "../mwworld/containerstore.hpp" diff --git a/apps/openmw/mwgui/cursor.hpp b/apps/openmw/mwgui/cursor.hpp index 3a4a05f4ca..badf82262b 100644 --- a/apps/openmw/mwgui/cursor.hpp +++ b/apps/openmw/mwgui/cursor.hpp @@ -3,7 +3,6 @@ #include #include -#include namespace MWGui { diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index a1bbee02c7..74fa8051c5 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -3,9 +3,6 @@ #include "windowbase.hpp" #include "referenceinterface.hpp" -#include - -#include "../mwworld/ptr.hpp" namespace MWGui { diff --git a/apps/openmw/mwgui/dialoguehistory.hpp b/apps/openmw/mwgui/dialoguehistory.hpp index c37504af77..4cf6de621d 100644 --- a/apps/openmw/mwgui/dialoguehistory.hpp +++ b/apps/openmw/mwgui/dialoguehistory.hpp @@ -1,5 +1,6 @@ #ifndef MWGUI_DIALOGE_HISTORY_H #define MWGUI_DIALOGE_HISTORY_H + #include namespace MWGui diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index c727a09749..8bad60c8e6 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -1,8 +1,6 @@ #ifndef MWGUI_ENCHANTINGDIALOG_H #define MWGUI_ENCHANTINGDIALOG_H -#include "windowbase.hpp" -#include "referenceinterface.hpp" #include "spellcreationdialog.hpp" #include "../mwbase/windowmanager.hpp" diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index c65566ce3e..1dd53683b8 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -1,7 +1,5 @@ #include "mapwindow.hpp" -#include - #include "../mwmechanics/stat.hpp" #include "../mwworld/ptr.hpp" diff --git a/apps/openmw/mwgui/itemselection.hpp b/apps/openmw/mwgui/itemselection.hpp index 3e812d26c5..19007de6b0 100644 --- a/apps/openmw/mwgui/itemselection.hpp +++ b/apps/openmw/mwgui/itemselection.hpp @@ -1,7 +1,5 @@ #include "container.hpp" -#include "../mwworld/ptr.hpp" - namespace MWGui { diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 7670b65f55..da05a6f0ec 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -1,10 +1,7 @@ #ifndef MWGUI_JOURNAL_H #define MWGUI_JOURNAL_H -#include -#include #include -#include #include "windowbase.hpp" #include "imagebutton.hpp" diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index 09e42e865e..956523c0dc 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -1,7 +1,6 @@ #ifndef MWGUI_LIST_HPP #define MWGUI_LIST_HPP -#include #include namespace MWGui diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 12e6504bca..87cedaa98c 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -2,7 +2,6 @@ #define MWGUI_LOADINGSCREEN_H #include -#include #include "windowbase.hpp" diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index cb40739023..0df6f3544b 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -1,8 +1,6 @@ #ifndef MWGUI_MESSAGE_BOX_H #define MWGUI_MESSAGE_BOX_H -#include - #include "windowbase.hpp" #include "../mwbase/windowmanager.hpp" diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 646ec2aa45..058519ece4 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -1,7 +1,6 @@ #ifndef MWGUI_QUICKKEYS_H #define MWGUI_QUICKKEYS_H - #include "../mwworld/ptr.hpp" #include "windowbase.hpp" diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index f3adce4447..893c4c90b6 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -1,11 +1,6 @@ #ifndef MWGUI_RACE_H #define MWGUI_RACE_H - -#include - -#include "../mwworld/esmstore.hpp" - #include "../mwrender/characterpreview.hpp" #include "windowbase.hpp" diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index 5d9a487199..d0f5c54c4b 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -3,7 +3,6 @@ #include "windowbase.hpp" -#include "../mwworld/ptr.hpp" #include "../mwmechanics/repair.hpp" namespace MWGui diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index d5df94e285..87d6fedfa7 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -2,7 +2,6 @@ #define MWGUI_REVIEW_H #include "windowbase.hpp" -#include "../mwmechanics/stat.hpp" #include "widgets.hpp" namespace MWGui diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index 4b723048cc..bec42d029b 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -3,11 +3,6 @@ #include "../mwworld/esmstore.hpp" -#include -#include -#include -#include - #include "../mwmechanics/stat.hpp" #include "windowpinnablebase.hpp" diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index e526a42ca5..892ce0297c 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -2,9 +2,6 @@ #define MWGUI_TRADEWINDOW_H #include "container.hpp" -#include "windowbase.hpp" - -#include "../mwworld/ptr.hpp" namespace MyGUI { diff --git a/apps/openmw/mwgui/travelwindow.hpp b/apps/openmw/mwgui/travelwindow.hpp index a814d04785..f2a23b0486 100644 --- a/apps/openmw/mwgui/travelwindow.hpp +++ b/apps/openmw/mwgui/travelwindow.hpp @@ -2,9 +2,6 @@ #define MWGUI_TravelWINDOW_H #include "container.hpp" -#include "windowbase.hpp" - -#include "../mwworld/ptr.hpp" namespace MyGUI { diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 038ce3f86f..1567946913 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -4,8 +4,6 @@ #include "../mwworld/esmstore.hpp" #include "../mwmechanics/stat.hpp" -#include -#include #include #include diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 3c9fc586a3..652ad870f3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -10,11 +10,6 @@ this class. **/ -#include -#include - -#include - #include "../mwbase/windowmanager.hpp" namespace MyGUI From 62e0abd94582060951c887ac6a1782ea1644aa2f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 10 Apr 2013 22:38:46 -0700 Subject: [PATCH 194/198] Move the mesh loader to its own source file --- components/CMakeLists.txt | 2 +- components/nifogre/mesh.cpp | 375 +++++++++++++++++++ components/nifogre/mesh.hpp | 55 +++ components/nifogre/ogrenifloader.cpp | 526 +++++---------------------- 4 files changed, 516 insertions(+), 442 deletions(-) create mode 100644 components/nifogre/mesh.cpp create mode 100644 components/nifogre/mesh.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index aa422b49e7..dd8f78eda6 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -19,7 +19,7 @@ add_component_dir (nif ) add_component_dir (nifogre - ogrenifloader skeleton material + ogrenifloader skeleton material mesh ) add_component_dir (nifbullet diff --git a/components/nifogre/mesh.cpp b/components/nifogre/mesh.cpp new file mode 100644 index 0000000000..3780306f6d --- /dev/null +++ b/components/nifogre/mesh.cpp @@ -0,0 +1,375 @@ +#include "mesh.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "material.hpp" + +namespace NifOgre +{ + +void getNodeProperties(const Nif::Node *node, + const Nif::NiTexturingProperty *&texprop, + const Nif::NiMaterialProperty *&matprop, + const Nif::NiAlphaProperty *&alphaprop, + const Nif::NiVertexColorProperty *&vertprop, + const Nif::NiZBufferProperty *&zprop, + const Nif::NiSpecularProperty *&specprop, + const Nif::NiWireframeProperty *&wireprop); + +// Helper class that computes the bounding box and of a mesh +class BoundsFinder +{ + struct MaxMinFinder + { + float max, min; + + MaxMinFinder() + { + min = std::numeric_limits::infinity(); + max = -min; + } + + void add(float f) + { + if (f > max) max = f; + if (f < min) min = f; + } + + // Return Max(max**2, min**2) + float getMaxSquared() + { + float m1 = max*max; + float m2 = min*min; + if (m1 >= m2) return m1; + return m2; + } + }; + + MaxMinFinder X, Y, Z; + +public: + // Add 'verts' vertices to the calculation. The 'data' pointer is + // expected to point to 3*verts floats representing x,y,z for each + // point. + void add(float *data, int verts) + { + for (int i=0;idata.getPtr(); + const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); + std::vector srcVerts = data->vertices; + std::vector srcNorms = data->normals; + Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC; + bool vertShadowBuffer = false; + if(skin != NULL) + { + vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; + vertShadowBuffer = true; + + // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be + // explicitly attached later. + mesh->setSkeletonName(mName); + + // Get the skeleton resource, so vertices can be transformed into the bones' initial state. + Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); + skel = skelMgr->getByName(mName); + + // Convert vertices and normals to bone space from bind position. It would be + // better to transform the bones into bind position, but there doesn't seem to + // be a reliable way to do that. + std::vector newVerts(srcVerts.size(), Ogre::Vector3(0.0f)); + std::vector newNorms(srcNorms.size(), Ogre::Vector3(0.0f)); + + const Nif::NiSkinData *data = skin->data.getPtr(); + const Nif::NodeList &bones = skin->bones; + for(size_t b = 0;b < bones.length();b++) + { + Ogre::Bone *bone = skel->getBone(bones[b]->name); + Ogre::Matrix4 mat; + mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), + Ogre::Quaternion(data->bones[b].trafo.rotation)); + mat = bone->_getFullTransform() * mat; + + const std::vector &weights = data->bones[b].weights; + for(size_t i = 0;i < weights.size();i++) + { + size_t index = weights[i].vertex; + float weight = weights[i].weight; + + newVerts.at(index) += (mat*srcVerts[index]) * weight; + if(newNorms.size() > index) + { + Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f); + vec4 = mat*vec4 * weight; + newNorms[index] += Ogre::Vector3(&vec4[0]); + } + } + } + + srcVerts = newVerts; + srcNorms = newNorms; + } + else + { + Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); + if(skelMgr->getByName(mName).isNull()) + { + // No skinning and no skeleton, so just transform the vertices and + // normals into position. + Ogre::Matrix4 mat4 = shape->getWorldTransform(); + for(size_t i = 0;i < srcVerts.size();i++) + { + Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f); + vec4 = mat4*vec4; + srcVerts[i] = Ogre::Vector3(&vec4[0]); + } + for(size_t i = 0;i < srcNorms.size();i++) + { + Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f); + vec4 = mat4*vec4; + srcNorms[i] = Ogre::Vector3(&vec4[0]); + } + } + } + + // Set the bounding box first + BoundsFinder bounds; + bounds.add(&srcVerts[0][0], srcVerts.size()); + if(!bounds.isValid()) + { + float v[3] = { 0.0f, 0.0f, 0.0f }; + bounds.add(&v[0], 1); + } + + mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f, + bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f)); + mesh->_setBoundingSphereRadius(bounds.getRadius()); + + // This function is just one long stream of Ogre-barf, but it works + // great. + Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr(); + Ogre::HardwareVertexBufferSharedPtr vbuf; + Ogre::HardwareIndexBufferSharedPtr ibuf; + Ogre::VertexBufferBinding *bind; + Ogre::VertexDeclaration *decl; + int nextBuf = 0; + + Ogre::SubMesh *sub = mesh->createSubMesh(); + + // Add vertices + sub->useSharedVertices = false; + sub->vertexData = new Ogre::VertexData(); + sub->vertexData->vertexStart = 0; + sub->vertexData->vertexCount = srcVerts.size(); + + decl = sub->vertexData->vertexDeclaration; + bind = sub->vertexData->vertexBufferBinding; + if(srcVerts.size()) + { + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), + srcVerts.size(), vertUsage, vertShadowBuffer); + vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true); + + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + bind->setBinding(nextBuf++, vbuf); + } + + // Vertex normals + if(srcNorms.size()) + { + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), + srcNorms.size(), vertUsage, vertShadowBuffer); + vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true); + + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); + bind->setBinding(nextBuf++, vbuf); + } + + // Vertex colors + const std::vector &colors = data->colors; + if(colors.size()) + { + Ogre::RenderSystem *rs = Ogre::Root::getSingleton().getRenderSystem(); + std::vector colorsRGB(colors.size()); + for(size_t i = 0;i < colorsRGB.size();i++) + { + Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]); + rs->convertColourValue(clr, &colorsRGB[i]); + } + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), + colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC); + vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true); + decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); + bind->setBinding(nextBuf++, vbuf); + } + + // Texture UV coordinates + size_t numUVs = data->uvlist.size(); + for(size_t i = 0;i < numUVs;i++) + { + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2), + srcVerts.size(), Ogre::HardwareBuffer::HBU_STATIC); + vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[i][0], true); + + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i); + bind->setBinding(nextBuf++, vbuf); + } + + // Triangle faces + const std::vector &srcIdx = data->triangles; + if(srcIdx.size()) + { + ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(), + Ogre::HardwareBuffer::HBU_STATIC); + ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true); + sub->indexData->indexBuffer = ibuf; + sub->indexData->indexCount = srcIdx.size(); + sub->indexData->indexStart = 0; + } + + // Assign bone weights for this TriShape + if(skin != NULL) + { + const Nif::NiSkinData *data = skin->data.getPtr(); + const Nif::NodeList &bones = skin->bones; + for(size_t i = 0;i < bones.length();i++) + { + Ogre::VertexBoneAssignment boneInf; + boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle(); + + const std::vector &weights = data->bones[i].weights; + for(size_t j = 0;j < weights.size();j++) + { + boneInf.vertexIndex = weights[j].vertex; + boneInf.weight = weights[j].weight; + sub->addBoneAssignment(boneInf); + } + } + } + + const Nif::NiTexturingProperty *texprop = NULL; + const Nif::NiMaterialProperty *matprop = NULL; + const Nif::NiAlphaProperty *alphaprop = NULL; + const Nif::NiVertexColorProperty *vertprop = NULL; + const Nif::NiZBufferProperty *zprop = NULL; + const Nif::NiSpecularProperty *specprop = NULL; + const Nif::NiWireframeProperty *wireprop = NULL; + bool needTangents = false; + + getNodeProperties(shape, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); + std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, + texprop, matprop, alphaprop, + vertprop, zprop, specprop, + wireprop, needTangents); + if(matname.length() > 0) + sub->setMaterialName(matname); + + // build tangents if the material needs them + if (needTangents) + { + unsigned short src,dest; + if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest)) + mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest); + } +} + + +NIFMeshLoader::NIFMeshLoader(const std::string &name, const std::string &group, size_t idx) + : mName(name), mGroup(group), mShapeIndex(idx) +{ +} + +void NIFMeshLoader::loadResource(Ogre::Resource *resource) +{ + Ogre::Mesh *mesh = dynamic_cast(resource); + OgreAssert(mesh, "Attempting to load a mesh into a non-mesh resource!"); + + Nif::NIFFile::ptr nif = Nif::NIFFile::create(mName); + if(mShapeIndex >= nif->numRecords()) + { + Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); + if(!skelMgr->getByName(mName).isNull()) + mesh->setSkeletonName(mName); + return; + } + + const Nif::Record *record = nif->getRecord(mShapeIndex); + createSubMesh(mesh, dynamic_cast(record)); +} + + +void NIFMeshLoader::createMesh(const std::string &name, const std::string &fullname, const std::string &group, size_t idx) +{ + NIFMeshLoader::LoaderMap::iterator loader; + loader = sLoaders.insert(std::make_pair(fullname, NIFMeshLoader(name, group, idx))).first; + + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); + Ogre::MeshPtr mesh = meshMgr.createManual(fullname, group, &loader->second); + mesh->setAutoBuildEdgeLists(false); +} + +} diff --git a/components/nifogre/mesh.hpp b/components/nifogre/mesh.hpp new file mode 100644 index 0000000000..731e49c903 --- /dev/null +++ b/components/nifogre/mesh.hpp @@ -0,0 +1,55 @@ +#ifndef COMPONENTS_NIFOGRE_MESH_HPP +#define COMPONENTS_NIFOGRE_MESH_HPP + +#include +#include +#include +#include + +#include + +namespace Nif +{ + class NiTriShape; +} + +namespace NifOgre +{ + +/** Manual resource loader for NiTriShapes. This is the main class responsible + * for translating the internal NIF meshes into something Ogre can use. + */ +class NIFMeshLoader : Ogre::ManualResourceLoader +{ + static void warn(const std::string &msg) + { + std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; + } + + static void fail(const std::string &msg) + { + std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; + abort(); + } + + std::string mName; + std::string mGroup; + size_t mShapeIndex; + + // Convert NiTriShape to Ogre::SubMesh + void createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape); + + typedef std::map LoaderMap; + static LoaderMap sLoaders; + + NIFMeshLoader(const std::string &name, const std::string &group, size_t idx); + + virtual void loadResource(Ogre::Resource *resource); + +public: + static void createMesh(const std::string &name, const std::string &fullname, const std::string &group, size_t idx); +}; + +} + +#endif diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 3bd93a1b9f..8d82c3ced7 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -25,12 +25,7 @@ #include -#include -#include -#include -#include #include -#include #include #include #include @@ -38,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -45,6 +42,7 @@ #include "skeleton.hpp" #include "material.hpp" +#include "mesh.hpp" namespace std { @@ -58,6 +56,46 @@ ostream& operator<<(ostream &o, const NifOgre::TextKeyMap&) namespace NifOgre { +void getNodeProperties(const Nif::Node *node, + const Nif::NiTexturingProperty *&texprop, + const Nif::NiMaterialProperty *&matprop, + const Nif::NiAlphaProperty *&alphaprop, + const Nif::NiVertexColorProperty *&vertprop, + const Nif::NiZBufferProperty *&zprop, + const Nif::NiSpecularProperty *&specprop, + const Nif::NiWireframeProperty *&wireprop) +{ + if(node->parent) + getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); + + const Nif::PropertyList &proplist = node->props; + for(size_t i = 0;i < proplist.length();i++) + { + // Entries may be empty + if(proplist[i].empty()) + continue; + + const Nif::Property *pr = proplist[i].getPtr(); + if(pr->recType == Nif::RC_NiTexturingProperty) + texprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiMaterialProperty) + matprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiAlphaProperty) + alphaprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiVertexColorProperty) + vertprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiZBufferProperty) + zprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiSpecularProperty) + specprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiWireframeProperty) + wireprop = static_cast(pr); + else + std::cerr<< "Unhandled property type: "<recName < { @@ -332,101 +370,13 @@ public: }; -// Helper class that computes the bounding box and of a mesh -class BoundsFinder -{ - struct MaxMinFinder - { - float max, min; - - MaxMinFinder() - { - min = std::numeric_limits::infinity(); - max = -min; - } - - void add(float f) - { - if (f > max) max = f; - if (f < min) min = f; - } - - // Return Max(max**2, min**2) - float getMaxSquared() - { - float m1 = max*max; - float m2 = min*min; - if (m1 >= m2) return m1; - return m2; - } - }; - - MaxMinFinder X, Y, Z; - -public: - // Add 'verts' vertices to the calculation. The 'data' pointer is - // expected to point to 3*verts floats representing x,y,z for each - // point. - void add(float *data, int verts) - { - for (int i=0;iparent) - getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); - - const Nif::PropertyList &proplist = node->props; - for(size_t i = 0;i < proplist.length();i++) - { - // Entries may be empty - if(proplist[i].empty()) - continue; - - const Nif::Property *pr = proplist[i].getPtr(); - if(pr->recType == Nif::RC_NiTexturingProperty) - texprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiMaterialProperty) - matprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiAlphaProperty) - alphaprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiVertexColorProperty) - vertprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiZBufferProperty) - zprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiSpecularProperty) - specprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiWireframeProperty) - wireprop = static_cast(pr); - else - warn("Unhandled property type: "+pr->recName); - } - } - - // Convert NiTriShape to Ogre::SubMesh - void createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape) - { - Ogre::SkeletonPtr skel; - const Nif::NiTriShapeData *data = shape->data.getPtr(); - const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); - std::vector srcVerts = data->vertices; - std::vector srcNorms = data->normals; - Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC; - bool vertShadowBuffer = false; - if(skin != NULL) - { - vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; - vertShadowBuffer = true; - - // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be - // explicitly attached later. - mesh->setSkeletonName(mName); - - // Get the skeleton resource, so vertices can be transformed into the bones' initial state. - Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - skel = skelMgr->getByName(mName); - - // Convert vertices and normals to bone space from bind position. It would be - // better to transform the bones into bind position, but there doesn't seem to - // be a reliable way to do that. - std::vector newVerts(srcVerts.size(), Ogre::Vector3(0.0f)); - std::vector newNorms(srcNorms.size(), Ogre::Vector3(0.0f)); - - const Nif::NiSkinData *data = skin->data.getPtr(); - const Nif::NodeList &bones = skin->bones; - for(size_t b = 0;b < bones.length();b++) - { - Ogre::Bone *bone = skel->getBone(bones[b]->name); - Ogre::Matrix4 mat; - mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), - Ogre::Quaternion(data->bones[b].trafo.rotation)); - mat = bone->_getFullTransform() * mat; - - const std::vector &weights = data->bones[b].weights; - for(size_t i = 0;i < weights.size();i++) - { - size_t index = weights[i].vertex; - float weight = weights[i].weight; - - newVerts.at(index) += (mat*srcVerts[index]) * weight; - if(newNorms.size() > index) - { - Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f); - vec4 = mat*vec4 * weight; - newNorms[index] += Ogre::Vector3(&vec4[0]); - } - } - } - - srcVerts = newVerts; - srcNorms = newNorms; - } - else - { - Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - if(skelMgr->getByName(mName).isNull()) - { - // No skinning and no skeleton, so just transform the vertices and - // normals into position. - Ogre::Matrix4 mat4 = shape->getWorldTransform(); - for(size_t i = 0;i < srcVerts.size();i++) - { - Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f); - vec4 = mat4*vec4; - srcVerts[i] = Ogre::Vector3(&vec4[0]); - } - for(size_t i = 0;i < srcNorms.size();i++) - { - Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f); - vec4 = mat4*vec4; - srcNorms[i] = Ogre::Vector3(&vec4[0]); - } - } - } - - // Set the bounding box first - BoundsFinder bounds; - bounds.add(&srcVerts[0][0], srcVerts.size()); - if(!bounds.isValid()) - { - float v[3] = { 0.0f, 0.0f, 0.0f }; - bounds.add(&v[0], 1); - } - - mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f, - bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f)); - mesh->_setBoundingSphereRadius(bounds.getRadius()); - - // This function is just one long stream of Ogre-barf, but it works - // great. - Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr(); - Ogre::HardwareVertexBufferSharedPtr vbuf; - Ogre::HardwareIndexBufferSharedPtr ibuf; - Ogre::VertexBufferBinding *bind; - Ogre::VertexDeclaration *decl; - int nextBuf = 0; - - Ogre::SubMesh *sub = mesh->createSubMesh(); - - // Add vertices - sub->useSharedVertices = false; - sub->vertexData = new Ogre::VertexData(); - sub->vertexData->vertexStart = 0; - sub->vertexData->vertexCount = srcVerts.size(); - - decl = sub->vertexData->vertexDeclaration; - bind = sub->vertexData->vertexBufferBinding; - if(srcVerts.size()) - { - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - srcVerts.size(), vertUsage, vertShadowBuffer); - vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true); - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - bind->setBinding(nextBuf++, vbuf); - } - - // Vertex normals - if(srcNorms.size()) - { - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - srcNorms.size(), vertUsage, vertShadowBuffer); - vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true); - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - bind->setBinding(nextBuf++, vbuf); - } - - // Vertex colors - const std::vector &colors = data->colors; - if(colors.size()) - { - Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); - std::vector colorsRGB(colors.size()); - for(size_t i = 0;i < colorsRGB.size();i++) - { - Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]); - rs->convertColourValue(clr, &colorsRGB[i]); - } - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), - colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC); - vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true); - decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); - bind->setBinding(nextBuf++, vbuf); - } - - // Texture UV coordinates - size_t numUVs = data->uvlist.size(); - for(size_t i = 0;i < numUVs;i++) - { - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2), - srcVerts.size(), Ogre::HardwareBuffer::HBU_STATIC); - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[i][0], true); - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i); - bind->setBinding(nextBuf++, vbuf); - } - - // Triangle faces - const std::vector &srcIdx = data->triangles; - if(srcIdx.size()) - { - ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(), - Ogre::HardwareBuffer::HBU_STATIC); - ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true); - sub->indexData->indexBuffer = ibuf; - sub->indexData->indexCount = srcIdx.size(); - sub->indexData->indexStart = 0; - } - - // Assign bone weights for this TriShape - if(skin != NULL) - { - const Nif::NiSkinData *data = skin->data.getPtr(); - const Nif::NodeList &bones = skin->bones; - for(size_t i = 0;i < bones.length();i++) - { - Ogre::VertexBoneAssignment boneInf; - boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle(); - - const std::vector &weights = data->bones[i].weights; - for(size_t j = 0;j < weights.size();j++) - { - boneInf.vertexIndex = weights[j].vertex; - boneInf.weight = weights[j].weight; - sub->addBoneAssignment(boneInf); - } - } - } - - const Nif::NiTexturingProperty *texprop = NULL; - const Nif::NiMaterialProperty *matprop = NULL; - const Nif::NiAlphaProperty *alphaprop = NULL; - const Nif::NiVertexColorProperty *vertprop = NULL; - const Nif::NiZBufferProperty *zprop = NULL; - const Nif::NiSpecularProperty *specprop = NULL; - const Nif::NiWireframeProperty *wireprop = NULL; - bool needTangents = false; - - getNodeProperties(shape, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); - std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, - texprop, matprop, alphaprop, - vertprop, zprop, specprop, - wireprop, needTangents); - if(matname.length() > 0) - sub->setMaterialName(matname); - - // build tangents if the material needs them - if (needTangents) - { - unsigned short src,dest; - if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest)) - mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest); - } - } - - - typedef std::map LoaderMap; - static LoaderMap sLoaders; - static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl) { @@ -743,8 +428,9 @@ class NIFObjectLoader : Ogre::ManualResourceLoader } } - Ogre::ParticleSystem *createParticleSystem(Ogre::SceneManager *sceneMgr, Ogre::Entity *entitybase, - const Nif::Node *partnode) + static Ogre::ParticleSystem *createParticleSystem(const std::string &name, const std::string &group, + Ogre::SceneManager *sceneMgr, Ogre::Entity *entitybase, + const Nif::Node *partnode) { const Nif::NiAutoNormalParticlesData *particledata = NULL; if(partnode->recType == Nif::RC_NiAutoNormalParticles) @@ -754,7 +440,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader Ogre::ParticleSystem *partsys = sceneMgr->createParticleSystem(); try { - std::string fullname = mName+"@index="+Ogre::StringConverter::toString(partnode->recIndex); + std::string fullname = name+"@index="+Ogre::StringConverter::toString(partnode->recIndex); if(partnode->name.length() > 0) fullname += "@type="+partnode->name; Misc::StringUtils::toLower(fullname); @@ -769,7 +455,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader bool needTangents = false; getNodeProperties(partnode, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); - partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, mGroup, + partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, group, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop, needTangents)); @@ -789,7 +475,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader createParticleEmitterAffectors(partsys, partctrl); if(!partctrl->emitter.empty() && !partsys->isAttached()) { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, partctrl->emitter->recIndex); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex); Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid); entitybase->attachObjectToBone(trgtbone->getName(), partsys); } @@ -799,7 +485,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader if(!partsys->isAttached()) { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, partnode->recIndex); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex); Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid); entitybase->attachObjectToBone(trgtbone->getName(), partsys); } @@ -813,29 +499,9 @@ class NIFObjectLoader : Ogre::ManualResourceLoader } - NIFObjectLoader(const std::string &name, const std::string &group) - : mName(name), mGroup(group), mShapeIndex(~(size_t)0) - { } - - virtual void loadResource(Ogre::Resource *resource) - { - Ogre::Mesh *mesh = dynamic_cast(resource); - OgreAssert(mesh, "Attempting to load a mesh into a non-mesh resource!"); - - Nif::NIFFile::ptr nif = Nif::NIFFile::create(mName); - if(mShapeIndex >= nif->numRecords()) - { - Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - if(!skelMgr->getByName(mName).isNull()) - mesh->setSkeletonName(mName); - return; - } - - const Nif::Record *record = nif->getRecord(mShapeIndex); - createSubMesh(mesh, dynamic_cast(record)); - } - - void createObjects(Ogre::SceneManager *sceneMgr, const Nif::Node *node, ObjectList &objectlist, int flags=0) + static void createObjects(const std::string &name, const std::string &group, + Ogre::SceneManager *sceneMgr, const Nif::Node *node, + ObjectList &objectlist, int flags=0) { // Do not create objects for the collision shape (includes all children) if(node->recType == Nif::RC_RootCollisionNode) @@ -868,7 +534,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader if(node->recType == Nif::RC_NiCamera) { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, node->recIndex); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); objectlist.mCameras.push_back(trgtbone); } @@ -880,7 +546,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader { const Nif::NiVisController *vis = static_cast(ctrl.getPtr()); - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); Ogre::ControllerValueRealPtr srcval; /* Filled in later */ Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr())); @@ -893,7 +559,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); if(!key->data.empty()) { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); Ogre::ControllerValueRealPtr srcval; /* Filled in later */ Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr())); @@ -909,24 +575,16 @@ class NIFObjectLoader : Ogre::ManualResourceLoader { const Nif::NiTriShape *shape = static_cast(node); - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - std::string fullname = mName+"@index="+Ogre::StringConverter::toString(shape->recIndex); + std::string fullname = name+"@index="+Ogre::StringConverter::toString(shape->recIndex); if(shape->name.length() > 0) fullname += "@shape="+shape->name; - Misc::StringUtils::toLower(fullname); - Ogre::MeshPtr mesh = meshMgr.getByName(fullname); - if(mesh.isNull()) - { - NIFObjectLoader *loader = &sLoaders[fullname]; - *loader = *this; - loader->mShapeIndex = shape->recIndex; - mesh = meshMgr.createManual(fullname, mGroup, loader); - mesh->setAutoBuildEdgeLists(false); - } + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); + if(meshMgr.getByName(fullname).isNull()) + NIFMeshLoader::createMesh(name, fullname, group, shape->recIndex); - Ogre::Entity *entity = sceneMgr->createEntity(mesh); + Ogre::Entity *entity = sceneMgr->createEntity(fullname); entity->setVisible(!(flags&0x01)); objectlist.mEntities.push_back(entity); @@ -936,7 +594,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader entity->shareSkeletonInstanceWith(objectlist.mSkelBase); else { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, shape->recIndex); + int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, shape->recIndex); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid); objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), entity); } @@ -963,7 +621,7 @@ class NIFObjectLoader : Ogre::ManualResourceLoader if(node->recType == Nif::RC_NiAutoNormalParticles || node->recType == Nif::RC_NiRotatingParticles) { - Ogre::ParticleSystem *partsys = createParticleSystem(sceneMgr, objectlist.mSkelBase, node); + Ogre::ParticleSystem *partsys = createParticleSystem(name, group, sceneMgr, objectlist.mSkelBase, node); if(partsys != NULL) { partsys->setVisible(!(flags&0x01)); @@ -978,71 +636,57 @@ class NIFObjectLoader : Ogre::ManualResourceLoader for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - createObjects(sceneMgr, children[i].getPtr(), objectlist, flags); + createObjects(name, group, sceneMgr, children[i].getPtr(), objectlist, flags); } } } - void createSkelBase(Ogre::SceneManager *sceneMgr, const Nif::Node *node, ObjectList &objectlist) + static void createSkelBase(const std::string &name, const std::string &group, + Ogre::SceneManager *sceneMgr, const Nif::Node *node, + ObjectList &objectlist) { /* 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. */ - std::string fullname = mName; - Misc::StringUtils::toLower(fullname); - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - Ogre::MeshPtr mesh = meshMgr.getByName(fullname); - if(mesh.isNull()) - { - NIFObjectLoader *loader = &sLoaders[fullname]; - *loader = *this; + if(meshMgr.getByName(name).isNull()) + NIFMeshLoader::createMesh(name, name, group, ~(size_t)0); - mesh = meshMgr.createManual(fullname, mGroup, loader); - mesh->setAutoBuildEdgeLists(false); - } - objectlist.mSkelBase = sceneMgr->createEntity(mesh); + objectlist.mSkelBase = sceneMgr->createEntity(name); objectlist.mEntities.push_back(objectlist.mSkelBase); } public: - NIFObjectLoader() : mShapeIndex(~(size_t)0) - { } - static void load(Ogre::SceneManager *sceneMgr, ObjectList &objectlist, const std::string &name, const std::string &group) { - Nif::NIFFile::ptr pnif = Nif::NIFFile::create(name); - Nif::NIFFile &nif = *pnif.get(); - if(nif.numRoots() < 1) + Nif::NIFFile::ptr nif = Nif::NIFFile::create(name); + if(nif->numRoots() < 1) { - nif.warn("Found no root nodes in "+name+"."); + nif->warn("Found no root nodes in "+name+"."); return; } - // The first record is assumed to be the root node - const Nif::Record *r = nif.getRoot(0); + const Nif::Record *r = nif->getRoot(0); assert(r != NULL); - const Nif::Node *node = dynamic_cast(r); + const Nif::Node *node = dynamic_cast(r); if(node == NULL) { - nif.warn("First root in "+name+" was not a node, but a "+ - r->recName+"."); + nif->warn("First root in "+name+" was not a node, but a "+ + r->recName+"."); return; } - bool hasSkel = Ogre::SkeletonManager::getSingleton().resourceExists(name); - if(!hasSkel) - hasSkel = !NIFSkeletonLoader::createSkeleton(name, group, node).isNull(); - - NIFObjectLoader meshldr(name, group); - if(hasSkel) - meshldr.createSkelBase(sceneMgr, node, objectlist); - meshldr.createObjects(sceneMgr, node, objectlist); + if(Ogre::SkeletonManager::getSingleton().resourceExists(name) || + !NIFSkeletonLoader::createSkeleton(name, group, node).isNull()) + { + // Create a base skeleton entity if this NIF needs one + createSkelBase(name, group, sceneMgr, node, objectlist); + } + createObjects(name, group, sceneMgr, node, objectlist); } }; -NIFObjectLoader::LoaderMap NIFObjectLoader::sLoaders; ObjectList Loader::createObjects(Ogre::SceneNode *parentNode, std::string name, const std::string &group) From d26ffe9de02dfd69a7477eae31349c6a9efbca94 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 10 Apr 2013 23:19:47 -0700 Subject: [PATCH 195/198] Move a method to the Node class --- components/nif/niffile.cpp | 38 +++++++++++++++++++++++++ components/nif/node.hpp | 8 ++++++ components/nifogre/mesh.cpp | 11 +------- components/nifogre/ogrenifloader.cpp | 42 +--------------------------- 4 files changed, 48 insertions(+), 51 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 44eae2953d..3b41e96a70 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -384,6 +384,44 @@ void NiSkinInstance::post(NIFFile *nif) } } + +void Node::getProperties(const Nif::NiTexturingProperty *&texprop, + const Nif::NiMaterialProperty *&matprop, + const Nif::NiAlphaProperty *&alphaprop, + const Nif::NiVertexColorProperty *&vertprop, + const Nif::NiZBufferProperty *&zprop, + const Nif::NiSpecularProperty *&specprop, + const Nif::NiWireframeProperty *&wireprop) const +{ + if(parent) + parent->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); + + for(size_t i = 0;i < props.length();i++) + { + // Entries may be empty + if(props[i].empty()) + continue; + + const Nif::Property *pr = props[i].getPtr(); + if(pr->recType == Nif::RC_NiTexturingProperty) + texprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiMaterialProperty) + matprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiAlphaProperty) + alphaprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiVertexColorProperty) + vertprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiZBufferProperty) + zprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiSpecularProperty) + specprop = static_cast(pr); + else if(pr->recType == Nif::RC_NiWireframeProperty) + wireprop = static_cast(pr); + else + std::cerr<< "Unhandled property type: "<recName <getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop, diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 8d82c3ced7..48893bf4a8 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -56,46 +56,6 @@ ostream& operator<<(ostream &o, const NifOgre::TextKeyMap&) namespace NifOgre { -void getNodeProperties(const Nif::Node *node, - const Nif::NiTexturingProperty *&texprop, - const Nif::NiMaterialProperty *&matprop, - const Nif::NiAlphaProperty *&alphaprop, - const Nif::NiVertexColorProperty *&vertprop, - const Nif::NiZBufferProperty *&zprop, - const Nif::NiSpecularProperty *&specprop, - const Nif::NiWireframeProperty *&wireprop) -{ - if(node->parent) - getNodeProperties(node->parent, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); - - const Nif::PropertyList &proplist = node->props; - for(size_t i = 0;i < proplist.length();i++) - { - // Entries may be empty - if(proplist[i].empty()) - continue; - - const Nif::Property *pr = proplist[i].getPtr(); - if(pr->recType == Nif::RC_NiTexturingProperty) - texprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiMaterialProperty) - matprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiAlphaProperty) - alphaprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiVertexColorProperty) - vertprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiZBufferProperty) - zprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiSpecularProperty) - specprop = static_cast(pr); - else if(pr->recType == Nif::RC_NiWireframeProperty) - wireprop = static_cast(pr); - else - std::cerr<< "Unhandled property type: "<recName < { @@ -454,7 +414,7 @@ class NIFObjectLoader const Nif::NiWireframeProperty *wireprop = NULL; bool needTangents = false; - getNodeProperties(partnode, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); + partnode->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, group, texprop, matprop, alphaprop, vertprop, zprop, specprop, From 6d3a2cd5a0c5364395cdad5aeedb291abeffc1e2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 11 Apr 2013 10:50:22 +0200 Subject: [PATCH 196/198] added comment token (for use in syntax colouring) --- components/compiler/parser.cpp | 5 +++++ components/compiler/parser.hpp | 7 +++++++ components/compiler/scanner.cpp | 9 ++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/components/compiler/parser.cpp b/components/compiler/parser.cpp index 896458e482..8d11c4086d 100644 --- a/components/compiler/parser.cpp +++ b/components/compiler/parser.cpp @@ -148,6 +148,11 @@ namespace Compiler return false; } + bool Parser::parseComment (const std::string& comment, const TokenLoc& loc, Scanner& scanner) + { + return true; + } + // Handle an EOF token. // // - Default-implementation: Report an error. diff --git a/components/compiler/parser.hpp b/components/compiler/parser.hpp index 221e7c2c9f..4fec570e9f 100644 --- a/components/compiler/parser.hpp +++ b/components/compiler/parser.hpp @@ -82,6 +82,13 @@ namespace Compiler /// /// - Default-implementation: Report an error. + virtual bool parseComment (const std::string& comment, const TokenLoc& loc, + Scanner& scanner); + ///< Handle comment token. + /// \return fetch another token? + /// + /// - Default-implementation: ignored (and return true). + virtual void parseEOF (Scanner& scanner); ///< Handle EOF token. /// diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 420fd8f7f3..38a9265a1e 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -88,6 +88,10 @@ namespace Compiler } else if (c==';') { + std::string comment; + + comment += c; + while (get (c)) { if (c=='\n') @@ -95,11 +99,14 @@ namespace Compiler putback (c); break; } + else + comment += c; } + TokenLoc loc (mLoc); mLoc.mLiteral.clear(); - return true; + return parser.parseComment (comment, loc, *this); } else if (isWhitespace (c)) { From f17cebde0aea9e8cc1aaedd3592923eb5618c0fb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 11 Apr 2013 10:50:35 +0200 Subject: [PATCH 197/198] syntax colouring for comments --- apps/opencs/view/world/scripthighlighter.cpp | 15 ++++++++++++++- apps/opencs/view/world/scripthighlighter.hpp | 7 +++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/world/scripthighlighter.cpp b/apps/opencs/view/world/scripthighlighter.cpp index 1e93ac26b7..288a3d12ac 100644 --- a/apps/opencs/view/world/scripthighlighter.cpp +++ b/apps/opencs/view/world/scripthighlighter.cpp @@ -40,6 +40,13 @@ bool CSVWorld::ScriptHighlighter::parseSpecial (int code, const Compiler::TokenL return true; } +bool CSVWorld::ScriptHighlighter::parseComment (const std::string& comment, + const Compiler::TokenLoc& loc, Compiler::Scanner& scanner) +{ + highlight (loc, Type_Comment); + return true; +} + void CSVWorld::ScriptHighlighter::parseEOF (Compiler::Scanner& scanner) {} @@ -67,7 +74,7 @@ CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent) { QTextCharFormat format; - format.setForeground (Qt::green); + format.setForeground (Qt::magenta); mScheme.insert (std::make_pair (Type_Float, format)); } @@ -88,6 +95,12 @@ CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent) format.setForeground (Qt::darkYellow); mScheme.insert (std::make_pair (Type_Special, format)); } + + { + QTextCharFormat format; + format.setForeground (Qt::green); + mScheme.insert (std::make_pair (Type_Comment, format)); + } } void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text) diff --git a/apps/opencs/view/world/scripthighlighter.hpp b/apps/opencs/view/world/scripthighlighter.hpp index e9918f99b7..3ef6978097 100644 --- a/apps/opencs/view/world/scripthighlighter.hpp +++ b/apps/opencs/view/world/scripthighlighter.hpp @@ -22,7 +22,8 @@ namespace CSVWorld Type_Float, Type_Name, Type_Keyword, - Type_Special + Type_Special, + Type_Comment }; private: @@ -58,7 +59,9 @@ namespace CSVWorld ///< Handle a special character token. /// \return fetch another token? - ///< Handle a special character token. + virtual bool parseComment (const std::string& comment, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner); + ///< Handle comment token. /// \return fetch another token? virtual void parseEOF (Compiler::Scanner& scanner); From 9c7ad758169c0a539b629540e3123348060505b2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 11 Apr 2013 14:44:02 +0200 Subject: [PATCH 198/198] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index f06377500a..6456e30a10 100644 --- a/credits.txt +++ b/credits.txt @@ -16,6 +16,7 @@ Alexander Nadeau (wareya) Alexander Olofsson (Ace) Artem Kotsynyak (greye) athile +Britt Mathis (galdor557) BrotherBrick Chris Robinson (KittyCat) Cory F. Cohen (cfcohen)