00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
00095
00096
00097
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
00123 Map_SaveFile(strFile.GetBuffer(0), false);
00124 Sys_SetTitle (currentmap);
00125 if (lSize > 12 * 1024 * 1024)
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
00139
00140
00141
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
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);
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
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
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();
00302
00303 Map_New();
00304
00305
00306 FillTextureMenu();
00307 FillBSPMenu();
00308
00309 return true;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319 qboolean QE_SaveProject (const char* pProjectFile)
00320 {
00321
00322 FILE *fp;
00323 epair_t *ep;
00324
00325
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
00345
00346
00347 #define SPEED_MOVE 32
00348 #define SPEED_TURN 22.5
00349
00350
00351
00352
00353
00354
00355
00356
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
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
00451
00452 g_qeglobals.d_gridsize = 8;
00453 g_qeglobals.d_showgrid = true;
00454
00455
00456
00457
00458 Texture_Init (true);
00459
00460
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
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
00507
00508
00509
00510
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
00530
00531
00532 double I_FloatTime (void)
00533 {
00534 time_t t;
00535
00536 time (&t);
00537
00538 return t;
00539 #if 0
00540
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
00561
00562
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
00577 skipwhite:
00578 while ( (c = *data) <= ' ')
00579 {
00580 if (c == 0)
00581 {
00582 com_eof = true;
00583 return NULL;
00584 }
00585 data++;
00586 }
00587
00588
00589 if (c=='/' && data[1] == '/')
00590 {
00591 while (*data && *data != '\n')
00592 data++;
00593 goto skipwhite;
00594 }
00595
00596
00597
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
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
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
00644
00645
00646
00647
00648
00649 int argc;
00650 char *argv[MAX_NUM_ARGVS];
00651
00652
00653
00654
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
00690
00691
00692
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
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