Win_main.cpp (29415B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 #include "stdafx.h" 23 #include "qe3.h" 24 #include <process.h> 25 #include "mru.h" 26 #include "entityw.h" 27 #include "PrefsDlg.h" 28 29 static HWND s_hwndToolbar; 30 31 BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize); 32 BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize); 33 34 static HWND CreateMyStatusWindow(HINSTANCE hInst); 35 static HWND CreateToolBar(HINSTANCE hinst); 36 37 extern void WXY_Print( void ); 38 39 /* 40 ============================================================================== 41 42 MENU 43 44 ============================================================================== 45 */ 46 47 void OpenDialog (void); 48 void SaveAsDialog (bool bRegion); 49 qboolean ConfirmModified (void); 50 void Select_Ungroup (void); 51 52 void QE_ExpandBspString (char *bspaction, char *out, char *mapname, bool useTemps) 53 { 54 char *in; 55 char src[2048]; 56 char rsh[2048]; 57 char base[2048]; 58 59 strcpy(src, mapname); 60 strlwr(src); 61 in = strstr(src, "maps/"); 62 if (!in) 63 { 64 in = strstr(src, "maps\\"); 65 } 66 if (in) 67 { 68 in += 5; 69 strcpy(base, in); 70 in = base; 71 while (*in) 72 { 73 if (*in == '\\') 74 { 75 *in = '/'; 76 } 77 in++; 78 } 79 } 80 else 81 { 82 ExtractFileName (mapname, base); 83 } 84 85 if (useTemps) { 86 CString str; 87 CString strExt = "map"; 88 if ( strstr(mapname, ".reg") ) { 89 strExt = "reg"; 90 } 91 str.Format("%s/maps/%i.%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), ::GetTickCount(), strExt); 92 CopyFile(mapname, str, FALSE); 93 sprintf (src, "-tempname %s %s/maps/%s", str, ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base); 94 } else { 95 sprintf (src, "%s/maps/%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base); 96 } 97 strcpy (rsh, ValueForKey(g_qeglobals.d_project_entity, "rshcmd")); 98 99 QE_ConvertDOSToUnixName(src, src); 100 101 in = ValueForKey( g_qeglobals.d_project_entity, bspaction ); 102 while (*in) 103 { 104 if (in[0] == '!') 105 { 106 strcpy (out, rsh); 107 out += strlen(rsh); 108 in++; 109 continue; 110 } 111 if (in[0] == '$') 112 { 113 strcpy (out, src); 114 out += strlen(src); 115 in++; 116 continue; 117 } 118 if (in[0] == '@') 119 { 120 *out++ = '"'; 121 in++; 122 continue; 123 } 124 *out++ = *in++; 125 } 126 *out = 0; 127 } 128 129 void FindReplace(CString& strContents, const char* pTag, const char* pValue) 130 { 131 if (strcmp(pTag, pValue) == 0) 132 return; 133 for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag)) 134 { 135 int nRightLen = strContents.GetLength() - strlen(pTag) - nPos; 136 CString strLeft = strContents.Left(nPos); 137 CString strRight = strContents.Right(nRightLen); 138 strLeft += pValue; 139 strLeft += strRight; 140 strContents = strLeft; 141 } 142 } 143 144 145 146 HWND g_hWnd = NULL; 147 HANDLE g_hToolThread = NULL; 148 CString g_strParams; 149 150 UINT ToolThread(LPVOID pParam) 151 { 152 char* p = reinterpret_cast<char*>(pParam); 153 if (g_PrefsDlg.m_bPAK) 154 RunTools(p, g_hWnd, g_PrefsDlg.m_strPAKFile); 155 else 156 RunTools(p, g_hWnd, ""); 157 g_hToolThread = NULL; 158 delete []p; 159 return 0; 160 } 161 162 void ThreadTools(char* p) 163 { 164 CWinThread* pThread = AfxBeginThread(ToolThread, reinterpret_cast<LPVOID>(p)); 165 g_hToolThread = pThread->m_hThread; 166 } 167 168 HWND g_hwndFoundIt = NULL; 169 170 BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { 171 char buff[1024]; 172 const char* p = reinterpret_cast<const char*>(lParam); 173 GetWindowText(hwnd, buff, 1024); 174 if (!strcmpi(p, buff)) { 175 g_hwndFoundIt = hwnd; 176 return 1; 177 } 178 return 1; 179 } 180 181 182 HWND FindAnyWindow(const char *pTitle) { 183 HWND hwndDesktop = GetDesktopWindow(); 184 g_hwndFoundIt = NULL; 185 if ( hwndDesktop ) { 186 EnumChildWindows(hwndDesktop, (WNDENUMPROC)EnumChildProc, reinterpret_cast<LPARAM>(pTitle)); 187 } 188 return g_hwndFoundIt; 189 } 190 191 192 const UINT wm_AddCommand = RegisterWindowMessage( "Q3MPC_AddCommand" ); 193 194 CTime g_tBegin; 195 void RunBsp (char *command) 196 { 197 char sys[2048]; 198 char batpath[2048]; 199 char outputpath[2048]; 200 char temppath[1024]; 201 char name[2048]; 202 char cWork[2048]; 203 FILE *hFile; 204 BOOL ret; 205 PROCESS_INFORMATION ProcessInformation; 206 STARTUPINFO startupinfo; 207 HWND hwndPClient = NULL; 208 209 g_hWnd = g_pParentWnd->GetSafeHwnd(); 210 SetInspectorMode(W_CONSOLE); 211 g_tBegin = CTime::GetCurrentTime(); 212 213 214 DWORD dwExitcode; 215 ret = GetExitCodeProcess (g_hToolThread, &dwExitcode); 216 if (dwExitcode != STILL_ACTIVE) 217 g_hToolThread = NULL; 218 219 if (bsp_process || g_hToolThread) 220 { 221 Sys_Printf ("BSP is still going...\n"); 222 return; 223 } 224 225 outputpath[0] = '\0'; 226 GetTempPath(512, temppath); 227 228 CString strOutFile = temppath; 229 AddSlash(strOutFile); 230 strOutFile += "junk.txt"; 231 232 sprintf (outputpath, " >>%s\r\n", strOutFile); 233 234 strcpy (name, currentmap); 235 if (region_active) 236 { 237 Map_SaveFile (name, false); 238 StripExtension (name); 239 strcat (name, ".reg"); 240 } 241 242 Map_SaveFile (name, region_active); 243 244 // FIXME: this code just gets worse and worse 245 CString strPath, strFile; 246 247 char *rsh = ValueForKey(g_qeglobals.d_project_entity, "rshcmd"); 248 if (rsh == NULL) 249 { 250 ExtractPath_and_Filename(name, strPath, strFile); 251 AddSlash(strPath); 252 BuildShortPathName(strPath, cWork, 1024); 253 strcat(cWork, strFile); 254 } 255 else 256 { 257 strcpy(cWork, name); 258 } 259 260 hwndPClient = FindWindow(NULL, "Q3Map Process Client"); 261 if ( hwndPClient == NULL ) { 262 hwndPClient = FindAnyWindow("Q3Map Process Client"); 263 } 264 265 Sys_Printf("Window info for Process Client %i\n", reinterpret_cast<int>(hwndPClient)); 266 267 bool processServer = (rsh && strlen(rsh) > 0 && hwndPClient); 268 269 QE_ExpandBspString (command, sys, cWork, processServer); 270 271 // if we can find the q3map process server running 272 // we will submit maps to it instead of via createprocess 273 // 274 if (processServer) 275 { 276 CString str; 277 char cBuff[2048]; 278 char *pStart = sys; 279 char *pEnd = strstr(pStart, "&&"); 280 while (pEnd) 281 { 282 int nLen = pEnd-pStart-1; 283 strncpy(cBuff, pStart, nLen); 284 cBuff[nLen] = 0; 285 str = cBuff; 286 FindReplace(str, rsh, ""); 287 str.TrimLeft(' '); 288 str.TrimRight(' '); 289 ATOM a = GlobalAddAtom(str); 290 PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a); 291 pStart = pEnd+2; 292 pEnd = strstr(pStart, "&&"); 293 } 294 str = pStart; 295 FindReplace(str, rsh, ""); 296 str.TrimLeft(' '); 297 str.TrimRight(' '); 298 ATOM a = GlobalAddAtom(str); 299 PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a); 300 Sys_Printf("Commands sent to Q3Map Process Client\n"); 301 return; 302 } 303 304 CString strSys = sys; 305 306 FindReplace(strSys, "&&", outputpath); 307 strcpy(sys, strSys); 308 strcat(sys, outputpath); 309 310 if (g_PrefsDlg.m_bInternalBSP) 311 { 312 g_tBegin = CTime::GetCurrentTime(); 313 strSys.MakeLower(); 314 char* p = new char[strSys.GetLength()+1]; 315 strcpy(p, strSys.GetBuffer(0)); 316 ThreadTools(p); 317 } 318 else 319 { 320 Sys_ClearPrintf (); 321 Sys_Printf ("==================\nRunning bsp command...\n"); 322 Sys_Printf ("\n%s\n", sys); 323 324 //++timo removed the old way BSP commands .. dumping to junk.txt doesn't work on my win98 box 325 // FIXME : will most likely break Quake2 BSP commands, is fitted to a one-lined sys command 326 // 327 // write qe3bsp.bat 328 // 329 330 sprintf (batpath, "%sqe3bsp.bat", temppath); 331 hFile = fopen(batpath, "w"); 332 if (!hFile) 333 Error ("Can't write to %s", batpath); 334 fprintf (hFile, sys); 335 fclose (hFile); 336 337 Pointfile_Delete (); 338 339 // delete junk.txt file 340 remove(strOutFile); 341 342 GetStartupInfo (&startupinfo); 343 344 ret = CreateProcess( 345 batpath, 346 NULL, 347 NULL, 348 NULL, 349 FALSE, 350 0, 351 NULL, 352 NULL, 353 &startupinfo, 354 &ProcessInformation 355 ); 356 357 if (!ret) 358 Error ("CreateProcess failed"); 359 360 bsp_process = ProcessInformation.hProcess; 361 362 Sleep (100); // give the new process a chance to open it's window 363 364 BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top 365 #if 0 366 // 367 // write qe3bsp.bat 368 // 369 sprintf (batpath, "%sqe3bsp.bat", temppath); 370 hFile = fopen(batpath, "w"); 371 if (!hFile) 372 Error ("Can't write to %s", batpath); 373 fprintf (hFile, sys); 374 fclose (hFile); 375 376 // 377 // write qe3bsp2.bat 378 // 379 sprintf (batpath, "%sqe3bsp2.bat", temppath); 380 hFile = fopen(batpath, "w"); 381 if (!hFile) 382 Error ("Can't write to %s", batpath); 383 fprintf (hFile, "%sqe3bsp.bat > %s", temppath, outputpath); 384 fclose (hFile); 385 386 Pointfile_Delete (); 387 388 GetStartupInfo (&startupinfo); 389 390 ret = CreateProcess( 391 batpath, // pointer to name of executable module 392 NULL, // pointer to command line string 393 NULL, // pointer to process security attributes 394 NULL, // pointer to thread security attributes 395 FALSE, // handle inheritance flag 396 0 /*DETACHED_PROCESS*/, // creation flags 397 NULL, // pointer to new environment block 398 NULL, // pointer to current directory name 399 &startupinfo, // pointer to STARTUPINFO 400 &ProcessInformation // pointer to PROCESS_INFORMATION 401 ); 402 403 if (!ret) 404 Error ("CreateProcess failed"); 405 406 bsp_process = ProcessInformation.hProcess; 407 408 Sleep (100); // give the new process a chance to open it's window 409 410 //BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top 411 //SetFocus (g_qeglobals.d_hwndCamera); 412 #endif 413 } 414 } 415 416 void DLLBuildDone() 417 { 418 g_hToolThread = NULL; 419 CTime tEnd = CTime::GetCurrentTime(); 420 CTimeSpan tElapsed = tEnd - g_tBegin; 421 CString strElapsed; 422 strElapsed.Format("Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds()); 423 Sys_Printf(strElapsed.GetBuffer(0)); 424 Pointfile_Check(); 425 426 if (g_PrefsDlg.m_bRunQuake == TRUE) 427 { 428 char cCurDir[1024]; 429 GetCurrentDirectory(1024, cCurDir); 430 CString strExePath = g_PrefsDlg.m_strQuake2; 431 CString strOrgPath; 432 CString strOrgFile; 433 ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile); 434 if (g_PrefsDlg.m_bSetGame == TRUE) // run in place with set game.. don't copy map 435 { 436 CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath"); 437 strExePath += " +set game "; 438 strExePath += strBasePath; 439 WinExec(strExePath, SW_SHOW); 440 } 441 else 442 { 443 CString strCopyPath = strExePath; 444 char* pBuffer = strCopyPath.GetBufferSetLength(_MAX_PATH + 1); 445 pBuffer[strCopyPath.ReverseFind('\\') + 1] = '\0'; 446 strCopyPath.ReleaseBuffer(); 447 SetCurrentDirectory(strCopyPath); 448 CString strOrgPath; 449 CString strOrgFile; 450 ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile); 451 AddSlash(strCopyPath); 452 FindReplace(strOrgFile, ".map", ".bsp"); 453 strCopyPath += "\\baseq2\\maps\\"; 454 strCopyPath += strOrgFile; 455 AddSlash(strOrgPath); 456 strOrgPath += strOrgFile; 457 bool bRun = (strOrgPath.CompareNoCase(strCopyPath) == 0); 458 if (!bRun) 459 bRun = (CopyFile(strOrgPath, strCopyPath, FALSE) == TRUE); 460 if (bRun) 461 { 462 FindReplace(strOrgFile, ".bsp", ""); 463 strExePath += " +map "; 464 strExePath += strOrgFile; 465 WinExec(strExePath, SW_SHOW); 466 } 467 } 468 SetCurrentDirectory(cCurDir); 469 } 470 471 } 472 473 /* 474 ============= 475 DoColor 476 477 ============= 478 */ 479 480 class CMyColorDialog : public CColorDialog 481 { 482 DECLARE_DYNCREATE(CMyColorDialog); 483 // Construction 484 public: 485 CMyColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd* 486 pParentWnd = NULL ); 487 // Statics 488 protected: 489 enum { NCUSTCOLORS = 16 }; 490 static COLORREF c_CustColors[NCUSTCOLORS]; 491 static COLORREF c_LastCustColors[NCUSTCOLORS]; 492 static bool c_NeedToInitCustColors; 493 protected: 494 static void InitCustColors(); 495 static void SaveCustColors(); 496 // Dialog Data 497 protected: 498 //{{AFX_DATA(CMyColorDialog) 499 //}}AFX_DATA 500 // Overrides 501 protected: 502 // ClassWizard generate virtual function overrides 503 //{{AFX_VIRTUAL(CMyColorDialog) 504 public: 505 virtual int DoModal(); 506 protected: 507 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 508 //}}AFX_VIRTUAL 509 // Implementation 510 protected: 511 // Generated message map functions 512 //{{AFX_MSG(CMyColorDialog) 513 //}}AFX_MSG 514 DECLARE_MESSAGE_MAP() 515 }; 516 517 IMPLEMENT_DYNCREATE(CMyColorDialog, CColorDialog) 518 519 bool CMyColorDialog::c_NeedToInitCustColors = true; 520 COLORREF CMyColorDialog::c_CustColors[]; 521 COLORREF CMyColorDialog::c_LastCustColors[]; 522 523 #define SECTION _T("Custom Colors") 524 525 void CMyColorDialog::InitCustColors() { 526 for (int i = 0; i < NCUSTCOLORS; i++) { 527 CString entry; entry.Format("%d",i); 528 c_LastCustColors[i] = c_CustColors[i] = 529 ::AfxGetApp()->GetProfileInt(SECTION,entry,RGB(255,255,255)); 530 } 531 c_NeedToInitCustColors= false; 532 } 533 534 void CMyColorDialog::SaveCustColors() { 535 for (int i = 0; i < NCUSTCOLORS; i++) { 536 if (c_LastCustColors[i] != c_CustColors[i]) { 537 CString entry; entry.Format("%d",i); 538 if (c_CustColors[i] == RGB(255,255,255)) { 539 ::AfxGetApp()->WriteProfileString(SECTION,entry,NULL); 540 } else { 541 ::AfxGetApp()->WriteProfileInt(SECTION, entry,c_CustColors[i]); 542 } 543 c_LastCustColors[i] = c_CustColors[i]; 544 } 545 } 546 } 547 548 CMyColorDialog::CMyColorDialog( COLORREF clrInit, DWORD dwFlags, 549 CWnd* pParentWnd) : CColorDialog(clrInit,dwFlags,pParentWnd) 550 { 551 //{{AFX_DATA_INIT(CMyColorDialog) 552 //}}AFX_DATA_INIT 553 if (c_NeedToInitCustColors) { 554 InitCustColors(); 555 } 556 m_cc.lpCustColors = c_CustColors; 557 } 558 559 int CMyColorDialog::DoModal() { 560 int code = CColorDialog::DoModal(); 561 SaveCustColors(); 562 return code; 563 } 564 565 void CMyColorDialog::DoDataExchange(CDataExchange* pDX) { 566 // overridden (calls this base class) 567 CColorDialog::DoDataExchange(pDX); 568 //{{AFX_DATA_MAP(CMyColorDialog) 569 //}}AFX_DATA_MAP 570 } 571 572 BEGIN_MESSAGE_MAP(CMyColorDialog, CColorDialog) 573 //{{AFX_MSG_MAP(CMyColorDialog) 574 //}}AFX_MSG_MAP 575 END_MESSAGE_MAP() 576 577 void DoNewColor(int* i1, int* i2, int* i3) 578 { 579 COLORREF cr = (*i1) + 580 ((*i2) <<8) + 581 ((*i3) <<16); 582 CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT); 583 if (dlg.DoModal() == IDOK) 584 { 585 *i1 = (dlg.m_cc.rgbResult & 255); 586 *i2 = ((dlg.m_cc.rgbResult >> 8) & 255); 587 *i3 = ((dlg.m_cc.rgbResult >> 16) & 255); 588 } 589 590 } 591 592 593 qboolean DoColor(int iIndex) 594 { 595 596 COLORREF cr = (int)(g_qeglobals.d_savedinfo.colors[iIndex][0]*255) + 597 (((int)(g_qeglobals.d_savedinfo.colors[iIndex][1]*255))<<8) + 598 (((int)(g_qeglobals.d_savedinfo.colors[iIndex][2]*255))<<16); 599 CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT); 600 if (dlg.DoModal() == IDOK) 601 { 602 g_qeglobals.d_savedinfo.colors[iIndex][0] = (dlg.m_cc.rgbResult&255)/255.0; 603 g_qeglobals.d_savedinfo.colors[iIndex][1] = ((dlg.m_cc.rgbResult>>8)&255)/255.0; 604 g_qeglobals.d_savedinfo.colors[iIndex][2] = ((dlg.m_cc.rgbResult>>16)&255)/255.0; 605 606 /* 607 ** scale colors so that at least one component is at 1.0F 608 ** if this is meant to select an entity color 609 */ 610 if ( iIndex == COLOR_ENTITY ) 611 { 612 float largest = 0.0F; 613 614 if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest ) 615 largest = g_qeglobals.d_savedinfo.colors[iIndex][0]; 616 if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest ) 617 largest = g_qeglobals.d_savedinfo.colors[iIndex][1]; 618 if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest ) 619 largest = g_qeglobals.d_savedinfo.colors[iIndex][2]; 620 621 if ( largest == 0.0F ) 622 { 623 g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F; 624 g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F; 625 g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F; 626 } 627 else 628 { 629 float scaler = 1.0F / largest; 630 631 g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler; 632 g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler; 633 g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler; 634 } 635 } 636 637 Sys_UpdateWindows (W_ALL); 638 return true; 639 } 640 else return false; 641 642 } 643 644 645 /* Copied from MSDN */ 646 647 BOOL DoMru(HWND hWnd,WORD wId) 648 { 649 char szFileName[128]; 650 OFSTRUCT of; 651 BOOL fExist; 652 653 GetMenuItem(g_qeglobals.d_lpMruMenu, wId, TRUE, szFileName, sizeof(szFileName)); 654 655 // Test if the file exists. 656 657 fExist = OpenFile(szFileName ,&of,OF_EXIST) != HFILE_ERROR; 658 659 if (fExist) { 660 661 // Place the file on the top of MRU. 662 AddNewItem(g_qeglobals.d_lpMruMenu,(LPSTR)szFileName); 663 664 // Now perform opening this file !!! 665 Map_LoadFile (szFileName); 666 } 667 else 668 // Remove the file on MRU. 669 DelMenuItem(g_qeglobals.d_lpMruMenu,wId,TRUE); 670 671 // Refresh the File menu. 672 PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0), 673 ID_FILE_EXIT); 674 675 return fExist; 676 } 677 678 679 680 /* 681 ============== 682 Main_Create 683 ============== 684 */ 685 686 void MFCCreate (HINSTANCE hInstance) 687 { 688 HMENU hMenu = NULL; 689 int i = sizeof(g_qeglobals.d_savedinfo); 690 long l = i; 691 692 g_qeglobals.d_savedinfo.exclude |= (EXCLUDE_HINT | EXCLUDE_CLIP); 693 LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l); 694 695 int nOldSize = g_qeglobals.d_savedinfo.iSize; 696 if (g_qeglobals.d_savedinfo.iSize != sizeof(g_qeglobals.d_savedinfo)) 697 { 698 // fill in new defaults 699 g_qeglobals.d_savedinfo.iSize = sizeof(g_qeglobals.d_savedinfo); 700 g_qeglobals.d_savedinfo.fGamma = 1.0; 701 g_qeglobals.d_savedinfo.iTexMenu = ID_VIEW_BILINEARMIPMAP; 702 g_qeglobals.d_savedinfo.m_nTextureTweak = 1; 703 704 //g_qeglobals.d_savedinfo.exclude = INCLUDE_EASY | INCLUDE_NORMAL | INCLUDE_HARD | INCLUDE_DEATHMATCH; 705 g_qeglobals.d_savedinfo.show_coordinates = true; 706 g_qeglobals.d_savedinfo.show_names = false; 707 708 for (i=0 ; i<3 ; i++) 709 { 710 g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25; 711 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0; 712 g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75; 713 g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5; 714 g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25; 715 } 716 717 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0; 718 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0; 719 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0; 720 721 g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 0.0; 722 g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 0.0; 723 g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 0.0; 724 725 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0; 726 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0; 727 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0; 728 729 g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0; 730 g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0; 731 g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0; 732 733 g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 0.0; 734 g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 0.0; 735 g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 0.0; 736 737 g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.5; 738 g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.0; 739 g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.75; 740 741 742 // old size was smaller, reload original prefs 743 if (nOldSize < sizeof(g_qeglobals.d_savedinfo)) 744 { 745 long l = nOldSize; 746 LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l); 747 } 748 749 } 750 if ( ( hMenu = GetMenu( g_qeglobals.d_hwndMain ) ) != 0 ) 751 { 752 // by default all of these are checked because that's how they're defined in the menu editor 753 if ( !g_qeglobals.d_savedinfo.show_names ) 754 CheckMenuItem( hMenu, ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED ); 755 if ( !g_qeglobals.d_savedinfo.show_coordinates ) 756 CheckMenuItem( hMenu, ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED ); 757 758 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS ) 759 CheckMenuItem( hMenu, ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED ); 760 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT ) 761 CheckMenuItem( hMenu, ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED ); 762 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS ) 763 CheckMenuItem( hMenu, ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED ); 764 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER ) 765 CheckMenuItem( hMenu, ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED ); 766 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD ) 767 CheckMenuItem( hMenu, ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED ); 768 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP ) 769 CheckMenuItem( hMenu, ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED ); 770 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT ) 771 CheckMenuItem( hMenu, ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_UNCHECKED ); 772 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK ) 773 CheckMenuItem( hMenu, ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_UNCHECKED ); 774 } 775 776 } 777 778 779 /* 780 ============================================================= 781 782 REGISTRY INFO 783 784 ============================================================= 785 */ 786 787 BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize) 788 { 789 LONG lres; 790 DWORD dwDisp; 791 HKEY hKeyId; 792 793 if (g_qeglobals.use_ini) 794 { 795 lres = RegCreateKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, NULL, 796 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp); 797 } 798 else 799 { 800 lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, NULL, 801 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp); 802 } 803 804 if (lres != ERROR_SUCCESS) 805 return FALSE; 806 807 lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, (unsigned char*)pvBuf, lSize); 808 809 RegCloseKey(hKeyId); 810 811 if (lres != ERROR_SUCCESS) 812 return FALSE; 813 814 return TRUE; 815 } 816 817 BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize) 818 { 819 HKEY hKey; 820 long lres, lType, lSize; 821 822 if (plSize == NULL) 823 plSize = &lSize; 824 825 if (g_qeglobals.use_ini) 826 { 827 lres = RegOpenKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, KEY_READ, &hKey); 828 } 829 else 830 { 831 lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, KEY_READ, &hKey); 832 } 833 834 lres = RegQueryValueEx(hKey, pszName, NULL, (unsigned long*)&lType, (unsigned char*)pvBuf, (unsigned long*)plSize); 835 836 RegCloseKey(hKey); 837 838 if (lres != ERROR_SUCCESS) 839 { 840 #ifdef _DEBUG 841 char Message[1024]; 842 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, lres, 0, &(Message[0]), 1024, NULL ); 843 Sys_Printf( "WARNING: RegQueryValueEx failed in LoadRegistryInfo for %s : %s", pszName, Message ); 844 #endif 845 return FALSE; 846 } 847 848 return TRUE; 849 } 850 851 BOOL SaveWindowState(HWND hWnd, const char *pszName) 852 { 853 RECT rc; 854 GetWindowRect(hWnd, &rc); 855 if (hWnd != g_qeglobals.d_hwndMain) // && g_pParentWnd->CurrentStyle() == QR_QE4) 856 { 857 if (::GetParent(hWnd) != g_qeglobals.d_hwndMain) 858 { 859 ::SetParent(hWnd, g_qeglobals.d_hwndMain); 860 } 861 MapWindowPoints(NULL, g_qeglobals.d_hwndMain, (POINT *)&rc, 2); 862 863 } 864 BOOL b = SaveRegistryInfo(pszName, &rc, sizeof(rc)); 865 return b; 866 } 867 868 869 BOOL LoadWindowState(HWND hWnd, const char *pszName) 870 { 871 RECT rc; 872 LONG lSize = sizeof(rc); 873 874 if (LoadRegistryInfo(pszName, &rc, &lSize)) 875 { 876 if (rc.left < 0) 877 rc.left = 0; 878 if (rc.top < 0) 879 rc.top = 0; 880 if (rc.right < rc.left + 16) 881 rc.right = rc.left + 16; 882 if (rc.bottom < rc.top + 16) 883 rc.bottom = rc.top + 16; 884 885 MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, 886 rc.bottom - rc.top, FALSE); 887 return TRUE; 888 } 889 890 return FALSE; 891 } 892 893 /* 894 =============================================================== 895 896 STATUS WINDOW 897 898 =============================================================== 899 */ 900 901 void Sys_UpdateStatusBar( void ) 902 { 903 extern int g_numbrushes, g_numentities; 904 905 char numbrushbuffer[100]=""; 906 907 sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities ); 908 g_pParentWnd->SetStatusText(2, numbrushbuffer); 909 //Sys_Status( numbrushbuffer, 2 ); 910 } 911 912 void Sys_Status(const char *psz, int part ) 913 { 914 SendMessage(g_qeglobals.d_hwndStatus, SB_SETTEXT, part, (LPARAM)psz); 915 } 916 917 static HWND CreateMyStatusWindow(HINSTANCE hInst) 918 { 919 HWND hWnd; 920 int partsize[3] = { 300, 1100, -1 }; 921 922 hWnd = CreateWindowEx( WS_EX_TOPMOST, // no extended styles 923 STATUSCLASSNAME, // status bar 924 "", // no text 925 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles 926 -100, -100, 10, 10, // x, y, cx, cy 927 g_qeglobals.d_hwndMain, // parent window 928 (HMENU)100, // window ID 929 hInst, // instance 930 NULL); // window data 931 932 SendMessage( hWnd, SB_SETPARTS, 3, ( long ) partsize ); 933 934 return hWnd; 935 } 936 937 //============================================================== 938 939 #define NUMBUTTONS 15 940 HWND CreateToolBar(HINSTANCE hinst) 941 { 942 HWND hwndTB; 943 TBADDBITMAP tbab; 944 TBBUTTON tbb[NUMBUTTONS]; 945 946 // Ensure that the common control DLL is loaded. 947 948 InitCommonControls(); 949 950 // Create a toolbar that the user can customize and that has a 951 // tooltip associated with it. 952 953 hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR) NULL, 954 WS_CHILD | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | WS_BORDER, 955 0, 0, 0, 0, g_qeglobals.d_hwndMain, (HMENU) IDR_TOOLBAR1, hinst, NULL); 956 957 // Send the TB_BUTTONSTRUCTSIZE message, which is required for 958 // backward compatibility. 959 960 SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0); 961 962 // Add the bitmap containing button images to the toolbar. 963 964 tbab.hInst = hinst; 965 tbab.nID = IDR_TOOLBAR1; 966 SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM)NUMBUTTONS, (WPARAM) &tbab); 967 968 // Fill the TBBUTTON array with button information, and add the 969 // buttons to the toolbar. 970 971 tbb[0].iBitmap = 0; 972 tbb[0].idCommand = ID_BRUSH_FLIPX; 973 tbb[0].fsState = TBSTATE_ENABLED; 974 tbb[0].fsStyle = TBSTYLE_BUTTON; 975 tbb[0].dwData = 0; 976 tbb[0].iString = 0; 977 978 tbb[1].iBitmap = 2; 979 tbb[1].idCommand = ID_BRUSH_FLIPY; 980 tbb[1].fsState = TBSTATE_ENABLED; 981 tbb[1].fsStyle = TBSTYLE_BUTTON; 982 tbb[1].dwData = 0; 983 tbb[1].iString = 0; 984 985 tbb[2].iBitmap = 4; 986 tbb[2].idCommand = ID_BRUSH_FLIPZ; 987 tbb[2].fsState = TBSTATE_ENABLED; 988 tbb[2].fsStyle = TBSTYLE_BUTTON; 989 tbb[2].dwData = 0; 990 tbb[2].iString = 0; 991 992 tbb[3].iBitmap = 1; 993 tbb[3].idCommand = ID_BRUSH_ROTATEX; 994 tbb[3].fsState = TBSTATE_ENABLED; 995 tbb[3].fsStyle = TBSTYLE_BUTTON; 996 tbb[3].dwData = 0; 997 tbb[3].iString = 0; 998 999 tbb[4].iBitmap = 3; 1000 tbb[4].idCommand = ID_BRUSH_ROTATEY; 1001 tbb[4].fsState = TBSTATE_ENABLED; 1002 tbb[4].fsStyle = TBSTYLE_BUTTON; 1003 tbb[4].dwData = 0; 1004 tbb[4].iString = 0; 1005 1006 tbb[5].iBitmap = 5; 1007 tbb[5].idCommand = ID_BRUSH_ROTATEZ; 1008 tbb[5].fsState = TBSTATE_ENABLED; 1009 tbb[5].fsStyle = TBSTYLE_BUTTON; 1010 tbb[5].dwData = 0; 1011 tbb[5].iString = 0; 1012 1013 tbb[6].iBitmap = 6; 1014 tbb[6].idCommand = ID_SELECTION_SELECTCOMPLETETALL; 1015 tbb[6].fsState = TBSTATE_ENABLED; 1016 tbb[6].fsStyle = TBSTYLE_BUTTON; 1017 tbb[6].dwData = 0; 1018 tbb[6].iString = 0; 1019 1020 tbb[7].iBitmap = 7; 1021 tbb[7].idCommand = ID_SELECTION_SELECTTOUCHING; 1022 tbb[7].fsState = TBSTATE_ENABLED; 1023 tbb[7].fsStyle = TBSTYLE_BUTTON; 1024 tbb[7].dwData = 0; 1025 tbb[7].iString = 0; 1026 1027 tbb[8].iBitmap = 8; 1028 tbb[8].idCommand = ID_SELECTION_SELECTPARTIALTALL; 1029 tbb[8].fsState = TBSTATE_ENABLED; 1030 tbb[8].fsStyle = TBSTYLE_BUTTON; 1031 tbb[8].dwData = 0; 1032 tbb[8].iString = 0; 1033 1034 1035 tbb[9].iBitmap = 9; 1036 tbb[9].idCommand = ID_SELECTION_SELECTINSIDE; 1037 tbb[9].fsState = TBSTATE_ENABLED; 1038 tbb[9].fsStyle = TBSTYLE_BUTTON; 1039 tbb[9].dwData = 0; 1040 tbb[9].iString = 0; 1041 1042 tbb[10].iBitmap = 10; 1043 tbb[10].idCommand = ID_SELECTION_CSGSUBTRACT; 1044 tbb[10].fsState = TBSTATE_ENABLED; 1045 tbb[10].fsStyle = TBSTYLE_BUTTON; 1046 tbb[10].dwData = 0; 1047 tbb[10].iString = 0; 1048 1049 1050 tbb[11].iBitmap = 11; 1051 tbb[11].idCommand = ID_SELECTION_MAKEHOLLOW; 1052 tbb[11].fsState = TBSTATE_ENABLED; 1053 tbb[11].fsStyle = TBSTYLE_BUTTON; 1054 tbb[11].dwData = 0; 1055 tbb[11].iString = 0; 1056 1057 tbb[12].iBitmap = 12; 1058 tbb[12].idCommand = ID_TEXTURES_WIREFRAME; 1059 tbb[12].fsState = TBSTATE_ENABLED; 1060 tbb[12].fsStyle = TBSTYLE_BUTTON; 1061 tbb[12].dwData = 0; 1062 tbb[12].iString = 0; 1063 1064 tbb[13].iBitmap = 13; 1065 tbb[13].idCommand = ID_TEXTURES_FLATSHADE; 1066 tbb[13].fsState = TBSTATE_ENABLED; 1067 tbb[13].fsStyle = TBSTYLE_BUTTON; 1068 tbb[13].dwData = 0; 1069 tbb[13].iString = 0; 1070 1071 tbb[14].iBitmap = 14; 1072 tbb[14].idCommand = ID_VIEW_TRILINEAR; 1073 tbb[14].fsState = TBSTATE_ENABLED; 1074 tbb[14].fsStyle = TBSTYLE_BUTTON; 1075 tbb[14].dwData = 0; 1076 tbb[14].iString = 0; 1077 1078 SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)NUMBUTTONS, 1079 (LPARAM) (LPTBBUTTON) &tbb); 1080 1081 ShowWindow(hwndTB, SW_SHOW); 1082 1083 return hwndTB; 1084 } 1085