Merge branch 'master'
commit
f675d8d039
@ -0,0 +1,10 @@
|
||||
Dongle's Oblivion Daedric font set
|
||||
http://www.uesp.net/wiki/Lore:Daedric_Alphabet#Daedric_Font
|
||||
|
||||
---------------------------------------------------
|
||||
|
||||
This was done entirely as a personal project. Bethesda Softworks graciously granted me the permission for it. I am not connected with them in any way.
|
||||
You may freely use these fonts to create anything you'd like. You may re-distribute the fonts freely, over the Internet, or by any other means. Always keep the .zip file intact, and this read me included.
|
||||
Please do not modify and redistribute the fonts without my permission.
|
||||
You may NOT sell any of these fonts under any circumstances. This includes putting them on compilation font CDs for sale, putting them in a "members only" pay-area of a website, or any other means of financial gain connected in ANY way with the redistribution of any of these fonts.
|
||||
You have my permission to create and sell any artwork made with these fonts, however you may need to contact Bethesda Softworks before doing so.
|
@ -0,0 +1,512 @@
|
||||
#include "alchemywindow.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
#include "window_manager.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string getIconPath(MWWorld::Ptr ptr)
|
||||
{
|
||||
std::string path = std::string("icons\\");
|
||||
path += MWWorld::Class::get(ptr).getInventoryIcon(ptr);
|
||||
int pos = path.rfind(".");
|
||||
path.erase(pos);
|
||||
path.append(".dds");
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager)
|
||||
: WindowBase("openmw_alchemy_window_layout.xml", parWindowManager)
|
||||
, ContainerBase(0)
|
||||
{
|
||||
getWidget(mCreateButton, "CreateButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
getWidget(mIngredient1, "Ingredient1");
|
||||
getWidget(mIngredient2, "Ingredient2");
|
||||
getWidget(mIngredient3, "Ingredient3");
|
||||
getWidget(mIngredient4, "Ingredient4");
|
||||
getWidget(mApparatus1, "Apparatus1");
|
||||
getWidget(mApparatus2, "Apparatus2");
|
||||
getWidget(mApparatus3, "Apparatus3");
|
||||
getWidget(mApparatus4, "Apparatus4");
|
||||
getWidget(mEffectsBox, "CreatedEffects");
|
||||
getWidget(mNameEdit, "NameEdit");
|
||||
|
||||
mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||
mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||
mIngredient3->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||
mIngredient4->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
|
||||
|
||||
MyGUI::Widget* buttonBox = mCancelButton->getParent();
|
||||
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
|
||||
mCancelButton->setCoord(buttonBox->getWidth() - cancelButtonWidth,
|
||||
mCancelButton->getTop(), cancelButtonWidth, mCancelButton->getHeight());
|
||||
int createButtonWidth = mCreateButton->getTextSize().width + 24;
|
||||
mCreateButton->setCoord(buttonBox->getWidth() - createButtonWidth - cancelButtonWidth - 4,
|
||||
mCreateButton->getTop(), createButtonWidth, mCreateButton->getHeight());
|
||||
|
||||
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
||||
|
||||
MyGUI::ScrollView* itemView;
|
||||
MyGUI::Widget* containerWidget;
|
||||
getWidget(containerWidget, "Items");
|
||||
getWidget(itemView, "ItemView");
|
||||
setWidgets(containerWidget, itemView);
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
mWindowManager.popGuiMode();
|
||||
mWindowManager.popGuiMode();
|
||||
}
|
||||
|
||||
void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
// check if mortar & pestle is available (always needed)
|
||||
/// \todo check albemic, calcinator, retort (sometimes needed)
|
||||
if (!mApparatus1->isUserString("ToolTipType"))
|
||||
{
|
||||
mWindowManager.messageBox("#{sNotifyMessage45}", std::vector<std::string>());
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure 2 or more ingredients were selected
|
||||
int numIngreds = 0;
|
||||
if (mIngredient1->isUserString("ToolTipType"))
|
||||
++numIngreds;
|
||||
if (mIngredient2->isUserString("ToolTipType"))
|
||||
++numIngreds;
|
||||
if (mIngredient3->isUserString("ToolTipType"))
|
||||
++numIngreds;
|
||||
if (mIngredient4->isUserString("ToolTipType"))
|
||||
++numIngreds;
|
||||
if (numIngreds < 2)
|
||||
{
|
||||
mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector<std::string>());
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure a name was entered
|
||||
std::string name = mNameEdit->getCaption();
|
||||
boost::algorithm::trim(name);
|
||||
if (name == "")
|
||||
{
|
||||
mWindowManager.messageBox("#{sNotifyMessage37}", std::vector<std::string>());
|
||||
return;
|
||||
}
|
||||
|
||||
// if there are no created effects, the potion will always fail (but the ingredients won't be destroyed)
|
||||
if (mEffects.empty())
|
||||
{
|
||||
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
|
||||
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rand() % 2 == 0) /// \todo
|
||||
{
|
||||
ESM::Potion newPotion;
|
||||
newPotion.name = mNameEdit->getCaption();
|
||||
ESM::EffectList effects;
|
||||
for (unsigned int i=0; i<4; ++i)
|
||||
{
|
||||
if (mEffects.size() >= i+1)
|
||||
{
|
||||
ESM::ENAMstruct effect;
|
||||
effect.effectID = mEffects[i].mEffectID;
|
||||
effect.area = 0;
|
||||
effect.range = ESM::RT_Self;
|
||||
effect.skill = mEffects[i].mSkill;
|
||||
effect.attribute = mEffects[i].mAttribute;
|
||||
effect.magnMin = 1; /// \todo
|
||||
effect.magnMax = 10; /// \todo
|
||||
effect.duration = 60; /// \todo
|
||||
effects.list.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
// UESP Wiki / Morrowind:Alchemy
|
||||
// "The weight of a potion is an average of the weight of the ingredients, rounded down."
|
||||
// note by scrawl: not rounding down here, I can't imagine a created potion to
|
||||
// have 0 weight when using ingredients with 0.1 weight respectively
|
||||
float weight = 0;
|
||||
if (mIngredient1->isUserString("ToolTipType"))
|
||||
weight += mIngredient1->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
|
||||
if (mIngredient2->isUserString("ToolTipType"))
|
||||
weight += mIngredient2->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
|
||||
if (mIngredient3->isUserString("ToolTipType"))
|
||||
weight += mIngredient3->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
|
||||
if (mIngredient4->isUserString("ToolTipType"))
|
||||
weight += mIngredient4->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
|
||||
newPotion.data.weight = weight / float(numIngreds);
|
||||
|
||||
newPotion.data.value = 100; /// \todo
|
||||
newPotion.effects = effects;
|
||||
// pick a random mesh and icon
|
||||
std::vector<std::string> names;
|
||||
/// \todo is the mesh/icon dependent on alchemy skill?
|
||||
names.push_back("standard");
|
||||
names.push_back("bargain");
|
||||
names.push_back("cheap");
|
||||
names.push_back("fresh");
|
||||
names.push_back("exclusive");
|
||||
names.push_back("quality");
|
||||
int random = rand() % names.size();
|
||||
newPotion.model = "m\\misc_potion_" + names[random ] + "_01.nif";
|
||||
newPotion.icon = "m\\tx_potion_" + names[random ] + "_01.dds";
|
||||
|
||||
// check if a similiar potion record exists already
|
||||
bool found = false;
|
||||
std::string objectId;
|
||||
typedef std::map<std::string, ESM::Potion> PotionMap;
|
||||
PotionMap potions = MWBase::Environment::get().getWorld()->getStore().potions.list;
|
||||
for (PotionMap::const_iterator it = potions.begin(); it != potions.end(); ++it)
|
||||
{
|
||||
if (found) break;
|
||||
|
||||
if (it->second.data.value == newPotion.data.value
|
||||
&& it->second.data.weight == newPotion.data.weight
|
||||
&& it->second.name == newPotion.name
|
||||
&& it->second.effects.list.size() == newPotion.effects.list.size())
|
||||
{
|
||||
// check effects
|
||||
for (unsigned int i=0; i < it->second.effects.list.size(); ++i)
|
||||
{
|
||||
const ESM::ENAMstruct& a = it->second.effects.list[i];
|
||||
const ESM::ENAMstruct& b = newPotion.effects.list[i];
|
||||
if (a.effectID == b.effectID
|
||||
&& a.area == b.area
|
||||
&& a.range == b.range
|
||||
&& a.skill == b.skill
|
||||
&& a.attribute == b.attribute
|
||||
&& a.magnMin == b.magnMin
|
||||
&& a.magnMax == b.magnMax
|
||||
&& a.duration == b.duration)
|
||||
{
|
||||
found = true;
|
||||
objectId = it->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
std::pair<std::string, const ESM::Potion*> result = MWBase::Environment::get().getWorld()->createRecord(newPotion);
|
||||
objectId = result.first;
|
||||
}
|
||||
|
||||
// create a reference and add it to player inventory
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), objectId);
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
ref.getPtr().getRefData().setCount(1);
|
||||
store.add(ref.getPtr());
|
||||
|
||||
mWindowManager.messageBox("#{sPotionSuccess}", std::vector<std::string>());
|
||||
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// potion failed
|
||||
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
|
||||
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
|
||||
}
|
||||
|
||||
// reduce count of the ingredients
|
||||
if (mIngredient1->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr ingred = *mIngredient1->getUserData<MWWorld::Ptr>();
|
||||
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
|
||||
if (ingred.getRefData().getCount() == 0)
|
||||
removeIngredient(mIngredient1);
|
||||
}
|
||||
if (mIngredient2->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr ingred = *mIngredient2->getUserData<MWWorld::Ptr>();
|
||||
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
|
||||
if (ingred.getRefData().getCount() == 0)
|
||||
removeIngredient(mIngredient2);
|
||||
}
|
||||
if (mIngredient3->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr ingred = *mIngredient3->getUserData<MWWorld::Ptr>();
|
||||
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
|
||||
if (ingred.getRefData().getCount() == 0)
|
||||
removeIngredient(mIngredient3);
|
||||
}
|
||||
if (mIngredient4->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr ingred = *mIngredient4->getUserData<MWWorld::Ptr>();
|
||||
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
|
||||
if (ingred.getRefData().getCount() == 0)
|
||||
removeIngredient(mIngredient4);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void AlchemyWindow::open()
|
||||
{
|
||||
openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
setFilter(ContainerBase::Filter_Ingredients);
|
||||
|
||||
// pick the best available apparatus
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
MWWorld::Ptr bestAlbemic;
|
||||
MWWorld::Ptr bestMortarPestle;
|
||||
MWWorld::Ptr bestCalcinator;
|
||||
MWWorld::Ptr bestRetort;
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it(store.begin(MWWorld::ContainerStore::Type_Apparatus));
|
||||
it != store.end(); ++it)
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData>* ref = it->get<ESM::Apparatus>();
|
||||
if (ref->base->data.type == ESM::Apparatus::Albemic
|
||||
&& (bestAlbemic.isEmpty() || ref->base->data.quality > bestAlbemic.get<ESM::Apparatus>()->base->data.quality))
|
||||
bestAlbemic = *it;
|
||||
else if (ref->base->data.type == ESM::Apparatus::MortarPestle
|
||||
&& (bestMortarPestle.isEmpty() || ref->base->data.quality > bestMortarPestle.get<ESM::Apparatus>()->base->data.quality))
|
||||
bestMortarPestle = *it;
|
||||
else if (ref->base->data.type == ESM::Apparatus::Calcinator
|
||||
&& (bestCalcinator.isEmpty() || ref->base->data.quality > bestCalcinator.get<ESM::Apparatus>()->base->data.quality))
|
||||
bestCalcinator = *it;
|
||||
else if (ref->base->data.type == ESM::Apparatus::Retort
|
||||
&& (bestRetort.isEmpty() || ref->base->data.quality > bestRetort.get<ESM::Apparatus>()->base->data.quality))
|
||||
bestRetort = *it;
|
||||
}
|
||||
|
||||
if (!bestMortarPestle.isEmpty())
|
||||
{
|
||||
mApparatus1->setUserString("ToolTipType", "ItemPtr");
|
||||
mApparatus1->setUserData(bestMortarPestle);
|
||||
mApparatus1->setImageTexture(getIconPath(bestMortarPestle));
|
||||
}
|
||||
if (!bestAlbemic.isEmpty())
|
||||
{
|
||||
mApparatus2->setUserString("ToolTipType", "ItemPtr");
|
||||
mApparatus2->setUserData(bestAlbemic);
|
||||
mApparatus2->setImageTexture(getIconPath(bestAlbemic));
|
||||
}
|
||||
if (!bestCalcinator.isEmpty())
|
||||
{
|
||||
mApparatus3->setUserString("ToolTipType", "ItemPtr");
|
||||
mApparatus3->setUserData(bestCalcinator);
|
||||
mApparatus3->setImageTexture(getIconPath(bestCalcinator));
|
||||
}
|
||||
if (!bestRetort.isEmpty())
|
||||
{
|
||||
mApparatus4->setUserString("ToolTipType", "ItemPtr");
|
||||
mApparatus4->setUserData(bestRetort);
|
||||
mApparatus4->setImageTexture(getIconPath(bestRetort));
|
||||
}
|
||||
}
|
||||
|
||||
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
|
||||
{
|
||||
removeIngredient(_sender);
|
||||
drawItems();
|
||||
update();
|
||||
}
|
||||
|
||||
void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item)
|
||||
{
|
||||
MyGUI::ImageBox* add = NULL;
|
||||
|
||||
// don't allow to add an ingredient that is already added
|
||||
// (which could happen if two similiar ingredients don't stack because of script / owner)
|
||||
bool alreadyAdded = false;
|
||||
std::string name = MWWorld::Class::get(item).getName(item);
|
||||
if (mIngredient1->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr item2 = *mIngredient1->getUserData<MWWorld::Ptr>();
|
||||
std::string name2 = MWWorld::Class::get(item2).getName(item2);
|
||||
if (name == name2)
|
||||
alreadyAdded = true;
|
||||
}
|
||||
if (mIngredient2->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr item2 = *mIngredient2->getUserData<MWWorld::Ptr>();
|
||||
std::string name2 = MWWorld::Class::get(item2).getName(item2);
|
||||
if (name == name2)
|
||||
alreadyAdded = true;
|
||||
}
|
||||
if (mIngredient3->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr item2 = *mIngredient3->getUserData<MWWorld::Ptr>();
|
||||
std::string name2 = MWWorld::Class::get(item2).getName(item2);
|
||||
if (name == name2)
|
||||
alreadyAdded = true;
|
||||
}
|
||||
if (mIngredient4->isUserString("ToolTipType"))
|
||||
{
|
||||
MWWorld::Ptr item2 = *mIngredient4->getUserData<MWWorld::Ptr>();
|
||||
std::string name2 = MWWorld::Class::get(item2).getName(item2);
|
||||
if (name == name2)
|
||||
alreadyAdded = true;
|
||||
}
|
||||
if (alreadyAdded)
|
||||
return;
|
||||
|
||||
if (!mIngredient1->isUserString("ToolTipType"))
|
||||
add = mIngredient1;
|
||||
if (add == NULL && !mIngredient2->isUserString("ToolTipType"))
|
||||
add = mIngredient2;
|
||||
if (add == NULL && !mIngredient3->isUserString("ToolTipType"))
|
||||
add = mIngredient3;
|
||||
if (add == NULL && !mIngredient4->isUserString("ToolTipType"))
|
||||
add = mIngredient4;
|
||||
|
||||
if (add != NULL)
|
||||
{
|
||||
add->setUserString("ToolTipType", "ItemPtr");
|
||||
add->setUserData(item);
|
||||
add->setImageTexture(getIconPath(item));
|
||||
drawItems();
|
||||
update();
|
||||
|
||||
std::string sound = MWWorld::Class::get(item).getUpSoundId(item);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MWWorld::Ptr> AlchemyWindow::itemsToIgnore()
|
||||
{
|
||||
std::vector<MWWorld::Ptr> ignore;
|
||||
// don't show ingredients that are currently selected in the "available ingredients" box.
|
||||
if (mIngredient1->isUserString("ToolTipType"))
|
||||
ignore.push_back(*mIngredient1->getUserData<MWWorld::Ptr>());
|
||||
if (mIngredient2->isUserString("ToolTipType"))
|
||||
ignore.push_back(*mIngredient2->getUserData<MWWorld::Ptr>());
|
||||
if (mIngredient3->isUserString("ToolTipType"))
|
||||
ignore.push_back(*mIngredient3->getUserData<MWWorld::Ptr>());
|
||||
if (mIngredient4->isUserString("ToolTipType"))
|
||||
ignore.push_back(*mIngredient4->getUserData<MWWorld::Ptr>());
|
||||
|
||||
return ignore;
|
||||
}
|
||||
|
||||
void AlchemyWindow::update()
|
||||
{
|
||||
Widgets::SpellEffectList effects;
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
MyGUI::ImageBox* ingredient;
|
||||
if (i==0)
|
||||
ingredient = mIngredient1;
|
||||
else if (i==1)
|
||||
ingredient = mIngredient2;
|
||||
else if (i==2)
|
||||
ingredient = mIngredient3;
|
||||
else if (i==3)
|
||||
ingredient = mIngredient4;
|
||||
|
||||
if (!ingredient->isUserString("ToolTipType"))
|
||||
continue;
|
||||
|
||||
// add the effects of this ingredient to list of effects
|
||||
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData>* ref = ingredient->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>();
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
if (ref->base->data.effectID[i] < 0)
|
||||
continue;
|
||||
MWGui::Widgets::SpellEffectParams params;
|
||||
params.mEffectID = ref->base->data.effectID[i];
|
||||
params.mAttribute = ref->base->data.attributes[i];
|
||||
params.mSkill = ref->base->data.skills[i];
|
||||
effects.push_back(params);
|
||||
}
|
||||
|
||||
// update ingredient count labels
|
||||
if (ingredient->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
|
||||
|
||||
MyGUI::TextBox* text = ingredient->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
|
||||
text->setTextAlign(MyGUI::Align::Right);
|
||||
text->setNeedMouseFocus(false);
|
||||
text->setTextShadow(true);
|
||||
text->setTextShadowColour(MyGUI::Colour(0,0,0));
|
||||
text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
|
||||
}
|
||||
|
||||
// now remove effects that are only present once
|
||||
Widgets::SpellEffectList::iterator it = effects.begin();
|
||||
while (it != effects.end())
|
||||
{
|
||||
Widgets::SpellEffectList::iterator next = it;
|
||||
++next;
|
||||
bool found = false;
|
||||
for (; next != effects.end(); ++next)
|
||||
{
|
||||
if (*next == *it)
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
it = effects.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
// now remove duplicates, and don't allow more than 4 effects
|
||||
Widgets::SpellEffectList old = effects;
|
||||
effects.clear();
|
||||
int i=0;
|
||||
for (Widgets::SpellEffectList::iterator it = old.begin();
|
||||
it != old.end(); ++it)
|
||||
{
|
||||
bool found = false;
|
||||
for (Widgets::SpellEffectList::iterator it2 = effects.begin();
|
||||
it2 != effects.end(); ++it2)
|
||||
{
|
||||
// MW considers all "foritfy attribute" effects as the same effect. See the
|
||||
// "Can't create multi-state boost potions" discussion on http://www.uesp.net/wiki/Morrowind_talk:Alchemy
|
||||
// thus, we are only checking effectID here and not attribute or skill
|
||||
if (it2->mEffectID == it->mEffectID)
|
||||
found = true;
|
||||
}
|
||||
if (!found && i<4)
|
||||
{
|
||||
++i;
|
||||
effects.push_back(*it);
|
||||
}
|
||||
}
|
||||
mEffects = effects;
|
||||
|
||||
while (mEffectsBox->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0));
|
||||
|
||||
MyGUI::IntCoord coord(0, 0, mEffectsBox->getWidth(), 24);
|
||||
Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget<Widgets::MWEffectList>
|
||||
("MW_StatName", coord, Align::Left | Align::Top);
|
||||
effectsWidget->setWindowManager(&mWindowManager);
|
||||
effectsWidget->setEffectList(effects);
|
||||
|
||||
std::vector<MyGUI::WidgetPtr> effectItems;
|
||||
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
|
||||
effectsWidget->setCoord(coord);
|
||||
}
|
||||
|
||||
void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient)
|
||||
{
|
||||
ingredient->clearUserStrings();
|
||||
static_cast<MyGUI::ImageBox*>(ingredient)->setImageTexture("");
|
||||
if (ingredient->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
#ifndef MWGUI_ALCHEMY_H
|
||||
#define MWGUI_ALCHEMY_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
#include "container.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class AlchemyWindow : public WindowBase, public ContainerBase
|
||||
{
|
||||
public:
|
||||
AlchemyWindow(WindowManager& parWindowManager);
|
||||
|
||||
virtual void open();
|
||||
|
||||
protected:
|
||||
MyGUI::Button* mCreateButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
|
||||
MyGUI::ImageBox* mIngredient1;
|
||||
MyGUI::ImageBox* mIngredient2;
|
||||
MyGUI::ImageBox* mIngredient3;
|
||||
MyGUI::ImageBox* mIngredient4;
|
||||
|
||||
MyGUI::ImageBox* mApparatus1;
|
||||
MyGUI::ImageBox* mApparatus2;
|
||||
MyGUI::ImageBox* mApparatus3;
|
||||
MyGUI::ImageBox* mApparatus4;
|
||||
|
||||
MyGUI::Widget* mEffectsBox;
|
||||
|
||||
MyGUI::EditBox* mNameEdit;
|
||||
|
||||
Widgets::SpellEffectList mEffects; // effects of created potion
|
||||
|
||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||
void onCreateButtonClicked(MyGUI::Widget* _sender);
|
||||
void onIngredientSelected(MyGUI::Widget* _sender);
|
||||
|
||||
virtual void onSelectedItemImpl(MWWorld::Ptr item);
|
||||
virtual std::vector<MWWorld::Ptr> itemsToIgnore();
|
||||
|
||||
void removeIngredient(MyGUI::Widget* ingredient);
|
||||
|
||||
virtual void onReferenceUnavailable() { ; }
|
||||
|
||||
void update();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,149 @@
|
||||
#include "bookwindow.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwinput/inputmanager.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
#include "formatting.hpp"
|
||||
#include "window_manager.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
BookWindow::BookWindow (WindowManager& parWindowManager) :
|
||||
WindowBase("openmw_book_layout.xml", parWindowManager)
|
||||
{
|
||||
getWidget(mCloseButton, "CloseButton");
|
||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked);
|
||||
|
||||
getWidget(mTakeButton, "TakeButton");
|
||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onTakeButtonClicked);
|
||||
|
||||
getWidget(mNextPageButton, "NextPageBTN");
|
||||
mNextPageButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onNextPageButtonClicked);
|
||||
|
||||
getWidget(mPrevPageButton, "PrevPageBTN");
|
||||
mPrevPageButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onPrevPageButtonClicked);
|
||||
|
||||
getWidget(mLeftPageNumber, "LeftPageNumber");
|
||||
getWidget(mRightPageNumber, "RightPageNumber");
|
||||
|
||||
getWidget(mLeftPage, "LeftPage");
|
||||
getWidget(mRightPage, "RightPage");
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
void BookWindow::clearPages()
|
||||
{
|
||||
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
|
||||
it!=mPages.end(); ++it)
|
||||
{
|
||||
MyGUI::Gui::getInstance().destroyWidget(*it);
|
||||
}
|
||||
mPages.clear();
|
||||
}
|
||||
|
||||
void BookWindow::open (MWWorld::Ptr book)
|
||||
{
|
||||
mBook = book;
|
||||
|
||||
clearPages();
|
||||
mCurrentPage = 0;
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
|
||||
|
||||
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||
mBook.get<ESM::Book>();
|
||||
|
||||
BookTextParser parser;
|
||||
std::vector<std::string> results = parser.split(ref->base->text, mLeftPage->getSize().width, mLeftPage->getSize().height);
|
||||
|
||||
int i=0;
|
||||
for (std::vector<std::string>::iterator it=results.begin();
|
||||
it!=results.end(); ++it)
|
||||
{
|
||||
MyGUI::Widget* parent;
|
||||
if (i%2 == 0)
|
||||
parent = mLeftPage;
|
||||
else
|
||||
parent = mRightPage;
|
||||
|
||||
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
|
||||
parser.parse(*it, pageWidget, mLeftPage->getSize().width);
|
||||
mPages.push_back(pageWidget);
|
||||
++i;
|
||||
}
|
||||
|
||||
updatePages();
|
||||
|
||||
setTakeButtonShow(true);
|
||||
}
|
||||
|
||||
void BookWindow::setTakeButtonShow(bool show)
|
||||
{
|
||||
mTakeButton->setVisible(show);
|
||||
}
|
||||
|
||||
void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
|
||||
{
|
||||
// no 3d sounds because the object could be in a container.
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
|
||||
|
||||
mWindowManager.popGuiMode();
|
||||
}
|
||||
|
||||
void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack);
|
||||
|
||||
MWWorld::ActionTake take(mBook);
|
||||
take.execute();
|
||||
|
||||
mWindowManager.popGuiMode();
|
||||
}
|
||||
|
||||
void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender)
|
||||
{
|
||||
if ((mCurrentPage+1)*2 < mPages.size())
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book page2", 1.0, 1.0);
|
||||
|
||||
++mCurrentPage;
|
||||
|
||||
updatePages();
|
||||
}
|
||||
}
|
||||
|
||||
void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* _sender)
|
||||
{
|
||||
if (mCurrentPage > 0)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book page", 1.0, 1.0);
|
||||
|
||||
--mCurrentPage;
|
||||
|
||||
updatePages();
|
||||
}
|
||||
}
|
||||
|
||||
void BookWindow::updatePages()
|
||||
{
|
||||
mLeftPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 1) );
|
||||
mRightPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 2) );
|
||||
|
||||
unsigned int i=0;
|
||||
for (std::vector<MyGUI::Widget*>::iterator it = mPages.begin();
|
||||
it != mPages.end(); ++it)
|
||||
{
|
||||
if (mCurrentPage*2 == i || mCurrentPage*2+1 == i)
|
||||
(*it)->setVisible(true);
|
||||
else
|
||||
{
|
||||
(*it)->setVisible(false);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
#ifndef MWGUI_BOOKWINDOW_H
|
||||
#define MWGUI_BOOKWINDOW_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class BookWindow : public WindowBase
|
||||
{
|
||||
public:
|
||||
BookWindow(WindowManager& parWindowManager);
|
||||
|
||||
void open(MWWorld::Ptr book);
|
||||
void setTakeButtonShow(bool show);
|
||||
|
||||
protected:
|
||||
void onNextPageButtonClicked (MyGUI::Widget* _sender);
|
||||
void onPrevPageButtonClicked (MyGUI::Widget* _sender);
|
||||
void onCloseButtonClicked (MyGUI::Widget* _sender);
|
||||
void onTakeButtonClicked (MyGUI::Widget* _sender);
|
||||
|
||||
void updatePages();
|
||||
void clearPages();
|
||||
|
||||
private:
|
||||
MyGUI::Button* mCloseButton;
|
||||
MyGUI::Button* mTakeButton;
|
||||
MyGUI::Button* mNextPageButton;
|
||||
MyGUI::Button* mPrevPageButton;
|
||||
MyGUI::TextBox* mLeftPageNumber;
|
||||
MyGUI::TextBox* mRightPageNumber;
|
||||
MyGUI::Widget* mLeftPage;
|
||||
MyGUI::Widget* mRightPage;
|
||||
|
||||
unsigned int mCurrentPage; // 0 is first page
|
||||
std::vector<MyGUI::Widget*> mPages;
|
||||
|
||||
MWWorld::Ptr mBook;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,70 @@
|
||||
#include "confirmationdialog.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
ConfirmationDialog::ConfirmationDialog(WindowManager& parWindowManager) :
|
||||
WindowBase("openmw_confirmation_dialog_layout.xml", parWindowManager)
|
||||
{
|
||||
getWidget(mMessage, "Message");
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onCancelButtonClicked);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked);
|
||||
}
|
||||
|
||||
void ConfirmationDialog::open(const std::string& message)
|
||||
{
|
||||
setVisible(true);
|
||||
|
||||
mMessage->setCaptionWithReplacing(message);
|
||||
|
||||
int height = mMessage->getTextSize().height + 72;
|
||||
|
||||
mMainWidget->setSize(mMainWidget->getWidth(), height);
|
||||
|
||||
mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height+24);
|
||||
|
||||
center();
|
||||
|
||||
// make other gui elements inaccessible while this dialog is open
|
||||
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
|
||||
|
||||
int okButtonWidth = mOkButton->getTextSize().width + 24;
|
||||
mOkButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth,
|
||||
mOkButton->getTop(),
|
||||
okButtonWidth,
|
||||
mOkButton->getHeight());
|
||||
|
||||
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
|
||||
mCancelButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth - cancelButtonWidth - 8,
|
||||
mCancelButton->getTop(),
|
||||
cancelButtonWidth,
|
||||
mCancelButton->getHeight());
|
||||
}
|
||||
|
||||
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
eventCancelClicked();
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
eventOkClicked();
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
void ConfirmationDialog::close()
|
||||
{
|
||||
setVisible(false);
|
||||
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
#ifndef MWGUI_CONFIRMATIONDIALOG_H
|
||||
#define MWGUI_CONFIRMATIONDIALOG_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class ConfirmationDialog : public WindowBase
|
||||
{
|
||||
public:
|
||||
ConfirmationDialog(WindowManager& parWindowManager);
|
||||
void open(const std::string& message);
|
||||
|
||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||
|
||||
/** Event : Ok button was clicked.\n
|
||||
signature : void method()\n
|
||||
*/
|
||||
EventHandle_Void eventOkClicked;
|
||||
EventHandle_Void eventCancelClicked;
|
||||
|
||||
private:
|
||||
MyGUI::EditBox* mMessage;
|
||||
MyGUI::Button* mOkButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
|
||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||
void onOkButtonClicked(MyGUI::Widget* _sender);
|
||||
|
||||
void close();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,681 @@
|
||||
#include "container.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwclass/container.hpp"
|
||||
#include "../mwinput/inputmanager.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
#include "window_manager.hpp"
|
||||
#include "widgets.hpp"
|
||||
#include "countdialog.hpp"
|
||||
#include "tradewindow.hpp"
|
||||
#include "inventorywindow.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
using namespace Widgets;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
bool compareType(std::string type1, std::string type2)
|
||||
{
|
||||
// this defines the sorting order of types. types that are first in the vector, appear before other types.
|
||||
std::vector<std::string> mapping;
|
||||
mapping.push_back( typeid(ESM::Weapon).name() );
|
||||
mapping.push_back( typeid(ESM::Armor).name() );
|
||||
mapping.push_back( typeid(ESM::Clothing).name() );
|
||||
mapping.push_back( typeid(ESM::Potion).name() );
|
||||
mapping.push_back( typeid(ESM::Ingredient).name() );
|
||||
mapping.push_back( typeid(ESM::Apparatus).name() );
|
||||
mapping.push_back( typeid(ESM::Book).name() );
|
||||
mapping.push_back( typeid(ESM::Light).name() );
|
||||
mapping.push_back( typeid(ESM::Miscellaneous).name() );
|
||||
mapping.push_back( typeid(ESM::Tool).name() );
|
||||
mapping.push_back( typeid(ESM::Repair).name() );
|
||||
mapping.push_back( typeid(ESM::Probe).name() );
|
||||
|
||||
assert( std::find(mapping.begin(), mapping.end(), type1) != mapping.end() );
|
||||
assert( std::find(mapping.begin(), mapping.end(), type2) != mapping.end() );
|
||||
|
||||
return std::find(mapping.begin(), mapping.end(), type1) < std::find(mapping.begin(), mapping.end(), type2);
|
||||
}
|
||||
|
||||
bool sortItems(MWWorld::Ptr left, MWWorld::Ptr right)
|
||||
{
|
||||
if (left.getTypeName() == right.getTypeName())
|
||||
{
|
||||
int cmp = MWWorld::Class::get(left).getName(left).compare(
|
||||
MWWorld::Class::get(right).getName(right));
|
||||
return cmp < 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return compareType(left.getTypeName(), right.getTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) :
|
||||
mDragAndDrop(dragAndDrop),
|
||||
mFilter(ContainerBase::Filter_All)
|
||||
{
|
||||
}
|
||||
|
||||
void ContainerBase::setWidgets(Widget* containerWidget, ScrollView* itemView)
|
||||
{
|
||||
mContainerWidget = containerWidget;
|
||||
mItemView = itemView;
|
||||
|
||||
mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked);
|
||||
mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel);
|
||||
}
|
||||
|
||||
ContainerBase::~ContainerBase()
|
||||
{
|
||||
}
|
||||
|
||||
void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
|
||||
{
|
||||
mSelectedItem = _sender;
|
||||
|
||||
if (mDragAndDrop && !isTrading())
|
||||
{
|
||||
if(!mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
|
||||
int count = object.getRefData().getCount();
|
||||
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
|
||||
{
|
||||
startDragItem(_sender, count);
|
||||
}
|
||||
else if (MyGUI::InputManager::getInstance().isControlPressed())
|
||||
{
|
||||
startDragItem(_sender, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string message = MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTake")->str;
|
||||
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
||||
dialog->open(MWWorld::Class::get(object).getName(object), message, count);
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::startDragItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
onContainerClicked(mContainerWidget);
|
||||
}
|
||||
else if (isTrading())
|
||||
{
|
||||
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
|
||||
int count = object.getRefData().getCount();
|
||||
|
||||
if (isInventory())
|
||||
{
|
||||
// the player is trying to sell an item, check if the merchant accepts it
|
||||
// also, don't allow selling gold (let's be better than Morrowind at this, can we?)
|
||||
if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)
|
||||
|| MWWorld::Class::get(object).getName(object) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str)
|
||||
{
|
||||
// user notification "i don't buy this item"
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog4")->str, std::vector<std::string>());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool buying = isTradeWindow(); // buying or selling?
|
||||
std::string message = buying ? MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sQuanityMenuMessage02")->str
|
||||
: MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sQuanityMenuMessage01")->str;
|
||||
|
||||
if (std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end())
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
|
||||
{
|
||||
sellAlreadyBoughtItem(NULL, count);
|
||||
}
|
||||
else if (MyGUI::InputManager::getInstance().isControlPressed())
|
||||
{
|
||||
sellAlreadyBoughtItem(NULL, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
||||
dialog->open(MWWorld::Class::get(object).getName(object), message, count);
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellAlreadyBoughtItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
|
||||
{
|
||||
sellItem(NULL, count);
|
||||
}
|
||||
else if (MyGUI::InputManager::getInstance().isControlPressed())
|
||||
{
|
||||
sellItem(NULL, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
||||
dialog->open(MWWorld::Class::get(object).getName(object), message, count);
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
onSelectedItemImpl(*_sender->getUserData<MWWorld::Ptr>());
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count)
|
||||
{
|
||||
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
|
||||
|
||||
if (isInventory())
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->addItem(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems();
|
||||
}
|
||||
else
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addItem(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
|
||||
}
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
||||
drawItems();
|
||||
}
|
||||
|
||||
void ContainerBase::sellItem(MyGUI::Widget* _sender, int count)
|
||||
{
|
||||
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
|
||||
|
||||
if (isInventory())
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems();
|
||||
}
|
||||
else
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count);
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
|
||||
}
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
||||
drawItems();
|
||||
}
|
||||
|
||||
void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count)
|
||||
{
|
||||
mDragAndDrop->mIsOnDragAndDrop = true;
|
||||
mSelectedItem->detachFromWidget();
|
||||
mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget);
|
||||
|
||||
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
|
||||
_unequipItem(object);
|
||||
|
||||
mDragAndDrop->mDraggedCount = count;
|
||||
|
||||
mDragAndDrop->mDraggedFrom = this;
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
||||
mDragAndDrop->mDraggedWidget = mSelectedItem;
|
||||
static_cast<MyGUI::ImageBox*>(mSelectedItem)->setImageTexture(""); // remove the background texture (not visible during drag)
|
||||
static_cast<MyGUI::TextBox*>(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption(
|
||||
getCountString(mDragAndDrop->mDraggedCount));
|
||||
|
||||
drawItems();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setDragDrop(true);
|
||||
}
|
||||
|
||||
void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (mDragAndDrop == NULL) return;
|
||||
|
||||
if(mDragAndDrop->mIsOnDragAndDrop) //drop item here
|
||||
{
|
||||
MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
|
||||
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
if (mDragAndDrop->mDraggedFrom != this)
|
||||
{
|
||||
assert(object.getContainerStore() && "Item is not in a container!");
|
||||
|
||||
// check the container's Organic flag (if this is a container). container with Organic flag doesn't allow putting items inside
|
||||
if (mPtr.getTypeName() == typeid(ESM::Container).name())
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mPtr.get<ESM::Container>();
|
||||
if (ref->base->flags & ESM::Container::Organic)
|
||||
{
|
||||
// user notification
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sContentsMessage2")->str, std::vector<std::string>());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int origCount = object.getRefData().getCount();
|
||||
|
||||
// check that we don't exceed the allowed weight (only for containers, not for inventory)
|
||||
if (!isInventory())
|
||||
{
|
||||
float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr);
|
||||
|
||||
// try adding the item, and if weight is exceeded, just remove it again.
|
||||
object.getRefData().setCount(mDragAndDrop->mDraggedCount);
|
||||
MWWorld::ContainerStoreIterator it = containerStore.add(object);
|
||||
|
||||
float curWeight = MWWorld::Class::get(mPtr).getEncumbrance(mPtr);
|
||||
if (curWeight > capacity)
|
||||
{
|
||||
it->getRefData().setCount(0);
|
||||
object.getRefData().setCount(origCount);
|
||||
// user notification
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sContentsMessage3")->str, std::vector<std::string>());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
|
||||
}
|
||||
std::cout << "container weight " << curWeight << "/" << capacity << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
object.getRefData().setCount (mDragAndDrop->mDraggedCount);
|
||||
containerStore.add(object);
|
||||
object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount);
|
||||
}
|
||||
}
|
||||
|
||||
mDragAndDrop->mIsOnDragAndDrop = false;
|
||||
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
|
||||
drawItems();
|
||||
mDragAndDrop->mDraggedFrom->drawItems();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel)
|
||||
{
|
||||
if (mItemView->getViewOffset().left + _rel*0.3 > 0)
|
||||
mItemView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0));
|
||||
}
|
||||
|
||||
void ContainerBase::setFilter(ContainerBase::Filter filter)
|
||||
{
|
||||
mFilter = filter;
|
||||
drawItems();
|
||||
}
|
||||
|
||||
void ContainerBase::openContainer(MWWorld::Ptr container)
|
||||
{
|
||||
mPtr = container;
|
||||
}
|
||||
|
||||
void ContainerBase::drawItems()
|
||||
{
|
||||
while (mContainerWidget->getChildCount())
|
||||
{
|
||||
MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0));
|
||||
}
|
||||
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int maxHeight = mItemView->getSize().height - 58;
|
||||
|
||||
bool onlyMagic = false;
|
||||
int categories;
|
||||
if (mFilter == Filter_All)
|
||||
categories = MWWorld::ContainerStore::Type_All;
|
||||
else if (mFilter == Filter_Weapon)
|
||||
categories = MWWorld::ContainerStore::Type_Weapon;
|
||||
else if (mFilter == Filter_Apparel)
|
||||
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor;
|
||||
else if (mFilter == Filter_Magic)
|
||||
{
|
||||
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor
|
||||
+ MWWorld::ContainerStore::Type_Weapon + MWWorld::ContainerStore::Type_Book
|
||||
+ MWWorld::ContainerStore::Type_Potion;
|
||||
onlyMagic = true;
|
||||
}
|
||||
else if (mFilter == Filter_Misc)
|
||||
{
|
||||
categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book
|
||||
+ MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair
|
||||
+ MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light
|
||||
+ MWWorld::ContainerStore::Type_Apparatus + MWWorld::ContainerStore::Type_Probe;
|
||||
}
|
||||
else if (mFilter == Filter_Ingredients)
|
||||
categories = MWWorld::ContainerStore::Type_Ingredient;
|
||||
|
||||
/// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
|
||||
|
||||
std::vector< std::pair<MWWorld::Ptr, ItemState> > items;
|
||||
|
||||
std::vector<MWWorld::Ptr> equippedItems = getEquippedItems();
|
||||
|
||||
// add bought items (always at the beginning)
|
||||
std::vector<MWWorld::Ptr> boughtItems;
|
||||
for (MWWorld::ContainerStoreIterator it (mBoughtItems.begin()); it!=mBoughtItems.end(); ++it)
|
||||
{
|
||||
boughtItems.push_back(*it);
|
||||
}
|
||||
std::sort(boughtItems.begin(), boughtItems.end(), sortItems);
|
||||
|
||||
for (std::vector<MWWorld::Ptr>::iterator it=boughtItems.begin();
|
||||
it != boughtItems.end(); ++it)
|
||||
{
|
||||
items.push_back( std::make_pair(*it, ItemState_Barter) );
|
||||
}
|
||||
|
||||
// filter out the equipped items of categories we don't want
|
||||
std::vector<MWWorld::Ptr> unwantedItems = equippedItems;
|
||||
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
|
||||
{
|
||||
std::vector<MWWorld::Ptr>::iterator found = std::find(unwantedItems.begin(), unwantedItems.end(), *iter);
|
||||
if (found != unwantedItems.end())
|
||||
{
|
||||
unwantedItems.erase(found);
|
||||
}
|
||||
}
|
||||
// now erase everything that's still in unwantedItems.
|
||||
for (std::vector<MWWorld::Ptr>::iterator it=unwantedItems.begin();
|
||||
it != unwantedItems.end(); ++it)
|
||||
{
|
||||
std::vector<MWWorld::Ptr>::iterator found = std::find(equippedItems.begin(), equippedItems.end(), *it);
|
||||
assert(found != equippedItems.end());
|
||||
equippedItems.erase(found);
|
||||
}
|
||||
// and add the items that are left (= have the correct category)
|
||||
if (!ignoreEquippedItems())
|
||||
{
|
||||
for (std::vector<MWWorld::Ptr>::const_iterator it=equippedItems.begin();
|
||||
it != equippedItems.end(); ++it)
|
||||
{
|
||||
items.push_back( std::make_pair(*it, ItemState_Equipped) );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MWWorld::Ptr> ignoreItems = itemsToIgnore();
|
||||
|
||||
// now add the regular items
|
||||
std::vector<MWWorld::Ptr> regularItems;
|
||||
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
|
||||
{
|
||||
if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end()
|
||||
&& std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()
|
||||
&& std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end())
|
||||
regularItems.push_back(*iter);
|
||||
}
|
||||
|
||||
// sort them and add
|
||||
std::sort(regularItems.begin(), regularItems.end(), sortItems);
|
||||
for (std::vector<MWWorld::Ptr>::const_iterator it=regularItems.begin(); it!=regularItems.end(); ++it)
|
||||
{
|
||||
items.push_back( std::make_pair(*it, ItemState_Normal) );
|
||||
}
|
||||
|
||||
for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin();
|
||||
it != items.end(); ++it)
|
||||
{
|
||||
const MWWorld::Ptr* iter = &((*it).first);
|
||||
|
||||
int displayCount = iter->getRefData().getCount();
|
||||
if (mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>())
|
||||
{
|
||||
displayCount -= mDragAndDrop->mDraggedCount;
|
||||
}
|
||||
if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name()))
|
||||
{
|
||||
std::string path = std::string("icons\\");
|
||||
path += MWWorld::Class::get(*iter).getInventoryIcon(*iter);
|
||||
|
||||
// background widget (for the "equipped" frame and magic item background image)
|
||||
bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != "");
|
||||
MyGUI::ImageBox* backgroundWidget = mContainerWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default);
|
||||
backgroundWidget->setUserString("ToolTipType", "ItemPtr");
|
||||
backgroundWidget->setUserData(*iter);
|
||||
|
||||
std::string backgroundTex = "textures\\menu_icon";
|
||||
if (isMagic)
|
||||
backgroundTex += "_magic";
|
||||
if (it->second == ItemState_Normal)
|
||||
{
|
||||
if (!isMagic)
|
||||
backgroundTex = "";
|
||||
}
|
||||
else if (it->second == ItemState_Equipped)
|
||||
{
|
||||
backgroundTex += "_equip";
|
||||
}
|
||||
else if (it->second == ItemState_Barter)
|
||||
{
|
||||
backgroundTex += "_barter";
|
||||
}
|
||||
if (backgroundTex != "")
|
||||
backgroundTex += ".dds";
|
||||
|
||||
backgroundWidget->setImageTexture(backgroundTex);
|
||||
if (it->second == ItemState_Barter && !isMagic)
|
||||
backgroundWidget->setProperty("ImageCoord", "2 2 42 42");
|
||||
else
|
||||
backgroundWidget->setProperty("ImageCoord", "0 0 42 42");
|
||||
backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem);
|
||||
backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel);
|
||||
|
||||
// image
|
||||
ImageBox* image = backgroundWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
|
||||
int pos = path.rfind(".");
|
||||
path.erase(pos);
|
||||
path.append(".dds");
|
||||
image->setImageTexture(path);
|
||||
image->setNeedMouseFocus(false);
|
||||
|
||||
// text widget that shows item count
|
||||
MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
|
||||
text->setTextAlign(MyGUI::Align::Right);
|
||||
text->setNeedMouseFocus(false);
|
||||
text->setTextShadow(true);
|
||||
text->setTextShadowColour(MyGUI::Colour(0,0,0));
|
||||
text->setCaption(getCountString(displayCount));
|
||||
|
||||
y += 42;
|
||||
if (y > maxHeight)
|
||||
{
|
||||
x += 42;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height);
|
||||
mItemView->setCanvasSize(size);
|
||||
mContainerWidget->setSize(size);
|
||||
|
||||
notifyContentChanged();
|
||||
}
|
||||
|
||||
std::string ContainerBase::getCountString(const int count)
|
||||
{
|
||||
if (count == 1)
|
||||
return "";
|
||||
if (count > 9999)
|
||||
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
|
||||
else
|
||||
return boost::lexical_cast<std::string>(count);
|
||||
}
|
||||
|
||||
void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count)
|
||||
{
|
||||
int origCount = item.getRefData().getCount();
|
||||
item.getRefData().setCount(count);
|
||||
MWWorld::ContainerStoreIterator it = mBoughtItems.add(item);
|
||||
item.getRefData().setCount(origCount - count);
|
||||
}
|
||||
|
||||
void ContainerBase::addItem(MWWorld::Ptr item, int count)
|
||||
{
|
||||
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
int origCount = item.getRefData().getCount();
|
||||
|
||||
item.getRefData().setCount(count);
|
||||
MWWorld::ContainerStoreIterator it = containerStore.add(item);
|
||||
|
||||
item.getRefData().setCount(origCount - count);
|
||||
}
|
||||
|
||||
void ContainerBase::transferBoughtItems()
|
||||
{
|
||||
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
|
||||
{
|
||||
containerStore.add(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store)
|
||||
{
|
||||
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
|
||||
{
|
||||
store.add(*it);
|
||||
}
|
||||
}
|
||||
|
||||
MWWorld::ContainerStore& ContainerBase::getContainerStore()
|
||||
{
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
return store;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop)
|
||||
: ContainerBase(dragAndDrop)
|
||||
, WindowBase("openmw_container_window_layout.xml", parWindowManager)
|
||||
{
|
||||
getWidget(mTakeButton, "TakeButton");
|
||||
getWidget(mCloseButton, "CloseButton");
|
||||
|
||||
MyGUI::ScrollView* itemView;
|
||||
MyGUI::Widget* containerWidget;
|
||||
getWidget(containerWidget, "Items");
|
||||
getWidget(itemView, "ItemView");
|
||||
setWidgets(containerWidget, itemView);
|
||||
|
||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
|
||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
||||
|
||||
// adjust buttons size to fit text
|
||||
int closeButtonWidth = mCloseButton->getTextSize().width+24;
|
||||
int takeButtonWidth = mTakeButton->getTextSize().width+24;
|
||||
mCloseButton->setCoord(600-20-closeButtonWidth, mCloseButton->getCoord().top, closeButtonWidth, mCloseButton->getCoord().height);
|
||||
mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height);
|
||||
|
||||
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
|
||||
//int h = MyGUI::RenderManager::getInstance().getViewSize().height;
|
||||
|
||||
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize);
|
||||
|
||||
setCoord(w-600,0,600,300);
|
||||
}
|
||||
|
||||
ContainerWindow::~ContainerWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void ContainerWindow::onWindowResize(MyGUI::Window* window)
|
||||
{
|
||||
drawItems();
|
||||
}
|
||||
|
||||
void ContainerWindow::open(MWWorld::Ptr container)
|
||||
{
|
||||
openContainer(container);
|
||||
setTitle(MWWorld::Class::get(container).getName(container));
|
||||
drawItems();
|
||||
}
|
||||
|
||||
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
// transfer everything into the player's inventory
|
||||
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
|
||||
|
||||
int i=0;
|
||||
for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter)
|
||||
{
|
||||
playerStore.add(*iter);
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
// play the sound of the first object
|
||||
std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
containerStore.clear();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerWindow::onReferenceUnavailable()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
#ifndef MGUI_CONTAINER_H
|
||||
#define MGUI_CONTAINER_H
|
||||
|
||||
#include <components/esm_store/store.hpp>
|
||||
|
||||
#include "window_base.hpp"
|
||||
#include "referenceinterface.hpp"
|
||||
|
||||
#include "../mwclass/container.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Gui;
|
||||
class Widget;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class WindowManager;
|
||||
class ContainerWindow;
|
||||
class ContainerBase;
|
||||
}
|
||||
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class DragAndDrop
|
||||
{
|
||||
public:
|
||||
bool mIsOnDragAndDrop;
|
||||
MyGUI::Widget* mDraggedWidget;
|
||||
MyGUI::Widget* mDragAndDropWidget;
|
||||
ContainerBase* mDraggedFrom;
|
||||
int mDraggedCount;
|
||||
};
|
||||
|
||||
class ContainerBase : public ReferenceInterface
|
||||
{
|
||||
public:
|
||||
ContainerBase(DragAndDrop* dragAndDrop);
|
||||
virtual ~ContainerBase();
|
||||
|
||||
enum Filter
|
||||
{
|
||||
Filter_All = 0x01,
|
||||
Filter_Weapon = 0x02,
|
||||
Filter_Apparel = 0x03,
|
||||
Filter_Magic = 0x04,
|
||||
Filter_Misc = 0x05,
|
||||
|
||||
Filter_Ingredients = 0x06
|
||||
};
|
||||
|
||||
enum ItemState
|
||||
{
|
||||
ItemState_Normal = 0x01,
|
||||
ItemState_Equipped = 0x02,
|
||||
ItemState_Barter = 0x03
|
||||
};
|
||||
|
||||
void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once
|
||||
|
||||
void addBarteredItem(MWWorld::Ptr item, int count);
|
||||
void addItem(MWWorld::Ptr item, int count);
|
||||
|
||||
void transferBoughtItems(); ///< transfer bought items into the inventory
|
||||
void returnBoughtItems(MWWorld::ContainerStore& store); ///< return bought items into the specified ContainerStore
|
||||
|
||||
MWWorld::ContainerStore& getContainerStore();
|
||||
MWWorld::ContainerStore& getBoughtItems() { return mBoughtItems; }
|
||||
|
||||
void openContainer(MWWorld::Ptr container);
|
||||
void setFilter(Filter filter); ///< set category filter
|
||||
void drawItems();
|
||||
|
||||
protected:
|
||||
MyGUI::ScrollView* mItemView;
|
||||
MyGUI::Widget* mContainerWidget;
|
||||
|
||||
MyGUI::Widget* mSelectedItem;
|
||||
|
||||
DragAndDrop* mDragAndDrop;
|
||||
|
||||
Filter mFilter;
|
||||
|
||||
// bought items are put in a separate ContainerStore so that they don't stack with other (not bought) items.
|
||||
MWWorld::ContainerStore mBoughtItems;
|
||||
|
||||
void onSelectedItem(MyGUI::Widget* _sender);
|
||||
void onContainerClicked(MyGUI::Widget* _sender);
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
|
||||
/// start dragging an item (drag & drop)
|
||||
void startDragItem(MyGUI::Widget* _sender, int count);
|
||||
|
||||
/// sell an item from this container
|
||||
void sellItem(MyGUI::Widget* _sender, int count);
|
||||
|
||||
/// sell an item from this container, that was previously just bought
|
||||
void sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count);
|
||||
|
||||
std::string getCountString(const int count);
|
||||
|
||||
virtual bool isTradeWindow() { return false; }
|
||||
virtual bool isInventory() { return false; }
|
||||
virtual std::vector<MWWorld::Ptr> getEquippedItems() { return std::vector<MWWorld::Ptr>(); }
|
||||
virtual void _unequipItem(MWWorld::Ptr item) { ; }
|
||||
|
||||
virtual bool isTrading() { return false; }
|
||||
|
||||
virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; }
|
||||
|
||||
virtual bool ignoreEquippedItems() { return false; }
|
||||
virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); }
|
||||
|
||||
virtual void notifyContentChanged() { ; }
|
||||
};
|
||||
|
||||
class ContainerWindow : public ContainerBase, public WindowBase
|
||||
{
|
||||
public:
|
||||
ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop);
|
||||
|
||||
virtual ~ContainerWindow();
|
||||
|
||||
void open(MWWorld::Ptr container);
|
||||
|
||||
protected:
|
||||
MyGUI::Button* mTakeButton;
|
||||
MyGUI::Button* mCloseButton;
|
||||
|
||||
void onWindowResize(MyGUI::Window* window);
|
||||
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
||||
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
||||
|
||||
virtual void onReferenceUnavailable();
|
||||
};
|
||||
}
|
||||
#endif // CONTAINER_H
|
@ -0,0 +1,108 @@
|
||||
#include "countdialog.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
CountDialog::CountDialog(WindowManager& parWindowManager) :
|
||||
WindowBase("openmw_count_window_layout.xml", parWindowManager)
|
||||
{
|
||||
getWidget(mSlider, "CountSlider");
|
||||
getWidget(mItemEdit, "ItemEdit");
|
||||
getWidget(mItemText, "ItemText");
|
||||
getWidget(mLabelText, "LabelText");
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked);
|
||||
mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange);
|
||||
mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved);
|
||||
}
|
||||
|
||||
void CountDialog::open(const std::string& item, const std::string& message, const int maxCount)
|
||||
{
|
||||
setVisible(true);
|
||||
|
||||
mLabelText->setCaption(message);
|
||||
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
||||
mSlider->setScrollRange(maxCount);
|
||||
mItemText->setCaption(item);
|
||||
|
||||
int width = std::max(mItemText->getTextSize().width + 128, 320);
|
||||
setCoord(viewSize.width/2 - width/2,
|
||||
viewSize.height/2 - mMainWidget->getHeight()/2,
|
||||
width,
|
||||
mMainWidget->getHeight());
|
||||
|
||||
// make other gui elements inaccessible while this dialog is open
|
||||
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
|
||||
|
||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(mItemEdit);
|
||||
|
||||
mSlider->setScrollPosition(maxCount-1);
|
||||
mItemEdit->setCaption(boost::lexical_cast<std::string>(maxCount));
|
||||
|
||||
int okButtonWidth = mOkButton->getTextSize().width + 24;
|
||||
mOkButton->setCoord(width - 30 - okButtonWidth,
|
||||
mOkButton->getTop(),
|
||||
okButtonWidth,
|
||||
mOkButton->getHeight());
|
||||
|
||||
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
|
||||
mCancelButton->setCoord(width - 30 - okButtonWidth - cancelButtonWidth - 8,
|
||||
mCancelButton->getTop(),
|
||||
cancelButtonWidth,
|
||||
mCancelButton->getHeight());
|
||||
}
|
||||
|
||||
void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
eventOkClicked(NULL, mSlider->getScrollPosition()+1);
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
void CountDialog::onEditTextChange(MyGUI::EditBox* _sender)
|
||||
{
|
||||
if (_sender->getCaption() == "")
|
||||
return;
|
||||
|
||||
unsigned int count;
|
||||
try
|
||||
{
|
||||
count = boost::lexical_cast<unsigned int>(_sender->getCaption());
|
||||
}
|
||||
catch (std::bad_cast&)
|
||||
{
|
||||
count = 1;
|
||||
}
|
||||
if (count > mSlider->getScrollRange())
|
||||
{
|
||||
count = mSlider->getScrollRange();
|
||||
}
|
||||
mSlider->setScrollPosition(count-1);
|
||||
onSliderMoved(mSlider, count-1);
|
||||
}
|
||||
|
||||
void CountDialog::onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position)
|
||||
{
|
||||
mItemEdit->setCaption(boost::lexical_cast<std::string>(_position+1));
|
||||
}
|
||||
|
||||
void CountDialog::close()
|
||||
{
|
||||
setVisible(false);
|
||||
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
#ifndef MWGUI_COUNTDIALOG_H
|
||||
#define MWGUI_COUNTDIALOG_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class CountDialog : public WindowBase
|
||||
{
|
||||
public:
|
||||
CountDialog(WindowManager& parWindowManager);
|
||||
void open(const std::string& item, const std::string& message, const int maxCount);
|
||||
|
||||
typedef MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, int> EventHandle_WidgetInt;
|
||||
|
||||
/** Event : Ok button was clicked.\n
|
||||
signature : void method(MyGUI::Widget* _sender, int _count)\n
|
||||
*/
|
||||
EventHandle_WidgetInt eventOkClicked;
|
||||
|
||||
private:
|
||||
MyGUI::ScrollBar* mSlider;
|
||||
MyGUI::EditBox* mItemEdit;
|
||||
MyGUI::TextBox* mItemText;
|
||||
MyGUI::TextBox* mLabelText;
|
||||
MyGUI::Button* mOkButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
|
||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||
void onOkButtonClicked(MyGUI::Widget* _sender);
|
||||
void onEditTextChange(MyGUI::EditBox* _sender);
|
||||
void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position);
|
||||
|
||||
void close();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,331 @@
|
||||
#include "formatting.hpp"
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
namespace
|
||||
{
|
||||
int convertFromHex(std::string hex)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
int a = 0;
|
||||
int b = hex.length() - 1;
|
||||
for (; b >= 0; a++, b--)
|
||||
{
|
||||
if (hex[b] >= '0' && hex[b] <= '9')
|
||||
{
|
||||
value += (hex[b] - '0') * (1 << (a * 4));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (hex[b])
|
||||
{
|
||||
case 'A':
|
||||
case 'a':
|
||||
value += 10 * (1 << (a * 4));
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
case 'b':
|
||||
value += 11 * (1 << (a * 4));
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
case 'c':
|
||||
value += 12 * (1 << (a * 4));
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
case 'd':
|
||||
value += 13 * (1 << (a * 4));
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
case 'e':
|
||||
value += 14 * (1 << (a * 4));
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
case 'f':
|
||||
value += 15 * (1 << (a * 4));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("invalid character in hex number");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> BookTextParser::split(std::string text, const int width, const int height)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
boost::algorithm::replace_all(text, "<BR>", "\n");
|
||||
boost::algorithm::replace_all(text, "<P>", "\n\n");
|
||||
|
||||
const int spacing = 48;
|
||||
|
||||
while (text.size() > 0)
|
||||
{
|
||||
// read in characters until we have exceeded the size, or run out of text
|
||||
int currentWidth = 0;
|
||||
int currentHeight = 0;
|
||||
std::string currentText;
|
||||
std::string currentWord;
|
||||
|
||||
unsigned int i=0;
|
||||
while (currentHeight <= height-spacing && i<text.size())
|
||||
{
|
||||
if (text[i] == '<')
|
||||
{
|
||||
if (text.find('>', i) == std::string::npos)
|
||||
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
|
||||
|
||||
if (text.size() > i+4 && text.substr(i, 4) == "<IMG")
|
||||
{
|
||||
int h = mHeight;
|
||||
parseImage(text.substr(i, text.find('>', i)-i), false);
|
||||
currentHeight += (mHeight-h);
|
||||
currentWidth = 0;
|
||||
}
|
||||
else if (text.size() > i+5 && text.substr(i, 5) == "<FONT")
|
||||
{
|
||||
parseFont(text.substr(i, text.find('>', i)-i));
|
||||
currentHeight += 18; // keep this in sync with the font size
|
||||
currentWidth = 0;
|
||||
}
|
||||
else if (text.size() > i+4 && text.substr(i, 4) == "<DIV")
|
||||
{
|
||||
parseDiv(text.substr(i, text.find('>', i)-i));
|
||||
currentHeight += 18; // keep this in sync with the font size
|
||||
currentWidth = 0;
|
||||
}
|
||||
|
||||
currentText += text.substr(i, text.find('>', i)-i+1);
|
||||
i = text.find('>', i);
|
||||
}
|
||||
else if (text[i] == '\n')
|
||||
{
|
||||
currentHeight += 18; // keep this in sync with the font size
|
||||
currentWidth = 0;
|
||||
currentWord = "";
|
||||
currentText += text[i];
|
||||
}
|
||||
else if (text[i] == ' ')
|
||||
{
|
||||
currentWidth += 3; // keep this in sync with the font's SpaceWidth property
|
||||
currentWord = "";
|
||||
currentText += text[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
currentWidth +=
|
||||
MyGUI::FontManager::getInstance().getByName (mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont)
|
||||
->getGlyphInfo(static_cast<unsigned int>(text[i]))->width;
|
||||
currentWord += text[i];
|
||||
currentText += text[i];
|
||||
}
|
||||
|
||||
if (currentWidth > width)
|
||||
{
|
||||
currentHeight += 18; // keep this in sync with the font size
|
||||
currentWidth = 0;
|
||||
|
||||
// add size of the current word
|
||||
unsigned int j=0;
|
||||
while (j<currentWord.size())
|
||||
{
|
||||
currentWidth +=
|
||||
MyGUI::FontManager::getInstance().getByName (mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont)
|
||||
->getGlyphInfo(static_cast<unsigned int>(currentWord[j]))->width;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
if (currentHeight > height-spacing)
|
||||
{
|
||||
// remove the last word
|
||||
currentText.erase(currentText.size()-currentWord.size(), currentText.size());
|
||||
}
|
||||
|
||||
result.push_back(currentText);
|
||||
text.erase(0, currentText.size());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width)
|
||||
{
|
||||
mParent = parent;
|
||||
mWidth = width;
|
||||
mHeight = 0;
|
||||
|
||||
assert(mParent);
|
||||
while (mParent->getChildCount())
|
||||
{
|
||||
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
|
||||
}
|
||||
|
||||
boost::algorithm::replace_all(text, "<BR>", "\n");
|
||||
boost::algorithm::replace_all(text, "<P>", "\n\n");
|
||||
|
||||
// remove leading newlines
|
||||
//while (text[0] == '\n')
|
||||
// text.erase(0);
|
||||
|
||||
// remove trailing "
|
||||
if (text[text.size()-1] == '\"')
|
||||
text.erase(text.size()-1);
|
||||
|
||||
parseSubText(text);
|
||||
return MyGUI::IntSize(mWidth, mHeight);
|
||||
}
|
||||
|
||||
void BookTextParser::parseImage(std::string tag, bool createWidget)
|
||||
{
|
||||
int src_start = tag.find("SRC=")+5;
|
||||
std::string image = tag.substr(src_start, tag.find('"', src_start)-src_start);
|
||||
|
||||
// fix texture extension to .dds
|
||||
if (image.size() > 4)
|
||||
{
|
||||
image[image.size()-3] = 'd';
|
||||
image[image.size()-2] = 'd';
|
||||
image[image.size()-1] = 's';
|
||||
}
|
||||
|
||||
int width_start = tag.find("WIDTH=")+7;
|
||||
int width = boost::lexical_cast<int>(tag.substr(width_start, tag.find('"', width_start)-width_start));
|
||||
|
||||
int height_start = tag.find("HEIGHT=")+8;
|
||||
int height = boost::lexical_cast<int>(tag.substr(height_start, tag.find('"', height_start)-height_start));
|
||||
|
||||
if (createWidget)
|
||||
{
|
||||
MyGUI::ImageBox* box = mParent->createWidget<MyGUI::ImageBox> ("ImageBox",
|
||||
MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top,
|
||||
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
|
||||
box->setImageTexture("bookart\\" + image);
|
||||
box->setProperty("NeedMouse", "false");
|
||||
}
|
||||
|
||||
mWidth = std::max(mWidth, width);
|
||||
mHeight += height;
|
||||
}
|
||||
|
||||
void BookTextParser::parseDiv(std::string tag)
|
||||
{
|
||||
if (tag.find("ALIGN=") == std::string::npos)
|
||||
return;
|
||||
|
||||
int align_start = tag.find("ALIGN=")+7;
|
||||
std::string align = tag.substr(align_start, tag.find('"', align_start)-align_start);
|
||||
if (align == "CENTER")
|
||||
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
|
||||
else if (align == "LEFT")
|
||||
mTextStyle.mTextAlign = MyGUI::Align::Left;
|
||||
}
|
||||
|
||||
void BookTextParser::parseFont(std::string tag)
|
||||
{
|
||||
if (tag.find("COLOR=") != std::string::npos)
|
||||
{
|
||||
int color_start = tag.find("COLOR=")+7;
|
||||
std::string color = tag.substr(color_start, tag.find('"', color_start)-color_start);
|
||||
|
||||
mTextStyle.mColour = MyGUI::Colour(
|
||||
convertFromHex(color.substr(0, 2))/255.0,
|
||||
convertFromHex(color.substr(2, 2))/255.0,
|
||||
convertFromHex(color.substr(4, 2))/255.0);
|
||||
}
|
||||
if (tag.find("FACE=") != std::string::npos)
|
||||
{
|
||||
int face_start = tag.find("FACE=")+6;
|
||||
std::string face = tag.substr(face_start, tag.find('"', face_start)-face_start);
|
||||
|
||||
if (face != "Magic Cards")
|
||||
mTextStyle.mFont = face;
|
||||
}
|
||||
if (tag.find("SIZE=") != std::string::npos)
|
||||
{
|
||||
/// \todo
|
||||
}
|
||||
}
|
||||
|
||||
void BookTextParser::parseSubText(std::string text)
|
||||
{
|
||||
if (text[0] == '<')
|
||||
{
|
||||
if (text.find('>') == std::string::npos)
|
||||
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
|
||||
|
||||
if (text.size() > 4 && text.substr(0, 4) == "<IMG")
|
||||
parseImage(text.substr(0, text.find('>')));
|
||||
else if (text.size() > 5 && text.substr(0, 5) == "<FONT")
|
||||
parseFont(text.substr(0, text.find('>')));
|
||||
else if (text.size() > 4 && text.substr(0, 4) == "<DIV")
|
||||
parseDiv(text.substr(0, text.find('>')));
|
||||
|
||||
text.erase(0, text.find('>')+1);
|
||||
}
|
||||
|
||||
bool tagFound = false;
|
||||
std::string realText; // real text, without tags
|
||||
unsigned int i=0;
|
||||
for (; i<text.size(); ++i)
|
||||
{
|
||||
char c = text[i];
|
||||
if (c == '<')
|
||||
{
|
||||
if (text[i+1] == '/') // ignore closing tags
|
||||
{
|
||||
while (c != '>')
|
||||
{
|
||||
if (i >= text.size())
|
||||
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
|
||||
++i;
|
||||
c = text[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
realText += c;
|
||||
}
|
||||
|
||||
MyGUI::EditBox* box = mParent->createWidget<MyGUI::EditBox>("NormalText",
|
||||
MyGUI::IntCoord(0, mHeight, mWidth, 24), MyGUI::Align::Left | MyGUI::Align::Top,
|
||||
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
|
||||
box->setProperty("Static", "true");
|
||||
box->setProperty("MultiLine", "true");
|
||||
box->setProperty("WordWrap", "true");
|
||||
box->setProperty("NeedMouse", "false");
|
||||
box->setMaxTextLength(realText.size());
|
||||
box->setTextAlign(mTextStyle.mTextAlign);
|
||||
box->setTextColour(mTextStyle.mColour);
|
||||
box->setFontName(mTextStyle.mFont);
|
||||
box->setCaption(realText);
|
||||
box->setSize(box->getSize().width, box->getTextSize().height);
|
||||
mHeight += box->getTextSize().height;
|
||||
|
||||
if (tagFound)
|
||||
{
|
||||
parseSubText(text.substr(i, text.size()));
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
#ifndef MWGUI_FORMATTING_H
|
||||
#define MWGUI_FORMATTING_H
|
||||
|
||||
#include <MyGUI.h>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
struct TextStyle
|
||||
{
|
||||
TextStyle() :
|
||||
mColour(0,0,0)
|
||||
, mFont("Default")
|
||||
, mTextSize(16)
|
||||
, mTextAlign(MyGUI::Align::Left | MyGUI::Align::Top)
|
||||
{
|
||||
}
|
||||
|
||||
MyGUI::Colour mColour;
|
||||
std::string mFont;
|
||||
int mTextSize;
|
||||
MyGUI::Align mTextAlign;
|
||||
};
|
||||
|
||||
/// \brief utilities for parsing book/scroll text as mygui widgets
|
||||
class BookTextParser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Parse markup as MyGUI widgets
|
||||
* @param markup to parse
|
||||
* @param parent for the created widgets
|
||||
* @param maximum width
|
||||
* @return size of the created widgets
|
||||
*/
|
||||
MyGUI::IntSize parse(std::string text, MyGUI::Widget* parent, const int width);
|
||||
|
||||
/**
|
||||
* Split the specified text into pieces that fit in the area specified by width and height parameters
|
||||
*/
|
||||
std::vector<std::string> split(std::string text, const int width, const int height);
|
||||
|
||||
protected:
|
||||
void parseSubText(std::string text);
|
||||
|
||||
void parseImage(std::string tag, bool createWidget=true);
|
||||
void parseDiv(std::string tag);
|
||||
void parseFont(std::string tag);
|
||||
private:
|
||||
MyGUI::Widget* mParent;
|
||||
int mWidth; // maximum width
|
||||
int mHeight; // current height
|
||||
TextStyle mTextStyle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,516 @@
|
||||
#include "hud.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <MyGUI.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "inventorywindow.hpp"
|
||||
#include "window_manager.hpp"
|
||||
#include "container.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
|
||||
: Layout("openmw_hud_layout.xml")
|
||||
, health(NULL)
|
||||
, magicka(NULL)
|
||||
, stamina(NULL)
|
||||
, weapImage(NULL)
|
||||
, spellImage(NULL)
|
||||
, weapStatus(NULL)
|
||||
, spellStatus(NULL)
|
||||
, effectBox(NULL)
|
||||
, effect1(NULL)
|
||||
, minimap(NULL)
|
||||
, compass(NULL)
|
||||
, crosshair(NULL)
|
||||
, fpsbox(NULL)
|
||||
, fpscounter(NULL)
|
||||
, trianglecounter(NULL)
|
||||
, batchcounter(NULL)
|
||||
, hmsBaseLeft(0)
|
||||
, weapBoxBaseLeft(0)
|
||||
, spellBoxBaseLeft(0)
|
||||
, effectBoxBaseRight(0)
|
||||
, minimapBoxBaseRight(0)
|
||||
, mDragAndDrop(dragAndDrop)
|
||||
, mCellNameTimer(0.0f)
|
||||
, mCellNameBox(NULL)
|
||||
, mMapVisible(true)
|
||||
, mWeaponVisible(true)
|
||||
, mSpellVisible(true)
|
||||
, mWorldMouseOver(false)
|
||||
{
|
||||
setCoord(0,0, width, height);
|
||||
|
||||
// Energy bars
|
||||
getWidget(mHealthFrame, "HealthFrame");
|
||||
getWidget(health, "Health");
|
||||
getWidget(magicka, "Magicka");
|
||||
getWidget(stamina, "Stamina");
|
||||
|
||||
hmsBaseLeft = mHealthFrame->getLeft();
|
||||
|
||||
MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame;
|
||||
getWidget(healthFrame, "HealthFrame");
|
||||
getWidget(magickaFrame, "MagickaFrame");
|
||||
getWidget(fatigueFrame, "FatigueFrame");
|
||||
healthFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
|
||||
magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
|
||||
fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
|
||||
|
||||
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
||||
// Item and spell images and status bars
|
||||
getWidget(weapBox, "WeapBox");
|
||||
getWidget(weapImage, "WeapImage");
|
||||
getWidget(weapStatus, "WeapStatus");
|
||||
weapBoxBaseLeft = weapBox->getLeft();
|
||||
weapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWeaponClicked);
|
||||
|
||||
getWidget(spellBox, "SpellBox");
|
||||
getWidget(spellImage, "SpellImage");
|
||||
getWidget(spellStatus, "SpellStatus");
|
||||
spellBoxBaseLeft = spellBox->getLeft();
|
||||
spellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
|
||||
|
||||
getWidget(effectBox, "EffectBox");
|
||||
getWidget(effect1, "Effect1");
|
||||
effectBoxBaseRight = viewSize.width - effectBox->getRight();
|
||||
effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
|
||||
|
||||
getWidget(minimapBox, "MiniMapBox");
|
||||
minimapBoxBaseRight = viewSize.width - minimapBox->getRight();
|
||||
minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
||||
getWidget(minimap, "MiniMap");
|
||||
getWidget(compass, "Compass");
|
||||
|
||||
getWidget(mCellNameBox, "CellName");
|
||||
getWidget(mWeaponSpellBox, "WeaponSpellName");
|
||||
|
||||
getWidget(crosshair, "Crosshair");
|
||||
|
||||
setFpsLevel(fpsLevel);
|
||||
|
||||
getWidget(trianglecounter, "TriangleCounter");
|
||||
getWidget(batchcounter, "BatchCounter");
|
||||
|
||||
setEffect("icons\\s\\tx_s_chameleon.dds");
|
||||
|
||||
LocalMapBase::init(minimap, compass, this);
|
||||
|
||||
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
||||
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
||||
mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus);
|
||||
}
|
||||
|
||||
void HUD::setFpsLevel(int level)
|
||||
{
|
||||
fpscounter = 0;
|
||||
|
||||
MyGUI::Widget* fps;
|
||||
getWidget(fps, "FPSBoxAdv");
|
||||
fps->setVisible(false);
|
||||
getWidget(fps, "FPSBox");
|
||||
fps->setVisible(false);
|
||||
|
||||
if (level == 2)
|
||||
{
|
||||
getWidget(fpsbox, "FPSBoxAdv");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounterAdv");
|
||||
}
|
||||
else if (level == 1)
|
||||
{
|
||||
getWidget(fpsbox, "FPSBox");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::setFPS(float fps)
|
||||
{
|
||||
if (fpscounter)
|
||||
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
|
||||
}
|
||||
|
||||
void HUD::setTriangleCount(size_t count)
|
||||
{
|
||||
trianglecounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||
}
|
||||
|
||||
void HUD::setBatchCount(size_t count)
|
||||
{
|
||||
batchcounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||
}
|
||||
|
||||
void HUD::setEffect(const char *img)
|
||||
{
|
||||
effect1->setImageTexture(img);
|
||||
}
|
||||
|
||||
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value)
|
||||
{
|
||||
static const char *ids[] =
|
||||
{
|
||||
"HBar", "MBar", "FBar", 0
|
||||
};
|
||||
|
||||
for (int i=0; ids[i]; ++i)
|
||||
if (ids[i]==id)
|
||||
{
|
||||
MyGUI::Widget* w;
|
||||
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
health->setProgressRange (value.getModified());
|
||||
health->setProgressPosition (value.getCurrent());
|
||||
getWidget(w, "HealthFrame");
|
||||
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
|
||||
break;
|
||||
case 1:
|
||||
magicka->setProgressRange (value.getModified());
|
||||
magicka->setProgressPosition (value.getCurrent());
|
||||
getWidget(w, "MagickaFrame");
|
||||
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
|
||||
break;
|
||||
case 2:
|
||||
stamina->setProgressRange (value.getModified());
|
||||
stamina->setProgressPosition (value.getCurrent());
|
||||
getWidget(w, "FatigueFrame");
|
||||
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible)
|
||||
{
|
||||
int weapDx = 0, spellDx = 0;
|
||||
if (!hmsVisible)
|
||||
spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft;
|
||||
|
||||
if (!weapVisible)
|
||||
spellDx += spellBoxBaseLeft - weapBoxBaseLeft;
|
||||
|
||||
mWeaponVisible = weapVisible;
|
||||
mSpellVisible = spellVisible;
|
||||
if (!mWeaponVisible && !mSpellVisible)
|
||||
mWeaponSpellBox->setVisible(false);
|
||||
|
||||
health->setVisible(hmsVisible);
|
||||
stamina->setVisible(hmsVisible);
|
||||
magicka->setVisible(hmsVisible);
|
||||
weapBox->setPosition(weapBoxBaseLeft - weapDx, weapBox->getTop());
|
||||
weapBox->setVisible(weapVisible);
|
||||
spellBox->setPosition(spellBoxBaseLeft - spellDx, spellBox->getTop());
|
||||
spellBox->setVisible(spellVisible);
|
||||
}
|
||||
|
||||
void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible)
|
||||
{
|
||||
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
||||
// effect box can have variable width -> variable left coordinate
|
||||
int effectsDx = 0;
|
||||
if (!minimapBoxVisible)
|
||||
effectsDx = (viewSize.width - minimapBoxBaseRight) - (viewSize.width - effectBoxBaseRight);
|
||||
|
||||
mMapVisible = minimapBoxVisible;
|
||||
minimapBox->setVisible(minimapBoxVisible);
|
||||
effectBox->setPosition((viewSize.width - effectBoxBaseRight) - effectBox->getWidth() + effectsDx, effectBox->getTop());
|
||||
effectBox->setVisible(effectBoxVisible);
|
||||
}
|
||||
|
||||
void HUD::onWorldClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
// drop item into the gameworld
|
||||
MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
|
||||
|
||||
MWWorld::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||
float mouseY = cursorPosition.top / float(viewSize.height);
|
||||
|
||||
int origCount = object.getRefData().getCount();
|
||||
object.getRefData().setCount(mDragAndDrop->mDraggedCount);
|
||||
|
||||
if (world->canPlaceObject(mouseX, mouseY))
|
||||
world->placeObject(object, mouseX, mouseY);
|
||||
else
|
||||
world->dropObjectOnGround(object);
|
||||
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
||||
// remove object from the container it was coming from
|
||||
object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
|
||||
|
||||
mDragAndDrop->mIsOnDragAndDrop = false;
|
||||
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
|
||||
mDragAndDrop->mDraggedWidget = 0;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
|
||||
}
|
||||
else
|
||||
{
|
||||
GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
|
||||
|
||||
if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) )
|
||||
return;
|
||||
|
||||
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
|
||||
MWWorld::Ptr object;
|
||||
try
|
||||
{
|
||||
object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GM_Console)
|
||||
MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object);
|
||||
else if ((mode == GM_Container) || (mode == GM_Inventory))
|
||||
{
|
||||
// pick up object
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
|
||||
{
|
||||
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
mWorldMouseOver = false;
|
||||
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||
float mouseY = cursorPosition.top / float(viewSize.height);
|
||||
|
||||
MWWorld::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// if we can't drop the object at the wanted position, show the "drop on ground" cursor.
|
||||
bool canDrop = world->canPlaceObject(mouseX, mouseY);
|
||||
|
||||
if (!canDrop)
|
||||
MyGUI::PointerManager::getInstance().setPointer("drop_ground");
|
||||
else
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
mWorldMouseOver = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new)
|
||||
{
|
||||
MyGUI::PointerManager::getInstance().setPointer("arrow");
|
||||
mWorldMouseOver = false;
|
||||
}
|
||||
|
||||
void HUD::onHMSClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats);
|
||||
}
|
||||
|
||||
void HUD::onMapClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
|
||||
}
|
||||
|
||||
void HUD::onWeaponClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
|
||||
}
|
||||
|
||||
void HUD::onMagicClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic);
|
||||
}
|
||||
|
||||
void HUD::setCellName(const std::string& cellName)
|
||||
{
|
||||
if (mCellName != cellName)
|
||||
{
|
||||
mCellNameTimer = 5.0f;
|
||||
mCellName = cellName;
|
||||
|
||||
mCellNameBox->setCaption(mCellName);
|
||||
mCellNameBox->setVisible(mMapVisible);
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::onFrame(float dt)
|
||||
{
|
||||
mCellNameTimer -= dt;
|
||||
mWeaponSpellTimer -= dt;
|
||||
if (mCellNameTimer < 0)
|
||||
mCellNameBox->setVisible(false);
|
||||
if (mWeaponSpellTimer < 0)
|
||||
mWeaponSpellBox->setVisible(false);
|
||||
}
|
||||
|
||||
void HUD::onResChange(int width, int height)
|
||||
{
|
||||
setCoord(0, 0, width, height);
|
||||
}
|
||||
|
||||
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
|
||||
std::string spellName = spell->name;
|
||||
if (spellName != mSpellName && mSpellVisible)
|
||||
{
|
||||
mWeaponSpellTimer = 5.0f;
|
||||
mSpellName = spellName;
|
||||
mWeaponSpellBox->setCaption(mSpellName);
|
||||
mWeaponSpellBox->setVisible(true);
|
||||
}
|
||||
|
||||
spellStatus->setProgressRange(100);
|
||||
spellStatus->setProgressPosition(successChancePercent);
|
||||
|
||||
if (spellImage->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0));
|
||||
|
||||
spellBox->setUserString("ToolTipType", "Spell");
|
||||
spellBox->setUserString("Spell", spellId);
|
||||
|
||||
// use the icon of the first effect
|
||||
const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->effects.list.front().effectID);
|
||||
std::string icon = effect->icon;
|
||||
int slashPos = icon.find("\\");
|
||||
icon.insert(slashPos+1, "b_");
|
||||
icon = std::string("icons\\") + icon;
|
||||
Widgets::fixTexturePath(icon);
|
||||
spellImage->setImageTexture(icon);
|
||||
}
|
||||
|
||||
void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
|
||||
{
|
||||
std::string itemName = MWWorld::Class::get(item).getName(item);
|
||||
if (itemName != mSpellName && mSpellVisible)
|
||||
{
|
||||
mWeaponSpellTimer = 5.0f;
|
||||
mSpellName = itemName;
|
||||
mWeaponSpellBox->setCaption(mSpellName);
|
||||
mWeaponSpellBox->setVisible(true);
|
||||
}
|
||||
|
||||
spellStatus->setProgressRange(100);
|
||||
spellStatus->setProgressPosition(chargePercent);
|
||||
|
||||
if (spellImage->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0));
|
||||
|
||||
spellBox->setUserString("ToolTipType", "ItemPtr");
|
||||
spellBox->setUserData(item);
|
||||
|
||||
spellImage->setImageTexture("textures\\menu_icon_magic_mini.dds");
|
||||
MyGUI::ImageBox* itemBox = spellImage->createWidgetReal<MyGUI::ImageBox>("ImageBox", MyGUI::FloatCoord(0,0,1,1)
|
||||
, MyGUI::Align::Stretch);
|
||||
|
||||
std::string path = std::string("icons\\");
|
||||
path+=MWWorld::Class::get(item).getInventoryIcon(item);
|
||||
Widgets::fixTexturePath(path);
|
||||
itemBox->setImageTexture(path);
|
||||
itemBox->setNeedMouseFocus(false);
|
||||
}
|
||||
|
||||
void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
|
||||
{
|
||||
std::string itemName = MWWorld::Class::get(item).getName(item);
|
||||
if (itemName != mWeaponName && mWeaponVisible)
|
||||
{
|
||||
mWeaponSpellTimer = 5.0f;
|
||||
mWeaponName = itemName;
|
||||
mWeaponSpellBox->setCaption(mWeaponName);
|
||||
mWeaponSpellBox->setVisible(true);
|
||||
}
|
||||
|
||||
weapBox->setUserString("ToolTipType", "ItemPtr");
|
||||
weapBox->setUserData(item);
|
||||
|
||||
weapStatus->setProgressRange(100);
|
||||
weapStatus->setProgressPosition(durabilityPercent);
|
||||
|
||||
if (weapImage->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0));
|
||||
|
||||
std::string path = std::string("icons\\");
|
||||
path+=MWWorld::Class::get(item).getInventoryIcon(item);
|
||||
Widgets::fixTexturePath(path);
|
||||
|
||||
if (MWWorld::Class::get(item).getEnchantment(item) != "")
|
||||
{
|
||||
weapImage->setImageTexture("textures\\menu_icon_magic_mini.dds");
|
||||
MyGUI::ImageBox* itemBox = weapImage->createWidgetReal<MyGUI::ImageBox>("ImageBox", MyGUI::FloatCoord(0,0,1,1)
|
||||
, MyGUI::Align::Stretch);
|
||||
itemBox->setImageTexture(path);
|
||||
itemBox->setNeedMouseFocus(false);
|
||||
}
|
||||
else
|
||||
weapImage->setImageTexture(path);
|
||||
}
|
||||
|
||||
void HUD::unsetSelectedSpell()
|
||||
{
|
||||
std::string spellName = "#{sNone}";
|
||||
if (spellName != mSpellName && mSpellVisible)
|
||||
{
|
||||
mWeaponSpellTimer = 5.0f;
|
||||
mSpellName = spellName;
|
||||
mWeaponSpellBox->setCaptionWithReplacing(mSpellName);
|
||||
mWeaponSpellBox->setVisible(true);
|
||||
}
|
||||
|
||||
if (spellImage->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0));
|
||||
spellStatus->setProgressRange(100);
|
||||
spellStatus->setProgressPosition(0);
|
||||
spellImage->setImageTexture("");
|
||||
spellBox->clearUserStrings();
|
||||
}
|
||||
|
||||
void HUD::unsetSelectedWeapon()
|
||||
{
|
||||
std::string itemName = "#{sSkillHandtohand}";
|
||||
if (itemName != mWeaponName && mWeaponVisible)
|
||||
{
|
||||
mWeaponSpellTimer = 5.0f;
|
||||
mWeaponName = itemName;
|
||||
mWeaponSpellBox->setCaptionWithReplacing(mWeaponName);
|
||||
mWeaponSpellBox->setVisible(true);
|
||||
}
|
||||
|
||||
if (weapImage->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0));
|
||||
weapStatus->setProgressRange(100);
|
||||
weapStatus->setProgressPosition(0);
|
||||
weapImage->setImageTexture("icons\\k\\stealth_handtohand.dds");
|
||||
weapBox->clearUserStrings();
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
#include "map_window.hpp"
|
||||
|
||||
#include <openengine/gui/layout.hpp>
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class DragAndDrop;
|
||||
|
||||
class HUD : public OEngine::GUI::Layout, public LocalMapBase
|
||||
{
|
||||
public:
|
||||
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
|
||||
void setEffect(const char *img);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
|
||||
void setFPS(float fps);
|
||||
void setTriangleCount(size_t count);
|
||||
void setBatchCount(size_t count);
|
||||
void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible);
|
||||
void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible);
|
||||
void setFpsLevel(const int level);
|
||||
|
||||
void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
||||
void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent);
|
||||
void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent);
|
||||
void unsetSelectedSpell();
|
||||
void unsetSelectedWeapon();
|
||||
|
||||
void onFrame(float dt);
|
||||
void onResChange(int width, int height);
|
||||
|
||||
void setCellName(const std::string& cellName);
|
||||
|
||||
bool getWorldMouseOver() { return mWorldMouseOver; }
|
||||
|
||||
MyGUI::ProgressPtr health, magicka, stamina;
|
||||
MyGUI::Widget* mHealthFrame;
|
||||
MyGUI::Widget *weapBox, *spellBox;
|
||||
MyGUI::ImageBox *weapImage, *spellImage;
|
||||
MyGUI::ProgressPtr weapStatus, spellStatus;
|
||||
MyGUI::Widget *effectBox, *minimapBox;
|
||||
MyGUI::ImageBox* effect1;
|
||||
MyGUI::ScrollView* minimap;
|
||||
MyGUI::ImageBox* compass;
|
||||
MyGUI::ImageBox* crosshair;
|
||||
MyGUI::TextBox* mCellNameBox;
|
||||
MyGUI::TextBox* mWeaponSpellBox;
|
||||
|
||||
MyGUI::WidgetPtr fpsbox;
|
||||
MyGUI::TextBox* fpscounter;
|
||||
MyGUI::TextBox* trianglecounter;
|
||||
MyGUI::TextBox* batchcounter;
|
||||
|
||||
private:
|
||||
// bottom left elements
|
||||
int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft;
|
||||
// bottom right elements
|
||||
int minimapBoxBaseRight, effectBoxBaseRight;
|
||||
|
||||
DragAndDrop* mDragAndDrop;
|
||||
|
||||
std::string mCellName;
|
||||
float mCellNameTimer;
|
||||
|
||||
std::string mWeaponName;
|
||||
std::string mSpellName;
|
||||
float mWeaponSpellTimer;
|
||||
|
||||
bool mMapVisible;
|
||||
bool mWeaponVisible;
|
||||
bool mSpellVisible;
|
||||
|
||||
bool mWorldMouseOver;
|
||||
|
||||
void onWorldClicked(MyGUI::Widget* _sender);
|
||||
void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y);
|
||||
void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new);
|
||||
void onHMSClicked(MyGUI::Widget* _sender);
|
||||
void onWeaponClicked(MyGUI::Widget* _sender);
|
||||
void onMagicClicked(MyGUI::Widget* _sender);
|
||||
void onMapClicked(MyGUI::Widget* _sender);
|
||||
};
|
||||
}
|
@ -0,0 +1,349 @@
|
||||
#include "inventorywindow.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../mwclass/container.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
#include "window_manager.hpp"
|
||||
#include "widgets.hpp"
|
||||
#include "bookwindow.hpp"
|
||||
#include "scrollwindow.hpp"
|
||||
#include "spellwindow.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string toLower (const std::string& name)
|
||||
{
|
||||
std::string lowerCase;
|
||||
|
||||
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
|
||||
(int(*)(int)) std::tolower);
|
||||
|
||||
return lowerCase;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop)
|
||||
: ContainerBase(dragAndDrop)
|
||||
, WindowPinnableBase("openmw_inventory_window_layout.xml", parWindowManager)
|
||||
, mTrading(false)
|
||||
{
|
||||
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize);
|
||||
|
||||
getWidget(mAvatar, "Avatar");
|
||||
getWidget(mEncumbranceBar, "EncumbranceBar");
|
||||
getWidget(mEncumbranceText, "EncumbranceBarT");
|
||||
getWidget(mFilterAll, "AllButton");
|
||||
getWidget(mFilterWeapon, "WeaponButton");
|
||||
getWidget(mFilterApparel, "ApparelButton");
|
||||
getWidget(mFilterMagic, "MagicButton");
|
||||
getWidget(mFilterMisc, "MiscButton");
|
||||
getWidget(mLeftPane, "LeftPane");
|
||||
getWidget(mRightPane, "RightPane");
|
||||
|
||||
mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
|
||||
|
||||
MyGUI::ScrollView* itemView;
|
||||
MyGUI::Widget* containerWidget;
|
||||
getWidget(containerWidget, "Items");
|
||||
getWidget(itemView, "ItemView");
|
||||
setWidgets(containerWidget, itemView);
|
||||
|
||||
// adjust size of buttons to fit text
|
||||
int curX = 0;
|
||||
mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height );
|
||||
curX += mFilterAll->getTextSize().width + 24 + 4;
|
||||
|
||||
mFilterWeapon->setPosition(curX, mFilterWeapon->getPosition().top);
|
||||
mFilterWeapon->setSize( mFilterWeapon->getTextSize().width + 24, mFilterWeapon->getSize().height );
|
||||
curX += mFilterWeapon->getTextSize().width + 24 + 4;
|
||||
|
||||
mFilterApparel->setPosition(curX, mFilterApparel->getPosition().top);
|
||||
mFilterApparel->setSize( mFilterApparel->getTextSize().width + 24, mFilterApparel->getSize().height );
|
||||
curX += mFilterApparel->getTextSize().width + 24 + 4;
|
||||
|
||||
mFilterMagic->setPosition(curX, mFilterMagic->getPosition().top);
|
||||
mFilterMagic->setSize( mFilterMagic->getTextSize().width + 24, mFilterMagic->getSize().height );
|
||||
curX += mFilterMagic->getTextSize().width + 24 + 4;
|
||||
|
||||
mFilterMisc->setPosition(curX, mFilterMisc->getPosition().top);
|
||||
mFilterMisc->setSize( mFilterMisc->getTextSize().width + 24, mFilterMisc->getSize().height );
|
||||
|
||||
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
|
||||
mFilterAll->setStateSelected(true);
|
||||
|
||||
setCoord(0, 342, 498, 258);
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
openContainer(player);
|
||||
}
|
||||
|
||||
void InventoryWindow::open()
|
||||
{
|
||||
updateEncumbranceBar();
|
||||
|
||||
mTrading = false;
|
||||
|
||||
mBoughtItems.clear();
|
||||
|
||||
onWindowResize(static_cast<MyGUI::Window*>(mMainWidget));
|
||||
}
|
||||
|
||||
void InventoryWindow::onWindowResize(MyGUI::Window* _sender)
|
||||
{
|
||||
const float aspect = 0.5; // fixed aspect ratio for the left pane
|
||||
mLeftPane->setSize( (_sender->getSize().height-44) * aspect, _sender->getSize().height-44 );
|
||||
mRightPane->setCoord( mLeftPane->getPosition().left + (_sender->getSize().height-44) * aspect + 4,
|
||||
mRightPane->getPosition().top,
|
||||
_sender->getSize().width - 12 - (_sender->getSize().height-44) * aspect - 15,
|
||||
_sender->getSize().height-44 );
|
||||
drawItems();
|
||||
}
|
||||
|
||||
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (_sender == mFilterAll)
|
||||
setFilter(ContainerBase::Filter_All);
|
||||
else if (_sender == mFilterWeapon)
|
||||
setFilter(ContainerBase::Filter_Weapon);
|
||||
else if (_sender == mFilterApparel)
|
||||
setFilter(ContainerBase::Filter_Apparel);
|
||||
else if (_sender == mFilterMagic)
|
||||
setFilter(ContainerBase::Filter_Magic);
|
||||
else if (_sender == mFilterMisc)
|
||||
setFilter(ContainerBase::Filter_Misc);
|
||||
|
||||
mFilterAll->setStateSelected(false);
|
||||
mFilterWeapon->setStateSelected(false);
|
||||
mFilterApparel->setStateSelected(false);
|
||||
mFilterMagic->setStateSelected(false);
|
||||
mFilterMisc->setStateSelected(false);
|
||||
|
||||
static_cast<MyGUI::Button*>(_sender)->setStateSelected(true);
|
||||
}
|
||||
|
||||
void InventoryWindow::onPinToggled()
|
||||
{
|
||||
mWindowManager.setWeaponVisibility(!mPinned);
|
||||
}
|
||||
|
||||
void InventoryWindow::onAvatarClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||
{
|
||||
MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
|
||||
|
||||
if (mDragAndDrop->mDraggedFrom != this)
|
||||
{
|
||||
// add item to the player's inventory
|
||||
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
MWWorld::ContainerStoreIterator it = invStore.begin();
|
||||
|
||||
int origCount = ptr.getRefData().getCount();
|
||||
ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
|
||||
it = invStore.add(ptr);
|
||||
(*it).getRefData().setCount(mDragAndDrop->mDraggedCount);
|
||||
ptr = *it;
|
||||
}
|
||||
|
||||
/// \todo scripts
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(ptr).use(ptr);
|
||||
|
||||
action->execute();
|
||||
|
||||
// this is necessary for books/scrolls: if they are already in the player's inventory,
|
||||
// the "Take" button should not be visible.
|
||||
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
|
||||
// without screwing up future book windows
|
||||
if (mDragAndDrop->mDraggedFrom == this)
|
||||
{
|
||||
mWindowManager.getBookWindow()->setTakeButtonShow(false);
|
||||
mWindowManager.getScrollWindow()->setTakeButtonShow(false);
|
||||
}
|
||||
|
||||
mDragAndDrop->mIsOnDragAndDrop = false;
|
||||
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
|
||||
|
||||
mWindowManager.setDragDrop(false);
|
||||
|
||||
drawItems();
|
||||
|
||||
// update selected weapon icon
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
if (weaponSlot == invStore.end())
|
||||
mWindowManager.unsetSelectedWeapon();
|
||||
else
|
||||
mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MWWorld::Ptr> InventoryWindow::getEquippedItems()
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
|
||||
std::vector<MWWorld::Ptr> items;
|
||||
|
||||
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
|
||||
if (it != invStore.end())
|
||||
{
|
||||
items.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void InventoryWindow::_unequipItem(MWWorld::Ptr item)
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
|
||||
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
|
||||
if (it != invStore.end() && *it == item)
|
||||
{
|
||||
invStore.equip(slot, invStore.end());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryWindow::updateEncumbranceBar()
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
|
||||
float capacity = MWWorld::Class::get(player).getCapacity(player);
|
||||
float encumbrance = MWWorld::Class::get(player).getEncumbrance(player);
|
||||
mEncumbranceBar->setProgressRange(capacity);
|
||||
mEncumbranceBar->setProgressPosition(encumbrance);
|
||||
mEncumbranceText->setCaption( boost::lexical_cast<std::string>(int(encumbrance)) + "/" + boost::lexical_cast<std::string>(int(capacity)) );
|
||||
}
|
||||
|
||||
void InventoryWindow::onFrame()
|
||||
{
|
||||
if (!mMainWidget->getVisible())
|
||||
return;
|
||||
|
||||
updateEncumbranceBar();
|
||||
}
|
||||
|
||||
int InventoryWindow::getPlayerGold()
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = invStore.begin();
|
||||
it != invStore.end(); ++it)
|
||||
{
|
||||
if (toLower(it->getCellRef().refID) == "gold_001")
|
||||
return it->getRefData().getCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InventoryWindow::startTrade()
|
||||
{
|
||||
mTrading = true;
|
||||
}
|
||||
|
||||
void InventoryWindow::notifyContentChanged()
|
||||
{
|
||||
// update the spell window just in case new enchanted items were added to inventory
|
||||
if (mWindowManager.getSpellWindow())
|
||||
mWindowManager.getSpellWindow()->updateSpells();
|
||||
|
||||
// update selected weapon icon
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
if (weaponSlot == invStore.end())
|
||||
mWindowManager.unsetSelectedWeapon();
|
||||
else
|
||||
mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability
|
||||
}
|
||||
|
||||
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
|
||||
{
|
||||
/// \todo scripts
|
||||
|
||||
// make sure the object is of a type that can be picked up
|
||||
std::string type = object.getTypeName();
|
||||
if ( (type != typeid(ESM::Apparatus).name())
|
||||
&& (type != typeid(ESM::Armor).name())
|
||||
&& (type != typeid(ESM::Book).name())
|
||||
&& (type != typeid(ESM::Clothing).name())
|
||||
&& (type != typeid(ESM::Ingredient).name())
|
||||
&& (type != typeid(ESM::Light).name())
|
||||
&& (type != typeid(ESM::Miscellaneous).name())
|
||||
&& (type != typeid(ESM::Tool).name())
|
||||
&& (type != typeid(ESM::Probe).name())
|
||||
&& (type != typeid(ESM::Repair).name())
|
||||
&& (type != typeid(ESM::Weapon).name())
|
||||
&& (type != typeid(ESM::Potion).name()))
|
||||
return;
|
||||
|
||||
// sound
|
||||
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1);
|
||||
|
||||
int count = object.getRefData().getCount();
|
||||
|
||||
// add to player inventory
|
||||
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::Ptr newObject = *MWWorld::Class::get (player).getContainerStore (player).add (object);
|
||||
// remove from world
|
||||
MWBase::Environment::get().getWorld()->deleteObject (object);
|
||||
|
||||
mDragAndDrop->mIsOnDragAndDrop = true;
|
||||
mDragAndDrop->mDraggedCount = count;
|
||||
|
||||
std::string path = std::string("icons\\");
|
||||
path += MWWorld::Class::get(newObject).getInventoryIcon(newObject);
|
||||
MyGUI::ImageBox* baseWidget = mContainerWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default);
|
||||
baseWidget->detachFromWidget();
|
||||
baseWidget->attachToWidget(mDragAndDrop->mDragAndDropWidget);
|
||||
baseWidget->setUserData(newObject);
|
||||
mDragAndDrop->mDraggedWidget = baseWidget;
|
||||
ImageBox* image = baseWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
|
||||
int pos = path.rfind(".");
|
||||
path.erase(pos);
|
||||
path.append(".dds");
|
||||
image->setImageTexture(path);
|
||||
image->setNeedMouseFocus(false);
|
||||
|
||||
// text widget that shows item count
|
||||
MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
|
||||
text->setTextAlign(MyGUI::Align::Right);
|
||||
text->setNeedMouseFocus(false);
|
||||
text->setTextShadow(true);
|
||||
text->setTextShadowColour(MyGUI::Colour(0,0,0));
|
||||
text->setCaption(getCountString(count));
|
||||
mDragAndDrop->mDraggedFrom = this;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
#ifndef MGUI_Inventory_H
|
||||
#define MGUI_Inventory_H
|
||||
|
||||
#include "container.hpp"
|
||||
#include "window_pinnable_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class InventoryWindow : public ContainerBase, public WindowPinnableBase
|
||||
{
|
||||
public:
|
||||
InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop);
|
||||
|
||||
virtual void open();
|
||||
|
||||
/// start trading, disables item drag&drop
|
||||
void startTrade();
|
||||
|
||||
void onFrame();
|
||||
|
||||
void pickUpObject (MWWorld::Ptr object);
|
||||
|
||||
int getPlayerGold();
|
||||
|
||||
protected:
|
||||
MyGUI::Widget* mAvatar;
|
||||
MyGUI::TextBox* mArmorRating;
|
||||
MyGUI::ProgressBar* mEncumbranceBar;
|
||||
MyGUI::TextBox* mEncumbranceText;
|
||||
|
||||
MyGUI::Widget* mLeftPane;
|
||||
MyGUI::Widget* mRightPane;
|
||||
|
||||
MyGUI::Button* mFilterAll;
|
||||
MyGUI::Button* mFilterWeapon;
|
||||
MyGUI::Button* mFilterApparel;
|
||||
MyGUI::Button* mFilterMagic;
|
||||
MyGUI::Button* mFilterMisc;
|
||||
|
||||
bool mTrading;
|
||||
|
||||
void onWindowResize(MyGUI::Window* _sender);
|
||||
void onFilterChanged(MyGUI::Widget* _sender);
|
||||
void onAvatarClicked(MyGUI::Widget* _sender);
|
||||
void onPinToggled();
|
||||
|
||||
void updateEncumbranceBar();
|
||||
|
||||
virtual bool isTrading() { return mTrading; }
|
||||
virtual bool isInventory() { return true; }
|
||||
virtual std::vector<MWWorld::Ptr> getEquippedItems();
|
||||
virtual void _unequipItem(MWWorld::Ptr item);
|
||||
|
||||
virtual void onReferenceUnavailable() { ; }
|
||||
|
||||
virtual void notifyContentChanged();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // Inventory_H
|
@ -1,332 +0,0 @@
|
||||
#include "layouts.hpp"
|
||||
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
#include "window_manager.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
|
||||
HUD::HUD(int width, int height, int fpsLevel)
|
||||
: Layout("openmw_hud_layout.xml")
|
||||
, health(NULL)
|
||||
, magicka(NULL)
|
||||
, stamina(NULL)
|
||||
, weapImage(NULL)
|
||||
, spellImage(NULL)
|
||||
, weapStatus(NULL)
|
||||
, spellStatus(NULL)
|
||||
, effectBox(NULL)
|
||||
, effect1(NULL)
|
||||
, minimap(NULL)
|
||||
, compass(NULL)
|
||||
, crosshair(NULL)
|
||||
, fpsbox(NULL)
|
||||
, fpscounter(NULL)
|
||||
, trianglecounter(NULL)
|
||||
, batchcounter(NULL)
|
||||
, hmsBaseLeft(0)
|
||||
, weapBoxBaseLeft(0)
|
||||
, spellBoxBaseLeft(0)
|
||||
, effectBoxBaseRight(0)
|
||||
, minimapBoxBaseRight(0)
|
||||
{
|
||||
setCoord(0,0, width, height);
|
||||
|
||||
// Energy bars
|
||||
getWidget(health, "Health");
|
||||
getWidget(magicka, "Magicka");
|
||||
getWidget(stamina, "Stamina");
|
||||
hmsBaseLeft = health->getLeft();
|
||||
|
||||
// Item and spell images and status bars
|
||||
getWidget(weapBox, "WeapBox");
|
||||
getWidget(weapImage, "WeapImage");
|
||||
getWidget(weapStatus, "WeapStatus");
|
||||
weapBoxBaseLeft = weapBox->getLeft();
|
||||
|
||||
getWidget(spellBox, "SpellBox");
|
||||
getWidget(spellImage, "SpellImage");
|
||||
getWidget(spellStatus, "SpellStatus");
|
||||
spellBoxBaseLeft = spellBox->getLeft();
|
||||
|
||||
getWidget(effectBox, "EffectBox");
|
||||
getWidget(effect1, "Effect1");
|
||||
effectBoxBaseRight = effectBox->getRight();
|
||||
|
||||
getWidget(minimapBox, "MiniMapBox");
|
||||
minimapBoxBaseRight = minimapBox->getRight();
|
||||
getWidget(minimap, "MiniMap");
|
||||
getWidget(compass, "Compass");
|
||||
|
||||
getWidget(crosshair, "Crosshair");
|
||||
|
||||
setFpsLevel(fpsLevel);
|
||||
|
||||
getWidget(trianglecounter, "TriangleCounter");
|
||||
getWidget(batchcounter, "BatchCounter");
|
||||
|
||||
compass->setImageTexture("textures\\compass.dds");
|
||||
crosshair->setImageTexture("textures\\target.dds");
|
||||
|
||||
// These are just demo values, you should replace these with
|
||||
// real calls from outside the class later.
|
||||
setWeapIcon("icons\\w\\tx_knife_iron.dds");
|
||||
setWeapStatus(90, 100);
|
||||
setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds");
|
||||
setSpellStatus(65, 100);
|
||||
setEffect("icons\\s\\tx_s_chameleon.dds");
|
||||
|
||||
LocalMapBase::init(minimap, this);
|
||||
}
|
||||
|
||||
void HUD::setFpsLevel(int level)
|
||||
{
|
||||
MyGUI::Widget* fps;
|
||||
getWidget(fps, "FPSBoxAdv");
|
||||
fps->setVisible(false);
|
||||
getWidget(fps, "FPSBox");
|
||||
fps->setVisible(false);
|
||||
|
||||
if (level == 2)
|
||||
{
|
||||
getWidget(fpsbox, "FPSBoxAdv");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounterAdv");
|
||||
}
|
||||
else if (level == 1)
|
||||
{
|
||||
getWidget(fpsbox, "FPSBox");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::setFPS(float fps)
|
||||
{
|
||||
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
|
||||
}
|
||||
|
||||
void HUD::setTriangleCount(size_t count)
|
||||
{
|
||||
trianglecounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||
}
|
||||
|
||||
void HUD::setBatchCount(size_t count)
|
||||
{
|
||||
batchcounter->setCaption(boost::lexical_cast<std::string>(count));
|
||||
}
|
||||
|
||||
void HUD::setStats(int h, int hmax, int m, int mmax, int s, int smax)
|
||||
{
|
||||
health->setProgressRange(hmax);
|
||||
health->setProgressPosition(h);
|
||||
magicka->setProgressRange(mmax);
|
||||
magicka->setProgressPosition(m);
|
||||
stamina->setProgressRange(smax);
|
||||
stamina->setProgressPosition(s);
|
||||
}
|
||||
|
||||
void HUD::setWeapIcon(const char *str)
|
||||
{
|
||||
weapImage->setImageTexture(str);
|
||||
}
|
||||
|
||||
void HUD::setSpellIcon(const char *str)
|
||||
{
|
||||
spellImage->setImageTexture(str);
|
||||
}
|
||||
|
||||
void HUD::setWeapStatus(int s, int smax)
|
||||
{
|
||||
weapStatus->setProgressRange(smax);
|
||||
weapStatus->setProgressPosition(s);
|
||||
}
|
||||
|
||||
void HUD::setSpellStatus(int s, int smax)
|
||||
{
|
||||
spellStatus->setProgressRange(smax);
|
||||
spellStatus->setProgressPosition(s);
|
||||
}
|
||||
|
||||
void HUD::setEffect(const char *img)
|
||||
{
|
||||
effect1->setImageTexture(img);
|
||||
}
|
||||
|
||||
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value)
|
||||
{
|
||||
static const char *ids[] =
|
||||
{
|
||||
"HBar", "MBar", "FBar", 0
|
||||
};
|
||||
|
||||
for (int i=0; ids[i]; ++i)
|
||||
if (ids[i]==id)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
health->setProgressRange (value.getModified());
|
||||
health->setProgressPosition (value.getCurrent());
|
||||
break;
|
||||
case 1:
|
||||
magicka->setProgressRange (value.getModified());
|
||||
magicka->setProgressPosition (value.getCurrent());
|
||||
break;
|
||||
case 2:
|
||||
stamina->setProgressRange (value.getModified());
|
||||
stamina->setProgressPosition (value.getCurrent());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::setPlayerDir(const float x, const float y)
|
||||
{
|
||||
if (!minimapBox->getVisible() || (x == mLastPositionX && y == mLastPositionY)) return;
|
||||
|
||||
MyGUI::ISubWidget* main = compass->getSubWidgetMain();
|
||||
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
|
||||
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
|
||||
float angle = std::atan2(x,y);
|
||||
rotatingSubskin->setAngle(angle);
|
||||
mLastPositionX = x;
|
||||
mLastPositionY = y;
|
||||
}
|
||||
|
||||
void HUD::setPlayerPos(const float x, const float y)
|
||||
{
|
||||
if (!minimapBox->getVisible() || (x == mLastDirectionX && y == mLastDirectionY)) return;
|
||||
|
||||
MyGUI::IntSize size = minimap->getCanvasSize();
|
||||
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
|
||||
MyGUI::IntCoord viewsize = minimap->getCoord();
|
||||
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
|
||||
|
||||
minimap->setViewOffset(pos);
|
||||
compass->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
|
||||
|
||||
mLastDirectionX = x;
|
||||
mLastDirectionY = y;
|
||||
}
|
||||
|
||||
void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible)
|
||||
{
|
||||
int weapDx = 0, spellDx = 0;
|
||||
if (!hmsVisible)
|
||||
spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft;
|
||||
|
||||
if (!weapVisible)
|
||||
spellDx -= spellBoxBaseLeft - weapBoxBaseLeft;
|
||||
|
||||
health->setVisible(hmsVisible);
|
||||
stamina->setVisible(hmsVisible);
|
||||
magicka->setVisible(hmsVisible);
|
||||
weapBox->setPosition(weapBoxBaseLeft - weapDx, weapBox->getTop());
|
||||
weapBox->setVisible(weapVisible);
|
||||
spellBox->setPosition(spellBoxBaseLeft - spellDx, spellBox->getTop());
|
||||
spellBox->setVisible(spellVisible);
|
||||
}
|
||||
|
||||
void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible)
|
||||
{
|
||||
// effect box can have variable width -> variable left coordinate
|
||||
int effectsDx = 0;
|
||||
if (!minimapBoxVisible)
|
||||
effectsDx = minimapBoxBaseRight - effectBoxBaseRight;
|
||||
|
||||
minimapBox->setVisible(minimapBoxVisible);
|
||||
effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop());
|
||||
effectBox->setVisible(effectBoxVisible);
|
||||
}
|
||||
|
||||
LocalMapBase::LocalMapBase()
|
||||
: mCurX(0)
|
||||
, mCurY(0)
|
||||
, mInterior(false)
|
||||
, mFogOfWar(true)
|
||||
, mLocalMap(NULL)
|
||||
, mPrefix()
|
||||
, mChanged(true)
|
||||
, mLayout(NULL)
|
||||
, mLastPositionX(0.0f)
|
||||
, mLastPositionY(0.0f)
|
||||
, mLastDirectionX(0.0f)
|
||||
, mLastDirectionY(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout)
|
||||
{
|
||||
mLocalMap = widget;
|
||||
mLayout = layout;
|
||||
}
|
||||
|
||||
void LocalMapBase::setCellPrefix(const std::string& prefix)
|
||||
{
|
||||
mPrefix = prefix;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void LocalMapBase::toggleFogOfWar()
|
||||
{
|
||||
mFogOfWar = !mFogOfWar;
|
||||
applyFogOfWar();
|
||||
}
|
||||
|
||||
void LocalMapBase::applyFogOfWar()
|
||||
{
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
{
|
||||
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
|
||||
+ boost::lexical_cast<std::string>(my);
|
||||
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(mCurX + (mx-1)) + "_"
|
||||
+ boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1)));
|
||||
MyGUI::ImageBox* fog;
|
||||
mLayout->getWidget(fog, name+"_fog");
|
||||
fog->setImageTexture(mFogOfWar ?
|
||||
((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog"
|
||||
: "black.png" )
|
||||
: "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
{
|
||||
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
|
||||
+ boost::lexical_cast<std::string>(my);
|
||||
|
||||
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(x + (mx-1)) + "_"
|
||||
+ boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1)));
|
||||
|
||||
MyGUI::ImageBox* box;
|
||||
mLayout->getWidget(box, name);
|
||||
|
||||
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
|
||||
box->setImageTexture(image);
|
||||
else
|
||||
box->setImageTexture("black.png");
|
||||
}
|
||||
}
|
||||
mInterior = interior;
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mChanged = false;
|
||||
applyFogOfWar();
|
||||
}
|
||||
|
@ -1,236 +0,0 @@
|
||||
#ifndef MWGUI_LAYOUTS_H
|
||||
#define MWGUI_LAYOUTS_H
|
||||
|
||||
#include <components/esm_store/store.hpp>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
#include "window_base.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
/*
|
||||
This file contains classes corresponding to window layouts
|
||||
defined in resources/mygui/ *.xml.
|
||||
|
||||
Each class inherites GUI::Layout and loads the XML file, and
|
||||
provides some helper functions to manipulate the elements of the
|
||||
window.
|
||||
|
||||
The windows are never created or destroyed (except at startup and
|
||||
shutdown), they are only hid. You can control visibility with
|
||||
setVisible().
|
||||
*/
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class LocalMapBase
|
||||
{
|
||||
public:
|
||||
LocalMapBase();
|
||||
void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout);
|
||||
|
||||
void setCellPrefix(const std::string& prefix);
|
||||
void setActiveCell(const int x, const int y, bool interior=false);
|
||||
|
||||
void toggleFogOfWar();
|
||||
|
||||
protected:
|
||||
int mCurX, mCurY;
|
||||
bool mInterior;
|
||||
MyGUI::ScrollView* mLocalMap;
|
||||
std::string mPrefix;
|
||||
bool mChanged;
|
||||
bool mFogOfWar;
|
||||
|
||||
void applyFogOfWar();
|
||||
|
||||
OEngine::GUI::Layout* mLayout;
|
||||
|
||||
float mLastPositionX;
|
||||
float mLastPositionY;
|
||||
float mLastDirectionX;
|
||||
float mLastDirectionY;
|
||||
};
|
||||
|
||||
class HUD : public OEngine::GUI::Layout, public LocalMapBase
|
||||
{
|
||||
public:
|
||||
HUD(int width, int height, int fpsLevel);
|
||||
void setStats(int h, int hmax, int m, int mmax, int s, int smax);
|
||||
void setWeapIcon(const char *str);
|
||||
void setSpellIcon(const char *str);
|
||||
void setWeapStatus(int s, int smax);
|
||||
void setSpellStatus(int s, int smax);
|
||||
void setEffect(const char *img);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
|
||||
void setFPS(float fps);
|
||||
void setTriangleCount(size_t count);
|
||||
void setBatchCount(size_t count);
|
||||
void setPlayerDir(const float x, const float y);
|
||||
void setPlayerPos(const float x, const float y);
|
||||
void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible);
|
||||
void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible);
|
||||
void setFpsLevel(const int level);
|
||||
|
||||
MyGUI::ProgressPtr health, magicka, stamina;
|
||||
MyGUI::Widget *weapBox, *spellBox;
|
||||
MyGUI::ImageBox *weapImage, *spellImage;
|
||||
MyGUI::ProgressPtr weapStatus, spellStatus;
|
||||
MyGUI::Widget *effectBox, *minimapBox;
|
||||
MyGUI::ImageBox* effect1;
|
||||
MyGUI::ScrollView* minimap;
|
||||
MyGUI::ImageBox* compass;
|
||||
MyGUI::ImageBox* crosshair;
|
||||
|
||||
MyGUI::WidgetPtr fpsbox;
|
||||
MyGUI::TextBox* fpscounter;
|
||||
MyGUI::TextBox* trianglecounter;
|
||||
MyGUI::TextBox* batchcounter;
|
||||
|
||||
private:
|
||||
// bottom left elements
|
||||
int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft;
|
||||
// bottom right elements
|
||||
int minimapBoxBaseRight, effectBoxBaseRight;
|
||||
};
|
||||
|
||||
class MainMenu : public OEngine::GUI::Layout
|
||||
{
|
||||
public:
|
||||
MainMenu(int w, int h)
|
||||
: Layout("openmw_mainmenu_layout.xml")
|
||||
{
|
||||
setCoord(0,0,w,h);
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
class InventoryWindow : public OEngine::GUI::Layout
|
||||
{
|
||||
public:
|
||||
enum CategoryMode
|
||||
{
|
||||
CM_All = 0, // All items
|
||||
CM_Weapon = 1, // Only weapons
|
||||
CM_Apparel = 2, // Apparel
|
||||
CM_Magic = 3, // Magic
|
||||
CM_Misc = 4 // Misc
|
||||
};
|
||||
|
||||
InventoryWindow ()
|
||||
: Layout("openmw_inventory_window_layout.xml")
|
||||
, categoryMode(CM_All)
|
||||
|
||||
// color should be fetched from skin
|
||||
, activeColor(0, 0, 1)
|
||||
, inactiveColor(0.7, 0.7, 0.7)
|
||||
{
|
||||
setCoord(0, 200, 600, 400);
|
||||
|
||||
// These are just demo values, you should replace these with
|
||||
// real calls from outside the class later.
|
||||
|
||||
mMainWidget->setCaption("Glass Frostsword");
|
||||
setText("EncumbranceBarT", "176/210");
|
||||
|
||||
MyGUI::ProgressPtr pt;
|
||||
getWidget(pt, "EncumbranceBar");
|
||||
pt->setProgressRange(210);
|
||||
pt->setProgressPosition(176);
|
||||
|
||||
MyGUI::WidgetPtr avatar;
|
||||
getWidget(avatar, "Avatar");
|
||||
|
||||
// Adjust armor rating text to bottom of avatar widget
|
||||
MyGUI::TextBox* armor_rating;
|
||||
getWidget(armor_rating, "ArmorRating");
|
||||
armor_rating->setCaption("Armor: 11");
|
||||
MyGUI::IntCoord coord = armor_rating->getCoord();
|
||||
coord.top = avatar->getCoord().height - 4 - coord.height;
|
||||
armor_rating->setCoord(coord);
|
||||
|
||||
names[0] = "All";
|
||||
names[1] = "Weapon";
|
||||
names[2] = "Apparel";
|
||||
names[3] = "Magic";
|
||||
names[4] = "Misc";
|
||||
|
||||
boost::array<CategoryMode, 5> categories = { {
|
||||
CM_All, CM_Weapon, CM_Apparel, CM_Magic, CM_Misc
|
||||
} };
|
||||
|
||||
// Initialize buttons with text and adjust sizes, also mark All as active button
|
||||
int margin = 2;
|
||||
int last_x = 0;
|
||||
for (int i = 0; i < categories.size(); ++i)
|
||||
{
|
||||
CategoryMode mode = categories[i];
|
||||
std::string name = names[mode];
|
||||
name += "Button";
|
||||
setText(name, names[mode]);
|
||||
getWidget(buttons[mode], name);
|
||||
|
||||
MyGUI::ButtonPtr &button_pt = buttons[mode];
|
||||
if (mode == CM_All)
|
||||
button_pt->setTextColour(activeColor);
|
||||
else
|
||||
button_pt->setTextColour(inactiveColor);
|
||||
MyGUI::IntCoord coord = button_pt->getCoord();
|
||||
coord.left = last_x;
|
||||
last_x += coord.width + margin;
|
||||
button_pt->setCoord(coord);
|
||||
|
||||
button_pt->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onCategorySelected);
|
||||
}
|
||||
}
|
||||
|
||||
void setCategory(CategoryMode mode)
|
||||
{
|
||||
MyGUI::ButtonPtr pt = getCategoryButton(categoryMode);
|
||||
pt->setTextColour(inactiveColor);
|
||||
|
||||
pt = getCategoryButton(mode);
|
||||
pt->setTextColour(activeColor);
|
||||
categoryMode = mode;
|
||||
}
|
||||
|
||||
MyGUI::ButtonPtr getCategoryButton(CategoryMode mode)
|
||||
{
|
||||
return buttons[mode];
|
||||
}
|
||||
|
||||
void onCategorySelected(MyGUI::Widget *widget)
|
||||
{
|
||||
boost::array<CategoryMode, 5> categories = { {
|
||||
CM_All, CM_Weapon, CM_Apparel, CM_Magic, CM_Misc
|
||||
} };
|
||||
|
||||
for (int i = 0; i < categories.size(); ++i)
|
||||
{
|
||||
CategoryMode mode = categories[i];
|
||||
if (widget == buttons[mode])
|
||||
{
|
||||
setCategory(mode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CategoryMode categoryMode; // Current category filter
|
||||
MyGUI::ButtonPtr buttons[5]; // Button pointers
|
||||
std::string names[5]; // Names of category buttons
|
||||
|
||||
MyGUI::Colour activeColor;
|
||||
MyGUI::Colour inactiveColor;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
#endif
|
@ -0,0 +1,131 @@
|
||||
#include "list.hpp"
|
||||
|
||||
#include <MyGUI.h>
|
||||
|
||||
using namespace MWGui;
|
||||
using namespace MWGui::Widgets;
|
||||
|
||||
MWList::MWList() :
|
||||
mClient(0)
|
||||
, mScrollView(0)
|
||||
, mItemHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
void MWList::initialiseOverride()
|
||||
{
|
||||
Base::initialiseOverride();
|
||||
|
||||
assignWidget(mClient, "Client");
|
||||
if (mClient == 0)
|
||||
mClient = this;
|
||||
|
||||
mScrollView = mClient->createWidgetReal<MyGUI::ScrollView>(
|
||||
"MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0),
|
||||
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
|
||||
}
|
||||
|
||||
void MWList::addItem(const std::string& name)
|
||||
{
|
||||
mItems.push_back(name);
|
||||
}
|
||||
|
||||
void MWList::addSeparator()
|
||||
{
|
||||
mItems.push_back("");
|
||||
}
|
||||
|
||||
void MWList::adjustSize()
|
||||
{
|
||||
redraw();
|
||||
}
|
||||
|
||||
void MWList::redraw(bool scrollbarShown)
|
||||
{
|
||||
const int _scrollBarWidth = 24; // fetch this from skin?
|
||||
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
|
||||
const int spacing = 3;
|
||||
|
||||
while (mScrollView->getChildCount())
|
||||
{
|
||||
MyGUI::Gui::getInstance().destroyWidget(mScrollView->getChildAt(0));
|
||||
}
|
||||
|
||||
mItemHeight = 0;
|
||||
for (std::vector<std::string>::const_iterator it=mItems.begin();
|
||||
it!=mItems.end(); ++it)
|
||||
{
|
||||
if (*it != "")
|
||||
{
|
||||
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(
|
||||
"MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
|
||||
MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it));
|
||||
button->setCaption((*it));
|
||||
button->getSubWidgetText()->setWordWrap(true);
|
||||
button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
|
||||
button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected);
|
||||
|
||||
int height = button->getTextSize().height;
|
||||
button->setSize(MyGUI::IntSize(button->getSize().width, height));
|
||||
|
||||
mItemHeight += height + spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine",
|
||||
MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth()-4, 18),
|
||||
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
|
||||
separator->setNeedMouseFocus(false);
|
||||
|
||||
mItemHeight += 18 + spacing;
|
||||
}
|
||||
}
|
||||
mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height));
|
||||
|
||||
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
|
||||
redraw(true);
|
||||
}
|
||||
|
||||
bool MWList::hasItem(const std::string& name)
|
||||
{
|
||||
return (std::find(mItems.begin(), mItems.end(), name) != mItems.end());
|
||||
}
|
||||
|
||||
unsigned int MWList::getItemCount()
|
||||
{
|
||||
return mItems.size();
|
||||
}
|
||||
|
||||
std::string MWList::getItemNameAt(unsigned int at)
|
||||
{
|
||||
assert(at < mItems.size() && "List item out of bounds");
|
||||
return mItems[at];
|
||||
}
|
||||
|
||||
void MWList::removeItem(const std::string& name)
|
||||
{
|
||||
assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() );
|
||||
mItems.erase( std::find(mItems.begin(), mItems.end(), name) );
|
||||
}
|
||||
|
||||
void MWList::clear()
|
||||
{
|
||||
mItems.clear();
|
||||
}
|
||||
|
||||
void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel)
|
||||
{
|
||||
//NB view offset is negative
|
||||
if (mScrollView->getViewOffset().top + _rel*0.3 > 0)
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3));
|
||||
}
|
||||
|
||||
void MWList::onItemSelected(MyGUI::Widget* _sender)
|
||||
{
|
||||
std::string name = static_cast<MyGUI::Button*>(_sender)->getCaption();
|
||||
|
||||
eventItemSelected(name);
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
#ifndef MWGUI_LIST_HPP
|
||||
#define MWGUI_LIST_HPP
|
||||
|
||||
#include <MyGUI.h>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
namespace Widgets
|
||||
{
|
||||
/**
|
||||
* \brief a very simple list widget that supports word-wrapping entries
|
||||
* \note if the width or height of the list changes, you must call adjustSize() method
|
||||
*/
|
||||
class MWList : public MyGUI::Widget
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(MWList)
|
||||
public:
|
||||
MWList();
|
||||
|
||||
typedef MyGUI::delegates::CMultiDelegate1<std::string> EventHandle_String;
|
||||
|
||||
/**
|
||||
* Event: Item selected with the mouse.
|
||||
* signature: void method(std::string itemName)
|
||||
*/
|
||||
EventHandle_String eventItemSelected;
|
||||
|
||||
/**
|
||||
* Call after the size of the list changed, or items were inserted/removed
|
||||
*/
|
||||
void adjustSize();
|
||||
|
||||
void addItem(const std::string& name);
|
||||
void addSeparator(); ///< add a seperator between the current and the next item.
|
||||
void removeItem(const std::string& name);
|
||||
bool hasItem(const std::string& name);
|
||||
unsigned int getItemCount();
|
||||
std::string getItemNameAt(unsigned int at); ///< \attention if there are separators, this method will return "" at the place where the separator is
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
void initialiseOverride();
|
||||
|
||||
void redraw(bool scrollbarShown = false);
|
||||
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
void onItemSelected(MyGUI::Widget* _sender);
|
||||
|
||||
private:
|
||||
MyGUI::ScrollView* mScrollView;
|
||||
MyGUI::Widget* mClient;
|
||||
|
||||
std::vector<std::string> mItems;
|
||||
|
||||
int mItemHeight; // height of all items
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,16 @@
|
||||
#include <openengine/gui/layout.hpp>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
class MainMenu : public OEngine::GUI::Layout
|
||||
{
|
||||
public:
|
||||
MainMenu(int w, int h)
|
||||
: Layout("openmw_mainmenu_layout.xml")
|
||||
{
|
||||
setCoord(0,0,w,h);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
#include "referenceinterface.hpp"
|
||||
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
ReferenceInterface::ReferenceInterface()
|
||||
: mCurrentPlayerCell(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void ReferenceInterface::checkReferenceAvailable()
|
||||
{
|
||||
if (mPtr.isEmpty())
|
||||
return;
|
||||
|
||||
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
|
||||
if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL)
|
||||
|| mPtr.getRefData().getCount() == 0)
|
||||
onReferenceUnavailable();
|
||||
|
||||
mCurrentPlayerCell = playerCell;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#ifndef MWGUI_REFERENCEINTERFACE_H
|
||||
#define MWGUI_REFERENCEINTERFACE_H
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
/// \brief this class is intended for GUI interfaces that access an MW-Reference
|
||||
/// for example dialogue window accesses an NPC, or Container window accesses a Container
|
||||
/// these classes have to be automatically closed if the reference becomes unavailable
|
||||
/// make sure that checkReferenceAvailable() is called every frame and that onReferenceUnavailable() has been overridden
|
||||
class ReferenceInterface
|
||||
{
|
||||
public:
|
||||
ReferenceInterface();
|
||||
|
||||
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
|
||||
|
||||
protected:
|
||||
virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable
|
||||
|
||||
MWWorld::Ptr mPtr;
|
||||
|
||||
private:
|
||||
MWWorld::Ptr::CellStore* mCurrentPlayerCell;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
#include "scrollwindow.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwinput/inputmanager.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
#include "formatting.hpp"
|
||||
#include "window_manager.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
ScrollWindow::ScrollWindow (WindowManager& parWindowManager) :
|
||||
WindowBase("openmw_scroll_layout.xml", parWindowManager)
|
||||
{
|
||||
getWidget(mTextView, "TextView");
|
||||
|
||||
getWidget(mCloseButton, "CloseButton");
|
||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ScrollWindow::onCloseButtonClicked);
|
||||
|
||||
getWidget(mTakeButton, "TakeButton");
|
||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ScrollWindow::onTakeButtonClicked);
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
void ScrollWindow::open (MWWorld::Ptr scroll)
|
||||
{
|
||||
// no 3d sounds because the object could be in a container.
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
|
||||
|
||||
mScroll = scroll;
|
||||
|
||||
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||
mScroll.get<ESM::Book>();
|
||||
|
||||
BookTextParser parser;
|
||||
MyGUI::IntSize size = parser.parse(ref->base->text, mTextView, 390);
|
||||
|
||||
if (size.height > mTextView->getSize().height)
|
||||
mTextView->setCanvasSize(MyGUI::IntSize(410, size.height));
|
||||
else
|
||||
mTextView->setCanvasSize(410, mTextView->getSize().height);
|
||||
|
||||
mTextView->setViewOffset(MyGUI::IntPoint(0,0));
|
||||
|
||||
setTakeButtonShow(true);
|
||||
}
|
||||
|
||||
void ScrollWindow::setTakeButtonShow(bool show)
|
||||
{
|
||||
mTakeButton->setVisible(show);
|
||||
}
|
||||
|
||||
void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
|
||||
|
||||
mWindowManager.popGuiMode();
|
||||
}
|
||||
|
||||
void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack);
|
||||
|
||||
MWWorld::ActionTake take(mScroll);
|
||||
take.execute();
|
||||
|
||||
mWindowManager.popGuiMode();
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
#ifndef MWGUI_SCROLLWINDOW_H
|
||||
#define MWGUI_SCROLLWINDOW_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class ScrollWindow : public WindowBase
|
||||
{
|
||||
public:
|
||||
ScrollWindow (WindowManager& parWindowManager);
|
||||
|
||||
void open (MWWorld::Ptr scroll);
|
||||
void setTakeButtonShow(bool show);
|
||||
|
||||
protected:
|
||||
void onCloseButtonClicked (MyGUI::Widget* _sender);
|
||||
void onTakeButtonClicked (MyGUI::Widget* _sender);
|
||||
|
||||
private:
|
||||
MyGUI::Button* mCloseButton;
|
||||
MyGUI::Button* mTakeButton;
|
||||
MyGUI::ScrollView* mTextView;
|
||||
|
||||
MWWorld::Ptr mScroll;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,342 @@
|
||||
#include "settingswindow.hpp"
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreRenderSystem.h>
|
||||
#include <OgreString.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
#include "../mwinput/inputmanager.hpp"
|
||||
|
||||
#include "window_manager.hpp"
|
||||
#include "confirmationdialog.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string fpsLevelToStr(int level)
|
||||
{
|
||||
if (level == 0)
|
||||
return "#{sOff}";
|
||||
else if (level == 1)
|
||||
return "Basic";
|
||||
else
|
||||
return "Detailed";
|
||||
}
|
||||
|
||||
std::string textureFilteringToStr(const std::string& val)
|
||||
{
|
||||
if (val == "none")
|
||||
return "None";
|
||||
else if (val == "anisotropic")
|
||||
return "Anisotropic";
|
||||
else if (val == "bilinear")
|
||||
return "Bilinear";
|
||||
else
|
||||
return "Trilinear";
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
SettingsWindow::SettingsWindow(WindowManager& parWindowManager) :
|
||||
WindowBase("openmw_settings_window_layout.xml", parWindowManager)
|
||||
{
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mResolutionList, "ResolutionList");
|
||||
getWidget(mMenuTransparencySlider, "MenuTransparencySlider");
|
||||
getWidget(mToolTipDelaySlider, "ToolTipDelaySlider");
|
||||
getWidget(mViewDistanceSlider, "ViewDistanceSlider");
|
||||
getWidget(mFullscreenButton, "FullscreenButton");
|
||||
getWidget(mVSyncButton, "VSyncButton");
|
||||
getWidget(mFPSButton, "FPSButton");
|
||||
getWidget(mFOVSlider, "FOVSlider");
|
||||
getWidget(mMasterVolumeSlider, "MasterVolume");
|
||||
getWidget(mVoiceVolumeSlider, "VoiceVolume");
|
||||
getWidget(mEffectsVolumeSlider, "EffectsVolume");
|
||||
getWidget(mFootstepsVolumeSlider, "FootstepsVolume");
|
||||
getWidget(mMusicVolumeSlider, "MusicVolume");
|
||||
getWidget(mAnisotropySlider, "AnisotropySlider");
|
||||
getWidget(mTextureFilteringButton, "TextureFilteringButton");
|
||||
getWidget(mAnisotropyLabel, "AnisotropyLabel");
|
||||
getWidget(mAnisotropyBox, "AnisotropyBox");
|
||||
getWidget(mWaterShaderButton, "WaterShaderButton");
|
||||
getWidget(mReflectObjectsButton, "ReflectObjectsButton");
|
||||
getWidget(mReflectActorsButton, "ReflectActorsButton");
|
||||
getWidget(mReflectTerrainButton, "ReflectTerrainButton");
|
||||
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
|
||||
mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled);
|
||||
mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled);
|
||||
mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mFOVSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
|
||||
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
|
||||
mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mFootstepsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
mMusicVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
|
||||
center();
|
||||
|
||||
int okSize = mOkButton->getTextSize().width + 24;
|
||||
mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(),
|
||||
okSize, mOkButton->getHeight());
|
||||
|
||||
// fill resolution list
|
||||
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
|
||||
const Ogre::StringVector& videoModes = rs->getConfigOptions()["Video Mode"].possibleValues;
|
||||
for (Ogre::StringVector::const_iterator it=videoModes.begin();
|
||||
it!=videoModes.end(); ++it)
|
||||
{
|
||||
mResolutionList->addItem(*it);
|
||||
}
|
||||
|
||||
// read settings
|
||||
int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI");
|
||||
mMenuTransparencySlider->setScrollPosition(menu_transparency);
|
||||
int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI");
|
||||
mToolTipDelaySlider->setScrollPosition(tooltip_delay);
|
||||
|
||||
float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin);
|
||||
mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1));
|
||||
MyGUI::TextBox* fovText;
|
||||
getWidget(fovText, "FovText");
|
||||
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getFloat("field of view", "General"))) + ")");
|
||||
|
||||
float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0;
|
||||
mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1));
|
||||
std::string tf = Settings::Manager::getString("texture filtering", "General");
|
||||
mTextureFilteringButton->setCaption(textureFilteringToStr(tf));
|
||||
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")");
|
||||
mAnisotropyBox->setVisible(tf == "anisotropic");
|
||||
|
||||
float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin);
|
||||
int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val;
|
||||
mViewDistanceSlider->setScrollPosition(viewdist);
|
||||
|
||||
mMasterVolumeSlider->setScrollPosition(Settings::Manager::getFloat("master volume", "Sound") * (mMasterVolumeSlider->getScrollRange()-1));
|
||||
mMusicVolumeSlider->setScrollPosition(Settings::Manager::getFloat("music volume", "Sound") * (mMusicVolumeSlider->getScrollRange()-1));
|
||||
mEffectsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("sfx volume", "Sound") * (mEffectsVolumeSlider->getScrollRange()-1));
|
||||
mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1));
|
||||
mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1));
|
||||
|
||||
mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}");
|
||||
mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}");
|
||||
mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}");
|
||||
mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}");
|
||||
|
||||
if (!MWRender::RenderingManager::waterShaderSupported())
|
||||
{
|
||||
mWaterShaderButton->setEnabled(false);
|
||||
mReflectObjectsButton->setEnabled(false);
|
||||
mReflectActorsButton->setEnabled(false);
|
||||
mReflectTerrainButton->setEnabled(false);
|
||||
}
|
||||
|
||||
mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}");
|
||||
mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}");
|
||||
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD")));
|
||||
}
|
||||
|
||||
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
mWindowManager.popGuiMode();
|
||||
}
|
||||
|
||||
void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index)
|
||||
{
|
||||
if (index == MyGUI::ITEM_NONE)
|
||||
return;
|
||||
|
||||
ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog();
|
||||
dialog->open("#{sNotifyMessage67}");
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept);
|
||||
dialog->eventCancelClicked.clear();
|
||||
dialog->eventCancelClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept);
|
||||
}
|
||||
|
||||
void SettingsWindow::onResolutionAccept()
|
||||
{
|
||||
std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected());
|
||||
size_t xPos = resStr.find("x");
|
||||
std::string resXStr = resStr.substr(0, xPos-1);
|
||||
Ogre::StringUtil::trim(resXStr);
|
||||
std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2));
|
||||
Ogre::StringUtil::trim(resYStr);
|
||||
int resX = boost::lexical_cast<int>(resXStr);
|
||||
int resY = boost::lexical_cast<int>(resYStr);
|
||||
|
||||
Settings::Manager::setInt("resolution x", "Video", resX);
|
||||
Settings::Manager::setInt("resolution y", "Video", resY);
|
||||
|
||||
apply();
|
||||
mResolutionList->setIndexSelected(MyGUI::ITEM_NONE);
|
||||
}
|
||||
|
||||
void SettingsWindow::onResolutionCancel()
|
||||
{
|
||||
mResolutionList->setIndexSelected(MyGUI::ITEM_NONE);
|
||||
}
|
||||
|
||||
void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender)
|
||||
{
|
||||
std::string on = mWindowManager.getGameSettingString("sOn", "On");
|
||||
std::string off = mWindowManager.getGameSettingString("sOff", "On");
|
||||
bool newState;
|
||||
if (_sender->castType<MyGUI::Button>()->getCaption() == on)
|
||||
{
|
||||
_sender->castType<MyGUI::Button>()->setCaption(off);
|
||||
newState = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sender->castType<MyGUI::Button>()->setCaption(on);
|
||||
newState = true;
|
||||
}
|
||||
|
||||
if (_sender == mFullscreenButton)
|
||||
{
|
||||
// check if this resolution is supported in fullscreen
|
||||
bool supported = false;
|
||||
for (unsigned int i=0; i<mResolutionList->getItemCount(); ++i)
|
||||
{
|
||||
std::string resStr = mResolutionList->getItemNameAt(i);
|
||||
size_t xPos = resStr.find("x");
|
||||
std::string resXStr = resStr.substr(0, xPos-1);
|
||||
Ogre::StringUtil::trim(resXStr);
|
||||
std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2));
|
||||
Ogre::StringUtil::trim(resYStr);
|
||||
int resX = boost::lexical_cast<int>(resXStr);
|
||||
int resY = boost::lexical_cast<int>(resYStr);
|
||||
|
||||
if (resX == Settings::Manager::getInt("resolution x", "Video")
|
||||
&& resY == Settings::Manager::getInt("resolution y", "Video"))
|
||||
supported = true;
|
||||
}
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
std::string msg = "This resolution is not supported in Fullscreen mode. Please select a resolution from the list.";
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
messageBox(msg, std::vector<std::string>());
|
||||
_sender->castType<MyGUI::Button>()->setCaption(off);
|
||||
}
|
||||
else
|
||||
{
|
||||
Settings::Manager::setBool("fullscreen", "Video", newState);
|
||||
apply();
|
||||
}
|
||||
}
|
||||
else if (_sender == mVSyncButton)
|
||||
{
|
||||
Settings::Manager::setBool("vsync", "Video", newState);
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
messageBox("VSync will be applied after a restart", std::vector<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_sender == mWaterShaderButton)
|
||||
Settings::Manager::setBool("shader", "Water", newState);
|
||||
else if (_sender == mReflectObjectsButton)
|
||||
{
|
||||
Settings::Manager::setBool("reflect misc", "Water", newState);
|
||||
Settings::Manager::setBool("reflect statics", "Water", newState);
|
||||
Settings::Manager::setBool("reflect statics small", "Water", newState);
|
||||
}
|
||||
else if (_sender == mReflectActorsButton)
|
||||
Settings::Manager::setBool("reflect actors", "Water", newState);
|
||||
else if (_sender == mReflectTerrainButton)
|
||||
Settings::Manager::setBool("reflect terrain", "Water", newState);
|
||||
|
||||
apply();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender)
|
||||
{
|
||||
int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3;
|
||||
Settings::Manager::setInt("fps", "HUD", newLevel);
|
||||
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(newLevel));
|
||||
apply();
|
||||
}
|
||||
|
||||
void SettingsWindow::onTextureFilteringToggled(MyGUI::Widget* _sender)
|
||||
{
|
||||
std::string current = Settings::Manager::getString("texture filtering", "General");
|
||||
std::string next;
|
||||
if (current == "none")
|
||||
next = "bilinear";
|
||||
else if (current == "bilinear")
|
||||
next = "trilinear";
|
||||
else if (current == "trilinear")
|
||||
next = "anisotropic";
|
||||
else
|
||||
next = "none";
|
||||
|
||||
mTextureFilteringButton->setCaption(textureFilteringToStr(next));
|
||||
mAnisotropyBox->setVisible(next == "anisotropic");
|
||||
|
||||
Settings::Manager::setString("texture filtering", "General", next);
|
||||
apply();
|
||||
}
|
||||
|
||||
void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
|
||||
{
|
||||
float val = pos / float(scroller->getScrollRange()-1);
|
||||
if (scroller == mMenuTransparencySlider)
|
||||
Settings::Manager::setFloat("menu transparency", "GUI", val);
|
||||
else if (scroller == mToolTipDelaySlider)
|
||||
Settings::Manager::setFloat("tooltip delay", "GUI", val);
|
||||
else if (scroller == mViewDistanceSlider)
|
||||
Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * sViewDistMin + val * sViewDistMax);
|
||||
else if (scroller == mFOVSlider)
|
||||
{
|
||||
MyGUI::TextBox* fovText;
|
||||
getWidget(fovText, "FovText");
|
||||
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int((1-val) * sFovMin + val * sFovMax)) + ")");
|
||||
Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax);
|
||||
}
|
||||
else if (scroller == mAnisotropySlider)
|
||||
{
|
||||
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")");
|
||||
Settings::Manager::setInt("anisotropy", "General", val * 16);
|
||||
}
|
||||
else if (scroller == mMasterVolumeSlider)
|
||||
Settings::Manager::setFloat("master volume", "Sound", val);
|
||||
else if (scroller == mVoiceVolumeSlider)
|
||||
Settings::Manager::setFloat("voice volume", "Sound", val);
|
||||
else if (scroller == mEffectsVolumeSlider)
|
||||
Settings::Manager::setFloat("sfx volume", "Sound", val);
|
||||
else if (scroller == mFootstepsVolumeSlider)
|
||||
Settings::Manager::setFloat("footsteps volume", "Sound", val);
|
||||
else if (scroller == mMusicVolumeSlider)
|
||||
Settings::Manager::setFloat("music volume", "Sound", val);
|
||||
|
||||
apply();
|
||||
}
|
||||
|
||||
void SettingsWindow::apply()
|
||||
{
|
||||
const Settings::CategorySettingVector changed = Settings::Manager::apply();
|
||||
MWBase::Environment::get().getWorld()->processChangedSettings(changed);
|
||||
MWBase::Environment::get().getSoundManager()->processChangedSettings(changed);
|
||||
MWBase::Environment::get().getWindowManager()->processChangedSettings(changed);
|
||||
MWBase::Environment::get().getInputManager()->processChangedSettings(changed);
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
#ifndef MWGUI_SETTINGS_H
|
||||
#define MWGUI_SETTINGS_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class WindowManager;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class SettingsWindow : public WindowBase
|
||||
{
|
||||
public:
|
||||
SettingsWindow(WindowManager& parWindowManager);
|
||||
|
||||
private:
|
||||
static const float sFovMin = 30;
|
||||
static const float sFovMax = 140;
|
||||
static const float sViewDistMin = 2000;
|
||||
static const float sViewDistMax = 5600;
|
||||
|
||||
protected:
|
||||
MyGUI::Button* mOkButton;
|
||||
|
||||
MyGUI::ScrollBar* mMenuTransparencySlider;
|
||||
MyGUI::ScrollBar* mToolTipDelaySlider;
|
||||
|
||||
// graphics
|
||||
MyGUI::ListBox* mResolutionList;
|
||||
MyGUI::Button* mFullscreenButton;
|
||||
MyGUI::Button* mVSyncButton;
|
||||
MyGUI::Button* mFPSButton;
|
||||
MyGUI::ScrollBar* mViewDistanceSlider;
|
||||
MyGUI::ScrollBar* mFOVSlider;
|
||||
MyGUI::ScrollBar* mAnisotropySlider;
|
||||
MyGUI::Button* mTextureFilteringButton;
|
||||
MyGUI::TextBox* mAnisotropyLabel;
|
||||
MyGUI::Widget* mAnisotropyBox;
|
||||
MyGUI::Button* mWaterShaderButton;
|
||||
MyGUI::Button* mReflectObjectsButton;
|
||||
MyGUI::Button* mReflectActorsButton;
|
||||
MyGUI::Button* mReflectTerrainButton;
|
||||
|
||||
// audio
|
||||
MyGUI::ScrollBar* mMasterVolumeSlider;
|
||||
MyGUI::ScrollBar* mVoiceVolumeSlider;
|
||||
MyGUI::ScrollBar* mEffectsVolumeSlider;
|
||||
MyGUI::ScrollBar* mFootstepsVolumeSlider;
|
||||
MyGUI::ScrollBar* mMusicVolumeSlider;
|
||||
|
||||
void onOkButtonClicked(MyGUI::Widget* _sender);
|
||||
void onFpsToggled(MyGUI::Widget* _sender);
|
||||
void onTextureFilteringToggled(MyGUI::Widget* _sender);
|
||||
void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
|
||||
void onButtonToggled(MyGUI::Widget* _sender);
|
||||
void onResolutionSelected(MyGUI::ListBox* _sender, size_t index);
|
||||
void onResolutionAccept();
|
||||
void onResolutionCancel();
|
||||
|
||||
void apply();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,459 @@
|
||||
#include "spellwindow.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwmechanics/spells.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/spellsuccess.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
#include "window_manager.hpp"
|
||||
#include "inventorywindow.hpp"
|
||||
#include "confirmationdialog.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool sortSpells(const std::string& left, const std::string& right)
|
||||
{
|
||||
const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left);
|
||||
const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right);
|
||||
|
||||
int cmp = a->name.compare(b->name);
|
||||
return cmp < 0;
|
||||
}
|
||||
|
||||
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
|
||||
{
|
||||
int cmp = MWWorld::Class::get(left).getName(left).compare(
|
||||
MWWorld::Class::get(right).getName(right));
|
||||
return cmp < 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
SpellWindow::SpellWindow(WindowManager& parWindowManager)
|
||||
: WindowPinnableBase("openmw_spell_window_layout.xml", parWindowManager)
|
||||
, mHeight(0)
|
||||
, mWidth(0)
|
||||
{
|
||||
getWidget(mSpellView, "SpellView");
|
||||
getWidget(mEffectBox, "EffectsBox");
|
||||
|
||||
setCoord(498, 300, 302, 300);
|
||||
|
||||
updateSpells();
|
||||
|
||||
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize);
|
||||
}
|
||||
|
||||
void SpellWindow::onPinToggled()
|
||||
{
|
||||
mWindowManager.setSpellVisibility(!mPinned);
|
||||
}
|
||||
|
||||
void SpellWindow::open()
|
||||
{
|
||||
updateSpells();
|
||||
}
|
||||
|
||||
void SpellWindow::updateSpells()
|
||||
{
|
||||
const int spellHeight = 18;
|
||||
|
||||
mHeight = 0;
|
||||
while (mSpellView->getChildCount())
|
||||
MyGUI::Gui::getInstance().destroyWidget(mSpellView->getChildAt(0));
|
||||
|
||||
// retrieve all player spells, divide them into Powers and Spells and sort them
|
||||
std::vector<std::string> spellList;
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.mSpells;
|
||||
|
||||
// the following code switches between selected enchanted item and selected spell (only one of these
|
||||
// can be active at a time)
|
||||
std::string selectedSpell = spells.getSelectedSpell();
|
||||
MWWorld::Ptr selectedItem;
|
||||
if (store.getSelectedEnchantItem() != store.end())
|
||||
{
|
||||
selectedSpell = "";
|
||||
selectedItem = *store.getSelectedEnchantItem();
|
||||
|
||||
bool allowSelectedItem = true;
|
||||
|
||||
// make sure that the item is still in the player inventory, otherwise it can't be selected
|
||||
bool found = false;
|
||||
for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it)
|
||||
{
|
||||
if (*it == selectedItem)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
allowSelectedItem = false;
|
||||
|
||||
// if the selected item can be equipped, make sure that it actually is equipped
|
||||
std::pair<std::vector<int>, bool> slots;
|
||||
slots = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem);
|
||||
if (!slots.first.empty())
|
||||
{
|
||||
bool equipped = false;
|
||||
for (int i=0; i < MWWorld::InventoryStore::Slots; ++i)
|
||||
{
|
||||
if (store.getSlot(i) != store.end() && *store.getSlot(i) == selectedItem)
|
||||
{
|
||||
equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!equipped)
|
||||
allowSelectedItem = false;
|
||||
}
|
||||
|
||||
if (!allowSelectedItem)
|
||||
{
|
||||
store.setSelectedEnchantItem(store.end());
|
||||
spells.setSelectedSpell("");
|
||||
mWindowManager.unsetSelectedSpell();
|
||||
selectedItem = MWWorld::Ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||
{
|
||||
spellList.push_back(*it);
|
||||
}
|
||||
|
||||
std::vector<std::string> powers;
|
||||
std::vector<std::string>::iterator it = spellList.begin();
|
||||
while (it != spellList.end())
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it);
|
||||
if (spell->data.type == ESM::Spell::ST_Power)
|
||||
{
|
||||
powers.push_back(*it);
|
||||
it = spellList.erase(it);
|
||||
}
|
||||
else if (spell->data.type == ESM::Spell::ST_Ability)
|
||||
{
|
||||
// abilities are always active and don't show in the spell window.
|
||||
it = spellList.erase(it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
std::sort(powers.begin(), powers.end(), sortSpells);
|
||||
std::sort(spellList.begin(), spellList.end(), sortSpells);
|
||||
|
||||
// retrieve player's enchanted items
|
||||
std::vector<MWWorld::Ptr> items;
|
||||
for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it)
|
||||
{
|
||||
std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it);
|
||||
if (enchantId != "")
|
||||
{
|
||||
// only add items with "Cast once" or "Cast on use"
|
||||
const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId);
|
||||
int type = enchant->data.type;
|
||||
if (type != ESM::Enchantment::CastOnce
|
||||
&& type != ESM::Enchantment::WhenUsed)
|
||||
continue;
|
||||
|
||||
items.push_back(*it);
|
||||
}
|
||||
}
|
||||
std::sort(items.begin(), items.end(), sortItems);
|
||||
|
||||
|
||||
int height = estimateHeight(items.size() + powers.size() + spellList.size());
|
||||
bool scrollVisible = height > mSpellView->getHeight();
|
||||
mWidth = mSpellView->getWidth() - (scrollVisible ? 18 : 0);
|
||||
|
||||
// powers
|
||||
addGroup("#{sPowers}", "");
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = powers.begin(); it != powers.end(); ++it)
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it);
|
||||
MyGUI::Button* t = mSpellView->createWidget<MyGUI::Button>("SpellText",
|
||||
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
t->setCaption(spell->name);
|
||||
t->setTextAlign(MyGUI::Align::Left);
|
||||
t->setUserString("ToolTipType", "Spell");
|
||||
t->setUserString("Spell", *it);
|
||||
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
|
||||
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
|
||||
|
||||
if (*it == selectedSpell)
|
||||
t->setStateSelected(true);
|
||||
|
||||
mHeight += spellHeight;
|
||||
}
|
||||
|
||||
// other spells
|
||||
addGroup("#{sSpells}", "#{sCostChance}");
|
||||
for (std::vector<std::string>::const_iterator it = spellList.begin(); it != spellList.end(); ++it)
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it);
|
||||
MyGUI::Button* t = mSpellView->createWidget<MyGUI::Button>("SpellText",
|
||||
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
t->setCaption(spell->name);
|
||||
t->setTextAlign(MyGUI::Align::Left);
|
||||
t->setUserString("ToolTipType", "Spell");
|
||||
t->setUserString("Spell", *it);
|
||||
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
|
||||
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
|
||||
t->setStateSelected(*it == selectedSpell);
|
||||
|
||||
// cost / success chance
|
||||
MyGUI::Button* costChance = mSpellView->createWidget<MyGUI::Button>("SpellText",
|
||||
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
std::string cost = boost::lexical_cast<std::string>(spell->data.cost);
|
||||
std::string chance = boost::lexical_cast<std::string>(int(MWMechanics::getSpellSuccessChance(*it, player)));
|
||||
costChance->setCaption(cost + "/" + chance);
|
||||
costChance->setTextAlign(MyGUI::Align::Right);
|
||||
costChance->setNeedMouseFocus(false);
|
||||
costChance->setStateSelected(*it == selectedSpell);
|
||||
|
||||
|
||||
mHeight += spellHeight;
|
||||
}
|
||||
|
||||
|
||||
// enchanted items
|
||||
addGroup("#{sMagicItem}", "#{sCostCharge}");
|
||||
|
||||
for (std::vector<MWWorld::Ptr>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
MWWorld::Ptr item = *it;
|
||||
|
||||
const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item));
|
||||
|
||||
// check if the item is currently equipped (will display in a different color)
|
||||
bool equipped = false;
|
||||
for (int i=0; i < MWWorld::InventoryStore::Slots; ++i)
|
||||
{
|
||||
if (store.getSlot(i) != store.end() && *store.getSlot(i) == item)
|
||||
{
|
||||
equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MyGUI::Button* t = mSpellView->createWidget<MyGUI::Button>(equipped ? "SpellText" : "SpellTextUnequipped",
|
||||
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
t->setCaption(MWWorld::Class::get(item).getName(item));
|
||||
t->setTextAlign(MyGUI::Align::Left);
|
||||
t->setUserData(item);
|
||||
t->setUserString("ToolTipType", "ItemPtr");
|
||||
t->setUserString("Equipped", equipped ? "true" : "false");
|
||||
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected);
|
||||
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
|
||||
t->setStateSelected(item == selectedItem);
|
||||
|
||||
// cost / charge
|
||||
MyGUI::Button* costCharge = mSpellView->createWidget<MyGUI::Button>(equipped ? "SpellText" : "SpellTextUnequipped",
|
||||
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
|
||||
std::string cost = boost::lexical_cast<std::string>(enchant->data.cost);
|
||||
std::string charge = boost::lexical_cast<std::string>(enchant->data.charge); /// \todo track current charge
|
||||
if (enchant->data.type == ESM::Enchantment::CastOnce)
|
||||
{
|
||||
// this is Morrowind behaviour
|
||||
cost = "100";
|
||||
charge = "100";
|
||||
}
|
||||
|
||||
costCharge->setCaption(cost + "/" + charge);
|
||||
costCharge->setTextAlign(MyGUI::Align::Right);
|
||||
costCharge->setNeedMouseFocus(false);
|
||||
costCharge->setStateSelected(item == selectedItem);
|
||||
|
||||
mHeight += spellHeight;
|
||||
}
|
||||
|
||||
mSpellView->setCanvasSize(mSpellView->getWidth(), std::max(mSpellView->getHeight(), mHeight));
|
||||
}
|
||||
|
||||
void SpellWindow::addGroup(const std::string &label, const std::string& label2)
|
||||
{
|
||||
if (mSpellView->getChildCount() > 0)
|
||||
{
|
||||
MyGUI::ImageBox* separator = mSpellView->createWidget<MyGUI::ImageBox>("MW_HLine",
|
||||
MyGUI::IntCoord(4, mHeight, mWidth-8, 18),
|
||||
MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
separator->setNeedMouseFocus(false);
|
||||
mHeight += 18;
|
||||
}
|
||||
|
||||
MyGUI::TextBox* groupWidget = mSpellView->createWidget<MyGUI::TextBox>("SandBrightText",
|
||||
MyGUI::IntCoord(0, mHeight, mWidth, 24),
|
||||
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
|
||||
groupWidget->setCaptionWithReplacing(label);
|
||||
groupWidget->setTextAlign(MyGUI::Align::Left);
|
||||
groupWidget->setNeedMouseFocus(false);
|
||||
|
||||
if (label2 != "")
|
||||
{
|
||||
MyGUI::TextBox* groupWidget2 = mSpellView->createWidget<MyGUI::TextBox>("SandBrightText",
|
||||
MyGUI::IntCoord(0, mHeight, mWidth-4, 24),
|
||||
MyGUI::Align::Left | MyGUI::Align::Top);
|
||||
groupWidget2->setCaptionWithReplacing(label2);
|
||||
groupWidget2->setTextAlign(MyGUI::Align::Right);
|
||||
groupWidget2->setNeedMouseFocus(false);
|
||||
}
|
||||
|
||||
mHeight += 24;
|
||||
}
|
||||
|
||||
void SpellWindow::onWindowResize(MyGUI::Window* _sender)
|
||||
{
|
||||
updateSpells();
|
||||
}
|
||||
|
||||
void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender)
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
|
||||
MWMechanics::Spells& spells = stats.mSpells;
|
||||
MWWorld::Ptr item = *_sender->getUserData<MWWorld::Ptr>();
|
||||
|
||||
// retrieve ContainerStoreIterator to the item
|
||||
MWWorld::ContainerStoreIterator it = store.begin();
|
||||
for (; it != store.end(); ++it)
|
||||
{
|
||||
if (*it == item)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(it != store.end());
|
||||
|
||||
// equip, if it can be equipped and is not already equipped
|
||||
if (_sender->getUserString("Equipped") == "false"
|
||||
&& !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
|
||||
{
|
||||
// sound
|
||||
MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0);
|
||||
|
||||
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
|
||||
|
||||
/// \todo the following code is pretty much copy&paste from ActionEquip, put it in a function?
|
||||
// slots that this item can be equipped in
|
||||
std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item);
|
||||
|
||||
// equip the item in the first free slot
|
||||
for (std::vector<int>::const_iterator slot=slots.first.begin();
|
||||
slot!=slots.first.end(); ++slot)
|
||||
{
|
||||
// if all slots are occupied, replace the last slot
|
||||
if (slot == --slots.first.end())
|
||||
{
|
||||
store.equip(*slot, it);
|
||||
break;
|
||||
}
|
||||
|
||||
if (store.getSlot(*slot) == store.end())
|
||||
{
|
||||
// slot is not occupied
|
||||
store.equip(*slot, it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/// \todo scripts?
|
||||
|
||||
// since we changed equipping status, update the inventory window
|
||||
mWindowManager.getInventoryWindow()->drawItems();
|
||||
}
|
||||
|
||||
store.setSelectedEnchantItem(it);
|
||||
spells.setSelectedSpell("");
|
||||
mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge %
|
||||
|
||||
updateSpells();
|
||||
}
|
||||
|
||||
void SpellWindow::onSpellSelected(MyGUI::Widget* _sender)
|
||||
{
|
||||
std::string spellId = _sender->getUserString("Spell");
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
|
||||
MWMechanics::Spells& spells = stats.mSpells;
|
||||
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
{
|
||||
// delete spell, if allowed
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
|
||||
if (spell->data.flags & ESM::Spell::F_Always
|
||||
|| spell->data.type == ESM::Spell::ST_Power)
|
||||
{
|
||||
mWindowManager.messageBox("#{sDeleteSpellError}", std::vector<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
// ask for confirmation
|
||||
mSpellToDelete = spellId;
|
||||
ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog();
|
||||
std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?");
|
||||
question = boost::str(boost::format(question) % spell->name);
|
||||
dialog->open(question);
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept);
|
||||
dialog->eventCancelClicked.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spells.setSelectedSpell(spellId);
|
||||
store.setSelectedEnchantItem(store.end());
|
||||
mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
||||
}
|
||||
|
||||
updateSpells();
|
||||
}
|
||||
|
||||
int SpellWindow::estimateHeight(int numSpells) const
|
||||
{
|
||||
int height = 0;
|
||||
height += 24 * 3 + 18 * 2; // group headings
|
||||
height += numSpells * 18;
|
||||
return height;
|
||||
}
|
||||
|
||||
void SpellWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
|
||||
{
|
||||
if (mSpellView->getViewOffset().top + _rel*0.3 > 0)
|
||||
mSpellView->setViewOffset(MyGUI::IntPoint(0, 0));
|
||||
else
|
||||
mSpellView->setViewOffset(MyGUI::IntPoint(0, mSpellView->getViewOffset().top + _rel*0.3));
|
||||
}
|
||||
|
||||
void SpellWindow::onDeleteSpellAccept()
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.mSpells;
|
||||
|
||||
if (spells.getSelectedSpell() == mSpellToDelete)
|
||||
{
|
||||
spells.setSelectedSpell("");
|
||||
mWindowManager.unsetSelectedSpell();
|
||||
}
|
||||
|
||||
spells.remove(mSpellToDelete);
|
||||
|
||||
updateSpells();
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
#ifndef MWGUI_SPELLWINDOW_H
|
||||
#define MWGUI_SPELLWINDOW_H
|
||||
|
||||
#include "window_pinnable_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class SpellWindow : public WindowPinnableBase
|
||||
{
|
||||
public:
|
||||
SpellWindow(WindowManager& parWindowManager);
|
||||
|
||||
void updateSpells();
|
||||
|
||||
protected:
|
||||
MyGUI::ScrollView* mSpellView;
|
||||
MyGUI::Widget* mEffectBox;
|
||||
|
||||
int mHeight;
|
||||
int mWidth;
|
||||
|
||||
std::string mSpellToDelete;
|
||||
|
||||
void addGroup(const std::string& label, const std::string& label2);
|
||||
|
||||
int estimateHeight(int numSpells) const;
|
||||
|
||||
void onWindowResize(MyGUI::Window* _sender);
|
||||
void onEnchantedItemSelected(MyGUI::Widget* _sender);
|
||||
void onSpellSelected(MyGUI::Widget* _sender);
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
void onDeleteSpellAccept();
|
||||
|
||||
virtual void onPinToggled();
|
||||
virtual void open();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue