2009-05-26 14:13:08 +00:00
|
|
|
/* Residual - A 3D game interpreter
|
2008-06-13 14:57:47 +00:00
|
|
|
*
|
|
|
|
* Residual 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-05-09 04:43:06 +08:00
|
|
|
#include "common/memstream.h"
|
|
|
|
|
2009-05-24 19:13:58 +00:00
|
|
|
#include "engines/grim/scene.h"
|
|
|
|
#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-03-21 05:16:27 +08:00
|
|
|
#include "engines/grim/lua.h"
|
2011-05-13 17:55:14 -07:00
|
|
|
#include "engines/grim/resource.h"
|
|
|
|
#include "engines/grim/bitmap.h"
|
2008-01-26 11:47:23 +00:00
|
|
|
|
2009-05-24 19:13:58 +00:00
|
|
|
#include "engines/grim/imuse/imuse.h"
|
2005-01-05 18:28:50 +00:00
|
|
|
|
2009-05-25 06:49:57 +00:00
|
|
|
namespace Grim {
|
|
|
|
|
2011-03-21 05:16:27 +08:00
|
|
|
int Scene::s_id = 0;
|
|
|
|
|
2011-05-22 12:02:20 +08:00
|
|
|
Scene::Scene(const Common::String &sceneName, const char *buf, int len) :
|
2011-05-23 19:18:20 +02:00
|
|
|
_locked(false), _name(sceneName), _enableLights(false), _lightsConfigured(false) {
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2011-04-18 17:11:16 +02:00
|
|
|
++s_id;
|
|
|
|
_id = s_id;
|
2004-02-24 22:43:32 +00:00
|
|
|
|
2011-05-09 04:43:06 +08:00
|
|
|
if (len >= 7 && memcmp(buf, "section", 7) == 0) {
|
|
|
|
TextSplitter ts(buf, len);
|
|
|
|
loadText(ts);
|
|
|
|
} else {
|
|
|
|
Common::MemoryReadStream ms((const byte *)buf, len);
|
|
|
|
loadBinary(&ms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Scene::Scene() :
|
|
|
|
_cmaps(NULL) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Scene::~Scene() {
|
|
|
|
if (_cmaps) {
|
|
|
|
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;
|
|
|
|
delete[] _lights;
|
|
|
|
for (int i = 0; i < _numSectors; ++i) {
|
|
|
|
delete _sectors[i];
|
|
|
|
}
|
|
|
|
delete[] _sectors;
|
|
|
|
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i)
|
|
|
|
delete (*i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-24 22:18:01 -07:00
|
|
|
int32 Scene::getId() {
|
|
|
|
return _id;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::setId(int32 id) {
|
|
|
|
if (id > s_id) {
|
|
|
|
s_id = id;
|
|
|
|
}
|
|
|
|
_id = id;
|
|
|
|
}
|
|
|
|
|
2011-05-09 04:43:06 +08:00
|
|
|
void Scene::loadText(TextSplitter &ts){
|
|
|
|
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-09 04:43:06 +08:00
|
|
|
_sectors[i] = new Sector();
|
2011-03-21 05:16:27 +08:00
|
|
|
_sectors[i]->load(ts);
|
2011-03-21 17:18:04 +01:00
|
|
|
}
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
|
|
|
|
2011-05-09 04:43:06 +08:00
|
|
|
void Scene::loadBinary(Common::MemoryReadStream *ms)
|
|
|
|
{
|
|
|
|
// 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-05-09 04:43:06 +08:00
|
|
|
_numSetups = ms->readUint32LE();
|
|
|
|
_setups = new Setup[_numSetups];
|
|
|
|
for (int i = 0; i < _numSetups; i++)
|
|
|
|
_setups[i].loadBinary(ms);
|
|
|
|
_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.
|
|
|
|
|
|
|
|
_numLights = ms->readUint32LE();
|
|
|
|
_lights = new Light[_numLights];
|
|
|
|
for (int i = 0; i < _numLights; i++)
|
|
|
|
_lights[i].loadBinary(ms);
|
|
|
|
|
|
|
|
// bypass light stuff for now
|
|
|
|
_numLights = 0;
|
|
|
|
|
|
|
|
_numSectors = ms->readUint32LE();
|
|
|
|
// Allocate and fill an array of sector info
|
|
|
|
_sectors = new Sector*[_numSectors];
|
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
|
|
|
_sectors[i] = new Sector();
|
|
|
|
_sectors[i]->loadBinary(ms);
|
2011-03-21 05:16:27 +08:00
|
|
|
}
|
2003-08-15 18:00:22 +00:00
|
|
|
}
|
|
|
|
|
2011-05-09 04:43:06 +08:00
|
|
|
|
2011-03-21 05:16:27 +08:00
|
|
|
void Scene::saveState(SaveGame *savedState) const {
|
|
|
|
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) {
|
|
|
|
Setup &set = _setups[i];
|
|
|
|
|
|
|
|
//name
|
|
|
|
savedState->writeString(set._name);
|
|
|
|
|
|
|
|
//bkgndBm
|
|
|
|
if (set._bkgndBm) {
|
2011-05-08 18:39:28 +02:00
|
|
|
savedState->writeLEUint32(set._bkgndBm->getId());
|
2011-03-21 05:16:27 +08:00
|
|
|
} else {
|
|
|
|
savedState->writeLEUint32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//bkgndZBm
|
|
|
|
if (set._bkgndZBm) {
|
2011-05-08 18:39:28 +02:00
|
|
|
savedState->writeLEUint32(set._bkgndZBm->getId());
|
2011-03-21 05:16:27 +08:00
|
|
|
} else {
|
|
|
|
savedState->writeLEUint32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
savedState->writeVector3d(set._pos);
|
|
|
|
savedState->writeVector3d(set._interest);
|
|
|
|
savedState->writeFloat(set._roll);
|
|
|
|
savedState->writeFloat(set._fov);
|
|
|
|
savedState->writeFloat(set._nclip);
|
|
|
|
savedState->writeFloat(set._fclip);
|
|
|
|
}
|
|
|
|
|
|
|
|
//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) {
|
|
|
|
Light &l = _lights[i];
|
|
|
|
|
|
|
|
//name
|
|
|
|
savedState->writeString(l._name);
|
|
|
|
|
|
|
|
//type
|
|
|
|
savedState->writeString(l._type);
|
|
|
|
|
|
|
|
savedState->writeVector3d(l._pos);
|
|
|
|
savedState->writeVector3d(l._dir);
|
|
|
|
|
|
|
|
savedState->writeColor(l._color);
|
|
|
|
|
|
|
|
savedState->writeFloat(l._intensity);
|
|
|
|
savedState->writeFloat(l._umbraangle);
|
|
|
|
savedState->writeFloat(l._penumbraangle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Scene::restoreState(SaveGame *savedState) {
|
|
|
|
_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-05-05 11:25:08 +02:00
|
|
|
ObjectState *o = g_grim->getObjectState(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) {
|
|
|
|
Setup &set = _setups[i];
|
|
|
|
|
|
|
|
set._name = savedState->readString();
|
|
|
|
|
2011-05-08 18:39:28 +02:00
|
|
|
set._bkgndBm = g_grim->getBitmap(savedState->readLEUint32());
|
|
|
|
set._bkgndZBm = g_grim->getBitmap(savedState->readLEUint32());
|
2011-03-21 05:16:27 +08:00
|
|
|
|
|
|
|
set._pos = savedState->readVector3d();
|
|
|
|
set._interest = savedState->readVector3d();
|
|
|
|
set._roll = savedState->readFloat();
|
|
|
|
set._fov = savedState->readFloat();
|
|
|
|
set._nclip = savedState->readFloat();
|
|
|
|
set._fclip = savedState->readFloat();
|
|
|
|
}
|
|
|
|
|
|
|
|
//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) {
|
|
|
|
Light &l = _lights[i];
|
|
|
|
|
|
|
|
l._name = savedState->readString();
|
|
|
|
l._type = savedState->readString();
|
|
|
|
|
|
|
|
l._pos = savedState->readVector3d();
|
|
|
|
l._dir = savedState->readVector3d();
|
|
|
|
|
|
|
|
l._color = savedState->readColor();
|
|
|
|
|
|
|
|
l._intensity = savedState->readFloat();
|
|
|
|
l._umbraangle = savedState->readFloat();
|
|
|
|
l._penumbraangle = savedState->readFloat();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2003-08-15 18:00:22 +00:00
|
|
|
void Scene::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) {
|
2009-05-25 19:21:58 +00:00
|
|
|
if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_ERROR || gDebugLevel == DEBUG_ALL)
|
2011-05-08 15:38:26 +02:00
|
|
|
warning("Unable to load scene bitmap: %s\n", buf);
|
2005-07-17 23:40:22 +00:00
|
|
|
} else {
|
2009-05-25 19:21:58 +00:00
|
|
|
if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL)
|
2011-05-08 15:38:26 +02:00
|
|
|
warning("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);
|
2009-05-25 19:21:58 +00:00
|
|
|
if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL)
|
2005-07-17 23:40:22 +00:00
|
|
|
printf("Loading scene z-buffer bitmap: %s\n", buf);
|
|
|
|
}
|
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-05-09 04:43:06 +08:00
|
|
|
void Scene::Setup::loadBinary(Common::MemoryReadStream *ms) {
|
|
|
|
char name[128];
|
|
|
|
ms->read(name, 128);
|
|
|
|
_name = Common::String(name);
|
|
|
|
|
|
|
|
// Skip an unknown number (this is the stringlength of the following string)
|
|
|
|
int fNameLen = 0;
|
|
|
|
fNameLen = ms->readUint32LE();
|
|
|
|
|
|
|
|
char* fileName = new char[fNameLen];
|
|
|
|
ms->read(fileName,fNameLen);
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
ms->read(_pos._coords, 12);
|
|
|
|
|
|
|
|
ms->read(_interest._coords, 12);
|
|
|
|
|
|
|
|
ms->read(&_roll, 4);
|
|
|
|
ms->read(&_fov, 4);
|
|
|
|
ms->read(&_nclip, 4);
|
|
|
|
ms->read(&_fclip, 4);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-08-15 18:00:22 +00:00
|
|
|
void Scene::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;
|
2003-08-15 18:00:22 +00:00
|
|
|
}
|
|
|
|
|
2011-05-09 04:43:06 +08:00
|
|
|
void Scene::Light::loadBinary(Common::MemoryReadStream *ms) {
|
|
|
|
// skip lights for now
|
|
|
|
ms->seek(100, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
2003-08-15 18:00:22 +00:00
|
|
|
void Scene::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
|
|
|
|
2005-01-12 18:06:43 +00:00
|
|
|
void Scene::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;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < _numLights; i++) {
|
2005-01-18 17:25:04 +00:00
|
|
|
g_driver->setupLight(&_lights[i], i);
|
2005-01-12 18:06:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-24 22:43:32 +00:00
|
|
|
void Scene::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
|
|
|
|
if (num >= _numSetups || 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-03-21 05:16:27 +08:00
|
|
|
void Scene::drawBackground() const {
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-22 11:23:37 +00:00
|
|
|
void Scene::drawBitmaps(ObjectState::Position stage) {
|
2010-02-04 19:43:50 +00:00
|
|
|
for (StateList::iterator i = _states.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-04-05 12:37:20 +02:00
|
|
|
Sector *Scene::findPointSector(Graphics::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;
|
|
|
|
}
|
|
|
|
|
2009-10-17 12:48:23 +00:00
|
|
|
void Scene::findClosestSector(Graphics::Vector3d p, Sector **sect, Graphics::Vector3d *closestPoint) {
|
2004-03-26 09:28:13 +00:00
|
|
|
Sector *resultSect = NULL;
|
2009-05-25 12:13:35 +00:00
|
|
|
Graphics::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-05-05 12:04:09 +02:00
|
|
|
Graphics::Vector3d closestPt = sector->getClosestPoint(p);
|
2004-03-26 09:28:13 +00:00
|
|
|
float thisDist = (closestPt - p).magnitude();
|
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
|
|
|
}
|
|
|
|
|
2004-03-23 10:38:02 +00:00
|
|
|
ObjectState *Scene::findState(const char *filename) {
|
2005-07-10 18:57:27 +00:00
|
|
|
// Check the different state objects for the bitmap
|
2010-02-04 19:43:50 +00:00
|
|
|
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) {
|
2011-05-22 12:02:20 +08:00
|
|
|
const Common::String &file = (*i)->getBitmapFilename();
|
2009-05-09 17:47:28 +00:00
|
|
|
|
2011-05-22 12:02:20 +08:00
|
|
|
if (file == filename)
|
2004-03-23 10:38:02 +00:00
|
|
|
return *i;
|
2011-05-22 12:02:20 +08:00
|
|
|
if (file.compareToIgnoreCase(filename) == 0) {
|
2009-05-25 19:21:58 +00:00
|
|
|
if (gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL)
|
2011-05-22 12:02:20 +08:00
|
|
|
warning("State object request '%s' matches object '%s' but is the wrong case", filename, file.c_str());
|
2005-07-10 18:57:27 +00:00
|
|
|
return *i;
|
|
|
|
}
|
2004-03-23 10:38:02 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-01-05 18:28:50 +00:00
|
|
|
|
2011-04-21 17:12:17 +02:00
|
|
|
void Scene::setLightIntensity(const char *light, float intensity) {
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::setLightIntensity(int light, float intensity) {
|
|
|
|
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-04-21 18:42:32 +02:00
|
|
|
void Scene::setLightPosition(const char *light, Graphics::Vector3d pos) {
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::setLightPosition(int light, Graphics::Vector3d pos) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-05-25 12:13:35 +00:00
|
|
|
void Scene::setSoundPosition(const char *soundName, Graphics::Vector3d pos) {
|
2011-04-20 17:04:33 +02:00
|
|
|
setSoundPosition(soundName, pos, _minVolume, _maxVolume);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::setSoundPosition(const char *soundName, Graphics::Vector3d pos, int minVol, int maxVol) {
|
2009-05-25 12:13:35 +00:00
|
|
|
Graphics::Vector3d cameraPos = _currSetup->_pos;
|
|
|
|
Graphics::Vector3d vector, vector2;
|
2005-01-05 18:28:50 +00:00
|
|
|
vector.set(fabs(cameraPos.x() - pos.x()), fabs(cameraPos.y() - pos.y()), fabs(cameraPos.z() - pos.z()));
|
|
|
|
float distance = vector.magnitude();
|
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;
|
2005-01-05 18:28:50 +00:00
|
|
|
g_imuse->setVolume(soundName, newVolume);
|
|
|
|
|
2005-01-09 18:05:57 +00:00
|
|
|
//TODO
|
|
|
|
//g_imuse->setPan(soundName, pan);
|
2005-01-05 18:28:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::setSoundParameters(int minVolume, int maxVolume) {
|
|
|
|
_minVolume = minVolume;
|
|
|
|
_maxVolume = maxVolume;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::getSoundParameters(int *minVolume, int *maxVolume) {
|
|
|
|
*minVolume = _minVolume;
|
|
|
|
*maxVolume = _maxVolume;
|
|
|
|
}
|
2005-04-08 12:41:19 +00:00
|
|
|
|
|
|
|
void Scene::moveObjectStateToFirst(ObjectState *s) {
|
|
|
|
_states.remove(s);
|
|
|
|
_states.push_front(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::moveObjectStateToLast(ObjectState *s) {
|
|
|
|
_states.remove(s);
|
|
|
|
_states.push_back(s);
|
|
|
|
}
|
2009-05-25 06:49:57 +00:00
|
|
|
|
|
|
|
} // end of namespace Grim
|