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 "globaldefs.h"
41 #include "debugging/debugging.h"
43 #include "ifilesystem.h"
48 #include <uilib/uilib.h>
50 #include "stream/textfilestream.h"
52 #include "stream/stringstream.h"
56 #include "gtkutil/messagebox.h"
61 #include "camwindow.h"
62 #include "mainframe.h"
63 #include "preferences.h"
68 QEGlobals_t g_qeglobals;
78 // VFS initialization -----------------------
79 // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files)
80 // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order
81 // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too
83 const char *gamename = gamename_get();
84 const char *basegame = basegame_get();
85 const char *userRoot = g_qeglobals.m_userEnginePath.c_str();
86 const char *globalRoot = EnginePath_get();
89 StringOutputStream editorGamePath(256);
90 editorGamePath << GlobalRadiant().getAppPath() << DEFAULT_EDITORVFS_DIRNAME;
91 GlobalFileSystem().initDirectory(editorGamePath.c_str());
93 // if we have a mod dir
94 if (!string_equal(gamename, basegame)) {
95 // ~/.<gameprefix>/<fs_game>
96 if (userRoot && !g_disableHomePath) {
97 StringOutputStream userGamePath(256);
98 userGamePath << userRoot << gamename << '/';
99 GlobalFileSystem().initDirectory(userGamePath.c_str());
102 // <fs_basepath>/<fs_game>
103 if (!g_disableEnginePath) {
104 StringOutputStream globalGamePath(256);
105 globalGamePath << globalRoot << gamename << '/';
106 GlobalFileSystem().initDirectory(globalGamePath.c_str());
110 // ~/.<gameprefix>/<fs_main>
111 if (userRoot && !g_disableHomePath) {
112 StringOutputStream userBasePath(256);
113 userBasePath << userRoot << basegame << '/';
114 GlobalFileSystem().initDirectory(userBasePath.c_str());
117 // <fs_basepath>/<fs_main>
118 if (!g_disableEnginePath) {
119 StringOutputStream globalBasePath(256);
120 globalBasePath << globalRoot << basegame << '/';
121 GlobalFileSystem().initDirectory(globalBasePath.c_str());
125 for (int i = 0; i < g_pakPathCount; i++) {
126 if (g_strcmp0(g_strPakPath[i].c_str(), "")) {
127 GlobalFileSystem().initDirectory(g_strPakPath[i].c_str());
132 int g_numbrushes = 0;
133 int g_numentities = 0;
135 void QE_UpdateStatusBar()
138 sprintf(buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities);
139 g_pParentWnd->SetStatusText(g_pParentWnd->m_brushcount_status, buffer);
142 SimpleCounter g_brushCount;
144 void QE_brushCountChanged()
146 g_numbrushes = int(g_brushCount.get());
147 QE_UpdateStatusBar();
150 SimpleCounter g_entityCount;
152 void QE_entityCountChanged()
154 g_numentities = int(g_entityCount.get());
155 QE_UpdateStatusBar();
158 bool ConfirmModified(const char *title)
160 if (!Map_Modified(g_map)) {
164 auto result = ui::alert(MainFrame_getWindow(),
165 "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?",
166 title, ui::alert_type::YESNOCANCEL, ui::alert_icon::Question);
167 if (result == ui::alert_response::CANCEL) {
170 if (result == ui::alert_response::YES) {
171 if (Map_Unnamed(g_map)) {
182 build_set_variable("RadiantPath", AppPath_get());
183 build_set_variable("ExecutableType", RADIANT_EXECUTABLE);
184 build_set_variable("EnginePath", EnginePath_get());
185 build_set_variable("UserEnginePath", g_qeglobals.m_userEnginePath.c_str());
186 build_set_variable("MonitorAddress", (g_WatchBSP_Enabled) ? "127.0.0.1:39000" : "");
187 build_set_variable("GameName", gamename_get());
189 StringBuffer ExtraQ3map2Args;
191 for (int i = 0; i < g_pakPathCount; i++) {
192 if (g_strcmp0(g_strPakPath[i].c_str(), "")) {
193 ExtraQ3map2Args.push_string(" -fs_pakpath \"");
194 ExtraQ3map2Args.push_string(g_strPakPath[i].c_str());
195 ExtraQ3map2Args.push_string("\"");
200 if (g_disableEnginePath) {
201 ExtraQ3map2Args.push_string(" -fs_nobasepath ");
204 if (g_disableHomePath) {
205 ExtraQ3map2Args.push_string(" -fs_nohomepath ");
208 build_set_variable("ExtraQ3map2Args", ExtraQ3map2Args.c_str());
210 const char *mapname = Map_Name(g_map);
211 StringOutputStream name(256);
212 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".bsp";
214 build_set_variable("MapFile", mapname);
215 build_set_variable("BspFile", name.c_str());
220 build_clear_variables();
223 class ArrayCommandListener : public CommandListener {
226 ArrayCommandListener()
228 m_array = g_ptr_array_new();
231 ~ArrayCommandListener()
233 g_ptr_array_free(m_array, TRUE);
236 void execute(const char *command)
238 g_ptr_array_add(m_array, g_strdup(command));
241 GPtrArray *array() const
247 class BatchCommandListener : public CommandListener {
248 TextOutputStream &m_file;
249 std::size_t m_commandCount;
250 const char *m_outputRedirect;
252 BatchCommandListener(TextOutputStream &file, const char *outputRedirect) : m_file(file), m_commandCount(0),
253 m_outputRedirect(outputRedirect)
257 void execute(const char *command)
260 if (m_commandCount == 0) {
265 m_file << "\"" << m_outputRedirect << "\"";
271 bool Region_cameraValid()
273 Vector3 vOrig(vector3_snapped(Camera_getOrigin(*g_pParentWnd->GetCamWnd())));
275 for (int i = 0; i < 3; i++) {
276 if (vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i]) {
284 void RunBSP(const char *name)
286 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
287 // make sure we don't attempt to region compile a map with the camera outside the region
288 if (region_active && !Region_cameraValid()) {
289 globalErrorStream() << "The camera must be in the region to start a region compile.\n";
295 if (Map_Unnamed(g_map)) {
296 globalOutputStream() << "build cancelled\n";
300 if (g_SnapShots_Enabled && !Map_Unnamed(g_map) && Map_Modified(g_map)) {
305 const char *mapname = Map_Name(g_map);
306 StringOutputStream name(256);
307 name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".reg";
308 Map_SaveRegion(name.c_str());
315 if (g_WatchBSP_Enabled) {
316 ArrayCommandListener listener;
317 build_run(name, listener);
318 // grab the file name for engine running
319 const char *fullname = Map_Name(g_map);
320 StringOutputStream bspname(64);
321 bspname << StringRange(path_get_filename_start(fullname), path_get_filename_base_end(fullname));
322 BuildMonitor_Run(listener.array(), bspname.c_str());
324 char junkpath[PATH_MAX];
325 strcpy(junkpath, SettingsPath_get());
326 strcat(junkpath, "junk.txt");
328 char batpath[PATH_MAX];
330 strcpy(batpath, SettingsPath_get());
331 strcat(batpath, "qe3bsp.sh");
332 #elif GDEF_OS_WINDOWS
333 strcpy( batpath, SettingsPath_get() );
334 strcat( batpath, "qe3bsp.bat" );
336 #error "unsupported platform"
338 bool written = false;
340 TextFileOutputStream batchFile(batpath);
341 if (!batchFile.failed()) {
343 batchFile << "#!/bin/sh \n\n";
345 BatchCommandListener listener(batchFile, junkpath);
346 build_run(name, listener);
352 chmod(batpath, 0744);
354 globalOutputStream() << "Writing the compile script to '" << batpath << "'\n";
355 globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n";
356 Q_Exec(batpath, NULL, NULL, true, false);
363 // =============================================================================
366 void Sys_SetTitle(const char *text, bool modified)
368 StringOutputStream title;
375 gtk_window_set_title(MainFrame_getWindow(), title.c_str());
378 bool g_bWaitCursor = false;
380 void Sys_BeginWait(void)
382 ScreenUpdates_Disable("Processing...", "Please Wait");
383 GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
384 gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), cursor);
385 gdk_cursor_unref(cursor);
386 g_bWaitCursor = true;
389 void Sys_EndWait(void)
391 ScreenUpdates_Enable();
392 gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), 0);
393 g_bWaitCursor = false;