Merge remote-tracking branch 'scrawl/master'

deque
Marc Zinnschlag 11 years ago
commit 5313862a46

@ -90,13 +90,13 @@ endif(UNIX AND NOT APPLE)
# Location of morrowind data files
if (APPLE)
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
set(MORROWIND_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
elseif(UNIX)
set(MORROWIND_DATA_FILES "/usr/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
set(MORROWIND_RESOURCE_FILES "/usr/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
set(MORROWIND_DATA_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
set(OPENMW_RESOURCE_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
else()
set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files")
set(MORROWIND_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
set(OPENMW_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
endif(APPLE)
if (WIN32)

@ -1,7 +1,7 @@
#ifndef GAME_MWSTATE_STATEMANAGER_H
#define GAME_MWSTATE_STATEMANAGER_H
#include <vector>
#include <list>
#include <string>
namespace MWState
@ -24,7 +24,7 @@ namespace MWBase
State_Running
};
typedef std::vector<MWState::Character>::const_iterator CharacterIterator;
typedef std::list<MWState::Character>::const_iterator CharacterIterator;
private:

@ -64,6 +64,9 @@ namespace MWClass
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health
virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const { return true; }
///< \return Item health data available? (default implementation: false)
};
}

@ -64,6 +64,9 @@ namespace MWClass
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health
virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const { return true; }
///< \return Item health data available? (default implementation: false)
};
}

@ -148,22 +148,6 @@ namespace
mTypesetter->lineBreak ();
}
};
struct AddQuestLink : AddContent
{
AddQuestLink (MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* style) :
AddContent (typesetter, style)
{
}
void operator () (MWGui::JournalViewModel::QuestId id, MWGui::JournalViewModel::Utf8Span name)
{
MWGui::BookTypesetter::Style* style = mTypesetter->createHotStyle (mBodyStyle, MyGUI::Colour::Black, linkHot, linkActive, id);
mTypesetter->write (style, name);
mTypesetter->lineBreak ();
}
};
}
namespace MWGui
@ -206,7 +190,7 @@ book JournalBooks::createJournalBook ()
BookTypesetter::Style* header = typesetter->createStyle ("", MyGUI::Colour (0.60f, 0.00f, 0.00f));
BookTypesetter::Style* body = typesetter->createStyle ("", MyGUI::Colour::Black);
mModel->visitJournalEntries (0, AddJournalEntry (typesetter, body, header, true));
mModel->visitJournalEntries ("", AddJournalEntry (typesetter, body, header, true));
return typesetter->complete ();
}
@ -227,16 +211,17 @@ book JournalBooks::createTopicBook (uintptr_t topicId)
return typesetter->complete ();
}
book JournalBooks::createQuestBook (uintptr_t questId)
book JournalBooks::createQuestBook (const std::string& questName)
{
BookTypesetter::Ptr typesetter = createTypesetter ();
BookTypesetter::Style* header = typesetter->createStyle ("", MyGUI::Colour (0.60f, 0.00f, 0.00f));
BookTypesetter::Style* body = typesetter->createStyle ("", MyGUI::Colour::Black);
mModel->visitQuestName (questId, AddQuestName (typesetter, header));
AddQuestName addName (typesetter, header);
addName(to_utf8_span(questName.c_str()));
mModel->visitJournalEntries (questId, AddJournalEntry (typesetter, body, header, false));
mModel->visitJournalEntries (questName, AddJournalEntry (typesetter, body, header, false));
return typesetter->complete ();
}
@ -269,26 +254,6 @@ book JournalBooks::createTopicIndexBook ()
return typesetter->complete ();
}
book JournalBooks::createTopicIndexBook (char character)
{
BookTypesetter::Ptr typesetter = BookTypesetter::create (0x7FFFFFFF, 0x7FFFFFFF);
BookTypesetter::Style* style = typesetter->createStyle ("", MyGUI::Colour::Black);
mModel->visitTopicNamesStartingWith (character, AddTopicLink (typesetter, style));
return typesetter->complete ();
}
book JournalBooks::createQuestIndexBook (bool activeOnly)
{
BookTypesetter::Ptr typesetter = BookTypesetter::create (0x7FFFFFFF, 0x7FFFFFFF);
BookTypesetter::Style* base = typesetter->createStyle ("", MyGUI::Colour::Black);
mModel->visitQuestNames (activeOnly, AddQuestLink (typesetter, base));
return typesetter->complete ();
}
BookTypesetter::Ptr JournalBooks::createTypesetter ()
{
//TODO: determine page size from layout...

@ -18,10 +18,9 @@ namespace MWGui
Book createEmptyJournalBook ();
Book createJournalBook ();
Book createTopicBook (uintptr_t topicId);
Book createQuestBook (uintptr_t questId);
Book createTopicBook (const std::string& topicId);
Book createQuestBook (const std::string& questName);
Book createTopicIndexBook ();
Book createTopicIndexBook (char character);
Book createQuestIndexBook (bool showAll);
private:
BookTypesetter::Ptr createTypesetter ();

@ -195,10 +195,12 @@ struct JournalViewModelImpl : JournalViewModel
};
void visitQuestNames (bool active_only, boost::function <void (QuestId, Utf8Span)> visitor) const
void visitQuestNames (bool active_only, boost::function <void (const std::string&)> visitor) const
{
MWBase::Journal * journal = MWBase::Environment::get ().getJournal ();
std::set<std::string> visitedQuests;
for (MWBase::Journal::TQuestIter i = journal->questBegin (); i != journal->questEnd (); ++i)
{
if (active_only && i->second.isFinished ())
@ -209,7 +211,15 @@ struct JournalViewModelImpl : JournalViewModel
// Note that even with Tribunal, some quests still don't have quest names. I'm assuming those are not supposed
// to appear in the quest book.
if (!quest.getName().empty())
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (quest.getName()));
{
// Don't list the same quest name twice
if (visitedQuests.find(quest.getName()) != visitedQuests.end())
continue;
visitor (quest.getName());
visitedQuests.insert(quest.getName());
}
}
}
@ -258,20 +268,29 @@ struct JournalViewModelImpl : JournalViewModel
}
};
void visitJournalEntries (QuestId questId, boost::function <void (JournalEntry const &)> visitor) const
void visitJournalEntries (const std::string& questName, boost::function <void (JournalEntry const &)> visitor) const
{
MWBase::Journal * journal = MWBase::Environment::get().getJournal();
if (questId != 0)
if (!questName.empty())
{
MWDialogue::Quest const * quest = reinterpret_cast <MWDialogue::Quest const *> (questId);
std::vector<MWDialogue::Quest const*> quests;
for (MWBase::Journal::TQuestIter questIt = journal->questBegin(); questIt != journal->questEnd(); ++questIt)
{
if (Misc::StringUtils::ciEqual(questIt->second.getName(), questName))
quests.push_back(&questIt->second);
}
for(MWBase::Journal::TEntryIter i = journal->begin(); i != journal->end (); ++i)
{
for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j)
for (std::vector<MWDialogue::Quest const*>::iterator questIt = quests.begin(); questIt != quests.end(); ++questIt)
{
if (i->mInfoId == j->mInfoId)
visitor (JournalEntryImpl <MWBase::Journal::TEntryIter> (this, i));
MWDialogue::Quest const* quest = *questIt;
for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j)
{
if (i->mInfoId == j->mInfoId)
visitor (JournalEntryImpl <MWBase::Journal::TEntryIter> (this, i));
}
}
}
}
@ -293,7 +312,7 @@ struct JournalViewModelImpl : JournalViewModel
visitor (toUtf8Span (topic.getName()));
}
void visitTopicNamesStartingWith (char character, boost::function < void (TopicId , Utf8Span) > visitor) const
void visitTopicNamesStartingWith (char character, boost::function < void (const std::string&) > visitor) const
{
MWBase::Journal * journal = MWBase::Environment::get().getJournal();
@ -302,7 +321,7 @@ struct JournalViewModelImpl : JournalViewModel
if (i->first [0] != std::tolower (character, mLocale))
continue;
visitor (TopicId (&i->second), toUtf8Span (i->second.getName()));
visitor (i->second.getName());
}
}

@ -70,17 +70,18 @@ namespace MWGui
/// 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 quest id and name
virtual void visitQuestNames (bool active_only, boost::function <void (QuestId, Utf8Span)> visitor) const = 0;
/// 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;
/// walks over the journal entries related to the specified quest identified by its id
virtual void visitJournalEntries (QuestId questId, boost::function <void (JournalEntry const &)> visitor) const = 0;
/// walks over the journal entries related to all quests with the given name
/// If \a questName is empty, simply visits all journal entries
virtual void visitJournalEntries (const std::string& questName, boost::function <void (JournalEntry const &)> visitor) const = 0;
/// provides the name of the topic specified by its id
virtual void visitTopicName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const = 0;
/// walks over the topics whose names start with the specified character providing the topics id and name
virtual void visitTopicNamesStartingWith (char character, boost::function < void (TopicId , Utf8Span) > visitor) const = 0;
/// walks over the topics whose names start with the specified character providing the topics name
virtual void visitTopicNamesStartingWith (char character, boost::function < void (const std::string&) > visitor) const = 0;
/// walks over the topic entries for the topic specified by its identifier
virtual void visitTopicEntries (TopicId topicId, boost::function <void (TopicEntry const &)> visitor) const = 0;

@ -3,6 +3,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/journal.hpp"
#include "list.hpp"
#include <sstream>
@ -19,6 +20,7 @@
#include "imagebutton.hpp"
#include "journalviewmodel.hpp"
#include "journalbooks.hpp"
#include "list.hpp"
namespace
{
@ -36,9 +38,7 @@ namespace
static char const PageOneNum [] = "PageOneNum";
static char const PageTwoNum [] = "PageTwoNum";
static char const TopicsList [] = "TopicsList";
static char const TopicsPage [] = "TopicsPage";
static char const QuestsList [] = "QuestsList";
static char const QuestsPage [] = "QuestsPage";
static char const LeftBookPage [] = "LeftBookPage";
static char const RightBookPage [] = "RightBookPage";
static char const LeftTopicIndex [] = "LeftTopicIndex";
@ -110,12 +110,17 @@ namespace
adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll );
adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(QuestsList);
list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked);
MWGui::Widgets::MWList* topicsList = getWidget<MWGui::Widgets::MWList>(TopicsList);
topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected);
{
MWGui::BookPage::ClickCallback callback;
callback = boost::bind (&JournalWindowImpl::notifyTopicClicked, this, _1);
getPage (TopicsPage)->adviseLinkClicked (callback);
getPage (LeftBookPage)->adviseLinkClicked (callback);
getPage (RightBookPage)->adviseLinkClicked (callback);
}
@ -129,14 +134,6 @@ namespace
getPage (RightTopicIndex)->adviseLinkClicked (callback);
}
{
MWGui::BookPage::ClickCallback callback;
callback = boost::bind (&JournalWindowImpl::notifyQuestClicked, this, _1);
getPage (QuestsPage)->adviseLinkClicked (callback);
}
adjustButton(OptionsBTN, true);
adjustButton(PrevPageBTN);
adjustButton(NextPageBTN);
@ -271,6 +268,10 @@ namespace
//TODO: figure out how to make "options" page overlay book page
// correctly, so that text may show underneath
getPage (RightBookPage)->showPage (Book (), 0);
// If in quest mode, ensure the quest list is updated
if (mQuestMode)
notifyQuests(getWidget<MyGUI::Widget>(QuestsList));
}
void pushBook (Book book, unsigned int page)
@ -349,9 +350,22 @@ namespace
setVisible (JournalBTN, true);
}
void notifyQuestClicked (intptr_t questId)
void notifyTopicSelected (const std::string& topic, int id)
{
const MWBase::Journal* journal = MWBase::Environment::get().getJournal();
intptr_t topicId = 0; /// \todo get rid of intptr ids
for(MWBase::Journal::TTopicIter i = journal->topicBegin(); i != journal->topicEnd (); ++i)
{
if (Misc::StringUtils::ciEqual(i->first, topic))
topicId = intptr_t (&i->second);
}
notifyTopicClicked(topicId);
}
void notifyQuestClicked (const std::string& name, int id)
{
Book book = createQuestBook (questId);
Book book = createQuestBook (name);
if (mStates.size () > 1)
replaceBook (book, 0);
@ -395,7 +409,14 @@ namespace
setVisible (RightTopicIndex, false);
setVisible (TopicsList, true);
showList (TopicsList, TopicsPage, createTopicIndexBook ((char)character));
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(TopicsList);
list->clear();
AddNamesToList add(list);
mModel->visitTopicNamesStartingWith((char) character, add);
list->adjustSize();
}
void notifyTopics(MyGUI::Widget* _sender)
@ -409,9 +430,21 @@ namespace
setVisible (ShowActiveBTN, false);
}
struct AddNamesToList
{
AddNamesToList(MWGui::Widgets::MWList* list) : mList(list) {}
MWGui::Widgets::MWList* mList;
void operator () (const std::string& name)
{
mList->addItem(name);
}
};
void notifyQuests(MyGUI::Widget* _sender)
{
mQuestMode = true;
setVisible (LeftTopicIndex, false);
setVisible (RightTopicIndex, false);
setVisible (TopicsList, false);
@ -419,23 +452,26 @@ namespace
setVisible (ShowAllBTN, !mAllQuests);
setVisible (ShowActiveBTN, mAllQuests);
showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests));
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(QuestsList);
list->clear();
AddNamesToList add(list);
mModel->visitQuestNames(!mAllQuests, add);
list->adjustSize();
}
void notifyShowAll(MyGUI::Widget* _sender)
{
mAllQuests = true;
setVisible (ShowAllBTN, !mAllQuests);
setVisible (ShowActiveBTN, mAllQuests);
showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests));
notifyQuests(_sender);
}
void notifyShowActive(MyGUI::Widget* _sender)
{
mAllQuests = false;
setVisible (ShowAllBTN, !mAllQuests);
setVisible (ShowActiveBTN, mAllQuests);
showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests));
notifyQuests(_sender);
}
void notifyCancel(MyGUI::Widget* _sender)

@ -65,8 +65,10 @@ namespace MWGui
{
if (*it != "")
{
if (mListItemSkin.empty())
throw std::runtime_error("MWList needs a ListItemSkin property");
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(
"MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
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);
@ -102,6 +104,14 @@ namespace MWGui
mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition));
}
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());

@ -22,7 +22,7 @@ namespace MWGui
/**
* Event: Item selected with the mouse.
* signature: void method(std::string itemName)
* signature: void method(std::string itemName, int index)
*/
EventHandle_StringInt eventItemSelected;
@ -49,6 +49,8 @@ namespace MWGui
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();
@ -60,6 +62,7 @@ namespace MWGui
private:
MyGUI::ScrollView* mScrollView;
MyGUI::Widget* mClient;
std::string mListItemSkin;
std::vector<std::string> mItems;

@ -11,6 +11,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/statemanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/inputmanager.hpp"
@ -26,7 +27,6 @@ namespace MWGui
, WindowBase("openmw_loading_screen.layout")
, mLastRenderTime(0.f)
, mLastWallpaperChangeTime(0.f)
, mFirstLoad(true)
, mProgress(0)
, mVSyncWasEnabled(false)
{
@ -77,7 +77,11 @@ namespace MWGui
mWindow->setVSyncEnabled(false);
#endif
if (!mFirstLoad)
bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState()
== MWBase::StateManager::State_NoGame);
if (!showWallpaper)
{
mBackgroundImage->setImageTexture("");
int width = mWindow->getWidth();
@ -103,12 +107,12 @@ namespace MWGui
setVisible(true);
if (mFirstLoad)
if (showWallpaper)
{
changeWallpaper();
}
MWBase::Environment::get().getWindowManager()->pushGuiMode(mFirstLoad ? GM_LoadingWallpaper : GM_Loading);
MWBase::Environment::get().getWindowManager()->pushGuiMode(showWallpaper ? GM_LoadingWallpaper : GM_Loading);
}
void LoadingScreen::loadingOff()
@ -188,11 +192,6 @@ namespace MWGui
draw();
}
void LoadingScreen::removeWallpaper()
{
mFirstLoad = false;
}
void LoadingScreen::draw()
{
const float loadingScreenFps = 20.f;
@ -201,7 +200,10 @@ namespace MWGui
{
mLastRenderTime = mTimer.getMilliseconds ();
if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1)
bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState()
== MWBase::StateManager::State_NoGame);
if (showWallpaper && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1)
{
mLastWallpaperChangeTime = mTimer.getMilliseconds ();
changeWallpaper();

@ -29,8 +29,6 @@ namespace MWGui
virtual void setVisible(bool visible);
virtual void removeWallpaper();
LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw);
virtual ~LoadingScreen();
@ -42,8 +40,6 @@ namespace MWGui
void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; }
private:
bool mFirstLoad;
Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow;

@ -117,7 +117,7 @@ namespace MWGui
std::string directory =
Misc::StringUtils::lowerCase (Settings::Manager::getString ("character", "Saves"));
int selectedIndex = MyGUI::ITEM_NONE;
size_t selectedIndex = MyGUI::ITEM_NONE;
for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it)
{

@ -190,6 +190,7 @@ namespace MWGui
costChance->setNeedMouseFocus(false);
costChance->setStateSelected(*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell());
t->setSize(mWidth-12-costChance->getTextSize().width, t->getHeight());
mHeight += spellHeight;
}
@ -255,6 +256,8 @@ namespace MWGui
if (store.getSelectedEnchantItem() != store.end())
costCharge->setStateSelected(item == *store.getSelectedEnchantItem());
t->setSize(mWidth-12-costCharge->getTextSize().width, t->getHeight());
mHeight += spellHeight;
}
@ -287,6 +290,8 @@ namespace MWGui
groupWidget2->setCaptionWithReplacing(label2);
groupWidget2->setTextAlign(MyGUI::Align::Right);
groupWidget2->setNeedMouseFocus(false);
groupWidget->setSize(mWidth-8-groupWidget2->getTextSize().width, groupWidget->getHeight());
}
mHeight += 24;

@ -989,7 +989,11 @@ namespace MWMechanics
if(!stats.isDead())
{
if(iter->second->isDead())
{
// Actor has been resurrected. Notify the CharacterController and re-enable collision.
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true);
iter->second->resurrect();
}
if(!stats.isDead())
continue;

@ -49,20 +49,17 @@ MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create)
void MWState::CharacterManager::deleteSlot(const MWState::Character *character, const MWState::Slot *slot)
{
int index = character - &mCharacters[0];
std::list<Character>::iterator it = findCharacter(character);
if (index<0 || index>=static_cast<int> (mCharacters.size()))
throw std::logic_error ("invalid character");
mCharacters[index].deleteSlot(slot);
it->deleteSlot(slot);
if (mCharacters[index].begin() == mCharacters[index].end())
if (character->begin() == character->end())
{
// All slots deleted, cleanup and remove this character
mCharacters[index].cleanup();
it->cleanup();
if (character == mCurrent)
mCurrent = NULL;
mCharacters.erase(mCharacters.begin() + index);
mCharacters.erase(it);
}
}
@ -78,14 +75,24 @@ void MWState::CharacterManager::createCharacter()
mCurrent = &mCharacters.back();
}
void MWState::CharacterManager::setCurrentCharacter (const Character *character)
std::list<MWState::Character>::iterator MWState::CharacterManager::findCharacter(const MWState::Character* character)
{
int index = character - &mCharacters[0];
if (index<0 || index>=static_cast<int> (mCharacters.size()))
std::list<Character>::iterator it = mCharacters.begin();
for (; it != mCharacters.end(); ++it)
{
if (&*it == character)
break;
}
if (it == mCharacters.end())
throw std::logic_error ("invalid character");
return it;
}
void MWState::CharacterManager::setCurrentCharacter (const Character *character)
{
std::list<Character>::iterator it = findCharacter(character);
mCurrent = &mCharacters[index];
mCurrent = &*it;
}
void MWState::CharacterManager::clearCurrentCharacter()
@ -93,12 +100,12 @@ void MWState::CharacterManager::clearCurrentCharacter()
mCurrent = 0;
}
std::vector<MWState::Character>::const_iterator MWState::CharacterManager::begin() const
std::list<MWState::Character>::const_iterator MWState::CharacterManager::begin() const
{
return mCharacters.begin();
}
std::vector<MWState::Character>::const_iterator MWState::CharacterManager::end() const
std::list<MWState::Character>::const_iterator MWState::CharacterManager::end() const
{
return mCharacters.end();
}

@ -11,7 +11,10 @@ namespace MWState
{
boost::filesystem::path mPath;
int mNext;
std::vector<Character> mCharacters;
// Uses std::list, so that mCurrent stays valid when characters are deleted
std::list<Character> mCharacters;
Character *mCurrent;
std::string mGame;
@ -23,6 +26,8 @@ namespace MWState
CharacterManager& operator= (const CharacterManager&);
///< Not implemented
std::list<Character>::iterator findCharacter(const MWState::Character* character);
public:
CharacterManager (const boost::filesystem::path& saves, const std::string& game);
@ -39,9 +44,9 @@ namespace MWState
void clearCurrentCharacter();
std::vector<Character>::const_iterator begin() const;
std::list<Character>::const_iterator begin() const;
std::vector<Character>::const_iterator end() const;
std::list<Character>::const_iterator end() const;
};
}

@ -149,91 +149,105 @@ void MWState::StateManager::endGame()
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot)
{
ESM::SavedGame profile;
try
{
ESM::SavedGame profile;
MWBase::World& world = *MWBase::Environment::get().getWorld();
MWBase::World& world = *MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world.getPlayerPtr();
MWWorld::Ptr player = world.getPlayerPtr();
profile.mContentFiles = world.getContentFiles();
profile.mContentFiles = world.getContentFiles();
profile.mPlayerName = player.getClass().getName (player);
profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();
profile.mPlayerName = player.getClass().getName (player);
profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();
std::string classId = player.get<ESM::NPC>()->mBase->mClass;
if (world.getStore().get<ESM::Class>().isDynamic(classId))
profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName;
else
profile.mPlayerClassId = classId;
profile.mPlayerCell = world.getCellName();
profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
profile.mInGameTime.mDay = world.getDay();
profile.mInGameTime.mMonth = world.getMonth();
profile.mInGameTime.mYear = world.getYear();
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
std::string classId = player.get<ESM::NPC>()->mBase->mClass;
if (world.getStore().get<ESM::Class>().isDynamic(classId))
profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName;
else
profile.mPlayerClassId = classId;
profile.mPlayerCell = world.getCellName();
profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
profile.mInGameTime.mDay = world.getDay();
profile.mInGameTime.mMonth = world.getMonth();
profile.mInGameTime.mYear = world.getYear();
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
ESM::ESMWriter writer;
ESM::ESMWriter writer;
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.setFormat (ESM::Header::CurrentFormat);
int recordCount = 1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords();
writer.setRecordCount (recordCount);
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.save (stream);
writer.setFormat (ESM::Header::CurrentFormat);
int recordCount = 1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords();
writer.setRecordCount (recordCount);
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener.setProgressRange(recordCount);
listener.setLabel("#{sNotifyMessage4}");
writer.save (stream);
Loading::ScopedLoad load(&listener);
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener.setProgressRange(recordCount);
listener.setLabel("#{sNotifyMessage4}");
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
listener.increaseProgress();
Loading::ScopedLoad load(&listener);
MWBase::Environment::get().getJournal()->write (writer, listener);
MWBase::Environment::get().getDialogueManager()->write (writer, listener);
MWBase::Environment::get().getWorld()->write (writer, listener);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
MWBase::Environment::get().getWindowManager()->write(writer, listener);
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
listener.increaseProgress();
// Ensure we have written the number of records that was estimated
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl;
MWBase::Environment::get().getJournal()->write (writer, listener);
MWBase::Environment::get().getDialogueManager()->write (writer, listener);
MWBase::Environment::get().getWorld()->write (writer, listener);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
MWBase::Environment::get().getWindowManager()->write(writer, listener);
writer.close();
// Ensure we have written the number of records that was estimated
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl;
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
}
catch (const std::exception& e)
{
std::stringstream error;
error << "Failed to save game: " << e.what();
writer.close();
std::cerr << error.str() << std::endl;
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
std::vector<std::string> buttons;
buttons.push_back("#{sOk}");
MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons);
}
}
void MWState::StateManager::quickSave (std::string name)
@ -371,10 +385,17 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
}
catch (const std::exception& e)
{
std::cerr << "failed to load saved game: " << e.what() << std::endl;
std::stringstream error;
error << "Failed to load saved game: " << e.what();
std::cerr << error.str() << std::endl;
cleanup (true);
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
std::vector<std::string> buttons;
buttons.push_back("#{sOk}");
MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons);
}
}

@ -314,6 +314,8 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type,
catch (...)
{
// silently drop cells that don't exist anymore
reader.skipRecord();
return true;
/// \todo log
}

@ -100,7 +100,7 @@ namespace MWWorld
if (iter!=mVariables.end())
iter->second.read (reader, ESM::Variant::Format_Global);
else
reader.skipHRecord();
reader.skipRecord();
return true;
}

@ -347,8 +347,6 @@ namespace MWWorld
MWBase::Environment::get().getWorld()->adjustSky();
mCellChanged = true;
loadingListener->removeWallpaper();
}
//We need the ogre renderer and a scene node.
@ -449,8 +447,6 @@ namespace MWWorld
mCellChanged = true;
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5);
loadingListener->removeWallpaper();
}
void Scene::changeToExteriorCell (const ESM::Position& position)

@ -368,6 +368,9 @@ namespace MWWorld
World::~World()
{
// Must be cleared before mRendering is destroyed
mProjectileManager->clear();
delete mWeatherManager;
delete mWorldScene;
delete mRendering;

@ -12,10 +12,26 @@ void Region::load(ESMReader &esm)
{
mName = esm.getHNOString("FNAM");
esm.getSubNameIs("WEAT");
esm.getSubHeader();
if (esm.getVer() == VER_12)
esm.getHNExact(&mData, sizeof(mData) - 2, "WEAT");
{
mData.mA = 0;
mData.mB = 0;
esm.getExact(&mData, sizeof(mData) - 2);
}
else if (esm.getVer() == VER_13)
esm.getHNExact(&mData, sizeof(mData), "WEAT");
{
// May include the additional two bytes (but not necessarily)
if (esm.getSubSize() == sizeof(mData))
esm.getExact(&mData, sizeof(mData));
else
{
mData.mA = 0;
mData.mB = 0;
esm.getExact(&mData, sizeof(mData)-2);
}
}
else
esm.fail("Don't know what to do in this version");

@ -6,6 +6,15 @@
#include "esmreader.hpp"
#include "variantimp.hpp"
#include "defs.hpp"
namespace
{
const uint32_t STRV = ESM::FourCC<'S','T','R','V'>::value;
const uint32_t INTV = ESM::FourCC<'I','N','T','V'>::value;
const uint32_t FLTV = ESM::FourCC<'F','L','T','V'>::value;
}
ESM::Variant::Variant() : mType (VT_None), mData (0) {}
ESM::Variant::~Variant()
@ -90,15 +99,17 @@ void ESM::Variant::read (ESMReader& esm, Format format)
esm.getSubName();
NAME name = esm.retSubName();
if (name=="STRV")
if (name==STRV)
{
type = VT_String;
}
else if (name=="INTV")
else if (name==INTV)
{
type = VT_Int;
}
else if (name=="FLTV")
else if (name==FLTV)
{
type = VT_Float;
}
@ -111,11 +122,11 @@ void ESM::Variant::read (ESMReader& esm, Format format)
esm.getSubName();
NAME name = esm.retSubName();
if (name=="INTV")
if (name==INTV)
{
type = VT_Int;
}
else if (name=="FLTV")
else if (name==FLTV)
{
type = VT_Float;
}
@ -279,4 +290,4 @@ bool ESM::operator== (const Variant& left, const Variant& right)
bool ESM::operator!= (const Variant& left, const Variant& right)
{
return !(left==right);
}
}

@ -18,9 +18,6 @@ namespace Loading
virtual void setProgressRange (size_t range) = 0;
virtual void setProgress (size_t value) = 0;
virtual void increaseProgress (size_t increase = 1) = 0;
/// Indicate the scene is now ready to be shown
virtual void removeWallpaper() = 0;
};
// Used for stopping a loading sequence when the object goes out of scope

@ -77,14 +77,10 @@
<Property key="ImagePushed" value="textures\tx_menubook_quests_all_pressed.dds"/>
</Widget>
<Widget type="ScrollView" skin="MW_ScrollView" position="20 15 184 245" name="TopicsList" align="Right VStretch">
<Property key="CanvasAlign" value="Left Top"/>
<Widget type="BookPage" skin="MW_BookPage" position="0 0 30000 30000" name="TopicsPage"/>
<Widget type="MWList" skin="MW_QuestList" position="8 35 208 225" name="TopicsList" align="Right VStretch">
</Widget>
<Widget type="ScrollView" skin="MW_ScrollView" position="20 35 184 225" name="QuestsList" align="Right VStretch">
<Property key="CanvasAlign" value="Left Top"/>
<Widget type="BookPage" skin="MW_BookPage" position="0 0 30000 30000" name="QuestsPage"/>
<Widget type="MWList" skin="MW_QuestList" position="8 35 208 225" name="QuestsList" align="Right VStretch">
</Widget>
<Widget type="ImageButton" skin="ImageBox" position="20 265 56 32" Align="Top|Left" name="TopicsBTN">

@ -12,4 +12,28 @@
<Skin name="MW_BookPage" size="0 0 50 50">
<BasisSkin type="PageDisplay"/>
</Skin>
<Skin name="MW_QuestList" size="516 516" align="Left Top">
<Property key="ListItemSkin" value="MW_QuestLink"/>
<Child type="Widget" skin="" offset="3 3 510 510" align="Top Left Stretch" name="Client"/>
</Skin>
<Skin name="MW_QuestLink" size="5 5">
<Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Left VCenter"/>
<BasisSkin type="SimpleText" offset="2 0 1 5" align="Stretch">
<State name="disabled" colour="0 0 0" shift="0"/>
<State name="normal" colour="0 0 0" shift="0"/>
<State name="highlighted" colour="0.4 0.4 0.8" shift="0"/>
<State name="pushed" colour="0.5 0.5 1" shift="0"/>
<State name="disabled_checked" colour="0 0 0" shift="0"/>
<State name="normal_checked" colour="0 0 0" shift="0"/>
<State name="highlighted_checked" colour="0.4 0.4 0.8" shift="0"/>
<State name="pushed_checked" colour="0.5 0.5 1" shift="0"/>
</BasisSkin>
</Skin>
</MyGUI>

@ -157,6 +157,7 @@
</Skin>
<Skin name="MW_SimpleList" size="516 516" align="Left Top">
<Property key="ListItemSkin" value="MW_ListLine"/>
<Child type="Widget" skin="MW_Box" offset="0 0 516 516" align="Stretch"/>

@ -1,4 +1,4 @@
data="?global?data"
data="?mw?Data Files"
data-local="?user?data"
resources=${MORROWIND_RESOURCE_FILES}
resources=${OPENMW_RESOURCE_FILES}

@ -615,6 +615,7 @@ namespace Physic
btCollisionObject *object)
{
DeepestNotMeContactTestResultCallback callback(filter, origin);
callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor;
dynamicsWorld->contactTest(object, callback);
return std::make_pair(callback.mObject, callback.mContactPoint);
}

Loading…
Cancel
Save