1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 18:35:20 +00:00
OpenMW/apps/openmw/mwgui/birth.cpp
florent.teppe 42e45723b7 Fixes issue in MW script compilation that would silently produce the wrong bytecode
Fixes issue when fetching MyGui values that were stored as RefId but fetched as String

Removed some uncessary copies, fixed issues with lowercase and uneeded changes
2022-12-27 19:15:57 +01:00

274 lines
9.2 KiB
C++

#include "birth.hpp"
#include <MyGUI_Gui.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ListBox.h>
#include <MyGUI_ScrollView.h>
#include <components/esm3/loadbsgn.hpp>
#include <components/esm3/loadspel.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/resourcesystem.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "ustring.hpp"
#include "widgets.hpp"
namespace
{
bool sortBirthSigns(const std::pair<ESM::RefId, const ESM::BirthSign*>& left,
const std::pair<ESM::RefId, const ESM::BirthSign*>& right)
{
return left.second->mName.compare(right.second->mName) < 0;
}
}
namespace MWGui
{
BirthDialog::BirthDialog()
: WindowModal("openmw_chargen_birth.layout")
{
// Centre dialog
center();
getWidget(mSpellArea, "SpellArea");
getWidget(mBirthImage, "BirthsignImage");
getWidget(mBirthList, "BirthsignList");
mBirthList->setScrollVisible(true);
mBirthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onAccept);
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
MyGUI::Button* backButton;
getWidget(backButton, "BackButton");
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
MyGUI::Button* okButton;
getWidget(okButton, "OKButton");
okButton->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
updateBirths();
updateSpells();
}
void BirthDialog::setNextButtonShow(bool shown)
{
MyGUI::Button* okButton;
getWidget(okButton, "OKButton");
if (shown)
okButton->setCaption(
toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNext", {})));
else
okButton->setCaption(
toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
}
void BirthDialog::onOpen()
{
WindowModal::onOpen();
updateBirths();
updateSpells();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mBirthList);
// Show the current birthsign by default
const auto& signId = MWBase::Environment::get().getWorld()->getPlayer().getBirthSign();
if (!signId.empty())
setBirthId(signId);
}
void BirthDialog::setBirthId(const ESM::RefId& birthId)
{
mCurrentBirthId = birthId;
mBirthList->setIndexSelected(MyGUI::ITEM_NONE);
size_t count = mBirthList->getItemCount();
for (size_t i = 0; i < count; ++i)
{
if (*mBirthList->getItemDataAt<ESM::RefId>(i) == birthId)
{
mBirthList->setIndexSelected(i);
break;
}
}
updateSpells();
}
// widget controls
void BirthDialog::onOkClicked(MyGUI::Widget* _sender)
{
if (mBirthList->getIndexSelected() == MyGUI::ITEM_NONE)
return;
eventDone(this);
}
void BirthDialog::onAccept(MyGUI::ListBox* _sender, size_t _index)
{
onSelectBirth(_sender, _index);
if (mBirthList->getIndexSelected() == MyGUI::ITEM_NONE)
return;
eventDone(this);
}
void BirthDialog::onBackClicked(MyGUI::Widget* _sender)
{
eventBack();
}
void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index)
{
if (_index == MyGUI::ITEM_NONE)
return;
const ESM::RefId& birthId = *mBirthList->getItemDataAt<ESM::RefId>(_index);
if (mCurrentBirthId == birthId)
return;
mCurrentBirthId = birthId;
updateSpells();
}
// update widget content
void BirthDialog::updateBirths()
{
mBirthList->removeAllItems();
const MWWorld::Store<ESM::BirthSign>& signs
= MWBase::Environment::get().getWorld()->getStore().get<ESM::BirthSign>();
// sort by name
std::vector<std::pair<ESM::RefId, const ESM::BirthSign*>> birthSigns;
for (const ESM::BirthSign& sign : signs)
{
birthSigns.emplace_back(sign.mId, &sign);
}
std::sort(birthSigns.begin(), birthSigns.end(), sortBirthSigns);
int index = 0;
for (auto& birthsignPair : birthSigns)
{
mBirthList->addItem(birthsignPair.second->mName, birthsignPair.first);
if (mCurrentBirthId.empty())
{
mBirthList->setIndexSelected(index);
mCurrentBirthId = birthsignPair.first;
}
else if (birthsignPair.first == mCurrentBirthId)
{
mBirthList->setIndexSelected(index);
}
index++;
}
}
void BirthDialog::updateSpells()
{
for (MyGUI::Widget* widget : mSpellItems)
{
MyGUI::Gui::getInstance().destroyWidget(widget);
}
mSpellItems.clear();
if (mCurrentBirthId.empty())
return;
Widgets::MWSpellPtr spellWidget;
const int lineHeight = MWBase::Environment::get().getWindowManager()->getFontHeight() + 2;
MyGUI::IntCoord coord(0, 0, mSpellArea->getWidth(), lineHeight);
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
const ESM::BirthSign* birth = store.get<ESM::BirthSign>().find(mCurrentBirthId);
mBirthImage->setImageTexture(Misc::ResourceHelpers::correctTexturePath(
birth->mTexture, MWBase::Environment::get().getResourceSystem()->getVFS()));
std::vector<ESM::RefId> abilities, powers, spells;
std::vector<ESM::RefId>::const_iterator it = birth->mPowers.mList.begin();
std::vector<ESM::RefId>::const_iterator end = birth->mPowers.mList.end();
for (; it != end; ++it)
{
const ESM::RefId& spellId = *it;
const ESM::Spell* spell = store.get<ESM::Spell>().search(spellId);
if (!spell)
continue; // Skip spells which cannot be found
ESM::Spell::SpellType type = static_cast<ESM::Spell::SpellType>(spell->mData.mType);
if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power)
continue; // We only want spell, ability and powers.
if (type == ESM::Spell::ST_Ability)
abilities.push_back(spellId);
else if (type == ESM::Spell::ST_Power)
powers.push_back(spellId);
else if (type == ESM::Spell::ST_Spell)
spells.push_back(spellId);
}
int i = 0;
struct
{
const std::vector<ESM::RefId>& spells;
const char* label;
} categories[3] = { { abilities, "sBirthsignmenu1" }, { powers, "sPowers" }, { spells, "sBirthsignmenu2" } };
for (int category = 0; category < 3; ++category)
{
if (!categories[category].spells.empty())
{
MyGUI::TextBox* label = mSpellArea->createWidget<MyGUI::TextBox>(
"SandBrightText", coord, MyGUI::Align::Default, std::string("Label"));
label->setCaption(toUString(MWBase::Environment::get().getWindowManager()->getGameSettingString(
categories[category].label, {})));
mSpellItems.push_back(label);
coord.top += lineHeight;
end = categories[category].spells.end();
for (it = categories[category].spells.begin(); it != end; ++it)
{
const ESM::RefId& spellId = *it;
spellWidget = mSpellArea->createWidget<Widgets::MWSpell>("MW_StatName", coord,
MyGUI::Align::Default, std::string("Spell") + MyGUI::utility::toString(i));
spellWidget->setSpellId(spellId);
mSpellItems.push_back(spellWidget);
coord.top += lineHeight;
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?
spellWidget->createEffectWidgets(
mSpellItems, mSpellArea, spellCoord, (category == 0) ? Widgets::MWEffectList::EF_Constant : 0);
coord.top = spellCoord.top;
++i;
}
}
}
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the
// scrollbar is hidden
mSpellArea->setVisibleVScroll(false);
mSpellArea->setCanvasSize(MyGUI::IntSize(mSpellArea->getWidth(), std::max(mSpellArea->getHeight(), coord.top)));
mSpellArea->setVisibleVScroll(true);
mSpellArea->setViewOffset(MyGUI::IntPoint(0, 0));
}
}