/
map.h
951 lines (791 loc) · 28.2 KB
/
map.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
/** @file map.h World map.
*
* @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_MAP_H
#define DENG_WORLD_MAP_H
#include "Mesh"
#include "BspNode"
#include "Line"
#include "Polyobj"
#ifdef __CLIENT__
# include "world/p_object.h"
# include "client/clplanemover.h"
# include "client/clpolymover.h"
# include "world/worldsystem.h"
# include "Generator"
# include "BiasSource"
# include "Lumobj"
#endif
#include <QList>
#include <QHash>
#include <QSet>
#include <doomsday/uri.h>
#include <de/BinaryTree>
#include <de/Observers>
#include <de/Vector>
class MapDef;
class BspLeaf;
class ConvexSubspace;
class LineBlockmap;
class Plane;
class Sector;
class SectorCluster;
class Surface;
class Vertex;
#ifdef __CLIENT__
class BiasTracker;
#endif
namespace de {
class Blockmap;
class EntityDatabase;
#ifdef __CLIENT__
class LightGrid;
#endif
class Thinkers;
/**
* World map.
*
* @ingroup world
*/
class Map
#ifdef __CLIENT__
: DENG2_OBSERVES(WorldSystem, FrameBegin)
#endif
{
DENG2_NO_COPY (Map)
DENG2_NO_ASSIGN(Map)
public:
/// Base error for runtime map editing errors. @ingroup errors
DENG2_ERROR(EditError);
/// Required blockmap is missing. @ingroup errors
DENG2_ERROR(MissingBlockmapError);
/// Required BSP data is missing. @ingroup errors
DENG2_ERROR(MissingBspTreeError);
/// Required thinker lists are missing. @ingroup errors
DENG2_ERROR(MissingThinkersError);
#ifdef __CLIENT__
/// Required light grid is missing. @ingroup errors
DENG2_ERROR(MissingLightGridError);
/// Attempted to add a new element when already full. @ingroup errors
DENG2_ERROR(FullError);
#endif
/// Notified when the map is about to be deleted.
DENG2_DEFINE_AUDIENCE(Deletion, void mapBeingDeleted(Map const &map))
/// Notified when a one-way window construct is first found.
DENG2_DEFINE_AUDIENCE(OneWayWindowFound,
void oneWayWindowFound(Line &line, Sector &backFacingSector))
/// Notified when an unclosed sector is first found.
DENG2_DEFINE_AUDIENCE(UnclosedSectorFound,
void unclosedSectorFound(Sector §or, Vector2d const &nearPoint))
/*
* Constants:
*/
#ifdef __CLIENT__
static int const MAX_BIAS_SOURCES = 8 * 32; // Hard limit due to change tracking.
/// Maximum number of generators per map.
static int const MAX_GENERATORS = 512;
#endif
/*
* Linked-element lists:
*/
typedef Mesh::Vertexes Vertexes;
typedef QList<Line *> Lines;
typedef QList<Polyobj *> Polyobjs;
typedef QList<Sector *> Sectors;
typedef QList<ConvexSubspace *> Subspaces;
#ifdef __CLIENT__
typedef QSet<Plane *> PlaneSet;
typedef QSet<Surface *> SurfaceSet;
typedef QList<BiasSource *> BiasSources;
typedef QList<Lumobj *> Lumobjs;
typedef QHash<thid_t, mobj_t *> ClMobjHash;
#endif
typedef de::BinaryTree<BspElement *> BspTree;
public: /// @todo make private:
coord_t _globalGravity; // The defined gravity for this map.
coord_t _effectiveGravity; // The effective gravity for this map.
int _ambientLightLevel; // Ambient lightlevel for the current map.
public:
/**
* Construct a new map initially configured in an editable state. Whilst
* editable new map elements can be added, thereby allowing the map to be
* constructed dynamically. When done editing @ref endEditing() should be
* called to switch the map into a non-editable (i.e., playable) state.
*
* @param mapDefinition Definition for the map (Can be set later, @ref setDef).
*/
Map(MapDef *mapDefinition = 0);
/**
* Change the definition associated with the map to @a newMapDefinition.
*/
void setDef(MapDef *newMapDefinition);
/**
* Returns the definition for the map.
*/
MapDef *def() const;
/**
* To be called following an engine reset to update the map state.
*/
void update();
/**
* Returns the points which describe the boundary of the map coordinate
* space, which, are defined by the minimal and maximal vertex coordinates
* of the non-editable, non-polyobj line geometries).
*/
AABoxd const &bounds() const;
inline Vector2d origin() const {
return Vector2d(bounds().min);
}
inline Vector2d dimensions() const {
return Vector2d(bounds().max) - Vector2d(bounds().min);
}
/**
* Returns the currently effective gravity multiplier for the map.
*/
coord_t gravity() const;
/**
* Change the effective gravity multiplier for the map.
*
* @param newGravity New gravity multiplier.
*/
void setGravity(coord_t newGravity);
/**
* Returns the minimum ambient light level for the whole map.
*/
int ambientLightLevel() const;
/**
* Provides access to the thinker lists for the map.
*/
Thinkers /*const*/ &thinkers() const;
/**
* Provides access to the primary @ref Mesh geometry owned by the map.
* Note that further meshes may be assigned to individual elements of
* the map should their geometries not be representable as a manifold
* with the primary mesh (e.g., polyobjs and BSP leaf "extra" meshes).
*/
Mesh const &mesh() const;
/**
* Provides a list of all the non-editable vertexes in the map.
*/
Vertexes const &vertexes() const;
/**
* Provides a list of all the non-editable lines in the map.
*/
Lines const &lines() const;
/**
* Provides a list of all the non-editable polyobjs in the map.
*/
Polyobjs const &polyobjs() const;
/**
* Provides a list of all the non-editable sectors in the map.
*/
Sectors const §ors() const;
inline int vertexCount() const { return vertexes().count(); }
inline int lineCount() const { return lines().count(); }
inline int sideCount() const { return lines().count() * 2; }
inline int polyobjCount() const { return polyobjs().count(); }
inline int sectorCount() const { return sectors().count(); }
/**
* Provides access to the subspace list for efficient traversal.
*/
Subspaces const &subspaces() const;
/**
* Returns the total number of subspaces in the map.
*/
inline int subspaceCount() const { return subspaces().count(); }
/**
* Returns the total number of SectorClusters in the map.
*/
int clusterCount() const;
/**
* Iterate through the SectorClusters of the map.
*
* @param sector If not @c nullptr, traverse the clusters of this Sector only.
*/
LoopResult forAllClusters(Sector *sector, std::function<LoopResult (SectorCluster &)> func);
inline LoopResult forAllClusters(std::function<LoopResult (SectorCluster &)> func) {
return forAllClusters(nullptr, func);
}
/**
* Helper function which returns the relevant side index given a @a lineIndex
* and @a side identifier.
*
* Indices are produced as follows:
* @code
* lineIndex / 2 + (backSide? 1 : 0);
* @endcode
*
* @param lineIndex Index of the line in the map.
* @param side Side of the line. @c =0 the Line::Front else Line::Back
*
* @return Unique index for the identified side.
*/
static int toSideIndex(int lineIndex, int side);
/**
* Locate a LineSide in the map by it's unique @a index.
*
* @param index Unique index attributed to the line side.
*
* @return Pointer to the identified LineSide instance; otherwise @c 0.
*
* @see toSideIndex()
*/
LineSide *sideByIndex(int index) const;
/**
* Locate a Polyobj in the map by it's unique in-map tag.
*
* @param tag Tag associated with the polyobj to be located.
*
* @return Pointer to the identified Polyobj instance; otherwise @c 0.
*/
Polyobj *polyobjByTag(int tag) const;
/**
* Provides access to the entity database.
*/
EntityDatabase &entityDatabase() const;
/**
* Provides access to the mobj blockmap.
*/
Blockmap const &mobjBlockmap() const;
/**
* Provides access to the line blockmap.
*/
LineBlockmap const &lineBlockmap() const;
/**
* Provides access to the polyobj blockmap.
*/
Blockmap const &polyobjBlockmap() const;
/**
* Provides access to the convex subspace blockmap.
*/
Blockmap const &subspaceBlockmap() const;
/**
* Returns @c true iff a BSP tree is available for the map.
*/
bool hasBspTree() const;
/**
* Provides access to map's BSP tree, for efficient traversal.
*/
BspTree const &bspTree() const;
/**
* Determine the BSP leaf on the back side of the BS partition that lies
* in front of the specified point within the map's coordinate space.
*
* @note Always returns a valid BspLeaf although the point may not actually
* lay within it (however it is on the same side of the space partition)!
*
* @param point Map space coordinates to determine the BSP leaf for.
*
* @return BspLeaf instance for that BSP node's leaf.
*/
BspLeaf &bspLeafAt(Vector2d const &point) const;
/**
* @copydoc bspLeafAt()
*
* The test is carried out using fixed-point math for behavior compatible
* with vanilla DOOM. Note that this means there is a maximum size for the
* point: it cannot exceed the fixed-point 16.16 range (about 65k units).
*/
BspLeaf &bspLeafAt_FixedPrecision(Vector2d const &point) const;
/**
* Determine the SectorCluster which contains @a point and which is on the
* back side of the BS partition that lies in front of @a point.
*
* @param point Map space coordinates to determine the BSP leaf for.
*
* @return SectorCluster containing the specified point if any or @c 0 if
* the clusters have not yet been built.
*/
SectorCluster *clusterAt(Vector2d const &point) const;
/**
* Links a mobj into both a block and a BSP leaf based on it's (x,y).
* Sets mobj->bspLeaf properly. Calling with flags==0 only updates
* the BspLeaf pointer. Can be called without unlinking first.
* Should be called AFTER mobj translation to (re-)insert the mobj.
*/
void link(struct mobj_s &mobj, int flags);
/**
* Link the specified @a polyobj in any internal data structures for
* bookkeeping purposes. Should be called AFTER Polyobj rotation and/or
* translation to (re-)insert the polyobj.
*
* @param polyobj Polyobj to be linked.
*/
void link(Polyobj &polyobj);
/**
* Unlinks a mobj from everything it has been linked to. Should be called
* BEFORE mobj translation to extract the mobj.
*
* @param mo Mobj to be unlinked.
*
* @return DDLINK_* flags denoting what the mobj was unlinked from
* (in case we need to re-link).
*/
int unlink(struct mobj_s &mobj);
/**
* Unlink the specified @a polyobj from any internal data structures for
* bookkeeping purposes. Should be called BEFORE Polyobj rotation and/or
* translation to extract the polyobj.
*
* @param polyobj Polyobj to be unlinked.
*/
void unlink(Polyobj &polyobj);
/**
* Given an @a emitter origin, attempt to identify the map element
* to which it belongs.
*
* @param emitter The sound emitter to be identified.
* @param sector The identified sector if found is written here.
* @param poly The identified polyobj if found is written here.
* @param plane The identified plane if found is written here.
* @param surface The identified line side surface if found is written here.
*
* @return @c true iff @a emitter is an identifiable map element.
*/
bool identifySoundEmitter(ddmobj_base_t const &emitter, Sector **sector,
Polyobj **poly, Plane **plane, Surface **surface) const;
int mobjBoxIterator(AABoxd const &box,
int (*callback) (struct mobj_s *mobj, void *context), void *context = 0) const;
int mobjPathIterator(Vector2d const &from, Vector2d const &to,
int (*callback) (struct mobj_s *mobj, void *context), void *context = 0) const;
/**
* Lines and Polyobj lines (note polyobj lines are iterated first).
*
* @note validCount should be incremented before calling this to begin
* a new logical traversal. Otherwise Lines marked with a validCount
* equal to this will be skipped over (can be used to avoid processing
* a line multiple times during complex / non-linear traversals.
*
* @param flags @ref lineIteratorFlags
*/
int lineBoxIterator(AABoxd const &box, int flags,
int (*callback) (Line *line, void *context), void *context = 0) const;
/// @copydoc lineBoxIterator()
inline int lineBoxIterator(AABoxd const &box,
int (*callback) (Line *line, void *context), void *context = 0) const
{
return lineBoxIterator(box, LIF_ALL, callback, context);
}
/**
* @param flags @ref lineIteratorFlags
*/
int linePathIterator(Vector2d const &from, Vector2d const &to, int flags,
int (*callback) (Line *line, void *context), void *context = 0) const;
/// @copydoc linePathIterator()
inline int linePathIterator(Vector2d const &from, Vector2d const &to,
int (*callback) (Line *line, void *context), void *context = 0) const
{
return linePathIterator(from, to, LIF_ALL, callback, context);
}
int subspaceBoxIterator(AABoxd const &box,
int (*callback) (ConvexSubspace *subspace, void *context), void *context = 0) const;
/**
* @note validCount should be incremented before calling this to begin a
* new logical traversal. Otherwise Lines marked with a validCount equal
* to this will be skipped over (can be used to avoid processing a line
* multiple times during complex / non-linear traversals.
*/
int polyobjBoxIterator(AABoxd const &box,
int (*callback) (struct polyobj_s *polyobj, void *context),
void *context = 0) const;
/**
* The callback function will be called once for each line that crosses
* trough the object. This means all the lines will be two-sided.
*/
int mobjTouchedLineIterator(struct mobj_s *mo,
int (*callback) (Line *, void *), void *context = 0) const;
/**
* Increment validCount before calling this routine. The callback function
* will be called once for each sector the mobj is touching (totally or
* partly inside). This is not a 3D check; the mobj may actually reside
* above or under the sector.
*/
int mobjTouchedSectorIterator(struct mobj_s *mo,
int (*callback) (Sector *sector, void *context), void *context = 0) const;
int lineTouchingMobjIterator(Line *line,
int (*callback) (struct mobj_s *mobj, void *context), void *context = 0) const;
/**
* Increment validCount before using this. 'func' is called for each mobj
* that is (even partly) inside the sector. This is not a 3D test, the
* mobjs may actually be above or under the sector.
*
* (Lovely name; actually this is a combination of SectorMobjs and
* a bunch of LineMobjs iterations.)
*/
int sectorTouchingMobjIterator(Sector *sector,
int (*callback) (struct mobj_s *mobj, void *context), void *context = 0) const;
#ifdef __CLIENT__
coord_t skyFix(bool ceiling) const;
inline coord_t skyFixFloor() const { return skyFix(false /*the floor*/); }
inline coord_t skyFixCeiling() const { return skyFix(true /*the ceiling*/); }
void setSkyFix(bool ceiling, coord_t newHeight);
inline void setSkyFixFloor(coord_t newHeight) {
setSkyFix(false /*the floor*/, newHeight);
}
inline void setSkyFixCeiling(coord_t newHeight) {
setSkyFix(true /*the ceiling*/, newHeight);
}
/**
* Attempt to spawn a new (particle) generator for the map. If no free identifier
* is available then @c 0 is returned.
*/
Generator *newGenerator();
void unlink(Generator &generator);
/**
* Iterate over all generators in the map making a callback for each. Iteration
* ends when all generators have been processed or a callback returns non-zero.
*
* @param callback Callback to make for each iteration.
* @param context User data to be passed to the callback.
*
* @return @c 0 iff iteration completed wholly.
*/
int generatorIterator(int (*callback) (Generator *, void *), void *context = 0);
/**
* Iterate over all generators in the map which are present in the identified
* list making a callback for each. Iteration ends when all targeted generators
* have been processed or a callback returns non-zero.
*
* @param listIndex Index of the list to traverse.
* @param callback Callback to make for each iteration.
* @param context User data to be passed to the callback.
*
* @return @c 0 iff iteration completed wholly.
*/
int generatorListIterator(uint listIndex, int (*callback) (Generator *, void *), void *context = 0);
/**
* Returns the total number of @em active generators in the map.
*/
int generatorCount() const;
/**
* Add a new lumobj to the map (a copy is made).
*
* @return Reference to the newly added lumobj.
*
* @see lumobjCount()
*/
Lumobj &addLumobj(Lumobj const &lumobj = Lumobj());
/**
* Removes the specified lumobj from the map.
*
* @see removeAllLumobjs()
*/
void removeLumobj(int which);
/**
* Remove all lumobjs from the map.
*
* @see removeLumobj()
*/
void removeAllLumobjs();
/**
* Provides a list of all the lumobjs in the map.
*/
Lumobjs const &lumobjs() const;
/**
* Returns the total number of lumobjs in the map.
*/
inline int lumobjCount() const { return lumobjs().count(); }
/**
* Lookup a lumobj in the map by it's unique @a index.
*/
inline Lumobj *lumobj(int index) const { return lumobjs().at(index); }
/**
* Attempt to add a new bias light source to the map (a copy is made).
*
* @note At most @ref MAX_BIAS_SOURCES are supported for technical reasons.
*
* @return Reference to the newly added bias source.
*
* @see biasSourceCount()
* @throws FullError Once capacity is reached.
*/
BiasSource &addBiasSource(BiasSource const &biasSource = BiasSource());
/**
* Removes the specified bias light source from the map.
*
* @see removeAllBiasSources()
*/
void removeBiasSource(int which);
/**
* Remove all bias sources from the map.
*
* @see removeBiasSource()
*/
void removeAllBiasSources();
/**
* Provides a list of all the bias sources in the map.
*/
BiasSources const &biasSources() const;
/**
* Returns the total number of bias sources in the map.
*/
inline int biasSourceCount() const { return biasSources().count(); }
/**
* Returns the time in milliseconds when the current render frame began. Used
* for interpolation purposes.
*/
uint biasCurrentTime() const;
/**
* Returns the frameCount of the current render frame. Used for tracking changes
* to bias sources/surfaces.
*/
uint biasLastChangeOnFrame() const;
/**
* Lookup a bias source in the map by it's unique @a index.
*/
BiasSource *biasSource(int index) const;
/**
* Finds the bias source nearest to the specified map space @a point.
*
* @note This result is not cached. May return @c 0 if no bias sources exist.
*/
BiasSource *biasSourceNear(Vector3d const &point) const;
/**
* Lookup the unique index for the given bias @a source.
*/
int toIndex(BiasSource const &source) const;
/**
* Deletes hidden, unpredictable or nulled mobjs for which we have not received
* updates in a while.
*/
void expireClMobjs();
/**
* Link the given @a surface in all material lists and surface sets which
* the map maintains to improve performance. Only surfaces attributed to
* the map will be linked (alien surfaces are ignored).
*
* @param surface The surface to be linked.
*/
void linkInMaterialLists(Surface *surface);
/**
* Unlink the given @a surface in all material lists and surface sets which
* the map maintains to improve performance.
*
* @note The material currently attributed to the surface does not matter
* for unlinking purposes and the surface will be unlinked from all lists
* regardless.
*
* @param surface The surface to be unlinked.
*/
void unlinkInMaterialLists(Surface *surface);
/**
* Returns the set of scrolling surfaces for the map.
*/
SurfaceSet /*const*/ &scrollingSurfaces();
/**
* $smoothmatoffset: Roll the surface material offset tracker buffers.
*/
void updateScrollingSurfaces();
/**
* Returns the set of tracked planes for the map.
*/
PlaneSet /*const*/ &trackedPlanes();
/**
* $smoothplane: Roll the height tracker buffers.
*/
void updateTrackedPlanes();
/**
* Returns @c true iff a LightGrid has been initialized for the map.
*
* @see lightGrid()
*/
bool hasLightGrid();
/**
* Provides access to the light grid for the map.
*
* @see hasLightGrid()
*/
LightGrid &lightGrid();
/**
* (Re)-initialize the light grid used for smoothed sector lighting.
*
* If the grid has not yet been initialized block light sources are determined
* at this time (SectorClusters must be built for this).
*
* If the grid has already been initialized calling this will perform a full update.
*
* @note Initialization may take some time depending on the complexity of the
* map (physial dimensions, number of sectors) and should therefore be done
* "off-line".
*/
void initLightGrid();
/**
* Perform spreading of all contacts in the specified map space @a region.
*/
void spreadAllContacts(AABoxd const ®ion);
#endif // __CLIENT__
public:
/**
* To be called to register the commands and variables of this module.
*/
static void consoleRegister();
/**
* To be called to initialize the dummy element arrays (which are used with
* the DMU API), with a fixed number of @em shared dummies.
*/
static void initDummies();
#ifdef __CLIENT__
protected:
/// Observes WorldSystem FrameBegin
void worldSystemFrameBegins(bool resetNextViewer);
#endif // __CLIENT__
public: /// @todo Make private:
/**
* Initialize the node piles and link rings. To be called after map load.
*/
void initNodePiles();
/**
* Initialize all polyobjs in the map. To be called after map load.
*/
void initPolyobjs();
#ifdef __CLIENT__
/**
* Fixing the sky means that for adjacent sky sectors the lower sky
* ceiling is lifted to match the upper sky. The raising only affects
* rendering, it has no bearing on gameplay.
*/
void initSkyFix();
/**
* Rebuild the surface material lists. To be called when a full update is
* necessary.
*/
void buildMaterialLists();
/**
* Initializes bias lighting for the map. New light sources are initialized
* from the loaded Light definitions. Map surfaces are prepared for tracking
* rays.
*
* Must be called before rendering a frame with bias lighting enabled.
*/
void initBias();
/**
* Initialize the map object => BSP leaf "contact" blockmaps.
*/
void initContactBlockmaps();
/**
* Spawn all generators for the map which should be initialized automatically
* during map setup.
*/
void initGenerators();
/**
* Attempt to spawn all flat-triggered particle generators for the map.
* To be called after map setup is completed.
*
* @note Cannot presently be done in @ref initGenerators() as this is called
* during initial Map load and before any saved game has been loaded.
*/
void spawnPlaneParticleGens();
/**
* Destroys all clientside clmobjs in the map. To be called when a network
* game ends.
*/
void clearClMobjs();
/**
* Find/create a client mobj with the unique identifier @a id. Client mobjs are
* just like normal mobjs, except they have additional network state.
*
* To check whether a given mobj is a client mobj, use Cl_IsClientMobj(). The network
* state can then be accessed with ClMobj_GetInfo().
*
* @param id Identifier of the client mobj. Every client mobj has a unique
* identifier.
*
* @return Pointer to the gameside mobj.
*/
mobj_t *clMobjFor(thid_t id, bool canCreate = false) const;
/**
* Iterate all client mobjs, making a callback for each. Iteration ends if a
* callback returns a non-zero value.
*
* @param callback Function to callback for each client mobj.
* @param context Data pointer passed to the callback.
*
* @return @c 0 if all callbacks return @c 0; otherwise the result of the last.
*/
int clMobjIterator(int (*callback) (mobj_t *, void *), void *context = 0);
/**
* Provides readonly access to the client mobj hash.
*/
ClMobjHash const &clMobjHash() const;
#endif // __CLIENT__
/**
* Returns a rich formatted, textual summary of the map's elements, suitable
* for logging.
*/
de::String elementSummaryAsStyledText() const;
/**
* Returns a rich formatted, textual summary of the map's objects, suitable
* for logging.
*/
de::String objectSummaryAsStyledText() const;
public:
/*
* Runtime map editing:
*/
/**
* Returns @c true iff the map is currently in an editable state.
*/
bool isEditable() const;
/**
* Switch the map from editable to non-editable (i.e., playable) state,
* incorporating any new map elements, (re)building the BSP, etc...
*
* @return @c true= mode switch was completed successfully.
*/
bool endEditing();
/**
* @see isEditable()
*/
Vertex *createVertex(Vector2d const &origin,
int archiveIndex = MapElement::NoIndex);
/**
* @see isEditable()
*/
Line *createLine(Vertex &v1, Vertex &v2, int flags = 0,
Sector *frontSector = 0, Sector *backSector = 0,
int archiveIndex = MapElement::NoIndex);
/**
* @see isEditable()
*/
Polyobj *createPolyobj(Vector2d const &origin);
/**
* @see isEditable()
*/
Sector *createSector(float lightLevel, Vector3f const &lightColor,
int archiveIndex = MapElement::NoIndex);
/**
* Provides a list of all the editable lines in the map.
*/
Lines const &editableLines() const;
/**
* Provides a list of all the editable polyobjs in the map.
*/
Polyobjs const &editablePolyobjs() const;
/**
* Provides a list of all the editable sectors in the map.
*/
Sectors const &editableSectors() const;
inline int editableLineCount() const { return editableLines().count(); }
inline int editablePolyobjCount() const { return editablePolyobjs().count(); }
inline int editableSectorCount() const { return editableSectors().count(); }
private:
DENG2_PRIVATE(d)
};
} // namespace de
#endif // DENG_WORLD_MAP_H