]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/ufoaiplug/ufoai_filters.cpp
netradiant: strip 16-bit png to 8-bit, fix #153
[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         return NodeTypeCast<Brush>::cast( node );
44 }
45
46 void hide_node( scene::Node& node, bool hide ){
47         hide
48         ? node.enable( scene::Node::eHidden )
49         : node.disable( scene::Node::eHidden );
50 }
51
52 typedef std::list<Entity*> entitylist_t;
53
54 class EntityFindByName : public scene::Graph::Walker
55 {
56 const char* m_name;
57 entitylist_t& m_entitylist;
58 /* this starts at 1 << level */
59 int m_flag;
60 int m_hide;
61 public:
62 EntityFindByName( const char* name, entitylist_t& entitylist, int flag, bool hide )
63         : m_name( name ), m_entitylist( entitylist ), m_flag( flag ), m_hide( hide ){
64 }
65 bool pre( const scene::Path& path, scene::Instance& instance ) const {
66         int spawnflagsInt;
67         Entity* entity = Node_getEntity( path.top() );
68         if ( entity != 0 ) {
69                 if ( string_equal( m_name, entity->getKeyValue( "classname" ) ) ) {
70                         const char *spawnflags = entity->getKeyValue( "spawnflags" );
71                         globalOutputStream() << "spawnflags for " << m_name << ": " << spawnflags << ".\n";
72
73                         if ( !string_empty( spawnflags ) ) {
74                                 spawnflagsInt = atoi( spawnflags );
75                                 if ( !( spawnflagsInt & m_flag ) ) {
76                                         hide_node( path.top(), m_hide );   // hide/unhide
77                                         m_entitylist.push_back( entity );
78                                 }
79                         }
80                         else
81                         {
82                                 globalOutputStream() << "UFO:AI: Warning: no spawnflags for " << m_name << ".\n";
83                         }
84                 }
85         }
86         return true;
87 }
88 };
89
90 class ForEachFace : public BrushVisitor
91 {
92 Brush &m_brush;
93 public:
94 mutable int m_contentFlagsVis;
95 mutable int m_surfaceFlagsVis;
96
97 ForEachFace( Brush& brush )
98         : m_brush( brush ){
99         m_contentFlagsVis = -1;
100         m_surfaceFlagsVis = -1;
101 }
102
103 void visit( Face& face ) const {
104 #if GDEF_DEBUG
105         if ( m_surfaceFlagsVis < 0 ) {
106                 m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
107         }
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         }
114         else if ( m_contentFlagsVis >= 0 && m_contentFlagsVis != face.getShader().m_flags.m_contentFlags ) {
115                 globalOutputStream() << "Faces with different contentflags at brush\n";
116         }
117 #else
118         m_surfaceFlagsVis = face.getShader().m_flags.m_surfaceFlags;
119         m_contentFlagsVis = face.getShader().m_flags.m_contentFlags;
120 #endif
121 }
122 };
123
124 typedef std::list<Brush*> brushlist_t;
125
126 class BrushGetLevel : public scene::Graph::Walker
127 {
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 bool pre( const scene::Path& path, scene::Instance& instance ) const {
138         Brush* brush = Node_getBrush( path.top() );
139         if ( brush != 0 ) {
140                 ForEachFace faces( *brush );
141                 brush->forEachFace( faces );
142                 // contentflags?
143                 if ( m_content ) {
144                         // are any flags set?
145                         if ( faces.m_contentFlagsVis > 0 ) {
146                                 // flag should not be set
147                                 if ( m_notset && ( !( faces.m_contentFlagsVis & m_flag ) ) ) {
148                                         hide_node( path.top(), m_hide );
149                                         m_brushlist.push_back( brush );
150                                 }
151                                 // check whether flag is set
152                                 else if ( !m_notset && ( ( faces.m_contentFlagsVis & m_flag ) ) ) {
153                                         hide_node( path.top(), m_hide );
154                                         m_brushlist.push_back( brush );
155                                 }
156                         }
157                 }
158                 // surfaceflags?
159                 else
160                 {
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         int level;
188         brushlist_t brushes;
189         entitylist_t entities;
190
191         level = ( flag >> 8 );
192
193         if ( level_active ) {
194                 GlobalSceneGraph().traverse( BrushGetLevel( brushes, ( level_active << 8 ), true, true, false ) );
195                 GlobalSceneGraph().traverse( EntityFindByName( "func_door", entities, level_active, false ) );
196                 GlobalSceneGraph().traverse( EntityFindByName( "func_breakable", entities, level_active, false ) );
197                 GlobalSceneGraph().traverse( EntityFindByName( "misc_model", entities, level_active, false ) );
198                 GlobalSceneGraph().traverse( EntityFindByName( "misc_particle", entities, level_active, false ) );
199                 entities.erase( entities.begin(), entities.end() );
200                 brushes.erase( brushes.begin(), brushes.end() );
201                 if ( level_active == level ) {
202                         level_active = 0;
203                         // just disabĺe level filter
204                         return;
205                 }
206         }
207         level_active = level;
208         globalOutputStream() << "UFO:AI: level_active: " << level_active << ", flag: " << flag << ".\n";
209
210         // first all brushes
211         GlobalSceneGraph().traverse( BrushGetLevel( brushes, flag, true, true, true ) );
212
213         // now all entities
214         GlobalSceneGraph().traverse( EntityFindByName( "func_door", entities, level, true ) );
215         GlobalSceneGraph().traverse( EntityFindByName( "func_breakable", entities, level, true ) );
216         GlobalSceneGraph().traverse( EntityFindByName( "misc_model", entities, level, true ) );
217         GlobalSceneGraph().traverse( EntityFindByName( "misc_particle", entities, level, true ) );
218
219 #if GDEF_DEBUG
220         if ( brushes.empty() ) {
221                 globalOutputStream() << "UFO:AI: No brushes.\n";
222         }
223         else
224         {
225                 globalOutputStream() << "UFO:AI: Found " << Unsigned( brushes.size() ) << " brushes.\n";
226         }
227
228         // now let's filter all entities like misc_model, func_breakable and func_door that have the spawnflags set
229         if ( entities.empty() ) {
230                 globalOutputStream() << "UFO:AI: No entities.\n";
231         }
232         else
233         {
234                 globalOutputStream() << "UFO:AI: Found " << Unsigned( entities.size() ) << " entities.\n";
235         }
236 #endif
237 }
238
239 void filter_stepon( void ){
240         if ( stepon_active ) {
241                 stepon_active = false;
242         }
243         else {
244                 stepon_active = true;
245         }
246         brushlist_t brushes;
247         GlobalSceneGraph().traverse( BrushGetLevel( brushes, CONTENTS_STEPON, true, false, stepon_active ) );
248
249         if ( brushes.empty() ) {
250                 globalOutputStream() << "UFO:AI: No brushes.\n";
251         }
252         else
253         {
254                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " stepon brushes.\n";
255         }
256 }
257
258 void filter_nodraw( void ){
259         if ( nodraw_active ) {
260                 nodraw_active = false;
261         }
262         else {
263                 nodraw_active = true;
264         }
265         brushlist_t brushes;
266         GlobalSceneGraph().traverse( BrushGetLevel( brushes, SURF_NODRAW, false, false, nodraw_active ) );
267
268 #if GDEF_DEBUG
269         if ( brushes.empty() ) {
270                 globalOutputStream() << "UFO:AI: No brushes.\n";
271         }
272         else
273         {
274                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " nodraw brushes.\n";
275         }
276 #endif
277 }
278
279 void filter_actorclip( void ){
280         if ( actorclip_active ) {
281                 actorclip_active = false;
282         }
283         else {
284                 actorclip_active = true;
285         }
286         brushlist_t brushes;
287         GlobalSceneGraph().traverse( BrushGetLevel( brushes, CONTENTS_ACTORCLIP, true, false, actorclip_active ) );
288
289 #if GDEF_DEBUG
290         if ( brushes.empty() ) {
291                 globalOutputStream() << "UFO:AI: No brushes.\n";
292         }
293         else
294         {
295                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " actorclip brushes.\n";
296         }
297 #endif
298 }
299
300 void filter_weaponclip( void ){
301         if ( weaponclip_active ) {
302                 weaponclip_active = false;
303         }
304         else {
305                 weaponclip_active = true;
306         }
307         brushlist_t brushes;
308         GlobalSceneGraph().traverse( BrushGetLevel( brushes, CONTENTS_WEAPONCLIP, true, false, weaponclip_active ) );
309
310 #if GDEF_DEBUG
311         if ( brushes.empty() ) {
312                 globalOutputStream() << "UFO:AI: No brushes.\n";
313         }
314         else
315         {
316                 globalOutputStream() << "UFO:AI: Hiding " << Unsigned( brushes.size() ) << " weaponclip brushes.\n";
317         }
318 #endif
319 }