Skip to content

Commit

Permalink
SCI: Implement Mac iconbar event handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
waltervn committed Mar 9, 2011
1 parent 354e7d0 commit 952d1a0
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 33 deletions.
14 changes: 13 additions & 1 deletion engines/sci/engine/kevent.cpp
Expand Up @@ -35,6 +35,7 @@
#include "sci/event.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/maciconbar.h"

namespace Sci {

Expand All @@ -46,6 +47,13 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->_segMan;
Common::Point mousePos;

// For Mac games with an icon bar, handle possible icon bar events first
if (g_sci->hasMacIconBar()) {
reg_t iconObj = g_sci->_gfxMacIconBar->handleEvents();
if (!iconObj.isNull())
invokeSelector(s, iconObj, SELECTOR(select), argc, argv, 0, NULL);
}

// If there's a simkey pending, and the game wants a keyboard event, use the
// simkey instead of a normal event
if (g_debug_simulated_key && (mask & SCI_EVENT_KEYBOARD)) {
Expand Down Expand Up @@ -145,7 +153,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
break;

default:
s->r_acc = NULL_REG; // Unknown or no event
// Return a null event
writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE);
writeSelectorValue(segMan, obj, SELECTOR(message), 0);
writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
s->r_acc = NULL_REG;
}

if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) {
Expand Down
19 changes: 9 additions & 10 deletions engines/sci/engine/kmisc.cpp
Expand Up @@ -359,23 +359,22 @@ reg_t kIconBar(EngineState *s, int argc, reg_t *argv) {
case 0: // InitIconBar
for (int i = 0; i < argv[1].toUint16(); i++)
g_sci->_gfxMacIconBar->addIcon(argv[i + 2]);

// TODO: Should return icon bar handle
// Said handle is then used by DisposeIconBar
break;
case 1: // DisposeIconBar
warning("kIconBar(Dispose)");
break;
case 2: // EnableIconBar (0xffff = all)
debug(0, "kIconBar(Enable, %d)", argv[1].toUint16());
g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toUint16(), true);
case 2: // EnableIconBar (-1 = all)
debug(0, "kIconBar(Enable, %i)", argv[1].toSint16());
g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), true);
break;
case 3: // DisableIconBar (0xffff = all)
debug(0, "kIconBar(Disable, %d)", argv[1].toUint16());
g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toUint16(), false);
case 3: // DisableIconBar (-1 = all)
debug(0, "kIconBar(Disable, %i)", argv[1].toSint16());
g_sci->_gfxMacIconBar->setIconEnabled(argv[1].toSint16(), false);
break;
case 4: // SetIconBarIcon
warning("kIconBar(SetIcon, %d, %d)", argv[1].toUint16(), argv[2].toUint16());
debug(0, "kIconBar(SetIcon, %d, %d)", argv[1].toUint16(), argv[2].toUint16());
if (argv[2].toSint16() == -1)
g_sci->_gfxMacIconBar->setInventoryIcon(argv[2].toSint16());
break;
default:
error("Unknown kIconBar(%d)", argv[0].toUint16());
Expand Down
1 change: 1 addition & 0 deletions engines/sci/engine/selector.cpp
Expand Up @@ -165,6 +165,7 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(vanishingX);
FIND_SELECTOR(vanishingY);
FIND_SELECTOR(iconIndex);
FIND_SELECTOR(select);

#ifdef ENABLE_SCI32
FIND_SELECTOR(data);
Expand Down
1 change: 1 addition & 0 deletions engines/sci/engine/selector.h
Expand Up @@ -130,6 +130,7 @@ struct SelectorCache {

// SCI1.1 Mac icon bar selectors
Selector iconIndex; ///< Used to index icon bar objects
Selector select;

#ifdef ENABLE_SCI32
Selector data; // Used by Array()/String()
Expand Down
3 changes: 3 additions & 0 deletions engines/sci/graphics/cursor.cpp
Expand Up @@ -39,6 +39,7 @@
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/view.h"
#include "sci/graphics/cursor.h"
#include "sci/graphics/maciconbar.h"

namespace Sci {

Expand Down Expand Up @@ -444,6 +445,8 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu
else // Unknown cursor, ignored
return;
}
if (g_sci->hasMacIconBar())
g_sci->_gfxMacIconBar->setInventoryIcon(viewNum);
} else {
// If we do have the list, we'll be using a remap based on what the
// scripts have given us.
Expand Down
150 changes: 132 additions & 18 deletions engines/sci/graphics/maciconbar.cpp
Expand Up @@ -27,6 +27,7 @@
#include "sci/engine/kernel.h"
#include "sci/engine/selector.h"
#include "sci/engine/state.h"
#include "sci/event.h"
#include "sci/graphics/maciconbar.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/screen.h"
Expand All @@ -40,9 +41,22 @@ namespace Sci {

GfxMacIconBar::GfxMacIconBar() {
_lastX = 0;

if (g_sci->getGameId() == GID_FREDDYPHARKAS)
_inventoryIndex = 5;
else
_inventoryIndex = 4;

_inventoryIcon = 0;
_allDisabled = true;
}

GfxMacIconBar::~GfxMacIconBar() {
if (_inventoryIcon) {
_inventoryIcon->free();
delete _inventoryIcon;
}

for (uint32 i = 0; i < _iconBarItems.size(); i++) {
if (_iconBarItems[i].nonSelectedImage) {
_iconBarItems[i].nonSelectedImage->free();
Expand All @@ -62,7 +76,12 @@ void GfxMacIconBar::addIcon(reg_t obj) {

item.object = obj;
item.nonSelectedImage = createImage(iconIndex, false);
item.selectedImage = createImage(iconIndex, true);

if (iconIndex != _inventoryIndex)
item.selectedImage = createImage(iconIndex, true);
else
item.selectedImage = 0;

item.enabled = true;

// Start after the main viewing window and add a two pixel buffer
Expand All @@ -82,17 +101,33 @@ void GfxMacIconBar::drawIcons() {
// Draw the icons to the bottom of the screen

for (uint32 i = 0; i < _iconBarItems.size(); i++)
redrawIcon(i);
drawIcon(i, false);
}

void GfxMacIconBar::redrawIcon(uint16 iconIndex) {
void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) {
if (iconIndex >= _iconBarItems.size())
return;

if (_iconBarItems[iconIndex].enabled)
drawEnabledImage(_iconBarItems[iconIndex].nonSelectedImage, _iconBarItems[iconIndex].rect);
else
drawDisabledImage(_iconBarItems[iconIndex].nonSelectedImage, _iconBarItems[iconIndex].rect);
Common::Rect rect = _iconBarItems[iconIndex].rect;

if (isIconEnabled(iconIndex)) {
if (selected)
drawEnabledImage(_iconBarItems[iconIndex].selectedImage, rect);
else
drawEnabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);
} else
drawDisabledImage(_iconBarItems[iconIndex].nonSelectedImage, rect);

if ((iconIndex == _inventoryIndex) && _inventoryIcon) {
Common::Rect invRect = Common::Rect(0, 0, _inventoryIcon->w, _inventoryIcon->h);
invRect.moveTo(rect.left, rect.top);
invRect.translate((rect.width() - invRect.width()) / 2, (rect.height() - invRect.height()) / 2);

if (isIconEnabled(iconIndex))
drawEnabledImage(_inventoryIcon, invRect);
else
drawDisabledImage(_inventoryIcon, invRect);
}
}

void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) {
Expand Down Expand Up @@ -128,30 +163,49 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::
void GfxMacIconBar::drawSelectedImage(uint16 iconIndex) {
assert(iconIndex <= _iconBarItems.size());

// TODO
drawEnabledImage(_iconBarItems[iconIndex].selectedImage, _iconBarItems[iconIndex].rect);
}

bool GfxMacIconBar::isIconEnabled(uint16 iconIndex) const {
if (iconIndex >= _iconBarItems.size())
return false;

return _iconBarItems[iconIndex].enabled;
return !_allDisabled && _iconBarItems[iconIndex].enabled;
}

void GfxMacIconBar::setIconEnabled(uint16 iconIndex, bool enabled) {
if (iconIndex == 0xffff) {
for (uint32 i = 0; i < _iconBarItems.size(); i++)
_iconBarItems[i].enabled = enabled;
} else if (iconIndex < _iconBarItems.size()) {
void GfxMacIconBar::setIconEnabled(int16 iconIndex, bool enabled) {
if (iconIndex < 0)
_allDisabled = !enabled;
else if (iconIndex < (int)_iconBarItems.size()) {
_iconBarItems[iconIndex].enabled = enabled;
}
}

Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) {
Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8());
ResourceType type = isSelected ? kResourceTypeMacIconBarPictS : kResourceTypeMacIconBarPictN;
void GfxMacIconBar::setInventoryIcon(int16 icon) {
Graphics::Surface *surface = 0;

if (icon >= 0)
surface = loadPict(ResourceId(kResourceTypeMacPict, icon));

if (_inventoryIcon) {
// Free old inventory icon if we're removing the inventory icon
// or setting a new one.
if ((icon < 0) || surface) {
_inventoryIcon->free();
delete _inventoryIcon;
_inventoryIcon = 0;
}
}

Resource *res = g_sci->getResMan()->findResource(ResourceId(type, iconIndex + 1), false);
if (surface)
_inventoryIcon = surface;

drawIcon(_inventoryIndex, false);
}

Graphics::Surface *GfxMacIconBar::loadPict(ResourceId id) {
Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8());
Resource *res = g_sci->getResMan()->findResource(id, false);

if (!res || res->size == 0)
return 0;
Expand All @@ -165,6 +219,11 @@ Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected)
return surface;
}

Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) {
ResourceType type = isSelected ? kResourceTypeMacIconBarPictS : kResourceTypeMacIconBarPictN;
return loadPict(ResourceId(type, iconIndex + 1));
}

void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
byte *pixels = (byte *)surf->pixels;

Expand All @@ -180,4 +239,59 @@ void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
}
}

bool GfxMacIconBar::pointOnIcon(uint32 iconIndex, Common::Point point) {
return _iconBarItems[iconIndex].rect.contains(point);
}

reg_t GfxMacIconBar::handleEvents() {
// Peek event queue for a mouse button press
EventManager *evtMgr = g_sci->getEventManager();
SciEvent evt = evtMgr->getSciEvent(SCI_EVENT_MOUSE_PRESS | SCI_EVENT_PEEK);

// No mouse press found
if (evt.type == SCI_EVENT_NONE)
return NULL_REG;

// If the mouse is not over the icon bar, return
if (evt.mousePos.y < g_sci->_gfxScreen->getHeight())
return NULL_REG;

// Remove event from queue
evtMgr->getSciEvent(SCI_EVENT_MOUSE_PRESS);

// Mouse press on the icon bar, check the icon rectangles
uint iconNr;
for (iconNr = 0; iconNr < _iconBarItems.size(); iconNr++) {
if (pointOnIcon(iconNr, evt.mousePos) && isIconEnabled(iconNr))
break;
}

// Mouse press not on an icon
if (iconNr == _iconBarItems.size())
return NULL_REG;

drawIcon(iconNr, true);
bool isSelected = true;

// Wait for mouse release
while (evt.type != SCI_EVENT_MOUSE_RELEASE) {
// Mimic behavior of SSCI when moving mouse with button held down
if (isSelected != pointOnIcon(iconNr, evt.mousePos)) {
isSelected = !isSelected;
drawIcon(iconNr, isSelected);
}

evt = evtMgr->getSciEvent(SCI_EVENT_MOUSE_RELEASE);
g_system->delayMillis(10);
}

drawIcon(iconNr, false);

// If user moved away from the icon, we do nothing
if (pointOnIcon(iconNr, evt.mousePos))
return _iconBarItems[iconNr].object;

return NULL_REG;
}

} // End of namespace Sci
15 changes: 11 additions & 4 deletions engines/sci/graphics/maciconbar.h
Expand Up @@ -43,10 +43,9 @@ class GfxMacIconBar {

void addIcon(reg_t obj);
void drawIcons();
void redrawIcon(uint16 index);
void drawSelectedImage(uint16 index);
bool isIconEnabled(uint16 index) const;
void setIconEnabled(uint16 index, bool enabled);
void setIconEnabled(int16 index, bool enabled);
void setInventoryIcon(int16 icon);
reg_t handleEvents();

private:
struct IconBarItem {
Expand All @@ -59,12 +58,20 @@ class GfxMacIconBar {

Common::Array<IconBarItem> _iconBarItems;
uint32 _lastX;
uint16 _inventoryIndex;
Graphics::Surface *_inventoryIcon;
bool _allDisabled;

Graphics::Surface *loadPict(ResourceId id);
Graphics::Surface *createImage(uint32 iconIndex, bool isSelected);
void remapColors(Graphics::Surface *surf, byte *palette);

void drawIcon(uint16 index, bool selected);
void drawSelectedImage(uint16 index);
bool isIconEnabled(uint16 index) const;
void drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect);
void drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect);
bool pointOnIcon(uint32 iconIndex, Common::Point point);
};

} // End of namespace Sci
Expand Down

0 comments on commit 952d1a0

Please sign in to comment.