automatically run the decompiler when specifying a BSP file in Import...
authorRudolf Polzer <divverent@alientrap.org>
Sun, 10 Oct 2010 14:04:41 +0000 (16:04 +0200)
committerRudolf Polzer <divverent@alientrap.org>
Sun, 10 Oct 2010 14:04:41 +0000 (16:04 +0200)
libs/cmdlib.h
libs/cmdlib/cmdlib.cpp
plugins/mapq3/plugin.cpp
radiant/gtkdlgs.cpp
radiant/map.cpp
radiant/qe3.cpp
radiant/watchbsp.cpp

index ffeb427..8961bd2 100644 (file)
@@ -43,7 +43,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //   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
 
index a09ed9e..f6ace0f 100644 (file)
@@ -36,16 +36,23 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #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;
@@ -84,7 +91,7 @@ bool Q_Exec(const char *cmd, char *cmdline, const char *, bool)
 #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};
@@ -121,7 +128,11 @@ bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateCon
                     &startupinfo,
                     &ProcessInformation
                     ))
+  {
+    if(waitfor)
+      WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
     return true;
+  }
   return false;
 }
 
index c08a7e2..fdb68a2 100644 (file)
@@ -264,8 +264,9 @@ public:
 
   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()
   {
index 2ba3e3f..57ed278 100644 (file)
@@ -1089,7 +1089,7 @@ void DoTextEditor (const char* filename, int cursorpos)
     
     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";
     }
index ac95068..7b8c570 100644 (file)
@@ -85,6 +85,7 @@ MapModules& ReferenceAPI_getMapModules();
 #include "commands.h"
 #include "autosave.h"
 #include "brushmodule.h"
+#include "brush.h"
 
 class NameObserver
 {
@@ -1637,28 +1638,80 @@ bool Map_ImportFile(const char* filename)
   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;
 }
 
index 0291d2c..c707d56 100644 (file)
@@ -333,7 +333,7 @@ void RunBSP(const char* name)
 #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);
     }
   }
 
index 83fba90..5c170b6 100644 (file)
@@ -577,7 +577,7 @@ void CWatchBSP::DoEBeginStep()
     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: ";
@@ -815,7 +815,7 @@ void CWatchBSP::RoutineProcessing()
             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();