/
sector.h
281 lines (240 loc) · 8.57 KB
/
sector.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/** @file sector.h World map sector.
*
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2006-2014 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program 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 General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/
#ifndef DENG_WORLD_SECTOR_H
#define DENG_WORLD_SECTOR_H
#include <functional>
#ifdef __CLIENT__
# include <de/aabox.h>
#endif
#include <de/Error>
#include <de/Observers>
#include <de/Vector>
#include "MapElement"
#include "Line"
#include "Plane"
struct mobj_s;
class Surface;
/**
* World map sector.
*
* @ingroup world
*/
class Sector : public de::MapElement
{
DENG2_NO_COPY (Sector)
DENG2_NO_ASSIGN(Sector)
public:
/// Required/referenced plane is missing. @ingroup errors
DENG2_ERROR(MissingPlaneError);
/// Notified whenever a light level change occurs.
DENG2_DEFINE_AUDIENCE(LightLevelChange, void sectorLightLevelChanged(Sector §or))
/// Notified whenever a light color change occurs.
DENG2_DEFINE_AUDIENCE(LightColorChange, void sectorLightColorChanged(Sector §or))
// Plane identifiers:
enum { Floor, Ceiling };
public:
/**
* Construct a new sector.
*
* @param lightLevel Ambient light level.
* @param lightColor Ambient light color.
*/
Sector(float lightLevel = 1,
de::Vector3f const &lightColor = de::Vector3f(1, 1, 1));
/**
* Returns @c true if at least one Plane in the sector is sky-masked.
*
* @see Surface::hasSkyMaskedMaterial()
*/
bool hasSkyMaskedPlane() const;
/**
* Returns the total number of planes in/owned by the sector.
*/
int planeCount() const;
/**
* Lookup a Plane by it's sector-unique @a planeIndex.
*/
Plane &plane(int planeIndex);
Plane const &plane(int planeIndex) const;
/**
* Returns the @em floor Plane of the sector.
*/
inline Plane &floor() { return plane(Floor); }
inline Plane const &floor() const { return plane(Floor); }
/**
* Returns the @em ceiling Plane of the sector.
*/
inline Plane &ceiling() { return plane(Ceiling); }
inline Plane const &ceiling() const { return plane(Ceiling); }
/**
* Add a new Plane to the sector.
*
* @param normal World space normal for the new plane.
* @param height World space Z axis coordinate for the new plane.
*/
Plane *addPlane(de::Vector3f const &normal, coord_t height);
/**
* Iterate through the Planes of the sector.
*
* @param func Callback to make for each Plane.
*/
de::LoopResult forAllPlanes(std::function<de::LoopResult (Plane &)> func) const;
/**
* Convenient accessor method for returning the surface of the specified
* plane of the sector.
*/
inline Surface &planeSurface(int planeIndex) { return plane(planeIndex).surface(); }
inline Surface const &planeSurface(int planeIndex) const { return plane(planeIndex).surface(); }
/**
* Convenient accessor method for returning the surface of the floor plane
* of the sector.
*/
inline Surface &floorSurface() { return floor().surface(); }
inline Surface const &floorSurface() const { return floor().surface(); }
/**
* Convenient accessor method for returning the surface of the ceiling plane
* of the sector.
*/
inline Surface &ceilingSurface() { return ceiling().surface(); }
inline Surface const &ceilingSurface() const { return ceiling().surface(); }
/**
* Returns the total number of Line::Sides which reference the sector.
*/
int sideCount() const;
/**
* Iterate through the Line::Sides of the sector.
*
* @param func Callback to make for each Line::Side.
*/
de::LoopResult forAllSides(std::function<de::LoopResult (LineSide &)> func) const;
/**
* (Re)Build the side list for the sector.
*
* @note In the special case of self-referencing line, only the front side
* reference is added to this list.
*
* @attention The behavior of some algorithms used in the DOOM game logic
* is dependant upon the order of this list. For example, EV_DoFloor and
* EV_BuildStairs. That same order is used here, for compatibility.
*
* Order: Original @em line index, ascending.
*/
void buildSides();
/**
* Returns the primary sound emitter for the sector. Other emitters in the
* sector are linked to this, forming a chain which can be traversed using
* the 'next' pointer of the emitter's thinker_t.
*/
SoundEmitter &soundEmitter();
SoundEmitter const &soundEmitter() const;
/**
* (Re)Build the sound emitter chains for the sector. These chains are used
* for efficiently traversing all sound emitters in the sector (e.g., when
* stopping all sounds emitted in the sector). To be called during map load
* once planes and sides have been initialized.
*
* @see addPlane(), buildSides()
*/
void chainSoundEmitters();
/**
* Returns the ambient light level in the sector. The LightLevelChange
* audience is notified whenever the light level changes.
*
* @see setLightLevel()
*/
float lightLevel() const;
/**
* Change the ambient light level in the sector. The LightLevelChange
* audience is notified whenever the light level changes.
*
* @param newLightLevel New ambient light level.
*
* @see lightLevel()
*/
void setLightLevel(float newLightLevel);
/**
* Returns the ambient light color in the sector. The LightColorChange
* audience is notified whenever the light color changes.
*
* @see setLightColor()
*/
de::Vector3f const &lightColor() const;
/**
* Change the ambient light color in the sector. The LightColorChange
* audience is notified whenever the light color changes.
*
* @param newLightColor New ambient light color.
*
* @see lightColor()
*/
void setLightColor(de::Vector3f const &newLightColor);
/**
* Returns the first mobj in the linked list of mobjs "in" the sector.
*/
struct mobj_s *firstMobj() const;
/**
* Unlink the mobj from the list of mobjs "in" the sector.
*
* @param mob Mobj to be unlinked.
*/
void unlink(struct mobj_s *mob);
/**
* Link the mobj to the head of the list of mobjs "in" the sector. Note that
* mobjs in this list may not actually be inside the sector. This is because
* the sector is determined by interpreting the BSP leaf as a half-space and
* not a closed convex subspace (@ref de::Map::link()).
*
* @param mob Mobj to be linked.
*/
void link(struct mobj_s *mob);
/**
* Returns the @em validCount of the sector. Used by some legacy iteration
* algorithms for marking sectors as processed/visited.
*
* @todo Refactor away.
*/
int validCount() const;
/// @todo Refactor away.
void setValidCount(int newValidCount);
#ifdef __CLIENT__
/**
* Returns the axis-aligned bounding box which encompases the geometry of
* all BSP leafs attributed to the sector (map units squared). Note that if
* no BSP leafs reference the sector the bounding box will be invalid (has
* negative dimensions).
*
* @todo Refactor away (still used by light decoration and particle systems).
*/
AABoxd const &aaBox() const;
/**
* Returns a rough approximation of the total combined area of the geometry
* for all BSP leafs attributed to the sector (map units squared).
*
* @todo Refactor away (still used by the particle system).
*/
coord_t roughArea() const;
#endif // __CLIENT__
protected:
int property(DmuArgs &args) const;
int setProperty(DmuArgs const &args);
private:
DENG2_PRIVATE(d)
};
#endif // DENG_WORLD_SECTOR_H