aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBorja Lorente2016-06-22 00:47:53 +0200
committerBorja Lorente2016-08-14 18:32:46 +0200
commit0743e9531b5ef871e17cd7ca88966ea2c07b7147 (patch)
treebcdb310d791ae610a2e3c6a1424987d7e3f2d385
parent4d8f8fd36bdb9b1f807f4da04c9e3e4c3438dbfa (diff)
downloadscummvm-rg350-0743e9531b5ef871e17cd7ca88966ea2c07b7147.tar.gz
scummvm-rg350-0743e9531b5ef871e17cd7ca88966ea2c07b7147.tar.bz2
scummvm-rg350-0743e9531b5ef871e17cd7ca88966ea2c07b7147.zip
MACVENTURE: Implemente dynamic object drawing
-rw-r--r--engines/macventure/gui.cpp108
-rw-r--r--engines/macventure/gui.h25
-rw-r--r--engines/macventure/image.cpp4
-rw-r--r--engines/macventure/image.h15
-rw-r--r--engines/macventure/macventure.cpp113
-rw-r--r--engines/macventure/macventure.h11
-rw-r--r--engines/macventure/module.mk2
-rw-r--r--engines/macventure/world.cpp2
8 files changed, 199 insertions, 81 deletions
diff --git a/engines/macventure/gui.cpp b/engines/macventure/gui.cpp
index 90d57aafc2..e202b82d3e 100644
--- a/engines/macventure/gui.cpp
+++ b/engines/macventure/gui.cpp
@@ -86,6 +86,16 @@ Gui::Gui(MacVentureEngine *engine, Common::MacResManager *resman) {
Gui::~Gui() {
+ if (_windowData)
+ delete _windowData;
+
+ if (_controlData)
+ delete _controlData;
+
+ Common::HashMap<ObjID, ImageAsset*>::const_iterator it = _assets.begin();
+ for (; it != _assets.end(); it++) {
+ delete it->_value;
+ }
}
void Gui::draw() {
@@ -104,6 +114,10 @@ void Gui::drawTitle() {
warning("drawTitle hasn't been tested yet");
}
+void Gui::drawExit(ObjID id) {
+ warning("Unimplemented method: drawExit");
+}
+
bool Gui::processEvent(Common::Event &event) {
bool processed = false;
if (event.type == Common::EVENT_LBUTTONDOWN) {
@@ -164,7 +178,7 @@ void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array
originx = originx > childPos.x ? childPos.x : originx;
originy = originy > childPos.y ? childPos.y : originy;
}
- data.children.push_back(child);
+ data.children.push_back(DrawableObject(child, kBlitDirect));
}
}
if (originx != 0x7fff) data.bounds.left = originx;
@@ -172,6 +186,20 @@ void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array
if (ref != kMainGameWindow) data.updateScroll = true;
}
+void Gui::addChild(WindowReference target, ObjID child) {
+ findWindowData(target).children.push_back(DrawableObject(child, kBlitDirect));
+}
+
+void Gui::removeChild(WindowReference target, ObjID child) {
+ WindowData data = findWindowData(target);
+ uint index = 0;
+ for (;index < data.children.size(); index++) {
+ if (data.children[index].obj == child) break;
+ }
+
+ data.children.remove_at(index);
+}
+
void Gui::initGUI() {
_screen.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8());
_wm.setScreen(&_screen);
@@ -230,6 +258,7 @@ void Gui::initWindows() {
_selfWindow->setCallback(selfWindowCallback, this);
loadBorder(_selfWindow, "border_self_inac.bmp", false);
loadBorder(_selfWindow, "border_self_act.bmp", true);
+ findWindowData(kSelfWindow).children.push_back(DrawableObject(1, kBlitDirect));
// Exits Window
_exitsWindow = _wm.addWindow(false, true, true);
@@ -443,7 +472,6 @@ void Gui::drawWindows() {
drawCommandsWindow();
drawMainGameWindow();
- drawSelfWindow();
}
void Gui::drawCommandsWindow() {
@@ -460,8 +488,7 @@ void Gui::drawCommandsWindow() {
data.bounds.right - data.bounds.left,
kColorBlack,
Graphics::kTextAlignCenter);
- }
- else {
+ } else {
Common::List<CommandButton>::const_iterator it = _controlData->begin();
for (; it != _controlData->end(); ++it) {
CommandButton button = *it;
@@ -474,32 +501,15 @@ void Gui::drawCommandsWindow() {
void Gui::drawMainGameWindow() {
Graphics::ManagedSurface *srf = _mainGameWindow->getSurface();
BorderBounds border = borderBounds(getWindowData(kMainGameWindow).type);
- srf->fillRect(
- Common::Rect(
- border.leftOffset * 2,
- border.topOffset * 2,
- srf->w - (border.rightOffset * 3),
- srf->h - (border.bottomOffset * 3)),
- kColorBlack);
-
- WindowData &data = findWindowData(kMainGameWindow);
- for (Common::Array<ObjID>::const_iterator it = data.children.begin(); it != data.children.end(); it++) {
- Common::Point pos = _engine->getObjPosition(*it);
- srf->fillRect(
- Common::Rect(
- border.leftOffset * 2 + pos.x,
- border.topOffset * 2 + pos.y,
- 5,
- 5),
- kColorBlack);
- }
- // Tests
- ImageAsset testBg(3, _graphics);
- testBg.blitInto(srf, border.leftOffset * 2, border.topOffset * 2, kBlitDirect);
+ ImageAsset bg(3, _graphics);
+ bg.blitInto(
+ _mainGameWindow->getSurface(),
+ border.leftOffset * 2,
+ border.topOffset * 2,
+ kBlitDirect);
- //ImageAsset testImg(428, _graphics);
- //testImg.blitInto(srf, border.leftOffset * 2 + 10,border.topOffset * 2 + 10, kBlitBIC);
+ drawObjectsInWindow(kMainGameWindow, _mainGameWindow->getSurface());
}
@@ -515,6 +525,27 @@ void Gui::drawSelfWindow() {
kColorWhite);
}
+void Gui::drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface * surface) {
+ WindowData &data = findWindowData(kMainGameWindow);
+ BorderBounds border = borderBounds(data.type);
+ Common::Point pos;
+ ObjID child;
+ BlitMode mode;
+ for (Common::Array<DrawableObject>::const_iterator it = data.children.begin(); it != data.children.end(); it++) {
+ child = (*it).obj;
+ mode = (BlitMode)(*it).mode;
+ pos = _engine->getObjPosition(child);
+ if (!_assets.contains(child)) {
+ _assets[child] = new ImageAsset(child, _graphics);
+ }
+ _assets[child]->blitInto(
+ surface,
+ border.leftOffset * 2 + pos.x,
+ border.topOffset * 2 + pos.y,
+ mode);
+ }
+}
+
WindowData & Gui::findWindowData(WindowReference reference) {
assert(_windowData);
@@ -631,7 +662,7 @@ void Gui::handleMenuAction(MenuAction action) {
}
void Gui::updateWindow(WindowReference winID, bool containerOpen) {
- if (winID > 0x90) return;
+ if (winID > 0x90 || winID == kNoWindow) return;
if (winID == kSelfWindow || containerOpen) {
if (winID == kMainGameWindow) {
drawMainGameWindow();
@@ -639,9 +670,21 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) {
warning("Unimplemented: fill window with background");
}
WindowData &data = findWindowData(winID);
- Common::Array<ObjID> children = data.children;
- for (Common::Array<ObjID>::const_iterator it = children.begin(); it != children.end(); it++) {
- warning("Unimplemented: draw object %x", *it);
+ Common::Array<DrawableObject> &children = data.children;
+ for (uint i = 0; i < children.size(); i++) {
+ uint flag = 0;
+ ObjID child = children[i].obj;
+ BlitMode mode;
+ bool off = _engine->isObjVisible(child);
+ if (!off || _engine->isObjClickable(child)) {
+ mode = kBlitBIC;
+ if (_engine->isObjSelected(child)) {
+ mode = kBlitOR;
+ } else if (off || flag) {
+ mode = kBlitXOR;
+ }
+ children[i] = DrawableObject(child, mode);
+ }
}
if (data.type == kZoomDoc && data.updateScroll) {
warning("Unimplemented: update scroll");
@@ -682,7 +725,6 @@ WindowReference Gui::createInventoryWindow() {
bool Gui::tryCloseWindow(WindowReference winID) {
WindowData data = findWindowData(winID);
- Graphics::MacWindow *wind;
if (winID < 0x80) { // Inventory window
warning("Window closing not implemented");
} else {
diff --git a/engines/macventure/gui.h b/engines/macventure/gui.h
index 404c18e808..2e8b6e20a2 100644
--- a/engines/macventure/gui.h
+++ b/engines/macventure/gui.h
@@ -39,7 +39,9 @@ using namespace Graphics::MacWindowConstants;
class MacVentureEngine;
typedef uint32 ObjID;
-//namespace MacVentureMenuActions {
+class CommandButton;
+class ImageAsset;
+
enum MenuAction {
kMenuActionAbout,
kMenuActionNew,
@@ -60,6 +62,7 @@ enum MenuAction {
//} using namespace MacVentureMenuActions;
enum WindowReference {
+ kNoWindow = 0,
kCommandsWindow = 0x80,
kMainGameWindow = 0x81,
kOutConsoleWindow = 0x82,
@@ -83,6 +86,16 @@ enum MVWindowType {
kRDoc10 = 0x16
};
+
+struct DrawableObject {
+ ObjID obj;
+ byte mode;
+ DrawableObject(ObjID id, byte md) {
+ obj = id;
+ mode = md;
+ }
+};
+
struct WindowData {
Common::Rect bounds;
MVWindowType type;
@@ -91,7 +104,7 @@ struct WindowData {
WindowReference refcon;
uint8 titleLength;
Common::String title;
- Common::Array<ObjID> children;
+ Common::Array<DrawableObject> children;
bool updateScroll;
};
@@ -139,6 +152,7 @@ public:
void draw();
void drawMenu();
void drawTitle();
+ void drawExit(ObjID id);
bool processEvent(Common::Event &event);
void handleMenuAction(MenuAction action);
void updateWindow(WindowReference winID, bool containerOpen);
@@ -164,6 +178,9 @@ public:
void setWindowTitle(WindowReference winID, Common::String string);
void updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array<ObjID> &children);
+ void addChild(WindowReference target, ObjID child);
+ void removeChild(WindowReference target, ObjID child);
+
// Ugly switches
BorderBounds borderBounds(MVWindowType type);
@@ -188,10 +205,10 @@ private: // Attributes
Graphics::Menu *_menu;
Container *_graphics;
+ Common::HashMap<ObjID, ImageAsset*> _assets;
private: // Methods
-
// Initializers
void initGUI();
void initWindows();
@@ -209,6 +226,8 @@ private: // Methods
void drawMainGameWindow();
void drawSelfWindow();
+ void drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface *surface);
+
// Finders
WindowData& findWindowData(WindowReference reference);
diff --git a/engines/macventure/image.cpp b/engines/macventure/image.cpp
index 46d440c957..47b755a829 100644
--- a/engines/macventure/image.cpp
+++ b/engines/macventure/image.cpp
@@ -318,9 +318,9 @@ byte ImageAsset::walkHuff(const PPICHuff & huff, Common::BitStream & stream) {
}
void ImageAsset::blitInto(Graphics::ManagedSurface *target, uint32 x, uint32 y, BlitMode mode) {
- debug("Blitting image %x ", _id);
if (mode == kBlitDirect) {
blitDirect(target, x, y, _imgData);
+ return;
}
if (_container->getItemByteSize(_mask)) { // Has mask
@@ -344,7 +344,7 @@ void ImageAsset::blitInto(Graphics::ManagedSurface *target, uint32 x, uint32 y,
}
}
if (_container->getItemByteSize(_id) && mode > 0) {
- blitXOR(target, x, y, _maskData);
+ blitXOR(target, x, y, _imgData);
}
}
diff --git a/engines/macventure/image.h b/engines/macventure/image.h
index 21e544a76e..eb52da83ad 100644
--- a/engines/macventure/image.h
+++ b/engines/macventure/image.h
@@ -31,6 +31,14 @@ namespace MacVenture {
typedef uint32 ObjID;
class Container;
+
+enum BlitMode {
+ kBlitDirect = 0,
+ kBlitBIC = 1,
+ kBlitOR = 2,
+ kBlitXOR = 3
+};
+
enum GraphicsEncoding {
kPPIC0 = 0,
kPPIC1 = 1,
@@ -44,13 +52,6 @@ struct PPICHuff {
uint8 symbols[17];
};
-enum BlitMode {
- kBlitDirect = 0,
- kBlitBIC = 1,
- kBlitOR = 2,
- kBlitXOR = 3
-};
-
class ImageAsset {
public:
ImageAsset(ObjID original, Container *container);
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 9bdb99d12f..87b5d51327 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -115,13 +115,15 @@ Common::Error MacVentureEngine::run() {
if (_prepared) {
_prepared = false;
+ if (!_halted)
+ updateState();
+
if (_cmdReady || _halted) {
_halted = false;
if (runScriptEngine()) {
_halted = true;
_paused = true;
- }
- else {
+ } else {
_paused = false;
if (!updateState()) {
updateControls();
@@ -131,10 +133,9 @@ Common::Error MacVentureEngine::run() {
if (_gameState == kGameStateWinnig || _gameState == kGameStateLosing) {
endGame();
- }
-
- _gui->draw();
+ }
}
+ _gui->draw();
g_system->updateScreen();
g_system->delayMillis(50);
@@ -210,7 +211,7 @@ void MacVentureEngine::enqueueObject(ObjectQueueID type, ObjID objID) {
obj.exitx = _world->getObjAttr(objID, kAttrExitX);
obj.exity = _world->getObjAttr(objID, kAttrExitY);
obj.hidden = _world->getObjAttr(objID, kAttrHiddenExit);
- obj.offsecreen = _world->getObjAttr(objID, kAttrInvisible);
+ obj.offscreen = _world->getObjAttr(objID, kAttrInvisible);
obj.invisible = _world->getObjAttr(objID, kAttrUnclickable);
_objQueue.push_back(obj);
}
@@ -224,7 +225,7 @@ void MacVentureEngine::enqueueText(TextQueueID type, ObjID target, ObjID source,
_textQueue.push_back(newText);
}
-void MacVentureEngine::printTexts() {
+bool MacVentureEngine::printTexts() {
warning("printTexts: unimplemented");
for (uint i = 0; i < _textQueue.size(); i++) {
QueuedText text = _textQueue.front();
@@ -232,12 +233,15 @@ void MacVentureEngine::printTexts() {
switch (text.id) {
case kTextNumber:
debug("Print Number: %d", text.asset);
+ gameChanged();
break;
case kTextNewLine:
debug("Print Newline: ");
+ gameChanged();
break;
case kTextPlain:
debug("Print Plain Text: %s", _world->getText(text.asset).c_str());
+ gameChanged();
break;
}
}
@@ -326,7 +330,8 @@ void MacVentureEngine::endGame() {
bool MacVentureEngine::updateState() {
runObjQueue();
- return true;
+ bool wait = printTexts();
+ return wait;
}
void MacVentureEngine::revert() {
@@ -359,7 +364,7 @@ void MacVentureEngine::runObjQueue() {
closeObject(obj.object);
break;
case 0x7:
- checkObject(obj.object);
+ checkObject(obj);
break;
case 0x8:
reflectSwap(obj.object);
@@ -428,40 +433,68 @@ void MacVentureEngine::closeObject(ObjID objID) {
return;
}
-void MacVentureEngine::checkObject(ObjID objID) {
+void MacVentureEngine::checkObject(QueuedObject old) {
//warning("checkObject: unimplemented");
bool hasChanged = false;
debug("Check Object[%d] parent[%d] x[%d] y[%d]",
- objID,
- _world->getObjAttr(objID, kAttrParentObject),
- _world->getObjAttr(objID, kAttrPosX),
- _world->getObjAttr(objID, kAttrPosY));
+ old.object,
+ _world->getObjAttr(old.object, kAttrParentObject),
+ _world->getObjAttr(old.object, kAttrPosX),
+ _world->getObjAttr(old.object, kAttrPosY));
//bool incoming = isIncomingObj(objID);
//if (incoming) removeIncoming(objID);
- if (objID == 1) {
- if (_world->getObjAttr(objID, kAttrParentObject) != 0) {
- enqueueObject(kSetToPlayerParent, objID);
- }
- }
- _gui->updateWindow(findParentWindow(objID), true);
-
- WindowReference win = getObjWindow(objID);
- ObjID parent = objID;
+ ObjID id = old.object;
+ if (id == 1) {
+ if (old.parent != _world->getObjAttr(id, kAttrParentObject)) {
+ enqueueObject(kSetToPlayerParent, id);
+ }
+ if (old.offscreen != _world->getObjAttr(id, kAttrInvisible) ||
+ old.invisible != _world->getObjAttr(id, kAttrUnclickable)) {
+ updateWindow(findParentWindow(id));
+ }
+ } else if (old.parent != _world->getObjAttr(id, kAttrParentObject) ||
+ old.x != _world->getObjAttr(id, kAttrPosX) ||
+ old.y != _world->getObjAttr(id, kAttrPosY)) {
+ WindowReference oldWin = getObjWindow(old.parent);
+ if (oldWin) {
+ _gui->removeChild(oldWin, id);
+ hasChanged = true;
+ }
+
+ WindowReference newWin = getObjWindow(id);
+ if (newWin) {
+ _gui->addChild(newWin, id);
+ hasChanged = true;
+ }
+ } else if (old.offscreen != _world->getObjAttr(id, kAttrInvisible) ||
+ old.invisible != _world->getObjAttr(id, kAttrUnclickable)) {
+ updateWindow(findParentWindow(id));
+ }
+
+ if (_world->getObjAttr(id, kAttrIsExit)) {
+ if (hasChanged ||
+ old.hidden != _world->getObjAttr(id, kAttrHiddenExit) ||
+ old.exitx != _world->getObjAttr(id, kAttrExitX) ||
+ old.exity != _world->getObjAttr(id, kAttrExitY))
+ _gui->drawExit(id);
+ }
+ WindowReference win = getObjWindow(id);
+ ObjID cur = id;
ObjID root = _world->getObjAttr(1, kAttrParentObject);
- while (parent != root) {
- if (parent == 0 || !_world->getObjAttr(parent, kAttrContainerOpen)) break;
- parent = _world->getObjAttr(parent, kAttrParentObject);
+ while (cur != root) {
+ if (cur == 0 || !_world->getObjAttr(cur, kAttrContainerOpen)) break;
+ cur = _world->getObjAttr(cur, kAttrParentObject);
}
- if (parent == root) {
+ if (cur == root) {
if (win) return;
- enqueueObject(kOpenWindow, objID);
+ enqueueObject(kOpenWindow, id); //open
} else {
if (!win) return;
- enqueueObject(kCloseWindow, objID);
+ enqueueObject(kCloseWindow, id); //close
}
// Update children
- Common::Array<ObjID> children = _world->getChildren(objID, true);
+ Common::Array<ObjID> children = _world->getChildren(id, true);
for (uint i = 0; i < children.size(); i++) {
enqueueObject(kUpdateObject, children[i]);
}
@@ -543,6 +576,19 @@ Common::Point MacVentureEngine::getObjPosition(ObjID objID) {
return Common::Point(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY));
}
+bool MacVentureEngine::isObjVisible(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrInvisible) == 0;
+}
+
+bool MacVentureEngine::isObjClickable(ObjID objID) {
+ return _world->getObjAttr(objID, kAttrUnclickable) == 0;
+}
+
+bool MacVentureEngine::isObjSelected(ObjID objID) {
+ warning("Unimplemented: isObjSelected");
+ return false;
+}
+
WindowReference MacVentureEngine::getObjWindow(ObjID objID) {
switch (objID) {
case 0xfffc: return kExitsWindow;
@@ -555,7 +601,12 @@ WindowReference MacVentureEngine::getObjWindow(ObjID objID) {
}
WindowReference MacVentureEngine::findObjWindow(ObjID objID) {
- return kMainGameWindow;
+ // This is a bit of a hack, we take advantage of the consecutive nature of references
+ for (uint i = kCommandsWindow; i <= kDiplomaWindow; i++) {
+ const WindowData &data = _gui->getWindowData((WindowReference)i);
+ if (data.refcon == objID) { return data.refcon; }
+ }
+ return kNoWindow;
}
WindowReference MacVentureEngine::findParentWindow(ObjID objID) {
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index a23dbecd30..7e6f362a8c 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -133,7 +133,7 @@ struct QueuedObject {
uint exitx;
uint exity;
bool hidden;
- bool offsecreen;
+ bool offscreen;
bool invisible;
};
@@ -175,7 +175,7 @@ public:
void enqueueText(TextQueueID type, ObjID target, ObjID source, ObjID text);
void runObjQueue();
- void printTexts();
+ bool printTexts();
void focusObjWin(ObjID objID);
void updateWindow(WindowReference winID);
@@ -190,7 +190,11 @@ public:
uint32 randBetween(uint32 min, uint32 max);
uint32 getInvolvedObjects();
+ // Attributes consult
Common::Point getObjPosition(ObjID objID);
+ bool isObjVisible(ObjID objID);
+ bool isObjClickable(ObjID objID);
+ bool isObjSelected(ObjID objID);
WindowReference getObjWindow(ObjID objID);
WindowReference findObjWindow(ObjID objID);
@@ -212,7 +216,7 @@ private:
void focusObjectWindow(ObjID objID);
void openObject(ObjID objID);
void closeObject(ObjID objID);
- void checkObject(ObjID objID);
+ void checkObject(QueuedObject objID);
void reflectSwap(ObjID objID);
void toggleExits();
void zoomObject(ObjID objID);
@@ -252,6 +256,7 @@ private: // Attributes
bool _gameChanged;
Common::Array<QueuedObject> _objQueue;
+ Common::Array<QueuedObject> _inQueue;
Common::Array<QueuedObject> _soundQueue;
Common::Array<QueuedText> _textQueue;
diff --git a/engines/macventure/module.mk b/engines/macventure/module.mk
index efd5a693be..022b8d7c32 100644
--- a/engines/macventure/module.mk
+++ b/engines/macventure/module.mk
@@ -1,13 +1,13 @@
MODULE := engines/macventure
MODULE_OBJS := \
+ image.o \
detection.o \
gui.o \
object.o \
text.o \
world.o \
script.o \
- image.o \
macventure.o
MODULE_DIRS += \
diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp
index 7a93773386..2ee7bae92f 100644
--- a/engines/macventure/world.cpp
+++ b/engines/macventure/world.cpp
@@ -122,7 +122,7 @@ Common::Array<ObjID> World::getChildren(ObjID objID, bool recursive) {
res.push_back(getChildren(child, false));
child = _relations[child * 2 + 1];
}
- return Common::Array<ObjID>();
+ return res;
}
Attribute World::getGlobal(uint32 attrID) {