2012-01-06 23:29:45 +01:00
|
|
|
/* ResidualVM - A 3D game interpreter
|
2008-06-13 14:57:47 +00:00
|
|
|
*
|
2012-01-06 23:29:45 +01:00
|
|
|
* ResidualVM is the legal property of its developers, whose names
|
2011-04-16 14:12:44 +02:00
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
2008-06-13 14:57:47 +00:00
|
|
|
* file distributed with this source distribution.
|
2006-04-02 14:20:45 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*
|
|
|
|
*/
|
2003-08-15 18:00:22 +00:00
|
|
|
|
2011-05-08 15:38:26 +02:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
|
|
|
|
2011-11-21 22:07:12 +01:00
|
|
|
#include "common/foreach.h"
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2011-07-23 15:37:14 +02:00
|
|
|
#include "engines/grim/debug.h"
|
2011-09-19 16:53:08 +02:00
|
|
|
#include "engines/grim/set.h"
|
2009-05-24 19:13:58 +00:00
|
|
|
#include "engines/grim/textsplit.h"
|
|
|
|
#include "engines/grim/colormap.h"
|
|
|
|
#include "engines/grim/grim.h"
|
2009-06-24 17:30:34 +00:00
|
|
|
#include "engines/grim/savegame.h"
|
2011-05-13 17:55:14 -07:00
|
|
|
#include "engines/grim/resource.h"
|
|
|
|
#include "engines/grim/bitmap.h"
|
2011-07-22 22:40:49 +02:00
|
|
|
#include "engines/grim/gfx_base.h"
|
2008-01-26 11:47:23 +00:00
|
|
|
|
2012-01-14 08:18:43 +01:00
|
|
|
#include "engines/grim/sound.h"
|
2005-01-05 18:28:50 +00:00
|
|
|
|
2009-05-25 06:49:57 +00:00
|
|
|
namespace Grim {
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
Set::Set(const Common::String &sceneName, Common::SeekableReadStream *data) :
|
2011-09-19 16:53:08 +02:00
|
|
|
PoolObject<Set, MKTAG('S', 'E', 'T', ' ')>(), _locked(false), _name(sceneName), _enableLights(false),
|
2011-09-07 23:08:59 +02:00
|
|
|
_lightsConfigured(false) {
|
2004-02-24 22:43:32 +00:00
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
char header[7];
|
|
|
|
data->read(header, 7);
|
|
|
|
data->seek(0, SEEK_SET);
|
|
|
|
if (memcmp(header, "section", 7) == 0) {
|
|
|
|
TextSplitter ts(data);
|
2011-05-09 04:43:06 +08:00
|
|
|
loadText(ts);
|
|
|
|
} else {
|
2011-12-19 18:50:14 +01:00
|
|
|
loadBinary(data);
|
2011-05-09 04:43:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
Set::Set() :
|
|
|
|
PoolObject<Set, MKTAG('S', 'E', 'T', ' ')>(), _cmaps(NULL) {
|
2011-05-09 04:43:06 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
Set::~Set() {
|
2012-01-26 06:51:10 +01:00
|
|
|
if (_cmaps || g_grim->getGameType() == GType_MONKEY4) {
|
2011-05-09 04:43:06 +08:00
|
|
|
delete[] _cmaps;
|
2011-05-09 21:53:41 +02:00
|
|
|
for (int i = 0; i < _numSetups; ++i) {
|
|
|
|
delete _setups[i]._bkgndBm;
|
|
|
|
delete _setups[i]._bkgndZBm;
|
|
|
|
}
|
2011-05-09 04:43:06 +08:00
|
|
|
delete[] _setups;
|
2011-10-18 18:01:52 +02:00
|
|
|
turnOffLights();
|
2011-05-09 04:43:06 +08:00
|
|
|
delete[] _lights;
|
|
|
|
for (int i = 0; i < _numSectors; ++i) {
|
|
|
|
delete _sectors[i];
|
|
|
|
}
|
|
|
|
delete[] _sectors;
|
2011-11-21 22:07:12 +01:00
|
|
|
foreach (ObjectState *s, _states)
|
|
|
|
delete s;
|
2011-05-09 04:43:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
void Set::loadText(TextSplitter &ts) {
|
2011-05-09 04:43:06 +08:00
|
|
|
char tempBuf[256];
|
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.expectString("section: colormaps");
|
2004-12-09 23:55:43 +00:00
|
|
|
ts.scanString(" numcolormaps %d", 1, &_numCmaps);
|
2011-05-13 17:55:14 -07:00
|
|
|
_cmaps = new ObjectPtr<CMap>[_numCmaps];
|
2004-02-24 22:43:32 +00:00
|
|
|
char cmap_name[256];
|
2004-12-09 23:55:43 +00:00
|
|
|
for (int i = 0; i < _numCmaps; i++) {
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.scanString(" colormap %256s", 1, cmap_name);
|
2011-03-21 05:16:27 +08:00
|
|
|
_cmaps[i] = g_resourceloader->getColormap(cmap_name);
|
2004-02-24 22:43:32 +00:00
|
|
|
}
|
|
|
|
|
2011-03-21 09:58:05 +08:00
|
|
|
if (ts.checkString("section: objectstates") || ts.checkString("sections: object_states")) {
|
|
|
|
ts.nextLine();
|
2005-08-27 16:08:44 +00:00
|
|
|
ts.scanString(" tot_objects %d", 1, &_numObjectStates);
|
|
|
|
char object_name[256];
|
2009-06-28 11:07:38 +00:00
|
|
|
for (int l = 0; l < _numObjectStates; l++) {
|
|
|
|
ts.scanString(" object %256s", 1, object_name);
|
|
|
|
}
|
2005-08-27 16:08:44 +00:00
|
|
|
} else {
|
|
|
|
_numObjectStates = 0;
|
|
|
|
}
|
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.expectString("section: setups");
|
2004-12-09 23:55:43 +00:00
|
|
|
ts.scanString(" numsetups %d", 1, &_numSetups);
|
|
|
|
_setups = new Setup[_numSetups];
|
|
|
|
for (int i = 0; i < _numSetups; i++)
|
2005-07-10 18:57:27 +00:00
|
|
|
_setups[i].load(ts);
|
2004-12-09 23:55:43 +00:00
|
|
|
_currSetup = _setups;
|
|
|
|
|
2011-05-20 06:24:14 +08:00
|
|
|
_lightsConfigured = false;
|
2004-12-09 23:55:43 +00:00
|
|
|
_numSectors = -1;
|
|
|
|
_numLights = -1;
|
|
|
|
_lights = NULL;
|
|
|
|
_sectors = NULL;
|
2005-01-05 18:28:50 +00:00
|
|
|
|
|
|
|
_minVolume = 0;
|
|
|
|
_maxVolume = 0;
|
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
// Lights are optional
|
2011-05-05 11:56:36 +02:00
|
|
|
if (ts.isEof())
|
2004-02-24 22:43:32 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
ts.expectString("section: lights");
|
2004-12-09 23:55:43 +00:00
|
|
|
ts.scanString(" numlights %d", 1, &_numLights);
|
|
|
|
_lights = new Light[_numLights];
|
|
|
|
for (int i = 0; i < _numLights; i++)
|
|
|
|
_lights[i].load(ts);
|
2004-02-24 22:43:32 +00:00
|
|
|
|
|
|
|
// Calculate the number of sectors
|
|
|
|
ts.expectString("section: sectors");
|
2011-05-05 11:56:36 +02:00
|
|
|
if (ts.isEof()) // Sectors are optional, but section: doesn't seem to be
|
2004-02-24 22:43:32 +00:00
|
|
|
return;
|
|
|
|
|
2005-12-28 05:22:18 +00:00
|
|
|
int sectorStart = ts.getLineNumber();
|
|
|
|
_numSectors = 0;
|
|
|
|
// Find the number of sectors (while the sectors usually
|
|
|
|
// count down from the highest number there are a few
|
|
|
|
// cases where they count up, see hh.set for example)
|
2011-05-05 11:56:36 +02:00
|
|
|
while (!ts.isEof()) {
|
2005-12-28 05:22:18 +00:00
|
|
|
ts.scanString(" %s", 1, tempBuf);
|
2011-05-01 18:39:28 +02:00
|
|
|
if (!scumm_stricmp(tempBuf, "sector"))
|
2005-12-28 05:22:18 +00:00
|
|
|
_numSectors++;
|
2004-02-24 22:43:32 +00:00
|
|
|
}
|
2005-12-28 05:22:18 +00:00
|
|
|
// Allocate and fill an array of sector info
|
2011-03-21 05:16:27 +08:00
|
|
|
_sectors = new Sector*[_numSectors];
|
2005-12-28 05:22:18 +00:00
|
|
|
ts.setLineNumber(sectorStart);
|
2011-03-21 05:16:27 +08:00
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
2011-05-27 19:06:23 +02:00
|
|
|
// Use the ids as index for the sector in the array.
|
|
|
|
// This way when looping they are checked from the id 0 sto the last,
|
|
|
|
// which seems important for sets with overlapping camera sectors, like ga.set.
|
|
|
|
Sector *s = new Sector();
|
|
|
|
s->load(ts);
|
|
|
|
_sectors[s->getSectorId()] = s;
|
2011-03-21 17:18:04 +01:00
|
|
|
}
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
void Set::loadBinary(Common::SeekableReadStream *data) {
|
2011-05-09 04:43:06 +08:00
|
|
|
// yes, an array of size 0
|
2011-05-22 11:06:44 +02:00
|
|
|
_cmaps = NULL;//new CMapPtr[0];
|
2011-03-21 05:16:27 +08:00
|
|
|
|
2003-08-15 18:00:22 +00:00
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
_numSetups = data->readUint32LE();
|
2011-05-09 04:43:06 +08:00
|
|
|
_setups = new Setup[_numSetups];
|
|
|
|
for (int i = 0; i < _numSetups; i++)
|
2011-12-19 18:50:14 +01:00
|
|
|
_setups[i].loadBinary(data);
|
2011-05-09 04:43:06 +08:00
|
|
|
_currSetup = _setups;
|
|
|
|
|
|
|
|
_numSectors = 0;
|
|
|
|
_numLights = 0;
|
|
|
|
_lights = NULL;
|
|
|
|
_sectors = NULL;
|
|
|
|
|
|
|
|
_minVolume = 0;
|
|
|
|
_maxVolume = 0;
|
|
|
|
|
|
|
|
// the rest may or may not be optional. Might be a good idea to check if there is no more data.
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
_numLights = data->readUint32LE();
|
2011-05-09 04:43:06 +08:00
|
|
|
_lights = new Light[_numLights];
|
|
|
|
for (int i = 0; i < _numLights; i++)
|
2011-12-19 18:50:14 +01:00
|
|
|
_lights[i].loadBinary(data);
|
2011-05-09 04:43:06 +08:00
|
|
|
|
|
|
|
// bypass light stuff for now
|
|
|
|
_numLights = 0;
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
_numSectors = data->readUint32LE();
|
2011-05-09 04:43:06 +08:00
|
|
|
// Allocate and fill an array of sector info
|
|
|
|
_sectors = new Sector*[_numSectors];
|
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
|
|
|
_sectors[i] = new Sector();
|
2011-12-19 18:50:14 +01:00
|
|
|
_sectors[i]->loadBinary(data);
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
2003-08-15 18:00:22 +00:00
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::saveState(SaveGame *savedState) const {
|
2011-03-21 05:16:27 +08:00
|
|
|
savedState->writeString(_name);
|
|
|
|
savedState->writeLESint32(_numCmaps);
|
|
|
|
for (int i = 0; i < _numCmaps; ++i) {
|
2011-05-22 12:02:20 +08:00
|
|
|
savedState->writeString(_cmaps[i]->getFilename());
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
2009-06-24 17:30:34 +00:00
|
|
|
savedState->writeLEUint32(_currSetup - _setups); // current setup id
|
|
|
|
savedState->writeLEUint32(_locked);
|
|
|
|
savedState->writeLEUint32(_enableLights);
|
|
|
|
savedState->writeLEUint32(_minVolume);
|
|
|
|
savedState->writeLEUint32(_maxVolume);
|
|
|
|
|
2011-03-21 05:16:27 +08:00
|
|
|
savedState->writeLEUint32(_states.size());
|
|
|
|
for (StateList::const_iterator i = _states.begin(); i != _states.end(); ++i) {
|
2011-05-02 03:50:09 +08:00
|
|
|
savedState->writeLEUint32((*i)->getId());
|
2009-06-24 17:30:34 +00:00
|
|
|
}
|
2011-03-21 05:16:27 +08:00
|
|
|
|
|
|
|
//Setups
|
|
|
|
savedState->writeLEUint32(_numSetups);
|
|
|
|
for (int i = 0; i < _numSetups; ++i) {
|
2012-01-19 14:19:36 -08:00
|
|
|
_setups[i].saveState(savedState);
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//Sectors
|
|
|
|
savedState->writeLEUint32(_numSectors);
|
|
|
|
for (int i = 0; i < _numSectors; ++i) {
|
|
|
|
_sectors[i]->saveState(savedState);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Lights
|
|
|
|
savedState->writeLEUint32(_numLights);
|
|
|
|
for (int i = 0; i < _numLights; ++i) {
|
2012-01-19 14:19:36 -08:00
|
|
|
_lights[i].saveState(savedState);
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
bool Set::restoreState(SaveGame *savedState) {
|
2011-03-21 05:16:27 +08:00
|
|
|
_name = savedState->readString();
|
|
|
|
_numCmaps = savedState->readLESint32();
|
|
|
|
_cmaps = new CMapPtr[_numCmaps];
|
|
|
|
for (int i = 0; i < _numCmaps; ++i) {
|
2011-05-22 16:40:56 -07:00
|
|
|
Common::String str = savedState->readString();
|
2011-03-21 05:16:27 +08:00
|
|
|
_cmaps[i] = g_resourceloader->getColormap(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 currSetupId = savedState->readLEUint32();
|
|
|
|
_locked = savedState->readLEUint32();
|
|
|
|
_enableLights = savedState->readLEUint32();
|
|
|
|
_minVolume = savedState->readLEUint32();
|
|
|
|
_maxVolume = savedState->readLEUint32();
|
|
|
|
|
|
|
|
_numObjectStates = savedState->readLEUint32();
|
|
|
|
_states.clear();
|
|
|
|
for (int i = 0; i < _numObjectStates; ++i) {
|
|
|
|
int32 id = savedState->readLEUint32();
|
2011-11-21 22:07:12 +01:00
|
|
|
ObjectState *o = ObjectState::getPool().getObject(id);
|
2011-03-21 05:16:27 +08:00
|
|
|
_states.push_back(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Setups
|
|
|
|
_numSetups = savedState->readLEUint32();
|
|
|
|
_setups = new Setup[_numSetups];
|
|
|
|
_currSetup = _setups + currSetupId;
|
|
|
|
for (int i = 0; i < _numSetups; ++i) {
|
2012-01-19 14:19:36 -08:00
|
|
|
_setups[i].restoreState(savedState);
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//Sectors
|
|
|
|
_numSectors = savedState->readLEUint32();
|
|
|
|
if (_numSectors > 0) {
|
|
|
|
_sectors = new Sector*[_numSectors];
|
|
|
|
for (int i = 0; i < _numSectors; ++i) {
|
|
|
|
_sectors[i] = new Sector();
|
|
|
|
_sectors[i]->restoreState(savedState);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_sectors = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
_numLights = savedState->readLEUint32();
|
|
|
|
_lights = new Light[_numLights];
|
|
|
|
for (int i = 0; i < _numLights; ++i) {
|
2012-01-19 14:19:36 -08:00
|
|
|
_lights[i].restoreState(savedState);;
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
|
|
|
|
2011-05-23 19:18:20 +02:00
|
|
|
_lightsConfigured = false;
|
|
|
|
|
2011-03-21 05:16:27 +08:00
|
|
|
return true;
|
2009-06-24 17:30:34 +00:00
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::Setup::load(TextSplitter &ts) {
|
2004-02-24 22:43:32 +00:00
|
|
|
char buf[256];
|
2003-08-17 00:12:02 +00:00
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.scanString(" setup %256s", 1, buf);
|
2004-12-09 23:55:43 +00:00
|
|
|
_name = buf;
|
2003-08-15 18:00:22 +00:00
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.scanString(" background %256s", 1, buf);
|
2011-05-08 18:39:28 +02:00
|
|
|
_bkgndBm = g_resourceloader->loadBitmap(buf);
|
2008-07-30 07:04:32 +00:00
|
|
|
if (!_bkgndBm) {
|
2011-10-07 23:05:20 +02:00
|
|
|
Debug::warning(Debug::Bitmaps | Debug::Sets,
|
|
|
|
"Unable to load scene bitmap: %s\n", buf);
|
2005-07-17 23:40:22 +00:00
|
|
|
} else {
|
2011-10-07 23:05:20 +02:00
|
|
|
Debug::debug(Debug::Bitmaps | Debug::Sets,
|
|
|
|
"Loaded scene bitmap: %s\n", buf);
|
2005-07-17 23:40:22 +00:00
|
|
|
}
|
2003-08-18 13:59:33 +00:00
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
// ZBuffer is optional
|
2011-05-10 21:50:33 +02:00
|
|
|
_bkgndZBm = NULL;
|
|
|
|
if (ts.checkString("zbuffer")) {
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.scanString(" zbuffer %256s", 1, buf);
|
2005-07-17 23:40:22 +00:00
|
|
|
// Don't even try to load if it's the "none" bitmap
|
|
|
|
if (strcmp(buf, "<none>.lbm") != 0) {
|
2011-05-08 18:39:28 +02:00
|
|
|
_bkgndZBm = g_resourceloader->loadBitmap(buf);
|
2011-10-07 23:05:20 +02:00
|
|
|
Debug::debug(Debug::Bitmaps | Debug::Sets,
|
|
|
|
"Loading scene z-buffer bitmap: %s\n", buf);
|
2005-07-17 23:40:22 +00:00
|
|
|
}
|
2004-02-24 22:43:32 +00:00
|
|
|
}
|
2003-08-15 18:00:22 +00:00
|
|
|
|
2004-12-09 23:55:43 +00:00
|
|
|
ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z());
|
|
|
|
ts.scanString(" interest %f %f %f", 3, &_interest.x(), &_interest.y(), &_interest.z());
|
|
|
|
ts.scanString(" roll %f", 1, &_roll);
|
|
|
|
ts.scanString(" fov %f", 1, &_fov);
|
|
|
|
ts.scanString(" nclip %f", 1, &_nclip);
|
|
|
|
ts.scanString(" fclip %f", 1, &_fclip);
|
2009-06-28 11:07:38 +00:00
|
|
|
for (;;) {
|
|
|
|
if (ts.checkString("object_art"))
|
|
|
|
ts.scanString(" object_art %256s", 1, buf);
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
if (ts.checkString("object_z"))
|
|
|
|
ts.scanString(" object_z %256s", 1, buf);
|
|
|
|
}
|
2003-08-15 18:00:22 +00:00
|
|
|
}
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
void Set::Setup::loadBinary(Common::SeekableReadStream *data) {
|
2011-05-09 04:43:06 +08:00
|
|
|
char name[128];
|
2011-12-19 18:50:14 +01:00
|
|
|
data->read(name, 128);
|
2011-05-09 04:43:06 +08:00
|
|
|
_name = Common::String(name);
|
|
|
|
|
|
|
|
// Skip an unknown number (this is the stringlength of the following string)
|
|
|
|
int fNameLen = 0;
|
2011-12-19 18:50:14 +01:00
|
|
|
fNameLen = data->readUint32LE();
|
2011-05-09 04:43:06 +08:00
|
|
|
|
|
|
|
char* fileName = new char[fNameLen];
|
2011-12-19 18:50:14 +01:00
|
|
|
data->read(fileName,fNameLen);
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2011-05-14 17:42:37 -07:00
|
|
|
_bkgndZBm = NULL;
|
2011-05-09 00:53:45 +02:00
|
|
|
_bkgndBm = g_resourceloader->loadBitmap(fileName);
|
2011-05-09 04:43:06 +08:00
|
|
|
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
data->read(_pos.getData(), 12);
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
data->read(_interest.getData(), 12);
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
data->read(&_roll, 4);
|
|
|
|
data->read(&_fov, 4);
|
|
|
|
data->read(&_nclip, 4);
|
|
|
|
data->read(&_fclip, 4);
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2012-01-26 06:51:10 +01:00
|
|
|
delete[] fileName;
|
2011-05-09 04:43:06 +08:00
|
|
|
}
|
|
|
|
|
2012-01-19 14:19:36 -08:00
|
|
|
void Set::Setup::saveState(SaveGame *savedState) const {
|
|
|
|
//name
|
|
|
|
savedState->writeString(_name);
|
|
|
|
|
|
|
|
//bkgndBm
|
|
|
|
if (_bkgndBm) {
|
|
|
|
savedState->writeLEUint32(_bkgndBm->getId());
|
|
|
|
} else {
|
|
|
|
savedState->writeLEUint32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//bkgndZBm
|
|
|
|
if (_bkgndZBm) {
|
|
|
|
savedState->writeLEUint32(_bkgndZBm->getId());
|
|
|
|
} else {
|
|
|
|
savedState->writeLEUint32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
savedState->writeVector3d(_pos);
|
|
|
|
savedState->writeVector3d(_interest);
|
|
|
|
savedState->writeFloat(_roll);
|
|
|
|
savedState->writeFloat(_fov);
|
|
|
|
savedState->writeFloat(_nclip);
|
|
|
|
savedState->writeFloat(_fclip);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Set::Setup::restoreState(SaveGame *savedState) {
|
|
|
|
_name = savedState->readString();
|
|
|
|
|
|
|
|
_bkgndBm = Bitmap::getPool().getObject(savedState->readLEUint32());
|
|
|
|
_bkgndZBm = Bitmap::getPool().getObject(savedState->readLEUint32());
|
|
|
|
|
|
|
|
_pos = savedState->readVector3d();
|
|
|
|
_interest = savedState->readVector3d();
|
|
|
|
_roll = savedState->readFloat();
|
|
|
|
_fov = savedState->readFloat();
|
|
|
|
_nclip = savedState->readFloat();
|
|
|
|
_fclip = savedState->readFloat();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-07-23 12:14:33 +02:00
|
|
|
void Light::load(TextSplitter &ts) {
|
2004-02-24 22:43:32 +00:00
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
// Light names can be null, but ts doesn't seem flexible enough to allow this
|
2011-05-05 11:56:36 +02:00
|
|
|
if (strlen(ts.getCurrentLine()) > strlen(" light"))
|
2004-02-24 22:43:32 +00:00
|
|
|
ts.scanString(" light %256s", 1, buf);
|
|
|
|
else {
|
|
|
|
ts.nextLine();
|
|
|
|
strcpy(buf, "");
|
|
|
|
}
|
2004-12-09 23:55:43 +00:00
|
|
|
_name = buf;
|
2004-02-24 22:43:32 +00:00
|
|
|
|
|
|
|
ts.scanString(" type %256s", 1, buf);
|
2004-12-09 23:55:43 +00:00
|
|
|
_type = buf;
|
|
|
|
|
|
|
|
ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z());
|
|
|
|
ts.scanString(" direction %f %f %f", 3, &_dir.x(), &_dir.y(), &_dir.z());
|
|
|
|
ts.scanString(" intensity %f", 1, &_intensity);
|
|
|
|
ts.scanString(" umbraangle %f", 1, &_umbraangle);
|
|
|
|
ts.scanString(" penumbraangle %f", 1, &_penumbraangle);
|
2009-05-09 17:47:28 +00:00
|
|
|
|
2005-01-15 17:10:32 +00:00
|
|
|
int r, g, b;
|
|
|
|
ts.scanString(" color %d %d %d", 3, &r, &g, &b);
|
2011-05-05 10:58:29 +02:00
|
|
|
_color.getRed() = r;
|
|
|
|
_color.getGreen() = g;
|
|
|
|
_color.getBlue() = b;
|
2011-06-03 19:24:54 +02:00
|
|
|
|
|
|
|
_enabled = true;
|
2003-08-15 18:00:22 +00:00
|
|
|
}
|
|
|
|
|
2011-12-19 18:50:14 +01:00
|
|
|
void Light::loadBinary(Common::SeekableReadStream *data) {
|
2011-05-09 04:43:06 +08:00
|
|
|
// skip lights for now
|
2011-12-19 18:50:14 +01:00
|
|
|
data->seek(100, SEEK_CUR);
|
2011-05-09 04:43:06 +08:00
|
|
|
}
|
|
|
|
|
2012-01-19 14:19:36 -08:00
|
|
|
void Light::saveState(SaveGame *savedState) const {
|
|
|
|
//name
|
|
|
|
savedState->writeString(_name);
|
|
|
|
savedState->writeLEBool(_enabled);
|
|
|
|
|
|
|
|
//type
|
|
|
|
savedState->writeString(_type);
|
|
|
|
|
|
|
|
savedState->writeVector3d(_pos);
|
|
|
|
savedState->writeVector3d(_dir);
|
|
|
|
|
|
|
|
savedState->writeColor(_color);
|
|
|
|
|
|
|
|
savedState->writeFloat(_intensity);
|
|
|
|
savedState->writeFloat(_umbraangle);
|
|
|
|
savedState->writeFloat(_penumbraangle);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Light::restoreState(SaveGame *savedState) {
|
|
|
|
_name = savedState->readString();
|
|
|
|
_enabled = savedState->readLEBool();
|
|
|
|
_type = savedState->readString();
|
|
|
|
|
|
|
|
_pos = savedState->readVector3d();
|
|
|
|
_dir = savedState->readVector3d();
|
|
|
|
|
|
|
|
_color = savedState->readColor();
|
|
|
|
|
|
|
|
_intensity = savedState->readFloat();
|
|
|
|
_umbraangle = savedState->readFloat();
|
|
|
|
_penumbraangle = savedState->readFloat();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::Setup::setupCamera() const {
|
2004-03-26 04:42:27 +00:00
|
|
|
// Ignore nclip_ and fclip_ for now. This fixes:
|
|
|
|
// (a) Nothing was being displayed in the Land of the Living
|
|
|
|
// diner because lr.set set nclip to 0.
|
|
|
|
// (b) The zbuffers for setups with different nclip or
|
|
|
|
// fclip values. If it turns out that the clipping planes
|
|
|
|
// are important at some point, we'll need to modify the
|
|
|
|
// zbuffer transformation in bitmap.cpp to take nclip_ and
|
|
|
|
// fclip_ into account.
|
2004-12-09 23:55:43 +00:00
|
|
|
g_driver->setupCamera(_fov, 0.01f, 3276.8f, _roll);
|
|
|
|
g_driver->positionCamera(_pos, _interest);
|
2003-08-15 18:00:22 +00:00
|
|
|
}
|
2003-08-30 17:58:33 +00:00
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setupLights() {
|
2011-05-20 06:24:14 +08:00
|
|
|
if (_lightsConfigured)
|
|
|
|
return;
|
|
|
|
_lightsConfigured = true;
|
2005-01-12 18:06:43 +00:00
|
|
|
if (!_enableLights) {
|
2005-01-18 17:25:04 +00:00
|
|
|
g_driver->disableLights();
|
2005-01-12 18:06:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-03 19:24:54 +02:00
|
|
|
int count = 0;
|
2005-01-12 18:06:43 +00:00
|
|
|
for (int i = 0; i < _numLights; i++) {
|
2011-06-03 19:24:54 +02:00
|
|
|
Light *l = &_lights[i];
|
|
|
|
if (l->_enabled) {
|
|
|
|
g_driver->setupLight(l, count);
|
|
|
|
++count;
|
|
|
|
}
|
2005-01-12 18:06:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-18 18:01:52 +02:00
|
|
|
void Set::turnOffLights() {
|
|
|
|
_enableLights = false;
|
|
|
|
int count = 0;
|
|
|
|
for (int i = 0; i < _numLights; i++) {
|
|
|
|
Light *l = &_lights[i];
|
|
|
|
if (l->_enabled) {
|
|
|
|
g_driver->turnOffLight(count);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setSetup(int num) {
|
2005-07-17 23:40:22 +00:00
|
|
|
// Looks like num is zero-based so >= should work to find values
|
|
|
|
// that are out of the range of valid setups
|
2012-01-11 19:13:44 +01:00
|
|
|
|
|
|
|
// Quite weird, but this is what the original does when the setup id is above
|
|
|
|
// the upper bound.
|
|
|
|
if (num >= _numSetups)
|
|
|
|
num %= _numSetups;
|
|
|
|
|
|
|
|
if (num < 0) {
|
2009-05-31 07:33:18 +00:00
|
|
|
error("Failed to change scene setup, value out of range");
|
2005-07-17 23:40:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-12-09 23:55:43 +00:00
|
|
|
_currSetup = _setups + num;
|
2009-05-17 08:24:17 +00:00
|
|
|
g_grim->flagRefreshShadowMask(true);
|
2011-05-20 06:24:14 +08:00
|
|
|
_lightsConfigured = false;
|
2003-08-30 17:58:33 +00:00
|
|
|
}
|
2004-03-22 11:23:37 +00:00
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::drawBackground() const {
|
2011-03-21 05:16:27 +08:00
|
|
|
if (_currSetup->_bkgndZBm) // Some screens have no zbuffer mask (eg, Alley)
|
|
|
|
_currSetup->_bkgndZBm->draw();
|
|
|
|
|
|
|
|
if (!_currSetup->_bkgndBm) {
|
|
|
|
// This should fail softly, for some reason jumping to the signpost (sg) will load
|
|
|
|
// the scene in such a way that the background isn't immediately available
|
|
|
|
warning("Background hasn't loaded yet for setup %s in %s!", _currSetup->_name.c_str(), _name.c_str());
|
|
|
|
} else {
|
|
|
|
_currSetup->_bkgndBm->draw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::drawBitmaps(ObjectState::Position stage) {
|
2011-07-14 16:11:14 +02:00
|
|
|
for (StateList::iterator i = _states.reverse_begin(); i != _states.end(); --i) {
|
2011-05-05 11:45:09 +02:00
|
|
|
if ((*i)->getPos() == stage && _currSetup == _setups + (*i)->getSetupID())
|
2004-03-22 11:23:37 +00:00
|
|
|
(*i)->draw();
|
|
|
|
}
|
|
|
|
}
|
2004-03-23 10:38:02 +00:00
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
Sector *Set::findPointSector(const Math::Vector3d &p, Sector::SectorType type) {
|
2004-12-09 23:55:43 +00:00
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
2011-03-21 05:16:27 +08:00
|
|
|
Sector *sector = _sectors[i];
|
2011-05-05 12:04:09 +02:00
|
|
|
if (sector && (sector->getType() & type) && sector->isVisible() && sector->isPointInSector(p))
|
2004-03-25 09:33:17 +00:00
|
|
|
return sector;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::findClosestSector(const Math::Vector3d &p, Sector **sect, Math::Vector3d *closestPoint) {
|
2004-03-26 09:28:13 +00:00
|
|
|
Sector *resultSect = NULL;
|
2011-09-10 17:46:07 +02:00
|
|
|
Math::Vector3d resultPt = p;
|
2008-07-13 10:53:39 +00:00
|
|
|
float minDist = 0.0;
|
2004-03-26 09:28:13 +00:00
|
|
|
|
2004-12-09 23:55:43 +00:00
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
2011-03-21 05:16:27 +08:00
|
|
|
Sector *sector = _sectors[i];
|
2011-05-05 12:04:09 +02:00
|
|
|
if ((sector->getType() & Sector::WalkType) == 0 || !sector->isVisible())
|
2004-03-26 09:28:13 +00:00
|
|
|
continue;
|
2011-09-10 17:46:07 +02:00
|
|
|
Math::Vector3d closestPt = sector->getClosestPoint(p);
|
2011-09-14 22:48:24 +02:00
|
|
|
float thisDist = (closestPt - p).getMagnitude();
|
2008-09-10 11:16:57 +00:00
|
|
|
if (!resultSect || thisDist < minDist) {
|
2004-03-26 09:28:13 +00:00
|
|
|
resultSect = sector;
|
2011-04-04 20:45:54 +02:00
|
|
|
resultPt = closestPt;
|
2004-03-26 09:28:13 +00:00
|
|
|
minDist = thisDist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-30 07:04:32 +00:00
|
|
|
if (sect)
|
2004-03-26 09:28:13 +00:00
|
|
|
*sect = resultSect;
|
2004-12-09 23:55:43 +00:00
|
|
|
|
2009-10-17 12:48:23 +00:00
|
|
|
if (closestPoint)
|
|
|
|
*closestPoint = resultPt;
|
2004-03-26 09:28:13 +00:00
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::shrinkBoxes(float radius) {
|
2011-06-10 15:09:17 +03:00
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
|
|
|
Sector *sector = _sectors[i];
|
|
|
|
sector->shrink(radius);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::unshrinkBoxes() {
|
2011-06-10 15:09:17 +03:00
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
|
|
|
Sector *sector = _sectors[i];
|
|
|
|
sector->unshrink();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightsDirty() {
|
2011-05-31 19:27:01 +02:00
|
|
|
_lightsConfigured = false;
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightIntensity(const char *light, float intensity) {
|
2011-04-21 17:12:17 +02:00
|
|
|
for (int i = 0; i < _numLights; ++i) {
|
|
|
|
Light &l = _lights[i];
|
|
|
|
if (l._name == light) {
|
|
|
|
l._intensity = intensity;
|
2011-05-20 06:24:14 +08:00
|
|
|
_lightsConfigured = false;
|
2011-05-20 23:13:20 +02:00
|
|
|
return;
|
2011-04-21 17:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightIntensity(int light, float intensity) {
|
2011-04-21 17:12:17 +02:00
|
|
|
Light &l = _lights[light];
|
|
|
|
l._intensity = intensity;
|
2011-05-20 06:24:14 +08:00
|
|
|
_lightsConfigured = false;
|
2011-04-21 17:12:17 +02:00
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightEnabled(const char *light, bool enabled) {
|
2011-06-03 19:24:54 +02:00
|
|
|
for (int i = 0; i < _numLights; ++i) {
|
|
|
|
Light &l = _lights[i];
|
|
|
|
if (l._name == light) {
|
|
|
|
l._enabled = enabled;
|
|
|
|
_lightsConfigured = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightEnabled(int light, bool enabled) {
|
2011-06-03 19:24:54 +02:00
|
|
|
Light &l = _lights[light];
|
|
|
|
l._enabled = enabled;
|
|
|
|
_lightsConfigured = false;
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightPosition(const char *light, const Math::Vector3d &pos) {
|
2011-04-21 18:42:32 +02:00
|
|
|
for (int i = 0; i < _numLights; ++i) {
|
|
|
|
Light &l = _lights[i];
|
|
|
|
if (l._name == light) {
|
|
|
|
l._pos = pos;
|
2011-05-20 06:24:14 +08:00
|
|
|
_lightsConfigured = false;
|
2011-05-20 23:13:20 +02:00
|
|
|
return;
|
2011-04-21 18:42:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setLightPosition(int light, const Math::Vector3d &pos) {
|
2011-04-21 18:42:32 +02:00
|
|
|
Light &l = _lights[light];
|
|
|
|
l._pos = pos;
|
2011-05-20 06:24:14 +08:00
|
|
|
_lightsConfigured = false;
|
2011-04-21 18:42:32 +02:00
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setSoundPosition(const char *soundName, Math::Vector3d pos) {
|
2011-04-20 17:04:33 +02:00
|
|
|
setSoundPosition(soundName, pos, _minVolume, _maxVolume);
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setSoundPosition(const char *soundName, Math::Vector3d pos, int minVol, int maxVol) {
|
2011-05-29 23:22:39 +03:00
|
|
|
// TODO: The volume and pan needs to be updated when the setup changes.
|
2011-09-10 17:46:07 +02:00
|
|
|
Math::Vector3d cameraPos = _currSetup->_pos;
|
|
|
|
Math::Vector3d vector = pos - cameraPos;
|
2011-09-14 22:48:24 +02:00
|
|
|
float distance = vector.getMagnitude();
|
2011-05-08 23:35:06 +02:00
|
|
|
float diffVolume = maxVol - minVol;
|
|
|
|
//This 8.f is a guess, so it may need some adjusting
|
|
|
|
int newVolume = (int)(8.f * diffVolume / distance);
|
2011-04-20 17:04:33 +02:00
|
|
|
newVolume += minVol;
|
2011-05-10 21:46:58 +02:00
|
|
|
if (newVolume > _maxVolume)
|
|
|
|
newVolume = _maxVolume;
|
2012-01-14 08:18:43 +01:00
|
|
|
g_sound->setVolume(soundName, newVolume);
|
2005-01-05 18:28:50 +00:00
|
|
|
|
2011-09-10 17:46:07 +02:00
|
|
|
Math::Vector3d cameraVector =_currSetup->_interest - _currSetup->_pos;
|
|
|
|
Math::Vector3d up(0,0,1);
|
|
|
|
Math::Vector3d right;
|
2011-05-29 23:22:39 +03:00
|
|
|
cameraVector.normalize();
|
|
|
|
float roll = -_currSetup->_roll * LOCAL_PI / 180.f;
|
|
|
|
float cosr = cos(roll);
|
|
|
|
// Rotate the up vector by roll.
|
2011-09-18 19:15:06 +02:00
|
|
|
up = up * cosr + Math::Vector3d::crossProduct(cameraVector, up) * sin(roll) +
|
|
|
|
cameraVector * Math::Vector3d::dotProduct(cameraVector, up) * (1 - cosr);
|
|
|
|
right = Math::Vector3d::crossProduct(cameraVector, up);
|
2011-05-29 23:22:39 +03:00
|
|
|
right.normalize();
|
2011-09-18 19:15:06 +02:00
|
|
|
float angle = atan2(Math::Vector3d::dotProduct(vector, right),
|
|
|
|
Math::Vector3d::dotProduct(vector, cameraVector));
|
2011-05-29 23:22:39 +03:00
|
|
|
float pan = sin(angle);
|
2012-01-14 08:18:43 +01:00
|
|
|
g_sound->setPan(soundName, (int)((pan + 1.f) / 2.f * 127.f + 0.5f));
|
2005-01-05 18:28:50 +00:00
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
Sector *Set::getSectorBase(int id) {
|
2011-05-27 16:04:22 -07:00
|
|
|
if ((_numSectors >= 0) && (id < _numSectors))
|
|
|
|
return _sectors[id];
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::setSoundParameters(int minVolume, int maxVolume) {
|
2005-01-05 18:28:50 +00:00
|
|
|
_minVolume = minVolume;
|
|
|
|
_maxVolume = maxVolume;
|
|
|
|
}
|
|
|
|
|
2011-09-19 16:53:08 +02:00
|
|
|
void Set::getSoundParameters(int *minVolume, int *maxVolume) {
|
2005-01-05 18:28:50 +00:00
|
|
|
*minVolume = _minVolume;
|
|
|
|
*maxVolume = _maxVolume;
|
|
|
|
}
|
2005-04-08 12:41:19 +00:00
|
|
|
|
2011-10-29 15:13:39 +02:00
|
|
|
void Set::addObjectState(const ObjectState::Ptr &s) {
|
2011-07-14 16:11:14 +02:00
|
|
|
_states.push_front(s);
|
|
|
|
}
|
|
|
|
|
2011-11-19 19:28:41 +01:00
|
|
|
ObjectState *Set::addObjectState(int setupID, ObjectState::Position pos, const char *bitmap, const char *zbitmap, bool transparency) {
|
|
|
|
ObjectState *state = findState(bitmap);
|
|
|
|
|
|
|
|
if (state) {
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = new ObjectState(setupID, pos, bitmap, zbitmap, transparency);
|
|
|
|
addObjectState(state);
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectState *Set::findState(const Common::String &filename) {
|
|
|
|
// Check the different state objects for the bitmap
|
|
|
|
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) {
|
|
|
|
const Common::String &file = (*i)->getBitmapFilename();
|
|
|
|
|
|
|
|
if (file == filename)
|
|
|
|
return *i;
|
|
|
|
if (file.compareToIgnoreCase(filename) == 0) {
|
|
|
|
Debug::warning(Debug::Sets, "State object request '%s' matches object '%s' but is the wrong case", filename.c_str(), file.c_str());
|
|
|
|
return *i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-10-29 15:13:39 +02:00
|
|
|
void Set::moveObjectStateToFront(const ObjectState::Ptr &s) {
|
2005-04-08 12:41:19 +00:00
|
|
|
_states.remove(s);
|
|
|
|
_states.push_front(s);
|
2011-07-14 16:24:46 +02:00
|
|
|
// Make the state invisible. This hides the deadbolt when brennis closes the switcher door
|
2012-01-06 13:32:30 +01:00
|
|
|
// in the server room (tu), and therefore fixes https://github.com/residualvm/residualvm/issues/24
|
2011-09-18 18:46:20 +02:00
|
|
|
s->setActiveImage(0);
|
2005-04-08 12:41:19 +00:00
|
|
|
}
|
|
|
|
|
2011-10-29 15:13:39 +02:00
|
|
|
void Set::moveObjectStateToBack(const ObjectState::Ptr &s) {
|
2005-04-08 12:41:19 +00:00
|
|
|
_states.remove(s);
|
|
|
|
_states.push_back(s);
|
|
|
|
}
|
2009-05-25 06:49:57 +00:00
|
|
|
|
|
|
|
} // end of namespace Grim
|