]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/ufoaiplug/ufoai_filters.cpp
clang: fix build. Still doesn't work right
[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 public:
94     mutable int m_contentFlagsVis;
95     mutable int m_surfaceFlagsVis;
96
97     ForEachFace()
98     {
99         m_contentFlagsVis = -1;
100         m_surfaceFlagsVis = -1;
101     }
102
103     void visit(Face &face) const
104     {
105 #if GDEF_DEBUG
106         if (m_surfaceFlagsVis < 0) {
107             m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
108         } else if (m_surfaceFlagsVis >= 0 && m_surfaceFlagsVis != face.getShader().m_flags.m_surfaceFlags) {
109             globalOutputStream() << "Faces with different surfaceflags at brush\n";
110         }
111         if (m_contentFlagsVis < 0) {
112             m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
113         } else if (m_contentFlagsVis >= 0 && m_contentFlagsVis != face.getShader().m_flags.m_contentFlags) {
114             globalOutputStream() << "Faces with different contentflags at brush\n";
115         }
116 #else
117         m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
118         m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
119 #endif
120     }
121 };
122
123 typedef std::list<Brush *> brushlist_t;
124
125 class BrushGetLevel : public scene::Graph::Walker {
126     brushlist_t &m_brushlist;
127     int m_flag;
128     bool m_content;     // if true - use m_contentFlags - otherwise m_surfaceFlags
129     mutable bool m_notset;
130     mutable bool m_hide;
131 public:
132     BrushGetLevel(brushlist_t &brushlist, int flag, bool content, bool notset, bool hide)
133             : m_brushlist(brushlist), m_flag(flag), m_content(content), m_notset(notset), m_hide(hide)
134     {
135     }
136
137     bool pre(const scene::Path &path, scene::Instance &instance) const
138     {
139         Brush *brush = Node_getBrush(path.top());
140         if (brush != 0) {
141             ForEachFace faces{};
142             brush->forEachFace(faces);
143             // contentflags?
144             if (m_content) {
145                 // are any flags set?
146                 if (faces.m_contentFlagsVis > 0) {
147                     // flag should not be set
148                     if (m_notset && (!(faces.m_contentFlagsVis & m_flag))) {
149                         hide_node(path.top(), m_hide);
150                         m_brushlist.push_back(brush);
151                     }
152                         // check whether flag is set
153                     else if (!m_notset && ((faces.m_contentFlagsVis & m_flag))) {
154                         hide_node(path.top(), m_hide);
155                         m_brushlist.push_back(brush);
156                     }
157                 }
158             }
159                 // surfaceflags?
160             else {
161                 // are any flags set?
162                 if (faces.m_surfaceFlagsVis > 0) {
163                     // flag should not be set
164                     if (m_notset && (!(faces.m_surfaceFlagsVis & m_flag))) {
165                         hide_node(path.top(), m_hide);
166                         m_brushlist.push_back(brush);
167                     }
168                         // check whether flag is set
169                     else if (!m_notset && ((faces.m_surfaceFlagsVis & m_flag))) {
170                         hide_node(path.top(), m_hide);
171                         m_brushlist.push_back(brush);
172                     }
173                 }
174             }
175
176         }
177         return true;
178     }
179 };
180
181 /**
182  * @brief Activates the level filter for the given level
183  * @param[in] level Which level to show?
184  * @todo Entities
185  */
186 void filter_level(int flag)
187 {
188     int level;
189     brushlist_t brushes;
190     entitylist_t entities;
191
192     level = (flag >> 8);
193
194     if (level_active) {
195         GlobalSceneGraph().traverse(BrushGetLevel(brushes, (level_active << 8), true, true, false));
196         GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level_active, false));
197         GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level_active, false));
198         GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level_active, false));
199         GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level_active, false));
200         entities.erase(entities.begin(), entities.end());
201         brushes.erase(brushes.begin(), brushes.end());
202         if (level_active == level) {
203             level_active = 0;
204             // just disabĺe level filter
205             return;
206         }
207     }
208     level_active = level;
209     globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n";
210
211     // first all brushes
212     GlobalSceneGraph().traverse(BrushGetLevel(brushes, flag, true, true, true));
213
214     // now all entities
215     GlobalSceneGraph().traverse(EntityFindByName("func_door", entities, level, true));
216     GlobalSceneGraph().traverse(EntityFindByName("func_breakable", entities, level, true));
217     GlobalSceneGraph().traverse(EntityFindByName("misc_model", entities, level, true));
218     GlobalSceneGraph().traverse(EntityFindByName("misc_particle", entities, level, true));
219
220 #if GDEF_DEBUG
221     if (brushes.empty()) {
222         globalOutputStream() << "UFO:AI: No brushes.\n";
223     } else {
224         globalOutputStream() << "UFO:AI: Found " << Unsigned(brushes.size()) << " brushes.\n";
225     }
226
227     // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set
228     if (entities.empty()) {
229         globalOutputStream() << "UFO:AI: No entities.\n";
230     } else {
231         globalOutputStream() << "UFO:AI: Found " << Unsigned(entities.size()) << " entities.\n";
232     }
233 #endif
234 }
235
236 void filter_stepon(void)
237 {
238     if (stepon_active) {
239         stepon_active = false;
240     } else {
241         stepon_active = true;
242     }
243     brushlist_t brushes;
244     GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_STEPON, true, false, stepon_active));
245
246     if (brushes.empty()) {
247         globalOutputStream() << "UFO:AI: No brushes.\n";
248     } else {
249         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " stepon brushes.\n";
250     }
251 }
252
253 void filter_nodraw(void)
254 {
255     if (nodraw_active) {
256         nodraw_active = false;
257     } else {
258         nodraw_active = true;
259     }
260     brushlist_t brushes;
261     GlobalSceneGraph().traverse(BrushGetLevel(brushes, SURF_NODRAW, false, false, nodraw_active));
262
263 #if GDEF_DEBUG
264     if (brushes.empty()) {
265         globalOutputStream() << "UFO:AI: No brushes.\n";
266     } else {
267         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " nodraw brushes.\n";
268     }
269 #endif
270 }
271
272 void filter_actorclip(void)
273 {
274     if (actorclip_active) {
275         actorclip_active = false;
276     } else {
277         actorclip_active = true;
278     }
279     brushlist_t brushes;
280     GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active));
281
282 #if GDEF_DEBUG
283     if (brushes.empty()) {
284         globalOutputStream() << "UFO:AI: No brushes.\n";
285     } else {
286         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " actorclip brushes.\n";
287     }
288 #endif
289 }
290
291 void filter_weaponclip(void)
292 {
293     if (weaponclip_active) {
294         weaponclip_active = false;
295     } else {
296         weaponclip_active = true;
297     }
298     brushlist_t brushes;
299     GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active));
300
301 #if GDEF_DEBUG
302     if (brushes.empty()) {
303         globalOutputStream() << "UFO:AI: No brushes.\n";
304     } else {
305         globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " weaponclip brushes.\n";
306     }
307 #endif
308 }