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/gdafile.h"
29 #include "src/aurora/2dareg.h"
30 #include "src/aurora/gff4file.h"
31 #include "src/aurora/talkman.h"
32 
34 
35 #include "src/graphics/graphics.h"
37 #include "src/graphics/camera.h"
38 
40 
41 #include "src/engines/sonic/area.h"
47 
48 static const uint32 kAREID = MKTAG('A', 'R', 'E', ' ');
49 
50 namespace Engines {
51 
52 namespace Sonic {
53 
55  _module(&module), _width(0), _height(0), _startPosX(0.0f), _startPosY(0.0f),
56  _miniMapWidth(0), _miniMapHeight(0), _soundMapBank(-1), _sound(-1), _soundType(-1), _soundBank(-1),
57  _numberRings(0), _numberChaoEggs(0), _activeObject(0), _highlightAll(false) {
58 
59  _id = id;
60  ObjectMan.registerObject(this);
61 
62  load();
63 
64  // Tell the module that we exist
65  _module->addObject(*this);
66 }
67 
69  ObjectMan.unregisterObject(this);
70 
71  _module->removeObject(*this);
72 
73  hide();
74 
75  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
76  _module->removeObject(**o);
77 }
78 
80  return _name;
81 }
82 
84  return _width;
85 }
86 
88  return _height;
89 }
90 
91 float Area::getStartX() const {
92  return _startPosX;
93 }
94 
95 float Area::getStartY() const {
96  return _startPosY;
97 }
98 
99 void Area::getCameraPosition(float x, float y, float &cameraX, float &cameraY, float &cameraZ) {
100  cameraX = x - kScreenWidth / 2.0f;
101  cameraY = kCameraHeight;
102  cameraZ = (y - kScreenHeight / 2.0f) / sin(Common::deg2rad(kCameraAngle));
103 }
104 
105 void Area::getWorldPosition(float x, float y, float z, float &worldX, float &worldY, float &worldZ) {
106  worldX = x + kScreenWidth / 2.0f;
107  worldY = z;
108  worldZ = (y - kScreenHeight + kScreenHeight / 2.0f) / sin(Common::deg2rad(kCameraAngle)) - kCameraHeight;
109 
110  worldZ = floor(worldZ);
111 }
112 
113 void Area::getCameraLimits(float &minX, float &minY, float &minZ,
114  float &maxX, float &maxY, float &maxZ) const {
115 
116  minX = kScreenWidth / 2.0f;
117  minY = -FLT_MAX;
118  minZ = (kScreenHeight / 2.0f) / sin(Common::deg2rad(kCameraAngle));
119  maxX = _width - kScreenWidth / 2.0f;
120  maxY = FLT_MAX;
121  maxZ = (_height - kScreenHeight / 2.0f) / sin(Common::deg2rad(kCameraAngle));
122 }
123 
124 void Area::show() {
125  GfxMan.lockFrame();
126 
127  if (_mmPanel)
128  _mmPanel->show();
129  if (_bgPanel)
130  _bgPanel->show();
131 
132  // Show objects
133  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
134  (*o)->show();
135 
136  GfxMan.unlockFrame();
137 }
138 
139 void Area::hide() {
140  GfxMan.lockFrame();
141 
142  removeFocus();
143 
144  // Hide objects
145  for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
146  (*o)->hide();
147 
148  if (_mmPanel)
149  _mmPanel->hide();
150  if (_bgPanel)
151  _bgPanel->hide();
152 
153  GfxMan.unlockFrame();
154 }
155 
156 void Area::enter() {
157  CameraMan.reset();
158 
159  if (_bgPanel) {
160  float x, y, z, minX, minY, minZ, maxX, maxY, maxZ;
161 
162  getCameraLimits(minX, minY, minZ, maxX, maxY, maxZ);
164 
165  CameraMan.limit(minX, minY, minZ, maxX, maxY, maxZ);
166  CameraMan.setOrientation(-kCameraAngle, 0.0f, 0.0f);
167  CameraMan.setPosition(x, y, z);
168  }
169 
170  CameraMan.update();
171 }
172 
173 void Area::leave() {
174  CameraMan.reset();
175  CameraMan.update();
176 }
177 
178 void Area::addEvent(const Events::Event &event) {
179  _eventQueue.push_back(event);
180 }
181 
183  bool hasMove = false;
184  for (std::list<Events::Event>::const_iterator e = _eventQueue.begin();
185  e != _eventQueue.end(); ++e) {
186 
187  if (e->type == Events::kEventMouseMove) {
188  hasMove = true;
189  } else if (e->type == Events::kEventKeyDown) {
190  if (e->key.keysym.sym == SDLK_TAB)
191  highlightAll(true);
192  } else if (e->type == Events::kEventKeyUp) {
193  if (e->key.keysym.sym == SDLK_TAB)
194  highlightAll(false);
195  }
196  }
197 
198  _eventQueue.clear();
199 
200  if (hasMove)
201  checkActive();
202 }
203 
204 void Area::load() {
205  loadDefinition();
206  loadBackground();
207  loadMiniMap();
208  loadLayout();
209 }
210 
212  const Aurora::GDAFile &areas = TwoDAReg.getGDA("areas");
213  if (!areas.hasRow(_id))
214  throw Common::Exception("No such Area ID %u (%u)", _id, (uint)areas.getRowCount());
215 
216  _name = TalkMan.getString(areas.getInt(_id, "Name", 0xFFFFFFFF));
217 
218  _background = areas.getString(_id, "Background");
219  if (_background.empty())
220  throw Common::Exception("Area has no background");
221 
222  _layout = areas.getString(_id, "Layout");
223  if (_layout.empty())
224  throw Common::Exception("Area has no layout");
225 
226  const uint32 tileSizeX = areas.getInt(_id, "TileSizeX");
227  const uint32 tileSizeY = areas.getInt(_id, "TileSizeY");
228  if ((tileSizeX != 64) || (tileSizeY != 64))
229  throw Common::Exception("Unsupported tile dimensions (%ux%u)", tileSizeX, tileSizeY);
230 
231  _width = areas.getInt(_id, "AreaWidth");
232  _height = areas.getInt(_id, "AreaHeight");
233  if ((_width == 0) || (_height == 0))
234  throw Common::Exception("Invalid area dimensions (%ux%u)", _width, _height);
235 
236  _startPosX = areas.getFloat(_id, "StartPosX");
237  _startPosY = areas.getFloat(_id, "StartPosY");
238 
239  if ((_startPosX < 0.0f) || (_startPosY < 0.0f) || (_startPosX > _width) || (_startPosY > _height))
240  throw Common::Exception("Invalid start position (%f+%f, %ux%u", _startPosX, _startPosY, _width, _height);
241 
242  _miniMap = areas.getString(_id, "MiniMapString");
243 
244  _miniMapWidth = areas.getInt(_id, "MiniMapWidth");
245  _miniMapHeight = areas.getInt(_id, "MiniMapHeight");
246 
247  _soundMap = areas.getString(_id, "SoundMap");
248 
249  _soundMapBank = areas.getInt(_id, "SoundMapBank" , -1);
250  _sound = areas.getInt(_id, "AreaSound" , -1);
251  _soundType = areas.getInt(_id, "AreaSoundType", -1);
252  _soundBank = areas.getInt(_id, "AreaSoundBank", -1);
253 
254  _numberRings = areas.getInt(_id, "NumberRings");
255  _numberChaoEggs = areas.getInt(_id, "NumberChaoEggs");
256 }
257 
259  _bgPanel.reset(new AreaBackground(_background));
260 
261  if ((_bgPanel->getImageWidth() != _width) || (_bgPanel->getImageHeight() != _height))
262  throw Common::Exception("Background and area dimensions don't match (%ux%u vs. %ux%u)",
263  _bgPanel->getImageWidth(), _bgPanel->getImageHeight(), _width, _height);
264 }
265 
267  if (!_miniMap.empty())
268  _mmPanel.reset(new AreaMiniMap(_miniMap));
269 }
270 
273  const Aurora::GFF4Struct &areTop = are.getTopLevel();
274 
275  _tag = areTop.getString(40000);
276 
277  if (areTop.hasField(40001))
278  loadPlaceables(areTop.getList(40001));
279 }
280 
281 void Area::loadObject(Object &object) {
282  _objects.push_back(&object);
283 
284  _objectMap.insert(std::make_pair(object.getModelID(), &object));
285  _module->addObject(object);
286 }
287 
289  for (Aurora::GFF4List::const_iterator p = list.begin(); p != list.end(); ++p) {
290  Placeable *placeable = new Placeable(**p);
291 
292  loadObject(*placeable);
293  }
294 }
295 
296 Object *Area::getObjectAt(int x, int y) {
297  const Graphics::Renderable *obj = GfxMan.getObjectAt(x, y);
298  if (!obj)
299  return 0;
300 
301  ObjectMap::iterator o = _objectMap.find(obj->getID());
302  if (o == _objectMap.end())
303  return 0;
304 
305  return o->second;
306 }
307 
308 void Area::setActive(Object *object) {
309  if (object == _activeObject)
310  return;
311 
312  if (_activeObject)
313  _activeObject->leave();
314 
315  _activeObject = object;
316 
317  if (_activeObject)
318  _activeObject->enter();
319 }
320 
322  if (_highlightAll)
323  return;
324 
326 
327  int x, y;
328  CursorMan.getPosition(x, y);
329 
330  setActive(getObjectAt(x, y));
331 }
332 
333 void Area::highlightAll(bool enabled) {
334  if (_highlightAll == enabled)
335  return;
336 
337  _highlightAll = enabled;
338 
339  for (ObjectMap::iterator o = _objectMap.begin(); o != _objectMap.end(); ++o)
340  o->second->highlight(enabled);
341 }
342 
344  if (_activeObject)
345  _activeObject->leave();
346 
347  _activeObject = 0;
348 }
349 
351  checkActive();
352 }
353 
354 } // End of namespace Sonic
355 
356 } // End of namespace Engines
#define ObjectMan
Definition: objectman.h:56
static const float kScreenHeight
Definition: types.h:35
#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 addObject(Sonic::Object &object)
Add an object to this container.
The context holding a Sonic Chronicles: The Dark Brotherhood area.
void loadDefinition()
Definition: area.cpp:211
Common::ScopedPtr< AreaBackground > _bgPanel
Definition: area.h:138
Handling BioWare&#39;s GDAs (2DAs, two-dimensional array, within V4.0 GFFs).
int32 getInt(size_t row, uint32 columnHash, int32 def=0) const
Definition: gdafile.cpp:184
The global graphics manager.
#define TalkMan
Shortcut for accessing the talk manager.
Definition: talkman.h:111
Common::UString getString(uint32 field, Common::Encoding encoding, const Common::UString &def="") const
Return a field string, read from the given encoding.
Definition: gff4file.cpp:949
A class holding an UTF-8 string.
Definition: ustring.h:48
Common::UString _background
Definition: area.h:112
Common::UString _soundMap
Definition: area.h:126
float getStartY() const
Return the starting Y position within this area.
Definition: area.cpp:95
Common::UString _miniMap
Definition: area.h:121
float getFloat(size_t row, uint32 columnHash, float def=0.0f) const
Definition: gdafile.cpp:202
Camera management.
void loadBackground()
Definition: area.cpp:258
void checkActive()
Definition: area.cpp:321
Area(Module &module, uint32 id)
Definition: area.cpp:54
A GFF (generic file format) V4.0/V4.1 file, found in Dragon Age: Origins, Dragon Age 2 and Sonic Chro...
Definition: gff4file.h:93
float _startPosY
Definition: area.h:119
static void getWorldPosition(float x, float y, float z, float &worldX, float &worldY, float &worldZ)
Return a position that would position on object at these coordinates within the area.
Definition: area.cpp:105
virtual void enter()
The cursor entered the object.
Definition: object.cpp:87
void loadMiniMap()
Definition: area.cpp:266
static const float kCameraAngle
Definition: types.h:44
uint32 getModelID() const
Return the ID of the object&#39;s model.
Definition: object.cpp:56
Mouse was moved.
Definition: types.h:48
uint32 _height
Definition: area.h:116
Exception that provides a stack of explanations.
Definition: error.h:36
Basic Sonic Chronicles: The Dark Brotherhood types and defines.
An object within a Sonic area.
Definition: object.h:40
SDL_Event Event
Definition: types.h:42
int32 _soundMapBank
Definition: area.h:128
Keyboard key was pressed.
Definition: types.h:46
std::vector< const GFF4Struct * > GFF4List
Definition: types.h:453
ObjectList _objects
Definition: area.h:141
Handling version V4.0/V4.1 of BioWare&#39;s GFFs (generic file format).
NWScript object manager.
Basic exceptions to throw.
Module * _module
Definition: area.h:109
void show()
Show the area.
Definition: area.cpp:124
void setActive(Object *object)
Definition: area.cpp:308
Common::Mutex _mutex
Definition: area.h:148
Utility templates and functions.
uint32 _numberRings
Definition: area.h:133
void processEventQueue()
Process the current event queue.
Definition: area.cpp:182
void getCameraLimits(float &minX, float &minY, float &minZ, float &maxX, float &maxY, float &maxZ) const
Definition: area.cpp:113
The area mini map in Sonic Chronicles: The Dark Brotherhood.
static const float kScreenWidth
Definition: types.h:34
Common::ScopedPtr< AreaMiniMap > _mmPanel
Definition: area.h:139
uint32 _numberChaoEggs
Definition: area.h:134
void loadObject(Object &object)
Definition: area.cpp:281
The scrolling background image panel in Sonic Chronicles: The Dark Brotherhood.
void hide()
Hide the area.
Definition: area.cpp:139
bool hasField(uint32 field) const
Does this specific field exist?
Definition: gff4file.cpp:573
uint32 getWidth() const
Return the width of the area, in pixels.
Definition: area.cpp:83
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
#define TwoDAReg
Shortcut for accessing the 2da registry.
Definition: 2dareg.h:101
Object * _activeObject
Definition: area.h:144
int32 _soundType
Definition: area.h:130
StackException Exception
Definition: error.h:59
The global 2DA registry.
#define CursorMan
Shortcut for accessing the cursor manager.
Definition: cursorman.h:129
Convenience class that locks a mutex on creation and unlocks it on destruction.
Definition: mutex.h:71
Object * getObjectAt(int x, int y)
Definition: area.cpp:296
size_t getRowCount() const
Return the number of rows in the array.
Definition: gdafile.cpp:61
The Aurora cursor manager.
static const uint32 kAREID
Definition: area.cpp:48
void removeFocus()
Forcibly remove the focus from the currently highlighted object.
Definition: area.cpp:343
An object that can be displayed by the graphics manager.
Definition: renderable.h:42
uint32 getHeight() const
Return the height of the area, in pixels.
Definition: area.cpp:87
static void getCameraPosition(float x, float y, float &cameraX, float &cameraY, float &cameraZ)
Return a position that would position the camera on these coordinates within the area.
Definition: area.cpp:99
The context needed to run a Sonic Chronicles: The Dark Brotherhood module.
Common::UString getString(size_t row, uint32 columnHash, const Common::UString &def="") const
Definition: gdafile.cpp:165
Common::UString _layout
Definition: area.h:113
A Sonic module.
Definition: module.h:45
ObjectMap _objectMap
Definition: area.h:142
uint32 getID() const
Get the object&#39;s unique ID.
Definition: renderable.cpp:86
uint32 _miniMapWidth
Definition: area.h:123
virtual void leave()
The cursor left the object.
Definition: object.cpp:90
void highlightAll(bool enabled)
Definition: area.cpp:333
uint32 _height
Definition: h263.cpp:54
uint32_t uint32
Definition: types.h:204
The global talk manager for Aurora strings.
int32 _soundBank
Definition: area.h:131
Common::UString _tag
Definition: object.h:56
Static area data, GFF.
Definition: types.h:81
void addEvent(const Events::Event &event)
Add a single event for consideration into the area event queue.
Definition: area.cpp:178
uint32 _miniMapHeight
Definition: area.h:124
bool hasRow(size_t row) const
Does this row exist in the GDA?
Definition: gdafile.cpp:69
#define CameraMan
Shortcut for accessing the camera manager.
Definition: camera.h:83
std::list< Events::Event > _eventQueue
Definition: area.h:136
A placeable object in a Sonic Chronicles: The Dark Brotherhood area.
static const float kCameraHeight
Definition: types.h:43
void removeObject(Sonic::Object &object)
Remove an object from this container.
const GFF4List & getList(uint32 field) const
Definition: gff4file.cpp:1394
Common::UString _name
Definition: area.h:111
uint32 _width
Definition: h263.cpp:53
float getStartX() const
Return the starting X position within this area.
Definition: area.cpp:91
void notifyCameraMoved()
Notify the area that the camera has been moved.
Definition: area.cpp:350
Keyboard key was released.
Definition: types.h:47
static float deg2rad(float deg)
Definition: maths.h:97
void enter()
Enter the area.
Definition: area.cpp:156
An object that can be displayed by the graphics manager.
const GFF4Struct & getTopLevel() const
Returns the top-level struct.
Definition: gff4file.cpp:135
#define FLT_MAX
Definition: maths.h:47
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
float _startPosX
Definition: area.h:118
void loadPlaceables(const Aurora::GFF4List &list)
Definition: area.cpp:288
Class to hold the GFF&#39;d two-dimensional array of a GDA file.
Definition: gdafile.h:62
unsigned int uint
Definition: types.h:211
const Common::UString & getName()
Return the area&#39;s localized name.
Definition: area.cpp:79
bool _highlightAll
Definition: area.h:146
void leave()
Leave the area.
Definition: area.cpp:173