2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #include "brushmodule.h"
24 #include "qerplugin.h"
26 #include "brushnode.h"
27 #include "brushmanip.h"
29 #include "preferencesystem.h"
34 #include "mainframe.h"
35 #include "preferences.h"
37 LatchedValue<bool> g_useAlternativeTextureProjection( false, "Use alternative texture-projection (\"brush primitives\")" );
38 bool g_showAlternativeTextureProjectionOption = false;
39 bool g_brush_always_caulk;
41 bool getTextureLockEnabled(){
42 return g_brush_texturelock_enabled;
45 struct Face_SnapPlanes {
46 static void Export(const QuantiseFunc &self, const Callback<void(bool)> &returnz) {
47 returnz(self == quantiseInteger);
50 static void Import(QuantiseFunc &self, bool value) {
51 self = value ? quantiseInteger : quantiseFloating;
55 void Brush_constructPreferences( PreferencesPage& page ){
57 "", "Snap planes to integer grid",
58 make_property<Face_SnapPlanes>(Face::m_quantise)
61 "Default texture scale",
62 g_texdef_default_scale
64 if ( g_showAlternativeTextureProjectionOption ) {
66 "", "Use alternative texture-projection (\"brush primitives\")",
67 make_property(g_useAlternativeTextureProjection)
71 page.appendCheckBox( "",
72 "Always use caulk for new brushes",
76 void Brush_constructPage( PreferenceGroup& group ){
77 PreferencesPage page( group.createPage( "Brush", "Brush Settings" ) );
78 Brush_constructPreferences( page );
80 void Brush_registerPreferencesPage(){
81 PreferencesDialog_addSettingsPage( makeCallbackF(Brush_constructPage) );
84 void Brush_unlatchPreferences(){
85 Brush_toggleFormat( 0 );
88 void Brush_toggleFormat( int i ){
89 if ( g_showAlternativeTextureProjectionOption ) {
90 g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i;
91 Brush::destroyStatic();
92 Brush::constructStatic( g_useAlternativeTextureProjection.m_value ? eBrushTypeQuake3BP : eBrushTypeQuake3 );
96 int Brush_toggleFormatCount(){
97 if ( g_showAlternativeTextureProjectionOption ) {
103 void Brush_switchFormat( bool switch_format ){
106 g_useAlternativeTextureProjection.m_latched = g_useAlternativeTextureProjection.m_value;
107 g_useAlternativeTextureProjection.m_value = !g_useAlternativeTextureProjection.m_value;
108 PreferencesDialog_restartRequired( g_useAlternativeTextureProjection.m_description );
109 PreferencesDialog_restartIfRequired();
113 void Brush_Construct( EBrushType type ){
114 if ( type == eBrushTypeQuake3 ) {
115 g_showAlternativeTextureProjectionOption = true;
117 const char *value = g_pGameDescription->getKeyValue( "brush_primit" );
118 if ( !string_empty( value ) ) {
119 g_useAlternativeTextureProjection.m_latched = atoi( value );
122 GlobalPreferenceSystem().registerPreference(
123 "AlternativeTextureProjection",
124 make_property_string( g_useAlternativeTextureProjection.m_latched )
127 g_useAlternativeTextureProjection.useLatched();
129 if ( g_useAlternativeTextureProjection.m_value ) {
130 type = eBrushTypeQuake3BP;
134 GlobalPreferenceSystem().registerPreference(
136 make_property_string( g_brush_always_caulk )
140 Brush_registerCommands();
141 Brush_registerPreferencesPage();
143 BrushFilters_construct();
145 BrushClipPlane::constructStatic();
146 BrushInstance::constructStatic();
147 Brush::constructStatic( type );
149 Brush::m_maxWorldCoord = g_MaxWorldCoord;
150 BrushInstance::m_counter = &g_brushCount;
152 g_texdef_default_scale = 0.5f;
153 const char* value = g_pGameDescription->getKeyValue( "default_scale" );
154 if ( !string_empty( value ) ) {
155 float scale = static_cast<float>( atof( value ) );
157 g_texdef_default_scale = scale;
161 globalErrorStream() << "error parsing \"default_scale\" attribute\n";
165 GlobalPreferenceSystem().registerPreference( "TextureLock", make_property_string( g_brush_texturelock_enabled ) );
166 GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", make_property_string<Face_SnapPlanes>(Face::m_quantise));
167 GlobalPreferenceSystem().registerPreference( "TexdefDefaultScale", make_property_string( g_texdef_default_scale ) );
169 GridStatus_getTextureLockEnabled = getTextureLockEnabled;
170 g_texture_lock_status_changed = makeCallbackF(GridStatus_onTextureLockEnabledChanged);
173 void Brush_Destroy(){
174 Brush::m_maxWorldCoord = 0;
175 BrushInstance::m_counter = 0;
177 Brush::destroyStatic();
178 BrushInstance::destroyStatic();
179 BrushClipPlane::destroyStatic();
182 void Brush_clipperColourChanged(){
183 BrushClipPlane::destroyStatic();
184 BrushClipPlane::constructStatic();
187 void BrushFaceData_fromFace( const BrushFaceDataCallback& callback, Face& face ){
188 _QERFaceData faceData;
189 faceData.m_p0 = face.getPlane().planePoints()[0];
190 faceData.m_p1 = face.getPlane().planePoints()[1];
191 faceData.m_p2 = face.getPlane().planePoints()[2];
192 faceData.m_shader = face.GetShader();
193 faceData.m_texdef = face.getTexdef().m_projection.m_texdef;
194 faceData.contents = face.getShader().m_flags.m_contentFlags;
195 faceData.flags = face.getShader().m_flags.m_surfaceFlags;
196 faceData.value = face.getShader().m_flags.m_value;
197 callback( faceData );
199 typedef ConstReferenceCaller<BrushFaceDataCallback, void(Face&), BrushFaceData_fromFace> BrushFaceDataFromFaceCaller;
200 typedef Callback<void(Face&)> FaceCallback;
202 class Quake3BrushCreator : public BrushCreator
205 scene::Node& createBrush(){
206 return ( new BrushNode )->node();
208 bool useAlternativeTextureProjection() const {
209 return g_useAlternativeTextureProjection.m_value;
211 void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ){
212 ::Brush_forEachFace( *Node_getBrush( brush ), FaceCallback( BrushFaceDataFromFaceCaller( callback ) ) );
214 bool Brush_addFace( scene::Node& brush, const _QERFaceData& faceData ){
215 Node_getBrush( brush )->undoSave();
216 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;
220 Quake3BrushCreator g_Quake3BrushCreator;
222 BrushCreator& GetBrushCreator(){
223 return g_Quake3BrushCreator;
226 #include "modulesystem/singletonmodule.h"
227 #include "modulesystem/moduleregistry.h"
230 class BrushDependencies :
231 public GlobalRadiantModuleRef,
232 public GlobalSceneGraphModuleRef,
233 public GlobalShaderCacheModuleRef,
234 public GlobalSelectionModuleRef,
235 public GlobalOpenGLModuleRef,
236 public GlobalUndoModuleRef,
237 public GlobalFilterModuleRef
241 class BrushDoom3API : public TypeSystemRef
243 BrushCreator* m_brushdoom3;
245 typedef BrushCreator Type;
246 STRING_CONSTANT( Name, "doom3" );
249 Brush_Construct( eBrushTypeDoom3 );
251 m_brushdoom3 = &GetBrushCreator();
256 BrushCreator* getTable(){
261 typedef SingletonModule<BrushDoom3API, BrushDependencies> BrushDoom3Module;
262 typedef Static<BrushDoom3Module> StaticBrushDoom3Module;
263 StaticRegisterModule staticRegisterBrushDoom3( StaticBrushDoom3Module::instance() );
266 class BrushQuake4API : public TypeSystemRef
268 BrushCreator* m_brushquake4;
270 typedef BrushCreator Type;
271 STRING_CONSTANT( Name, "quake4" );
274 Brush_Construct( eBrushTypeQuake4 );
276 m_brushquake4 = &GetBrushCreator();
281 BrushCreator* getTable(){
282 return m_brushquake4;
286 typedef SingletonModule<BrushQuake4API, BrushDependencies> BrushQuake4Module;
287 typedef Static<BrushQuake4Module> StaticBrushQuake4Module;
288 StaticRegisterModule staticRegisterBrushQuake4( StaticBrushQuake4Module::instance() );
291 class BrushQuake3API : public TypeSystemRef
293 BrushCreator* m_brushquake3;
295 typedef BrushCreator Type;
296 STRING_CONSTANT( Name, "quake3" );
299 Brush_Construct( eBrushTypeQuake3 );
301 m_brushquake3 = &GetBrushCreator();
306 BrushCreator* getTable(){
307 return m_brushquake3;
311 typedef SingletonModule<BrushQuake3API, BrushDependencies> BrushQuake3Module;
312 typedef Static<BrushQuake3Module> StaticBrushQuake3Module;
313 StaticRegisterModule staticRegisterBrushQuake3( StaticBrushQuake3Module::instance() );
316 class BrushQuake2API : public TypeSystemRef
318 BrushCreator* m_brushquake2;
320 typedef BrushCreator Type;
321 STRING_CONSTANT( Name, "quake2" );
324 Brush_Construct( eBrushTypeQuake2 );
326 m_brushquake2 = &GetBrushCreator();
331 BrushCreator* getTable(){
332 return m_brushquake2;
336 typedef SingletonModule<BrushQuake2API, BrushDependencies> BrushQuake2Module;
337 typedef Static<BrushQuake2Module> StaticBrushQuake2Module;
338 StaticRegisterModule staticRegisterBrushQuake2( StaticBrushQuake2Module::instance() );
341 class BrushQuake1API : public TypeSystemRef
343 BrushCreator* m_brushquake1;
345 typedef BrushCreator Type;
346 STRING_CONSTANT( Name, "quake" );
349 Brush_Construct( eBrushTypeQuake );
351 m_brushquake1 = &GetBrushCreator();
356 BrushCreator* getTable(){
357 return m_brushquake1;
361 typedef SingletonModule<BrushQuake1API, BrushDependencies> BrushQuake1Module;
362 typedef Static<BrushQuake1Module> StaticBrushQuake1Module;
363 StaticRegisterModule staticRegisterBrushQuake1( StaticBrushQuake1Module::instance() );
366 class BrushHalfLifeAPI : public TypeSystemRef
368 BrushCreator* m_brushhalflife;
370 typedef BrushCreator Type;
371 STRING_CONSTANT( Name, "halflife" );
374 Brush_Construct( eBrushTypeHalfLife );
376 m_brushhalflife = &GetBrushCreator();
381 BrushCreator* getTable(){
382 return m_brushhalflife;
386 typedef SingletonModule<BrushHalfLifeAPI, BrushDependencies> BrushHalfLifeModule;
387 typedef Static<BrushHalfLifeModule> StaticBrushHalfLifeModule;
388 StaticRegisterModule staticRegisterBrushHalfLife( StaticBrushHalfLifeModule::instance() );