Merge remote-tracking branch 'refs/remotes/master/master' into dialog-fix

This commit is contained in:
Marek Kochanowicz 2014-06-16 09:44:49 +02:00
commit 48691136fb
55 changed files with 878 additions and 674 deletions

View file

@ -307,10 +307,17 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float)); mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float));
weaponColumns.mReach = &mColumns.back(); weaponColumns.mReach = &mColumns.back();
for (int i=0; i<6; ++i) for (int i=0; i<3; ++i)
{ {
mColumns.push_back (RefIdColumn (Columns::ColumnId_MinChop + i, ColumnBase::Display_Integer)); const RefIdColumn **column =
weaponColumns.mChop[i] = &mColumns.back(); i==0 ? weaponColumns.mChop : (i==1 ? weaponColumns.mSlash : weaponColumns.mThrust);
for (int j=0; j<2; ++j)
{
mColumns.push_back (
RefIdColumn (Columns::ColumnId_MinChop+i*2+j, ColumnBase::Display_Integer));
column[j] = &mColumns.back();
}
} }
static const struct static const struct

View file

@ -33,7 +33,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog
recharge mode videowidget backgroundimage recharge mode videowidget backgroundimage itemwidget
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

View file

@ -680,7 +680,7 @@ namespace MWClass
else else
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur? getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
if(ishealth) if(ishealth && !attacker.isEmpty()) // Don't use armor mitigation for fall damage
{ {
// Hit percentages: // Hit percentages:
// cuirass = 30% // cuirass = 30%

View file

@ -13,20 +13,7 @@
#include "inventoryitemmodel.hpp" #include "inventoryitemmodel.hpp"
#include "sortfilteritemmodel.hpp" #include "sortfilteritemmodel.hpp"
#include "itemview.hpp" #include "itemview.hpp"
#include "itemwidget.hpp"
namespace
{
std::string getIconPath(MWWorld::Ptr ptr)
{
std::string path = std::string("icons\\");
path += ptr.getClass().getInventoryIcon(ptr);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
return path;
}
}
namespace MWGui namespace MWGui
{ {
@ -149,7 +136,7 @@ namespace MWGui
{ {
mApparatus.at (index)->setUserString ("ToolTipType", "ItemPtr"); mApparatus.at (index)->setUserString ("ToolTipType", "ItemPtr");
mApparatus.at (index)->setUserData (*iter); mApparatus.at (index)->setUserData (*iter);
mApparatus.at (index)->setImageTexture (getIconPath (*iter)); mApparatus.at (index)->setItem(*iter);
} }
} }
@ -189,7 +176,7 @@ namespace MWGui
MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients (); MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients ();
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
{ {
MyGUI::ImageBox* ingredient = mIngredients[i]; ItemWidget* ingredient = mIngredients[i];
MWWorld::Ptr item; MWWorld::Ptr item;
if (it != mAlchemy.endIngredients ()) if (it != mAlchemy.endIngredients ())
@ -204,15 +191,15 @@ namespace MWGui
if (ingredient->getChildCount()) if (ingredient->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
ingredient->setImageTexture("");
ingredient->clearUserStrings (); ingredient->clearUserStrings ();
ingredient->setItem(item);
if (item.isEmpty ()) if (item.isEmpty ())
continue; continue;
ingredient->setUserString("ToolTipType", "ItemPtr"); ingredient->setUserString("ToolTipType", "ItemPtr");
ingredient->setUserData(item); ingredient->setUserData(item);
ingredient->setImageTexture(getIconPath(item));
MyGUI::TextBox* text = ingredient->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); 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->setTextAlign(MyGUI::Align::Right);

View file

@ -11,6 +11,7 @@
namespace MWGui namespace MWGui
{ {
class ItemView; class ItemView;
class ItemWidget;
class SortFilterItemModel; class SortFilterItemModel;
class AlchemyWindow : public WindowBase class AlchemyWindow : public WindowBase
@ -44,8 +45,8 @@ namespace MWGui
MWMechanics::Alchemy mAlchemy; MWMechanics::Alchemy mAlchemy;
std::vector<MyGUI::ImageBox *> mApparatus; std::vector<ItemWidget*> mApparatus;
std::vector<MyGUI::ImageBox *> mIngredients; std::vector<ItemWidget*> mIngredients;
}; };
} }

View file

@ -20,6 +20,7 @@
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "itemview.hpp" #include "itemview.hpp"
#include "itemwidget.hpp"
#include "inventoryitemmodel.hpp" #include "inventoryitemmodel.hpp"
#include "sortfilteritemmodel.hpp" #include "sortfilteritemmodel.hpp"
#include "pickpocketitemmodel.hpp" #include "pickpocketitemmodel.hpp"
@ -46,22 +47,15 @@ namespace MWGui
mSourceSortModel->addDragItem(mItem.mBase, count); mSourceSortModel->addDragItem(mItem.mBase, count);
} }
std::string path = std::string("icons\\"); ItemWidget* baseWidget = mDragAndDropWidget->createWidget<ItemWidget>
path += mItem.mBase.getClass().getInventoryIcon(mItem.mBase); ("MW_ItemIcon", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default);
MyGUI::ImageBox* baseWidget = mDragAndDropWidget->createWidget<MyGUI::ImageBox>
("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default);
mDraggedWidget = baseWidget; mDraggedWidget = baseWidget;
MyGUI::ImageBox* image = baseWidget->createWidget<MyGUI::ImageBox>("ImageBox", baseWidget->setItem(mItem.mBase);
MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); baseWidget->setNeedMouseFocus(false);
size_t pos = path.rfind(".");
if (pos != std::string::npos)
path.erase(pos);
path.append(".dds");
image->setImageTexture(path);
image->setNeedMouseFocus(false);
// text widget that shows item count // text widget that shows item count
MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", // TODO: move to ItemWidget
MyGUI::TextBox* text = baseWidget->createWidget<MyGUI::TextBox>("SandBrightText",
MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
text->setTextAlign(MyGUI::Align::Right); text->setTextAlign(MyGUI::Align::Right);
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);

View file

@ -14,6 +14,7 @@
#include "itemselection.hpp" #include "itemselection.hpp"
#include "container.hpp" #include "container.hpp"
#include "itemwidget.hpp"
#include "sortfilteritemmodel.hpp" #include "sortfilteritemmodel.hpp"
@ -57,8 +58,45 @@ namespace MWGui
void EnchantingDialog::open() void EnchantingDialog::open()
{ {
center(); center();
onRemoveItem(NULL);
onRemoveSoul(NULL); setSoulGem(MWWorld::Ptr());
setItem(MWWorld::Ptr());
}
void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem)
{
if (gem.isEmpty())
{
mSoulBox->setItem(MWWorld::Ptr());
mSoulBox->clearUserStrings();
mEnchanting.setSoulGem(MWWorld::Ptr());
}
else
{
mSoulBox->setItem(gem);
mSoulBox->setUserString ("ToolTipType", "ItemPtr");
mSoulBox->setUserData(gem);
mEnchanting.setSoulGem(gem);
}
updateLabels();
}
void EnchantingDialog::setItem(const MWWorld::Ptr &item)
{
if (item.isEmpty())
{
mItemBox->setItem(MWWorld::Ptr());
mItemBox->clearUserStrings();
mEnchanting.setOldItem(MWWorld::Ptr());
}
else
{
mItemBox->setItem(item);
mItemBox->setUserString ("ToolTipType", "ItemPtr");
mItemBox->setUserData(item);
mEnchanting.setOldItem(item);
}
updateLabels();
} }
void EnchantingDialog::exit() void EnchantingDialog::exit()
@ -122,16 +160,7 @@ namespace MWGui
startEditing(); startEditing();
mEnchanting.setSoulGem(soulgem); mEnchanting.setSoulGem(soulgem);
MyGUI::ImageBox* image = mSoulBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); setSoulGem(soulgem);
std::string path = std::string("icons\\");
path += soulgem.getClass().getInventoryIcon(soulgem);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setUserString ("ToolTipType", "ItemPtr");
image->setUserData(soulgem);
image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul);
mPrice->setVisible(false); mPrice->setVisible(false);
mPriceText->setVisible(false); mPriceText->setVisible(false);
@ -151,46 +180,31 @@ namespace MWGui
void EnchantingDialog::onSelectItem(MyGUI::Widget *sender) void EnchantingDialog::onSelectItem(MyGUI::Widget *sender)
{ {
delete mItemSelectionDialog; if (mEnchanting.getOldItem().isEmpty())
mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}"); {
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); delete mItemSelectionDialog;
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}");
mItemSelectionDialog->setVisible(true); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr()); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel);
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyEnchantable); mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyEnchantable);
}
else
{
setItem(MWWorld::Ptr());
}
} }
void EnchantingDialog::onItemSelected(MWWorld::Ptr item) void EnchantingDialog::onItemSelected(MWWorld::Ptr item)
{ {
mItemSelectionDialog->setVisible(false); mItemSelectionDialog->setVisible(false);
while (mItemBox->getChildCount ()) setItem(item);
MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0));
MyGUI::ImageBox* image = mItemBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += item.getClass().getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setUserString ("ToolTipType", "ItemPtr");
image->setUserData(item);
image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveItem);
mEnchanting.setOldItem(item);
mEnchanting.nextCastStyle(); mEnchanting.nextCastStyle();
updateLabels(); updateLabels();
} }
void EnchantingDialog::onRemoveItem(MyGUI::Widget *sender)
{
while (mItemBox->getChildCount ())
MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0));
mEnchanting.setOldItem(MWWorld::Ptr());
updateLabels();
}
void EnchantingDialog::onItemCancel() void EnchantingDialog::onItemCancel()
{ {
mItemSelectionDialog->setVisible(false); mItemSelectionDialog->setVisible(false);
@ -207,28 +221,7 @@ namespace MWGui
return; return;
} }
while (mSoulBox->getChildCount ()) setSoulGem(item);
MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0));
MyGUI::ImageBox* image = mSoulBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += item.getClass().getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setUserString ("ToolTipType", "ItemPtr");
image->setUserData(item);
image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul);
updateLabels();
}
void EnchantingDialog::onRemoveSoul(MyGUI::Widget *sender)
{
while (mSoulBox->getChildCount ())
MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0));
mEnchanting.setSoulGem(MWWorld::Ptr());
updateLabels();
} }
void EnchantingDialog::onSoulCancel() void EnchantingDialog::onSoulCancel()
@ -238,15 +231,22 @@ namespace MWGui
void EnchantingDialog::onSelectSoul(MyGUI::Widget *sender) void EnchantingDialog::onSelectSoul(MyGUI::Widget *sender)
{ {
delete mItemSelectionDialog; if (mEnchanting.getGem().isEmpty())
mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}"); {
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); delete mItemSelectionDialog;
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}");
mItemSelectionDialog->setVisible(true); mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr()); mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel);
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyChargedSoulstones); mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyChargedSoulstones);
//MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}"); //MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}");
}
else
{
setSoulGem(MWWorld::Ptr());
}
} }
void EnchantingDialog::notifyEffectsChanged () void EnchantingDialog::notifyEffectsChanged ()

View file

@ -11,6 +11,7 @@ namespace MWGui
{ {
class ItemSelectionDialog; class ItemSelectionDialog;
class ItemWidget;
class EnchantingDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase class EnchantingDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase
{ {
@ -22,6 +23,9 @@ namespace MWGui
virtual void exit(); virtual void exit();
void setSoulGem (const MWWorld::Ptr& gem);
void setItem (const MWWorld::Ptr& item);
void startEnchanting(MWWorld::Ptr actor); void startEnchanting(MWWorld::Ptr actor);
void startSelfEnchanting(MWWorld::Ptr soulgem); void startSelfEnchanting(MWWorld::Ptr soulgem);
@ -32,8 +36,6 @@ namespace MWGui
void onCancelButtonClicked(MyGUI::Widget* sender); void onCancelButtonClicked(MyGUI::Widget* sender);
void onSelectItem (MyGUI::Widget* sender); void onSelectItem (MyGUI::Widget* sender);
void onSelectSoul (MyGUI::Widget* sender); void onSelectSoul (MyGUI::Widget* sender);
void onRemoveItem (MyGUI::Widget* sender);
void onRemoveSoul (MyGUI::Widget* sender);
void onItemSelected(MWWorld::Ptr item); void onItemSelected(MWWorld::Ptr item);
void onItemCancel(); void onItemCancel();
@ -46,8 +48,8 @@ namespace MWGui
ItemSelectionDialog* mItemSelectionDialog; ItemSelectionDialog* mItemSelectionDialog;
MyGUI::Button* mCancelButton; MyGUI::Button* mCancelButton;
MyGUI::ImageBox* mItemBox; ItemWidget* mItemBox;
MyGUI::ImageBox* mSoulBox; ItemWidget* mSoulBox;
MyGUI::Button* mTypeButton; MyGUI::Button* mTypeButton;
MyGUI::Button* mBuyButton; MyGUI::Button* mBuyButton;

View file

@ -64,10 +64,15 @@ namespace
return unicode; return unicode;
} }
// getUtf8, aka the worst function ever written.
// This includes various hacks for dealing with Morrowind's .fnt files that are *mostly*
// in the expected win12XX encoding, but also have randomly swapped characters sometimes.
// Looks like the Morrowind developers found standard encodings too boring and threw in some twists for fun.
std::string getUtf8 (unsigned char c, ToUTF8::Utf8Encoder& encoder, ToUTF8::FromType encoding) std::string getUtf8 (unsigned char c, ToUTF8::Utf8Encoder& encoder, ToUTF8::FromType encoding)
{ {
if (encoding == ToUTF8::WINDOWS_1250) if (encoding == ToUTF8::WINDOWS_1250)
{ {
// Hacks for polish font
unsigned char win1250; unsigned char win1250;
std::map<unsigned char, unsigned char> conv; std::map<unsigned char, unsigned char> conv;
conv[0x80] = 0xc6; conv[0x80] = 0xc6;
@ -101,7 +106,8 @@ namespace
conv[0xa3] = 0xbf; conv[0xa3] = 0xbf;
conv[0xa4] = 0x0; // not contained in win1250 conv[0xa4] = 0x0; // not contained in win1250
conv[0xe1] = 0x8c; conv[0xe1] = 0x8c;
conv[0xe1] = 0x8c; // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste?
//conv[0xe1] = 0x8c;
conv[0xe3] = 0x0; // not contained in win1250 conv[0xe3] = 0x0; // not contained in win1250
conv[0xf5] = 0x0; // not contained in win1250 conv[0xf5] = 0x0; // not contained in win1250
@ -252,6 +258,21 @@ namespace MWGui
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize-data[i].ascent))); + MyGUI::utility::toString((fontSize-data[i].ascent)));
// More hacks! The french game uses U+2019, which is nowhere to be found in
// the CP437 encoding of the font. Fall back to 39 (regular apostrophe)
if (i == 39 && mEncoding == ToUTF8::CP437)
{
MyGUI::xml::ElementPtr code = codes->createChild("Code");
code->addAttribute("index", 0x2019);
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
+ MyGUI::utility::toString(y1) + " "
+ MyGUI::utility::toString(w) + " "
+ MyGUI::utility::toString(h));
code->addAttribute("advance", data[i].width);
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
}
// ASCII vertical bar, use this as text input cursor // ASCII vertical bar, use this as text input cursor
if (i == 124) if (i == 124)
{ {
@ -265,18 +286,30 @@ namespace MWGui
cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize-data[i].ascent))); + MyGUI::utility::toString((fontSize-data[i].ascent)));
} }
// Question mark, use for NotDefined marker (used for glyphs not existing in the font)
if (i == 63)
{
MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code");
cursorCode->addAttribute("index", MyGUI::FontCodeType::NotDefined);
cursorCode->addAttribute("coord", MyGUI::utility::toString(x1) + " "
+ MyGUI::utility::toString(y1) + " "
+ MyGUI::utility::toString(w) + " "
+ MyGUI::utility::toString(h));
cursorCode->addAttribute("advance", data[i].width);
cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
}
} }
// These are required as well, but the fonts don't provide them // These are required as well, but the fonts don't provide them
for (int i=0; i<3; ++i) for (int i=0; i<2; ++i)
{ {
MyGUI::FontCodeType::Enum type; MyGUI::FontCodeType::Enum type;
if(i == 0) if(i == 0)
type = MyGUI::FontCodeType::Selected; type = MyGUI::FontCodeType::Selected;
else if (i == 1) else if (i == 1)
type = MyGUI::FontCodeType::SelectedBack; type = MyGUI::FontCodeType::SelectedBack;
else if (i == 2)
type = MyGUI::FontCodeType::NotDefined;
MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code"); MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code");
cursorCode->addAttribute("index", type); cursorCode->addAttribute("index", type);

View file

@ -18,6 +18,7 @@
#include "container.hpp" #include "container.hpp"
#include "itemmodel.hpp" #include "itemmodel.hpp"
#include "itemwidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -423,9 +424,6 @@ namespace MWGui
mSpellStatus->setProgressRange(100); mSpellStatus->setProgressRange(100);
mSpellStatus->setProgressPosition(successChancePercent); mSpellStatus->setProgressPosition(successChancePercent);
if (mSpellImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mSpellImage->getChildAt(0));
mSpellBox->setUserString("ToolTipType", "Spell"); mSpellBox->setUserString("ToolTipType", "Spell");
mSpellBox->setUserString("Spell", spellId); mSpellBox->setUserString("Spell", spellId);
@ -438,7 +436,9 @@ namespace MWGui
icon.insert(slashPos+1, "b_"); icon.insert(slashPos+1, "b_");
icon = std::string("icons\\") + icon; icon = std::string("icons\\") + icon;
Widgets::fixTexturePath(icon); Widgets::fixTexturePath(icon);
mSpellImage->setImageTexture(icon);
mSpellImage->setItem(MWWorld::Ptr());
mSpellImage->setIcon(icon);
} }
void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent) void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
@ -455,21 +455,10 @@ namespace MWGui
mSpellStatus->setProgressRange(100); mSpellStatus->setProgressRange(100);
mSpellStatus->setProgressPosition(chargePercent); mSpellStatus->setProgressPosition(chargePercent);
if (mSpellImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mSpellImage->getChildAt(0));
mSpellBox->setUserString("ToolTipType", "ItemPtr"); mSpellBox->setUserString("ToolTipType", "ItemPtr");
mSpellBox->setUserData(item); mSpellBox->setUserData(item);
mSpellImage->setImageTexture("textures\\menu_icon_magic_mini.dds"); mSpellImage->setItem(item);
MyGUI::ImageBox* itemBox = mSpellImage->createWidgetReal<MyGUI::ImageBox>("ImageBox", MyGUI::FloatCoord(0,0,1,1)
, MyGUI::Align::Stretch);
std::string path = std::string("icons\\");
path+=item.getClass().getInventoryIcon(item);
Widgets::fixTexturePath(path);
itemBox->setImageTexture(path);
itemBox->setNeedMouseFocus(false);
} }
void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent) void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
@ -489,23 +478,7 @@ namespace MWGui
mWeapStatus->setProgressRange(100); mWeapStatus->setProgressRange(100);
mWeapStatus->setProgressPosition(durabilityPercent); mWeapStatus->setProgressPosition(durabilityPercent);
if (mWeapImage->getChildCount()) mWeapImage->setItem(item);
MyGUI::Gui::getInstance().destroyWidget(mWeapImage->getChildAt(0));
std::string path = std::string("icons\\");
path+=item.getClass().getInventoryIcon(item);
Widgets::fixTexturePath(path);
if (item.getClass().getEnchantment(item) != "")
{
mWeapImage->setImageTexture("textures\\menu_icon_magic_mini.dds");
MyGUI::ImageBox* itemBox = mWeapImage->createWidgetReal<MyGUI::ImageBox>("ImageBox", MyGUI::FloatCoord(0,0,1,1)
, MyGUI::Align::Stretch);
itemBox->setImageTexture(path);
itemBox->setNeedMouseFocus(false);
}
else
mWeapImage->setImageTexture(path);
} }
void HUD::unsetSelectedSpell() void HUD::unsetSelectedSpell()
@ -519,11 +492,9 @@ namespace MWGui
mWeaponSpellBox->setVisible(true); mWeaponSpellBox->setVisible(true);
} }
if (mSpellImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mSpellImage->getChildAt(0));
mSpellStatus->setProgressRange(100); mSpellStatus->setProgressRange(100);
mSpellStatus->setProgressPosition(0); mSpellStatus->setProgressPosition(0);
mSpellImage->setImageTexture(""); mSpellImage->setItem(MWWorld::Ptr());
mSpellBox->clearUserStrings(); mSpellBox->clearUserStrings();
} }
@ -538,17 +509,17 @@ namespace MWGui
mWeaponSpellBox->setVisible(true); mWeaponSpellBox->setVisible(true);
} }
if (mWeapImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mWeapImage->getChildAt(0));
mWeapStatus->setProgressRange(100); mWeapStatus->setProgressRange(100);
mWeapStatus->setProgressPosition(0); mWeapStatus->setProgressPosition(0);
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr(); MWWorld::Ptr player = world->getPlayerPtr();
mWeapImage->setItem(MWWorld::Ptr());
if (player.getClass().getNpcStats(player).isWerewolf()) if (player.getClass().getNpcStats(player).isWerewolf())
mWeapImage->setImageTexture("icons\\k\\tx_werewolf_hand.dds"); mWeapImage->setIcon("icons\\k\\tx_werewolf_hand.dds");
else else
mWeapImage->setImageTexture("icons\\k\\stealth_handtohand.dds"); mWeapImage->setIcon("icons\\k\\stealth_handtohand.dds");
mWeapBox->clearUserStrings(); mWeapBox->clearUserStrings();
} }

View file

@ -10,6 +10,7 @@ namespace MWGui
{ {
class DragAndDrop; class DragAndDrop;
class SpellIcons; class SpellIcons;
class ItemWidget;
class HUD : public OEngine::GUI::Layout, public LocalMapBase class HUD : public OEngine::GUI::Layout, public LocalMapBase
{ {
@ -63,7 +64,7 @@ namespace MWGui
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning; MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
MyGUI::Widget* mHealthFrame; MyGUI::Widget* mHealthFrame;
MyGUI::Widget *mWeapBox, *mSpellBox, *mSneakBox; MyGUI::Widget *mWeapBox, *mSpellBox, *mSneakBox;
MyGUI::ImageBox *mWeapImage, *mSpellImage; ItemWidget *mWeapImage, *mSpellImage;
MyGUI::ProgressBar *mWeapStatus, *mSpellStatus; MyGUI::ProgressBar *mWeapStatus, *mSpellStatus;
MyGUI::Widget *mEffectBox, *mMinimapBox; MyGUI::Widget *mEffectBox, *mMinimapBox;
MyGUI::Button* mMinimapButton; MyGUI::Button* mMinimapButton;

View file

@ -12,6 +12,7 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "itemmodel.hpp" #include "itemmodel.hpp"
#include "itemwidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -80,53 +81,24 @@ void ItemView::update()
const ItemStack& item = mModel->getItem(i); const ItemStack& item = mModel->getItem(i);
/// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
std::string path = std::string("icons\\"); ItemWidget* itemWidget = dragArea->createWidget<ItemWidget>("MW_ItemIcon",
path += item.mBase.getClass().getInventoryIcon(item.mBase);
// background widget (for the "equipped" frame and magic item background image)
bool isMagic = (item.mFlags & ItemStack::Flag_Enchanted);
MyGUI::ImageBox* backgroundWidget = dragArea->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default);
backgroundWidget->setUserString("ToolTipType", "ItemModelIndex"); itemWidget->setUserString("ToolTipType", "ItemModelIndex");
backgroundWidget->setUserData(std::make_pair(i, mModel)); itemWidget->setUserData(std::make_pair(i, mModel));
ItemWidget::ItemState state = ItemWidget::None;
if (item.mType == ItemStack::Type_Barter)
state = ItemWidget::Barter;
if (item.mType == ItemStack::Type_Equipped)
state = ItemWidget::Equip;
itemWidget->setItem(item.mBase, state);
std::string backgroundTex = "textures\\menu_icon"; itemWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedItem);
if (isMagic) itemWidget->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheel);
backgroundTex += "_magic";
if (item.mType == ItemStack::Type_Normal)
{
if (!isMagic)
backgroundTex = "";
}
else if (item.mType == ItemStack::Type_Equipped)
backgroundTex += "_equip";
else if (item.mType == ItemStack::Type_Barter)
backgroundTex += "_barter";
if (backgroundTex != "")
backgroundTex += ".dds";
backgroundWidget->setImageTexture(backgroundTex);
if ((item.mType == ItemStack::Type_Barter) && !isMagic)
backgroundWidget->setProperty("ImageCoord", "2 2 42 42");
else
backgroundWidget->setProperty("ImageCoord", "0 0 42 42");
backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ItemView::onSelectedItem);
backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ItemView::onMouseWheel);
// image
MyGUI::ImageBox* image = backgroundWidget->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
std::string::size_type pos = path.rfind(".");
if(pos != std::string::npos)
path.erase(pos);
path.append(".dds");
image->setImageTexture(path);
image->setNeedMouseFocus(false);
// text widget that shows item count // text widget that shows item count
MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", // TODO: move to ItemWidget
MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label")); MyGUI::TextBox* text = itemWidget->createWidget<MyGUI::TextBox>("SandBrightText",
MyGUI::IntCoord(5, 19, 32, 18), MyGUI::Align::Default, std::string("Label"));
text->setTextAlign(MyGUI::Align::Right); text->setTextAlign(MyGUI::Align::Right);
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);
text->setTextShadow(true); text->setTextShadow(true);

View file

@ -0,0 +1,105 @@
#include "itemwidget.hpp"
#include <MyGUI_FactoryManager.h>
#include <MyGUI_ImageBox.h>
#include "../mwworld/class.hpp"
namespace MWGui
{
ItemWidget::ItemWidget()
: mItem(NULL)
{
}
void ItemWidget::registerComponents()
{
MyGUI::FactoryManager::getInstance().registerFactory<ItemWidget>("Widget");
}
void ItemWidget::initialiseOverride()
{
assignWidget(mItem, "Item");
if (mItem)
mItem->setNeedMouseFocus(false);
assignWidget(mFrame, "Frame");
if (mFrame)
mFrame->setNeedMouseFocus(false);
Base::initialiseOverride();
}
void ItemWidget::setIcon(const std::string &icon)
{
if (mItem)
mItem->setImageTexture(icon);
}
void ItemWidget::setFrame(const std::string &frame, const MyGUI::IntCoord &coord)
{
if (mFrame)
{
mFrame->setImageTexture(frame);
mFrame->setImageTile(MyGUI::IntSize(coord.width, coord.height)); // Why is this needed? MyGUI bug?
mFrame->setImageCoord(coord);
}
}
void ItemWidget::setIcon(const MWWorld::Ptr &ptr)
{
// image
std::string path = std::string("icons\\");
path += ptr.getClass().getInventoryIcon(ptr);
std::string::size_type pos = path.rfind(".");
if(pos != std::string::npos)
path.erase(pos);
path.append(".dds");
setIcon(path);
}
void ItemWidget::setItem(const MWWorld::Ptr &ptr, ItemState state)
{
if (!mItem)
return;
if (ptr.isEmpty())
{
if (mFrame)
mFrame->setImageTexture("");
mItem->setImageTexture("");
return;
}
bool isMagic = !ptr.getClass().getEnchantment(ptr).empty();
std::string backgroundTex = "textures\\menu_icon";
if (isMagic)
backgroundTex += "_magic";
if (state == None)
{
if (!isMagic)
backgroundTex = "";
}
else if (state == Equip)
{
backgroundTex += "_equip";
}
else if (state == Barter)
backgroundTex += "_barter";
if (backgroundTex != "")
backgroundTex += ".dds";
if (state == Barter && !isMagic)
setFrame(backgroundTex, MyGUI::IntCoord(2,2,42,42));
else
setFrame(backgroundTex, MyGUI::IntCoord(0,0,42,42));
setIcon(ptr);
}
}

View file

@ -0,0 +1,49 @@
#ifndef OPENMW_MWGUI_ITEMWIDGET_H
#define OPENMW_MWGUI_ITEMWIDGET_H
#include <MyGUI_Widget.h>
namespace MWWorld
{
class Ptr;
}
namespace MWGui
{
/// @brief A widget that shows an icon for an MWWorld::Ptr
class ItemWidget : public MyGUI::Widget
{
MYGUI_RTTI_DERIVED(ItemWidget)
public:
ItemWidget();
/// Register needed components with MyGUI's factory manager
static void registerComponents ();
enum ItemState
{
None,
Equip,
Barter,
Magic
};
/// \a ptr may be empty
void setItem (const MWWorld::Ptr& ptr, ItemState state = None);
// Set icon and frame manually
void setIcon (const std::string& icon);
void setIcon (const MWWorld::Ptr& ptr);
void setFrame (const std::string& frame, const MyGUI::IntCoord& coord);
private:
virtual void initialiseOverride();
MyGUI::ImageBox* mItem;
MyGUI::ImageBox* mFrame;
};
}
#endif

View file

@ -179,7 +179,6 @@ namespace MWGui
{ {
WindowModal::open(); WindowModal::open();
int fixedWidth = 500;
int textPadding = 10; // padding between text-widget and main-widget int textPadding = 10; // padding between text-widget and main-widget
int textButtonPadding = 20; // padding between the text-widget und the button-widget int textButtonPadding = 20; // padding between the text-widget und the button-widget
int buttonLeftPadding = 10; // padding between the buttons if horizontal int buttonLeftPadding = 10; // padding between the buttons if horizontal
@ -232,102 +231,52 @@ namespace MWGui
buttonsWidth += buttonLeftPadding; buttonsWidth += buttonLeftPadding;
MyGUI::IntSize mainWidgetSize; MyGUI::IntSize mainWidgetSize;
if(buttonsWidth < fixedWidth) // among each other
{ if(biggestButtonWidth > textSize.width) {
// on one line mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
if(textSize.width + 2*textPadding < buttonsWidth)
{
mainWidgetSize.width = buttonsWidth;
}
else
{
mainWidgetSize.width = textSize.width + 3*textPadding;
}
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
MyGUI::IntPoint absPos;
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
mMainWidget->setPosition(absPos);
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
mMessageWidget->setCoord(messageWidgetCoord);
mMessageWidget->setSize(textSize);
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding;
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonCord.left = left;
buttonCord.top = textSize.height + textButtonPadding;
buttonSize.width = (*button)->getTextSize().width + 2*buttonPadding;
buttonSize.height = (*button)->getTextSize().height + 2*buttonPadding;
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
left += buttonSize.width + buttonLeftPadding;
}
} }
else else {
{ mainWidgetSize.width = textSize.width + 3*textPadding;
// among each other
if(biggestButtonWidth > textSize.width) {
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
}
else {
mainWidgetSize.width = textSize.width + 3*textPadding;
}
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int top = textButtonPadding + buttonTopPadding + textSize.height;
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2;
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2;
buttonCord.top = top;
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
top += buttonSize.height + 2*buttonTopPadding;
}
mainWidgetSize.height = top + buttonMainPadding;
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntPoint absPos;
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
mMainWidget->setPosition(absPos);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
messageWidgetCoord.width = textSize.width;
messageWidgetCoord.height = textSize.height;
mMessageWidget->setCoord(messageWidgetCoord);
} }
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int top = textButtonPadding + buttonTopPadding + textSize.height;
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2;
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2;
buttonCord.top = top;
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
top += buttonSize.height + 2*buttonTopPadding;
}
mainWidgetSize.height = top + buttonMainPadding;
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntPoint absPos;
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
mMainWidget->setPosition(absPos);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
messageWidgetCoord.width = textSize.width;
messageWidgetCoord.height = textSize.height;
mMessageWidget->setCoord(messageWidgetCoord);
// Set key focus to "Ok" button // Set key focus to "Ok" button
std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}"));
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button) for(button = mButtons.begin(); button != mButtons.end(); ++button)
{ {
if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok)) if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok))

View file

@ -23,6 +23,8 @@
#include "spellwindow.hpp" #include "spellwindow.hpp"
#include "itemwidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -46,14 +48,16 @@ namespace MWGui
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
{ {
MyGUI::Button* button; ItemWidget* button;
getWidget(button, "QuickKey" + boost::lexical_cast<std::string>(i+1)); getWidget(button, "QuickKey" + boost::lexical_cast<std::string>(i+1));
button->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); button->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
unassign(button, i);
mQuickKeyButtons.push_back(button); mQuickKeyButtons.push_back(button);
mAssigned.push_back(Type_Unassigned);
unassign(button, i);
} }
} }
@ -77,12 +81,14 @@ namespace MWGui
delete mMagicSelectionDialog; delete mMagicSelectionDialog;
} }
void QuickKeysMenu::unassign(MyGUI::Widget* key, int index) void QuickKeysMenu::unassign(ItemWidget* key, int index)
{ {
while (key->getChildCount ()) key->clearUserStrings();
MyGUI::Gui::getInstance ().destroyWidget (key->getChildAt(0)); key->setItem(MWWorld::Ptr());
while (key->getChildCount()) // Destroy number label
MyGUI::Gui::getInstance().destroyWidget(key->getChildAt(0));
key->setUserData(Type_Unassigned); mAssigned[index] = Type_Unassigned;
MyGUI::TextBox* textBox = key->createWidgetReal<MyGUI::TextBox>("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default); MyGUI::TextBox* textBox = key->createWidgetReal<MyGUI::TextBox>("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default);
textBox->setTextAlign (MyGUI::Align::Center); textBox->setTextAlign (MyGUI::Align::Center);
@ -156,27 +162,16 @@ namespace MWGui
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item) void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
{ {
MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; assert (mSelectedIndex > 0);
while (button->getChildCount ()) ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); while (button->getChildCount()) // Destroy number label
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
button->setUserData(Type_Item); mAssigned[mSelectedIndex] = Type_Item;
MyGUI::ImageBox* frame = button->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); button->setItem(item, ItemWidget::Barter);
std::string backgroundTex = "textures\\menu_icon_barter.dds"; button->setUserString ("ToolTipType", "ItemPtr");
frame->setImageTexture (backgroundTex); button->setUserData(item);
frame->setImageCoord (MyGUI::IntCoord(4, 4, 40, 40));
frame->setUserString ("ToolTipType", "ItemPtr");
frame->setUserData(item);
frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
MyGUI::ImageBox* image = frame->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += item.getClass().getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setNeedMouseFocus (false);
if (mItemSelectionDialog) if (mItemSelectionDialog)
mItemSelectionDialog->setVisible(false); mItemSelectionDialog->setVisible(false);
@ -189,28 +184,18 @@ namespace MWGui
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item) void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
{ {
MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; assert (mSelectedIndex > 0);
while (button->getChildCount ()) ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); while (button->getChildCount()) // Destroy number label
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
button->setUserData(Type_MagicItem); mAssigned[mSelectedIndex] = Type_MagicItem;
MyGUI::ImageBox* frame = button->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
std::string backgroundTex = "textures\\menu_icon_select_magic_magic.dds"; button->setIcon(item);
frame->setImageTexture (backgroundTex);
frame->setImageCoord (MyGUI::IntCoord(2, 2, 40, 40));
frame->setUserString ("ToolTipType", "ItemPtr");
frame->setUserData(item);
frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
MyGUI::ImageBox* image = frame->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); button->setUserString ("ToolTipType", "ItemPtr");
std::string path = std::string("icons\\"); button->setUserData(item);
path += item.getClass().getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture (path);
image->setNeedMouseFocus (false);
if (mMagicSelectionDialog) if (mMagicSelectionDialog)
mMagicSelectionDialog->setVisible(false); mMagicSelectionDialog->setVisible(false);
@ -218,21 +203,16 @@ namespace MWGui
void QuickKeysMenu::onAssignMagic (const std::string& spellId) void QuickKeysMenu::onAssignMagic (const std::string& spellId)
{ {
MyGUI::Button* button = mQuickKeyButtons[mSelectedIndex]; assert (mSelectedIndex > 0);
while (button->getChildCount ()) ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
MyGUI::Gui::getInstance ().destroyWidget (button->getChildAt(0)); while (button->getChildCount()) // Destroy number label
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
button->setUserData(Type_Magic); mAssigned[mSelectedIndex] = Type_Magic;
MyGUI::ImageBox* frame = button->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(9, 8, 42, 42), MyGUI::Align::Default); button->setItem(MWWorld::Ptr());
std::string backgroundTex = "textures\\menu_icon_select_magic.dds"; button->setUserString ("ToolTipType", "Spell");
frame->setImageTexture (backgroundTex); button->setUserString ("Spell", spellId);
frame->setImageCoord (MyGUI::IntCoord(2, 2, 40, 40));
frame->setUserString ("ToolTipType", "Spell");
frame->setUserString ("Spell", spellId);
frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
MyGUI::ImageBox* image = frame->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
const MWWorld::ESMStore &esmStore = const MWWorld::ESMStore &esmStore =
MWBase::Environment::get().getWorld()->getStore(); MWBase::Environment::get().getWorld()->getStore();
@ -251,8 +231,8 @@ namespace MWGui
path.erase(pos); path.erase(pos);
path.append(".dds"); path.append(".dds");
image->setImageTexture (path); button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
image->setNeedMouseFocus (false); button->setIcon(path);
if (mMagicSelectionDialog) if (mMagicSelectionDialog)
mMagicSelectionDialog->setVisible(false); mMagicSelectionDialog->setVisible(false);
@ -265,16 +245,17 @@ namespace MWGui
void QuickKeysMenu::activateQuickKey(int index) void QuickKeysMenu::activateQuickKey(int index)
{ {
MyGUI::Button* button = mQuickKeyButtons[index-1]; assert (index-1 > 0);
ItemWidget* button = mQuickKeyButtons[index-1];
QuickKeyType type = *button->getUserData<QuickKeyType>(); QuickKeyType type = mAssigned[index-1];
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
if (type == Type_Item || type == Type_MagicItem) if (type == Type_Item || type == Type_MagicItem)
{ {
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>(); MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
// make sure the item is available // make sure the item is available
if (item.getRefData ().getCount() < 1) if (item.getRefData ().getCount() < 1)
{ {
@ -286,7 +267,7 @@ namespace MWGui
if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id)) if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id))
{ {
item = *it; item = *it;
button->getChildAt(0)->setUserData(item); button->setUserData(item);
break; break;
} }
} }
@ -303,7 +284,7 @@ namespace MWGui
if (type == Type_Magic) if (type == Type_Magic)
{ {
std::string spellId = button->getChildAt(0)->getUserString("Spell"); std::string spellId = button->getUserString("Spell");
// Make sure the player still has this spell // Make sure the player still has this spell
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
@ -315,13 +296,13 @@ namespace MWGui
} }
else if (type == Type_Item) else if (type == Type_Item)
{ {
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>(); MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
} }
else if (type == Type_MagicItem) else if (type == Type_MagicItem)
{ {
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>(); MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
// retrieve ContainerStoreIterator to the item // retrieve ContainerStoreIterator to the item
MWWorld::ContainerStoreIterator it = store.begin(); MWWorld::ContainerStoreIterator it = store.begin();
@ -403,9 +384,9 @@ namespace MWGui
for (int i=0; i<10; ++i) for (int i=0; i<10; ++i)
{ {
MyGUI::Button* button = mQuickKeyButtons[i]; ItemWidget* button = mQuickKeyButtons[i];
int type = *button->getUserData<QuickKeyType>(); int type = mAssigned[i];
ESM::QuickKeys::QuickKey key; ESM::QuickKeys::QuickKey key;
key.mType = type; key.mType = type;
@ -417,12 +398,12 @@ namespace MWGui
case Type_Item: case Type_Item:
case Type_MagicItem: case Type_MagicItem:
{ {
MWWorld::Ptr item = *button->getChildAt(0)->getUserData<MWWorld::Ptr>(); MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
key.mId = item.getCellRef().getRefId(); key.mId = item.getCellRef().getRefId();
break; break;
} }
case Type_Magic: case Type_Magic:
std::string spellId = button->getChildAt(0)->getUserString("Spell"); std::string spellId = button->getUserString("Spell");
key.mId = spellId; key.mId = spellId;
break; break;
} }
@ -452,7 +433,7 @@ namespace MWGui
mSelectedIndex = i; mSelectedIndex = i;
int keyType = it->mType; int keyType = it->mType;
std::string id = it->mId; std::string id = it->mId;
MyGUI::Button* button = mQuickKeyButtons[i]; ItemWidget* button = mQuickKeyButtons[i];
switch (keyType) switch (keyType)
{ {

View file

@ -11,6 +11,7 @@ namespace MWGui
class QuickKeysMenuAssign; class QuickKeysMenuAssign;
class ItemSelectionDialog; class ItemSelectionDialog;
class MagicSelectionDialog; class MagicSelectionDialog;
class ItemWidget;
class QuickKeysMenu : public WindowBase class QuickKeysMenu : public WindowBase
{ {
@ -51,7 +52,8 @@ namespace MWGui
MyGUI::EditBox* mInstructionLabel; MyGUI::EditBox* mInstructionLabel;
MyGUI::Button* mOkButton; MyGUI::Button* mOkButton;
std::vector<MyGUI::Button*> mQuickKeyButtons; std::vector<ItemWidget*> mQuickKeyButtons;
std::vector<QuickKeyType> mAssigned;
QuickKeysMenuAssign* mAssignDialog; QuickKeysMenuAssign* mAssignDialog;
ItemSelectionDialog* mItemSelectionDialog; ItemSelectionDialog* mItemSelectionDialog;
@ -63,7 +65,7 @@ namespace MWGui
void onQuickKeyButtonClicked(MyGUI::Widget* sender); void onQuickKeyButtonClicked(MyGUI::Widget* sender);
void onOkButtonClicked(MyGUI::Widget* sender); void onOkButtonClicked(MyGUI::Widget* sender);
void unassign(MyGUI::Widget* key, int index); void unassign(ItemWidget* key, int index);
}; };
class QuickKeysMenuAssign : public WindowModal class QuickKeysMenuAssign : public WindowModal

View file

@ -14,6 +14,7 @@
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "itemwidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -45,12 +46,7 @@ void Recharge::exit()
void Recharge::start (const MWWorld::Ptr &item) void Recharge::start (const MWWorld::Ptr &item)
{ {
std::string path = std::string("icons\\"); mGemIcon->setItem(item);
path += item.getClass().getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
mGemIcon->setImageTexture (path);
mGemIcon->setUserString("ToolTipType", "ItemPtr"); mGemIcon->setUserString("ToolTipType", "ItemPtr");
mGemIcon->setUserData(item); mGemIcon->setUserData(item);
@ -108,14 +104,9 @@ void Recharge::updateView()
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);
currentY += 19; currentY += 19;
MyGUI::ImageBox* icon = mView->createWidget<MyGUI::ImageBox> ( ItemWidget* icon = mView->createWidget<ItemWidget> (
"ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\"); icon->setItem(*iter);
path += iter->getClass().getInventoryIcon(*iter);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
icon->setImageTexture (path);
icon->setUserString("ToolTipType", "ItemPtr"); icon->setUserString("ToolTipType", "ItemPtr");
icon->setUserData(*iter); icon->setUserData(*iter);
icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onItemClicked); icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onItemClicked);

View file

@ -8,6 +8,8 @@
namespace MWGui namespace MWGui
{ {
class ItemWidget;
class Recharge : public WindowBase class Recharge : public WindowBase
{ {
public: public:
@ -25,7 +27,7 @@ protected:
MyGUI::Widget* mGemBox; MyGUI::Widget* mGemBox;
MyGUI::ImageBox* mGemIcon; ItemWidget* mGemIcon;
MyGUI::TextBox* mChargeLabel; MyGUI::TextBox* mChargeLabel;

View file

@ -13,6 +13,8 @@
#include "widgets.hpp" #include "widgets.hpp"
#include "itemwidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -44,12 +46,7 @@ void Repair::startRepairItem(const MWWorld::Ptr &item)
{ {
mRepair.setTool(item); mRepair.setTool(item);
std::string path = std::string("icons\\"); mToolIcon->setItem(item);
path += item.getClass().getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
mToolIcon->setImageTexture (path);
mToolIcon->setUserString("ToolTipType", "ItemPtr"); mToolIcon->setUserString("ToolTipType", "ItemPtr");
mToolIcon->setUserData(item); mToolIcon->setUserData(item);
@ -113,14 +110,9 @@ void Repair::updateRepairView()
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);
currentY += 19; currentY += 19;
MyGUI::ImageBox* icon = mRepairView->createWidget<MyGUI::ImageBox> ( ItemWidget* icon = mRepairView->createWidget<ItemWidget> (
"ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\"); icon->setItem(*iter);
path += iter->getClass().getInventoryIcon(*iter);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
icon->setImageTexture (path);
icon->setUserString("ToolTipType", "ItemPtr"); icon->setUserString("ToolTipType", "ItemPtr");
icon->setUserData(*iter); icon->setUserData(*iter);
icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem); icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem);

View file

@ -8,6 +8,8 @@
namespace MWGui namespace MWGui
{ {
class ItemWidget;
class Repair : public WindowBase class Repair : public WindowBase
{ {
public: public:
@ -25,7 +27,7 @@ protected:
MyGUI::Widget* mToolBox; MyGUI::Widget* mToolBox;
MyGUI::ImageBox* mToolIcon; ItemWidget* mToolIcon;
MyGUI::TextBox* mUsesLabel; MyGUI::TextBox* mUsesLabel;
MyGUI::TextBox* mQualityLabel; MyGUI::TextBox* mQualityLabel;

View file

@ -400,7 +400,7 @@ namespace MWGui
if (!info.effects.empty()) if (!info.effects.empty())
{ {
MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("", MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
MyGUI::IntCoord(0, totalSize.height, 300, 300-totalSize.height), MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height),
MyGUI::Align::Stretch, "ToolTipEffectArea"); MyGUI::Align::Stretch, "ToolTipEffectArea");
MyGUI::IntCoord coord(0, 6, totalSize.width, 24); MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
@ -419,7 +419,7 @@ namespace MWGui
{ {
assert(enchant); assert(enchant);
MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("", MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
MyGUI::IntCoord(0, totalSize.height, 300, 300-totalSize.height), MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height),
MyGUI::Align::Stretch, "ToolTipEnchantArea"); MyGUI::Align::Stretch, "ToolTipEnchantArea");
MyGUI::IntCoord coord(0, 6, totalSize.width, 24); MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
@ -512,7 +512,11 @@ namespace MWGui
std::string ToolTips::toString(const float value) std::string ToolTips::toString(const float value)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << std::setprecision(3) << value;
if (value != int(value))
stream << std::setprecision(3);
stream << value;
return stream.str(); return stream.str();
} }

View file

@ -345,7 +345,7 @@ namespace MWGui
x += abs(int(npcTerm - pcTerm)); x += abs(int(npcTerm - pcTerm));
int roll = std::rand()%100 + 1; int roll = std::rand()%100 + 1;
if(roll > x) //trade refused if(roll > x || (mCurrentMerchantOffer < 0) != (mCurrentBalance < 0)) //trade refused
{ {
MWBase::Environment::get().getWindowManager()-> MWBase::Environment::get().getWindowManager()->
messageBox("#{sNotifyMessage9}"); messageBox("#{sNotifyMessage9}");

View file

@ -42,4 +42,9 @@ bool VideoWidget::update()
return mPlayer.isPlaying(); return mPlayer.isPlaying();
} }
void VideoWidget::cleanup()
{
mPlayer.close();
}
} }

View file

@ -26,6 +26,9 @@ namespace MWGui
/// @return Is the video still playing? /// @return Is the video still playing?
bool update(); bool update();
/// Free video player resources (done automatically on destruction)
void cleanup();
private: private:
bool mAllowSkipping; bool mAllowSkipping;

View file

@ -64,6 +64,7 @@
#include "fontloader.hpp" #include "fontloader.hpp"
#include "videowidget.hpp" #include "videowidget.hpp"
#include "backgroundimage.hpp" #include "backgroundimage.hpp"
#include "itemwidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -166,6 +167,7 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget");
BookPage::registerMyGUIComponents (); BookPage::registerMyGUIComponents ();
ItemView::registerComponents(); ItemView::registerComponents();
ItemWidget::registerComponents();
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatClick>("Controller"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatClick>("Controller");
@ -1579,12 +1581,13 @@ namespace MWGui
bool cursorWasVisible = mCursorVisible; bool cursorWasVisible = mCursorVisible;
setCursorVisible(false); setCursorVisible(false);
while (mVideoWidget->update()) while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
{ {
MWBase::Environment::get().getInputManager()->update(0, true, false); MWBase::Environment::get().getInputManager()->update(0, true, false);
mRendering->getWindow()->update(); mRendering->getWindow()->update();
} }
mVideoWidget->cleanup();
setCursorVisible(cursorWasVisible); setCursorVisible(cursorWasVisible);

View file

@ -118,6 +118,7 @@ namespace MWInput
, mTimeIdle(0.f) , mTimeIdle(0.f)
, mOverencumberedMessageDelay(0.f) , mOverencumberedMessageDelay(0.f)
, mAlwaysRunActive(false) , mAlwaysRunActive(false)
, mAttemptJump(false)
, mControlsDisabled(false) , mControlsDisabled(false)
{ {
@ -165,6 +166,21 @@ namespace MWInput
delete mInputManager; delete mInputManager;
} }
void InputManager::setPlayerControlsEnabled(bool enabled)
{
int nPlayerChannels = 17;
int playerChannels[] = {A_Activate, A_AutoMove, A_AlwaysRun, A_ToggleWeapon,
A_ToggleSpell, A_Rest, A_QuickKey1, A_QuickKey2,
A_QuickKey3, A_QuickKey4, A_QuickKey5, A_QuickKey6,
A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10,
A_Use};
for(int i = 0; i < nPlayerChannels; i++) {
int pc = playerChannels[i];
mInputBinder->getChannel(pc)->setEnabled(enabled);
}
}
void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue)
{ {
if (mDragDrop) if (mDragDrop)
@ -179,6 +195,11 @@ namespace MWInput
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue);
} }
if (action == A_Jump)
{
mAttemptJump = (currentValue == 1.0 && previousValue == 0.0);
}
if (currentValue == 1) if (currentValue == 1)
{ {
// trigger action activated // trigger action activated
@ -305,107 +326,107 @@ namespace MWInput
} }
// Disable movement in Gui mode // Disable movement in Gui mode
if (MWBase::Environment::get().getWindowManager()->isGuiMode() if (!(MWBase::Environment::get().getWindowManager()->isGuiMode()
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running) || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running))
return;
// Configure player movement according to keyboard input. Actual movement will
// be done in the physics system.
if (mControlSwitch["playercontrols"])
{ {
bool triedToMove = false; // Configure player movement according to keyboard input. Actual movement will
if (actionIsActive(A_MoveLeft)) // be done in the physics system.
if (mControlSwitch["playercontrols"])
{ {
triedToMove = true; bool triedToMove = false;
mPlayer->setLeftRight (-1); if (actionIsActive(A_MoveLeft))
}
else if (actionIsActive(A_MoveRight))
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
if (actionIsActive(A_MoveForward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;
mPlayer->setForwardBackward (1);
}
mPlayer->setSneak(actionIsActive(A_Sneak));
if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"])
{
mPlayer->setUpDown (1);
triedToMove = true;
}
if (mAlwaysRunActive)
mPlayer->setRunState(!actionIsActive(A_Run));
else
mPlayer->setRunState(actionIsActive(A_Run));
// if player tried to start moving, but can't (due to being overencumbered), display a notification.
if (triedToMove)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
mOverencumberedMessageDelay -= dt;
if (player.getClass().getEncumbrance(player) >= player.getClass().getCapacity(player))
{ {
triedToMove = true;
mPlayer->setLeftRight (-1);
}
else if (actionIsActive(A_MoveRight))
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
if (actionIsActive(A_MoveForward))
{
triedToMove = true;
mPlayer->setAutoMove (false); mPlayer->setAutoMove (false);
if (mOverencumberedMessageDelay <= 0) mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;
mPlayer->setForwardBackward (1);
}
mPlayer->setSneak(actionIsActive(A_Sneak));
if (mAttemptJump && mControlSwitch["playerjumping"])
{
mPlayer->setUpDown (1);
triedToMove = true;
}
if (mAlwaysRunActive)
mPlayer->setRunState(!actionIsActive(A_Run));
else
mPlayer->setRunState(actionIsActive(A_Run));
// if player tried to start moving, but can't (due to being overencumbered), display a notification.
if (triedToMove)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
mOverencumberedMessageDelay -= dt;
if (player.getClass().getEncumbrance(player) >= player.getClass().getCapacity(player))
{ {
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}"); mPlayer->setAutoMove (false);
mOverencumberedMessageDelay = 1.0; if (mOverencumberedMessageDelay <= 0)
{
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}");
mOverencumberedMessageDelay = 1.0;
}
}
}
if (mControlSwitch["playerviewswitch"]) {
// work around preview mode toggle when pressing Alt+Tab
if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) {
if (mPreviewPOVDelay <= 0.5 &&
(mPreviewPOVDelay += dt) > 0.5)
{
mPreviewPOVDelay = 1.f;
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
}
} else {
//disable preview mode
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) {
MWBase::Environment::get().getWorld()->togglePOV();
}
mPreviewPOVDelay = 0.f;
} }
} }
} }
if (actionIsActive(A_MoveForward) ||
if (mControlSwitch["playerviewswitch"]) { actionIsActive(A_MoveBackward) ||
actionIsActive(A_MoveLeft) ||
// work around preview mode toggle when pressing Alt+Tab actionIsActive(A_MoveRight) ||
if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) { actionIsActive(A_Jump) ||
if (mPreviewPOVDelay <= 0.5 && actionIsActive(A_Sneak) ||
(mPreviewPOVDelay += dt) > 0.5) actionIsActive(A_TogglePOV))
{ {
mPreviewPOVDelay = 1.f; resetIdleTime();
MWBase::Environment::get().getWorld()->togglePreviewMode(true); } else {
} updateIdleTime(dt);
} else {
//disable preview mode
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) {
MWBase::Environment::get().getWorld()->togglePOV();
}
mPreviewPOVDelay = 0.f;
}
} }
} }
if (actionIsActive(A_MoveForward) || mAttemptJump = false; // Can only jump on first frame input is on
actionIsActive(A_MoveBackward) ||
actionIsActive(A_MoveLeft) ||
actionIsActive(A_MoveRight) ||
actionIsActive(A_Jump) ||
actionIsActive(A_Sneak) ||
actionIsActive(A_TogglePOV))
{
resetIdleTime();
} else {
updateIdleTime(dt);
}
} }
void InputManager::setDragDrop(bool dragDrop) void InputManager::setDragDrop(bool dragDrop)
@ -517,13 +538,15 @@ namespace MWInput
} }
} }
if (!mControlsDisabled)
mInputBinder->keyPressed (arg);
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
if (kc != OIS::KC_UNASSIGNED) if (kc != OIS::KC_UNASSIGNED)
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); {
bool guiFocus = MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0);
setPlayerControlsEnabled(!guiFocus);
}
if (!mControlsDisabled)
mInputBinder->keyPressed (arg);
} }
void InputManager::textInput(const SDL_TextInputEvent &arg) void InputManager::textInput(const SDL_TextInputEvent &arg)
@ -536,36 +559,51 @@ namespace MWInput
void InputManager::keyReleased(const SDL_KeyboardEvent &arg ) void InputManager::keyReleased(const SDL_KeyboardEvent &arg )
{ {
mInputBinder->keyReleased (arg);
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)); setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)));
mInputBinder->keyReleased (arg);
} }
void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id )
{ {
mInputBinder->mousePressed (arg, id); bool guiMode = false;
if (id != SDL_BUTTON_LEFT && id != SDL_BUTTON_RIGHT) if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI only uses these mouse events
return; // MyGUI has no use for these events
MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id));
if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0)
{ {
MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType<MyGUI::Button>(false); guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
if (b && b->getEnabled()) guiMode = MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)) && guiMode;
if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0)
{ {
MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType<MyGUI::Button>(false);
if (b && b->getEnabled())
{
MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f);
}
} }
} }
setPlayerControlsEnabled(!guiMode);
mInputBinder->mousePressed (arg, id);
} }
void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id )
{ {
mInputBinder->mouseReleased (arg, id);
MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); if(mInputBinder->detectingBindingState())
{
mInputBinder->mouseReleased (arg, id);
} else {
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)) && guiMode;
if(mInputBinder->detectingBindingState()) return; // don't allow same mouseup to bind as initiated bind
setPlayerControlsEnabled(!guiMode);
mInputBinder->mouseReleased (arg, id);
}
} }
void InputManager::mouseMoved(const SFO::MouseMotionEvent &arg ) void InputManager::mouseMoved(const SFO::MouseMotionEvent &arg )

View file

@ -163,6 +163,7 @@ namespace MWInput
int mMouseWheel; int mMouseWheel;
bool mUserFileExists; bool mUserFileExists;
bool mAlwaysRunActive; bool mAlwaysRunActive;
bool mAttemptJump;
std::map<std::string, bool> mControlSwitch; std::map<std::string, bool> mControlSwitch;
@ -173,6 +174,8 @@ namespace MWInput
void resetIdleTime(); void resetIdleTime();
void updateIdleTime(float dt); void updateIdleTime(float dt);
void setPlayerControlsEnabled(bool enabled);
private: private:
void toggleMainMenu(); void toggleMainMenu();
void toggleSpell(); void toggleSpell();

View file

@ -932,7 +932,7 @@ namespace MWMechanics
for (std::list<MWWorld::Ptr>::iterator it = listGuards.begin(); it != listGuards.end(); ++it) for (std::list<MWWorld::Ptr>::iterator it = listGuards.begin(); it != listGuards.end(); ++it)
{ {
engageCombat(iter->first, *it, false); engageCombat(iter->first, *it, *it == player);
} }
} }
@ -1088,10 +1088,10 @@ namespace MWMechanics
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
float healthHours = healthPerHour >= 0 float healthHours = healthPerHour > 0
? (stats.getHealth().getModified() - stats.getHealth().getCurrent()) / healthPerHour ? (stats.getHealth().getModified() - stats.getHealth().getCurrent()) / healthPerHour
: 1.0f; : 1.0f;
float magickaHours = magickaPerHour >= 0 float magickaHours = magickaPerHour > 0
? (stats.getMagicka().getModified() - stats.getMagicka().getCurrent()) / magickaPerHour ? (stats.getMagicka().getModified() - stats.getMagicka().getCurrent()) / magickaPerHour
: 1.0f; : 1.0f;

View file

@ -395,7 +395,8 @@ int MWMechanics::Alchemy::addIngredient (const MWWorld::Ptr& ingredient)
return -1; return -1;
for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter) for (TIngredientsIterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter)
if (!iter->isEmpty() && ingredient.get<ESM::Ingredient>()==iter->get<ESM::Ingredient>()) if (!iter->isEmpty() && Misc::StringUtils::ciEqual(ingredient.getClass().getId(ingredient),
iter->getClass().getId(*iter)))
return -1; return -1;
mIngredients[slot] = ingredient; mIngredients[slot] = ingredient;

View file

@ -409,6 +409,13 @@ MWWorld::ContainerStoreIterator getActiveWeapon(CreatureStats &stats, MWWorld::I
void CharacterController::playDeath(float startpoint, CharacterState death) void CharacterController::playDeath(float startpoint, CharacterState death)
{ {
if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr())
{
// The first-person animations do not include death, so we need to
// force-switch to third person before playing the death animation.
MWBase::Environment::get().getWorld()->useDeathCamera();
}
switch (death) switch (death)
{ {
case CharState_SwimDeath: case CharState_SwimDeath:

View file

@ -73,9 +73,16 @@ namespace MWMechanics
return false; return false;
MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker); MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker);
// Don't block when in spellcasting state (shield is equipped, but not visible)
if (blockerStats.getDrawState() == DrawState_Spell) if (blockerStats.getDrawState() == DrawState_Spell)
return false; return false;
// Don't block when in hand-to-hand combat (shield is equipped, but not visible)
if (blockerStats.getDrawState() == DrawState_Weapon &&
inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight) == inv.end())
return false;
MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker);
float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2 * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2 * blockerStats.getAttribute(ESM::Attribute::Agility).getModified()

View file

@ -140,11 +140,11 @@ namespace MWRender
} }
} }
void Camera::toggleViewMode() void Camera::toggleViewMode(bool force)
{ {
// Changing the view will stop all playing animations, so if we are playing // Changing the view will stop all playing animations, so if we are playing
// anything important, queue the view change for later // anything important, queue the view change for later
if (!mAnimation->allowSwitchViewMode()) if (!mAnimation->allowSwitchViewMode() && !force)
{ {
mViewModeToggleQueued = true; mViewModeToggleQueued = true;
return; return;

View file

@ -75,7 +75,8 @@ namespace MWRender
/// Attach camera to object /// Attach camera to object
void attachTo(const MWWorld::Ptr &); void attachTo(const MWWorld::Ptr &);
void toggleViewMode(); /// @param Force view mode switch, even if currently not allowed by the animation.
void toggleViewMode(bool force=false);
bool toggleVanityMode(bool enable); bool toggleVanityMode(bool enable);
void allowVanityMode(bool allow); void allowVanityMode(bool allow);

View file

@ -308,7 +308,7 @@ void NpcAnimation::updateParts()
ESM::PartReferenceType parts[] = { ESM::PartReferenceType parts[] = {
ESM::PRT_Groin, ESM::PRT_Skirt, ESM::PRT_RLeg, ESM::PRT_LLeg, ESM::PRT_Groin, ESM::PRT_Skirt, ESM::PRT_RLeg, ESM::PRT_LLeg,
ESM::PRT_RUpperarm, ESM::PRT_LUpperarm, ESM::PRT_RKnee, ESM::PRT_LKnee, ESM::PRT_RUpperarm, ESM::PRT_LUpperarm, ESM::PRT_RKnee, ESM::PRT_LKnee,
ESM::PRT_RForearm, ESM::PRT_LForearm, ESM::PRT_RPauldron, ESM::PRT_LPauldron ESM::PRT_RForearm, ESM::PRT_LForearm
}; };
size_t parts_size = sizeof(parts)/sizeof(parts[0]); size_t parts_size = sizeof(parts)/sizeof(parts[0]);
for(size_t p = 0;p < parts_size;++p) for(size_t p = 0;p < parts_size;++p)
@ -351,8 +351,6 @@ void NpcAnimation::updateParts()
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination // Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping; static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping;
static std::map <std::pair<std::string,int>, std::vector<const ESM::BodyPart*> > sVampireMapping;
static const int Flag_Female = 1<<0; static const int Flag_Female = 1<<0;
static const int Flag_FirstPerson = 1<<1; static const int Flag_FirstPerson = 1<<1;
@ -408,8 +406,6 @@ void NpcAnimation::updateParts()
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin) if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
continue; continue;
if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
continue;
if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace)) if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace))
continue; continue;
@ -435,6 +431,20 @@ void NpcAnimation::updateParts()
} }
continue; continue;
} }
if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
{
// Allow opposite gender's parts as fallback if parts for our gender are missing
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));
while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart)
{
if(!parts[bIt->second])
parts[bIt->second] = &*it;
++bIt;
}
continue;
}
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart)); BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));
while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart) while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart)
{ {

View file

@ -144,7 +144,6 @@ void MWState::StateManager::newGame (bool bypass)
void MWState::StateManager::endGame() void MWState::StateManager::endGame()
{ {
mState = State_Ended; mState = State_Ended;
MWBase::Environment::get().getWorld()->useDeathCamera();
} }
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot) void MWState::StateManager::saveGame (const std::string& description, const Slot *slot)

View file

@ -41,6 +41,8 @@ namespace MWWorld
// slots that this item can be equipped in // slots that this item can be equipped in
std::pair<std::vector<int>, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget()); std::pair<std::vector<int>, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget());
if (slots_.first.empty())
return;
// retrieve ContainerStoreIterator to the item // retrieve ContainerStoreIterator to the item
MWWorld::ContainerStoreIterator it = invStore.begin(); MWWorld::ContainerStoreIterator it = invStore.begin();
@ -55,20 +57,13 @@ namespace MWWorld
assert(it != invStore.end()); assert(it != invStore.end());
// equip the item in the first free slot // equip the item in the first free slot
for (std::vector<int>::const_iterator slot=slots_.first.begin(); std::vector<int>::const_iterator slot=slots_.first.begin();
slot!=slots_.first.end(); ++slot) for (;slot!=slots_.first.end(); ++slot)
{ {
// if the item is equipped already, nothing to do // if the item is equipped already, nothing to do
if (invStore.getSlot(*slot) == it) if (invStore.getSlot(*slot) == it)
return; return;
// if all slots are occupied, replace the last slot
if (slot == --slots_.first.end())
{
invStore.equip(*slot, it, actor);
break;
}
if (invStore.getSlot(*slot) == invStore.end()) if (invStore.getSlot(*slot) == invStore.end())
{ {
// slot is not occupied // slot is not occupied
@ -76,5 +71,19 @@ namespace MWWorld
break; break;
} }
} }
// all slots are occupied -> cycle
// move all slots one towards begin(), then equip the item in the slot that is now free
if (slot == slots_.first.end())
{
for (slot=slots_.first.begin();slot!=slots_.first.end(); ++slot)
{
invStore.unequipSlot(*slot, actor);
if (slot+1 != slots_.first.end())
invStore.equip(*slot, invStore.getSlot(*(slot+1)), actor);
else
invStore.equip(*slot, it, actor);
}
}
} }
} }

View file

@ -299,17 +299,33 @@ namespace MWWorld
continue; // velocity updated, calculate nextpos again continue; // velocity updated, calculate nextpos again
} }
// trace to where character would go if there were no obstructions if(!newPosition.positionCloses(nextpos, 0.00000001))
tracer.doTrace(colobj, newPosition, nextpos, engine);
// check for obstructions
if(tracer.mFraction >= 1.0f)
{ {
newPosition = tracer.mEndPos; // ok to move, so set newPosition // trace to where character would go if there were no obstructions
tracer.doTrace(colobj, newPosition, nextpos, engine);
// check for obstructions
if(tracer.mFraction >= 1.0f)
{
newPosition = tracer.mEndPos; // ok to move, so set newPosition
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
break;
}
}
else
{
// The current position and next position are nearly the same, so just exit.
// Note: Bullet can trigger an assert in debug modes if the positions
// are the same, since that causes it to attempt to normalize a zero
// length vector (which can also happen with nearly identical vectors, since
// precision can be lost due to any math Bullet does internally). Since we
// aren't performing any collision detection, we want to reject the next
// position, so that we don't slowly move inside another object.
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it? remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
break; break;
} }
Ogre::Vector3 oldPosition = newPosition; Ogre::Vector3 oldPosition = newPosition;
// We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over) // We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over)
// NOTE: stepMove modifies newPosition if successful // NOTE: stepMove modifies newPosition if successful
@ -492,7 +508,7 @@ namespace MWWorld
return std::make_pair(true, ray.getPoint(len * test.second)); return std::make_pair(true, ray.getPoint(len * test.second));
} }
std::pair<bool, Ogre::Vector3> PhysicsSystem::castRay(float mouseX, float mouseY, Ogre::Vector3* normal) std::pair<bool, Ogre::Vector3> PhysicsSystem::castRay(float mouseX, float mouseY, Ogre::Vector3* normal, std::string* hit)
{ {
Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay( Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay(
mouseX, mouseX,
@ -510,6 +526,8 @@ namespace MWWorld
return std::make_pair(false, Ogre::Vector3()); return std::make_pair(false, Ogre::Vector3());
else else
{ {
if (hit != NULL)
*hit = result.first;
return std::make_pair(true, ray.getPoint(200*result.second)); /// \todo make this distance (ray length) configurable return std::make_pair(true, ray.getPoint(200*result.second)); /// \todo make this distance (ray length) configurable
} }
} }

View file

@ -70,9 +70,10 @@ namespace MWWorld
std::pair<bool, Ogre::Vector3> std::pair<bool, Ogre::Vector3>
castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len); castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len);
std::pair<bool, Ogre::Vector3> castRay(float mouseX, float mouseY, Ogre::Vector3* normal = NULL); std::pair<bool, Ogre::Vector3> castRay(float mouseX, float mouseY, Ogre::Vector3* normal = NULL, std::string* hit = NULL);
///< cast ray from the mouse, return true if it hit something and the first result ///< cast ray from the mouse, return true if it hit something and the first result
/// @param normal if non-NULL, the hit normal will be written there (if there is a hit) /// @param normal if non-NULL, the hit normal will be written there (if there is a hit)
/// @param hit if non-NULL, the string handle of the hit object will be written there (if there is a hit)
OEngine::Physic::PhysicEngine* getEngine(); OEngine::Physic::PhysicEngine* getEngine();

View file

@ -432,7 +432,7 @@ namespace MWWorld
mRendering->getCamera()->toggleVanityMode(false); mRendering->getCamera()->toggleVanityMode(false);
} }
if(mRendering->getCamera()->isFirstPerson()) if(mRendering->getCamera()->isFirstPerson())
togglePOV(); mRendering->getCamera()->toggleViewMode(true);
} }
MWWorld::Player& World::getPlayer() MWWorld::Player& World::getPlayer()
@ -1624,12 +1624,20 @@ namespace MWWorld
bool World::canPlaceObject(float cursorX, float cursorY) bool World::canPlaceObject(float cursorX, float cursorY)
{ {
Ogre::Vector3 normal(0,0,0); Ogre::Vector3 normal(0,0,0);
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY, &normal); std::string handle;
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY, &normal, &handle);
if (result.first) if (result.first)
{ {
// check if the wanted position is on a flat surface, and not e.g. against a vertical wall // check if the wanted position is on a flat surface, and not e.g. against a vertical wall
return (normal.angleBetween(Ogre::Vector3(0.f,0.f,1.f)).valueDegrees() < 30); if (normal.angleBetween(Ogre::Vector3(0.f,0.f,1.f)).valueDegrees() >= 30)
return false;
MWWorld::Ptr hitObject = searchPtrViaHandle(handle);
if (!hitObject.isEmpty() && hitObject.getClass().isActor())
return false;
return true;
} }
else else
return false; return false;
@ -1851,7 +1859,12 @@ namespace MWWorld
if (!mPlayer) if (!mPlayer)
mPlayer = new MWWorld::Player(player, *this); mPlayer = new MWWorld::Player(player, *this);
else else
{
// Remove the old CharacterController
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr());
mPlayer->set(player); mPlayer->set(player);
}
Ptr ptr = mPlayer->getPlayer(); Ptr ptr = mPlayer->getPlayer();
mRendering->setupPlayer(ptr); mRendering->setupPlayer(ptr);

View file

@ -413,12 +413,25 @@ struct NiMorphData : public Record
struct NiKeyframeData : public Record struct NiKeyframeData : public Record
{ {
QuaternionKeyList mRotations; QuaternionKeyList mRotations;
//\FIXME mXYZ_Keys are read, but not used.
FloatKeyList mXYZ_Keys;
Vector3KeyList mTranslations; Vector3KeyList mTranslations;
FloatKeyList mScales; FloatKeyList mScales;
void read(NIFStream *nif) void read(NIFStream *nif)
{ {
mRotations.read(nif); mRotations.read(nif);
if(mRotations.mInterpolationType == mRotations.sXYZInterpolation)
{
//Chomp unused float
nif->getFloat();
for(size_t i=0;i<3;++i)
{
//Read concatenates items together.
mXYZ_Keys.read(nif,true);
}
nif->file->warn("XYZ_ROTATION_KEY read, but not used!");
}
mTranslations.read(nif); mTranslations.read(nif);
mScales.read(nif); mScales.read(nif);
} }

View file

@ -113,24 +113,24 @@ public:
}; };
/// Get a given record /// Get a given record
Record *getRecord(size_t index) Record *getRecord(size_t index) const
{ {
Record *res = records.at(index); Record *res = records.at(index);
assert(res != NULL); assert(res != NULL);
return res; return res;
} }
/// Number of records /// Number of records
size_t numRecords() { return records.size(); } size_t numRecords() const { return records.size(); }
/// Get a given root /// Get a given root
Record *getRoot(size_t index=0) Record *getRoot(size_t index=0) const
{ {
Record *res = roots.at(index); Record *res = roots.at(index);
assert(res != NULL); assert(res != NULL);
return res; return res;
} }
/// Number of roots /// Number of roots
size_t numRoots() { return roots.size(); } size_t numRoots() const { return roots.size(); }
}; };
@ -153,96 +153,94 @@ template<typename T, T (NIFStream::*getValue)()>
struct KeyListT { struct KeyListT {
typedef std::vector< KeyT<T> > VecType; typedef std::vector< KeyT<T> > VecType;
static const int sLinearInterpolation = 1; static const unsigned int sLinearInterpolation = 1;
static const int sQuadraticInterpolation = 2; static const unsigned int sQuadraticInterpolation = 2;
static const int sTBCInterpolation = 3; static const unsigned int sTBCInterpolation = 3;
static const int sXYZInterpolation = 4; static const unsigned int sXYZInterpolation = 4;
int mInterpolationType; unsigned int mInterpolationType;
VecType mKeys; VecType mKeys;
//Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html)
void read(NIFStream *nif, bool force=false) void read(NIFStream *nif, bool force=false)
{ {
size_t count = nif->getInt(); assert(nif);
size_t count = nif->getUInt();
if(count == 0 && !force) if(count == 0 && !force)
return; return;
mInterpolationType = nif->getInt(); //If we aren't forcing things, make sure that read clears any previous keys
mKeys.resize(count); if(!force)
if(mInterpolationType == sLinearInterpolation) mKeys.clear();
mInterpolationType = nif->getUInt();
KeyT<T> key;
NIFStream &nifReference = *nif;
for(size_t i = 0;i < count;i++)
{ {
for(size_t i = 0;i < count;i++) if(mInterpolationType == sLinearInterpolation)
{ {
KeyT<T> &key = mKeys[i]; readTimeAndValue(nifReference, key);
key.mTime = nif->getFloat(); mKeys.push_back(key);
key.mValue = (nif->*getValue)();
} }
else if(mInterpolationType == sQuadraticInterpolation)
{
readQuadratic(nifReference, key);
mKeys.push_back(key);
}
else if(mInterpolationType == sTBCInterpolation)
{
readTBC(nifReference, key);
mKeys.push_back(key);
}
//XYZ keys aren't actually read here.
//data.hpp sees that the last type read was sXYZInterpolation and:
// Eats a floating point number, then
// Re-runs the read function 3 more times, with force enabled so that the previous values aren't cleared.
// When it does that it's reading in a bunch of sLinearInterpolation keys, not sXYZInterpolation.
else if(mInterpolationType == sXYZInterpolation)
{
//Don't try to read XYZ keys into the wrong part
if ( count != 1 )
nif->file->fail("XYZ_ROTATION_KEY count should always be '1' . Retrieved Value: "+Ogre::StringConverter::toString(count));
}
else if (0 == mInterpolationType)
{
if (count != 0)
nif->file->fail("Interpolation type 0 doesn't work with keys");
}
else
nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType));
} }
else if(mInterpolationType == sQuadraticInterpolation)
{
for(size_t i = 0;i < count;i++)
{
KeyT<T> &key = mKeys[i];
key.mTime = nif->getFloat();
key.mValue = (nif->*getValue)();
if( typeid(Ogre::Quaternion) != typeid(T) )
{
key.mForwardValue = (nif->*getValue)();
key.mBackwardValue = (nif->*getValue)();
}
}
}
else if(mInterpolationType == sTBCInterpolation)
{
for(size_t i = 0;i < count;i++)
{
KeyT<T> &key = mKeys[i];
key.mTime = nif->getFloat();
key.mValue = (nif->*getValue)();
key.mTension = nif->getFloat();
key.mBias = nif->getFloat();
key.mContinuity = nif->getFloat();
}
}
//\FIXME This now reads the correct amount of data in the file, but doesn't actually do anything with it.
else if(mInterpolationType == sXYZInterpolation)
{
if (count != 1)
{
nif->file->fail("count should always be '1' for XYZ_ROTATION_KEY. Retrieved Value: "+Ogre::StringConverter::toString(count));
return;
}
//KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html)
//Chomp unknown and possibly unused float
nif->getFloat();
for(size_t i=0;i<3;++i)
{
unsigned int numKeys = nif->getInt();
if(numKeys != 0)
{
int interpolationTypeAgain = nif->getInt();
if( interpolationTypeAgain != sLinearInterpolation)
{
nif->file->fail("XYZ_ROTATION_KEY's KeyGroup keyType must be '1' (Linear Interpolation). Retrieved Value: "+Ogre::StringConverter::toString(interpolationTypeAgain));
return;
}
for(size_t j = 0;j < numKeys;j++)
{
//For now just chomp these
nif->getFloat();
nif->getFloat();
}
}
nif->file->warn("XYZ_ROTATION_KEY read, but not used!");
}
} }
else if (mInterpolationType == 0)
{ private:
if (count != 0) static void readTimeAndValue(NIFStream &nif, KeyT<T> &key)
nif->file->fail("Interpolation type 0 doesn't work with keys"); {
} key.mTime = nif.getFloat();
else key.mValue = (nif.*getValue)();
nif->file->fail("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); }
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
{
readTimeAndValue(nif, key);
}
template <typename U>
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
{
readTimeAndValue(nif, key);
key.mForwardValue = (nif.*getValue)();
key.mBackwardValue = (nif.*getValue)();
}
static void readTBC(NIFStream &nif, KeyT<T> &key)
{
readTimeAndValue(nif, key);
key.mTension = nif.getFloat();
key.mBias = nif.getFloat();
key.mContinuity = nif.getFloat();
} }
}; };
typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList; typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList;

View file

@ -36,6 +36,7 @@ Eli2
Emanuel Guével (potatoesmaster) Emanuel Guével (potatoesmaster)
Fil Krynicki (filkry) Fil Krynicki (filkry)
gugus/gus gugus/gus
Hallfaer Tuilinn
Jacob Essex (Yacoby) Jacob Essex (Yacoby)
Jannik Heller (scrawl) Jannik Heller (scrawl)
Jason Hooks (jhooks) Jason Hooks (jhooks)

View file

@ -38,6 +38,7 @@ namespace ICS
, mValue(initialValue) , mValue(initialValue)
, mSymmetricAt(symmetricAt) , mSymmetricAt(symmetricAt)
, mBezierStep(bezierStep) , mBezierStep(bezierStep)
, mEnabled(true)
{ {
mBezierMidPoint.x = bezierMidPointX; mBezierMidPoint.x = bezierMidPointX;
mBezierMidPoint.y = bezierMidPointY; mBezierMidPoint.y = bezierMidPointY;
@ -45,6 +46,11 @@ namespace ICS
setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep); setBezierFunction(bezierMidPointY, bezierMidPointX, symmetricAt, bezierStep);
} }
void Channel::setEnabled(bool enabled)
{
mEnabled = enabled;
}
float Channel::getValue() float Channel::getValue()
{ {
if(mValue == 0 || mValue == 1) if(mValue == 0 || mValue == 1)
@ -78,7 +84,7 @@ namespace ICS
mValue = value; mValue = value;
if(previousValue != value) if(previousValue != value && mEnabled)
{ {
notifyListeners(previousValue); notifyListeners(previousValue);
} }
@ -124,7 +130,7 @@ namespace ICS
void Channel::update() void Channel::update()
{ {
if(this->getControlsCount() == 1) if(this->getControlsCount() == 1)
{ {
ControlChannelBinderItem ccBinderItem = mAttachedControls.back(); ControlChannelBinderItem ccBinderItem = mAttachedControls.back();
float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue(); float diff = ccBinderItem.control->getValue() - ccBinderItem.control->getInitialValue();

View file

@ -89,6 +89,8 @@ namespace ICS
IntervalList& getIntervals(){ return mIntervals; }; IntervalList& getIntervals(){ return mIntervals; };
void setEnabled(bool enabled);
protected: protected:
int mNumber; int mNumber;
@ -112,7 +114,9 @@ namespace ICS
std::vector<ControlChannelBinderItem> mAttachedControls; std::vector<ControlChannelBinderItem> mAttachedControls;
std::list<ChannelListener* > mListeners; std::list<ChannelListener* > mListeners;
void notifyListeners(float previousValue); void notifyListeners(float previousValue);
bool mEnabled;
}; };

View file

@ -796,6 +796,11 @@ namespace ICS
mMouseAxisBindingInitialValues[0] = ICS_MOUSE_AXIS_BINDING_NULL_VALUE; mMouseAxisBindingInitialValues[0] = ICS_MOUSE_AXIS_BINDING_NULL_VALUE;
} }
bool InputControlSystem::detectingBindingState()
{
return mDetectingBindingControl != NULL;
}
void InputControlSystem::cancelDetectingBindingState() void InputControlSystem::cancelDetectingBindingState()
{ {
mDetectingBindingControl = NULL; mDetectingBindingControl = NULL;

View file

@ -146,6 +146,7 @@ namespace ICS
void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction); void enableDetectingBindingState(Control* control, Control::ControlChangingDirection direction);
void cancelDetectingBindingState(); void cancelDetectingBindingState();
bool detectingBindingState();
bool save(std::string fileName = ""); bool save(std::string fileName = "");

View file

@ -23,21 +23,13 @@
<Widget type="Widget" skin="" position="10 66 260 50"> <Widget type="Widget" skin="" position="10 66 260 50">
<Widget type="Widget" skin="MW_Box" position="0 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 50 50" name="Apparatus1"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Apparatus1"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="60 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="60 0 50 50" name="Apparatus2"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Apparatus2"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="120 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="120 0 50 50" name="Apparatus3"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Apparatus3"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="180 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="180 0 50 50" name="Apparatus4"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Apparatus4"/>
</Widget>
</Widget> </Widget>
@ -51,21 +43,13 @@
<Widget type="Widget" skin="" position="10 146 260 50"> <Widget type="Widget" skin="" position="10 146 260 50">
<Widget type="Widget" skin="MW_Box" position="0 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 50 50" name="Ingredient1"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Ingredient1"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="60 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="60 0 50 50" name="Ingredient2"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Ingredient2"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="120 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="120 0 50 50" name="Ingredient3"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Ingredient3"/>
</Widget>
<Widget type="Widget" skin="MW_Box" position="180 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="180 0 50 50" name="Ingredient4"/>
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="Ingredient4"/>
</Widget>
</Widget> </Widget>

View file

@ -73,4 +73,9 @@ as around the sections of the stats window, or around popup info windows -->
<Child type="Widget" skin="IB_BL" offset="0 514 2 2" align="Bottom Left"/> <Child type="Widget" skin="IB_BL" offset="0 514 2 2" align="Bottom Left"/>
<Child type="Widget" skin="IB_BR" offset="514 514 2 2" align="Bottom Right"/> <Child type="Widget" skin="IB_BR" offset="514 514 2 2" align="Bottom Right"/>
</Skin> </Skin>
<Skin name="MW_Box_Overlay" size="516 516">
<Property key="NeedMouse" value="false"/>
<Child type="Widget" skin="MW_Box" offset="0 0 516 516" align="Stretch"/>
</Skin>
</MyGUI> </MyGUI>

View file

@ -26,8 +26,7 @@
<Widget type="AutoSizedTextBox" skin="NormalText"> <Widget type="AutoSizedTextBox" skin="NormalText">
<Property key="Caption" value="#{sItem}"/> <Property key="Caption" value="#{sItem}"/>
</Widget> </Widget>
<Widget type="Widget" skin="MW_Box" position="0 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 50 50" name="ItemBox">
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="ItemBox"/>
</Widget> </Widget>
<Widget type="Widget" position="0 0 8 0"/> <Widget type="Widget" position="0 0 8 0"/>
@ -35,8 +34,7 @@
<Widget type="AutoSizedTextBox" skin="NormalText"> <Widget type="AutoSizedTextBox" skin="NormalText">
<Property key="Caption" value="#{sSoulGem}"/> <Property key="Caption" value="#{sSoulGem}"/>
</Widget> </Widget>
<Widget type="Button" skin="MW_Box" position="0 0 50 50"> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 50 50" name="SoulBox">
<Widget type="ImageBox" skin="ImageBox" position="9 9 32 32" name="SoulBox"/>
</Widget> </Widget>
</Widget> </Widget>

View file

@ -59,7 +59,7 @@
<Widget type="Button" skin="" position="82 146 36 41" align="Left Bottom" name="WeapBox"> <Widget type="Button" skin="" position="82 146 36 41" align="Left Bottom" name="WeapBox">
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36"> <Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
<Property key="NeedMouse" value="false"/> <Property key="NeedMouse" value="false"/>
<Widget type="ImageBox" skin="ImageBox" position="2 2 32 32" align="Left Top" name="WeapImage"> <Widget type="ItemWidget" skin="MW_ItemIcon" position="-3 -3 42 42" align="Left Top" name="WeapImage">
<Property key="NeedMouse" value="false"/> <Property key="NeedMouse" value="false"/>
</Widget> </Widget>
</Widget> </Widget>
@ -71,7 +71,7 @@
<!-- Selected spell box --> <!-- Selected spell box -->
<Widget type="Button" position="122 146 36 41" align="Left Bottom" name="SpellBox"> <Widget type="Button" position="122 146 36 41" align="Left Bottom" name="SpellBox">
<Widget type="Widget" skin="HUD_Box" position="0 0 36 36"> <Widget type="Widget" skin="HUD_Box" position="0 0 36 36">
<Widget type="ImageBox" skin="ImageBox" position="2 2 32 32" align="Left Top" name="SpellImage"/> <Widget type="ItemWidget" skin="MW_ItemIcon" position="-3 -3 42 42" align="Left Top" name="SpellImage"/>
<Property key="NeedMouse" value="false"/> <Property key="NeedMouse" value="false"/>
</Widget> </Widget>
<Widget type="ProgressBar" skin="MW_EnergyBar_Red" position="0 36 36 6" align="Left Bottom" name="SpellStatus"> <Widget type="ProgressBar" skin="MW_EnergyBar_Red" position="0 36 36 6" align="Left Bottom" name="SpellStatus">

View file

@ -17,16 +17,16 @@
<Widget type="Widget" skin="" position="15 55 332 128" align="Left Bottom HCenter"> <Widget type="Widget" skin="" position="15 55 332 128" align="Left Bottom HCenter">
<Widget type="Button" skin="MW_Box" position="0 0 60 59" name="QuickKey1"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 60 59" name="QuickKey1"/>
<Widget type="Button" skin="MW_Box" position="68 0 60 59" name="QuickKey2"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 0 60 59" name="QuickKey2"/>
<Widget type="Button" skin="MW_Box" position="136 0 60 59" name="QuickKey3"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 0 60 59" name="QuickKey3"/>
<Widget type="Button" skin="MW_Box" position="204 0 60 59" name="QuickKey4"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 0 60 59" name="QuickKey4"/>
<Widget type="Button" skin="MW_Box" position="272 0 60 59" name="QuickKey5"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 0 60 59" name="QuickKey5"/>
<Widget type="Button" skin="MW_Box" position="0 67 60 59" name="QuickKey6"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 67 60 59" name="QuickKey6"/>
<Widget type="Button" skin="MW_Box" position="68 67 60 59" name="QuickKey7"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 67 60 59" name="QuickKey7"/>
<Widget type="Button" skin="MW_Box" position="136 67 60 59" name="QuickKey8"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 67 60 59" name="QuickKey8"/>
<Widget type="Button" skin="MW_Box" position="204 67 60 59" name="QuickKey9"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 67 60 59" name="QuickKey9"/>
<Widget type="Button" skin="MW_Box" position="272 67 60 59" name="QuickKey10"/> <Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 67 60 59" name="QuickKey10"/>
</Widget> </Widget>

View file

@ -4,7 +4,7 @@
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 329 253" name="_Main"> <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 329 253" name="_Main">
<Widget type="Widget" skin="" position="4 4 321 42" name="GemBox"> <Widget type="Widget" skin="" position="4 4 321 42" name="GemBox">
<Widget type="ImageBox" skin="ImageBox" position="5 6 32 32" name="GemIcon"/> <Widget type="ItemWidget" skin="MW_ItemIconSmall" position="5 6 32 32" name="GemIcon"/>
<Widget type="TextBox" skin="SandText" position="55 13 250 18" name="ChargeLabel"> <Widget type="TextBox" skin="SandText" position="55 13 250 18" name="ChargeLabel">
<Property key="Caption" value="#{sQuality}"/> <Property key="Caption" value="#{sQuality}"/>

View file

@ -4,7 +4,7 @@
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 329 253" name="_Main"> <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 329 253" name="_Main">
<Widget type="Widget" skin="" position="4 4 321 42" name="ToolBox"> <Widget type="Widget" skin="" position="4 4 321 42" name="ToolBox">
<Widget type="ImageBox" skin="ImageBox" position="5 6 32 32" name="ToolIcon"/> <Widget type="ItemWidget" skin="MW_ItemIconSmall" position="5 6 32 32" name="ToolIcon"/>
<Widget type="AutoSizedTextBox" skin="SandText" position="55 13 300 18" name="UsesLabel"> <Widget type="AutoSizedTextBox" skin="SandText" position="55 13 300 18" name="UsesLabel">
<Property key="Caption" value="#{sUses}"/> <Property key="Caption" value="#{sUses}"/>

View file

@ -319,4 +319,30 @@
</Widget> </Widget>
</Resource> </Resource>
<Resource type="ResourceLayout" name="MW_ItemIcon" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 42 42" name="Root">
<Widget type="ImageBox" skin="ImageBox" position="0 0 42 42" align="Stretch" name="Frame">
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Stretch" name="Item"/>
</Widget>
</Widget>
</Resource>
<Resource type="ResourceLayout" name="MW_ItemIconSmall" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 32 32" name="Root">
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Frame">
<Widget type="ImageBox" skin="ImageBox" position="0 0 32 32" align="Stretch" name="Item"/>
</Widget>
</Widget>
</Resource>
<Resource type="ResourceLayout" name="MW_ItemIconBox" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 50 50" name="Root">
<Widget type="ImageBox" skin="ImageBox" position="4 4 42 42" align="Center" name="Frame">
<Widget type="ImageBox" skin="ImageBox" position="5 5 32 32" align="Center" name="Item"/>
</Widget>
<Widget type="Widget" skin="MW_Box_Overlay" position="0 0 50 50" align="Stretch"/>
</Widget>
</Resource>
</MyGUI> </MyGUI>