2 This file is part of GtkRadiant.
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.
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.
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
19 #include "ufoai_filters.h"
23 #include "iscenegraph.h"
25 // believe me, i'm sorry
26 #include "../../radiant/brush.h"
28 #include "generic/callback.h"
32 bool actorclip_active = false;
33 bool stepon_active = false;
34 bool nodraw_active = false;
35 bool weaponclip_active = false;
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)
43 return NodeTypeCast<Brush>::cast(node);
46 void hide_node(scene::Node& node, bool hide)
49 ? node.enable(scene::Node::eHidden)
50 : node.disable(scene::Node::eHidden);
53 typedef std::list<Entity*> entitylist_t;
55 class EntityFindByName : public scene::Graph::Walker
58 entitylist_t& m_entitylist;
59 /* this starts at 1 << level */
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)
67 bool pre(const scene::Path& path, scene::Instance& instance) const
70 Entity* entity = Node_getEntity(path.top());
73 if (string_equal(m_name, entity->getKeyValue("classname")))
75 const char *spawnflags = entity->getKeyValue("spawnflags");
76 globalOutputStream() << "spawnflags for " << m_name << ": " << spawnflags << ".\n";
78 if (!string_empty(spawnflags)) {
79 spawnflagsInt = atoi(spawnflags);
80 if (!(spawnflagsInt & m_flag))
82 hide_node(path.top(), m_hide); // hide/unhide
83 m_entitylist.push_back(entity);
88 globalOutputStream() << "UFO:AI: Warning: no spawnflags for " << m_name << ".\n";
96 class ForEachFace : public BrushVisitor
100 mutable int m_contentFlagsVis;
101 mutable int m_surfaceFlagsVis;
103 ForEachFace(Brush& brush)
106 m_contentFlagsVis = -1;
107 m_surfaceFlagsVis = -1;
110 void visit(Face& face) const
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";
122 m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
123 m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
128 typedef std::list<Brush*> brushlist_t;
130 class BrushGetLevel : public scene::Graph::Walker
132 brushlist_t& m_brushlist;
134 bool m_content; // if true - use m_contentFlags - otherwise m_surfaceFlags
135 mutable bool m_notset;
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)
142 bool pre(const scene::Path& path, scene::Instance& instance) const
144 Brush* brush = Node_getBrush(path.top());
147 ForEachFace faces(*brush);
148 brush->forEachFace(faces);
152 // are any flags set?
153 if (faces.m_contentFlagsVis > 0)
155 // flag should not be set
156 if (m_notset && (!(faces.m_contentFlagsVis & m_flag)))
158 hide_node(path.top(), m_hide);
159 m_brushlist.push_back(brush);
161 // check whether flag is set
162 else if (!m_notset && ((faces.m_contentFlagsVis & m_flag)))
164 hide_node(path.top(), m_hide);
165 m_brushlist.push_back(brush);
172 // are any flags set?
173 if (faces.m_surfaceFlagsVis > 0)
175 // flag should not be set
176 if (m_notset && (!(faces.m_surfaceFlagsVis & m_flag)))
178 hide_node(path.top(), m_hide);
179 m_brushlist.push_back(brush);
181 // check whether flag is set
182 else if (!m_notset && ((faces.m_surfaceFlagsVis & m_flag)))
184 hide_node(path.top(), m_hide);
185 m_brushlist.push_back(brush);
196 * @brief Activates the level filter for the given level
197 * @param[in] level Which level to show?
200 void filter_level(int flag)
204 entitylist_t entities;
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)
220 // just disabĺe level filter
224 level_active = level;
225 globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n";
228 GlobalSceneGraph().traverse(BrushGetLevel(brushes, flag, true, true, true));
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));
239 globalOutputStream() << "UFO:AI: No brushes.\n";
243 globalOutputStream() << "UFO:AI: Found " << Unsigned(brushes.size()) << " brushes.\n";
246 // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set
247 if (entities.empty())
249 globalOutputStream() << "UFO:AI: No entities.\n";
253 globalOutputStream() << "UFO:AI: Found " << Unsigned(entities.size()) << " entities.\n";
258 void filter_stepon (void)
261 stepon_active = false;
263 stepon_active = true;
266 GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_STEPON, true, false, stepon_active));
270 globalOutputStream() << "UFO:AI: No brushes.\n";
274 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " stepon brushes.\n";
278 void filter_nodraw (void)
281 nodraw_active = false;
283 nodraw_active = true;
286 GlobalSceneGraph().traverse(BrushGetLevel(brushes, SURF_NODRAW, false, false, nodraw_active));
291 globalOutputStream() << "UFO:AI: No brushes.\n";
295 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " nodraw brushes.\n";
300 void filter_actorclip (void)
302 if (actorclip_active) {
303 actorclip_active = false;
305 actorclip_active = true;
308 GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active));
313 globalOutputStream() << "UFO:AI: No brushes.\n";
317 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " actorclip brushes.\n";
322 void filter_weaponclip (void)
324 if (weaponclip_active) {
325 weaponclip_active = false;
327 weaponclip_active = true;
330 GlobalSceneGraph().traverse(BrushGetLevel(brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active));
335 globalOutputStream() << "UFO:AI: No brushes.\n";
339 globalOutputStream() << "UFO:AI: Hiding " << Unsigned(brushes.size()) << " weaponclip brushes.\n";