/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ /* * This file is based on WME Lite. * http://dead-code.org/redir.php?target=wmelite * Copyright (c) 2011 Jan Nedoma */ #include "engines/wintermute/ad/ad_game.h" #include "engines/wintermute/ad/ad_inventory_box.h" #include "engines/wintermute/ad/ad_inventory.h" #include "engines/wintermute/ad/ad_item.h" #include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/base_parser.h" #include "engines/wintermute/base/base_file_manager.h" #include "engines/wintermute/base/base_viewport.h" #include "engines/wintermute/base/base_dynamic_buffer.h" #include "engines/wintermute/base/gfx/base_renderer.h" #include "engines/wintermute/ui/ui_button.h" #include "engines/wintermute/ui/ui_window.h" #include "engines/wintermute/platform_osystem.h" #include "common/str.h" #include "common/rect.h" namespace Wintermute { IMPLEMENT_PERSISTENT(AdInventoryBox, false) ////////////////////////////////////////////////////////////////////////// AdInventoryBox::AdInventoryBox(BaseGame *inGame) : BaseObject(inGame) { _itemsArea.setEmpty(); _scrollOffset = 0; _spacing = 0; _itemWidth = _itemHeight = 50; _scrollBy = 1; _window = nullptr; _closeButton = nullptr; _hideSelected = false; _visible = false; _exclusive = false; } ////////////////////////////////////////////////////////////////////////// AdInventoryBox::~AdInventoryBox() { _gameRef->unregisterObject(_window); _window = nullptr; delete _closeButton; _closeButton = nullptr; } ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::listen(BaseScriptHolder *param1, uint32 param2) { UIObject *obj = (UIObject *)param1; switch (obj->_type) { case UI_BUTTON: if (scumm_stricmp(obj->getName(), "close") == 0) { _visible = false; } else if (scumm_stricmp(obj->getName(), "prev") == 0) { _scrollOffset -= _scrollBy; _scrollOffset = MAX(_scrollOffset, 0); } else if (scumm_stricmp(obj->getName(), "next") == 0) { _scrollOffset += _scrollBy; } else { return BaseObject::listen(param1, param2); } break; default: error("AdInventoryBox::Listen - Unhandled enum"); break; } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::display() { AdGame *adGame = (AdGame *)_gameRef; if (!_visible) { return STATUS_OK; } int itemsX, itemsY; itemsX = (int)floor((float)((_itemsArea.right - _itemsArea.left + _spacing) / (_itemWidth + _spacing))); itemsY = (int)floor((float)((_itemsArea.bottom - _itemsArea.top + _spacing) / (_itemHeight + _spacing))); if (_window) { _window->enableWidget("prev", _scrollOffset > 0); _window->enableWidget("next", _scrollOffset + itemsX * itemsY < (int32)adGame->_inventoryOwner->getInventory()->_takenItems.size()); } if (_closeButton) { _closeButton->_posX = _closeButton->_posY = 0; _closeButton->setWidth(_gameRef->_renderer->getWidth()); _closeButton->setHeight(_gameRef->_renderer->getHeight()); _closeButton->display(); } // display window Rect32 rect = _itemsArea; if (_window) { rect.offsetRect(_window->_posX, _window->_posY); _window->display(); } // display items if (_window && _window->_alphaColor != 0) { _gameRef->_renderer->_forceAlphaColor = _window->_alphaColor; } int yyy = rect.top; for (int j = 0; j < itemsY; j++) { int xxx = rect.left; for (int i = 0; i < itemsX; i++) { int itemIndex = _scrollOffset + j * itemsX + i; if (itemIndex >= 0 && itemIndex < (int32)adGame->_inventoryOwner->getInventory()->_takenItems.size()) { AdItem *item = adGame->_inventoryOwner->getInventory()->_takenItems[itemIndex]; if (item != ((AdGame *)_gameRef)->_selectedItem || !_hideSelected) { item->update(); item->display(xxx, yyy); } } xxx += (_itemWidth + _spacing); } yyy += (_itemHeight + _spacing); } if (_window && _window->_alphaColor != 0) { _gameRef->_renderer->_forceAlphaColor = 0; } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::loadFile(const char *filename) { char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename); if (buffer == nullptr) { _gameRef->LOG(0, "AdInventoryBox::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } bool ret; setFilename(filename); if (DID_FAIL(ret = loadBuffer(buffer, true))) { _gameRef->LOG(0, "Error parsing INVENTORY_BOX file '%s'", filename); } delete[] buffer; return ret; } TOKEN_DEF_START TOKEN_DEF(INVENTORY_BOX) TOKEN_DEF(TEMPLATE) TOKEN_DEF(WINDOW) TOKEN_DEF(EXCLUSIVE) TOKEN_DEF(ALWAYS_VISIBLE) TOKEN_DEF(AREA) TOKEN_DEF(SPACING) TOKEN_DEF(ITEM_WIDTH) TOKEN_DEF(ITEM_HEIGHT) TOKEN_DEF(SCROLL_BY) TOKEN_DEF(NAME) TOKEN_DEF(CAPTION) TOKEN_DEF(HIDE_SELECTED) TOKEN_DEF(EDITOR_PROPERTY) TOKEN_DEF_END ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::loadBuffer(char *buffer, bool complete) { TOKEN_TABLE_START(commands) TOKEN_TABLE(INVENTORY_BOX) TOKEN_TABLE(TEMPLATE) TOKEN_TABLE(WINDOW) TOKEN_TABLE(EXCLUSIVE) TOKEN_TABLE(ALWAYS_VISIBLE) TOKEN_TABLE(AREA) TOKEN_TABLE(SPACING) TOKEN_TABLE(ITEM_WIDTH) TOKEN_TABLE(ITEM_HEIGHT) TOKEN_TABLE(SCROLL_BY) TOKEN_TABLE(NAME) TOKEN_TABLE(CAPTION) TOKEN_TABLE(HIDE_SELECTED) TOKEN_TABLE(EDITOR_PROPERTY) TOKEN_TABLE_END char *params; int cmd = 2; BaseParser parser; bool alwaysVisible = false; _exclusive = false; if (complete) { if (parser.getCommand(&buffer, commands, ¶ms) != TOKEN_INVENTORY_BOX) { _gameRef->LOG(0, "'INVENTORY_BOX' keyword expected."); return STATUS_FAILED; } buffer = params; } while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) { switch (cmd) { case TOKEN_TEMPLATE: if (DID_FAIL(loadFile(params))) { cmd = PARSERR_GENERIC; } break; case TOKEN_NAME: setName(params); break; case TOKEN_CAPTION: setCaption(params); break; case TOKEN_WINDOW: delete _window; _window = new UIWindow(_gameRef); if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { delete _window; _window = nullptr; cmd = PARSERR_GENERIC; } else { _gameRef->registerObject(_window); } break; case TOKEN_AREA: parser.scanStr(params, "%d,%d,%d,%d", &_itemsArea.left, &_itemsArea.top, &_itemsArea.right, &_itemsArea.bottom); break; case TOKEN_EXCLUSIVE: parser.scanStr(params, "%b", &_exclusive); break; case TOKEN_HIDE_SELECTED: parser.scanStr(params, "%b", &_hideSelected); break; case TOKEN_ALWAYS_VISIBLE: parser.scanStr(params, "%b", &alwaysVisible); break; case TOKEN_SPACING: parser.scanStr(params, "%d", &_spacing); break; case TOKEN_ITEM_WIDTH: parser.scanStr(params, "%d", &_itemWidth); break; case TOKEN_ITEM_HEIGHT: parser.scanStr(params, "%d", &_itemHeight); break; case TOKEN_SCROLL_BY: parser.scanStr(params, "%d", &_scrollBy); break; case TOKEN_EDITOR_PROPERTY: parseEditorProperty(params, false); break; } } if (cmd == PARSERR_TOKENNOTFOUND) { _gameRef->LOG(0, "Syntax error in INVENTORY_BOX definition"); return STATUS_FAILED; } if (cmd == PARSERR_GENERIC) { _gameRef->LOG(0, "Error loading INVENTORY_BOX definition"); return STATUS_FAILED; } if (_exclusive) { delete _closeButton; _closeButton = new UIButton(_gameRef); if (_closeButton) { _closeButton->setName("close"); _closeButton->setListener(this, _closeButton, 0); _closeButton->_parent = _window; } } _visible = alwaysVisible; if (_window) { for (uint32 i = 0; i < _window->_widgets.size(); i++) { if (!_window->_widgets[i]->getListener()) { _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); } } } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::saveAsText(BaseDynamicBuffer *buffer, int indent) { buffer->putTextIndent(indent, "INVENTORY_BOX\n"); buffer->putTextIndent(indent, "{\n"); buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); buffer->putTextIndent(indent + 2, "AREA { %d, %d, %d, %d }\n", _itemsArea.left, _itemsArea.top, _itemsArea.right, _itemsArea.bottom); buffer->putTextIndent(indent + 2, "EXCLUSIVE=%s\n", _exclusive ? "TRUE" : "FALSE"); buffer->putTextIndent(indent + 2, "HIDE_SELECTED=%s\n", _hideSelected ? "TRUE" : "FALSE"); buffer->putTextIndent(indent + 2, "ALWAYS_VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); buffer->putTextIndent(indent + 2, "SPACING=%d\n", _spacing); buffer->putTextIndent(indent + 2, "ITEM_WIDTH=%d\n", _itemWidth); buffer->putTextIndent(indent + 2, "ITEM_HEIGHT=%d\n", _itemHeight); buffer->putTextIndent(indent + 2, "SCROLL_BY=%d\n", _scrollBy); buffer->putTextIndent(indent + 2, "\n"); // window if (_window) { _window->saveAsText(buffer, indent + 2); } buffer->putTextIndent(indent + 2, "\n"); // editor properties BaseClass::saveAsText(buffer, indent + 2); buffer->putTextIndent(indent, "}\n"); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::persist(BasePersistenceManager *persistMgr) { BaseObject::persist(persistMgr); persistMgr->transferPtr(TMEMBER_PTR(_closeButton)); persistMgr->transferBool(TMEMBER(_hideSelected)); persistMgr->transferSint32(TMEMBER(_itemHeight)); persistMgr->transferRect32(TMEMBER(_itemsArea)); persistMgr->transferSint32(TMEMBER(_itemWidth)); persistMgr->transferSint32(TMEMBER(_scrollBy)); persistMgr->transferSint32(TMEMBER(_scrollOffset)); persistMgr->transferSint32(TMEMBER(_spacing)); persistMgr->transferBool(TMEMBER(_visible)); persistMgr->transferPtr(TMEMBER_PTR(_window)); persistMgr->transferBool(TMEMBER(_exclusive)); return STATUS_OK; } } // End of namespace Wintermute