// if the spawn was fine
// TODO TTimo add functionality to track the process until it dies
-bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole);
+bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole, bool waitfor);
// some easy portability crap
#if defined (POSIX)
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
-bool Q_Exec(const char *cmd, char *cmdline, const char *, bool)
+bool Q_Exec(const char *cmd, char *cmdline, const char *, bool, bool waitfor)
{
char fullcmd[2048];
char *pCmd;
+ pid_t pid;
#ifdef _DEBUG
printf("Q_Exec damnit\n");
#endif
- switch (fork())
+ switch ((pid = fork()))
{
+ default:
+ if(waitfor)
+ waitpid(pid, NULL, 0);
+ break;
case -1:
return true;
break;
#include <windows.h>
// NOTE TTimo windows is VERY nitpicky about the syntax in CreateProcess
-bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole)
+bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole, bool waitfor)
{
PROCESS_INFORMATION ProcessInformation;
STARTUPINFO startupinfo = {0};
&startupinfo,
&ProcessInformation
))
+ {
+ if(waitfor)
+ WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
return true;
+ }
return false;
}
MapQ3API()
{
- GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake3 maps", "*.map"));
- GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake3 region", "*.reg"));
+ GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake3 maps", "*.map", true, true, true));
+ GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake3 region", "*.reg", true, true, true));
+ GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake3 compiled maps", "*.bsp", false, true, false));
}
MapFormat* getTable()
{
globalOutputStream() << "Launching: " << strEditCommand.c_str() << "\n";
// note: linux does not return false if the command failed so it will assume success
- if (Q_Exec(0, const_cast<char*>(strEditCommand.c_str()), 0, true) == false)
+ if (Q_Exec(0, const_cast<char*>(strEditCommand.c_str()), 0, true, false) == false)
{
globalOutputStream() << "Failed to execute " << strEditCommand.c_str() << ", using default\n";
}
#include "commands.h"
#include "autosave.h"
#include "brushmodule.h"
+#include "brush.h"
class NameObserver
{
ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map");
bool success = false;
+
+ if(extension_equal(path_get_extension(filename), "bsp"))
+ goto tryDecompile;
+
{
Resource* resource = GlobalReferenceCache().capture(filename);
resource->refresh(); // avoid loading old version if map has changed on disk since last import
- if(resource->load())
+ if(!resource->load())
{
- NodeSmartReference clone(NewMapRoot(""));
-
- {
- //ScopeTimer timer("clone subgraph");
- Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone));
- }
-
- Map_gatherNamespaced(clone);
- Map_mergeClonedNames();
- MergeMap(clone);
- success = true;
+ GlobalReferenceCache().release(filename);
+ goto tryDecompile;
}
+ NodeSmartReference clone(NewMapRoot(""));
+ Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone));
+ Map_gatherNamespaced(clone);
+ Map_mergeClonedNames();
+ MergeMap(clone);
+ success = true;
GlobalReferenceCache().release(filename);
}
- SceneChangeNotify();
+ SceneChangeNotify();
+
+ return success;
+tryDecompile:
+
+ const char *type = GlobalRadiant().getRequiredGameDescriptionKeyValue("q3map2_type");
+ int n = string_length(path_get_extension(filename));
+ if(n && (extension_equal(path_get_extension(filename), "bsp") || extension_equal(path_get_extension(filename), "map")))
+ {
+ StringBuffer output;
+ output.push_string(AppPath_get());
+ output.push_string("q3map2.");
+ output.push_string(RADIANT_EXECUTABLE);
+ output.push_string(" -v -game ");
+ output.push_string((type && *type) ? type : "quake3");
+ output.push_string(" -fs_basepath \"");
+ output.push_string(EnginePath_get());
+ output.push_string("\" -fs_game ");
+ output.push_string(gamename_get());
+ output.push_string(" -convert -format ");
+ output.push_string(Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map");
+ output.push_string(" \"");
+ output.push_string(filename);
+ output.push_string("\"");
+
+ // run
+ Q_Exec(NULL, output.c_str(), NULL, false, true);
+
+ // rebuild filename as "filenamewithoutext_converted.map"
+ output.clear();
+ output.push_range(filename, filename + string_length(filename) - (n + 1));
+ output.push_string("_converted.map");
+ filename = output.c_str();
+
+ // open
+ Resource* resource = GlobalReferenceCache().capture(filename);
+ resource->refresh(); // avoid loading old version if map has changed on disk since last import
+ if(!resource->load())
+ {
+ GlobalReferenceCache().release(filename);
+ goto tryDecompile;
+ }
+ NodeSmartReference clone(NewMapRoot(""));
+ Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone));
+ Map_gatherNamespaced(clone);
+ Map_mergeClonedNames();
+ MergeMap(clone);
+ success = true;
+ GlobalReferenceCache().release(filename);
+ }
+
+ SceneChangeNotify();
return success;
}
#endif
globalOutputStream() << "Writing the compile script to '" << batpath << "'\n";
globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n";
- Q_Exec(batpath, NULL, NULL, true);
+ Q_Exec(batpath, NULL, NULL, true, false);
}
}
globalOutputStream() << "=== running build command ===\n"
<< static_cast<const char*>(g_ptr_array_index( m_pCmd, m_iCurrentStep )) << "\n";
- if (!Q_Exec(NULL, (char *)g_ptr_array_index( m_pCmd, m_iCurrentStep ), NULL, true ))
+ if (!Q_Exec(NULL, (char *)g_ptr_array_index( m_pCmd, m_iCurrentStep ), NULL, true, false ))
{
StringOutputStream msg(256);
msg << "Failed to execute the following command: ";
globalOutputStream() << cmd.c_str() << " " << cmdline.c_str() << "\n";
// execute now
- if (!Q_Exec(cmd.c_str(), (char *)cmdline.c_str(), EnginePath_get(), false))
+ if (!Q_Exec(cmd.c_str(), (char *)cmdline.c_str(), EnginePath_get(), false, false))
{
StringOutputStream msg;
msg << "Failed to execute the following command: " << cmd.c_str() << cmdline.c_str();