Radiant.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "qe3.h"
  23. #include "radiant.h"
  24. #include "MainFrm.h"
  25. #include "lightdlg.h"
  26. #include <process.h> // for _beginthreadex and _endthreadex
  27. #include <ddeml.h> // for MSGF_DDEMGR
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. idCVar radiant_entityMode( "radiant_entityMode", "0", CVAR_TOOL | CVAR_ARCHIVE, "" );
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CRadiantApp
  36. BEGIN_MESSAGE_MAP(CRadiantApp, CWinApp)
  37. //{{AFX_MSG_MAP(CRadiantApp)
  38. ON_COMMAND(ID_HELP, OnHelp)
  39. //}}AFX_MSG_MAP
  40. // Standard file based document commands
  41. ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
  42. ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
  43. // Standard print setup command
  44. ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
  45. END_MESSAGE_MAP()
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CRadiantApp construction
  48. CRadiantApp::CRadiantApp()
  49. {
  50. // TODO: add construction code here,
  51. // Place all significant initialization in InitInstance
  52. }
  53. /////////////////////////////////////////////////////////////////////////////
  54. // The one and only CRadiantApp object
  55. CRadiantApp theApp;
  56. HINSTANCE g_DoomInstance = NULL;
  57. bool g_editorAlive = false;
  58. void RadiantPrint( const char *text ) {
  59. if ( g_editorAlive && g_Inspectors ) {
  60. if (g_Inspectors->consoleWnd.GetSafeHwnd()) {
  61. g_Inspectors->consoleWnd.AddText( text );
  62. }
  63. }
  64. }
  65. void RadiantShutdown( void ) {
  66. theApp.ExitInstance();
  67. }
  68. /*
  69. =================
  70. RadiantInit
  71. This is also called when you 'quit' in doom
  72. =================
  73. */
  74. void RadiantInit( void ) {
  75. // make sure the renderer is initialized
  76. if ( !renderSystem->IsOpenGLRunning() ) {
  77. common->Printf( "no OpenGL running\n" );
  78. return;
  79. }
  80. g_editorAlive = true;
  81. // allocate a renderWorld and a soundWorld
  82. if ( g_qeglobals.rw == NULL ) {
  83. g_qeglobals.rw = renderSystem->AllocRenderWorld();
  84. g_qeglobals.rw->InitFromMap( NULL );
  85. }
  86. if ( g_qeglobals.sw == NULL ) {
  87. g_qeglobals.sw = soundSystem->AllocSoundWorld( g_qeglobals.rw );
  88. }
  89. if ( g_DoomInstance ) {
  90. if ( ::IsWindowVisible( win32.hWnd ) ) {
  91. ::ShowWindow( win32.hWnd, SW_HIDE );
  92. g_pParentWnd->ShowWindow( SW_SHOW );
  93. g_pParentWnd->SetFocus();
  94. }
  95. } else {
  96. Sys_GrabMouseCursor( false );
  97. g_DoomInstance = win32.hInstance;
  98. CWinApp* pApp = AfxGetApp();
  99. CWinThread *pThread = AfxGetThread();
  100. InitAfx();
  101. // App global initializations (rare)
  102. pApp->InitApplication();
  103. // Perform specific initializations
  104. pThread->InitInstance();
  105. qglFinish();
  106. //qwglMakeCurrent(0, 0);
  107. qwglMakeCurrent(win32.hDC, win32.hGLRC);
  108. // hide the doom window by default
  109. ::ShowWindow( win32.hWnd, SW_HIDE );
  110. }
  111. }
  112. extern void Map_VerifyCurrentMap(const char *map);
  113. void RadiantSync( const char *mapName, const idVec3 &viewOrg, const idAngles &viewAngles ) {
  114. if ( g_DoomInstance == NULL ) {
  115. RadiantInit();
  116. }
  117. if ( g_DoomInstance ) {
  118. idStr osPath;
  119. osPath = fileSystem->RelativePathToOSPath( mapName );
  120. Map_VerifyCurrentMap( osPath );
  121. idAngles flip = viewAngles;
  122. flip.pitch = -flip.pitch;
  123. g_pParentWnd->GetCamera()->SetView( viewOrg, flip );
  124. g_pParentWnd->SetFocus();
  125. Sys_UpdateWindows( W_ALL );
  126. g_pParentWnd->RoutineProcessing();
  127. }
  128. }
  129. void RadiantRun( void ) {
  130. static bool exceptionErr = false;
  131. int show = ::IsWindowVisible(win32.hWnd);
  132. try {
  133. if (!exceptionErr && !show) {
  134. //qglPushAttrib(GL_ALL_ATTRIB_BITS);
  135. qglDepthMask(true);
  136. theApp.Run();
  137. //qglPopAttrib();
  138. //qwglMakeCurrent(0, 0);
  139. qwglMakeCurrent(win32.hDC, win32.hGLRC);
  140. }
  141. }
  142. catch( idException &ex ) {
  143. ::MessageBox(NULL, ex.error, "Exception error", MB_OK);
  144. RadiantShutdown();
  145. }
  146. }
  147. /////////////////////////////////////////////////////////////////////////////
  148. // CRadiantApp initialization
  149. HINSTANCE g_hOpenGL32 = NULL;
  150. HINSTANCE g_hOpenGL = NULL;
  151. bool g_bBuildList = false;
  152. BOOL CRadiantApp::InitInstance()
  153. {
  154. //g_hOpenGL32 = ::LoadLibrary("opengl32.dll");
  155. // AfxEnableControlContainer();
  156. // Standard initialization
  157. // If you are not using these features and wish to reduce the size
  158. // of your final executable, you should remove from the following
  159. // the specific initialization routines you do not need.
  160. //AfxEnableMemoryTracking(FALSE);
  161. #ifdef _AFXDLL
  162. //Enable3dControls(); // Call this when using MFC in a shared DLL
  163. #else
  164. //Enable3dControlsStatic(); // Call this when linking to MFC statically
  165. #endif
  166. // If there's a .INI file in the directory use it instead of registry
  167. char RadiantPath[_MAX_PATH];
  168. GetModuleFileName( NULL, RadiantPath, _MAX_PATH );
  169. // search for exe
  170. CFileFind Finder;
  171. Finder.FindFile( RadiantPath );
  172. Finder.FindNextFile();
  173. // extract root
  174. CString Root = Finder.GetRoot();
  175. // build root\*.ini
  176. CString IniPath = Root + "\\REGISTRY.INI";
  177. // search for ini file
  178. Finder.FindNextFile();
  179. if (Finder.FindFile( IniPath ))
  180. {
  181. Finder.FindNextFile();
  182. // use the .ini file instead of the registry
  183. free((void*)m_pszProfileName);
  184. m_pszProfileName=_tcsdup(_T(Finder.GetFilePath()));
  185. // look for the registry key for void* buffers storage ( these can't go into .INI files )
  186. int i=0;
  187. CString key;
  188. HKEY hkResult;
  189. DWORD dwDisp;
  190. DWORD type;
  191. char iBuf[3];
  192. do
  193. {
  194. sprintf( iBuf, "%d", i );
  195. key = "Software\\Q3Radiant\\IniPrefs" + CString(iBuf);
  196. // does this key exists ?
  197. if ( RegOpenKeyEx( HKEY_CURRENT_USER, key, 0, KEY_ALL_ACCESS, &hkResult ) != ERROR_SUCCESS )
  198. {
  199. // this key doesn't exist, so it's the one we'll use
  200. strcpy( g_qeglobals.use_ini_registry, key.GetBuffer(0) );
  201. RegCreateKeyEx( HKEY_CURRENT_USER, key, 0, NULL,
  202. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkResult, &dwDisp );
  203. RegSetValueEx( hkResult, "RadiantName", 0, REG_SZ, reinterpret_cast<CONST BYTE *>(RadiantPath), strlen( RadiantPath )+1 );
  204. RegCloseKey( hkResult );
  205. break;
  206. }
  207. else
  208. {
  209. char RadiantAux[ _MAX_PATH ];
  210. unsigned long size = _MAX_PATH;
  211. // the key exists, is it the one we are looking for ?
  212. RegQueryValueEx( hkResult, "RadiantName", 0, &type, reinterpret_cast<BYTE *>(RadiantAux), &size );
  213. RegCloseKey( hkResult );
  214. if ( !strcmp( RadiantAux, RadiantPath ) )
  215. {
  216. // got it !
  217. strcpy( g_qeglobals.use_ini_registry, key.GetBuffer(0) );
  218. break;
  219. }
  220. }
  221. i++;
  222. } while (1);
  223. g_qeglobals.use_ini = true;
  224. }
  225. else
  226. {
  227. // Change the registry key under which our settings are stored.
  228. SetRegistryKey( EDITOR_REGISTRY_KEY );
  229. g_qeglobals.use_ini = false;
  230. }
  231. LoadStdProfileSettings(); // Load standard INI file options (including MRU)
  232. // Register the application's document templates. Document templates
  233. // serve as the connection between documents, frame windows and views.
  234. // CMultiDocTemplate* pDocTemplate;
  235. // pDocTemplate = new CMultiDocTemplate(
  236. // IDR_RADIANTYPE,
  237. // RUNTIME_CLASS(CRadiantDoc),
  238. // RUNTIME_CLASS(CMainFrame), // custom MDI child frame
  239. // RUNTIME_CLASS(CRadiantView));
  240. // AddDocTemplate(pDocTemplate);
  241. // create main MDI Frame window
  242. g_PrefsDlg.LoadPrefs();
  243. qglEnableClientState( GL_VERTEX_ARRAY );
  244. CString strTemp = m_lpCmdLine;
  245. strTemp.MakeLower();
  246. if (strTemp.Find("builddefs") >= 0) {
  247. g_bBuildList = true;
  248. }
  249. CMainFrame* pMainFrame = new CMainFrame;
  250. if (!pMainFrame->LoadFrame(IDR_MENU_QUAKE3)) {
  251. return FALSE;
  252. }
  253. if (pMainFrame->m_hAccelTable) {
  254. ::DestroyAcceleratorTable(pMainFrame->m_hAccelTable);
  255. }
  256. pMainFrame->LoadAccelTable(MAKEINTRESOURCE(IDR_MINIACCEL));
  257. m_pMainWnd = pMainFrame;
  258. // The main window has been initialized, so show and update it.
  259. pMainFrame->ShowWindow(m_nCmdShow);
  260. pMainFrame->UpdateWindow();
  261. return TRUE;
  262. }
  263. /////////////////////////////////////////////////////////////////////////////
  264. // CRadiantApp commands
  265. int CRadiantApp::ExitInstance()
  266. {
  267. common->Shutdown();
  268. g_pParentWnd = NULL;
  269. int ret = CWinApp::ExitInstance();
  270. ExitProcess(0);
  271. return ret;
  272. }
  273. BOOL CRadiantApp::OnIdle(LONG lCount) {
  274. if (g_pParentWnd) {
  275. g_pParentWnd->RoutineProcessing();
  276. }
  277. return FALSE;
  278. //return CWinApp::OnIdle(lCount);
  279. }
  280. void CRadiantApp::OnHelp()
  281. {
  282. ShellExecute(m_pMainWnd->GetSafeHwnd(), "open", "http://www.idDevNet.com", NULL, NULL, SW_SHOW);
  283. }
  284. int CRadiantApp::Run( void )
  285. {
  286. BOOL bIdle = TRUE;
  287. LONG lIdleCount = 0;
  288. #if _MSC_VER >= 1300
  289. MSG *msg = AfxGetCurrentMessage(); // TODO Robert fix me!!
  290. #else
  291. MSG *msg = &m_msgCur;
  292. #endif
  293. // phase1: check to see if we can do idle work
  294. while (bIdle && !::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE)) {
  295. // call OnIdle while in bIdle state
  296. if (!OnIdle(lIdleCount++)) {
  297. bIdle = FALSE; // assume "no idle" state
  298. }
  299. }
  300. // phase2: pump messages while available
  301. do {
  302. // pump message, but quit on WM_QUIT
  303. if (!PumpMessage()) {
  304. return ExitInstance();
  305. }
  306. // reset "no idle" state after pumping "normal" message
  307. if (IsIdleMessage(msg)) {
  308. bIdle = TRUE;
  309. lIdleCount = 0;
  310. }
  311. } while (::PeekMessage(msg, NULL, NULL, NULL, PM_NOREMOVE));
  312. return 0;
  313. }
  314. /*
  315. =============================================================
  316. REGISTRY INFO
  317. =============================================================
  318. */
  319. bool SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize)
  320. {
  321. SetCvarBinary(pszName, pvBuf, lSize);
  322. common->WriteFlaggedCVarsToFile( "editor.cfg", CVAR_TOOL, "sett" );
  323. return true;
  324. }
  325. bool LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize)
  326. {
  327. return GetCvarBinary(pszName, pvBuf, *plSize);
  328. }
  329. bool SaveWindowState(HWND hWnd, const char *pszName)
  330. {
  331. RECT rc;
  332. GetWindowRect(hWnd, &rc);
  333. if (hWnd != g_pParentWnd->GetSafeHwnd()) {
  334. if (::GetParent(hWnd) != g_pParentWnd->GetSafeHwnd()) {
  335. ::SetParent(hWnd, g_pParentWnd->GetSafeHwnd());
  336. }
  337. MapWindowPoints(NULL, g_pParentWnd->GetSafeHwnd(), (POINT *)&rc, 2);
  338. }
  339. return SaveRegistryInfo(pszName, &rc, sizeof(rc));
  340. }
  341. bool LoadWindowState(HWND hWnd, const char *pszName)
  342. {
  343. RECT rc;
  344. LONG lSize = sizeof(rc);
  345. if (LoadRegistryInfo(pszName, &rc, &lSize))
  346. {
  347. if (rc.left < 0)
  348. rc.left = 0;
  349. if (rc.top < 0)
  350. rc.top = 0;
  351. if (rc.right < rc.left + 16)
  352. rc.right = rc.left + 16;
  353. if (rc.bottom < rc.top + 16)
  354. rc.bottom = rc.top + 16;
  355. MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
  356. return true;
  357. }
  358. return false;
  359. }
  360. /*
  361. ===============================================================
  362. STATUS WINDOW
  363. ===============================================================
  364. */
  365. void Sys_UpdateStatusBar( void )
  366. {
  367. extern int g_numbrushes, g_numentities;
  368. char numbrushbuffer[100] = "";
  369. sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities );
  370. Sys_Status( numbrushbuffer, 2 );
  371. }
  372. void Sys_Status(const char *psz, int part )
  373. {
  374. if ( part < 0 ) {
  375. common->Printf("%s", psz);
  376. part = 0;
  377. }
  378. g_pParentWnd->SetStatusText(part, psz);
  379. }