1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 23:23:52 +00:00
openmw-tes3mp/apps/openmw/mwgui/container.cpp

401 lines
14 KiB
C++
Raw Normal View History

2012-04-15 15:52:39 +00:00
#include "container.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <assert.h>
#include <iostream>
#include <boost/lexical_cast.hpp>
2012-04-15 15:52:39 +00:00
2012-05-11 09:52:07 +00:00
#include "../mwbase/environment.hpp"
2012-04-15 15:52:39 +00:00
#include "../mwworld/manualref.hpp"
2012-05-11 14:58:07 +00:00
#include "../mwworld/world.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
2012-05-12 12:01:59 +00:00
#include "../mwworld/player.hpp"
2012-05-11 14:58:07 +00:00
#include "../mwclass/container.hpp"
#include "../mwinput/inputmanager.hpp"
2012-05-12 12:29:49 +00:00
#include "../mwsound/soundmanager.hpp"
2012-05-11 14:58:07 +00:00
#include "window_manager.hpp"
#include "widgets.hpp"
#include "countdialog.hpp"
2012-04-15 15:52:39 +00:00
using namespace MWGui;
using namespace Widgets;
2012-05-12 20:44:12 +00:00
ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) :
2012-05-06 09:04:07 +00:00
mDragAndDrop(dragAndDrop),
2012-05-12 20:44:12 +00:00
mFilter(ContainerBase::Filter_All)
2012-04-15 15:52:39 +00:00
{
2012-05-12 20:44:12 +00:00
}
void ContainerBase::setWidgets(Widget* containerWidget, ScrollView* itemView)
{
mContainerWidget = containerWidget;
mItemView = itemView;
2012-04-15 15:52:39 +00:00
2012-05-12 11:12:37 +00:00
mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked);
mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel);
2012-05-12 11:12:37 +00:00
}
2012-05-12 11:12:37 +00:00
ContainerBase::~ContainerBase()
{
}
2012-05-11 14:58:07 +00:00
2012-05-12 11:12:37 +00:00
void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
{
if(!mDragAndDrop->mIsOnDragAndDrop)
{
mSelectedItem = _sender;
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
int count = object.getRefData().getCount();
2012-05-11 14:58:07 +00:00
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
{
onSelectedItemImpl(_sender, count);
}
else if (MyGUI::InputManager::getInstance().isControlPressed())
{
onSelectedItemImpl(_sender, 1);
}
else
{
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->open(MWWorld::Class::get(object).getName(object), count);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::onSelectedItemImpl);
}
2012-05-12 11:12:37 +00:00
}
else
onContainerClicked(mContainerWidget);
2012-04-15 15:52:39 +00:00
}
void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count)
{
mDragAndDrop->mIsOnDragAndDrop = true;
mSelectedItem->detachFromWidget();
mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget);
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
_unequipItem(object);
int originalCount = object.getRefData().getCount();
object.getRefData().setCount(count);
mDragAndDrop->mStore.add(object);
object.getRefData().setCount(originalCount - count);
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
mDragAndDrop->mDraggedWidget = mSelectedItem;
static_cast<MyGUI::ImageBox*>(mSelectedItem)->setImageTexture(""); // remove the background texture (not visible during drag)
static_cast<MyGUI::TextBox*>(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption(
getCountString((*mDragAndDrop->mStore.begin()).getRefData().getCount()));
mDragAndDrop->mWasInInventory = isInventory();
drawItems();
MWBase::Environment::get().getWindowManager()->setDragDrop(true);
}
2012-05-12 11:12:37 +00:00
void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
2012-04-21 08:51:01 +00:00
{
2012-05-12 11:12:37 +00:00
if(mDragAndDrop->mIsOnDragAndDrop) //drop widget here
{
MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
2012-05-12 12:29:49 +00:00
assert(object.getContainerStore() && "Item is not in a container!");
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
2012-05-12 11:12:37 +00:00
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer);
containerStore.add(*mDragAndDrop->mStore.begin());
mDragAndDrop->mStore.clear();
mDragAndDrop->mIsOnDragAndDrop = false;
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
2012-05-12 11:12:37 +00:00
drawItems();
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
2012-05-12 11:12:37 +00:00
}
2012-04-21 08:51:01 +00:00
}
2012-05-12 11:12:37 +00:00
void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mItemView->getViewOffset().left + _rel*0.3 > 0)
mItemView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0));
}
2012-05-12 19:28:04 +00:00
void ContainerBase::setFilter(ContainerBase::Filter filter)
2012-05-12 18:35:50 +00:00
{
mFilter = filter;
drawItems();
}
2012-05-12 20:44:12 +00:00
void ContainerBase::openContainer(MWWorld::Ptr container)
2012-04-15 15:52:39 +00:00
{
2012-05-06 09:04:07 +00:00
mContainer = container;
drawItems();
}
2012-04-15 15:52:39 +00:00
2012-05-12 11:12:37 +00:00
void ContainerBase::drawItems()
2012-05-06 09:04:07 +00:00
{
while (mContainerWidget->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0));
}
2012-05-06 09:04:07 +00:00
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer);
2012-04-15 15:52:39 +00:00
int x = 0;
int y = 0;
int maxHeight = mItemView->getSize().height - 58;
int index = 0;
2012-04-15 15:52:39 +00:00
2012-05-12 19:28:04 +00:00
bool onlyMagic = false;
int categories;
if (mFilter == Filter_All)
categories = MWWorld::ContainerStore::Type_All;
else if (mFilter == Filter_Weapon)
categories = MWWorld::ContainerStore::Type_Weapon;
else if (mFilter == Filter_Apparel)
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor;
else if (mFilter == Filter_Magic)
{
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor
+ MWWorld::ContainerStore::Type_Weapon + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Potion;
onlyMagic = true;
}
else if (mFilter == Filter_Misc)
{
categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair
+ MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light
+ MWWorld::ContainerStore::Type_Apparatus;
2012-05-12 19:28:04 +00:00
}
/// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
std::vector< std::pair<MWWorld::Ptr, ItemState> > items;
std::vector<MWWorld::Ptr> equippedItems = getEquippedItems();
// filter out the equipped items of categories we don't want
std::vector<MWWorld::Ptr> unwantedItems = equippedItems;
2012-05-12 19:28:04 +00:00
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
{
std::vector<MWWorld::Ptr>::iterator found = std::find(unwantedItems.begin(), unwantedItems.end(), *iter);
if (found != unwantedItems.end())
{
unwantedItems.erase(found);
}
}
// now erase everything that's still in unwantedItems.
for (std::vector<MWWorld::Ptr>::iterator it=unwantedItems.begin();
it != unwantedItems.end(); ++it)
{
equippedItems.erase(std::find(unwantedItems.begin(), unwantedItems.end(), *it));
}
// and add the items that are left (= have the correct category)
for (std::vector<MWWorld::Ptr>::const_iterator it=equippedItems.begin();
it != equippedItems.end(); ++it)
{
items.push_back( std::make_pair(*it, ItemState_Equipped) );
}
// now add the regular items
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
{
/// \todo sorting
if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end())
items.push_back( std::make_pair(*iter, ItemState_Normal) );
}
for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin();
it != items.end(); ++it)
2012-04-15 15:52:39 +00:00
{
index++;
const MWWorld::Ptr* iter = &((*it).first);
2012-05-12 19:28:04 +00:00
if(iter->getRefData().getCount() > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name()))
2012-04-15 15:52:39 +00:00
{
2012-05-06 09:04:07 +00:00
std::string path = std::string("icons\\");
path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter);
// background widget (for the "equipped" frame and magic item background image)
bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != "");
MyGUI::ImageBox* backgroundWidget = mContainerWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default);
backgroundWidget->setUserString("ToolTipType", "ItemPtr");
backgroundWidget->setUserData(*iter);
std::string backgroundTex = "textures\\menu_icon";
if (isMagic)
backgroundTex += "_magic";
if (it->second == ItemState_Normal)
{
if (!isMagic)
backgroundTex = "";
}
else if (it->second == ItemState_Equipped)
{
backgroundTex += "_equip";
}
backgroundTex += ".dds";
backgroundWidget->setImageTexture(backgroundTex);
backgroundWidget->setProperty("ImageCoord", "0 0 42 42");
backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem);
backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel);
// image
ImageBox* image = backgroundWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture(path);
image->setNeedMouseFocus(false);
// text widget that shows item count
MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
text->setTextAlign(MyGUI::Align::Right);
text->setNeedMouseFocus(false);
2012-05-14 15:41:17 +00:00
text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0));
2012-05-12 18:14:19 +00:00
y += 42;
if (y > maxHeight)
{
2012-05-12 18:14:19 +00:00
x += 42;
y = 0;
}
2012-04-15 15:52:39 +00:00
text->setCaption(getCountString(iter->getRefData().getCount()));
2012-05-06 09:04:07 +00:00
}
}
2012-05-12 18:14:19 +00:00
MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height);
mItemView->setCanvasSize(size);
mContainerWidget->setSize(size);
2012-04-15 15:52:39 +00:00
}
std::string ContainerBase::getCountString(const int count)
{
if (count == 1)
return "";
if (count > 9999)
return boost::lexical_cast<std::string>(count/1000.f) + "k";
else
return boost::lexical_cast<std::string>(count);
}
2012-05-12 11:12:37 +00:00
void ContainerBase::Update()
2012-04-15 15:52:39 +00:00
{
2012-04-30 11:01:18 +00:00
if(mDragAndDrop->mIsOnDragAndDrop)
{
2012-04-30 11:01:18 +00:00
if(mDragAndDrop->mDraggedWidget)
mDragAndDrop->mDraggedWidget->setPosition(MyGUI::InputManager::getInstance().getMousePosition());
2012-04-30 11:01:18 +00:00
else mDragAndDrop->mIsOnDragAndDrop = false; //If this happens, there is a bug.
2012-04-15 15:52:39 +00:00
}
}
2012-05-12 11:12:37 +00:00
// ------------------------------------------------------------------------------------------------
ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop)
2012-05-12 20:44:12 +00:00
: ContainerBase(dragAndDrop)
, WindowBase("openmw_container_window_layout.xml", parWindowManager)
2012-05-12 11:12:37 +00:00
{
getWidget(mTakeButton, "TakeButton");
getWidget(mCloseButton, "CloseButton");
2012-05-12 20:44:12 +00:00
MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget;
getWidget(containerWidget, "Items");
getWidget(itemView, "ItemView");
setWidgets(containerWidget, itemView);
2012-05-12 11:12:37 +00:00
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
setText("CloseButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sClose")->str);
setText("TakeButton", MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTakeAll")->str);
// adjust buttons size to fit text
int closeButtonWidth = mCloseButton->getTextSize().width+24;
int takeButtonWidth = mTakeButton->getTextSize().width+24;
mCloseButton->setCoord(600-20-closeButtonWidth, mCloseButton->getCoord().top, closeButtonWidth, mCloseButton->getCoord().height);
mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height);
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
//int h = MyGUI::RenderManager::getInstance().getViewSize().height;
2012-05-12 11:46:03 +00:00
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize);
setCoord(w-600,0,600,300);
2012-05-12 11:12:37 +00:00
}
ContainerWindow::~ContainerWindow()
{
}
2012-05-12 11:46:03 +00:00
void ContainerWindow::onWindowResize(MyGUI::Window* window)
{
drawItems();
2012-05-12 11:46:03 +00:00
}
2012-05-12 20:44:12 +00:00
void ContainerWindow::open(MWWorld::Ptr container)
{
openContainer(container);
setTitle(MWWorld::Class::get(container).getName(container));
}
2012-05-11 14:34:36 +00:00
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
2012-04-15 19:02:54 +00:00
{
2012-04-30 11:01:18 +00:00
if(!mDragAndDrop->mIsOnDragAndDrop)
{
2012-05-11 09:52:07 +00:00
MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game);
2012-04-30 11:01:18 +00:00
setVisible(false);
}
2012-04-15 15:52:39 +00:00
}
2012-05-11 14:58:07 +00:00
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
{
if(!mDragAndDrop->mIsOnDragAndDrop)
{
2012-05-12 12:01:59 +00:00
// transfer everything into the player's inventory
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
2012-05-12 18:39:21 +00:00
int i=0;
2012-05-12 12:01:59 +00:00
for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter)
{
if(iter->getRefData().getCount() > 0)
{
playerStore.add(*iter);
2012-05-12 18:39:21 +00:00
if (i==0)
{
// play the sound of the first object
std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
++i;
2012-05-12 12:01:59 +00:00
}
}
containerStore.clear();
2012-05-11 14:58:07 +00:00
MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game);
setVisible(false);
}
}