Merge branch 'master' into tables

deque
Marc Zinnschlag 10 years ago
commit f4c9897bbd

@ -607,8 +607,8 @@ if (WIN32)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)\" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)\" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)" )
endforeach( OUTPUTCONFIG ) endforeach( OUTPUTCONFIG )
if (USE_DEBUG_CONSOLE) if (USE_DEBUG_CONSOLE)

File diff suppressed because it is too large Load Diff

@ -412,7 +412,7 @@ void Record<ESM::Armor>::print()
std::cout << " Armor: " << mData.mData.mArmor << std::endl; std::cout << " Armor: " << mData.mData.mArmor << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit; std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++) for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{ {
std::cout << " Body Part: " << bodyPartLabel(pit->mPart) std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl; << " (" << (int)(pit->mPart) << ")" << std::endl;
@ -484,7 +484,7 @@ void Record<ESM::BirthSign>::print()
std::cout << " Texture: " << mData.mTexture << std::endl; std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl; std::cout << " Description: " << mData.mDescription << std::endl;
std::vector<std::string>::iterator pit; std::vector<std::string>::iterator pit;
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); pit++) for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); ++pit)
std::cout << " Power: " << *pit << std::endl; std::cout << " Power: " << *pit << std::endl;
} }
@ -554,7 +554,7 @@ void Record<ESM::Clothing>::print()
std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit; std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++) for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{ {
std::cout << " Body Part: " << bodyPartLabel(pit->mPart) std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl; << " (" << (int)(pit->mPart) << ")" << std::endl;
@ -574,7 +574,7 @@ void Record<ESM::Container>::print()
std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mWeight << std::endl; std::cout << " Weight: " << mData.mWeight << std::endl;
std::vector<ESM::ContItem>::iterator cit; std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl; << " Item: " << cit->mItem.toString() << std::endl;
} }
@ -619,12 +619,12 @@ void Record<ESM::Creature>::print()
std::cout << " Gold: " << mData.mData.mGold << std::endl; std::cout << " Gold: " << mData.mData.mGold << std::endl;
std::vector<ESM::ContItem>::iterator cit; std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl; << " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit; std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
@ -639,7 +639,7 @@ void Record<ESM::Creature>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl; std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit; std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++) for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit); printAIPackage(*pit);
} }
@ -706,7 +706,7 @@ void Record<ESM::Faction>::print()
<< mData.mData.mRankData[i].mFactReaction << std::endl; << mData.mData.mRankData[i].mFactReaction << std::endl;
} }
std::map<std::string, int>::iterator rit; std::map<std::string, int>::iterator rit;
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++) for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); ++rit)
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl; std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
} }
@ -763,7 +763,7 @@ void Record<ESM::DialInfo>::print()
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl; std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
std::vector<ESM::DialInfo::SelectStruct>::iterator sit; std::vector<ESM::DialInfo::SelectStruct>::iterator sit;
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); sit++) for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); ++sit)
std::cout << " Select Rule: " << ruleString(*sit) << std::endl; std::cout << " Select Rule: " << ruleString(*sit) << std::endl;
if (mData.mResultScript != "") if (mData.mResultScript != "")
@ -835,7 +835,7 @@ void Record<ESM::CreatureLevList>::print()
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl; std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit; std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++) for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Creature: Level: " << iit->mLevel std::cout << " Creature: Level: " << iit->mLevel
<< " Creature: " << iit->mId << std::endl; << " Creature: " << iit->mId << std::endl;
} }
@ -847,7 +847,7 @@ void Record<ESM::ItemLevList>::print()
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl; std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit; std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++) for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Inventory: Level: " << iit->mLevel std::cout << " Inventory: Level: " << iit->mLevel
<< " Item: " << iit->mId << std::endl; << " Item: " << iit->mId << std::endl;
} }
@ -1031,16 +1031,16 @@ void Record<ESM::NPC>::print()
} }
std::vector<ESM::ContItem>::iterator cit; std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl; << " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit; std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit; std::vector<ESM::NPC::Dest>::iterator dit;
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); dit++) for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit)
{ {
std::cout << " Destination Position: " std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << "," << boost::format("%12.3f") % dit->mPos.pos[0] << ","
@ -1066,7 +1066,7 @@ void Record<ESM::NPC>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl; std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit; std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++) for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit); printAIPackage(*pit);
} }
@ -1140,7 +1140,7 @@ void Record<ESM::Race>::print()
<< mData.mData.mBonus[i].mBonus << std::endl; << mData.mData.mBonus[i].mBonus << std::endl;
std::vector<std::string>::iterator sit; std::vector<std::string>::iterator sit;
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); sit++) for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); ++sit)
std::cout << " Power: " << *sit << std::endl; std::cout << " Power: " << *sit << std::endl;
} }
@ -1164,7 +1164,7 @@ void Record<ESM::Region>::print()
if (mData.mSleepList != "") if (mData.mSleepList != "")
std::cout << " Sleep List: " << mData.mSleepList << std::endl; std::cout << " Sleep List: " << mData.mSleepList << std::endl;
std::vector<ESM::Region::SoundRef>::iterator sit; std::vector<ESM::Region::SoundRef>::iterator sit;
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); sit++) for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); ++sit)
std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl; std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl;
} }
@ -1181,12 +1181,12 @@ void Record<ESM::Script>::print()
std::vector<std::string>::iterator vit; std::vector<std::string>::iterator vit;
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); vit++) for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); ++vit)
std::cout << " Variable: " << *vit << std::endl; std::cout << " Variable: " << *vit << std::endl;
std::cout << " ByteCode: "; std::cout << " ByteCode: ";
std::vector<unsigned char>::iterator cit; std::vector<unsigned char>::iterator cit;
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++) for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); ++cit)
std::cout << boost::format("%02X") % (int)(*cit); std::cout << boost::format("%02X") % (int)(*cit);
std::cout << std::endl; std::cout << std::endl;

@ -15,6 +15,7 @@ namespace bfs = boost::filesystem;
MwIniImporter::MwIniImporter() MwIniImporter::MwIniImporter()
: mVerbose(false) : mVerbose(false)
, mEncoding(ToUTF8::WINDOWS_1250)
{ {
const char *map[][2] = const char *map[][2] =
{ {
@ -709,8 +710,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
continue; continue;
} }
multistrmap::iterator it; if(map.find(key) == map.end()) {
if((it = map.find(key)) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) ); map.insert( std::make_pair (key, std::vector<std::string>() ) );
} }
map[key].push_back(value); map[key].push_back(value);
@ -746,8 +746,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filenam
std::string key(line.substr(0,pos)); std::string key(line.substr(0,pos));
std::string value(line.substr(pos+1)); std::string value(line.substr(pos+1));
multistrmap::iterator it; if(map.find(key) == map.end()) {
if((it = map.find(key)) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) ); map.insert( std::make_pair (key, std::vector<std::string>() ) );
} }
map[key].push_back(value); map[key].push_back(value);

@ -37,6 +37,8 @@ public:
char **get() const { return const_cast<char **>(argv); } char **get() const { return const_cast<char **>(argv); }
private: private:
utf8argv(const utf8argv&);
utf8argv& operator=(const utf8argv&);
const char **argv; const char **argv;
std::vector<std::string> args; std::vector<std::string> args;

@ -103,11 +103,6 @@ namespace CSMDoc
if (state==CSMWorld::RecordBase::State_Modified || if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly) state==CSMWorld::RecordBase::State_ModifiedOnly)
{ {
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic (change ESMWriter interface?)
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId); mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId);
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter()); mCollection.getRecord (stage).mModified.save (mState.getWriter());

@ -71,6 +71,14 @@ namespace CSMWorld
record.load (reader); record.load (reader);
if (index==-1)
{
std::string newId = IdAccessorT().getId(record);
int newIndex = this->searchId(newId);
if (newIndex != -1 && id != newId)
index = newIndex;
}
load (record, base, index); load (record, base, index);
} }
} }

@ -6,18 +6,20 @@
void CSMWorld::ResourcesManager::addResources (const Resources& resources) void CSMWorld::ResourcesManager::addResources (const Resources& resources)
{ {
mResources.insert (std::make_pair (resources.getType(), resources)); mResources.insert (std::make_pair (resources.getType(), resources));
mResources.insert (std::make_pair (UniversalId::getParentType (resources.getType()),
resources));
} }
void CSMWorld::ResourcesManager::listResources() void CSMWorld::ResourcesManager::listResources()
{ {
static const char * const sMeshTypes[] = { "nif", 0 }; static const char * const sMeshTypes[] = { "nif", 0 };
addResources (Resources ("meshes", UniversalId::Type_Meshes, sMeshTypes)); addResources (Resources ("meshes", UniversalId::Type_Mesh, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icons)); addResources (Resources ("icons", UniversalId::Type_Icon));
addResources (Resources ("music", UniversalId::Type_Musics)); addResources (Resources ("music", UniversalId::Type_Music));
addResources (Resources ("sound", UniversalId::Type_SoundsRes)); addResources (Resources ("sound", UniversalId::Type_SoundRes));
addResources (Resources ("textures", UniversalId::Type_Textures)); addResources (Resources ("textures", UniversalId::Type_Texture));
addResources (Resources ("videos", UniversalId::Type_Videos)); addResources (Resources ("videos", UniversalId::Type_Video));
} }
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const

@ -11,9 +11,14 @@ float CSVRender::Navigation::getFactor (bool mouse) const
return factor; return factor;
} }
CSVRender::Navigation::Navigation()
: mFastModeFactor(1)
{
}
CSVRender::Navigation::~Navigation() {} CSVRender::Navigation::~Navigation() {}
void CSVRender::Navigation::setFastModeFactor (float factor) void CSVRender::Navigation::setFastModeFactor (float factor)
{ {
mFastModeFactor = factor; mFastModeFactor = factor;
} }

@ -20,6 +20,7 @@ namespace CSVRender
public: public:
Navigation();
virtual ~Navigation(); virtual ~Navigation();
void setFastModeFactor (float factor); void setFastModeFactor (float factor);

@ -361,11 +361,6 @@ namespace CSVRender
} }
} }
int SceneWidget::getFastFactor() const
{
return mFast ? mFastFactor : 1;
}
void SceneWidget::setLighting (Lighting *lighting) void SceneWidget::setLighting (Lighting *lighting)
{ {
if (mLighting) if (mLighting)

@ -80,8 +80,6 @@ namespace CSVRender
void updateOgreWindow(); void updateOgreWindow();
int getFastFactor() const;
void setLighting (Lighting *lighting); void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this. ///< \attention The ownership of \a lighting is not transferred to *this.

@ -38,7 +38,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps ()
} }
} }
void CSVWorld::DataDisplayDelegate::setIconSize(const QSize size) void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size)
{ {
mIconSize = size; mIconSize = size;
buildPixmaps(); buildPixmaps();

@ -50,7 +50,7 @@ namespace CSVWorld
virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
/// pass a QSize defining height / width of icon. Default is QSize (16,16). /// pass a QSize defining height / width of icon. Default is QSize (16,16).
void setIconSize (const QSize icon); void setIconSize (const QSize& icon);
/// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels. /// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels.
void setIconLeftOffset (int offset); void setIconLeftOffset (int offset);

@ -32,7 +32,7 @@ add_openmw_dir (mwinput
add_openmw_dir (mwgui add_openmw_dir (mwgui
textinput widgets race class birth review windowmanagerimp console dialogue textinput widgets race class birth review windowmanagerimp console dialogue
windowbase statswindow messagebox journalwindow charactercreation windowbase statswindow messagebox journalwindow charactercreation
mapwindow windowpinnablebase tooltips scrollwindow bookwindow list mapwindow windowpinnablebase tooltips scrollwindow bookwindow
formatting inventorywindow container hud countdialog tradewindow settingswindow formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
@ -40,7 +40,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
recharge mode videowidget backgroundimage itemwidget screenfader recharge mode videowidget backgroundimage itemwidget screenfader debugwindow
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

@ -127,7 +127,6 @@ static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid) static void gdb_info(pid_t pid)
{ {
char respfile[64]; char respfile[64];
char cmd_buf[128];
FILE *f; FILE *f;
int fd; int fd;
@ -156,6 +155,7 @@ static void gdb_info(pid_t pid)
fclose(f); fclose(f);
/* Run gdb and print process info. */ /* Run gdb and print process info. */
char cmd_buf[128];
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile); snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf); printf("Executing: %s\n", cmd_buf);
fflush(stdout); fflush(stdout);

@ -62,7 +62,6 @@ void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap
FallbackMap *map = boost::any_cast<FallbackMap>(&v); FallbackMap *map = boost::any_cast<FallbackMap>(&v);
std::map<std::string,std::string>::iterator mapIt;
for(std::vector<std::string>::const_iterator it=tokens.begin(); it != tokens.end(); ++it) for(std::vector<std::string>::const_iterator it=tokens.begin(); it != tokens.end(); ++it)
{ {
int sep = it->find(","); int sep = it->find(",");
@ -76,7 +75,7 @@ void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap
std::string key(it->substr(0,sep)); std::string key(it->substr(0,sep));
std::string value(it->substr(sep+1)); std::string value(it->substr(sep+1));
if((mapIt = map->mMap.find(key)) == map->mMap.end()) if(map->mMap.find(key) == map->mMap.end())
{ {
map->mMap.insert(std::make_pair (key,value)); map->mMap.insert(std::make_pair (key,value));
} }

@ -128,7 +128,8 @@ namespace MWBase
OffenseType type, int arg=0) = 0; OffenseType type, int arg=0) = 0;
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0; OffenseType type, int arg=0) = 0;
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0; /// @return false if the attack was considered a "friendly hit" and forgiven
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
/// Utility to check if taking this item is illegal and calling commitCrime if so /// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0; virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so

@ -225,7 +225,6 @@ namespace MWBase
virtual void showCrosshair(bool show) = 0; virtual void showCrosshair(bool show) = 0;
virtual bool getSubtitlesEnabled() = 0; virtual bool getSubtitlesEnabled() = 0;
virtual void toggleHud() = 0;
virtual bool toggleGui() = 0; virtual bool toggleGui() = 0;
virtual void disallowMouse() = 0; virtual void disallowMouse() = 0;
@ -338,6 +337,8 @@ namespace MWBase
virtual void fadeScreenTo(const int percent, const float time) = 0; virtual void fadeScreenTo(const int percent, const float time) = 0;
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor) = 0; virtual void setScreenFactor (float factor) = 0;
virtual void toggleDebugWindow() = 0;
}; };
} }

@ -338,11 +338,12 @@ namespace MWClass
getCreatureStats(ptr).setAttacked(true); getCreatureStats(ptr).setAttacked(true);
// Self defense // Self defense
bool setOnPcHitMe = true; // Note OnPcHitMe is not set for friendly hits.
if ((canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures if ((canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
// (they have no movement or attacks anyway) // (they have no movement or attacks anyway)
&& !attacker.isEmpty()) && !attacker.isEmpty())
{ {
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
} }
if(!successful) if(!successful)
@ -357,7 +358,7 @@ namespace MWClass
if(!object.isEmpty()) if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object));
if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player") if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
{ {
const std::string &script = ptr.get<ESM::Creature>()->mBase->mScript; const std::string &script = ptr.get<ESM::Creature>()->mBase->mScript;
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */

@ -644,11 +644,13 @@ namespace MWClass
bool wasDead = getCreatureStats(ptr).isDead(); bool wasDead = getCreatureStats(ptr).isDead();
// Note OnPcHitMe is not set for friendly hits.
bool setOnPcHitMe = true;
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)) if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker))
{ {
getCreatureStats(ptr).setAttacked(true); getCreatureStats(ptr).setAttacked(true);
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
} }
if(!successful) if(!successful)
@ -663,7 +665,7 @@ namespace MWClass
if(!object.isEmpty()) if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object));
if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player") if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
{ {
const std::string &script = ptr.getClass().getScript(ptr); const std::string &script = ptr.getClass().getScript(ptr);
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */
@ -1123,10 +1125,13 @@ namespace MWClass
return cast.cast(id); return cast.cast(id);
} }
void Npc::skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const void Npc::skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor) const
{ {
MWMechanics::NpcStats& stats = getNpcStats (ptr); MWMechanics::NpcStats& stats = getNpcStats (ptr);
if (stats.isWerewolf())
return;
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
const ESM::Class *class_ = const ESM::Class *class_ =
@ -1134,7 +1139,7 @@ namespace MWClass
ref->mBase->mClass ref->mBase->mClass
); );
stats.useSkill (skill, *class_, usageType); stats.useSkill (skill, *class_, usageType, extraFactor);
} }
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
@ -1185,13 +1190,6 @@ namespace MWClass
+ shield; + shield;
} }
void Npc::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const
{
y = 0;
x = 0;
}
void Npc::adjustScale(const MWWorld::Ptr &ptr, float &scale) const void Npc::adjustScale(const MWWorld::Ptr &ptr, float &scale) const
{ {
MWWorld::LiveCellRef<ESM::NPC> *ref = MWWorld::LiveCellRef<ESM::NPC> *ref =

@ -136,11 +136,9 @@ namespace MWClass
virtual void adjustScale (const MWWorld::Ptr &ptr, float &scale) const; virtual void adjustScale (const MWWorld::Ptr &ptr, float &scale) const;
virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const; virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const;
///< Inform actor \a ptr that a skill use has succeeded. ///< Inform actor \a ptr that a skill use has succeeded.
virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const;
virtual bool isEssential (const MWWorld::Ptr& ptr) const; virtual bool isEssential (const MWWorld::Ptr& ptr) const;
///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable) ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable)

@ -729,10 +729,10 @@ namespace MWDialogue
{ {
std::vector<HyperTextToken> result; std::vector<HyperTextToken> result;
MyGUI::UString utext(text); MyGUI::UString utext(text);
size_t pos_begin, pos_end, iteration_pos = 0; size_t pos_end, iteration_pos = 0;
for(;;) for(;;)
{ {
pos_begin = utext.find('@', iteration_pos); size_t pos_begin = utext.find('@', iteration_pos);
if (pos_begin != std::string::npos) if (pos_begin != std::string::npos)
pos_end = utext.find('#', pos_begin); pos_end = utext.find('#', pos_begin);
@ -758,12 +758,12 @@ namespace MWDialogue
size_t RemovePseudoAsterisks(std::string& phrase) size_t RemovePseudoAsterisks(std::string& phrase)
{ {
size_t pseudoAsterisksCount = 0; size_t pseudoAsterisksCount = 0;
const char specialPseudoAsteriskCharacter = 127;
if( !phrase.empty() ) if( !phrase.empty() )
{ {
std::string::reverse_iterator rit = phrase.rbegin(); std::string::reverse_iterator rit = phrase.rbegin();
const char specialPseudoAsteriskCharacter = 127;
while( rit != phrase.rend() && *rit == specialPseudoAsteriskCharacter ) while( rit != phrase.rend() && *rit == specialPseudoAsteriskCharacter )
{ {
pseudoAsterisksCount++; pseudoAsterisksCount++;

@ -70,11 +70,6 @@ namespace MWGui
void BookWindow::clearPages() void BookWindow::clearPages()
{ {
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
it!=mPages.end(); ++it)
{
MyGUI::Gui::getInstance().destroyWidget(*it);
}
mPages.clear(); mPages.clear();
} }
@ -89,25 +84,9 @@ namespace MWGui
MWWorld::LiveCellRef<ESM::Book> *ref = mBook.get<ESM::Book>(); MWWorld::LiveCellRef<ESM::Book> *ref = mBook.get<ESM::Book>();
BookTextParser parser; Formatting::BookFormatter formatter;
std::vector<std::string> results = parser.split(ref->mBase->mText, mLeftPage->getSize().width, mLeftPage->getSize().height); mPages = formatter.markupToWidget(mLeftPage, ref->mBase->mText);
formatter.markupToWidget(mRightPage, ref->mBase->mText);
int i=0;
for (std::vector<std::string>::iterator it=results.begin();
it!=results.end(); ++it)
{
MyGUI::Widget* parent;
if (i%2 == 0)
parent = mLeftPage;
else
parent = mRightPage;
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
pageWidget->setNeedMouseFocus(false);
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
mPages.push_back(pageWidget);
++i;
}
updatePages(); updatePages();
@ -164,19 +143,6 @@ namespace MWGui
mLeftPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 1) ); mLeftPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 1) );
mRightPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 2) ); mRightPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 2) );
unsigned int i=0;
for (std::vector<MyGUI::Widget*>::iterator it = mPages.begin();
it != mPages.end(); ++it)
{
if (mCurrentPage*2 == i || mCurrentPage*2+1 == i)
(*it)->setVisible(true);
else
{
(*it)->setVisible(false);
}
++i;
}
//If it is the last page, hide the button "Next Page" //If it is the last page, hide the button "Next Page"
if ( (mCurrentPage+1)*2 == mPages.size() if ( (mCurrentPage+1)*2 == mPages.size()
|| (mCurrentPage+1)*2 == mPages.size() + 1) || (mCurrentPage+1)*2 == mPages.size() + 1)
@ -191,6 +157,27 @@ namespace MWGui
} else { } else {
mPrevPageButton->setVisible(true); mPrevPageButton->setVisible(true);
} }
if (mPages.empty())
return;
MyGUI::Widget * paper;
paper = mLeftPage->getChildAt(0);
paper->setCoord(paper->getPosition().left, -mPages[mCurrentPage*2].first,
paper->getWidth(), mPages[mCurrentPage*2].second);
paper = mRightPage->getChildAt(0);
if ((mCurrentPage+1)*2 <= mPages.size())
{
paper->setCoord(paper->getPosition().left, -mPages[mCurrentPage*2+1].first,
paper->getWidth(), mPages[mCurrentPage*2+1].second);
paper->setVisible(true);
}
else
{
paper->setVisible(false);
}
} }
void BookWindow::adjustButton (Gui::ImageButton* button) void BookWindow::adjustButton (Gui::ImageButton* button)

@ -34,17 +34,21 @@ namespace MWGui
void adjustButton(Gui::ImageButton* button); void adjustButton(Gui::ImageButton* button);
private: private:
typedef std::pair<int, int> Page;
typedef std::vector<Page> Pages;
Gui::ImageButton* mCloseButton; Gui::ImageButton* mCloseButton;
Gui::ImageButton* mTakeButton; Gui::ImageButton* mTakeButton;
Gui::ImageButton* mNextPageButton; Gui::ImageButton* mNextPageButton;
Gui::ImageButton* mPrevPageButton; Gui::ImageButton* mPrevPageButton;
MyGUI::TextBox* mLeftPageNumber; MyGUI::TextBox* mLeftPageNumber;
MyGUI::TextBox* mRightPageNumber; MyGUI::TextBox* mRightPageNumber;
MyGUI::Widget* mLeftPage; MyGUI::Widget* mLeftPage;
MyGUI::Widget* mRightPage; MyGUI::Widget* mRightPage;
unsigned int mCurrentPage; // 0 is first page unsigned int mCurrentPage; // 0 is first page
std::vector<MyGUI::Widget*> mPages; Pages mPages;
MWWorld::Ptr mBook; MWWorld::Ptr mBook;

@ -277,7 +277,6 @@ namespace MWGui
InfoBoxDialog::InfoBoxDialog() InfoBoxDialog::InfoBoxDialog()
: WindowModal("openmw_infobox.layout") : WindowModal("openmw_infobox.layout")
, mCurrentButton(-1)
{ {
getWidget(mTextBox, "TextBox"); getWidget(mTextBox, "TextBox");
getWidget(mText, "Text"); getWidget(mText, "Text");
@ -306,7 +305,6 @@ namespace MWGui
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
} }
this->mButtons.clear(); this->mButtons.clear();
mCurrentButton = -1;
// TODO: The buttons should be generated from a template in the layout file, ie. cloning an existing widget // TODO: The buttons should be generated from a template in the layout file, ie. cloning an existing widget
MyGUI::Button* button; MyGUI::Button* button;
@ -336,11 +334,6 @@ namespace MWGui
center(); center();
} }
int InfoBoxDialog::getChosenButton() const
{
return mCurrentButton;
}
void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender) void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender)
{ {
std::vector<MyGUI::Button*>::const_iterator end = mButtons.end(); std::vector<MyGUI::Button*>::const_iterator end = mButtons.end();
@ -349,7 +342,6 @@ namespace MWGui
{ {
if (*it == _sender) if (*it == _sender)
{ {
mCurrentButton = i;
eventButtonSelected(i); eventButtonSelected(i);
return; return;
} }
@ -671,8 +663,6 @@ namespace MWGui
// Centre dialog // Centre dialog
center(); center();
setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationMenu1", ""));
getWidget(mSpecialization0, "Specialization0"); getWidget(mSpecialization0, "Specialization0");
getWidget(mSpecialization1, "Specialization1"); getWidget(mSpecialization1, "Specialization1");
getWidget(mSpecialization2, "Specialization2"); getWidget(mSpecialization2, "Specialization2");
@ -694,7 +684,6 @@ namespace MWGui
MyGUI::Button* cancelButton; MyGUI::Button* cancelButton;
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
} }
@ -737,8 +726,6 @@ namespace MWGui
// Centre dialog // Centre dialog
center(); center();
setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sAttributesMenu1", ""));
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
Widgets::MWAttributePtr attribute; Widgets::MWAttributePtr attribute;
@ -752,7 +739,6 @@ namespace MWGui
MyGUI::Button* cancelButton; MyGUI::Button* cancelButton;
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
} }
@ -788,11 +774,6 @@ namespace MWGui
// Centre dialog // Centre dialog
center(); center();
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++) for(int i = 0; i < 9; i++)
{ {
char theIndex = '0'+i; char theIndex = '0'+i;
@ -849,7 +830,6 @@ namespace MWGui
MyGUI::Button* cancelButton; MyGUI::Button* cancelButton;
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
} }

@ -24,7 +24,6 @@ namespace MWGui
void setButtons(ButtonList &buttons); void setButtons(ButtonList &buttons);
virtual void open(); virtual void open();
int getChosenButton() const;
// Events // Events
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int; typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
@ -41,7 +40,6 @@ namespace MWGui
void fitToText(MyGUI::TextBox* widget); void fitToText(MyGUI::TextBox* widget);
void layoutVertically(MyGUI::Widget* widget, int margin); void layoutVertically(MyGUI::Widget* widget, int margin);
int mCurrentButton;
MyGUI::Widget* mTextBox; MyGUI::Widget* mTextBox;
MyGUI::TextBox* mText; MyGUI::TextBox* mText;
MyGUI::Widget* mButtonBar; MyGUI::Widget* mButtonBar;

@ -155,11 +155,6 @@ namespace MWGui
mCommandLine->setFontName(fntName); mCommandLine->setFontName(fntName);
} }
void Console::clearHistory()
{
mHistory->setCaption("");
}
void Console::print(const std::string &msg) void Console::print(const std::string &msg)
{ {
mHistory->addText(msg); mHistory->addText(msg);

@ -48,8 +48,6 @@ namespace MWGui
void onResChange(int width, int height); void onResChange(int width, int height);
void clearHistory();
// Print a message to the console. Messages may contain color // Print a message to the console. Messages may contain color
// code, eg. "#FFFFFF this is white". // code, eg. "#FFFFFF this is white".
void print(const std::string &msg); void print(const std::string &msg);

@ -2,6 +2,8 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -19,7 +21,7 @@ namespace MWGui
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked);
mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange); mItemEdit->eventValueChanged += MyGUI::newDelegate(this, &CountDialog::onEditValueChanged);
mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved); mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved);
// make sure we read the enter key being pressed to accept multiple items // make sure we read the enter key being pressed to accept multiple items
mItemEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &CountDialog::onEnterKeyPressed); mItemEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &CountDialog::onEnterKeyPressed);
@ -46,7 +48,10 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mItemEdit); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mItemEdit);
mSlider->setScrollPosition(maxCount-1); mSlider->setScrollPosition(maxCount-1);
mItemEdit->setCaption(boost::lexical_cast<std::string>(maxCount));
mItemEdit->setMinValue(1);
mItemEdit->setMaxValue(maxCount);
mItemEdit->setValue(maxCount);
} }
void CountDialog::cancel() //Keeping this here as I don't know if anything else relies on it. void CountDialog::cancel() //Keeping this here as I don't know if anything else relies on it.
@ -80,30 +85,13 @@ namespace MWGui
setVisible(false); setVisible(false);
} }
void CountDialog::onEditTextChange(MyGUI::EditBox* _sender) void CountDialog::onEditValueChanged(int value)
{ {
if (_sender->getCaption() == "") mSlider->setScrollPosition(value-1);
return;
unsigned int count;
try
{
count = boost::lexical_cast<unsigned int>(_sender->getCaption());
}
catch (std::bad_cast&)
{
count = 1;
}
if (count > mSlider->getScrollRange())
{
count = mSlider->getScrollRange();
}
mSlider->setScrollPosition(count-1);
onSliderMoved(mSlider, count-1);
} }
void CountDialog::onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position) void CountDialog::onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position)
{ {
mItemEdit->setCaption(boost::lexical_cast<std::string>(_position+1)); mItemEdit->setValue(_position+1);
} }
} }

@ -3,6 +3,11 @@
#include "windowbase.hpp" #include "windowbase.hpp"
namespace Gui
{
class NumericEditBox;
}
namespace MWGui namespace MWGui
{ {
class CountDialog : public WindowModal class CountDialog : public WindowModal
@ -22,7 +27,7 @@ namespace MWGui
private: private:
MyGUI::ScrollBar* mSlider; MyGUI::ScrollBar* mSlider;
MyGUI::EditBox* mItemEdit; Gui::NumericEditBox* mItemEdit;
MyGUI::TextBox* mItemText; MyGUI::TextBox* mItemText;
MyGUI::TextBox* mLabelText; MyGUI::TextBox* mLabelText;
MyGUI::Button* mOkButton; MyGUI::Button* mOkButton;
@ -30,7 +35,7 @@ namespace MWGui
void onCancelButtonClicked(MyGUI::Widget* _sender); void onCancelButtonClicked(MyGUI::Widget* _sender);
void onOkButtonClicked(MyGUI::Widget* _sender); void onOkButtonClicked(MyGUI::Widget* _sender);
void onEditTextChange(MyGUI::EditBox* _sender); void onEditValueChanged(int value);
void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position); void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position);
void onEnterKeyPressed(MyGUI::EditBox* _sender); void onEnterKeyPressed(MyGUI::EditBox* _sender);
}; };

@ -0,0 +1,116 @@
#include "debugwindow.hpp"
#include <LinearMath/btQuickprof.h>
namespace
{
void bulletDumpRecursive(CProfileIterator* pit, int spacing, std::stringstream& os)
{
pit->First();
if (pit->Is_Done())
return;
float accumulated_time=0,parent_time = pit->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : pit->Get_Current_Parent_Total_Time();
int i,j;
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
for (i=0;i<spacing;i++) os << ".";
os << "----------------------------------\n";
for (i=0;i<spacing;i++) os << ".";
std::string s = "Profiling: "+
std::string(pit->Get_Current_Parent_Name())+" (total running time: "+MyGUI::utility::toString(parent_time,3)+" ms) ---\n";
os << s;
//float totalTime = 0.f;
int numChildren = 0;
for (i = 0; !pit->Is_Done(); i++,pit->Next())
{
numChildren++;
float current_total_time = pit->Get_Current_Total_Time();
accumulated_time += current_total_time;
float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
for (j=0;j<spacing;j++) os << ".";
double ms = (current_total_time / (double)frames_since_reset);
s = MyGUI::utility::toString(i)+" -- "+pit->Get_Current_Name()+" ("+MyGUI::utility::toString(fraction,2)+" %) :: "+MyGUI::utility::toString(ms,3)+" ms / frame ("+MyGUI::utility::toString(pit->Get_Current_Total_Calls())+" calls)\n";
os << s;
//totalTime += current_total_time;
//recurse into children
}
if (parent_time < accumulated_time)
{
os << "what's wrong\n";
}
for (i=0;i<spacing;i++) os << ".";
double unaccounted= parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f;
s = "Unaccounted: ("+MyGUI::utility::toString(unaccounted,3)+" %) :: "+MyGUI::utility::toString(parent_time - accumulated_time,3)+" ms\n";
os << s;
for (i=0;i<numChildren;i++)
{
pit->Enter_Child(i);
bulletDumpRecursive(pit, spacing+3, os);
pit->Enter_Parent();
}
}
void bulletDumpAll(std::stringstream& os)
{
CProfileIterator* profileIterator = 0;
profileIterator = CProfileManager::Get_Iterator();
bulletDumpRecursive(profileIterator, 0, os);
CProfileManager::Release_Iterator(profileIterator);
}
}
namespace MWGui
{
DebugWindow::DebugWindow()
: WindowBase("openmw_debug_window.layout")
{
getWidget(mTabControl, "TabControl");
// Ideas for other tabs:
// - Texture / compositor texture viewer
// - Log viewer
// - Material editor
// - Shader editor
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
mBulletProfilerEdit = item->createWidgetReal<MyGUI::EditBox>
("LogEdit", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Stretch);
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
mMainWidget->setSize(viewSize);
}
void DebugWindow::onFrame(float dt)
{
if (!isVisible())
return;
static float timer = 0;
timer -= dt;
if (timer > 0)
return;
timer = 1;
std::stringstream stream;
bulletDumpAll(stream);
if (mBulletProfilerEdit->isTextSelection()) // pause updating while user is trying to copy text
return;
size_t previousPos = mBulletProfilerEdit->getVScrollPosition();
mBulletProfilerEdit->setCaption(stream.str());
mBulletProfilerEdit->setVScrollPosition(std::min(previousPos, mBulletProfilerEdit->getVScrollRange()-1));
}
}

@ -0,0 +1,24 @@
#ifndef OPENMW_MWGUI_DEBUGWINDOW_H
#define OPENMW_MWGUI_DEBUGWINDOW_H
#include "windowbase.hpp"
namespace MWGui
{
class DebugWindow : public WindowBase
{
public:
DebugWindow();
void onFrame(float dt);
private:
MyGUI::TabControl* mTabControl;
MyGUI::EditBox* mBulletProfilerEdit;
};
}
#endif

@ -3,6 +3,8 @@
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/widgets/list.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
@ -17,7 +19,6 @@
#include "../mwdialogue/dialoguemanagerimp.hpp" #include "../mwdialogue/dialoguemanagerimp.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "list.hpp"
#include "tradewindow.hpp" #include "tradewindow.hpp"
#include "spellbuyingwindow.hpp" #include "spellbuyingwindow.hpp"
#include "travelwindow.hpp" #include "travelwindow.hpp"
@ -124,10 +125,10 @@ namespace MWGui
// We need this copy for when @# hyperlinks are replaced // We need this copy for when @# hyperlinks are replaced
std::string text = mText; std::string text = mText;
size_t pos_begin, pos_end; size_t pos_end;
for(;;) for(;;)
{ {
pos_begin = text.find('@'); size_t pos_begin = text.find('@');
if (pos_begin != std::string::npos) if (pos_begin != std::string::npos)
pos_end = text.find('#', pos_begin); pos_end = text.find('#', pos_begin);
@ -561,12 +562,11 @@ namespace MWGui
MyGUI::Button* byeButton; MyGUI::Button* byeButton;
getWidget(byeButton, "ByeButton"); getWidget(byeButton, "ByeButton");
if(MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye) { bool goodbyeEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() || mGoodbye;
byeButton->setEnabled(false); byeButton->setEnabled(goodbyeEnabled);
}
else { bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye;
byeButton->setEnabled(true); mTopicsList->setEnabled(topicsEnabled);
}
} }
void DialogueWindow::notifyLinkClicked (TypesetBook::InteractiveId link) void DialogueWindow::notifyLinkClicked (TypesetBook::InteractiveId link)
@ -656,7 +656,6 @@ namespace MWGui
{ {
mLinks.push_back(new Goodbye()); mLinks.push_back(new Goodbye());
mGoodbye = true; mGoodbye = true;
mTopicsList->setEnabled(false);
mEnabled = false; mEnabled = false;
updateHistory(); updateHistory();
} }

@ -8,14 +8,14 @@
#include "keywordsearch.hpp" #include "keywordsearch.hpp"
namespace Gui
{
class MWList;
}
namespace MWGui namespace MWGui
{ {
class WindowManager; class WindowManager;
namespace Widgets
{
class MWList;
}
} }
/* /*
@ -169,7 +169,7 @@ namespace MWGui
KeywordSearchT mKeywordSearch; KeywordSearchT mKeywordSearch;
BookPage* mHistory; BookPage* mHistory;
Widgets::MWList* mTopicsList; Gui::MWList* mTopicsList;
MyGUI::ScrollBar* mScrollBar; MyGUI::ScrollBar* mScrollBar;
MyGUI::Progress* mDispositionBar; MyGUI::Progress* mDispositionBar;
MyGUI::EditBox* mDispositionText; MyGUI::EditBox* mDispositionText;

@ -2,401 +2,404 @@
#include <components/interpreter/defines.hpp> #include <components/interpreter/defines.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/misc/stringops.hpp>
#include "../mwscript/interpretercontext.hpp" #include "../mwscript/interpretercontext.hpp"
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <OgreUTFString.h>
#include <OgreUTFString.h>
#include <OgreResourceGroupManager.h> #include <OgreResourceGroupManager.h>
namespace #include <MyGUI_EditText.h>
{
int convertFromHex(std::string hex)
{
int value = 0;
int a = 0;
int b = hex.length() - 1;
for (; b >= 0; a++, b--)
{
if (hex[b] >= '0' && hex[b] <= '9')
{
value += (hex[b] - '0') * (1 << (a * 4));
}
else
{
switch (hex[b])
{
case 'A':
case 'a':
value += 10 * (1 << (a * 4));
break;
case 'B':
case 'b':
value += 11 * (1 << (a * 4));
break;
case 'C':
case 'c':
value += 12 * (1 << (a * 4));
break;
case 'D':
case 'd':
value += 13 * (1 << (a * 4));
break;
case 'E':
case 'e':
value += 14 * (1 << (a * 4));
break;
case 'F':
case 'f':
value += 15 * (1 << (a * 4));
break;
default:
throw std::runtime_error("invalid character in hex number");
break;
}
}
}
return value;
}
Ogre::UTFString::unicode_char unicodeCharFromChar(char ch)
{
std::string s;
s += ch;
Ogre::UTFString string(s);
return string.getChar(0);
}
bool is_not_empty(const std::string& s) {
std::string temp = s;
boost::algorithm::trim(temp);
return !temp.empty();
}
}
namespace MWGui namespace MWGui
{ {
namespace Formatting
std::vector<std::string> BookTextParser::split(std::string utf8Text, const int width, const int height)
{ {
using Ogre::UTFString; /* BookTextParser */
std::vector<std::string> result; BookTextParser::BookTextParser(const std::string & text)
: mIndex(0), mText(text), mIgnoreNewlineTags(true), mIgnoreLineEndings(true)
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor {
utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext); MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
mText = Interpreter::fixDefinesBook(mText, interpreterContext);
boost::algorithm::replace_all(utf8Text, "\n", ""); boost::algorithm::replace_all(mText, "\r", "");
boost::algorithm::replace_all(utf8Text, "\r", "");
boost::algorithm::replace_all(utf8Text, "<BR>", "\n");
boost::algorithm::replace_all(utf8Text, "<P>", "\n\n");
UTFString text(utf8Text); registerTag("br", Event_BrTag);
const int spacing = 48; registerTag("p", Event_PTag);
registerTag("img", Event_ImgTag);
registerTag("div", Event_DivTag);
registerTag("font", Event_FontTag);
}
const UTFString::unicode_char LEFT_ANGLE = unicodeCharFromChar('<'); void BookTextParser::registerTag(const std::string & tag, BookTextParser::Events type)
const UTFString::unicode_char NEWLINE = unicodeCharFromChar('\n'); {
const UTFString::unicode_char SPACE = unicodeCharFromChar(' '); mTagTypes[tag] = type;
}
while (!text.empty()) std::string BookTextParser::getReadyText()
{ {
// read in characters until we have exceeded the size, or run out of text return mReadyText;
int currentWidth = 0; }
int currentHeight = 0;
size_t currentWordStart = 0; BookTextParser::Events BookTextParser::next()
size_t index = 0; {
while (mIndex < mText.size())
{
std::string texToTrim = text.asUTF8();
boost::algorithm::trim( texToTrim );
text = UTFString(texToTrim);
}
while (currentHeight <= height - spacing && index < text.size())
{ {
const UTFString::unicode_char ch = text.getChar(index); char ch = mText[mIndex];
if (ch == LEFT_ANGLE) if (ch == '<')
{ {
const size_t tagStart = index + 1; const size_t tagStart = mIndex + 1;
const size_t tagEnd = text.find('>', tagStart); const size_t tagEnd = mText.find('>', tagStart);
if (tagEnd == UTFString::npos) if (tagEnd == std::string::npos)
throw std::runtime_error("BookTextParser Error: Tag is not terminated"); throw std::runtime_error("BookTextParser Error: Tag is not terminated");
const std::string tag = text.substr(tagStart, tagEnd - tagStart).asUTF8(); parseTag(mText.substr(tagStart, tagEnd - tagStart));
mIndex = tagEnd;
if (boost::algorithm::starts_with(tag, "IMG")) if (mTagTypes.find(mTag) != mTagTypes.end())
{ {
const int h = mHeight; Events type = mTagTypes.at(mTag);
parseImage(tag, false);
currentHeight += (mHeight - h); if (type == Event_BrTag || type == Event_PTag)
currentWidth = 0; {
} if (!mIgnoreNewlineTags)
else if (boost::algorithm::starts_with(tag, "FONT")) {
{ if (type == Event_BrTag)
parseFont(tag); mBuffer.push_back('\n');
if (currentWidth != 0) { else
currentHeight += currentFontHeight(); {
mBuffer.append("\n\n");
}
}
mIgnoreLineEndings = true;
} }
currentWidth = 0; else
} flushBuffer();
else if (boost::algorithm::starts_with(tag, "DIV"))
{ if (type == Event_ImgTag)
parseDiv(tag); {
if (currentWidth != 0) { mIgnoreLineEndings = false;
currentHeight += currentFontHeight(); mIgnoreNewlineTags = false;
currentWidth = 0;
} }
++mIndex;
return type;
} }
index = tagEnd;
} }
else if (ch == NEWLINE) else
{ {
currentHeight += currentFontHeight(); if (!mIgnoreLineEndings || ch != '\n')
currentWidth = 0; {
currentWordStart = index; mBuffer.push_back(ch);
mIgnoreLineEndings = false;
mIgnoreNewlineTags = false;
}
} }
else if (ch == SPACE)
++mIndex;
}
flushBuffer();
return Event_EOF;
}
void BookTextParser::flushBuffer()
{
mReadyText = mBuffer;
mBuffer.clear();
}
const BookTextParser::Attributes & BookTextParser::getAttributes() const
{
return mAttributes;
}
void BookTextParser::parseTag(std::string tag)
{
size_t tagNameEndPos = tag.find(' ');
mTag = tag.substr(0, tagNameEndPos);
Misc::StringUtils::toLower(mTag);
mAttributes.clear();
if (tagNameEndPos == std::string::npos)
return;
tag.erase(0, tagNameEndPos+1);
while (!tag.empty())
{
size_t sepPos = tag.find('=');
if (sepPos == std::string::npos)
return;
std::string key = tag.substr(0, sepPos);
Misc::StringUtils::toLower(key);
tag.erase(0, sepPos+1);
std::string value;
if (tag.empty())
return;
if (tag[0] == '"')
{ {
currentWidth += 3; // keep this in sync with the font's SpaceWidth property size_t quoteEndPos = tag.find('"', 1);
currentWordStart = index; if (quoteEndPos == std::string::npos)
throw std::runtime_error("BookTextParser Error: Missing end quote in tag");
value = tag.substr(1, quoteEndPos-1);
tag.erase(0, quoteEndPos+2);
} }
else else
{ {
currentWidth += widthForCharGlyph(ch); size_t valEndPos = tag.find(' ');
if (valEndPos == std::string::npos)
{
value = tag;
tag.erase();
}
else
{
value = tag.substr(0, valEndPos);
tag.erase(0, valEndPos+1);
}
} }
if (currentWidth > width) mAttributes[key] = value;
{
currentHeight += currentFontHeight();
currentWidth = 0;
// add size of the current word
UTFString word = text.substr(currentWordStart, index - currentWordStart);
for (UTFString::const_iterator it = word.begin(), end = word.end(); it != end; ++it)
currentWidth += widthForCharGlyph(it.getCharacter());
}
index += UTFString::_utf16_char_length(ch);
} }
const size_t pageEnd = (currentHeight > height - spacing && currentWordStart != 0)
? currentWordStart : index;
result.push_back(text.substr(0, pageEnd).asUTF8());
text.erase(0, pageEnd);
} }
std::vector<std::string> nonEmptyPages;
boost::copy(result | boost::adaptors::filtered(is_not_empty), std::back_inserter(nonEmptyPages));
return nonEmptyPages;
}
float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const /* BookFormatter */
{ Paginator::Pages BookFormatter::markupToWidget(MyGUI::Widget * parent, const std::string & markup, const int pageWidth, const int pageHeight)
std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont); {
return MyGUI::FontManager::getInstance().getByName(fontName) Paginator pag(pageWidth, pageHeight);
->getGlyphInfo(unicodeChar)->width;
}
float BookTextParser::currentFontHeight() const while (parent->getChildCount())
{ {
std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont); MyGUI::Gui::getInstance().destroyWidget(parent->getChildAt(0));
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight(); }
}
MyGUI::IntSize BookTextParser::parsePage(std::string text, MyGUI::Widget* parent, const int width) MyGUI::Widget * paper = parent->createWidget<MyGUI::Widget>("Widget", MyGUI::IntCoord(0, 0, pag.getPageWidth(), pag.getPageHeight()), MyGUI::Align::Left | MyGUI::Align::Top);
{ paper->setNeedMouseFocus(false);
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext);
mParent = parent; BookTextParser parser(markup);
mWidth = width; for (;;)
mHeight = 0; {
BookTextParser::Events event = parser.next();
if (event == BookTextParser::Event_BrTag || event == BookTextParser::Event_PTag)
continue;
assert(mParent); std::string plainText = parser.getReadyText();
while (mParent->getChildCount()) if (!plainText.empty())
{ {
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0)); // if there's a newline at the end of the box caption, remove it
} if (plainText[plainText.size()-1] == '\n')
plainText.erase(plainText.end()-1);
#if (MYGUI_VERSION < MYGUI_DEFINE_VERSION(3, 2, 2))
// splitting won't be fully functional until 3.2.2 (see TextElement::pageSplit())
// hack: prevent newlines at the end of the book possibly creating unnecessary pages
if (event == BookTextParser::Event_EOF)
{
while (plainText.size() && plainText[plainText.size()-1] == '\n')
plainText.erase(plainText.end()-1);
}
#endif
// remove trailing " TextElement elem(paper, pag, mTextStyle, plainText);
if (text[text.size()-1] == '\"') elem.paginate();
text.erase(text.size()-1); }
parseSubText(text); if (event == BookTextParser::Event_EOF)
return MyGUI::IntSize(mWidth, mHeight); break;
}
MyGUI::IntSize BookTextParser::parseScroll(std::string text, MyGUI::Widget* parent, const int width)
{
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext);
mParent = parent; switch (event)
mWidth = width; {
mHeight = 0; case BookTextParser::Event_ImgTag:
{
const BookTextParser::Attributes & attr = parser.getAttributes();
assert(mParent); if (attr.find("src") == attr.end() || attr.find("width") == attr.end() || attr.find("height") == attr.end())
while (mParent->getChildCount()) continue;
{
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
}
boost::algorithm::replace_all(text, "<BR>", "\n"); std::string src = attr.at("src");
boost::algorithm::replace_all(text, "<P>", "\n\n"); int width = boost::lexical_cast<int>(attr.at("width"));
boost::algorithm::trim_left(text); int height = boost::lexical_cast<int>(attr.at("height"));
// remove trailing " ImageElement elem(paper, pag, src, width, height);
if (text[text.size()-1] == '\"') elem.paginate();
text.erase(text.size()-1); break;
}
case BookTextParser::Event_FontTag:
handleFont(parser.getAttributes());
break;
case BookTextParser::Event_DivTag:
handleDiv(parser.getAttributes());
break;
default:
break;
}
}
parseSubText(text); // insert last page
return MyGUI::IntSize(mWidth, mHeight); if (pag.getStartTop() != pag.getCurrentTop())
} pag << Paginator::Page(pag.getStartTop(), pag.getStartTop() + pag.getPageHeight());
void BookTextParser::parseImage(std::string tag, bool createWidget) paper->setSize(paper->getWidth(), pag.getCurrentTop());
{
int src_start = tag.find("SRC=")+5;
int width_start = tag.find("WIDTH=")+7; return pag.getPages();
int width = boost::lexical_cast<int>(tag.substr(width_start, tag.find('"', width_start)-width_start)); }
int height_start = tag.find("HEIGHT=")+8; Paginator::Pages BookFormatter::markupToWidget(MyGUI::Widget * parent, const std::string & markup)
int height = boost::lexical_cast<int>(tag.substr(height_start, tag.find('"', height_start)-height_start)); {
return markupToWidget(parent, markup, parent->getWidth(), parent->getHeight());
}
if (createWidget) void BookFormatter::handleDiv(const BookTextParser::Attributes & attr)
{ {
MyGUI::ImageBox* box = mParent->createWidget<MyGUI::ImageBox> ("ImageBox", if (attr.find("align") == attr.end())
MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top, return;
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
std::string image = Misc::ResourceHelpers::correctBookartPath(tag.substr(src_start, tag.find('"', src_start)-src_start), width, height); std::string align = attr.at("align");
box->setImageTexture(image);
box->setProperty("NeedMouse", "false"); if (Misc::StringUtils::ciEqual(align, "center"))
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
else if (Misc::StringUtils::ciEqual(align, "left"))
mTextStyle.mTextAlign = MyGUI::Align::Left;
} }
mWidth = std::max(mWidth, width); void BookFormatter::handleFont(const BookTextParser::Attributes & attr)
mHeight += height; {
} if (attr.find("color") != attr.end())
{
int color;
std::stringstream ss;
ss << attr.at("color");
ss >> std::hex >> color;
mTextStyle.mColour = MyGUI::Colour(
(color>>16 & 0xFF) / 255.f,
(color>>8 & 0xFF) / 255.f,
(color & 0xFF) / 255.f);
}
if (attr.find("face") != attr.end())
{
std::string face = attr.at("face");
void BookTextParser::parseDiv(std::string tag) if (face != "Magic Cards")
{ mTextStyle.mFont = face;
if (tag.find("ALIGN=") == std::string::npos) }
return; if (attr.find("size") != attr.end())
{
int align_start = tag.find("ALIGN=")+7; /// \todo
std::string align = tag.substr(align_start, tag.find('"', align_start)-align_start); }
if (align == "CENTER") }
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
else if (align == "LEFT")
mTextStyle.mTextAlign = MyGUI::Align::Left;
}
void BookTextParser::parseFont(std::string tag) /* GraphicElement */
{ GraphicElement::GraphicElement(MyGUI::Widget * parent, Paginator & pag)
if (tag.find("COLOR=") != std::string::npos) : mParent(parent), mPaginator(pag)
{ {
int color_start = tag.find("COLOR=")+7; }
std::string color = tag.substr(color_start, tag.find('"', color_start)-color_start);
mTextStyle.mColour = MyGUI::Colour( void GraphicElement::paginate()
convertFromHex(color.substr(0, 2))/255.0, {
convertFromHex(color.substr(2, 2))/255.0, int newTop = mPaginator.getCurrentTop() + getHeight();
convertFromHex(color.substr(4, 2))/255.0); while (newTop-mPaginator.getStartTop() > mPaginator.getPageHeight())
{
int newStartTop = pageSplit();
mPaginator << Paginator::Page(mPaginator.getStartTop(), newStartTop);
mPaginator.setStartTop(newStartTop);
}
mPaginator.setCurrentTop(newTop);
} }
if (tag.find("FACE=") != std::string::npos)
int GraphicElement::pageSplit()
{ {
int face_start = tag.find("FACE=")+6; return mPaginator.getStartTop() + mPaginator.getPageHeight();
std::string face = tag.substr(face_start, tag.find('"', face_start)-face_start); }
if (face != "Magic Cards") /* TextElement */
mTextStyle.mFont = face; TextElement::TextElement(MyGUI::Widget * parent, Paginator & pag,
const TextStyle & style, const std::string & text)
: GraphicElement(parent, pag),
mStyle(style)
{
MyGUI::EditBox* box = parent->createWidget<MyGUI::EditBox>("NormalText",
MyGUI::IntCoord(0, pag.getCurrentTop(), pag.getPageWidth(), 0), MyGUI::Align::Left | MyGUI::Align::Top,
parent->getName() + boost::lexical_cast<std::string>(parent->getChildCount()));
box->setProperty("Static", "true");
box->setProperty("MultiLine", "true");
box->setProperty("WordWrap", "true");
box->setProperty("NeedMouse", "false");
box->setMaxTextLength(text.size());
box->setTextAlign(mStyle.mTextAlign);
box->setTextColour(mStyle.mColour);
box->setFontName(mStyle.mFont);
box->setCaption(MyGUI::TextIterator::toTagsString(text));
box->setSize(box->getSize().width, box->getTextSize().height);
mEditBox = box;
} }
if (tag.find("SIZE=") != std::string::npos)
int TextElement::currentFontHeight() const
{ {
/// \todo std::string fontName(mStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
} }
}
void BookTextParser::parseSubText(std::string text) int TextElement::getHeight()
{
if (text[0] == '<')
{ {
const size_t tagStart = 1; return mEditBox->getTextSize().height;
const size_t tagEnd = text.find('>', tagStart);
if (tagEnd == std::string::npos)
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
const std::string tag = text.substr(tagStart, tagEnd - tagStart);
if (boost::algorithm::starts_with(tag, "IMG"))
parseImage(tag);
if (boost::algorithm::starts_with(tag, "FONT"))
parseFont(tag);
if (boost::algorithm::starts_with(tag, "DIV"))
parseDiv(tag);
text.erase(0, tagEnd + 1);
} }
size_t tagStart = std::string::npos; int TextElement::pageSplit()
std::string realText; // real text, without tags
for (size_t i = 0; i<text.size(); ++i)
{ {
char c = text[i]; // split lines
if (c == '<') const int lineHeight = currentFontHeight();
unsigned int lastLine = (mPaginator.getStartTop() + mPaginator.getPageHeight() - mPaginator.getCurrentTop()) / lineHeight;
int ret = mPaginator.getCurrentTop() + lastLine * lineHeight;
// first empty lines that would go to the next page should be ignored
// unfortunately, getLineInfo method won't be available until 3.2.2
#if (MYGUI_VERSION >= MYGUI_DEFINE_VERSION(3, 2, 2))
const MyGUI::VectorLineInfo & lines = mEditBox->getSubWidgetText()->castType<MyGUI::EditText>()->getLineInfo();
for (unsigned int i = lastLine; i < lines.size(); ++i)
{ {
if ((i + 1 < text.size()) && text[i+1] == '/') // ignore closing tags if (lines[i].width == 0)
{ ret += lineHeight;
while (c != '>')
{
if (i >= text.size())
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
++i;
c = text[i];
}
continue;
}
else else
{
tagStart = i;
break; break;
}
} }
else #endif
realText += c; return ret;
} }
MyGUI::EditBox* box = mParent->createWidget<MyGUI::EditBox>("NormalText", /* ImageElement */
MyGUI::IntCoord(0, mHeight, mWidth, 24), MyGUI::Align::Left | MyGUI::Align::Top, ImageElement::ImageElement(MyGUI::Widget * parent, Paginator & pag,
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount())); const std::string & src, int width, int height)
box->setProperty("Static", "true"); : GraphicElement(parent, pag),
box->setProperty("MultiLine", "true"); mImageHeight(height)
box->setProperty("WordWrap", "true");
box->setProperty("NeedMouse", "false");
box->setMaxTextLength(realText.size());
box->setTextAlign(mTextStyle.mTextAlign);
box->setTextColour(mTextStyle.mColour);
box->setFontName(mTextStyle.mFont);
box->setCaption(MyGUI::TextIterator::toTagsString(realText));
box->setSize(box->getSize().width, box->getTextSize().height);
mHeight += box->getTextSize().height;
if (tagStart != std::string::npos)
{ {
parseSubText(text.substr(tagStart, text.size())); mImageBox = parent->createWidget<MyGUI::ImageBox> ("ImageBox",
MyGUI::IntCoord(0, pag.getCurrentTop(), width, mImageHeight), MyGUI::Align::Left | MyGUI::Align::Top,
parent->getName() + boost::lexical_cast<std::string>(parent->getChildCount()));
std::string image = Misc::ResourceHelpers::correctBookartPath(src, width, mImageHeight);
mImageBox->setImageTexture(image);
mImageBox->setProperty("NeedMouse", "false");
} }
}
int ImageElement::getHeight()
{
return mImageHeight;
}
int ImageElement::pageSplit()
{
// if the image is larger than the page, fall back to the default pageSplit implementation
if (mImageHeight > mPaginator.getPageHeight())
return GraphicElement::pageSplit();
return mPaginator.getCurrentTop();
}
}
} }

@ -2,66 +2,150 @@
#define MWGUI_FORMATTING_H #define MWGUI_FORMATTING_H
#include <MyGUI.h> #include <MyGUI.h>
#include <map>
namespace MWGui namespace MWGui
{ {
struct TextStyle namespace Formatting
{ {
TextStyle() : struct TextStyle
mColour(0,0,0)
, mFont("Default")
, mTextSize(16)
, mTextAlign(MyGUI::Align::Left | MyGUI::Align::Top)
{ {
} TextStyle() :
mColour(0,0,0)
, mFont("Default")
, mTextSize(16)
, mTextAlign(MyGUI::Align::Left | MyGUI::Align::Top)
{
}
MyGUI::Colour mColour; MyGUI::Colour mColour;
std::string mFont; std::string mFont;
int mTextSize; int mTextSize;
MyGUI::Align mTextAlign; MyGUI::Align mTextAlign;
}; };
/// \brief utilities for parsing book/scroll text as mygui widgets class BookTextParser
class BookTextParser {
{ public:
public: typedef std::map<std::string, std::string> Attributes;
/** enum Events
* Parse markup as MyGUI widgets {
* @param markup to parse Event_None = -2,
* @param parent for the created widgets Event_EOF = -1,
* @param maximum width Event_BrTag,
* @return size of the created widgets Event_PTag,
*/ Event_ImgTag,
MyGUI::IntSize parsePage(std::string text, MyGUI::Widget* parent, const int width); Event_DivTag,
Event_FontTag
/** };
* Parse markup as MyGUI widgets
* @param markup to parse BookTextParser(const std::string & text);
* @param parent for the created widgets void registerTag(const std::string & tag, Events type);
* @param maximum width std::string getReadyText();
* @return size of the created widgets
*/ Events next();
MyGUI::IntSize parseScroll(std::string text, MyGUI::Widget* parent, const int width); void flushBuffer();
const Attributes & getAttributes() const;
/** void parseTag(std::string tag);
* Split the specified text into pieces that fit in the area specified by width and height parameters
*/ private:
std::vector<std::string> split(std::string text, const int width, const int height); size_t mIndex;
std::string mText;
protected: std::string mReadyText;
float widthForCharGlyph(unsigned unicodeChar) const;
float currentFontHeight() const; bool mIgnoreNewlineTags;
void parseSubText(std::string text); bool mIgnoreLineEndings;
Attributes mAttributes;
void parseImage(std::string tag, bool createWidget=true); std::string mTag;
void parseDiv(std::string tag); std::map<std::string, Events> mTagTypes;
void parseFont(std::string tag); std::string mBuffer;
private: };
MyGUI::Widget* mParent;
int mWidth; // maximum width class Paginator
int mHeight; // current height {
TextStyle mTextStyle; public:
}; typedef std::pair<int, int> Page;
typedef std::vector<Page> Pages;
Paginator(int pageWidth, int pageHeight)
: mStartTop(0), mCurrentTop(0),
mPageWidth(pageWidth), mPageHeight(pageHeight)
{
}
int getStartTop() const { return mStartTop; }
int getCurrentTop() const { return mCurrentTop; }
int getPageWidth() const { return mPageWidth; }
int getPageHeight() const { return mPageHeight; }
Pages getPages() const { return mPages; }
void setStartTop(int top) { mStartTop = top; }
void setCurrentTop(int top) { mCurrentTop = top; }
Paginator & operator<<(const Page & page)
{
mPages.push_back(page);
return *this;
}
private:
int mStartTop, mCurrentTop;
int mPageWidth, mPageHeight;
Pages mPages;
};
/// \brief utilities for parsing book/scroll text as mygui widgets
class BookFormatter
{
public:
Paginator::Pages markupToWidget(MyGUI::Widget * parent, const std::string & markup, const int pageWidth, const int pageHeight);
Paginator::Pages markupToWidget(MyGUI::Widget * parent, const std::string & markup);
protected:
void handleImg(const BookTextParser::Attributes & attr);
void handleDiv(const BookTextParser::Attributes & attr);
void handleFont(const BookTextParser::Attributes & attr);
private:
TextStyle mTextStyle;
};
class GraphicElement
{
public:
GraphicElement(MyGUI::Widget * parent, Paginator & pag);
virtual int getHeight() = 0;
virtual void paginate();
virtual int pageSplit();
protected:
MyGUI::Widget * mParent;
Paginator & mPaginator;
};
class TextElement : public GraphicElement
{
public:
TextElement(MyGUI::Widget * parent, Paginator & pag, const TextStyle & style, const std::string & text);
virtual int getHeight();
virtual int pageSplit();
private:
int currentFontHeight() const;
TextStyle mStyle;
MyGUI::EditBox * mEditBox;
};
class ImageElement : public GraphicElement
{
public:
ImageElement(MyGUI::Widget * parent, Paginator & pag, const std::string & src, int width, int height);
virtual int getHeight();
virtual int pageSplit();
private:
int mImageHeight;
MyGUI::ImageBox * mImageBox;
};
}
} }
#endif #endif

@ -278,14 +278,14 @@ namespace MWGui
if (item.mType == ItemStack::Type_Barter) if (item.mType == ItemStack::Type_Barter)
{ {
// this was an item borrowed to us by the merchant // this was an item borrowed to us by the merchant
MWBase::Environment::get().getWindowManager()->getTradeWindow()->returnItem(mSelectedItem, count);
mTradeModel->returnItemBorrowedToUs(mSelectedItem, count); mTradeModel->returnItemBorrowedToUs(mSelectedItem, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->returnItem(mSelectedItem, count);
} }
else else
{ {
// borrow item to the merchant // borrow item to the merchant
MWBase::Environment::get().getWindowManager()->getTradeWindow()->borrowItem(mSelectedItem, count);
mTradeModel->borrowItemFromUs(mSelectedItem, count); mTradeModel->borrowItemFromUs(mSelectedItem, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->borrowItem(mSelectedItem, count);
} }
mItemView->update(); mItemView->update();

@ -36,7 +36,8 @@ namespace MWGui
Misc::StringUtils::toLower(currentGMSTID); Misc::StringUtils::toLower(currentGMSTID);
// Don't bother checking this GMST if it's not a sMagicBound* one. // Don't bother checking this GMST if it's not a sMagicBound* one.
if (currentGMSTID.find("smagicbound") != 0) const std::string& toFind = "smagicbound";
if (currentGMSTID.compare(0, toFind.length(), toFind) != 0)
continue; continue;
// All sMagicBound* GMST's should be of type string // All sMagicBound* GMST's should be of type string

@ -113,10 +113,10 @@ struct JournalViewModelImpl : JournalViewModel
utf8text = getText (); utf8text = getText ();
size_t pos_begin, pos_end; size_t pos_end = 0;
for(;;) for(;;)
{ {
pos_begin = utf8text.find('@'); size_t pos_begin = utf8text.find('@');
if (pos_begin != std::string::npos) if (pos_begin != std::string::npos)
pos_end = utf8text.find('#', pos_begin); pos_end = utf8text.find('#', pos_begin);
@ -223,15 +223,6 @@ struct JournalViewModelImpl : JournalViewModel
} }
} }
void visitQuestName (QuestId questId, boost::function <void (Utf8Span)> visitor) const
{
MWDialogue::Quest const * quest = reinterpret_cast <MWDialogue::Quest const *> (questId);
std::string name = quest->getName ();
visitor (toUtf8Span (name));
}
template <typename iterator_t> template <typename iterator_t>
struct JournalEntryImpl : BaseEntry <iterator_t, JournalEntry> struct JournalEntryImpl : BaseEntry <iterator_t, JournalEntry>
{ {
@ -301,11 +292,6 @@ struct JournalViewModelImpl : JournalViewModel
} }
} }
void visitTopics (boost::function <void (TopicId, Utf8Span)> visitor) const
{
throw std::runtime_error ("not implemented");
}
void visitTopicName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const void visitTopicName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const
{ {
MWDialogue::Topic const & topic = * reinterpret_cast <MWDialogue::Topic const *> (topicId); MWDialogue::Topic const & topic = * reinterpret_cast <MWDialogue::Topic const *> (topicId);

@ -67,9 +67,6 @@ namespace MWGui
/// returns true if their are no journal entries to display /// returns true if their are no journal entries to display
virtual bool isEmpty () const = 0; virtual bool isEmpty () const = 0;
/// provides access to the name of the quest with the specified identifier
virtual void visitQuestName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const = 0;
/// walks the active and optionally completed, quests providing the name /// walks the active and optionally completed, quests providing the name
virtual void visitQuestNames (bool active_only, boost::function <void (const std::string&)> visitor) const = 0; virtual void visitQuestNames (bool active_only, boost::function <void (const std::string&)> visitor) const = 0;

@ -4,7 +4,6 @@
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/journal.hpp" #include "../mwbase/journal.hpp"
#include "list.hpp"
#include <sstream> #include <sstream>
#include <set> #include <set>
@ -16,12 +15,12 @@
#include "boost/lexical_cast.hpp" #include "boost/lexical_cast.hpp"
#include <components/widgets/imagebutton.hpp> #include <components/widgets/imagebutton.hpp>
#include <components/widgets/list.hpp>
#include "bookpage.hpp" #include "bookpage.hpp"
#include "windowbase.hpp" #include "windowbase.hpp"
#include "journalviewmodel.hpp" #include "journalviewmodel.hpp"
#include "journalbooks.hpp" #include "journalbooks.hpp"
#include "list.hpp"
namespace namespace
{ {
@ -111,10 +110,10 @@ namespace
adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll ); adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll );
adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive); adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(QuestsList); Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked); list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked);
MWGui::Widgets::MWList* topicsList = getWidget<MWGui::Widgets::MWList>(TopicsList); Gui::MWList* topicsList = getWidget<Gui::MWList>(TopicsList);
topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected); topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected);
{ {
@ -394,25 +393,13 @@ namespace
popBook (); popBook ();
} }
void showList (char const * listId, char const * pageId, Book book)
{
std::pair <int, int> size = book->getSize ();
getPage (pageId)->showPage (book, 0);
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
getWidget <MyGUI::ScrollView> (listId)->setVisibleVScroll(false);
getWidget <MyGUI::ScrollView> (listId)->setCanvasSize (size.first, size.second);
getWidget <MyGUI::ScrollView> (listId)->setVisibleVScroll(true);
}
void notifyIndexLinkClicked (MWGui::TypesetBook::InteractiveId character) void notifyIndexLinkClicked (MWGui::TypesetBook::InteractiveId character)
{ {
setVisible (LeftTopicIndex, false); setVisible (LeftTopicIndex, false);
setVisible (RightTopicIndex, false); setVisible (RightTopicIndex, false);
setVisible (TopicsList, true); setVisible (TopicsList, true);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(TopicsList); Gui::MWList* list = getWidget<Gui::MWList>(TopicsList);
list->clear(); list->clear();
AddNamesToList add(list); AddNamesToList add(list);
@ -435,9 +422,9 @@ namespace
struct AddNamesToList struct AddNamesToList
{ {
AddNamesToList(MWGui::Widgets::MWList* list) : mList(list) {} AddNamesToList(Gui::MWList* list) : mList(list) {}
MWGui::Widgets::MWList* mList; Gui::MWList* mList;
void operator () (const std::string& name) void operator () (const std::string& name)
{ {
mList->addItem(name); mList->addItem(name);
@ -455,7 +442,7 @@ namespace
setVisible (ShowAllBTN, !mAllQuests); setVisible (ShowAllBTN, !mAllQuests);
setVisible (ShowActiveBTN, mAllQuests); setVisible (ShowActiveBTN, mAllQuests);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(QuestsList); Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
list->clear(); list->clear();
AddNamesToList add(list); AddNamesToList add(list);

@ -5,6 +5,7 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/fallback.hpp" #include "../mwworld/fallback.hpp"
@ -139,7 +140,7 @@ namespace MWGui
// Vanilla uses thief.dds for custom classes. // Vanilla uses thief.dds for custom classes.
// Choosing Stealth specialization and Speed/Agility as attributes, if possible. Otherwise fall back to first class found. // Choosing Stealth specialization and Speed/Agility as attributes, if possible. Otherwise fall back to first class found.
MWWorld::SharedIterator<ESM::Class> it = world->getStore().get<ESM::Class>().begin(); MWWorld::SharedIterator<ESM::Class> it = world->getStore().get<ESM::Class>().begin();
for(; it != world->getStore().get<ESM::Class>().end(); it++) for(; it != world->getStore().get<ESM::Class>().end(); ++it)
{ {
if(it->mData.mIsPlayable && it->mData.mSpecialization == 2 && it->mData.mAttribute[0] == 4 && it->mData.mAttribute[1] == 3) if(it->mData.mIsPlayable && it->mData.mSpecialization == 2 && it->mData.mAttribute[0] == 4 && it->mData.mAttribute[1] == 3)
break; break;
@ -191,6 +192,9 @@ namespace MWGui
setAttributeValues(); setAttributeValues();
center(); center();
// Play LevelUp Music
MWBase::Environment::get().getSoundManager()->streamMusic("Special/MW_Triumph.mp3");
} }
void LevelupDialog::onOkButtonClicked(MyGUI::Widget* sender) void LevelupDialog::onOkButtonClicked(MyGUI::Widget* sender)

@ -1,169 +0,0 @@
#include "list.hpp"
#include <MyGUI_Gui.h>
#include <MyGUI_Button.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ScrollBar.h>
namespace MWGui
{
namespace Widgets
{
MWList::MWList() :
mClient(0)
, mScrollView(0)
, mItemHeight(0)
{
}
void MWList::initialiseOverride()
{
Base::initialiseOverride();
assignWidget(mClient, "Client");
if (mClient == 0)
mClient = this;
mScrollView = mClient->createWidgetReal<MyGUI::ScrollView>(
"MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0),
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
}
void MWList::addItem(const std::string& name)
{
mItems.push_back(name);
}
void MWList::addSeparator()
{
mItems.push_back("");
}
void MWList::adjustSize()
{
redraw();
}
void MWList::redraw(bool scrollbarShown)
{
const int _scrollBarWidth = 20; // fetch this from skin?
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
const int spacing = 3;
size_t viewPosition = -mScrollView->getViewOffset().top;
while (mScrollView->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mScrollView->getChildAt(0));
}
mItemHeight = 0;
int i=0;
for (std::vector<std::string>::const_iterator it=mItems.begin();
it!=mItems.end(); ++it)
{
if (*it != "")
{
if (mListItemSkin.empty())
throw std::runtime_error("MWList needs a ListItemSkin property");
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(
mListItemSkin, MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it));
button->setCaption((*it));
button->getSubWidgetText()->setWordWrap(true);
button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected);
int height = button->getTextSize().height;
button->setSize(MyGUI::IntSize(button->getSize().width, height));
button->setUserData(i);
mItemHeight += height + spacing;
}
else
{
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine",
MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth() - scrollBarWidth - 4, 18),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
separator->setNeedMouseFocus(false);
mItemHeight += 18 + spacing;
}
++i;
}
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
mScrollView->setVisibleVScroll(false);
mScrollView->setCanvasSize(mClient->getSize().width, std::max(mItemHeight, mClient->getSize().height));
mScrollView->setVisibleVScroll(true);
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
redraw(true);
size_t viewRange = mScrollView->getCanvasSize().height;
if(viewPosition > viewRange)
viewPosition = viewRange;
mScrollView->setViewOffset(MyGUI::IntPoint(0, viewPosition * -1));
}
void MWList::setPropertyOverride(const std::string &_key, const std::string &_value)
{
if (_key == "ListItemSkin")
mListItemSkin = _value;
else
Base::setPropertyOverride(_key, _value);
}
bool MWList::hasItem(const std::string& name)
{
return (std::find(mItems.begin(), mItems.end(), name) != mItems.end());
}
unsigned int MWList::getItemCount()
{
return mItems.size();
}
std::string MWList::getItemNameAt(unsigned int at)
{
assert(at < mItems.size() && "List item out of bounds");
return mItems[at];
}
void MWList::removeItem(const std::string& name)
{
assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() );
mItems.erase( std::find(mItems.begin(), mItems.end(), name) );
}
void MWList::clear()
{
mItems.clear();
}
void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
//NB view offset is negative
if (mScrollView->getViewOffset().top + _rel*0.3 > 0)
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3));
}
void MWList::onItemSelected(MyGUI::Widget* _sender)
{
std::string name = _sender->castType<MyGUI::Button>()->getCaption();
int id = *_sender->getUserData<int>();
eventItemSelected(name, id);
eventWidgetSelected(_sender);
}
MyGUI::Widget* MWList::getItemWidget(const std::string& name)
{
return mScrollView->findWidget (getName() + "_item_" + name);
}
}
}

@ -1,74 +0,0 @@
#ifndef MWGUI_LIST_HPP
#define MWGUI_LIST_HPP
#include <MyGUI_ScrollView.h>
namespace MWGui
{
namespace Widgets
{
/**
* \brief a very simple list widget that supports word-wrapping entries
* \note if the width or height of the list changes, you must call adjustSize() method
*/
class MWList : public MyGUI::Widget
{
MYGUI_RTTI_DERIVED(MWList)
public:
MWList();
typedef MyGUI::delegates::CMultiDelegate2<const std::string&, int> EventHandle_StringInt;
typedef MyGUI::delegates::CMultiDelegate1<MyGUI::Widget*> EventHandle_Widget;
/**
* Event: Item selected with the mouse.
* signature: void method(std::string itemName, int index)
*/
EventHandle_StringInt eventItemSelected;
/**
* Event: Item selected with the mouse.
* signature: void method(MyGUI::Widget* sender)
*/
EventHandle_Widget eventWidgetSelected;
/**
* Call after the size of the list changed, or items were inserted/removed
*/
void adjustSize();
void addItem(const std::string& name);
void addSeparator(); ///< add a seperator between the current and the next item.
void removeItem(const std::string& name);
bool hasItem(const std::string& name);
unsigned int getItemCount();
std::string getItemNameAt(unsigned int at); ///< \attention if there are separators, this method will return "" at the place where the separator is
void clear();
MyGUI::Widget* getItemWidget(const std::string& name);
///< get widget for an item name, useful to set up tooltip
virtual void setPropertyOverride(const std::string& _key, const std::string& _value);
protected:
void initialiseOverride();
void redraw(bool scrollbarShown = false);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onItemSelected(MyGUI::Widget* _sender);
private:
MyGUI::ScrollView* mScrollView;
MyGUI::Widget* mClient;
std::string mListItemSkin;
std::vector<std::string> mItems;
int mItemHeight; // height of all items
};
}
}
#endif

@ -26,15 +26,55 @@ namespace
const int cellSize = 8192; const int cellSize = 8192;
enum WidgetDepth enum LocalMapWidgetDepth
{ {
CompassLayer = 0, Local_CompassLayer = 0,
MarkerAboveFogLayer = 1, Local_MarkerAboveFogLayer = 1,
FogLayer = 2, Local_FogLayer = 2,
MarkerLayer = 3, Local_MarkerLayer = 3,
MapLayer = 4 Local_MapLayer = 4
}; };
enum GlobalMapWidgetDepth
{
Global_CompassLayer = 0,
Global_MarkerLayer = 1,
Global_ExploreOverlayLayer = 2,
Global_MapLayer = 3
};
/// @brief A widget that changes its color when hovered.
class MarkerWidget: public MyGUI::Widget
{
MYGUI_RTTI_DERIVED(MarkerWidget)
public:
void setNormalColour(const MyGUI::Colour& colour)
{
mNormalColour = colour;
setColour(colour);
}
void setHoverColour(const MyGUI::Colour& colour)
{
mHoverColour = colour;
}
private:
MyGUI::Colour mNormalColour;
MyGUI::Colour mHoverColour;
void onMouseLostFocus(MyGUI::Widget* _new)
{
setColour(mNormalColour);
}
void onMouseSetFocus(MyGUI::Widget* _old)
{
setColour(mHoverColour);
}
};
} }
namespace MWGui namespace MWGui
@ -140,7 +180,7 @@ namespace MWGui
mLocalMap = widget; mLocalMap = widget;
mCompass = compass; mCompass = compass;
mCompass->setDepth(CompassLayer); mCompass->setDepth(Local_CompassLayer);
mCompass->setNeedMouseFocus(false); mCompass->setNeedMouseFocus(false);
// create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each // create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each
@ -151,12 +191,12 @@ namespace MWGui
MyGUI::ImageBox* map = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::ImageBox* map = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize),
MyGUI::Align::Top | MyGUI::Align::Left); MyGUI::Align::Top | MyGUI::Align::Left);
map->setDepth(MapLayer); map->setDepth(Local_MapLayer);
MyGUI::ImageBox* fog = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::ImageBox* fog = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize), MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize),
MyGUI::Align::Top | MyGUI::Align::Left); MyGUI::Align::Top | MyGUI::Align::Left);
fog->setDepth(FogLayer); fog->setDepth(Local_FogLayer);
map->setNeedMouseFocus(false); map->setNeedMouseFocus(false);
fog->setNeedMouseFocus(false); fog->setNeedMouseFocus(false);
@ -273,16 +313,17 @@ namespace MWGui
MyGUI::IntCoord widgetCoord(widgetPos.left - 4, MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4, widgetPos.top - 4,
8, 8); 8, 8);
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage", MarkerWidget* markerWidget = mLocalMap->createWidget<MarkerWidget>("MarkerButton",
widgetCoord, MyGUI::Align::Default); widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerAboveFogLayer); markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote)); markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote));
markerWidget->setColour(MyGUI::Colour(1.0,0.3,0.3)); markerWidget->setNormalColour(MyGUI::Colour(1.0,0.3,0.3));
markerWidget->setHoverColour(MyGUI::Colour(1.0,0.5,0.5));
markerWidget->setUserData(marker); markerWidget->setUserData(marker);
markerWidget->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &LocalMapBase::onCustomMarkerDoubleClicked); markerWidget->setNeedMouseFocus(true);
customMarkerCreated(markerWidget);
mCustomMarkerWidgets.push_back(markerWidget); mCustomMarkerWidgets.push_back(markerWidget);
} }
redraw(); redraw();
@ -357,16 +398,19 @@ namespace MWGui
widgetPos.top - 4, widgetPos.top - 4,
8, 8); 8, 8);
++counter; ++counter;
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage", MarkerWidget* markerWidget = mLocalMap->createWidget<MarkerWidget>("MarkerButton",
widgetCoord, MyGUI::Align::Default); widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerLayer); markerWidget->setNormalColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}")));
markerWidget->setImageResource("DoorMarker"); markerWidget->setHoverColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal_over}")));
markerWidget->setDepth(Local_MarkerLayer);
markerWidget->setNeedMouseFocus(true);
markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", marker.name); markerWidget->setUserString("Caption_TextOneLine", marker.name);
// Used by tooltips to not show the tooltip if marker is hidden by fog of war // Used by tooltips to not show the tooltip if marker is hidden by fog of war
markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos); markerWidget->setUserData(markerPos);
doorMarkerCreated(markerWidget);
mDoorMarkerWidgets.push_back(markerWidget); mDoorMarkerWidgets.push_back(markerWidget);
} }
@ -458,7 +502,7 @@ namespace MWGui
++counter; ++counter;
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
widgetCoord, MyGUI::Align::Default); widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerAboveFogLayer); markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageTexture(markerTexture); markerWidget->setImageTexture(markerTexture);
markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos); markerWidget->setUserData(markerPos);
@ -503,7 +547,7 @@ namespace MWGui
8, 8); 8, 8);
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
widgetCoord, MyGUI::Align::Default); widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerAboveFogLayer); markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageTexture("textures\\menu_map_smark.dds"); markerWidget->setImageTexture("textures\\menu_map_smark.dds");
markerWidget->setUserString("IsMarker", "true"); markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos); markerWidget->setUserData(markerPos);
@ -523,7 +567,18 @@ namespace MWGui
, mGlobalMap(0) , mGlobalMap(0)
, mGlobalMapRender(0) , mGlobalMapRender(0)
, mEditNoteDialog() , mEditNoteDialog()
, mEventBoxGlobal(NULL)
, mEventBoxLocal(NULL)
, mGlobalMapImage(NULL)
, mGlobalMapOverlay(NULL)
{ {
static bool registered = false;
if (!registered)
{
MyGUI::FactoryManager::getInstance().registerFactory<MarkerWidget>("Widget");
registered = true;
}
mEditNoteDialog.setVisible(false); mEditNoteDialog.setVisible(false);
mEditNoteDialog.eventOkClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditOk); mEditNoteDialog.eventOkClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditOk);
mEditNoteDialog.eventDeleteClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditDelete); mEditNoteDialog.eventDeleteClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditDelete);
@ -537,6 +592,11 @@ namespace MWGui
getWidget(mPlayerArrowLocal, "CompassLocal"); getWidget(mPlayerArrowLocal, "CompassLocal");
getWidget(mPlayerArrowGlobal, "CompassGlobal"); getWidget(mPlayerArrowGlobal, "CompassGlobal");
mPlayerArrowGlobal->setDepth(Global_CompassLayer);
mPlayerArrowGlobal->setNeedMouseFocus(false);
mGlobalMapImage->setDepth(Global_MapLayer);
mGlobalMapOverlay->setDepth(Global_ExploreOverlayLayer);
mLastScrollWindowCoordinates = mLocalMap->getCoord(); mLastScrollWindowCoordinates = mLocalMap->getCoord();
mLocalMap->eventChangeCoord += MyGUI::newDelegate(this, &MapWindow::onChangeScrollWindowCoord); mLocalMap->eventChangeCoord += MyGUI::newDelegate(this, &MapWindow::onChangeScrollWindowCoord);
@ -549,6 +609,8 @@ namespace MWGui
getWidget(mEventBoxGlobal, "EventBoxGlobal"); getWidget(mEventBoxGlobal, "EventBoxGlobal");
mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
mEventBoxGlobal->setDepth(Global_ExploreOverlayLayer);
getWidget(mEventBoxLocal, "EventBoxLocal"); getWidget(mEventBoxLocal, "EventBoxLocal");
mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
@ -672,34 +734,32 @@ namespace MWGui
void MapWindow::addVisitedLocation(const std::string& name, int x, int y) 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 = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default);
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
++_counter;
markerWidget = mEventBoxGlobal->createWidget<MyGUI::Button>("",
widgetCoord, MyGUI::Align::Default);
markerWidget->setNeedMouseFocus (true);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
CellId cell; CellId cell;
cell.first = x; cell.first = x;
cell.second = y; cell.second = y;
mMarkers.push_back(cell); if (mMarkers.insert(cell).second)
{
float worldX, worldY;
mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY);
int markerSize = 12;
int offset = mGlobalMapRender->getCellSize()/2 - markerSize/2;
MyGUI::IntCoord widgetCoord(
worldX * mGlobalMapRender->getWidth()+offset,
worldY * mGlobalMapRender->getHeight()+offset,
markerSize, markerSize);
MyGUI::Widget* markerWidget = mGlobalMap->createWidget<MyGUI::Widget>("MarkerButton",
widgetCoord, MyGUI::Align::Default);
markerWidget->setNeedMouseFocus(true);
markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}")));
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
markerWidget->setDepth(Global_MarkerLayer);
markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
}
} }
void MapWindow::cellExplored(int x, int y) void MapWindow::cellExplored(int x, int y)
@ -827,8 +887,6 @@ namespace MWGui
while (mEventBoxGlobal->getChildCount()) while (mEventBoxGlobal->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mEventBoxGlobal->getChildAt(0)); MyGUI::Gui::getInstance().destroyWidget(mEventBoxGlobal->getChildAt(0));
while (mGlobalMapOverlay->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0));
} }
void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress) void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress)
@ -853,7 +911,7 @@ namespace MWGui
mGlobalMapRender->read(map); mGlobalMapRender->read(map);
for (std::vector<ESM::GlobalMap::CellId>::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it) for (std::set<ESM::GlobalMap::CellId>::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it)
{ {
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second); const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
if (cell && !cell->mName.empty()) if (cell && !cell->mName.empty())
@ -871,6 +929,19 @@ namespace MWGui
(*it)->setVisible(alpha == 1); (*it)->setVisible(alpha == 1);
} }
void MapWindow::customMarkerCreated(MyGUI::Widget *marker)
{
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
marker->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onCustomMarkerDoubleClicked);
}
void MapWindow::doorMarkerCreated(MyGUI::Widget *marker)
{
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
EditNoteDialog::EditNoteDialog() EditNoteDialog::EditNoteDialog()

@ -119,7 +119,8 @@ namespace MWGui
virtual void notifyPlayerUpdate() {} virtual void notifyPlayerUpdate() {}
virtual void notifyMapChanged() {} virtual void notifyMapChanged() {}
virtual void onCustomMarkerDoubleClicked(MyGUI::Widget* sender) {} virtual void customMarkerCreated(MyGUI::Widget* marker) {}
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
void updateMagicMarkers(); void updateMagicMarkers();
void addDetectionMarkers(int type); void addDetectionMarkers(int type);
@ -199,6 +200,7 @@ namespace MWGui
void onMouseDrag(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 onWorldButtonClicked(MyGUI::Widget* _sender);
void onMapDoubleClicked(MyGUI::Widget* sender); void onMapDoubleClicked(MyGUI::Widget* sender);
void onCustomMarkerDoubleClicked(MyGUI::Widget* sender);
void onNoteEditOk(); void onNoteEditOk();
void onNoteEditDelete(); void onNoteEditDelete();
void onNoteEditDeleteConfirm(); void onNoteEditDeleteConfirm();
@ -219,7 +221,7 @@ namespace MWGui
// Markers on global map // Markers on global map
typedef std::pair<int, int> CellId; typedef std::pair<int, int> CellId;
std::vector<CellId> mMarkers; std::set<CellId> mMarkers;
// Cells that should be explored in the next frame (i.e. their map revealed on the global map) // Cells that should be explored in the next frame (i.e. their map revealed on the global map)
// We can't do this immediately, because the map update is not immediate either (see mNeedMapUpdate in scene.cpp) // We can't do this immediately, because the map update is not immediate either (see mNeedMapUpdate in scene.cpp)
@ -235,7 +237,9 @@ namespace MWGui
virtual void onPinToggled(); virtual void onPinToggled();
virtual void onTitleDoubleClicked(); virtual void onTitleDoubleClicked();
virtual void onCustomMarkerDoubleClicked(MyGUI::Widget* sender);
virtual void doorMarkerCreated(MyGUI::Widget* marker);
virtual void customMarkerCreated(MyGUI::Widget *marker);
virtual void notifyPlayerUpdate(); virtual void notifyPlayerUpdate();

@ -139,11 +139,6 @@ namespace MWGui
return false; return false;
} }
void MessageBoxManager::setMessageBoxSpeed (int speed)
{
mMessageBoxSpeed = speed;
}
int MessageBoxManager::readPressedButton () int MessageBoxManager::readPressedButton ()
{ {
int pressed = mLastButtonPressed; int pressed = mLastButtonPressed;
@ -218,7 +213,6 @@ namespace MWGui
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
int biggestButtonWidth = 0; int biggestButtonWidth = 0;
int buttonWidth = 0;
int buttonsWidth = 0; int buttonsWidth = 0;
int buttonsHeight = 0; int buttonsHeight = 0;
int buttonHeight = 0; int buttonHeight = 0;
@ -241,7 +235,7 @@ namespace MWGui
if (buttonsWidth != 0) if (buttonsWidth != 0)
buttonsWidth += buttonLeftPadding; buttonsWidth += buttonLeftPadding;
buttonWidth = button->getTextSize().width + 2*buttonPadding; int buttonWidth = button->getTextSize().width + 2*buttonPadding;
buttonsWidth += buttonWidth; buttonsWidth += buttonWidth;
buttonHeight = button->getTextSize().height + 2*buttonPadding; buttonHeight = button->getTextSize().height + 2*buttonPadding;

@ -34,7 +34,6 @@ namespace MWGui
void clear(); void clear();
bool removeMessageBox (MessageBox *msgbox); bool removeMessageBox (MessageBox *msgbox);
void setMessageBoxSpeed (int speed);
int readPressedButton (); int readPressedButton ();

@ -393,7 +393,6 @@ namespace MWGui
if (mCurrentRaceId.empty()) if (mCurrentRaceId.empty())
return; return;
Widgets::MWSpellPtr spellPowerWidget;
const int lineHeight = 18; const int lineHeight = 18;
MyGUI::IntCoord coord(0, 0, mSpellPowerList->getWidth(), 18); MyGUI::IntCoord coord(0, 0, mSpellPowerList->getWidth(), 18);
@ -405,7 +404,7 @@ namespace MWGui
for (int i = 0; it != end; ++it) for (int i = 0; it != end; ++it)
{ {
const std::string &spellpower = *it; const std::string &spellpower = *it;
spellPowerWidget = mSpellPowerList->createWidget<Widgets::MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i)); Widgets::MWSpellPtr spellPowerWidget = mSpellPowerList->createWidget<Widgets::MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i));
spellPowerWidget->setSpellId(spellpower); spellPowerWidget->setSpellId(spellpower);
spellPowerWidget->setUserString("ToolTipType", "Spell"); spellPowerWidget->setUserString("ToolTipType", "Spell");
spellPowerWidget->setUserString("Spell", spellpower); spellPowerWidget->setUserString("Spell", spellpower);

@ -322,7 +322,8 @@ namespace MWGui
if (i == pos) if (i == pos)
mCurrentSlot = &*it; mCurrentSlot = &*it;
} }
assert(mCurrentSlot && "Can't find selected slot"); if (!mCurrentSlot)
throw std::runtime_error("Can't find selected slot");
std::stringstream text; std::stringstream text;
time_t time = mCurrentSlot->mTimeStamp; time_t time = mCurrentSlot->mTimeStamp;

@ -54,8 +54,9 @@ namespace MWGui
MWWorld::LiveCellRef<ESM::Book> *ref = mScroll.get<ESM::Book>(); MWWorld::LiveCellRef<ESM::Book> *ref = mScroll.get<ESM::Book>();
BookTextParser parser; Formatting::BookFormatter formatter;
MyGUI::IntSize size = parser.parseScroll(ref->mBase->mText, mTextView, 390); formatter.markupToWidget(mTextView, ref->mBase->mText, 390, mTextView->getHeight());
MyGUI::IntSize size = mTextView->getChildAt(0)->getSize();
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
mTextView->setVisibleVScroll(false); mTextView->setVisibleVScroll(false);

@ -362,8 +362,7 @@ namespace MWGui
void SettingsWindow::onShaderModeToggled(MyGUI::Widget* _sender) void SettingsWindow::onShaderModeToggled(MyGUI::Widget* _sender)
{ {
std::string val = _sender->castType<MyGUI::Button>()->getCaption(); std::string val = hlslGlsl();
val = hlslGlsl();
_sender->castType<MyGUI::Button>()->setCaption(val); _sender->castType<MyGUI::Button>()->setCaption(val);

@ -39,6 +39,7 @@ namespace MWGui
EditEffectDialog::EditEffectDialog() EditEffectDialog::EditEffectDialog()
: WindowModal("openmw_edit_effect.layout") : WindowModal("openmw_edit_effect.layout")
, mEditing(false) , mEditing(false)
, mMagicEffect(NULL)
{ {
getWidget(mCancelButton, "CancelButton"); getWidget(mCancelButton, "CancelButton");
getWidget(mOkButton, "OkButton"); getWidget(mOkButton, "OkButton");
@ -181,7 +182,7 @@ namespace MWGui
{ {
mAreaBox->setPosition(mAreaBox->getPosition().left, curY); mAreaBox->setPosition(mAreaBox->getPosition().left, curY);
mAreaBox->setVisible (true); mAreaBox->setVisible (true);
curY += mAreaBox->getSize().height; //curY += mAreaBox->getSize().height;
} }
} }
@ -522,7 +523,7 @@ namespace MWGui
updateEffectsView (); updateEffectsView ();
} }
void EffectEditorBase::setWidgets (Widgets::MWList *availableEffectsList, MyGUI::ScrollView *usedEffectsView) void EffectEditorBase::setWidgets (Gui::MWList *availableEffectsList, MyGUI::ScrollView *usedEffectsView)
{ {
mAvailableEffectsList = availableEffectsList; mAvailableEffectsList = availableEffectsList;
mUsedEffectsView = usedEffectsView; mUsedEffectsView = usedEffectsView;

@ -1,9 +1,10 @@
#ifndef MWGUI_SPELLCREATION_H #ifndef MWGUI_SPELLCREATION_H
#define MWGUI_SPELLCREATION_H #define MWGUI_SPELLCREATION_H
#include <components/widgets/list.hpp>
#include "windowbase.hpp" #include "windowbase.hpp"
#include "referenceinterface.hpp" #include "referenceinterface.hpp"
#include "list.hpp"
#include "widgets.hpp" #include "widgets.hpp"
namespace MWGui namespace MWGui
@ -97,7 +98,7 @@ namespace MWGui
protected: protected:
std::map<int, short> mButtonMapping; // maps button ID to effect ID std::map<int, short> mButtonMapping; // maps button ID to effect ID
Widgets::MWList* mAvailableEffectsList; Gui::MWList* mAvailableEffectsList;
MyGUI::ScrollView* mUsedEffectsView; MyGUI::ScrollView* mUsedEffectsView;
EditEffectDialog mAddEffectDialog; EditEffectDialog mAddEffectDialog;
@ -124,7 +125,7 @@ namespace MWGui
void updateEffectsView(); void updateEffectsView();
void startEditing(); void startEditing();
void setWidgets (Widgets::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView); void setWidgets (Gui::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView);
virtual void notifyEffectsChanged () {} virtual void notifyEffectsChanged () {}
@ -157,8 +158,6 @@ namespace MWGui
MyGUI::Button* mCancelButton; MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPriceLabel; MyGUI::TextBox* mPriceLabel;
Widgets::MWEffectList* mUsedEffectsList;
ESM::Spell mSpell; ESM::Spell mSpell;
}; };

@ -2,6 +2,8 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
@ -86,7 +88,7 @@ namespace MWGui
mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed); mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed);
mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased); mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased);
mTotalBalance->eventEditTextChange += MyGUI::newDelegate(this, &TradeWindow::onBalanceEdited); mTotalBalance->eventValueChanged += MyGUI::newDelegate(this, &TradeWindow::onBalanceValueChanged);
setCoord(400, 0, 400, 300); setCoord(400, 0, 400, 300);
} }
@ -324,12 +326,12 @@ namespace MWGui
const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player); const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player);
float a1 = std::min(player.getClass().getSkill(player, ESM::Skill::Mercantile), 100); float a1 = player.getClass().getSkill(player, ESM::Skill::Mercantile);
float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); float b1 = 0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified();
float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); float c1 = 0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified();
float d1 = std::min(mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile), 100); float d1 = mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile);
float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); float e1 = 0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified();
float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); float f1 = 0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified();
float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm();
float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm(); float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm();
@ -352,7 +354,15 @@ namespace MWGui
} }
//skill use! //skill use!
player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0); float skillGain = 0.f;
int finalPrice = std::abs(mCurrentBalance);
int initialMerchantOffer = std::abs(mCurrentMerchantOffer);
if (!buying && (finalPrice > initialMerchantOffer) && finalPrice > 0)
skillGain = int(100 * (finalPrice - initialMerchantOffer) / float(finalPrice));
else if (buying && (finalPrice < initialMerchantOffer) && initialMerchantOffer > 0)
skillGain = int(100 * (initialMerchantOffer - finalPrice) / float(initialMerchantOffer));
player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0, skillGain);
} }
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt(); int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
@ -425,21 +435,14 @@ namespace MWGui
MyGUI::ControllerManager::getInstance().removeItem(_sender); MyGUI::ControllerManager::getInstance().removeItem(_sender);
} }
void TradeWindow::onBalanceEdited(MyGUI::EditBox *_sender) void TradeWindow::onBalanceValueChanged(int value)
{ {
try // Entering a "-" sign inverts the buying/selling state
{ mCurrentBalance = (mCurrentBalance >= 0 ? 1 : -1) * value;
unsigned int count = boost::lexical_cast<unsigned int>(_sender->getCaption()); updateLabels();
mCurrentBalance = count * (mCurrentBalance >= 0 ? 1 : -1);
updateLabels(); if (value != std::abs(value))
} mTotalBalance->setValue(std::abs(value));
catch (std::bad_cast&)
{
if (_sender->getCaption().empty())
mTotalBalance->setCaption("0");
else
mTotalBalance->setCaption(boost::lexical_cast<std::string>(std::abs(mCurrentBalance)));
}
} }
void TradeWindow::onIncreaseButtonTriggered() void TradeWindow::onIncreaseButtonTriggered()
@ -463,41 +466,52 @@ namespace MWGui
mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast<std::string>(playerGold)); mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast<std::string>(playerGold));
std::string balanceCaption;
if (mCurrentBalance > 0) if (mCurrentBalance > 0)
{ {
mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalSold}"); mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalSold}");
balanceCaption = boost::lexical_cast<std::string>(mCurrentBalance);
} }
else else
{ {
mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalCost}"); mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalCost}");
balanceCaption = boost::lexical_cast<std::string>(-mCurrentBalance);
} }
if (balanceCaption != mTotalBalance->getCaption().asUTF8()) // Don't reset text cursor if text doesn't need to be changed
mTotalBalance->setCaption(balanceCaption); mTotalBalance->setValue(std::abs(mCurrentBalance));
mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast<std::string>(getMerchantGold())); mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast<std::string>(getMerchantGold()));
} }
void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem) void TradeWindow::updateOffer()
{ {
int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(item, count), boughtItem); TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
mCurrentBalance += diff; int merchantOffer = 0;
mCurrentMerchantOffer += diff;
std::vector<ItemStack> playerBorrowed = playerTradeModel->getItemsBorrowedToUs();
for (std::vector<ItemStack>::const_iterator it = playerBorrowed.begin(); it != playerBorrowed.end(); ++it)
{
merchantOffer -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(it->mBase, it->mCount), true);
}
std::vector<ItemStack> merchantBorrowed = mTradeModel->getItemsBorrowedToUs();
for (std::vector<ItemStack>::const_iterator it = merchantBorrowed.begin(); it != merchantBorrowed.end(); ++it)
{
merchantOffer += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(it->mBase, it->mCount), false);
}
int diff = merchantOffer - mCurrentMerchantOffer;
mCurrentMerchantOffer = merchantOffer;
mCurrentBalance += diff;
updateLabels(); updateLabels();
} }
void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem) void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem)
{ {
int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(item, count), !soldItem); updateOffer();
}
mCurrentBalance -= diff;
mCurrentMerchantOffer -= diff;
updateLabels(); void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem)
{
updateOffer();
} }
void TradeWindow::onReferenceUnavailable() void TradeWindow::onReferenceUnavailable()

@ -3,10 +3,9 @@
#include "container.hpp" #include "container.hpp"
namespace MyGUI namespace Gui
{ {
class Gui; class NumericEditBox;
class Widget;
} }
namespace MWGui namespace MWGui
@ -54,7 +53,7 @@ namespace MWGui
MyGUI::Button* mIncreaseButton; MyGUI::Button* mIncreaseButton;
MyGUI::Button* mDecreaseButton; MyGUI::Button* mDecreaseButton;
MyGUI::TextBox* mTotalBalanceLabel; MyGUI::TextBox* mTotalBalanceLabel;
MyGUI::EditBox* mTotalBalance; Gui::NumericEditBox* mTotalBalance;
MyGUI::Widget* mBottomPane; MyGUI::Widget* mBottomPane;
@ -72,6 +71,8 @@ namespace MWGui
void sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem); ///< only used for adjusting the gold balance void sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem); ///< only used for adjusting the gold balance
void buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem); ///< only used for adjusting the gold balance void buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem); ///< only used for adjusting the gold balance
void updateOffer();
void onItemSelected (int index); void onItemSelected (int index);
void sellItem (MyGUI::Widget* sender, int count); void sellItem (MyGUI::Widget* sender, int count);
@ -82,7 +83,7 @@ namespace MWGui
void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onBalanceEdited(MyGUI::EditBox* _sender); void onBalanceValueChanged(int value);
void onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller); void onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller);
void addRepeatController(MyGUI::Widget* widget); void addRepeatController(MyGUI::Widget* widget);

@ -225,11 +225,10 @@ namespace MWGui
const ESM::Spell *spell = store.get<ESM::Spell>().search(mId); const ESM::Spell *spell = store.get<ESM::Spell>().search(mId);
MYGUI_ASSERT(spell, "spell with id '" << mId << "' not found"); MYGUI_ASSERT(spell, "spell with id '" << mId << "' not found");
MWSpellEffectPtr effect = NULL;
std::vector<ESM::ENAMstruct>::const_iterator end = spell->mEffects.mList.end(); std::vector<ESM::ENAMstruct>::const_iterator end = spell->mEffects.mList.end();
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != end; ++it) for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != end; ++it)
{ {
effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default); MWSpellEffectPtr effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
SpellEffectParams params; SpellEffectParams params;
params.mEffectID = it->mEffectID; params.mEffectID = it->mEffectID;
params.mSkill = it->mSkill; params.mSkill = it->mSkill;
@ -565,22 +564,6 @@ namespace MWGui
} }
} }
void MWScrollBar::setEnableRepeat(bool enable)
{
mEnableRepeat = enable;
}
bool MWScrollBar::getEnableRepeat()
{
return mEnableRepeat;
}
void MWScrollBar::getRepeat(float &trigger, float &step)
{
trigger = mRepeatTriggerTime;
step = mRepeatStepTime;
}
void MWScrollBar::setRepeat(float trigger, float step) void MWScrollBar::setRepeat(float trigger, float step)
{ {
mRepeatTriggerTime = trigger; mRepeatTriggerTime = trigger;

@ -307,9 +307,6 @@ namespace MWGui
MWScrollBar(); MWScrollBar();
virtual ~MWScrollBar(); virtual ~MWScrollBar();
void setEnableRepeat(bool enable);
bool getEnableRepeat();
void getRepeat(float &trigger, float &step);
void setRepeat(float trigger, float step); void setRepeat(float trigger, float step);
protected: protected:

@ -76,6 +76,8 @@ void WindowModal::close()
NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget) NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget)
: mDrag(drag), mWidget(widget), mTransparent(false) : mDrag(drag), mWidget(widget), mTransparent(false)
{ {
if (!mWidget)
throw std::runtime_error("NoDrop needs a non-NULL widget!");
} }
void NoDrop::onFrame(float dt) void NoDrop::onFrame(float dt)

@ -18,7 +18,8 @@
#include <components/fontloader/fontloader.hpp> #include <components/fontloader/fontloader.hpp>
#include <components/widgets/box.hpp> #include <components/widgets/widgets.hpp>
#include <components/widgets/tags.hpp>
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
#include "../mwbase/statemanager.hpp" #include "../mwbase/statemanager.hpp"
@ -71,6 +72,7 @@
#include "backgroundimage.hpp" #include "backgroundimage.hpp"
#include "itemwidget.hpp" #include "itemwidget.hpp"
#include "screenfader.hpp" #include "screenfader.hpp"
#include "debugwindow.hpp"
namespace MWGui namespace MWGui
{ {
@ -119,6 +121,7 @@ namespace MWGui
, mVideoBackground(NULL) , mVideoBackground(NULL)
, mVideoWidget(NULL) , mVideoWidget(NULL)
, mScreenFader(NULL) , mScreenFader(NULL)
, mDebugWindow(NULL)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
, mCharGen(NULL) , mCharGen(NULL)
, mInputBlocker(NULL) , mInputBlocker(NULL)
@ -164,13 +167,6 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWList>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::HBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::VBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::AutoSizedTextBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::AutoSizedEditBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::AutoSizedButton>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::ImageButton>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
@ -178,6 +174,7 @@ namespace MWGui
BookPage::registerMyGUIComponents (); BookPage::registerMyGUIComponents ();
ItemView::registerComponents(); ItemView::registerComponents();
ItemWidget::registerComponents(); ItemWidget::registerComponents();
Gui::registerAllWidgets();
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatEvent>("Controller"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatEvent>("Controller");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
@ -271,6 +268,7 @@ namespace MWGui
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
trackWindow(mCompanionWindow, "companion"); trackWindow(mCompanionWindow, "companion");
mScreenFader = new ScreenFader(); mScreenFader = new ScreenFader();
mDebugWindow = new DebugWindow();
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay"); mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay");
@ -362,6 +360,7 @@ namespace MWGui
delete mRecharge; delete mRecharge;
delete mCompanionWindow; delete mCompanionWindow;
delete mScreenFader; delete mScreenFader;
delete mDebugWindow;
cleanupGarbage(); cleanupGarbage();
@ -864,6 +863,8 @@ namespace MWGui
mCompanionWindow->onFrame(); mCompanionWindow->onFrame();
mScreenFader->update(frameDuration); mScreenFader->update(frameDuration);
mDebugWindow->onFrame(frameDuration);
} }
void WindowManager::changeCell(MWWorld::CellStore* cell) void WindowManager::changeCell(MWWorld::CellStore* cell)
@ -991,50 +992,13 @@ namespace MWGui
std::string tokenToFind = "sCell="; std::string tokenToFind = "sCell=";
size_t tokenLength = tokenToFind.length(); size_t tokenLength = tokenToFind.length();
std::string fontcolour = "fontcolour=";
size_t fontcolourLength = fontcolour.length();
std::string fontcolourhtml = "fontcolourhtml=";
size_t fontcolourhtmlLength = fontcolourhtml.length();
if (tag.compare(0, tokenLength, tokenToFind) == 0) if (tag.compare(0, tokenLength, tokenToFind) == 0)
{ {
_result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength)); _result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength));
} }
else if (tag.compare(0, fontcolourLength, fontcolour) == 0) else if (Gui::replaceTag(tag, _result, mFallbackMap))
{ {
std::string fallbackName = "FontColor_color_" + tag.substr(fontcolourLength); return;
std::map<std::string, std::string>::const_iterator it = mFallbackMap.find(fallbackName);
if (it == mFallbackMap.end())
throw std::runtime_error("Unknown fallback name: " + fallbackName);
std::string str = it->second;
std::string ret[3];
unsigned int j=0;
for(unsigned int i=0;i<str.length();++i){
if(str[i]==',') j++;
else if (str[i] != ' ') ret[j]+=str[i];
}
MyGUI::Colour col (MyGUI::utility::parseInt(ret[0])/255.f,MyGUI::utility::parseInt(ret[1])/255.f,MyGUI::utility::parseInt(ret[2])/255.f);
_result = col.print();
}
else if (tag.compare(0, fontcolourhtmlLength, fontcolourhtml) == 0)
{
std::string fallbackName = "FontColor_color_" + tag.substr(fontcolourhtmlLength);
std::map<std::string, std::string>::const_iterator it = mFallbackMap.find(fallbackName);
if (it == mFallbackMap.end())
throw std::runtime_error("Unknown fallback name: " + fallbackName);
std::string str = it->second;
std::string ret[3];
unsigned int j=0;
for(unsigned int i=0;i<str.length();++i){
if(str[i]==',') j++;
else if (str[i] != ' ') ret[j]+=str[i];
}
std::stringstream html;
html << "#" << std::hex << MyGUI::utility::parseInt(ret[0]) << MyGUI::utility::parseInt(ret[1]) << MyGUI::utility::parseInt(ret[2]);
_result = html.str();
} }
else else
{ {
@ -1390,12 +1354,6 @@ namespace MWGui
return mSubtitlesEnabled; return mSubtitlesEnabled;
} }
void WindowManager::toggleHud ()
{
mHudEnabled = !mHudEnabled;
mHud->setVisible (mHudEnabled);
}
bool WindowManager::toggleGui() bool WindowManager::toggleGui()
{ {
mGuiEnabled = !mGuiEnabled; mGuiEnabled = !mGuiEnabled;
@ -1711,7 +1669,7 @@ namespace MWGui
WindowModal* WindowManager::getCurrentModal() const WindowModal* WindowManager::getCurrentModal() const
{ {
if(mCurrentModals.size() > 0) if(!mCurrentModals.empty())
return mCurrentModals.top(); return mCurrentModals.top();
else else
return NULL; return NULL;
@ -1721,7 +1679,7 @@ namespace MWGui
{ {
// Only remove the top if it matches the current pointer. A lot of things hide their visibility before showing it, // Only remove the top if it matches the current pointer. A lot of things hide their visibility before showing it,
//so just popping the top would cause massive issues. //so just popping the top would cause massive issues.
if(mCurrentModals.size() > 0) if(!mCurrentModals.empty())
if(input == mCurrentModals.top()) if(input == mCurrentModals.top())
mCurrentModals.pop(); mCurrentModals.pop();
} }
@ -1797,4 +1755,9 @@ namespace MWGui
SDL_free(text); SDL_free(text);
} }
void WindowManager::toggleDebugWindow()
{
mDebugWindow->setVisible(!mDebugWindow->isVisible());
}
} }

@ -89,6 +89,7 @@ namespace MWGui
class VideoWidget; class VideoWidget;
class WindowModal; class WindowModal;
class ScreenFader; class ScreenFader;
class DebugWindow;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -222,7 +223,6 @@ namespace MWGui
virtual void showCrosshair(bool show); virtual void showCrosshair(bool show);
virtual bool getSubtitlesEnabled(); virtual bool getSubtitlesEnabled();
virtual void toggleHud();
/// Turn visibility of *all* GUI elements on or off (HUD and all windows, except the console) /// Turn visibility of *all* GUI elements on or off (HUD and all windows, except the console)
virtual bool toggleGui(); virtual bool toggleGui();
@ -334,6 +334,8 @@ namespace MWGui
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor); virtual void setScreenFactor (float factor);
virtual void toggleDebugWindow();
private: private:
bool mConsoleOnlyScripts; bool mConsoleOnlyScripts;
@ -387,6 +389,7 @@ namespace MWGui
MyGUI::ImageBox* mVideoBackground; MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget; VideoWidget* mVideoWidget;
ScreenFader* mScreenFader; ScreenFader* mScreenFader;
DebugWindow* mDebugWindow;
Translation::Storage& mTranslationDataStorage; Translation::Storage& mTranslationDataStorage;
Cursor* mSoftwareCursor; Cursor* mSoftwareCursor;

@ -279,6 +279,9 @@ namespace MWInput
case A_ToggleHUD: case A_ToggleHUD:
MWBase::Environment::get().getWindowManager()->toggleGui(); MWBase::Environment::get().getWindowManager()->toggleGui();
break; break;
case A_ToggleDebug:
MWBase::Environment::get().getWindowManager()->toggleDebugWindow();
break;
case A_QuickSave: case A_QuickSave:
quickSave(); quickSave();
break; break;
@ -902,6 +905,7 @@ namespace MWInput
defaultKeyBindings[A_QuickKey10] = SDL_SCANCODE_0; defaultKeyBindings[A_QuickKey10] = SDL_SCANCODE_0;
defaultKeyBindings[A_Screenshot] = SDL_SCANCODE_F12; defaultKeyBindings[A_Screenshot] = SDL_SCANCODE_F12;
defaultKeyBindings[A_ToggleHUD] = SDL_SCANCODE_F11; defaultKeyBindings[A_ToggleHUD] = SDL_SCANCODE_F11;
defaultKeyBindings[A_ToggleDebug] = SDL_SCANCODE_F10;
defaultKeyBindings[A_AlwaysRun] = SDL_SCANCODE_CAPSLOCK; defaultKeyBindings[A_AlwaysRun] = SDL_SCANCODE_CAPSLOCK;
defaultKeyBindings[A_QuickSave] = SDL_SCANCODE_F5; defaultKeyBindings[A_QuickSave] = SDL_SCANCODE_F5;
defaultKeyBindings[A_QuickLoad] = SDL_SCANCODE_F9; defaultKeyBindings[A_QuickLoad] = SDL_SCANCODE_F9;

@ -259,6 +259,8 @@ namespace MWInput
A_ToggleHUD, A_ToggleHUD,
A_ToggleDebug,
A_Last // Marker for the last item A_Last // Marker for the last item
}; };
}; };

@ -275,7 +275,7 @@ namespace MWMechanics
void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer) void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer)
{ {
CreatureStats& creatureStats = actor1.getClass().getCreatureStats(actor1); CreatureStats& creatureStats = actor1.getClass().getCreatureStats(actor1);
if (actor2.getClass().getCreatureStats(actor2).isDead() if (actor2.getClass().getCreatureStats(actor2).isDead()
|| actor1.getClass().getCreatureStats(actor1).isDead()) || actor1.getClass().getCreatureStats(actor1).isDead())
return; return;
@ -296,7 +296,7 @@ namespace MWMechanics
bool aggressive; bool aggressive;
if (againstPlayer) if (againstPlayer)
{ {
// followers with high fight should not engage in combat with the player (e.g. bm_bear_black_summon) // followers with high fight should not engage in combat with the player (e.g. bm_bear_black_summon)
const std::list<MWWorld::Ptr>& followers = getActorsFollowing(actor2); const std::list<MWWorld::Ptr>& followers = getActorsFollowing(actor2);
@ -323,8 +323,9 @@ namespace MWMechanics
for (std::list<MWWorld::Ptr>::const_iterator it = followers.begin(); it != followers.end(); ++it) for (std::list<MWWorld::Ptr>::const_iterator it = followers.begin(); it != followers.end(); ++it)
{ {
// need to check both ways since player doesn't use AI packages // need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(*it) if ((creatureStats2.getAiSequence().isInCombat(*it)
|| it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(actor2)) || it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(actor2))
&& !creatureStats.getAiSequence().isInCombat(*it))
aggressive = true; aggressive = true;
} }
@ -337,6 +338,9 @@ namespace MWMechanics
if (followTarget.isEmpty()) if (followTarget.isEmpty())
continue; continue;
if (creatureStats.getAiSequence().isInCombat(followTarget))
continue;
// need to check both ways since player doesn't use AI packages // need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(followTarget) if (creatureStats2.getAiSequence().isInCombat(followTarget)
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2)) || followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
@ -466,13 +470,13 @@ namespace MWMechanics
return; return;
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
// restore fatigue // restore fatigue
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat (); const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat (); static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * endurance; float x = fFatigueReturnBase + fFatigueReturnMult * endurance;
@ -1099,7 +1103,7 @@ namespace MWMechanics
void Actors::update (float duration, bool paused) void Actors::update (float duration, bool paused)
{ {
if(!paused) if(!paused)
{ {
static float timerUpdateAITargets = 0; static float timerUpdateAITargets = 0;
// target lists get updated once every 1.0 sec // target lists get updated once every 1.0 sec
@ -1175,14 +1179,26 @@ namespace MWMechanics
iter->second->updateContinuousVfx(); iter->second->updateContinuousVfx();
// Animation/movement update // Animation/movement update
CharacterController* playerCharacter = NULL;
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
ESM::MagicEffect::Paralyze).getMagnitude() > 0) ESM::MagicEffect::Paralyze).getMagnitude() > 0)
iter->second->skipAnim(); iter->second->skipAnim();
// Handle player last, in case a cell transition occurs by casting a teleportation spell
// (would invalidate the iterator)
if (iter->first.getCellRef().getRefId() == "player")
{
playerCharacter = iter->second;
continue;
}
iter->second->update(duration); iter->second->update(duration);
} }
if (playerCharacter)
playerCharacter->update(duration);
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
const MWWorld::Class &cls = iter->first.getClass(); const MWWorld::Class &cls = iter->first.getClass();
@ -1207,26 +1223,27 @@ namespace MWMechanics
// check if we still have any player enemies to switch music // check if we still have any player enemies to switch music
static bool isBattleMusic = false; static bool isBattleMusic = false;
if (isBattleMusic && hostilesCount == 0) if (isBattleMusic && hostilesCount == 0 && !(player.getClass().getCreatureStats(player).isDead() &&
MWBase::Environment::get().getSoundManager()->isMusicPlaying()))
{ {
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore")); MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));
isBattleMusic = false; isBattleMusic = false;
} }
else if (!isBattleMusic && hostilesCount > 0) else if (!isBattleMusic && hostilesCount > 0)
{ {
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Battle")); MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Battle"));
isBattleMusic = true; isBattleMusic = true;
} }
static float sneakTimer = 0.f; // times update of sneak icon static float sneakTimer = 0.f; // times update of sneak icon
static float sneakSkillTimer = 0.f; // times sneak skill progress from "avoid notice"
// if player is in sneak state see if anyone detects him // if player is in sneak state see if anyone detects him
if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak))
{ {
static float sneakSkillTimer = 0.f; // times sneak skill progress from "avoid notice"
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
const int radius = esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->getInt(); const int radius = esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->getInt();
bool detected = false;
static float fSneakUseDelay = esmStore.get<ESM::GameSetting>().find("fSneakUseDelay")->getFloat(); static float fSneakUseDelay = esmStore.get<ESM::GameSetting>().find("fSneakUseDelay")->getFloat();
@ -1238,6 +1255,8 @@ namespace MWMechanics
// Set when an NPC is within line of sight and distance, but is still unaware. Used for skill progress. // Set when an NPC is within line of sight and distance, but is still unaware. Used for skill progress.
bool avoidedNotice = false; bool avoidedNotice = false;
bool detected = false;
for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
if (iter->first == player) // not the player if (iter->first == player) // not the player
@ -1405,7 +1424,7 @@ namespace MWMechanics
std::list<MWWorld::Ptr> Actors::getActorsFollowing(const MWWorld::Ptr& actor) std::list<MWWorld::Ptr> Actors::getActorsFollowing(const MWWorld::Ptr& actor)
{ {
std::list<MWWorld::Ptr> list; std::list<MWWorld::Ptr> list;
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{ {
const MWWorld::Class &cls = iter->first.getClass(); const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first);
@ -1437,7 +1456,7 @@ namespace MWMechanics
getObjectsInRange(position, getObjectsInRange(position,
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(), MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(),
neighbors); //only care about those within the alarm disance neighbors); //only care about those within the alarm disance
for(std::vector<MWWorld::Ptr>::iterator iter(neighbors.begin());iter != neighbors.end();iter++) for(std::vector<MWWorld::Ptr>::iterator iter(neighbors.begin());iter != neighbors.end();++iter)
{ {
const MWWorld::Class &cls = iter->getClass(); const MWWorld::Class &cls = iter->getClass();
CreatureStats &stats = cls.getCreatureStats(*iter); CreatureStats &stats = cls.getCreatureStats(*iter);

@ -35,8 +35,6 @@ namespace MWMechanics
private: private:
std::string mObjectId; std::string mObjectId;
int mCellX;
int mCellY;
}; };
} }
#endif // GAME_MWMECHANICS_AIACTIVATE_H #endif // GAME_MWMECHANICS_AIACTIVATE_H

@ -64,7 +64,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration
// Make all nearby actors also avoid the door // Make all nearby actors also avoid the door
std::vector<MWWorld::Ptr> actors; std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors); MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors);
for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); it++) { for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); ++it) {
if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player
MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence(); MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence();
if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once

@ -301,18 +301,20 @@ namespace MWMechanics
if (!target.isEmpty() && target.getClass().getCreatureStats(target).getAttribute(effect.mAttribute).getModified() <= 0) if (!target.isEmpty() && target.getClass().getCreatureStats(target).getAttribute(effect.mAttribute).getModified() <= 0)
return 0.f; return 0.f;
{ {
const float attributePriorities[ESM::Attribute::Length] = {
1.f, // Strength
0.5, // Intelligence
0.6, // Willpower
0.7, // Agility
0.5, // Speed
0.8, // Endurance
0.7, // Personality
0.3 // Luck
};
if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length) if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length)
{
const float attributePriorities[ESM::Attribute::Length] = {
1.f, // Strength
0.5, // Intelligence
0.6, // Willpower
0.7, // Agility
0.5, // Speed
0.8, // Endurance
0.7, // Personality
0.3 // Luck
};
rating *= attributePriorities[effect.mAttribute]; rating *= attributePriorities[effect.mAttribute];
}
} }
break; break;

@ -54,6 +54,7 @@ namespace MWMechanics
, mCellY(std::numeric_limits<int>::max()) , mCellY(std::numeric_limits<int>::max())
, mCellId(escort->mCellId) , mCellId(escort->mCellId)
, mRemainingDuration(escort->mRemainingDuration) , mRemainingDuration(escort->mRemainingDuration)
, mMaxDist(450)
{ {
} }
@ -91,7 +92,11 @@ namespace MWMechanics
if(distanceBetweenResult <= mMaxDist * mMaxDist) if(distanceBetweenResult <= mMaxDist * mMaxDist)
{ {
if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete ESM::Pathgrid::Point point(mX,mY,mZ);
point.mAutogenerated = 0;
point.mConnectionNum = 0;
point.mUnknown = 0;
if(pathTo(actor,point,duration)) //Returns true on path complete
return true; return true;
mMaxDist = 450; mMaxDist = 450;
} }

@ -50,11 +50,6 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration)
) )
return true; //Target doesn't exist return true; //Target doesn't exist
// Only the player can be actively followed. AiFollow packages with targets other than the player
// are only used for defining combat alliances, since NPCs will defend whoever they are following or being followed by.
if (target != MWBase::Environment::get().getWorld()->getPlayerPtr())
return false;
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor ESM::Position pos = actor.getRefData().getPosition(); //position of the actor

@ -69,7 +69,6 @@ namespace MWMechanics
PathFinder mPathFinder; PathFinder mPathFinder;
ObstacleCheck mObstacleCheck; ObstacleCheck mObstacleCheck;
float mDoorCheckDuration;
float mTimer; float mTimer;
float mStuckTimer; float mStuckTimer;

@ -41,8 +41,6 @@ namespace MWMechanics
private: private:
int mTargetActorId; // The actor to pursue int mTargetActorId; // The actor to pursue
int mCellX;
int mCellY;
}; };
} }
#endif #endif

@ -31,9 +31,11 @@ void AiSequence::copy (const AiSequence& sequence)
AiSequence::AiSequence() : mDone (false), mLastAiPackage(-1) {} AiSequence::AiSequence() : mDone (false), mLastAiPackage(-1) {}
AiSequence::AiSequence (const AiSequence& sequence) : mDone (false) AiSequence::AiSequence (const AiSequence& sequence)
{ {
copy (sequence); copy (sequence);
mDone = sequence.mDone;
mLastAiPackage = sequence.mLastAiPackage;
} }
AiSequence& AiSequence::operator= (const AiSequence& sequence) AiSequence& AiSequence::operator= (const AiSequence& sequence)
@ -43,6 +45,7 @@ AiSequence& AiSequence::operator= (const AiSequence& sequence)
clear(); clear();
copy (sequence); copy (sequence);
mDone = sequence.mDone; mDone = sequence.mDone;
mLastAiPackage = sequence.mLastAiPackage;
} }
return *this; return *this;
@ -120,33 +123,6 @@ bool AiSequence::isInCombat(const MWWorld::Ptr &actor) const
return false; return false;
} }
bool AiSequence::canAddTarget(const ESM::Position& actorPos, float distToTarget) const
{
bool firstCombatFound = false;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
for(std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
{
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
{
firstCombatFound = true;
const AiCombat *combat = static_cast<const AiCombat *>(*it);
if (combat->getTarget() != player ) return false; // only 1 non-player target allowed
else
{
// add new target only if current target (player) is farther
const ESM::Position &targetPos = combat->getTarget().getRefData().getPosition();
float distToCurrTarget = (Ogre::Vector3(targetPos.pos) - Ogre::Vector3(actorPos.pos)).length();
return (distToCurrTarget > distToTarget);
}
}
else if (firstCombatFound) break; // assumes combat packages go one-by-one in packages list
}
return true;
}
void AiSequence::stopCombat() void AiSequence::stopCombat()
{ {
while (getTypeId() == AiPackage::TypeIdCombat) while (getTypeId() == AiPackage::TypeIdCombat)
@ -295,11 +271,6 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor)
mPackages.push_front (package.clone()); mPackages.push_front (package.clone());
} }
void AiSequence::queue (const AiPackage& package)
{
mPackages.push_back (package.clone());
}
AiPackage* MWMechanics::AiSequence::getActivePackage() AiPackage* MWMechanics::AiSequence::getActivePackage()
{ {
if(mPackages.empty()) if(mPackages.empty())

@ -98,10 +98,6 @@ namespace MWMechanics
@param actor The actor that owns this AiSequence **/ @param actor The actor that owns this AiSequence **/
void stack (const AiPackage& package, const MWWorld::Ptr& actor); void stack (const AiPackage& package, const MWWorld::Ptr& actor);
/// Add \a package to the end of the sequence
/** Executed after all other packages have been completed **/
void queue (const AiPackage& package);
/// Return the current active package. /// Return the current active package.
/** If there is no active package, it will throw an exception **/ /** If there is no active package, it will throw an exception **/
AiPackage* getActivePackage(); AiPackage* getActivePackage();

@ -686,16 +686,15 @@ namespace MWMechanics
} }
AiWander::AiWander (const ESM::AiSequence::AiWander* wander) AiWander::AiWander (const ESM::AiSequence::AiWander* wander)
: mDistance(wander->mData.mDistance)
, mDuration(wander->mData.mDuration)
, mStartTime(MWWorld::TimeStamp(wander->mStartTime))
, mTimeOfDay(wander->mData.mTimeOfDay)
, mRepeat(wander->mData.mShouldRepeat)
{ {
mDistance = wander->mData.mDistance;
mDuration = wander->mData.mDuration;
mStartTime = MWWorld::TimeStamp(wander->mStartTime);
mTimeOfDay = wander->mData.mTimeOfDay;
for (int i=0; i<8; ++i) for (int i=0; i<8; ++i)
mIdle.push_back(wander->mData.mIdle[i]); mIdle.push_back(wander->mData.mIdle[i]);
mRepeat = wander->mData.mShouldRepeat;
init(); init();
} }
} }

@ -27,6 +27,11 @@
#include "creaturestats.hpp" #include "creaturestats.hpp"
#include "npcstats.hpp" #include "npcstats.hpp"
MWMechanics::Alchemy::Alchemy()
: mValue(0)
{
}
std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const
{ {
std::map<EffectKey, int> effects; std::map<EffectKey, int> effects;

@ -22,6 +22,8 @@ namespace MWMechanics
{ {
public: public:
Alchemy();
typedef std::vector<MWWorld::Ptr> TToolsContainer; typedef std::vector<MWWorld::Ptr> TToolsContainer;
typedef TToolsContainer::const_iterator TToolsIterator; typedef TToolsContainer::const_iterator TToolsIterator;

@ -220,7 +220,7 @@ namespace MWMechanics
if (spell->mData.mFlags & ESM::Spell::F_Always) if (spell->mData.mFlags & ESM::Spell::F_Always)
return 100.f; return 100.f;
float skillTerm; float skillTerm = 0;
if (effectiveSchool != -1) if (effectiveSchool != -1)
skillTerm = 2.f * actorSkills[mapSchoolToSkill(effectiveSchool)]; skillTerm = 2.f * actorSkills[mapSchoolToSkill(effectiveSchool)];
else else

@ -1611,7 +1611,7 @@ void CharacterController::update(float duration)
if(mMovementAnimationControlled && mPtr.getClass().isActor()) if(mMovementAnimationControlled && mPtr.getClass().isActor())
world->queueMovement(mPtr, moved); world->queueMovement(mPtr, moved);
} }
else if (mAnimation) else
mAnimation->updateEffects(duration); mAnimation->updateEffects(duration);
mSkipAnim = false; mSkipAnim = false;
@ -1703,6 +1703,10 @@ bool CharacterController::kill()
mIdleState = CharState_None; mIdleState = CharState_None;
mCurrentIdle.clear(); mCurrentIdle.clear();
// Play Death Music if it was the player dying
if(mPtr.getRefData().getHandle()=="player")
MWBase::Environment::get().getSoundManager()->streamMusic("Special/MW_Death.mp3");
return true; return true;
} }

@ -193,13 +193,11 @@ namespace MWMechanics
return; return;
} }
float damage = 0.0f;
float fDamageStrengthBase = gmst.find("fDamageStrengthBase")->getFloat(); float fDamageStrengthBase = gmst.find("fDamageStrengthBase")->getFloat();
float fDamageStrengthMult = gmst.find("fDamageStrengthMult")->getFloat(); float fDamageStrengthMult = gmst.find("fDamageStrengthMult")->getFloat();
const unsigned char* attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop; const unsigned char* attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage float damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage
if (weapon != projectile) if (weapon != projectile)
{ {
// Arrow/bolt damage // Arrow/bolt damage

@ -120,11 +120,6 @@ namespace MWMechanics
return mSpells; return mSpells;
} }
void CreatureStats::setSpells(const Spells &spells)
{
mSpells = spells;
}
ActiveSpells &CreatureStats::getActiveSpells() ActiveSpells &CreatureStats::getActiveSpells()
{ {
return mActiveSpells; return mActiveSpells;
@ -200,11 +195,6 @@ namespace MWMechanics
mLevel = level; mLevel = level;
} }
void CreatureStats::setActiveSpells(const ActiveSpells &active)
{
mActiveSpells = active;
}
void CreatureStats::modifyMagicEffects(const MagicEffects &effects) void CreatureStats::modifyMagicEffects(const MagicEffects &effects)
{ {
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier() if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()
@ -536,7 +526,6 @@ namespace MWMechanics
mLastRestock = MWWorld::TimeStamp(state.mTradeTime); mLastRestock = MWWorld::TimeStamp(state.mTradeTime);
mGoldPool = state.mGoldPool; mGoldPool = state.mGoldPool;
mFallHeight = state.mFallHeight;
mDead = state.mDead; mDead = state.mDead;
mDied = state.mDied; mDied = state.mDied;

@ -40,7 +40,6 @@ namespace MWMechanics
bool mTalkedTo; bool mTalkedTo;
bool mAlarmed; bool mAlarmed;
bool mAttacked; bool mAttacked;
bool mHostile;
bool mAttackingOrSpell; bool mAttackingOrSpell;
bool mKnockdown; bool mKnockdown;
bool mKnockdownOneFrame; bool mKnockdownOneFrame;
@ -138,10 +137,6 @@ namespace MWMechanics
void setDynamic (int index, const DynamicStat<float> &value); void setDynamic (int index, const DynamicStat<float> &value);
void setSpells(const Spells &spells);
void setActiveSpells(const ActiveSpells &active);
/// Set Modifier for each magic effect according to \a effects. Does not touch Base values. /// Set Modifier for each magic effect according to \a effects. Does not touch Base values.
void modifyMagicEffects(const MagicEffects &effects); void modifyMagicEffects(const MagicEffects &effects);

@ -166,16 +166,15 @@ namespace MWMechanics
float enchantmentCost = 0; float enchantmentCost = 0;
int effectsLeftCnt = mEffects.size(); int effectsLeftCnt = mEffects.size();
float baseCost, magnitudeCost, areaCost;
int magMin, magMax, area;
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{ {
baseCost = (store.get<ESM::MagicEffect>().find(it->mEffectID))->mData.mBaseCost; float baseCost = (store.get<ESM::MagicEffect>().find(it->mEffectID))->mData.mBaseCost;
// To reflect vanilla behavior // To reflect vanilla behavior
magMin = (it->mMagnMin == 0) ? 1 : it->mMagnMin; int magMin = (it->mMagnMin == 0) ? 1 : it->mMagnMin;
magMax = (it->mMagnMax == 0) ? 1 : it->mMagnMax; int magMax = (it->mMagnMax == 0) ? 1 : it->mMagnMax;
area = (it->mArea == 0) ? 1 : it->mArea; int area = (it->mArea == 0) ? 1 : it->mArea;
float magnitudeCost = 0;
if (mCastStyle == ESM::Enchantment::ConstantEffect) if (mCastStyle == ESM::Enchantment::ConstantEffect)
{ {
magnitudeCost = (magMin + magMax) * baseCost * 2.5; magnitudeCost = (magMin + magMax) * baseCost * 2.5;
@ -187,7 +186,7 @@ namespace MWMechanics
magnitudeCost *= 1.5; magnitudeCost *= 1.5;
} }
areaCost = area * 0.025 * baseCost; float areaCost = area * 0.025 * baseCost;
if (it->mRange == ESM::RT_Target) if (it->mRange == ESM::RT_Target)
areaCost *= 1.5; areaCost *= 1.5;

@ -566,11 +566,14 @@ namespace MWMechanics
MWWorld::LiveCellRef<ESM::NPC>* player = playerPtr.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC>* player = playerPtr.get<ESM::NPC>();
const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr); const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr);
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fDispRaceMod = gmst.find("fDispRaceMod")->getFloat();
if (Misc::StringUtils::ciEqual(npc->mBase->mRace, player->mBase->mRace)) if (Misc::StringUtils::ciEqual(npc->mBase->mRace, player->mBase->mRace))
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispRaceMod")->getFloat(); x += fDispRaceMod;
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityMult")->getFloat() static const float fDispPersonalityMult = gmst.find("fDispPersonalityMult")->getFloat();
* (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityBase")->getFloat()); static const float fDispPersonalityBase = gmst.find("fDispPersonalityBase")->getFloat();
x += fDispPersonalityMult * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - fDispPersonalityBase);
float reaction = 0; float reaction = 0;
int rank = 0; int rank = 0;
@ -606,16 +609,23 @@ namespace MWMechanics
reaction = 0; reaction = 0;
rank = 0; rank = 0;
} }
x += (MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankMult")->getFloat() * rank
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankBase")->getFloat())
* MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionMod")->getFloat() * reaction;
x -= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispCrimeMod")->getFloat() * playerStats.getBounty(); static const float fDispFactionRankMult = gmst.find("fDispFactionRankMult")->getFloat();
static const float fDispFactionRankBase = gmst.find("fDispFactionRankBase")->getFloat();
static const float fDispFactionMod = gmst.find("fDispFactionMod")->getFloat();
x += (fDispFactionRankMult * rank
+ fDispFactionRankBase)
* fDispFactionMod * reaction;
static const float fDispCrimeMod = gmst.find("fDispCrimeMod")->getFloat();
static const float fDispDiseaseMod = gmst.find("fDispDiseaseMod")->getFloat();
x -= fDispCrimeMod * playerStats.getBounty();
if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease()) if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease())
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispDiseaseMod")->getFloat(); x += fDispDiseaseMod;
static const float fDispWeaponDrawn = gmst.find("fDispWeaponDrawn")->getFloat();
if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon) if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon)
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat(); x += fDispWeaponDrawn;
x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).getMagnitude(); x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).getMagnitude();
@ -1111,10 +1121,10 @@ namespace MWMechanics
} }
} }
void MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker) bool MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker)
{ {
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
return; return false;
std::list<MWWorld::Ptr> followers = getActorsFollowing(attacker); std::list<MWWorld::Ptr> followers = getActorsFollowing(attacker);
if (std::find(followers.begin(), followers.end(), ptr) != followers.end()) if (std::find(followers.begin(), followers.end(), ptr) != followers.end())
@ -1124,13 +1134,25 @@ namespace MWMechanics
if (ptr.getClass().getCreatureStats(ptr).getFriendlyHits() < 4) if (ptr.getClass().getCreatureStats(ptr).getFriendlyHits() < 4)
{ {
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit"); MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
return; return false;
}
}
// Attacking an NPC that is already in combat with any other NPC is not a crime
AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence();
bool isFightingNpc = false;
for (std::list<AiPackage*>::const_iterator it = seq.begin(); it != seq.end(); ++it)
{
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
{
MWWorld::Ptr target = static_cast<AiCombat*>(*it)->getTarget();
if (!target.isEmpty() && target.getClass().isNpc())
isFightingNpc = true;
} }
} }
// Attacking peaceful NPCs is a crime
if (ptr.getClass().isNpc() && !attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker) if (ptr.getClass().isNpc() && !attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)
&& !isAggressive(ptr, attacker)) && !isAggressive(ptr, attacker) && !isFightingNpc)
commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr) if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr)
@ -1141,6 +1163,8 @@ namespace MWMechanics
// Note: accidental or collateral damage attacks are ignored. // Note: accidental or collateral damage attacks are ignored.
startCombat(ptr, attacker); startCombat(ptr, attacker);
} }
return true;
} }
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer) bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)

@ -120,7 +120,8 @@ namespace MWMechanics
OffenseType type, int arg=0); OffenseType type, int arg=0);
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0); OffenseType type, int arg=0);
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker); /// @return false if the attack was considered a "friendly hit" and forgiven
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// Utility to check if taking this item is illegal and calling commitCrime if so /// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count); virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so

@ -107,7 +107,7 @@ bool MWMechanics::NpcStats::isSameFaction (const NpcStats& npcStats) const
} }
float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& class_, int usageType, float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& class_, int usageType,
int level) const int level, float extraFactor) const
{ {
if (level<0) if (level<0)
level = static_cast<int> (getSkill (skillIndex).getBase()); level = static_cast<int> (getSkill (skillIndex).getBase());
@ -131,6 +131,8 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
return 0; return 0;
} }
skillFactor *= extraFactor;
const MWWorld::Store<ESM::GameSetting> &gmst = const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
@ -167,7 +169,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
return 1.0 / ((level+1) * (1.0/skillFactor) * typeFactor * specialisationFactor); return 1.0 / ((level+1) * (1.0/skillFactor) * typeFactor * specialisationFactor);
} }
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType) void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor)
{ {
// Don't increase skills as a werewolf // Don't increase skills as a werewolf
if(mIsWerewolf) if(mIsWerewolf)
@ -175,7 +177,7 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
MWMechanics::SkillValue& value = getSkill (skillIndex); MWMechanics::SkillValue& value = getSkill (skillIndex);
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType)); value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType, -1, extraFactor));
if (value.getProgress()>=1) if (value.getProgress()>=1)
{ {

@ -81,12 +81,12 @@ namespace MWMechanics
///< Do *this and \a npcStats share a faction? ///< Do *this and \a npcStats share a faction?
float getSkillGain (int skillIndex, const ESM::Class& class_, int usageType = -1, float getSkillGain (int skillIndex, const ESM::Class& class_, int usageType = -1,
int level = -1) const; int level = -1, float extraFactor=1.f) const;
///< \param usageType: Usage specific factor, specified in the respective skill record; ///< \param usageType: Usage specific factor, specified in the respective skill record;
/// -1: use a factor of 1.0 instead. /// -1: use a factor of 1.0 instead.
/// \param level Level to base calculation on; -1: use current level. /// \param level Level to base calculation on; -1: use current level.
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1); void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f);
///< Increase skill by usage. ///< Increase skill by usage.
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress); void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress);

@ -283,13 +283,6 @@ namespace MWMechanics
return Ogre::Radian(Ogre::Math::ACos(directionY / directionResult) * sgn(Ogre::Math::ASin(directionX / directionResult))).valueDegrees(); return Ogre::Radian(Ogre::Math::ACos(directionY / directionResult) * sgn(Ogre::Math::ASin(directionX / directionResult))).valueDegrees();
} }
// Used by AiCombat, use Euclidean distance
float PathFinder::getDistToNext(float x, float y, float z)
{
ESM::Pathgrid::Point nextPoint = *mPath.begin();
return distance(nextPoint, x, y, z);
}
bool PathFinder::checkWaypoint(float x, float y, float z) bool PathFinder::checkWaypoint(float x, float y, float z)
{ {
if(mPath.empty()) if(mPath.empty())

@ -47,8 +47,6 @@ namespace MWMechanics
float getZAngleToNext(float x, float y) const; float getZAngleToNext(float x, float y) const;
float getDistToNext(float x, float y, float z);
bool isPathConstructed() const bool isPathConstructed() const
{ {
return mIsPathConstructed; return mIsPathConstructed;

@ -521,7 +521,7 @@ float Animation::getVelocity(const std::string &groupname) const
{ {
/* Look in reverse; last-inserted source has priority. */ /* Look in reverse; last-inserted source has priority. */
AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin()); AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin());
for(;animsrc != mAnimSources.rend();animsrc++) for(;animsrc != mAnimSources.rend();++animsrc)
{ {
const NifOgre::TextKeyMap &keys = (*animsrc)->mTextKeys; const NifOgre::TextKeyMap &keys = (*animsrc)->mTextKeys;
if(findGroupStart(keys, groupname) != keys.end()) if(findGroupStart(keys, groupname) != keys.end())
@ -831,8 +831,7 @@ void Animation::handleTextKey(AnimState &state, const std::string &groupname, co
void Animation::changeGroups(const std::string &groupname, int groups) void Animation::changeGroups(const std::string &groupname, int groups)
{ {
AnimStateMap::iterator stateiter = mStates.begin(); AnimStateMap::iterator stateiter = mStates.find(groupname);
stateiter = mStates.find(groupname);
if(stateiter != mStates.end()) if(stateiter != mStates.end())
{ {
if(stateiter->second.mGroups != groups) if(stateiter->second.mGroups != groups)

@ -26,7 +26,6 @@ namespace MWRender
mNearest(30.f), mNearest(30.f),
mFurthest(800.f), mFurthest(800.f),
mIsNearest(false), mIsNearest(false),
mIsFurthest(false),
mHeight(128.f), mHeight(128.f),
mCameraDistance(300.f), mCameraDistance(300.f),
mDistanceAdjusted(false), mDistanceAdjusted(false),
@ -292,7 +291,6 @@ namespace MWRender
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
return; return;
mIsFurthest = false;
mIsNearest = false; mIsNearest = false;
Ogre::Vector3 v(0.f, 0.f, dist); Ogre::Vector3 v(0.f, 0.f, dist);
@ -301,7 +299,6 @@ namespace MWRender
} }
if (v.z >= mFurthest) { if (v.z >= mFurthest) {
v.z = mFurthest; v.z = mFurthest;
mIsFurthest = true;
} else if (!override && v.z < 10.f) { } else if (!override && v.z < 10.f) {
v.z = 10.f; v.z = 10.f;
} else if (override && v.z <= mNearest) { } else if (override && v.z <= mNearest) {
@ -389,9 +386,4 @@ namespace MWRender
{ {
return mIsNearest; return mIsNearest;
} }
bool Camera::isFurthest()
{
return mIsFurthest;
}
} }

@ -36,7 +36,6 @@ namespace MWRender
float mNearest; float mNearest;
float mFurthest; float mFurthest;
bool mIsNearest; bool mIsNearest;
bool mIsFurthest;
struct { struct {
bool enabled, allowed; bool enabled, allowed;
@ -118,8 +117,6 @@ namespace MWRender
bool isVanityOrPreviewModeEnabled(); bool isVanityOrPreviewModeEnabled();
bool isNearest(); bool isNearest();
bool isFurthest();
}; };
} }

@ -281,9 +281,9 @@ namespace MWRender
RaceSelectionPreview::RaceSelectionPreview() RaceSelectionPreview::RaceSelectionPreview()
: CharacterPreview(MWBase::Environment::get().getWorld()->getPlayerPtr(), : CharacterPreview(MWBase::Environment::get().getWorld()->getPlayerPtr(),
512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 6, -35), Ogre::Vector3(0,125,0)) 512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 6, -35), Ogre::Vector3(0,125,0))
, mBase (*mCharacter.get<ESM::NPC>()->mBase)
, mRef(&mBase) , mRef(&mBase)
{ {
mBase = *mCharacter.get<ESM::NPC>()->mBase;
mCharacter = MWWorld::Ptr(&mRef, NULL); mCharacter = MWWorld::Ptr(&mRef, NULL);
} }

@ -150,7 +150,7 @@ void CreatureWeaponAnimation::updatePart(NifOgre::ObjectScenePtr& scene, int slo
} }
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(scene->mControllers.begin()); std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(scene->mControllers.begin());
for(;ctrl != scene->mControllers.end();ctrl++) for(;ctrl != scene->mControllers.end();++ctrl)
{ {
if(ctrl->getSource().isNull()) if(ctrl->getSource().isNull())
{ {

@ -29,6 +29,7 @@ namespace MWRender
, mWidth(0) , mWidth(0)
, mHeight(0) , mHeight(0)
{ {
mCellSize = Settings::Manager::getInt("global map cell size", "Map");
} }
GlobalMap::~GlobalMap() GlobalMap::~GlobalMap()
@ -57,9 +58,8 @@ namespace MWRender
mMaxY = it->getGridY(); mMaxY = it->getGridY();
} }
int cellSize = 24; mWidth = mCellSize*(mMaxX-mMinX+1);
mWidth = cellSize*(mMaxX-mMinX+1); mHeight = mCellSize*(mMaxY-mMinY+1);
mHeight = cellSize*(mMaxY-mMinY+1);
loadingListener->loadingOn(); loadingListener->loadingOn();
loadingListener->setLabel("Creating map"); loadingListener->setLabel("Creating map");
@ -90,29 +90,29 @@ namespace MWRender
land->loadData(mask); land->loadData(mask);
} }
for (int cellY=0; cellY<cellSize; ++cellY) for (int cellY=0; cellY<mCellSize; ++cellY)
{ {
for (int cellX=0; cellX<cellSize; ++cellX) for (int cellX=0; cellX<mCellSize; ++cellX)
{ {
int vertexX = float(cellX)/float(cellSize) * ESM::Land::LAND_SIZE; int vertexX = float(cellX)/float(mCellSize) * ESM::Land::LAND_SIZE;
int vertexY = float(cellY)/float(cellSize) * ESM::Land::LAND_SIZE; int vertexY = float(cellY)/float(mCellSize) * ESM::Land::LAND_SIZE;
int texelX = (x-mMinX) * cellSize + cellX; int texelX = (x-mMinX) * mCellSize + cellX;
int texelY = (mHeight-1) - ((y-mMinY) * cellSize + cellY); int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY);
unsigned char r,g,b; unsigned char r,g,b;
if (land) if (land)
{ {
const float landHeight = land->mLandData->mHeights[vertexY * ESM::Land::LAND_SIZE + vertexX]; const float landHeight = land->mLandData->mHeights[vertexY * ESM::Land::LAND_SIZE + vertexX];
const float mountainHeight = 15000.f;
const float hillHeight = 2500.f;
if (landHeight >= 0) if (landHeight >= 0)
{ {
const float hillHeight = 2500.f;
if (landHeight >= hillHeight) if (landHeight >= hillHeight)
{ {
const float mountainHeight = 15000.f;
float factor = std::min(1.f, float(landHeight-hillHeight)/mountainHeight); float factor = std::min(1.f, float(landHeight-hillHeight)/mountainHeight);
r = (hillColour.r * (1-factor) + mountainColour.r * factor) * 255; r = (hillColour.r * (1-factor) + mountainColour.r * factor) * 255;
g = (hillColour.g * (1-factor) + mountainColour.g * factor) * 255; g = (hillColour.g * (1-factor) + mountainColour.g * factor) * 255;
@ -197,11 +197,9 @@ namespace MWRender
void GlobalMap::exploreCell(int cellX, int cellY) void GlobalMap::exploreCell(int cellX, int cellY)
{ {
const int size = 24; float originX = (cellX - mMinX) * mCellSize;
float originX = (cellX - mMinX) * size;
// NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is
float originY = mHeight - (cellY+1 - mMinY) * size; float originY = mHeight - (cellY+1 - mMinY) * mCellSize;
if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY)
return; return;
@ -213,17 +211,17 @@ namespace MWRender
{ {
mOverlayTexture->load(); mOverlayTexture->load();
mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,512,512), mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,512,512),
Ogre::Image::Box(originX,originY,originX+size,originY+size)); Ogre::Image::Box(originX,originY,originX+mCellSize,originY+mCellSize));
Ogre::Image backup; Ogre::Image backup;
std::vector<Ogre::uchar> data; std::vector<Ogre::uchar> data;
data.resize(size*size*4, 0); data.resize(mCellSize*mCellSize*4, 0);
backup.loadDynamicImage(&data[0], size, size, Ogre::PF_A8B8G8R8); backup.loadDynamicImage(&data[0], mCellSize, mCellSize, Ogre::PF_A8B8G8R8);
localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,512,512), backup.getPixelBox()); localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,512,512), backup.getPixelBox());
for (int x=0; x<size; ++x) for (int x=0; x<mCellSize; ++x)
for (int y=0; y<size; ++y) for (int y=0; y<mCellSize; ++y)
{ {
assert (originX+x < mOverlayImage.getWidth()); assert (originX+x < mOverlayImage.getWidth());
assert (originY+y < mOverlayImage.getHeight()); assert (originY+y < mOverlayImage.getHeight());
@ -292,7 +290,7 @@ namespace MWRender
// If cell bounds of the currently loaded content and the loaded savegame do not match, // If cell bounds of the currently loaded content and the loaded savegame do not match,
// we need to resize source/dest boxes to accommodate // we need to resize source/dest boxes to accommodate
// This means nonexisting cells will be dropped silently // This means nonexisting cells will be dropped silently
int cellImageSizeDst = 24; int cellImageSizeDst = mCellSize;
// Completely off-screen? -> no need to blit anything // Completely off-screen? -> no need to blit anything
if (bounds.mMaxX < mMinX if (bounds.mMaxX < mMinX
@ -326,7 +324,8 @@ namespace MWRender
mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox); mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox);
if (srcBox.left == destBox.left && srcBox.right == destBox.right if (srcBox.left == destBox.left && srcBox.right == destBox.right
&& srcBox.top == destBox.top && srcBox.bottom == destBox.bottom) && srcBox.top == destBox.top && srcBox.bottom == destBox.bottom
&& int(image.getWidth()) == mWidth && int(image.getHeight()) == mHeight)
mOverlayImage = image; mOverlayImage = image;
else else
mOverlayTexture->convertToImage(mOverlayImage); mOverlayTexture->convertToImage(mOverlayImage);

@ -26,8 +26,10 @@ namespace MWRender
void render(Loading::Listener* loadingListener); void render(Loading::Listener* loadingListener);
int getWidth() { return mWidth; } int getWidth() const { return mWidth; }
int getHeight() { return mHeight; } int getHeight() const { return mHeight; }
int getCellSize() const { return mCellSize; }
void worldPosToImageSpace(float x, float z, float& imageX, float& imageY); void worldPosToImageSpace(float x, float z, float& imageX, float& imageY);
@ -46,6 +48,8 @@ namespace MWRender
private: private:
std::string mCacheDir; std::string mCacheDir;
int mCellSize;
std::vector< std::pair<int,int> > mExploredCells; std::vector< std::pair<int,int> > mExploredCells;
Ogre::TexturePtr mOverlayTexture; Ogre::TexturePtr mOverlayTexture;

@ -410,15 +410,18 @@ void NpcAnimation::updateParts()
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination // Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping; static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping;
static const int Flag_Female = 1<<0;
static const int Flag_FirstPerson = 1<<1;
bool isWerewolf = (mNpcType == Type_Werewolf); bool isWerewolf = (mNpcType == Type_Werewolf);
int flags = (isWerewolf ? -1 : 0); int flags = (isWerewolf ? -1 : 0);
if(!mNpc->isMale()) if(!mNpc->isMale())
{
static const int Flag_Female = 1<<0;
flags |= Flag_Female; flags |= Flag_Female;
}
if(mViewMode == VM_FirstPerson) if(mViewMode == VM_FirstPerson)
{
static const int Flag_FirstPerson = 1<<1;
flags |= Flag_FirstPerson; flags |= Flag_FirstPerson;
}
std::string race = (isWerewolf ? "werewolf" : Misc::StringUtils::lowerCase(mNpc->mRace)); std::string race = (isWerewolf ? "werewolf" : Misc::StringUtils::lowerCase(mNpc->mRace));
std::pair<std::string, int> thisCombination = std::make_pair(race, flags); std::pair<std::string, int> thisCombination = std::make_pair(race, flags);
@ -604,7 +607,7 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
if (mObjectParts[i].isNull()) if (mObjectParts[i].isNull())
continue; continue;
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[i]->mControllers.begin()); std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[i]->mControllers.begin());
for(;ctrl != mObjectParts[i]->mControllers.end();ctrl++) for(;ctrl != mObjectParts[i]->mControllers.end();++ctrl)
ctrl->update(); ctrl->update();
Ogre::Entity *ent = mObjectParts[i]->mSkelBase; Ogre::Entity *ent = mObjectParts[i]->mSkelBase;
@ -678,7 +681,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
} }
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[type]->mControllers.begin()); std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[type]->mControllers.begin());
for(;ctrl != mObjectParts[type]->mControllers.end();ctrl++) for(;ctrl != mObjectParts[type]->mControllers.end();++ctrl)
{ {
if(ctrl->getSource().isNull()) if(ctrl->getSource().isNull())
{ {
@ -715,7 +718,7 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : ""; const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
std::vector<ESM::PartReference>::const_iterator part(parts.begin()); std::vector<ESM::PartReference>::const_iterator part(parts.begin());
for(;part != parts.end();part++) for(;part != parts.end();++part)
{ {
const ESM::BodyPart *bodypart = 0; const ESM::BodyPart *bodypart = 0;
if(!mNpc->isMale() && !part->mFemale.empty()) if(!mNpc->isMale() && !part->mFemale.empty())

@ -574,24 +574,6 @@ void RenderingManager::configureAmbient(MWWorld::CellStore &mCell)
sunEnable(false); sunEnable(false);
} }
} }
// Switch through lighting modes.
void RenderingManager::toggleLight()
{
if (mAmbientMode==2)
mAmbientMode = 0;
else
++mAmbientMode;
switch (mAmbientMode)
{
case 0: std::cout << "Setting lights to normal\n"; break;
case 1: std::cout << "Turning the lights up\n"; break;
case 2: std::cout << "Turning the lights to full\n"; break;
}
setAmbientMode();
}
void RenderingManager::setSunColour(const Ogre::ColourValue& colour) void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
{ {
@ -695,11 +677,6 @@ void RenderingManager::enableLights(bool sun)
sunEnable(sun); sunEnable(sun);
} }
Shadows* RenderingManager::getShadows()
{
return mShadows;
}
void RenderingManager::notifyWorldSpaceChanged() void RenderingManager::notifyWorldSpaceChanged()
{ {
mEffectManager->clear(); mEffectManager->clear();

@ -93,7 +93,6 @@ public:
MWRender::Camera* getCamera() const; MWRender::Camera* getCamera() const;
void toggleLight();
bool toggleRenderMode(int mode); bool toggleRenderMode(int mode);
void removeCell (MWWorld::CellStore *store); void removeCell (MWWorld::CellStore *store);
@ -157,8 +156,6 @@ public:
float getTerrainHeightAt (Ogre::Vector3 worldPos); float getTerrainHeightAt (Ogre::Vector3 worldPos);
Shadows* getShadows();
void notifyWorldSpaceChanged(); void notifyWorldSpaceChanged();
void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches); void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches);

@ -41,6 +41,9 @@ public:
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr); void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
private: private:
RippleSimulation(const RippleSimulation&);
RippleSimulation& operator=(const RippleSimulation&);
std::vector<Emitter> mEmitters; std::vector<Emitter> mEmitters;
Ogre::RenderTexture* mRenderTargets[4]; Ogre::RenderTexture* mRenderTargets[4];

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save