2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
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.
32 // Leonardo Zide (leo@lokigames.com)
37 #include "debugging/debugging.h"
39 #include "ifilesystem.h"
44 #include <gtk/gtktearoffmenuitem.h>
46 #include "stream/textfilestream.h"
48 #include "stream/stringstream.h"
52 #include "gtkutil/messagebox.h"
57 #include "camwindow.h"
58 #include "mainframe.h"
59 #include "preferences.h"
64 QEGlobals_t g_qeglobals;
74 // VFS initialization -----------------------
75 // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files)
76 // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order
77 // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too
79 const char* gamename = gamename_get();
80 const char* basegame = basegame_get();
81 const char* userRoot = g_qeglobals.m_userEnginePath.c_str();
82 const char* globalRoot = EnginePath_get();
84 // if we have a mod dir
85 if(!string_equal(gamename, basegame))
87 // ~/.<gameprefix>/<fs_game>
90 StringOutputStream userGamePath(256);
91 userGamePath << userRoot << gamename << '/';
92 GlobalFileSystem().initDirectory(userGamePath.c_str());
95 // <fs_basepath>/<fs_game>
97 StringOutputStream globalGamePath(256);
98 globalGamePath << globalRoot << gamename << '/';
99 GlobalFileSystem().initDirectory(globalGamePath.c_str());
103 // ~/.<gameprefix>/<fs_main>
106 StringOutputStream userBasePath(256);
107 userBasePath << userRoot << basegame << '/';
108 GlobalFileSystem().initDirectory(userBasePath.c_str());
111 // <fs_basepath>/<fs_main>
113 StringOutputStream globalBasePath(256);
114 globalBasePath << globalRoot << basegame << '/';
115 GlobalFileSystem().initDirectory(globalBasePath.c_str());
119 int g_numbrushes = 0;
120 int g_numentities = 0;
122 void QE_UpdateStatusBar()
125 sprintf(buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities);
126 g_pParentWnd->SetStatusText(g_pParentWnd->m_brushcount_status, buffer);
129 SimpleCounter g_brushCount;
131 void QE_brushCountChanged()
133 g_numbrushes = int(g_brushCount.get());
134 QE_UpdateStatusBar();
137 SimpleCounter g_entityCount;
139 void QE_entityCountChanged()
141 g_numentities = int(g_entityCount.get());
142 QE_UpdateStatusBar();
145 bool ConfirmModified(const char* title)
147 if (!Map_Modified(g_map))
150 EMessageBoxReturn result = gtk_MessageBox(GTK_WIDGET(MainFrame_getWindow()), "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?", title, eMB_YESNOCANCEL, eMB_ICONQUESTION);
151 if(result == eIDCANCEL)
157 if(Map_Unnamed(g_map))
171 build_set_variable("RadiantPath", AppPath_get());
172 build_set_variable("ExecutableType", RADIANT_EXECUTABLE);
173 build_set_variable("EnginePath", EnginePath_get());
174 build_set_variable("MonitorAddress", (g_WatchBSP_Enabled) ? "127.0.0.1:39000" : "");
175 build_set_variable("GameName", gamename_get());
177 const char* mapname = Map_Name(g_map);
178 StringOutputStream name(256);
179 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".bsp";
181 build_set_variable("MapFile", mapname);
182 build_set_variable("BspFile", name.c_str());
187 build_clear_variables();
190 class ArrayCommandListener : public CommandListener
194 ArrayCommandListener()
196 m_array = g_ptr_array_new();
198 ~ArrayCommandListener()
200 g_ptr_array_free(m_array, TRUE);
203 void execute(const char* command)
205 g_ptr_array_add(m_array, g_strdup(command));
208 GPtrArray* array() const
214 class BatchCommandListener : public CommandListener
216 TextOutputStream& m_file;
217 std::size_t m_commandCount;
218 const char* m_outputRedirect;
220 BatchCommandListener(TextOutputStream& file, const char* outputRedirect) : m_file(file), m_commandCount(0), m_outputRedirect(outputRedirect)
224 void execute(const char* command)
227 if (m_commandCount == 0)
235 m_file << "\"" << m_outputRedirect << "\"";
241 bool Region_cameraValid()
243 Vector3 vOrig(vector3_snapped(Camera_getOrigin(*g_pParentWnd->GetCamWnd())));
245 for (int i=0 ; i<3 ; i++)
247 if (vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i])
256 void RunBSP(const char* name)
258 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
259 // make sure we don't attempt to region compile a map with the camera outside the region
260 if (region_active && !Region_cameraValid())
262 globalErrorStream() << "The camera must be in the region to start a region compile.\n";
268 if(Map_Unnamed(g_map))
270 globalOutputStream() << "build cancelled\n";
274 if (g_SnapShots_Enabled && !Map_Unnamed(g_map) && Map_Modified(g_map))
281 const char* mapname = Map_Name(g_map);
282 StringOutputStream name(256);
283 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".reg";
284 Map_SaveRegion(name.c_str());
291 if (g_WatchBSP_Enabled)
293 ArrayCommandListener listener;
294 build_run(name, listener);
295 // grab the file name for engine running
296 const char* fullname = Map_Name(g_map);
297 StringOutputStream bspname(64);
298 bspname << StringRange(path_get_filename_start(fullname), path_get_filename_base_end(fullname));
299 BuildMonitor_Run( listener.array(), bspname.c_str() );
303 char junkpath[PATH_MAX];
304 strcpy(junkpath, SettingsPath_get());
305 strcat(junkpath, "junk.txt");
307 char batpath[PATH_MAX];
309 strcpy(batpath, SettingsPath_get());
310 strcat(batpath, "qe3bsp.sh");
312 strcpy(batpath, SettingsPath_get());
313 strcat(batpath, "qe3bsp.bat");
315 #error "unsupported platform"
317 bool written = false;
319 TextFileOutputStream batchFile(batpath);
320 if(!batchFile.failed())
323 batchFile << "#!/bin/sh \n\n";
325 BatchCommandListener listener(batchFile, junkpath);
326 build_run(name, listener);
333 chmod (batpath, 0744);
335 globalOutputStream() << "Writing the compile script to '" << batpath << "'\n";
336 globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n";
337 Q_Exec(batpath, NULL, NULL, true, false);
344 // =============================================================================
347 void Sys_SetTitle(const char *text, bool modified)
349 StringOutputStream title;
357 gtk_window_set_title(MainFrame_getWindow(), title.c_str());
360 bool g_bWaitCursor = false;
362 void Sys_BeginWait (void)
364 ScreenUpdates_Disable("Processing...", "Please Wait");
365 GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
366 gdk_window_set_cursor(GTK_WIDGET(MainFrame_getWindow())->window, cursor);
367 gdk_cursor_unref (cursor);
368 g_bWaitCursor = true;
371 void Sys_EndWait (void)
373 ScreenUpdates_Enable();
374 gdk_window_set_cursor(GTK_WIDGET(MainFrame_getWindow())->window, 0);
375 g_bWaitCursor = false;