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