/* Copyright (C) 1999-2007 id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. 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 */ // // User preferences // // Leonardo Zide (leo@lokigames.com) // #include "stdafx.h" #include #include #include #if defined ( __linux__ ) || defined ( __APPLE__ ) #include #include #include #include #include #endif #include "missing.h" #include "gtkmisc.h" #ifdef _WIN32 #include #define X_OK 0 #include #endif #define PREF_SECTION "Prefs" #define INTERNAL_SECTION "Internals" #define MOUSE_KEY "MouseButtons" #define WINDOW_KEY "QE4StyleWindows" #define LAYOUT_KEY "WindowLayout" #define RUNQ2_KEY "RunQuake2Run" #define TLOCK_KEY "TextureLock" #define RLOCK_KEY "RotateLock" #define LOADLAST_KEY "LoadLast" #define LOADLASTMAP_KEY "LoadLastMap" #define LASTPROJ_KEY "LastProject" #define LASTPROJVER_KEY "LastProjectKey" #define LASTMAP_KEY "LastMap" #define FACE_KEY "NewFaceGrab" #define BSP_KEY "InternalBSP" #define RCLICK_KEY "NewRightClick" #define VERTEX_KEY "NewVertex" #define AUTOSAVE_KEY "Autosave" #define AUTOSAVETIME_KEY "AutosaveMinutes" #define PAK_KEY "UsePAK" #define NEWAPPLY_KEY "ApplyDismissesSurface" #define HACK_KEY "Gatewayescapehack" #define TEXTURE_KEY "NewTextureWindowStuff" #define TINYBRUSH_KEY "CleanTinyBrushes" #define TINYSIZE_KEY "CleanTinyBrusheSize" #define SNAPSHOT_KEY "Snapshots" #define MOVESPEED_KEY "MoveSpeed" #define ANGLESPEED_KEY "AngleSpeed" #define SETGAME_KEY "UseSetGame" #define CAMXYUPDATE_KEY "CamXYUpdate" #define CAMDRAGMULTISELECT_KEY "CamDragMultiSelect" #define CAMFREELOOK_KEY "CamFreeLook" #define CAMINVERSEMOUSE_KEY "CamInverseMouse" #define CAMDISCRETE_KEY "CamDiscrete" #define LIGHTDRAW_KEY "NewLightStyle" #define WHATGAME_KEY "WhichGame" #define CUBICCLIP_KEY "CubicClipping" #define CUBICSCALE_KEY "CubicScale" #define ALTEDGE_KEY "ALTEdgeDrag" #define FACECOLORS_KEY "FaceColors" #define SNAPT_KEY "SnapT" #define XZVIS_KEY "XZVIS" #define YZVIS_KEY "YZVIS" #define ZVIS_KEY "ZVIS" #define SIZEPAINT_KEY "SizePainting" #define DLLENTITIES_KEY "DLLEntities" #define DETACHABLEMENUS_KEY "DetachableMenus" #define PATCHTOOLBAR_KEY "PatchToolBar" #define WIDETOOLBAR_KEY "WideToolBar" #define PLUGINTOOLBAR_KEY "PluginToolBar" #define NOCLAMP_KEY "NoClamp" #define SNAP_KEY "Snap" #define PREFAB_KEY "PrefabPath" #define USERINI_KEY "UserINIPath" #define ROTATION_KEY "Rotation" #define BUGGYICD_KEY "BuggyICD" #define CHASEMOUSE_KEY "ChaseMouse" #define ENTITYSHOW_KEY "EntityShow" #define TEXTURESCALE_KEY "TextureScale" #define TEXTURESCROLLBAR_KEY "TextureScrollbar" #define DISPLAYLISTS_KEY "UseDisplayLists" #define ANTIALIASEDLINES_KEY "UseAntialiasedPointsAndLines" // Fishman - Add antialiazed points and lines support. 09/03/00 #define NORMALIZECOLORS_KEY "NormalizeColors" #define SHADERS_KEY "UseShaders" #define SWITCHCLIP_KEY "SwitchClipKey" #define SELWHOLEENTS_KEY "SelectWholeEntitiesKey" #define TEXTURESUBSET_KEY "UseTextureSubsetLoading" #define TEXTUREQUALITY_KEY "TextureQuality" #define SHOWSHADERS_KEY "ShowShaders" #define SHADERTEST_KEY "ShaderTest" #define GLLIGHTING_KEY "UseGLLighting" #define LOADSHADERS_KEY "LoadShaders" #define NOSTIPPLE_KEY "NoStipple" #define UNDOLEVELS_KEY "UndoLevels" #define VERTEXMODE_KEY "VertexSplit" #define ENGINEPATH_KEY "EnginePath" #define ENGINE_KEY "Engine" #define LOGCONSOLE_KEY "LogConsole" #define SELECTCURVES_KEY "SelectCurves" #define SELECTMODELS_KEY "SelectModels" #define SHADERLISTONLY_KEY "ShowShaderlistOnly" #define WATCHBSP_KEY "WatchBSP" #define LEAKSTOP_KEY "LeakStop" #define DOSLEEP_KEY "SleepMode" #define SUBDIVISIONS_KEY "Subdivisions" #define DEFAULTTEXURESCALE_KEY "DefaultTextureScale" #define CLIPCAULK_KEY "ClipCaulk" #define PATCHSHOWBOUNDS_KEY "PatchShowBounds" #define NATIVEGUI_KEY "NativeGUI" #define STARTONPRIMMON_KEY "StartOnPrimMon" #define NOSYSMENUPOPUPS_KEY "NoSysMenuPopups" #define SNAPTTOGRID_KEY "SnapTToGrid" #define FLOATINGZ_KEY "FloatingZ" #define TARGETFIX_KEY "TargetFix" #define GLPOINTWORKAROUND_KEY "GlPointWorkaround" // Gef: Workaround for broken Kyro * gl driver 25-aug-2001 #define WHEELINC_KEY "WheelMouseInc" #define PATCHBBOXSEL_KEY "PatchBBoxSel" #define LASTLIGHTINTENSITY_KEY "LastLightIntensity" #define CUSTOMSHADEREDITOR_KEY "UseCustomShaderEditor" #define CUSTOMSHADEREDITORCOMMAND_KEY "CustomShaderEditorCommand" #define TEXTURECOMPRESSIONFORMAT_KEY "TextureCompressionFormat" #define LIGHTRADIUS_KEY "LightRadiuses" #define Q3MAP2TEX_KEY "Q3Map2Tex" #ifdef ATIHACK_812 #define ATIHACK_KEY "ATIHack" #endif #ifdef NVIDIA_AERO_HACK #define NVAEROHACK_KEY "NvidiaAeroHack" #endif // window stuff #define ENTITYSPLIT1_KEY "EntitySplit1" #define ENTITYSPLIT2_KEY "EntitySplit2" #define POSITIONX_KEY "PositionX" #define POSITIONY_KEY "PositionY" #define ENTITYWND_KEY "EntityWnd" #define MAPINFOWND_KEY "MapInfoDlg" #define CAMWND_KEY "CamWnd" #define ZWND_KEY "ZWnd" #define XYWND_KEY "XYWnd" #define XZWND_KEY "XZWnd" #define YZWND_KEY "YZWnd" #define PATCHWND_KEY "PatchWnd" #define SURFACEWND_KEY "SurfaceWnd" #define ENTITYINFOWND_KEY "EntityInfoDlg" #define WIDTH_KEY "Width" #define HEIGHT_KEY "Height" #define ZWIDTH_KEY "ZWidth" #define XYHEIGHT_KEY "XYHeight" #define XYWIDTH_KEY "XYWidth" #define CAMWIDTH_KEY "CamWidth" #define CAMHEIGHT_KEY "CamHeight" #define ZFLOATWIDTH_KEY "ZWidthFloating" #define STATE_KEY "State" // menu stuff #define COUNT_KEY "Count" #define FILE_KEY "File" //saved info #define SI_TEXMENU_KEY "SI_TexMenu" #define SI_GAMMA_KEY "SI_Gamma" #define SI_COLORS_KEY "SI_Colors" #define SI_EXCLUDE_KEY "SI_Exclude" #define SI_INCLUDE_KEY "SI_Include" #define SI_SURFACE_TEXDEF_KEY "SI_SurfaceTexdef" #define SI_PATCH_TEXDEF_KEY "SI_PatchTexdef" #define SI_AXISCOLORS_KEY "SI_AxisColors" #define SI_SHOWNAMES_KEY "SI_ShowNames" #define SI_SHOWCOORDS_KEY "SI_ShowCoords" #define SI_SHOWANGLES_KEY "SI_ShowAngles" #define SI_SHOWOUTLINES_KEY "SI_ShowOutlines" #define SI_SHOWAXIS_KEY "SI_ShowAxis" #define SI_NOSELOUTLINES_KEY "SI_NoSelectedOutlines" #define SI_OUTLINESTYLE_KEY "SI_OutLineStyle" //for texdefs #define TD_SCALE1_KEY "_Scale1" #define TD_SCALE2_KEY "_Scale2" #define TD_SHIFT1_KEY "_Shift1" #define TD_SHIFT2_KEY "_Shift2" #define TD_ROTATE_KEY "_Rotate" #define MOUSE_DEF 1 #define WINDOW_DEF 0 #define RUNQ2_DEF 0 #define WATCHBSP_DEF 1 #define TLOCK_DEF 1 #define LOADLAST_DEF 1 #define RUN_DEF 0 #define SUBDIVISIONS_DEF 4 void WindowPosition_Parse( window_position_t& m_value, const CString& value ){ if ( sscanf( value.GetBuffer(), "%d %d %d %d", &m_value.x, &m_value.y, &m_value.w, &m_value.h ) != 4 ) { m_value.x = m_value.y = m_value.w = m_value.h = -1; } } void WindowPosition_Write( const window_position_t& m_value, CString& value ){ char buffer[64]; sprintf( buffer, "%d %d %d %d", m_value.x, m_value.y, m_value.w, m_value.h ); value = buffer; } CXMLPropertyBag::CXMLPropertyBag() { mStrFilename = ""; mpDoc = NULL; mbEmpty = false; } // generic preference functions void CXMLPropertyBag::PushAssignment( const char *name, PrefTypes_t type, void *pV ){ list::iterator iAssign; for ( iAssign = mPrefAssignments.begin(); iAssign != mPrefAssignments.end(); iAssign++ ) { if ( ( *iAssign ).mName == name ) { // we have it already, check anyway if ( pV != ( *iAssign ).mVal ) { Sys_FPrintf( SYS_ERR, "PushAssignment, '%s' has different mVal\n", name ); return; } } } // ok, it's not in our list yet mPrefAssignments.push_front( CPrefAssignment( name, type, pV ) ); } xmlNodePtr CXMLPropertyBag::EpairForName( const char *name ){ xmlNodePtr ret = NULL; xmlNodePtr pNode = mpDocNode->children; while ( pNode != NULL ) { if ( pNode->type == XML_ELEMENT_NODE ) { xmlAttrPtr tmp_attr_ptr = xmlHasProp( pNode, (xmlChar *)"name" ); if ( tmp_attr_ptr != NULL && !strcmp( name, (char *)tmp_attr_ptr->children->content ) ) { if ( ret ) { Sys_FPrintf( SYS_WRN, "WARNING: dupe property in CXMLPropertyBag::EpairForName '%s'\n", name ); } else { ret = pNode; } } } pNode = pNode->next; } return ret; } void CXMLPropertyBag::GetPref( const char *name, Str *pV, const char *V ){ xmlNodePtr pNode = EpairForName( name ); if ( pNode ) { if ( pNode->children && pNode->children->content ) { *pV = pNode->children->content; } else { // means the pref exists, and that the value is "" *pV = ""; } } else { pNode = xmlNewChild( mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)V ); xmlSetProp( pNode, (xmlChar *)"name", (xmlChar *)name ); } // push the pref assignment if needed PushAssignment( name, PREF_STR, pV ); } void CXMLPropertyBag::GetPref( const char *name, int *pV, int V ){ xmlNodePtr pNode; if ( ( pNode = EpairForName( name ) ) && pNode->children && pNode->children->content ) { *pV = atoi( (char *)pNode->children->content ); } else { char s[10]; sprintf( s, "%d", V ); pNode = xmlNewChild( mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s ); xmlSetProp( pNode, (xmlChar *)"name", (xmlChar *)name ); *pV = V; } // push the pref assignment if needed PushAssignment( name, PREF_INT, pV ); } void CXMLPropertyBag::GetPref( const char *name, bool *pV, bool V ){ xmlNodePtr pNode; if ( ( pNode = EpairForName( name ) ) && pNode->children && pNode->children->content ) { if ( !strcmp( (char *)pNode->children->content, "true" ) ) { *pV = true; } else { *pV = false; } } else { char s[10]; V ? strcpy( s, "true" ) : strcpy( s, "false" ); pNode = xmlNewChild( mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s ); xmlSetProp( pNode, (xmlChar *)"name", (xmlChar *)name ); *pV = V; } // push the pref assignment PushAssignment( name, PREF_BOOL, pV ); } void CXMLPropertyBag::GetPref( const char *name, float *pV, float V ){ xmlNodePtr pNode; if ( ( pNode = EpairForName( name ) ) && pNode->children && pNode->children->content ) { *pV = atof( (char *)pNode->children->content ); } else { char s[10]; sprintf( s, "%f", V ); pNode = xmlNewChild( mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s ); xmlSetProp( pNode, (xmlChar *)"name", (xmlChar *)name ); *pV = V; } // push the pref assignment if needed PushAssignment( name, PREF_FLOAT, pV ); } void CXMLPropertyBag::GetPref( const char *name, float* pV, float* V ){ xmlNodePtr pNode; if ( ( pNode = EpairForName( name ) ) && pNode->children && pNode->children->content ) { sscanf( (char *)pNode->children->content, "%f %f %f", &pV[0], &pV[1], &pV[2] ); } else { char s[128]; sprintf( s, "%f %f %f", V[0], V[1], V[2] ); pNode = xmlNewChild( mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s ); xmlSetProp( pNode, (xmlChar *)"name", (xmlChar *)name ); pV[0] = V[0]; pV[1] = V[1]; pV[2] = V[2]; } // push the pref assignment if needed PushAssignment( name, PREF_VEC3, pV ); } void CXMLPropertyBag::GetPref( const char *name, window_position_t* pV, window_position_t V ){ xmlNodePtr pNode; if ( ( pNode = EpairForName( name ) ) && pNode->children && pNode->children->content ) { WindowPosition_Parse( *pV, CString( (xmlChar *)pNode->children->content ) ); } else { CString str; WindowPosition_Write( V, str ); pNode = xmlNewChild( mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)str.GetBuffer() ); xmlSetProp( pNode, (xmlChar *)"name", (xmlChar *)name ); *pV = V; } // push the pref assignment if needed PushAssignment( name, PREF_WNDPOS, pV ); } void CXMLPropertyBag::UpdatePrefTree(){ // read the assignments and update the tree list::iterator iPref; for ( iPref = mPrefAssignments.begin(); iPref != mPrefAssignments.end(); iPref++ ) { CPrefAssignment *pPref = &( *iPref ); // look for the node xmlNodePtr pNode; char s[64]; pNode = EpairForName( pPref->mName.GetBuffer() ); // we never expect that the node could not be found, because this is supposed to happen // after the tree was built with GetPref calls, never on a blank tree if ( !pNode ) { Sys_FPrintf( SYS_ERR, "Unexpected EpairForName '%s' not found in UpdatePrefTree\n", pPref->mName.GetBuffer() ); return; } switch ( ( *iPref ).mType ) { case PREF_STR: xmlNodeSetContent( pNode, (const xmlChar *)( (Str *)pPref->mVal )->GetBuffer() ); break; case PREF_INT: sprintf( s, "%d", *(int *)pPref->mVal ); xmlNodeSetContent( pNode, (xmlChar *)s ); break; case PREF_FLOAT: sprintf( s, "%f", *(float *)pPref->mVal ); xmlNodeSetContent( pNode, (xmlChar *)s ); break; case PREF_BOOL: *(bool *)pPref->mVal ? strcpy( s, "true" ) : strcpy( s, "false" ); xmlNodeSetContent( pNode, (xmlChar *)s ); break; case PREF_VEC3: { float* v = (float*)pPref->mVal; sprintf( s, "%f %f %f", v[0], v[1], v[2] ); xmlNodeSetContent( pNode, (xmlChar *)s ); } break; case PREF_WNDPOS: { CString str; WindowPosition_Write( *(window_position_t*)pPref->mVal, str ); xmlNodeSetContent( pNode, (xmlChar*)str.GetBuffer() ); } break; } } } void CXMLPropertyBag::Clear(){ if ( !InUse() ) { return; } xmlFreeDoc( mpDoc ); mpDoc = NULL; mpDocNode = NULL; mbEmpty = false; } void CXMLPropertyBag::ReadXMLFile( const char* pFilename ){ mpDoc = xmlParseFile( pFilename ); // basic checks if ( mpDoc ) { mpDocNode = mpDoc->children; xmlAttrPtr tmp_attr_ptr = xmlHasProp( mpDocNode, (xmlChar *)"version" ); if ( strcmp( (char *)mpDocNode->name, "qpref" ) ) { Sys_FPrintf( SYS_ERR, "Unrecognized node '%s' in '%s'\n", mpDocNode->name, mpDoc->URL ); xmlFreeDoc( mpDoc ); mpDoc = NULL; } else if ( tmp_attr_ptr != NULL && strcmp( (char*)tmp_attr_ptr->children->content, "1" ) ) { Sys_FPrintf( SYS_ERR, "Wrong version '%s' in node for '%s'\n", (char*)tmp_attr_ptr->children->content, mpDoc->URL ); xmlFreeDoc( mpDoc ); mpDoc = NULL; } Sys_Printf( "Opened XML property file: '%s'\n", pFilename ); } if ( !mpDoc ) { mbEmpty = true; // no document, create one mpDoc = xmlNewDoc( (xmlChar *)"1.0" ); mpDocNode = xmlNewDocNode( mpDoc, NULL, (xmlChar *)"qpref", NULL ); xmlDocSetRootElement( mpDoc, mpDocNode ); xmlSetProp( mpDocNode, (xmlChar *)"version", (xmlChar *)"1" ); Sys_Printf( "XML property file '%s' invalid/not found, creating blank properties tree\n", pFilename ); } } qboolean CXMLPropertyBag::WriteXMLFile( const char* pFilename ){ int res = xmlSaveFormatFile( pFilename, mpDoc, 1 ); if ( res == -1 ) { return false; } Sys_Printf( "Wrote XML property file '%s'\n", pFilename ); return true; } // ============================================================================= // Widget callbacks for PrefsDlg #if !defined( WIN32 ) // browse for custom editor executable static void OnBtnBrowseEditor( GtkWidget *widget, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; const char *filename = file_dialog( g_PrefsDlg.GetWidget(), TRUE, _( "Executable for Custom Editor" ) ); if ( filename != NULL ) { dlg->m_strEditorCommand = filename; dlg->UpdateData( FALSE ); } } #endif static void OnBtnBrowseprefab( GtkWidget *widget, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; char *path = dlg->m_strPrefabPath; if ( strlen( path ) == 0 ) { path = g_strGameToolsPath; } char *dir = dir_dialog( g_PrefsDlg.GetWidget(), _( "Set prefab path" ), path ); dlg->UpdateData( TRUE ); if ( dir != NULL ) { CString strPath; strPath = dir; AddSlash( strPath ); dlg->m_strPrefabPath = strPath; dlg->UpdateData( FALSE ); free( dir ); } } static void OnBtnBrowseuserini( GtkWidget *widget, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; char *path = dlg->m_strUserPath; if ( strlen( path ) == 0 ) { path = g_strGameToolsPath; } // TODO: INI filter? const char *filename = file_dialog( g_PrefsDlg.GetWidget(), TRUE, _( "Find INI file" ), path ); if ( filename != NULL ) { dlg->UpdateData( TRUE ); dlg->m_strUserPath = filename; dlg->UpdateData( FALSE ); } } static void OnButtonClean( GtkWidget *widget, gpointer data ){ // make sure this is what the user wants if ( gtk_MessageBox( g_PrefsDlg.GetWidget(), _( "This will close Radiant and clean the corresponding registry entries.\n" "Next time you start Radiant it will be good as new. Do you wish to continue?" ), _( "Reset Registry" ), MB_YESNO ) == IDYES ) { PrefsDlg *dlg = (PrefsDlg*)data; dlg->EndModal( IDCANCEL ); g_qeglobals.disable_ini = true; remove( dlg->m_inipath->str ); char buf[PATH_MAX]; sprintf( buf, "%sSavedInfo.bin", dlg->m_rc_path->str ); remove( buf ); HandleCommand( NULL, GINT_TO_POINTER( ID_FILE_EXIT ) ); _exit( 0 ); } } // ============================================================================= // PrefsDlg class // IMPORTANT NOTE: the values here don't matter very much // the actual intialization if you start with an empty .ini is done when loading the prefs for the first time // profile_load_int takes an argument to use if the value is not found PrefsDlg::PrefsDlg (){ m_bWarn = TRUE; m_nMouse = 1; m_nView = MainFrame::eRegular; m_bLoadLast = FALSE; m_bInternalBSP = FALSE; m_bRightClick = FALSE; m_bSetGame = FALSE; m_bAutoSave = TRUE; m_nAutoSave = 5; m_bLoadLastMap = FALSE; m_bTextureWindow = FALSE; m_bSnapShots = FALSE; m_fTinySize = 0.5; m_bCleanTiny = FALSE; m_bCamXYUpdate = TRUE; m_bCamDragMultiSelect = FALSE; m_bCamFreeLook = TRUE; m_bCamFreeLookStrafe = FALSE; m_bCamInverseMouse = FALSE; m_bCamDiscrete = TRUE; m_bNewLightDraw = FALSE; m_strPrefabPath = ""; m_nWhatGame = 0; m_bALTEdge = FALSE; m_bFaceColors = FALSE; m_bXZVis = FALSE; m_bYZVis = FALSE; m_bZVis = FALSE; m_bSizePaint = FALSE; m_bDLLEntities = FALSE; #ifdef _WIN32 m_bDetachableMenus = FALSE; // Most win32 users will find detachable menus annoying #else m_bDetachableMenus = TRUE; // Linux/Apple users are used to them... #endif m_bPatchToolbar = TRUE; m_bWideToolbar = TRUE; m_bPluginToolbar = TRUE; m_bNoClamp = FALSE; m_bSnap = TRUE; m_strUserPath = ""; m_nRotation = 0; m_bChaseMouse = FALSE; m_bTextureScrollbar = TRUE; m_bDisplayLists = TRUE; m_bAntialiasedPointsAndLines = FALSE; // Fishman - Add antialiazed points and lines support. 09/03/00 m_bShowShaders = FALSE; m_nShader = -1; m_bNoStipple = FALSE; m_bVertexSplit = FALSE; m_bSelectCurves = TRUE; m_bSelectModels = TRUE; m_nEntityShowState = ENTITY_SKINNED_BOXED; m_nTextureScale = 2; m_bSwitchClip = FALSE; m_bSelectWholeEntities = TRUE; m_nTextureQuality = 3; m_bShowShaders = TRUE; m_bGLLighting = FALSE; m_nShader = 0; m_nUndoLevels = 30; m_bTexturesShaderlistOnly = FALSE; // paths to ini files m_rc_path = NULL; m_inipath = NULL; m_bWatchBSP = TRUE; m_bLeakStop = TRUE; m_iTimeout = 15; m_bRunQuake = TRUE; m_bDoSleep = FALSE; m_nSubdivisions = 4; // not prefs m_bFloatingZ = FALSE; m_bGlPtWorkaround = FALSE; // Gef: Kyro/GL_POINTS workaround 25-aug-2001 #ifdef _WIN32 m_bNativeGUI = FALSE; m_bStartOnPrimMon = FALSE; #endif m_global_rc_path = NULL; #ifdef _WIN32 m_bUseWin32Editor = TRUE; #else // custom shader editor options m_bUseCustomEditor = FALSE; m_strEditorCommand = ""; #endif m_nLightRadiuses = 1; m_bQ3Map2Texturing = TRUE; #ifdef ATIHACK_812 m_bGlATIHack = FALSE; #endif #ifdef NVIDIA_AERO_HACK m_bGlNvidiaAeroHack = TRUE; m_bGlNvidiaAeroHackPrevState = -1; // -1 is uninitialized, 0 is FALSE, 1 is TRUE #endif } /*! ========================================================= Games selection dialog ========================================================= */ #if defined( WIN32 ) #define TOOLS_ATTRIBUTE "gametools_win32" #define ENGINE_ATTRIBUTE "engine_win32" #define ENGINEPATH_ATTRIBUTE "enginepath_win32" #define MP_ENGINE_ATTRIBUTE "mp_engine_win32" #elif defined( __linux__ ) || defined ( __FreeBSD__ ) #define TOOLS_ATTRIBUTE "gametools_linux" #define ENGINE_ATTRIBUTE "engine_linux" #define ENGINEPATH_ATTRIBUTE "enginepath_linux" #define MP_ENGINE_ATTRIBUTE "mp_engine_linux" #elif defined( __APPLE__ ) #define TOOLS_ATTRIBUTE "gametools_macos" #define ENGINE_ATTRIBUTE "engine_macos" #define ENGINEPATH_ATTRIBUTE "enginepath_macos" #define MP_ENGINE_ATTRIBUTE "mp_engine_macos" #else #error "unsupported platform" #endif CGameDescription::CGameDescription( xmlDocPtr pDoc, const Str &GameFile ){ char *p, *prop; mpDoc = pDoc; // read the user-friendly game name xmlNodePtr pNode = mpDoc->children; while ( strcmp( (const char*)pNode->name, "game" ) && pNode != NULL ) pNode = pNode->next; if ( !pNode ) { ///< \todo add the file name (this node and gametools should all be part of CGameDescription anyway) Error( "Didn't find 'game' node in the game description file '%s'\n", pDoc->URL ); } // on win32, game tools path can now be specified relative to the exe's cwd prop = (char*)xmlGetProp( pNode, (xmlChar*)TOOLS_ATTRIBUTE ); if ( prop == NULL ) { Error( "Didn't find '"TOOLS_ATTRIBUTE "' node in the game description file '%s'\n", pDoc->URL ); } { char full[PATH_MAX]; #ifdef _WIN32 _fullpath( full, prop, PATH_MAX ); #else strncpy( full, prop, PATH_MAX ); #endif xmlFree( prop ); prop = NULL; for ( p = full; *p != '\0'; p++ ) { if ( *p == '\\' ) { *p = '/'; } mGameToolsPath = full; if ( p != full && *( p - 1 ) != '/' ) { mGameToolsPath += "/"; } } } prop = (char*)xmlGetProp( pNode, (xmlChar*)"name" ); if ( prop == NULL ) { Sys_FPrintf( SYS_WRN, "Warning, 'name' attribute not found in '%s'\n", pDoc->URL ); mGameName = pDoc->URL; } else { mGameName = prop; xmlFree( prop ); } mGameFile = GameFile; prop = (char*)xmlGetProp( pNode, (xmlChar*)"quake2" ); if ( prop == NULL ) { // default quake2 = false; } else { quake2 = true; xmlFree( prop ); } // if this is set, the open maps dialoge will open the engine path not the // home dir for map loading and saving prop = (char*)xmlGetProp( pNode, (xmlChar*)"no_maps_in_home" ); if ( prop == NULL ) { // default noMapsInHome = false; } else { noMapsInHome = true; xmlFree( prop ); } prop = (char*)xmlGetProp( pNode, (xmlChar*)"basegame" ); if ( prop == NULL ) { // default mBaseGame = "baseq3"; } else { mBaseGame = prop; xmlFree( prop ); } prop = (char*)xmlGetProp( pNode, (const xmlChar*)ENGINE_ATTRIBUTE ); if ( prop == NULL ) { #ifdef _WIN32 mEngine = "quake3.exe"; #elif __linux__ mEngine = "quake3"; #elif __APPLE__ mEngine = "Quake3.app"; #endif } else { mEngine = prop; xmlFree( prop ); } prop = (char*)xmlGetProp( pNode, (const xmlChar*)MP_ENGINE_ATTRIBUTE ); if ( prop == NULL ) { #ifdef _WIN32 mMultiplayerEngine = "quake3.exe"; #elif __linux__ mMultiplayerEngine = "quake3"; #elif __APPLE__ mMultiplayerEngine = "Quake3.app"; #endif } else { mMultiplayerEngine = prop; xmlFree( prop ); } { // on win32, engine path can now be specified relative to the exe's cwd prop = (char*)xmlGetProp( pNode, (const xmlChar *)ENGINEPATH_ATTRIBUTE ); if ( prop != NULL ) { char full[PATH_MAX]; #ifdef _WIN32 _fullpath( full, prop, PATH_MAX ); #else strncpy( full, prop, PATH_MAX ); #endif xmlFree( prop ); prop = NULL; // process seperators for ( p = full; *p != '\0'; p++ ) { if ( *p == '\\' ) { *p = '/'; } } mEnginePath = full; if ( p != full && *( p - 1 ) != '/' ) { mEnginePath += "/"; } } else { // if engine path was not specified in the .game, it implies we can guess it from the gametools path // on win32, and for most game package, the gametools are installed with the game char aux_path[PATH_MAX]; // aux strcpy( aux_path, mGameToolsPath.GetBuffer() ); if ( ( aux_path[ strlen( aux_path ) - 1 ] == '/' ) || ( aux_path[ strlen( aux_path ) - 1 ] == '\\' ) ) { aux_path[strlen( aux_path ) - 1] = '\0'; // strip ending '/' if any } char up_path[PATH_MAX]; // up one level ExtractFilePath( aux_path, up_path ); mEnginePath = up_path; } } #if defined ( __linux__ ) || defined ( __APPLE__ ) // *nix specific prop = (char*)xmlGetProp( pNode, (const xmlChar *)"prefix" ); if ( prop != NULL ) { mUserPathPrefix = prop; xmlFree( prop ); } #endif mShaderPath = xmlGetProp( pNode, (const xmlChar *)"shaderpath" ); if ( !mShaderPath.GetLength() ) { mShaderPath = "scripts/"; mShaderlist = "scripts/shaderlist.txt"; } else { AddSlash( mShaderPath ); mShaderlist = mShaderPath; mShaderlist += "shaderlist.txt"; } xmlChar* default_scale = xmlGetProp( pNode, (const xmlChar *)"default_scale" ); if ( default_scale ) { mTextureDefaultScale = atof( (const char *)default_scale ); xmlFree( default_scale ); } else{ mTextureDefaultScale = 0.5f; } xmlChar* eclass_singleload = xmlGetProp( pNode, (const xmlChar*)"eclass_singleload" ); if ( eclass_singleload ) { mEClassSingleLoad = true; xmlFree( eclass_singleload ); } else{ mEClassSingleLoad = false; } xmlChar* no_patch = xmlGetProp( pNode, (const xmlChar *)"no_patch" ); if ( no_patch ) { mNoPatch = true; xmlFree( no_patch ); } else{ mNoPatch = false; } xmlChar* caulk_shader = xmlGetProp( pNode, (const xmlChar *)"caulk_shader" ); if ( caulk_shader ) { mCaulkShader = caulk_shader; xmlFree( caulk_shader ); } else{ mCaulkShader = "textures/common/caulk"; } } void CGameDescription::Dump(){ #ifdef _WIN32 if ( CGameDialog::GetNetrun() ) { Sys_Printf( "Running in network mode, prefs path set to '%s'\n", g_strTempPath.GetBuffer() ); } #endif Sys_Printf( "game name : '%s'\n", mGameName.GetBuffer() ); Sys_Printf( "game file : '%s'\n", mGameFile.GetBuffer() ); Sys_Printf( "game path : '%s'\n", mGameToolsPath.GetBuffer() ); Sys_Printf( "base game : '%s'\n", mBaseGame.GetBuffer() ); Sys_Printf( "engine path : '%s'\n", mEnginePath.GetBuffer() ); Sys_Printf( "engine : '%s'\n", mEngine.GetBuffer() ); Sys_Printf( "shaderlist : '%s'\n", mShaderlist.GetBuffer() ); Sys_Printf( "caulk shader: '%s'\n", mCaulkShader.GetBuffer() ); #if defined ( __linux__ ) || defined ( __APPLE__ ) Sys_Printf( "prefix : '%s'\n", mUserPathPrefix.GetBuffer() ); #endif Sys_Printf( "default texture scale: %g\n", mTextureDefaultScale ); Sys_Printf( "single eclass load : %s\n", mEClassSingleLoad ? "Yes" : "No" ); Sys_Printf( "patches supported : %s\n", mNoPatch ? "No" : "Yes" ); } CPrefAssignment& CPrefAssignment::operator =( const CPrefAssignment& ass ){ if ( &ass != this ) { mName = ass.mName; mType = ass.mType; mVal = ass.mVal; } return *this; } CPrefAssignment::CPrefAssignment( const CPrefAssignment& ass ){ *this = ass; } void CGameDialog::LoadPrefs(){ // if we already have a document loaded, we will free and reload from file if ( mGlobalPrefs.InUse() ) { Sys_Printf( "Reloading global prefs from file\n" ); mGlobalPrefs.Clear(); } // load global .pref file CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; strGlobalPref += "global.pref"; mGlobalPrefs.ReadXMLFile( strGlobalPref.GetBuffer() ); mGlobalPrefs.GetPref( "gamefile", &m_sGameFile, "" ); // NOTE: there's no default, user HAS to select something mGlobalPrefs.GetPref( "autoload", &m_bAutoLoadGame, false ); mGlobalPrefs.GetPref( "log console", &m_bLogConsole, false ); // in a very particular post-.pid startup // we may have the console turned on and want to keep it that way // so we use a latching system if ( m_bForceLogConsole ) { m_bLogConsole = true; Sys_Printf( "console logging has been latched on, saving prefs\n" ); SavePrefs(); m_bForceLogConsole = false; } // console logging: call Sys_LogConsole to check console logging status // it is important that we would log console as early as possible to make it useful Sys_LogFile(); if ( mGlobalPrefs.mbEmpty ) { Sys_Printf( "Saving global.pref with default pref values\n" ); SavePrefs(); } } void CGameDialog::SavePrefs(){ // update the tree and save it mGlobalPrefs.UpdatePrefTree(); CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; strGlobalPref += "global.pref"; if ( !mGlobalPrefs.WriteXMLFile( strGlobalPref.GetBuffer() ) ) { Sys_FPrintf( SYS_ERR, "Error occured while saving global prefs file '%s'\n", strGlobalPref.GetBuffer() ); } } void CGameDialog::DoGameInstall() { // make sure console logging is on whenever we enter the installation loop g_PrefsDlg.mGamesDialog.m_bLogConsole = true; Sys_LogFile(); mGameInstall.Run(); } void CGameDialog::DoGameDialog() { // allow looping the game selection dialog with calls to the game configure dialog in between while ( m_bDoGameInstall ) { m_bDoGameInstall = false; if ( DoModal() == IDCANCEL ) { Error( "game selection dialog canceled, cannot continue" ); return; } if ( m_bDoGameInstall ) { DoGameInstall(); ScanForGames(); // and we will loop to do another DoModal dialog } } // unhook so we can use in other places // we manually incref'ed it when creating, it won't be freed (destructor) gtk_container_remove( GTK_CONTAINER( mTopBox ), GetGlobalFrame() ); // we save the prefs file SavePrefs(); } GtkWidget* CGameDialog::GetGlobalFrame(){ GtkWidget *vbox, *text, *combo, *check; if ( mFrame != NULL ) { return mFrame; } mFrame = gtk_frame_new( NULL ); gtk_container_set_border_width( GTK_CONTAINER( mFrame ), 5 ); gtk_widget_show( mFrame ); vbox = gtk_vbox_new( FALSE, 6 ); gtk_widget_show( vbox ); gtk_container_add( GTK_CONTAINER( mFrame ), vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); text = gtk_label_new( _( "Select the game:" ) ); gtk_widget_show( text ); gtk_box_pack_start( GTK_BOX( vbox ), text, FALSE, FALSE, 0 ); combo = gtk_combo_box_new_text(); gtk_widget_show( combo ); gtk_box_pack_start( GTK_BOX( vbox ), combo, FALSE, FALSE, 0 ); AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT ); mGameCombo = GTK_COMBO_BOX( combo ); UpdateGameCombo(); check = gtk_check_button_new_with_label( _( "Auto load selected game on startup" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bAutoLoadGame, DLG_CHECK_BOOL ); text = gtk_label_new( _( "(this frame is available in the prefs menu if you set auto-select)" ) ); gtk_widget_show( text ); gtk_box_pack_start( GTK_BOX( vbox ), text, FALSE, FALSE, 0 ); #ifdef _WIN32 check = gtk_check_button_new_with_label( _( "Networked install - per-user settings" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bNetRun, DLG_CHECK_BOOL ); #endif check = gtk_check_button_new_with_label( _( "Log the console to radiant.log" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLogConsole, DLG_CHECK_BOOL ); // incref it so we can pass it around gtk_widget_ref( GTK_WIDGET( mFrame ) ); return mFrame; } void CGameDialog::UpdateData( bool retrieve ) { if ( !retrieve ) { // use m_sGameFile to set m_nComboSelect list::iterator iGame; int i = 0; for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { if ( ( *iGame )->mGameFile == m_sGameFile ) { m_nComboSelect = i; break; } i++; } #ifdef _WIN32 UpdateNetrun( false ); #endif } Dialog::UpdateData( retrieve ); if ( retrieve ) { // use m_nComboSelect to set m_sGameFile list::iterator iGame = mGames.begin(); int i; for ( i = 0; i < m_nComboSelect; i++ ) { iGame++; } m_sGameFile = ( *iGame )->mGameFile; #ifdef _WIN32 UpdateNetrun( true ); #endif } } void CGameDialog::SInstallCallback( GtkWidget *widget, gpointer data ) { CGameDialog *d = static_cast< CGameDialog* >( data ); d->m_bDoGameInstall = true; d->EndModal( 0 ); } void CGameDialog::BuildDialog() { GtkWidget *dlg, *vbox1, *button, *setup_button; dlg = m_pWidget; gtk_window_set_title( GTK_WINDOW( dlg ), _( "Select Game" ) ); vbox1 = gtk_vbox_new( FALSE, 0 ); gtk_widget_show( vbox1 ); gtk_container_add( GTK_CONTAINER( dlg ), vbox1 ); gtk_container_add( GTK_CONTAINER( vbox1 ), GetGlobalFrame() ); mTopBox = vbox1; setup_button = gtk_button_new_with_label( _( "Configure more games" ) ); gtk_widget_show( setup_button ); gtk_box_pack_start( GTK_BOX( vbox1 ), setup_button, FALSE, FALSE, 0 ); gtk_signal_connect( GTK_OBJECT( setup_button ), "clicked", GTK_SIGNAL_FUNC( SInstallCallback ), this ); button = gtk_button_new_with_label( _( "OK" ) ); gtk_widget_show( button ); gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); AddModalButton( button, IDOK ); button = gtk_button_new_with_label( _( "Cancel" ) ); gtk_widget_show( button ); gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); AddModalButton( button, IDCANCEL ); gtk_widget_set_usize( button, 60, -2 ); } void CGameDialog::UpdateGameCombo() { // fill in with the game descriptions list::iterator iGame; if ( mGameCombo == NULL ) { Sys_Printf( "mGameCombo == NULL\n" ); return; } // clear whatever is in - wtf no way to know how many text entries? // use set/get active to track gtk_combo_box_set_active( mGameCombo, 0 ); while ( gtk_combo_box_get_active( mGameCombo ) == 0 ) { gtk_combo_box_remove_text( mGameCombo, 0 ); gtk_combo_box_set_active( mGameCombo, 0 ); } for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { gtk_combo_box_append_text( mGameCombo, ( *iGame )->mGameName.GetBuffer() ); } gtk_combo_box_set_active( mGameCombo, 0 ); } void CGameDialog::ScanForGames(){ CString strPath; char *dirlist; GDir *dir; CString strGamesPath = g_strAppPath.GetBuffer(); strGamesPath += "games"; const char *path = strGamesPath.GetBuffer(); if ( !mGames.empty() ) { Sys_Printf( "Clearing game list\n" ); list::iterator iGame; for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { delete ( *iGame ); } mGames.clear(); } Sys_Printf( "Scanning for game description files: %s\n", path ); /*! \todo FIXME LINUX: do we put game description files below g_strAppPath, or in ~/.radiant i.e. read only or read/write? my guess .. readonly cause it's an install we will probably want to add ~/.radiant//games/ scanning on top of that for developers (if that's really needed) */ // FIXME need to catch the 'no game description' situation and exit with a clean error dir = g_dir_open( path, 0, NULL ); if ( dir != NULL ) { while ( 1 ) { const gchar* name = g_dir_read_name( dir ); if ( name == NULL ) { break; } dirlist = g_strdup( name ); #ifdef _WIN32 strlwr( dirlist ); #endif char *ext = strrchr( dirlist, '.' ); if ( ( ext == NULL ) || ( strcmp( ext, ".game" ) != 0 ) ) { continue; } strPath.Format( "%s/%s", path, dirlist ); Sys_Printf( "%s\n", strPath.GetBuffer() ); // got one, load it xmlDocPtr pDoc = xmlParseFile( strPath.GetBuffer() ); if ( pDoc ) { mGames.push_front( new CGameDescription( pDoc, dirlist ) ); } else { Sys_FPrintf( SYS_ERR, "XML parser failed on '%s'\n", strPath.GetBuffer() ); } g_free( dirlist ); } g_dir_close( dir ); } // entries in the combo need to be updated UpdateGameCombo(); } CGameDescription* CGameDialog::GameDescriptionForComboItem(){ list::iterator iGame; int i = 0; for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++,i++ ) { if ( i == m_nComboSelect ) { return ( *iGame ); } } return NULL; // not found } void CGameDialog::InitGlobalPrefPath(){ GString *global_rc_path; // configure m_global_rc_path // this is the g_strTempPath, and it has already been mkdir'ed global_rc_path = g_string_new( g_strTempPath.GetBuffer() ); g_PrefsDlg.m_global_rc_path = global_rc_path; } void CGameDialog::Reset(){ if ( !g_PrefsDlg.m_global_rc_path ) { InitGlobalPrefPath(); } CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; strGlobalPref += "global.pref"; remove( strGlobalPref.GetBuffer() ); } void CGameDialog::Init(){ InitGlobalPrefPath(); ScanForGames(); if ( mGames.empty() ) { DoGameInstall(); ScanForGames(); if ( mGames.empty() ) { Error( "No games setup, aborting\n" ); } } LoadPrefs(); if ( m_bAutoLoadGame ) { // search by .game name list::iterator iGame; for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { if ( ( *iGame )->mGameFile == m_sGameFile ) { m_pCurrentGameDescription = ( *iGame ); break; } } } if ( !m_bAutoLoadGame || !m_pCurrentGameDescription ) { DoGameDialog(); // use m_nComboSelect to identify the game to run as and set the globals m_pCurrentGameDescription = GameDescriptionForComboItem(); if ( !m_pCurrentGameDescription ) { Error( "Lookup of game description object failed, can't continue\n" ); } } g_pGameDescription = m_pCurrentGameDescription; g_strGameToolsPath = g_pGameDescription->mGameToolsPath; // NOTE TTimo: this is moved from QE_LoadProject in 1.2 // (probably broken) // NOTE Hydra: was broken for win32, we don't use m_strHomeGame or m_strFSBasePath #if defined ( __linux__ ) || defined ( __APPLE__ ) g_qeglobals.m_strHomeGame = g_get_home_dir(); g_qeglobals.m_strHomeGame += "/"; g_qeglobals.m_strHomeGame += m_pCurrentGameDescription->mUserPathPrefix.GetBuffer(); g_qeglobals.m_strHomeGame += "/"; #else g_qeglobals.m_strHomeGame = g_pGameDescription->mEnginePath.GetBuffer(); #endif g_pGameDescription->Dump(); } CGameDialog::~CGameDialog(){ if ( mFrame ) { // NOTE I'm not too sure how reliable this is gtk_widget_unref( GTK_WIDGET( mFrame ) ); } // free all the game descriptions list::iterator iGame; for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { delete ( *iGame ); *iGame = NULL; } } void CGameDialog::AddPacksURL( Str &URL ){ // add the URLs for the list of game packs installed // FIXME: this is kinda hardcoded for now.. list::iterator iGame; for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { if ( ( *iGame )->mGameFile == "q3.game" ) { URL += "&Games_dlup%5B%5D=1"; } else if ( ( *iGame )->mGameFile == "wolf.game" ) { URL += "&Games_dlup%5B%5D=2"; } // FIXME: double entry else if ( ( *iGame )->mGameFile == "wolf.game" ) { URL += "&Games_dlup%5B%5D=3"; } else if ( ( *iGame )->mGameFile == "jk2.game" ) { URL += "&Games_dlup%5B%5D=4"; } else if ( ( *iGame )->mGameFile == "stvef.game" ) { URL += "&Games_dlup%5B%5D=5"; } else if ( ( *iGame )->mGameFile == "sof2.game" ) { URL += "&Games_dlup%5B%5D=6"; } else if ( ( *iGame )->mGameFile == "ja.game" ) { URL += "&Games_dlup%5B%5D=7"; } } } #ifdef _WIN32 #define NETRUN_FILENAME "netrun.conf" bool CGameDialog::m_bNetRun; void CGameDialog::UpdateNetrun( bool retrieve ){ FILE *f_netrun; CString strNetrun; strNetrun = g_strAppPath; strNetrun += NETRUN_FILENAME; if ( !retrieve ) { // now check if we are running from a network installation // use a dummy file as the flag f_netrun = fopen( strNetrun.GetBuffer(), "r" ); if ( f_netrun ) { fclose( f_netrun ); m_bNetRun = true; } else{ m_bNetRun = false; } } else { if ( m_bNetRun ) { f_netrun = fopen( strNetrun.GetBuffer(), "w" ); if ( !f_netrun ) { Sys_FPrintf( SYS_ERR, "ERROR: Failed to create netrun file '%s'\n", strNetrun.GetBuffer() ); m_bNetRun = false; } else { fclose( f_netrun ); Sys_Printf( "Created/Checked '%s'\n", strNetrun.GetBuffer() ); } } else { if ( remove( strNetrun.GetBuffer() ) == -1 ) { if ( errno != ENOENT ) { Sys_FPrintf( SYS_ERR, "Failed to remove netrun file '%s'\n", strNetrun.GetBuffer() ); } m_bNetRun = true; } else { Sys_Printf( "Netrun mode is disabled\n" ); } } } } bool CGameDialog::GetNetrun(){ return m_bNetRun; } #endif /* ======== very first prefs init deals with selecting the game and the game tools path then we can load .ini stuff using prefs / ini settings: those are per-game win32: look in g_strGameToolsPath for .ini linux: look in ~/.radiant//gamename ======== */ #define PREFS_LOCAL_FILENAME "local.pref" void PrefsDlg::Init(){ mGamesDialog.Init(); // m_global_rc_path has been set above, do m_rc_path with game specific stuff now // the win32 and linux versions have been unified for network mode #ifdef _WIN32 if ( !CGameDialog::GetNetrun() ) { // legacy prefs settings, this goes where the game pack is installed m_rc_path = g_string_new( g_strGameToolsPath.GetBuffer() ); m_inipath = g_string_new( m_rc_path->str ); g_string_append( m_inipath, PREFS_LOCAL_FILENAME ); return; } #endif // this is common to win32 and Linux init now m_rc_path = g_string_new( m_global_rc_path->str ); // game sub-dir g_string_append( m_rc_path, g_pGameDescription->mGameFile.GetBuffer() ); g_string_append( m_rc_path, "/" ); Q_mkdir( m_rc_path->str, 0775 ); // then the ini file m_inipath = g_string_new( m_rc_path->str ); g_string_append( m_inipath, PREFS_LOCAL_FILENAME ); } void PrefsDlg::UpdateData( bool retrieve ){ // leo: the "changed" signal confuses the update function if ( m_pWidget == NULL ) { return; } mGamesDialog.UpdateData( retrieve ); Dialog::UpdateData( retrieve ); } #ifdef _WIN32 #define PREFSHSPACE 5 #else #define PREFSHSPACE 0 #endif static void UpdateSensitivity( GtkWidget *widget, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; dlg->DoSensitivity(); } static void UpdateEditorSensitivity( GtkWidget *widget, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; dlg->DoEditorSensitivity(); } // start new prefs dialog /*! Utility function for swapping notebook pages for tree list selections */ void PrefsDlg::showPrefPage( int prefpage ){ if ( gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) != prefpage ) { gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), prefpage ); } return; } static void treeSelection( GtkTreeSelection* selection, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; GtkTreeModel* model; GtkTreeIter selected; if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) { int prefpage; gtk_tree_model_get( model, &selected, 1, (gpointer*)&prefpage, -1 ); dlg->showPrefPage( prefpage ); } } void PrefsDlg::BuildDialog(){ // Main Preferences dialog GtkWidget *dialog, *mainvbox, *hbox, *sc_win, *preflabel; // Widgets on notebook pages GtkWidget *check, *label, *scale, *hbox2, *combo, *table, *spin, *entry, *pixmap, *radio, *button, *pageframe, *vbox; GList *combo_list = (GList*)NULL; GtkObject *adj; dialog = m_pWidget; gtk_window_set_title( GTK_WINDOW( dialog ), _( "GtkRadiant Preferences" ) ); gtk_widget_realize( dialog ); mainvbox = gtk_vbox_new( FALSE, 5 ); gtk_container_add( GTK_CONTAINER( dialog ), mainvbox ); gtk_container_set_border_width( GTK_CONTAINER( mainvbox ), 5 ); gtk_widget_show( mainvbox ); hbox = gtk_hbox_new( FALSE, 5 ); gtk_widget_show( hbox ); gtk_box_pack_end( GTK_BOX( mainvbox ), hbox, FALSE, TRUE, 0 ); button = gtk_button_new_with_label( _( "OK" ) ); gtk_widget_show( button ); gtk_box_pack_end( GTK_BOX( hbox ), button, FALSE, FALSE, 0 ); gtk_widget_set_usize( button, 60, -2 ); AddModalButton( button, IDOK ); button = gtk_button_new_with_label( _( "Cancel" ) ); gtk_widget_show( button ); gtk_box_pack_end( GTK_BOX( hbox ), button, FALSE, FALSE, 0 ); gtk_widget_set_usize( button, 60, -2 ); AddModalButton( button, IDCANCEL ); button = gtk_button_new_with_label( _( "Clean" ) ); gtk_widget_show( button ); gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnButtonClean ), this ); gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 ); gtk_widget_set_usize( button, 60, -2 ); hbox = gtk_hbox_new( FALSE, 5 ); gtk_box_pack_start( GTK_BOX( mainvbox ), hbox, TRUE, TRUE, 0 ); gtk_widget_show( hbox ); sc_win = gtk_scrolled_window_new( NULL, NULL ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sc_win ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); gtk_box_pack_start( GTK_BOX( hbox ), sc_win, FALSE, FALSE, 0 ); gtk_widget_show( sc_win ); // prefs pages notebook notebook = gtk_notebook_new(); // hide the notebook tabs since its not supposed to look like a notebook gtk_notebook_set_show_tabs( GTK_NOTEBOOK( notebook ), FALSE ); gtk_box_pack_start( GTK_BOX( hbox ), notebook, TRUE, TRUE, 0 ); gtk_widget_show( notebook ); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sc_win ), GTK_SHADOW_IN ); { GtkTreeStore* store = gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER ); GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) ); gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE ); { GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( _( "Preferences" ), renderer, "text", 0, NULL ); gtk_tree_view_append_column( GTK_TREE_VIEW( view ), column ); } { GtkTreeSelection* selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) ); g_signal_connect( G_OBJECT( selection ), "changed", G_CALLBACK( treeSelection ), this ); } gtk_widget_show( view ); gtk_container_add( GTK_CONTAINER( sc_win ), view ); { /********************************************************************/ /* Add preference tree options */ /********************************************************************/ { GtkTreeIter group; gtk_tree_store_append( store, &group, NULL ); gtk_tree_store_set( store, &group, 0, _( "Globals" ), 1, PTAB_FRONT, -1 ); { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Game settings" ), 1, (gpointer)PTAB_GAME_SETTINGS, -1 ); } } { GtkTreeIter group; gtk_tree_store_append( store, &group, NULL ); gtk_tree_store_set( store, &group, 0, _( "Display" ), 1, PTAB_FRONT, -1 ); { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "2D Display/Rendering" ), 1, (gpointer)PTAB_2D, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "3D View" ), 1, (gpointer)PTAB_CAMERA, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Texture Settings" ), 1, (gpointer)PTAB_TEXTURE, -1 ); } } { GtkTreeIter group; gtk_tree_store_append( store, &group, NULL ); gtk_tree_store_set( store, &group, 0, _( "Interface" ), 1, PTAB_FRONT, -1 ); { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Layout" ), 1, (gpointer)PTAB_LAYOUT, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Mouse" ), 1, (gpointer)PTAB_MOUSE, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Editing" ), 1, (gpointer)PTAB_EDITING, -1 ); } } { GtkTreeIter group; gtk_tree_store_append( store, &group, NULL ); gtk_tree_store_set( store, &group, 0, _( "Other" ), 1, PTAB_FRONT, -1 ); { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Startup/Auto save" ), 1, (gpointer)PTAB_STARTUP, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Paths" ), 1, (gpointer)PTAB_PATHS, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Brush" ), 1, (gpointer)PTAB_BRUSH, -1 ); } { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "Misc" ), 1, (gpointer)PTAB_MISC, -1 ); } if ( !g_qeglobals.bBSPFrontendPlugin ) { GtkTreeIter tab; gtk_tree_store_append( store, &tab, &group ); gtk_tree_store_set( store, &tab, 0, _( "BSP Monitoring" ), 1, (gpointer)PTAB_BSPMONITOR, -1 ); } } } gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) ); g_object_unref( G_OBJECT( store ) ); } /**********************************************************************/ /* build the prefs pages */ /**********************************************************************/ // Front page... // todo : add something interesting here // NOTE TTimo: tip of the day? or a logo? preflabel = gtk_label_new( _( "Front Page" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( NULL ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_widget_set_usize( GTK_WIDGET( vbox ), 350, -2 ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** global preferences group ****************************/ preflabel = gtk_label_new( _( "Globals" ) ); gtk_widget_show( preflabel ); pageframe = mGamesDialog.GetGlobalFrame(); gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** 2D prefs group (xy views/rendering options) *********/ preflabel = gtk_label_new( _( "2D Display" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "2D Display" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // OpenGL Display Lists check = gtk_check_button_new_with_label( _( "OpenGL Display Lists" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bDisplayLists, DLG_CHECK_BOOL ); // Antialiased points & lines // Fishman - Add antialiazed points and lines support. 09/03/00 check = gtk_check_button_new_with_label( _( "OpenGL antialiased points and lines" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bAntialiasedPointsAndLines, DLG_CHECK_BOOL ); // Solid selection boxes check = gtk_check_button_new_with_label( _( "Solid selection boxes" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bNoStipple, DLG_CHECK_BOOL ); // Display size info check = gtk_check_button_new_with_label( _( "Display size info" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bSizePaint, DLG_CHECK_BOOL ); // Alternate vertex/edge handles // Gef: Kyro GL_POINT work around 25-aug-2001 check = gtk_check_button_new_with_label( _( "Alternate vertex/edge handles" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bGlPtWorkaround, DLG_CHECK_BOOL ); g_list_free( combo_list ); #ifdef ATIHACK_812 // ATI bugs check = gtk_check_button_new_with_label( _( "ATI and Intel cards w/ buggy drivers (disappearing polygons)" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bGlATIHack, DLG_CHECK_BOOL ); #endif #ifdef NVIDIA_AERO_HACK check = gtk_check_button_new_with_label( _( "NVIDIA/Aero bug - disable Windows composition" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bGlNvidiaAeroHack, DLG_CHECK_BOOL ); #endif // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** 3D Camera view group *********/ preflabel = gtk_label_new( _( "3D View" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "3D View" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Directional velocity (Movement Velocity) // label container hbox2 = gtk_hbox_new( FALSE, 0 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); // label label = gtk_label_new( _( "Movement Velocity" ) ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // adjustment adj = gtk_adjustment_new( 100, 50, 300, 1, 10, 10 ); AddDialogData( adj, &m_nMoveSpeed, DLG_ADJ_INT ); // scale scale = gtk_hscale_new( GTK_ADJUSTMENT( adj ) ); gtk_widget_show( scale ); gtk_box_pack_start( GTK_BOX( vbox ), scale, FALSE, TRUE, 2 ); gtk_scale_set_draw_value( GTK_SCALE( scale ), TRUE ); // Angular velocity (Rotational Velocity) // label container hbox2 = gtk_hbox_new( FALSE, 0 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); // label label = gtk_label_new( _( "Rotational Velocity" ) ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // adjustment adj = gtk_adjustment_new( 3, 1, 180, 1, 10, 10 ); // value, low, high, step, page_step, page_size AddDialogData( adj, &m_nAngleSpeed, DLG_ADJ_INT ); // scale scale = gtk_hscale_new( GTK_ADJUSTMENT( adj ) ); gtk_widget_show( scale ); gtk_box_pack_start( GTK_BOX( vbox ), scale, FALSE, TRUE, 2 ); gtk_scale_set_draw_value( GTK_SCALE( scale ), TRUE ); // Text under the velocity sliders // container hbox2 = gtk_hbox_new( FALSE, 0 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); // label label = gtk_label_new( _( "slow" ) ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // label label = gtk_label_new( _( "fast" ) ); gtk_widget_show( label ); gtk_box_pack_end( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // Allow drag to select multiple faces/brushes // container table = gtk_table_new( 2, 1, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); label = gtk_label_new( _( "Use paint-select in camera view:" ) ); gtk_widget_show( label ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); combo_list = NULL; combo_list = g_list_append( combo_list, (void *)_( "No" ) ); combo_list = g_list_append( combo_list, (void *)_( "Yes" ) ); combo_list = g_list_append( combo_list, (void *)_( "Yes (Classic Key Setup)" ) ); combo = gtk_combo_new(); gtk_combo_set_popdown_strings( GTK_COMBO( combo ), combo_list ); gtk_widget_show( combo ); gtk_table_attach( GTK_TABLE( table ), combo, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_entry_set_editable( GTK_ENTRY( GTK_COMBO( combo )->entry ), FALSE ); AddDialogData( combo, &m_nCamDragMultiSelect, DLG_COMBO_INT ); // Freelook in Camera view check = gtk_check_button_new_with_label( _( "Freelook in Camera view" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); gtk_label_set_justify( GTK_LABEL( GTK_BIN( check )->child ), GTK_JUSTIFY_LEFT ); AddDialogData( check, &m_bCamFreeLook, DLG_CHECK_BOOL ); // Freelook in Camera view w/ forward & back strafing instead of up and down looking check = gtk_check_button_new_with_label( _( "Freelook strafes Forward and Back" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); gtk_label_set_justify( GTK_LABEL( GTK_BIN( check )->child ), GTK_JUSTIFY_LEFT ); AddDialogData( check, &m_bCamFreeLookStrafe, DLG_CHECK_BOOL ); // Invert mouse in freelook check = gtk_check_button_new_with_label( _( "Invert mouse in freelook" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); gtk_label_set_justify( GTK_LABEL( GTK_BIN( check )->child ), GTK_JUSTIFY_LEFT ); AddDialogData( check, &m_bCamInverseMouse, DLG_CHECK_BOOL ); // Discrete movement check = gtk_check_button_new_with_label( _( "Discrete movement" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); gtk_label_set_justify( GTK_LABEL( GTK_BIN( check )->child ), GTK_JUSTIFY_LEFT ); AddDialogData( check, &m_bCamDiscrete, DLG_CHECK_BOOL ); // Update XY views on camera move check = gtk_check_button_new_with_label( _( "Update XY views on camera move" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); gtk_label_set_justify( GTK_LABEL( GTK_BIN( check )->child ), GTK_JUSTIFY_LEFT ); AddDialogData( check, &m_bCamXYUpdate, DLG_CHECK_BOOL ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Texture group *********/ preflabel = gtk_label_new( _( "Textures" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Textures" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 6 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Texture quality slider // label label = gtk_label_new( _( "Texture quality" ) ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( vbox ), label, FALSE, FALSE, 0 ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // adjustment adj = gtk_adjustment_new( 0, 0, 4, 1, 1, 1 ); AddDialogData( adj, &m_nLatchedTextureQuality, DLG_ADJ_INT ); // scale scale = gtk_hscale_new( GTK_ADJUSTMENT( adj ) ); gtk_widget_show( scale ); gtk_box_pack_start( GTK_BOX( vbox ), scale, FALSE, FALSE, 0 ); gtk_scale_set_draw_value( GTK_SCALE( scale ), FALSE ); // text under the texture slider hbox2 = gtk_hbox_new( FALSE, 0 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); label = gtk_label_new( _( "low" ) ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); label = gtk_label_new( _( "high" ) ); gtk_widget_show( label ); gtk_box_pack_end( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // texture subsets check = gtk_check_button_new_with_label( _( "Texture subsets" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bTextureWindow, DLG_CHECK_BOOL ); // texture scrollbar check = gtk_check_button_new_with_label( _( "Texture scrollbar" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bTextureScrollbar, DLG_CHECK_BOOL ); // texture increment matches grid check = gtk_check_button_new_with_label( _( "Tex increment matches grid" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bSnapTToGrid, DLG_CHECK_BOOL ); // RIANT // Texture compression choice label // container table = gtk_table_new( 2, 1, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); label = gtk_label_new( _( "Texture Compression (if available):" ) ); gtk_widget_show( label ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); // Texture compression choice label combo_list = NULL; // NONE will always be in pos 0 combo_list = g_list_append( combo_list, (void *)_( "None" ) ); // if OpenGL compression is enabled it will always be // in pos 1 if ( g_qeglobals.m_bOpenGLCompressionSupported ) { combo_list = g_list_append( combo_list, (void *)_( "OpenGL ARB" ) ); } // If S3 is enabled offer all 3 valid compression schemes in RGBA if ( g_qeglobals.m_bS3CompressionSupported ) { combo_list = g_list_append( combo_list, (void *)_( "S3TC DXT1" ) ); combo_list = g_list_append( combo_list, (void *)_( "S3TC DXT3" ) ); combo_list = g_list_append( combo_list, (void *)_( "S3TC DXT5" ) ); } combo = gtk_combo_new(); gtk_combo_set_popdown_strings( GTK_COMBO( combo ), combo_list ); gtk_widget_show( combo ); gtk_table_attach( GTK_TABLE( table ), combo, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_entry_set_editable( GTK_ENTRY( GTK_COMBO( combo )->entry ), FALSE ); AddDialogData( combo, &m_nTextureCompressionFormat, DLG_COMBO_INT ); g_list_free( combo_list ); // container table = gtk_table_new( 2, 1, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); // Startup shaders // label label = gtk_label_new( _( "Startup Shaders:" ) ); gtk_widget_show( label ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); // combo list combo_list = NULL; combo_list = g_list_append( combo_list, (void *)_( "None" ) ); if ( g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game" ) { combo_list = g_list_append( combo_list, (void *)_( "System" ) ); } else if ( g_pGameDescription->mGameFile == "sof2.game" ) { combo_list = g_list_append( combo_list, (void *)( "Tools" ) ); } else{ combo_list = g_list_append( combo_list, (void *)_( "Common" ) ); } combo_list = g_list_append( combo_list, (void *)_( "All" ) ); combo = gtk_combo_new(); gtk_combo_set_popdown_strings( GTK_COMBO( combo ), combo_list ); gtk_widget_show( combo ); gtk_table_attach( GTK_TABLE( table ), combo, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_entry_set_editable( GTK_ENTRY( GTK_COMBO( combo )->entry ), FALSE ); AddDialogData( combo, &m_nLatchedShader, DLG_COMBO_INT ); g_list_free( combo_list ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Layout group *********/ preflabel = gtk_label_new( _( "Layout" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Layout" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // View types // table table = gtk_table_new( 2, 4, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); // view type 1 pixmap = new_pixmap( g_pParentWnd->m_pWidget, "window1.bmp" ); gtk_widget_show( pixmap ); gtk_table_attach( GTK_TABLE( table ), pixmap, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 2 pixmap = new_pixmap( g_pParentWnd->m_pWidget, "window2.bmp" ); gtk_widget_show( pixmap ); gtk_table_attach( GTK_TABLE( table ), pixmap, 1, 2, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 3 pixmap = new_pixmap( g_pParentWnd->m_pWidget, "window3.bmp" ); gtk_widget_show( pixmap ); gtk_table_attach( GTK_TABLE( table ), pixmap, 2, 3, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 4 pixmap = new_pixmap( g_pParentWnd->m_pWidget, "window4.bmp" ); gtk_widget_show( pixmap ); gtk_table_attach( GTK_TABLE( table ), pixmap, 3, 4, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 1 selector radio = gtk_radio_button_new( NULL ); gtk_widget_show( radio ); gtk_table_attach( GTK_TABLE( table ), radio, 0, 1, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 2 selector radio = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON( radio ) ); gtk_widget_show( radio ); gtk_table_attach( GTK_TABLE( table ), radio, 1, 2, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 3 selector radio = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON( radio ) ); gtk_widget_show( radio ); gtk_table_attach( GTK_TABLE( table ), radio, 2, 3, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // view type 4 selector radio = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON( radio ) ); gtk_widget_show( radio ); gtk_table_attach( GTK_TABLE( table ), radio, 3, 4, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); AddDialogData( radio, &m_nLatchedView, DLG_RADIO_INT ); // Floating Z window check = gtk_check_button_new_with_label( _( "Floating Z Window" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLatchedFloatingZ, DLG_CHECK_BOOL ); // show menu tear-off seperators check = gtk_check_button_new_with_label( _( "Detachable Menus" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLatchedDetachableMenus, DLG_CHECK_BOOL ); if ( !g_pGameDescription->mNoPatch ) { // show patch toolbar check = gtk_check_button_new_with_label( _( "Patch Toolbar" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_patchtoolbar", check ); // Allow to be disabled for Q1/Q2 AddDialogData( check, &m_bLatchedPatchToolbar, DLG_CHECK_BOOL ); } // use wide toolbar check = gtk_check_button_new_with_label( _( "Wide Toolbar" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLatchedWideToolbar, DLG_CHECK_BOOL ); // use plugin toolbar check = gtk_check_button_new_with_label( _( "Plugin Toolbar" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLatchedPluginToolbar, DLG_CHECK_BOOL ); #ifdef _WIN32 // win32 file dialog check = gtk_check_button_new_with_label( _( "Use win32 file dialog (hacky)" ) ); gtk_widget_show( check ); // gtk_container_add (GTK_CONTAINER (vbox), check); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bNativeGUI, DLG_CHECK_BOOL ); // position on primary monitor check = gtk_check_button_new_with_label( _( "Start on Primary Monitor" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_startonprimary", check ); gtk_signal_connect( GTK_OBJECT( check ), "clicked", GTK_SIGNAL_FUNC( UpdateSensitivity ), this ); AddDialogData( check, &m_bStartOnPrimMon, DLG_CHECK_BOOL ); #endif // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Mouse group *********/ preflabel = gtk_label_new( _( "Mouse" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Mouse" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Buttons // container hbox2 = gtk_hbox_new( FALSE, 5 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); // 2 button radio radio = gtk_radio_button_new_with_label( NULL, _( "2 button" ) ); gtk_widget_show( radio ); gtk_box_pack_start( GTK_BOX( hbox2 ), radio, FALSE, FALSE, 0 ); // 3 button radio radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON( radio ), _( "3 button" ) ); gtk_widget_show( radio ); gtk_box_pack_start( GTK_BOX( hbox2 ), radio, FALSE, FALSE, 0 ); AddDialogData( radio, &m_nMouse, DLG_RADIO_INT ); // right click to drop entity check = gtk_check_button_new_with_label( _( "Right click to drop entities" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bRightClick, DLG_CHECK_BOOL ); // Mouse chaser (and this does what?) check = gtk_check_button_new_with_label( _( "Mouse chaser" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bChaseMouse, DLG_CHECK_BOOL ); // Alt + multi-drag check = gtk_check_button_new_with_label( _( "ALT + multi-drag" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bALTEdge, DLG_CHECK_BOOL ); // Mouse wheel increments // container hbox2 = gtk_hbox_new( FALSE, 5 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); // label label = gtk_label_new( _( "Wheel Mouse inc:" ) ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // entry entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_widget_set_usize( entry, 40, -2 ); gtk_box_pack_start( GTK_BOX( hbox2 ), entry, FALSE, FALSE, 0 ); AddDialogData( entry, &m_nWheelInc, DLG_ENTRY_INT ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Editing group *********/ preflabel = gtk_label_new( _( "Editing" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Editing" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Vertex editing splits faces check = gtk_check_button_new_with_label( _( "Vertex editing splits face" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bVertexSplit, DLG_CHECK_BOOL ); // Fix target/targetname collisions check = gtk_check_button_new_with_label( _( "Fix target/targetname collisions" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bDoTargetFix, DLG_CHECK_BOOL ); // Clipper tool uses caulk check = gtk_check_button_new_with_label( _( "Clipper tool uses caulk" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bClipCaulk, DLG_CHECK_BOOL ); // Don't clamp plane points check = gtk_check_button_new_with_label( _( "Don't clamp plane points" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bNoClamp, DLG_CHECK_BOOL ); // Snap to grid check = gtk_check_button_new_with_label( _( "Snap to grid" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bSnap, DLG_CHECK_BOOL ); // Select patch by bounding box check = gtk_check_button_new_with_label( _( "Select patches by bounding box" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bPatchBBoxSelect, DLG_CHECK_BOOL ); // Rotation increment // container table = gtk_table_new( 2, 3, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); // label label = gtk_label_new( _( "Rotation increment:" ) ); gtk_widget_show( label ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // entry entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_widget_set_usize( entry, 60, -2 ); gtk_table_attach( GTK_TABLE( table ), entry, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); AddDialogData( entry, &m_nRotation, DLG_ENTRY_INT ); // Undo levels // label label = gtk_label_new( _( "Undo Levels:" ) ); gtk_widget_show( label ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // spinner (allows undo levels to be set to zero) spin = gtk_spin_button_new( GTK_ADJUSTMENT( gtk_adjustment_new( 1, 0, 64, 1, 10, 10 ) ), 1, 0 ); gtk_widget_show( spin ); gtk_table_attach( GTK_TABLE( table ), spin, 1, 2, 1, 2, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_widget_set_usize( spin, 60, -2 ); AddDialogData( spin, &m_nUndoLevels, DLG_SPIN_INT ); // Patch subdivisions // label label = gtk_label_new( _( "Patch subdivisions:" ) ); gtk_widget_show( label ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 2, 3, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // entry (spinner perhaps? [2-16]) entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_widget_set_usize( entry, 60, -2 ); gtk_table_attach( GTK_TABLE( table ), entry, 1, 2, 2, 3, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); AddDialogData( entry, &m_nSubdivisions, DLG_ENTRY_INT ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Save/Load group *********/ preflabel = gtk_label_new( _( "Startup/Auto save" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Startup/Auto save" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Snapshots check = gtk_check_button_new_with_label( _( "Snapshots" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bSnapShots, DLG_CHECK_BOOL ); // load last project on open check = gtk_check_button_new_with_label( _( "Load last project on open" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLoadLast, DLG_CHECK_BOOL ); // load last map on open check = gtk_check_button_new_with_label( _( "Load last map on open" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bLoadLastMap, DLG_CHECK_BOOL ); // Auto save.. // container hbox2 = gtk_hbox_new( FALSE, 5 ); gtk_widget_show( hbox2 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox2, FALSE, FALSE, 0 ); gtk_container_set_border_width( GTK_CONTAINER( hbox2 ), 0 ); // label check = gtk_check_button_new_with_label( _( "Auto save every" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( hbox2 ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bAutoSave, DLG_CHECK_BOOL ); // spinner spin = gtk_spin_button_new( GTK_ADJUSTMENT( gtk_adjustment_new( 1, 1, 60, 1, 10, 10 ) ), 1, 0 ); gtk_widget_show( spin ); gtk_box_pack_start( GTK_BOX( hbox2 ), spin, FALSE, FALSE, 0 ); gtk_widget_set_usize( spin, 60, -2 ); AddDialogData( spin, &m_nAutoSave, DLG_SPIN_INT ); // label label = gtk_label_new( _( "minutes" ) ); gtk_widget_show( label ); gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Paths group *********/ preflabel = gtk_label_new( _( "Paths" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Paths" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // prefab path // table table = gtk_table_new( 3, 3, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); // label label = gtk_label_new( _( "Prefab path:" ) ); gtk_widget_show( label ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); // path entry entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_widget_set_usize( GTK_WIDGET( entry ), 240, -2 ); gtk_table_attach( GTK_TABLE( table ), entry, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 1, 0 ); AddDialogData( entry, &m_strPrefabPath, DLG_ENTRY_TEXT ); #if 0 // browse button button = gtk_button_new_with_label( "..." ); gtk_widget_show( button ); gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseprefab ), this ); gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); #endif // User ini path // label label = gtk_label_new( _( "User INI path:" ) ); gtk_widget_show( label ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); // user ini path entry entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_table_attach( GTK_TABLE( table ), entry, 1, 2, 1, 2, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 1, 0 ); AddDialogData( entry, &m_strUserPath, DLG_ENTRY_TEXT ); // user ini browse button button = gtk_button_new_with_label( "..." ); gtk_widget_show( button ); gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseuserini ), this ); gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 1, 2, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Brush group ********/ preflabel = gtk_label_new( _( "Brush" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Brush" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // default texture scale // table table = gtk_table_new( 2, 1, FALSE ); // I believe that the 2 and 1 are switched here, and this is // intentional to be consistent with other calls to gtk_table_new() // [that are probably also switched]. gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); // label label = gtk_label_new( _( "Default texture scale:" ) ); gtk_widget_show( label ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); // scale entry entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_widget_set_usize( GTK_WIDGET( entry ), 60, -2 ); gtk_table_attach( GTK_TABLE( table ), entry, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); AddDialogData( entry, &m_fDefTextureScale, DLG_ENTRY_FLOAT ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** Misc group *********/ preflabel = gtk_label_new( _( "Misc" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "Misc" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Light drawing check = gtk_check_button_new_with_label( _( "Light drawing" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &m_bNewLightDraw, DLG_CHECK_BOOL ); // Light radiuses // container table = gtk_table_new( 2, 1, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); label = gtk_label_new( _( "Light radiuses:" ) ); gtk_widget_show( label ); gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); combo_list = NULL; combo_list = g_list_append( combo_list, (void *)_( "Disabled" ) ); combo_list = g_list_append( combo_list, (void *)_( "True Q3Map2 Style" ) ); combo_list = g_list_append( combo_list, (void *)_( "Classic Style" ) ); combo = gtk_combo_new(); gtk_combo_set_popdown_strings( GTK_COMBO( combo ), combo_list ); gtk_widget_show( combo ); gtk_table_attach( GTK_TABLE( table ), combo, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_entry_set_editable( GTK_ENTRY( GTK_COMBO( combo )->entry ), FALSE ); AddDialogData( combo, &m_nLightRadiuses, DLG_COMBO_INT ); #ifdef _WIN32 check = gtk_check_button_new_with_label( _( "Use win32 file associations to open text files instead of builtin editor" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); AddDialogData( check, &g_PrefsDlg.m_bUseWin32Editor, DLG_CHECK_BOOL ); #else // use custom shader editor check = gtk_check_button_new_with_label( _( "Use Custom Shader Editor" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); gtk_signal_connect( GTK_OBJECT( check ), "clicked", GTK_SIGNAL_FUNC( UpdateEditorSensitivity ), this ); g_object_set_data( G_OBJECT( dialog ), "check_customeditor", check ); AddDialogData( check, &g_PrefsDlg.m_bUseCustomEditor, DLG_CHECK_BOOL ); // custom shader editor executable // table table = gtk_table_new( 3, 1, FALSE ); gtk_widget_show( table ); gtk_box_pack_start( GTK_BOX( vbox ), table, FALSE, TRUE, 0 ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); // label label = gtk_label_new( _( "Custom Editor Command" ) ); gtk_widget_show( label ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 ); g_object_set_data( G_OBJECT( dialog ), "label_customeditor", label ); gtk_widget_set_sensitive( label, g_PrefsDlg.m_bUseCustomEditor ); // custom editor command entry entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_widget_set_usize( GTK_WIDGET( entry ), 240, -2 ); gtk_table_attach( GTK_TABLE( table ), entry, 1, 2, 0, 1, (GtkAttachOptions) ( GTK_FILL ), (GtkAttachOptions) ( 0 ), 1, 0 ); AddDialogData( entry, &m_strEditorCommand, DLG_ENTRY_TEXT ); gtk_widget_set_sensitive( entry, g_PrefsDlg.m_bUseCustomEditor ); g_object_set_data( G_OBJECT( dialog ), "entry_customeditor", entry ); // browse button button = gtk_button_new_with_label( _( "..." ) ); gtk_widget_show( button ); gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseEditor ), this ); gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 0, 1, (GtkAttachOptions) ( 0 ), (GtkAttachOptions) ( 0 ), 0, 0 ); g_object_set_data( G_OBJECT( dialog ), "button_customeditor", button ); gtk_widget_set_sensitive( button, g_PrefsDlg.m_bUseCustomEditor ); #endif // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); /******** BSP Monitoring group *********/ // this is never displayed if the plugin isn't available preflabel = gtk_label_new( _( "BSP Monitoring" ) ); gtk_widget_show( preflabel ); pageframe = gtk_frame_new( _( "BSP Monitoring" ) ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 5 ); gtk_widget_show( pageframe ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); // Enable BSP process monitoring check = gtk_check_button_new_with_label( _( "Enable BSP process monitoring" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_monitorbsp", check ); gtk_signal_connect( GTK_OBJECT( check ), "clicked", GTK_SIGNAL_FUNC( UpdateSensitivity ), this ); AddDialogData( check, &g_PrefsDlg.m_bWatchBSP, DLG_CHECK_BOOL ); // Stop on leak check = gtk_check_button_new_with_label( _( "Stop compilation on leak" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_leakstop", check ); AddDialogData( check, &g_PrefsDlg.m_bLeakStop, DLG_CHECK_BOOL ); // engine after compile check = gtk_check_button_new_with_label( _( "Run engine after compile" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_runengine", check ); gtk_signal_connect( GTK_OBJECT( check ), "clicked", GTK_SIGNAL_FUNC( UpdateSensitivity ), this ); AddDialogData( check, &g_PrefsDlg.m_bRunQuake, DLG_CHECK_BOOL ); // sleep mode when running engine check = gtk_check_button_new_with_label( _( "Activate sleep mode when running the engine" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_sleep", check ); AddDialogData( check, &g_PrefsDlg.m_bDoSleep, DLG_CHECK_BOOL ); // use q3map2's texture projection check = gtk_check_button_new_with_label( _( "Texturing compatible with q3map2" ) ); gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); g_object_set_data( G_OBJECT( dialog ), "check_q3map2", check ); AddDialogData( check, &g_PrefsDlg.m_bQ3Map2Texturing, DLG_CHECK_BOOL ); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), PTAB_FRONT ); return; } // end new prefs dialog void PrefsDlg::LoadTexdefPref( texdef_t* pTexdef, const char* pName ){ char buffer[256]; memset( pTexdef, 0, sizeof( texdef_t ) ); sprintf( buffer, "%s%s", pName, TD_SCALE1_KEY ); mLocalPrefs.GetPref( buffer, &pTexdef->scale[0], 0.5f ); sprintf( buffer, "%s%s", pName, TD_SCALE2_KEY ); mLocalPrefs.GetPref( buffer, &pTexdef->scale[1], 0.5f ); sprintf( buffer, "%s%s", pName, TD_SHIFT1_KEY ); mLocalPrefs.GetPref( buffer, &pTexdef->shift[0], 8.f ); sprintf( buffer, "%s%s", pName, TD_SHIFT2_KEY ); mLocalPrefs.GetPref( buffer, &pTexdef->shift[1], 8.f ); sprintf( buffer, "%s%s", pName, TD_ROTATE_KEY ); mLocalPrefs.GetPref( buffer, &pTexdef->rotate, 45 ); } void PrefsDlg::UpdateTextureCompression(){ // if OpenGL is not ready yet, don't do anything if ( !g_qeglobals.m_bOpenGLReady ) { Sys_Printf( "OpenGL not ready - postpone texture compression capability check\n" ); return; } if ( g_qeglobals.bTextureCompressionSupported ) { if ( m_nTextureCompressionFormat >= 2 && !g_qeglobals.m_bS3CompressionSupported ) { Sys_Printf( "Inconsistant pref setting for texture compression (%d), rolling back\n", m_nTextureCompressionFormat ); m_nTextureCompressionFormat = 1; // if this is not supported either, see below } if ( m_nTextureCompressionFormat == 1 && !g_qeglobals.m_bOpenGLCompressionSupported ) { Sys_Printf( "Inconsistant pref setting for texture compression (GL_COMPRESSED_RGBA), rolling back\n" ); m_nTextureCompressionFormat = 0; } switch ( m_nTextureCompressionFormat ) { case ( 0 ): { g_qeglobals.texture_components = GL_RGBA; Sys_Printf( "texture compression disabled by preferences settings\n" ); break; } case ( 1 ): { g_qeglobals.texture_components = GL_COMPRESSED_RGBA; Sys_Printf( "OpenGL texture compression enabled\n" ); break; } case ( 2 ): { g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; Sys_Printf( "S3TC DXT1 texture compression enabled\n" ); break; } case ( 3 ): { g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; Sys_Printf( "S3TC DXT3 texture compression enabled\n" ); break; } case ( 4 ): { g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; Sys_Printf( "S3TC DXT5 texture compression enabled\n" ); break; } } } else { Sys_Printf( "texture compression is not supported by your current graphic card/drivers\n" ); g_qeglobals.texture_components = GL_RGBA; m_nTextureCompressionFormat = 0; } } #ifdef ATIHACK_812 void PrefsDlg::UpdateATIHack() { // if OpenGL is not ready yet, don't do anything if ( !g_qeglobals.m_bOpenGLReady ) { Sys_Printf( "OpenGL not ready - postpone ATI bug workaround setup\n" ); return; } if ( m_bGlATIHack ) { qglCullFace = &qglCullFace_ATIHack; qglDisable = &qglDisable_ATIHack; qglEnable = &qglEnable_ATIHack; qglPolygonMode = &qglPolygonMode_ATIHack; Sys_Printf( "ATI bug workaround enabled\n" ); } else { qglCullFace = qglCullFace_real; qglDisable = qglDisable_real; qglEnable = qglEnable_real; qglPolygonMode = qglPolygonMode_real; Sys_Printf( "ATI bug workaround disabled\n" ); } } #endif #ifdef NVIDIA_AERO_HACK void PrefsDlg::UpdateNvidiaAeroHack() { if ( m_bGlNvidiaAeroHack && m_bGlNvidiaAeroHackPrevState == 1 ) { return; } if ( ( !m_bGlNvidiaAeroHack ) && m_bGlNvidiaAeroHackPrevState == 0 ) { return; } if ( ( !m_bGlNvidiaAeroHack ) && m_bGlNvidiaAeroHackPrevState < 0 ) { // The hack state is uninitialized, meaning that this is the first call // to this function. I prefer not to explicitly enable composition because // the user may have set the application to disable it, and I don't want to // override that. Leave the state of composition as-is if the hack checkbox // isn't checked. m_bGlNvidiaAeroHackPrevState = 0; return; } HMODULE lib = LoadLibrary( "dwmapi.dll" ); if ( lib ) { void ( WINAPI *qDwmEnableComposition )( bool bEnable ) = ( void (WINAPI *) ( bool bEnable ) )GetProcAddress( lib, "DwmEnableComposition" ); if ( qDwmEnableComposition ) { if ( m_bGlNvidiaAeroHack ) { Sys_Printf( "Disabling Windows composition\n" ); qDwmEnableComposition( 0 ); m_bGlNvidiaAeroHackPrevState = 1; } else { Sys_Printf( "Enabling Windows composition\n" ); qDwmEnableComposition( 1 ); m_bGlNvidiaAeroHackPrevState = 0; } } FreeLibrary( lib ); } } #endif // TTimo: m_strEnginePath has a special status, if not found in registry we need to // initiliaze it for sure. It is not totally failsafe but we can use the same // code than in q3map, expecting to find some "quake" above us. If not, we prompt // for the engine executable path void PrefsDlg::LoadPrefs(){ int i; // first things first, load prefs from global prefs mGamesDialog.LoadPrefs(); // if we already have a document loaded, we will free and reload from file if ( mLocalPrefs.InUse() ) { mLocalPrefs.Clear(); } // load local.pref file mLocalPrefs.ReadXMLFile( m_inipath->str ); mLocalPrefs.GetPref( PATCHSHOWBOUNDS_KEY, &g_bPatchShowBounds, FALSE ); mLocalPrefs.GetPref( MOUSE_KEY, &m_nMouse, MOUSE_DEF ); m_nMouseButtons = m_nMouse ? 3 : 2; // project file // if it's not found here, mainframe.cpp will take care of finding one mLocalPrefs.GetPref( LASTPROJ_KEY, &m_strLastProject, "" ); mLocalPrefs.GetPref( LASTPROJVER_KEY, &m_nLastProjectVer, -1 ); // prefab path // NOTE TTimo: I'm not sure why this is in prefs // should probably be a project setting // and I'm not sure that we really have a way to set this reliably either CString strPrefab; strPrefab = g_qeglobals.m_strHomeGame.GetBuffer(); strPrefab += g_pGameDescription->mBaseGame.GetBuffer(); strPrefab += "/prefabs/"; mLocalPrefs.GetPref( PREFAB_KEY, &m_strPrefabPath, strPrefab ); mLocalPrefs.GetPref( LASTLIGHTINTENSITY_KEY, &m_iLastLightIntensity, 300 ); mLocalPrefs.GetPref( TLOCK_KEY, &m_bTextureLock, TLOCK_DEF ); mLocalPrefs.GetPref( RLOCK_KEY, &m_bRotateLock, TLOCK_DEF ); mLocalPrefs.GetPref( LASTMAP_KEY, &m_strLastMap, "" ); mLocalPrefs.GetPref( LOADLAST_KEY, &m_bLoadLast, LOADLAST_DEF ); mLocalPrefs.GetPref( BSP_KEY, &m_bInternalBSP, FALSE ); mLocalPrefs.GetPref( RCLICK_KEY, &m_bRightClick, TRUE ); mLocalPrefs.GetPref( AUTOSAVE_KEY, &m_bAutoSave, TRUE ); mLocalPrefs.GetPref( LOADLASTMAP_KEY, &m_bLoadLastMap, FALSE ); mLocalPrefs.GetPref( TINYBRUSH_KEY, &m_bCleanTiny, FALSE ); mLocalPrefs.GetPref( TINYSIZE_KEY, &m_fTinySize, 0.5f ); mLocalPrefs.GetPref( AUTOSAVETIME_KEY, &m_nAutoSave, 5 ); mLocalPrefs.GetPref( SNAPSHOT_KEY, &m_bSnapShots, FALSE ); mLocalPrefs.GetPref( MOVESPEED_KEY, &m_nMoveSpeed, 100 ); mLocalPrefs.GetPref( ANGLESPEED_KEY, &m_nAngleSpeed, 3 ); mLocalPrefs.GetPref( SETGAME_KEY, &m_bSetGame, FALSE ); mLocalPrefs.GetPref( CAMXYUPDATE_KEY, &m_bCamXYUpdate, TRUE ); mLocalPrefs.GetPref( CAMDRAGMULTISELECT_KEY, &m_nCamDragMultiSelect, TRUE ); mLocalPrefs.GetPref( CAMFREELOOK_KEY, &m_bCamFreeLook, TRUE ); mLocalPrefs.GetPref( CAMINVERSEMOUSE_KEY, &m_bCamInverseMouse, FALSE ); mLocalPrefs.GetPref( CAMDISCRETE_KEY, &m_bCamDiscrete, TRUE ); mLocalPrefs.GetPref( LIGHTDRAW_KEY, &m_bNewLightDraw, TRUE ); mLocalPrefs.GetPref( CUBICCLIP_KEY, &m_bCubicClipping, TRUE ); mLocalPrefs.GetPref( CUBICSCALE_KEY, &m_nCubicScale, 13 ); mLocalPrefs.GetPref( ALTEDGE_KEY, &m_bALTEdge, FALSE ); mLocalPrefs.GetPref( FACECOLORS_KEY, &m_bFaceColors, FALSE ); mLocalPrefs.GetPref( XZVIS_KEY, &m_bXZVis, FALSE ); mLocalPrefs.GetPref( YZVIS_KEY, &m_bYZVis, FALSE ); mLocalPrefs.GetPref( ZVIS_KEY, &m_bZVis, FALSE ); mLocalPrefs.GetPref( SIZEPAINT_KEY, &m_bSizePaint, FALSE ); mLocalPrefs.GetPref( DLLENTITIES_KEY, &m_bDLLEntities, FALSE ); mLocalPrefs.GetPref( DETACHABLEMENUS_KEY, &m_bLatchedDetachableMenus, TRUE ); m_bDetachableMenus = m_bLatchedDetachableMenus; if ( g_pGameDescription->mNoPatch ) { m_bPatchToolbar = false; } else { mLocalPrefs.GetPref( PATCHTOOLBAR_KEY, &m_bLatchedPatchToolbar, TRUE ); m_bPatchToolbar = m_bLatchedPatchToolbar; } mLocalPrefs.GetPref( WIDETOOLBAR_KEY, &m_bLatchedWideToolbar, TRUE ); m_bWideToolbar = m_bLatchedWideToolbar; mLocalPrefs.GetPref( PLUGINTOOLBAR_KEY, &m_bLatchedPluginToolbar, TRUE ); m_bPluginToolbar = m_bLatchedPluginToolbar; mLocalPrefs.GetPref( WINDOW_KEY, (int*)&m_nLatchedView, WINDOW_DEF ); m_nView = m_nLatchedView; mLocalPrefs.GetPref( FLOATINGZ_KEY, &m_bLatchedFloatingZ, FALSE ); m_bFloatingZ = m_bLatchedFloatingZ; mLocalPrefs.GetPref( TEXTUREQUALITY_KEY, &m_nLatchedTextureQuality, 3 ); m_nTextureQuality = m_nLatchedTextureQuality; mLocalPrefs.GetPref( LOADSHADERS_KEY, &m_nLatchedShader, 0 ); m_nShader = m_nLatchedShader; mLocalPrefs.GetPref( NOCLAMP_KEY, &m_bNoClamp, FALSE ); mLocalPrefs.GetPref( SNAP_KEY, &m_bSnap, TRUE ); mLocalPrefs.GetPref( USERINI_KEY, &m_strUserPath, "" ); mLocalPrefs.GetPref( ROTATION_KEY, &m_nRotation, 45 ); mLocalPrefs.GetPref( CHASEMOUSE_KEY, &m_bChaseMouse, TRUE ); mLocalPrefs.GetPref( ENTITYSHOW_KEY, &m_nEntityShowState, ENTITY_SKINNED_BOXED ); // this will probably need to be 75 or 100 for Q1. mLocalPrefs.GetPref( TEXTURESCALE_KEY, &m_nTextureScale, 50 ); // FIXME: Hydra - actually, this stuff is Q1,Q2 and HL specific. if ( ( g_pGameDescription->mGameFile == "hl.game" ) ) { // No BSP monitoring in the default compiler tools for Half-life (yet) mLocalPrefs.GetPref( WATCHBSP_KEY, &m_bWatchBSP, FALSE ); // Texture subset on by default (HL specific really, because of halflife.wad's size) mLocalPrefs.GetPref( TEXTURE_KEY, &m_bTextureWindow, TRUE ); } else if ( g_pGameDescription->quake2 ) { // BSP monitoring is implemented in Quake2 and Heretic2 tools mLocalPrefs.GetPref( WATCHBSP_KEY, &m_bWatchBSP, TRUE ); // Texture subset on by default (HL specific really, because of halflife.wad's size) mLocalPrefs.GetPref( TEXTURE_KEY, &m_bTextureWindow, TRUE ); } else { mLocalPrefs.GetPref( WATCHBSP_KEY, &m_bWatchBSP, WATCHBSP_DEF ); mLocalPrefs.GetPref( TEXTURE_KEY, &m_bTextureWindow, FALSE ); } mLocalPrefs.GetPref( TEXTURESCROLLBAR_KEY, &m_bTextureScrollbar, TRUE ); mLocalPrefs.GetPref( DISPLAYLISTS_KEY, &m_bDisplayLists, TRUE ); mLocalPrefs.GetPref( ANTIALIASEDLINES_KEY, &m_bAntialiasedPointsAndLines, FALSE ); mLocalPrefs.GetPref( SWITCHCLIP_KEY, &m_bSwitchClip, TRUE ); mLocalPrefs.GetPref( SELWHOLEENTS_KEY, &m_bSelectWholeEntities, TRUE ); mLocalPrefs.GetPref( SHOWSHADERS_KEY, &m_bShowShaders, TRUE ); mLocalPrefs.GetPref( GLLIGHTING_KEY, &m_bGLLighting, FALSE ); mLocalPrefs.GetPref( NOSTIPPLE_KEY, &m_bNoStipple, FALSE ); mLocalPrefs.GetPref( UNDOLEVELS_KEY, &m_nUndoLevels, 30 ); mLocalPrefs.GetPref( VERTEXMODE_KEY, &m_bVertexSplit, TRUE ); mLocalPrefs.GetPref( RUNQ2_KEY, &m_bRunQuake, RUNQ2_DEF ); mLocalPrefs.GetPref( LEAKSTOP_KEY, &m_bLeakStop, TRUE ); mLocalPrefs.GetPref( DOSLEEP_KEY, &m_bDoSleep, FALSE ); mLocalPrefs.GetPref( SELECTCURVES_KEY, &m_bSelectCurves, TRUE ); mLocalPrefs.GetPref( SELECTMODELS_KEY, &m_bSelectModels, TRUE ); mLocalPrefs.GetPref( SHADERLISTONLY_KEY, &m_bTexturesShaderlistOnly, FALSE ); mLocalPrefs.GetPref( DEFAULTTEXURESCALE_KEY, &m_fDefTextureScale, g_pGameDescription->mTextureDefaultScale ); mLocalPrefs.GetPref( SUBDIVISIONS_KEY, &m_nSubdivisions, SUBDIVISIONS_DEF ); mLocalPrefs.GetPref( CLIPCAULK_KEY, &m_bClipCaulk, FALSE ); mLocalPrefs.GetPref( SNAPTTOGRID_KEY, &m_bSnapTToGrid, FALSE ); mLocalPrefs.GetPref( TARGETFIX_KEY, &m_bDoTargetFix, TRUE ); mLocalPrefs.GetPref( WHEELINC_KEY, &m_nWheelInc, 64 ); mLocalPrefs.GetPref( PATCHBBOXSEL_KEY, &m_bPatchBBoxSelect, FALSE ); // Gef: Kyro GL_POINT workaround mLocalPrefs.GetPref( GLPOINTWORKAROUND_KEY, &m_bGlPtWorkaround, FALSE ); // window positioning mLocalPrefs.GetPref( ENTITYSPLIT1_KEY, &mWindowInfo.nEntitySplit1, -1 ); mLocalPrefs.GetPref( ENTITYSPLIT2_KEY, &mWindowInfo.nEntitySplit2, -1 ); mLocalPrefs.GetPref( POSITIONX_KEY, &mWindowInfo.position.x, -1 ); mLocalPrefs.GetPref( POSITIONY_KEY, &mWindowInfo.position.y, -1 ); mLocalPrefs.GetPref( WIDTH_KEY, &mWindowInfo.position.w, -1 ); mLocalPrefs.GetPref( HEIGHT_KEY, &mWindowInfo.position.h, 450 ); const window_position_t default_window_pos = { 0, 0, 200, 200, }; mLocalPrefs.GetPref( ENTITYWND_KEY, &mWindowInfo.posEntityWnd, default_window_pos ); mLocalPrefs.GetPref( MAPINFOWND_KEY, &mWindowInfo.posMapInfoWnd, default_window_pos ); mLocalPrefs.GetPref( CAMWND_KEY, &mWindowInfo.posCamWnd, default_window_pos ); mLocalPrefs.GetPref( ZWND_KEY, &mWindowInfo.posZWnd, default_window_pos ); mLocalPrefs.GetPref( XYWND_KEY, &mWindowInfo.posXYWnd, default_window_pos ); mLocalPrefs.GetPref( YZWND_KEY, &mWindowInfo.posYZWnd, default_window_pos ); mLocalPrefs.GetPref( XZWND_KEY, &mWindowInfo.posXZWnd, default_window_pos ); mLocalPrefs.GetPref( PATCHWND_KEY, &mWindowInfo.posPatchWnd, default_window_pos ); mLocalPrefs.GetPref( SURFACEWND_KEY, &mWindowInfo.posSurfaceWnd, default_window_pos ); mLocalPrefs.GetPref( ENTITYINFOWND_KEY, &mWindowInfo.posEntityInfoWnd, default_window_pos ); mLocalPrefs.GetPref( ZWIDTH_KEY, &mWindowInfo.nZWidth, 30 ); mLocalPrefs.GetPref( XYHEIGHT_KEY, &mWindowInfo.nXYHeight, 300 ); mLocalPrefs.GetPref( XYWIDTH_KEY, &mWindowInfo.nXYWidth, 300 ); mLocalPrefs.GetPref( CAMWIDTH_KEY, &mWindowInfo.nCamWidth, 200 ); mLocalPrefs.GetPref( CAMHEIGHT_KEY, &mWindowInfo.nCamHeight, 200 ); mLocalPrefs.GetPref( ZFLOATWIDTH_KEY, &mWindowInfo.nZFloatWidth, 300 ); #ifdef _WIN32 mLocalPrefs.GetPref( STATE_KEY, &mWindowInfo.nState, SW_SHOW ); #endif // menu stuff mLocalPrefs.GetPref( COUNT_KEY, &m_nMRUCount, 0 ); for ( i = 0; i < 4; i++ ) { char buf[64]; sprintf( buf, "%s%d", FILE_KEY, i ); mLocalPrefs.GetPref( buf, &m_strMRUFiles[i], "" ); } // some platform specific prefs #ifdef _WIN32 mLocalPrefs.GetPref( NATIVEGUI_KEY, &m_bNativeGUI, TRUE ); mLocalPrefs.GetPref( STARTONPRIMMON_KEY, &m_bStartOnPrimMon, FALSE ); #endif mLocalPrefs.GetPref( SI_TEXMENU_KEY, &g_qeglobals.d_savedinfo.iTexMenu, ID_VIEW_BILINEARMIPMAP ); mLocalPrefs.GetPref( SI_GAMMA_KEY, &g_qeglobals.d_savedinfo.fGamma, 1.0f ); mLocalPrefs.GetPref( SI_EXCLUDE_KEY, &g_qeglobals.d_savedinfo.exclude, 0 ); // nothing filtered by default mLocalPrefs.GetPref( SI_INCLUDE_KEY, &g_qeglobals.d_savedinfo.include, INCLUDE_NAMES | INCLUDE_COORDS | INCLUDE_ANGLES | INCLUDE_CAMERATINT ); mLocalPrefs.GetPref( SI_SHOWNAMES_KEY, &g_qeglobals.d_savedinfo.show_names, FALSE ); mLocalPrefs.GetPref( SI_SHOWCOORDS_KEY, &g_qeglobals.d_savedinfo.show_coordinates, TRUE ); mLocalPrefs.GetPref( SI_SHOWANGLES_KEY, &g_qeglobals.d_savedinfo.show_angles, TRUE ); mLocalPrefs.GetPref( SI_SHOWOUTLINES_KEY, &g_qeglobals.d_savedinfo.show_outline, FALSE ); mLocalPrefs.GetPref( SI_SHOWAXIS_KEY, &g_qeglobals.d_savedinfo.show_axis, TRUE ); mLocalPrefs.GetPref( SI_NOSELOUTLINES_KEY, &g_qeglobals.d_savedinfo.bNoSelectedOutlines, FALSE ); mLocalPrefs.GetPref( SI_OUTLINESTYLE_KEY, &g_qeglobals.d_savedinfo.iSelectedOutlinesStyle, OUTLINE_ZBUF | OUTLINE_BSEL ); LoadTexdefPref( &g_qeglobals.d_savedinfo.m_SIIncrement, SI_SURFACE_TEXDEF_KEY ); LoadTexdefPref( &g_qeglobals.d_savedinfo.m_PIIncrement, SI_PATCH_TEXDEF_KEY ); // text editor binding #ifdef _WIN32 mLocalPrefs.GetPref( CUSTOMSHADEREDITOR_KEY, &m_bUseWin32Editor, TRUE ); #else mLocalPrefs.GetPref( CUSTOMSHADEREDITOR_KEY, &m_bUseCustomEditor, FALSE ); mLocalPrefs.GetPref( CUSTOMSHADEREDITORCOMMAND_KEY, &m_strEditorCommand, "" ); #endif vec3_t vDefaultAxisColours[3] = { {0.f, 0.5f, 0.f}, {0.f, 0.f, 1.f}, {1.f, 0.f, 0.f}, }; for ( i = 0; i < 3; i++ ) { char buf[64]; sprintf( buf, "%s%d", SI_AXISCOLORS_KEY, i ); mLocalPrefs.GetPref( buf, g_qeglobals.d_savedinfo.AxisColors[i], vDefaultAxisColours[i] ); } vec3_t vDefaultColours[COLOR_LAST] = { {0.25f, 0.25f, 0.25f}, {1.f, 1.f, 1.f}, {0.75f, 0.75f, 0.75f}, {0.5f, 0.5f, 0.5f}, {0.25f, 0.25f, 0.25f}, {0.0f, 0.0f, 0.0f}, {0.f, 0.f, 1.f}, {0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, {0.5f, 0.f, 0.75f}, {1.0f, 0.f, 0.f}, {0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, }; for ( i = 0; i < COLOR_LAST; i++ ) { char buf[64]; sprintf( buf, "%s%d", SI_COLORS_KEY, i ); mLocalPrefs.GetPref( buf, g_qeglobals.d_savedinfo.colors[i], vDefaultColours[i] ); } mLocalPrefs.GetPref( TEXTURECOMPRESSIONFORMAT_KEY, &m_nTextureCompressionFormat, 1 ); mLocalPrefs.GetPref( LIGHTRADIUS_KEY, &m_nLightRadiuses, TRUE ); mLocalPrefs.GetPref( Q3MAP2TEX_KEY, &m_bQ3Map2Texturing, TRUE ); #ifdef ATIHACK_812 mLocalPrefs.GetPref( ATIHACK_KEY, &m_bGlATIHack, FALSE ); #endif #ifdef NVIDIA_AERO_HACK mLocalPrefs.GetPref( NVAEROHACK_KEY, &m_bGlNvidiaAeroHack, TRUE ); #endif Undo_SetMaxSize( m_nUndoLevels ); // set it internally as well / FIXME: why not just have one global value? UpdateTextureCompression(); #ifdef ATIHACK_812 UpdateATIHack(); #endif #ifdef NVIDIA_AERO_HACK UpdateNvidiaAeroHack(); #endif if ( mLocalPrefs.mbEmpty ) { mLocalPrefs.mbEmpty = false; Sys_Printf( "Saving local.pref with default pref values\n" ); SavePrefs(); } } void PrefsDlg::SavePrefs(){ if ( g_qeglobals.disable_ini ) { return; } #ifdef _DEBUG Sys_Printf( "PrefsDlg::SavePrefs\n" ); #endif // this will take care of copying back from the dialog to the variables // NOTE: it may be overkill to call systematically before a SavePrefs, but it's safer // this will also cause an UpdateData for the mGamesDialog UpdateData( TRUE ); mGamesDialog.SavePrefs(); // update the tree and save it mLocalPrefs.UpdatePrefTree(); if ( !mLocalPrefs.WriteXMLFile( m_inipath->str ) ) { Sys_FPrintf( SYS_ERR, "Error occured while saving local prefs file '%s'\n", m_inipath->str ); } if ( m_nMouse == 0 ) { m_nMouseButtons = 2; } else { m_nMouseButtons = 3; } } void PrefsDlg::PostModal( int code ){ if ( code == IDOK ) { SavePrefs(); // make sure the logfile is ok Sys_LogFile(); #ifdef ATIHACK_812 UpdateATIHack(); #endif #ifdef NVIDIA_AERO_HACK UpdateNvidiaAeroHack(); #endif if ( g_pParentWnd ) { g_pParentWnd->SetGridStatus(); } Sys_UpdateWindows( W_ALL ); if ( m_nUndoLevels != 0 ) { Undo_SetMaxSize( m_nUndoLevels ); } } } void PrefsDlg::DoEditorSensitivity(){ if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( m_pWidget ), "check_customeditor" ) ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "label_customeditor" ) ), TRUE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "entry_customeditor" ) ), TRUE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "button_customeditor" ) ), TRUE ); } else { gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "label_customeditor" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "entry_customeditor" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "button_customeditor" ) ), FALSE ); } } void PrefsDlg::DoSensitivity(){ #if 0 // first, look at the project file version ... will monitoring work? // project files now XML, guaranteed to be at least version 2 if ( 0 ) { //IntForKey( g_qeglobals.d_project_entity, "version" ) < 2) if ( m_bWarn ) { Str Msg; Msg = "The current project file ("; Msg += g_PrefsDlg.m_strLastProject; Msg += ") is not at least version 2.\nI need version 2 or above to setup BSP monitoring correctly."; gtk_MessageBox( m_pWidget, Msg.GetBuffer(), MB_OK ); m_bWarn = false; } // go ahead, disable everybuddy gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_leakstop" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_monitorbsp" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_runengine" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_sleep" ) ), FALSE ); } else { #endif // m_bWarn = true; gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_leakstop" ) ), TRUE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_monitorbsp" ) ), TRUE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_runengine" ) ), TRUE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_sleep" ) ), TRUE ); if ( !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( m_pWidget ), "check_monitorbsp" ) ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_leakstop" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_runengine" ) ), FALSE ); gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_sleep" ) ), FALSE ); } else if ( !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( m_pWidget ), "check_runengine" ) ) ) ) { gtk_widget_set_sensitive( GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "check_sleep" ) ), FALSE ); } } /* ============================================================ CGameInstall ============================================================ */ CGameInstall::CGameInstall() { memset( m_availGames, 0, sizeof( m_availGames ) ); } void CGameInstall::OnBtnBrowseEngine( GtkWidget *widget, gpointer data ) { Sys_Printf( "OnBtnBrowseEngine\n" ); CGameInstall* i = static_cast( data ); char *dir = dir_dialog( i->m_pWidget, _( "Select game directory" ), NULL ); i->UpdateData( TRUE ); if ( dir != NULL ) { i->m_strEngine = dir; i->UpdateData( FALSE ); g_free( dir ); } } void CGameInstall::OnGameSelectChanged( GtkWidget *widget, gpointer data ) { Sys_Printf( "OnGameSelectChanged\n" ); CGameInstall* i = static_cast( data ); i->UpdateData( TRUE ); i->m_strName = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget ) ); i->UpdateData( FALSE ); } void CGameInstall::BuildDialog() { GtkWidget *dlg, *vbox1, *button, *text, *combo, *entry, *hbox; dlg = m_pWidget; gtk_window_set_title( GTK_WINDOW( dlg ), _( "Configure games" ) ); vbox1 = gtk_vbox_new( FALSE, 0 ); gtk_widget_show( vbox1 ); gtk_container_add( GTK_CONTAINER( dlg ), vbox1 ); text = gtk_label_new( _( "Select the game to configure" ) ); gtk_widget_show( text ); gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); combo = gtk_combo_box_new_text(); gtk_widget_show( combo ); gtk_box_pack_start( GTK_BOX( vbox1 ), combo, FALSE, FALSE, 0 ); // GList *combo_list = NULL; int iGame = 0; while ( m_availGames[ iGame ] != GAME_NONE ) { switch ( m_availGames[ iGame ] ) { case GAME_Q2: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Quake II" ) ); break; case GAME_Q3: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Quake III Arena and mods" ) ); break; case GAME_URT: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Urban Terror (standalone)" ) ); break; case GAME_UFOAI: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "UFO: Alien Invasion" ) ); break; case GAME_Q2W: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Quake2World" ) ); break; case GAME_WARSOW: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Warsow" ) ); break; case GAME_NEXUIZ: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Nexuiz" ) ); break; case GAME_TREMULOUS: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Tremulous" ) ); break; case GAME_JA: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Jedi Academy and mods" ) ); break; case GAME_REACTION: gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _( "Reaction Quake 3" ) ); break; } iGame++; } AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT ); gtk_signal_connect( GTK_OBJECT( combo ), "changed", G_CALLBACK( OnGameSelectChanged ), this ); gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 ); // NOTE: will trigger signal text = gtk_label_new( _( "Name:" ) ); gtk_widget_show( text ); gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 ); AddDialogData( entry, &m_strName, DLG_ENTRY_TEXT ); text = gtk_label_new( _( "Engine directory:" ) ); gtk_widget_show( text ); gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); hbox = gtk_hbox_new( FALSE, 0 ); gtk_widget_show( hbox ); gtk_box_pack_start( GTK_BOX( vbox1 ), hbox, FALSE, FALSE, 0 ); entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_box_pack_start( GTK_BOX( hbox ), entry, FALSE, FALSE, 0 ); AddDialogData( entry, &m_strEngine, DLG_ENTRY_TEXT ); button = gtk_button_new_with_label( _( "..." ) ); gtk_widget_show( button ); gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseEngine ), this ); gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 ); // this gets done in the project stuff atm #if 0 text = gtk_label_new( _( "Mod subdirectory:" ) ); gtk_widget_show( text ); gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 ); entry = gtk_entry_new(); gtk_widget_show( entry ); gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 ); AddDialogData( entry, &m_strMod, DLG_ENTRY_TEXT ); #endif button = gtk_button_new_with_label( _( "OK" ) ); gtk_widget_show( button ); gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); AddModalButton( button, IDOK ); button = gtk_button_new_with_label( _( "Cancel" ) ); gtk_widget_show( button ); gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 ); AddModalButton( button, IDCANCEL ); gtk_widget_set_usize( button, 60, -2 ); } void CGameInstall::Run() { ScanGames(); if ( m_availGames[0] == GAME_NONE ) { return; } if ( DoModal() == IDCANCEL ) { Sys_Printf( "game dialog cancelled\n" ); return; } Sys_Printf( "combo: %d name: %s engine: %s mod: %s\n", m_nComboSelect, m_strName.GetBuffer(), m_strEngine.GetBuffer(), m_strMod.GetBuffer() ); // write out the game file Str gameFilePath = g_strAppPath.GetBuffer(); gameFilePath += "games/"; if(CheckFile(gameFilePath) != PATH_DIRECTORY) { radCreateDirectory(gameFilePath); } switch ( m_availGames[ m_nComboSelect ] ) { case GAME_Q2: gameFilePath += "q2.game"; break; case GAME_Q3: gameFilePath += "q3.game"; break; case GAME_URT: gameFilePath += "urt.game"; break; case GAME_UFOAI: gameFilePath += "ufoai.game"; break; case GAME_Q2W: gameFilePath += "q2w.game"; break; case GAME_WARSOW: gameFilePath += "warsow.game"; break; case GAME_NEXUIZ: gameFilePath += "nexuiz.game"; break; case GAME_TREMULOUS: gameFilePath += "tremulous.game"; break; case GAME_JA: gameFilePath += "ja.game"; break; case GAME_REACTION: gameFilePath += "reaction.game"; break; } Sys_Printf( "game file: %s\n", gameFilePath.GetBuffer() ); FILE * fg = fopen( gameFilePath.GetBuffer(), "w" ); if ( fg == NULL ) { Error( "Failed to open %s for writing\n", gameFilePath.GetBuffer() ); } fprintf( fg, "\n\n" ); fclose( fg ); } /* =============== CGameInstall::ScanGames scan for active games that can be installed, based on the presence =============== */ void CGameInstall::ScanGames() { Str pakPaths = g_strAppPath.GetBuffer(); int iGame = 0; const char *dirname; pakPaths += "installs/"; FindFiles fileScan( pakPaths.GetBuffer() ); while ( ( dirname = fileScan.NextFile() ) != NULL ) { if ( stricmp( dirname, Q3_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_Q3; } if ( stricmp( dirname, URT_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_URT; } if ( stricmp( dirname, UFOAI_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_UFOAI; } if ( stricmp( dirname, Q2W_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_Q2W; } if ( stricmp( dirname, WARSOW_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_WARSOW; } if ( stricmp( dirname, NEXUIZ_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_NEXUIZ; } if ( stricmp( dirname, Q2_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_Q2; } if ( stricmp( dirname, TREMULOUS_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_TREMULOUS; } if ( stricmp( dirname, JA_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_JA; } if ( stricmp( dirname, REACTION_PACK ) == 0 ) { m_availGames[ iGame++ ] = GAME_REACTION; } } Sys_Printf( "No installable games found in: %s\n", pakPaths.GetBuffer() ); }