]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/mediasource/netradiant-src/contrib/hydratoolz/plugin.cpp
Move the netradiant and fteqcc sources
[voretournament/voretournament.git] / misc / mediasource / netradiant-src / contrib / hydratoolz / plugin.cpp
diff --git a/misc/mediasource/netradiant-src/contrib/hydratoolz/plugin.cpp b/misc/mediasource/netradiant-src/contrib/hydratoolz/plugin.cpp
new file mode 100644 (file)
index 0000000..abc57fc
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+Copyright (C) 1999-2006 Id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "plugin.h"
+#include "version.h"
+
+/*! \file plugin.cpp
+    \brief HydraToolz!
+
+    HydraToolz by Dominic Clifton - Hydra (Hydra@Hydras-World.com)
+
+    Overview
+    ========
+
+
+    Version History
+    ===============
+
+    v0.1 - 28/May/2002
+      - Initial version.
+
+
+    ToDo
+    ====
+
+    * Code it ? :)
+
+*/
+
+// =============================================================================
+// Globals
+
+_QERFuncTable_1 g_FuncTable;
+_QERFileSystemTable g_FileSystemTable;
+_QEREntityTable g_EntityTable;
+
+// cast to GtkWidget*
+void *g_pMainWnd;
+
+// =============================================================================
+// Ripped from TexTool.cpp
+
+static void dialog_button_callback (GtkWidget *widget, gpointer data)
+{
+  GtkWidget *parent;
+  int *loop, *ret;
+
+  parent = gtk_widget_get_toplevel (widget);
+  loop = (int*)gtk_object_get_data (GTK_OBJECT (parent), "loop");
+  ret = (int*)gtk_object_get_data (GTK_OBJECT (parent), "ret");
+
+  *loop = 0;
+  *ret = gpointer_to_int (data);
+}
+
+static gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
+{
+  int *loop;
+
+  gtk_widget_hide (widget);
+  loop = (int*)gtk_object_get_data (GTK_OBJECT (widget), "loop");
+  *loop = 0;
+
+  return TRUE;
+}
+
+int DoMessageBox (const char* lpText, const char* lpCaption, guint32 uType)
+{
+  GtkWidget *window, *w, *vbox, *hbox;
+  int mode = (uType & MB_TYPEMASK), ret, loop = 1;
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+                      GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
+  gtk_signal_connect (GTK_OBJECT (window), "destroy",
+                      GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
+  gtk_window_set_title (GTK_WINDOW (window), lpCaption);
+  gtk_container_border_width (GTK_CONTAINER (window), 10);
+  gtk_object_set_data (GTK_OBJECT (window), "loop", &loop);
+  gtk_object_set_data (GTK_OBJECT (window), "ret", &ret);
+  gtk_widget_realize (window);
+
+  vbox = gtk_vbox_new (FALSE, 10);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+  gtk_widget_show (vbox);
+
+  w = gtk_label_new (lpText);
+  gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
+  gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
+  gtk_widget_show (w);
+
+  w = gtk_hseparator_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
+  gtk_widget_show (w);
+
+  hbox = gtk_hbox_new (FALSE, 10);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
+  gtk_widget_show (hbox);
+
+  if (mode == MB_OK)
+  {
+    w = gtk_button_new_with_label ("Ok");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
+    GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
+    gtk_widget_grab_default (w);
+    gtk_widget_show (w);
+    ret = IDOK;
+  }
+  else if (mode ==  MB_OKCANCEL)
+  {
+    w = gtk_button_new_with_label ("Ok");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
+    GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
+    gtk_widget_grab_default (w);
+    gtk_widget_show (w);
+
+    w = gtk_button_new_with_label ("Cancel");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
+    gtk_widget_show (w);
+    ret = IDCANCEL;
+  }
+  else if (mode == MB_YESNOCANCEL)
+  {
+    w = gtk_button_new_with_label ("Yes");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));
+    GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
+    gtk_widget_grab_default (w);
+    gtk_widget_show (w);
+
+    w = gtk_button_new_with_label ("No");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));
+    gtk_widget_show (w);
+
+    w = gtk_button_new_with_label ("Cancel");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
+    gtk_widget_show (w);
+    ret = IDCANCEL;
+  }
+  else /* if (mode == MB_YESNO) */
+  {
+    w = gtk_button_new_with_label ("Yes");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));
+    GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
+    gtk_widget_grab_default (w);
+    gtk_widget_show (w);
+
+    w = gtk_button_new_with_label ("No");
+    gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                        GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));
+    gtk_widget_show (w);
+    ret = IDNO;
+  }
+
+  gtk_widget_show (window);
+  gtk_grab_add (window);
+
+  while (loop)
+    gtk_main_iteration ();
+
+  gtk_grab_remove (window);
+  gtk_widget_destroy (window);
+
+  return ret;
+}
+
+// End of rip from TexTool.cpp
+
+// =============================================================================
+// Ripped from cmdlib.cpp
+
+/*
+====================
+Extract file parts
+====================
+*/
+void ExtractFilePath (const char *path, char *dest)
+{
+  const char *src;
+
+  src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+  while (src != path && *(src-1) != '/' && *(src-1) != '\\')
+    src--;
+
+  memcpy (dest, path, src-path);
+  dest[src-path] = 0;
+}
+
+void ExtractFileName (const char *path, char *dest)
+{
+  const char *src;
+
+  src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+  while (src != path && *(src-1) != '/'
+         && *(src-1) != '\\' )
+    src--;
+
+  while (*src)
+  {
+    *dest++ = *src++;
+  }
+  *dest = 0;
+}
+
+void ConvertDOSToUnixName( char *dst, const char *src )
+{
+  while ( *src )
+  {
+    if ( *src == '\\' )
+      *dst = '/';
+    else
+      *dst = *src;
+    dst++; src++;
+  }
+  *dst = 0;
+}
+
+// End of rip from cmdlib.cpp
+
+// =============================================================================
+// Actual Plugin Code
+
+// get the wad name from the shader name (or an actual wadname) and add to a list of wad names making
+// sure we don't add duplicates.
+
+GSList *AddToWadList(GSList *wadlist, const char *shadername, const char *wad)
+{
+  char tmpstr[QER_MAX_NAMELEN];
+  char *wadname;
+  if (!shadername && !wad) return wadlist;
+
+  if (shadername)
+  {
+    if (strcmp(shadername,"color") == 0)
+      return wadlist;
+    ExtractFilePath(shadername,tmpstr);
+    // Sys_Printf("checking: %s\n",shadername);
+
+    int l = strlen(tmpstr) - 1;
+
+    if (tmpstr[l] == '/' || tmpstr[l] == '\\')
+      tmpstr[l] = 0;
+    else
+    {
+      Sys_Printf("WARNING: Unknown wad file for shader %s\n",shadername);
+      return wadlist;
+    }
+
+    ExtractFileName(tmpstr,tmpstr);
+
+    wadname = (char *)malloc(strlen(tmpstr) + 5);
+    sprintf(wadname,"%s.wad",tmpstr);
+  }
+  else
+  {
+    wadname=strdup(wad);
+  }
+
+  for (GSList *l = wadlist; l != NULL ; l = l->next)
+  {
+    if (string_equal_nocase((char *)l->data,wadname))
+    {
+      free( wadname );
+      return wadlist;
+    }
+  }
+
+  Sys_Printf("Adding Wad File to WAD list: %s (reason: ",wadname);
+  if (shadername)
+    Sys_Printf("see shader \"%s\")\n", shadername);
+  else
+    Sys_Printf("already in WAD key. )\n");
+  return ( g_slist_append (wadlist, wadname ) );
+}
+
+void UpdateWadKeyPair( void )
+{
+  int i,nb;
+
+  char wads[2048]; // change to CString usage ?
+  wads[0] = 0;
+  char *p1,*p2;
+  entity_t *pEntity;
+  epair_t *pEpair;
+  GSList *wadlist = NULL;
+  face_t  *f;
+  brush_t *b;
+  char cleanwadname[QER_MAX_NAMELEN];
+  const char *actualwad;
+
+
+  pEntity = (entity_t *)g_FuncTable.m_pfnGetEntityHandle(0); // get the worldspawn ent
+
+  Sys_Printf("Searching for in-use wad files...\n");
+  for(pEpair = pEntity->epairs; pEpair != NULL; pEpair = pEpair->next)
+  {
+    if (string_equal_nocase(pEpair->key,"wad"))
+    {
+      strcpy(wads,pEpair->value);
+      ConvertDOSToUnixName(wads,wads);
+
+      // ok, we got the list of ; delimited wads, now split it into a GSList that contains
+      // just the wad names themselves.
+
+      p1 = wads;
+
+      do
+      {
+        p2 = strchr(p1,';');
+        if (p2)
+          *p2 = 0; // swap the ; with a null terminator
+
+        if (strchr(p1,'/') || strchr(p1,'\\'))
+        {
+          ExtractFileName(p1,cleanwadname);
+          wadlist = AddToWadList (wadlist, NULL, cleanwadname);
+        }
+        else
+        {
+          wadlist = AddToWadList (wadlist, NULL, p1);
+        }
+        if (p2)
+          p1 = p2+1; // point back to the remainder of the string
+        else
+          p1 = NULL; // make it so we exit the loop.
+
+      } while (p1);
+
+      // ok, now we have a list of wads in GSList.
+      // now we need to add any new wadfiles (with their paths) to this list
+      // so scan all brushes and see what wads are in use
+      // FIXME: scan brushes only in the region ?
+
+      break; // we don't need to process any more key/pairs.
+    }
+  }
+
+  nb = g_FuncTable.m_pfnAllocateActiveBrushHandles();
+  for( i = 0; i < nb; i++ )
+       {
+    b = (brush_t *)g_FuncTable.m_pfnGetActiveBrushHandle(i);
+    if (b->patchBrush) // patches in halflife ?
+    {
+      wadlist = AddToWadList(wadlist, b->pPatch->pShader->getName(),NULL);
+    } else
+    {
+      for (f=b->brush_faces ; f ; f=f->next)
+      {
+        wadlist = AddToWadList(wadlist, f->pShader->getName(),NULL);
+      }
+    }
+  }
+  g_FuncTable.m_pfnReleaseActiveBrushHandles();
+
+  nb = g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+  for( i = 0; i < nb; i++ )
+       {
+    b = (brush_t *)g_FuncTable.m_pfnGetSelectedBrushHandle(i);
+    if (b->patchBrush) // patches in halflife ?
+    {
+      wadlist = AddToWadList(wadlist, b->pPatch->pShader->getName(),NULL);
+    } else
+    {
+      for (f=b->brush_faces ; f ; f=f->next)
+      {
+        wadlist = AddToWadList(wadlist, f->pShader->getName(),NULL);
+      }
+    }
+  }
+  g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+
+  // Now we have a complete list of wadnames (without paths) so we just have to turn this
+  // back to a ; delimited list.
+
+  wads[0] = 0;
+  while (wadlist)
+  {
+    if (string_equal_nocase((char *)wadlist->data,"common-hydra.wad"))
+    {
+      Sys_Printf("Skipping radiant-supplied wad file %s\n",(char *)wadlist->data);
+    }
+    else
+    {
+      if (wads[0])
+        strcat(wads,";");
+
+      actualwad = vfsGetFullPath((char *)wadlist->data);
+
+      if (actualwad)
+      {
+        strcat(wads, actualwad);
+      }
+      else
+      {
+        Sys_Printf("WARNING: could not locate wad file %s\n",(char *)wadlist->data);
+        strcat(wads, (char *)wadlist->data);
+      }
+    }
+
+    free (wadlist->data);
+    wadlist = g_slist_remove (wadlist, wadlist->data);
+  }
+
+  // store the wad list back in the worldspawn.
+  if (wads[0])
+  {
+    //free(pEpair->value);
+    //pEpair->value = strdup(wads);
+    SetKeyValue(pEntity, "wad", wads);
+  }
+
+}
+
+// =============================================================================
+// PLUGIN INTERFACE STUFF
+
+// plugin name
+const char *PLUGIN_NAME = "Q3 Texture Tools";
+
+// commands in the menu
+const char *PLUGIN_COMMANDS = "About...;Create/Update WAD keypair";
+
+const char *PLUGIN_ABOUT = "HydraToolz for GTKRadiant\n\n"
+                           "By Hydra!";
+
+extern "C" void* WINAPI QERPlug_GetFuncTable ()
+{
+  return &g_FuncTable;
+}
+
+const char* QERPlug_Init (void* hApp, void *pWidget)
+{
+  GtkWidget* pMainWidget = static_cast<GtkWidget*>(pWidget);
+
+  g_pMainWnd = pMainWidget;
+  memset(&g_FuncTable, 0, sizeof(_QERFuncTable_1));
+  g_FuncTable.m_nSize = sizeof(_QERFuncTable_1);
+  return "HydraToolz for GTKRadiant"; // do we need this ? hmmm
+}
+
+const char* QERPlug_GetName()
+{
+  return (char*)PLUGIN_NAME;
+}
+
+const char* QERPlug_GetCommandList()
+{
+  return PLUGIN_COMMANDS;
+}
+
+extern "C" void QERPlug_Dispatch(const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)
+{
+       if(!strcmp(p, "Create/Update WAD keypair"))
+               UpdateWadKeyPair();
+       else if(!strcmp(p, "About..."))
+               g_FuncTable.m_pfnMessageBox((GtkWidget*)NULL, PLUGIN_ABOUT, "About", eMB_OK);
+}
+
+// =============================================================================
+// SYNAPSE
+
+CSynapseServer* g_pSynapseServer = NULL;
+CSynapseClientHydraToolz g_SynapseClient;
+
+extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces (const char *version, CSynapseServer *pServer)
+{
+  if (strcmp(version, SYNAPSE_VERSION))
+  {
+    Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
+    return NULL;
+  }
+  g_pSynapseServer = pServer;
+  g_pSynapseServer->IncRef();
+  Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());
+
+  g_SynapseClient.AddAPI(PLUGIN_MAJOR, "HydraToolz", sizeof(_QERPluginTable));
+  g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
+  g_SynapseClient.AddAPI(VFS_MAJOR, "wad", sizeof(g_FileSystemTable), SYN_REQUIRE, &g_FileSystemTable);
+  g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);
+  return &g_SynapseClient;
+}
+
+bool CSynapseClientHydraToolz::RequestAPI(APIDescriptor_t *pAPI)
+{
+  if (!strcmp(pAPI->major_name, PLUGIN_MAJOR))
+  {
+    _QERPluginTable *pTable = static_cast<_QERPluginTable*>(pAPI->mpTable);
+    pTable->m_pfnQERPlug_Init = QERPlug_Init;
+    pTable->m_pfnQERPlug_GetName = QERPlug_GetName;
+    pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
+    pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
+    return true;
+  }
+
+  Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
+  return false;
+}
+
+const char* CSynapseClientHydraToolz::GetInfo()
+{
+  return "HydraToolz plugin built " __DATE__ " " RADIANT_VERSION;
+}