1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-22 03:39:40 +00:00

Merge remote-tracking branch 'kcat/animations' into ref

This commit is contained in:
Marc Zinnschlag 2013-04-25 20:12:14 +02:00
commit 2c1796cc74
99 changed files with 10193 additions and 9948 deletions

View file

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version # Version
set (OPENMW_VERSION_MAJOR 0) set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 22) set (OPENMW_VERSION_MINOR 23)
set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")

View file

@ -439,7 +439,7 @@ void Record<ESM::Apparatus>::print()
template<> template<>
void Record<ESM::BodyPart>::print() void Record<ESM::BodyPart>::print()
{ {
std::cout << " Name: " << mData.mName << std::endl; std::cout << " Race: " << mData.mRace << std::endl;
std::cout << " Model: " << mData.mModel << std::endl; std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Type: " << meshTypeLabel(mData.mData.mType) std::cout << " Type: " << meshTypeLabel(mData.mData.mType)
<< " (" << (int)mData.mData.mType << ")" << std::endl; << " (" << (int)mData.mData.mType << ")" << std::endl;

View file

@ -102,3 +102,9 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage) add_definitions (--coverage)
target_link_libraries(omwlauncher gcov) target_link_libraries(omwlauncher gcov)
endif() endif()
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
if (UNIX AND NOT APPLE)
target_link_libraries(omwlauncher dl Xt)
endif()

View file

@ -96,15 +96,15 @@ bool GameSettings::readFile(QTextStream &stream)
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
while (!stream.atEnd()) { while (!stream.atEnd()) {
QString line = stream.readLine().simplified(); QString line = stream.readLine();
if (line.isEmpty() || line.startsWith("#")) if (line.isEmpty() || line.startsWith("#"))
continue; continue;
if (keyRe.indexIn(line) != -1) { if (keyRe.indexIn(line) != -1) {
QString key = keyRe.cap(1).simplified(); QString key = keyRe.cap(1);
QString value = keyRe.cap(2).simplified(); QString value = keyRe.cap(2);
// Don't remove existing data entries // Don't remove existing data entries
if (key != QLatin1String("data")) if (key != QLatin1String("data"))

View file

@ -52,7 +52,7 @@ public:
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
while (!stream.atEnd()) { while (!stream.atEnd()) {
QString line = stream.readLine().simplified(); QString line = stream.readLine();
if (line.isEmpty() || line.startsWith("#")) if (line.isEmpty() || line.startsWith("#"))
continue; continue;
@ -65,8 +65,8 @@ public:
if (keyRe.indexIn(line) != -1) { if (keyRe.indexIn(line) != -1) {
QString key = keyRe.cap(1).simplified(); QString key = keyRe.cap(1);
QString value = keyRe.cap(2).simplified(); QString value = keyRe.cap(2);
if (!sectionPrefix.isEmpty()) if (!sectionPrefix.isEmpty())
key.prepend(sectionPrefix); key.prepend(sectionPrefix);

View file

@ -122,6 +122,12 @@ if (UNIX AND NOT APPLE)
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
if (UNIX AND NOT APPLE)
target_link_libraries(openmw dl Xt)
endif()
if(APPLE) if(APPLE)
find_library(CARBON_FRAMEWORK Carbon) find_library(CARBON_FRAMEWORK Carbon)
find_library(COCOA_FRAMEWORK Cocoa) find_library(COCOA_FRAMEWORK Cocoa)

View file

@ -99,6 +99,9 @@ namespace MWBase
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange) = 0; float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange) = 0;
///< Perform a persuasion action on NPC ///< Perform a persuasion action on NPC
virtual void forceStateUpdate(const MWWorld::Ptr &ptr) = 0;
///< Forces an object to refresh its animation state.
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number=1) = 0; virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number=1) = 0;
///< Run animation for a MW-reference. Calls to this function for references that are currently not ///< Run animation for a MW-reference. Calls to this function for references that are currently not
/// in the scene should be ignored. /// in the scene should be ignored.

View file

@ -49,6 +49,67 @@ namespace
{ {
return new CustomData (*this); return new CustomData (*this);
} }
void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats)
{
// race bonus
const ESM::Race *race =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npc->mRace);
bool male = (npc->mFlags & ESM::NPC::Female) == 0;
int level = creatureStats.getLevel();
for (int i=0; i<ESM::Attribute::Length; ++i)
{
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
creatureStats.getAttribute(i).setBase (male ? attribute.mMale : attribute.mFemale);
}
// class bonus
const ESM::Class *class_ =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc->mClass);
for (int i=0; i<2; ++i)
{
int attribute = class_->mData.mAttribute[i];
if (attribute>=0 && attribute<8)
{
creatureStats.getAttribute(attribute).setBase (
creatureStats.getAttribute(attribute).getBase() + 10);
}
}
// skill bonus
for (int attribute=0; attribute<ESM::Attribute::Length; ++attribute)
{
float modifierSum = 0;
for (int j=0; j<ESM::Skill::Length; ++j)
{
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(j);
if (skill->mData.mAttribute != attribute)
continue;
// is this a minor or major skill?
float add=0.2;
for (int k=0; k<5; ++k)
{
if (class_->mData.mSkills[k][0] == j)
add=0.5;
}
for (int k=0; k<5; ++k)
{
if (class_->mData.mSkills[k][1] == j)
add=1.0;
}
modifierSum += add;
}
creatureStats.getAttribute(attribute).setBase ( std::min(creatureStats.getAttribute(attribute).getBase()
+ static_cast<int>((level-1) * modifierSum+0.5), 100) );
}
}
} }
namespace MWClass namespace MWClass
@ -126,15 +187,14 @@ namespace MWClass
} }
else else
{ {
for (int i=0; i<8; ++i)
data->mCreatureStats.getAttribute (i).set (10);
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
data->mCreatureStats.setDynamic (i, 10); data->mCreatureStats.setDynamic (i, 10);
data->mCreatureStats.setLevel(ref->mBase->mNpdt12.mLevel); data->mCreatureStats.setLevel(ref->mBase->mNpdt12.mLevel);
data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt12.mDisposition); data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt12.mDisposition);
data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation); data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation);
autoCalculateAttributes(ref->mBase, data->mCreatureStats);
} }
data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello); data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello);

View file

@ -426,6 +426,7 @@ namespace MWDialogue
void DialogueManager::questionAnswered (const std::string& answer) void DialogueManager::questionAnswered (const std::string& answer)
{ {
if (mChoiceMap.find(answer) != mChoiceMap.end()) if (mChoiceMap.find(answer) != mChoiceMap.end())
{ {
mChoice = mChoiceMap[answer]; mChoice = mChoiceMap[answer];
@ -442,6 +443,10 @@ namespace MWDialogue
std::string text = info->mResponse; std::string text = info->mResponse;
parseText (text); parseText (text);
mChoiceMap.clear();
mChoice = -1;
mIsInChoice = false;
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext)); MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext));
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId); MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId);
@ -449,9 +454,6 @@ namespace MWDialogue
mLastDialogue = *info; mLastDialogue = *info;
} }
} }
mChoiceMap.clear();
mChoice = -1;
mIsInChoice = false;
} }
updateTopics(); updateTopics();

View file

@ -73,6 +73,11 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
if (iter->second < info.mData.mRank) if (iter->second < info.mData.mRank)
return false; return false;
} }
else if (info.mData.mRank != -1)
{
// if there is a rank condition, but the NPC is not in a faction, always fail
return false;
}
// Gender // Gender
if (!isCreature) if (!isCreature)

View file

@ -27,7 +27,7 @@ namespace MWDialogue
static std::string idFromIndex (const std::string& topic, int index); static std::string idFromIndex (const std::string& topic, int index);
}; };
/// \biref A quest entry with a timestamp. /// \brief A quest entry with a timestamp.
struct StampedJournalEntry : public JournalEntry struct StampedJournalEntry : public JournalEntry
{ {
int mDay; int mDay;

View file

@ -8,8 +8,6 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/containerstore.hpp"
namespace namespace
{ {

View file

@ -10,7 +10,6 @@
namespace MWGui namespace MWGui
{ {
class AlchemyWindow : public WindowBase, public ContainerBase class AlchemyWindow : public WindowBase, public ContainerBase
{ {
public: public:

View file

@ -3,30 +3,28 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "widgets.hpp" #include "widgets.hpp"
using namespace MWGui;
using namespace Widgets;
namespace namespace
{ {
bool sortBirthSigns(const std::pair<std::string, const ESM::BirthSign*>& left, const std::pair<std::string, const ESM::BirthSign*>& right) bool sortBirthSigns(const std::pair<std::string, const ESM::BirthSign*>& left, const std::pair<std::string, const ESM::BirthSign*>& right)
{ {
return left.second->mName.compare (right.second->mName) < 0; return left.second->mName.compare (right.second->mName) < 0;
} }
} }
BirthDialog::BirthDialog() namespace MWGui
: WindowModal("openmw_chargen_birth.layout")
{ {
BirthDialog::BirthDialog()
: WindowModal("openmw_chargen_birth.layout")
{
// Centre dialog // Centre dialog
center(); center();
@ -51,10 +49,10 @@ BirthDialog::BirthDialog()
updateBirths(); updateBirths();
updateSpells(); updateSpells();
} }
void BirthDialog::setNextButtonShow(bool shown) void BirthDialog::setNextButtonShow(bool shown)
{ {
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
@ -62,18 +60,18 @@ void BirthDialog::setNextButtonShow(bool shown)
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", ""));
else else
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
} }
void BirthDialog::open() void BirthDialog::open()
{ {
WindowModal::open(); WindowModal::open();
updateBirths(); updateBirths();
updateSpells(); updateSpells();
} }
void BirthDialog::setBirthId(const std::string &birthId) void BirthDialog::setBirthId(const std::string &birthId)
{ {
mCurrentBirthId = birthId; mCurrentBirthId = birthId;
mBirthList->setIndexSelected(MyGUI::ITEM_NONE); mBirthList->setIndexSelected(MyGUI::ITEM_NONE);
size_t count = mBirthList->getItemCount(); size_t count = mBirthList->getItemCount();
@ -89,24 +87,24 @@ void BirthDialog::setBirthId(const std::string &birthId)
} }
updateSpells(); updateSpells();
} }
// widget controls // widget controls
void BirthDialog::onOkClicked(MyGUI::Widget* _sender) void BirthDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
if(mBirthList->getIndexSelected() == MyGUI::ITEM_NONE) if(mBirthList->getIndexSelected() == MyGUI::ITEM_NONE)
return; return;
eventDone(this); eventDone(this);
} }
void BirthDialog::onBackClicked(MyGUI::Widget* _sender) void BirthDialog::onBackClicked(MyGUI::Widget* _sender)
{ {
eventBack(); eventBack();
} }
void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index) void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index)
{ {
if (_index == MyGUI::ITEM_NONE) if (_index == MyGUI::ITEM_NONE)
return; return;
@ -119,12 +117,12 @@ void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index)
mCurrentBirthId = *birthId; mCurrentBirthId = *birthId;
updateSpells(); updateSpells();
} }
// update widget content // update widget content
void BirthDialog::updateBirths() void BirthDialog::updateBirths()
{ {
mBirthList->removeAllItems(); mBirthList->removeAllItems();
const MWWorld::Store<ESM::BirthSign> &signs = const MWWorld::Store<ESM::BirthSign> &signs =
@ -155,10 +153,10 @@ void BirthDialog::updateBirths()
mBirthList->setIndexSelected(index); mBirthList->setIndexSelected(index);
} }
} }
} }
void BirthDialog::updateSpells() void BirthDialog::updateSpells()
{ {
for (std::vector<MyGUI::Widget*>::iterator it = mSpellItems.begin(); it != mSpellItems.end(); ++it) for (std::vector<MyGUI::Widget*>::iterator it = mSpellItems.begin(); it != mSpellItems.end(); ++it)
{ {
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
@ -168,7 +166,7 @@ void BirthDialog::updateSpells()
if (mCurrentBirthId.empty()) if (mCurrentBirthId.empty())
return; return;
MWSpellPtr spellWidget; Widgets::MWSpellPtr spellWidget;
const int lineHeight = 18; const int lineHeight = 18;
MyGUI::IntCoord coord(0, 0, mSpellArea->getWidth(), 18); MyGUI::IntCoord coord(0, 0, mSpellArea->getWidth(), 18);
@ -179,7 +177,7 @@ void BirthDialog::updateSpells()
store.get<ESM::BirthSign>().find(mCurrentBirthId); store.get<ESM::BirthSign>().find(mCurrentBirthId);
std::string texturePath = std::string("textures\\") + birth->mTexture; std::string texturePath = std::string("textures\\") + birth->mTexture;
fixTexturePath(texturePath); Widgets::fixTexturePath(texturePath);
mBirthImage->setImageTexture(texturePath); mBirthImage->setImageTexture(texturePath);
std::vector<std::string> abilities, powers, spells; std::vector<std::string> abilities, powers, spells;
@ -229,7 +227,7 @@ void BirthDialog::updateSpells()
for (std::vector<std::string>::const_iterator it = categories[category].spells.begin(); it != end; ++it) for (std::vector<std::string>::const_iterator it = categories[category].spells.begin(); it != end; ++it)
{ {
const std::string &spellId = *it; const std::string &spellId = *it;
spellWidget = mSpellArea->createWidget<MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("Spell") + boost::lexical_cast<std::string>(i)); spellWidget = mSpellArea->createWidget<Widgets::MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("Spell") + boost::lexical_cast<std::string>(i));
spellWidget->setSpellId(spellId); spellWidget->setSpellId(spellId);
mSpellItems.push_back(spellWidget); mSpellItems.push_back(spellWidget);
@ -237,11 +235,13 @@ void BirthDialog::updateSpells()
MyGUI::IntCoord spellCoord = coord; MyGUI::IntCoord spellCoord = coord;
spellCoord.height = 24; // TODO: This should be fetched from the skin somehow, or perhaps a widget in the layout as a template? spellCoord.height = 24; // TODO: This should be fetched from the skin somehow, or perhaps a widget in the layout as a template?
spellWidget->createEffectWidgets(mSpellItems, mSpellArea, spellCoord, (category == 0) ? MWEffectList::EF_Constant : 0); spellWidget->createEffectWidgets(mSpellItems, mSpellArea, spellCoord, (category == 0) ? Widgets::MWEffectList::EF_Constant : 0);
coord.top = spellCoord.top; coord.top = spellCoord.top;
++i; ++i;
} }
} }
} }
}
} }

View file

@ -12,13 +12,14 @@
#include "formatting.hpp" #include "formatting.hpp"
using namespace MWGui; namespace MWGui
{
BookWindow::BookWindow () BookWindow::BookWindow ()
: WindowBase("openmw_book.layout") : WindowBase("openmw_book.layout")
, mTakeButtonShow(true) , mTakeButtonShow(true)
, mTakeButtonAllowed(true) , mTakeButtonAllowed(true)
{ {
getWidget(mCloseButton, "CloseButton"); getWidget(mCloseButton, "CloseButton");
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked); mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked);
@ -38,20 +39,20 @@ BookWindow::BookWindow ()
getWidget(mRightPage, "RightPage"); getWidget(mRightPage, "RightPage");
center(); center();
} }
void BookWindow::clearPages() void BookWindow::clearPages()
{ {
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin(); for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
it!=mPages.end(); ++it) it!=mPages.end(); ++it)
{ {
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
} }
mPages.clear(); mPages.clear();
} }
void BookWindow::open (MWWorld::Ptr book) void BookWindow::open (MWWorld::Ptr book)
{ {
mBook = book; mBook = book;
clearPages(); clearPages();
@ -83,40 +84,40 @@ void BookWindow::open (MWWorld::Ptr book)
updatePages(); updatePages();
setTakeButtonShow(true); setTakeButtonShow(true);
} }
void BookWindow::setTakeButtonShow(bool show) void BookWindow::setTakeButtonShow(bool show)
{ {
mTakeButtonShow = show; mTakeButtonShow = show;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
} }
void BookWindow::setInventoryAllowed(bool allowed) void BookWindow::setInventoryAllowed(bool allowed)
{ {
mTakeButtonAllowed = allowed; mTakeButtonAllowed = allowed;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
} }
void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender) void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender)
{ {
// no 3d sounds because the object could be in a container. // no 3d sounds because the object could be in a container.
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book);
} }
void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender) void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack); MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack);
MWWorld::ActionTake take(mBook); MWWorld::ActionTake take(mBook);
take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book);
} }
void BookWindow::onNextPageButtonClicked (MyGUI::Widget* sender) void BookWindow::onNextPageButtonClicked (MyGUI::Widget* sender)
{ {
if ((mCurrentPage+1)*2 < mPages.size()) if ((mCurrentPage+1)*2 < mPages.size())
{ {
MWBase::Environment::get().getSoundManager()->playSound ("book page2", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book page2", 1.0, 1.0);
@ -125,10 +126,10 @@ void BookWindow::onNextPageButtonClicked (MyGUI::Widget* sender)
updatePages(); updatePages();
} }
} }
void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* sender) void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* sender)
{ {
if (mCurrentPage > 0) if (mCurrentPage > 0)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("book page", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book page", 1.0, 1.0);
@ -137,10 +138,10 @@ void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* sender)
updatePages(); updatePages();
} }
} }
void BookWindow::updatePages() void BookWindow::updatePages()
{ {
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) );
@ -156,4 +157,6 @@ void BookWindow::updatePages()
} }
++i; ++i;
} }
}
} }

View file

@ -5,8 +5,6 @@
#include "class.hpp" #include "class.hpp"
#include "birth.hpp" #include "birth.hpp"
#include "review.hpp" #include "review.hpp"
#include "dialogue.hpp"
#include "mode.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -45,9 +43,10 @@ namespace
}; };
} }
using namespace MWGui; namespace MWGui
{
CharacterCreation::CharacterCreation() CharacterCreation::CharacterCreation()
: mNameDialog(0) : mNameDialog(0)
, mRaceDialog(0) , mRaceDialog(0)
, mClassChoiceDialog(0) , mClassChoiceDialog(0)
@ -58,12 +57,12 @@ CharacterCreation::CharacterCreation()
, mBirthSignDialog(0) , mBirthSignDialog(0)
, mReviewDialog(0) , mReviewDialog(0)
, mGenerateClassStep(0) , mGenerateClassStep(0)
{ {
mCreationStage = CSE_NotStarted; mCreationStage = CSE_NotStarted;
} }
void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value) void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
{ {
if (mReviewDialog) if (mReviewDialog)
{ {
static const char *ids[] = static const char *ids[] =
@ -79,10 +78,10 @@ void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat
mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value); mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value);
} }
} }
} }
void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
if (mReviewDialog) if (mReviewDialog)
{ {
if (id == "HBar") if (id == "HBar")
@ -98,22 +97,22 @@ void CharacterCreation::setValue (const std::string& id, const MWMechanics::Dyna
mReviewDialog->setFatigue (value); mReviewDialog->setFatigue (value);
} }
} }
} }
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value) void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
{ {
if (mReviewDialog) if (mReviewDialog)
mReviewDialog->setSkillValue(parSkill, value); mReviewDialog->setSkillValue(parSkill, value);
} }
void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor) void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor)
{ {
if (mReviewDialog) if (mReviewDialog)
mReviewDialog->configureSkills(major, minor); mReviewDialog->configureSkills(major, minor);
} }
void CharacterCreation::spawnDialog(const char id) void CharacterCreation::spawnDialog(const char id)
{ {
switch (id) switch (id)
{ {
case GM_Name: case GM_Name:
@ -237,41 +236,41 @@ void CharacterCreation::spawnDialog(const char id)
mCreationStage = CSE_BirthSignChosen; mCreationStage = CSE_BirthSignChosen;
break; break;
} }
} }
void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<float>& value) void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerHealth = value; mPlayerHealth = value;
} }
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<float>& value) void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerMagicka = value; mPlayerMagicka = value;
} }
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<float>& value) void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerFatigue = value; mPlayerFatigue = value;
} }
void CharacterCreation::onReviewDialogDone(WindowBase* parWindow) void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
mReviewDialog = 0; mReviewDialog = 0;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
void CharacterCreation::onReviewDialogBack() void CharacterCreation::onReviewDialogBack()
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
mReviewDialog = 0; mReviewDialog = 0;
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth);
} }
void CharacterCreation::onReviewActivateDialog(int parDialog) void CharacterCreation::onReviewActivateDialog(int parDialog)
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
mReviewDialog = 0; mReviewDialog = 0;
mCreationStage = CSE_ReviewNext; mCreationStage = CSE_ReviewNext;
@ -292,10 +291,10 @@ void CharacterCreation::onReviewActivateDialog(int parDialog)
case ReviewDialog::BIRTHSIGN_DIALOG: case ReviewDialog::BIRTHSIGN_DIALOG:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth);
}; };
} }
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow) void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
{ {
if (mPickClassDialog) if (mPickClassDialog)
{ {
const std::string &classId = mPickClassDialog->getClassId(); const std::string &classId = mPickClassDialog->getClassId();
@ -329,10 +328,10 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
mCreationStage = CSE_ClassChosen; mCreationStage = CSE_ClassChosen;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
void CharacterCreation::onPickClassDialogBack() void CharacterCreation::onPickClassDialogBack()
{ {
if (mPickClassDialog) if (mPickClassDialog)
{ {
const std::string classId = mPickClassDialog->getClassId(); const std::string classId = mPickClassDialog->getClassId();
@ -344,10 +343,10 @@ void CharacterCreation::onPickClassDialogBack()
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
} }
void CharacterCreation::onClassChoice(int _index) void CharacterCreation::onClassChoice(int _index)
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog);
mClassChoiceDialog = 0; mClassChoiceDialog = 0;
@ -369,10 +368,10 @@ void CharacterCreation::onClassChoice(int _index)
break; break;
}; };
} }
void CharacterCreation::onNameDialogDone(WindowBase* parWindow) void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
{ {
if (mNameDialog) if (mNameDialog)
{ {
mPlayerName = mNameDialog->getTextInput(); mPlayerName = mNameDialog->getTextInput();
@ -397,10 +396,10 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
mCreationStage = CSE_NameChosen; mCreationStage = CSE_NameChosen;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
void CharacterCreation::onRaceDialogBack() void CharacterCreation::onRaceDialogBack()
{ {
if (mRaceDialog) if (mRaceDialog)
{ {
const ESM::NPC &data = mRaceDialog->getResult(); const ESM::NPC &data = mRaceDialog->getResult();
@ -419,10 +418,10 @@ void CharacterCreation::onRaceDialogBack()
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
} }
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
{ {
if (mRaceDialog) if (mRaceDialog)
{ {
const ESM::NPC &data = mRaceDialog->getResult(); const ESM::NPC &data = mRaceDialog->getResult();
@ -456,10 +455,10 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
mCreationStage = CSE_RaceChosen; mCreationStage = CSE_RaceChosen;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
{ {
if (mBirthSignDialog) if (mBirthSignDialog)
{ {
mPlayerBirthSignId = mBirthSignDialog->getBirthId(); mPlayerBirthSignId = mBirthSignDialog->getBirthId();
@ -479,10 +478,10 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
mCreationStage = CSE_BirthSignChosen; mCreationStage = CSE_BirthSignChosen;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
void CharacterCreation::onBirthSignDialogBack() void CharacterCreation::onBirthSignDialogBack()
{ {
if (mBirthSignDialog) if (mBirthSignDialog)
{ {
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId()); MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId());
@ -492,10 +491,10 @@ void CharacterCreation::onBirthSignDialogBack()
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
} }
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
{ {
if (mCreateClassDialog) if (mCreateClassDialog)
{ {
ESM::Class klass; ESM::Class klass;
@ -542,19 +541,19 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
mCreationStage = CSE_ClassChosen; mCreationStage = CSE_ClassChosen;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
void CharacterCreation::onCreateClassDialogBack() void CharacterCreation::onCreateClassDialogBack()
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
mCreateClassDialog = 0; mCreateClassDialog = 0;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
} }
void CharacterCreation::onClassQuestionChosen(int _index) void CharacterCreation::onClassQuestionChosen(int _index)
{ {
MWBase::Environment::get().getSoundManager()->stopSay(); MWBase::Environment::get().getSoundManager()->stopSay();
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassQuestionDialog);
@ -576,10 +575,10 @@ void CharacterCreation::onClassQuestionChosen(int _index)
++mGenerateClassSpecializations[2]; ++mGenerateClassSpecializations[2];
++mGenerateClassStep; ++mGenerateClassStep;
showClassQuestionDialog(); showClassQuestionDialog();
} }
void CharacterCreation::showClassQuestionDialog() void CharacterCreation::showClassQuestionDialog()
{ {
if (mGenerateClassStep == 10) if (mGenerateClassStep == 10)
{ {
static boost::array<ClassPoint, 23> classes = { { static boost::array<ClassPoint, 23> classes = { {
@ -669,10 +668,10 @@ void CharacterCreation::showClassQuestionDialog()
mGenerateClassQuestionDialog->setVisible(true); mGenerateClassQuestionDialog->setVisible(true);
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps(mGenerateClassStep).mSound); MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps(mGenerateClassStep).mSound);
} }
void CharacterCreation::onGenerateClassBack() void CharacterCreation::onGenerateClassBack()
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
mGenerateClassResultDialog = 0; mGenerateClassResultDialog = 0;
@ -680,10 +679,10 @@ void CharacterCreation::onGenerateClassBack()
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
} }
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
mGenerateClassResultDialog = 0; mGenerateClassResultDialog = 0;
@ -710,10 +709,10 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
mCreationStage = CSE_ClassChosen; mCreationStage = CSE_ClassChosen;
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
CharacterCreation::~CharacterCreation() CharacterCreation::~CharacterCreation()
{ {
delete mNameDialog; delete mNameDialog;
delete mRaceDialog; delete mRaceDialog;
delete mClassChoiceDialog; delete mClassChoiceDialog;
@ -723,4 +722,6 @@ CharacterCreation::~CharacterCreation()
delete mCreateClassDialog; delete mCreateClassDialog;
delete mBirthSignDialog; delete mBirthSignDialog;
delete mReviewDialog; delete mReviewDialog;
}
} }

View file

@ -1,11 +1,6 @@
#include "class.hpp" #include "class.hpp"
#include <iterator>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -16,13 +11,14 @@
#undef min #undef min
#undef max #undef max
using namespace MWGui; namespace MWGui
/* GenerateClassResultDialog */
GenerateClassResultDialog::GenerateClassResultDialog()
: WindowModal("openmw_chargen_generate_class_result.layout")
{ {
/* GenerateClassResultDialog */
GenerateClassResultDialog::GenerateClassResultDialog()
: WindowModal("openmw_chargen_generate_class_result.layout")
{
// Centre dialog // Centre dialog
center(); center();
@ -39,37 +35,37 @@ GenerateClassResultDialog::GenerateClassResultDialog()
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
} }
std::string GenerateClassResultDialog::getClassId() const std::string GenerateClassResultDialog::getClassId() const
{ {
return mClassName->getCaption(); return mClassName->getCaption();
} }
void GenerateClassResultDialog::setClassId(const std::string &classId) void GenerateClassResultDialog::setClassId(const std::string &classId)
{ {
mCurrentClassId = classId; mCurrentClassId = classId;
mClassImage->setImageTexture(std::string("textures\\levelup\\") + mCurrentClassId + ".dds"); mClassImage->setImageTexture(std::string("textures\\levelup\\") + mCurrentClassId + ".dds");
mClassName->setCaption(MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(mCurrentClassId)->mName); mClassName->setCaption(MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(mCurrentClassId)->mName);
} }
// widget controls // widget controls
void GenerateClassResultDialog::onOkClicked(MyGUI::Widget* _sender) void GenerateClassResultDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
eventDone(this); eventDone(this);
} }
void GenerateClassResultDialog::onBackClicked(MyGUI::Widget* _sender) void GenerateClassResultDialog::onBackClicked(MyGUI::Widget* _sender)
{ {
eventBack(); eventBack();
} }
/* PickClassDialog */ /* PickClassDialog */
PickClassDialog::PickClassDialog() PickClassDialog::PickClassDialog()
: WindowModal("openmw_chargen_class.layout") : WindowModal("openmw_chargen_class.layout")
{ {
// Centre dialog // Centre dialog
center(); center();
@ -103,10 +99,10 @@ PickClassDialog::PickClassDialog()
updateClasses(); updateClasses();
updateStats(); updateStats();
} }
void PickClassDialog::setNextButtonShow(bool shown) void PickClassDialog::setNextButtonShow(bool shown)
{ {
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
@ -114,18 +110,18 @@ void PickClassDialog::setNextButtonShow(bool shown)
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", ""));
else else
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
} }
void PickClassDialog::open() void PickClassDialog::open()
{ {
WindowModal::open (); WindowModal::open ();
updateClasses(); updateClasses();
updateStats(); updateStats();
} }
void PickClassDialog::setClassId(const std::string &classId) void PickClassDialog::setClassId(const std::string &classId)
{ {
mCurrentClassId = classId; mCurrentClassId = classId;
mClassList->setIndexSelected(MyGUI::ITEM_NONE); mClassList->setIndexSelected(MyGUI::ITEM_NONE);
size_t count = mClassList->getItemCount(); size_t count = mClassList->getItemCount();
@ -141,24 +137,24 @@ void PickClassDialog::setClassId(const std::string &classId)
} }
updateStats(); updateStats();
} }
// widget controls // widget controls
void PickClassDialog::onOkClicked(MyGUI::Widget* _sender) void PickClassDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
if(mClassList->getIndexSelected() == MyGUI::ITEM_NONE) if(mClassList->getIndexSelected() == MyGUI::ITEM_NONE)
return; return;
eventDone(this); eventDone(this);
} }
void PickClassDialog::onBackClicked(MyGUI::Widget* _sender) void PickClassDialog::onBackClicked(MyGUI::Widget* _sender)
{ {
eventBack(); eventBack();
} }
void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index) void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
{ {
if (_index == MyGUI::ITEM_NONE) if (_index == MyGUI::ITEM_NONE)
return; return;
@ -171,12 +167,12 @@ void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
mCurrentClassId = *classId; mCurrentClassId = *classId;
updateStats(); updateStats();
} }
// update widget content // update widget content
void PickClassDialog::updateClasses() void PickClassDialog::updateClasses()
{ {
mClassList->removeAllItems(); mClassList->removeAllItems();
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
@ -202,10 +198,10 @@ void PickClassDialog::updateClasses()
} }
++index; ++index;
} }
} }
void PickClassDialog::updateStats() void PickClassDialog::updateStats()
{ {
if (mCurrentClassId.empty()) if (mCurrentClassId.empty())
return; return;
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
@ -238,22 +234,22 @@ void PickClassDialog::updateStats()
} }
mClassImage->setImageTexture(std::string("textures\\levelup\\") + mCurrentClassId + ".dds"); mClassImage->setImageTexture(std::string("textures\\levelup\\") + mCurrentClassId + ".dds");
} }
/* InfoBoxDialog */ /* InfoBoxDialog */
void InfoBoxDialog::fitToText(MyGUI::TextBox* widget) void InfoBoxDialog::fitToText(MyGUI::TextBox* widget)
{ {
MyGUI::IntCoord inner = widget->getTextRegion(); MyGUI::IntCoord inner = widget->getTextRegion();
MyGUI::IntCoord outer = widget->getCoord(); MyGUI::IntCoord outer = widget->getCoord();
MyGUI::IntSize size = widget->getTextSize(); MyGUI::IntSize size = widget->getTextSize();
size.width += outer.width - inner.width; size.width += outer.width - inner.width;
size.height += outer.height - inner.height; size.height += outer.height - inner.height;
widget->setSize(size); widget->setSize(size);
} }
void InfoBoxDialog::layoutVertically(MyGUI::Widget* widget, int margin) void InfoBoxDialog::layoutVertically(MyGUI::Widget* widget, int margin)
{ {
size_t count = widget->getChildCount(); size_t count = widget->getChildCount();
int pos = 0; int pos = 0;
pos += margin; pos += margin;
@ -270,34 +266,34 @@ void InfoBoxDialog::layoutVertically(MyGUI::Widget* widget, int margin)
} }
width += margin*2; width += margin*2;
widget->setSize(width, pos); widget->setSize(width, pos);
} }
InfoBoxDialog::InfoBoxDialog() InfoBoxDialog::InfoBoxDialog()
: WindowModal("openmw_infobox.layout") : WindowModal("openmw_infobox.layout")
, mCurrentButton(-1) , mCurrentButton(-1)
{ {
getWidget(mTextBox, "TextBox"); getWidget(mTextBox, "TextBox");
getWidget(mText, "Text"); getWidget(mText, "Text");
mText->getSubWidgetText()->setWordWrap(true); mText->getSubWidgetText()->setWordWrap(true);
getWidget(mButtonBar, "ButtonBar"); getWidget(mButtonBar, "ButtonBar");
center(); center();
} }
void InfoBoxDialog::setText(const std::string &str) void InfoBoxDialog::setText(const std::string &str)
{ {
mText->setCaption(str); mText->setCaption(str);
mTextBox->setVisible(!str.empty()); mTextBox->setVisible(!str.empty());
fitToText(mText); fitToText(mText);
} }
std::string InfoBoxDialog::getText() const std::string InfoBoxDialog::getText() const
{ {
return mText->getCaption(); return mText->getCaption();
} }
void InfoBoxDialog::setButtons(ButtonList &buttons) void InfoBoxDialog::setButtons(ButtonList &buttons)
{ {
for (std::vector<MyGUI::Button*>::iterator it = this->mButtons.begin(); it != this->mButtons.end(); ++it) for (std::vector<MyGUI::Button*>::iterator it = this->mButtons.begin(); it != this->mButtons.end(); ++it)
{ {
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
@ -320,10 +316,10 @@ void InfoBoxDialog::setButtons(ButtonList &buttons)
coord.top += button->getHeight(); coord.top += button->getHeight();
this->mButtons.push_back(button); this->mButtons.push_back(button);
} }
} }
void InfoBoxDialog::open() void InfoBoxDialog::open()
{ {
WindowModal::open(); WindowModal::open();
// Fix layout // Fix layout
layoutVertically(mTextBox, 4); layoutVertically(mTextBox, 4);
@ -331,15 +327,15 @@ void InfoBoxDialog::open()
layoutVertically(mMainWidget, 4 + 6); layoutVertically(mMainWidget, 4 + 6);
center(); center();
} }
int InfoBoxDialog::getChosenButton() const int InfoBoxDialog::getChosenButton() const
{ {
return mCurrentButton; 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();
int i = 0; int i = 0;
for (std::vector<MyGUI::Button*>::const_iterator it = mButtons.begin(); it != end; ++it) for (std::vector<MyGUI::Button*>::const_iterator it = mButtons.begin(); it != end; ++it)
@ -352,13 +348,13 @@ void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender)
} }
++i; ++i;
} }
} }
/* ClassChoiceDialog */ /* ClassChoiceDialog */
ClassChoiceDialog::ClassChoiceDialog() ClassChoiceDialog::ClassChoiceDialog()
: InfoBoxDialog() : InfoBoxDialog()
{ {
setText(""); setText("");
ButtonList buttons; ButtonList buttons;
buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu1", "")); buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu1", ""));
@ -366,17 +362,17 @@ ClassChoiceDialog::ClassChoiceDialog()
buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu3", "")); buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sClassChoiceMenu3", ""));
buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBack", "")); buttons.push_back(MWBase::Environment::get().getWindowManager()->getGameSettingString("sBack", ""));
setButtons(buttons); setButtons(buttons);
} }
/* CreateClassDialog */ /* CreateClassDialog */
CreateClassDialog::CreateClassDialog() CreateClassDialog::CreateClassDialog()
: WindowModal("openmw_chargen_create_class.layout") : WindowModal("openmw_chargen_create_class.layout")
, mSpecDialog(NULL) , mSpecDialog(NULL)
, mAttribDialog(NULL) , mAttribDialog(NULL)
, mSkillDialog(NULL) , mSkillDialog(NULL)
, mDescDialog(NULL) , mDescDialog(NULL)
{ {
// Centre dialog // Centre dialog
center(); center();
@ -444,18 +440,18 @@ CreateClassDialog::CreateClassDialog()
setSpecialization(0); setSpecialization(0);
update(); update();
} }
CreateClassDialog::~CreateClassDialog() CreateClassDialog::~CreateClassDialog()
{ {
delete mSpecDialog; delete mSpecDialog;
delete mAttribDialog; delete mAttribDialog;
delete mSkillDialog; delete mSkillDialog;
delete mDescDialog; delete mDescDialog;
} }
void CreateClassDialog::update() void CreateClassDialog::update()
{ {
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
{ {
ToolTips::createSkillToolTip(mMajorSkill[i], mMajorSkill[i]->getSkillId()); ToolTips::createSkillToolTip(mMajorSkill[i], mMajorSkill[i]->getSkillId());
@ -464,53 +460,53 @@ void CreateClassDialog::update()
ToolTips::createAttributeToolTip(mFavoriteAttribute0, mFavoriteAttribute0->getAttributeId()); ToolTips::createAttributeToolTip(mFavoriteAttribute0, mFavoriteAttribute0->getAttributeId());
ToolTips::createAttributeToolTip(mFavoriteAttribute1, mFavoriteAttribute1->getAttributeId()); ToolTips::createAttributeToolTip(mFavoriteAttribute1, mFavoriteAttribute1->getAttributeId());
} }
std::string CreateClassDialog::getName() const std::string CreateClassDialog::getName() const
{ {
return mEditName->getOnlyText(); return mEditName->getOnlyText();
} }
std::string CreateClassDialog::getDescription() const std::string CreateClassDialog::getDescription() const
{ {
return mDescription; return mDescription;
} }
ESM::Class::Specialization CreateClassDialog::getSpecializationId() const ESM::Class::Specialization CreateClassDialog::getSpecializationId() const
{ {
return mSpecializationId; return mSpecializationId;
} }
std::vector<int> CreateClassDialog::getFavoriteAttributes() const std::vector<int> CreateClassDialog::getFavoriteAttributes() const
{ {
std::vector<int> v; std::vector<int> v;
v.push_back(mFavoriteAttribute0->getAttributeId()); v.push_back(mFavoriteAttribute0->getAttributeId());
v.push_back(mFavoriteAttribute1->getAttributeId()); v.push_back(mFavoriteAttribute1->getAttributeId());
return v; return v;
} }
std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMajorSkills() const std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMajorSkills() const
{ {
std::vector<ESM::Skill::SkillEnum> v; std::vector<ESM::Skill::SkillEnum> v;
for(int i = 0; i < 5; i++) for(int i = 0; i < 5; i++)
{ {
v.push_back(mMajorSkill[i]->getSkillId()); v.push_back(mMajorSkill[i]->getSkillId());
} }
return v; return v;
} }
std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMinorSkills() const std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMinorSkills() const
{ {
std::vector<ESM::Skill::SkillEnum> v; std::vector<ESM::Skill::SkillEnum> v;
for(int i=0; i < 5; i++) for(int i=0; i < 5; i++)
{ {
v.push_back(mMinorSkill[i]->getSkillId()); v.push_back(mMinorSkill[i]->getSkillId());
} }
return v; return v;
} }
void CreateClassDialog::setNextButtonShow(bool shown) void CreateClassDialog::setNextButtonShow(bool shown)
{ {
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
@ -518,12 +514,12 @@ void CreateClassDialog::setNextButtonShow(bool shown)
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", ""));
else else
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
} }
// widget controls // widget controls
void CreateClassDialog::onDialogCancel() void CreateClassDialog::onDialogCancel()
{ {
MWBase::Environment::get().getWindowManager()->removeDialog(mSpecDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mSpecDialog);
mSpecDialog = 0; mSpecDialog = 0;
@ -535,28 +531,28 @@ void CreateClassDialog::onDialogCancel()
MWBase::Environment::get().getWindowManager()->removeDialog(mDescDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mDescDialog);
mDescDialog = 0; mDescDialog = 0;
} }
void CreateClassDialog::onSpecializationClicked(MyGUI::Widget* _sender) void CreateClassDialog::onSpecializationClicked(MyGUI::Widget* _sender)
{ {
delete mSpecDialog; delete mSpecDialog;
mSpecDialog = new SelectSpecializationDialog(); mSpecDialog = new SelectSpecializationDialog();
mSpecDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mSpecDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
mSpecDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected); mSpecDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationSelected);
mSpecDialog->setVisible(true); mSpecDialog->setVisible(true);
} }
void CreateClassDialog::onSpecializationSelected() void CreateClassDialog::onSpecializationSelected()
{ {
mSpecializationId = mSpecDialog->getSpecializationId(); mSpecializationId = mSpecDialog->getSpecializationId();
setSpecialization(mSpecializationId); setSpecialization(mSpecializationId);
MWBase::Environment::get().getWindowManager()->removeDialog(mSpecDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mSpecDialog);
mSpecDialog = 0; mSpecDialog = 0;
} }
void CreateClassDialog::setSpecialization(int id) void CreateClassDialog::setSpecialization(int id)
{ {
mSpecializationId = (ESM::Class::Specialization) id; mSpecializationId = (ESM::Class::Specialization) id;
static const char *specIds[3] = { static const char *specIds[3] = {
"sSpecializationCombat", "sSpecializationCombat",
@ -566,20 +562,20 @@ void CreateClassDialog::setSpecialization(int id)
std::string specName = MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[mSpecializationId], specIds[mSpecializationId]); std::string specName = MWBase::Environment::get().getWindowManager()->getGameSettingString(specIds[mSpecializationId], specIds[mSpecializationId]);
mSpecializationName->setCaption(specName); mSpecializationName->setCaption(specName);
ToolTips::createSpecializationToolTip(mSpecializationName, specName, mSpecializationId); ToolTips::createSpecializationToolTip(mSpecializationName, specName, mSpecializationId);
} }
void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender)
{ {
delete mAttribDialog; delete mAttribDialog;
mAttribDialog = new SelectAttributeDialog(); mAttribDialog = new SelectAttributeDialog();
mAffectedAttribute = _sender; mAffectedAttribute = _sender;
mAttribDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mAttribDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
mAttribDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected); mAttribDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onAttributeSelected);
mAttribDialog->setVisible(true); mAttribDialog->setVisible(true);
} }
void CreateClassDialog::onAttributeSelected() void CreateClassDialog::onAttributeSelected()
{ {
ESM::Attribute::AttributeID id = mAttribDialog->getAttributeId(); ESM::Attribute::AttributeID id = mAttribDialog->getAttributeId();
if (mAffectedAttribute == mFavoriteAttribute0) if (mAffectedAttribute == mFavoriteAttribute0)
{ {
@ -596,20 +592,20 @@ void CreateClassDialog::onAttributeSelected()
mAttribDialog = 0; mAttribDialog = 0;
update(); update();
} }
void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender)
{ {
delete mSkillDialog; delete mSkillDialog;
mSkillDialog = new SelectSkillDialog(); mSkillDialog = new SelectSkillDialog();
mAffectedSkill = _sender; mAffectedSkill = _sender;
mSkillDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); mSkillDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
mSkillDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected); mSkillDialog->eventItemSelected += MyGUI::newDelegate(this, &CreateClassDialog::onSkillSelected);
mSkillDialog->setVisible(true); mSkillDialog->setVisible(true);
} }
void CreateClassDialog::onSkillSelected() void CreateClassDialog::onSkillSelected()
{ {
ESM::Skill::SkillEnum id = mSkillDialog->getSkillId(); ESM::Skill::SkillEnum id = mSkillDialog->getSkillId();
// Avoid duplicate skills by swapping any skill field that matches the selected one // Avoid duplicate skills by swapping any skill field that matches the selected one
@ -629,40 +625,40 @@ void CreateClassDialog::onSkillSelected()
MWBase::Environment::get().getWindowManager()->removeDialog(mSkillDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mSkillDialog);
mSkillDialog = 0; mSkillDialog = 0;
update(); update();
} }
void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender)
{ {
mDescDialog = new DescriptionDialog(); mDescDialog = new DescriptionDialog();
mDescDialog->setTextInput(mDescription); mDescDialog->setTextInput(mDescription);
mDescDialog->eventDone += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered); mDescDialog->eventDone += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionEntered);
mDescDialog->setVisible(true); mDescDialog->setVisible(true);
} }
void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow) void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow)
{ {
mDescription = mDescDialog->getTextInput(); mDescription = mDescDialog->getTextInput();
MWBase::Environment::get().getWindowManager()->removeDialog(mDescDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mDescDialog);
mDescDialog = 0; mDescDialog = 0;
} }
void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender) void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
if(getName().size() <= 0) if(getName().size() <= 0)
return; return;
eventDone(this); eventDone(this);
} }
void CreateClassDialog::onBackClicked(MyGUI::Widget* _sender) void CreateClassDialog::onBackClicked(MyGUI::Widget* _sender)
{ {
eventBack(); eventBack();
} }
/* SelectSpecializationDialog */ /* SelectSpecializationDialog */
SelectSpecializationDialog::SelectSpecializationDialog() SelectSpecializationDialog::SelectSpecializationDialog()
: WindowModal("openmw_chargen_select_specialization.layout") : WindowModal("openmw_chargen_select_specialization.layout")
{ {
// Centre dialog // Centre dialog
center(); center();
@ -691,16 +687,16 @@ SelectSpecializationDialog::SelectSpecializationDialog()
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", "")); cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
} }
SelectSpecializationDialog::~SelectSpecializationDialog() SelectSpecializationDialog::~SelectSpecializationDialog()
{ {
} }
// widget controls // widget controls
void SelectSpecializationDialog::onSpecializationClicked(MyGUI::Widget* _sender) void SelectSpecializationDialog::onSpecializationClicked(MyGUI::Widget* _sender)
{ {
if (_sender == mSpecialization0) if (_sender == mSpecialization0)
mSpecializationId = ESM::Class::Combat; mSpecializationId = ESM::Class::Combat;
else if (_sender == mSpecialization1) else if (_sender == mSpecialization1)
@ -711,18 +707,18 @@ void SelectSpecializationDialog::onSpecializationClicked(MyGUI::Widget* _sender)
return; return;
eventItemSelected(); eventItemSelected();
} }
void SelectSpecializationDialog::onCancelClicked(MyGUI::Widget* _sender) void SelectSpecializationDialog::onCancelClicked(MyGUI::Widget* _sender)
{ {
eventCancel(); eventCancel();
} }
/* SelectAttributeDialog */ /* SelectAttributeDialog */
SelectAttributeDialog::SelectAttributeDialog() SelectAttributeDialog::SelectAttributeDialog()
: WindowModal("openmw_chargen_select_attribute.layout") : WindowModal("openmw_chargen_select_attribute.layout")
{ {
// Centre dialog // Centre dialog
center(); center();
@ -743,32 +739,32 @@ SelectAttributeDialog::SelectAttributeDialog()
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", "")); cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
} }
SelectAttributeDialog::~SelectAttributeDialog() SelectAttributeDialog::~SelectAttributeDialog()
{ {
} }
// widget controls // widget controls
void SelectAttributeDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) void SelectAttributeDialog::onAttributeClicked(Widgets::MWAttributePtr _sender)
{ {
// TODO: Change MWAttribute to set and get AttributeID enum instead of int // TODO: Change MWAttribute to set and get AttributeID enum instead of int
mAttributeId = static_cast<ESM::Attribute::AttributeID>(_sender->getAttributeId()); mAttributeId = static_cast<ESM::Attribute::AttributeID>(_sender->getAttributeId());
eventItemSelected(); eventItemSelected();
} }
void SelectAttributeDialog::onCancelClicked(MyGUI::Widget* _sender) void SelectAttributeDialog::onCancelClicked(MyGUI::Widget* _sender)
{ {
eventCancel(); eventCancel();
} }
/* SelectSkillDialog */ /* SelectSkillDialog */
SelectSkillDialog::SelectSkillDialog() SelectSkillDialog::SelectSkillDialog()
: WindowModal("openmw_chargen_select_skill.layout") : WindowModal("openmw_chargen_select_skill.layout")
{ {
// Centre dialog // Centre dialog
center(); center();
@ -835,30 +831,30 @@ SelectSkillDialog::SelectSkillDialog()
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", "")); cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
} }
SelectSkillDialog::~SelectSkillDialog() SelectSkillDialog::~SelectSkillDialog()
{ {
} }
// widget controls // widget controls
void SelectSkillDialog::onSkillClicked(Widgets::MWSkillPtr _sender) void SelectSkillDialog::onSkillClicked(Widgets::MWSkillPtr _sender)
{ {
mSkillId = _sender->getSkillId(); mSkillId = _sender->getSkillId();
eventItemSelected(); eventItemSelected();
} }
void SelectSkillDialog::onCancelClicked(MyGUI::Widget* _sender) void SelectSkillDialog::onCancelClicked(MyGUI::Widget* _sender)
{ {
eventCancel(); eventCancel();
} }
/* DescriptionDialog */ /* DescriptionDialog */
DescriptionDialog::DescriptionDialog() DescriptionDialog::DescriptionDialog()
: WindowModal("openmw_chargen_class_description.layout") : WindowModal("openmw_chargen_class_description.layout")
{ {
// Centre dialog // Centre dialog
center(); center();
@ -871,15 +867,17 @@ DescriptionDialog::DescriptionDialog()
// Make sure the edit box has focus // Make sure the edit box has focus
MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
DescriptionDialog::~DescriptionDialog() DescriptionDialog::~DescriptionDialog()
{ {
} }
// widget controls // widget controls
void DescriptionDialog::onOkClicked(MyGUI::Widget* _sender) void DescriptionDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
eventDone(this); eventDone(this);
}
} }

View file

@ -2,7 +2,6 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/dialoguemanager.hpp" #include "../mwbase/dialoguemanager.hpp"

View file

@ -1,10 +1,5 @@
#include "confirmationdialog.hpp" #include "confirmationdialog.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWGui namespace MWGui
{ {
ConfirmationDialog::ConfirmationDialog() : ConfirmationDialog::ConfirmationDialog() :

View file

@ -1,13 +1,7 @@
#include "console.hpp" #include "console.hpp"
#include <algorithm>
#include <fstream>
#include <components/compiler/exception.hpp> #include <components/compiler/exception.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwscript/extensions.hpp" #include "../mwscript/extensions.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -284,16 +278,15 @@ namespace MWGui
std::string Console::complete( std::string input, std::vector<std::string> &matches ) std::string Console::complete( std::string input, std::vector<std::string> &matches )
{ {
using namespace std; std::string output = input;
string output=input; std::string tmp = input;
string tmp=input;
bool has_front_quote = false; bool has_front_quote = false;
/* Does the input string contain things that don't have to be completed? If yes erase them. */ /* Does the input string contain things that don't have to be completed? If yes erase them. */
/* Are there quotation marks? */ /* Are there quotation marks? */
if( tmp.find('"') != string::npos ) { if( tmp.find('"') != std::string::npos ) {
int numquotes=0; int numquotes=0;
for(string::iterator it=tmp.begin(); it < tmp.end(); ++it) { for(std::string::iterator it=tmp.begin(); it < tmp.end(); ++it) {
if( *it == '"' ) if( *it == '"' )
numquotes++; numquotes++;
} }
@ -305,7 +298,7 @@ namespace MWGui
} }
else { else {
size_t pos; size_t pos;
if( ( ((pos = tmp.rfind(' ')) != string::npos ) ) && ( pos > tmp.rfind('"') ) ) { if( ( ((pos = tmp.rfind(' ')) != std::string::npos ) ) && ( pos > tmp.rfind('"') ) ) {
tmp.erase( 0, tmp.rfind(' ')+1); tmp.erase( 0, tmp.rfind(' ')+1);
} }
else { else {
@ -317,7 +310,7 @@ namespace MWGui
/* No quotation marks. Are there spaces?*/ /* No quotation marks. Are there spaces?*/
else { else {
size_t rpos; size_t rpos;
if( (rpos=tmp.rfind(' ')) != string::npos ) { if( (rpos=tmp.rfind(' ')) != std::string::npos ) {
if( rpos == 0 ) { if( rpos == 0 ) {
tmp.clear(); tmp.clear();
} }
@ -336,7 +329,7 @@ namespace MWGui
} }
/* Iterate through the vector. */ /* Iterate through the vector. */
for(vector<string>::iterator it=mNames.begin(); it < mNames.end();++it) { for(std::vector<std::string>::iterator it=mNames.begin(); it < mNames.end();++it) {
bool string_different=false; bool string_different=false;
/* Is the string shorter than the input string? If yes skip it. */ /* Is the string shorter than the input string? If yes skip it. */
@ -344,7 +337,7 @@ namespace MWGui
continue; continue;
/* Is the beginning of the string different from the input string? If yes skip it. */ /* Is the beginning of the string different from the input string? If yes skip it. */
for( string::iterator iter=tmp.begin(), iter2=(*it).begin(); iter < tmp.end();iter++, iter2++) { for( std::string::iterator iter=tmp.begin(), iter2=(*it).begin(); iter < tmp.end();iter++, iter2++) {
if( tolower(*iter) != tolower(*iter2) ) { if( tolower(*iter) != tolower(*iter2) ) {
string_different=true; string_different=true;
break; break;
@ -367,24 +360,24 @@ namespace MWGui
/* Only one match. We're done. */ /* Only one match. We're done. */
if( matches.size() == 1 ) { if( matches.size() == 1 ) {
/* Adding quotation marks when the input string started with a quotation mark or has spaces in it*/ /* Adding quotation marks when the input string started with a quotation mark or has spaces in it*/
if( ( matches.front().find(' ') != string::npos ) ) { if( ( matches.front().find(' ') != std::string::npos ) ) {
if( !has_front_quote ) if( !has_front_quote )
output.append(string("\"")); output.append(std::string("\""));
return output.append(matches.front() + string("\" ")); return output.append(matches.front() + std::string("\" "));
} }
else if( has_front_quote ) { else if( has_front_quote ) {
return output.append(matches.front() + string("\" ")); return output.append(matches.front() + std::string("\" "));
} }
else { else {
return output.append(matches.front() + string(" ")); return output.append(matches.front() + std::string(" "));
} }
} }
/* Check if all matching strings match further than input. If yes complete to this match. */ /* Check if all matching strings match further than input. If yes complete to this match. */
int i = tmp.length(); int i = tmp.length();
for(string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); iter++, i++) { for(std::string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); iter++, i++) {
for(vector<string>::iterator it=matches.begin(); it < matches.end();++it) { for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end();++it) {
if( tolower((*it)[i]) != tolower(*iter) ) { if( tolower((*it)[i]) != tolower(*iter) ) {
/* Append the longest match to the end of the output string*/ /* Append the longest match to the end of the output string*/
output.append(matches.front().substr( 0, i)); output.append(matches.front().substr( 0, i));

View file

@ -1,11 +1,5 @@
#include "container.hpp" #include "container.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <iostream>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -13,23 +7,13 @@
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwclass/container.hpp"
#include "widgets.hpp"
#include "countdialog.hpp" #include "countdialog.hpp"
#include "tradewindow.hpp" #include "tradewindow.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
using namespace MWGui;
using namespace Widgets;
namespace namespace
{ {
bool compareType(std::string type1, std::string type2) bool compareType(std::string type1, std::string type2)
@ -80,30 +64,32 @@ namespace
} }
} }
namespace MWGui
{
ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) ContainerBase::ContainerBase(DragAndDrop* dragAndDrop)
: mDragAndDrop(dragAndDrop) : mDragAndDrop(dragAndDrop)
, mFilter(ContainerBase::Filter_All) , mFilter(ContainerBase::Filter_All)
, mDisplayEquippedItems(true) , mDisplayEquippedItems(true)
, mHighlightEquippedItems(true) , mHighlightEquippedItems(true)
{ {
} }
void ContainerBase::setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView) void ContainerBase::setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView)
{ {
mContainerWidget = containerWidget; mContainerWidget = containerWidget;
mItemView = itemView; mItemView = itemView;
mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked); mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked);
mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel); mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel);
} }
ContainerBase::~ContainerBase() ContainerBase::~ContainerBase()
{ {
} }
void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
{ {
mSelectedItem = _sender; mSelectedItem = _sender;
if (mDragAndDrop && !isTrading()) if (mDragAndDrop && !isTrading())
@ -194,10 +180,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
{ {
onSelectedItemImpl(*_sender->getUserData<MWWorld::Ptr>()); onSelectedItemImpl(*_sender->getUserData<MWWorld::Ptr>());
} }
} }
void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count)
{ {
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>(); MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
if (isInventory()) if (isInventory())
@ -217,10 +203,10 @@ void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count)
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
drawItems(); drawItems();
} }
void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) void ContainerBase::sellItem(MyGUI::Widget* _sender, int count)
{ {
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>(); MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
if (isInventory()) if (isInventory())
@ -240,10 +226,10 @@ void ContainerBase::sellItem(MyGUI::Widget* _sender, int count)
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
drawItems(); drawItems();
} }
void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count) void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count)
{ {
mDragAndDrop->mIsOnDragAndDrop = true; mDragAndDrop->mIsOnDragAndDrop = true;
mSelectedItem->detachFromWidget(); mSelectedItem->detachFromWidget();
mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget); mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget);
@ -266,10 +252,10 @@ void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count)
drawItems(); drawItems();
MWBase::Environment::get().getWindowManager()->setDragDrop(true); MWBase::Environment::get().getWindowManager()->setDragDrop(true);
} }
void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
{ {
if (mDragAndDrop == NULL) return; if (mDragAndDrop == NULL) return;
if(mDragAndDrop->mIsOnDragAndDrop) //drop item here if(mDragAndDrop->mIsOnDragAndDrop) //drop item here
@ -343,29 +329,29 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
std::string sound = MWWorld::Class::get(object).getDownSoundId(object); std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
} }
} }
void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel) void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{ {
if (mItemView->getViewOffset().left + _rel*0.3 > 0) if (mItemView->getViewOffset().left + _rel*0.3 > 0)
mItemView->setViewOffset(MyGUI::IntPoint(0, 0)); mItemView->setViewOffset(MyGUI::IntPoint(0, 0));
else else
mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0)); mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0));
} }
void ContainerBase::setFilter(int filter) void ContainerBase::setFilter(int filter)
{ {
mFilter = filter; mFilter = filter;
drawItems(); drawItems();
} }
void ContainerBase::openContainer(MWWorld::Ptr container) void ContainerBase::openContainer(MWWorld::Ptr container)
{ {
mPtr = container; mPtr = container;
} }
void ContainerBase::drawItems() void ContainerBase::drawItems()
{ {
while (mContainerWidget->getChildCount()) while (mContainerWidget->getChildCount())
{ {
MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0));
@ -570,28 +556,28 @@ void ContainerBase::drawItems()
mContainerWidget->setSize(size); mContainerWidget->setSize(size);
notifyContentChanged(); notifyContentChanged();
} }
std::string ContainerBase::getCountString(const int count) std::string ContainerBase::getCountString(const int count)
{ {
if (count == 1) if (count == 1)
return ""; return "";
if (count > 9999) if (count > 9999)
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k"; return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
else else
return boost::lexical_cast<std::string>(count); return boost::lexical_cast<std::string>(count);
} }
void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count)
{ {
int origCount = item.getRefData().getCount(); int origCount = item.getRefData().getCount();
item.getRefData().setCount(count); item.getRefData().setCount(count);
MWWorld::ContainerStoreIterator it = mBoughtItems.add(item); MWWorld::ContainerStoreIterator it = mBoughtItems.add(item);
item.getRefData().setCount(origCount - count); item.getRefData().setCount(origCount - count);
} }
void ContainerBase::addItem(MWWorld::Ptr item, int count) void ContainerBase::addItem(MWWorld::Ptr item, int count)
{ {
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
int origCount = item.getRefData().getCount(); int origCount = item.getRefData().getCount();
@ -600,28 +586,28 @@ void ContainerBase::addItem(MWWorld::Ptr item, int count)
MWWorld::ContainerStoreIterator it = containerStore.add(item); MWWorld::ContainerStoreIterator it = containerStore.add(item);
item.getRefData().setCount(origCount - count); item.getRefData().setCount(origCount - count);
} }
void ContainerBase::transferBoughtItems() void ContainerBase::transferBoughtItems()
{ {
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
{ {
containerStore.add(*it); containerStore.add(*it);
} }
} }
void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store) void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store)
{ {
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
{ {
store.add(*it); store.add(*it);
} }
} }
std::vector<MWWorld::Ptr> ContainerBase::getEquippedItems() std::vector<MWWorld::Ptr> ContainerBase::getEquippedItems()
{ {
if (mPtr.getTypeName() != typeid(ESM::NPC).name()) if (mPtr.getTypeName() != typeid(ESM::NPC).name())
return std::vector<MWWorld::Ptr>(); return std::vector<MWWorld::Ptr>();
@ -639,20 +625,20 @@ std::vector<MWWorld::Ptr> ContainerBase::getEquippedItems()
} }
return items; return items;
} }
MWWorld::ContainerStore& ContainerBase::getContainerStore() MWWorld::ContainerStore& ContainerBase::getContainerStore()
{ {
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
return store; return store;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop)
: ContainerBase(dragAndDrop) : ContainerBase(dragAndDrop)
, WindowBase("openmw_container_window.layout") , WindowBase("openmw_container_window.layout")
{ {
getWidget(mDisposeCorpseButton, "DisposeCorpseButton"); getWidget(mDisposeCorpseButton, "DisposeCorpseButton");
getWidget(mTakeButton, "TakeButton"); getWidget(mTakeButton, "TakeButton");
getWidget(mCloseButton, "CloseButton"); getWidget(mCloseButton, "CloseButton");
@ -670,19 +656,19 @@ ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop)
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize); static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize);
setCoord(200,0,600,300); setCoord(200,0,600,300);
} }
ContainerWindow::~ContainerWindow() ContainerWindow::~ContainerWindow()
{ {
} }
void ContainerWindow::onWindowResize(MyGUI::Window* window) void ContainerWindow::onWindowResize(MyGUI::Window* window)
{ {
drawItems(); drawItems();
} }
void ContainerWindow::open(MWWorld::Ptr container, bool loot) void ContainerWindow::open(MWWorld::Ptr container, bool loot)
{ {
mDisplayEquippedItems = true; mDisplayEquippedItems = true;
mHighlightEquippedItems = false; mHighlightEquippedItems = false;
if (container.getTypeName() == typeid(ESM::NPC).name() && !loot) if (container.getTypeName() == typeid(ESM::NPC).name() && !loot)
@ -696,18 +682,18 @@ void ContainerWindow::open(MWWorld::Ptr container, bool loot)
openContainer(container); openContainer(container);
setTitle(MWWorld::Class::get(container).getName(container)); setTitle(MWWorld::Class::get(container).getName(container));
drawItems(); drawItems();
} }
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
{ {
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{ {
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
} }
} }
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
{ {
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{ {
// transfer everything into the player's inventory // transfer everything into the player's inventory
@ -741,10 +727,10 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
} }
} }
void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender) void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender)
{ {
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{ {
onTakeAllButtonClicked(mTakeButton); onTakeAllButtonClicked(mTakeButton);
@ -757,9 +743,11 @@ void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender)
mPtr = MWWorld::Ptr(); mPtr = MWWorld::Ptr();
} }
} }
void ContainerWindow::onReferenceUnavailable() void ContainerWindow::onReferenceUnavailable()
{ {
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
} }

View file

@ -2,9 +2,6 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWGui namespace MWGui
{ {
CountDialog::CountDialog() : CountDialog::CountDialog() :

View file

@ -2,13 +2,11 @@
#include <MyGUI_PointerManager.h> #include <MyGUI_PointerManager.h>
#include <MyGUI_InputManager.h> #include <MyGUI_InputManager.h>
#include <MyGUI_RenderManager.h>
#include <MyGUI_RotatingSkin.h> #include <MyGUI_RotatingSkin.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <OgreMath.h> #include <OgreMath.h>
namespace MWGui namespace MWGui
{ {

View file

@ -1,18 +1,11 @@
#include "dialogue.hpp" #include "dialogue.hpp"
#include <iostream>
#include <iterator>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
@ -26,38 +19,37 @@
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "travelwindow.hpp" #include "travelwindow.hpp"
using namespace MWGui;
using namespace Widgets;
/** /**
*Copied from the internet. *Copied from the internet.
*/ */
namespace { namespace
std::string lower_string(const std::string& str)
{ {
std::string lower_string(const std::string& str)
{
std::string lowerCase = Misc::StringUtils::lowerCase (str); std::string lowerCase = Misc::StringUtils::lowerCase (str);
return lowerCase; return lowerCase;
} }
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos) std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
{ {
return lower_string(str).find(lower_string(substr),pos); return lower_string(str).find(lower_string(substr),pos);
} }
bool sortByLength (const std::string& left, const std::string& right) bool sortByLength (const std::string& left, const std::string& right)
{ {
return left.size() > right.size(); return left.size() > right.size();
} }
} }
namespace MWGui
PersuasionDialog::PersuasionDialog()
: WindowModal("openmw_persuasion_dialog.layout")
{ {
PersuasionDialog::PersuasionDialog()
: WindowModal("openmw_persuasion_dialog.layout")
{
getWidget(mCancelButton, "CancelButton"); getWidget(mCancelButton, "CancelButton");
getWidget(mAdmireButton, "AdmireButton"); getWidget(mAdmireButton, "AdmireButton");
getWidget(mIntimidateButton, "IntimidateButton"); getWidget(mIntimidateButton, "IntimidateButton");
@ -74,15 +66,15 @@ PersuasionDialog::PersuasionDialog()
mBribe10Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); mBribe10Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
mBribe100Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); mBribe100Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
mBribe1000Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade); mBribe1000Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
} }
void PersuasionDialog::onCancel(MyGUI::Widget *sender) void PersuasionDialog::onCancel(MyGUI::Widget *sender)
{ {
setVisible(false); setVisible(false);
} }
void PersuasionDialog::onPersuade(MyGUI::Widget *sender) void PersuasionDialog::onPersuade(MyGUI::Widget *sender)
{ {
MWBase::MechanicsManager::PersuasionType type; MWBase::MechanicsManager::PersuasionType type;
if (sender == mAdmireButton) type = MWBase::MechanicsManager::PT_Admire; if (sender == mAdmireButton) type = MWBase::MechanicsManager::PT_Admire;
else if (sender == mIntimidateButton) type = MWBase::MechanicsManager::PT_Intimidate; else if (sender == mIntimidateButton) type = MWBase::MechanicsManager::PT_Intimidate;
@ -106,10 +98,10 @@ void PersuasionDialog::onPersuade(MyGUI::Widget *sender)
MWBase::Environment::get().getDialogueManager()->persuade(type); MWBase::Environment::get().getDialogueManager()->persuade(type);
setVisible(false); setVisible(false);
} }
void PersuasionDialog::open() void PersuasionDialog::open()
{ {
WindowModal::open(); WindowModal::open();
center(); center();
@ -120,16 +112,16 @@ void PersuasionDialog::open()
mBribe1000Button->setEnabled (playerGold >= 1000); mBribe1000Button->setEnabled (playerGold >= 1000);
mGoldLabel->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(playerGold)); mGoldLabel->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(playerGold));
} }
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
DialogueWindow::DialogueWindow() DialogueWindow::DialogueWindow()
: WindowBase("openmw_dialogue_window.layout") : WindowBase("openmw_dialogue_window.layout")
, mPersuasionDialog() , mPersuasionDialog()
, mEnabled(false) , mEnabled(false)
, mServices(0) , mServices(0)
{ {
// Centre dialog // Centre dialog
center(); center();
@ -159,10 +151,10 @@ DialogueWindow::DialogueWindow()
getWidget(mDispositionText,"DispositionText"); getWidget(mDispositionText,"DispositionText");
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &DialogueWindow::onWindowResize); static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &DialogueWindow::onWindowResize);
} }
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender) void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
{ {
MyGUI::ISubWidgetText* t = mHistory->getClient()->getSubWidgetText(); MyGUI::ISubWidgetText* t = mHistory->getClient()->getSubWidgetText();
if(t == NULL) if(t == NULL)
return; return;
@ -206,28 +198,28 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
if(color == "#572D21") if(color == "#572D21")
MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key)); MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key));
} }
} }
void DialogueWindow::onWindowResize(MyGUI::Window* _sender) void DialogueWindow::onWindowResize(MyGUI::Window* _sender)
{ {
mTopicsList->adjustSize(); mTopicsList->adjustSize();
} }
void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{ {
if (mHistory->getVScrollPosition() - _rel*0.3 < 0) if (mHistory->getVScrollPosition() - _rel*0.3 < 0)
mHistory->setVScrollPosition(0); mHistory->setVScrollPosition(0);
else else
mHistory->setVScrollPosition(mHistory->getVScrollPosition() - _rel*0.3); mHistory->setVScrollPosition(mHistory->getVScrollPosition() - _rel*0.3);
} }
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
} }
void DialogueWindow::onSelectTopic(const std::string& topic, int id) void DialogueWindow::onSelectTopic(const std::string& topic, int id)
{ {
if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice()) if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
return; return;
@ -293,10 +285,10 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id)
} }
} }
} }
} }
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
{ {
mEnabled = true; mEnabled = true;
mPtr = actor; mPtr = actor;
mTopicsList->setEnabled(true); mTopicsList->setEnabled(true);
@ -306,10 +298,10 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
mHyperLinks.clear(); mHyperLinks.clear();
mHistory->setCaption(""); mHistory->setCaption("");
updateOptions(); updateOptions();
} }
void DialogueWindow::setKeywords(std::list<std::string> keyWords) void DialogueWindow::setKeywords(std::list<std::string> keyWords)
{ {
mTopicsList->clear(); mTopicsList->clear();
bool isCompanion = !MWWorld::Class::get(mPtr).getScript(mPtr).empty() bool isCompanion = !MWWorld::Class::get(mPtr).getScript(mPtr).empty()
@ -356,19 +348,19 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
mTopicsList->addItem(*it); mTopicsList->addItem(*it);
} }
mTopicsList->adjustSize(); mTopicsList->adjustSize();
} }
void DialogueWindow::removeKeyword(std::string keyWord) void DialogueWindow::removeKeyword(std::string keyWord)
{ {
if(mTopicsList->hasItem(keyWord)) if(mTopicsList->hasItem(keyWord))
{ {
mTopicsList->removeItem(keyWord); mTopicsList->removeItem(keyWord);
} }
mTopicsList->adjustSize(); mTopicsList->adjustSize();
} }
void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2) void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2)
{ {
size_t pos = 0; size_t pos = 0;
while((pos = find_str_ci(str,keyword, pos)) != std::string::npos) while((pos = find_str_ci(str,keyword, pos)) != std::string::npos)
{ {
@ -394,10 +386,10 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c
str.insert(pos,color2); str.insert(pos,color2);
pos+= color2.length(); pos+= color2.length();
} }
} }
std::string DialogueWindow::parseText(const std::string& text) std::string DialogueWindow::parseText(const std::string& text)
{ {
bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored) bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored)
std::vector<std::string> topics; std::vector<std::string> topics;
@ -471,20 +463,20 @@ std::string DialogueWindow::parseText(const std::string& text)
} }
return result; return result;
} }
void DialogueWindow::addText(std::string text) void DialogueWindow::addText(std::string text)
{ {
mHistory->addDialogText("#B29154"+parseText(text)+"#B29154"); mHistory->addDialogText("#B29154"+parseText(text)+"#B29154");
} }
void DialogueWindow::addMessageBox(const std::string& text) void DialogueWindow::addMessageBox(const std::string& text)
{ {
mHistory->addDialogText("\n#FFFFFF"+text+"#B29154"); mHistory->addDialogText("\n#FFFFFF"+text+"#B29154");
} }
void DialogueWindow::addTitle(std::string text) void DialogueWindow::addTitle(std::string text)
{ {
// This is called from the dialogue manager, so text is // This is called from the dialogue manager, so text is
// case-smashed - thus we have to retrieve the correct case // case-smashed - thus we have to retrieve the correct case
// of the text through the topic list. // of the text through the topic list.
@ -496,15 +488,15 @@ void DialogueWindow::addTitle(std::string text)
} }
mHistory->addDialogHeading(text); mHistory->addDialogHeading(text);
} }
void DialogueWindow::askQuestion(std::string question) void DialogueWindow::askQuestion(std::string question)
{ {
mHistory->addDialogText("#572D21"+question+"#B29154"+" "); mHistory->addDialogText("#572D21"+question+"#B29154"+" ");
} }
void DialogueWindow::updateOptions() void DialogueWindow::updateOptions()
{ {
//Clear the list of topics //Clear the list of topics
mTopicsList->clear(); mTopicsList->clear();
mHyperLinks.clear(); mHyperLinks.clear();
@ -517,22 +509,22 @@ void DialogueWindow::updateOptions()
mDispositionText->eraseText(0, mDispositionText->getTextLength()); mDispositionText->eraseText(0, mDispositionText->getTextLength());
mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154"); mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154");
} }
} }
void DialogueWindow::goodbye() void DialogueWindow::goodbye()
{ {
mHistory->addDialogText("\n#572D21" + MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->getString()); mHistory->addDialogText("\n#572D21" + MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->getString());
mTopicsList->setEnabled(false); mTopicsList->setEnabled(false);
mEnabled = false; mEnabled = false;
} }
void DialogueWindow::onReferenceUnavailable() void DialogueWindow::onReferenceUnavailable()
{ {
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
} }
void DialogueWindow::onFrame() void DialogueWindow::onFrame()
{ {
if(mMainWidget->getVisible() && mEnabled && mPtr.getTypeName() == typeid(ESM::NPC).name()) if(mMainWidget->getVisible() && mEnabled && mPtr.getTypeName() == typeid(ESM::NPC).name())
{ {
int disp = std::max(0, std::min(100, int disp = std::max(0, std::min(100,
@ -543,4 +535,5 @@ void DialogueWindow::onFrame()
mDispositionText->eraseText(0, mDispositionText->getTextLength()); mDispositionText->eraseText(0, mDispositionText->getTextLength());
mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(disp)+std::string("/100")+"#B29154"); mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(disp)+std::string("/100")+"#B29154");
} }
}
} }

View file

@ -12,11 +12,11 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
using namespace MWGui; namespace MWGui
using namespace Widgets;
MyGUI::UString DialogueHistory::getColorAtPos(size_t _pos)
{ {
MyGUI::UString DialogueHistory::getColorAtPos(size_t _pos)
{
MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour()); MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour());
MyGUI::TextIterator iterator(getCaption()); MyGUI::TextIterator iterator(getCaption());
while(iterator.moveNext()) while(iterator.moveNext())
@ -29,10 +29,10 @@ MyGUI::UString DialogueHistory::getColorAtPos(size_t _pos)
break; break;
} }
return colour; return colour;
} }
MyGUI::UString DialogueHistory::getColorTextAt(size_t _pos) MyGUI::UString DialogueHistory::getColorTextAt(size_t _pos)
{ {
bool breakOnNext = false; bool breakOnNext = false;
MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour()); MyGUI::UString colour = MyGUI::TextIterator::convertTagColour(getTextColour());
MyGUI::UString colour2 = colour; MyGUI::UString colour2 = colour;
@ -59,18 +59,20 @@ MyGUI::UString DialogueHistory::getColorTextAt(size_t _pos)
} }
} }
return ""; return "";
} }
void DialogueHistory::addDialogHeading(const MyGUI::UString& parText) void DialogueHistory::addDialogHeading(const MyGUI::UString& parText)
{ {
MyGUI::UString head("\n#D8C09A"); MyGUI::UString head("\n#D8C09A");
head.append(parText); head.append(parText);
head.append("#B29154\n"); head.append("#B29154\n");
addText(head); addText(head);
} }
void DialogueHistory::addDialogText(const MyGUI::UString& parText) void DialogueHistory::addDialogText(const MyGUI::UString& parText)
{ {
addText(parText); addText(parText);
addText("\n"); addText("\n");
}
} }

View file

@ -3,15 +3,12 @@
#include <components/interpreter/defines.hpp> #include <components/interpreter/defines.hpp>
#include "../mwscript/interpretercontext.hpp" #include "../mwscript/interpretercontext.hpp"
#include "../mwworld/ptr.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/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <OgreUTFString.h> #include <OgreUTFString.h>
using namespace MWGui;
namespace namespace
{ {
int convertFromHex(std::string hex) int convertFromHex(std::string hex)
@ -79,8 +76,11 @@ namespace
} }
} }
std::vector<std::string> BookTextParser::split(std::string utf8Text, const int width, const int height) namespace MWGui
{ {
std::vector<std::string> BookTextParser::split(std::string utf8Text, const int width, const int height)
{
using Ogre::UTFString; using Ogre::UTFString;
std::vector<std::string> result; std::vector<std::string> result;
@ -178,23 +178,23 @@ std::vector<std::string> BookTextParser::split(std::string utf8Text, const int w
} }
return result; return result;
} }
float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const
{ {
std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont); std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName) return MyGUI::FontManager::getInstance().getByName(fontName)
->getGlyphInfo(unicodeChar)->width; ->getGlyphInfo(unicodeChar)->width;
} }
float BookTextParser::currentFontHeight() const float BookTextParser::currentFontHeight() const
{ {
std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont); std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight(); return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
} }
MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width)
{ {
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext); text = Interpreter::fixDefinesBook(text, interpreterContext);
@ -213,8 +213,8 @@ MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, co
boost::algorithm::replace_all(text, "<P>", "\n\n"); boost::algorithm::replace_all(text, "<P>", "\n\n");
// remove leading newlines // remove leading newlines
// while (text[0] == '\n') // while (text[0] == '\n')
// text.erase(0); // text.erase(0);
// remove trailing " // remove trailing "
if (text[text.size()-1] == '\"') if (text[text.size()-1] == '\"')
@ -222,10 +222,10 @@ MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, co
parseSubText(text); parseSubText(text);
return MyGUI::IntSize(mWidth, mHeight); return MyGUI::IntSize(mWidth, mHeight);
} }
void BookTextParser::parseImage(std::string tag, bool createWidget) void BookTextParser::parseImage(std::string tag, bool createWidget)
{ {
int src_start = tag.find("SRC=")+5; int src_start = tag.find("SRC=")+5;
std::string image = tag.substr(src_start, tag.find('"', src_start)-src_start); std::string image = tag.substr(src_start, tag.find('"', src_start)-src_start);
@ -254,10 +254,10 @@ void BookTextParser::parseImage(std::string tag, bool createWidget)
mWidth = std::max(mWidth, width); mWidth = std::max(mWidth, width);
mHeight += height; mHeight += height;
} }
void BookTextParser::parseDiv(std::string tag) void BookTextParser::parseDiv(std::string tag)
{ {
if (tag.find("ALIGN=") == std::string::npos) if (tag.find("ALIGN=") == std::string::npos)
return; return;
@ -267,10 +267,10 @@ void BookTextParser::parseDiv(std::string tag)
mTextStyle.mTextAlign = MyGUI::Align::HCenter; mTextStyle.mTextAlign = MyGUI::Align::HCenter;
else if (align == "LEFT") else if (align == "LEFT")
mTextStyle.mTextAlign = MyGUI::Align::Left; mTextStyle.mTextAlign = MyGUI::Align::Left;
} }
void BookTextParser::parseFont(std::string tag) void BookTextParser::parseFont(std::string tag)
{ {
if (tag.find("COLOR=") != std::string::npos) if (tag.find("COLOR=") != std::string::npos)
{ {
int color_start = tag.find("COLOR=")+7; int color_start = tag.find("COLOR=")+7;
@ -293,10 +293,10 @@ void BookTextParser::parseFont(std::string tag)
{ {
/// \todo /// \todo
} }
} }
void BookTextParser::parseSubText(std::string text) void BookTextParser::parseSubText(std::string text)
{ {
if (text[0] == '<') if (text[0] == '<')
{ {
const size_t tagStart = 1; const size_t tagStart = 1;
@ -362,4 +362,6 @@ void BookTextParser::parseSubText(std::string text)
{ {
parseSubText(text.substr(tagStart, text.size())); parseSubText(text.substr(tagStart, text.size()));
} }
}
} }

View file

@ -1,30 +1,21 @@
#include "hud.hpp" #include "hud.hpp"
#include <cmath>
#include <MyGUI_Widget.h>
#include <MyGUI_RenderManager.h>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwgui/widgets.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "container.hpp"
#include "console.hpp" #include "console.hpp"
#include "spellicons.hpp" #include "spellicons.hpp"
using namespace MWGui; namespace MWGui
{
HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
: Layout("openmw_hud.layout") : Layout("openmw_hud.layout")
, mHealth(NULL) , mHealth(NULL)
, mMagicka(NULL) , mMagicka(NULL)
@ -53,7 +44,7 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
, mWeaponVisible(true) , mWeaponVisible(true)
, mSpellVisible(true) , mSpellVisible(true)
, mWorldMouseOver(false) , mWorldMouseOver(false)
{ {
setCoord(0,0, width, height); setCoord(0,0, width, height);
// Energy bars // Energy bars
@ -113,15 +104,15 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus); mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus);
mSpellIcons = new SpellIcons(); mSpellIcons = new SpellIcons();
} }
HUD::~HUD() HUD::~HUD()
{ {
delete mSpellIcons; delete mSpellIcons;
} }
void HUD::setFpsLevel(int level) void HUD::setFpsLevel(int level)
{ {
mFpsCounter = 0; mFpsCounter = 0;
MyGUI::Widget* fps; MyGUI::Widget* fps;
@ -142,26 +133,26 @@ void HUD::setFpsLevel(int level)
mFpsBox->setVisible(true); mFpsBox->setVisible(true);
getWidget(mFpsCounter, "FPSCounter"); getWidget(mFpsCounter, "FPSCounter");
} }
} }
void HUD::setFPS(float fps) void HUD::setFPS(float fps)
{ {
if (mFpsCounter) if (mFpsCounter)
mFpsCounter->setCaption(boost::lexical_cast<std::string>((int)fps)); mFpsCounter->setCaption(boost::lexical_cast<std::string>((int)fps));
} }
void HUD::setTriangleCount(unsigned int count) void HUD::setTriangleCount(unsigned int count)
{ {
mTriangleCounter->setCaption(boost::lexical_cast<std::string>(count)); mTriangleCounter->setCaption(boost::lexical_cast<std::string>(count));
} }
void HUD::setBatchCount(unsigned int count) void HUD::setBatchCount(unsigned int count)
{ {
mBatchCounter->setCaption(boost::lexical_cast<std::string>(count)); mBatchCounter->setCaption(boost::lexical_cast<std::string>(count));
} }
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value) void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {
"HBar", "MBar", "FBar", 0 "HBar", "MBar", "FBar", 0
@ -194,10 +185,10 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>&
break; break;
} }
} }
} }
void HUD::onWorldClicked(MyGUI::Widget* _sender) void HUD::onWorldClicked(MyGUI::Widget* _sender)
{ {
if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ()) if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ())
return; return;
@ -254,10 +245,10 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object);
} }
} }
} }
void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y) void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
{ {
if (mDragAndDrop->mIsOnDragAndDrop) if (mDragAndDrop->mIsOnDragAndDrop)
{ {
mWorldMouseOver = false; mWorldMouseOver = false;
@ -283,36 +274,36 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
MWBase::Environment::get().getWindowManager()->changePointer("arrow"); MWBase::Environment::get().getWindowManager()->changePointer("arrow");
mWorldMouseOver = true; mWorldMouseOver = true;
} }
} }
void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new)
{ {
MWBase::Environment::get().getWindowManager()->changePointer("arrow"); MWBase::Environment::get().getWindowManager()->changePointer("arrow");
mWorldMouseOver = false; mWorldMouseOver = false;
} }
void HUD::onHMSClicked(MyGUI::Widget* _sender) void HUD::onHMSClicked(MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats);
} }
void HUD::onMapClicked(MyGUI::Widget* _sender) void HUD::onMapClicked(MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
} }
void HUD::onWeaponClicked(MyGUI::Widget* _sender) void HUD::onWeaponClicked(MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
} }
void HUD::onMagicClicked(MyGUI::Widget* _sender) void HUD::onMagicClicked(MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic);
} }
void HUD::setCellName(const std::string& cellName) void HUD::setCellName(const std::string& cellName)
{ {
if (mCellName != cellName) if (mCellName != cellName)
{ {
mCellNameTimer = 5.0f; mCellNameTimer = 5.0f;
@ -321,25 +312,25 @@ void HUD::setCellName(const std::string& cellName)
mCellNameBox->setCaptionWithReplacing("#{sCell=" + mCellName + "}"); mCellNameBox->setCaptionWithReplacing("#{sCell=" + mCellName + "}");
mCellNameBox->setVisible(mMapVisible); mCellNameBox->setVisible(mMapVisible);
} }
} }
void HUD::onFrame(float dt) void HUD::onFrame(float dt)
{ {
mCellNameTimer -= dt; mCellNameTimer -= dt;
mWeaponSpellTimer -= dt; mWeaponSpellTimer -= dt;
if (mCellNameTimer < 0) if (mCellNameTimer < 0)
mCellNameBox->setVisible(false); mCellNameBox->setVisible(false);
if (mWeaponSpellTimer < 0) if (mWeaponSpellTimer < 0)
mWeaponSpellBox->setVisible(false); mWeaponSpellBox->setVisible(false);
} }
void HUD::onResChange(int width, int height) void HUD::onResChange(int width, int height)
{ {
setCoord(0, 0, width, height); setCoord(0, 0, width, height);
} }
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
{ {
const ESM::Spell* spell = const ESM::Spell* spell =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId); MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
@ -371,10 +362,10 @@ void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
icon = std::string("icons\\") + icon; icon = std::string("icons\\") + icon;
Widgets::fixTexturePath(icon); Widgets::fixTexturePath(icon);
mSpellImage->setImageTexture(icon); mSpellImage->setImageTexture(icon);
} }
void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
{ {
std::string itemName = MWWorld::Class::get(item).getName(item); std::string itemName = MWWorld::Class::get(item).getName(item);
if (itemName != mSpellName && mSpellVisible) if (itemName != mSpellName && mSpellVisible)
{ {
@ -402,10 +393,10 @@ void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
Widgets::fixTexturePath(path); Widgets::fixTexturePath(path);
itemBox->setImageTexture(path); itemBox->setImageTexture(path);
itemBox->setNeedMouseFocus(false); itemBox->setNeedMouseFocus(false);
} }
void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
{ {
std::string itemName = MWWorld::Class::get(item).getName(item); std::string itemName = MWWorld::Class::get(item).getName(item);
if (itemName != mWeaponName && mWeaponVisible) if (itemName != mWeaponName && mWeaponVisible)
{ {
@ -438,10 +429,10 @@ void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
} }
else else
mWeapImage->setImageTexture(path); mWeapImage->setImageTexture(path);
} }
void HUD::unsetSelectedSpell() void HUD::unsetSelectedSpell()
{ {
std::string spellName = "#{sNone}"; std::string spellName = "#{sNone}";
if (spellName != mSpellName && mSpellVisible) if (spellName != mSpellName && mSpellVisible)
{ {
@ -457,10 +448,10 @@ void HUD::unsetSelectedSpell()
mSpellStatus->setProgressPosition(0); mSpellStatus->setProgressPosition(0);
mSpellImage->setImageTexture(""); mSpellImage->setImageTexture("");
mSpellBox->clearUserStrings(); mSpellBox->clearUserStrings();
} }
void HUD::unsetSelectedWeapon() void HUD::unsetSelectedWeapon()
{ {
std::string itemName = "#{sSkillHandtohand}"; std::string itemName = "#{sSkillHandtohand}";
if (itemName != mWeaponName && mWeaponVisible) if (itemName != mWeaponName && mWeaponVisible)
{ {
@ -476,47 +467,47 @@ void HUD::unsetSelectedWeapon()
mWeapStatus->setProgressPosition(0); mWeapStatus->setProgressPosition(0);
mWeapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); mWeapImage->setImageTexture("icons\\k\\stealth_handtohand.dds");
mWeapBox->clearUserStrings(); mWeapBox->clearUserStrings();
} }
void HUD::setCrosshairVisible(bool visible) void HUD::setCrosshairVisible(bool visible)
{ {
mCrosshair->setVisible (visible); mCrosshair->setVisible (visible);
} }
void HUD::setHmsVisible(bool visible) void HUD::setHmsVisible(bool visible)
{ {
mHealth->setVisible(visible); mHealth->setVisible(visible);
mMagicka->setVisible(visible); mMagicka->setVisible(visible);
mStamina->setVisible(visible); mStamina->setVisible(visible);
updatePositions(); updatePositions();
} }
void HUD::setWeapVisible(bool visible) void HUD::setWeapVisible(bool visible)
{ {
mWeapBox->setVisible(visible); mWeapBox->setVisible(visible);
updatePositions(); updatePositions();
} }
void HUD::setSpellVisible(bool visible) void HUD::setSpellVisible(bool visible)
{ {
mSpellBox->setVisible(visible); mSpellBox->setVisible(visible);
updatePositions(); updatePositions();
} }
void HUD::setEffectVisible(bool visible) void HUD::setEffectVisible(bool visible)
{ {
mEffectBox->setVisible (visible); mEffectBox->setVisible (visible);
updatePositions(); updatePositions();
} }
void HUD::setMinimapVisible(bool visible) void HUD::setMinimapVisible(bool visible)
{ {
mMinimapBox->setVisible (visible); mMinimapBox->setVisible (visible);
updatePositions(); updatePositions();
} }
void HUD::updatePositions() void HUD::updatePositions()
{ {
int weapDx = 0, spellDx = 0; int weapDx = 0, spellDx = 0;
if (!mHealth->getVisible()) if (!mHealth->getVisible())
spellDx = weapDx = mWeapBoxBaseLeft - mHealthManaStaminaBaseLeft; spellDx = weapDx = mWeapBoxBaseLeft - mHealthManaStaminaBaseLeft;
@ -541,9 +532,11 @@ void HUD::updatePositions()
mMapVisible = mMinimapBox->getVisible (); mMapVisible = mMinimapBox->getVisible ();
mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop()); mEffectBox->setPosition((viewSize.width - mEffectBoxBaseRight) - mEffectBox->getWidth() + effectsDx, mEffectBox->getTop());
} }
void HUD::update() void HUD::update()
{ {
mSpellIcons->updateWidgets(mEffectBox, true); mSpellIcons->updateWidgets(mEffectBox, true);
}
} }

View file

@ -1,28 +1,15 @@
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/compiler/locals.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "widgets.hpp"
#include "bookwindow.hpp" #include "bookwindow.hpp"
#include "scrollwindow.hpp" #include "scrollwindow.hpp"
#include "spellwindow.hpp" #include "spellwindow.hpp"

View file

@ -4,9 +4,6 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/journal.hpp" #include "../mwbase/journal.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwdialogue/journalentry.hpp"
namespace namespace
{ {

View file

@ -8,12 +8,10 @@
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/fallback.hpp" #include "../mwworld/fallback.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/stat.hpp"
namespace MWGui namespace MWGui
{ {

View file

@ -5,18 +5,21 @@
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_ScrollBar.h> #include <MyGUI_ScrollBar.h>
using namespace MWGui; namespace MWGui
using namespace MWGui::Widgets; {
MWList::MWList() : namespace Widgets
{
MWList::MWList() :
mClient(0) mClient(0)
, mScrollView(0) , mScrollView(0)
, mItemHeight(0) , mItemHeight(0)
{ {
} }
void MWList::initialiseOverride() void MWList::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
assignWidget(mClient, "Client"); assignWidget(mClient, "Client");
@ -26,25 +29,25 @@ void MWList::initialiseOverride()
mScrollView = mClient->createWidgetReal<MWGui::Widgets::MWScrollView>( mScrollView = mClient->createWidgetReal<MWGui::Widgets::MWScrollView>(
"MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0), "MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0),
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView"); MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
} }
void MWList::addItem(const std::string& name) void MWList::addItem(const std::string& name)
{ {
mItems.push_back(name); mItems.push_back(name);
} }
void MWList::addSeparator() void MWList::addSeparator()
{ {
mItems.push_back(""); mItems.push_back("");
} }
void MWList::adjustSize() void MWList::adjustSize()
{ {
redraw(); redraw();
} }
void MWList::redraw(bool scrollbarShown) void MWList::redraw(bool scrollbarShown)
{ {
const int _scrollBarWidth = 24; // fetch this from skin? const int _scrollBarWidth = 24; // fetch this from skin?
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0; const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
const int spacing = 3; const int spacing = 3;
@ -97,67 +100,70 @@ void MWList::redraw(bool scrollbarShown)
if(scrollbarPosition > scrollbarRange) if(scrollbarPosition > scrollbarRange)
scrollbarPosition = scrollbarRange; scrollbarPosition = scrollbarRange;
mScrollView->setScrollPosition(scrollbarPosition); mScrollView->setScrollPosition(scrollbarPosition);
} }
bool MWList::hasItem(const std::string& name) bool MWList::hasItem(const std::string& name)
{ {
return (std::find(mItems.begin(), mItems.end(), name) != mItems.end()); return (std::find(mItems.begin(), mItems.end(), name) != mItems.end());
} }
unsigned int MWList::getItemCount() unsigned int MWList::getItemCount()
{ {
return mItems.size(); return mItems.size();
} }
std::string MWList::getItemNameAt(unsigned int at) std::string MWList::getItemNameAt(unsigned int at)
{ {
assert(at < mItems.size() && "List item out of bounds"); assert(at < mItems.size() && "List item out of bounds");
return mItems[at]; return mItems[at];
} }
void MWList::removeItem(const std::string& name) void MWList::removeItem(const std::string& name)
{ {
assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() ); assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() );
mItems.erase( std::find(mItems.begin(), mItems.end(), name) ); mItems.erase( std::find(mItems.begin(), mItems.end(), name) );
} }
void MWList::clear() void MWList::clear()
{ {
mItems.clear(); mItems.clear();
} }
void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel) void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{ {
//NB view offset is negative //NB view offset is negative
if (mScrollView->getViewOffset().top + _rel*0.3 > 0) if (mScrollView->getViewOffset().top + _rel*0.3 > 0)
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
else else
mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3)); mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3));
} }
void MWList::onItemSelected(MyGUI::Widget* _sender) void MWList::onItemSelected(MyGUI::Widget* _sender)
{ {
std::string name = static_cast<MyGUI::Button*>(_sender)->getCaption(); std::string name = static_cast<MyGUI::Button*>(_sender)->getCaption();
int id = *_sender->getUserData<int>(); int id = *_sender->getUserData<int>();
eventItemSelected(name, id); eventItemSelected(name, id);
eventWidgetSelected(_sender); eventWidgetSelected(_sender);
} }
MyGUI::Widget* MWList::getItemWidget(const std::string& name) MyGUI::Widget* MWList::getItemWidget(const std::string& name)
{ {
return mScrollView->findWidget (getName() + "_item_" + name); return mScrollView->findWidget (getName() + "_item_" + name);
} }
size_t MWScrollView::getScrollPosition() size_t MWScrollView::getScrollPosition()
{ {
return getVScroll()->getScrollPosition(); return getVScroll()->getScrollPosition();
} }
void MWScrollView::setScrollPosition(size_t position) void MWScrollView::setScrollPosition(size_t position)
{ {
getVScroll()->setScrollPosition(position); getVScroll()->setScrollPosition(position);
} }
size_t MWScrollView::getScrollRange() size_t MWScrollView::getScrollRange()
{ {
return getVScroll()->getScrollRange(); return getVScroll()->getScrollRange();
}
}
} }

View file

@ -1,25 +1,16 @@
#include "loadingscreen.hpp" #include "loadingscreen.hpp"
#include <OgreRenderWindow.h> #include <OgreRenderWindow.h>
#include <OgreRoot.h>
#include <OgreCompositorManager.h> #include <OgreCompositorManager.h>
#include <OgreCompositorChain.h> #include <OgreCompositorChain.h>
#include <OgreMaterial.h>
#include <boost/algorithm/string.hpp>
#include <openengine/ogre/fader.hpp> #include <openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include <components/esm/records.hpp>
namespace MWGui namespace MWGui
{ {

View file

@ -3,7 +3,6 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"

View file

@ -2,12 +2,8 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <OgreVector2.h>
#include <OgreTextureManager.h>
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <MyGUI_Gui.h>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -17,9 +13,10 @@
#include "widgets.hpp" #include "widgets.hpp"
using namespace MWGui; namespace MWGui
{
LocalMapBase::LocalMapBase() LocalMapBase::LocalMapBase()
: mCurX(0) : mCurX(0)
, mCurY(0) , mCurY(0)
, mInterior(false) , mInterior(false)
@ -34,11 +31,11 @@ LocalMapBase::LocalMapBase()
, mLastDirectionX(0.0f) , mLastDirectionX(0.0f)
, mLastDirectionY(0.0f) , mLastDirectionY(0.0f)
, mCompass(NULL) , mCompass(NULL)
{ {
} }
void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop) void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop)
{ {
mLocalMap = widget; mLocalMap = widget;
mLayout = layout; mLayout = layout;
mMapDragAndDrop = mapDragAndDrop; mMapDragAndDrop = mapDragAndDrop;
@ -68,22 +65,22 @@ void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEn
mFogWidgets.push_back(fog); mFogWidgets.push_back(fog);
} }
} }
} }
void LocalMapBase::setCellPrefix(const std::string& prefix) void LocalMapBase::setCellPrefix(const std::string& prefix)
{ {
mPrefix = prefix; mPrefix = prefix;
mChanged = true; mChanged = true;
} }
void LocalMapBase::toggleFogOfWar() void LocalMapBase::toggleFogOfWar()
{ {
mFogOfWar = !mFogOfWar; mFogOfWar = !mFogOfWar;
applyFogOfWar(); applyFogOfWar();
} }
void LocalMapBase::applyFogOfWar() void LocalMapBase::applyFogOfWar()
{ {
for (int mx=0; mx<3; ++mx) for (int mx=0; mx<3; ++mx)
{ {
for (int my=0; my<3; ++my) for (int my=0; my<3; ++my)
@ -101,20 +98,20 @@ void LocalMapBase::applyFogOfWar()
} }
} }
notifyMapChanged (); notifyMapChanged ();
} }
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2) void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
{ {
applyFogOfWar (); applyFogOfWar ();
} }
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2) void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
{ {
applyFogOfWar (); applyFogOfWar ();
} }
void LocalMapBase::setActiveCell(const int x, const int y, bool interior) void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{ {
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
// clear all previous markers // clear all previous markers
@ -222,11 +219,11 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
std::string tex = "textures\\compass.dds"; std::string tex = "textures\\compass.dds";
mCompass->setImageTexture(""); mCompass->setImageTexture("");
mCompass->setImageTexture(tex); mCompass->setImageTexture(tex);
} }
void LocalMapBase::setPlayerPos(const float x, const float y) void LocalMapBase::setPlayerPos(const float x, const float y)
{ {
if (x == mLastPositionX && y == mLastPositionY) if (x == mLastPositionX && y == mLastPositionY)
return; return;
@ -241,10 +238,10 @@ void LocalMapBase::setPlayerPos(const float x, const float y)
mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16)); mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16));
mLastPositionX = x; mLastPositionX = x;
mLastPositionY = y; mLastPositionY = y;
} }
void LocalMapBase::setPlayerDir(const float x, const float y) void LocalMapBase::setPlayerDir(const float x, const float y)
{ {
if (x == mLastDirectionX && y == mLastDirectionY) if (x == mLastDirectionX && y == mLastDirectionY)
return; return;
@ -258,14 +255,14 @@ void LocalMapBase::setPlayerDir(const float x, const float y)
mLastDirectionX = x; mLastDirectionX = x;
mLastDirectionY = y; mLastDirectionY = y;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
MapWindow::MapWindow(const std::string& cacheDir) MapWindow::MapWindow(const std::string& cacheDir)
: MWGui::WindowPinnableBase("openmw_map_window.layout") : MWGui::WindowPinnableBase("openmw_map_window.layout")
, mGlobal(false) , mGlobal(false)
{ {
setCoord(500,0,320,300); setCoord(500,0,320,300);
mGlobalMapRender = new MWRender::GlobalMap(cacheDir); mGlobalMapRender = new MWRender::GlobalMap(cacheDir);
@ -295,20 +292,20 @@ MapWindow::MapWindow(const std::string& cacheDir)
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this); LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this);
} }
MapWindow::~MapWindow() MapWindow::~MapWindow()
{ {
delete mGlobalMapRender; delete mGlobalMapRender;
} }
void MapWindow::setCellName(const std::string& cellName) void MapWindow::setCellName(const std::string& cellName)
{ {
setTitle("#{sCell=" + cellName + "}"); setTitle("#{sCell=" + cellName + "}");
} }
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; float worldX, worldY;
mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY); mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY);
@ -333,21 +330,21 @@ void MapWindow::addVisitedLocation(const std::string& name, int x, int y)
markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name); markerWidget->setUserString("Caption_TextOneLine", name);
} }
void MapWindow::cellExplored(int x, int y) void MapWindow::cellExplored(int x, int y)
{ {
mGlobalMapRender->exploreCell(x,y); mGlobalMapRender->exploreCell(x,y);
} }
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{ {
if (_id!=MyGUI::MouseButton::Left) return; if (_id!=MyGUI::MouseButton::Left) return;
mLastDragPos = MyGUI::IntPoint(_left, _top); mLastDragPos = MyGUI::IntPoint(_left, _top);
} }
void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{ {
if (_id!=MyGUI::MouseButton::Left) return; if (_id!=MyGUI::MouseButton::Left) return;
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos; MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
@ -359,10 +356,10 @@ void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::
mLastDragPos = MyGUI::IntPoint(_left, _top); mLastDragPos = MyGUI::IntPoint(_left, _top);
} }
void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
{ {
mGlobal = !mGlobal; mGlobal = !mGlobal;
mGlobalMap->setVisible(mGlobal); mGlobalMap->setVisible(mGlobal);
mLocalMap->setVisible(!mGlobal); mLocalMap->setVisible(!mGlobal);
@ -372,15 +369,15 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
if (mGlobal) if (mGlobal)
globalMapUpdatePlayer (); globalMapUpdatePlayer ();
} }
void MapWindow::onPinToggled() void MapWindow::onPinToggled()
{ {
MWBase::Environment::get().getWindowManager()->setMinimapVisibility(!mPinned); MWBase::Environment::get().getWindowManager()->setMinimapVisibility(!mPinned);
} }
void MapWindow::open() void MapWindow::open()
{ {
mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); mGlobalMap->setCanvasSize (mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight()); mGlobalMapImage->setSize(mGlobalMapRender->getWidth(), mGlobalMapRender->getHeight());
@ -393,10 +390,10 @@ void MapWindow::open()
globalMapUpdatePlayer(); globalMapUpdatePlayer();
mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds"); mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds");
} }
void MapWindow::globalMapUpdatePlayer () void MapWindow::globalMapUpdatePlayer ()
{ {
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition (); Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation (); Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y); Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
@ -424,15 +421,15 @@ void MapWindow::globalMapUpdatePlayer ()
MyGUI::IntPoint viewoffs(0.5*viewsize.width - worldX, 0.5*viewsize.height - worldY); MyGUI::IntPoint viewoffs(0.5*viewsize.width - worldX, 0.5*viewsize.height - worldY);
mGlobalMap->setViewOffset(viewoffs); mGlobalMap->setViewOffset(viewoffs);
} }
} }
void MapWindow::notifyPlayerUpdate () void MapWindow::notifyPlayerUpdate ()
{ {
globalMapUpdatePlayer (); globalMapUpdatePlayer ();
} }
void MapWindow::notifyMapChanged () void MapWindow::notifyMapChanged ()
{ {
// workaround to prevent the map from drawing on top of the button // workaround to prevent the map from drawing on top of the button
MyGUI::IntCoord oldCoord = mButton->getCoord (); MyGUI::IntCoord oldCoord = mButton->getCoord ();
MyGUI::Gui::getInstance().destroyWidget (mButton); MyGUI::Gui::getInstance().destroyWidget (mButton);
@ -443,4 +440,6 @@ void MapWindow::notifyMapChanged ()
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" : mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" :
"#{sWorld}"); "#{sWorld}");
}
} }

View file

@ -9,10 +9,7 @@
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "list.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "tradewindow.hpp" #include "tradewindow.hpp"

View file

@ -5,17 +5,18 @@
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
using namespace MWGui; namespace MWGui
MessageBoxManager::MessageBoxManager ()
{ {
MessageBoxManager::MessageBoxManager ()
{
// defines // defines
mMessageBoxSpeed = 0.1; mMessageBoxSpeed = 0.1;
mInterMessageBoxe = NULL; mInterMessageBoxe = NULL;
} }
void MessageBoxManager::onFrame (float frameDuration) void MessageBoxManager::onFrame (float frameDuration)
{ {
std::vector<MessageBoxManagerTimer>::iterator it; std::vector<MessageBoxManagerTimer>::iterator it;
for(it = mTimers.begin(); it != mTimers.end();) for(it = mTimers.begin(); it != mTimers.end();)
{ {
@ -65,10 +66,10 @@ void MessageBoxManager::onFrame (float frameDuration)
MWBase::Environment::get().getInputManager()->changeInputMode( MWBase::Environment::get().getInputManager()->changeInputMode(
MWBase::Environment::get().getWindowManager()->isGuiMode()); MWBase::Environment::get().getWindowManager()->isGuiMode());
} }
} }
void MessageBoxManager::createMessageBox (const std::string& message) void MessageBoxManager::createMessageBox (const std::string& message)
{ {
MessageBox *box = new MessageBox(*this, message); MessageBox *box = new MessageBox(*this, message);
removeMessageBox(message.length()*mMessageBoxSpeed, box); removeMessageBox(message.length()*mMessageBoxSpeed, box);
@ -87,10 +88,10 @@ void MessageBoxManager::createMessageBox (const std::string& message)
(*it)->update(height); (*it)->update(height);
height += (*it)->getHeight(); height += (*it)->getHeight();
} }
} }
bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons) bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons)
{ {
if(mInterMessageBoxe != NULL) { if(mInterMessageBoxe != NULL) {
throw std::runtime_error("There is a message box already"); throw std::runtime_error("There is a message box already");
} }
@ -98,25 +99,25 @@ bool MessageBoxManager::createInteractiveMessageBox (const std::string& message,
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons); mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
return true; return true;
} }
bool MessageBoxManager::isInteractiveMessageBox () bool MessageBoxManager::isInteractiveMessageBox ()
{ {
return mInterMessageBoxe != NULL; return mInterMessageBoxe != NULL;
} }
void MessageBoxManager::removeMessageBox (float time, MessageBox *msgbox) void MessageBoxManager::removeMessageBox (float time, MessageBox *msgbox)
{ {
MessageBoxManagerTimer timer; MessageBoxManagerTimer timer;
timer.current = 0; timer.current = 0;
timer.max = time; timer.max = time;
timer.messageBox = msgbox; timer.messageBox = msgbox;
mTimers.insert(mTimers.end(), timer); mTimers.insert(mTimers.end(), timer);
} }
bool MessageBoxManager::removeMessageBox (MessageBox *msgbox) bool MessageBoxManager::removeMessageBox (MessageBox *msgbox)
{ {
std::vector<MessageBox*>::iterator it; std::vector<MessageBox*>::iterator it;
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it) for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
{ {
@ -128,36 +129,36 @@ bool MessageBoxManager::removeMessageBox (MessageBox *msgbox)
} }
} }
return false; return false;
} }
void MessageBoxManager::setMessageBoxSpeed (int speed) void MessageBoxManager::setMessageBoxSpeed (int speed)
{ {
mMessageBoxSpeed = speed; mMessageBoxSpeed = speed;
} }
void MessageBoxManager::enterPressed () void MessageBoxManager::enterPressed ()
{ {
if(mInterMessageBoxe != NULL) if(mInterMessageBoxe != NULL)
mInterMessageBoxe->enterPressed(); mInterMessageBoxe->enterPressed();
} }
int MessageBoxManager::readPressedButton () int MessageBoxManager::readPressedButton ()
{ {
if(mInterMessageBoxe != NULL) if(mInterMessageBoxe != NULL)
{ {
return mInterMessageBoxe->readPressedButton(); return mInterMessageBoxe->readPressedButton();
} }
return -1; return -1;
} }
MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message) MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message)
: Layout("openmw_messagebox.layout") : Layout("openmw_messagebox.layout")
, mMessageBoxManager(parMessageBoxManager) , mMessageBoxManager(parMessageBoxManager)
, mMessage(message) , mMessage(message)
{ {
// defines // defines
mFixedWidth = 300; mFixedWidth = 300;
mBottomPadding = 20; mBottomPadding = 20;
@ -186,10 +187,10 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin
mMainWidget->setSize(size); mMainWidget->setSize(size);
size.width -= 15; // this is to center the text (see messagebox.layout, Widget type="Edit" position="-2 -3 0 0") size.width -= 15; // this is to center the text (see messagebox.layout, Widget type="Edit" position="-2 -3 0 0")
mMessageWidget->setSize(size); mMessageWidget->setSize(size);
} }
void MessageBox::update (int height) void MessageBox::update (int height)
{ {
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntCoord coord; MyGUI::IntCoord coord;
coord.left = (gameWindowSize.width - mFixedWidth)/2; coord.left = (gameWindowSize.width - mFixedWidth)/2;
@ -202,20 +203,20 @@ void MessageBox::update (int height)
mMainWidget->setCoord(coord); mMainWidget->setCoord(coord);
mMainWidget->setSize(size); mMainWidget->setSize(size);
mMainWidget->setVisible(true); mMainWidget->setVisible(true);
} }
int MessageBox::getHeight () int MessageBox::getHeight ()
{ {
return mHeight+mNextBoxPadding; // 20 is the padding between this and the next MessageBox return mHeight+mNextBoxPadding; // 20 is the padding between this and the next MessageBox
} }
InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons) InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons)
: WindowModal("openmw_interactive_messagebox.layout") : WindowModal("openmw_interactive_messagebox.layout")
, mMessageBoxManager(parMessageBoxManager) , mMessageBoxManager(parMessageBoxManager)
, mButtonPressed(-1) , mButtonPressed(-1)
{ {
WindowModal::open(); WindowModal::open();
int fixedWidth = 500; int fixedWidth = 500;
@ -366,10 +367,10 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
} }
} }
} }
void InteractiveMessageBox::enterPressed() void InteractiveMessageBox::enterPressed()
{ {
std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}"));
std::vector<MyGUI::Button*>::const_iterator button; std::vector<MyGUI::Button*>::const_iterator button;
@ -383,15 +384,15 @@ void InteractiveMessageBox::enterPressed()
} }
} }
} }
void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed) void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed)
{ {
buttonActivated (pressed); buttonActivated (pressed);
} }
void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed) void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed)
{ {
mMarkedToDelete = true; mMarkedToDelete = true;
int index = 0; int index = 0;
std::vector<MyGUI::Button*>::const_iterator button; std::vector<MyGUI::Button*>::const_iterator button;
@ -405,11 +406,13 @@ void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed)
} }
index++; index++;
} }
} }
int InteractiveMessageBox::readPressedButton () int InteractiveMessageBox::readPressedButton ()
{ {
int pressed = mButtonPressed; int pressed = mButtonPressed;
mButtonPressed = -1; mButtonPressed = -1;
return pressed; return pressed;
}
} }

View file

@ -2,13 +2,9 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/actionequip.hpp" #include "../mwworld/actionequip.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/spellsuccess.hpp" #include "../mwmechanics/spellsuccess.hpp"
#include "../mwgui/inventorywindow.hpp" #include "../mwgui/inventorywindow.hpp"
#include "../mwgui/bookwindow.hpp" #include "../mwgui/bookwindow.hpp"

View file

@ -1,76 +1,38 @@
#include "race.hpp" #include "race.hpp"
#include <iostream>
#include <iterator>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "widgets.hpp"
#include "tooltips.hpp" #include "tooltips.hpp"
using namespace MWGui;
using namespace Widgets;
namespace namespace
{ {
int wrap(int index, int max) int wrap(int index, int max)
{ {
if (index < 0) if (index < 0)
return max - 1; return max - 1;
else if (index >= max) else if (index >= max)
return 0; return 0;
else else
return index; return index;
}
} }
int countParts(const std::string &part, const std::string &race, bool male) namespace MWGui
{ {
/// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs
const MWWorld::Store<ESM::BodyPart> &store =
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
std::string prefix = RaceDialog::RaceDialog()
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
std::string suffix;
suffix.reserve(prefix.size() + 3);
int count = -1;
do {
++count;
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
}
while (store.search(prefix + suffix) != 0);
if (count == 0 && part == "hair") {
count = -1;
do {
++count;
suffix = (boost::format("%02d") % (count + 1)).str();
}
while (store.search(prefix + suffix) != 0);
}
return count;
}
}
RaceDialog::RaceDialog()
: WindowModal("openmw_chargen_race.layout") : WindowModal("openmw_chargen_race.layout")
, mGenderIndex(0) , mGenderIndex(0)
, mFaceIndex(0) , mFaceIndex(0)
, mHairIndex(0) , mHairIndex(0)
, mFaceCount(10)
, mHairCount(14)
, mCurrentAngle(0) , mCurrentAngle(0)
{ {
// Centre dialog // Centre dialog
center(); center();
@ -128,10 +90,10 @@ RaceDialog::RaceDialog()
updateRaces(); updateRaces();
updateSkills(); updateSkills();
updateSpellPowers(); updateSpellPowers();
} }
void RaceDialog::setNextButtonShow(bool shown) void RaceDialog::setNextButtonShow(bool shown)
{ {
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
@ -139,10 +101,10 @@ void RaceDialog::setNextButtonShow(bool shown)
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", ""));
else else
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
} }
void RaceDialog::open() void RaceDialog::open()
{ {
WindowModal::open(); WindowModal::open();
updateRaces(); updateRaces();
@ -164,11 +126,11 @@ void RaceDialog::open()
mHairIndex = boost::lexical_cast<int>(index) - 1; mHairIndex = boost::lexical_cast<int>(index) - 1;
mPreviewImage->setImageTexture ("CharacterHeadPreview"); mPreviewImage->setImageTexture ("CharacterHeadPreview");
} }
void RaceDialog::setRaceId(const std::string &raceId) void RaceDialog::setRaceId(const std::string &raceId)
{ {
mCurrentRaceId = raceId; mCurrentRaceId = raceId;
mRaceList->setIndexSelected(MyGUI::ITEM_NONE); mRaceList->setIndexSelected(MyGUI::ITEM_NONE);
size_t count = mRaceList->getItemCount(); size_t count = mRaceList->getItemCount();
@ -185,117 +147,78 @@ void RaceDialog::setRaceId(const std::string &raceId)
updateSkills(); updateSkills();
updateSpellPowers(); updateSpellPowers();
} }
void RaceDialog::close() void RaceDialog::close()
{ {
delete mPreview; delete mPreview;
mPreview = 0; mPreview = 0;
} }
// widget controls // widget controls
void RaceDialog::onOkClicked(MyGUI::Widget* _sender) void RaceDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
if(mRaceList->getIndexSelected() == MyGUI::ITEM_NONE) if(mRaceList->getIndexSelected() == MyGUI::ITEM_NONE)
return; return;
eventDone(this); eventDone(this);
} }
void RaceDialog::onBackClicked(MyGUI::Widget* _sender) void RaceDialog::onBackClicked(MyGUI::Widget* _sender)
{ {
eventBack(); eventBack();
} }
void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position) void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position)
{ {
float angle = (float(_position) / 49.f - 0.5) * 3.14 * 2; float angle = (float(_position) / 49.f - 0.5) * 3.14 * 2;
float diff = angle - mCurrentAngle; float diff = angle - mCurrentAngle;
mPreview->update (diff); mPreview->update (diff);
mCurrentAngle += diff; mCurrentAngle += diff;
} }
void RaceDialog::onSelectPreviousGender(MyGUI::Widget*) void RaceDialog::onSelectPreviousGender(MyGUI::Widget*)
{ {
mGenderIndex = wrap(mGenderIndex - 1, 2); mGenderIndex = wrap(mGenderIndex - 1, 2);
recountParts(); recountParts();
updatePreview(); updatePreview();
} }
void RaceDialog::onSelectNextGender(MyGUI::Widget*) void RaceDialog::onSelectNextGender(MyGUI::Widget*)
{ {
mGenderIndex = wrap(mGenderIndex + 1, 2); mGenderIndex = wrap(mGenderIndex + 1, 2);
recountParts(); recountParts();
updatePreview(); updatePreview();
} }
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*) void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
{ {
do mFaceIndex = wrap(mFaceIndex - 1, mAvailableHeads.size());
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
while (!isFacePlayable());
updatePreview(); updatePreview();
} }
void RaceDialog::onSelectNextFace(MyGUI::Widget*) void RaceDialog::onSelectNextFace(MyGUI::Widget*)
{ {
do mFaceIndex = wrap(mFaceIndex + 1, mAvailableHeads.size());
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
while (!isFacePlayable());
updatePreview(); updatePreview();
} }
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*) void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
{ {
do mHairIndex = wrap(mHairIndex - 1, mAvailableHairs.size());
mHairIndex = wrap(mHairIndex - 1, mHairCount);
while (!isHairPlayable());
updatePreview(); updatePreview();
} }
void RaceDialog::onSelectNextHair(MyGUI::Widget*) void RaceDialog::onSelectNextHair(MyGUI::Widget*)
{ {
do mHairIndex = wrap(mHairIndex + 1, mAvailableHairs.size());
mHairIndex = wrap(mHairIndex + 1, mHairCount);
while (!isHairPlayable());
updatePreview(); updatePreview();
} }
bool RaceDialog::isFacePlayable() void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
{ {
std::string prefix =
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
const MWWorld::Store<ESM::BodyPart> &parts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
if (parts.search(prefix + "head_" + headIndex) == 0)
return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
else
return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
}
bool RaceDialog::isHairPlayable()
{
std::string prefix =
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
const MWWorld::Store<ESM::BodyPart> &parts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
if (parts.search(prefix + "hair_" + hairIndex) == 0)
return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
else
return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
}
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
{
if (_index == MyGUI::ITEM_NONE) if (_index == MyGUI::ITEM_NONE)
return; return;
@ -312,50 +235,61 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
updatePreview(); updatePreview();
updateSkills(); updateSkills();
updateSpellPowers(); updateSpellPowers();
} }
void RaceDialog::recountParts() void RaceDialog::getBodyParts (int part, std::vector<std::string>& out)
{ {
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); out.clear();
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); const MWWorld::Store<ESM::BodyPart> &store =
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
for (MWWorld::Store<ESM::BodyPart>::iterator it = store.begin(); it != store.end(); ++it)
{
const ESM::BodyPart& bodypart = *it;
if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable)
continue;
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
continue;
if (bodypart.mData.mPart != static_cast<ESM::BodyPart::MeshPart>(part))
continue;
if (mGenderIndex != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
continue;
bool firstPerson = (bodypart.mId.size() >= 3)
&& bodypart.mId[bodypart.mId.size()-3] == '1'
&& bodypart.mId[bodypart.mId.size()-2] == 's'
&& bodypart.mId[bodypart.mId.size()-1] == 't';
if (firstPerson)
continue;
if (Misc::StringUtils::ciEqual(bodypart.mRace, mCurrentRaceId))
out.push_back(bodypart.mId);
}
}
void RaceDialog::recountParts()
{
getBodyParts(ESM::BodyPart::MP_Hair, mAvailableHairs);
getBodyParts(ESM::BodyPart::MP_Head, mAvailableHeads);
mFaceIndex = 0; mFaceIndex = 0;
mHairIndex = 0; mHairIndex = 0;
}
while (!isHairPlayable()) // update widget content
mHairIndex = wrap(mHairIndex + 1, mHairCount);
while (!isFacePlayable())
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
}
// update widget content void RaceDialog::updatePreview()
{
void RaceDialog::updatePreview()
{
ESM::NPC record = mPreview->getPrototype(); ESM::NPC record = mPreview->getPrototype();
record.mRace = mCurrentRaceId; record.mRace = mCurrentRaceId;
record.setIsMale(mGenderIndex == 0); record.setIsMale(mGenderIndex == 0);
std::string prefix = record.mHead = mAvailableHeads[mFaceIndex];
"b_n_" + mCurrentRaceId + ((record.isMale()) ? "_m_" : "_f_"); record.mHair = mAvailableHairs[mHairIndex];
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
record.mHead = prefix + "head_" + headIndex;
record.mHair = prefix + "hair_" + hairIndex;
const MWWorld::Store<ESM::BodyPart> &parts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
if (parts.search(record.mHair) == 0) {
record.mHair = prefix + "hair" + hairIndex;
}
mPreview->setPrototype(record); mPreview->setPrototype(record);
} }
void RaceDialog::updateRaces() void RaceDialog::updateRaces()
{ {
mRaceList->removeAllItems(); mRaceList->removeAllItems();
const MWWorld::Store<ESM::Race> &races = const MWWorld::Store<ESM::Race> &races =
@ -375,10 +309,10 @@ void RaceDialog::updateRaces()
mRaceList->setIndexSelected(index); mRaceList->setIndexSelected(index);
++index; ++index;
} }
} }
void RaceDialog::updateSkills() void RaceDialog::updateSkills()
{ {
for (std::vector<MyGUI::Widget*>::iterator it = mSkillItems.begin(); it != mSkillItems.end(); ++it) for (std::vector<MyGUI::Widget*>::iterator it = mSkillItems.begin(); it != mSkillItems.end(); ++it)
{ {
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
@ -388,7 +322,7 @@ void RaceDialog::updateSkills()
if (mCurrentRaceId.empty()) if (mCurrentRaceId.empty())
return; return;
MWSkillPtr skillWidget; Widgets::MWSkillPtr skillWidget;
const int lineHeight = 18; const int lineHeight = 18;
MyGUI::IntCoord coord1(0, 0, mSkillList->getWidth(), 18); MyGUI::IntCoord coord1(0, 0, mSkillList->getWidth(), 18);
@ -401,10 +335,10 @@ void RaceDialog::updateSkills()
if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes
continue; continue;
skillWidget = mSkillList->createWidget<MWSkill>("MW_StatNameValue", coord1, MyGUI::Align::Default, skillWidget = mSkillList->createWidget<Widgets::MWSkill>("MW_StatNameValue", coord1, MyGUI::Align::Default,
std::string("Skill") + boost::lexical_cast<std::string>(i)); std::string("Skill") + boost::lexical_cast<std::string>(i));
skillWidget->setSkillNumber(skillId); skillWidget->setSkillNumber(skillId);
skillWidget->setSkillValue(MWSkill::SkillValue(race->mData.mBonus[i].mBonus)); skillWidget->setSkillValue(Widgets::MWSkill::SkillValue(race->mData.mBonus[i].mBonus));
ToolTips::createSkillToolTip(skillWidget, skillId); ToolTips::createSkillToolTip(skillWidget, skillId);
@ -412,10 +346,10 @@ void RaceDialog::updateSkills()
coord1.top += lineHeight; coord1.top += lineHeight;
} }
} }
void RaceDialog::updateSpellPowers() void RaceDialog::updateSpellPowers()
{ {
for (std::vector<MyGUI::Widget*>::iterator it = mSpellPowerItems.begin(); it != mSpellPowerItems.end(); ++it) for (std::vector<MyGUI::Widget*>::iterator it = mSpellPowerItems.begin(); it != mSpellPowerItems.end(); ++it)
{ {
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
@ -425,7 +359,7 @@ void RaceDialog::updateSpellPowers()
if (mCurrentRaceId.empty()) if (mCurrentRaceId.empty())
return; return;
MWSpellPtr spellPowerWidget; 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);
@ -437,7 +371,7 @@ void RaceDialog::updateSpellPowers()
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<MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i)); 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);
@ -447,4 +381,5 @@ void RaceDialog::updateSpellPowers()
coord.top += lineHeight; coord.top += lineHeight;
++i; ++i;
} }
}
} }

View file

@ -76,8 +76,10 @@ namespace MWGui
void updatePreview(); void updatePreview();
void recountParts(); void recountParts();
bool isHairPlayable(); void getBodyParts (int part, std::vector<std::string>& out);
bool isFacePlayable();
std::vector<std::string> mAvailableHeads;
std::vector<std::string> mAvailableHairs;
MyGUI::ImageBox* mPreviewImage; MyGUI::ImageBox* mPreviewImage;
MyGUI::ListBox* mRaceList; MyGUI::ListBox* mRaceList;
@ -90,7 +92,6 @@ namespace MWGui
std::vector<MyGUI::Widget*> mSpellPowerItems; std::vector<MyGUI::Widget*> mSpellPowerItems;
int mGenderIndex, mFaceIndex, mHairIndex; int mGenderIndex, mFaceIndex, mHairIndex;
int mFaceCount, mHairCount;
std::string mCurrentRaceId; std::string mCurrentRaceId;

View file

@ -18,18 +18,18 @@ namespace MWGui
void ReferenceInterface::checkReferenceAvailable() void ReferenceInterface::checkReferenceAvailable()
{ {
if (mPtr.isEmpty())
return;
MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
// check if player has changed cell, or count of the reference has become 0 // check if player has changed cell, or count of the reference has become 0
if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL) if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL)
|| mPtr.getRefData().getCount() == 0) || (!mPtr.isEmpty() && mPtr.getRefData().getCount() == 0))
{
if (!mPtr.isEmpty())
{ {
mPtr = MWWorld::Ptr(); mPtr = MWWorld::Ptr();
onReferenceUnavailable(); onReferenceUnavailable();
} }
}
mCurrentPlayerCell = playerCell; mCurrentPlayerCell = playerCell;
} }

View file

@ -1,31 +1,25 @@
#include "review.hpp" #include "review.hpp"
#include <cmath>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "widgets.hpp"
#include "tooltips.hpp" #include "tooltips.hpp"
#undef min #undef min
#undef max #undef max
using namespace MWGui; namespace MWGui
using namespace Widgets; {
const int ReviewDialog::sLineHeight = 18; const int ReviewDialog::sLineHeight = 18;
ReviewDialog::ReviewDialog() ReviewDialog::ReviewDialog()
: WindowModal("openmw_chargen_review.layout") : WindowModal("openmw_chargen_review.layout")
, mLastPos(0) , mLastPos(0)
{ {
// Centre dialog // Centre dialog
center(); center();
@ -66,13 +60,13 @@ ReviewDialog::ReviewDialog()
// Setup attributes // Setup attributes
MWAttributePtr attribute; Widgets::MWAttributePtr attribute;
for (int idx = 0; idx < ESM::Attribute::Length; ++idx) for (int idx = 0; idx < ESM::Attribute::Length; ++idx)
{ {
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx)); getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute)); mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]); attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
attribute->setAttributeValue(MWAttribute::AttributeValue(0, 0)); attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue(0, 0));
} }
// Setup skills // Setup skills
@ -92,21 +86,21 @@ ReviewDialog::ReviewDialog()
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onOkClicked);
} }
void ReviewDialog::open() void ReviewDialog::open()
{ {
WindowModal::open(); WindowModal::open();
updateSkillArea(); updateSkillArea();
} }
void ReviewDialog::setPlayerName(const std::string &name) void ReviewDialog::setPlayerName(const std::string &name)
{ {
mNameWidget->setCaption(name); mNameWidget->setCaption(name);
} }
void ReviewDialog::setRace(const std::string &raceId) void ReviewDialog::setRace(const std::string &raceId)
{ {
mRaceId = raceId; mRaceId = raceId;
const ESM::Race *race = const ESM::Race *race =
@ -116,17 +110,17 @@ void ReviewDialog::setRace(const std::string &raceId)
ToolTips::createRaceToolTip(mRaceWidget, race); ToolTips::createRaceToolTip(mRaceWidget, race);
mRaceWidget->setCaption(race->mName); mRaceWidget->setCaption(race->mName);
} }
} }
void ReviewDialog::setClass(const ESM::Class& class_) void ReviewDialog::setClass(const ESM::Class& class_)
{ {
mKlass = class_; mKlass = class_;
mClassWidget->setCaption(mKlass.mName); mClassWidget->setCaption(mKlass.mName);
ToolTips::createClassToolTip(mClassWidget, mKlass); ToolTips::createClassToolTip(mClassWidget, mKlass);
} }
void ReviewDialog::setBirthSign(const std::string& signId) void ReviewDialog::setBirthSign(const std::string& signId)
{ {
mBirthSignId = signId; mBirthSignId = signId;
const ESM::BirthSign *sign = const ESM::BirthSign *sign =
@ -136,40 +130,40 @@ void ReviewDialog::setBirthSign(const std::string& signId)
mBirthSignWidget->setCaption(sign->mName); mBirthSignWidget->setCaption(sign->mName);
ToolTips::createBirthsignToolTip(mBirthSignWidget, mBirthSignId); ToolTips::createBirthsignToolTip(mBirthSignWidget, mBirthSignId);
} }
} }
void ReviewDialog::setHealth(const MWMechanics::DynamicStat<float>& value) void ReviewDialog::setHealth(const MWMechanics::DynamicStat<float>& value)
{ {
mHealth->setValue(value.getCurrent(), value.getModified()); mHealth->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
} }
void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<float>& value) void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<float>& value)
{ {
mMagicka->setValue(value.getCurrent(), value.getModified()); mMagicka->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
} }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value) void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value)
{ {
mFatigue->setValue(value.getCurrent(), value.getModified()); mFatigue->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
} }
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value) void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value)
{ {
std::map<int, MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId)); std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
if (attr == mAttributeWidgets.end()) if (attr == mAttributeWidgets.end())
return; return;
attr->second->setAttributeValue(value); attr->second->setAttributeValue(value);
} }
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value) void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
{ {
mSkillValues[skillId] = value; mSkillValues[skillId] = value;
MyGUI::TextBox* widget = mSkillWidgetMap[skillId]; MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
if (widget) if (widget)
@ -186,10 +180,10 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic
widget->_setWidgetState(state); widget->_setWidgetState(state);
} }
} }
void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vector<int>& minor) void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vector<int>& minor)
{ {
mMajorSkills = major; mMajorSkills = major;
mMinorSkills = minor; mMinorSkills = minor;
@ -207,10 +201,10 @@ void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vec
} }
updateSkillArea(); updateSkillArea();
} }
void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::ImageBox* separator = mSkillView->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); MyGUI::ImageBox* separator = mSkillView->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
@ -218,10 +212,10 @@ void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2
coord1.top += separator->getHeight(); coord1.top += separator->getHeight();
coord2.top += separator->getHeight(); coord2.top += separator->getHeight();
} }
void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* groupWidget = mSkillView->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); MyGUI::TextBox* groupWidget = mSkillView->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default);
groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel); groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
groupWidget->setCaption(label); groupWidget->setCaption(label);
@ -229,10 +223,10 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M
coord1.top += sLineHeight; coord1.top += sLineHeight;
coord2.top += sLineHeight; coord2.top += sLineHeight;
} }
MyGUI::TextBox* ReviewDialog::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) MyGUI::TextBox* ReviewDialog::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillNameWidget;
MyGUI::TextBox* skillValueWidget; MyGUI::TextBox* skillValueWidget;
@ -252,10 +246,10 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string& text, const std::s
coord2.top += sLineHeight; coord2.top += sLineHeight;
return skillValueWidget; return skillValueWidget;
} }
void ReviewDialog::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillNameWidget;
skillNameWidget = mSkillView->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget = mSkillView->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
@ -266,10 +260,10 @@ void ReviewDialog::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyG
coord1.top += sLineHeight; coord1.top += sLineHeight;
coord2.top += sLineHeight; coord2.top += sLineHeight;
} }
void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
// Add a line separator if there are items above // Add a line separator if there are items above
if (!mSkillWidgets.empty()) if (!mSkillWidgets.empty())
{ {
@ -304,10 +298,10 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId
mSkillWidgetMap[skillId] = widget; mSkillWidgetMap[skillId] = widget;
} }
} }
void ReviewDialog::updateSkillArea() void ReviewDialog::updateSkillArea()
{ {
for (std::vector<MyGUI::Widget*>::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) for (std::vector<MyGUI::Widget*>::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it)
{ {
MyGUI::Gui::getInstance().destroyWidget(*it); MyGUI::Gui::getInstance().destroyWidget(*it);
@ -330,44 +324,46 @@ void ReviewDialog::updateSkillArea()
mClientHeight = coord1.top; mClientHeight = coord1.top;
mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight));
} }
// widget controls // widget controls
void ReviewDialog::onOkClicked(MyGUI::Widget* _sender) void ReviewDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
eventDone(this); eventDone(this);
} }
void ReviewDialog::onBackClicked(MyGUI::Widget* _sender) void ReviewDialog::onBackClicked(MyGUI::Widget* _sender)
{ {
eventBack(); eventBack();
} }
void ReviewDialog::onNameClicked(MyGUI::Widget* _sender) void ReviewDialog::onNameClicked(MyGUI::Widget* _sender)
{ {
eventActivateDialog(NAME_DIALOG); eventActivateDialog(NAME_DIALOG);
} }
void ReviewDialog::onRaceClicked(MyGUI::Widget* _sender) void ReviewDialog::onRaceClicked(MyGUI::Widget* _sender)
{ {
eventActivateDialog(RACE_DIALOG); eventActivateDialog(RACE_DIALOG);
} }
void ReviewDialog::onClassClicked(MyGUI::Widget* _sender) void ReviewDialog::onClassClicked(MyGUI::Widget* _sender)
{ {
eventActivateDialog(CLASS_DIALOG); eventActivateDialog(CLASS_DIALOG);
} }
void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender) void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender)
{ {
eventActivateDialog(BIRTHSIGN_DIALOG); eventActivateDialog(BIRTHSIGN_DIALOG);
} }
void ReviewDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel) void ReviewDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{ {
if (mSkillView->getViewOffset().top + _rel*0.3 > 0) if (mSkillView->getViewOffset().top + _rel*0.3 > 0)
mSkillView->setViewOffset(MyGUI::IntPoint(0, 0)); mSkillView->setViewOffset(MyGUI::IntPoint(0, 0));
else else
mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3)); mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3));
}
} }

View file

@ -10,13 +10,14 @@
#include "formatting.hpp" #include "formatting.hpp"
using namespace MWGui; namespace MWGui
{
ScrollWindow::ScrollWindow () ScrollWindow::ScrollWindow ()
: WindowBase("openmw_scroll.layout") : WindowBase("openmw_scroll.layout")
, mTakeButtonShow(true) , mTakeButtonShow(true)
, mTakeButtonAllowed(true) , mTakeButtonAllowed(true)
{ {
getWidget(mTextView, "TextView"); getWidget(mTextView, "TextView");
getWidget(mCloseButton, "CloseButton"); getWidget(mCloseButton, "CloseButton");
@ -26,10 +27,10 @@ ScrollWindow::ScrollWindow ()
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ScrollWindow::onTakeButtonClicked); mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ScrollWindow::onTakeButtonClicked);
center(); center();
} }
void ScrollWindow::open (MWWorld::Ptr scroll) void ScrollWindow::open (MWWorld::Ptr scroll)
{ {
// no 3d sounds because the object could be in a container. // no 3d sounds because the object could be in a container.
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
@ -48,33 +49,34 @@ void ScrollWindow::open (MWWorld::Ptr scroll)
mTextView->setViewOffset(MyGUI::IntPoint(0,0)); mTextView->setViewOffset(MyGUI::IntPoint(0,0));
setTakeButtonShow(true); setTakeButtonShow(true);
} }
void ScrollWindow::setTakeButtonShow(bool show) void ScrollWindow::setTakeButtonShow(bool show)
{ {
mTakeButtonShow = show; mTakeButtonShow = show;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
} }
void ScrollWindow::setInventoryAllowed(bool allowed) void ScrollWindow::setInventoryAllowed(bool allowed)
{ {
mTakeButtonAllowed = allowed; mTakeButtonAllowed = allowed;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed); mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
} }
void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll);
} }
void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack); MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack);
MWWorld::ActionTake take(mScroll); MWWorld::ActionTake take(mScroll);
take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll);
}
} }

View file

@ -1,24 +1,18 @@
#include "settingswindow.hpp" #include "settingswindow.hpp"
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreRenderSystem.h>
#include <OgrePlugin.h> #include <OgrePlugin.h>
#include <OgreString.h>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/math/common_factor_rt.hpp> #include <boost/math/common_factor_rt.hpp>
#include <components/settings/settings.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"
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwrender/renderingmanager.hpp"
#include "confirmationdialog.hpp" #include "confirmationdialog.hpp"
namespace namespace

View file

@ -1,6 +1,5 @@
#include "soulgemdialog.hpp" #include "soulgemdialog.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "messagebox.hpp" #include "messagebox.hpp"

View file

@ -1,7 +1,5 @@
#include "spellbuyingwindow.hpp" #include "spellbuyingwindow.hpp"
#include <algorithm>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -11,9 +9,7 @@
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"

View file

@ -4,22 +4,14 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/spellsuccess.hpp" #include "../mwmechanics/spellsuccess.hpp"
#include "tooltips.hpp" #include "tooltips.hpp"
#include "widgets.hpp"
#include "class.hpp" #include "class.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "tradewindow.hpp" #include "tradewindow.hpp"

View file

@ -1,9 +1,5 @@
#include "spellicons.hpp" #include "spellicons.hpp"
#include <MyGUI_Widget.h>
#include <MyGUI_Gui.h>
#include <MyGUI_ImageBox.h>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -14,7 +10,6 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwmechanics/activespells.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "tooltips.hpp" #include "tooltips.hpp"

View file

@ -1,22 +1,14 @@
#include "spellwindow.hpp" #include "spellwindow.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/actionequip.hpp" #include "../mwworld/actionequip.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/spellsuccess.hpp" #include "../mwmechanics/spellsuccess.hpp"
#include "spellicons.hpp" #include "spellicons.hpp"

View file

@ -1,14 +1,9 @@
#include "statswindow.hpp" #include "statswindow.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
@ -18,11 +13,12 @@
#include "tooltips.hpp" #include "tooltips.hpp"
namespace MWGui
{
using namespace MWGui; const int StatsWindow::sLineHeight = 18;
const int StatsWindow::sLineHeight = 18;
StatsWindow::StatsWindow () StatsWindow::StatsWindow ()
: WindowPinnableBase("openmw_stats_window.layout") : WindowPinnableBase("openmw_stats_window.layout")
, mSkillView(NULL) , mSkillView(NULL)
, mClientHeight(0) , mClientHeight(0)
@ -38,7 +34,7 @@ StatsWindow::StatsWindow ()
, mBounty(0) , mBounty(0)
, mSkillWidgets() , mSkillWidgets()
, mChanged(true) , mChanged(true)
{ {
setCoord(0,0,498, 342); setCoord(0,0,498, 342);
const char *names[][2] = const char *names[][2] =
@ -72,25 +68,25 @@ StatsWindow::StatsWindow ()
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget); MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
} }
void StatsWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) void StatsWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{ {
if (mSkillView->getViewOffset().top + _rel*0.3 > 0) if (mSkillView->getViewOffset().top + _rel*0.3 > 0)
mSkillView->setViewOffset(MyGUI::IntPoint(0, 0)); mSkillView->setViewOffset(MyGUI::IntPoint(0, 0));
else else
mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3)); mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3));
} }
void StatsWindow::onWindowResize(MyGUI::Window* window) void StatsWindow::onWindowResize(MyGUI::Window* window)
{ {
mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) ); mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) );
mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) ); mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) );
mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight));
} }
void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max) void StatsWindow::setBar(const std::string& name, const std::string& tname, int val, int max)
{ {
MyGUI::ProgressPtr pt; MyGUI::ProgressPtr pt;
getWidget(pt, name); getWidget(pt, name);
pt->setProgressRange(max); pt->setProgressRange(max);
@ -99,16 +95,16 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int
std::stringstream out; std::stringstream out;
out << val << "/" << max; out << val << "/" << max;
setText(tname, out.str().c_str()); setText(tname, out.str().c_str());
} }
void StatsWindow::setPlayerName(const std::string& playerName) void StatsWindow::setPlayerName(const std::string& playerName)
{ {
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(playerName); static_cast<MyGUI::Window*>(mMainWidget)->setCaption(playerName);
adjustWindowCaption(); adjustWindowCaption();
} }
void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value) void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
@ -135,10 +131,10 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>&
break; break;
} }
} }
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {
"HBar", "MBar", "FBar", "HBar", "MBar", "FBar",
@ -172,30 +168,30 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicSta
} }
} }
} }
} }
void StatsWindow::setValue (const std::string& id, const std::string& value) void StatsWindow::setValue (const std::string& id, const std::string& value)
{ {
if (id=="name") if (id=="name")
setPlayerName (value); setPlayerName (value);
else if (id=="race") else if (id=="race")
setText ("RaceText", value); setText ("RaceText", value);
else if (id=="class") else if (id=="class")
setText ("ClassText", value); setText ("ClassText", value);
} }
void StatsWindow::setValue (const std::string& id, int value) void StatsWindow::setValue (const std::string& id, int value)
{ {
if (id=="level") if (id=="level")
{ {
std::ostringstream text; std::ostringstream text;
text << value; text << value;
setText("LevelText", text.str()); setText("LevelText", text.str());
} }
} }
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value) void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
{ {
mSkillValues[parSkill] = value; mSkillValues[parSkill] = value;
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill]; MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
if (widget) if (widget)
@ -211,10 +207,10 @@ void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechani
widget->setCaption(text); widget->setCaption(text);
widget->_setWidgetState(state); widget->_setWidgetState(state);
} }
} }
void StatsWindow::configureSkills (const std::vector<int>& major, const std::vector<int>& minor) void StatsWindow::configureSkills (const std::vector<int>& major, const std::vector<int>& minor)
{ {
mMajorSkills = major; mMajorSkills = major;
mMinorSkills = minor; mMinorSkills = minor;
@ -232,10 +228,10 @@ void StatsWindow::configureSkills (const std::vector<int>& major, const std::vec
} }
updateSkillArea(); updateSkillArea();
} }
void StatsWindow::onFrame () void StatsWindow::onFrame ()
{ {
if (!mMainWidget->getVisible()) if (!mMainWidget->getVisible())
return; return;
@ -263,37 +259,37 @@ void StatsWindow::onFrame ()
if (mChanged) if (mChanged)
updateSkillArea(); updateSkillArea();
} }
void StatsWindow::setFactions (const FactionList& factions) void StatsWindow::setFactions (const FactionList& factions)
{ {
if (mFactions != factions) if (mFactions != factions)
{ {
mFactions = factions; mFactions = factions;
mChanged = true; mChanged = true;
} }
} }
void StatsWindow::setExpelled (const std::set<std::string>& expelled) void StatsWindow::setExpelled (const std::set<std::string>& expelled)
{ {
if (mExpelled != expelled) if (mExpelled != expelled)
{ {
mExpelled = expelled; mExpelled = expelled;
mChanged = true; mChanged = true;
} }
} }
void StatsWindow::setBirthSign (const std::string& signId) void StatsWindow::setBirthSign (const std::string& signId)
{ {
if (signId != mBirthSignId) if (signId != mBirthSignId)
{ {
mBirthSignId = signId; mBirthSignId = signId;
mChanged = true; mChanged = true;
} }
} }
void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::ImageBox* separator = mSkillView->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::ImageBox* separator = mSkillView->createWidget<MyGUI::ImageBox>("MW_HLine",
MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
@ -302,10 +298,10 @@ void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
coord1.top += separator->getHeight(); coord1.top += separator->getHeight();
coord2.top += separator->getHeight(); coord2.top += separator->getHeight();
} }
void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* groupWidget = mSkillView->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::TextBox* groupWidget = mSkillView->createWidget<MyGUI::TextBox>("SandBrightText",
MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
@ -315,10 +311,10 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My
coord1.top += sLineHeight; coord1.top += sLineHeight;
coord2.top += sLineHeight; coord2.top += sLineHeight;
} }
MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox *skillNameWidget, *skillValueWidget; MyGUI::TextBox *skillNameWidget, *skillValueWidget;
skillNameWidget = mSkillView->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); skillNameWidget = mSkillView->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
@ -337,10 +333,10 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st
coord2.top += sLineHeight; coord2.top += sLineHeight;
return skillValueWidget; return skillValueWidget;
} }
MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillNameWidget;
skillNameWidget = mSkillView->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget = mSkillView->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
@ -353,10 +349,10 @@ MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &co
coord2.top += sLineHeight; coord2.top += sLineHeight;
return skillNameWidget; return skillNameWidget;
} }
void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
// Add a line separator if there are items above // Add a line separator if there are items above
if (!mSkillWidgets.empty()) if (!mSkillWidgets.empty())
{ {
@ -413,10 +409,10 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId,
mSkillWidgetMap[skillId] = widget; mSkillWidgetMap[skillId] = widget;
} }
} }
void StatsWindow::updateSkillArea() void StatsWindow::updateSkillArea()
{ {
mChanged = false; mChanged = false;
for (std::vector<MyGUI::Widget*>::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it) for (std::vector<MyGUI::Widget*>::iterator it = mSkillWidgets.begin(); it != mSkillWidgets.end(); ++it)
@ -572,9 +568,10 @@ void StatsWindow::updateSkillArea()
mClientHeight = coord1.top; mClientHeight = coord1.top;
mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight)); mSkillView->setCanvasSize (mSkillView->getWidth(), std::max(mSkillView->getHeight(), mClientHeight));
} }
void StatsWindow::onPinToggled() void StatsWindow::onPinToggled()
{ {
MWBase::Environment::get().getWindowManager()->setHMSVisibility(!mPinned); MWBase::Environment::get().getWindowManager()->setHMSVisibility(!mPinned);
}
} }

View file

@ -3,11 +3,12 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
using namespace MWGui; namespace MWGui
TextInputDialog::TextInputDialog()
: WindowModal("openmw_text_input.layout")
{ {
TextInputDialog::TextInputDialog()
: WindowModal("openmw_text_input.layout")
{
// Centre dialog // Centre dialog
center(); center();
@ -20,10 +21,10 @@ TextInputDialog::TextInputDialog()
// Make sure the edit box has focus // Make sure the edit box has focus
MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
void TextInputDialog::setNextButtonShow(bool shown) void TextInputDialog::setNextButtonShow(bool shown)
{ {
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
@ -31,24 +32,24 @@ void TextInputDialog::setNextButtonShow(bool shown)
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", ""));
else else
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
} }
void TextInputDialog::setTextLabel(const std::string &label) void TextInputDialog::setTextLabel(const std::string &label)
{ {
setText("LabelT", label); setText("LabelT", label);
} }
void TextInputDialog::open() void TextInputDialog::open()
{ {
WindowModal::open(); WindowModal::open();
// Make sure the edit box has focus // Make sure the edit box has focus
MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
// widget controls // widget controls
void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) void TextInputDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
if (mTextEdit->getCaption() == "") if (mTextEdit->getCaption() == "")
{ {
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}");
@ -56,10 +57,10 @@ void TextInputDialog::onOkClicked(MyGUI::Widget* _sender)
} }
else else
eventDone(this); eventDone(this);
} }
void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender)
{ {
if (mTextEdit->getCaption() == "") if (mTextEdit->getCaption() == "")
{ {
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}");
@ -67,4 +68,6 @@ void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender)
} }
else else
eventDone(this); eventDone(this);
}
} }

View file

@ -2,24 +2,17 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <OgreResourceGroupManager.h>
#include <components/settings/settings.hpp>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/class.hpp"
#include "mapwindow.hpp" #include "mapwindow.hpp"
#include "widgets.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
using namespace MWGui; namespace MWGui
using namespace MyGUI; {
ToolTips::ToolTips() : ToolTips::ToolTips() :
Layout("openmw_tooltips.layout") Layout("openmw_tooltips.layout")
, mGameMode(true) , mGameMode(true)
, mFullHelp(false) , mFullHelp(false)
@ -31,7 +24,7 @@ ToolTips::ToolTips() :
, mLastMouseX(0) , mLastMouseX(0)
, mLastMouseY(0) , mLastMouseY(0)
, mHorizontalScrollIndex(0) , mHorizontalScrollIndex(0)
{ {
getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
mDynamicToolTipBox->setVisible(false); mDynamicToolTipBox->setVisible(false);
@ -48,15 +41,15 @@ ToolTips::ToolTips() :
{ {
mMainWidget->getChildAt(i)->setVisible(false); mMainWidget->getChildAt(i)->setVisible(false);
} }
} }
void ToolTips::setEnabled(bool enabled) void ToolTips::setEnabled(bool enabled)
{ {
mEnabled = enabled; mEnabled = enabled;
} }
void ToolTips::onFrame(float frameDuration) void ToolTips::onFrame(float frameDuration)
{ {
while (mDynamicToolTipBox->getChildCount()) while (mDynamicToolTipBox->getChildCount())
{ {
@ -69,7 +62,7 @@ void ToolTips::onFrame(float frameDuration)
mMainWidget->getChildAt(i)->setVisible(false); mMainWidget->getChildAt(i)->setVisible(false);
} }
const IntSize &viewSize = RenderManager::getInstance().getViewSize(); const MyGUI::IntSize &viewSize = MyGUI::RenderManager::getInstance().getViewSize();
if (!mEnabled) if (!mEnabled)
{ {
@ -78,7 +71,7 @@ void ToolTips::onFrame(float frameDuration)
if (!mGameMode) if (!mGameMode)
{ {
const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition(); const MyGUI::IntPoint& mousePos = MyGUI::InputManager::getInstance().getMousePosition();
if (MWBase::Environment::get().getWindowManager()->getWorldMouseOver() && ((MWBase::Environment::get().getWindowManager()->getMode() == GM_Console) if (MWBase::Environment::get().getWindowManager()->getWorldMouseOver() && ((MWBase::Environment::get().getWindowManager()->getMode() == GM_Console)
|| (MWBase::Environment::get().getWindowManager()->getMode() == GM_Container) || (MWBase::Environment::get().getWindowManager()->getMode() == GM_Container)
@ -91,7 +84,7 @@ void ToolTips::onFrame(float frameDuration)
const MWWorld::Class& objectclass = MWWorld::Class::get (mFocusObject); const MWWorld::Class& objectclass = MWWorld::Class::get (mFocusObject);
IntSize tooltipSize; MyGUI::IntSize tooltipSize;
if ((!objectclass.hasToolTip(mFocusObject))&&(MWBase::Environment::get().getWindowManager()->getMode() == GM_Console)) if ((!objectclass.hasToolTip(mFocusObject))&&(MWBase::Environment::get().getWindowManager()->getMode() == GM_Console))
{ {
setCoord(0, 0, 300, 300); setCoord(0, 0, 300, 300);
@ -104,7 +97,7 @@ void ToolTips::onFrame(float frameDuration)
else else
tooltipSize = getToolTipViaPtr(true); tooltipSize = getToolTipViaPtr(true);
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); MyGUI::IntPoint tooltipPosition = MyGUI::InputManager::getInstance().getMousePosition() + MyGUI::IntPoint(0, 24);
// make the tooltip stay completely in the viewport // make the tooltip stay completely in the viewport
if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) if ((tooltipPosition.left + tooltipSize.width) > viewSize.width)
@ -121,7 +114,7 @@ void ToolTips::onFrame(float frameDuration)
else else
{ {
const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left); const MyGUI::IntPoint& lastPressed = MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
if (mousePos == lastPressed) // mouseclick makes tooltip disappear if (mousePos == lastPressed) // mouseclick makes tooltip disappear
return; return;
@ -142,11 +135,11 @@ void ToolTips::onFrame(float frameDuration)
if (mRemainingDelay > 0) if (mRemainingDelay > 0)
return; return;
Widget* focus = InputManager::getInstance().getMouseFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getMouseFocusWidget();
if (focus == 0) if (focus == 0)
return; return;
IntSize tooltipSize; MyGUI::IntSize tooltipSize;
// try to go 1 level up until there is a widget that has tooltip // try to go 1 level up until there is a widget that has tooltip
// this is necessary because some skin elements are actually separate widgets // this is necessary because some skin elements are actually separate widgets
@ -259,7 +252,7 @@ void ToolTips::onFrame(float frameDuration)
else else
throw std::runtime_error ("unknown tooltip type"); throw std::runtime_error ("unknown tooltip type");
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24); MyGUI::IntPoint tooltipPosition = MyGUI::InputManager::getInstance().getMousePosition() + MyGUI::IntPoint(0, 24);
// make the tooltip stay completely in the viewport // make the tooltip stay completely in the viewport
if ((tooltipPosition.left + tooltipSize.width) > viewSize.width) if ((tooltipPosition.left + tooltipSize.width) > viewSize.width)
@ -278,7 +271,7 @@ void ToolTips::onFrame(float frameDuration)
{ {
if (!mFocusObject.isEmpty()) if (!mFocusObject.isEmpty())
{ {
IntSize tooltipSize = getToolTipViaPtr(); MyGUI::IntSize tooltipSize = getToolTipViaPtr();
setCoord(viewSize.width/2 - tooltipSize.width/2, setCoord(viewSize.width/2 - tooltipSize.width/2,
std::max(0, int(mFocusToolTipY*viewSize.height - tooltipSize.height)), std::max(0, int(mFocusToolTipY*viewSize.height - tooltipSize.height)),
@ -288,29 +281,29 @@ void ToolTips::onFrame(float frameDuration)
mDynamicToolTipBox->setVisible(true); mDynamicToolTipBox->setVisible(true);
} }
} }
} }
void ToolTips::enterGameMode() void ToolTips::enterGameMode()
{ {
mGameMode = true; mGameMode = true;
} }
void ToolTips::enterGuiMode() void ToolTips::enterGuiMode()
{ {
mGameMode = false; mGameMode = false;
} }
void ToolTips::setFocusObject(const MWWorld::Ptr& focus) void ToolTips::setFocusObject(const MWWorld::Ptr& focus)
{ {
mFocusObject = focus; mFocusObject = focus;
} }
IntSize ToolTips::getToolTipViaPtr (bool image) MyGUI::IntSize ToolTips::getToolTipViaPtr (bool image)
{ {
// this the maximum width of the tooltip before it starts word-wrapping // this the maximum width of the tooltip before it starts word-wrapping
setCoord(0, 0, 300, 300); setCoord(0, 0, 300, 300);
IntSize tooltipSize; MyGUI::IntSize tooltipSize;
const MWWorld::Class& object = MWWorld::Class::get (mFocusObject); const MWWorld::Class& object = MWWorld::Class::get (mFocusObject);
if (!object.hasToolTip(mFocusObject)) if (!object.hasToolTip(mFocusObject))
@ -328,10 +321,10 @@ IntSize ToolTips::getToolTipViaPtr (bool image)
} }
return tooltipSize; return tooltipSize;
} }
void ToolTips::findImageExtension(std::string& image) void ToolTips::findImageExtension(std::string& image)
{ {
int len = image.size(); int len = image.size();
if (len < 4) return; if (len < 4) return;
@ -342,10 +335,10 @@ void ToolTips::findImageExtension(std::string& image)
image[len-2] = 'd'; image[len-2] = 'd';
image[len-1] = 's'; image[len-1] = 's';
} }
} }
IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info) MyGUI::IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
{ {
mDynamicToolTipBox->setVisible(true); mDynamicToolTipBox->setVisible(true);
std::string caption = info.caption; std::string caption = info.caption;
@ -378,7 +371,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
// this the maximum width of the tooltip before it starts word-wrapping // this the maximum width of the tooltip before it starts word-wrapping
setCoord(0, 0, 300, 300); setCoord(0, 0, 300, 300);
const IntPoint padding(8, 8); const MyGUI::IntPoint padding(8, 8);
const int maximumWidth = 500; const int maximumWidth = 500;
@ -388,32 +381,32 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
std::string realImage = "icons\\" + image; std::string realImage = "icons\\" + image;
findImageExtension(realImage); findImageExtension(realImage);
EditBox* captionWidget = mDynamicToolTipBox->createWidget<EditBox>("NormalText", IntCoord(0, 0, 300, 300), Align::Left | Align::Top, "ToolTipCaption"); MyGUI::EditBox* captionWidget = mDynamicToolTipBox->createWidget<MyGUI::EditBox>("NormalText", MyGUI::IntCoord(0, 0, 300, 300), MyGUI::Align::Left | MyGUI::Align::Top, "ToolTipCaption");
captionWidget->setProperty("Static", "true"); captionWidget->setProperty("Static", "true");
captionWidget->setCaptionWithReplacing(caption); captionWidget->setCaptionWithReplacing(caption);
IntSize captionSize = captionWidget->getTextSize(); MyGUI::IntSize captionSize = captionWidget->getTextSize();
int captionHeight = std::max(caption != "" ? captionSize.height : 0, imageSize); int captionHeight = std::max(caption != "" ? captionSize.height : 0, imageSize);
EditBox* textWidget = mDynamicToolTipBox->createWidget<EditBox>("SandText", IntCoord(0, captionHeight+imageCaptionVPadding, 300, 300-captionHeight-imageCaptionVPadding), Align::Stretch, "ToolTipText"); MyGUI::EditBox* textWidget = mDynamicToolTipBox->createWidget<MyGUI::EditBox>("SandText", MyGUI::IntCoord(0, captionHeight+imageCaptionVPadding, 300, 300-captionHeight-imageCaptionVPadding), MyGUI::Align::Stretch, "ToolTipText");
textWidget->setProperty("Static", "true"); textWidget->setProperty("Static", "true");
textWidget->setProperty("MultiLine", "true"); textWidget->setProperty("MultiLine", "true");
textWidget->setProperty("WordWrap", info.wordWrap ? "true" : "false"); textWidget->setProperty("WordWrap", info.wordWrap ? "true" : "false");
textWidget->setCaptionWithReplacing(text); textWidget->setCaptionWithReplacing(text);
textWidget->setTextAlign(Align::HCenter | Align::Top); textWidget->setTextAlign(MyGUI::Align::HCenter | MyGUI::Align::Top);
IntSize textSize = textWidget->getTextSize(); MyGUI::IntSize textSize = textWidget->getTextSize();
captionSize += IntSize(imageSize, 0); // adjust for image captionSize += MyGUI::IntSize(imageSize, 0); // adjust for image
IntSize totalSize = IntSize( std::min(std::max(textSize.width,captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),maximumWidth), MyGUI::IntSize totalSize = MyGUI::IntSize( std::min(std::max(textSize.width,captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),maximumWidth),
((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight ); ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
if (!info.effects.empty()) if (!info.effects.empty())
{ {
Widget* effectArea = mDynamicToolTipBox->createWidget<Widget>("", MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
IntCoord(0, totalSize.height, 300, 300-totalSize.height), MyGUI::IntCoord(0, totalSize.height, 300, 300-totalSize.height),
Align::Stretch, "ToolTipEffectArea"); MyGUI::Align::Stretch, "ToolTipEffectArea");
IntCoord coord(0, 6, totalSize.width, 24); MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
/** /**
* \todo * \todo
@ -422,7 +415,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
*/ */
Widgets::MWEffectListPtr effectsWidget = effectArea->createWidget<Widgets::MWEffectList> Widgets::MWEffectListPtr effectsWidget = effectArea->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, Align::Default, "ToolTipEffectsWidget"); ("MW_StatName", coord, MyGUI::Align::Default, "ToolTipEffectsWidget");
effectsWidget->setEffectList(info.effects); effectsWidget->setEffectList(info.effects);
std::vector<MyGUI::Widget*> effectItems; std::vector<MyGUI::Widget*> effectItems;
@ -434,14 +427,14 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
if (info.enchant != "") if (info.enchant != "")
{ {
assert(enchant); assert(enchant);
Widget* enchantArea = mDynamicToolTipBox->createWidget<Widget>("", MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
IntCoord(0, totalSize.height, 300, 300-totalSize.height), MyGUI::IntCoord(0, totalSize.height, 300, 300-totalSize.height),
Align::Stretch, "ToolTipEnchantArea"); MyGUI::Align::Stretch, "ToolTipEnchantArea");
IntCoord coord(0, 6, totalSize.width, 24); MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList> Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget"); ("MW_StatName", coord, MyGUI::Align::Default, "ToolTipEnchantWidget");
enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->mEffects)); enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->mEffects));
std::vector<MyGUI::Widget*> enchantEffectItems; std::vector<MyGUI::Widget*> enchantEffectItems;
@ -458,7 +451,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
const int chargeWidth = 204; const int chargeWidth = 204;
TextBox* chargeText = enchantArea->createWidget<TextBox>("SandText", IntCoord(0, 0, 10, 18), Align::Default, "ToolTipEnchantChargeText"); MyGUI::TextBox* chargeText = enchantArea->createWidget<MyGUI::TextBox>("SandText", MyGUI::IntCoord(0, 0, 10, 18), MyGUI::Align::Default, "ToolTipEnchantChargeText");
chargeText->setCaptionWithReplacing("#{sCharges}"); chargeText->setCaptionWithReplacing("#{sCharges}");
const int chargeTextWidth = chargeText->getTextSize().width + 5; const int chargeTextWidth = chargeText->getTextSize().width + 5;
@ -469,18 +462,18 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
chargeText->setCoord((totalSize.width - chargeAndTextWidth)/2, coord.top+6, chargeTextWidth, 18); chargeText->setCoord((totalSize.width - chargeAndTextWidth)/2, coord.top+6, chargeTextWidth, 18);
IntCoord chargeCoord; MyGUI::IntCoord chargeCoord;
if (totalSize.width < chargeWidth) if (totalSize.width < chargeWidth)
{ {
totalSize.width = chargeWidth; totalSize.width = chargeWidth;
chargeCoord = IntCoord(0, coord.top+6, chargeWidth, 18); chargeCoord = MyGUI::IntCoord(0, coord.top+6, chargeWidth, 18);
} }
else else
{ {
chargeCoord = IntCoord((totalSize.width - chargeAndTextWidth)/2 + chargeTextWidth, coord.top+6, chargeWidth, 18); chargeCoord = MyGUI::IntCoord((totalSize.width - chargeAndTextWidth)/2 + chargeTextWidth, coord.top+6, chargeWidth, 18);
} }
Widgets::MWDynamicStatPtr chargeWidget = enchantArea->createWidget<Widgets::MWDynamicStat> Widgets::MWDynamicStatPtr chargeWidget = enchantArea->createWidget<Widgets::MWDynamicStat>
("MW_ChargeBar", chargeCoord, Align::Default, "ToolTipEnchantCharge"); ("MW_ChargeBar", chargeCoord, MyGUI::Align::Default, "ToolTipEnchantCharge");
chargeWidget->setValue(charge, charge); chargeWidget->setValue(charge, charge);
totalSize.height += 24; totalSize.height += 24;
} }
@ -504,83 +497,83 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
}else{ }else{
horizontal_scroll = 80 - mHorizontalScrollIndex; horizontal_scroll = 80 - mHorizontalScrollIndex;
} }
captionWidget->setPosition (IntPoint(horizontal_scroll, captionWidget->getPosition().top + padding.top)); captionWidget->setPosition (MyGUI::IntPoint(horizontal_scroll, captionWidget->getPosition().top + padding.top));
} else { } else {
captionWidget->setPosition (captionWidget->getPosition() + padding); captionWidget->setPosition (captionWidget->getPosition() + padding);
} }
textWidget->setPosition (textWidget->getPosition() + IntPoint(0, padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter textWidget->setPosition (textWidget->getPosition() + MyGUI::IntPoint(0, padding.top)); // only apply vertical padding, the horizontal works automatically due to Align::HCenter
if (image != "") if (image != "")
{ {
ImageBox* imageWidget = mDynamicToolTipBox->createWidget<ImageBox>("ImageBox", MyGUI::ImageBox* imageWidget = mDynamicToolTipBox->createWidget<MyGUI::ImageBox>("ImageBox",
IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize), MyGUI::IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize),
Align::Left | Align::Top, "ToolTipImage"); MyGUI::Align::Left | MyGUI::Align::Top, "ToolTipImage");
imageWidget->setImageTexture(realImage); imageWidget->setImageTexture(realImage);
imageWidget->setPosition (imageWidget->getPosition() + padding); imageWidget->setPosition (imageWidget->getPosition() + padding);
} }
totalSize += IntSize(padding.left*2, padding.top*2); totalSize += MyGUI::IntSize(padding.left*2, padding.top*2);
return totalSize; return totalSize;
} }
std::string ToolTips::toString(const float value) std::string ToolTips::toString(const float value)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << std::setprecision(3) << value; stream << std::setprecision(3) << value;
return stream.str(); return stream.str();
} }
std::string ToolTips::toString(const int value) std::string ToolTips::toString(const int value)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << value; stream << value;
return stream.str(); return stream.str();
} }
std::string ToolTips::getValueString(const int value, const std::string& prefix) std::string ToolTips::getValueString(const int value, const std::string& prefix)
{ {
if (value == 0) if (value == 0)
return ""; return "";
else else
return "\n" + prefix + ": " + toString(value); return "\n" + prefix + ": " + toString(value);
} }
std::string ToolTips::getMiscString(const std::string& text, const std::string& prefix) std::string ToolTips::getMiscString(const std::string& text, const std::string& prefix)
{ {
if (text == "") if (text == "")
return ""; return "";
else else
return "\n" + prefix + ": " + text; return "\n" + prefix + ": " + text;
} }
std::string ToolTips::getCountString(const int value) std::string ToolTips::getCountString(const int value)
{ {
if (value == 1) if (value == 1)
return ""; return "";
else else
return " (" + boost::lexical_cast<std::string>(value) + ")"; return " (" + boost::lexical_cast<std::string>(value) + ")";
} }
void ToolTips::toggleFullHelp() void ToolTips::toggleFullHelp()
{ {
mFullHelp = !mFullHelp; mFullHelp = !mFullHelp;
} }
bool ToolTips::getFullHelp() const bool ToolTips::getFullHelp() const
{ {
return mFullHelp; return mFullHelp;
} }
void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y)
{ {
mFocusToolTipX = (min_x + max_x) / 2; mFocusToolTipX = (min_x + max_x) / 2;
mFocusToolTipY = min_y; mFocusToolTipY = min_y;
} }
void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId) void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId)
{ {
if (skillId == -1) if (skillId == -1)
return; return;
@ -602,10 +595,10 @@ void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId)
widget->setUserString("Caption_SkillNoProgressDescription", skill->mDescription); widget->setUserString("Caption_SkillNoProgressDescription", skill->mDescription);
widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->mName + "}"); widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->mName + "}");
widget->setUserString("ImageTexture_SkillNoProgressImage", icon); widget->setUserString("ImageTexture_SkillNoProgressImage", icon);
} }
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId) void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId)
{ {
if (attributeId == -1) if (attributeId == -1)
return; return;
@ -618,10 +611,10 @@ void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId)
widget->setUserString("Caption_AttributeName", "#{"+name+"}"); widget->setUserString("Caption_AttributeName", "#{"+name+"}");
widget->setUserString("Caption_AttributeDescription", "#{"+desc+"}"); widget->setUserString("Caption_AttributeDescription", "#{"+desc+"}");
widget->setUserString("ImageTexture_AttributeImage", icon); widget->setUserString("ImageTexture_AttributeImage", icon);
} }
void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId) void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId)
{ {
widget->setUserString("Caption_CenteredCaption", name); widget->setUserString("Caption_CenteredCaption", name);
std::string specText; std::string specText;
// get all skills of this specialisation // get all skills of this specialisation
@ -637,10 +630,10 @@ void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::str
widget->setUserString("Caption_CenteredCaptionText", specText); widget->setUserString("Caption_CenteredCaptionText", specText);
widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip");
widget->setUserString("ToolTipType", "Layout"); widget->setUserString("ToolTipType", "Layout");
} }
void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId) void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId)
{ {
const MWWorld::ESMStore &store = const MWWorld::ESMStore &store =
MWBase::Environment::get().getWorld()->getStore(); MWBase::Environment::get().getWorld()->getStore();
@ -705,18 +698,18 @@ void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string&
} }
widget->setUserString("Caption_BirthSignText", text); widget->setUserString("Caption_BirthSignText", text);
} }
void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace) void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace)
{ {
widget->setUserString("Caption_CenteredCaption", playerRace->mName); widget->setUserString("Caption_CenteredCaption", playerRace->mName);
widget->setUserString("Caption_CenteredCaptionText", playerRace->mDescription); widget->setUserString("Caption_CenteredCaptionText", playerRace->mDescription);
widget->setUserString("ToolTipType", "Layout"); widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip"); widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip");
} }
void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass) void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass)
{ {
if (playerClass.mName == "") if (playerClass.mName == "")
return; return;
@ -734,10 +727,10 @@ void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playe
widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr); widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
widget->setUserString("ToolTipType", "Layout"); widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "ClassToolTip"); widget->setUserString("ToolTipLayout", "ClassToolTip");
} }
void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id) void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id)
{ {
const ESM::MagicEffect* effect = const ESM::MagicEffect* effect =
MWBase::Environment::get().getWorld ()->getStore ().get<ESM::MagicEffect>().find(id); MWBase::Environment::get().getWorld ()->getStore ().get<ESM::MagicEffect>().find(id);
const std::string &name = ESM::MagicEffect::effectIdToString (id); const std::string &name = ESM::MagicEffect::effectIdToString (id);
@ -767,10 +760,12 @@ void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id)
widget->setUserString("Caption_MagicEffectDescription", effect->mDescription); widget->setUserString("Caption_MagicEffectDescription", effect->mDescription);
widget->setUserString("Caption_MagicEffectSchool", "#{sSchool}: " + schools[effect->mData.mSchool]); widget->setUserString("Caption_MagicEffectSchool", "#{sSchool}: " + schools[effect->mData.mSchool]);
widget->setUserString("ImageTexture_MagicEffectImage", icon); widget->setUserString("ImageTexture_MagicEffectImage", icon);
} }
void ToolTips::setDelay(float delay) void ToolTips::setDelay(float delay)
{ {
mDelay = delay; mDelay = delay;
mRemainingDelay = mDelay; mRemainingDelay = mDelay;
}
} }

View file

@ -9,7 +9,6 @@
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/dialoguemanager.hpp" #include "../mwbase/dialoguemanager.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"

View file

@ -1,22 +1,15 @@
#include "travelwindow.hpp" #include "travelwindow.hpp"
#include <algorithm>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <libs/openengine/ogre/fader.hpp> #include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "tradewindow.hpp" #include "tradewindow.hpp"

View file

@ -1,7 +1,5 @@
#include "waitdialog.hpp" #include "waitdialog.hpp"
#include <cmath>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <libs/openengine/ogre/fader.hpp> #include <libs/openengine/ogre/fader.hpp>
@ -11,9 +9,7 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/timestamp.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"

View file

@ -9,61 +9,61 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwworld/esmstore.hpp"
#undef min #undef min
#undef max #undef max
using namespace MWGui; namespace MWGui
using namespace MWGui::Widgets; {
namespace Widgets
{
/* Helper functions */ /* Helper functions */
/* /*
* Fixes the filename of a texture path to use the correct .dds extension. * Fixes the filename of a texture path to use the correct .dds extension.
* This is needed on some ESM entries which point to a .tga file instead. * This is needed on some ESM entries which point to a .tga file instead.
*/ */
void MWGui::Widgets::fixTexturePath(std::string &path) void fixTexturePath(std::string &path)
{ {
int offset = path.rfind("."); int offset = path.rfind(".");
if (offset < 0) if (offset < 0)
return; return;
path.replace(offset, path.length() - offset, ".dds"); path.replace(offset, path.length() - offset, ".dds");
} }
/* MWSkill */ /* MWSkill */
MWSkill::MWSkill() MWSkill::MWSkill()
: mSkillId(ESM::Skill::Length) : mSkillId(ESM::Skill::Length)
, mSkillNameWidget(NULL) , mSkillNameWidget(NULL)
, mSkillValueWidget(NULL) , mSkillValueWidget(NULL)
{ {
} }
void MWSkill::setSkillId(ESM::Skill::SkillEnum skill) void MWSkill::setSkillId(ESM::Skill::SkillEnum skill)
{ {
mSkillId = skill; mSkillId = skill;
updateWidgets(); updateWidgets();
} }
void MWSkill::setSkillNumber(int skill) void MWSkill::setSkillNumber(int skill)
{ {
if (skill < 0) if (skill < 0)
setSkillId(ESM::Skill::Length); setSkillId(ESM::Skill::Length);
else if (skill < ESM::Skill::Length) else if (skill < ESM::Skill::Length)
setSkillId(static_cast<ESM::Skill::SkillEnum>(skill)); setSkillId(static_cast<ESM::Skill::SkillEnum>(skill));
else else
throw new std::runtime_error("Skill number out of range"); throw new std::runtime_error("Skill number out of range");
} }
void MWSkill::setSkillValue(const SkillValue& value) void MWSkill::setSkillValue(const SkillValue& value)
{ {
mValue = value; mValue = value;
updateWidgets(); updateWidgets();
} }
void MWSkill::updateWidgets() void MWSkill::updateWidgets()
{ {
if (mSkillNameWidget) if (mSkillNameWidget)
{ {
if (mSkillId == ESM::Skill::Length) if (mSkillId == ESM::Skill::Length)
@ -87,19 +87,19 @@ void MWSkill::updateWidgets()
else else
mSkillValueWidget->_setWidgetState("normal"); mSkillValueWidget->_setWidgetState("normal");
} }
} }
void MWSkill::onClicked(MyGUI::Widget* _sender) void MWSkill::onClicked(MyGUI::Widget* _sender)
{ {
eventClicked(this); eventClicked(this);
} }
MWSkill::~MWSkill() MWSkill::~MWSkill()
{ {
} }
void MWSkill::initialiseOverride() void MWSkill::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
assignWidget(mSkillNameWidget, "StatName"); assignWidget(mSkillNameWidget, "StatName");
@ -120,36 +120,36 @@ void MWSkill::initialiseOverride()
mSkillNameWidget = button; mSkillNameWidget = button;
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWSkill::onClicked); button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWSkill::onClicked);
} }
} }
/* MWAttribute */ /* MWAttribute */
MWAttribute::MWAttribute() MWAttribute::MWAttribute()
: mId(-1) : mId(-1)
, mAttributeNameWidget(NULL) , mAttributeNameWidget(NULL)
, mAttributeValueWidget(NULL) , mAttributeValueWidget(NULL)
{ {
} }
void MWAttribute::setAttributeId(int attributeId) void MWAttribute::setAttributeId(int attributeId)
{ {
mId = attributeId; mId = attributeId;
updateWidgets(); updateWidgets();
} }
void MWAttribute::setAttributeValue(const AttributeValue& value) void MWAttribute::setAttributeValue(const AttributeValue& value)
{ {
mValue = value; mValue = value;
updateWidgets(); updateWidgets();
} }
void MWAttribute::onClicked(MyGUI::Widget* _sender) void MWAttribute::onClicked(MyGUI::Widget* _sender)
{ {
eventClicked(this); eventClicked(this);
} }
void MWAttribute::updateWidgets() void MWAttribute::updateWidgets()
{ {
if (mAttributeNameWidget) if (mAttributeNameWidget)
{ {
if (mId < 0 || mId >= 8) if (mId < 0 || mId >= 8)
@ -183,14 +183,14 @@ void MWAttribute::updateWidgets()
else else
mAttributeValueWidget->_setWidgetState("normal"); mAttributeValueWidget->_setWidgetState("normal");
} }
} }
MWAttribute::~MWAttribute() MWAttribute::~MWAttribute()
{ {
} }
void MWAttribute::initialiseOverride() void MWAttribute::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
assignWidget(mAttributeNameWidget, "StatName"); assignWidget(mAttributeNameWidget, "StatName");
@ -211,23 +211,23 @@ void MWAttribute::initialiseOverride()
mAttributeValueWidget = button; mAttributeValueWidget = button;
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWAttribute::onClicked); button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWAttribute::onClicked);
} }
} }
/* MWSpell */ /* MWSpell */
MWSpell::MWSpell() MWSpell::MWSpell()
: mSpellNameWidget(NULL) : mSpellNameWidget(NULL)
{ {
} }
void MWSpell::setSpellId(const std::string &spellId) void MWSpell::setSpellId(const std::string &spellId)
{ {
mId = spellId; mId = spellId;
updateWidgets(); updateWidgets();
} }
void MWSpell::createEffectWidgets(std::vector<MyGUI::Widget*> &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, int flags) void MWSpell::createEffectWidgets(std::vector<MyGUI::Widget*> &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, int flags)
{ {
const MWWorld::ESMStore &store = const MWWorld::ESMStore &store =
MWBase::Environment::get().getWorld()->getStore(); MWBase::Environment::get().getWorld()->getStore();
@ -254,10 +254,10 @@ void MWSpell::createEffectWidgets(std::vector<MyGUI::Widget*> &effects, MyGUI::W
coord.top += effect->getHeight(); coord.top += effect->getHeight();
coord.width = std::max(coord.width, effect->getRequestedWidth()); coord.width = std::max(coord.width, effect->getRequestedWidth());
} }
} }
void MWSpell::updateWidgets() void MWSpell::updateWidgets()
{ {
if (mSpellNameWidget && MWBase::Environment::get().getWindowManager()) if (mSpellNameWidget && MWBase::Environment::get().getWindowManager())
{ {
const MWWorld::ESMStore &store = const MWWorld::ESMStore &store =
@ -269,34 +269,34 @@ void MWSpell::updateWidgets()
else else
static_cast<MyGUI::TextBox*>(mSpellNameWidget)->setCaption(""); static_cast<MyGUI::TextBox*>(mSpellNameWidget)->setCaption("");
} }
} }
void MWSpell::initialiseOverride() void MWSpell::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
assignWidget(mSpellNameWidget, "StatName"); assignWidget(mSpellNameWidget, "StatName");
} }
MWSpell::~MWSpell() MWSpell::~MWSpell()
{ {
} }
/* MWEffectList */ /* MWEffectList */
MWEffectList::MWEffectList() MWEffectList::MWEffectList()
: mEffectList(0) : mEffectList(0)
{ {
} }
void MWEffectList::setEffectList(const SpellEffectList& list) void MWEffectList::setEffectList(const SpellEffectList& list)
{ {
mEffectList = list; mEffectList = list;
updateWidgets(); updateWidgets();
} }
void MWEffectList::createEffectWidgets(std::vector<MyGUI::Widget*> &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, bool center, int flags) void MWEffectList::createEffectWidgets(std::vector<MyGUI::Widget*> &effects, MyGUI::Widget* creator, MyGUI::IntCoord &coord, bool center, int flags)
{ {
// We don't know the width of all the elements beforehand, so we do it in // We don't know the width of all the elements beforehand, so we do it in
// 2 steps: first, create all widgets and check their width.... // 2 steps: first, create all widgets and check their width....
MWSpellEffectPtr effect = NULL; MWSpellEffectPtr effect = NULL;
@ -334,23 +334,23 @@ void MWEffectList::createEffectWidgets(std::vector<MyGUI::Widget*> &effects, MyG
// inform the parent about width // inform the parent about width
coord.width = maxwidth; coord.width = maxwidth;
} }
void MWEffectList::updateWidgets() void MWEffectList::updateWidgets()
{ {
} }
void MWEffectList::initialiseOverride() void MWEffectList::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
} }
MWEffectList::~MWEffectList() MWEffectList::~MWEffectList()
{ {
} }
SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects) SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects)
{ {
SpellEffectList result; SpellEffectList result;
std::vector<ESM::ENAMstruct>::const_iterator end = effects->mList.end(); std::vector<ESM::ENAMstruct>::const_iterator end = effects->mList.end();
for (std::vector<ESM::ENAMstruct>::const_iterator it = effects->mList.begin(); it != end; ++it) for (std::vector<ESM::ENAMstruct>::const_iterator it = effects->mList.begin(); it != end; ++it)
@ -367,25 +367,25 @@ SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects)
result.push_back(params); result.push_back(params);
} }
return result; return result;
} }
/* MWSpellEffect */ /* MWSpellEffect */
MWSpellEffect::MWSpellEffect() MWSpellEffect::MWSpellEffect()
: mImageWidget(NULL) : mImageWidget(NULL)
, mTextWidget(NULL) , mTextWidget(NULL)
, mRequestedWidth(0) , mRequestedWidth(0)
{ {
} }
void MWSpellEffect::setSpellEffect(const SpellEffectParams& params) void MWSpellEffect::setSpellEffect(const SpellEffectParams& params)
{ {
mEffectParams = params; mEffectParams = params;
updateWidgets(); updateWidgets();
} }
void MWSpellEffect::updateWidgets() void MWSpellEffect::updateWidgets()
{ {
if (!mEffectParams.mKnown) if (!mEffectParams.mKnown)
{ {
mTextWidget->setCaption ("?"); mTextWidget->setCaption ("?");
@ -462,33 +462,33 @@ void MWSpellEffect::updateWidgets()
std::string path = std::string("icons\\") + magicEffect->mIcon; std::string path = std::string("icons\\") + magicEffect->mIcon;
fixTexturePath(path); fixTexturePath(path);
mImageWidget->setImageTexture(path); mImageWidget->setImageTexture(path);
} }
MWSpellEffect::~MWSpellEffect() MWSpellEffect::~MWSpellEffect()
{ {
} }
void MWSpellEffect::initialiseOverride() void MWSpellEffect::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
assignWidget(mTextWidget, "Text"); assignWidget(mTextWidget, "Text");
assignWidget(mImageWidget, "Image"); assignWidget(mImageWidget, "Image");
} }
/* MWDynamicStat */ /* MWDynamicStat */
MWDynamicStat::MWDynamicStat() MWDynamicStat::MWDynamicStat()
: mValue(0) : mValue(0)
, mMax(1) , mMax(1)
, mTextWidget(NULL) , mTextWidget(NULL)
, mBarWidget(NULL) , mBarWidget(NULL)
, mBarTextWidget(NULL) , mBarTextWidget(NULL)
{ {
} }
void MWDynamicStat::setValue(int cur, int max) void MWDynamicStat::setValue(int cur, int max)
{ {
mValue = cur; mValue = cur;
mMax = max; mMax = max;
@ -510,33 +510,33 @@ void MWDynamicStat::setValue(int cur, int max)
else else
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(""); static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption("");
} }
} }
void MWDynamicStat::setTitle(const std::string& text) void MWDynamicStat::setTitle(const std::string& text)
{ {
if (mTextWidget) if (mTextWidget)
static_cast<MyGUI::TextBox*>(mTextWidget)->setCaption(text); static_cast<MyGUI::TextBox*>(mTextWidget)->setCaption(text);
} }
MWDynamicStat::~MWDynamicStat() MWDynamicStat::~MWDynamicStat()
{ {
} }
void MWDynamicStat::initialiseOverride() void MWDynamicStat::initialiseOverride()
{ {
Base::initialiseOverride(); Base::initialiseOverride();
assignWidget(mTextWidget, "Text"); assignWidget(mTextWidget, "Text");
assignWidget(mBarWidget, "Bar"); assignWidget(mBarWidget, "Bar");
assignWidget(mBarTextWidget, "BarText"); assignWidget(mBarTextWidget, "BarText");
} }
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
void AutoSizedWidget::notifySizeChange (MyGUI::Widget* w) void AutoSizedWidget::notifySizeChange (MyGUI::Widget* w)
{ {
if (w->getParent () != 0) if (w->getParent () != 0)
{ {
Box* b = dynamic_cast<Box*>(w->getParent()); Box* b = dynamic_cast<Box*>(w->getParent());
@ -552,23 +552,23 @@ void AutoSizedWidget::notifySizeChange (MyGUI::Widget* w)
w->setSize(getRequestedSize ()); w->setSize(getRequestedSize ());
} }
} }
} }
MyGUI::IntSize AutoSizedTextBox::getRequestedSize() MyGUI::IntSize AutoSizedTextBox::getRequestedSize()
{ {
return getTextSize(); return getTextSize();
} }
void AutoSizedTextBox::setCaption(const MyGUI::UString& _value) void AutoSizedTextBox::setCaption(const MyGUI::UString& _value)
{ {
TextBox::setCaption(_value); TextBox::setCaption(_value);
notifySizeChange (this); notifySizeChange (this);
} }
void AutoSizedTextBox::setPropertyOverride(const std::string& _key, const std::string& _value) void AutoSizedTextBox::setPropertyOverride(const std::string& _key, const std::string& _value)
{ {
if (_key == "ExpandDirection") if (_key == "ExpandDirection")
{ {
mExpandDirection = MyGUI::Align::parse (_value); mExpandDirection = MyGUI::Align::parse (_value);
@ -577,24 +577,24 @@ void AutoSizedTextBox::setPropertyOverride(const std::string& _key, const std::s
{ {
TextBox::setPropertyOverride (_key, _value); TextBox::setPropertyOverride (_key, _value);
} }
} }
MyGUI::IntSize AutoSizedEditBox::getRequestedSize() MyGUI::IntSize AutoSizedEditBox::getRequestedSize()
{ {
if (getAlign().isHStretch()) if (getAlign().isHStretch())
throw std::runtime_error("AutoSizedEditBox can't have HStretch align (" + getName() + ")"); throw std::runtime_error("AutoSizedEditBox can't have HStretch align (" + getName() + ")");
return MyGUI::IntSize(getSize().width, getTextSize().height); return MyGUI::IntSize(getSize().width, getTextSize().height);
} }
void AutoSizedEditBox::setCaption(const MyGUI::UString& _value) void AutoSizedEditBox::setCaption(const MyGUI::UString& _value)
{ {
EditBox::setCaption(_value); EditBox::setCaption(_value);
notifySizeChange (this); notifySizeChange (this);
} }
void AutoSizedEditBox::setPropertyOverride(const std::string& _key, const std::string& _value) void AutoSizedEditBox::setPropertyOverride(const std::string& _key, const std::string& _value)
{ {
if (_key == "ExpandDirection") if (_key == "ExpandDirection")
{ {
mExpandDirection = MyGUI::Align::parse (_value); mExpandDirection = MyGUI::Align::parse (_value);
@ -603,25 +603,25 @@ void AutoSizedEditBox::setPropertyOverride(const std::string& _key, const std::s
{ {
EditBox::setPropertyOverride (_key, _value); EditBox::setPropertyOverride (_key, _value);
} }
} }
MyGUI::IntSize AutoSizedButton::getRequestedSize() MyGUI::IntSize AutoSizedButton::getRequestedSize()
{ {
MyGUI::IntSize size = getTextSize() + MyGUI::IntSize(24,0); MyGUI::IntSize size = getTextSize() + MyGUI::IntSize(24,0);
size.height = std::max(24, size.height); size.height = std::max(24, size.height);
return size; return size;
} }
void AutoSizedButton::setCaption(const MyGUI::UString& _value) void AutoSizedButton::setCaption(const MyGUI::UString& _value)
{ {
Button::setCaption(_value); Button::setCaption(_value);
notifySizeChange (this); notifySizeChange (this);
} }
void AutoSizedButton::setPropertyOverride(const std::string& _key, const std::string& _value) void AutoSizedButton::setPropertyOverride(const std::string& _key, const std::string& _value)
{ {
if (_key == "ExpandDirection") if (_key == "ExpandDirection")
{ {
mExpandDirection = MyGUI::Align::parse (_value); mExpandDirection = MyGUI::Align::parse (_value);
@ -630,33 +630,33 @@ void AutoSizedButton::setPropertyOverride(const std::string& _key, const std::st
{ {
Button::setPropertyOverride (_key, _value); Button::setPropertyOverride (_key, _value);
} }
} }
Box::Box() Box::Box()
: mSpacing(4) : mSpacing(4)
, mPadding(0) , mPadding(0)
, mAutoResize(false) , mAutoResize(false)
{ {
} }
void Box::notifyChildrenSizeChanged () void Box::notifyChildrenSizeChanged ()
{ {
align(); align();
} }
void Box::_setPropertyImpl(const std::string& _key, const std::string& _value) void Box::_setPropertyImpl(const std::string& _key, const std::string& _value)
{ {
if (_key == "Spacing") if (_key == "Spacing")
mSpacing = MyGUI::utility::parseValue<int>(_value); mSpacing = MyGUI::utility::parseValue<int>(_value);
else if (_key == "Padding") else if (_key == "Padding")
mPadding = MyGUI::utility::parseValue<int>(_value); mPadding = MyGUI::utility::parseValue<int>(_value);
else if (_key == "AutoResize") else if (_key == "AutoResize")
mAutoResize = MyGUI::utility::parseValue<bool>(_value); mAutoResize = MyGUI::utility::parseValue<bool>(_value);
} }
void HBox::align () void HBox::align ()
{ {
unsigned int count = getChildCount (); unsigned int count = getChildCount ();
size_t h_stretched_count = 0; size_t h_stretched_count = 0;
int total_width = 0; int total_width = 0;
@ -718,32 +718,32 @@ void HBox::align ()
if (i != count-1) if (i != count-1)
curX += mSpacing; curX += mSpacing;
} }
} }
void HBox::setPropertyOverride(const std::string& _key, const std::string& _value) void HBox::setPropertyOverride(const std::string& _key, const std::string& _value)
{ {
Box::_setPropertyImpl (_key, _value); Box::_setPropertyImpl (_key, _value);
} }
void HBox::setSize (const MyGUI::IntSize& _value) void HBox::setSize (const MyGUI::IntSize& _value)
{ {
MyGUI::Widget::setSize (_value); MyGUI::Widget::setSize (_value);
align(); align();
} }
void HBox::setCoord (const MyGUI::IntCoord& _value) void HBox::setCoord (const MyGUI::IntCoord& _value)
{ {
MyGUI::Widget::setCoord (_value); MyGUI::Widget::setCoord (_value);
align(); align();
} }
void HBox::onWidgetCreated(MyGUI::Widget* _widget) void HBox::onWidgetCreated(MyGUI::Widget* _widget)
{ {
align(); align();
} }
MyGUI::IntSize HBox::getRequestedSize () MyGUI::IntSize HBox::getRequestedSize ()
{ {
MyGUI::IntSize size(0,0); MyGUI::IntSize size(0,0);
for (unsigned int i = 0; i < getChildCount (); ++i) for (unsigned int i = 0; i < getChildCount (); ++i)
{ {
@ -771,13 +771,13 @@ MyGUI::IntSize HBox::getRequestedSize ()
size.width += mPadding*2; size.width += mPadding*2;
} }
return size; return size;
} }
void VBox::align () void VBox::align ()
{ {
unsigned int count = getChildCount (); unsigned int count = getChildCount ();
size_t v_stretched_count = 0; size_t v_stretched_count = 0;
int total_height = 0; int total_height = 0;
@ -839,27 +839,27 @@ void VBox::align ()
if (i != count-1) if (i != count-1)
curY += mSpacing; curY += mSpacing;
} }
} }
void VBox::setPropertyOverride(const std::string& _key, const std::string& _value) void VBox::setPropertyOverride(const std::string& _key, const std::string& _value)
{ {
Box::_setPropertyImpl (_key, _value); Box::_setPropertyImpl (_key, _value);
} }
void VBox::setSize (const MyGUI::IntSize& _value) void VBox::setSize (const MyGUI::IntSize& _value)
{ {
MyGUI::Widget::setSize (_value); MyGUI::Widget::setSize (_value);
align(); align();
} }
void VBox::setCoord (const MyGUI::IntCoord& _value) void VBox::setCoord (const MyGUI::IntCoord& _value)
{ {
MyGUI::Widget::setCoord (_value); MyGUI::Widget::setCoord (_value);
align(); align();
} }
MyGUI::IntSize VBox::getRequestedSize () MyGUI::IntSize VBox::getRequestedSize ()
{ {
MyGUI::IntSize size(0,0); MyGUI::IntSize size(0,0);
for (unsigned int i = 0; i < getChildCount (); ++i) for (unsigned int i = 0; i < getChildCount (); ++i)
{ {
@ -887,9 +887,11 @@ MyGUI::IntSize VBox::getRequestedSize ()
size.width += mPadding*2; size.width += mPadding*2;
} }
return size; return size;
} }
void VBox::onWidgetCreated(MyGUI::Widget* _widget) void VBox::onWidgetCreated(MyGUI::Widget* _widget)
{ {
align(); align();
}
}
} }

View file

@ -1,7 +1,5 @@
#include "windowbase.hpp" #include "windowbase.hpp"
#include <components/settings/settings.hpp>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
using namespace MWGui; using namespace MWGui;

View file

@ -1,39 +1,20 @@
#include "windowmanagerimp.hpp" #include "windowmanagerimp.hpp"
#include <cassert>
#include <iterator>
#include <MyGUI_UString.h>
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/gui/manager.hpp> #include <openengine/gui/manager.hpp>
#include <components/settings/settings.hpp>
#include <components/translation/translation.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/cellstore.hpp"
#include "console.hpp" #include "console.hpp"
#include "journalwindow.hpp" #include "journalwindow.hpp"
#include "charactercreation.hpp" #include "charactercreation.hpp"
#include "textinput.hpp"
#include "review.hpp"
#include "dialogue.hpp" #include "dialogue.hpp"
#include "dialoguehistory.hpp" #include "dialoguehistory.hpp"
#include "mapwindow.hpp"
#include "statswindow.hpp" #include "statswindow.hpp"
#include "messagebox.hpp" #include "messagebox.hpp"
#include "container.hpp"
#include "inventorywindow.hpp"
#include "tooltips.hpp" #include "tooltips.hpp"
#include "scrollwindow.hpp" #include "scrollwindow.hpp"
#include "bookwindow.hpp" #include "bookwindow.hpp"
#include "list.hpp"
#include "hud.hpp" #include "hud.hpp"
#include "mainmenu.hpp" #include "mainmenu.hpp"
#include "countdialog.hpp" #include "countdialog.hpp"
@ -48,21 +29,20 @@
#include "loadingscreen.hpp" #include "loadingscreen.hpp"
#include "levelupdialog.hpp" #include "levelupdialog.hpp"
#include "waitdialog.hpp" #include "waitdialog.hpp"
#include "spellcreationdialog.hpp"
#include "enchantingdialog.hpp" #include "enchantingdialog.hpp"
#include "trainingwindow.hpp" #include "trainingwindow.hpp"
#include "imagebutton.hpp"
#include "exposedwindow.hpp" #include "exposedwindow.hpp"
#include "cursor.hpp" #include "cursor.hpp"
#include "spellicons.hpp"
#include "merchantrepair.hpp" #include "merchantrepair.hpp"
#include "repair.hpp" #include "repair.hpp"
#include "soulgemdialog.hpp" #include "soulgemdialog.hpp"
#include "companionwindow.hpp" #include "companionwindow.hpp"
#include "inventorywindow.hpp"
using namespace MWGui; namespace MWGui
{
WindowManager::WindowManager( WindowManager::WindowManager(
const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *ogre, const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *ogre,
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
Translation::Storage& translationDataStorage) Translation::Storage& translationDataStorage)
@ -120,7 +100,7 @@ WindowManager::WindowManager(
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true) , mHudEnabled(true)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
{ {
// Set up the GUI system // Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath);
mGui = mGuiManager->getGui(); mGui = mGuiManager->getGui();
@ -223,10 +203,10 @@ WindowManager::WindowManager(
// Set up visibility // Set up visibility
updateVisible(); updateVisible();
} }
WindowManager::~WindowManager() WindowManager::~WindowManager()
{ {
delete mConsole; delete mConsole;
delete mMessageBoxManager; delete mMessageBoxManager;
delete mHud; delete mHud;
@ -265,10 +245,10 @@ WindowManager::~WindowManager()
cleanupGarbage(); cleanupGarbage();
delete mGuiManager; delete mGuiManager;
} }
void WindowManager::cleanupGarbage() void WindowManager::cleanupGarbage()
{ {
// Delete any dialogs which are no longer in use // Delete any dialogs which are no longer in use
if (!mGarbageDialogs.empty()) if (!mGarbageDialogs.empty())
{ {
@ -278,10 +258,10 @@ void WindowManager::cleanupGarbage()
} }
mGarbageDialogs.clear(); mGarbageDialogs.clear();
} }
} }
void WindowManager::update() void WindowManager::update()
{ {
cleanupGarbage(); cleanupGarbage();
mHud->setFPS(mFPS); mHud->setFPS(mFPS);
@ -291,10 +271,10 @@ void WindowManager::update()
mHud->update(); mHud->update();
mCursor->update(); mCursor->update();
} }
void WindowManager::updateVisible() void WindowManager::updateVisible()
{ {
// Start out by hiding everything except the HUD // Start out by hiding everything except the HUD
mMap->setVisible(false); mMap->setVisible(false);
mMenu->setVisible(false); mMenu->setVisible(false);
@ -477,10 +457,10 @@ void WindowManager::updateVisible()
// Unsupported mode, switch back to game // Unsupported mode, switch back to game
break; break;
} }
} }
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value) void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
mCharGen->setValue(id, value); mCharGen->setValue(id, value);
@ -507,20 +487,20 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int
mPlayerAttributes[attributes[i]] = value; mPlayerAttributes[attributes[i]] = value;
break; break;
} }
} }
void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& value) void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& value)
{ {
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we /// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
/// allow custom skills. /// allow custom skills.
mStatsWindow->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value); mStatsWindow->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value);
mCharGen->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value); mCharGen->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value);
mPlayerSkillValues[parSkill] = value; mPlayerSkillValues[parSkill] = value;
} }
void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
mHud->setValue (id, value); mHud->setValue (id, value);
mCharGen->setValue(id, value); mCharGen->setValue(id, value);
@ -539,72 +519,72 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS
mPlayerFatigue = value; mPlayerFatigue = value;
mCharGen->setPlayerFatigue (value); mCharGen->setPlayerFatigue (value);
} }
} }
#if 0 #if 0
MWMechanics::DynamicStat<int> WindowManager::getValue(const std::string& id) MWMechanics::DynamicStat<int> WindowManager::getValue(const std::string& id)
{ {
if(id == "HBar") if(id == "HBar")
return layerHealth; return layerHealth;
else if (id == "MBar") else if (id == "MBar")
return mPlayerMagicka; return mPlayerMagicka;
else if (id == "FBar") else if (id == "FBar")
return mPlayerFatigue; return mPlayerFatigue;
} }
#endif #endif
void WindowManager::setValue (const std::string& id, const std::string& value) void WindowManager::setValue (const std::string& id, const std::string& value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
if (id=="name") if (id=="name")
mPlayerName = value; mPlayerName = value;
else if (id=="race") else if (id=="race")
mPlayerRaceId = value; mPlayerRaceId = value;
} }
void WindowManager::setValue (const std::string& id, int value) void WindowManager::setValue (const std::string& id, int value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
} }
void WindowManager::setPlayerClass (const ESM::Class &class_) void WindowManager::setPlayerClass (const ESM::Class &class_)
{ {
mStatsWindow->setValue("class", class_.mName); mStatsWindow->setValue("class", class_.mName);
} }
void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) void WindowManager::configureSkills (const SkillList& major, const SkillList& minor)
{ {
mStatsWindow->configureSkills (major, minor); mStatsWindow->configureSkills (major, minor);
mCharGen->configureSkills(major, minor); mCharGen->configureSkills(major, minor);
mPlayerMajorSkills = major; mPlayerMajorSkills = major;
mPlayerMinorSkills = minor; mPlayerMinorSkills = minor;
} }
void WindowManager::setReputation (int reputation) void WindowManager::setReputation (int reputation)
{ {
mStatsWindow->setReputation (reputation); mStatsWindow->setReputation (reputation);
} }
void WindowManager::setBounty (int bounty) void WindowManager::setBounty (int bounty)
{ {
mStatsWindow->setBounty (bounty); mStatsWindow->setBounty (bounty);
} }
void WindowManager::updateSkillArea() void WindowManager::updateSkillArea()
{ {
mStatsWindow->updateSkillArea(); mStatsWindow->updateSkillArea();
} }
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog) void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
{ {
if (!dialog) if (!dialog)
return; return;
dialog->setVisible(false); dialog->setVisible(false);
mGarbageDialogs.push_back(dialog); mGarbageDialogs.push_back(dialog);
} }
void WindowManager::messageBox (const std::string& message, const std::vector<std::string>& buttons) void WindowManager::messageBox (const std::string& message, const std::vector<std::string>& buttons)
{ {
if(buttons.empty()){ if(buttons.empty()){
/* If there are no buttons, and there is a dialogue window open, messagebox goes to the dialogue window */ /* If there are no buttons, and there is a dialogue window open, messagebox goes to the dialogue window */
if(!mGuiModes.empty() && mGuiModes.back() == GM_Dialogue) if(!mGuiModes.empty() && mGuiModes.back() == GM_Dialogue)
@ -618,20 +598,20 @@ void WindowManager::messageBox (const std::string& message, const std::vector<st
mMessageBoxManager->createInteractiveMessageBox(message, buttons); mMessageBoxManager->createInteractiveMessageBox(message, buttons);
MWBase::Environment::get().getInputManager()->changeInputMode(isGuiMode()); MWBase::Environment::get().getInputManager()->changeInputMode(isGuiMode());
} }
} }
void WindowManager::enterPressed () void WindowManager::enterPressed ()
{ {
mMessageBoxManager->enterPressed(); mMessageBoxManager->enterPressed();
} }
int WindowManager::readPressedButton () int WindowManager::readPressedButton ()
{ {
return mMessageBoxManager->readPressedButton(); return mMessageBoxManager->readPressedButton();
} }
std::string WindowManager::getGameSettingString(const std::string &id, const std::string &default_) std::string WindowManager::getGameSettingString(const std::string &id, const std::string &default_)
{ {
const ESM::GameSetting *setting = const ESM::GameSetting *setting =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().search(id); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().search(id);
@ -639,10 +619,10 @@ std::string WindowManager::getGameSettingString(const std::string &id, const std
return setting->mValue.getString(); return setting->mValue.getString();
return default_; return default_;
} }
void WindowManager::onDialogueWindowBye() void WindowManager::onDialogueWindowBye()
{ {
if (mDialogueWindow) if (mDialogueWindow)
{ {
//FIXME set some state and stuff? //FIXME set some state and stuff?
@ -650,10 +630,10 @@ void WindowManager::onDialogueWindowBye()
mDialogueWindow->setVisible(false); mDialogueWindow->setVisible(false);
} }
removeGuiMode(GM_Dialogue); removeGuiMode(GM_Dialogue);
} }
void WindowManager::onFrame (float frameDuration) void WindowManager::onFrame (float frameDuration)
{ {
mMessageBoxManager->onFrame(frameDuration); mMessageBoxManager->onFrame(frameDuration);
mToolTips->onFrame(frameDuration); mToolTips->onFrame(frameDuration);
@ -686,10 +666,10 @@ void WindowManager::onFrame (float frameDuration)
mContainerWindow->checkReferenceAvailable(); mContainerWindow->checkReferenceAvailable();
mCompanionWindow->checkReferenceAvailable(); mCompanionWindow->checkReferenceAvailable();
mConsole->checkReferenceAvailable(); mConsole->checkReferenceAvailable();
} }
void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
{ {
if (cell->mCell->isExterior()) if (cell->mCell->isExterior())
{ {
std::string name; std::string name;
@ -726,86 +706,86 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
mHud->setCellPrefix( cell->mCell->mName ); mHud->setCellPrefix( cell->mCell->mName );
} }
} }
void WindowManager::setInteriorMapTexture(const int x, const int y) void WindowManager::setInteriorMapTexture(const int x, const int y)
{ {
mMap->setActiveCell(x,y, true); mMap->setActiveCell(x,y, true);
mHud->setActiveCell(x,y, true); mHud->setActiveCell(x,y, true);
} }
void WindowManager::setPlayerPos(const float x, const float y) void WindowManager::setPlayerPos(const float x, const float y)
{ {
mMap->setPlayerPos(x,y); mMap->setPlayerPos(x,y);
mHud->setPlayerPos(x,y); mHud->setPlayerPos(x,y);
} }
void WindowManager::setPlayerDir(const float x, const float y) void WindowManager::setPlayerDir(const float x, const float y)
{ {
mMap->setPlayerDir(x,y); mMap->setPlayerDir(x,y);
mHud->setPlayerDir(x,y); mHud->setPlayerDir(x,y);
} }
void WindowManager::setHMSVisibility(bool visible) void WindowManager::setHMSVisibility(bool visible)
{ {
mHud->setHmsVisible (visible); mHud->setHmsVisible (visible);
} }
void WindowManager::setMinimapVisibility(bool visible) void WindowManager::setMinimapVisibility(bool visible)
{ {
mHud->setMinimapVisible (visible); mHud->setMinimapVisible (visible);
} }
void WindowManager::toggleFogOfWar() void WindowManager::toggleFogOfWar()
{ {
mMap->toggleFogOfWar(); mMap->toggleFogOfWar();
mHud->toggleFogOfWar(); mHud->toggleFogOfWar();
} }
void WindowManager::setFocusObject(const MWWorld::Ptr& focus) void WindowManager::setFocusObject(const MWWorld::Ptr& focus)
{ {
mToolTips->setFocusObject(focus); mToolTips->setFocusObject(focus);
} }
void WindowManager::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) void WindowManager::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y)
{ {
mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y); mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y);
} }
void WindowManager::toggleFullHelp() void WindowManager::toggleFullHelp()
{ {
mToolTips->toggleFullHelp(); mToolTips->toggleFullHelp();
} }
bool WindowManager::getFullHelp() const bool WindowManager::getFullHelp() const
{ {
return mToolTips->getFullHelp(); return mToolTips->getFullHelp();
} }
void WindowManager::setWeaponVisibility(bool visible) void WindowManager::setWeaponVisibility(bool visible)
{ {
mHud->setWeapVisible (visible); mHud->setWeapVisible (visible);
} }
void WindowManager::setSpellVisibility(bool visible) void WindowManager::setSpellVisibility(bool visible)
{ {
mHud->setSpellVisible (visible); mHud->setSpellVisible (visible);
mHud->setEffectVisible (visible); mHud->setEffectVisible (visible);
} }
void WindowManager::setMouseVisible(bool visible) void WindowManager::setMouseVisible(bool visible)
{ {
mCursor->setVisible(visible); mCursor->setVisible(visible);
} }
void WindowManager::setDragDrop(bool dragDrop) void WindowManager::setDragDrop(bool dragDrop)
{ {
mToolTips->setEnabled(!dragDrop); mToolTips->setEnabled(!dragDrop);
MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop);
} }
void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result)
{ {
std::string tag(_tag); std::string tag(_tag);
std::string tokenToFind = "sCell="; std::string tokenToFind = "sCell=";
@ -825,10 +805,10 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r
else else
_result = tag; _result = tag;
} }
} }
void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed)
{ {
mHud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); mHud->setFpsLevel(Settings::Manager::getInt("fps", "HUD"));
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
@ -873,10 +853,10 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector
mGuiManager->updateWindow (mRendering->getWindow ()); mGuiManager->updateWindow (mRendering->getWindow ());
mLoadingScreen->updateWindow (mRendering->getWindow ()); mLoadingScreen->updateWindow (mRendering->getWindow ());
} }
} }
void WindowManager::pushGuiMode(GuiMode mode) void WindowManager::pushGuiMode(GuiMode mode)
{ {
if (mode==GM_Inventory && mAllowed==GW_None) if (mode==GM_Inventory && mAllowed==GW_None)
return; return;
@ -893,10 +873,10 @@ void WindowManager::pushGuiMode(GuiMode mode)
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible(); updateVisible();
} }
void WindowManager::popGuiMode() void WindowManager::popGuiMode()
{ {
if (!mGuiModes.empty()) if (!mGuiModes.empty())
mGuiModes.pop_back(); mGuiModes.pop_back();
@ -904,10 +884,10 @@ void WindowManager::popGuiMode()
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible(); updateVisible();
} }
void WindowManager::removeGuiMode(GuiMode mode) void WindowManager::removeGuiMode(GuiMode mode)
{ {
std::vector<GuiMode>::iterator it = mGuiModes.begin(); std::vector<GuiMode>::iterator it = mGuiModes.begin();
while (it != mGuiModes.end()) while (it != mGuiModes.end())
{ {
@ -921,103 +901,103 @@ void WindowManager::removeGuiMode(GuiMode mode)
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible(); updateVisible();
} }
void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent)
{ {
mHud->setSelectedSpell(spellId, successChancePercent); mHud->setSelectedSpell(spellId, successChancePercent);
const ESM::Spell* spell = const ESM::Spell* spell =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId); MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
mSpellWindow->setTitle(spell->mName); mSpellWindow->setTitle(spell->mName);
} }
void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item) void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item)
{ {
const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>() const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>()
.find(MWWorld::Class::get(item).getEnchantment(item)); .find(MWWorld::Class::get(item).getEnchantment(item));
int chargePercent = item.getCellRef().mEnchantmentCharge / static_cast<float>(ench->mData.mCharge) * 100; int chargePercent = item.getCellRef().mEnchantmentCharge / static_cast<float>(ench->mData.mCharge) * 100;
mHud->setSelectedEnchantItem(item, chargePercent); mHud->setSelectedEnchantItem(item, chargePercent);
mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item)); mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item));
} }
void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item)
{ {
int durabilityPercent = item.getCellRef().mCharge / static_cast<float>(MWWorld::Class::get(item).getItemMaxHealth(item)) * 100; int durabilityPercent = item.getCellRef().mCharge / static_cast<float>(MWWorld::Class::get(item).getItemMaxHealth(item)) * 100;
mHud->setSelectedWeapon(item, durabilityPercent); mHud->setSelectedWeapon(item, durabilityPercent);
mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item)); mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item));
} }
void WindowManager::unsetSelectedSpell() void WindowManager::unsetSelectedSpell()
{ {
mHud->unsetSelectedSpell(); mHud->unsetSelectedSpell();
mSpellWindow->setTitle("#{sNone}"); mSpellWindow->setTitle("#{sNone}");
} }
void WindowManager::unsetSelectedWeapon() void WindowManager::unsetSelectedWeapon()
{ {
mHud->unsetSelectedWeapon(); mHud->unsetSelectedWeapon();
mInventoryWindow->setTitle("#{sSkillHandtohand}"); mInventoryWindow->setTitle("#{sSkillHandtohand}");
} }
void WindowManager::getMousePosition(int &x, int &y) void WindowManager::getMousePosition(int &x, int &y)
{ {
const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition();
x = pos.left; x = pos.left;
y = pos.top; y = pos.top;
} }
void WindowManager::getMousePosition(float &x, float &y) void WindowManager::getMousePosition(float &x, float &y)
{ {
const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition();
x = pos.left; x = pos.left;
y = pos.top; y = pos.top;
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
x /= viewSize.width; x /= viewSize.width;
y /= viewSize.height; y /= viewSize.height;
} }
bool WindowManager::getWorldMouseOver() bool WindowManager::getWorldMouseOver()
{ {
return mHud->getWorldMouseOver(); return mHud->getWorldMouseOver();
} }
void WindowManager::executeInConsole (const std::string& path) void WindowManager::executeInConsole (const std::string& path)
{ {
mConsole->executeFile (path); mConsole->executeFile (path);
} }
void WindowManager::wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) void WindowManager::wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount)
{ {
mFPS = fps; mFPS = fps;
mTriangleCount = triangleCount; mTriangleCount = triangleCount;
mBatchCount = batchCount; mBatchCount = batchCount;
} }
MyGUI::Gui* WindowManager::getGui() const { return mGui; } MyGUI::Gui* WindowManager::getGui() const { return mGui; }
MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; } MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; }
MWGui::ContainerWindow* WindowManager::getContainerWindow() { return mContainerWindow; } MWGui::ContainerWindow* WindowManager::getContainerWindow() { return mContainerWindow; }
MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; }
MWGui::BookWindow* WindowManager::getBookWindow() { return mBookWindow; } MWGui::BookWindow* WindowManager::getBookWindow() { return mBookWindow; }
MWGui::ScrollWindow* WindowManager::getScrollWindow() { return mScrollWindow; } MWGui::ScrollWindow* WindowManager::getScrollWindow() { return mScrollWindow; }
MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; } MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
MWGui::SpellBuyingWindow* WindowManager::getSpellBuyingWindow() { return mSpellBuyingWindow; } MWGui::SpellBuyingWindow* WindowManager::getSpellBuyingWindow() { return mSpellBuyingWindow; }
MWGui::TravelWindow* WindowManager::getTravelWindow() { return mTravelWindow; } MWGui::TravelWindow* WindowManager::getTravelWindow() { return mTravelWindow; }
MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; } MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; }
MWGui::Console* WindowManager::getConsole() { return mConsole; } MWGui::Console* WindowManager::getConsole() { return mConsole; }
bool WindowManager::isAllowed (GuiWindow wnd) const bool WindowManager::isAllowed (GuiWindow wnd) const
{ {
return mAllowed & wnd; return mAllowed & wnd;
} }
void WindowManager::allow (GuiWindow wnd) void WindowManager::allow (GuiWindow wnd)
{ {
mAllowed = (GuiWindow)(mAllowed | wnd); mAllowed = (GuiWindow)(mAllowed | wnd);
if (wnd & GW_Inventory) if (wnd & GW_Inventory)
@ -1027,176 +1007,178 @@ void WindowManager::allow (GuiWindow wnd)
} }
updateVisible(); updateVisible();
} }
void WindowManager::disallowAll() void WindowManager::disallowAll()
{ {
mAllowed = GW_None; mAllowed = GW_None;
mBookWindow->setInventoryAllowed (false); mBookWindow->setInventoryAllowed (false);
mScrollWindow->setInventoryAllowed (false); mScrollWindow->setInventoryAllowed (false);
updateVisible(); updateVisible();
} }
void WindowManager::toggleVisible (GuiWindow wnd) void WindowManager::toggleVisible (GuiWindow wnd)
{ {
mShown = (mShown & wnd) ? (GuiWindow) (mShown & ~wnd) : (GuiWindow) (mShown | wnd); mShown = (mShown & wnd) ? (GuiWindow) (mShown & ~wnd) : (GuiWindow) (mShown | wnd);
updateVisible(); updateVisible();
} }
bool WindowManager::isGuiMode() const bool WindowManager::isGuiMode() const
{ {
return !mGuiModes.empty() || mMessageBoxManager->isInteractiveMessageBox(); return !mGuiModes.empty() || mMessageBoxManager->isInteractiveMessageBox();
} }
bool WindowManager::isConsoleMode() const bool WindowManager::isConsoleMode() const
{ {
if (!mGuiModes.empty() && mGuiModes.back()==GM_Console) if (!mGuiModes.empty() && mGuiModes.back()==GM_Console)
return true; return true;
return false; return false;
} }
MWGui::GuiMode WindowManager::getMode() const MWGui::GuiMode WindowManager::getMode() const
{ {
if (mGuiModes.empty()) if (mGuiModes.empty())
return GM_None; return GM_None;
return mGuiModes.back(); return mGuiModes.back();
} }
std::map<int, MWMechanics::Stat<float> > WindowManager::getPlayerSkillValues() std::map<int, MWMechanics::Stat<float> > WindowManager::getPlayerSkillValues()
{ {
return mPlayerSkillValues; return mPlayerSkillValues;
} }
std::map<int, MWMechanics::Stat<int> > WindowManager::getPlayerAttributeValues() std::map<int, MWMechanics::Stat<int> > WindowManager::getPlayerAttributeValues()
{ {
return mPlayerAttributes; return mPlayerAttributes;
} }
WindowManager::SkillList WindowManager::getPlayerMinorSkills() WindowManager::SkillList WindowManager::getPlayerMinorSkills()
{ {
return mPlayerMinorSkills; return mPlayerMinorSkills;
} }
WindowManager::SkillList WindowManager::getPlayerMajorSkills() WindowManager::SkillList WindowManager::getPlayerMajorSkills()
{ {
return mPlayerMajorSkills; return mPlayerMajorSkills;
} }
void WindowManager::disallowMouse() void WindowManager::disallowMouse()
{ {
mInputBlocker->setVisible (true); mInputBlocker->setVisible (true);
} }
void WindowManager::allowMouse() void WindowManager::allowMouse()
{ {
mInputBlocker->setVisible (!isGuiMode ()); mInputBlocker->setVisible (!isGuiMode ());
} }
void WindowManager::notifyInputActionBound () void WindowManager::notifyInputActionBound ()
{ {
mSettingsWindow->updateControlsBox (); mSettingsWindow->updateControlsBox ();
allowMouse(); allowMouse();
} }
void WindowManager::showCrosshair (bool show) void WindowManager::showCrosshair (bool show)
{ {
mHud->setCrosshairVisible (show && mCrosshairEnabled); mHud->setCrosshairVisible (show && mCrosshairEnabled);
} }
void WindowManager::activateQuickKey (int index) void WindowManager::activateQuickKey (int index)
{ {
mQuickKeysMenu->activateQuickKey(index); mQuickKeysMenu->activateQuickKey(index);
} }
bool WindowManager::getSubtitlesEnabled () bool WindowManager::getSubtitlesEnabled ()
{ {
return mSubtitlesEnabled; return mSubtitlesEnabled;
} }
void WindowManager::toggleHud () void WindowManager::toggleHud ()
{ {
mHudEnabled = !mHudEnabled; mHudEnabled = !mHudEnabled;
mHud->setVisible (mHudEnabled); mHud->setVisible (mHudEnabled);
} }
void WindowManager::setLoadingProgress (const std::string& stage, int depth, int current, int total) void WindowManager::setLoadingProgress (const std::string& stage, int depth, int current, int total)
{ {
mLoadingScreen->setLoadingProgress (stage, depth, current, total); mLoadingScreen->setLoadingProgress (stage, depth, current, total);
} }
void WindowManager::loadingDone () void WindowManager::loadingDone ()
{ {
mLoadingScreen->loadingDone (); mLoadingScreen->loadingDone ();
} }
bool WindowManager::getPlayerSleeping () bool WindowManager::getPlayerSleeping ()
{ {
return mWaitDialog->getSleeping(); return mWaitDialog->getSleeping();
} }
void WindowManager::wakeUpPlayer() void WindowManager::wakeUpPlayer()
{ {
mWaitDialog->wakeUp(); mWaitDialog->wakeUp();
} }
void WindowManager::addVisitedLocation(const std::string& name, int x, int y) void WindowManager::addVisitedLocation(const std::string& name, int x, int y)
{ {
mMap->addVisitedLocation (name, x, y); mMap->addVisitedLocation (name, x, y);
} }
void WindowManager::startSpellMaking(MWWorld::Ptr actor) void WindowManager::startSpellMaking(MWWorld::Ptr actor)
{ {
mSpellCreationDialog->startSpellMaking (actor); mSpellCreationDialog->startSpellMaking (actor);
} }
void WindowManager::startEnchanting (MWWorld::Ptr actor) void WindowManager::startEnchanting (MWWorld::Ptr actor)
{ {
mEnchantingDialog->startEnchanting (actor); mEnchantingDialog->startEnchanting (actor);
} }
void WindowManager::startSelfEnchanting(MWWorld::Ptr soulgem) void WindowManager::startSelfEnchanting(MWWorld::Ptr soulgem)
{ {
mEnchantingDialog->startSelfEnchanting(soulgem); mEnchantingDialog->startSelfEnchanting(soulgem);
} }
void WindowManager::startTraining(MWWorld::Ptr actor) void WindowManager::startTraining(MWWorld::Ptr actor)
{ {
mTrainingWindow->startTraining(actor); mTrainingWindow->startTraining(actor);
} }
void WindowManager::startRepair(MWWorld::Ptr actor) void WindowManager::startRepair(MWWorld::Ptr actor)
{ {
mMerchantRepair->startRepair(actor); mMerchantRepair->startRepair(actor);
} }
void WindowManager::startRepairItem(MWWorld::Ptr item) void WindowManager::startRepairItem(MWWorld::Ptr item)
{ {
mRepair->startRepairItem(item); mRepair->startRepairItem(item);
} }
const Translation::Storage& WindowManager::getTranslationDataStorage() const const Translation::Storage& WindowManager::getTranslationDataStorage() const
{ {
return mTranslationDataStorage; return mTranslationDataStorage;
} }
void WindowManager::showCompanionWindow(MWWorld::Ptr actor) void WindowManager::showCompanionWindow(MWWorld::Ptr actor)
{ {
mCompanionWindow->open(actor); mCompanionWindow->open(actor);
} }
void WindowManager::changePointer(const std::string &name) void WindowManager::changePointer(const std::string &name)
{ {
mCursor->onCursorChange(name); mCursor->onCursorChange(name);
} }
void WindowManager::showSoulgemDialog(MWWorld::Ptr item) void WindowManager::showSoulgemDialog(MWWorld::Ptr item)
{ {
mSoulgemDialog->show(item); mSoulgemDialog->show(item);
} }
void WindowManager::frameStarted (float dt) void WindowManager::frameStarted (float dt)
{ {
mInventoryWindow->doRenderUpdate (); mInventoryWindow->doRenderUpdate ();
}
} }

View file

@ -1,22 +1,20 @@
#include "windowpinnablebase.hpp" #include "windowpinnablebase.hpp"
#include "../mwbase/windowmanager.hpp"
#include "exposedwindow.hpp" #include "exposedwindow.hpp"
using namespace MWGui; namespace MWGui
WindowPinnableBase::WindowPinnableBase(const std::string& parLayout)
: WindowBase(parLayout), mPinned(false), mVisible(false)
{ {
WindowPinnableBase::WindowPinnableBase(const std::string& parLayout)
: WindowBase(parLayout), mPinned(false), mVisible(false)
{
ExposedWindow* window = static_cast<ExposedWindow*>(mMainWidget); ExposedWindow* window = static_cast<ExposedWindow*>(mMainWidget);
mPinButton = window->getSkinWidget ("Button"); mPinButton = window->getSkinWidget ("Button");
mPinButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonClicked); mPinButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonClicked);
} }
void WindowPinnableBase::onPinButtonClicked(MyGUI::Widget* _sender) void WindowPinnableBase::onPinButtonClicked(MyGUI::Widget* _sender)
{ {
mPinned = !mPinned; mPinned = !mPinned;
if (mPinned) if (mPinned)
@ -25,4 +23,5 @@ void WindowPinnableBase::onPinButtonClicked(MyGUI::Widget* _sender)
mPinButton->changeWidgetSkin ("PinUp"); mPinButton->changeWidgetSkin ("PinUp");
onPinToggled(); onPinToggled();
}
} }

View file

@ -290,6 +290,13 @@ namespace MWMechanics
return 0; return 0;
} }
void Actors::forceStateUpdate(const MWWorld::Ptr & ptr)
{
PtrControllerMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
iter->second.forceStateUpdate();
}
void Actors::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) void Actors::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number)
{ {
PtrControllerMap::iterator iter = mActors.find(ptr); PtrControllerMap::iterator iter = mActors.find(ptr);

View file

@ -78,6 +78,8 @@ namespace MWMechanics
int countDeaths (const std::string& id) const; int countDeaths (const std::string& id) const;
///< Return the number of deaths for actors with the given ID. ///< Return the number of deaths for actors with the given ID.
void forceStateUpdate(const MWWorld::Ptr &ptr);
void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number); void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
void skipAnimation(const MWWorld::Ptr& ptr); void skipAnimation(const MWWorld::Ptr& ptr);
}; };

View file

@ -103,14 +103,13 @@ static void getStateInfo(CharacterState state, std::string *group)
CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop) CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop)
: mPtr(ptr), mAnimation(anim), mState(state), mSkipAnim(false) : mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false)
{ {
if(!mAnimation) if(!mAnimation)
return; return;
mAnimation->setController(this); std::string group;
getStateInfo(mCharState, &group);
getStateInfo(mState, &mCurrentGroup);
if(MWWorld::Class::get(mPtr).isActor()) if(MWWorld::Class::get(mPtr).isActor())
{ {
/* Accumulate along X/Y only for now, until we can figure out how we should /* Accumulate along X/Y only for now, until we can figure out how we should
@ -122,19 +121,8 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
/* Don't accumulate with non-actors. */ /* Don't accumulate with non-actors. */
mAnimation->setAccumulation(Ogre::Vector3(0.0f)); mAnimation->setAccumulation(Ogre::Vector3(0.0f));
} }
if(mAnimation->hasAnimation(mCurrentGroup)) if(mAnimation->hasAnimation(group))
mAnimation->play(mCurrentGroup, "stop", "stop", loop); mMovingAnim = mAnimation->play(group, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0);
}
CharacterController::CharacterController(const CharacterController &rhs)
: mPtr(rhs.mPtr), mAnimation(rhs.mAnimation), mAnimQueue(rhs.mAnimQueue)
, mCurrentGroup(rhs.mCurrentGroup), mState(rhs.mState)
, mSkipAnim(rhs.mSkipAnim)
{
if(!mAnimation)
return;
/* We've been copied. Update the animation with the new controller. */
mAnimation->setController(this);
} }
CharacterController::~CharacterController() CharacterController::~CharacterController()
@ -148,31 +136,6 @@ void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
} }
void CharacterController::markerEvent(float time, const std::string &evt)
{
if(evt == "stop")
{
if(mAnimQueue.size() >= 2 && mAnimQueue[0] == mAnimQueue[1])
{
mAnimQueue.pop_front();
mAnimation->play(mCurrentGroup, "loop start", "stop", false);
}
else if(mAnimQueue.size() > 0)
{
mAnimQueue.pop_front();
if(mAnimQueue.size() > 0)
{
mCurrentGroup = mAnimQueue.front();
mAnimation->play(mCurrentGroup, "start", "stop", false);
}
}
return;
}
std::cerr<< "Unhandled animation event: "<<evt <<std::endl;
}
void CharacterController::update(float duration, Movement &movement) void CharacterController::update(float duration, Movement &movement)
{ {
float speed = 0.0f; float speed = 0.0f;
@ -214,11 +177,13 @@ void CharacterController::update(float duration, Movement &movement)
if(vec.x > 0.0f) if(vec.x > 0.0f)
setState(inwater ? (isrunning ? CharState_SwimRunRight : CharState_SwimWalkRight) setState(inwater ? (isrunning ? CharState_SwimRunRight : CharState_SwimWalkRight)
: (sneak ? CharState_SneakRight : (isrunning ? CharState_RunRight : CharState_WalkRight)), true); : (sneak ? CharState_SneakRight : (isrunning ? CharState_RunRight : CharState_WalkRight)), true);
else if(vec.x < 0.0f) else if(vec.x < 0.0f)
setState(inwater ? (isrunning ? CharState_SwimRunLeft : CharState_SwimWalkLeft) setState(inwater ? (isrunning ? CharState_SwimRunLeft : CharState_SwimWalkLeft)
: (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true); : (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true);
// If this animation isn't moving us sideways, do it manually
if(!mMovingAnim)
movement.mPosition[0] += vec.x * (speed*duration);
// Apply any forward/backward movement manually // Apply any forward/backward movement manually
movement.mPosition[1] += vec.y * (speed*duration); movement.mPosition[1] += vec.y * (speed*duration);
} }
@ -227,12 +192,15 @@ void CharacterController::update(float duration, Movement &movement)
if(vec.y > 0.0f) if(vec.y > 0.0f)
setState(inwater ? (isrunning ? CharState_SwimRunForward : CharState_SwimWalkForward) setState(inwater ? (isrunning ? CharState_SwimRunForward : CharState_SwimWalkForward)
: (sneak ? CharState_SneakForward : (isrunning ? CharState_RunForward : CharState_WalkForward)), true); : (sneak ? CharState_SneakForward : (isrunning ? CharState_RunForward : CharState_WalkForward)), true);
else if(vec.y < 0.0f) else if(vec.y < 0.0f)
setState(inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack) setState(inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack)
: (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack)), true); : (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack)), true);
// Apply any sideways movement manually // Apply any sideways movement manually
movement.mPosition[0] += vec.x * (speed*duration); movement.mPosition[0] += vec.x * (speed*duration);
// If this animation isn't moving us forward/backward, do it manually
if(!mMovingAnim)
movement.mPosition[1] += vec.y * (speed*duration);
} }
else if(rot.z != 0.0f && !inwater && !sneak) else if(rot.z != 0.0f && !inwater && !sneak)
{ {
@ -241,8 +209,18 @@ void CharacterController::update(float duration, Movement &movement)
else if(rot.z < 0.0f) else if(rot.z < 0.0f)
setState(CharState_TurnLeft, true); setState(CharState_TurnLeft, true);
} }
else if(mAnimQueue.size() == 0) else if(getState() != CharState_SpecialIdle || !mAnimation->isPlaying(0))
{
if(mAnimQueue.size() == 0)
setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true);
else
{
mMovingAnim = mAnimation->play(mAnimQueue.front().first,
"start", "stop", 0.0f,
mAnimQueue.front().second);
mAnimQueue.pop_front();
}
}
movement.mRotation[0] += rot.x * duration; movement.mRotation[0] += rot.x * duration;
movement.mRotation[1] += rot.y * duration; movement.mRotation[1] += rot.y * duration;
@ -268,20 +246,17 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int
else else
{ {
count = std::max(count, 1); count = std::max(count, 1);
if(mode != 0 || mAnimQueue.size() == 0) if(mode != 0 || getState() != CharState_SpecialIdle)
{ {
mAnimQueue.clear(); mAnimQueue.clear();
while(count-- > 0) mCharState = CharState_SpecialIdle;
mAnimQueue.push_back(groupname); mLooping = false;
mCurrentGroup = groupname; mMovingAnim = mAnimation->play(groupname, ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1);
mState = CharState_SpecialIdle;
mAnimation->play(mCurrentGroup, ((mode==2) ? "loop start" : "start"), "stop", false);
} }
else if(mode == 0) else if(mode == 0)
{ {
mAnimQueue.resize(1); mAnimQueue.clear();
while(count-- > 0) mAnimQueue.push_back(std::make_pair(groupname, count-1));
mAnimQueue.push_back(groupname);
} }
} }
} }
@ -294,25 +269,24 @@ void CharacterController::skipAnim()
void CharacterController::setState(CharacterState state, bool loop) void CharacterController::setState(CharacterState state, bool loop)
{ {
if(mState == state) if(mCharState == state)
{
if(mAnimation)
mAnimation->setLooping(loop);
return; return;
} mCharState = state;
mState = state; mLooping = loop;
forceStateUpdate();
}
void CharacterController::forceStateUpdate()
{
if(!mAnimation) if(!mAnimation)
return; return;
mAnimQueue.clear(); mAnimQueue.clear();
std::string anim; std::string anim;
getStateInfo(mState, &anim); getStateInfo(mCharState, &anim);
if(mAnimation->hasAnimation(anim)) if((mMovingAnim=mAnimation->hasAnimation(anim)) != false)
{ mMovingAnim = mAnimation->play(anim, "start", "stop", 0.0f, mLooping ? (~(size_t)0) : 0);
mCurrentGroup = anim;
mAnimation->play(mCurrentGroup, "start", "stop", loop);
}
} }
} }

View file

@ -72,22 +72,17 @@ class CharacterController
MWWorld::Ptr mPtr; MWWorld::Ptr mPtr;
MWRender::Animation *mAnimation; MWRender::Animation *mAnimation;
typedef std::deque<std::string> AnimationQueue; typedef std::deque<std::pair<std::string,size_t> > AnimationQueue;
AnimationQueue mAnimQueue; AnimationQueue mAnimQueue;
std::string mCurrentGroup; CharacterState mCharState;
CharacterState mState; bool mLooping;
bool mSkipAnim; bool mSkipAnim;
protected: bool mMovingAnim;
/* Called by the animation whenever a new text key is reached. */
void markerEvent(float time, const std::string &evt);
friend class MWRender::Animation;
public: public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop); CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop);
CharacterController(const CharacterController &rhs);
virtual ~CharacterController(); virtual ~CharacterController();
void updatePtr(const MWWorld::Ptr &ptr); void updatePtr(const MWWorld::Ptr &ptr);
@ -99,7 +94,9 @@ public:
void setState(CharacterState state, bool loop); void setState(CharacterState state, bool loop);
CharacterState getState() const CharacterState getState() const
{ return mState; } { return mCharState; }
void forceStateUpdate();
}; };
} }

View file

@ -548,7 +548,7 @@ namespace MWMechanics
float bribeMod; float bribeMod;
if (type == PT_Bribe10) bribeMod = gmst.find("fBribe10Mod")->getFloat(); if (type == PT_Bribe10) bribeMod = gmst.find("fBribe10Mod")->getFloat();
if (type == PT_Bribe100) bribeMod = gmst.find("fBribe100Mod")->getFloat(); else if (type == PT_Bribe100) bribeMod = gmst.find("fBribe100Mod")->getFloat();
else bribeMod = gmst.find("fBribe1000Mod")->getFloat(); else bribeMod = gmst.find("fBribe1000Mod")->getFloat();
float target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod; float target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod;
@ -654,6 +654,12 @@ namespace MWMechanics
} }
} }
void MechanicsManager::forceStateUpdate(const MWWorld::Ptr &ptr)
{
if(MWWorld::Class::get(ptr).isActor())
mActors.forceStateUpdate(ptr);
}
void MechanicsManager::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) void MechanicsManager::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number)
{ {
if(MWWorld::Class::get(ptr).isActor()) if(MWWorld::Class::get(ptr).isActor())

View file

@ -96,6 +96,8 @@ namespace MWMechanics
void toLower(std::string npcFaction); void toLower(std::string npcFaction);
///< Perform a persuasion action on NPC ///< Perform a persuasion action on NPC
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number); virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
virtual void skipAnimation(const MWWorld::Ptr& ptr); virtual void skipAnimation(const MWWorld::Ptr& ptr);
}; };

View file

@ -1,5 +1,5 @@
#include "pathfinding.hpp" #include "pathfinding.hpp"
#include <boost/graph/astar_search.hpp> #include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/adjacency_list.hpp>
#include "boost/tuple/tuple.hpp" #include "boost/tuple/tuple.hpp"
#include "OgreMath.h" #include "OgreMath.h"
@ -55,7 +55,7 @@ namespace
struct found_path {}; struct found_path {};
class goalVisited : public boost::default_astar_visitor /*class goalVisited : public boost::default_astar_visitor
{ {
public: public:
goalVisited(PointID goal) : mGoal(goal) {} goalVisited(PointID goal) : mGoal(goal) {}
@ -69,7 +69,7 @@ namespace
PointID mGoal; PointID mGoal;
}; };
class DistanceHeuristic : public boost::astar_heuristic <PathGridGraph, float> class DistanceHeuristic : public boost::atasr_heuristic <PathGridGraph, float>
{ {
public: public:
DistanceHeuristic(const PathGridGraph & l, PointID goal) DistanceHeuristic(const PathGridGraph & l, PointID goal)
@ -87,11 +87,23 @@ namespace
private: private:
const PathGridGraph & mGraph; const PathGridGraph & mGraph;
PointID mGoal; PointID mGoal;
}; };*/
}
class goalVisited : public boost::default_dijkstra_visitor
{
public:
goalVisited(PointID goal) : mGoal(goal) {}
void examine_vertex(PointID u, const PathGridGraph g)
{
if(u == mGoal)
throw found_path();
}
private:
PointID mGoal;
};
namespace MWMechanics
{
PathGridGraph buildGraph(const ESM::Pathgrid* pathgrid,float xCell = 0,float yCell = 0) PathGridGraph buildGraph(const ESM::Pathgrid* pathgrid,float xCell = 0,float yCell = 0)
{ {
PathGridGraph graph; PathGridGraph graph;
@ -126,11 +138,10 @@ namespace MWMechanics
std::list<ESM::Pathgrid::Point> shortest_path; std::list<ESM::Pathgrid::Point> shortest_path;
try { try {
boost::astar_search boost::dijkstra_shortest_paths
( (
graph, graph,
start, start,
DistanceHeuristic(graph,end),
boost::predecessor_map(&p[0]).distance_map(&d[0]).visitor(goalVisited(end))//.weight_map(boost::get(&Edge::distance, graph)) boost::predecessor_map(&p[0]).distance_map(&d[0]).visitor(goalVisited(end))//.weight_map(boost::get(&Edge::distance, graph))
); );
@ -146,6 +157,10 @@ namespace MWMechanics
//end of helpers functions //end of helpers functions
}
namespace MWMechanics
{
PathFinder::PathFinder() PathFinder::PathFinder()
{ {
mIsPathConstructed = false; mIsPathConstructed = false;

View file

@ -1,10 +1,5 @@
#include "activatoranimation.hpp" #include "activatoranimation.hpp"
#include <OgreEntity.h>
#include <OgreParticleSystem.h>
#include <OgreSceneManager.h>
#include <OgreSubEntity.h>
#include "renderconst.hpp" #include "renderconst.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -24,28 +19,10 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr)
assert (ref->mBase != NULL); assert (ref->mBase != NULL);
if(!ref->mBase->mModel.empty()) if(!ref->mBase->mModel.empty())
{ {
std::string mesh = "meshes\\" + ref->mBase->mModel; const std::string name = "meshes\\"+ref->mBase->mModel;
createObjectList(mPtr.getRefData().getBaseNode(), mesh); addObjectList(mPtr.getRefData().getBaseNode(), name, false);
for(size_t i = 0;i < mObjectList.mEntities.size();i++) setRenderProperties(mObjects.back().mObjectList, RV_Misc, RQG_Main, RQG_Alpha);
{
Ogre::Entity *ent = mObjectList.mEntities[i];
ent->setVisibilityFlags(RV_Misc);
for(unsigned int j=0; j < ent->getNumSubEntities(); ++j)
{
Ogre::SubEntity* subEnt = ent->getSubEntity(j);
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
}
}
for(size_t i = 0;i < mObjectList.mParticles.size();i++)
{
Ogre::ParticleSystem *part = mObjectList.mParticles[i];
part->setVisibilityFlags(RV_Misc);
part->setRenderQueueGroup(RQG_Alpha);
}
setAnimationSource(mesh);
} }
} }

View file

@ -94,6 +94,9 @@ void Actors::insertActivator (const MWWorld::Ptr& ptr)
bool Actors::deleteObject (const MWWorld::Ptr& ptr) bool Actors::deleteObject (const MWWorld::Ptr& ptr)
{ {
if (mAllActors.find(ptr) == mAllActors.end())
return false;
mRendering->removeWaterRippleEmitter (ptr); mRendering->removeWaterRippleEmitter (ptr);
delete mAllActors[ptr]; delete mAllActors[ptr];
@ -139,6 +142,7 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store)
Ogre::SceneNode *base = celliter->second; Ogre::SceneNode *base = celliter->second;
base->removeAndDestroyAllChildren(); base->removeAndDestroyAllChildren();
mRend.getScene()->destroySceneNode(base); mRend.getScene()->destroySceneNode(base);
mCellSceneNodes.erase(celliter); mCellSceneNodes.erase(celliter);
} }
} }

View file

@ -3,6 +3,8 @@
#include <OgreSkeletonManager.h> #include <OgreSkeletonManager.h>
#include <OgreSkeletonInstance.h> #include <OgreSkeletonInstance.h>
#include <OgreEntity.h> #include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreParticleSystem.h>
#include <OgreBone.h> #include <OgreBone.h>
#include <OgreSubMesh.h> #include <OgreSubMesh.h>
#include <OgreSceneManager.h> #include <OgreSceneManager.h>
@ -16,6 +18,32 @@
namespace MWRender namespace MWRender
{ {
Animation::AnimLayer::AnimLayer()
: mControllers(NULL)
, mTextKeys(NULL)
, mTime(0.0f)
, mPlaying(false)
, mLoopCount(0)
{
}
Ogre::Real Animation::AnimationValue::getValue() const
{
size_t idx = mIndex;
while(idx > 0 && mAnimation->mLayer[idx].mGroupName.empty())
idx--;
if(!mAnimation->mLayer[idx].mGroupName.empty())
return mAnimation->mLayer[idx].mTime;
return 0.0f;
}
void Animation::AnimationValue::setValue(Ogre::Real value)
{
mAnimation->mLayer[mIndex].mTime = value;
}
void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects) void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects)
{ {
for(size_t i = 0;i < objects.mParticles.size();i++) for(size_t i = 0;i < objects.mParticles.size();i++)
@ -31,22 +59,22 @@ void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectL
Animation::Animation(const MWWorld::Ptr &ptr) Animation::Animation(const MWWorld::Ptr &ptr)
: mPtr(ptr) : mPtr(ptr)
, mController(NULL)
, mInsert(NULL) , mInsert(NULL)
, mSkelBase(NULL)
, mAccumRoot(NULL) , mAccumRoot(NULL)
, mNonAccumRoot(NULL) , mNonAccumRoot(NULL)
, mAccumulate(Ogre::Vector3::ZERO) , mNonAccumCtrl(NULL)
, mAccumulate(0.0f)
, mLastPosition(0.0f) , mLastPosition(0.0f)
, mCurrentControllers(NULL)
, mCurrentKeys(NULL)
, mCurrentAnim(NULL)
, mCurrentTime(0.0f)
, mStopTime(0.0f)
, mPlaying(false)
, mLooping(false)
, mAnimVelocity(0.0f) , mAnimVelocity(0.0f)
, mAnimSpeedMult(1.0f) , mAnimSpeedMult(1.0f)
{ {
for(size_t i = 0;i < sMaxLayers;i++)
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this, i));
/* As long as we remain under 128 active controllers, we can avoid
* reallocations. */
mActiveCtrls.reserve(128);
} }
Animation::~Animation() Animation::~Animation()
@ -54,105 +82,34 @@ Animation::~Animation()
if(mInsert) if(mInsert)
{ {
Ogre::SceneManager *sceneMgr = mInsert->getCreator(); Ogre::SceneManager *sceneMgr = mInsert->getCreator();
destroyObjectList(sceneMgr, mObjectList); for(size_t i = 0;i < mObjects.size();i++)
destroyObjectList(sceneMgr, mObjects[i].mObjectList);
for(size_t i = 0;i < mAnimationSources.size();i++) mObjects.clear();
destroyObjectList(sceneMgr, mAnimationSources[i]);
mAnimationSources.clear();
} }
} }
void Animation::setAnimationSources(const std::vector<std::string> &names) void Animation::addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly)
{ {
if(!mObjectList.mSkelBase) if(!mInsert)
return;
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
mCurrentControllers = &mObjectList.mControllers;
mCurrentAnim = NULL;
mCurrentKeys = NULL;
mAnimVelocity = 0.0f;
mAccumRoot = NULL;
mNonAccumRoot = NULL;
mTextKeys.clear();
for(size_t i = 0;i < mAnimationSources.size();i++)
destroyObjectList(sceneMgr, mAnimationSources[i]);
mAnimationSources.clear();
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton();
std::vector<std::string>::const_iterator nameiter;
for(nameiter = names.begin();nameiter != names.end();nameiter++)
{ {
mAnimationSources.push_back(NifOgre::Loader::createObjectBase(sceneMgr, *nameiter));
if(!mAnimationSources.back().mSkelBase)
{
std::cerr<< "Failed to get skeleton source "<<*nameiter <<std::endl;
destroyObjectList(sceneMgr, mAnimationSources.back());
mAnimationSources.pop_back();
continue;
}
NifOgre::ObjectList &objects = mAnimationSources.back();
for(size_t i = 0;i < objects.mControllers.size();i++)
{
NifOgre::NodeTargetValue<Ogre::Real> *dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objects.mControllers[i].getDestination().getPointer());
if(!dstval) continue;
const Ogre::String &trgtname = dstval->getNode()->getName();
if(!skelinst->hasBone(trgtname)) continue;
Ogre::Bone *bone = skelinst->getBone(trgtname);
dstval->setNode(bone);
}
for(size_t i = 0;i < objects.mControllers.size();i++)
{
if(objects.mControllers[i].getSource().isNull())
objects.mControllers[i].setSource(ctrlval);
}
Ogre::Entity *ent = objects.mSkelBase;
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName());
Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator();
while(boneiter.hasMoreElements())
{
Ogre::Bone *bone = boneiter.getNext();
Ogre::UserObjectBindings &bindings = bone->getUserObjectBindings();
const Ogre::Any &data = bindings.getUserAny(NifOgre::sTextKeyExtraDataID);
if(data.isEmpty() || !Ogre::any_cast<bool>(data))
continue;
if(!mNonAccumRoot)
{
mAccumRoot = mInsert;
mNonAccumRoot = mObjectList.mSkelBase->getSkeleton()->getBone(bone->getName());
}
for(int i = 0;i < skel->getNumAnimations();i++)
{
Ogre::Animation *anim = skel->getAnimation(i);
const Ogre::Any &groupdata = bindings.getUserAny(std::string(NifOgre::sTextKeyExtraDataID)+
"@"+anim->getName());
if(!groupdata.isEmpty())
mTextKeys[anim->getName()] = Ogre::any_cast<NifOgre::TextKeyMap>(groupdata);
}
break;
}
}
}
void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model)
{
mInsert = node->createChildSceneNode(); mInsert = node->createChildSceneNode();
assert(mInsert); assert(mInsert);
}
mObjectList = NifOgre::Loader::createObjects(mInsert, model); mObjects.push_back(ObjectInfo());
if(mObjectList.mSkelBase) ObjectInfo &obj = mObjects.back();
obj.mActiveLayers = 0;
obj.mObjectList = (!baseonly ? NifOgre::Loader::createObjects(mInsert, model) :
NifOgre::Loader::createObjectBase(mInsert, model));
NifOgre::ObjectList &objlist = obj.mObjectList;
if(objlist.mSkelBase)
{ {
Ogre::AnimationStateSet *aset = mObjectList.mSkelBase->getAllAnimationStates(); if(mObjects.size() == 1)
mSkelBase = objlist.mSkelBase;
Ogre::AnimationStateSet *aset = objlist.mSkelBase->getAllAnimationStates();
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
while(asiter.hasMoreElements()) while(asiter.hasMoreElements())
{ {
@ -164,27 +121,184 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model
// Set the bones as manually controlled since we're applying the // Set the bones as manually controlled since we're applying the
// transformations manually (needed if we want to apply an animation // transformations manually (needed if we want to apply an animation
// from one skeleton onto another). // from one skeleton onto another).
Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton(); Ogre::SkeletonInstance *skelinst = objlist.mSkelBase->getSkeleton();
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
while(boneiter.hasMoreElements()) while(boneiter.hasMoreElements())
boneiter.getNext()->setManuallyControlled(true); boneiter.getNext()->setManuallyControlled(true);
} }
if(objlist.mSkelBase && mSkelBase)
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
for(size_t i = 0;i < mObjectList.mControllers.size();i++)
{ {
if(mObjectList.mControllers[i].getSource().isNull()) Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
mObjectList.mControllers[i].setSource(ctrlval); if(mSkelBase == objlist.mSkelBase)
{
if(objlist.mTextKeys.size() > 0)
{
mAccumRoot = mInsert;
mNonAccumRoot = baseinst->getBone(objlist.mTextKeys.begin()->first);
}
}
else
{
for(size_t i = 0;i < objlist.mControllers.size();i++)
{
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objlist.mControllers[i].getDestination().getPointer());
if(!dstval) continue;
const Ogre::String &trgtname = dstval->getNode()->getName();
if(!baseinst->hasBone(trgtname)) continue;
Ogre::Bone *bone = baseinst->getBone(trgtname);
dstval->setNode(bone);
}
}
}
for(size_t i = 0;i < objlist.mControllers.size();i++)
{
if(objlist.mControllers[i].getSource().isNull())
objlist.mControllers[i].setSource(mAnimationValuePtr[0]);
}
mActiveCtrls.insert(mActiveCtrls.end(), objlist.mControllers.begin(), objlist.mControllers.end());
}
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue)
{
for(size_t i = 0;i < objlist.mEntities.size();i++)
{
Ogre::Entity *ent = objlist.mEntities[i];
if(visflags != 0)
ent->setVisibilityFlags(visflags);
for(unsigned int j = 0;j < ent->getNumSubEntities();++j)
{
Ogre::SubEntity* subEnt = ent->getSubEntity(j);
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? transqueue : solidqueue);
}
}
for(size_t i = 0;i < objlist.mParticles.size();i++)
{
Ogre::ParticleSystem *part = objlist.mParticles[i];
if(visflags != 0)
part->setVisibilityFlags(visflags);
// TODO: Check particle material for actual transparency
part->setRenderQueueGroup(transqueue);
}
}
void Animation::clearExtraSources()
{
for(size_t layer = 0;layer < sMaxLayers;layer++)
{
mLayer[layer].mGroupName.clear();
mLayer[layer].mTextKeys = NULL;
mLayer[layer].mControllers = NULL;
mLayer[layer].mTime = 0.0f;
mLayer[layer].mLoopCount = 0;
mLayer[layer].mPlaying = false;
}
mNonAccumCtrl = NULL;
mAnimVelocity = 0.0f;
mLastPosition = Ogre::Vector3(0.0f);
if(mAccumRoot)
mAccumRoot->setPosition(mLastPosition);
if(mObjects.size() > 1)
{
mObjects.resize(1);
mObjects[0].mActiveLayers = 0;
NifOgre::ObjectList &objlist = mObjects[0].mObjectList;
mActiveCtrls.clear();
mActiveCtrls.insert(mActiveCtrls.end(), objlist.mControllers.begin(), objlist.mControllers.end());
}
}
void Animation::updateActiveControllers()
{
mActiveCtrls.clear();
/* First, get all controllers that don't target a node, or that target
* nodes that don't belong to any particular layer.
*/
std::vector<ObjectInfo>::iterator obj(mObjects.begin());
for(;obj != mObjects.end();obj++)
{
std::vector<Ogre::Controller<Ogre::Real> >::const_iterator ctrl(obj->mObjectList.mControllers.begin());
for(;ctrl != obj->mObjectList.mControllers.end();ctrl++)
{
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrl->getDestination().getPointer());
if(dstval)
{
/*if(getLayerByName(dstval->getNode()->getName()) >= 0)*/
continue;
}
mActiveCtrls.insert(mActiveCtrls.end(), *ctrl);
}
}
std::vector<Ogre::Controller<Ogre::Real> > *ctrls = NULL;
size_t layer = 0;
while(layer < sMaxLayers)
{
/* Now get controllers that target nodes that belong to this layer from
* whatever objectlist is active on this layer.
*/
std::vector<ObjectInfo>::iterator obj(mObjects.begin());
for(;obj != mObjects.end();obj++)
{
if((obj->mActiveLayers&(1<<layer)))
{
ctrls = &obj->mObjectList.mControllers;
break;
}
}
if(ctrls == NULL)
{
layer++;
continue;
}
/* Check if any objectlists are active on subsequent layers. Include
* those layers if not.
*/
size_t nextlayer = layer+1;
for(;nextlayer < sMaxLayers;nextlayer++)
{
for(obj = mObjects.begin();obj != mObjects.end();obj++)
{
if((obj->mActiveLayers&(1<<nextlayer)))
break;
}
}
std::vector<Ogre::Controller<Ogre::Real> >::const_iterator ctrl(ctrls->begin());
for(;ctrl != ctrls->end();ctrl++)
{
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrl->getDestination().getPointer());
if(dstval)
{
/*ssize_t idx = getLayerByName(dstval->getNode()->getName());
if(idx >= (ssize_t)layer && idx < (ssize_t)nextlayer)*/
mActiveCtrls.insert(mActiveCtrls.end(), *ctrl);
}
}
layer = nextlayer;
} }
mCurrentControllers = &mObjectList.mControllers;
} }
Ogre::Node *Animation::getNode(const std::string &name) Ogre::Node *Animation::getNode(const std::string &name)
{ {
if(mObjectList.mSkelBase) if(mSkelBase)
{ {
Ogre::SkeletonInstance *skel = mObjectList.mSkelBase->getSkeleton(); Ogre::SkeletonInstance *skel = mSkelBase->getSkeleton();
if(skel->hasBone(name)) if(skel->hasBone(name))
return skel->getBone(name); return skel->getBone(name);
} }
@ -192,20 +306,34 @@ Ogre::Node *Animation::getNode(const std::string &name)
} }
bool Animation::hasAnimation(const std::string &anim) NifOgre::TextKeyMap::const_iterator Animation::findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname)
{ {
for(std::vector<NifOgre::ObjectList>::const_iterator iter(mAnimationSources.begin());iter != mAnimationSources.end();iter++) NifOgre::TextKeyMap::const_iterator iter(keys.begin());
for(;iter != keys.end();iter++)
{ {
if(iter->mSkelBase->hasAnimationState(anim)) if(iter->second.compare(0, groupname.size(), groupname) == 0 &&
return true; iter->second.compare(groupname.size(), 2, ": ") == 0)
break;
} }
return false; return iter;
} }
void Animation::setController(MWMechanics::CharacterController *controller) bool Animation::hasAnimation(const std::string &anim)
{ {
mController = controller; if(!mSkelBase)
return false;
for(std::vector<ObjectInfo>::const_iterator iter(mObjects.begin());iter != mObjects.end();iter++)
{
if(iter->mObjectList.mTextKeys.size() == 0)
continue;
const NifOgre::TextKeyMap &keys = iter->mObjectList.mTextKeys.begin()->second;
if(findGroupStart(keys, anim) != keys.end())
return true;
}
return false;
} }
@ -221,10 +349,6 @@ void Animation::setSpeed(float speed)
mAnimSpeedMult = speed / mAnimVelocity; mAnimSpeedMult = speed / mAnimVelocity;
} }
void Animation::setLooping(bool loop)
{
mLooping = loop;
}
void Animation::updatePtr(const MWWorld::Ptr &ptr) void Animation::updatePtr(const MWWorld::Ptr &ptr)
{ {
@ -232,47 +356,36 @@ void Animation::updatePtr(const MWWorld::Ptr &ptr)
} }
void Animation::calcAnimVelocity() float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const Ogre::Vector3 &accum, const std::string &groupname)
{ {
const Ogre::NodeAnimationTrack *track = 0; const std::string start = groupname+": start";
const std::string loopstart = groupname+": loop start";
Ogre::Animation::NodeTrackIterator trackiter = mCurrentAnim->getNodeTrackIterator(); const std::string loopstop = groupname+": loop stop";
while(!track && trackiter.hasMoreElements()) const std::string stop = groupname+": stop";
float starttime = std::numeric_limits<float>::max();
float stoptime = 0.0f;
NifOgre::TextKeyMap::const_iterator keyiter(keys.begin());
while(keyiter != keys.end())
{ {
const Ogre::NodeAnimationTrack *cur = trackiter.getNext(); if(keyiter->second == start || keyiter->second == loopstart)
if(cur->getAssociatedNode()->getName() == mNonAccumRoot->getName()) starttime = keyiter->first;
track = cur; else if(keyiter->second == loopstop || keyiter->second == stop)
}
if(track && track->getNumKeyFrames() > 1)
{ {
float loopstarttime = 0.0f; stoptime = keyiter->first;
float loopstoptime = mCurrentAnim->getLength();
NifOgre::TextKeyMap::const_iterator keyiter = mCurrentKeys->begin();
while(keyiter != mCurrentKeys->end())
{
if(keyiter->second == "loop start")
loopstarttime = keyiter->first;
else if(keyiter->second == "loop stop")
{
loopstoptime = keyiter->first;
break; break;
} }
keyiter++; keyiter++;
} }
if(loopstoptime > loopstarttime) if(stoptime > starttime)
{ {
Ogre::TransformKeyFrame startkf(0, loopstarttime); Ogre::Vector3 startpos = nonaccumctrl->getTranslation(starttime) * accum;
Ogre::TransformKeyFrame endkf(0, loopstoptime); Ogre::Vector3 endpos = nonaccumctrl->getTranslation(stoptime) * accum;
track->getInterpolatedKeyFrame(mCurrentAnim->_getTimeIndex(loopstarttime), &startkf); return startpos.distance(endpos) / (stoptime-starttime);
track->getInterpolatedKeyFrame(mCurrentAnim->_getTimeIndex(loopstoptime), &endkf); }
mAnimVelocity = startkf.getTranslate().distance(endkf.getTranslate()) / return 0.0f;
(loopstoptime-loopstarttime);
}
}
} }
static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone) static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone)
@ -313,93 +426,90 @@ void Animation::updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Og
} }
Ogre::Vector3 Animation::updatePosition() void Animation::updatePosition(Ogre::Vector3 &position)
{ {
Ogre::Vector3 posdiff; Ogre::Vector3 posdiff;
Ogre::TransformKeyFrame kf(0, mCurrentTime); /* Get the non-accumulation root's difference from the last update, and move the position
Ogre::Animation::NodeTrackIterator trackiter = mCurrentAnim->getNodeTrackIterator(); * accordingly.
while(trackiter.hasMoreElements()) */
{ posdiff = (mNonAccumCtrl->getTranslation(mLayer[0].mTime) - mLastPosition) * mAccumulate;
const Ogre::NodeAnimationTrack *track = trackiter.getNext(); position += posdiff;
if(track->getAssociatedNode()->getName() == mNonAccumRoot->getName())
{
track->getInterpolatedKeyFrame(mCurrentAnim->_getTimeIndex(mCurrentTime), &kf);
break;
}
}
/* Get the non-accumulation root's difference from the last update. */
posdiff = (kf.getTranslate() - mLastPosition) * mAccumulate;
/* Translate the accumulation root back to compensate for the move. */ /* Translate the accumulation root back to compensate for the move. */
mLastPosition += posdiff; mLastPosition += posdiff;
mAccumRoot->setPosition(-mLastPosition); mAccumRoot->setPosition(-mLastPosition);
return posdiff;
} }
void Animation::reset(const std::string &start, const std::string &stop) bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint)
{ {
mNextKey = mCurrentKeys->begin(); std::string tag = groupname+": "+start;
NifOgre::TextKeyMap::const_iterator startkey(keys.begin());
while(mNextKey != mCurrentKeys->end() && mNextKey->second != start) while(startkey != keys.end() && startkey->second != tag)
mNextKey++; startkey++;
if(mNextKey != mCurrentKeys->end()) if(startkey == keys.end() && start == "loop start")
mCurrentTime = mNextKey->first;
else
{ {
mNextKey = mCurrentKeys->begin(); tag = groupname+": start";
while(mNextKey != mCurrentKeys->end() && mNextKey->second != "start") startkey = keys.begin();
mNextKey++; while(startkey != keys.end() && startkey->second != tag)
if(mNextKey != mCurrentKeys->end()) startkey++;
mCurrentTime = mNextKey->first;
else
{
mNextKey = mCurrentKeys->begin();
mCurrentTime = 0.0f;
} }
if(startkey == keys.end())
return false;
tag = groupname+": "+stop;
NifOgre::TextKeyMap::const_iterator stopkey(startkey);
while(stopkey != keys.end() && stopkey->second != tag)
stopkey++;
if(stopkey == keys.end())
return false;
if(startkey == stopkey)
return false;
mLayer[layeridx].mStartKey = startkey;
mLayer[layeridx].mLoopStartKey = startkey;
mLayer[layeridx].mStopKey = stopkey;
mLayer[layeridx].mNextKey = startkey;
mLayer[layeridx].mTime = mLayer[layeridx].mStartKey->first + ((mLayer[layeridx].mStopKey->first-
mLayer[layeridx].mStartKey->first) * startpoint);
tag = groupname+": loop start";
while(mLayer[layeridx].mNextKey->first <= mLayer[layeridx].mTime && mLayer[layeridx].mNextKey != mLayer[layeridx].mStopKey)
{
if(mLayer[layeridx].mNextKey->second == tag)
mLayer[layeridx].mLoopStartKey = mLayer[layeridx].mNextKey;
mLayer[layeridx].mNextKey++;
} }
if(stop.length() > 0) if(layeridx == 0 && nonaccumctrl)
{ mLastPosition = nonaccumctrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate;
NifOgre::TextKeyMap::const_iterator stopKey = mNextKey;
while(stopKey != mCurrentKeys->end() && stopKey->second != stop)
stopKey++;
if(stopKey != mCurrentKeys->end())
mStopTime = stopKey->first;
else
mStopTime = mCurrentAnim->getLength();
}
if(mNonAccumRoot)
{
const Ogre::NodeAnimationTrack *track = 0;
Ogre::Animation::NodeTrackIterator trackiter = mCurrentAnim->getNodeTrackIterator();
while(!track && trackiter.hasMoreElements())
{
const Ogre::NodeAnimationTrack *cur = trackiter.getNext();
if(cur->getAssociatedNode()->getName() == mNonAccumRoot->getName())
track = cur;
}
if(track)
{
Ogre::TransformKeyFrame kf(0, mCurrentTime);
track->getInterpolatedKeyFrame(mCurrentAnim->_getTimeIndex(mCurrentTime), &kf);
mLastPosition = kf.getTranslate() * mAccumulate;
}
}
}
bool Animation::handleEvent(float time, const std::string &evt)
{
if(evt == "start" || evt == "loop start")
{
/* Do nothing */
return true; return true;
} }
bool Animation::doLoop(size_t layeridx)
{
if(mLayer[layeridx].mLoopCount == 0)
return false;
mLayer[layeridx].mLoopCount--;
mLayer[layeridx].mTime = mLayer[layeridx].mLoopStartKey->first;
mLayer[layeridx].mNextKey = mLayer[layeridx].mLoopStartKey;
mLayer[layeridx].mNextKey++;
mLayer[layeridx].mPlaying = true;
if(layeridx == 0 && mNonAccumCtrl)
mLastPosition = mNonAccumCtrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate;
return true;
}
bool Animation::handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key)
{
float time = key->first;
const std::string &evt = key->second;
if(evt.compare(0, 7, "sound: ") == 0) if(evt.compare(0, 7, "sound: ") == 0)
{ {
@ -414,105 +524,214 @@ bool Animation::handleEvent(float time, const std::string &evt)
return true; return true;
} }
if(evt == "loop stop") if(evt.compare(0, mLayer[layeridx].mGroupName.size(), mLayer[layeridx].mGroupName) != 0 ||
evt.compare(mLayer[layeridx].mGroupName.size(), 2, ": ") != 0)
{ {
if(mLooping) // Not ours, skip it
return true;
}
size_t off = mLayer[layeridx].mGroupName.size()+2;
size_t len = evt.size() - off;
if(evt.compare(off, len, "start") == 0 || evt.compare(off, len, "loop start") == 0)
{ {
reset("loop start", ""); mLayer[layeridx].mLoopStartKey = key;
if(mCurrentTime >= time) return true;
}
if(evt.compare(off, len, "loop stop") == 0 || evt.compare(off, len, "stop") == 0)
{
if(doLoop(layeridx))
{
if(mLayer[layeridx].mTime >= time)
return false; return false;
} }
return true; return true;
} }
if(evt == "stop")
{ std::cerr<< "Unhandled animation textkey: "<<evt <<std::endl;
if(mLooping)
{
reset("loop start", "");
if(mCurrentTime >= time)
return false;
return true;
}
// fall-through
}
if(mController)
mController->markerEvent(time, evt);
return true; return true;
} }
void Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, bool loop) bool Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops)
{ {
try { // TODO: parameterize this
bool found = false; size_t layeridx = 0;
if(!mSkelBase)
return false;
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
iter->mActiveLayers &= ~(1<<layeridx);
mLayer[layeridx].mGroupName.clear();
mLayer[layeridx].mTextKeys = NULL;
mLayer[layeridx].mControllers = NULL;
mLayer[layeridx].mTime = 0.0f;
mLayer[layeridx].mLoopCount = 0;
mLayer[layeridx].mPlaying = false;
bool movinganim = false;
bool foundanim = false;
/* Look in reverse; last-inserted source has priority. */ /* Look in reverse; last-inserted source has priority. */
for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) for(std::vector<ObjectInfo>::reverse_iterator iter(mObjects.rbegin());iter != mObjects.rend();iter++)
{ {
if(iter->mSkelBase->hasAnimationState(groupname)) NifOgre::ObjectList &objlist = iter->mObjectList;
if(objlist.mTextKeys.size() == 0)
continue;
const NifOgre::TextKeyMap &keys = objlist.mTextKeys.begin()->second;
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
if(layeridx == 0 && mNonAccumRoot)
{ {
mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname); for(size_t i = 0;i < objlist.mControllers.size();i++)
mCurrentKeys = &mTextKeys[groupname]; {
mCurrentControllers = &iter->mControllers; NifOgre::NodeTargetValue<Ogre::Real> *dstval;
mAnimVelocity = 0.0f; dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objlist.mControllers[i].getDestination().getPointer());
if(dstval && dstval->getNode() == mNonAccumRoot)
if(mNonAccumRoot) {
calcAnimVelocity(); nonaccumctrl = dstval;
found = true;
break; break;
} }
} }
if(!found) }
throw std::runtime_error("Failed to find animation "+groupname);
reset(start, stop); if(!foundanim)
setLooping(loop); {
mPlaying = true; if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop, startpoint))
continue;
mLayer[layeridx].mGroupName = groupname;
mLayer[layeridx].mTextKeys = &keys;
mLayer[layeridx].mControllers = &objlist.mControllers;
mLayer[layeridx].mLoopCount = loops;
mLayer[layeridx].mPlaying = true;
if(layeridx == 0)
{
mNonAccumCtrl = nonaccumctrl;
mAnimVelocity = 0.0f;
} }
catch(std::exception &e) {
std::cerr<< e.what() <<std::endl; iter->mActiveLayers |= (1<<layeridx);
foundanim = true;
if(mAccumulate == Ogre::Vector3(0.0f))
break;
} }
if(!nonaccumctrl)
break;
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, mAccumulate, groupname);
if(mAnimVelocity > 1.0f)
{
movinganim = (nonaccumctrl==mNonAccumCtrl);
break;
}
}
if(!foundanim)
std::cerr<< "Failed to find animation "<<groupname <<std::endl;
updateActiveControllers();
return movinganim;
} }
Ogre::Vector3 Animation::runAnimation(float timepassed) void Animation::disable(size_t layeridx)
{
if(mLayer[layeridx].mGroupName.empty())
return;
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
iter->mActiveLayers &= ~(1<<layeridx);
mLayer[layeridx].mGroupName.clear();
mLayer[layeridx].mTextKeys = NULL;
mLayer[layeridx].mControllers = NULL;
mLayer[layeridx].mTime = 0.0f;
mLayer[layeridx].mLoopCount = 0;
mLayer[layeridx].mPlaying = false;
updateActiveControllers();
}
bool Animation::getInfo(size_t layeridx, float *complete, std::string *groupname, std::string *start, std::string *stop) const
{
if(mLayer[layeridx].mGroupName.empty())
{
if(complete) *complete = 0.0f;
if(groupname) *groupname = "";
if(start) *start = "";
if(stop) *stop = "";
return false;
}
if(complete) *complete = (mLayer[layeridx].mTime - mLayer[layeridx].mStartKey->first) /
(mLayer[layeridx].mStopKey->first - mLayer[layeridx].mStartKey->first);
if(groupname) *groupname = mLayer[layeridx].mGroupName;
if(start) *start = mLayer[layeridx].mStartKey->second.substr(mLayer[layeridx].mGroupName.size()+2);
if(stop) *stop = mLayer[layeridx].mStopKey->second.substr(mLayer[layeridx].mGroupName.size()+2);
return true;
}
Ogre::Vector3 Animation::runAnimation(float duration)
{ {
Ogre::Vector3 movement(0.0f); Ogre::Vector3 movement(0.0f);
timepassed *= mAnimSpeedMult; duration *= mAnimSpeedMult;
while(mCurrentAnim && mPlaying) for(size_t layeridx = 0;layeridx < sMaxLayers;layeridx++)
{ {
float targetTime = mCurrentTime + timepassed; if(mLayer[layeridx].mGroupName.empty())
if(mNextKey == mCurrentKeys->end() || mNextKey->first > targetTime) continue;
float timepassed = duration;
while(mLayer[layeridx].mPlaying)
{ {
mCurrentTime = std::min(mStopTime, targetTime); float targetTime = mLayer[layeridx].mTime + timepassed;
if(mNonAccumRoot) if(mLayer[layeridx].mNextKey->first > targetTime)
movement += updatePosition(); {
mPlaying = (mLooping || mStopTime > mCurrentTime); mLayer[layeridx].mTime = targetTime;
timepassed = targetTime - mCurrentTime; if(layeridx == 0 && mNonAccumCtrl)
updatePosition(movement);
break; break;
} }
float time = mNextKey->first; NifOgre::TextKeyMap::const_iterator key(mLayer[layeridx].mNextKey++);
const std::string &evt = mNextKey->second; mLayer[layeridx].mTime = key->first;
mNextKey++; if(layeridx == 0 && mNonAccumCtrl)
updatePosition(movement);
mCurrentTime = time; mLayer[layeridx].mPlaying = (key != mLayer[layeridx].mStopKey);
if(mNonAccumRoot) timepassed = targetTime - mLayer[layeridx].mTime;
movement += updatePosition();
mPlaying = (mLooping || mStopTime > mCurrentTime);
timepassed = targetTime - mCurrentTime;
if(!handleEvent(time, evt)) if(!handleTextKey(layeridx, key))
break; break;
} }
for(size_t i = 0;i < mCurrentControllers->size();i++) }
(*mCurrentControllers)[i].update();
if(mObjectList.mSkelBase) for(size_t i = 0;i < mActiveCtrls.size();i++)
mActiveCtrls[i].update();
if(mSkelBase)
{ {
const Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
{
Ogre::Entity *ent = iter->mObjectList.mSkelBase;
if(!ent) continue;
Ogre::SkeletonInstance *inst = ent->getSkeleton();
if(baseinst != inst)
updateSkeletonInstance(baseinst, inst);
// HACK: Dirty the animation state set so that Ogre will apply the // HACK: Dirty the animation state set so that Ogre will apply the
// transformations to entities this skeleton instance is shared with. // transformations to entities this skeleton instance is shared with.
mObjectList.mSkelBase->getAllAnimationStates()->_notifyDirty(); ent->getAllAnimationStates()->_notifyDirty();
}
} }
return movement; return movement;

View file

@ -8,10 +8,6 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
namespace MWMechanics
{
class CharacterController;
}
namespace MWRender namespace MWRender
{ {
@ -23,48 +19,67 @@ protected:
{ {
private: private:
Animation *mAnimation; Animation *mAnimation;
size_t mIndex;
public: public:
AnimationValue(Animation *anim) : mAnimation(anim) AnimationValue(Animation *anim, size_t layeridx)
: mAnimation(anim), mIndex(layeridx)
{ } { }
virtual Ogre::Real getValue() const virtual Ogre::Real getValue() const;
{ virtual void setValue(Ogre::Real value);
return mAnimation->mCurrentTime; };
}
virtual void setValue(Ogre::Real value) struct ObjectInfo {
{ NifOgre::ObjectList mObjectList;
mAnimation->mCurrentTime = value; /* Bit-field specifying which animation layers this object list is
} * explicitly animating on (1 = layer 0, 2 = layer 1, 4 = layer 2.
* etc).
*/
int mActiveLayers;
};
struct AnimLayer {
std::string mGroupName;
std::vector<Ogre::Controller<Ogre::Real> > *mControllers;
const NifOgre::TextKeyMap *mTextKeys;
NifOgre::TextKeyMap::const_iterator mStartKey;
NifOgre::TextKeyMap::const_iterator mLoopStartKey;
NifOgre::TextKeyMap::const_iterator mStopKey;
NifOgre::TextKeyMap::const_iterator mNextKey;
float mTime;
bool mPlaying;
size_t mLoopCount;
AnimLayer();
}; };
MWWorld::Ptr mPtr; MWWorld::Ptr mPtr;
MWMechanics::CharacterController *mController;
Ogre::SceneNode* mInsert; Ogre::SceneNode *mInsert;
NifOgre::ObjectList mObjectList; Ogre::Entity *mSkelBase;
std::map<std::string,NifOgre::TextKeyMap> mTextKeys; std::vector<ObjectInfo> mObjects;
Ogre::Node *mAccumRoot; Ogre::Node *mAccumRoot;
Ogre::Bone *mNonAccumRoot; Ogre::Bone *mNonAccumRoot;
NifOgre::NodeTargetValue<Ogre::Real> *mNonAccumCtrl;
Ogre::Vector3 mAccumulate; Ogre::Vector3 mAccumulate;
Ogre::Vector3 mLastPosition; Ogre::Vector3 mLastPosition;
std::vector<NifOgre::ObjectList> mAnimationSources; std::vector<Ogre::Controller<Ogre::Real> > mActiveCtrls;
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
NifOgre::TextKeyMap *mCurrentKeys;
NifOgre::TextKeyMap::const_iterator mNextKey;
Ogre::Animation *mCurrentAnim;
float mCurrentTime;
float mStopTime;
bool mPlaying;
bool mLooping;
float mAnimVelocity; float mAnimVelocity;
float mAnimSpeedMult; float mAnimSpeedMult;
void calcAnimVelocity(); static const size_t sMaxLayers = 1;
AnimLayer mLayer[sMaxLayers];
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > mAnimationValuePtr[sMaxLayers];
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
const Ogre::Vector3 &accum,
const std::string &groupname);
/* Updates a skeleton instance so that all bones matching the source skeleton (based on /* Updates a skeleton instance so that all bones matching the source skeleton (based on
* bone names) are positioned identically. */ * bone names) are positioned identically. */
@ -72,34 +87,39 @@ protected:
/* Updates the position of the accum root node for the current time, and /* Updates the position of the accum root node for the current time, and
* returns the wanted movement vector from the previous update. */ * returns the wanted movement vector from the previous update. */
Ogre::Vector3 updatePosition(); void updatePosition(Ogre::Vector3 &position);
static NifOgre::TextKeyMap::const_iterator findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname);
/* Resets the animation to the time of the specified start marker, without /* Resets the animation to the time of the specified start marker, without
* moving anything, and set the end time to the specified stop marker. If * moving anything, and set the end time to the specified stop marker. If
* the marker is not found, it resets to the beginning or end respectively. * the marker is not found, or if the markers are the same, it returns
* false.
*/ */
void reset(const std::string &start, const std::string &stop); bool reset(size_t layeridx, const NifOgre::TextKeyMap &keys,
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
const std::string &groupname, const std::string &start, const std::string &stop,
float startpoint);
bool handleEvent(float time, const std::string &evt); bool doLoop(size_t layeridx);
/* Specifies a list of skeleton names to use as animation sources. */ bool handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_iterator &key);
void setAnimationSources(const std::vector<std::string> &names);
/* Specifies a single skeleton name to use as an animation source. */ void addObjectList(Ogre::SceneNode *node, const std::string &model, bool baseonly);
void setAnimationSource(const std::string &name)
{
std::vector<std::string> names(1, name);
setAnimationSources(names);
}
void createObjectList(Ogre::SceneNode *node, const std::string &model);
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects); static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue);
void updateActiveControllers();
public: public:
Animation(const MWWorld::Ptr &ptr); Animation(const MWWorld::Ptr &ptr);
virtual ~Animation(); virtual ~Animation();
void setController(MWMechanics::CharacterController *controller); /** Clears all ObjectLists except the first one. As a consequence, any
* playing animations are stopped.
*/
void clearExtraSources();
void updatePtr(const MWWorld::Ptr &ptr); void updatePtr(const MWWorld::Ptr &ptr);
@ -112,10 +132,38 @@ public:
void setSpeed(float speed); void setSpeed(float speed);
void setLooping(bool loop); /** Plays an animation.
* \param groupname Name of the animation group to play.
* \param start Key marker from which to start.
* \param stop Key marker to stop at.
* \param startpoint How far in between the two markers to start. 0 starts
* at the start marker, 1 starts at the stop marker.
* \param loops How many times to loop the animation. This will use the
* "loop start" and "loop stop" markers if they exist,
* otherwise it will use "start" and "stop".
* \return Boolean specifying whether the animation will return movement
* for the character at all.
*/
bool play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops);
void play(const std::string &groupname, const std::string &start, const std::string &stop, bool loop); /** Stops and removes the animation from the given layer. */
virtual Ogre::Vector3 runAnimation(float timepassed); void disable(size_t layeridx);
/** Gets info about the given animation layer.
* \param layeridx Layer index to get info about.
* \param complete Stores completion amount (0 = at start key, 0.5 = half way between start and stop keys), etc.
* \param groupname Stores animation group being played.
* \param start Stores the start key
* \param stop Stores the stop key
* \return True if an animation is active on the layer, false otherwise.
*/
bool getInfo(size_t layeridx, float *complete=NULL, std::string *groupname=NULL, std::string *start=NULL, std::string *stop=NULL) const;
virtual Ogre::Vector3 runAnimation(float duration);
/* Returns if there's an animation playing on the given layer. */
bool isPlaying(size_t layeridx) const
{ return mLayer[layeridx].mPlaying; }
Ogre::Node *getNode(const std::string &name); Ogre::Node *getNode(const std::string &name);
}; };

View file

@ -21,13 +21,15 @@ namespace MWRender
CharacterPreview::CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name, CharacterPreview::CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name,
Ogre::Vector3 position, Ogre::Vector3 lookAt) Ogre::Vector3 position, Ogre::Vector3 lookAt)
: mSizeX(sizeX)
, mSizeY(sizeY) : mSceneMgr (0)
, mName(name)
, mPosition(position) , mPosition(position)
, mLookAt(lookAt) , mLookAt(lookAt)
, mCharacter(character) , mCharacter(character)
, mAnimation(NULL) , mAnimation(NULL)
, mName(name)
, mSizeX(sizeX)
, mSizeY(sizeY)
{ {
} }
@ -87,17 +89,21 @@ namespace MWRender
} }
CharacterPreview::~CharacterPreview () CharacterPreview::~CharacterPreview ()
{
if (mSceneMgr)
{ {
//Ogre::TextureManager::getSingleton().remove(mName); //Ogre::TextureManager::getSingleton().remove(mName);
mSceneMgr->destroyCamera (mName); mSceneMgr->destroyAllCameras();
delete mAnimation; delete mAnimation;
Ogre::Root::getSingleton().destroySceneManager(mSceneMgr); Ogre::Root::getSingleton().destroySceneManager(mSceneMgr);
} }
}
void CharacterPreview::rebuild() void CharacterPreview::rebuild()
{ {
assert(mAnimation); assert(mAnimation);
delete mAnimation; delete mAnimation;
mAnimation = 0;
mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter), mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter),
0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); 0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
@ -149,7 +155,7 @@ namespace MWRender
if (!mSelectionBuffer) if (!mSelectionBuffer)
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0); mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0);
mAnimation->play("inventoryhandtohand", "start", "stop", false); mAnimation->play("inventoryhandtohand", "start", "stop", 0.0f, 0);
} }
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
@ -183,7 +189,7 @@ namespace MWRender
void RaceSelectionPreview::onSetup () void RaceSelectionPreview::onSetup ()
{ {
mAnimation->play("idle", "start", "stop", false); mAnimation->play("idle", "start", "stop", 0.0f, 0);
updateCamera(); updateCamera();
} }

View file

@ -1,10 +1,5 @@
#include "creatureanimation.hpp" #include "creatureanimation.hpp"
#include <OgreEntity.h>
#include <OgreParticleSystem.h>
#include <OgreSceneManager.h>
#include <OgreSubEntity.h>
#include "renderconst.hpp" #include "renderconst.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -26,31 +21,11 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
{ {
std::string model = "meshes\\"+ref->mBase->mModel; std::string model = "meshes\\"+ref->mBase->mModel;
createObjectList(mPtr.getRefData().getBaseNode(), model);
for(size_t i = 0;i < mObjectList.mEntities.size();i++)
{
Ogre::Entity *ent = mObjectList.mEntities[i];
ent->setVisibilityFlags(RV_Actors);
for(unsigned int j=0; j < ent->getNumSubEntities(); ++j)
{
Ogre::SubEntity* subEnt = ent->getSubEntity(j);
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
}
}
for(size_t i = 0;i < mObjectList.mParticles.size();i++)
{
Ogre::ParticleSystem *part = mObjectList.mParticles[i];
part->setVisibilityFlags(RV_Actors);
part->setRenderQueueGroup(RQG_Alpha);
}
std::vector<std::string> names;
if((ref->mBase->mFlags&ESM::Creature::Biped)) if((ref->mBase->mFlags&ESM::Creature::Biped))
names.push_back("meshes\\base_anim.nif"); addObjectList(mPtr.getRefData().getBaseNode(), "meshes\\base_anim.nif", true);
names.push_back(model);
setAnimationSources(names); addObjectList(mPtr.getRefData().getBaseNode(), model, false);
setRenderProperties(mObjects.back().mObjectList, RV_Actors, RQG_Main, RQG_Alpha);
} }
} }

View file

@ -11,6 +11,7 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "renderconst.hpp" #include "renderconst.hpp"
@ -96,39 +97,24 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
createObjectList(node, smodel); addObjectList(node, smodel, true);
for(size_t i = 0;i < mObjectList.mEntities.size();i++) if(mBodyPrefix.find("argonian") != std::string::npos)
{ addObjectList(node, "meshes\\argonian_swimkna.nif", true);
Ogre::Entity *base = mObjectList.mEntities[i]; else if(!mNpc->isMale() && !isBeast)
addObjectList(node, "meshes\\base_anim_female.nif", true);
base->getUserObjectBindings().setUserAny(Ogre::Any(-1));
if (mVisibilityFlags != 0)
base->setVisibilityFlags(mVisibilityFlags);
for(unsigned int j=0; j < base->getNumSubEntities(); ++j)
{
Ogre::SubEntity* subEnt = base->getSubEntity(j);
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
}
}
for(size_t i = 0;i < mObjectList.mParticles.size();i++)
{
Ogre::ParticleSystem *part = mObjectList.mParticles[i];
part->getUserObjectBindings().setUserAny(Ogre::Any(-1));
if(mVisibilityFlags != 0)
part->setVisibilityFlags(mVisibilityFlags);
part->setRenderQueueGroup(RQG_Alpha);
}
std::vector<std::string> skelnames(1, smodel);
if(!mNpc->isMale() && !isBeast)
skelnames.push_back("meshes\\base_anim_female.nif");
else if(mBodyPrefix.find("argonian") != std::string::npos)
skelnames.push_back("meshes\\argonian_swimkna.nif");
if(mNpc->mModel.length() > 0) if(mNpc->mModel.length() > 0)
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); addObjectList(node, "meshes\\"+mNpc->mModel, true);
setAnimationSources(skelnames); if(mViewMode == VM_FirstPerson)
{
/* A bit counter-intuitive, but unlike third-person anims, it seems
* beast races get both base_anim.1st.nif and base_animkna.1st.nif.
*/
addObjectList(node, "meshes\\base_anim.1st.nif", true);
if(isBeast)
addObjectList(node, "meshes\\base_animkna.1st.nif", true);
if(!mNpc->isMale() && !isBeast)
addObjectList(node, "meshes\\base_anim_female.1st.nif", true);
}
forceUpdate(); forceUpdate();
} }
@ -138,28 +124,31 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
assert(viewMode != VM_HeadOnly); assert(viewMode != VM_HeadOnly);
mViewMode = viewMode; mViewMode = viewMode;
/* FIXME: Enable this once first-person animations work. */ Ogre::SceneNode *node = mInsert->getParentSceneNode();
#if 0
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace); const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
std::vector<std::string> skelnames(1, smodel); clearExtraSources();
if(!mNpc->isMale() && !isBeast) if(mBodyPrefix.find("argonian") != std::string::npos)
skelnames.push_back("meshes\\base_anim_female.nif"); addObjectList(node, "meshes\\argonian_swimkna.nif", true);
else if(mBodyPrefix.find("argonian") != std::string::npos) else if(!mNpc->isMale() && !isBeast)
skelnames.push_back("meshes\\argonian_swimkna.nif"); addObjectList(node, "meshes\\base_anim_female.nif", true);
if(mNpc->mModel.length() > 0) if(mNpc->mModel.length() > 0)
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); addObjectList(node, "meshes\\"+mNpc->mModel, true);
if(mViewMode == VM_FirstPerson) if(mViewMode == VM_FirstPerson)
{ {
smodel = (!isBeast ? "meshes\\base_anim.1st.nif" : "meshes\\base_animkna.1st.nif"); /* A bit counter-intuitive, but unlike third-person anims, it seems
skelnames.push_back(smodel); * beast races get both base_anim.1st.nif and base_animkna.1st.nif.
*/
addObjectList(node, "meshes\\base_anim.1st.nif", true);
if(isBeast)
addObjectList(node, "meshes\\base_animkna.1st.nif", true);
if(!mNpc->isMale() && !isBeast)
addObjectList(node, "meshes\\base_anim_female.1st.nif", true);
} }
setAnimationSources(skelnames); MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr);
#endif
for(size_t i = 0;i < sPartListSize;i++) for(size_t i = 0;i < sPartListSize;i++)
removeIndividualPart(i); removeIndividualPart(i);
@ -305,81 +294,95 @@ void NpcAnimation::updateParts(bool forceupdate)
if(mViewMode == VM_HeadOnly) if(mViewMode == VM_HeadOnly)
return; return;
static const struct { std::map<int, int> bodypartMap;
ESM::PartReferenceType type; bodypartMap[ESM::PRT_Neck] = ESM::BodyPart::MP_Neck;
const char name[2][12]; bodypartMap[ESM::PRT_Cuirass] = ESM::BodyPart::MP_Chest;
} PartTypeList[] = { bodypartMap[ESM::PRT_Groin] = ESM::BodyPart::MP_Groin;
{ ESM::PRT_Neck, { "neck", "" } }, bodypartMap[ESM::PRT_RHand] = ESM::BodyPart::MP_Hand;
{ ESM::PRT_Cuirass, { "chest", "" } }, bodypartMap[ESM::PRT_LHand] = ESM::BodyPart::MP_Hand;
{ ESM::PRT_Groin, { "groin", "" } }, bodypartMap[ESM::PRT_RWrist] = ESM::BodyPart::MP_Wrist;
{ ESM::PRT_RHand, { "hand", "hands" } }, bodypartMap[ESM::PRT_LWrist] = ESM::BodyPart::MP_Wrist;
{ ESM::PRT_LHand, { "hand", "hands" } }, bodypartMap[ESM::PRT_RForearm] = ESM::BodyPart::MP_Forearm;
{ ESM::PRT_RWrist, { "wrist", "" } }, bodypartMap[ESM::PRT_LForearm] = ESM::BodyPart::MP_Forearm;
{ ESM::PRT_LWrist, { "wrist", "" } }, bodypartMap[ESM::PRT_RUpperarm] = ESM::BodyPart::MP_Upperarm;
{ ESM::PRT_RForearm, { "forearm", "" } }, bodypartMap[ESM::PRT_LUpperarm] = ESM::BodyPart::MP_Upperarm;
{ ESM::PRT_LForearm, { "forearm", "" } }, bodypartMap[ESM::PRT_RFoot] = ESM::BodyPart::MP_Foot;
{ ESM::PRT_RUpperarm, { "upper arm", "" } }, bodypartMap[ESM::PRT_LFoot] = ESM::BodyPart::MP_Foot;
{ ESM::PRT_LUpperarm, { "upper arm", "" } }, bodypartMap[ESM::PRT_RAnkle] = ESM::BodyPart::MP_Ankle;
{ ESM::PRT_RFoot, { "foot", "feet" } }, bodypartMap[ESM::PRT_LAnkle] = ESM::BodyPart::MP_Ankle;
{ ESM::PRT_LFoot, { "foot", "feet" } }, bodypartMap[ESM::PRT_RKnee] = ESM::BodyPart::MP_Knee;
{ ESM::PRT_RAnkle, { "ankle", "" } }, bodypartMap[ESM::PRT_LKnee] = ESM::BodyPart::MP_Knee;
{ ESM::PRT_LAnkle, { "ankle", "" } }, bodypartMap[ESM::PRT_RLeg] = ESM::BodyPart::MP_Upperleg;
{ ESM::PRT_RKnee, { "knee", "" } }, bodypartMap[ESM::PRT_LLeg] = ESM::BodyPart::MP_Upperleg;
{ ESM::PRT_LKnee, { "knee", "" } }, bodypartMap[ESM::PRT_Tail] = ESM::BodyPart::MP_Tail;
{ ESM::PRT_RLeg, { "upper leg", "" } },
{ ESM::PRT_LLeg, { "upper leg", "" } },
{ ESM::PRT_Tail, { "tail", "" } }
};
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++)
const int Flag_Female = 0x01;
const int Flag_FirstPerson = 0x02;
int flags = 0;
if (!mNpc->isMale())
flags |= Flag_Female;
if (mViewMode == VM_FirstPerson)
flags |= Flag_FirstPerson;
// 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;
std::string race = Misc::StringUtils::lowerCase(mNpc->mRace);
std::pair<std::string, int> thisCombination = std::make_pair(race, flags);
if (sRaceMapping.find(thisCombination) == sRaceMapping.end())
{ {
if(mPartPriorities[PartTypeList[i].type] < 1) sRaceMapping[thisCombination].resize(ESM::PRT_Count);
{ for (int i=0; i<ESM::PRT_Count; ++i)
const ESM::BodyPart *part = NULL; sRaceMapping[thisCombination][i] = NULL;
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>(); const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
if(!mNpc->isMale()) for (MWWorld::Store<ESM::BodyPart>::iterator it = partStore.begin(); it != partStore.end(); ++it)
{ {
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]+ext); const ESM::BodyPart& bodypart = *it;
if(part == 0) if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable)
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]+ext); continue;
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
{
continue;
} }
if(part == 0) if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]+ext); continue;
if(part == 0) if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace))
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]+ext); continue;
if(part) bool firstPerson = (bodypart.mId.size() >= 3)
addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel); && bodypart.mId[bodypart.mId.size()-3] == '1'
&& bodypart.mId[bodypart.mId.size()-2] == 's'
&& bodypart.mId[bodypart.mId.size()-1] == 't';
if (firstPerson != (mViewMode == VM_FirstPerson))
continue;
for (std::map<int, int>::iterator bIt = bodypartMap.begin(); bIt != bodypartMap.end(); ++bIt )
if (bIt->second == bodypart.mData.mPart)
sRaceMapping[thisCombination][bIt->first] = &*it;
} }
} }
for (int part = ESM::PRT_Neck; part < ESM::PRT_Count; ++part)
{
const ESM::BodyPart* bodypart = sRaceMapping[thisCombination][part];
if (mPartPriorities[part] < 1 && bodypart)
addOrReplaceIndividualPart(part, -1,1, "meshes\\"+bodypart->mModel);
}
} }
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename) NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename)
{ {
NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mObjectList.mSkelBase, bonename, NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, model);
mInsert, model); setRenderProperties(objects, mVisibilityFlags, RQG_Main, RQG_Alpha);
for(size_t i = 0;i < objects.mEntities.size();i++)
{
objects.mEntities[i]->getUserObjectBindings().setUserAny(Ogre::Any(group));
if(mVisibilityFlags != 0)
objects.mEntities[i]->setVisibilityFlags(mVisibilityFlags);
for(unsigned int j=0; j < objects.mEntities[i]->getNumSubEntities(); ++j) for(size_t i = 0;i < objects.mEntities.size();i++)
{ objects.mEntities[i]->getUserObjectBindings().setUserAny(Ogre::Any(group));
Ogre::SubEntity* subEnt = objects.mEntities[i]->getSubEntity(j);
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
}
}
for(size_t i = 0;i < objects.mParticles.size();i++) for(size_t i = 0;i < objects.mParticles.size();i++)
{
objects.mParticles[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); objects.mParticles[i]->getUserObjectBindings().setUserAny(Ogre::Any(group));
if(mVisibilityFlags != 0)
objects.mParticles[i]->setVisibilityFlags(mVisibilityFlags);
objects.mParticles[i]->setRenderQueueGroup(RQG_Alpha);
}
if(objects.mSkelBase) if(objects.mSkelBase)
{ {
Ogre::AnimationStateSet *aset = objects.mSkelBase->getAllAnimationStates(); Ogre::AnimationStateSet *aset = objects.mSkelBase->getAllAnimationStates();
@ -395,6 +398,7 @@ NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, in
while(boneiter.hasMoreElements()) while(boneiter.hasMoreElements())
boneiter.getNext()->setManuallyControlled(true); boneiter.getNext()->setManuallyControlled(true);
} }
return objects; return objects;
} }
@ -408,14 +412,16 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
mTimeToChange -= timepassed; mTimeToChange -= timepassed;
Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::Vector3 ret = Animation::runAnimation(timepassed);
const Ogre::SkeletonInstance *skelsrc = mObjectList.mSkelBase->getSkeleton();
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
for(size_t i = 0;i < sPartListSize;i++) for(size_t i = 0;i < sPartListSize;i++)
{ {
Ogre::Entity *ent = mObjectParts[i].mSkelBase; Ogre::Entity *ent = mObjectParts[i].mSkelBase;
if(!ent) continue; if(!ent) continue;
updateSkeletonInstance(skelsrc, ent->getSkeleton()); updateSkeletonInstance(baseinst, ent->getSkeleton());
ent->getAllAnimationStates()->_notifyDirty(); ent->getAllAnimationStates()->_notifyDirty();
} }
return ret; return ret;
} }

View file

@ -30,6 +30,8 @@
#include "../mwbase/inputmanager.hpp" // FIXME #include "../mwbase/inputmanager.hpp" // FIXME
#include "../mwbase/windowmanager.hpp" // FIXME #include "../mwbase/windowmanager.hpp" // FIXME
#include "../mwmechanics/creaturestats.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
@ -315,13 +317,15 @@ void RenderingManager::update (float duration, bool paused)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
mRendering.getFader()->setFactor(1.f-(blind / 100.f));
setAmbientMode();
// player position // player position
MWWorld::RefData &data = MWWorld::RefData &data = player.getRefData();
MWBase::Environment::get()
.getWorld()
->getPlayer()
.getPlayer()
.getRefData();
float *_playerPos = data.getPosition().pos; float *_playerPos = data.getPosition().pos;
Ogre::Vector3 playerPos(_playerPos[0], _playerPos[1], _playerPos[2]); Ogre::Vector3 playerPos(_playerPos[0], _playerPos[1], _playerPos[2]);
@ -597,8 +601,15 @@ void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour) void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
{ {
mRendering.getScene()->setAmbientLight(colour); mAmbientColor = colour;
mTerrainManager->setAmbient(colour);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
int nightEye = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::NightEye)).mMagnitude;
Ogre::ColourValue final = colour;
final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f));
mRendering.getScene()->setAmbientLight(final);
mTerrainManager->setAmbient(final);
} }
void RenderingManager::sunEnable(bool real) void RenderingManager::sunEnable(bool real)

View file

@ -788,8 +788,8 @@ void VideoState::decode_thread_loop(VideoState *self)
// main decode loop // main decode loop
while(!self->quit) while(!self->quit)
{ {
if((self->audio_st >= 0 && self->audioq.size > MAX_AUDIOQ_SIZE) || if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) ||
(self->video_st >= 0 && self->videoq.size > MAX_VIDEOQ_SIZE)) (self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE))
{ {
boost::this_thread::sleep(boost::posix_time::milliseconds(10)); boost::this_thread::sleep(boost::posix_time::milliseconds(10));
continue; continue;

View file

@ -13,8 +13,8 @@ namespace ESM
namespace MWWorld namespace MWWorld
{ {
/// List all (Ogre-)handles. /// List all (Ogre-)handles, then reset RefData::mBaseNode to 0.
struct ListHandles struct ListAndResetHandles
{ {
std::vector<Ogre::SceneNode*> mHandles; std::vector<Ogre::SceneNode*> mHandles;
@ -23,6 +23,8 @@ namespace MWWorld
Ogre::SceneNode* handle = data.getBaseNode(); Ogre::SceneNode* handle = data.getBaseNode();
if (handle) if (handle)
mHandles.push_back (handle); mHandles.push_back (handle);
data.setBaseNode(0);
return true; return true;
} }
}; };

View file

@ -193,6 +193,8 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
{ {
count = std::abs(count); /// \todo implement item restocking (indicated by negative count) count = std::abs(count); /// \todo implement item restocking (indicated by negative count)
try
{
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id); ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id);
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
@ -247,6 +249,13 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
ref.getPtr().getCellRef().mOwner = owner; ref.getPtr().getCellRef().mOwner = owner;
addImp (ref.getPtr()); addImp (ref.getPtr());
} }
}
catch (std::logic_error& e)
{
// Vanilla doesn't fail on nonexistent items in levelled lists
std::cerr << "Warning: ignoring nonexistent item '" << id << "'" << std::endl;
return;
}
} }
void MWWorld::ContainerStore::clear() void MWWorld::ContainerStore::clear()

View file

@ -76,16 +76,18 @@ namespace MWWorld
void Scene::unloadCell (CellStoreCollection::iterator iter) void Scene::unloadCell (CellStoreCollection::iterator iter)
{ {
std::cout << "Unloading cell\n"; std::cout << "Unloading cell\n";
ListHandles functor; ListAndResetHandles functor;
(*iter)->forEach<ListHandles>(functor); (*iter)->forEach<ListAndResetHandles>(functor);
{ {
// silence annoying g++ warning // silence annoying g++ warning
for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin()); for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin());
iter2!=functor.mHandles.end(); ++iter2){ iter2!=functor.mHandles.end(); ++iter2)
{
Ogre::SceneNode* node = *iter2; Ogre::SceneNode* node = *iter2;
mPhysics->removeObject (node->getName()); mPhysics->removeObject (node->getName());
} }
}
if ((*iter)->mCell->isExterior()) if ((*iter)->mCell->isExterior())
{ {
@ -97,7 +99,6 @@ namespace MWWorld
if (land) if (land)
mPhysics->removeHeightField( (*iter)->mCell->getGridX(), (*iter)->mCell->getGridY() ); mPhysics->removeHeightField( (*iter)->mCell->getGridX(), (*iter)->mCell->getGridY() );
} }
}
mRendering.removeCell(*iter); mRendering.removeCell(*iter);

View file

@ -415,8 +415,18 @@ namespace MWWorld
} }
}; };
struct DynamicExtCmp
{
bool operator()(const std::pair<int, int> &left, const std::pair<int, int> &right) const {
if (left.first == right.first) {
return left.second < right.second;
}
return left.first < right.first;
}
};
typedef std::map<std::string, ESM::Cell> DynamicInt; typedef std::map<std::string, ESM::Cell> DynamicInt;
typedef std::map<std::pair<int, int>, ESM::Cell> DynamicExt; typedef std::map<std::pair<int, int>, ESM::Cell, DynamicExtCmp> DynamicExt;
DynamicInt mInt; DynamicInt mInt;
DynamicExt mExt; DynamicExt mExt;
@ -465,7 +475,7 @@ namespace MWWorld
cell.mData.mX = x, cell.mData.mY = y; cell.mData.mX = x, cell.mData.mY = y;
std::pair<int, int> key(x, y); std::pair<int, int> key(x, y);
std::map<std::pair<int, int>, ESM::Cell>::const_iterator it = mExt.find(key); DynamicExt::const_iterator it = mExt.find(key);
if (it != mExt.end()) { if (it != mExt.end()) {
return &(it->second); return &(it->second);
} }
@ -483,7 +493,7 @@ namespace MWWorld
cell.mData.mX = x, cell.mData.mY = y; cell.mData.mX = x, cell.mData.mY = y;
std::pair<int, int> key(x, y); std::pair<int, int> key(x, y);
std::map<std::pair<int, int>, ESM::Cell>::const_iterator it = mExt.find(key); DynamicExt::const_iterator it = mExt.find(key);
if (it != mExt.end()) { if (it != mExt.end()) {
return &(it->second); return &(it->second);
} }
@ -524,7 +534,7 @@ namespace MWWorld
void setUp() { void setUp() {
//typedef std::vector<ESM::Cell>::iterator Iterator; //typedef std::vector<ESM::Cell>::iterator Iterator;
typedef std::map<std::pair<int, int>, ESM::Cell>::iterator ExtIterator; typedef DynamicExt::iterator ExtIterator;
typedef std::map<std::string, ESM::Cell>::iterator IntIterator; typedef std::map<std::string, ESM::Cell>::iterator IntIterator;
//std::sort(mInt.begin(), mInt.end(), RecordCmp()); //std::sort(mInt.begin(), mInt.end(), RecordCmp());
@ -862,7 +872,28 @@ namespace MWWorld
} }
void setUp() { void setUp() {
std::sort(mStatic.begin(), mStatic.end(), Compare()); /// \note This method sorts indexed values for further
/// searches. Every loaded item is present in storage, but
/// latest loaded shadows any previous while searching.
/// If memory cost will be too high, it is possible to remove
/// unused values.
Compare cmp;
std::stable_sort(mStatic.begin(), mStatic.end(), cmp);
typename std::vector<T>::iterator first, next;
next = first = mStatic.begin();
while (first != mStatic.end() && ++next != mStatic.end()) {
while (next != mStatic.end() && !cmp(*first, *next)) {
++next;
}
if (first != --next) {
std::swap(*first, *next);
}
first = ++next;
}
} }
const T *search(int index) const { const T *search(int index) const {

View file

@ -38,7 +38,9 @@ enum PartReferenceType
PRT_RPauldron = 23, PRT_RPauldron = 23,
PRT_LPauldron = 24, PRT_LPauldron = 24,
PRT_Weapon = 25, PRT_Weapon = 25,
PRT_Tail = 26 PRT_Tail = 26,
PRT_Count = 27
}; };
// Reference to body parts // Reference to body parts

View file

@ -9,13 +9,13 @@ namespace ESM
void BodyPart::load(ESMReader &esm) void BodyPart::load(ESMReader &esm)
{ {
mModel = esm.getHNString("MODL"); mModel = esm.getHNString("MODL");
mName = esm.getHNString("FNAM"); mRace = esm.getHNString("FNAM");
esm.getHNT(mData, "BYDT", 4); esm.getHNT(mData, "BYDT", 4);
} }
void BodyPart::save(ESMWriter &esm) void BodyPart::save(ESMWriter &esm)
{ {
esm.writeHNCString("MODL", mModel); esm.writeHNCString("MODL", mModel);
esm.writeHNCString("FNAM", mName); esm.writeHNCString("FNAM", mRace);
esm.writeHNT("BYDT", mData, 4); esm.writeHNT("BYDT", mData, 4);
} }

View file

@ -27,7 +27,9 @@ struct BodyPart
MP_Knee = 11, MP_Knee = 11,
MP_Upperleg = 12, MP_Upperleg = 12,
MP_Clavicle = 13, MP_Clavicle = 13,
MP_Tail = 14 MP_Tail = 14,
MP_Count = 15
}; };
enum Flags enum Flags
@ -52,7 +54,7 @@ struct BodyPart
}; };
BYDTstruct mData; BYDTstruct mData;
std::string mId, mModel, mName; std::string mId, mModel, mRace;
void load(ESMReader &esm); void load(ESMReader &esm);
void save(ESMWriter &esm); void save(ESMWriter &esm);

View file

@ -303,5 +303,28 @@ public:
} }
}; };
class NiFlipController : public Controller
{
public:
int mTexSlot;
float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources
NiSourceTextureList mSources;
void read(NIFStream *nif)
{
Controller::read(nif);
mTexSlot = nif->getUInt();
/*unknown=*/nif->getUInt();/*0?*/
mDelta = nif->getFloat();
mSources.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
mSources.post(nif);
}
};
} // Namespace } // Namespace
#endif #endif

View file

@ -208,7 +208,7 @@ static const RecordFactoryEntry recordFactories [] = {
{ "NiNode", &construct <NiNode >, RC_NiNode }, { "NiNode", &construct <NiNode >, RC_NiNode },
{ "AvoidNode", &construct <NiNode >, RC_NiNode }, { "AvoidNode", &construct <NiNode >, RC_NiNode },
{ "NiBSParticleNode", &construct <NiNode >, RC_NiNode }, { "NiBSParticleNode", &construct <NiNode >, RC_NiBSParticleNode },
{ "NiBSAnimationNode", &construct <NiNode >, RC_NiBSAnimationNode }, { "NiBSAnimationNode", &construct <NiNode >, RC_NiBSAnimationNode },
{ "NiBillboardNode", &construct <NiNode >, RC_NiNode }, { "NiBillboardNode", &construct <NiNode >, RC_NiNode },
{ "NiTriShape", &construct <NiTriShape >, RC_NiTriShape }, { "NiTriShape", &construct <NiTriShape >, RC_NiTriShape },
@ -235,6 +235,7 @@ static const RecordFactoryEntry recordFactories [] = {
{ "NiMaterialColorController", &construct <NiMaterialColorController >, RC_NiMaterialColorController }, { "NiMaterialColorController", &construct <NiMaterialColorController >, RC_NiMaterialColorController },
{ "NiBSPArrayController", &construct <NiBSPArrayController >, RC_NiBSPArrayController }, { "NiBSPArrayController", &construct <NiBSPArrayController >, RC_NiBSPArrayController },
{ "NiParticleSystemController", &construct <NiParticleSystemController >, RC_NiParticleSystemController }, { "NiParticleSystemController", &construct <NiParticleSystemController >, RC_NiParticleSystemController },
{ "NiFlipController", &construct <NiFlipController >, RC_NiFlipController },
{ "NiAmbientLight", &construct <NiLight >, RC_NiLight }, { "NiAmbientLight", &construct <NiLight >, RC_NiLight },
{ "NiDirectionalLight", &construct <NiLight >, RC_NiLight }, { "NiDirectionalLight", &construct <NiLight >, RC_NiLight },
{ "NiTextureEffect", &construct <NiTextureEffect >, RC_NiTextureEffect }, { "NiTextureEffect", &construct <NiTextureEffect >, RC_NiTextureEffect },

View file

@ -128,13 +128,17 @@ struct NiNode : Node
NodeList children; NodeList children;
NodeList effects; NodeList effects;
/* Known NiNode flags: enum Flags {
0x01 hidden Flag_Hidden = 0x0001,
0x02 use mesh for collision Flag_MeshCollision = 0x0002,
0x04 use bounding box for collision (?) Flag_BBoxCollision = 0x0004
0x08 unknown, but common };
0x20, 0x40, 0x80 unknown enum BSAnimFlags {
*/ AnimFlag_AutoPlay = 0x0020
};
enum BSParticleFlags {
ParticleFlag_AutoPlay = 0x0020
};
void read(NIFStream *nif) void read(NIFStream *nif)
{ {

View file

@ -39,6 +39,7 @@ enum RecordType
RC_NiTriShape, RC_NiTriShape,
RC_NiRotatingParticles, RC_NiRotatingParticles,
RC_NiAutoNormalParticles, RC_NiAutoNormalParticles,
RC_NiBSParticleNode,
RC_NiCamera, RC_NiCamera,
RC_NiTexturingProperty, RC_NiTexturingProperty,
RC_NiMaterialProperty, RC_NiMaterialProperty,
@ -59,6 +60,7 @@ enum RecordType
RC_NiMaterialColorController, RC_NiMaterialColorController,
RC_NiBSPArrayController, RC_NiBSPArrayController,
RC_NiParticleSystemController, RC_NiParticleSystemController,
RC_NiFlipController,
RC_NiBSAnimationNode, RC_NiBSAnimationNode,
RC_NiLight, RC_NiLight,
RC_NiTextureEffect, RC_NiTextureEffect,

View file

@ -163,6 +163,7 @@ typedef RecordPtrT<NiAutoNormalParticlesData> NiAutoNormalParticlesDataPtr;
typedef RecordListT<Node> NodeList; typedef RecordListT<Node> NodeList;
typedef RecordListT<Property> PropertyList; typedef RecordListT<Property> PropertyList;
typedef RecordListT<NiSourceTexture> NiSourceTextureList;
} // Namespace } // Namespace
#endif #endif

View file

@ -255,9 +255,9 @@ void ManualBulletShapeLoader::handleNiTriShape(btTriangleMesh* mesh, const Nif::
assert(shape != NULL); assert(shape != NULL);
// Interpret flags // Interpret flags
bool hidden = (flags & 0x01) != 0; // Not displayed bool hidden = (flags&Nif::NiNode::Flag_Hidden) != 0;
bool collide = (flags & 0x02) != 0; // Use mesh for collision bool collide = (flags&Nif::NiNode::Flag_MeshCollision) != 0;
bool bbcollide = (flags & 0x04) != 0; // Use bounding box for collision bool bbcollide = (flags&Nif::NiNode::Flag_BBoxCollision) != 0;
// If the object was marked "NCO" earlier, it shouldn't collide with // If the object was marked "NCO" earlier, it shouldn't collide with
// anything. So don't do anything. // anything. So don't do anything.

View file

@ -109,13 +109,26 @@ NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders;
void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape) void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape)
{ {
Ogre::SkeletonPtr skel;
const Nif::NiTriShapeData *data = shape->data.getPtr(); const Nif::NiTriShapeData *data = shape->data.getPtr();
const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr());
std::vector<Ogre::Vector3> srcVerts = data->vertices; std::vector<Ogre::Vector3> srcVerts = data->vertices;
std::vector<Ogre::Vector3> srcNorms = data->normals; std::vector<Ogre::Vector3> srcNorms = data->normals;
Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC; Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC;
bool vertShadowBuffer = false; bool vertShadowBuffer = false;
if(!shape->controller.empty())
{
Nif::ControllerPtr ctrl = shape->controller;
do {
if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{
vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
vertShadowBuffer = true;
break;
}
} while(!(ctrl=ctrl->next).empty());
}
if(skin != NULL) if(skin != NULL)
{ {
vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
@ -125,10 +138,6 @@ void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape
// explicitly attached later. // explicitly attached later.
mesh->setSkeletonName(mName); mesh->setSkeletonName(mName);
// Get the skeleton resource, so vertices can be transformed into the bones' initial state.
Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr();
skel = skelMgr->getByName(mName);
// Convert vertices and normals to bone space from bind position. It would be // Convert vertices and normals to bone space from bind position. It would be
// better to transform the bones into bind position, but there doesn't seem to // better to transform the bones into bind position, but there doesn't seem to
// be a reliable way to do that. // be a reliable way to do that.
@ -139,11 +148,10 @@ void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape
const Nif::NodeList &bones = skin->bones; const Nif::NodeList &bones = skin->bones;
for(size_t b = 0;b < bones.length();b++) for(size_t b = 0;b < bones.length();b++)
{ {
Ogre::Bone *bone = skel->getBone(bones[b]->name);
Ogre::Matrix4 mat; Ogre::Matrix4 mat;
mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale),
Ogre::Quaternion(data->bones[b].trafo.rotation)); Ogre::Quaternion(data->bones[b].trafo.rotation));
mat = bone->_getFullTransform() * mat; mat = bones[b]->getWorldTransform() * mat;
const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights; const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights;
for(size_t i = 0;i < weights.size();i++) for(size_t i = 0;i < weights.size();i++)
@ -260,13 +268,24 @@ void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape
// Texture UV coordinates // Texture UV coordinates
size_t numUVs = data->uvlist.size(); size_t numUVs = data->uvlist.size();
for(size_t i = 0;i < numUVs;i++) if (numUVs)
{ {
vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2), size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
srcVerts.size(), Ogre::HardwareBuffer::HBU_STATIC);
vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[i][0], true); for(size_t i = 0; i < numUVs; i++)
decl->addElement(nextBuf, elemSize*i, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i);
vbuf = hwBufMgr->createVertexBuffer(decl->getVertexSize(nextBuf), srcVerts.size(),
Ogre::HardwareBuffer::HBU_STATIC);
std::vector<Ogre::Vector2> allUVs;
allUVs.reserve(srcVerts.size()*numUVs);
for (size_t vert = 0; vert<srcVerts.size(); ++vert)
for(size_t i = 0; i < numUVs; i++)
allUVs.push_back(data->uvlist[i][vert]);
vbuf->writeData(0, elemSize*srcVerts.size()*numUVs, &allUVs[0], true);
decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i);
bind->setBinding(nextBuf++, vbuf); bind->setBinding(nextBuf++, vbuf);
} }
@ -285,6 +304,8 @@ void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape
// Assign bone weights for this TriShape // Assign bone weights for this TriShape
if(skin != NULL) if(skin != NULL)
{ {
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(mName);
const Nif::NiSkinData *data = skin->data.getPtr(); const Nif::NiSkinData *data = skin->data.getPtr();
const Nif::NodeList &bones = skin->bones; const Nif::NodeList &bones = skin->bones;
for(size_t i = 0;i < bones.length();i++) for(size_t i = 0;i < bones.length();i++)

View file

@ -44,15 +44,6 @@
#include "material.hpp" #include "material.hpp"
#include "mesh.hpp" #include "mesh.hpp"
namespace std
{
// TODO: Do something useful
ostream& operator<<(ostream &o, const NifOgre::TextKeyMap&)
{ return o; }
}
namespace NifOgre namespace NifOgre
{ {
@ -74,11 +65,7 @@ public:
, mStopTime(ctrl->timeStop) , mStopTime(ctrl->timeStop)
{ {
if(mDeltaInput) if(mDeltaInput)
{
mDeltaCount = mPhase; mDeltaCount = mPhase;
while(mDeltaCount < mStartTime)
mDeltaCount += (mStopTime-mStartTime);
}
} }
virtual Ogre::Real calculate(Ogre::Real value) virtual Ogre::Real calculate(Ogre::Real value)
@ -86,6 +73,9 @@ public:
if(mDeltaInput) if(mDeltaInput)
{ {
mDeltaCount += value*mFrequency; mDeltaCount += value*mFrequency;
if(mDeltaCount < mStartTime)
mDeltaCount = mStopTime - std::fmod(mStartTime - mDeltaCount,
mStopTime - mStartTime);
mDeltaCount = std::fmod(mDeltaCount - mStartTime, mDeltaCount = std::fmod(mDeltaCount - mStartTime,
mStopTime - mStartTime) + mStartTime; mStopTime - mStartTime) + mStartTime;
return mDeltaCount; return mDeltaCount;
@ -104,7 +94,7 @@ public:
private: private:
std::vector<Nif::NiVisData::VisData> mData; std::vector<Nif::NiVisData::VisData> mData;
virtual bool calculate(Ogre::Real time) bool calculate(Ogre::Real time) const
{ {
if(mData.size() == 0) if(mData.size() == 0)
return true; return true;
@ -144,10 +134,19 @@ public:
, mData(data->mVis) , mData(data->mVis)
{ } { }
virtual Ogre::Quaternion getRotation(float time) const
{ return Ogre::Quaternion(); }
virtual Ogre::Vector3 getTranslation(float time) const
{ return Ogre::Vector3(0.0f); }
virtual Ogre::Vector3 getScale(float time) const
{ return Ogre::Vector3(1.0f); }
virtual Ogre::Real getValue() const virtual Ogre::Real getValue() const
{ {
// Should not be called // Should not be called
return 1.0f; return 0.0f;
} }
virtual void setValue(Ogre::Real time) virtual void setValue(Ogre::Real time)
@ -170,6 +169,60 @@ public:
Nif::Vector3KeyList mTranslations; Nif::Vector3KeyList mTranslations;
Nif::FloatKeyList mScales; Nif::FloatKeyList mScales;
static float interpKey(const Nif::FloatKeyList::VecType &keys, float time)
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::FloatKeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
static Ogre::Vector3 interpKey(const Nif::Vector3KeyList::VecType &keys, float time)
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::Vector3KeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::Vector3KeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
static Ogre::Quaternion interpKey(const Nif::QuaternionKeyList::VecType &keys, float time)
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::QuaternionKeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::QuaternionKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return Ogre::Quaternion::nlerp(a, last->mValue, iter->mValue);
}
return keys.back().mValue;
}
public: public:
Value(Ogre::Node *target, const Nif::NiKeyframeData *data) Value(Ogre::Node *target, const Nif::NiKeyframeData *data)
: NodeTargetValue<Ogre::Real>(target) : NodeTargetValue<Ogre::Real>(target)
@ -178,6 +231,27 @@ public:
, mScales(data->mScales) , mScales(data->mScales)
{ } { }
virtual Ogre::Quaternion getRotation(float time) const
{
if(mRotations.mKeys.size() > 0)
return interpKey(mRotations.mKeys, time);
return mNode->getOrientation();
}
virtual Ogre::Vector3 getTranslation(float time) const
{
if(mTranslations.mKeys.size() > 0)
return interpKey(mTranslations.mKeys, time);
return mNode->getPosition();
}
virtual Ogre::Vector3 getScale(float time) const
{
if(mScales.mKeys.size() > 0)
return Ogre::Vector3(interpKey(mScales.mKeys, time));
return mNode->getScale();
}
virtual Ogre::Real getValue() const virtual Ogre::Real getValue() const
{ {
// Should not be called // Should not be called
@ -187,68 +261,11 @@ public:
virtual void setValue(Ogre::Real time) virtual void setValue(Ogre::Real time)
{ {
if(mRotations.mKeys.size() > 0) if(mRotations.mKeys.size() > 0)
{ mNode->setOrientation(interpKey(mRotations.mKeys, time));
if(time <= mRotations.mKeys.front().mTime)
mNode->setOrientation(mRotations.mKeys.front().mValue);
else if(time >= mRotations.mKeys.back().mTime)
mNode->setOrientation(mRotations.mKeys.back().mValue);
else
{
Nif::QuaternionKeyList::VecType::const_iterator iter(mRotations.mKeys.begin()+1);
for(;iter != mRotations.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::QuaternionKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
mNode->setOrientation(Ogre::Quaternion::nlerp(a, last->mValue, iter->mValue));
break;
}
}
}
if(mTranslations.mKeys.size() > 0) if(mTranslations.mKeys.size() > 0)
{ mNode->setPosition(interpKey(mTranslations.mKeys, time));
if(time <= mTranslations.mKeys.front().mTime)
mNode->setPosition(mTranslations.mKeys.front().mValue);
else if(time >= mTranslations.mKeys.back().mTime)
mNode->setPosition(mTranslations.mKeys.back().mValue);
else
{
Nif::Vector3KeyList::VecType::const_iterator iter(mTranslations.mKeys.begin()+1);
for(;iter != mTranslations.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::Vector3KeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
mNode->setPosition(last->mValue + ((iter->mValue - last->mValue)*a));
break;
}
}
}
if(mScales.mKeys.size() > 0) if(mScales.mKeys.size() > 0)
{ mNode->setScale(Ogre::Vector3(interpKey(mScales.mKeys, time)));
if(time <= mScales.mKeys.front().mTime)
mNode->setScale(Ogre::Vector3(mScales.mKeys.front().mValue));
else if(time >= mScales.mKeys.back().mTime)
mNode->setScale(Ogre::Vector3(mScales.mKeys.back().mValue));
else
{
Nif::FloatKeyList::VecType::const_iterator iter(mScales.mKeys.begin()+1);
for(;iter != mScales.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
mNode->setScale(Ogre::Vector3(last->mValue + ((iter->mValue - last->mValue)*a)));
break;
}
}
}
} }
}; };
@ -289,7 +306,7 @@ public:
} }
public: public:
Value(const Ogre::MaterialPtr &material, Nif::NiUVData *data) Value(const Ogre::MaterialPtr &material, const Nif::NiUVData *data)
: mMaterial(material) : mMaterial(material)
, mUTrans(data->mKeyList[0]) , mUTrans(data->mKeyList[0])
, mVTrans(data->mKeyList[1]) , mVTrans(data->mKeyList[1])
@ -329,11 +346,70 @@ public:
typedef DefaultFunction Function; typedef DefaultFunction Function;
}; };
class ParticleSystemController
{
public:
class Value : public Ogre::ControllerValue<Ogre::Real>
{
private:
Ogre::ParticleSystem *mParticleSys;
float mEmitStart;
float mEmitStop;
public:
Value(Ogre::ParticleSystem *psys, const Nif::NiParticleSystemController *pctrl)
: mParticleSys(psys)
, mEmitStart(pctrl->startTime)
, mEmitStop(pctrl->stopTime)
{
}
Ogre::Real getValue() const
{ return 0.0f; }
void setValue(Ogre::Real value)
{
mParticleSys->setEmitting(value >= mEmitStart && value < mEmitStop);
}
};
typedef DefaultFunction Function;
};
class GeomMorpherController
{
public:
class Value : public Ogre::ControllerValue<Ogre::Real>
{
private:
Ogre::SubEntity *mSubEntity;
std::vector<Nif::NiMorphData::MorphData> mMorphs;
public:
Value(Ogre::SubEntity *subent, const Nif::NiMorphData *data)
: mSubEntity(subent)
, mMorphs(data->mMorphs)
{ }
virtual Ogre::Real getValue() const
{
// Should not be called
return 0.0f;
}
virtual void setValue(Ogre::Real value)
{
// TODO: Implement
}
};
typedef DefaultFunction Function;
};
/** Manual resource loader for NIF objects (meshes, particle systems, etc). /** Object creator for NIFs. This is the main class responsible for creating
* This is the main class responsible for translating the internal NIF * "live" Ogre objects (entities, particle systems, controllers, etc) from
* structures into something Ogre can use. * their NIF equivalents.
*/ */
class NIFObjectLoader class NIFObjectLoader
{ {
@ -349,14 +425,79 @@ class NIFObjectLoader
} }
static void createEntity(const std::string &name, const std::string &group,
Ogre::SceneManager *sceneMgr, ObjectList &objectlist,
const Nif::Node *node, int flags, int animflags)
{
const Nif::NiTriShape *shape = static_cast<const Nif::NiTriShape*>(node);
std::string fullname = name+"@index="+Ogre::StringConverter::toString(shape->recIndex);
if(shape->name.length() > 0)
fullname += "@shape="+shape->name;
Misc::StringUtils::toLower(fullname);
Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton();
if(meshMgr.getByName(fullname).isNull())
NIFMeshLoader::createMesh(name, fullname, group, shape->recIndex);
Ogre::Entity *entity = sceneMgr->createEntity(fullname);
entity->setVisible(!(flags&Nif::NiNode::Flag_Hidden));
objectlist.mEntities.push_back(entity);
if(objectlist.mSkelBase)
{
if(entity->hasSkeleton())
entity->shareSkeletonInstanceWith(objectlist.mSkelBase);
else
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, shape->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), entity);
}
}
Nif::ControllerPtr ctrl = node->controller;
while(!ctrl.empty())
{
if(ctrl->recType == Nif::RC_NiUVController)
{
const Nif::NiUVController *uv = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
const Ogre::MaterialPtr &material = entity->getSubEntity(0)->getMaterial();
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
else if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{
const Nif::NiGeomMorpherController *geom = static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr());
Ogre::SubEntity *subent = entity->getSubEntity(0);
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW GeomMorpherController::Value(subent, geom->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW GeomMorpherController::Function(geom, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrl = ctrl->next;
}
}
static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl) static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl)
{ {
Ogre::ParticleEmitter *emitter = partsys->addEmitter("Nif"); Ogre::ParticleEmitter *emitter = partsys->addEmitter("Nif");
emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom, emitter->setParticleVelocity(partctrl->velocity - partctrl->velocityRandom*0.5f,
partctrl->velocity+partctrl->velocityRandom); partctrl->velocity + partctrl->velocityRandom*0.5f);
emitter->setEmissionRate(partctrl->emitRate); emitter->setEmissionRate(partctrl->emitRate);
emitter->setTimeToLive(partctrl->lifetime-partctrl->lifetimeRandom, emitter->setTimeToLive(partctrl->lifetime - partctrl->lifetimeRandom*0.5f,
partctrl->lifetime+partctrl->lifetimeRandom); partctrl->lifetime + partctrl->lifetimeRandom*0.5f);
emitter->setParameter("width", Ogre::StringConverter::toString(partctrl->offsetRandom.x)); emitter->setParameter("width", Ogre::StringConverter::toString(partctrl->offsetRandom.x));
emitter->setParameter("height", Ogre::StringConverter::toString(partctrl->offsetRandom.y)); emitter->setParameter("height", Ogre::StringConverter::toString(partctrl->offsetRandom.y));
emitter->setParameter("depth", Ogre::StringConverter::toString(partctrl->offsetRandom.z)); emitter->setParameter("depth", Ogre::StringConverter::toString(partctrl->offsetRandom.z));
@ -416,9 +557,9 @@ class NIFObjectLoader
} }
} }
static Ogre::ParticleSystem *createParticleSystem(const std::string &name, const std::string &group, static void createParticleSystem(const std::string &name, const std::string &group,
Ogre::SceneManager *sceneMgr, Ogre::Entity *entitybase, Ogre::SceneManager *sceneMgr, ObjectList &objectlist,
const Nif::Node *partnode) const Nif::Node *partnode, int flags, int partflags)
{ {
const Nif::NiAutoNormalParticlesData *particledata = NULL; const Nif::NiAutoNormalParticlesData *particledata = NULL;
if(partnode->recType == Nif::RC_NiAutoNormalParticles) if(partnode->recType == Nif::RC_NiAutoNormalParticles)
@ -426,13 +567,13 @@ class NIFObjectLoader
else if(partnode->recType == Nif::RC_NiRotatingParticles) else if(partnode->recType == Nif::RC_NiRotatingParticles)
particledata = static_cast<const Nif::NiRotatingParticles*>(partnode)->data.getPtr(); particledata = static_cast<const Nif::NiRotatingParticles*>(partnode)->data.getPtr();
Ogre::ParticleSystem *partsys = sceneMgr->createParticleSystem();
try {
std::string fullname = name+"@index="+Ogre::StringConverter::toString(partnode->recIndex); std::string fullname = name+"@index="+Ogre::StringConverter::toString(partnode->recIndex);
if(partnode->name.length() > 0) if(partnode->name.length() > 0)
fullname += "@type="+partnode->name; fullname += "@type="+partnode->name;
Misc::StringUtils::toLower(fullname); Misc::StringUtils::toLower(fullname);
Ogre::ParticleSystem *partsys = sceneMgr->createParticleSystem();
const Nif::NiTexturingProperty *texprop = NULL; const Nif::NiTexturingProperty *texprop = NULL;
const Nif::NiMaterialProperty *matprop = NULL; const Nif::NiMaterialProperty *matprop = NULL;
const Nif::NiAlphaProperty *alphaprop = NULL; const Nif::NiAlphaProperty *alphaprop = NULL;
@ -467,9 +608,17 @@ class NIFObjectLoader
if(!partctrl->emitter.empty() && !partsys->isAttached()) if(!partctrl->emitter.empty() && !partsys->isAttached())
{ {
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex);
Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
entitybase->attachObjectToBone(trgtbone->getName(), partsys); objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), partsys);
} }
Ogre::ControllerValueRealPtr srcval((partflags&Nif::NiNode::ParticleFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW ParticleSystemController::Value(partsys, partctrl));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW ParticleSystemController::Function(partctrl, (partflags&Nif::NiNode::ParticleFlag_AutoPlay)));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }
ctrl = ctrl->next; ctrl = ctrl->next;
} }
@ -477,22 +626,80 @@ class NIFObjectLoader
if(!partsys->isAttached()) if(!partsys->isAttached())
{ {
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex);
Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid); Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
entitybase->attachObjectToBone(trgtbone->getName(), partsys); objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), partsys);
}
partsys->setVisible(!(flags&Nif::NiNode::Flag_Hidden));
objectlist.mParticles.push_back(partsys);
}
static void createNodeControllers(const std::string &name, Nif::ControllerPtr ctrl, ObjectList &objectlist, int animflags)
{
do {
if(ctrl->recType == Nif::RC_NiVisController)
{
const Nif::NiVisController *vis = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW VisController::Function(vis, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
else if(ctrl->recType == Nif::RC_NiKeyframeController)
{
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
if(!key->data.empty())
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
}
ctrl = ctrl->next;
} while(!ctrl.empty());
}
static void extractTextKeys(const Nif::NiTextKeyExtraData *tk, TextKeyMap &textkeys)
{
for(size_t i = 0;i < tk->list.size();i++)
{
const std::string &str = tk->list[i].text;
std::string::size_type pos = 0;
while(pos < str.length())
{
if(::isspace(str[pos]))
{
pos++;
continue;
}
std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos));
std::string result = str.substr(pos, nextpos-pos);
textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result)));
pos = nextpos;
} }
} }
catch(std::exception &e) {
std::cerr<< "Particles exception: "<<e.what() <<std::endl;
sceneMgr->destroyParticleSystem(partsys);
partsys = NULL;
};
return partsys;
} }
static void createObjects(const std::string &name, const std::string &group, static void createObjects(const std::string &name, const std::string &group,
Ogre::SceneManager *sceneMgr, const Nif::Node *node, Ogre::SceneManager *sceneMgr, const Nif::Node *node,
ObjectList &objectlist, int flags) ObjectList &objectlist, int flags, int animflags, int partflags)
{ {
// Do not create objects for the collision shape (includes all children) // Do not create objects for the collision shape (includes all children)
if(node->recType == Nif::RC_RootCollisionNode) if(node->recType == Nif::RC_RootCollisionNode)
@ -503,12 +710,24 @@ class NIFObjectLoader
if (node->name.find("marker") != std::string::npos) if (node->name.find("marker") != std::string::npos)
return; return;
if(node->recType == Nif::RC_NiBSAnimationNode)
animflags |= node->flags;
else if(node->recType == Nif::RC_NiBSParticleNode)
partflags |= node->flags;
else
flags |= node->flags; flags |= node->flags;
Nif::ExtraPtr e = node->extra; Nif::ExtraPtr e = node->extra;
while(!e.empty()) while(!e.empty())
{ {
if(e->recType == Nif::RC_NiStringExtraData) if(e->recType == Nif::RC_NiTextKeyExtraData)
{
const Nif::NiTextKeyExtraData *tk = static_cast<const Nif::NiTextKeyExtraData*>(e.getPtr());
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex);
extractTextKeys(tk, objectlist.mTextKeys[trgtid]);
}
else if(e->recType == Nif::RC_NiStringExtraData)
{ {
const Nif::NiStringExtraData *sd = static_cast<const Nif::NiStringExtraData*>(e.getPtr()); const Nif::NiStringExtraData *sd = static_cast<const Nif::NiStringExtraData*>(e.getPtr());
// String markers may contain important information // String markers may contain important information
@ -520,9 +739,13 @@ class NIFObjectLoader
flags |= 0x80000000; flags |= 0x80000000;
} }
} }
e = e->extra; e = e->extra;
} }
if(!node->controller.empty())
createNodeControllers(name, node->controller, objectlist, animflags);
if(node->recType == Nif::RC_NiCamera) if(node->recType == Nif::RC_NiCamera)
{ {
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex);
@ -530,94 +753,15 @@ class NIFObjectLoader
objectlist.mCameras.push_back(trgtbone); objectlist.mCameras.push_back(trgtbone);
} }
Nif::ControllerPtr ctrl = node->controller;
while(!ctrl.empty())
{
if(ctrl->recType == Nif::RC_NiVisController)
{
const Nif::NiVisController *vis = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval; /* Filled in later */
Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW VisController::Function(vis, false));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
else if(ctrl->recType == Nif::RC_NiKeyframeController)
{
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
if(!key->data.empty())
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval; /* Filled in later */
Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, false));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
}
ctrl = ctrl->next;
}
if(node->recType == Nif::RC_NiTriShape && !(flags&0x80000000)) if(node->recType == Nif::RC_NiTriShape && !(flags&0x80000000))
{ {
const Nif::NiTriShape *shape = static_cast<const Nif::NiTriShape*>(node); createEntity(name, group, sceneMgr, objectlist, node, flags, animflags);
std::string fullname = name+"@index="+Ogre::StringConverter::toString(shape->recIndex);
if(shape->name.length() > 0)
fullname += "@shape="+shape->name;
Misc::StringUtils::toLower(fullname);
Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton();
if(meshMgr.getByName(fullname).isNull())
NIFMeshLoader::createMesh(name, fullname, group, shape->recIndex);
Ogre::Entity *entity = sceneMgr->createEntity(fullname);
entity->setVisible(!(flags&0x01));
objectlist.mEntities.push_back(entity);
if(objectlist.mSkelBase)
{
if(entity->hasSkeleton())
entity->shareSkeletonInstanceWith(objectlist.mSkelBase);
else
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, shape->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), entity);
}
}
Nif::ControllerPtr ctrl = node->controller;
while(!ctrl.empty())
{
if(ctrl->recType == Nif::RC_NiUVController)
{
const Nif::NiUVController *uv = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
const Ogre::MaterialPtr &material = entity->getSubEntity(0)->getMaterial();
Ogre::ControllerValueRealPtr srcval(Ogre::ControllerManager::getSingleton().getFrameTimeSource());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv, true));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrl = ctrl->next;
}
} }
if((node->recType == Nif::RC_NiAutoNormalParticles || if((node->recType == Nif::RC_NiAutoNormalParticles ||
node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x40000000)) node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x40000000))
{ {
Ogre::ParticleSystem *partsys = createParticleSystem(name, group, sceneMgr, objectlist.mSkelBase, node); createParticleSystem(name, group, sceneMgr, objectlist, node, flags, partflags);
if(partsys != NULL)
{
partsys->setVisible(!(flags&0x01));
objectlist.mParticles.push_back(partsys);
}
} }
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node); const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
@ -627,7 +771,7 @@ class NIFObjectLoader
for(size_t i = 0;i < children.length();i++) for(size_t i = 0;i < children.length();i++)
{ {
if(!children[i].empty()) if(!children[i].empty())
createObjects(name, group, sceneMgr, children[i].getPtr(), objectlist, flags); createObjects(name, group, sceneMgr, children[i].getPtr(), objectlist, flags, animflags, partflags);
} }
} }
} }
@ -674,7 +818,7 @@ public:
// Create a base skeleton entity if this NIF needs one // Create a base skeleton entity if this NIF needs one
createSkelBase(name, group, sceneMgr, node, objectlist); createSkelBase(name, group, sceneMgr, node, objectlist);
} }
createObjects(name, group, sceneMgr, node, objectlist, flags); createObjects(name, group, sceneMgr, node, objectlist, flags, 0, 0);
} }
}; };
@ -757,12 +901,15 @@ ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonena
} }
ObjectList Loader::createObjectBase(Ogre::SceneManager *sceneMgr, std::string name, const std::string &group) ObjectList Loader::createObjectBase(Ogre::SceneNode *parentNode, std::string name, const std::string &group)
{ {
ObjectList objectlist; ObjectList objectlist;
Misc::StringUtils::toLower(name); Misc::StringUtils::toLower(name);
NIFObjectLoader::load(sceneMgr, objectlist, name, group, 0xC0000000); NIFObjectLoader::load(parentNode->getCreator(), objectlist, name, group, 0xC0000000);
if(objectlist.mSkelBase)
parentNode->attachObject(objectlist.mSkelBase);
return objectlist; return objectlist;
} }

View file

@ -50,6 +50,8 @@ struct ObjectList {
// bones in the mSkelBase which are NiCamera nodes. // bones in the mSkelBase which are NiCamera nodes.
std::vector<Ogre::Bone*> mCameras; std::vector<Ogre::Bone*> mCameras;
std::map<int,TextKeyMap> mTextKeys;
std::vector<Ogre::Controller<Ogre::Real> > mControllers; std::vector<Ogre::Controller<Ogre::Real> > mControllers;
ObjectList() : mSkelBase(0) ObjectList() : mSkelBase(0)
@ -69,7 +71,7 @@ public:
std::string name, std::string name,
const std::string &group="General"); const std::string &group="General");
static ObjectList createObjectBase(Ogre::SceneManager *sceneMgr, static ObjectList createObjectBase(Ogre::SceneNode *parentNode,
std::string name, std::string name,
const std::string &group="General"); const std::string &group="General");
}; };
@ -85,6 +87,10 @@ public:
NodeTargetValue(Ogre::Node *target) : mNode(target) NodeTargetValue(Ogre::Node *target) : mNode(target)
{ } { }
virtual Ogre::Quaternion getRotation(T value) const = 0;
virtual Ogre::Vector3 getTranslation(T value) const = 0;
virtual Ogre::Vector3 getScale(T value) const = 0;
void setNode(Ogre::Node *target) void setNode(Ogre::Node *target)
{ mNode = target; } { mNode = target; }
Ogre::Node *getNode() const Ogre::Node *getNode() const
@ -94,14 +100,4 @@ typedef Ogre::SharedPtr<NodeTargetValue<Ogre::Real> > NodeTargetValueRealPtr;
} }
namespace std
{
// These operators allow extra data types to be stored in an Ogre::Any
// object, which can then be stored in user object bindings on the nodes
ostream& operator<<(ostream &o, const NifOgre::TextKeyMap&);
}
#endif #endif

View file

@ -11,142 +11,7 @@
namespace NifOgre namespace NifOgre
{ {
void NIFSkeletonLoader::buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector<const Nif::NiKeyframeController*> &ctrls, const std::vector<std::string> &targets, float startTime, float stopTime) void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent)
{
Ogre::Animation *anim = skel->createAnimation(name, stopTime);
for(size_t i = 0;i < ctrls.size();i++)
{
const Nif::NiKeyframeController *kfc = ctrls[i];
if(kfc->data.empty())
continue;
const Nif::NiKeyframeData *kf = kfc->data.getPtr();
/* Get the keyframes and make sure they're sorted first to last */
const Nif::QuaternionKeyList &quatkeys = kf->mRotations;
const Nif::Vector3KeyList &trankeys = kf->mTranslations;
const Nif::FloatKeyList &scalekeys = kf->mScales;
Nif::QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin();
Nif::Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin();
Nif::FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin();
Ogre::Bone *bone = skel->getBone(targets[i]);
// NOTE: For some reason, Ogre doesn't like the node track ID being different from
// the bone ID
Ogre::NodeAnimationTrack *nodetrack = anim->hasNodeTrack(bone->getHandle()) ?
anim->getNodeTrack(bone->getHandle()) :
anim->createNodeTrack(bone->getHandle(), bone);
Ogre::Quaternion lastquat, curquat;
Ogre::Vector3 lasttrans(0.0f), curtrans(0.0f);
Ogre::Vector3 lastscale(1.0f), curscale(1.0f);
if(quatiter != quatkeys.mKeys.end())
lastquat = curquat = quatiter->mValue;
if(traniter != trankeys.mKeys.end())
lasttrans = curtrans = traniter->mValue;
if(scaleiter != scalekeys.mKeys.end())
lastscale = curscale = Ogre::Vector3(scaleiter->mValue);
bool didlast = false;
while(!didlast)
{
float curtime = std::numeric_limits<float>::max();
//Get latest time
if(quatiter != quatkeys.mKeys.end())
curtime = std::min(curtime, quatiter->mTime);
if(traniter != trankeys.mKeys.end())
curtime = std::min(curtime, traniter->mTime);
if(scaleiter != scalekeys.mKeys.end())
curtime = std::min(curtime, scaleiter->mTime);
curtime = std::max(curtime, startTime);
if(curtime >= stopTime)
{
didlast = true;
curtime = stopTime;
}
// Get the latest quaternions, translations, and scales for the
// current time
while(quatiter != quatkeys.mKeys.end() && curtime >= quatiter->mTime)
{
lastquat = curquat;
if(++quatiter != quatkeys.mKeys.end())
curquat = quatiter->mValue;
}
while(traniter != trankeys.mKeys.end() && curtime >= traniter->mTime)
{
lasttrans = curtrans;
if(++traniter != trankeys.mKeys.end())
curtrans = traniter->mValue;
}
while(scaleiter != scalekeys.mKeys.end() && curtime >= scaleiter->mTime)
{
lastscale = curscale;
if(++scaleiter != scalekeys.mKeys.end())
curscale = Ogre::Vector3(scaleiter->mValue);
}
Ogre::TransformKeyFrame *kframe;
kframe = nodetrack->createNodeKeyFrame(curtime);
if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin())
kframe->setRotation(curquat);
else
{
Nif::QuaternionKeyList::VecType::const_iterator last = quatiter-1;
float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime);
kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat));
}
if(traniter == trankeys.mKeys.end() || traniter == trankeys.mKeys.begin())
kframe->setTranslate(curtrans);
else
{
Nif::Vector3KeyList::VecType::const_iterator last = traniter-1;
float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime);
kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff));
}
if(scaleiter == scalekeys.mKeys.end() || scaleiter == scalekeys.mKeys.begin())
kframe->setScale(curscale);
else
{
Nif::FloatKeyList::VecType::const_iterator last = scaleiter-1;
float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime);
kframe->setScale(lastscale + ((curscale-lastscale)*diff));
}
}
}
anim->optimise();
}
TextKeyMap NIFSkeletonLoader::extractTextKeys(const Nif::NiTextKeyExtraData *tk)
{
TextKeyMap textkeys;
for(size_t i = 0;i < tk->list.size();i++)
{
const std::string &str = tk->list[i].text;
std::string::size_type pos = 0;
while(pos < str.length())
{
if(::isspace(str[pos]))
{
pos++;
continue;
}
std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos));
std::string result = str.substr(pos, nextpos-pos);
textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result)));
pos = nextpos;
}
}
return textkeys;
}
void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector<Nif::NiKeyframeController const*> &ctrls, Ogre::Bone *parent)
{ {
Ogre::Bone *bone; Ogre::Bone *bone;
if(!skel->hasBone(node->name)) if(!skel->hasBone(node->name))
@ -164,6 +29,8 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node,
if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */
node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */ node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */
node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */ node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */
node->recType == Nif::RC_NiBSAnimationNode || /* Handled in the object loader */
node->recType == Nif::RC_NiBSParticleNode ||
node->recType == Nif::RC_NiCamera || node->recType == Nif::RC_NiCamera ||
node->recType == Nif::RC_NiAutoNormalParticles || node->recType == Nif::RC_NiAutoNormalParticles ||
node->recType == Nif::RC_NiRotatingParticles node->recType == Nif::RC_NiRotatingParticles
@ -173,28 +40,16 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node,
Nif::ControllerPtr ctrl = node->controller; Nif::ControllerPtr ctrl = node->controller;
while(!ctrl.empty()) while(!ctrl.empty())
{ {
if(ctrl->recType == Nif::RC_NiKeyframeController) if(!(ctrl->recType == Nif::RC_NiParticleSystemController ||
ctrls.push_back(static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr()));
else if(!(ctrl->recType == Nif::RC_NiParticleSystemController ||
ctrl->recType == Nif::RC_NiVisController || ctrl->recType == Nif::RC_NiVisController ||
ctrl->recType == Nif::RC_NiUVController ctrl->recType == Nif::RC_NiUVController ||
ctrl->recType == Nif::RC_NiKeyframeController ||
ctrl->recType == Nif::RC_NiGeomMorpherController
)) ))
warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName());
ctrl = ctrl->next; ctrl = ctrl->next;
} }
Nif::ExtraPtr e = node->extra;
while(!e.empty())
{
if(e->recType == Nif::RC_NiTextKeyExtraData && !animroot)
{
const Nif::NiTextKeyExtraData *tk = static_cast<const Nif::NiTextKeyExtraData*>(e.getPtr());
textkeys = extractTextKeys(tk);
animroot = bone;
}
e = e->extra;
}
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node); const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode) if(ninode)
{ {
@ -202,7 +57,7 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node,
for(size_t i = 0;i < children.length();i++) for(size_t i = 0;i < children.length();i++)
{ {
if(!children[i].empty()) if(!children[i].empty())
buildBones(skel, children[i].getPtr(), animroot, textkeys, ctrls, bone); buildBones(skel, children[i].getPtr(), bone);
} }
} }
} }
@ -215,84 +70,14 @@ void NIFSkeletonLoader::loadResource(Ogre::Resource *resource)
Nif::NIFFile::ptr nif(Nif::NIFFile::create(skel->getName())); Nif::NIFFile::ptr nif(Nif::NIFFile::create(skel->getName()));
const Nif::Node *node = static_cast<const Nif::Node*>(nif->getRoot(0)); const Nif::Node *node = static_cast<const Nif::Node*>(nif->getRoot(0));
std::vector<const Nif::NiKeyframeController*> ctrls;
Ogre::Bone *animroot = NULL;
TextKeyMap textkeys;
try { try {
buildBones(skel, node, animroot, textkeys, ctrls); buildBones(skel, node);
} }
catch(std::exception &e) { catch(std::exception &e) {
std::cerr<< "Exception while loading "<<skel->getName() <<std::endl; std::cerr<< "Exception while loading "<<skel->getName() <<std::endl;
std::cerr<< e.what() <<std::endl; std::cerr<< e.what() <<std::endl;
return; return;
} }
/* Animations without textkeys don't get Ogre::Animation objects. */
if(!animroot)
return;
std::vector<std::string> targets;
// TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file
if(ctrls.size() == 0) // No animations? Then we're done.
return;
float maxtime = 0.0f;
for(size_t i = 0;i < ctrls.size();i++)
{
const Nif::NiKeyframeController *ctrl = ctrls[i];
maxtime = std::max(maxtime, ctrl->timeStop);
Nif::Named *target = dynamic_cast<Nif::Named*>(ctrl->target.getPtr());
if(target != NULL)
targets.push_back(target->name);
}
if(targets.size() != ctrls.size())
{
warn("Target size mismatch ("+Ogre::StringConverter::toString(targets.size())+" targets, "+
Ogre::StringConverter::toString(ctrls.size())+" controllers)");
return;
}
Ogre::UserObjectBindings &bindings = animroot->getUserObjectBindings();
bindings.setUserAny(sTextKeyExtraDataID, Ogre::Any(true));
std::string currentgroup;
TextKeyMap::const_iterator keyiter = textkeys.begin();
for(keyiter = textkeys.begin();keyiter != textkeys.end();keyiter++)
{
std::string::size_type sep = keyiter->second.find(':');
if((sep == currentgroup.length() && keyiter->second.compare(0, sep, currentgroup) == 0) ||
(sep == sizeof("soundgen")-1 && keyiter->second.compare(0, sep, "soundgen") == 0) ||
(sep == sizeof("sound")-1 && keyiter->second.compare(0, sep, "sound") == 0))
continue;
currentgroup = keyiter->second.substr(0, sep);
if(skel->hasAnimation(currentgroup))
continue;
TextKeyMap::const_iterator lastkeyiter = textkeys.end();
while((--lastkeyiter)->first > keyiter->first)
{
if(lastkeyiter->second.find(':') == currentgroup.length() &&
lastkeyiter->second.compare(0, currentgroup.length(), currentgroup) == 0)
break;
}
buildAnimation(skel, currentgroup, ctrls, targets, keyiter->first, lastkeyiter->first);
TextKeyMap::const_iterator insiter(keyiter);
TextKeyMap groupkeys;
do {
sep = insiter->second.find(':');
if(sep == currentgroup.length() && insiter->second.compare(0, sep, currentgroup) == 0)
groupkeys.insert(std::make_pair(insiter->first, insiter->second.substr(sep+2)));
else if((sep == sizeof("soundgen")-1 && insiter->second.compare(0, sep, "soundgen") == 0) ||
(sep == sizeof("sound")-1 && insiter->second.compare(0, sep, "sound") == 0))
groupkeys.insert(std::make_pair(insiter->first, insiter->second));
} while(insiter++ != lastkeyiter);
bindings.setUserAny(std::string(sTextKeyExtraDataID)+"@"+currentgroup, Ogre::Any(groupkeys));
}
} }
@ -300,16 +85,16 @@ Ogre::SkeletonPtr NIFSkeletonLoader::createSkeleton(const std::string &name, con
{ {
/* We need to be a little aggressive here, since some NIFs have a crap-ton /* We need to be a little aggressive here, since some NIFs have a crap-ton
* of nodes and Ogre only supports 256 bones. We will skip a skeleton if: * of nodes and Ogre only supports 256 bones. We will skip a skeleton if:
* There are no bones used for skinning, there are no controllers on non- * There are no bones used for skinning, there are no controllers, there
* NiTriShape nodes, there are no nodes named "AttachLight", and the tree * are no nodes named "AttachLight", and the tree consists of NiNode,
* consists of NiNode, NiTriShape, and RootCollisionNode types only. * NiTriShape, and RootCollisionNode types only.
*/ */
if(!node->boneTrafo) if(!node->boneTrafo)
{ {
if(node->recType == Nif::RC_NiTriShape)
return Ogre::SkeletonPtr();
if(node->controller.empty() && node->name != "AttachLight") if(node->controller.empty() && node->name != "AttachLight")
{ {
if(node->recType == Nif::RC_NiTriShape)
return Ogre::SkeletonPtr();
if(node->recType == Nif::RC_NiNode || node->recType == Nif::RC_RootCollisionNode) if(node->recType == Nif::RC_NiNode || node->recType == Nif::RC_RootCollisionNode)
{ {
const Nif::NiNode *ninode = static_cast<const Nif::NiNode*>(node); const Nif::NiNode *ninode = static_cast<const Nif::NiNode*>(node);

View file

@ -36,10 +36,7 @@ class NIFSkeletonLoader : public Ogre::ManualResourceLoader
abort(); abort();
} }
static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector<const Nif::NiKeyframeController*> &ctrls, const std::vector<std::string> &targets, float startTime, float stopTime); void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent=NULL);
static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk);
void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector<Nif::NiKeyframeController const*> &ctrls, Ogre::Bone *parent=NULL);
// Lookup to retrieve an Ogre bone handle for a given Nif record index // Lookup to retrieve an Ogre bone handle for a given Nif record index
std::map<int,int> mNifToOgreHandleMap; std::map<int,int> mNifToOgreHandleMap;

View file

@ -9,6 +9,7 @@
<Property key="OffsetHeight" value="0"/> <Property key="OffsetHeight" value="0"/>
<Codes> <Codes>
<Code range="33 126"/> <Code range="33 126"/>
<Code range="160"/> <!-- Non-breaking space -->
<Code range="192 382"/> <!-- Central and Eastern European languages glyphs --> <Code range="192 382"/> <!-- Central and Eastern European languages glyphs -->
<Code range="1025 1105"/> <Code range="1025 1105"/>
<Code range="2026"/> <!-- Ellipsis --> <Code range="2026"/> <!-- Ellipsis -->

View file

@ -511,8 +511,8 @@ namespace Physic
void PhysicEngine::stepSimulation(double deltaT) void PhysicEngine::stepSimulation(double deltaT)
{ {
// This isn't needed as there are no dynamic objects at this point // This seems to be needed for character controller objects
//dynamicsWorld->stepSimulation(deltaT,10, 1/60.0); dynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
if(isDebugCreated) if(isDebugCreated)
{ {
mDebugDrawer->step(); mDebugDrawer->step();

View file

@ -559,6 +559,8 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
assert(mgr); assert(mgr);
mSceneMgr = mgr; mSceneMgr = mgr;
mShaderRenderManager = NULL;
mRenderManager = NULL;
using namespace MyGUI; using namespace MyGUI;
@ -574,7 +576,10 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
// Set up OGRE platform (bypassing OgrePlatform). We might make this more generic later. // Set up OGRE platform (bypassing OgrePlatform). We might make this more generic later.
mLogManager = new LogManager(); mLogManager = new LogManager();
mRenderManager = new MyGUI::ShaderBasedRenderManager(); if (!Ogre::Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(Ogre::RSC_FIXED_FUNCTION))
mShaderRenderManager = new MyGUI::ShaderBasedRenderManager();
else
mRenderManager = new MyGUI::OgreRenderManager();
mDataManager = new MyGUI::FixedOgreDataManager(); mDataManager = new MyGUI::FixedOgreDataManager();
LogManager::getInstance().setSTDOutputEnabled(logging); LogManager::getInstance().setSTDOutputEnabled(logging);
@ -582,6 +587,9 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
if (!theLogFile.empty()) if (!theLogFile.empty())
LogManager::getInstance().createDefaultSource(theLogFile); LogManager::getInstance().createDefaultSource(theLogFile);
if (mShaderRenderManager)
mShaderRenderManager->initialise(wnd, mgr);
else
mRenderManager->initialise(wnd, mgr); mRenderManager->initialise(wnd, mgr);
mDataManager->initialise("General"); mDataManager->initialise("General");
@ -592,8 +600,16 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
void MyGUIManager::updateWindow (Ogre::RenderWindow *wnd) void MyGUIManager::updateWindow (Ogre::RenderWindow *wnd)
{ {
if (mShaderRenderManager)
{
mShaderRenderManager->setRenderWindow (wnd);
mShaderRenderManager->setActiveViewport(0);
}
else
{
mRenderManager->setRenderWindow (wnd); mRenderManager->setRenderWindow (wnd);
mRenderManager->setActiveViewport(0); mRenderManager->setActiveViewport(0);
}
} }
void MyGUIManager::shutdown() void MyGUIManager::shutdown()
@ -606,6 +622,12 @@ void MyGUIManager::shutdown()
delete mRenderManager; delete mRenderManager;
mRenderManager = NULL; mRenderManager = NULL;
} }
if(mShaderRenderManager)
{
mShaderRenderManager->shutdown();
delete mShaderRenderManager;
mShaderRenderManager = NULL;
}
if(mDataManager) if(mDataManager)
{ {
mDataManager->shutdown(); mDataManager->shutdown();

View file

@ -8,6 +8,7 @@ namespace MyGUI
class Gui; class Gui;
class LogManager; class LogManager;
class OgreDataManager; class OgreDataManager;
class OgreRenderManager;
class ShaderBasedRenderManager; class ShaderBasedRenderManager;
} }
@ -25,12 +26,12 @@ namespace GUI
MyGUI::Gui *mGui; MyGUI::Gui *mGui;
MyGUI::LogManager* mLogManager; MyGUI::LogManager* mLogManager;
MyGUI::OgreDataManager* mDataManager; MyGUI::OgreDataManager* mDataManager;
MyGUI::ShaderBasedRenderManager* mRenderManager; MyGUI::OgreRenderManager* mRenderManager;
MyGUI::ShaderBasedRenderManager* mShaderRenderManager;
Ogre::SceneManager* mSceneMgr; Ogre::SceneManager* mSceneMgr;
public: public:
MyGUIManager() : mLogManager(NULL), mDataManager(NULL), mRenderManager(NULL), mGui(NULL) {}
MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string("")) MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string(""))
{ {
setup(wnd,mgr,logging, logDir); setup(wnd,mgr,logging, logDir);

View file

@ -19,6 +19,7 @@ Fader::Fader(Ogre::SceneManager* sceneMgr)
, mTargetAlpha(0.f) , mTargetAlpha(0.f)
, mCurrentAlpha(0.f) , mCurrentAlpha(0.f)
, mStartAlpha(0.f) , mStartAlpha(0.f)
, mFactor(1.f)
{ {
// Create the fading material // Create the fading material
MaterialPtr material = MaterialManager::getSingleton().create("FadeInOutMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); MaterialPtr material = MaterialManager::getSingleton().create("FadeInOutMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
@ -63,18 +64,19 @@ void Fader::update(float dt)
if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha; if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha;
} }
applyAlpha();
mRemainingTime -= dt; mRemainingTime -= dt;
} }
if (mCurrentAlpha == 0.f) mRectangle->setVisible(false); if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f)
mRectangle->setVisible(false);
else
applyAlpha();
} }
void Fader::applyAlpha() void Fader::applyAlpha()
{ {
mRectangle->setVisible(true); mRectangle->setVisible(true);
mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, mCurrentAlpha); mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 1.f-((1.f-mCurrentAlpha) * mFactor));
} }
void Fader::fadeIn(float time) void Fader::fadeIn(float time)

View file

@ -29,6 +29,8 @@ namespace Render
void fadeOut(const float time); void fadeOut(const float time);
void fadeTo(const int percent, const float time); void fadeTo(const int percent, const float time);
void setFactor (float factor) { mFactor = factor; }
private: private:
enum FadingMode enum FadingMode
{ {
@ -49,6 +51,8 @@ namespace Render
float mCurrentAlpha; float mCurrentAlpha;
float mStartAlpha; float mStartAlpha;
float mFactor;
Ogre::SceneManager* mSceneMgr; Ogre::SceneManager* mSceneMgr;
}; };
}} }}

View file

@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind
OpenMW is an attempt at recreating the engine for the popular role-playing game OpenMW is an attempt at recreating the engine for the popular role-playing game
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
Version: 0.22.0 Version: 0.23.0
License: GPL (see GPL3.txt for more information) License: GPL (see GPL3.txt for more information)
Website: http://www.openmw.org Website: http://www.openmw.org
@ -94,6 +94,68 @@ Allowed options:
CHANGELOG CHANGELOG
0.23.0
Bug #522: Player collides with placeable items
Bug #553: Open/Close sounds played when accessing main menu w/ Journal Open
Bug #561: Tooltip word wrapping delay
Bug #578: Bribing works incorrectly
Bug #601: PositionCell fails on negative coordinates
Bug #606: Some NPCs hairs not rendered with Better Heads addon
Bug #609: Bad rendering of bone boots
Bug #613: Messagebox causing assert to fail
Bug #631: Segfault on shutdown
Bug #634: Exception when talking to Calvus Horatius in Mournhold, royal palace courtyard
Bug #635: Scale NPCs depending on race
Bug #643: Dialogue Race select function is inverted
Bug #646: Twohanded weapons don't work properly
Bug #654: Crash when dropping objects without a collision shape
Bug #655/656: Objects that were disabled or deleted (but not both) were added to the scene when re-entering a cell
Bug #660: "g" in "change" cut off in Race Menu
Bug #661: Arrille sells me the key to his upstairs room
Bug #662: Day counter starts at 2 instead of 1
Bug #663: Cannot select "come unprepared" topic in dialog with Dagoth Ur
Bug #665: Pickpocket -> "Grab all" grabs all NPC inventory, even not listed in container window.
Bug #666: Looking up/down problem
Bug #667: Active effects border visible during loading
Bug #669: incorrect player position at new game start
Bug #670: race selection menu: sex, face and hair left button not totally clickable
Bug #671: new game: player is naked
Bug #674: buying or selling items doesn't change amount of gold
Bug #675: fatigue is not set to its maximum when starting a new game
Bug #678: Wrong rotation order causes RefData's rotation to be stored incorrectly
Bug #680: different gold coins in Tel Mara
Bug #682: Race menu ignores playable flag for some hairs and faces
Bug #685: Script compiler does not accept ":" after a function name
Bug #688: dispose corpse makes cross-hair to disappear
Bug #691: Auto equipping ignores equipment conditions
Bug #692: OpenMW doesnt load "loose file" texture packs that places resources directly in data folder
Bug #696: Draugr incorrect head offset
Bug #697: Sail transparency issue
Bug #700: "On the rocks" mod does not load its UV coordinates correctly.
Bug #702: Some race mods don't work
Bug #711: Crash during character creation
Bug #715: Growing Tauryon
Bug #725: Auto calculate stats
Bug #728: Failure to open container and talk dialogue
Bug #731: Crash with Mush-Mere's "background" topic
Feature #55/657: Item Repairing
Feature #62/87: Enchanting
Feature #99: Pathfinding
Feature #104: AI Package: Travel
Feature #129: Levelled items
Feature #204: Texture animations
Feature #239: Fallback-Settings
Feature #535: Console object selection improvements
Feature #629: Add levelup description in levelup layout dialog
Feature #630: Optional format subrecord in (tes3) header
Feature #641: Armor rating
Feature #645: OnDeath script function
Feature #683: Companion item UI
Feature #698: Basic Particles
Task #648: Split up components/esm/loadlocks
Task #695: mwgui cleanup
0.22.0 0.22.0
Bug #311: Potential infinite recursion in script compiler Bug #311: Potential infinite recursion in script compiler