ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

inventorywindow.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/ui/world/inventorywindow.h"
00024 
00025 #include "engines/stark/ui/cursor.h"
00026 #include "engines/stark/ui/world/actionmenu.h"
00027 
00028 #include "engines/stark/gfx/driver.h"
00029 
00030 #include "engines/stark/resources/knowledgeset.h"
00031 #include "engines/stark/resources/item.h"
00032 #include "engines/stark/resources/pattable.h"
00033 
00034 #include "engines/stark/services/global.h"
00035 #include "engines/stark/services/services.h"
00036 #include "engines/stark/services/staticprovider.h"
00037 #include "engines/stark/services/gameinterface.h"
00038 
00039 #include "engines/stark/visual/image.h"
00040 
00041 namespace Stark {
00042 
00043 static const int kAutoCloseSuspended = -1;
00044 static const int kAutoCloseDisabled  = -2;
00045 static const int kAutoCloseDelay     = 200;
00046 
00047 InventoryWindow::InventoryWindow(Gfx::Driver *gfx, Cursor *cursor, ActionMenu *actionMenu) :
00048         Window(gfx, cursor),
00049     _actionMenu(actionMenu),
00050     _selectedInventoryItem(-1),
00051     _firstVisibleSlot(0),
00052     _autoCloseTimeRemaining(kAutoCloseDisabled) {
00053     // The window has the same size as the game window
00054     _position = Common::Rect(Gfx::Driver::kGameViewportWidth, Gfx::Driver::kGameViewportHeight);
00055     _position.translate(0, Gfx::Driver::kTopBorderHeight);
00056 
00057     _backgroundTexture = StarkStaticProvider->getUIImage(StaticProvider::kInventoryBg);
00058 
00059     // Center the background in the window
00060     _backgroundRect = Common::Rect(_backgroundTexture->getWidth(), _backgroundTexture->getHeight());
00061     _backgroundRect.translate((_position.width() - _backgroundRect.width()) / 2,
00062             (_position.height() - _backgroundRect.height()) / 2);
00063 
00064     _scrollUpArrowImage = StarkStaticProvider->getUIElement(StaticProvider::kInventoryScrollUpArrow);
00065     _scrollDownArrowImage = StarkStaticProvider->getUIElement(StaticProvider::kInventoryScrollDownArrow);
00066 
00067     _scrollUpArrowRect = Common::Rect(_scrollUpArrowImage->getWidth(), _scrollUpArrowImage->getHeight());
00068     _scrollUpArrowRect.translate(_backgroundRect.right - _scrollUpArrowRect.width(),
00069                                  _backgroundRect.top + 2);
00070     _scrollDownArrowRect = Common::Rect(_scrollDownArrowImage->getWidth(), _scrollDownArrowImage->getHeight());
00071     _scrollDownArrowRect.translate(_backgroundRect.right - _scrollDownArrowRect.width(),
00072                                    _backgroundRect.bottom - _scrollDownArrowRect.height() - 2);
00073 }
00074 
00075 void InventoryWindow::open() {
00076     if (!_visible) {
00077         _actionMenu->close();
00078     }
00079 
00080     _visible = true;
00081 
00082     // The user needs to move the mouse over the background at least once
00083     // before autoclose is enabled.
00084     _autoCloseTimeRemaining = kAutoCloseDisabled;
00085 }
00086 
00087 void InventoryWindow::close() {
00088     if (_visible) {
00089         _actionMenu->close();
00090     }
00091 
00092     _visible = false;
00093 }
00094 
00095 void InventoryWindow::setSelectedInventoryItem(int16 selectedInventoryItem) {
00096     _selectedInventoryItem = selectedInventoryItem;
00097 }
00098 
00099 int16 InventoryWindow::getSelectedInventoryItem() const {
00100     return _selectedInventoryItem;
00101 }
00102 
00103 Common::Rect InventoryWindow::getSlotRect(uint32 slot) const {
00104     Common::Rect rect = Common::Rect(64, 64);
00105     rect.translate(
00106             96 * (slot % 5) + _backgroundRect.left + 24,
00107             96 * (slot / 5) + _backgroundRect.left + 8); // The original uses left here as well
00108     return rect;
00109 }
00110 
00111 Common::Rect InventoryWindow::getItemRect(uint32 slot, VisualImageXMG *image) const {
00112     Common::Rect rect = getSlotRect(slot % _visibleSlotsCount);
00113 
00114     // Center the image in the inventory slot
00115     rect.translate((rect.width() - image->getWidth()) / 2,
00116                   (rect.height() - image->getHeight()) / 2);
00117 
00118     return rect;
00119 }
00120 
00121 void InventoryWindow::onRender() {
00122     _renderEntries = StarkGlobal->getInventory()->getInventoryRenderEntries();
00123 
00124     _backgroundTexture->render(Common::Point(_backgroundRect.left, _backgroundRect.top), false);
00125     drawScrollArrows();
00126 
00127     for (uint i = _firstVisibleSlot; i < _renderEntries.size() && isSlotVisible(i); i++) {
00128         VisualImageXMG *image = _renderEntries[i]->getImage();
00129 
00130         // Get the item rect
00131         Common::Rect pos = getItemRect(i, image);
00132 
00133         image->render(Common::Point(pos.left, pos.top), false);
00134     }
00135 }
00136 
00137 void InventoryWindow::drawScrollArrows() const {
00138     if (canScrollUp()) {
00139         _scrollUpArrowImage->render(Common::Point(_scrollUpArrowRect.left, _scrollUpArrowRect.top), false);
00140     }
00141     if (canScrollDown()) {
00142         _scrollDownArrowImage->render(Common::Point(_scrollDownArrowRect.left, _scrollDownArrowRect.top), false);
00143     }
00144 }
00145 
00146 void InventoryWindow::checkObjectAtPos(Common::Point pos, Resources::ItemVisual **item, int16 selectedInventoryItem, int16 &singlePossibleAction) {
00147     *item = nullptr;
00148     singlePossibleAction = -1;
00149 
00150     // Check for inventory mouse overs
00151     for (uint i = _firstVisibleSlot; i < _renderEntries.size() && isSlotVisible(i); i++) {
00152         VisualImageXMG *image = _renderEntries[i]->getImage();
00153         Common::Rect itemRect = getItemRect(i, image);
00154 
00155         if (itemRect.contains(pos)) {
00156             *item = _renderEntries[i]->getOwner();
00157             break;
00158         }
00159     }
00160 
00161     if (!*item) {
00162         // No item at specified position
00163         return;
00164     }
00165 
00166     if (selectedInventoryItem == -1) {
00167         Resources::ActionArray actionsPossible;
00168         actionsPossible = StarkGameInterface->listStockActionsPossibleForObject(*item);
00169 
00170         if (actionsPossible.empty()) {
00171             // The item can still be taken
00172             singlePossibleAction = Resources::PATTable::kActionUse;
00173         }
00174     } else {
00175         if (StarkGameInterface->itemHasAction(*item, selectedInventoryItem)) {
00176             singlePossibleAction = selectedInventoryItem;
00177         }
00178     }
00179 }
00180 
00181 void InventoryWindow::onMouseMove(const Common::Point &pos) {
00182     Resources::ItemVisual *hoveredItem = nullptr;
00183     int16 hoveredItemAction = -1;
00184 
00185     checkObjectAtPos(pos, &hoveredItem, _selectedInventoryItem, hoveredItemAction);
00186 
00187     if (_selectedInventoryItem == -1) {
00188         if (hoveredItem) {
00189             _cursor->setCursorType(Cursor::kActive);
00190         } else if ((canScrollDown() && _scrollDownArrowRect.contains(pos))
00191                    || (canScrollUp() && _scrollUpArrowRect.contains(pos))) {
00192             _cursor->setCursorType(Cursor::kActive);
00193             _cursor->setFading(false);
00194         } else {
00195             _cursor->setCursorType(Cursor::kDefault);
00196         }
00197         _cursor->setFading(false);
00198     } else {
00199         VisualImageXMG *cursorImage = StarkGameInterface->getCursorImage(_selectedInventoryItem);
00200         _cursor->setCursorImage(cursorImage);
00201         _cursor->setFading(hoveredItemAction == _selectedInventoryItem);
00202     }
00203 
00204     if (hoveredItem) {
00205         Common::String hint = StarkGameInterface->getItemTitle(hoveredItem);
00206         _cursor->setMouseHint(hint);
00207     } else {
00208         _cursor->setMouseHint("");
00209     }
00210 
00211     if (!_backgroundRect.contains(pos)) {
00212         if (_autoCloseTimeRemaining == kAutoCloseSuspended) {
00213             _autoCloseTimeRemaining = kAutoCloseDelay;
00214         }
00215     } else {
00216         _autoCloseTimeRemaining = kAutoCloseSuspended;
00217     }
00218 }
00219 
00220 void InventoryWindow::onClick(const Common::Point &pos) {
00221     _actionMenu->close();
00222 
00223     Resources::ItemVisual *clickedItem = nullptr;
00224     int16 clickedItemAction = -1;
00225     checkObjectAtPos(pos, &clickedItem, _selectedInventoryItem, clickedItemAction);
00226 
00227     if (clickedItem) {
00228         // An item was clicked
00229         if (clickedItemAction != -1) {
00230             // A single action is possible
00231             if (clickedItemAction == Resources::PATTable::kActionUse) {
00232                 setSelectedInventoryItem(clickedItem->getIndex());
00233             } else {
00234                 StarkGameInterface->itemDoAction(clickedItem, clickedItemAction);
00235             }
00236         } else {
00237             // Multiple actions are possible
00238             if (_selectedInventoryItem == -1) {
00239                 _actionMenu->open(clickedItem, Common::Point());
00240             }
00241         }
00242     } else if (_scrollDownArrowRect.contains(pos)) {
00243         if (canScrollDown()) {
00244             scrollDown();
00245         }
00246     } else if (_scrollUpArrowRect.contains(pos)) {
00247         if (canScrollUp()) {
00248             scrollUp();
00249         }
00250     } else {
00251         // Nothing was under the mouse cursor, close the inventory
00252         close();
00253     }
00254 }
00255 
00256 void InventoryWindow::onRightClick(const Common::Point &pos) {
00257     if (_selectedInventoryItem == -1) {
00258         close();
00259     } else {
00260         setSelectedInventoryItem(-1);
00261     }
00262 }
00263 
00264 void InventoryWindow::reset() {
00265     _renderEntries.clear();
00266 }
00267 
00268 bool InventoryWindow::isSlotVisible(uint32 slot) const {
00269     return slot < _firstVisibleSlot + _visibleSlotsCount;
00270 }
00271 
00272 bool InventoryWindow::canScrollDown() const {
00273     return _renderEntries.size() - _firstVisibleSlot > _visibleSlotsCount;
00274 }
00275 
00276 bool InventoryWindow::canScrollUp() const {
00277     return _firstVisibleSlot > 0;
00278 }
00279 
00280 void InventoryWindow::scrollDown() {
00281     if (canScrollDown()) {
00282         _firstVisibleSlot += _visibleSlotsCount;
00283     }
00284 }
00285 
00286 void InventoryWindow::scrollUp() {
00287     if (canScrollUp()) {
00288         _firstVisibleSlot -= _visibleSlotsCount;
00289     }
00290 }
00291 
00292 void InventoryWindow::onGameLoop() {
00293     if (_autoCloseTimeRemaining >= 0 && !_actionMenu->isVisible()) {
00294         _autoCloseTimeRemaining -= StarkGlobal->getMillisecondsPerGameloop();
00295 
00296         if (_autoCloseTimeRemaining <= 0) {
00297             _autoCloseTimeRemaining = kAutoCloseSuspended;
00298             close();
00299         }
00300     }
00301 }
00302 } // End of namespace Stark


Generated on Sat Mar 16 2019 05:01:39 for ResidualVM by doxygen 1.7.1
curved edge   curved edge