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