]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/qe3.cpp
Remove <gtk/gtk.h> from radiant/dialog.h
[xonotic/netradiant.git] / radiant / qe3.cpp
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    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 GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 /*
23    The following source code is licensed by Id Software and subject to the terms of
24    its LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with
25    GtkRadiant. If you did not receive a LIMITED USE SOFTWARE LICENSE AGREEMENT,
26    please contact Id Software immediately at info@idsoftware.com.
27  */
28
29 //
30 // Linux stuff
31 //
32 // Leonardo Zide (leo@lokigames.com)
33 //
34
35 #include "qe3.h"
36
37 #include <gtk/gtk.h>
38
39 #include "debugging/debugging.h"
40
41 #include "ifilesystem.h"
42 //#include "imap.h"
43
44 #include <map>
45
46 #include <uilib/uilib.h>
47
48 #include "stream/textfilestream.h"
49 #include "cmdlib.h"
50 #include "stream/stringstream.h"
51 #include "os/path.h"
52 #include "scenelib.h"
53
54 #include "gtkutil/messagebox.h"
55 #include "error.h"
56 #include "map.h"
57 #include "build.h"
58 #include "points.h"
59 #include "camwindow.h"
60 #include "mainframe.h"
61 #include "preferences.h"
62 #include "watchbsp.h"
63 #include "autosave.h"
64 #include "convert.h"
65
66 QEGlobals_t g_qeglobals;
67
68
69 #if defined( WIN32 )
70 #define PATH_MAX 260
71 #endif
72
73
74 void QE_InitVFS(){
75         // VFS initialization -----------------------
76         // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files)
77         // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order
78         // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too
79
80         const char* gamename = gamename_get();
81         const char* basegame = basegame_get();
82         const char* userRoot = g_qeglobals.m_userEnginePath.c_str();
83         const char* globalRoot = EnginePath_get();
84
85         // if we have a mod dir
86         if ( !string_equal( gamename, basegame ) ) {
87                 // ~/.<gameprefix>/<fs_game>
88                 if ( userRoot ) {
89                         StringOutputStream userGamePath( 256 );
90                         userGamePath << userRoot << gamename << '/';
91                         GlobalFileSystem().initDirectory( userGamePath.c_str() );
92                 }
93
94                 // <fs_basepath>/<fs_game>
95                 {
96                         StringOutputStream globalGamePath( 256 );
97                         globalGamePath << globalRoot << gamename << '/';
98                         GlobalFileSystem().initDirectory( globalGamePath.c_str() );
99                 }
100         }
101
102         // ~/.<gameprefix>/<fs_main>
103         if ( userRoot ) {
104                 StringOutputStream userBasePath( 256 );
105                 userBasePath << userRoot << basegame << '/';
106                 GlobalFileSystem().initDirectory( userBasePath.c_str() );
107         }
108
109         // <fs_basepath>/<fs_main>
110         {
111                 StringOutputStream globalBasePath( 256 );
112                 globalBasePath << globalRoot << basegame << '/';
113                 GlobalFileSystem().initDirectory( globalBasePath.c_str() );
114         }
115 }
116
117 int g_numbrushes = 0;
118 int g_numentities = 0;
119
120 void QE_UpdateStatusBar(){
121         char buffer[128];
122         sprintf( buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities );
123         g_pParentWnd->SetStatusText( g_pParentWnd->m_brushcount_status, buffer );
124 }
125
126 SimpleCounter g_brushCount;
127
128 void QE_brushCountChanged(){
129         g_numbrushes = int(g_brushCount.get() );
130         QE_UpdateStatusBar();
131 }
132
133 SimpleCounter g_entityCount;
134
135 void QE_entityCountChanged(){
136         g_numentities = int(g_entityCount.get() );
137         QE_UpdateStatusBar();
138 }
139
140 bool ConfirmModified( const char* title ){
141         if ( !Map_Modified( g_map ) ) {
142                 return true;
143         }
144
145         auto result = MainFrame_getWindow().alert( "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?", title, ui::alert_type::YESNOCANCEL, ui::alert_icon::Question );
146         if ( result == ui::alert_response::CANCEL ) {
147                 return false;
148         }
149         if ( result == ui::alert_response::YES ) {
150                 if ( Map_Unnamed( g_map ) ) {
151                         return Map_SaveAs();
152                 }
153                 else
154                 {
155                         return Map_Save();
156                 }
157         }
158         return true;
159 }
160
161 void bsp_init(){
162         build_set_variable( "RadiantPath", AppPath_get() );
163         build_set_variable( "ExecutableType", RADIANT_EXECUTABLE );
164         build_set_variable( "EnginePath", EnginePath_get() );
165         build_set_variable( "UserEnginePath", g_qeglobals.m_userEnginePath.c_str() );
166         build_set_variable( "MonitorAddress", ( g_WatchBSP_Enabled ) ? "127.0.0.1:39000" : "" );
167         build_set_variable( "GameName", gamename_get() );
168
169         const char* mapname = Map_Name( g_map );
170         StringOutputStream name( 256 );
171         name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".bsp";
172
173         build_set_variable( "MapFile", mapname );
174         build_set_variable( "BspFile", name.c_str() );
175 }
176
177 void bsp_shutdown(){
178         build_clear_variables();
179 }
180
181 class ArrayCommandListener : public CommandListener
182 {
183 GPtrArray* m_array;
184 public:
185 ArrayCommandListener(){
186         m_array = g_ptr_array_new();
187 }
188 ~ArrayCommandListener(){
189         g_ptr_array_free( m_array, TRUE );
190 }
191
192 void execute( const char* command ){
193         g_ptr_array_add( m_array, g_strdup( command ) );
194 }
195
196 GPtrArray* array() const {
197         return m_array;
198 }
199 };
200
201 class BatchCommandListener : public CommandListener
202 {
203 TextOutputStream& m_file;
204 std::size_t m_commandCount;
205 const char* m_outputRedirect;
206 public:
207 BatchCommandListener( TextOutputStream& file, const char* outputRedirect ) : m_file( file ), m_commandCount( 0 ), m_outputRedirect( outputRedirect ){
208 }
209
210 void execute( const char* command ){
211         m_file << command;
212         if ( m_commandCount == 0 ) {
213                 m_file << " > ";
214         }
215         else
216         {
217                 m_file << " >> ";
218         }
219         m_file << "\"" << m_outputRedirect << "\"";
220         m_file << "\n";
221         ++m_commandCount;
222 }
223 };
224
225 bool Region_cameraValid(){
226         Vector3 vOrig( vector3_snapped( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ) );
227
228         for ( int i = 0 ; i < 3 ; i++ )
229         {
230                 if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) {
231                         return false;
232                 }
233         }
234         return true;
235 }
236
237
238 void RunBSP( const char* name ){
239         // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
240         // make sure we don't attempt to region compile a map with the camera outside the region
241         if ( region_active && !Region_cameraValid() ) {
242                 globalErrorStream() << "The camera must be in the region to start a region compile.\n";
243                 return;
244         }
245
246         SaveMap();
247
248         if ( Map_Unnamed( g_map ) ) {
249                 globalOutputStream() << "build cancelled\n";
250                 return;
251         }
252
253         if ( g_SnapShots_Enabled && !Map_Unnamed( g_map ) && Map_Modified( g_map ) ) {
254                 Map_Snapshot();
255         }
256
257         if ( region_active ) {
258                 const char* mapname = Map_Name( g_map );
259                 StringOutputStream name( 256 );
260                 name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg";
261                 Map_SaveRegion( name.c_str() );
262         }
263
264         Pointfile_Delete();
265
266         bsp_init();
267
268         if ( g_WatchBSP_Enabled ) {
269                 ArrayCommandListener listener;
270                 build_run( name, listener );
271                 // grab the file name for engine running
272                 const char* fullname = Map_Name( g_map );
273                 StringOutputStream bspname( 64 );
274                 bspname << StringRange( path_get_filename_start( fullname ), path_get_filename_base_end( fullname ) );
275                 BuildMonitor_Run( listener.array(), bspname.c_str() );
276         }
277         else
278         {
279                 char junkpath[PATH_MAX];
280                 strcpy( junkpath, SettingsPath_get() );
281                 strcat( junkpath, "junk.txt" );
282
283                 char batpath[PATH_MAX];
284 #if defined( POSIX )
285                 strcpy( batpath, SettingsPath_get() );
286                 strcat( batpath, "qe3bsp.sh" );
287 #elif defined( WIN32 )
288                 strcpy( batpath, SettingsPath_get() );
289                 strcat( batpath, "qe3bsp.bat" );
290 #else
291 #error "unsupported platform"
292 #endif
293                 bool written = false;
294                 {
295                         TextFileOutputStream batchFile( batpath );
296                         if ( !batchFile.failed() ) {
297 #if defined ( POSIX )
298                                 batchFile << "#!/bin/sh \n\n";
299 #endif
300                                 BatchCommandListener listener( batchFile, junkpath );
301                                 build_run( name, listener );
302                                 written = true;
303                         }
304                 }
305                 if ( written ) {
306 #if defined ( POSIX )
307                         chmod( batpath, 0744 );
308 #endif
309                         globalOutputStream() << "Writing the compile script to '" << batpath << "'\n";
310                         globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n";
311                         Q_Exec( batpath, NULL, NULL, true, false );
312                 }
313         }
314
315         bsp_shutdown();
316 }
317
318 // =============================================================================
319 // Sys_ functions
320
321 void Sys_SetTitle( const char *text, bool modified ){
322         StringOutputStream title;
323         title << text;
324
325         if ( modified ) {
326                 title << " *";
327         }
328
329         gtk_window_set_title(MainFrame_getWindow(), title.c_str() );
330 }
331
332 bool g_bWaitCursor = false;
333
334 void Sys_BeginWait( void ){
335         ScreenUpdates_Disable( "Processing...", "Please Wait" );
336         GdkCursor *cursor = gdk_cursor_new( GDK_WATCH );
337         gdk_window_set_cursor( gtk_widget_get_window(MainFrame_getWindow()), cursor );
338         gdk_cursor_unref( cursor );
339         g_bWaitCursor = true;
340 }
341
342 void Sys_EndWait( void ){
343         ScreenUpdates_Enable();
344         gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), 0 );
345         g_bWaitCursor = false;
346 }
347
348 void Sys_Beep( void ){
349         gdk_beep();
350 }