Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

QE3.CPP

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #include "stdafx.h"
00023 #include "qe3.h"
00024 #include "PrefsDlg.h"
00025 #include <direct.h>  
00026 #include <sys\stat.h> 
00027 
00028 QEGlobals_t  g_qeglobals;
00029 
00030 void WINAPI QE_CheckOpenGLForErrors(void)
00031 {
00032   CString strMsg;
00033   int i = qglGetError();
00034   if (i != GL_NO_ERROR)
00035   {
00036     if (i == GL_OUT_OF_MEMORY)
00037     {
00038       //strMsg.Format("OpenGL out of memory error %s\nDo you wish to save before exiting?", qgluErrorString((GLenum)i));
00039       if (MessageBox(g_qeglobals.d_hwndMain, strMsg, "Q3Radiant Error", MB_YESNO) == IDYES)
00040       {
00041         Map_SaveFile(NULL, false);
00042       }
00043           exit(1);
00044     }
00045     else
00046     {
00047       //strMsg.Format("Warning: OpenGL Error %s\n ", qgluErrorString((GLenum)i));
00048           Sys_Printf (strMsg.GetBuffer(0));
00049     }
00050   }
00051 }
00052 
00053 
00054 char *ExpandReletivePath (char *p)
00055 {
00056     static char temp[1024];
00057     char    *base;
00058 
00059     if (!p || !p[0])
00060         return NULL;
00061     if (p[0] == '/' || p[0] == '\\')
00062         return p;
00063 
00064     base = ValueForKey(g_qeglobals.d_project_entity, "basepath");
00065     sprintf (temp, "%s/%s", base, p);
00066     return temp;
00067 }
00068 
00069 char *copystring (char *s)
00070 {
00071     char    *b;
00072     b = (char*)malloc(strlen(s)+1);
00073     strcpy (b,s);
00074     return b;
00075 }
00076 
00077 
00078 bool DoesFileExist(const char* pBuff, long& lSize)
00079 {
00080   CFile file;
00081   if (file.Open(pBuff, CFile::modeRead | CFile::shareDenyNone))
00082   {
00083     lSize += file.GetLength();
00084     file.Close();
00085     return true;
00086   }
00087   return false;
00088 }
00089 
00090 
00091 void Map_Snapshot()
00092 {
00093   CString strMsg;
00094   // we need to do the following
00095   // 1. make sure the snapshot directory exists (create it if it doesn't)
00096   // 2. find out what the lastest save is based on number
00097   // 3. inc that and save the map
00098   CString strOrgPath, strOrgFile;
00099   ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
00100   AddSlash(strOrgPath);
00101   strOrgPath += "snapshots";
00102   bool bGo = true;
00103   struct _stat Stat;
00104   if (_stat(strOrgPath, &Stat) == -1)
00105   {
00106     bGo = (_mkdir(strOrgPath) != -1);
00107   }
00108   AddSlash(strOrgPath);
00109   if (bGo)
00110   {
00111     int nCount = 0;
00112     long lSize = 0;
00113     CString strNewPath = strOrgPath;
00114     strNewPath += strOrgFile;
00115     CString strFile;
00116     while (bGo)
00117     {
00118       strFile.Format("%s.%i", strNewPath, nCount);
00119       bGo = DoesFileExist(strFile, lSize);
00120       nCount++;
00121     }
00122     // strFile has the next available slot
00123     Map_SaveFile(strFile.GetBuffer(0), false);
00124         Sys_SetTitle (currentmap);
00125     if (lSize > 12 * 1024 * 1024) // total size of saves > 4 mb
00126     {
00127       Sys_Printf("The snapshot files in the [%s] directory total more than 4 megabytes. You might consider cleaning the directory up.", strOrgPath);
00128     }
00129   }
00130   else
00131   {
00132     strMsg.Format("Snapshot save failed.. unabled to create directory\n%s", strOrgPath);
00133     g_pParentWnd->MessageBox(strMsg);
00134   }
00135 }
00136 /*
00137 ===============
00138 QE_CheckAutoSave
00139 
00140 If five minutes have passed since making a change
00141 and the map hasn't been saved, save it out.
00142 ===============
00143 */
00144 
00145 
00146 void QE_CheckAutoSave( void )
00147 {
00148     static clock_t s_start;
00149     clock_t        now;
00150 
00151     now = clock();
00152 
00153     if ( modified != 1 || !s_start)
00154     {
00155         s_start = now;
00156         return;
00157     }
00158 
00159     if ( now - s_start > ( CLOCKS_PER_SEC * 60 * g_PrefsDlg.m_nAutoSave))
00160     {
00161 
00162     if (g_PrefsDlg.m_bAutoSave)
00163     {
00164       CString strMsg = g_PrefsDlg.m_bSnapShots ? "Autosaving snapshot..." : "Autosaving...";
00165           Sys_Printf(strMsg.GetBuffer(0));
00166       Sys_Printf("\n");
00167           Sys_Status (strMsg.GetBuffer(0),0);
00168 
00169       // only snapshot if not working on a default map
00170       if (g_PrefsDlg.m_bSnapShots && stricmp(currentmap, "unnamed.map") != 0)
00171       {
00172         Map_Snapshot();
00173       }
00174       else
00175       {
00176             Map_SaveFile (ValueForKey(g_qeglobals.d_project_entity, "autosave"), false);
00177       }
00178 
00179           Sys_Status ("Autosaving...Saved.", 0 );
00180           modified = 2;
00181     }
00182     else
00183     {
00184           Sys_Printf ("Autosave skipped...\n");
00185           Sys_Status ("Autosave skipped...", 0 );
00186     }
00187         s_start = now;
00188     }
00189 }
00190 
00191 
00192 int BuildShortPathName(const char* pPath, char* pBuffer, int nBufferLen)
00193 {
00194   char *pFile = NULL;
00195   int nResult = GetFullPathName(pPath, nBufferLen, pBuffer, &pFile); 
00196   nResult = GetShortPathName(pPath, pBuffer, nBufferLen);
00197   if (nResult == 0)
00198     strcpy(pBuffer, pPath);                     // Use long filename
00199   return nResult;
00200 }
00201 
00202 
00203 
00204 const char *g_pPathFixups[]=
00205 {
00206   "basepath",
00207   "remotebasepath",
00208   "entitypath",
00209   "texturepath",
00210   "autosave",
00211   "mapspath"
00212 };
00213 
00214 const int g_nPathFixupCount = sizeof(g_pPathFixups) / sizeof(const char*);
00215 
00216 /*
00217 ===========
00218 QE_LoadProject
00219 ===========
00220 */
00221 qboolean QE_LoadProject (char *projectfile)
00222 {
00223     char    *data;
00224 
00225     Sys_Printf ("QE_LoadProject (%s)\n", projectfile);
00226     
00227     if ( LoadFileNoCrash (projectfile, (void **)&data) == -1)
00228         return false;
00229     
00230     g_strProject = projectfile;
00231     
00232     CString strData = data;
00233     free(data);
00234     
00235     CString strQ2Path = g_PrefsDlg.m_strQuake2;
00236     CString strQ2File;
00237     ExtractPath_and_Filename(g_PrefsDlg.m_strQuake2, strQ2Path, strQ2File);
00238     AddSlash(strQ2Path);
00239     
00240     
00241     char* pBuff = new char[1024];
00242     
00243     BuildShortPathName(strQ2Path, pBuff, 1024);
00244     FindReplace(strData, "__Q2PATH", pBuff);
00245     BuildShortPathName(g_strAppPath, pBuff, 1024);
00246     FindReplace(strData, "__QERPATH", pBuff);
00247     
00248     char* pFile;
00249     if (GetFullPathName(projectfile, 1024, pBuff, &pFile))
00250     {
00251         g_PrefsDlg.m_strLastProject = pBuff;
00252         BuildShortPathName(g_PrefsDlg.m_strLastProject, pBuff, 1024);
00253         g_PrefsDlg.m_strLastProject = pBuff;
00254         g_PrefsDlg.SavePrefs();
00255         
00256         ExtractPath_and_Filename(pBuff, strQ2Path, strQ2File);
00257         int nLen = strQ2Path.GetLength();
00258         if (nLen > 0)
00259         {
00260             if (strQ2Path[nLen - 1] == '\\')
00261                 strQ2Path.SetAt(nLen-1,'\0');
00262             char* pBuffer = strQ2Path.GetBufferSetLength(_MAX_PATH + 1);
00263             int n = strQ2Path.ReverseFind('\\');
00264             if (n >=0 )
00265                 pBuffer[n + 1] = '\0';
00266             strQ2Path.ReleaseBuffer();
00267             FindReplace(strData, "__QEPROJPATH", strQ2Path);
00268         }
00269     }
00270     
00271     
00272     StartTokenParsing (strData.GetBuffer(0));
00273     g_qeglobals.d_project_entity = Entity_Parse (true);
00274     if (!g_qeglobals.d_project_entity)
00275         Error ("Couldn't parse %s", projectfile);
00276 
00277   for (int i = 0; i < g_nPathFixupCount; i++)
00278   {
00279     char *pPath = ValueForKey (g_qeglobals.d_project_entity, g_pPathFixups[i]);
00280     if (pPath[0] != '\\' && pPath[0] != '/')
00281     {
00282         if (GetFullPathName(pPath, 1024, pBuff, &pFile))
00283       {
00284         SetKeyValue(g_qeglobals.d_project_entity, g_pPathFixups[i], pBuff);
00285       }
00286     }
00287   }
00288 
00289     delete []pBuff;
00290 
00291     // set here some default project settings you need
00292     if ( strlen( ValueForKey( g_qeglobals.d_project_entity, "brush_primit" ) ) == 0 )
00293     {
00294         SetKeyValue( g_qeglobals.d_project_entity, "brush_primit", "0" );
00295     }
00296 
00297     g_qeglobals.m_bBrushPrimitMode = IntForKey( g_qeglobals.d_project_entity, "brush_primit" );
00298 
00299 
00300     Eclass_InitForSourceDirectory (ValueForKey (g_qeglobals.d_project_entity, "entitypath"));
00301     FillClassList();        // list in entity window
00302     
00303     Map_New();
00304     
00305     
00306     FillTextureMenu();
00307     FillBSPMenu();
00308     
00309     return true;
00310 }
00311 
00312 /*
00313 ===========
00314 QE_SaveProject
00315 ===========
00316 */
00317 //extern char   *bsp_commands[256];
00318 
00319 qboolean QE_SaveProject (const char* pProjectFile)
00320 {
00321     //char  filename[1024];
00322     FILE    *fp;
00323     epair_t *ep;
00324 
00325     //sprintf (filename, "%s\\%s.prj", g_projectdir, g_username);
00326 
00327     if (!(fp = fopen (pProjectFile, "w+")))
00328         Error ("Could not open project file!");
00329     
00330     fprintf (fp, "{\n");
00331     for (ep = g_qeglobals.d_project_entity->epairs; ep; ep=ep->next)
00332         fprintf (fp, "\"%s\" \"%s\"\n", ep->key, ep->value);
00333     fprintf (fp, "}\n");
00334 
00335     fclose (fp);
00336     
00337     return TRUE;
00338 }
00339 
00340 
00341 
00342 /*
00343 ===========
00344 QE_KeyDown
00345 ===========
00346 */
00347 #define SPEED_MOVE  32
00348 #define SPEED_TURN  22.5
00349 
00350 
00351 /*
00352 ===============
00353 ConnectEntities
00354 
00355 Sets target / targetname on the two entities selected
00356 from the first selected to the secon
00357 ===============
00358 */
00359 void ConnectEntities (void)
00360 {
00361     entity_t    *e1, *e2, *e;
00362     char        *target, *tn;
00363     int         maxtarg, targetnum;
00364     char        newtarg[32];
00365 
00366     if (g_qeglobals.d_select_count != 2)
00367     {
00368         Sys_Status ("Must have two brushes selected.", 0);
00369         Sys_Beep ();
00370         return;
00371     }
00372 
00373     e1 = g_qeglobals.d_select_order[0]->owner;
00374     e2 = g_qeglobals.d_select_order[1]->owner;
00375 
00376     if (e1 == world_entity || e2 == world_entity)
00377     {
00378         Sys_Status ("Can't connect to the world.", 0);
00379         Sys_Beep ();
00380         return;
00381     }
00382 
00383     if (e1 == e2)
00384     {
00385         Sys_Status ("Brushes are from same entity.", 0);
00386         Sys_Beep ();
00387         return;
00388     }
00389 
00390     target = ValueForKey (e1, "target");
00391     if (target && target[0])
00392         strcpy (newtarg, target);
00393     else
00394     {
00395         target = ValueForKey (e2, "targetname");
00396         if (target && target[0])
00397             strcpy (newtarg, target);
00398         else
00399         {
00400             // make a unique target value
00401             maxtarg = 0;
00402             for (e=entities.next ; e != &entities ; e=e->next)
00403             {
00404                 tn = ValueForKey (e, "targetname");
00405                 if (tn && tn[0])
00406                 {
00407                     targetnum = atoi(tn+1);
00408                     if (targetnum > maxtarg)
00409                         maxtarg = targetnum;
00410                 }
00411             }
00412             sprintf (newtarg, "t%i", maxtarg+1);
00413         }
00414     }
00415 
00416     SetKeyValue (e1, "target", newtarg);
00417     SetKeyValue (e2, "targetname", newtarg);
00418     Sys_UpdateWindows (W_XY | W_CAMERA);
00419 
00420     Select_Deselect();
00421     Select_Brush (g_qeglobals.d_select_order[1]);
00422 }
00423 
00424 qboolean QE_SingleBrush (bool bQuiet)
00425 {
00426     if ( (selected_brushes.next == &selected_brushes)
00427         || (selected_brushes.next->next != &selected_brushes) )
00428     {
00429       if (!bQuiet)
00430     {
00431         Sys_Printf ("Error: you must have a single brush selected\n");
00432       }
00433         return false;
00434     }
00435     if (selected_brushes.next->owner->eclass->fixedsize)
00436     {
00437       if (!bQuiet)
00438       {
00439           Sys_Printf ("Error: you cannot manipulate fixed size entities\n");
00440       }
00441         return false;
00442     }
00443 
00444     return true;
00445 }
00446 
00447 void QE_Init (void)
00448 {
00449     /*
00450     ** initialize variables
00451     */
00452     g_qeglobals.d_gridsize = 8;
00453     g_qeglobals.d_showgrid = true;
00454 
00455     /*
00456     ** other stuff
00457     */
00458     Texture_Init (true);
00459     //Cam_Init ();
00460     //XY_Init ();
00461     Z_Init ();
00462     Terrain_Init();
00463 }
00464 
00465 void WINAPI QE_ConvertDOSToUnixName( char *dst, const char *src )
00466 {
00467     while ( *src )
00468     {
00469         if ( *src == '\\' )
00470             *dst = '/';
00471         else
00472             *dst = *src;
00473         dst++; src++;
00474     }
00475     *dst = 0;
00476 }
00477 
00478 int g_numbrushes, g_numentities;
00479 
00480 void QE_CountBrushesAndUpdateStatusBar( void )
00481 {
00482     static int      s_lastbrushcount, s_lastentitycount;
00483     static qboolean s_didonce;
00484     
00485     //entity_t   *e;
00486     brush_t    *b, *next;
00487 
00488     g_numbrushes = 0;
00489     g_numentities = 0;
00490     
00491     if ( active_brushes.next != NULL )
00492     {
00493         for ( b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
00494         {
00495             next = b->next;
00496             if (b->brush_faces )
00497             {
00498                 if ( !b->owner->eclass->fixedsize)
00499                     g_numbrushes++;
00500                 else
00501                     g_numentities++;
00502             }
00503         }
00504     }
00505 /*
00506     if ( entities.next != NULL )
00507     {
00508         for ( e = entities.next ; e != &entities && g_numentities != MAX_MAP_ENTITIES ; e = e->next)
00509         {
00510             g_numentities++;
00511         }
00512     }
00513 */
00514     if ( ( ( g_numbrushes != s_lastbrushcount ) || ( g_numentities != s_lastentitycount ) ) || ( !s_didonce ) )
00515     {
00516         Sys_UpdateStatusBar();
00517 
00518         s_lastbrushcount = g_numbrushes;
00519         s_lastentitycount = g_numentities;
00520         s_didonce = true;
00521     }
00522 }
00523 
00524 char        com_token[1024];
00525 qboolean    com_eof;
00526 
00527 /*
00528 ================
00529 I_FloatTime
00530 ================
00531 */
00532 double I_FloatTime (void)
00533 {
00534     time_t  t;
00535     
00536     time (&t);
00537     
00538     return t;
00539 #if 0
00540 // more precise, less portable
00541     struct timeval tp;
00542     struct timezone tzp;
00543     static int      secbase;
00544 
00545     gettimeofday(&tp, &tzp);
00546     
00547     if (!secbase)
00548     {
00549         secbase = tp.tv_sec;
00550         return tp.tv_usec/1000000.0;
00551     }
00552     
00553     return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
00554 #endif
00555 }
00556 
00557 
00558 /*
00559 ==============
00560 COM_Parse
00561 
00562 Parse a token out of a string
00563 ==============
00564 */
00565 char *COM_Parse (char *data)
00566 {
00567     int     c;
00568     int     len;
00569     
00570     len = 0;
00571     com_token[0] = 0;
00572     
00573     if (!data)
00574         return NULL;
00575         
00576 // skip whitespace
00577 skipwhite:
00578     while ( (c = *data) <= ' ')
00579     {
00580         if (c == 0)
00581         {
00582             com_eof = true;
00583             return NULL;            // end of file;
00584         }
00585         data++;
00586     }
00587     
00588 // skip // comments
00589     if (c=='/' && data[1] == '/')
00590     {
00591         while (*data && *data != '\n')
00592             data++;
00593         goto skipwhite;
00594     }
00595     
00596 
00597 // handle quoted strings specially
00598     if (c == '\"')
00599     {
00600         data++;
00601         do
00602         {
00603             c = *data++;
00604             if (c=='\"')
00605             {
00606                 com_token[len] = 0;
00607                 return data;
00608             }
00609             com_token[len] = c;
00610             len++;
00611         } while (1);
00612     }
00613 
00614 // parse single characters
00615     if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
00616     {
00617         com_token[len] = c;
00618         len++;
00619         com_token[len] = 0;
00620         return data+1;
00621     }
00622 
00623 // parse a regular word
00624     do
00625     {
00626         com_token[len] = c;
00627         data++;
00628         len++;
00629         c = *data;
00630     if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
00631             break;
00632     } while (c>32);
00633     
00634     com_token[len] = 0;
00635     return data;
00636 }
00637 
00638 
00639 
00640 /*
00641 =============================================================================
00642 
00643                         MISC FUNCTIONS
00644 
00645 =============================================================================
00646 */
00647 
00648 
00649 int     argc;
00650 char    *argv[MAX_NUM_ARGVS];
00651 
00652 /*
00653 ============
00654 ParseCommandLine
00655 ============
00656 */
00657 void ParseCommandLine (char *lpCmdLine)
00658 {
00659     argc = 1;
00660     argv[0] = "programname";
00661 
00662     while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
00663     {
00664         while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
00665             lpCmdLine++;
00666 
00667         if (*lpCmdLine)
00668         {
00669             argv[argc] = lpCmdLine;
00670             argc++;
00671 
00672             while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
00673                 lpCmdLine++;
00674 
00675             if (*lpCmdLine)
00676             {
00677                 *lpCmdLine = 0;
00678                 lpCmdLine++;
00679             }
00680             
00681         }
00682     }
00683 }
00684 
00685 
00686 
00687 /*
00688 =================
00689 CheckParm
00690 
00691 Checks for the given parameter in the program's command line arguments
00692 Returns the argument number (1 to argc-1) or 0 if not present
00693 =================
00694 */
00695 int CheckParm (char *check)
00696 {
00697     int             i;
00698 
00699     for (i = 1;i<argc;i++)
00700     {
00701         if ( stricmp(check, argv[i]) )
00702             return i;
00703     }
00704 
00705     return 0;
00706 }
00707 
00708 
00709 
00710 
00711 /*
00712 ==============
00713 ParseNum / ParseHex
00714 ==============
00715 */
00716 int ParseHex (char *hex)
00717 {
00718     char    *str;
00719     int    num;
00720 
00721     num = 0;
00722     str = hex;
00723 
00724     while (*str)
00725     {
00726         num <<= 4;
00727         if (*str >= '0' && *str <= '9')
00728             num += *str-'0';
00729         else if (*str >= 'a' && *str <= 'f')
00730             num += 10 + *str-'a';
00731         else if (*str >= 'A' && *str <= 'F')
00732             num += 10 + *str-'A';
00733         else
00734             Error ("Bad hex number: %s",hex);
00735         str++;
00736     }
00737 
00738     return num;
00739 }
00740 
00741 
00742 int ParseNum (char *str)
00743 {
00744     if (str[0] == '$')
00745         return ParseHex (str+1);
00746     if (str[0] == '0' && str[1] == 'x')
00747         return ParseHex (str+2);
00748     return atol (str);
00749 }
00750 
00751 

Generated on Thu Aug 25 12:38:37 2005 for Quake III Arena by  doxygen 1.3.9.1