ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

emi.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/foreach.h"
00024 
00025 #include "engines/grim/emi/emi.h"
00026 #include "engines/grim/emi/emi_registry.h"
00027 #include "engines/grim/emi/lua_v2.h"
00028 #include "engines/grim/primitives.h"
00029 #include "engines/grim/set.h"
00030 #include "engines/grim/gfx_base.h"
00031 #include "engines/grim/actor.h"
00032 #include "graphics/pixelbuffer.h"
00033 
00034 
00035 namespace Grim {
00036 
00037 EMIEngine *g_emi = nullptr;
00038 
00039 EMIEngine::EMIEngine(OSystem *syst, uint32 gameFlags, GrimGameType gameType, Common::Platform platform, Common::Language language) :
00040         GrimEngine(syst, gameFlags, gameType, platform, language), _sortOrderInvalidated(false), _textObjectsSortOrderInvalidated(true) {
00041 
00042     g_emi = this;
00043     g_emiregistry = new EmiRegistry();
00044 }
00045 
00046 
00047 
00048 EMIEngine::~EMIEngine() {
00049     g_emi = nullptr;
00050     delete g_emiregistry;
00051     g_emiregistry = nullptr;
00052 }
00053 
00054 LuaBase *EMIEngine::createLua() {
00055     return new Lua_V2();
00056 }
00057 
00058 const char *EMIEngine::getUpdateFilename() {
00059     if (getGamePlatform() == Common::kPlatformWindows && !(getGameFlags() & ADGF_DEMO)) {
00060         switch (getGameLanguage()) {
00061             case Common::FR_FRA:
00062                 return "MonkeyUpdate_FRA.exe";
00063                 break;
00064             case Common::DE_DEU:
00065                 return "MonkeyUpdate_DEU.exe";
00066                 break;
00067             case Common::IT_ITA:
00068                 return "MonkeyUpdate_ITA.exe";
00069                 break;
00070             case Common::PT_BRA:
00071                 return "MonkeyUpdate_BRZ.exe";
00072                 break;
00073             case Common::ES_ESP:
00074                 return "MonkeyUpdate_ESP.exe";
00075                 break;
00076             case Common::EN_ANY:
00077             case Common::EN_GRB:
00078             case Common::EN_USA:
00079             default:
00080                 return "MonkeyUpdate.exe";
00081                 break;
00082         }
00083     } else
00084         return nullptr;
00085 }
00086 
00087 void EMIEngine::pushText() {
00088     foreach (TextObject *t, TextObject::getPool()) {
00089         t->incStackLevel();
00090     }
00091     invalidateTextObjectsSortOrder();
00092 }
00093 
00094 void EMIEngine::popText() {
00095     Common::List<TextObject *> toDelete;
00096 
00097     foreach (TextObject *t, TextObject::getPool()) {
00098         if (t->getStackLevel() == 0) {
00099             warning("Text stack top not empty; deleting object");
00100             toDelete.push_back(t);
00101         } else {
00102             t->decStackLevel();
00103         }
00104     }
00105 
00106     while (!toDelete.empty()) {
00107         TextObject *t = toDelete.front();
00108         toDelete.pop_front();
00109         delete t;
00110     }
00111 
00112     invalidateTextObjectsSortOrder();
00113 }
00114 
00115 void EMIEngine::purgeText() {
00116     Common::List<TextObject *> toDelete;
00117 
00118     foreach (TextObject *t, TextObject::getPool()) {
00119         if (t->getStackLevel() == 0) {
00120             toDelete.push_back(t);
00121         }
00122     }
00123 
00124     while (!toDelete.empty()) {
00125         TextObject *t = toDelete.front();
00126         toDelete.pop_front();
00127         delete t;
00128     }
00129 
00130     invalidateTextObjectsSortOrder();
00131 }
00132 
00133 void EMIEngine::drawNormalMode() {
00134     _currSet->setupCamera();
00135 
00136     g_driver->set3DMode();
00137 
00138     if (_setupChanged) {
00139         cameraPostChangeHandle(_currSet->getSetup());
00140         _setupChanged = false;
00141     }
00142 
00143     // Draw actors
00144     buildActiveActorsList();
00145     sortActiveActorsList();
00146     sortLayers();
00147 
00148     Bitmap *background = _currSet->getCurrSetup()->_bkgndBm;
00149     background->_data->load();
00150     uint32 numLayers = background->_data->_numLayers;
00151 
00152     Common::List<Layer *>::const_iterator nextLayer = _layers.begin();
00153     Common::List<Actor *>::const_iterator nextActor = _activeActors.begin();
00154     int32 currentLayer = numLayers - 1;
00155 
00156     int aso = (nextActor != _activeActors.end()) ? (*nextActor)->getEffectiveSortOrder() : -1;
00157     int lso = (nextLayer != _layers.end()) ? (*nextLayer)->getSortOrder() : -1;
00158     int bgso = currentLayer * 10;
00159 
00160     // interleave actors, background layers and additional stand-alone layers based
00161     // on their sortorder
00162     //
00163     // priority for same sort order:
00164     //   background layers (highest priority)
00165     //   stand-alone layers
00166     //   actors
00167     while (1) {
00168         if (aso >= 0 && aso > bgso && aso > lso) {
00169             if ((*nextActor)->isVisible() && ! (*nextActor)->isInOverworld())
00170                 (*nextActor)->draw();
00171             nextActor++;
00172             aso = (nextActor != _activeActors.end()) ? (*nextActor)->getEffectiveSortOrder() : -1;
00173             continue;
00174         }
00175         if (bgso >= 0 && bgso >= lso && bgso >= aso) {
00176             background->drawLayer(currentLayer);
00177             currentLayer--;
00178             bgso = currentLayer * 10;
00179             continue;
00180         }
00181         if (lso >= 0 && lso > bgso && lso >= aso) {
00182             (*nextLayer)->draw();
00183             nextLayer++;
00184             lso = (nextLayer != _layers.end()) ? (*nextLayer)->getSortOrder() : -1;
00185             continue;
00186         }
00187         break;
00188     }
00189 
00190     /* Clear depth buffer before starting to draw the Overworld:
00191      * - all actors of the Overworld should cover any non-Overworld drawings
00192      * - Overworld actors need to use the depth Buffer so that e.g. the pause screen
00193      *   is drawn above the inventory
00194      */
00195     g_driver->clearDepthBuffer();
00196 
00197     g_driver->drawDimPlane();
00198 
00199     foreach (Actor *a, _activeActors) {
00200         if (a->isInOverworld())
00201             a->draw();
00202     }
00203 
00204     // Draw Primitives
00205     foreach (PrimitiveObject *p, PrimitiveObject::getPool()) {
00206         p->draw();
00207     }
00208 
00209     flagRefreshShadowMask(false);
00210 
00211 }
00212 
00213 void EMIEngine::storeSaveGameImage(SaveGame *state) {
00214     unsigned int width = 160, height = 120;
00215     Bitmap *screenshot = g_driver->getScreenshot(width, height, true);
00216     if (!screenshot) {
00217         warning("Unable to store screenshot.");
00218         return;
00219     }
00220 
00221     // screenshots are not using the whole size of the texture
00222     // copy the actual screenshot to the correct position
00223     unsigned int texWidth = 256, texHeight = 128;
00224     unsigned int size = texWidth * texHeight;
00225     Graphics::PixelBuffer buffer = Graphics::PixelBuffer::createBuffer<565>(size, DisposeAfterUse::YES);
00226     buffer.clear(size);
00227     for (unsigned int j = 0; j < 120; j++) {
00228         buffer.copyBuffer(j * texWidth, j * width, width, screenshot->getData(0));
00229     }
00230 
00231     state->beginSection('SIMG');
00232     uint16 *data = (uint16 *)buffer.getRawBuffer();
00233     for (unsigned int l = 0; l < size; l++) {
00234         state->writeLEUint16(data[l]);
00235     }
00236     state->endSection();
00237     delete screenshot;
00238 }
00239 
00240 void EMIEngine::temporaryStoreSaveGameImage() {
00241     // store current rendered screen in g_driver
00242     g_grim->updateDisplayScene();
00243     g_driver->storeDisplay();
00244 }
00245 
00246 void EMIEngine::updateDrawMode() {
00247     // For EMI, draw mode is just like normal mode with frozen frame time.
00248     updateNormalMode();
00249 }
00250 
00251 void EMIEngine::invalidateTextObjectsSortOrder() {
00252     _textObjectsSortOrderInvalidated = true;
00253 }
00254 
00255 void EMIEngine::invalidateActiveActorsList() {
00256     GrimEngine::invalidateActiveActorsList();
00257     invalidateSortOrder();
00258 }
00259 
00260 void EMIEngine::invalidateSortOrder() {
00261     _sortOrderInvalidated = true;
00262 }
00263 
00264 bool EMIEngine::compareTextLayer(const TextObject *x, const TextObject *y) {
00265     int xl = x->getLayer();
00266     int yl = y->getLayer();
00267 
00268     if (xl == yl) {
00269         return x->getId() < y->getId();
00270     } else {
00271         return xl < yl;
00272     }
00273 }
00274 
00275 bool EMIEngine::compareLayer(const Layer *x, const Layer *y) {
00276     return x->getSortOrder() > y->getSortOrder();
00277 }
00278 
00279 void EMIEngine::drawTextObjects() {
00280     sortTextObjects();
00281     foreach (TextObject *t, _textObjects) {
00282         t->draw();
00283     }
00284 }
00285 
00286 void EMIEngine::sortTextObjects() {
00287     if (!_textObjectsSortOrderInvalidated)
00288         return;
00289 
00290     _textObjectsSortOrderInvalidated = false;
00291 
00292     _textObjects.clear();
00293     foreach (TextObject *t, TextObject::getPool()) {
00294         if (t->getStackLevel() == 0) {
00295             _textObjects.push_back(t);
00296         }
00297     }
00298 
00299     Common::sort(_textObjects.begin(), _textObjects.end(), compareTextLayer);
00300 }
00301 
00302 void EMIEngine::sortLayers() {
00303     _layers.clear();
00304     foreach (Layer *l, Layer::getPool()) {
00305         _layers.push_back(l);
00306     }
00307 
00308     Common::sort(_layers.begin(), _layers.end(), compareLayer);
00309 }
00310 
00311 bool EMIEngine::compareActor(const Actor *x, const Actor *y) {
00312     if (x->getEffectiveSortOrder() == y->getEffectiveSortOrder()) {
00313         Set::Setup *setup = g_grim->getCurrSet()->getCurrSetup();
00314         Math::Matrix4 camRot = setup->_rot;
00315 
00316         Math::Vector3d xp(x->getWorldPos() - setup->_pos);
00317         Math::Vector3d yp(y->getWorldPos() - setup->_pos);
00318         camRot.inverseRotate(&xp);
00319         camRot.inverseRotate(&yp);
00320 
00321         if (fabs(xp.z() - yp.z()) < 0.001f) {
00322             return x->getId() < y->getId();
00323         } else {
00324             return xp.z() > yp.z();
00325         }
00326     }
00327     return x->getEffectiveSortOrder() > y->getEffectiveSortOrder();
00328 }
00329 
00330 void EMIEngine::sortActiveActorsList() {
00331     if (!_sortOrderInvalidated) {
00332         return;
00333     }
00334 
00335     _sortOrderInvalidated = false;
00336 
00337     Common::sort(_activeActors.begin(), _activeActors.end(), compareActor);
00338 }
00339 
00340 } // end of namespace Grim


Generated on Sat Jul 13 2019 05:01:03 for ResidualVM by doxygen 1.7.1
curved edge   curved edge