]> icculus.org git repositories - divverent/netradiant.git/blob - radiant/brushmodule.cpp
new args -meta and -patchmeta to -convert with .map file argument
[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");
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",
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     GlobalPreferenceSystem().registerPreference(
122       "AlternativeTextureProjection",
123       BoolImportStringCaller(g_useAlternativeTextureProjection.m_latched),
124       BoolExportStringCaller(g_useAlternativeTextureProjection.m_latched)
125     );
126     g_useAlternativeTextureProjection.useLatched();
127
128     if(g_useAlternativeTextureProjection.m_value)
129     {
130       type = eBrushTypeQuake3BP;
131     }
132     
133     // d1223m
134     GlobalPreferenceSystem().registerPreference(
135       "BrushAlwaysCaulk", 
136       BoolImportStringCaller(g_brush_always_caulk), 
137       BoolExportStringCaller(g_brush_always_caulk));
138   }
139
140   Brush_registerCommands();
141   Brush_registerPreferencesPage();
142
143   BrushFilters_construct();
144
145   BrushClipPlane::constructStatic();
146   BrushInstance::constructStatic();
147   Brush::constructStatic(type);
148
149   Brush::m_maxWorldCoord = g_MaxWorldCoord;
150   BrushInstance::m_counter = &g_brushCount;
151
152   g_texdef_default_scale = 0.5f;
153   const char* value = g_pGameDescription->getKeyValue("default_scale");
154   if(!string_empty(value))
155   {
156     float scale = static_cast<float>(atof(value));
157     if(scale != 0)
158     {
159       g_texdef_default_scale = scale;
160     }
161     else
162     {
163       globalErrorStream() << "error parsing \"default_scale\" attribute\n";
164     }
165   }
166
167   GlobalPreferenceSystem().registerPreference("TextureLock", BoolImportStringCaller(g_brush_texturelock_enabled), BoolExportStringCaller(g_brush_texturelock_enabled));
168   GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", makeBoolStringImportCallback(FaceImportSnapPlanesCaller()), makeBoolStringExportCallback(FaceExportSnapPlanesCaller()));
169   GlobalPreferenceSystem().registerPreference("TexdefDefaultScale", FloatImportStringCaller(g_texdef_default_scale), FloatExportStringCaller(g_texdef_default_scale));
170
171   GridStatus_getTextureLockEnabled = getTextureLockEnabled;
172   g_texture_lock_status_changed = FreeCaller<GridStatus_onTextureLockEnabledChanged>();
173 }
174
175 void Brush_Destroy()
176 {
177   Brush::m_maxWorldCoord = 0;
178   BrushInstance::m_counter = 0;
179
180   Brush::destroyStatic();
181   BrushInstance::destroyStatic();
182   BrushClipPlane::destroyStatic();
183 }
184
185 void Brush_clipperColourChanged()
186 {
187   BrushClipPlane::destroyStatic();
188   BrushClipPlane::constructStatic();
189 }
190
191 void BrushFaceData_fromFace(const BrushFaceDataCallback& callback, Face& face)
192 {
193   _QERFaceData faceData;
194   faceData.m_p0 = face.getPlane().planePoints()[0];
195   faceData.m_p1 = face.getPlane().planePoints()[1];
196   faceData.m_p2 = face.getPlane().planePoints()[2];
197   faceData.m_shader = face.GetShader();
198   faceData.m_texdef = face.getTexdef().m_projection.m_texdef;
199   faceData.contents = face.getShader().m_flags.m_contentFlags;
200   faceData.flags = face.getShader().m_flags.m_surfaceFlags;
201   faceData.value = face.getShader().m_flags.m_value;
202   callback(faceData);
203 }
204 typedef ConstReferenceCaller1<BrushFaceDataCallback, Face&, BrushFaceData_fromFace> BrushFaceDataFromFaceCaller;
205 typedef Callback1<Face&> FaceCallback;
206
207 class Quake3BrushCreator : public BrushCreator
208 {
209 public:
210   scene::Node& createBrush()
211   {
212     return (new BrushNode)->node();
213   }
214   bool useAlternativeTextureProjection() const
215   {
216     return g_useAlternativeTextureProjection.m_value;
217   }
218   void Brush_forEachFace(scene::Node& brush, const BrushFaceDataCallback& callback)
219   {
220     ::Brush_forEachFace(*Node_getBrush(brush), FaceCallback(BrushFaceDataFromFaceCaller(callback)));
221   }
222   bool Brush_addFace(scene::Node& brush, const _QERFaceData& faceData)
223   {
224     Node_getBrush(brush)->undoSave();
225     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;
226   }
227 };
228
229 Quake3BrushCreator g_Quake3BrushCreator;
230
231 BrushCreator& GetBrushCreator()
232 {
233   return g_Quake3BrushCreator;
234 }
235
236 #include "modulesystem/singletonmodule.h"
237 #include "modulesystem/moduleregistry.h"
238
239
240 class BrushDependencies :
241   public GlobalRadiantModuleRef,
242   public GlobalSceneGraphModuleRef,
243   public GlobalShaderCacheModuleRef,
244   public GlobalSelectionModuleRef,
245   public GlobalOpenGLModuleRef,
246   public GlobalUndoModuleRef,
247   public GlobalFilterModuleRef
248 {
249 };
250
251 class BrushDoom3API : public TypeSystemRef
252 {
253   BrushCreator* m_brushdoom3;
254 public:
255   typedef BrushCreator Type;
256   STRING_CONSTANT(Name, "doom3");
257
258   BrushDoom3API()
259   {
260     Brush_Construct(eBrushTypeDoom3);
261
262      m_brushdoom3 = &GetBrushCreator();
263   }
264   ~BrushDoom3API()
265   {
266     Brush_Destroy();
267   }
268   BrushCreator* getTable()
269   {
270     return m_brushdoom3;
271   }
272 };
273
274 typedef SingletonModule<BrushDoom3API, BrushDependencies> BrushDoom3Module;
275 typedef Static<BrushDoom3Module> StaticBrushDoom3Module;
276 StaticRegisterModule staticRegisterBrushDoom3(StaticBrushDoom3Module::instance());
277
278
279 class BrushQuake4API : public TypeSystemRef
280 {
281   BrushCreator* m_brushquake4;
282 public:
283   typedef BrushCreator Type;
284   STRING_CONSTANT(Name, "quake4");
285
286   BrushQuake4API()
287   {
288     Brush_Construct(eBrushTypeQuake4);
289
290      m_brushquake4 = &GetBrushCreator();
291   }
292   ~BrushQuake4API()
293   {
294     Brush_Destroy();
295   }
296   BrushCreator* getTable()
297   {
298     return m_brushquake4;
299   }
300 };
301
302 typedef SingletonModule<BrushQuake4API, BrushDependencies> BrushQuake4Module;
303 typedef Static<BrushQuake4Module> StaticBrushQuake4Module;
304 StaticRegisterModule staticRegisterBrushQuake4(StaticBrushQuake4Module::instance());
305
306
307 class BrushQuake3API : public TypeSystemRef
308 {
309   BrushCreator* m_brushquake3;
310 public:
311   typedef BrushCreator Type;
312   STRING_CONSTANT(Name, "quake3");
313
314   BrushQuake3API()
315   {
316     Brush_Construct(eBrushTypeQuake3);
317
318     m_brushquake3 = &GetBrushCreator();
319   }
320   ~BrushQuake3API()
321   {
322     Brush_Destroy();
323   }
324   BrushCreator* getTable()
325   {
326     return m_brushquake3;
327   }
328 };
329
330 typedef SingletonModule<BrushQuake3API, BrushDependencies> BrushQuake3Module;
331 typedef Static<BrushQuake3Module> StaticBrushQuake3Module;
332 StaticRegisterModule staticRegisterBrushQuake3(StaticBrushQuake3Module::instance());
333
334
335 class BrushQuake2API : public TypeSystemRef
336 {
337   BrushCreator* m_brushquake2;
338 public:
339   typedef BrushCreator Type;
340   STRING_CONSTANT(Name, "quake2");
341
342   BrushQuake2API()
343   {
344     Brush_Construct(eBrushTypeQuake2);
345
346     m_brushquake2 = &GetBrushCreator();
347   }
348   ~BrushQuake2API()
349   {
350     Brush_Destroy();
351   }
352   BrushCreator* getTable()
353   {
354     return m_brushquake2;
355   }
356 };
357
358 typedef SingletonModule<BrushQuake2API, BrushDependencies> BrushQuake2Module;
359 typedef Static<BrushQuake2Module> StaticBrushQuake2Module;
360 StaticRegisterModule staticRegisterBrushQuake2(StaticBrushQuake2Module::instance());
361
362
363 class BrushQuake1API : public TypeSystemRef
364 {
365   BrushCreator* m_brushquake1;
366 public:
367   typedef BrushCreator Type;
368   STRING_CONSTANT(Name, "quake");
369
370   BrushQuake1API()
371   {
372     Brush_Construct(eBrushTypeQuake);
373
374     m_brushquake1 = &GetBrushCreator();
375   }
376   ~BrushQuake1API()
377   {
378     Brush_Destroy();
379   }
380   BrushCreator* getTable()
381   {
382     return m_brushquake1;
383   }
384 };
385
386 typedef SingletonModule<BrushQuake1API, BrushDependencies> BrushQuake1Module;
387 typedef Static<BrushQuake1Module> StaticBrushQuake1Module;
388 StaticRegisterModule staticRegisterBrushQuake1(StaticBrushQuake1Module::instance());
389
390
391 class BrushHalfLifeAPI : public TypeSystemRef
392 {
393   BrushCreator* m_brushhalflife;
394 public:
395   typedef BrushCreator Type;
396   STRING_CONSTANT(Name, "halflife");
397
398   BrushHalfLifeAPI()
399   {
400     Brush_Construct(eBrushTypeHalfLife);
401
402     m_brushhalflife = &GetBrushCreator();
403   }
404   ~BrushHalfLifeAPI()
405   {
406     Brush_Destroy();
407   }
408   BrushCreator* getTable()
409   {
410     return m_brushhalflife;
411   }
412 };
413
414 typedef SingletonModule<BrushHalfLifeAPI, BrushDependencies> BrushHalfLifeModule;
415 typedef Static<BrushHalfLifeModule> StaticBrushHalfLifeModule;
416 StaticRegisterModule staticRegisterBrushHalfLife(StaticBrushHalfLifeModule::instance());