]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/ufoaiplug/ufoai_filters.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/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 #include "globaldefs.h"
21
22 #include "ibrush.h"
23 #include "ientity.h"
24 #include "iscenegraph.h"
25
26 // believe me, i'm sorry
27 #include "../../radiant/brush.h"
28
29 #include "generic/callback.h"
30
31 #include <list>
32
33 bool actorclip_active = false;
34 bool stepon_active = false;
35 bool nodraw_active = false;
36 bool weaponclip_active = false;
37 int level_active = 0;
38
39 // TODO: This should be added to ibrush.h
40 // like already done for Node_getEntity in ientity.h
41 // FIXME: Doesn't belong here
42 inline Brush *Node_getBrush(scene::Node &node)
43 {
44     return NodeTypeCast<Brush>::cast(node);
45 }
46
47 void hide_node(scene::Node &node, bool hide)
48 {
49     hide
50     ? node.enable(scene::Node::eHidden)
51     : node.disable(scene::Node::eHidden);
52 }
53
54 typedef std::list<Entity *> entitylist_t;
55
56 class EntityFindByName : public scene::Graph::Walker {
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
68     bool pre(const scene::Path &path, scene::Instance &instance) const
69     {
70         int spawnflagsInt;
71         Entity *entity = Node_getEntity(path.top());
72         if (entity != 0) {
73             if (string_equal(m_name, entity->getKeyValue("classname"))) {
74                 const char *spawnflags = entity->getKeyValue("spawnflags");
75                 globalOutputStream() << "spawnflags for " << m_name << ": " << spawnflags << ".\n";
76
77                 if (!string_empty(spawnflags)) {
78                     spawnflagsInt = atoi(spawnflags);
79                     if (!(spawnflagsInt & m_flag)) {
80                         hide_node(path.top(), m_hide);   // hide/unhide
81                         m_entitylist.push_back(entity);
82                     }
83                 } else {
84                     globalOutputStream() << "UFO:AI: Warning: no spawnflags for " << m_name << ".\n";
85                 }
86             }
87         }
88         return true;
89     }
90 };
91
92 class ForEachFace : public BrushVisitor {
93     Brush &m_brush;
94 public:
95     mutable int m_contentFlagsVis;
96     mutable int m_surfaceFlagsVis;
97
98     ForEachFace(Brush &brush)
99             : m_brush(brush)
100     {
101         m_contentFlagsVis = -1;
102         m_surfaceFlagsVis = -1;
103     }
104
105     void visit(Face &face) const
106     {
107 #if GDEF_DEBUG
108         if (m_surfaceFlagsVis < 0) {
109             m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
110         } else if (m_surfaceFlagsVis >= 0 && m_surfaceFlagsVis != face.getShader().m_flags.m_surfaceFlags) {
111             globalOutputStream() << "Faces with different surfaceflags at brush\n";
112         }
113         if (m_contentFlagsVis < 0) {
114             m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
115         } else if (m_contentFlagsVis >= 0 && m_contentFlagsVis != face.getShader().m_flags.m_contentFlags) {
116             globalOutputStream() << "Faces with different contentflags at brush\n";
117         }
118 #else
119         m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
120         m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
121 #endif
122     }
123 };
124
125 typedef std::list<Brush *> brushlist_t;
126
127 class BrushGetLevel : public scene::Graph::Walker {
128     brushlist_t &m_brushlist;
129     int m_flag;
130     bool m_content;     // if true - use m_contentFlags - otherwise m_surfaceFlags
131     mutable bool m_notset;
132     mutable bool m_hide;
133 public:
134     BrushGetLevel(brushlist_t &brushlist, int flag, bool content, bool notset, bool hide)
135             : m_brushlist(brushlist), m_flag(flag), m_content(content), m_notset(notset), m_hide(hide)
136     {
137     }
138
139     bool pre(const scene::Path &path, scene::Instance &instance) const
140     {
141         Brush *brush = Node_getBrush(path.top());
142         if (brush != 0) {
143             ForEachFace faces(*brush);
144             brush->forEachFace(faces);
145             // contentflags?
146             if (m_content) {
147                 // are any flags set?
148                 if (faces.m_contentFlagsVis > 0) {
149                     // flag should not be set
150                     if (m_notset && (!(faces.m_contentFlagsVis & m_flag))) {
151                         hide_node(path.top(), m_hide);
152                         m_brushlist.push_back(brush);
153                     }
154                         // check whether flag is set
155                     else if (!m_notset && ((faces.m_contentFlagsVis & m_flag))) {
156                         hide_node(path.top(), m_hide);
157                         m_brushlist.push_back(brush);
158                     }
159                 }
160             }
161                 // surfaceflags?
162             else {
163                 // are any flags set?
164                 if (faces.m_surfaceFlagsVis > 0) {
165                     // flag should not be set
166                     if (m_notset && (!(faces.m_surfaceFlagsVis & m_flag))) {
167                         hide_node(path.top(), m_hide);
168                         m_brushlist.push_back(brush);
169                     }
170                         // check whether flag is set
171                     else if (!m_notset && ((faces.m_surfaceFlagsVis & m_flag))) {
172                         hide_node(path.top(), m_hide);
173                         m_brushlist.push_back(brush);
174                     }
175                 }
176             }
177
178         }
179         return true;
180     }
181 };
182
183 /**
184  * @brief Activates the level filter for the given level
185  * @param[in] level Which level to show?
186  * @todo Entities
187  */
188 void filter_level(int flag)
189 {
190     int level;
191     brushlist_t brushes;
192     entitylist_t entities;
193
194     level = (flag >> 8);
195
196     if (level_active) {
197         GlobalSceneGraph().traverse(BrushGetLevel(brushes, (level_active << 8), true, true, false));
198         GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level_active, false));
199         GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level_active, false));
200         GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level_active, false));
201         GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level_active, false));
202         entities.erase(entities.begin(), entities.end());
203         brushes.erase(brushes.begin(), brushes.end());
204         if (level_active == level) {
205             level_active = 0;
206             // just disabĺe level filter
207             return;
208         }
209     }
210     level_active = level;
211     globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n";
212
213     // first all brushes
214     GlobalSceneGraph().traverse(BrushGetLevel(brushes, flag, true, true, true));
215
216     // now all entities
217     GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level, true));
218     GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level, true));
219     GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level, true));
220     GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level, true));
221
222 #if GDEF_DEBUG
223     if (brushes.empty()) {
224         globalOutputStream() << "UFO:AI: No brushes.\n";
225     } else {
226         globalOutputStream() << "UFO:AI: Found " << Unsigned(brushes.size()) << " brushes.\n";
227     }
228
229     // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set
230     if (entities.empty()) {
231         globalOutputStream() << "UFO:AI: No entities.\n";
232     } else {
233         globalOutputStream() << "UFO:AI: Found " << Unsigned(entities.size()) << " entities.\n";
234     }
235 #endif
236 }
237
238 void filter_stepon(void)
239 {
240     if (stepon_active) {
241         stepon_active = false;
242     } else {
243         stepon_active = true;
244     }
245     brushlist_t brushes;
246     GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_STEPON, true, false, stepon_active));
247
248     if (brushes.empty()) {
249         globalOutputStream() << "UFO:AI: No brushes.\n";
250     } else {
251         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " stepon brushes.\n";
252     }
253 }
254
255 void filter_nodraw(void)
256 {
257     if (nodraw_active) {
258         nodraw_active = false;
259     } else {
260         nodraw_active = true;
261     }
262     brushlist_t brushes;
263     GlobalSceneGraph().traverse(BrushGetLevel(brushes, SURF_NODRAW, false, false, nodraw_active));
264
265 #if GDEF_DEBUG
266     if (brushes.empty()) {
267         globalOutputStream() << "UFO:AI: No brushes.\n";
268     } else {
269         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " nodraw brushes.\n";
270     }
271 #endif
272 }
273
274 void filter_actorclip(void)
275 {
276     if (actorclip_active) {
277         actorclip_active = false;
278     } else {
279         actorclip_active = true;
280     }
281     brushlist_t brushes;
282     GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active));
283
284 #if GDEF_DEBUG
285     if (brushes.empty()) {
286         globalOutputStream() << "UFO:AI: No brushes.\n";
287     } else {
288         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " actorclip brushes.\n";
289     }
290 #endif
291 }
292
293 void filter_weaponclip(void)
294 {
295     if (weaponclip_active) {
296         weaponclip_active = false;
297     } else {
298         weaponclip_active = true;
299     }
300     brushlist_t brushes;
301     GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active));
302
303 #if GDEF_DEBUG
304     if (brushes.empty()) {
305         globalOutputStream() << "UFO:AI: No brushes.\n";
306     } else {
307         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " weaponclip brushes.\n";
308     }
309 #endif
310 }