From 2a521bb22df9c5e5d477deb32ebc8b6a54e91fde Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Fri, 15 Jul 2016 12:47:27 +0200 Subject: MACVENTURE: Add dialog system --- engines/macventure/dialog.cpp | 254 ++++++++++++++++++++++++++++++++++++++++++ engines/macventure/dialog.h | 146 ++++++++++++++++++++++++ engines/macventure/gui.cpp | 24 +++- engines/macventure/gui.h | 5 + engines/macventure/image.cpp | 27 +---- engines/macventure/module.mk | 3 +- 6 files changed, 434 insertions(+), 25 deletions(-) create mode 100644 engines/macventure/dialog.cpp create mode 100644 engines/macventure/dialog.h (limited to 'engines/macventure') diff --git a/engines/macventure/dialog.cpp b/engines/macventure/dialog.cpp new file mode 100644 index 0000000000..78fb942db1 --- /dev/null +++ b/engines/macventure/dialog.cpp @@ -0,0 +1,254 @@ +/* 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. +* +*/ + +#include "common/system.h" + +#include "macventure/dialog.h" + +namespace MacVenture { + +// Prebuilt dialogs + +enum { + // HACK + kMaxPrebuiltDialogElements = 10 +}; + +struct PrebuiltDialog { + Common::Rect bounds; + PrebuiltDialogElement elements[kMaxPrebuiltDialogElements]; +}; + +PrebuiltDialog prebuiltDialogs[kPrebuiltDialogCount] = { + + {/* kSaveAsDialog */ + Common::Rect(0, 146, 456, 254), + { {kDEButton, "YES", kDANone, Common::Point(24, 68), 120, 22}, + {kDEButton, "NO", kDACloseDialog, Common::Point(168, 68), 120, 22}, + {kDEButton, "CANCEL", kDACloseDialog, Common::Point(312, 68), 120, 22}, + {kDEPlainText, "Save As...", kDANone, Common::Point(100, 10), 340, 38}, + {kDETextInput, "", kDANone, Common::Point(100, 30), 340, 20}, + {kDEEnd, "", kDANone, Common::Point(0, 0), 0, 0}} + } + +}; + +Dialog::Dialog(Gui *gui, Common::Point pos, uint width, uint height) : + _gui(gui), _bounds(Common::Rect(pos.x, pos.y, pos.x + width, pos.y + height)) {} + +Dialog::Dialog(Gui *gui, PrebuiltDialogs prebuilt) { + _gui = gui; + const PrebuiltDialog &dialog = prebuiltDialogs[prebuilt]; + _bounds = dialog.bounds; + for (int i = 0; dialog.elements[i].type != kDEEnd; i++) { + addPrebuiltElement(dialog.elements[i]); + } +} + +Dialog::~Dialog() { + for (Common::Array::iterator it = _elements.begin(); it != _elements.end(); it++) { + delete *it; + } +} + +void Dialog::handleDialogAction(DialogElement *trigger, DialogAction action) { + switch(action) { + case kDACloseDialog: + _gui->closeDialog(); + break; + } +} + +const Graphics::Font& Dialog::getFont() { + return _gui->getCurrentFont(); +} + +bool Dialog::processEvent(Common::Event event) { + for (Common::Array::iterator it = _elements.begin(); it != _elements.end(); it++) { + if ((*it)->processEvent(this, event)) return true; + } +} + +void Dialog::addButton(Common::String title, MacVenture::DialogAction action, Common::Point position, uint width, uint height) { + _elements.push_back(new DialogButton(this, title, action, position, width, height)); +} + +void Dialog::addText(Common::String content, Common::Point position) { + _elements.push_back(new DialogPlainText(this, content, position)); +} + +void Dialog::addTextInput(Common::Point position, int width, int height) { + _elements.push_back(new DialogTextInput(this, position, width, height)); +} + +void Dialog::draw() { + Graphics::ManagedSurface compose; + // Compose the surface + compose.create(_bounds.width(), _bounds.height()); + Common::Rect base(0, 0, _bounds.width(), _bounds.height()); + compose.fillRect(base, kColorWhite); + compose.frameRect(base, kColorBlack); + for (Common::Array::iterator it = _elements.begin(); it != _elements.end(); it++) { + (*it)->draw(this, compose); + } + + g_system->copyRectToScreen(compose.getPixels(), compose.pitch, + _bounds.left, _bounds.top, _bounds.width(), _bounds.height()); +} + +void Dialog::localize(Common::Point &point) { + point.x -= _bounds.left; + point.y -= _bounds.top; +} + +void Dialog::setUserInput(Common::String content) { + _userInput = content; + debug(2, "Set user input: %s", _userInput.c_str()); +} + +void Dialog::addPrebuiltElement(const MacVenture::PrebuiltDialogElement &element) { + switch(element.type) { + case kDEButton: + addButton(element.title, element.action, element.position, element.width, element.height); + break; + case kDEPlainText: + addText(element.title, element.position); + break; + case kDETextInput: + addTextInput(element.position, element.width, element.height); + break; + } +} + +// Dialog Element + +DialogElement::DialogElement(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width, uint height) : + _text(title), _action(action) { + if (width == 0) { + width = dialog->getFont().getStringWidth(title); + } + if (height == 0) { + height = dialog->getFont().getFontHeight(); + } + _bounds = Common::Rect(position.x, position.y, position.x + width, position.y + height); + } + +bool DialogElement::processEvent(MacVenture::Dialog *dialog, Common::Event event) { + // HACK for test, please delete me + Common::Point mouse = event.mouse; + dialog->localize(mouse); + if (_bounds.contains(mouse)) debug(1, "Hovering over: %s", _text.c_str()); + + return doProcessEvent(dialog, event); +} + +void DialogElement::draw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) { + doDraw(dialog, target); +} + +const Common::String& DialogElement::getText() { + return doGetText(); +} + +const Common::String& DialogElement::doGetText() { + return _text; +} + +// CONCRETE DIALOG ELEMENTS + +DialogButton::DialogButton(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width, uint height): + DialogElement(dialog, title, action, position, width, height) {} + +bool DialogButton::doProcessEvent(MacVenture::Dialog *dialog, Common::Event event) { + Common::Point mouse = event.mouse; + if (event.type == Common::EVENT_LBUTTONDOWN) { + dialog->localize(mouse); + if (_bounds.contains(mouse)) { + debug(1, "Click! Button: %s", _text.c_str()); + dialog->handleDialogAction(this, _action); + return true; + } + } + return false; +} + +void DialogButton::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) { + target.fillRect(_bounds, kColorWhite); + target.frameRect(_bounds, kColorBlack); + // Draw title + dialog->getFont().drawString( + &target, _text, _bounds.left, _bounds.top, _bounds.width(), kColorBlack, Graphics::kTextAlignCenter); +} + +DialogPlainText::DialogPlainText(Dialog *dialog, Common::String content, Common::Point position) : + DialogElement(dialog, content, kDANone, position, 0, 0) { } + +DialogPlainText::~DialogPlainText() {} + +bool DialogPlainText::doProcessEvent(MacVenture::Dialog *dialog, Common::Event event) { + return false; +} + +void DialogPlainText::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) { + // Draw contents + dialog->getFont().drawString( + &target, _text, _bounds.left, _bounds.top, _bounds.width(), kColorBlack); + +} + +DialogTextInput::DialogTextInput(Dialog *dialog, Common::Point position, uint width, uint height) : + DialogElement(dialog, "", kDANone, position, width, height) {} +DialogTextInput::~DialogTextInput() {} + +bool DialogTextInput::doProcessEvent(Dialog *dialog, Common::Event event) { + if (event.type == Common::EVENT_KEYDOWN) { + switch (event.kbd.keycode) { + case Common::KEYCODE_BACKSPACE: + if (!_text.empty()) { + _text.deleteLastChar(); + dialog->setUserInput(_text); + return true; + } + break; + + default: + if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { + _text += (char)event.kbd.ascii; + dialog->setUserInput(_text); + return true; + } + + break; + } + } + return false; +} +void DialogTextInput::doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) { + target.fillRect(_bounds, kColorWhite); + target.frameRect(_bounds, kColorBlack); + dialog->getFont().drawString( + &target, _text, _bounds.left, _bounds.top, _bounds.width(), kColorBlack); +} + + + +} // End of namespace MacVenture diff --git a/engines/macventure/dialog.h b/engines/macventure/dialog.h new file mode 100644 index 0000000000..fa17432018 --- /dev/null +++ b/engines/macventure/dialog.h @@ -0,0 +1,146 @@ +/* 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. +* +*/ + +#ifndef MACVENTURE_DIALOG_H +#define MACVENTURE_DIALOG_H + +#include "graphics/macgui/macwindowmanager.h" + +#include "macventure/macventure.h" +#include "macventure/gui.h" + +namespace MacVenture { + +using namespace Graphics::MacGUIConstants; +class Gui; + +class DialogElement; + +enum DialogAction { + kDANone, + kDACloseDialog +}; + +enum PrebuiltDialogs { + kSaveAsDialog = 0, + kPrebuiltDialogCount +}; + +enum PrebuiltElementType { + kDEPlainText, + kDEButton, + kDETextInput, + kDEEnd +}; + +struct PrebuiltDialogElement { + PrebuiltElementType type; + Common::String title; + DialogAction action; + Common::Point position; + uint width; + uint height; +}; + +class Dialog { +public: + Dialog(Gui *gui, Common::Point pos, uint width, uint height); + Dialog(Gui *gui, PrebuiltDialogs prebuilt); + + ~Dialog(); + + bool processEvent(Common::Event event); + void draw(); + void localize(Common::Point &point); + void handleDialogAction(DialogElement *trigger, DialogAction action); + + const Graphics::Font& getFont(); + + void addButton(Common::String title, DialogAction action, Common::Point position, uint width = 0, uint height = 0); + void addText(Common::String content, Common::Point position); + void addTextInput(Common::Point position, int width, int height); + + void setUserInput(Common::String content); + +private: + void addPrebuiltElement(const PrebuiltDialogElement &element); + +private: + Gui *_gui; + + Common::String _userInput; + Common::Array _elements; + Common::Rect _bounds; +}; + +class DialogElement { +public: + DialogElement(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width = 0, uint height = 0); + virtual ~DialogElement() {} + + bool processEvent(Dialog *dialog, Common::Event event); + void draw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target); + const Common::String& getText(); + +private: + virtual bool doProcessEvent(Dialog *dialog, Common::Event event) = 0; + virtual void doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target) = 0; + virtual const Common::String& doGetText(); + +protected: + Common::String _text; + Common::Rect _bounds; + DialogAction _action; +}; + +// Dialog elements +class DialogButton : public DialogElement { +public: + DialogButton(Dialog *dialog, Common::String title, DialogAction action, Common::Point position, uint width = 0, uint height = 0); + ~DialogButton() {} + +private: + bool doProcessEvent(Dialog *dialog, Common::Event event); + void doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target); +}; + +class DialogPlainText : public DialogElement { +public: + DialogPlainText(Dialog *dialog, Common::String content, Common::Point position); + ~DialogPlainText(); +private: + bool doProcessEvent(Dialog *dialog, Common::Event event); + void doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target); +}; + +class DialogTextInput : public DialogElement { +public: + DialogTextInput(Dialog *dialog, Common::Point position, uint width, uint height); + ~DialogTextInput(); +private: + bool doProcessEvent(Dialog *dialog, Common::Event event); + void doDraw(MacVenture::Dialog *dialog, Graphics::ManagedSurface &target); +}; + +} // End of namespace MacVenture + +#endif diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp index 02f603659e..4b01f8bca9 100644 --- a/engines/macventure/gui.cpp +++ b/engines/macventure/gui.cpp @@ -112,6 +112,7 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) { _controlData = nullptr; _draggedObj.id = 0; _draggedObj.pos = Common::Point(0, 0); + _dialog = nullptr; _cursor = new Cursor(this); g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 500000, this, "macVentureCursor"); @@ -138,6 +139,9 @@ Gui::~Gui() { if (_consoleText) delete _consoleText; + if (_dialog) + delete _dialog; + Common::HashMap::const_iterator it = _assets.begin(); for (; it != _assets.end(); it++) { delete it->_value; @@ -181,7 +185,7 @@ void Gui::draw() { _wm.draw(); drawDraggedObject(); - + drawDialog(); //drawWindowTitle(kMainGameWindow, _mainGameWindow->getSurface()); } @@ -703,6 +707,10 @@ void Gui::drawDraggedObject() { } } +void Gui::drawDialog() { + if (_dialog) _dialog->draw(); +} + void Gui::updateWindow(WindowReference winID, bool containerOpen) { if (winID == kNoWindow) return; if (winID == kSelfWindow || containerOpen) { @@ -794,6 +802,11 @@ void Gui::printText(const Common::String & text) { _consoleText->printLine(text, _outConsoleWindow->getDimensions().width()); } +void Gui::closeDialog() { + delete _dialog; + _dialog = nullptr; +} + void Gui::moveDraggedObject(Common::Point target) { Common::Point newPos = target + _draggedObj.mouseOffset; bool movement = false; @@ -1006,6 +1019,8 @@ void Gui::handleMenuAction(MenuAction action) { break; case MacVenture::kMenuActionSaveAs: debug("MacVenture Menu Action: Save As"); + // HACK this should be wrapped in a function + _dialog = new Dialog(this, kSaveAsDialog); break; case MacVenture::kMenuActionQuit: debug("MacVenture Menu Action: Quit"); @@ -1120,6 +1135,8 @@ bool Gui::processEvent(Common::Event &event) { processed |= _cursor->processEvent(event); + if (_dialog && _dialog->processEvent(event)) return true; + if (event.type == Common::EVENT_MOUSEMOVE) { if (_draggedObj.id != 0) { moveDraggedObject(event.mouse); @@ -1247,8 +1264,6 @@ bool Gui::processInventoryEvents(WindowClick click, Common::Event & event) { // Find the appropriate window WindowReference ref = findWindowAtPoint(event.mouse); - // TODO DELETE MEEEE! - debug("WindowFound: %d", ref); if (ref == kNoWindow) return false; Graphics::MacWindow *win = findWindow(ref); WindowData &data = findWindowData((WindowReference) ref); @@ -1267,11 +1282,14 @@ void Gui::processCursorTick() { void Gui::handleSingleClick(Common::Point pos) { debug("Single Click"); + // HACK + if (_dialog) return; handleDragRelease(pos, false, false); } void Gui::handleDoubleClick(Common::Point pos) { debug("Double Click"); + if (_dialog) return; handleDragRelease(pos, false, true); } diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h index a44813511c..046e7e516c 100644 --- a/engines/macventure/gui.h +++ b/engines/macventure/gui.h @@ -31,6 +31,7 @@ #include "macventure/container.h" #include "macventure/image.h" +#include "macventure/dialog.h" namespace MacVenture { @@ -43,6 +44,7 @@ class Cursor; class ConsoleText; class CommandButton; class ImageAsset; +class Dialog; enum MenuAction { kMenuActionAbout, @@ -244,6 +246,7 @@ public: void updateExit(ObjID id); void printText(const Common::String &text); + void closeDialog(); // Ugly switches BorderBounds borderBounds(MVWindowType type); @@ -268,6 +271,7 @@ private: // Attributes Graphics::MacWindow *_diplomaWindow; Common::Array _inventoryWindows; Graphics::Menu *_menu; + Dialog *_dialog; Container *_graphics; Common::HashMap _assets; @@ -305,6 +309,7 @@ private: // Methods void drawDraggedObject(); void drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface *surface); void drawWindowTitle(WindowReference target, Graphics::ManagedSurface *surface); + void drawDialog(); void moveDraggedObject(Common::Point target); diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp index 21986e382c..cbe3cc910d 100644 --- a/engines/macventure/image.cpp +++ b/engines/macventure/image.cpp @@ -100,7 +100,7 @@ void ImageAsset::decodePPIC(ObjID id, Common::Array &data) { _bitWidth = w; _bitHeight = h; - for (uint i = 0; i < _rowBytes * h; i++) { + for (int i = 0; i < _rowBytes * h; i++) { data.push_back(0); } @@ -141,22 +141,7 @@ void ImageAsset::decodePPIC0(Common::BitStream & stream, Common::Array &da data[p] = v & 0xff; p++; } } - /* - for (var i=0;i>>=16-ppic.bit; - bitmap.data[p++]=(v>>8)&0xff; - bitmap.data[p++]=v&0xff; - } - if (bytes) - { - v=ppic.bits(bytes); - v<<=16-bytes; - bitmap.data[p++]=(v>>8)&0xff; - bitmap.data[p++]=v&0xff; - } - */ + } void ImageAsset::decodePPIC1(Common::BitStream & stream, Common::Array &data) { @@ -186,7 +171,7 @@ void ImageAsset::decodePPIC3(Common::BitStream & stream, Common::Array &da if (huff.symbols[j] >= huff.symbols[i - 1]) huff.symbols[j]++; - for (uint i = 0x10; i >= 0; i--) { + for (int i = 0x10; i >= 0; i--) { if (huff.symbols[i] == 0x10) { huff.symbols[i] = 0xff; break; @@ -297,7 +282,7 @@ void ImageAsset::decodeHuffGraphic(const PPICHuff & huff, Common::BitStream & st if (flags & 2) delta *= 2; pos = 0; uint q = delta; - for (uint i = 0;i < _bitHeight * _rowBytes - delta;i++) { + for (int i = 0; i < _bitHeight * _rowBytes - delta; i++) { data[q] ^= data[pos]; q++; pos++; @@ -390,10 +375,10 @@ bool ImageAsset::isRectInside(Common::Rect rect) { // HACK is it &&, or ||? if (_maskData.empty()) return (rect.width() > 0 && rect.height() > 0); - for (uint y = rect.top; y < rect.top + rect.height(); y++) { + for (int y = rect.top; y < rect.top + rect.height(); y++) { uint bmpofs = y * _rowBytes; byte pix; - for (uint x = rect.left; x < rect.left + rect.width(); x++) { + for (int x = rect.left; x < rect.left + rect.width(); x++) { pix = _maskData[bmpofs + (x >> 3)] & (1 << (7 - (x & 7))); if (pix) return true; } diff --git a/engines/macventure/module.mk b/engines/macventure/module.mk index 022b8d7c32..813677c33c 100644 --- a/engines/macventure/module.mk +++ b/engines/macventure/module.mk @@ -8,7 +8,8 @@ MODULE_OBJS := \ text.o \ world.o \ script.o \ - macventure.o + macventure.o \ + dialog.o MODULE_DIRS += \ engines/macventure -- cgit v1.2.3