xoreos  0.0.5
area.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/util.h"
26 #include "src/common/error.h"
27 
28 #include "src/aurora/gff3file.h"
29 #include "src/aurora/2dafile.h"
30 #include "src/aurora/2dareg.h"
31 
32 #include "src/graphics/graphics.h"
33 
36 
37 #include "src/sound/sound.h"
38 
41 
48 
49 namespace Engines {
50 
51 namespace Witcher {
52 
54  _module(&module), _resRef(resRef), _visible(false),
55  _activeObject(0), _highlightAll(false) {
56 
57  try {
58  // Load ARE and GIT
59 
60  Aurora::GFF3File are(_resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' '));
61  loadARE(are.getTopLevel());
62 
63  Aurora::GFF3File git(_resRef, Aurora::kFileTypeGIT, MKTAG('G', 'I', 'T', ' '));
64  loadGIT(git.getTopLevel());
65 
66  } catch (...) {
67  clear();
68  throw;
69  }
70 
71  // Tell the module that we exist
72  _module->addObject(*this);
73 }
74 
76  _module->removeObject(*this);
77 
78  hide();
79 
80  removeFocus();
81 
82  clear();
83 }
84 
85 void Area::clear() {
86  // Delete objects
87  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
88  _module->removeObject(**o);
89 
90  _objects.clear();
91 
92  // Delete area geometry model
93  _model.reset();
94 }
95 
97  try {
98  Aurora::GFF3File are(resRef, Aurora::kFileTypeARE, MKTAG('A', 'R', 'E', ' '));
99 
100  Aurora::LocString name;
101  are.getTopLevel().getLocString("Name", name);
102 
103  return name;
104 
105  } catch (...) {
106  }
107 
108  return Aurora::LocString();
109 }
110 
112  return _resRef;
113 }
114 
116  return Witcher::Object::getName();
117 }
118 
120  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
121  (*o)->refreshLocalized();
122 }
123 
125  return _musicDayTrack;
126 }
127 
129  return _musicNightTrack;
130 }
131 
133  return _musicBattleTrack;
134 }
135 
137  _musicDayTrack = track;
138  _musicDay = TwoDAReg.get2DA("ambientmusic").getRow(track).getString("Resource");
139 }
140 
142  _musicNightTrack = track;
143  _musicNight = TwoDAReg.get2DA("ambientmusic").getRow(track).getString("Resource");
144 }
145 
147  _musicBattleTrack = track;
148  _musicBattle = TwoDAReg.get2DA("ambientmusic").getRow(_musicBattleTrack).getString("Resource");
149 }
150 
152  SoundMan.stopChannel(_ambientMusic);
153 }
154 
157 
158  // TODO: Area::playAmbientMusic(): Day/Night
159  if (music.empty())
160  music = _musicDay;
161 
162  if (music.empty())
163  return;
164 
166 }
167 
168 void Area::show() {
169  if (_visible)
170  return;
171 
172  loadModels();
173 
174  GfxMan.lockFrame();
175 
176  // Show area geometry model
177  if (_model)
178  _model->show();
179 
180  // Show objects
181  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
182  (*o)->show();
183 
184  GfxMan.unlockFrame();
185 
187 
188  _visible = true;
189 }
190 
191 void Area::hide() {
192  if (!_visible)
193  return;
194 
195  removeFocus();
196 
198 
199  GfxMan.lockFrame();
200 
201  // Hide objects
202  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
203  (*o)->hide();
204 
205  // Hide area geometry model
206  if (_model)
207  _model->show();
208 
209  GfxMan.unlockFrame();
210 
211  unloadModels();
212 
213  _visible = false;
214 }
215 
217  // Tag
218 
219  _tag = are.getString("Tag");
220 
221  // Name
222 
223  are.getLocString("Name", _name);
225 
226  // Generic properties
227 
228  if (are.hasField("AreaProperties"))
229  loadProperties(are.getStruct("AreaProperties"));
230 
231  // Area geometry model
232 
233  _modelName = are.getString("Tileset");
234 
235  // Scripts
236  readScripts(are);
237 }
238 
240  // Waypoints
241  if (git.hasField("WaypointList"))
242  loadWaypoints(git.getList("WaypointList"));
243 
244  // Placeables
245  if (git.hasField("Placeable List"))
246  loadPlaceables(git.getList("Placeable List"));
247 
248  // Doors
249  if (git.hasField("Door List"))
250  loadDoors(git.getList("Door List"));
251 }
252 
254  setMusicDayTrack (props.getUint("MusicDay" , Aurora::kStrRefInvalid));
255  setMusicNightTrack (props.getUint("MusicNight" , Aurora::kStrRefInvalid));
256  setMusicBattleTrack(props.getUint("MusicBattle", Aurora::kStrRefInvalid));
257 }
258 
260  loadAreaModel();
261 
262  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o) {
263  Engines::Witcher::Object &object = **o;
264 
265  object.loadModel();
266 
267  if (!object.isStatic()) {
268  const std::list<uint32> &ids = object.getIDs();
269 
270  for (std::list<uint32>::const_iterator id = ids.begin(); id != ids.end(); ++id)
271  _objectMap.insert(std::make_pair(*id, &object));
272  }
273  }
274 }
275 
277  _objectMap.clear();
278 
279  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
280  (*o)->unloadModel();
281 
282  unloadAreaModel();
283 }
284 
286  if (_modelName.empty())
287  return;
288 
290  if (!_model)
291  throw Common::Exception("Can't load area geometry model \"%s\"", _modelName.c_str());
292 
293  _model->setPosition(1500.0f, 1500.0f, 0.0f);
294 }
295 
297  _model.reset();
298 }
299 
301  object.setArea(this);
302 
303  _objects.push_back(&object);
304  _module->addObject(object);
305 }
306 
308  for (Aurora::GFF3List::const_iterator d = list.begin(); d != list.end(); ++d) {
309  Waypoint *waypoint = new Waypoint(**d);
310 
311  loadObject(*waypoint);
312  }
313 }
314 
316  for (Aurora::GFF3List::const_iterator p = list.begin(); p != list.end(); ++p) {
317  Placeable *placeable = new Placeable(**p);
318 
319  loadObject(*placeable);
320  }
321 }
322 
324  for (Aurora::GFF3List::const_iterator d = list.begin(); d != list.end(); ++d) {
325  Door *door = new Door(*_module, **d);
326 
327  loadObject(*door);
328  }
329 }
330 
331 void Area::addEvent(const Events::Event &event) {
332  _eventQueue.push_back(event);
333 }
334 
336  bool hasMove = false;
337  for (std::list<Events::Event>::const_iterator e = _eventQueue.begin();
338  e != _eventQueue.end(); ++e) {
339 
340  if (e->type == Events::kEventMouseMove) { // Moving the mouse
341  hasMove = true;
342  } else if (e->type == Events::kEventMouseDown) { // Clicking
343  if (e->button.button == SDL_BUTTON_LMASK) {
344  checkActive(e->button.x, e->button.y);
345  click(e->button.x, e->button.y);
346  }
347  } else if (e->type == Events::kEventKeyDown) { // Holding down TAB
348  if (e->key.keysym.sym == SDLK_TAB)
349  highlightAll(true);
350  } else if (e->type == Events::kEventKeyUp) { // Releasing TAB
351  if (e->key.keysym.sym == SDLK_TAB)
352  highlightAll(false);
353  }
354  }
355 
356  _eventQueue.clear();
357 
358  if (hasMove)
359  checkActive();
360 }
361 
363  const Graphics::Renderable *obj = GfxMan.getObjectAt(x, y);
364  if (!obj)
365  return 0;
366 
367  ObjectMap::iterator o = _objectMap.find(obj->getID());
368  if (o == _objectMap.end())
369  return 0;
370 
371  return o->second;
372 }
373 
375  if (object == _activeObject)
376  return;
377 
378  if (_activeObject)
379  _activeObject->leave();
380 
381  _activeObject = object;
382 
383  if (_activeObject)
384  _activeObject->enter();
385 }
386 
387 void Area::checkActive(int x, int y) {
388  if (_highlightAll)
389  return;
390 
392 
393  if ((x < 0) || (y < 0))
394  CursorMan.getPosition(x, y);
395 
396  setActive(getObjectAt(x, y));
397 }
398 
399 void Area::click(int x, int y) {
401 
403  if (!o)
404  return;
405 
406  o->click(_module->getPC());
407 }
408 
409 void Area::highlightAll(bool enabled) {
410  if (_highlightAll == enabled)
411  return;
412 
413  _highlightAll = enabled;
414 
415  for (ObjectMap::iterator o = _objectMap.begin(); o != _objectMap.end(); ++o)
416  if (o->second->isClickable())
417  o->second->highlight(enabled);
418 }
419 
421  if (_activeObject)
422  _activeObject->leave();
423 
424  _activeObject = 0;
425 }
426 
428  checkActive();
429 }
430 
431 } // End of namespace Witcher
432 
433 } // End of namespace Engines
void loadGIT(const Aurora::GFF3Struct &git)
Definition: area.cpp:239
Handling version V3.2/V3.3 of BioWare&#39;s GFFs (generic file format).
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
void setMusicBattleTrack(uint32 track)
Set the music track ID playing in battle.
Definition: area.cpp:146
The global graphics manager.
void addObject(Witcher::Object &object)
Add an object to this container.
void click(int x, int y)
Definition: area.cpp:399
bool getLocString(const Common::UString &field, LocString &str) const
Definition: gff3file.cpp:614
A class holding an UTF-8 string.
Definition: ustring.h:48
An object within a Witcher area.
Definition: object.h:51
A localized string.
Definition: locstring.h:43
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
void loadObject(Engines::Witcher::Object &object)
Definition: area.cpp:300
void playAmbientMusic(Common::UString music="")
Play the specified music (or the area&#39;s default) as ambient music.
Definition: area.cpp:155
Engines::Witcher::Object * _activeObject
The currently active (highlighted) object.
Definition: area.h:146
bool hasField(const Common::UString &field) const
Does this specific field exist?
Definition: gff3file.cpp:400
void loadARE(const Aurora::GFF3Struct &are)
Definition: area.cpp:216
uint32 getMusicNightTrack() const
Return the music track ID playing by night.
Definition: area.cpp:128
void removeFocus()
Forcibly remove the focus from the currently highlighted object.
Definition: area.cpp:420
void readScripts(const Aurora::GFF3Struct &gff)
Definition: container.cpp:129
const GFF3Struct & getTopLevel() const
Returns the top-level struct.
Definition: gff3file.cpp:91
uint64 getUint(const Common::UString &field, uint64 def=0) const
Definition: gff3file.cpp:436
const Common::UString & getResRef() const
Return the area&#39;s resref (resource ID).
Definition: area.cpp:111
uint32 getMusicDayTrack() const
Return the music track ID playing by day.
Definition: area.cpp:124
void highlightAll(bool enabled)
Definition: area.cpp:409
Common::UString _musicNight
Music that plays by night.
Definition: area.h:132
virtual bool click(Object *triggerer=0)
The object was clicked.
Definition: object.cpp:215
Mouse was moved.
Definition: types.h:48
A door in a The Witcher area.
Fake value for an area object.
Definition: types.h:52
Engines::Witcher::Object * getObjectAt(int x, int y)
Definition: area.cpp:362
void hide()
Hide the area.
Definition: area.cpp:191
SDL_Event Event
Definition: types.h:42
Mouse button was pressed.
Definition: types.h:49
void processEventQueue()
Process the current event queue.
Definition: area.cpp:335
Keyboard key was pressed.
Definition: types.h:46
Basic exceptions to throw.
void removeObject(Witcher::Object &object)
Remove an object from this container.
A creature in a The Witcher area.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
uint32 _musicDayTrack
Music track ID that plays by day.
Definition: area.h:127
ObjectMap _objectMap
Map of all non-static objects in the area.
Definition: area.h:143
Utility templates and functions.
void show()
Show the area.
Definition: area.cpp:168
void unloadAreaModel()
Definition: area.cpp:296
Handling BioWare&#39;s 2DAs (two-dimensional array).
A GFF (generic file format) V3.2/V3.3 file, found in all Aurora games except Sonic Chronicles: The Da...
Definition: gff3file.h:85
const Aurora::LocString & getName() const
Return the object&#39;s name.
Definition: object.cpp:81
A 3D model of an object.
static const uint32 kStrRefInvalid
Definition: types.h:444
bool _highlightAll
Are we currently highlighting all objects?
Definition: area.h:148
The global sound manager, handling all sound output.
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
#define TwoDAReg
Shortcut for accessing the 2da registry.
Definition: 2dareg.h:101
void checkActive(int x=-1, int y=-1)
Definition: area.cpp:387
#define SoundMan
Shortcut for accessing the sound manager.
Definition: sound.h:293
Common::UString _resRef
The area&#39;s resref (resource ID).
Definition: area.h:125
StackException Exception
Definition: error.h:59
bool _visible
Is the area currently visible?
Definition: area.h:135
The global 2DA registry.
A waypoint in a The Witcher area.
std::list< Events::Event > _eventQueue
The event queue.
Definition: area.h:150
#define CursorMan
Shortcut for accessing the cursor manager.
Definition: cursorman.h:129
void stopAmbientMusic()
Stop the ambient music.
Definition: area.cpp:151
Common::UString _musicDay
Music that plays by day.
Definition: area.h:131
std::vector< const GFF3Struct * > GFF3List
Definition: types.h:449
Convenience class that locks a mutex on creation and unlocks it on destruction.
Definition: mutex.h:71
Module * _module
Definition: area.h:123
The Aurora cursor manager.
void loadProperties(const Aurora::GFF3Struct &props)
Definition: area.cpp:253
Sound::ChannelHandle playSound(const Common::UString &sound, Sound::SoundType soundType, bool loop, float volume, bool pitchVariance)
Play this sound resource.
Definition: util.cpp:81
virtual void enter()
The cursor entered the object.
Definition: object.cpp:159
An object that can be displayed by the graphics manager.
Definition: renderable.h:42
uint32 getMusicBattleTrack() const
Return the music track ID playing in battle.
Definition: area.cpp:132
const GFF3List & getList(const Common::UString &field) const
Definition: gff3file.cpp:741
uint32 _musicBattleTrack
Music track ID that plays in battle.
Definition: area.h:129
uint32 getID() const
Get the object&#39;s unique ID.
Definition: renderable.cpp:86
Dynamic area data, GFF.
Definition: types.h:89
Common::UString _musicBattle
Music that plays in battle.
Definition: area.h:133
void clear()
Definition: ptrlist.h:47
A struct within a GFF3.
Definition: gff3file.h:164
void loadDoors(const Aurora::GFF3List &list)
Definition: area.cpp:323
Common::Mutex _mutex
Mutex securing access to the area.
Definition: area.h:152
Common::ScopedPtr< Graphics::Aurora::Model > _model
The actual area geometry model.
Definition: area.h:140
uint32_t uint32
Definition: types.h:204
const GFF3Struct & getStruct(const Common::UString &field) const
Definition: gff3file.cpp:728
The context needed to run a The Witcher module.
Common::UString _tag
Definition: object.h:56
Static area data, GFF.
Definition: types.h:81
Common::UString _modelName
Name of area geometry ("tile") model.
Definition: area.h:139
void setActive(Engines::Witcher::Object *object)
Definition: area.cpp:374
The context holding a The Witcher area.
Sound::ChannelHandle _ambientMusic
Sound handle of the currently playing music.
Definition: area.h:137
void refreshLocalized()
Refresh all localized strings.
Definition: area.cpp:119
bool isStatic() const
Is the object static (not manipulable at all)?
Definition: object.cpp:96
uint32 _musicNightTrack
Music track ID that plays by night.
Definition: area.h:128
void addEvent(const Events::Event &event)
Add a single event for consideration into the area event queue.
Definition: area.cpp:331
Common::UString getString(const Common::UString &field, const Common::UString &def="") const
Definition: gff3file.cpp:527
Aurora::LocString _name
The object&#39;s name.
Definition: object.h:146
Generic Aurora engines utility functions.
ObjectList _objects
List of all objects in the area.
Definition: area.h:142
void loadPlaceables(const Aurora::GFF3List &list)
Definition: area.cpp:315
const Aurora::LocString & getName() const
Return the area&#39;s name.
Definition: area.cpp:115
virtual void leave()
The cursor left the object.
Definition: object.cpp:162
virtual void loadModel()
Load the object&#39;s model(s).
Definition: object.cpp:65
void notifyCameraMoved()
Notify the area that the camera has been moved.
Definition: area.cpp:427
Graphics::Aurora::Model * loadModelObject(const Common::UString &resref, const Common::UString &texture)
Definition: model.cpp:47
void setMusicDayTrack(uint32 track)
Set the music track ID playing by day.
Definition: area.cpp:136
void loadWaypoints(const Aurora::GFF3List &list)
Definition: area.cpp:307
Keyboard key was released.
Definition: types.h:47
Creature * getPC()
Return the currently playing PC.
Definition: module.cpp:79
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
void setMusicNightTrack(uint32 track)
Set the music track ID playing by night.
Definition: area.cpp:141
A placeable object in a The Witcher area.
Area(Module &module, const Common::UString &resRef)
Definition: area.cpp:53
Generic Aurora engines model functions.