]> icculus.org git repositories - divverent/netradiant.git/blob - contrib/ufoaiplug/ufoai_filters.cpp
256 surfaceparms
[divverent/netradiant.git] / contrib / ufoaiplug / ufoai_filters.cpp
1 /*
2 This file is part of GtkRadiant.
3
4 GtkRadiant is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 GtkRadiant is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GtkRadiant; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include "ufoai_filters.h"
20
21 #include "ibrush.h"
22 #include "ientity.h"
23 #include "iscenegraph.h"
24
25 // believe me, i'm sorry
26 #include "../../radiant/brush.h"
27
28 #include "generic/callback.h"
29
30 #include <list>
31
32 bool actorclip_active = false;
33 bool stepon_active = false;
34 bool nodraw_active = false;
35 bool weaponclip_active = false;
36 int level_active = 0;
37
38 // TODO: This should be added to ibrush.h
39 // like already done for Node_getEntity in ientity.h
40 // FIXME: Doesn't belong here
41 inline Brush* Node_getBrush(scene::Node& node)
42 {
43         return NodeTypeCast<Brush>::cast(node);
44 }
45
46 void hide_node(scene::Node& node, bool hide)
47 {
48         hide
49         ? node.enable(scene::Node::eHidden)
50         : node.disable(scene::Node::eHidden);
51 }
52
53 typedef std::list<Entity*> entitylist_t;
54
55 class EntityFindByName : public scene::Graph::Walker
56 {
57         const char* m_name;
58         entitylist_t& m_entitylist;
59         /* this starts at 1 << level */
60         int m_flag;
61         int m_hide;
62 public:
63         EntityFindByName(const char* name, entitylist_t& entitylist, int flag, bool hide)
64                 : m_name(name), m_entitylist(entitylist), m_flag(flag), m_hide(hide)
65         {
66         }
67         bool pre(const scene::Path& path, scene::Instance& instance) const
68         {
69                 int spawnflagsInt;
70                 Entity* entity = Node_getEntity(path.top());
71                 if (entity != 0)
72                 {
73                         if (string_equal(m_name, entity->getKeyValue("classname")))
74                         {
75                                 const char *spawnflags = entity->getKeyValue("spawnflags");
76                                 globalOutputStream() << "spawnflags for " << m_name << ": " << spawnflags << ".\n";
77
78                                 if (!string_empty(spawnflags)) {
79                                         spawnflagsInt = atoi(spawnflags);
80                                         if (!(spawnflagsInt & m_flag))
81                                         {
82                                                 hide_node(path.top(), m_hide); // hide/unhide
83                                                 m_entitylist.push_back(entity);
84                                         }
85                                 }
86                                 else
87                                 {
88                                         globalOutputStream() << "UFO:AI: Warning: no spawnflags for " << m_name << ".\n";
89                                 }
90                         }
91                 }
92                 return true;
93         }
94 };
95
96 class ForEachFace : public BrushVisitor
97 {
98         Brush &m_brush;
99 public:
100         mutable int m_contentFlagsVis;
101         mutable int m_surfaceFlagsVis;
102
103         ForEachFace(Brush& brush)
104                 : m_brush(brush)
105         {
106                 m_contentFlagsVis = -1;
107                 m_surfaceFlagsVis = -1;
108         }
109
110         void visit(Face& face) const
111         {
112 #if _DEBUG
113                 if (m_surfaceFlagsVis < 0)
114                         m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
115                 else if (m_surfaceFlagsVis >= 0 && m_surfaceFlagsVis != face.getShader().m_flags.m_surfaceFlags)
116                         globalOutputStream() << "Faces with different surfaceflags at brush\n";
117                 if (m_contentFlagsVis < 0)
118                         m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
119                 else if (m_contentFlagsVis >= 0 && m_contentFlagsVis != face.getShader().m_flags.m_contentFlags)
120                         globalOutputStream() << "Faces with different contentflags at brush\n";
121 #else
122                 m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
123                 m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
124 #endif
125         }
126 };
127
128 typedef std::list<Brush*> brushlist_t;
129
130 class BrushGetLevel : public scene::Graph::Walker
131 {
132         brushlist_t& m_brushlist;
133         int m_flag;
134         bool m_content; // if true - use m_contentFlags - otherwise m_surfaceFlags
135         mutable bool m_notset;
136         mutable bool m_hide;
137 public:
138         BrushGetLevel(brushlist_t& brushlist, int flag, bool content, bool notset, bool hide)
139                 : m_brushlist(brushlist), m_flag(flag), m_content(content), m_notset(notset), m_hide(hide)
140         {
141         }
142         bool pre(const scene::Path& path, scene::Instance& instance) const
143         {
144                 Brush* brush = Node_getBrush(path.top());
145                 if (brush != 0)
146                 {
147                         ForEachFace faces(*brush);
148                         brush->forEachFace(faces);
149                         // contentflags?
150                         if (m_content)
151                         {
152                                 // are any flags set?
153                                 if (faces.m_contentFlagsVis > 0)
154                                 {
155                                         // flag should not be set
156                                         if (m_notset && (!(faces.m_contentFlagsVis & m_flag)))
157                                         {
158                                                 hide_node(path.top(), m_hide);
159                                                 m_brushlist.push_back(brush);
160                                         }
161                                         // check whether flag is set
162                                         else if (!m_notset && ((faces.m_contentFlagsVis & m_flag)))
163                                         {
164                                                 hide_node(path.top(), m_hide);
165                                                 m_brushlist.push_back(brush);
166                                         }
167                                 }
168                         }
169                         // surfaceflags?
170                         else
171                         {
172                                 // are any flags set?
173                                 if (faces.m_surfaceFlagsVis > 0)
174                                 {
175                                         // flag should not be set
176                                         if (m_notset && (!(faces.m_surfaceFlagsVis & m_flag)))
177                                         {
178                                                 hide_node(path.top(), m_hide);
179                                                 m_brushlist.push_back(brush);
180                                         }
181                                         // check whether flag is set
182                                         else if (!m_notset && ((faces.m_surfaceFlagsVis & m_flag)))
183                                         {
184                                                 hide_node(path.top(), m_hide);
185                                                 m_brushlist.push_back(brush);
186                                         }
187                                 }
188                         }
189
190                 }
191                 return true;
192         }
193 };
194
195 /**
196  * @brief Activates the level filter for the given level
197  * @param[in] level Which level to show?
198  * @todo Entities
199  */
200 void filter_level(int flag)
201 {
202         int level;
203         brushlist_t brushes;
204         entitylist_t entities;
205
206         level = (flag >> 8);
207
208         if (level_active)
209         {
210                 GlobalSceneGraph().traverse(BrushGetLevel(brushes, (level_active << 8), true, true, false));
211                 GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level_active, false));
212                 GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level_active, false));
213                 GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level_active, false));
214                 GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level_active, false));
215                 entities.erase(entities.begin(), entities.end());
216                 brushes.erase(brushes.begin(), brushes.end());
217                 if (level_active == level)
218                 {
219                         level_active = 0;
220                         // just disabĺe level filter
221                         return;
222                 }
223         }
224         level_active = level;
225         globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n";
226
227         // first all brushes
228         GlobalSceneGraph().traverse(BrushGetLevel(brushes, flag, true, true, true));
229
230         // now all entities
231         GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level, true));
232         GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level, true));
233         GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level, true));
234         GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level, true));
235
236 #ifdef _DEBUG
237         if (brushes.empty())
238         {
239                 globalOutputStream() << "UFO:AI: No brushes.\n";
240         }
241         else
242         {
243                 globalOutputStream() << "UFO:AI: Found " << Unsigned(brushes.size()) << " brushes.\n";
244         }
245
246         // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set
247         if (entities.empty())
248         {
249                 globalOutputStream() << "UFO:AI: No entities.\n";
250         }
251         else
252         {
253                 globalOutputStream() << "UFO:AI: Found " << Unsigned(entities.size()) << " entities.\n";
254         }
255 #endif
256 }
257
258 void filter_stepon (void)
259 {
260         if (stepon_active) {
261                 stepon_active = false;
262         } else {
263                 stepon_active = true;
264         }
265         brushlist_t brushes;
266         GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_STEPON, true, false, stepon_active));
267
268         if (brushes.empty())
269         {
270                 globalOutputStream() << "UFO:AI: No brushes.\n";
271         }
272         else
273         {
274                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " stepon brushes.\n";
275         }
276 }
277
278 void filter_nodraw (void)
279 {
280         if (nodraw_active) {
281                 nodraw_active = false;
282         } else {
283                 nodraw_active = true;
284         }
285         brushlist_t brushes;
286         GlobalSceneGraph().traverse(BrushGetLevel(brushes, SURF_NODRAW, false, false, nodraw_active));
287
288 #ifdef _DEBUG
289         if (brushes.empty())
290         {
291                 globalOutputStream() << "UFO:AI: No brushes.\n";
292         }
293         else
294         {
295                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " nodraw brushes.\n";
296         }
297 #endif
298 }
299
300 void filter_actorclip (void)
301 {
302         if (actorclip_active) {
303                 actorclip_active = false;
304         } else {
305                 actorclip_active = true;
306         }
307         brushlist_t brushes;
308         GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active));
309
310 #ifdef _DEBUG
311         if (brushes.empty())
312         {
313                 globalOutputStream() << "UFO:AI: No brushes.\n";
314         }
315         else
316         {
317                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " actorclip brushes.\n";
318         }
319 #endif
320 }
321
322 void filter_weaponclip (void)
323 {
324         if (weaponclip_active) {
325                 weaponclip_active = false;
326         } else {
327                 weaponclip_active = true;
328         }
329         brushlist_t brushes;
330         GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active));
331
332 #ifdef _DEBUG
333         if (brushes.empty())
334         {
335                 globalOutputStream() << "UFO:AI: No brushes.\n";
336         }
337         else
338         {
339                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " weaponclip brushes.\n";
340         }
341 #endif
342 }