scummvm/engines/m4/m4_views.cpp

346 lines
10 KiB
C++
Raw Normal View History

/* 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