/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "brushmodule.h" #include "qerplugin.h" #include "brushnode.h" #include "brushmanip.h" #include "preferencesystem.h" #include "stringio.h" #include "map.h" #include "qe3.h" #include "mainframe.h" #include "preferences.h" LatchedValue g_useAlternativeTextureProjection(false, "Use alternative texture-projection (\"brush primitives\")"); static int g_numbrushtypes = 0; static int g_selectedbrushtype; static EBrushType g_brushTypes[8], g_brushType; //bool g_showAlternativeTextureProjectionOption = false; bool g_brush_always_caulk; bool getTextureLockEnabled() { return g_brush_texturelock_enabled; } struct Face_SnapPlanes { static void Export(const QuantiseFunc &self, const Callback &returnz) { returnz(self == quantiseInteger); } static void Import(QuantiseFunc &self, bool value) { self = value ? quantiseInteger : quantiseFloating; } }; const char* BrushType_getName( EBrushType type ){ switch ( type ) { case eBrushTypeQuake: case eBrushTypeQuake2: case eBrushTypeQuake3: return "Axial Projection"; case eBrushTypeQuake3BP: return "Brush Primitives"; case eBrushTypeQuake3Valve: case eBrushTypeHalfLife: return "Valve 220"; case eBrushTypeDoom3: return "Doom3"; case eBrushTypeQuake4: return "Quake4"; default: return "unknown"; } } void Brush_constructPreferences(PreferencesPage &page) { page.appendCheckBox( "", "Snap planes to integer grid", make_property(Face::m_quantise) ); page.appendEntry( "Default texture scale", g_texdef_default_scale ); if (g_numbrushtypes > 1) { const char *names[8]; for(int i = 0; i < g_numbrushtypes; i++) names[i] = BrushType_getName(g_brushTypes[i]); page.appendCombo("Default Brush Type", g_selectedbrushtype, StringArrayRange(names, names+g_numbrushtypes)); } // d1223m page.appendCheckBox("", "Always use caulk for new brushes", g_brush_always_caulk ); } void Brush_constructPage(PreferenceGroup &group) { PreferencesPage page(group.createPage("Brush", "Brush Settings")); Brush_constructPreferences(page); } void Brush_registerPreferencesPage() { PreferencesDialog_addSettingsPage(makeCallbackF(Brush_constructPage)); } void Brush_unlatchPreferences() { Brush_toggleFormat(0); } void Brush_setFormat(EBrushType t) { if (g_numbrushtypes) { // g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i; Brush::destroyStatic(); g_brushType = t; Brush::constructStatic(t); } } void Brush_toggleFormat(int i) { if (g_numbrushtypes) { // g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i; Brush::destroyStatic(); g_brushType = g_brushTypes[i]; Brush::constructStatic(g_brushType); } } int Brush_toggleFormatCount() { if (g_numbrushtypes) { return g_numbrushtypes; } return 1; } static void Brush_Construct(void) { EBrushType type = g_brushType = g_brushTypes[g_selectedbrushtype]; // d1223m GlobalPreferenceSystem().registerPreference( "BrushAlwaysCaulk", make_property_string(g_brush_always_caulk) ); Brush_registerCommands(); Brush_registerPreferencesPage(); BrushFilters_construct(); BrushClipPlane::constructStatic(); BrushInstance::constructStatic(); Brush::constructStatic(type); Brush::m_maxWorldCoord = g_MaxWorldCoord; BrushInstance::m_counter = &g_brushCount; g_texdef_default_scale = 0.5f; const char *value = g_pGameDescription->getKeyValue("default_scale"); if (!string_empty(value)) { float scale = static_cast( atof(value)); if (scale != 0) { g_texdef_default_scale = scale; } else { globalErrorStream() << "error parsing \"default_scale\" attribute\n"; } } GlobalPreferenceSystem().registerPreference("TextureLock", make_property_string(g_brush_texturelock_enabled)); GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", make_property_string(Face::m_quantise)); GlobalPreferenceSystem().registerPreference("TexdefDefaultScale", make_property_string(g_texdef_default_scale)); GridStatus_getTextureLockEnabled = getTextureLockEnabled; g_texture_lock_status_changed = makeCallbackF(GridStatus_onTextureLockEnabledChanged); } static void Brush_Construct(EBrushType type0, EBrushType type1, EBrushType type2) { g_numbrushtypes = 0; g_brushTypes[g_numbrushtypes++] = type0; if (type1 != type0) g_brushTypes[g_numbrushtypes++] = type1; if (type2 != type0 && type2 != type1) g_brushTypes[g_numbrushtypes++] = type2; if (g_numbrushtypes) { const char *value = g_pGameDescription->getKeyValue("brush_primit"); if (!string_empty(value)) { g_selectedbrushtype = atoi(value); if (g_selectedbrushtype < 0 || g_selectedbrushtype >= g_numbrushtypes) g_selectedbrushtype = 0; } // GlobalPreferenceSystem().registerPreference( // "BrushType", // make_property(g_selectedbrushtype) // ); } Brush_Construct(); } static void Brush_Construct(EBrushType type0, EBrushType type1) { Brush_Construct(type0, type1, type0); } static void Brush_Construct(EBrushType type0) { Brush_Construct(type0, type0, type0); } void Brush_Destroy() { Brush::m_maxWorldCoord = 0; BrushInstance::m_counter = 0; Brush::destroyStatic(); BrushInstance::destroyStatic(); BrushClipPlane::destroyStatic(); } void Brush_clipperColourChanged() { BrushClipPlane::destroyStatic(); BrushClipPlane::constructStatic(); } void BrushFaceData_fromFace(const BrushFaceDataCallback &callback, Face &face) { _QERFaceData faceData; faceData.m_p0 = face.getPlane().planePoints()[0]; faceData.m_p1 = face.getPlane().planePoints()[1]; faceData.m_p2 = face.getPlane().planePoints()[2]; faceData.m_shader = face.GetShader(); faceData.m_texdef = face.getTexdef().m_projection.m_texdef; faceData.contents = face.getShader().m_flags.m_contentFlags; faceData.flags = face.getShader().m_flags.m_surfaceFlags; faceData.value = face.getShader().m_flags.m_value; callback(faceData); } typedef ConstReferenceCaller BrushFaceDataFromFaceCaller; typedef Callback FaceCallback; class Quake3BrushCreator : public BrushCreator { public: scene::Node &createBrush() { return (new BrushNode)->node(); } virtual EBrushType getBrushType() { return g_brushType; } virtual void setBrushType(EBrushType t) { if (g_brushType != t) Brush_setFormat(t); } void Brush_forEachFace(scene::Node &brush, const BrushFaceDataCallback &callback) { ::Brush_forEachFace(*Node_getBrush(brush), FaceCallback(BrushFaceDataFromFaceCaller(callback))); } bool Brush_addFace(scene::Node &brush, const _QERFaceData &faceData) { Node_getBrush(brush)->undoSave(); 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; } }; Quake3BrushCreator g_Quake3BrushCreator; BrushCreator &GetBrushCreator() { return g_Quake3BrushCreator; } #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" class BrushDependencies : public GlobalRadiantModuleRef, public GlobalSceneGraphModuleRef, public GlobalShaderCacheModuleRef, public GlobalSelectionModuleRef, public GlobalOpenGLModuleRef, public GlobalUndoModuleRef, public GlobalFilterModuleRef { }; class BrushDoom3API : public TypeSystemRef { BrushCreator *m_brushdoom3; public: typedef BrushCreator Type; STRING_CONSTANT(Name, "doom3"); BrushDoom3API() { Brush_Construct(eBrushTypeDoom3); m_brushdoom3 = &GetBrushCreator(); } ~BrushDoom3API() { Brush_Destroy(); } BrushCreator *getTable() { return m_brushdoom3; } }; typedef SingletonModule BrushDoom3Module; typedef Static StaticBrushDoom3Module; StaticRegisterModule staticRegisterBrushDoom3(StaticBrushDoom3Module::instance()); class BrushQuake4API : public TypeSystemRef { BrushCreator *m_brushquake4; public: typedef BrushCreator Type; STRING_CONSTANT(Name, "quake4"); BrushQuake4API() { Brush_Construct(eBrushTypeQuake4); m_brushquake4 = &GetBrushCreator(); } ~BrushQuake4API() { Brush_Destroy(); } BrushCreator *getTable() { return m_brushquake4; } }; typedef SingletonModule BrushQuake4Module; typedef Static StaticBrushQuake4Module; StaticRegisterModule staticRegisterBrushQuake4(StaticBrushQuake4Module::instance()); class BrushQuake3API : public TypeSystemRef { BrushCreator *m_brushquake3; public: typedef BrushCreator Type; STRING_CONSTANT(Name, "quake3"); BrushQuake3API() { Brush_Construct(eBrushTypeQuake3, eBrushTypeQuake3BP, eBrushTypeQuake3Valve); m_brushquake3 = &GetBrushCreator(); } ~BrushQuake3API() { Brush_Destroy(); } BrushCreator *getTable() { return m_brushquake3; } }; typedef SingletonModule BrushQuake3Module; typedef Static StaticBrushQuake3Module; StaticRegisterModule staticRegisterBrushQuake3(StaticBrushQuake3Module::instance()); class BrushQuake2API : public TypeSystemRef { BrushCreator *m_brushquake2; public: typedef BrushCreator Type; STRING_CONSTANT(Name, "quake2"); BrushQuake2API() { Brush_Construct(eBrushTypeQuake2); m_brushquake2 = &GetBrushCreator(); } ~BrushQuake2API() { Brush_Destroy(); } BrushCreator *getTable() { return m_brushquake2; } }; typedef SingletonModule BrushQuake2Module; typedef Static StaticBrushQuake2Module; StaticRegisterModule staticRegisterBrushQuake2(StaticBrushQuake2Module::instance()); class BrushQuake1API : public TypeSystemRef { BrushCreator *m_brushquake1; public: typedef BrushCreator Type; STRING_CONSTANT(Name, "quake"); BrushQuake1API() { Brush_Construct(eBrushTypeQuake, eBrushTypeHalfLife); m_brushquake1 = &GetBrushCreator(); } ~BrushQuake1API() { Brush_Destroy(); } BrushCreator *getTable() { return m_brushquake1; } }; typedef SingletonModule BrushQuake1Module; typedef Static StaticBrushQuake1Module; StaticRegisterModule staticRegisterBrushQuake1(StaticBrushQuake1Module::instance()); class BrushHalfLifeAPI : public TypeSystemRef { BrushCreator *m_brushhalflife; public: typedef BrushCreator Type; STRING_CONSTANT(Name, "halflife"); BrushHalfLifeAPI() { Brush_Construct(eBrushTypeHalfLife); m_brushhalflife = &GetBrushCreator(); } ~BrushHalfLifeAPI() { Brush_Destroy(); } BrushCreator *getTable() { return m_brushhalflife; } }; typedef SingletonModule BrushHalfLifeModule; typedef Static StaticBrushHalfLifeModule; StaticRegisterModule staticRegisterBrushHalfLife(StaticBrushHalfLifeModule::instance());