]> icculus.org git repositories - divverent/netradiant.git/blob - radiant/brushmodule.cpp
NOW I do it right: #woxblox#
[divverent/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 {
43   return g_brush_texturelock_enabled;
44 }
45
46 void Face_importSnapPlanes(bool value)
47 {
48   Face::m_quantise = value ? quantiseInteger : quantiseFloating;
49 }
50 typedef FreeCaller1<bool, Face_importSnapPlanes> FaceImportSnapPlanesCaller;
51
52 void Face_exportSnapPlanes(const BoolImportCallback& importer)
53 {
54   importer(Face::m_quantise == quantiseInteger);
55 }
56 typedef FreeCaller1<const BoolImportCallback&, Face_exportSnapPlanes> FaceExportSnapPlanesCaller;
57
58 void Brush_constructPreferences(PreferencesPage& page)
59 {
60   page.appendCheckBox(
61     "", "Snap planes to integer grid",
62     FaceImportSnapPlanesCaller(),
63     FaceExportSnapPlanesCaller()
64   );
65   page.appendEntry(
66     "Default texture scale",
67     g_texdef_default_scale
68   );
69   if(g_showAlternativeTextureProjectionOption)
70   {
71     page.appendCheckBox(
72       "", "Use alternative texture-projection (\"brush primitives\")",
73       LatchedBoolImportCaller(g_useAlternativeTextureProjection),
74       BoolExportCaller(g_useAlternativeTextureProjection.m_latched)
75     );
76   }
77   // d1223m
78   page.appendCheckBox("", 
79     "Always use caulk for new brushes",
80     g_brush_always_caulk
81   );
82 }
83 void Brush_constructPage(PreferenceGroup& group)
84 {
85   PreferencesPage page(group.createPage("Brush", "Brush Settings"));
86   Brush_constructPreferences(page);
87 }
88 void Brush_registerPreferencesPage()
89 {
90   PreferencesDialog_addSettingsPage(FreeCaller1<PreferenceGroup&, Brush_constructPage>());
91 }
92
93 void Brush_unlatchPreferences()
94 {
95         Brush_toggleFormat(0);
96 }
97
98 void Brush_toggleFormat(int i)
99 {
100         if(g_showAlternativeTextureProjectionOption)
101         {
102                 g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i;
103                 Brush::destroyStatic();
104                 Brush::constructStatic(g_useAlternativeTextureProjection.m_value ? eBrushTypeQuake3BP : eBrushTypeQuake3);
105         }
106 }
107
108 int Brush_toggleFormatCount()
109 {
110         if(g_showAlternativeTextureProjectionOption)
111                 return 2;
112         return 1;
113 }
114
115 void Brush_Construct(EBrushType type)
116 {
117   if(type == eBrushTypeQuake3)
118   {
119     g_showAlternativeTextureProjectionOption = true;
120
121     const char *value = g_pGameDescription->getKeyValue("brush_primit");
122     if(!string_empty(value))
123       g_useAlternativeTextureProjection.m_latched = atoi(value);
124
125     GlobalPreferenceSystem().registerPreference(
126       "AlternativeTextureProjection",
127       BoolImportStringCaller(g_useAlternativeTextureProjection.m_latched),
128       BoolExportStringCaller(g_useAlternativeTextureProjection.m_latched)
129     );
130     g_useAlternativeTextureProjection.useLatched();
131
132     if(g_useAlternativeTextureProjection.m_value)
133     {
134       type = eBrushTypeQuake3BP;
135     }
136     
137     // d1223m
138     GlobalPreferenceSystem().registerPreference(
139       "BrushAlwaysCaulk", 
140       BoolImportStringCaller(g_brush_always_caulk), 
141       BoolExportStringCaller(g_brush_always_caulk));
142   }
143
144   Brush_registerCommands();
145   Brush_registerPreferencesPage();
146
147   BrushFilters_construct();
148
149   BrushClipPlane::constructStatic();
150   BrushInstance::constructStatic();
151   Brush::constructStatic(type);
152
153   Brush::m_maxWorldCoord = g_MaxWorldCoord;
154   BrushInstance::m_counter = &g_brushCount;
155
156   g_texdef_default_scale = 0.5f;
157   const char* value = g_pGameDescription->getKeyValue("default_scale");
158   if(!string_empty(value))
159   {
160     float scale = static_cast<float>(atof(value));
161     if(scale != 0)
162     {
163       g_texdef_default_scale = scale;
164     }
165     else
166     {
167       globalErrorStream() << "error parsing \"default_scale\" attribute\n";
168     }
169   }
170
171   GlobalPreferenceSystem().registerPreference("TextureLock", BoolImportStringCaller(g_brush_texturelock_enabled), BoolExportStringCaller(g_brush_texturelock_enabled));
172   GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", makeBoolStringImportCallback(FaceImportSnapPlanesCaller()), makeBoolStringExportCallback(FaceExportSnapPlanesCaller()));
173   GlobalPreferenceSystem().registerPreference("TexdefDefaultScale", FloatImportStringCaller(g_texdef_default_scale), FloatExportStringCaller(g_texdef_default_scale));
174
175   GridStatus_getTextureLockEnabled = getTextureLockEnabled;
176   g_texture_lock_status_changed = FreeCaller<GridStatus_onTextureLockEnabledChanged>();
177 }
178
179 void Brush_Destroy()
180 {
181   Brush::m_maxWorldCoord = 0;
182   BrushInstance::m_counter = 0;
183
184   Brush::destroyStatic();
185   BrushInstance::destroyStatic();
186   BrushClipPlane::destroyStatic();
187 }
188
189 void Brush_clipperColourChanged()
190 {
191   BrushClipPlane::destroyStatic();
192   BrushClipPlane::constructStatic();
193 }
194
195 void BrushFaceData_fromFace(const BrushFaceDataCallback& callback, Face& face)
196 {
197   _QERFaceData faceData;
198   faceData.m_p0 = face.getPlane().planePoints()[0];
199   faceData.m_p1 = face.getPlane().planePoints()[1];
200   faceData.m_p2 = face.getPlane().planePoints()[2];
201   faceData.m_shader = face.GetShader();
202   faceData.m_texdef = face.getTexdef().m_projection.m_texdef;
203   faceData.contents = face.getShader().m_flags.m_contentFlags;
204   faceData.flags = face.getShader().m_flags.m_surfaceFlags;
205   faceData.value = face.getShader().m_flags.m_value;
206   callback(faceData);
207 }
208 typedef ConstReferenceCaller1<BrushFaceDataCallback, Face&, BrushFaceData_fromFace> BrushFaceDataFromFaceCaller;
209 typedef Callback1<Face&> FaceCallback;
210
211 class Quake3BrushCreator : public BrushCreator
212 {
213 public:
214   scene::Node& createBrush()
215   {
216     return (new BrushNode)->node();
217   }
218   bool useAlternativeTextureProjection() const
219   {
220     return g_useAlternativeTextureProjection.m_value;
221   }
222   void Brush_forEachFace(scene::Node& brush, const BrushFaceDataCallback& callback)
223   {
224     ::Brush_forEachFace(*Node_getBrush(brush), FaceCallback(BrushFaceDataFromFaceCaller(callback)));
225   }
226   bool Brush_addFace(scene::Node& brush, const _QERFaceData& faceData)
227   {
228     Node_getBrush(brush)->undoSave();
229     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;
230   }
231 };
232
233 Quake3BrushCreator g_Quake3BrushCreator;
234
235 BrushCreator& GetBrushCreator()
236 {
237   return g_Quake3BrushCreator;
238 }
239
240 #include "modulesystem/singletonmodule.h"
241 #include "modulesystem/moduleregistry.h"
242
243
244 class BrushDependencies :
245   public GlobalRadiantModuleRef,
246   public GlobalSceneGraphModuleRef,
247   public GlobalShaderCacheModuleRef,
248   public GlobalSelectionModuleRef,
249   public GlobalOpenGLModuleRef,
250   public GlobalUndoModuleRef,
251   public GlobalFilterModuleRef
252 {
253 };
254
255 class BrushDoom3API : public TypeSystemRef
256 {
257   BrushCreator* m_brushdoom3;
258 public:
259   typedef BrushCreator Type;
260   STRING_CONSTANT(Name, "doom3");
261
262   BrushDoom3API()
263   {
264     Brush_Construct(eBrushTypeDoom3);
265
266      m_brushdoom3 = &GetBrushCreator();
267   }
268   ~BrushDoom3API()
269   {
270     Brush_Destroy();
271   }
272   BrushCreator* getTable()
273   {
274     return m_brushdoom3;
275   }
276 };
277
278 typedef SingletonModule<BrushDoom3API, BrushDependencies> BrushDoom3Module;
279 typedef Static<BrushDoom3Module> StaticBrushDoom3Module;
280 StaticRegisterModule staticRegisterBrushDoom3(StaticBrushDoom3Module::instance());
281
282
283 class BrushQuake4API : public TypeSystemRef
284 {
285   BrushCreator* m_brushquake4;
286 public:
287   typedef BrushCreator Type;
288   STRING_CONSTANT(Name, "quake4");
289
290   BrushQuake4API()
291   {
292     Brush_Construct(eBrushTypeQuake4);
293
294      m_brushquake4 = &GetBrushCreator();
295   }
296   ~BrushQuake4API()
297   {
298     Brush_Destroy();
299   }
300   BrushCreator* getTable()
301   {
302     return m_brushquake4;
303   }
304 };
305
306 typedef SingletonModule<BrushQuake4API, BrushDependencies> BrushQuake4Module;
307 typedef Static<BrushQuake4Module> StaticBrushQuake4Module;
308 StaticRegisterModule staticRegisterBrushQuake4(StaticBrushQuake4Module::instance());
309
310
311 class BrushQuake3API : public TypeSystemRef
312 {
313   BrushCreator* m_brushquake3;
314 public:
315   typedef BrushCreator Type;
316   STRING_CONSTANT(Name, "quake3");
317
318   BrushQuake3API()
319   {
320     Brush_Construct(eBrushTypeQuake3);
321
322     m_brushquake3 = &GetBrushCreator();
323   }
324   ~BrushQuake3API()
325   {
326     Brush_Destroy();
327   }
328   BrushCreator* getTable()
329   {
330     return m_brushquake3;
331   }
332 };
333
334 typedef SingletonModule<BrushQuake3API, BrushDependencies> BrushQuake3Module;
335 typedef Static<BrushQuake3Module> StaticBrushQuake3Module;
336 StaticRegisterModule staticRegisterBrushQuake3(StaticBrushQuake3Module::instance());
337
338
339 class BrushQuake2API : public TypeSystemRef
340 {
341   BrushCreator* m_brushquake2;
342 public:
343   typedef BrushCreator Type;
344   STRING_CONSTANT(Name, "quake2");
345
346   BrushQuake2API()
347   {
348     Brush_Construct(eBrushTypeQuake2);
349
350     m_brushquake2 = &GetBrushCreator();
351   }
352   ~BrushQuake2API()
353   {
354     Brush_Destroy();
355   }
356   BrushCreator* getTable()
357   {
358     return m_brushquake2;
359   }
360 };
361
362 typedef SingletonModule<BrushQuake2API, BrushDependencies> BrushQuake2Module;
363 typedef Static<BrushQuake2Module> StaticBrushQuake2Module;
364 StaticRegisterModule staticRegisterBrushQuake2(StaticBrushQuake2Module::instance());
365
366
367 class BrushQuake1API : public TypeSystemRef
368 {
369   BrushCreator* m_brushquake1;
370 public:
371   typedef BrushCreator Type;
372   STRING_CONSTANT(Name, "quake");
373
374   BrushQuake1API()
375   {
376     Brush_Construct(eBrushTypeQuake);
377
378     m_brushquake1 = &GetBrushCreator();
379   }
380   ~BrushQuake1API()
381   {
382     Brush_Destroy();
383   }
384   BrushCreator* getTable()
385   {
386     return m_brushquake1;
387   }
388 };
389
390 typedef SingletonModule<BrushQuake1API, BrushDependencies> BrushQuake1Module;
391 typedef Static<BrushQuake1Module> StaticBrushQuake1Module;
392 StaticRegisterModule staticRegisterBrushQuake1(StaticBrushQuake1Module::instance());
393
394
395 class BrushHalfLifeAPI : public TypeSystemRef
396 {
397   BrushCreator* m_brushhalflife;
398 public:
399   typedef BrushCreator Type;
400   STRING_CONSTANT(Name, "halflife");
401
402   BrushHalfLifeAPI()
403   {
404     Brush_Construct(eBrushTypeHalfLife);
405
406     m_brushhalflife = &GetBrushCreator();
407   }
408   ~BrushHalfLifeAPI()
409   {
410     Brush_Destroy();
411   }
412   BrushCreator* getTable()
413   {
414     return m_brushhalflife;
415   }
416 };
417
418 typedef SingletonModule<BrushHalfLifeAPI, BrushDependencies> BrushHalfLifeModule;
419 typedef Static<BrushHalfLifeModule> StaticBrushHalfLifeModule;
420 StaticRegisterModule staticRegisterBrushHalfLife(StaticBrushHalfLifeModule::instance());