]> git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brushmodule.cpp
Hack around segfault at launch, patch from danfe: https://github.com/TTimo/GtkRadiant...
[xonotic/netradiant.git] / radiant / brushmodule.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "brushmodule.h"
23
24 #include "qerplugin.h"
25
26 #include "brushnode.h"
27 #include "brushmanip.h"
28
29 #include "preferencesystem.h"
30 #include "stringio.h"
31
32 #include "map.h"
33 #include "qe3.h"
34 #include "mainframe.h"
35 #include "preferences.h"
36
37 LatchedBool g_useAlternativeTextureProjection( false, "Use alternative texture-projection (\"brush primitives\")" );
38 bool g_showAlternativeTextureProjectionOption = false;
39 bool g_brush_always_caulk;
40
41 bool getTextureLockEnabled(){
42         return g_brush_texturelock_enabled;
43 }
44
45 void Face_importSnapPlanes( bool value ){
46         Face::m_quantise = value ? quantiseInteger : quantiseFloating;
47 }
48 typedef FreeCaller1<bool, Face_importSnapPlanes> FaceImportSnapPlanesCaller;
49
50 void Face_exportSnapPlanes( const BoolImportCallback& importer ){
51         importer( Face::m_quantise == quantiseInteger );
52 }
53 typedef FreeCaller1<const BoolImportCallback&, Face_exportSnapPlanes> FaceExportSnapPlanesCaller;
54
55 void Brush_constructPreferences( PreferencesPage& page ){
56         page.appendCheckBox(
57                 "", "Snap planes to integer grid",
58                 FaceImportSnapPlanesCaller(),
59                 FaceExportSnapPlanesCaller()
60                 );
61         page.appendEntry(
62                 "Default texture scale",
63                 g_texdef_default_scale
64                 );
65         if ( g_showAlternativeTextureProjectionOption ) {
66                 page.appendCheckBox(
67                         "", "Use alternative texture-projection (\"brush primitives\")",
68                         LatchedBoolImportCaller( g_useAlternativeTextureProjection ),
69                         BoolExportCaller( g_useAlternativeTextureProjection.m_latched )
70                         );
71         }
72         // d1223m
73         page.appendCheckBox( "",
74                                                  "Always use caulk for new brushes",
75                                                  g_brush_always_caulk
76                                                  );
77 }
78 void Brush_constructPage( PreferenceGroup& group ){
79         PreferencesPage page( group.createPage( "Brush", "Brush Settings" ) );
80         Brush_constructPreferences( page );
81 }
82 void Brush_registerPreferencesPage(){
83         PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Brush_constructPage>() );
84 }
85
86 void Brush_unlatchPreferences(){
87         Brush_toggleFormat( 0 );
88 }
89
90 void Brush_toggleFormat( int i ){
91         if ( g_showAlternativeTextureProjectionOption ) {
92                 g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i;
93                 Brush::destroyStatic();
94                 Brush::constructStatic( g_useAlternativeTextureProjection.m_value ? eBrushTypeQuake3BP : eBrushTypeQuake3 );
95         }
96 }
97
98 int Brush_toggleFormatCount(){
99         if ( g_showAlternativeTextureProjectionOption ) {
100                 return 2;
101         }
102         return 1;
103 }
104
105 void Brush_Construct( EBrushType type ){
106         if ( type == eBrushTypeQuake3 ) {
107                 g_showAlternativeTextureProjectionOption = true;
108
109                 const char *value = g_pGameDescription->getKeyValue( "brush_primit" );
110                 if ( !string_empty( value ) ) {
111                         g_useAlternativeTextureProjection.m_latched = atoi( value );
112                 }
113
114                 GlobalPreferenceSystem().registerPreference(
115                         "AlternativeTextureProjection",
116                         BoolImportStringCaller( g_useAlternativeTextureProjection.m_latched ),
117                         BoolExportStringCaller( g_useAlternativeTextureProjection.m_latched )
118                         );
119                 g_useAlternativeTextureProjection.useLatched();
120
121                 if ( g_useAlternativeTextureProjection.m_value ) {
122                         type = eBrushTypeQuake3BP;
123                 }
124
125                 // d1223m
126                 GlobalPreferenceSystem().registerPreference(
127                         "BrushAlwaysCaulk",
128                         BoolImportStringCaller( g_brush_always_caulk ),
129                         BoolExportStringCaller( g_brush_always_caulk ) );
130         }
131
132         Brush_registerCommands();
133         Brush_registerPreferencesPage();
134
135         BrushFilters_construct();
136
137         BrushClipPlane::constructStatic();
138         BrushInstance::constructStatic();
139         Brush::constructStatic( type );
140
141         Brush::m_maxWorldCoord = g_MaxWorldCoord;
142         BrushInstance::m_counter = &g_brushCount;
143
144         g_texdef_default_scale = 0.5f;
145         const char* value = g_pGameDescription->getKeyValue( "default_scale" );
146         if ( !string_empty( value ) ) {
147                 float scale = static_cast<float>( atof( value ) );
148                 if ( scale != 0 ) {
149                         g_texdef_default_scale = scale;
150                 }
151                 else
152                 {
153                         globalErrorStream() << "error parsing \"default_scale\" attribute\n";
154                 }
155         }
156
157         GlobalPreferenceSystem().registerPreference( "TextureLock", BoolImportStringCaller( g_brush_texturelock_enabled ), BoolExportStringCaller( g_brush_texturelock_enabled ) );
158         GlobalPreferenceSystem().registerPreference( "BrushSnapPlanes", makeBoolStringImportCallback( FaceImportSnapPlanesCaller() ), makeBoolStringExportCallback( FaceExportSnapPlanesCaller() ) );
159         GlobalPreferenceSystem().registerPreference( "TexdefDefaultScale", FloatImportStringCaller( g_texdef_default_scale ), FloatExportStringCaller( g_texdef_default_scale ) );
160
161         GridStatus_getTextureLockEnabled = getTextureLockEnabled;
162         g_texture_lock_status_changed = FreeCaller<GridStatus_onTextureLockEnabledChanged>();
163 }
164
165 void Brush_Destroy(){
166         Brush::m_maxWorldCoord = 0;
167         BrushInstance::m_counter = 0;
168
169         Brush::destroyStatic();
170         BrushInstance::destroyStatic();
171         BrushClipPlane::destroyStatic();
172 }
173
174 void Brush_clipperColourChanged(){
175         BrushClipPlane::destroyStatic();
176         BrushClipPlane::constructStatic();
177 }
178
179 void BrushFaceData_fromFace( const BrushFaceDataCallback& callback, Face& face ){
180         _QERFaceData faceData;
181         faceData.m_p0 = face.getPlane().planePoints()[0];
182         faceData.m_p1 = face.getPlane().planePoints()[1];
183         faceData.m_p2 = face.getPlane().planePoints()[2];
184         faceData.m_shader = face.GetShader();
185         faceData.m_texdef = face.getTexdef().m_projection.m_texdef;
186         faceData.contents = face.getShader().m_flags.m_contentFlags;
187         faceData.flags = face.getShader().m_flags.m_surfaceFlags;
188         faceData.value = face.getShader().m_flags.m_value;
189         callback( faceData );
190 }
191 typedef ConstReferenceCaller1<BrushFaceDataCallback, Face&, BrushFaceData_fromFace> BrushFaceDataFromFaceCaller;
192 typedef Callback1<Face&> FaceCallback;
193
194 class Quake3BrushCreator : public BrushCreator
195 {
196 public:
197 scene::Node& createBrush(){
198         return ( new BrushNode )->node();
199 }
200 bool useAlternativeTextureProjection() const {
201         return g_useAlternativeTextureProjection.m_value;
202 }
203 void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ){
204         ::Brush_forEachFace( *Node_getBrush( brush ), FaceCallback( BrushFaceDataFromFaceCaller( callback ) ) );
205 }
206 bool Brush_addFace( scene::Node& brush, const _QERFaceData& faceData ){
207         Node_getBrush( brush )->undoSave();
208         return Node_getBrush( brush )->addPlane( faceData.m_p0, faceData.m_p1, faceData.m_p2, faceData.m_shader, TextureProjection( faceData.m_texdef, brushprimit_texdef_t(), Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ) ) != 0;
209 }
210 };
211
212 Quake3BrushCreator g_Quake3BrushCreator;
213
214 BrushCreator& GetBrushCreator(){
215         return g_Quake3BrushCreator;
216 }
217
218 #include "modulesystem/singletonmodule.h"
219 #include "modulesystem/moduleregistry.h"
220
221
222 class BrushDependencies :
223         public GlobalRadiantModuleRef,
224         public GlobalSceneGraphModuleRef,
225         public GlobalShaderCacheModuleRef,
226         public GlobalSelectionModuleRef,
227         public GlobalOpenGLModuleRef,
228         public GlobalUndoModuleRef,
229         public GlobalFilterModuleRef
230 {
231 };
232
233 class BrushDoom3API : public TypeSystemRef
234 {
235 BrushCreator* m_brushdoom3;
236 public:
237 typedef BrushCreator Type;
238 STRING_CONSTANT( Name, "doom3" );
239
240 BrushDoom3API(){
241         Brush_Construct( eBrushTypeDoom3 );
242
243         m_brushdoom3 = &GetBrushCreator();
244 }
245 ~BrushDoom3API(){
246         Brush_Destroy();
247 }
248 BrushCreator* getTable(){
249         return m_brushdoom3;
250 }
251 };
252
253 typedef SingletonModule<BrushDoom3API, BrushDependencies> BrushDoom3Module;
254 typedef Static<BrushDoom3Module> StaticBrushDoom3Module;
255 StaticRegisterModule staticRegisterBrushDoom3( StaticBrushDoom3Module::instance() );
256
257
258 class BrushQuake4API : public TypeSystemRef
259 {
260 BrushCreator* m_brushquake4;
261 public:
262 typedef BrushCreator Type;
263 STRING_CONSTANT( Name, "quake4" );
264
265 BrushQuake4API(){
266         Brush_Construct( eBrushTypeQuake4 );
267
268         m_brushquake4 = &GetBrushCreator();
269 }
270 ~BrushQuake4API(){
271         Brush_Destroy();
272 }
273 BrushCreator* getTable(){
274         return m_brushquake4;
275 }
276 };
277
278 typedef SingletonModule<BrushQuake4API, BrushDependencies> BrushQuake4Module;
279 typedef Static<BrushQuake4Module> StaticBrushQuake4Module;
280 StaticRegisterModule staticRegisterBrushQuake4( StaticBrushQuake4Module::instance() );
281
282
283 class BrushQuake3API : public TypeSystemRef
284 {
285 BrushCreator* m_brushquake3;
286 public:
287 typedef BrushCreator Type;
288 STRING_CONSTANT( Name, "quake3" );
289
290 BrushQuake3API(){
291         Brush_Construct( eBrushTypeQuake3 );
292
293         m_brushquake3 = &GetBrushCreator();
294 }
295 ~BrushQuake3API(){
296         Brush_Destroy();
297 }
298 BrushCreator* getTable(){
299         return m_brushquake3;
300 }
301 };
302
303 typedef SingletonModule<BrushQuake3API, BrushDependencies> BrushQuake3Module;
304 typedef Static<BrushQuake3Module> StaticBrushQuake3Module;
305 StaticRegisterModule staticRegisterBrushQuake3( StaticBrushQuake3Module::instance() );
306
307
308 class BrushQuake2API : public TypeSystemRef
309 {
310 BrushCreator* m_brushquake2;
311 public:
312 typedef BrushCreator Type;
313 STRING_CONSTANT( Name, "quake2" );
314
315 BrushQuake2API(){
316         Brush_Construct( eBrushTypeQuake2 );
317
318         m_brushquake2 = &GetBrushCreator();
319 }
320 ~BrushQuake2API(){
321         Brush_Destroy();
322 }
323 BrushCreator* getTable(){
324         return m_brushquake2;
325 }
326 };
327
328 typedef SingletonModule<BrushQuake2API, BrushDependencies> BrushQuake2Module;
329 typedef Static<BrushQuake2Module> StaticBrushQuake2Module;
330 StaticRegisterModule staticRegisterBrushQuake2( StaticBrushQuake2Module::instance() );
331
332
333 class BrushQuake1API : public TypeSystemRef
334 {
335 BrushCreator* m_brushquake1;
336 public:
337 typedef BrushCreator Type;
338 STRING_CONSTANT( Name, "quake" );
339
340 BrushQuake1API(){
341         Brush_Construct( eBrushTypeQuake );
342
343         m_brushquake1 = &GetBrushCreator();
344 }
345 ~BrushQuake1API(){
346         Brush_Destroy();
347 }
348 BrushCreator* getTable(){
349         return m_brushquake1;
350 }
351 };
352
353 typedef SingletonModule<BrushQuake1API, BrushDependencies> BrushQuake1Module;
354 typedef Static<BrushQuake1Module> StaticBrushQuake1Module;
355 StaticRegisterModule staticRegisterBrushQuake1( StaticBrushQuake1Module::instance() );
356
357
358 class BrushHalfLifeAPI : public TypeSystemRef
359 {
360 BrushCreator* m_brushhalflife;
361 public:
362 typedef BrushCreator Type;
363 STRING_CONSTANT( Name, "halflife" );
364
365 BrushHalfLifeAPI(){
366         Brush_Construct( eBrushTypeHalfLife );
367
368         m_brushhalflife = &GetBrushCreator();
369 }
370 ~BrushHalfLifeAPI(){
371         Brush_Destroy();
372 }
373 BrushCreator* getTable(){
374         return m_brushhalflife;
375 }
376 };
377
378 typedef SingletonModule<BrushHalfLifeAPI, BrushDependencies> BrushHalfLifeModule;
379 typedef Static<BrushHalfLifeModule> StaticBrushHalfLifeModule;
380 StaticRegisterModule staticRegisterBrushHalfLife( StaticBrushHalfLifeModule::instance() );