aboutsummaryrefslogtreecommitdiff
path: root/engines/m4/m4_views.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/m4/m4_views.cpp')
-rw-r--r--engines/m4/m4_views.cpp345
1 files changed, 345 insertions, 0 deletions
diff --git a/engines/m4/m4_views.cpp b/engines/m4/m4_views.cpp
new file mode 100644
index 0000000000..9bf964ee96
--- /dev/null
+++ b/engines/m4/m4_views.cpp
@@ -0,0 +1,345 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "m4/m4_views.h"
+#include "m4/events.h"
+#include "m4/font.h"
+#include "m4/globals.h"
+#include "m4/m4.h"
+
+namespace M4 {
+
+GUIInventory::GUIInventory(View *owner, M4Engine *vm, const Common::Rect &bounds, int horizCells,
+ int vertCells, int cellWidth, int cellHeight, int tag): GUIRect(owner, bounds, tag) {
+
+ _vm = vm;
+ _cellCount.x = horizCells;
+ _cellCount.y = vertCells;
+ _cellSize.x = cellWidth;
+ _cellSize.y = cellHeight;
+
+ // Validate the cell settings
+ if ((_cellCount.x * _cellSize.x > _bounds.width()) ||
+ (_cellCount.y * _cellSize.y > _bounds.height()))
+ error("Cell settings for inventory display exceeded control size");
+
+ _visible = true;
+ _scrollPosition = 0;
+ _scrollable = false;
+ _highlightedIndex = -1;
+ _selectedIndex = -1;
+}
+
+void GUIInventory::onRefresh() {
+ _parent->fillRect(_bounds, _vm->_palette->BLACK);
+ //_parent->frameRect(_bounds, _vm->_palette->LIGHT_GRAY);
+
+ if (_visible) {
+ //kernel_trigger_dispatch(kernel_trigger_create(TRIG_INV_CLICK));
+
+ _scrollable = false;
+
+ // Get to the starting inventory position for display
+ ItemsIterator i = _inventoryItems.begin();
+ int index = _scrollPosition;
+ while (index-- > 0) ++i;
+
+ // Loop through displaying entries
+ for (index = 0; (i != _inventoryItems.end()) && (index < _cellCount.x * _cellCount.y); ++index, ++i) {
+ GUIInventoryItem *item = (*i).get();
+ const Common::Point cellPos = getCellPosition(index);
+/* Common::Rect cellBounds(_bounds.left + cellPos.x + xOffset,
+ _bounds.top + cellPos.y + yOffset,
+ _bounds.left + cellPos.x + xOffset + _cellSize.x,
+ _bounds.top + cellPos.y + _cellSize.y);*/
+ Common::Rect cellBounds(_bounds.left + cellPos.x, _bounds.top + cellPos.y,
+ _bounds.left + cellPos.x + _cellSize.x, _bounds.top + cellPos.y + _cellSize.y);
+
+ Common::Point iconPt(
+ cellBounds.left + (cellBounds.width() - item->icon->width()) / 2,
+ cellBounds.top + (cellBounds.height() - item->icon->height()) / 2);
+
+ item->icon->copyTo(_parent, iconPt.x, iconPt.y, 0);
+
+ if (_highlightedIndex == index)
+ _parent->frameRect(Common::Rect(iconPt.x - 2, iconPt.y - 2,
+ iconPt.x + item->icon->width() + 2, iconPt.y + item->icon->height() + 2),
+ _vm->_palette->LIGHT_GRAY);
+ }
+ }
+}
+
+bool GUIInventory::onEvent(M4EventType eventType, int param, int x, int y, GUIObject *&currentItem) {
+ bool result = false;
+ int overIndex = getInsideIndex(x, y);
+ bool isPressed = (eventType == MEVENT_LEFT_CLICK) || (eventType == MEVENT_LEFT_HOLD) ||
+ (eventType == MEVENT_LEFT_DRAG);
+ ItemsIterator curItem = _inventoryItems.begin();
+
+ if (isPressed) {
+ if (_selectedIndex == -1 && overIndex != -1) {
+ setHighlight(overIndex);
+ _selectedIndex = overIndex;
+ for (int i = 0; i < _scrollPosition + _selectedIndex; i++)
+ ++curItem;
+ if (_scrollPosition + _selectedIndex < (int)_inventoryItems.size())
+ _vm->_mouse->setCursorNum(curItem->get()->iconIndex);
+ result = true;
+ } else {
+ // We are over something being tracked
+ if (_selectedIndex == overIndex) {
+ setHighlight(overIndex);
+ result = true;
+ } else {
+ // Otherwise reset highlighting
+ setHighlight(-1);
+ result = false;
+ }
+ }
+ } else {
+ // No button pressed
+ if (_selectedIndex == overIndex) {
+ result = (_selectedIndex != -1);
+ } else {
+ result = (overIndex + _scrollPosition < (int)_inventoryItems.size());
+ if (result) {
+ for (int i = 0; i < overIndex + _scrollPosition; i++)
+ ++curItem;
+ _vm->_interfaceView->setStatusText(curItem->get()->name);
+ }
+ }
+
+ // Stop tracking anything
+ setHighlight(overIndex);
+ }
+
+ return result;
+}
+
+void GUIInventory::add(const char *name, const char *verb, M4Surface *icon, int iconIndex) {
+ // First scan through the list to prevent duplicate objects
+ for (ItemsIterator i = _inventoryItems.begin(); i != _inventoryItems.end(); ++i) {
+ if (!strcmp(name, ((*i).get())->name))
+ return;
+ }
+
+ _inventoryItems.push_back(InventoryList::value_type(new GUIInventoryItem(name, verb, icon, iconIndex)));
+}
+
+bool GUIInventory::remove(const char *name) {
+ for (ItemsIterator i = _inventoryItems.begin(); i != _inventoryItems.end(); ++i) {
+ if (!strcmp(name, ((*i).get())->name)) {
+ _inventoryItems.erase(i);
+ _scrollPosition = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int GUIInventory::getInsideIndex(int x, int y) {
+ if (!_bounds.contains(x, y))
+ return -1;
+
+ int localX = x - _bounds.left;
+ int localY = y - _bounds.top;
+ return (localX / _cellSize.x) * _cellCount.y + (localY / _cellSize.y);
+}
+
+const char *GUIInventory::getSelectedObjectName() {
+ if (_selectedIndex != -1) {
+ ItemsIterator curItem = _inventoryItems.begin();
+ for (int i = 0; i < _selectedIndex; i++)
+ ++curItem;
+ return curItem->get()->name;
+ } else {
+ return NULL;
+ }
+}
+
+const Common::Point &GUIInventory::getCellPosition(int index) {
+ static Common::Point result;
+
+ if (_cellCount.x > _cellCount.y) {
+ // Horizontal orientation
+ result.x = (index / _cellCount.y) * _cellSize.x;
+ result.y = (index % _cellCount.y) * _cellSize.x;
+ } else {
+ // Vertical orientation
+ result.x = (index / _cellCount.x) * _cellSize.y;
+ result.y = (index % _cellCount.x) * _cellSize.y;
+ }
+
+ return result;
+}
+
+void GUIInventory::setHighlight(int index) {
+ if (_highlightedIndex == index)
+ return;
+
+ _highlightedIndex = index;
+}
+
+void GUIInventory::setScrollPosition(int value) {
+ if (value < 0)
+ return;
+ else if (value >= (int)_inventoryItems.size() - (_cellCount.x * _cellCount.y))
+ return;
+
+ _scrollPosition = value;
+}
+
+//--------------------------------------------------------------------------
+
+const char *INTERFACE_SERIES = "999intr";
+
+#define SPR(x) _sprites->getFrame(x)
+
+GameInterfaceView::GameInterfaceView(M4Engine *vm):
+ View(vm, Common::Rect(0, vm->_screen->height() - INTERFACE_HEIGHT,
+ vm->_screen->width(), vm->_screen->height())),
+ _statusText(GUITextField(this, Common::Rect(200, 1, 450, 21))),
+ _inventory(GUIInventory(this, vm, Common::Rect(188, 22, 539, 97), 9, 1, 39, 75, 3)) {
+
+ _screenType = VIEWID_INTERFACE;
+ _screenFlags.layer = LAYER_INTERFACE;
+ _screenFlags.visible = false;
+ _screenFlags.get = SCREVENT_MOUSE;
+ _highlightedIndex = -1;
+ _selected = false;
+
+ Common::SeekableReadStream *data = _vm->res()->get(INTERFACE_SERIES);
+ RGB8 *palette;
+
+ _sprites = new SpriteAsset(_vm, data, data->size(), INTERFACE_SERIES);
+ palette = _sprites->getPalette();
+
+ //Palette.setPalette(palette, 0, _sprites->getColorCount());
+
+ _vm->res()->toss(INTERFACE_SERIES);
+
+ // Setup the interface buttons
+
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(15, 35, 47, 66), 0, SPR(0), SPR(1), SPR(2)))); // look
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(60, 35, 92, 66), 1, SPR(3), SPR(4), SPR(5)))); // take
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(105, 35, 137, 66), 2, SPR(6), SPR(7), SPR(8)))); // manipulate
+
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(580, 10, 620, 69), 3, SPR(69), SPR(70), SPR(71)))); // abduction
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(582, 70, 619, 105), 4, SPR(76), SPR(77), SPR(78)))); // menu
+
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(168, 22, 188, 97), 5, SPR(60), SPR(61), SPR(62)))); // Scroll left
+ _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(539, 22, 559, 97), 6, SPR(64), SPR(65), SPR(66)))); // Scroll right
+}
+
+#undef SPR
+
+GameInterfaceView::~GameInterfaceView() {
+ delete _sprites;
+}
+
+void GameInterfaceView::setHighlightedButton(int index) {
+ if (index == _highlightedIndex)
+ return;
+
+ _selected = (index == -1);
+ _highlightedIndex = index;
+}
+
+bool GameInterfaceView::onEvent(M4EventType eventType, int param, int x, int y, bool &captureEvents) {
+ static bool selectionFlag = false;
+ if (eventType == MEVENT_LEFT_RELEASE)
+ selectionFlag = false;
+
+ captureEvents = isInside(x, y);
+ if (!captureEvents)
+ return false;
+
+ int localX = x - _coords.left;
+ int localY = y - _coords.top;
+ GUIObject *currentItem;
+
+ _statusText.onEvent(eventType, param, localX, localY, currentItem);
+ _inventory.onEvent(eventType, param, localX, localY, currentItem);
+
+ if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
+ _vm->_mouse->getCursorNum() != CURSOR_TAKE &&
+ _vm->_mouse->getCursorNum() != CURSOR_USE &&
+ _vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
+ if (_vm->_mouse->getCursorNum() != 0)
+ _vm->_mouse->setCursorNum(0);
+ }
+
+ for (ButtonsIterator i = _buttons.begin(); i != _buttons.end(); ++i) {
+ GUIButton *btn = (*i).get();
+ btn->onEvent(eventType, param, localX, localY, currentItem);
+ if ((btn->getState() == BUTTON_PRESSED) && !selectionFlag) {
+ selectionFlag = true;
+ _highlightedIndex = btn->getTag();
+
+ switch (_highlightedIndex) {
+ case 0:
+ _vm->_mouse->setCursorNum(CURSOR_LOOK);
+ break;
+ case 1:
+ _vm->_mouse->setCursorNum(CURSOR_TAKE);
+ break;
+ case 2:
+ _vm->_mouse->setCursorNum(CURSOR_USE);
+ break;
+ case 3:
+ // TODO: Jump to abduction
+ break;
+ case 4:
+ _vm->loadMenu(GAME_MENU);
+ break;
+ case 5:
+ _inventory.scrollLeft();
+ break;
+ case 6:
+ _inventory.scrollRight();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+void GameInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
+ empty();
+
+ _statusText.onRefresh();
+ _inventory.onRefresh();
+ for (ButtonsIterator i = _buttons.begin(); i != _buttons.end(); ++i)
+ ((*i).get())->onRefresh();
+
+ View::onRefresh(rects, destSurface);
+}
+
+
+} // End of namespace M4