From c80af54ef9b5564e35f052f93748eccbfd2b25a6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 23 Aug 2011 21:12:07 +1000 Subject: TSAGE: Started implementation of Blue Force UI classes --- engines/tsage/blue_force/blueforce_logic.cpp | 9 +- engines/tsage/blue_force/blueforce_logic.h | 16 +- engines/tsage/blue_force/blueforce_ui.cpp | 369 +++++++++++++++++++++++++++ engines/tsage/blue_force/blueforce_ui.h | 135 ++++++++++ engines/tsage/core.cpp | 20 ++ engines/tsage/core.h | 13 + engines/tsage/globals.cpp | 1 + engines/tsage/globals.h | 2 + engines/tsage/module.mk | 1 + 9 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 engines/tsage/blue_force/blueforce_ui.cpp create mode 100644 engines/tsage/blue_force/blueforce_ui.h diff --git a/engines/tsage/blue_force/blueforce_logic.cpp b/engines/tsage/blue_force/blueforce_logic.cpp index 46c9307632..c680143c0d 100644 --- a/engines/tsage/blue_force/blueforce_logic.cpp +++ b/engines/tsage/blue_force/blueforce_logic.cpp @@ -263,7 +263,7 @@ SceneExt::SceneExt(): Scene() { _field372 = 0; _field37A = 0; - _field37C = NULL; + _eventHandler = NULL; } void SceneExt::postInit(SceneObjectList *OwnerList) { @@ -350,6 +350,13 @@ void SceneHandlerExt::process(Event &event) { // TODO: All the new stuff from Blue Force } +/*--------------------------------------------------------------------------*/ + +BlueForceInvObjectList::BlueForceInvObjectList() { + +} + + } // End of namespace BlueForce } // End of namespace TsAGE diff --git a/engines/tsage/blue_force/blueforce_logic.h b/engines/tsage/blue_force/blueforce_logic.h index 9ab8a87a0c..af3da97551 100644 --- a/engines/tsage/blue_force/blueforce_logic.h +++ b/engines/tsage/blue_force/blueforce_logic.h @@ -37,6 +37,8 @@ namespace BlueForce { using namespace TsAGE; +#define BLUE_INVENTORY (*((::TsAGE::BlueForce::BlueForceInvObjectList *)_globals->_inventory)) + class BlueForceGame: public Game { public: virtual void start(); @@ -87,12 +89,17 @@ public: virtual void startMove(SceneObject *sceneObj, va_list va); }; +class SceneItemType3: public SceneItemType1 { +public: + +}; + class SceneExt: public Scene { public: AObjectArray _timerList, _objArray2; int _field372; int _field37A; - EventHandler *_field37C; + EventHandler *_eventHandler; Rect _v51C34; public: @@ -130,6 +137,13 @@ class BlueAnimatedSpeaker: public Speaker { public: }; +class BlueForceInvObjectList : public InvObjectList { +public: + BlueForceInvObjectList(); + + virtual Common::String getClassName() { return "BlueForceInvObjectList"; } +}; + } // End of namespace BlueForce } // End of namespace TsAGE diff --git a/engines/tsage/blue_force/blueforce_ui.cpp b/engines/tsage/blue_force/blueforce_ui.cpp new file mode 100644 index 0000000000..9214f2b5cd --- /dev/null +++ b/engines/tsage/blue_force/blueforce_ui.cpp @@ -0,0 +1,369 @@ +/* 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 "tsage/blue_force/blueforce_ui.h" +#include "tsage/blue_force/blueforce_logic.h" +#include "tsage/tsage.h" +#include "tsage/core.h" + +namespace TsAGE { + +namespace BlueForce { + +void UIElement::synchronize(Serializer &s) { + AltSceneObject::synchronize(s); + s.syncAsSint16LE(_field88); + s.syncAsSint16LE(_enabled); + s.syncAsSint16LE(_frameNum); +} + +void UIElement::setup(int visage, int stripNum, int frameNum, int posX, int posY, int priority) { + _field88 = 0; + _frameNum = frameNum; + _enabled = true; + + SceneObject::setup(visage, stripNum, frameNum, posX, posY, priority); +} + +void UIElement::setEnabled(bool flag) { + if (_enabled != flag) { + _enabled = flag; + setFrame(_enabled ? _frameNum : _frameNum + 2); + } +} + +/*--------------------------------------------------------------------------*/ + +void UIQuestion::process(Event &event) { + if (event.eventType == EVENT_BUTTON_DOWN) { + int currentCursor = GLOBALS._events.getCursor(); + GLOBALS._events.hideCursor(); + showDescription(currentCursor); + + event.handled = true; + } +} + +void UIQuestion::showDescription(int lineNum) { + if (lineNum == 8) { + // Unknown object description + } else { + // Display object description + SceneItem::display(9001, lineNum, SET_WIDTH, 312, SET_X, 4, SET_Y, + GLOBALS._sceneManager._scene->_sceneBounds.top + BF_INTERFACE_Y + 2, + SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 19, SET_EXT_BGCOLOR, 9, + SET_EXT_FGCOLOR, 13, LIST_END); + } +} + +void UIQuestion::setEnabled(bool flag) { + if (_enabled != flag) { + UIElement::setEnabled(flag); + BF_GLOBALS._uiElements.draw(); + } +} + +/*--------------------------------------------------------------------------*/ + +void UIScore::postInit(SceneObjectList *OwnerList) { + int xp = 266; + _digit3.setup(1, 6, 1, 266, 180, 255); + xp += 7; + _digit2.setup(1, 6, 1, 266, 180, 255); + xp += 7; + _digit1.setup(1, 6, 1, 266, 180, 255); + xp += 7; + _digit0.setup(1, 6, 1, 266, 180, 255); +} + +void UIScore::draw() { + _digit3.draw(); + _digit2.draw(); + _digit1.draw(); + _digit0.draw(); +} + +void UIScore::updateScore() { + int score = BF_GLOBALS._uiElements._scoreValue; + + _digit3.setFrame(score / 1000); score %= 1000; + _digit2.setFrame(score / 100); score %= 100; + _digit1.setFrame(score / 10); score %= 10; + _digit0.setFrame(score); +} + +/*--------------------------------------------------------------------------*/ + +UIInventorySlot::UIInventorySlot(): UIElement() { + _objIndex = 0; +} + +void UIInventorySlot::synchronize(Serializer &s) { + UIElement::synchronize(s); + s.syncAsSint16LE(_objIndex); +} + +void UIInventorySlot::process(Event &event) { + if (event.eventType == EVENT_BUTTON_DOWN) { + event.handled = true; + + if (_objIndex == 66) { + // Handle showing gun and ammo + warning("TODO: show gun"); + } else if (_objIndex != 0) { + GLOBALS._events.setCursor((CursorType)_objIndex); + } + } +} + +/*--------------------------------------------------------------------------*/ + +UIInventoryScroll::UIInventoryScroll() { + _isLeft = false; +} + +void UIInventoryScroll::synchronize(Serializer &s) { + UIElement::synchronize(s); + s.syncAsSint16LE(_isLeft); +} + +void UIInventoryScroll::process(Event &event) { + if (event.eventType == EVENT_BUTTON_DOWN) { + warning("TODO: UIInventoryScroll::process"); + event.handled = true; + } +} + +/*--------------------------------------------------------------------------*/ + +UICollection::UICollection(): EventHandler() { + _clearScreen = false; + _visible = false; + _field4E = 0; +} + +void UICollection::setup(const Common::Point &pt) { + _position = pt; + _bounds.left = _bounds.right = pt.x; + _bounds.top = _bounds.bottom = pt.y; +} + +void UICollection::hide() { + erase(); + _visible = false; +} + +void UICollection::erase() { + if (_clearScreen) { + Rect tempRect(0, BF_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT); + GLOBALS._screenSurface.fillRect(tempRect, 0); + _clearScreen = false; + } +} + +void UICollection::resetClear() { + _clearScreen = false; +} + +void UICollection::draw() { + if (_visible) { + // Draw the elements + for (uint idx = 0; idx < _objList.size(); ++idx) + _objList[idx]->draw(); + + // Update the screen + g_system->updateScreen(); + _clearScreen = 1; + } +} + +/*--------------------------------------------------------------------------*/ + +void UIElements::process(Event &event) { + if (_clearScreen && BF_GLOBALS._player._field8E && (BF_GLOBALS._sceneManager._sceneNumber != 50)) { + if (_bounds.contains(event.mousePos)) { + + } else if (_field4E) { + BF_GLOBALS._events.hideCursor(); + BF_GLOBALS._events.setCursor((CursorType)1); + _field4E = 0; + + SceneExt *scene = (SceneExt *)BF_GLOBALS._sceneManager._scene; + if (scene->_eventHandler) { + error("TODO: UIElements::process _eventHandler"); + } + } + } +} + +void UIElements::setup(const Common::Point &pt) { + _slotStart = 0; + _itemList.clear(); + _scoreValue = 0; + _field820 = 1; + UICollection::setup(pt); + hide(); + + _object1.setup(1, 3, 1, 0, 0, 255); + add(&_object1); + + // Set up the inventory slots + for (int idx = 0; idx < 4; ++idx) { + UIElement *item = NULL; + switch (idx) { + case 0: + item = &_slot1; + break; + case 1: + item = &_slot2; + break; + case 2: + item = &_slot3; + break; + case 3: + item = &_slot4; + break; + } + + item->setup(9, 1, idx, idx * 63 + 2, 4, 255); + add(item); + } + + // Setup bottom-right hand buttons + int xp = 62; + _question.setup(1, 4, 7, xp, 16, 255); + _question.setEnabled(false); + + xp += 21; + _scrollLeft.setup(1, 4, 1, xp, 16, 255); + add(&_scrollLeft); + _scrollLeft._isLeft = true; + + xp += 22; + _scrollRight.setup(1, 4, 4, xp, 16, 255); + add(&_scrollRight); + _scrollRight._isLeft = false; + + // Set up the score + _score.postInit(); + add(&_score); + + // Set interface area + _bounds = Rect(0, BF_INTERFACE_Y - 1, SCREEN_WIDTH, SCREEN_HEIGHT); + + updateInventory(); +} + +void UIElements::add(UIElement *obj) { + // Add object + assert(_objList.size() < 12); + _objList.push_back(obj); + + obj->setPosition(Common::Point(_bounds.left + obj->_bounds.left, _bounds.top + obj->_bounds.top)); + GfxSurface s = obj->getFrame(); + s.draw(obj->_position); +} + +/** + * Handles updating the visual inventory in the user interface + */ +void UIElements::updateInventory() { + _score.updateScore(); + updateInvList(); + + // Enable scroll buttons if the player has more than four items + if (_itemCount > 4) { + _scrollLeft.setEnabled(true); + _scrollRight.setEnabled(true); + } else { + _scrollLeft.setEnabled(false); + _scrollRight.setEnabled(false); + } + + // Handle cropping the slots start within inventory + int last = (_itemList.size() - 1) / 4 + 1; + if (_slotStart < 0) + _slotStart = last - 1; + else if (_slotStart > (last - 1)) + _slotStart = 0; + + // Handle refreshing slot graphics + UIInventorySlot *slotList[4] = { &_slot1, &_slot2, &_slot3, &_slot4 }; + + SynchronizedList::iterator i; + int objIndex = 0; + for (i = BLUE_INVENTORY._itemList.begin(); i != BLUE_INVENTORY._itemList.end(); ++i, ++objIndex) { + InvObject *obj = *i; + + for (int slotIndex = 0; slotIndex < 4; ++slotIndex) { + int idx = _slotStart + slotIndex; + int objectIdx = (idx < (int)_itemList.size()) ? _itemList[idx] : 0; + + if (objectIdx == objIndex) { + UIInventorySlot *slot = slotList[slotIndex]; + + slot->_objIndex = objIndex; + slot->setVisage(obj->_visage); + slot->setStrip(obj->_strip); + slot->setFrame(obj->_frame); + } + } + } + + if (_field820) + draw(); +} + +/** + * Update the list of the indexes of items in the player's inventory + */ +void UIElements::updateInvList() { + // Update the index list of items in the player's inventory + _itemList.clear(); + + SynchronizedList::iterator i; + int itemIndex = 0; + for (i = BF_GLOBALS._inventory->_itemList.begin(); i != BF_GLOBALS._inventory->_itemList.end(); ++i, ++itemIndex) { + InvObject *invObject = *i; + if (invObject->inInventory()) + _itemList.push_back(itemIndex); + } +} + +/** + * Updates an inventory slot with the item to be displayed + +void UIElements::updateInvSlot(UIInventorySlot *slot, int objIndex) { + slot->_objIndex = objIndex; + int itemId = (objIndex < (int)_itemList.size()) ? _itemList[objIndex] : 0; + InvObject *obj = BF_GLOBALS._inventory->_itemList[itemId + 2]; + + // TODO: Validate usage of fields + slot->setVisage(obj._displayResNum); + slot->setStrip(obj._rlbNum); + slot->setFrame(obj._cursorNum); +} +*/ + +} // End of namespace BlueForce + +} // End of namespace TsAGE diff --git a/engines/tsage/blue_force/blueforce_ui.h b/engines/tsage/blue_force/blueforce_ui.h new file mode 100644 index 0000000000..15e7a760d9 --- /dev/null +++ b/engines/tsage/blue_force/blueforce_ui.h @@ -0,0 +1,135 @@ +/* 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 TSAGE_BLUEFORCE_UI_H +#define TSAGE_BLUEFORCE_UI_H + +#include "common/scummsys.h" +#include "tsage/core.h" +#include "tsage/sound.h" + +namespace TsAGE { + +namespace BlueForce { + +using namespace TsAGE; + +class UIElement: public AltSceneObject { +public: + int _field88; + bool _enabled; + int _frameNum; + + virtual Common::String getClassName() { return "UIElement"; } + virtual void synchronize(Serializer &s); + + void setup(int visage, int stripNum, int frameNum, int posX, int posY, int priority); + void setEnabled(bool flag); +}; + +// This class implements the Question mark button +class UIQuestion: public UIElement { +private: + void showDescription(int lineNum); +public: + virtual void process(Event &event); + void setEnabled(bool flag); +}; + +// This class implements the score counter +class UIScore: public UIElement { +private: + void showDescription(int lineNum); +public: + UIElement _digit3, _digit2, _digit1, _digit0; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void draw(); + + void updateScore(); +}; + +class UIInventorySlot: public UIElement { +public: + int _objIndex; + + UIInventorySlot(); + virtual Common::String getClassName() { return "UIInventorySlot"; } + virtual void synchronize(Serializer &s); + virtual void process(Event &event); +}; + +class UIInventoryScroll: public UIElement { +public: + bool _isLeft; + + UIInventoryScroll(); + virtual Common::String getClassName() { return "UIInventoryScroll"; } + virtual void synchronize(Serializer &s); + virtual void process(Event &event); +}; + +class UICollection: public EventHandler { +protected: + void erase(); +public: + Common::Point _position; + Rect _bounds; + bool _visible; + bool _clearScreen; + int _field4E; + Common::Array _objList; + + UICollection(); + void setup(const Common::Point &pt); + void hide(); + void resetClear(); + void draw(); +}; + +class UIElements: public UICollection { +private: + void add(UIElement *obj); + void updateInventory(); + void updateInvList(); +public: + UIElement _object1; + UIQuestion _question; + UIScore _score; + UIInventorySlot _slot1, _slot2, _slot3, _slot4; + UIInventoryScroll _scrollLeft, _scrollRight; + ASound _sound; + int _itemCount, _slotStart, _scoreValue; + bool _field820; + Common::Array _itemList; + + virtual void postInit(SceneObjectList *OwnerList = NULL) { error("Wrong init() called"); } + virtual void process(Event &event); + + void setup(const Common::Point &pt); +}; + +} // End of namespace BlueForce + +} // End of namespace TsAGE + +#endif diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp index 42cb1d039f..cb97a2902a 100644 --- a/engines/tsage/core.cpp +++ b/engines/tsage/core.cpp @@ -55,6 +55,13 @@ InvObject::InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType curs DEALLOCATE(imgData); } +InvObject::InvObject(int visage, int strip, int frame, int sceneNumber) { + _visage = visage; + _strip = strip; + _frame = frame; + _sceneNumber = sceneNumber; +} + void InvObject::setCursor() { _globals->_events._currentCursor = _cursorId; @@ -2306,6 +2313,16 @@ void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, i /*--------------------------------------------------------------------------*/ +void AltSceneObject::postInit(SceneObjectList *OwnerList) { + SceneObject::postInit(&_globals->_sceneManager._altSceneObjects); +} + +void AltSceneObject::draw() { + SceneObject::draw(); +} + +/*--------------------------------------------------------------------------*/ + void SceneObjectExt2::postInit(SceneObjectList *OwnerList) { _v8A = -1; _v8C = -1; @@ -2750,6 +2767,9 @@ void Player::synchronize(Serializer &s) { s.syncAsByte(_canWalk); s.syncAsByte(_uiEnabled); s.syncAsSint16LE(_field8C); + + if (_vm->getGameID() == GType_BlueForce) + s.syncAsSint16LE(_field8E); } /*--------------------------------------------------------------------------*/ diff --git a/engines/tsage/core.h b/engines/tsage/core.h index 19987ed399..d9fa59a98a 100644 --- a/engines/tsage/core.h +++ b/engines/tsage/core.h @@ -55,8 +55,13 @@ public: CursorType _cursorId; Common::String _description; int _iconResNum; + + int _visage; + int _strip; + int _frame; public: InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType cursorId, const Common::String description); + InvObject(int visage, int strip, int frame, int sceneNumber); bool inInventory() const { return _sceneNumber == 1; } void setCursor(); @@ -567,6 +572,13 @@ public: void setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority); }; +class AltSceneObject: public SceneObject { +public: + virtual Common::String getClassName() { return "AltObjectExt"; } + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void draw(); +}; + class SceneObjectExt : public SceneObject { public: int _state; @@ -613,6 +625,7 @@ public: bool _canWalk; bool _uiEnabled; int _field8C; + int _field8E; public: Player(); diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp index 27067c7d1c..b20280ae87 100644 --- a/engines/tsage/globals.cpp +++ b/engines/tsage/globals.cpp @@ -121,6 +121,7 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface case GType_BlueForce: _game = new BlueForce::BlueForceGame(); + _inventory = new BlueForce::BlueForceInvObjectList(); _sceneHandler = new BlueForce::SceneHandlerExt(); break; } diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h index 2d409b6343..fb95f009cc 100644 --- a/engines/tsage/globals.h +++ b/engines/tsage/globals.h @@ -30,6 +30,7 @@ #include "tsage/events.h" #include "tsage/sound.h" #include "tsage/saveload.h" +#include "tsage/blue_force/blueforce_ui.h" namespace TsAGE { @@ -113,6 +114,7 @@ using namespace TsAGE; class BlueForceGlobals: public Globals { public: ASoundExt _sound1, _sound2, _sound3; + UIElements _uiElements; int _v4CEA2; int _v4CEA8; int _v4CEF2; diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk index 5c7104936e..2e775a6f2c 100644 --- a/engines/tsage/module.mk +++ b/engines/tsage/module.mk @@ -4,6 +4,7 @@ MODULE_OBJS := \ blue_force/blueforce_logic.o \ blue_force/blueforce_scenes0.o \ blue_force/blueforce_scenes1.o \ + blue_force/blueforce_ui.o \ converse.o \ core.o \ debugger.o \ -- cgit v1.2.3