more eol-style
authorTTimo <ttimo@ttimo.net>
Sun, 4 Nov 2007 03:53:53 +0000 (03:53 +0000)
committerTTimo <ttimo@ttimo.net>
Sun, 4 Nov 2007 03:53:53 +0000 (03:53 +0000)
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/ZeroRadiant.ab@186 8a3a26a2-13c4-0310-b231-cf6edde360e5

211 files changed:
contrib/bkgrnd2d/bkgrnd2d.cpp
contrib/bkgrnd2d/dialog.cpp
contrib/bkgrnd2d/plugin.cpp
contrib/bobtoolz/DBobView.cpp
contrib/bobtoolz/DBrush.cpp
contrib/bobtoolz/DEPair.cpp
contrib/bobtoolz/DEntity.cpp
contrib/bobtoolz/DListener.cpp
contrib/bobtoolz/DMap.cpp
contrib/bobtoolz/DPatch.cpp
contrib/bobtoolz/DPlane.cpp
contrib/bobtoolz/DPoint.cpp
contrib/bobtoolz/DShape.cpp
contrib/bobtoolz/DTrainDrawer.cpp
contrib/bobtoolz/DTreePlanter.cpp
contrib/bobtoolz/DVisDrawer.cpp
contrib/bobtoolz/DWinding.cpp
contrib/bobtoolz/ScriptParser.cpp
contrib/bobtoolz/StdAfx.cpp
contrib/bobtoolz/bobToolz-GTK.cpp
contrib/bobtoolz/bsploader.cpp
contrib/bobtoolz/cportals.cpp
contrib/bobtoolz/ctfToolz-GTK.cpp
contrib/bobtoolz/dialogs/AboutDialog.cpp
contrib/bobtoolz/dialogs/AutoCaulkDialog.cpp
contrib/bobtoolz/dialogs/AutoCaulkStartDialog.cpp
contrib/bobtoolz/dialogs/DoorDialog.cpp
contrib/bobtoolz/dialogs/IntersectDialog.cpp
contrib/bobtoolz/dialogs/IntersectInfoDialog.cpp
contrib/bobtoolz/dialogs/PolygonDialog.cpp
contrib/bobtoolz/dialogs/StairDialog.cpp
contrib/bobtoolz/dialogs/TextureResetDialog.cpp
contrib/bobtoolz/dialogs/brushcheckdialog.cpp
contrib/bobtoolz/dialogs/dialogs-gtk.cpp
contrib/bobtoolz/dialogs/pathplotterdialog.cpp
contrib/bobtoolz/funchandlers-GTK.cpp
contrib/bobtoolz/funchandlers-ctf-GTK.cpp
contrib/bobtoolz/funchandlers.cpp
contrib/bobtoolz/lists.cpp
contrib/bobtoolz/misc.cpp
contrib/bobtoolz/shapes.cpp
contrib/bobtoolz/visfind.cpp
contrib/camera/camera.cpp
contrib/camera/dialogs.cpp
contrib/camera/dialogs_common.cpp
contrib/camera/funchandlers.cpp
contrib/camera/listener.cpp
contrib/camera/misc.cpp
contrib/camera/renderer.cpp
contrib/gtkgensurf/bitmap.cpp
contrib/gtkgensurf/dec.cpp
contrib/gtkgensurf/face.cpp
contrib/gtkgensurf/font.cpp
contrib/gtkgensurf/gendlgs.cpp
contrib/gtkgensurf/genmap.cpp
contrib/gtkgensurf/gensurf.cpp
contrib/gtkgensurf/heretic.cpp
contrib/gtkgensurf/plugin.cpp
contrib/gtkgensurf/view.cpp
contrib/hydratoolz/plugin.cpp
contrib/prtview/AboutDialog.cpp
contrib/prtview/ConfigDialog.cpp
contrib/prtview/LoadPortalFileDialog.cpp
contrib/prtview/gtkdlgs.cpp
contrib/prtview/portals.cpp
contrib/prtview/prtview.cpp
contrib/prtview/stdafx.cpp
docs/developer/XMLPush/StdAfx.cpp
docs/developer/XMLPush/XMLPush.cpp
libs/cmdlib/cmdlib.cpp
libs/jpeg6/jcomapi.cpp
libs/jpeg6/jdapimin.cpp
libs/jpeg6/jdapistd.cpp
libs/jpeg6/jdatasrc.cpp
libs/jpeg6/jdcoefct.cpp
libs/jpeg6/jdcolor.cpp
libs/jpeg6/jddctmgr.cpp
libs/jpeg6/jdhuff.cpp
libs/jpeg6/jdinput.cpp
libs/jpeg6/jdmainct.cpp
libs/jpeg6/jdmarker.cpp
libs/jpeg6/jdmaster.cpp
libs/jpeg6/jdpostct.cpp
libs/jpeg6/jdsample.cpp
libs/jpeg6/jdtrans.cpp
libs/jpeg6/jerror.cpp
libs/jpeg6/jfdctflt.cpp
libs/jpeg6/jidctflt.cpp
libs/jpeg6/jmemmgr.cpp
libs/jpeg6/jmemnobs.cpp
libs/jpeg6/jpgload.cpp
libs/jpeg6/jutils.cpp
libs/pak/pakstuff.cpp
libs/pak/unzip.cpp
libs/splines/math_angles.cpp
libs/splines/math_matrix.cpp
libs/splines/math_quaternion.cpp
libs/splines/math_vector.cpp
libs/splines/q_parse.cpp
libs/splines/q_shared.cpp
libs/splines/splines.cpp
libs/splines/util_str.cpp
libs/synapse/synapse.cpp
plugins/eclassfgd/plugin.cpp
plugins/entity/eclassmodel.cpp
plugins/entity/entity.cpp
plugins/entity/entity_entitymodel.cpp
plugins/entity/light.cpp
plugins/entity/miscmodel.cpp
plugins/entity/plugin.cpp
plugins/image/bmp.cpp
plugins/image/image.cpp
plugins/image/jpeg.cpp
plugins/image/lbmlib.cpp
plugins/imagehl/imagehl.cpp
plugins/imagehl/lbmlib.cpp
plugins/imagem8/imagem8.cpp
plugins/imagem8/m32.cpp
plugins/imagem8/m8.cpp
plugins/imagepng/plugin.cpp
plugins/imagewal/imagewal.cpp
plugins/imagewal/wal.cpp
plugins/map/parse.cpp
plugins/map/plugin.cpp
plugins/map/write.cpp
plugins/mapxml/plugin.cpp
plugins/mapxml/xmlparse.cpp
plugins/mapxml/xmlwrite.cpp
plugins/model/cpicomodel.cpp
plugins/model/cpicosurface.cpp
plugins/model/miscmodel.cpp
plugins/model/model.cpp
plugins/model/plugin.cpp
plugins/model/remap.cpp
plugins/shaders/plugin.cpp
plugins/shaders/shaders.cpp
plugins/spritemodel/plugin.cpp
plugins/spritemodel/spritemodel.cpp
plugins/surface/surfacedialog.cpp
plugins/surface/surfdlg_plugin.cpp
plugins/surface_heretic2/surfacedialog.cpp
plugins/surface_heretic2/surfaceflagsdialog_heretic2.cpp
plugins/surface_heretic2/surfdlg_plugin.cpp
plugins/surface_quake2/surfacedialog.cpp
plugins/surface_quake2/surfaceflagsdialog_quake2.cpp
plugins/surface_quake2/surfdlg_plugin.cpp
plugins/textool/2DView.cpp
plugins/textool/ControlPointsManager.cpp
plugins/textool/StdAfx.cpp
plugins/textool/TexTool.cpp
plugins/vfspak/vfs.cpp
plugins/vfspak/vfspak.cpp
plugins/vfspk3/unzip.cpp
plugins/vfspk3/vfs.cpp
plugins/vfspk3/vfspk3.cpp
plugins/vfswad/unwad.cpp
plugins/vfswad/vfs.cpp
plugins/vfswad/vfswad.cpp
radiant/bp_dlg.cpp
radiant/brush.cpp
radiant/brush_primit.cpp
radiant/brushscript.cpp
radiant/camwindow.cpp
radiant/csg.cpp
radiant/dialog.cpp
radiant/dialoginfo.cpp
radiant/drag.cpp
radiant/eclass.cpp
radiant/eclass_def.cpp
radiant/error.cpp
radiant/feedback.cpp
radiant/file.cpp
radiant/filters.cpp
radiant/findtexturedialog.cpp
radiant/glinterface.cpp
radiant/glwidget.cpp
radiant/glwindow.cpp
radiant/groupdialog.cpp
radiant/gtkdlgs.cpp
radiant/gtkmisc.cpp
radiant/main.cpp
radiant/mainframe.cpp
radiant/map.cpp
radiant/missing.cpp
radiant/parse.cpp
radiant/patchdialog.cpp
radiant/pluginentities.cpp
radiant/pluginmanager.cpp
radiant/pmesh.cpp
radiant/points.cpp
radiant/preferences.cpp
radiant/profile.cpp
radiant/qe3.cpp
radiant/qgl_ext.cpp
radiant/queuedraw.cpp
radiant/select.cpp
radiant/selectedface.cpp
radiant/stdafx.cpp
radiant/surfacedialog.cpp
radiant/surfaceplugin.cpp
radiant/targetname.cpp
radiant/texmanip.cpp
radiant/texwindow.cpp
radiant/ui.cpp
radiant/undo.cpp
radiant/vertsel.cpp
radiant/watchbsp.cpp
radiant/winding.cpp
radiant/xywindow.cpp
radiant/z.cpp
radiant/zwindow.cpp

index b2f09ff..0789083 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-//\r
-// bkgrnd2d Plugin\r
-//\r
-// Code by reyalP aka Reed Mideke\r
-//\r
-// Based on various other plugins\r
-//\r
-\r
-#include "bkgrnd2d.h"\r
-\r
-CBackgroundRender render;\r
-\r
-CBackgroundImage backgroundXY(XY),backgroundXZ(XZ),backgroundYZ(YZ);\r
-\r
-CBackgroundRender::CBackgroundRender()\r
-{\r
-       refCount = 1;\r
-}\r
-\r
-CBackgroundRender::~CBackgroundRender()\r
-{\r
-}\r
-\r
-void CBackgroundRender::Register()\r
-{\r
-       g_QglTable.m_pfnHookGL2DWindow( this );\r
-}\r
-\r
-void CBackgroundRender::Draw2D( VIEWTYPE vt )\r
-{\r
-       switch(vt)\r
-       {\r
-       case XY:\r
-               backgroundXY.Render();\r
-               break;\r
-       case XZ:\r
-               backgroundXZ.Render();\r
-               break;\r
-       case YZ:\r
-               backgroundYZ.Render();\r
-               break;\r
-       }\r
-}\r
-\r
-\r
-CBackgroundImage::CBackgroundImage(VIEWTYPE vt)\r
-{\r
-       m_tex = NULL;\r
-       m_alpha = 0.5;\r
-\r
-       // TODO, sensible defaults ? Or not show until we have extents ?\r
-       m_xmin = m_ymin = 0.0f;\r
-       m_xmax = m_ymax = 0.0f;\r
-\r
-       m_bActive = false;\r
-\r
-       m_vt = vt;\r
-\r
-       switch(m_vt)\r
-       {\r
-               case XY:\r
-                       m_ix = 0;\r
-                       m_iy = 1;\r
-                       break;\r
-               case XZ:\r
-                       m_ix = 0;\r
-                       m_iy = 2;\r
-                       break;\r
-               case YZ:\r
-                       m_ix = 1;\r
-                       m_iy = 2;\r
-                       break;\r
-       }\r
-}\r
-\r
-/*\r
- * should cleanup, but I don't think we can be sure it happens before our \r
- * interfaces are gone\r
-CBackgroundImage::~CBackgroundImage()\r
-{\r
-}\r
-*/\r
-\r
-void CBackgroundImage::Cleanup()\r
-{\r
-       if(m_tex) {\r
-               g_QglTable.m_pfn_qglDeleteTextures(1,&m_tex->texture_number);\r
-               g_free(m_tex);\r
-               m_tex = NULL;\r
-       }\r
-}\r
-\r
-void CBackgroundImage::Render()\r
-{\r
-       if (!m_bActive || !Valid())\r
-               return;\r
-       g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);\r
-\r
-       g_QglTable.m_pfn_qglEnable(GL_TEXTURE_2D);\r
-       g_QglTable.m_pfn_qglEnable(GL_BLEND);\r
-       g_QglTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
-       g_QglTable.m_pfn_qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);\r
-       g_QglTable.m_pfn_qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);\r
-       g_QglTable.m_pfn_qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);\r
-\r
-       g_QglTable.m_pfn_qglPolygonMode(GL_FRONT,GL_FILL);\r
-       // TODO, just so we can tell if we end up going the wrong way\r
-       // g_QglTable.m_pfn_qglPolygonMode(GL_BACK,GL_LINE);\r
-       // TODO any other state we should not assume ?\r
-\r
-       g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, m_tex->texture_number);\r
-       g_QglTable.m_pfn_qglBegin(GL_QUADS);\r
-\r
-       g_QglTable.m_pfn_qglColor4f(1.0,1.0,1.0,m_alpha);\r
-       g_QglTable.m_pfn_qglTexCoord2f(0.0,1.0);\r
-       g_QglTable.m_pfn_qglVertex2f(m_xmin,m_ymin);\r
-\r
-       g_QglTable.m_pfn_qglTexCoord2f(1.0,1.0);\r
-       g_QglTable.m_pfn_qglVertex2f(m_xmax,m_ymin);\r
-\r
-       g_QglTable.m_pfn_qglTexCoord2f(1.0,0.0);\r
-       g_QglTable.m_pfn_qglVertex2f(m_xmax,m_ymax);\r
-\r
-       g_QglTable.m_pfn_qglTexCoord2f(0.0,0.0);\r
-       g_QglTable.m_pfn_qglVertex2f(m_xmin,m_ymax);\r
-\r
-       g_QglTable.m_pfn_qglEnd();\r
-       g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, 0);\r
-\r
-       g_QglTable.m_pfn_qglPopAttrib();\r
-}\r
-\r
-bool CBackgroundImage::Load(const char *filename)\r
-{\r
-       qtexture_t *newtex;\r
-       \r
-       unsigned char *image = NULL; // gets allocated with what ? g_malloc\r
-       int width = 0, height = 0;\r
-\r
-       g_FuncTable.m_pfnLoadImage(filename,&image,&width,&height);\r
-\r
-       if(!image) {\r
-               Syn_Printf(MSG_WARN "load %s failed\n",filename);\r
-               return false;\r
-       }\r
-\r
-// just in case we want to build for an old version\r
-// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=900\r
-#ifdef BKGRND2D_JPG_WORKAROUND\r
-       if ( strlen(filename) > 4 && !strcmp(".jpg",filename + strlen(filename) - 4)) {\r
-               Syn_Printf(MSG_PREFIX ".jpg workaround, clearing alpha channel\n");\r
-               int size = width*height*4;\r
-               int i;\r
-               for (i = 3; i < size; i+=4) {\r
-                       image[i] = 255;\r
-               }\r
-       }\r
-#endif\r
-       \r
-       //TODO bug for stored texture size\r
-       //TODO whose gl context are we in, anyway ?\r
-       newtex = g_FuncTable.m_pfnLoadTextureRGBA(image,width,height);\r
-\r
-       g_free(image);\r
-\r
-       if(!newtex) {\r
-               Syn_Printf(MSG_WARN "image to texture failed\n");\r
-               return false;\r
-       }\r
-\r
-       Cleanup();\r
-       m_tex = newtex;\r
-\r
-       g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-\r
-       return true;\r
-}\r
-\r
-bool CBackgroundImage::SetExtentsMM()\r
-{\r
-       entity_s *worldentity;\r
-       const char *val;\r
-       int xmin = 0, ymin = 0, xmax = 0, ymax = 0;\r
-\r
-       worldentity = (entity_s *)g_FuncTable.m_pfnGetEntityHandle(0);\r
-       if(!worldentity) {\r
-               Syn_Printf(MSG_WARN "SetExtentsMM worldspawn not found\n");\r
-               return false;\r
-       }\r
-       //TODO val is not NULL even if key does not exist\r
-       val = g_EntityTable.m_pfnValueForKey(worldentity,"mapcoordsmins");\r
-       if(!val || !val[0]) {\r
-               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmins not found\n");\r
-               return false;\r
-       }\r
-// we could be more robust\r
-// note contortions due to splashs strange idea of min and max\r
-       if(sscanf(val, "%d %d",&xmin,&ymax) != 2)\r
-       {\r
-               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmins malformed\n");\r
-               return false;\r
-       }\r
-\r
-       val = g_EntityTable.m_pfnValueForKey(worldentity,"mapcoordsmaxs");\r
-       if(!val || !val[0]) {\r
-               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmaxs not found\n");\r
-               return false;\r
-       }\r
-       if(sscanf(val, "%d %d",&xmax,&ymin) != 2)\r
-       {\r
-               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmaxs malformed\n");\r
-               return false;\r
-       }\r
-       //might do sanity check before we commit\r
-       m_xmin = (float)xmin;\r
-       m_ymin = (float)ymin;\r
-       m_xmax = (float)xmax;\r
-       m_ymax = (float)ymax;\r
-\r
-       g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-       return true;\r
-}\r
-\r
-// TODO, this should just be exported from core\r
-// ripped directly from radiant/select.cpp:Select_GetBounds\r
-//\r
-static bool get_selection_bounds (vec3_t mins, vec3_t maxs)\r
-{\r
-       brush_t *b;\r
-       int             i;\r
-       brush_t *selected_brushes = g_DataTable.m_pfnSelectedBrushes();\r
-       //TODO should never happen\r
-       if(!selected_brushes) {\r
-         Sys_Printf (MSG_PREFIX "selected_brushes = NULL\n"); \r
-         return false;\r
-       }\r
-       // this should mean no selection\r
-       if(selected_brushes == selected_brushes->next) {\r
-         Sys_Printf (MSG_PREFIX "nothing selected\n"); \r
-\r
-         return false;\r
-       }\r
-\r
-       for (i=0 ; i<3 ; i++)\r
-       {\r
-               mins[i] = 99999;\r
-               maxs[i] = -99999;\r
-       }\r
-\r
-       for (b=selected_brushes->next ; b != selected_brushes ; b=b->next)\r
-       {\r
-               if (b->owner->eclass->fixedsize)\r
-               {\r
-                       for (i=0 ; i<3 ; i++)\r
-                       {\r
-                               if (b->owner->origin[i] < mins[i])\r
-                                       mins[i] = b->owner->origin[i];\r
-                               if (b->owner->origin[i] > maxs[i])\r
-                                       maxs[i] = b->owner->origin[i];\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       for (i=0 ; i<3 ; i++)\r
-                       {\r
-                               if (b->mins[i] < mins[i])\r
-                                       mins[i] = b->mins[i];\r
-                               if (b->maxs[i] > maxs[i])\r
-                                       maxs[i] = b->maxs[i];\r
-                       }\r
-               }\r
-       }\r
-  return true;\r
-}\r
-\r
-bool CBackgroundImage::SetExtentsSel()\r
-{\r
-       vec3_t mins,maxs;\r
-\r
-       if(!get_selection_bounds(mins,maxs)) \r
-               return false;\r
-\r
-       if(((int)mins[m_ix] == (int)maxs[m_ix]) ||\r
-     ((int)mins[m_iy] == (int)maxs[m_iy])) {\r
-               Syn_Printf(MSG_PREFIX "tiny selection\n");\r
-               return false;\r
-       }\r
-\r
-       m_xmin = mins[m_ix];\r
-       m_ymin = mins[m_iy];\r
-       m_xmax = maxs[m_ix];\r
-       m_ymax = maxs[m_iy];\r
-\r
-       g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-\r
-  return true;\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 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
+*/
+
+//
+// bkgrnd2d Plugin
+//
+// Code by reyalP aka Reed Mideke
+//
+// Based on various other plugins
+//
+
+#include "bkgrnd2d.h"
+
+CBackgroundRender render;
+
+CBackgroundImage backgroundXY(XY),backgroundXZ(XZ),backgroundYZ(YZ);
+
+CBackgroundRender::CBackgroundRender()
+{
+       refCount = 1;
+}
+
+CBackgroundRender::~CBackgroundRender()
+{
+}
+
+void CBackgroundRender::Register()
+{
+       g_QglTable.m_pfnHookGL2DWindow( this );
+}
+
+void CBackgroundRender::Draw2D( VIEWTYPE vt )
+{
+       switch(vt)
+       {
+       case XY:
+               backgroundXY.Render();
+               break;
+       case XZ:
+               backgroundXZ.Render();
+               break;
+       case YZ:
+               backgroundYZ.Render();
+               break;
+       }
+}
+
+
+CBackgroundImage::CBackgroundImage(VIEWTYPE vt)
+{
+       m_tex = NULL;
+       m_alpha = 0.5;
+
+       // TODO, sensible defaults ? Or not show until we have extents ?
+       m_xmin = m_ymin = 0.0f;
+       m_xmax = m_ymax = 0.0f;
+
+       m_bActive = false;
+
+       m_vt = vt;
+
+       switch(m_vt)
+       {
+               case XY:
+                       m_ix = 0;
+                       m_iy = 1;
+                       break;
+               case XZ:
+                       m_ix = 0;
+                       m_iy = 2;
+                       break;
+               case YZ:
+                       m_ix = 1;
+                       m_iy = 2;
+                       break;
+       }
+}
+
+/*
+ * should cleanup, but I don't think we can be sure it happens before our 
+ * interfaces are gone
+CBackgroundImage::~CBackgroundImage()
+{
+}
+*/
+
+void CBackgroundImage::Cleanup()
+{
+       if(m_tex) {
+               g_QglTable.m_pfn_qglDeleteTextures(1,&m_tex->texture_number);
+               g_free(m_tex);
+               m_tex = NULL;
+       }
+}
+
+void CBackgroundImage::Render()
+{
+       if (!m_bActive || !Valid())
+               return;
+       g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);
+
+       g_QglTable.m_pfn_qglEnable(GL_TEXTURE_2D);
+       g_QglTable.m_pfn_qglEnable(GL_BLEND);
+       g_QglTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       g_QglTable.m_pfn_qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+       g_QglTable.m_pfn_qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+       g_QglTable.m_pfn_qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+       g_QglTable.m_pfn_qglPolygonMode(GL_FRONT,GL_FILL);
+       // TODO, just so we can tell if we end up going the wrong way
+       // g_QglTable.m_pfn_qglPolygonMode(GL_BACK,GL_LINE);
+       // TODO any other state we should not assume ?
+
+       g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, m_tex->texture_number);
+       g_QglTable.m_pfn_qglBegin(GL_QUADS);
+
+       g_QglTable.m_pfn_qglColor4f(1.0,1.0,1.0,m_alpha);
+       g_QglTable.m_pfn_qglTexCoord2f(0.0,1.0);
+       g_QglTable.m_pfn_qglVertex2f(m_xmin,m_ymin);
+
+       g_QglTable.m_pfn_qglTexCoord2f(1.0,1.0);
+       g_QglTable.m_pfn_qglVertex2f(m_xmax,m_ymin);
+
+       g_QglTable.m_pfn_qglTexCoord2f(1.0,0.0);
+       g_QglTable.m_pfn_qglVertex2f(m_xmax,m_ymax);
+
+       g_QglTable.m_pfn_qglTexCoord2f(0.0,0.0);
+       g_QglTable.m_pfn_qglVertex2f(m_xmin,m_ymax);
+
+       g_QglTable.m_pfn_qglEnd();
+       g_QglTable.m_pfn_qglBindTexture(GL_TEXTURE_2D, 0);
+
+       g_QglTable.m_pfn_qglPopAttrib();
+}
+
+bool CBackgroundImage::Load(const char *filename)
+{
+       qtexture_t *newtex;
+       
+       unsigned char *image = NULL; // gets allocated with what ? g_malloc
+       int width = 0, height = 0;
+
+       g_FuncTable.m_pfnLoadImage(filename,&image,&width,&height);
+
+       if(!image) {
+               Syn_Printf(MSG_WARN "load %s failed\n",filename);
+               return false;
+       }
+
+// just in case we want to build for an old version
+// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=900
+#ifdef BKGRND2D_JPG_WORKAROUND
+       if ( strlen(filename) > 4 && !strcmp(".jpg",filename + strlen(filename) - 4)) {
+               Syn_Printf(MSG_PREFIX ".jpg workaround, clearing alpha channel\n");
+               int size = width*height*4;
+               int i;
+               for (i = 3; i < size; i+=4) {
+                       image[i] = 255;
+               }
+       }
+#endif
+       
+       //TODO bug for stored texture size
+       //TODO whose gl context are we in, anyway ?
+       newtex = g_FuncTable.m_pfnLoadTextureRGBA(image,width,height);
+
+       g_free(image);
+
+       if(!newtex) {
+               Syn_Printf(MSG_WARN "image to texture failed\n");
+               return false;
+       }
+
+       Cleanup();
+       m_tex = newtex;
+
+       g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+
+       return true;
+}
+
+bool CBackgroundImage::SetExtentsMM()
+{
+       entity_s *worldentity;
+       const char *val;
+       int xmin = 0, ymin = 0, xmax = 0, ymax = 0;
+
+       worldentity = (entity_s *)g_FuncTable.m_pfnGetEntityHandle(0);
+       if(!worldentity) {
+               Syn_Printf(MSG_WARN "SetExtentsMM worldspawn not found\n");
+               return false;
+       }
+       //TODO val is not NULL even if key does not exist
+       val = g_EntityTable.m_pfnValueForKey(worldentity,"mapcoordsmins");
+       if(!val || !val[0]) {
+               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmins not found\n");
+               return false;
+       }
+// we could be more robust
+// note contortions due to splashs strange idea of min and max
+       if(sscanf(val, "%d %d",&xmin,&ymax) != 2)
+       {
+               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmins malformed\n");
+               return false;
+       }
+
+       val = g_EntityTable.m_pfnValueForKey(worldentity,"mapcoordsmaxs");
+       if(!val || !val[0]) {
+               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmaxs not found\n");
+               return false;
+       }
+       if(sscanf(val, "%d %d",&xmax,&ymin) != 2)
+       {
+               Syn_Printf(MSG_WARN "SetExtentsMM mapcoordsmaxs malformed\n");
+               return false;
+       }
+       //might do sanity check before we commit
+       m_xmin = (float)xmin;
+       m_ymin = (float)ymin;
+       m_xmax = (float)xmax;
+       m_ymax = (float)ymax;
+
+       g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+       return true;
+}
+
+// TODO, this should just be exported from core
+// ripped directly from radiant/select.cpp:Select_GetBounds
+//
+static bool get_selection_bounds (vec3_t mins, vec3_t maxs)
+{
+       brush_t *b;
+       int             i;
+       brush_t *selected_brushes = g_DataTable.m_pfnSelectedBrushes();
+       //TODO should never happen
+       if(!selected_brushes) {
+         Sys_Printf (MSG_PREFIX "selected_brushes = NULL\n"); 
+         return false;
+       }
+       // this should mean no selection
+       if(selected_brushes == selected_brushes->next) {
+         Sys_Printf (MSG_PREFIX "nothing selected\n"); 
+
+         return false;
+       }
+
+       for (i=0 ; i<3 ; i++)
+       {
+               mins[i] = 99999;
+               maxs[i] = -99999;
+       }
+
+       for (b=selected_brushes->next ; b != selected_brushes ; b=b->next)
+       {
+               if (b->owner->eclass->fixedsize)
+               {
+                       for (i=0 ; i<3 ; i++)
+                       {
+                               if (b->owner->origin[i] < mins[i])
+                                       mins[i] = b->owner->origin[i];
+                               if (b->owner->origin[i] > maxs[i])
+                                       maxs[i] = b->owner->origin[i];
+                       }
+               }
+               else
+               {
+                       for (i=0 ; i<3 ; i++)
+                       {
+                               if (b->mins[i] < mins[i])
+                                       mins[i] = b->mins[i];
+                               if (b->maxs[i] > maxs[i])
+                                       maxs[i] = b->maxs[i];
+                       }
+               }
+       }
+  return true;
+}
+
+bool CBackgroundImage::SetExtentsSel()
+{
+       vec3_t mins,maxs;
+
+       if(!get_selection_bounds(mins,maxs)) 
+               return false;
+
+       if(((int)mins[m_ix] == (int)maxs[m_ix]) ||
+     ((int)mins[m_iy] == (int)maxs[m_iy])) {
+               Syn_Printf(MSG_PREFIX "tiny selection\n");
+               return false;
+       }
+
+       m_xmin = mins[m_ix];
+       m_ymin = mins[m_iy];
+       m_xmax = maxs[m_ix];
+       m_ymax = maxs[m_iy];
+
+       g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+
+  return true;
+}
+
index 43fe771..9f4ec49 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-//\r
-// bkgrnd2d Plugin dialog\r
-//\r
-// Code by reyalP aka Reed Mideke\r
-//\r
-// Based on various other plugins\r
-//\r
-\r
-#include <gtk/gtk.h>\r
-\r
-#include "bkgrnd2d.h"\r
-#include "dialog.h"\r
-\r
-// spaces to make label nice and big\r
-#define NO_FILE_MSG "        (no file loaded)        "\r
-\r
-static GtkWidget *pDialogWnd;\r
-static GtkWidget *pNotebook;\r
-static GtkTooltips *pTooltips;\r
-\r
-class CBackgroundDialogPage\r
-{\r
-private:\r
-       GtkWidget *m_pWidget;\r
-       GtkWidget *m_pTabLabel;\r
-       GtkWidget *m_pFileLabel;\r
-       GtkWidget *m_pPosLabel;\r
-       VIEWTYPE m_vt;\r
-       bool m_bValidFile;\r
-\r
-public:\r
-       CBackgroundImage *m_pImage;\r
-       CBackgroundDialogPage( VIEWTYPE vt );\r
-       void Append(GtkWidget *notebook);\r
-       void Browse();\r
-       void Reload();\r
-       void SetPosLabel();\r
-//  ~BackgroundDialogPage();\r
-};\r
-\r
-\r
-// dialog page callbacks\r
-static void browse_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       ((CBackgroundDialogPage *)data)->Browse();\r
-}\r
-\r
-static void reload_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       ((CBackgroundDialogPage *)data)->Reload();\r
-}\r
-\r
-static void size_sel_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;\r
-       if (pPage->m_pImage->SetExtentsSel())\r
-               pPage->SetPosLabel();\r
-}\r
-\r
-static void size_mm_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;\r
-       if(pPage->m_pImage->SetExtentsMM())\r
-               pPage->SetPosLabel();\r
-}\r
-\r
-static void alpha_adjust_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;\r
-       pPage->m_pImage->m_alpha = (float)gtk_range_get_value (GTK_RANGE(widget));\r
-       g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-}\r
-\r
-void CBackgroundDialogPage::Reload()\r
-{\r
-       if(m_bValidFile)\r
-               m_pImage->Load(gtk_label_get_text(GTK_LABEL(m_pFileLabel)));\r
-}\r
-\r
-void CBackgroundDialogPage::Browse()\r
-{\r
-       char browsedir[PATH_MAX];\r
-       const char *ct;\r
-       const char *newfile;\r
-       char *t;\r
-       \r
-       //TODO GetMapName saves the map. eeep!\r
-       //also with no map, returns unnamed.map, otherwise returns full path\r
-//     Syn_Printf(MSG_PREFIX "GetMapName() %s\n",\r
-//                             g_FuncTable.m_pfnGetMapName());\r
-       \r
-       ct = g_FuncTable.m_pfnReadProjectKey("basepath");\r
-       // TODO shouldn't need this stuff\r
-       if(!ct || !strlen(ct)) {\r
-               Syn_Printf(MSG_PREFIX "basepath = NULL or empty\n");\r
-               return;\r
-       }\r
-       Syn_Printf(MSG_PREFIX "basepath: %s\n",ct);\r
-       if(strlen(ct) >= PATH_MAX) {\r
-               Syn_Printf(MSG_PREFIX "base game dir too long\n");\r
-               return;\r
-       }\r
-\r
-       strcpy(browsedir,ct);\r
-       // make sure we have a trailing / \r
-       if(browsedir[strlen(browsedir) - 1] != '/')\r
-               strcat(browsedir,"/");\r
-\r
-       //if we dont have a file yet, don't try to use it for default dir\r
-       if(m_bValidFile) {\r
-       // filename should always be a nice clean unix style relative path\r
-               ct = gtk_label_get_text(GTK_LABEL(m_pFileLabel));\r
-               strcat(browsedir,ct);\r
-               Syn_Printf(MSG_PREFIX "full path: %s\n",browsedir);\r
-\r
-               // lop off the file part\r
-               t = browsedir + strlen(browsedir) - 1;\r
-               while (t != browsedir && *t != '/') \r
-                       t--;\r
-               *t = 0;\r
-       }\r
-       Syn_Printf(MSG_PREFIX "browse directory %s\n",browsedir);\r
-       \r
-//does NOT need freeing contrary to include/qerplugin.h comments\r
-//TODO bug/patch for comments\r
-//TODO patern gets fucked up sometimes if empty\r
-//http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=915\r
-       newfile = g_FuncTable.m_pfnFileDialog(pDialogWnd,TRUE,\r
-                                                                 "Load Background Image",browsedir,FILETYPE_KEY);\r
-       if(!newfile) {\r
-               Syn_Printf(MSG_PREFIX "newfile = NULL\n");\r
-               return;\r
-       }\r
-       Syn_Printf(MSG_PREFIX "newfile: %s\n",newfile);\r
-       newfile = g_FileSystemTable.m_pfnExtractRelativePath(newfile);\r
-\r
-       if(!newfile) {\r
-               Syn_Printf(MSG_PREFIX "newfile = NULL\n");\r
-               return;\r
-       }\r
-       Syn_Printf(MSG_PREFIX "newfile: %s\n",newfile);\r
-\r
-       if(m_pImage->Load(newfile)) {\r
-               m_bValidFile = true;\r
-               gtk_label_set_text(GTK_LABEL(m_pFileLabel),newfile);\r
-       }\r
-}\r
-\r
-void CBackgroundDialogPage::SetPosLabel()\r
-{\r
-       char s[64];\r
-       // TODO no snprintf ?\r
-       sprintf(s, "Size/Position (%d,%d) (%d,%d)",(int)(m_pImage->m_xmin),\r
-                       (int)(m_pImage->m_ymin),(int)(m_pImage->m_xmax),(int)(m_pImage->m_ymax));\r
-       gtk_label_set_text(GTK_LABEL(m_pPosLabel),s);\r
-}\r
-\r
-CBackgroundDialogPage::CBackgroundDialogPage(VIEWTYPE vt )\r
-{\r
-       GtkWidget *frame;\r
-       GtkWidget *hbox;\r
-       GtkWidget *w;\r
-\r
-       m_vt = vt;\r
-\r
-       m_bValidFile = false;\r
-\r
-       switch(m_vt)\r
-       {\r
-               case XY:\r
-                       m_pTabLabel = gtk_label_new("X/Y");\r
-                       m_pImage = &backgroundXY;\r
-                       break;\r
-               case XZ:\r
-                       m_pTabLabel = gtk_label_new("X/Z");\r
-                       m_pImage = &backgroundXZ;\r
-                       break;\r
-               case YZ:\r
-                       m_pTabLabel = gtk_label_new("Y/Z");\r
-                       m_pImage = &backgroundYZ;\r
-                       break;\r
-       }\r
-// A vbox to hold everything\r
-       m_pWidget = gtk_vbox_new(FALSE,0); \r
-// Frame for file row\r
-       frame = gtk_frame_new("File");\r
-       gtk_box_pack_start (GTK_BOX (m_pWidget),frame, FALSE, FALSE, 2);\r
-\r
-// hbox for first row\r
-       hbox = gtk_hbox_new(FALSE,5);\r
-       gtk_container_set_border_width(GTK_CONTAINER (hbox),4);\r
-       gtk_container_add (GTK_CONTAINER (frame), hbox);\r
-\r
-// label to display filename\r
-       m_pFileLabel  = gtk_label_new(NO_FILE_MSG);\r
-       gtk_label_set_selectable(GTK_LABEL(m_pFileLabel),TRUE);\r
-//TODO set min size ? done with spaces right now\r
-       gtk_box_pack_start (GTK_BOX (hbox),m_pFileLabel, TRUE, TRUE, 5);\r
-\r
-  gtk_widget_show (m_pFileLabel);\r
-\r
-       w = gtk_button_new_with_label ("Browse...");\r
-       g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (browse_callback),\r
-                                                              (gpointer)this);\r
-       gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);\r
-       gtk_tooltips_set_tip (pTooltips, w, "Select a file", NULL);\r
-  gtk_widget_show (w);\r
-       \r
-       w = gtk_button_new_with_label ("Reload");\r
-       g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (reload_callback),\r
-                                                              (gpointer)this);\r
-       // TODO disable until we have file\r
-       // gtk_widget_set_sensitive(w,FALSE);\r
-       gtk_tooltips_set_tip (pTooltips, w, "Reload current file", NULL);\r
-       gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);\r
-  gtk_widget_show (w);\r
-\r
-       gtk_widget_show (hbox);\r
-       gtk_widget_show (frame);\r
-\r
-// second row (rendering options)\r
-       frame = gtk_frame_new("Rendering");\r
-       gtk_box_pack_start (GTK_BOX (m_pWidget),frame, FALSE, FALSE, 2);\r
-\r
-       hbox = gtk_hbox_new(FALSE,5);\r
-       gtk_container_set_border_width(GTK_CONTAINER (hbox),4);\r
-       gtk_container_add (GTK_CONTAINER (frame), hbox);\r
-\r
-       w = gtk_label_new("Vertex alpha:");\r
-       gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);\r
-  gtk_widget_show (w);\r
-\r
-       w = gtk_hscale_new_with_range(0.0,1.0,0.01);\r
-       gtk_range_set_value(GTK_RANGE(w),0.5);\r
-       gtk_scale_set_value_pos(GTK_SCALE(w),GTK_POS_LEFT);\r
-       g_signal_connect (G_OBJECT (w), "value-changed",\r
-                          G_CALLBACK (alpha_adjust_callback), (gpointer)this);\r
-       gtk_box_pack_start (GTK_BOX (hbox),w, TRUE, TRUE, 5);\r
-       gtk_tooltips_set_tip (pTooltips, w, "Set image transparancy", NULL);\r
-  gtk_widget_show (w);\r
-\r
-       gtk_widget_show (hbox);\r
-       gtk_widget_show (frame);\r
-// Third row (size and position)\r
-       frame = gtk_frame_new("Size/Position (undefined)");\r
-       m_pPosLabel = gtk_frame_get_label_widget (GTK_FRAME(frame));\r
-       gtk_box_pack_start ( GTK_BOX (m_pWidget), frame, FALSE, FALSE, 2);\r
-\r
-       hbox = gtk_hbox_new(FALSE,5);\r
-       gtk_container_add (GTK_CONTAINER (frame), hbox);\r
-       gtk_container_set_border_width(GTK_CONTAINER (hbox),4);\r
-\r
-       w = gtk_button_new_with_label ("from selection");\r
-       gtk_box_pack_start (GTK_BOX (hbox),w, TRUE, FALSE, 5);\r
-       g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (size_sel_callback),\r
-                                                                (gpointer)this);\r
-       gtk_tooltips_set_tip (pTooltips, w, "Set the size of the image to the bounding rectangle of all selected brushes and entities", NULL);\r
-  gtk_widget_show (w);\r
-\r
-       if(m_vt == XY) {\r
-               w = gtk_button_new_with_label ("from map mins/maxs");\r
-               gtk_box_pack_start ( GTK_BOX (hbox),w, TRUE, FALSE, 2);\r
-               g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (size_mm_callback),\r
-                                                                (gpointer)this);\r
-               gtk_tooltips_set_tip (pTooltips, w, "Set the size of the image using the mapcoordsmins and mapcoordsmaxs keys of the worldspawn entity", NULL);\r
-               gtk_widget_show (w);\r
-       }\r
-\r
-       gtk_widget_show (hbox);\r
-       gtk_widget_show (frame);\r
-\r
-  gtk_widget_show ( m_pWidget );\r
-}\r
-\r
-void CBackgroundDialogPage::Append(GtkWidget *notebook)\r
-{\r
-       gtk_notebook_append_page( GTK_NOTEBOOK(notebook), m_pWidget, m_pTabLabel);\r
-}\r
-\r
-// dialog global callbacks\r
-/*\r
-static gint expose_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       return FALSE;\r
-}\r
-*/\r
-\r
-static void response_callback( GtkWidget *widget, gint response, gpointer data )\r
-{\r
-       if( response == GTK_RESPONSE_CLOSE )\r
-               gtk_widget_hide( pDialogWnd );\r
-}\r
-\r
-static gint close_callback( GtkWidget *widget, gpointer data )\r
-{\r
-       gtk_widget_hide( pDialogWnd );\r
-       return TRUE;\r
-}\r
-\r
-void InitBackgroundDialog()\r
-{\r
-       CBackgroundDialogPage *pPage;\r
-\r
-       pDialogWnd = gtk_dialog_new_with_buttons ("Background Images",\r
-                              GTK_WINDOW(g_pMainWidget),\r
-                              (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT),\r
-        // TODO dialog with no buttons\r
-        //                                                                               GTK_STOCK_CLOSE,\r
-        //                                                                               GTK_RESPONSE_CLOSE,\r
-                              NULL);\r
-       gtk_signal_connect( GTK_OBJECT (pDialogWnd), "delete_event",\r
-                                    GTK_SIGNAL_FUNC( close_callback ), NULL );\r
-       gtk_signal_connect( GTK_OBJECT (pDialogWnd), "response",\r
-                                  GTK_SIGNAL_FUNC( response_callback ), NULL );\r
-//     gtk_signal_connect( GTK_OBJECT (pDialogWnd), "expose_event", GTK_SIGNAL_FUNC( ci_expose ), NULL );\r
-\r
-       pTooltips = gtk_tooltips_new();\r
-\r
-       pNotebook = gtk_notebook_new();\r
-       pPage = new CBackgroundDialogPage(XY);\r
-       pPage->Append(pNotebook);\r
-       pPage = new CBackgroundDialogPage(XZ);\r
-       pPage->Append(pNotebook);\r
-       pPage = new CBackgroundDialogPage(YZ);\r
-       pPage->Append(pNotebook);\r
-\r
-       gtk_box_pack_start (GTK_BOX (GTK_DIALOG(pDialogWnd)->vbox), pNotebook, TRUE, TRUE, 0);\r
-\r
-  gtk_widget_show ( pNotebook );\r
-       \r
-       gtk_widget_realize( pDialogWnd );\r
-}\r
-\r
-void ShowBackgroundDialog()\r
-{\r
-       gtk_window_present( GTK_WINDOW(pDialogWnd) );\r
-}\r
-\r
-void ShowBackgroundDialogPG(int page)\r
-{\r
-       gtk_notebook_set_current_page(GTK_NOTEBOOK(pNotebook),page);\r
-       ShowBackgroundDialog();\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 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
+*/
+
+//
+// bkgrnd2d Plugin dialog
+//
+// Code by reyalP aka Reed Mideke
+//
+// Based on various other plugins
+//
+
+#include <gtk/gtk.h>
+
+#include "bkgrnd2d.h"
+#include "dialog.h"
+
+// spaces to make label nice and big
+#define NO_FILE_MSG "        (no file loaded)        "
+
+static GtkWidget *pDialogWnd;
+static GtkWidget *pNotebook;
+static GtkTooltips *pTooltips;
+
+class CBackgroundDialogPage
+{
+private:
+       GtkWidget *m_pWidget;
+       GtkWidget *m_pTabLabel;
+       GtkWidget *m_pFileLabel;
+       GtkWidget *m_pPosLabel;
+       VIEWTYPE m_vt;
+       bool m_bValidFile;
+
+public:
+       CBackgroundImage *m_pImage;
+       CBackgroundDialogPage( VIEWTYPE vt );
+       void Append(GtkWidget *notebook);
+       void Browse();
+       void Reload();
+       void SetPosLabel();
+//  ~BackgroundDialogPage();
+};
+
+
+// dialog page callbacks
+static void browse_callback( GtkWidget *widget, gpointer data )
+{
+       ((CBackgroundDialogPage *)data)->Browse();
+}
+
+static void reload_callback( GtkWidget *widget, gpointer data )
+{
+       ((CBackgroundDialogPage *)data)->Reload();
+}
+
+static void size_sel_callback( GtkWidget *widget, gpointer data )
+{
+       CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;
+       if (pPage->m_pImage->SetExtentsSel())
+               pPage->SetPosLabel();
+}
+
+static void size_mm_callback( GtkWidget *widget, gpointer data )
+{
+       CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;
+       if(pPage->m_pImage->SetExtentsMM())
+               pPage->SetPosLabel();
+}
+
+static void alpha_adjust_callback( GtkWidget *widget, gpointer data )
+{
+       CBackgroundDialogPage *pPage = (CBackgroundDialogPage *)data;
+       pPage->m_pImage->m_alpha = (float)gtk_range_get_value (GTK_RANGE(widget));
+       g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+}
+
+void CBackgroundDialogPage::Reload()
+{
+       if(m_bValidFile)
+               m_pImage->Load(gtk_label_get_text(GTK_LABEL(m_pFileLabel)));
+}
+
+void CBackgroundDialogPage::Browse()
+{
+       char browsedir[PATH_MAX];
+       const char *ct;
+       const char *newfile;
+       char *t;
+       
+       //TODO GetMapName saves the map. eeep!
+       //also with no map, returns unnamed.map, otherwise returns full path
+//     Syn_Printf(MSG_PREFIX "GetMapName() %s\n",
+//                             g_FuncTable.m_pfnGetMapName());
+       
+       ct = g_FuncTable.m_pfnReadProjectKey("basepath");
+       // TODO shouldn't need this stuff
+       if(!ct || !strlen(ct)) {
+               Syn_Printf(MSG_PREFIX "basepath = NULL or empty\n");
+               return;
+       }
+       Syn_Printf(MSG_PREFIX "basepath: %s\n",ct);
+       if(strlen(ct) >= PATH_MAX) {
+               Syn_Printf(MSG_PREFIX "base game dir too long\n");
+               return;
+       }
+
+       strcpy(browsedir,ct);
+       // make sure we have a trailing / 
+       if(browsedir[strlen(browsedir) - 1] != '/')
+               strcat(browsedir,"/");
+
+       //if we dont have a file yet, don't try to use it for default dir
+       if(m_bValidFile) {
+       // filename should always be a nice clean unix style relative path
+               ct = gtk_label_get_text(GTK_LABEL(m_pFileLabel));
+               strcat(browsedir,ct);
+               Syn_Printf(MSG_PREFIX "full path: %s\n",browsedir);
+
+               // lop off the file part
+               t = browsedir + strlen(browsedir) - 1;
+               while (t != browsedir && *t != '/') 
+                       t--;
+               *t = 0;
+       }
+       Syn_Printf(MSG_PREFIX "browse directory %s\n",browsedir);
+       
+//does NOT need freeing contrary to include/qerplugin.h comments
+//TODO bug/patch for comments
+//TODO patern gets fucked up sometimes if empty
+//http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=915
+       newfile = g_FuncTable.m_pfnFileDialog(pDialogWnd,TRUE,
+                                                                 "Load Background Image",browsedir,FILETYPE_KEY);
+       if(!newfile) {
+               Syn_Printf(MSG_PREFIX "newfile = NULL\n");
+               return;
+       }
+       Syn_Printf(MSG_PREFIX "newfile: %s\n",newfile);
+       newfile = g_FileSystemTable.m_pfnExtractRelativePath(newfile);
+
+       if(!newfile) {
+               Syn_Printf(MSG_PREFIX "newfile = NULL\n");
+               return;
+       }
+       Syn_Printf(MSG_PREFIX "newfile: %s\n",newfile);
+
+       if(m_pImage->Load(newfile)) {
+               m_bValidFile = true;
+               gtk_label_set_text(GTK_LABEL(m_pFileLabel),newfile);
+       }
+}
+
+void CBackgroundDialogPage::SetPosLabel()
+{
+       char s[64];
+       // TODO no snprintf ?
+       sprintf(s, "Size/Position (%d,%d) (%d,%d)",(int)(m_pImage->m_xmin),
+                       (int)(m_pImage->m_ymin),(int)(m_pImage->m_xmax),(int)(m_pImage->m_ymax));
+       gtk_label_set_text(GTK_LABEL(m_pPosLabel),s);
+}
+
+CBackgroundDialogPage::CBackgroundDialogPage(VIEWTYPE vt )
+{
+       GtkWidget *frame;
+       GtkWidget *hbox;
+       GtkWidget *w;
+
+       m_vt = vt;
+
+       m_bValidFile = false;
+
+       switch(m_vt)
+       {
+               case XY:
+                       m_pTabLabel = gtk_label_new("X/Y");
+                       m_pImage = &backgroundXY;
+                       break;
+               case XZ:
+                       m_pTabLabel = gtk_label_new("X/Z");
+                       m_pImage = &backgroundXZ;
+                       break;
+               case YZ:
+                       m_pTabLabel = gtk_label_new("Y/Z");
+                       m_pImage = &backgroundYZ;
+                       break;
+       }
+// A vbox to hold everything
+       m_pWidget = gtk_vbox_new(FALSE,0); 
+// Frame for file row
+       frame = gtk_frame_new("File");
+       gtk_box_pack_start (GTK_BOX (m_pWidget),frame, FALSE, FALSE, 2);
+
+// hbox for first row
+       hbox = gtk_hbox_new(FALSE,5);
+       gtk_container_set_border_width(GTK_CONTAINER (hbox),4);
+       gtk_container_add (GTK_CONTAINER (frame), hbox);
+
+// label to display filename
+       m_pFileLabel  = gtk_label_new(NO_FILE_MSG);
+       gtk_label_set_selectable(GTK_LABEL(m_pFileLabel),TRUE);
+//TODO set min size ? done with spaces right now
+       gtk_box_pack_start (GTK_BOX (hbox),m_pFileLabel, TRUE, TRUE, 5);
+
+  gtk_widget_show (m_pFileLabel);
+
+       w = gtk_button_new_with_label ("Browse...");
+       g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (browse_callback),
+                                                              (gpointer)this);
+       gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);
+       gtk_tooltips_set_tip (pTooltips, w, "Select a file", NULL);
+  gtk_widget_show (w);
+       
+       w = gtk_button_new_with_label ("Reload");
+       g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (reload_callback),
+                                                              (gpointer)this);
+       // TODO disable until we have file
+       // gtk_widget_set_sensitive(w,FALSE);
+       gtk_tooltips_set_tip (pTooltips, w, "Reload current file", NULL);
+       gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);
+  gtk_widget_show (w);
+
+       gtk_widget_show (hbox);
+       gtk_widget_show (frame);
+
+// second row (rendering options)
+       frame = gtk_frame_new("Rendering");
+       gtk_box_pack_start (GTK_BOX (m_pWidget),frame, FALSE, FALSE, 2);
+
+       hbox = gtk_hbox_new(FALSE,5);
+       gtk_container_set_border_width(GTK_CONTAINER (hbox),4);
+       gtk_container_add (GTK_CONTAINER (frame), hbox);
+
+       w = gtk_label_new("Vertex alpha:");
+       gtk_box_pack_start (GTK_BOX (hbox),w, FALSE, FALSE, 5);
+  gtk_widget_show (w);
+
+       w = gtk_hscale_new_with_range(0.0,1.0,0.01);
+       gtk_range_set_value(GTK_RANGE(w),0.5);
+       gtk_scale_set_value_pos(GTK_SCALE(w),GTK_POS_LEFT);
+       g_signal_connect (G_OBJECT (w), "value-changed",
+                          G_CALLBACK (alpha_adjust_callback), (gpointer)this);
+       gtk_box_pack_start (GTK_BOX (hbox),w, TRUE, TRUE, 5);
+       gtk_tooltips_set_tip (pTooltips, w, "Set image transparancy", NULL);
+  gtk_widget_show (w);
+
+       gtk_widget_show (hbox);
+       gtk_widget_show (frame);
+// Third row (size and position)
+       frame = gtk_frame_new("Size/Position (undefined)");
+       m_pPosLabel = gtk_frame_get_label_widget (GTK_FRAME(frame));
+       gtk_box_pack_start ( GTK_BOX (m_pWidget), frame, FALSE, FALSE, 2);
+
+       hbox = gtk_hbox_new(FALSE,5);
+       gtk_container_add (GTK_CONTAINER (frame), hbox);
+       gtk_container_set_border_width(GTK_CONTAINER (hbox),4);
+
+       w = gtk_button_new_with_label ("from selection");
+       gtk_box_pack_start (GTK_BOX (hbox),w, TRUE, FALSE, 5);
+       g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (size_sel_callback),
+                                                                (gpointer)this);
+       gtk_tooltips_set_tip (pTooltips, w, "Set the size of the image to the bounding rectangle of all selected brushes and entities", NULL);
+  gtk_widget_show (w);
+
+       if(m_vt == XY) {
+               w = gtk_button_new_with_label ("from map mins/maxs");
+               gtk_box_pack_start ( GTK_BOX (hbox),w, TRUE, FALSE, 2);
+               g_signal_connect (G_OBJECT (w), "clicked", G_CALLBACK (size_mm_callback),
+                                                                (gpointer)this);
+               gtk_tooltips_set_tip (pTooltips, w, "Set the size of the image using the mapcoordsmins and mapcoordsmaxs keys of the worldspawn entity", NULL);
+               gtk_widget_show (w);
+       }
+
+       gtk_widget_show (hbox);
+       gtk_widget_show (frame);
+
+  gtk_widget_show ( m_pWidget );
+}
+
+void CBackgroundDialogPage::Append(GtkWidget *notebook)
+{
+       gtk_notebook_append_page( GTK_NOTEBOOK(notebook), m_pWidget, m_pTabLabel);
+}
+
+// dialog global callbacks
+/*
+static gint expose_callback( GtkWidget *widget, gpointer data )
+{
+       return FALSE;
+}
+*/
+
+static void response_callback( GtkWidget *widget, gint response, gpointer data )
+{
+       if( response == GTK_RESPONSE_CLOSE )
+               gtk_widget_hide( pDialogWnd );
+}
+
+static gint close_callback( GtkWidget *widget, gpointer data )
+{
+       gtk_widget_hide( pDialogWnd );
+       return TRUE;
+}
+
+void InitBackgroundDialog()
+{
+       CBackgroundDialogPage *pPage;
+
+       pDialogWnd = gtk_dialog_new_with_buttons ("Background Images",
+                              GTK_WINDOW(g_pMainWidget),
+                              (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT),
+        // TODO dialog with no buttons
+        //                                                                               GTK_STOCK_CLOSE,
+        //                                                                               GTK_RESPONSE_CLOSE,
+                              NULL);
+       gtk_signal_connect( GTK_OBJECT (pDialogWnd), "delete_event",
+                                    GTK_SIGNAL_FUNC( close_callback ), NULL );
+       gtk_signal_connect( GTK_OBJECT (pDialogWnd), "response",
+                                  GTK_SIGNAL_FUNC( response_callback ), NULL );
+//     gtk_signal_connect( GTK_OBJECT (pDialogWnd), "expose_event", GTK_SIGNAL_FUNC( ci_expose ), NULL );
+
+       pTooltips = gtk_tooltips_new();
+
+       pNotebook = gtk_notebook_new();
+       pPage = new CBackgroundDialogPage(XY);
+       pPage->Append(pNotebook);
+       pPage = new CBackgroundDialogPage(XZ);
+       pPage->Append(pNotebook);
+       pPage = new CBackgroundDialogPage(YZ);
+       pPage->Append(pNotebook);
+
+       gtk_box_pack_start (GTK_BOX (GTK_DIALOG(pDialogWnd)->vbox), pNotebook, TRUE, TRUE, 0);
+
+  gtk_widget_show ( pNotebook );
+       
+       gtk_widget_realize( pDialogWnd );
+}
+
+void ShowBackgroundDialog()
+{
+       gtk_window_present( GTK_WINDOW(pDialogWnd) );
+}
+
+void ShowBackgroundDialogPG(int page)
+{
+       gtk_notebook_set_current_page(GTK_NOTEBOOK(pNotebook),page);
+       ShowBackgroundDialog();
+}
+
index 56150e3..25a1c3f 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-//\r
-// 2d background Plugin\r
-//\r
-// Code by reyalP aka Reed Mideke\r
-//\r
-// Based on \r
-//\r
-\r
-/*\r
-    Overview\r
-    ========\r
-       This little plugin allows you to display an image in the background of the\r
-       gtkradiant XY window.\r
-\r
-    Version History\r
-    ===============\r
-\r
-    v0.1\r
-      - Initial version.\r
-       v0.2\r
-         - three views, dialog box, toolbar\r
-    v0.25\r
-      - tooltips, follow gtkradiant coding conventions\r
-\r
-    Why ?\r
-    -----\r
-      http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=88\r
-\r
-\r
-    How ?\r
-    -----\r
-     - textures 'n widgets 'n stuff.\r
-*/\r
-\r
-//#include "plugin.h"\r
-//TODO we just poke the objects directly\r
-#include "bkgrnd2d.h"\r
-#include "dialog.h"\r
-\r
-#define CMD_SEP "-" \r
-#define CMD_CONFIG "Configure..."\r
-#define CMD_ABOUT "About..."\r
-// =============================================================================\r
-// Globals\r
-\r
-// function tables\r
-_QERFuncTable_1 g_FuncTable;\r
-_QERQglTable g_QglTable;\r
-_QERFileSystemTable g_FileSystemTable;\r
-_QEREntityTable g_EntityTable;\r
-_QERAppDataTable g_DataTable;\r
-\r
-// for the file load dialog\r
-void *g_pMainWidget;\r
-\r
-// =============================================================================\r
-// plugin implementation\r
-\r
-static const char *PLUGIN_NAME = "2d window background plugin";\r
-\r
-//backwards for some reason\r
-static const char *PLUGIN_COMMANDS = CMD_ABOUT ";" \r
-                                     CMD_SEP ";"\r
-                                                                                        CMD_CONFIG\r
-                                     ;\r
-\r
-static const char *PLUGIN_ABOUT = "2d window background v0.25\n\n"\r
-                                  "By reyalP (hellsownpuppy@yahoo.com)";\r
-\r
-\r
-\r
-\r
-void DoBkgrndToggleXY();\r
-void DoBkgrndToggleXZ();\r
-void DoBkgrndToggleYZ();\r
-\r
-#define NUM_TOOLBAR_BUTTONS 4\r
-struct toolbar_button_info_s\r
-{\r
-       char *image;\r
-       char *text;\r
-       char *tip;\r
-       void (*func)();\r
-       IToolbarButton::EType type;\r
-};\r
-\r
-struct toolbar_button_info_s toolbar_buttons[NUM_TOOLBAR_BUTTONS] = \r
-{\r
-       {\r
-               "bkgrnd2d_xy_toggle.bmp",\r
-               "xy background",\r
-    "Toggle xy background image",\r
-               DoBkgrndToggleXY,\r
-               IToolbarButton::eToggleButton\r
-       },\r
-       {\r
-               "bkgrnd2d_xz_toggle.bmp",\r
-               "xz background",\r
-    "Toggle xz background image",\r
-               DoBkgrndToggleXZ,\r
-               IToolbarButton::eToggleButton\r
-       },\r
-       {\r
-               "bkgrnd2d_yz_toggle.bmp",\r
-               "yz background",\r
-    "Toggle yz background image",\r
-               DoBkgrndToggleYZ,\r
-               IToolbarButton::eToggleButton\r
-       },\r
-       {\r
-               "bkgrnd2d_conf.bmp",\r
-               "Configure",\r
-    "Configure background images",\r
-               ShowBackgroundDialog,\r
-               IToolbarButton::eButton\r
-       },\r
-};\r
-\r
-class Bkgrnd2dButton : public IToolbarButton\r
-{\r
-public:\r
-  const toolbar_button_info_s *bi;\r
-  virtual const char* getImage() const\r
-  {\r
-    return bi->image;\r
-  }\r
-  virtual const char* getText() const\r
-  {\r
-    return bi->text;\r
-  }\r
-  virtual const char* getTooltip() const\r
-  {\r
-    return bi->tip;\r
-  }\r
-  virtual void activate() const\r
-  {\r
-    bi->func();\r
-    return ;\r
-  }\r
-  virtual EType getType() const\r
-  {\r
-    return bi->type;\r
-  }\r
-};\r
-\r
-Bkgrnd2dButton g_bkgrnd2dbuttons[NUM_TOOLBAR_BUTTONS];\r
-\r
-unsigned int ToolbarButtonCount()\r
-{\r
-  return NUM_TOOLBAR_BUTTONS;\r
-}\r
-\r
-const IToolbarButton* GetToolbarButton(unsigned int index)\r
-{\r
-  g_bkgrnd2dbuttons[index].bi = &toolbar_buttons[index];\r
-  return &g_bkgrnd2dbuttons[index];\r
-}\r
-\r
-extern "C" const char* QERPlug_Init (void *hApp, void* pMainWidget)\r
-{\r
-  g_pMainWidget = pMainWidget;\r
-\r
-  InitBackgroundDialog();\r
-  render.Register();\r
-\r
-//TODO is it right ? is it wrong ? it works\r
-//TODO figure out supported image types\r
-  GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("all files", "*.*"));\r
-  GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("jpeg files", "*.jpg"));\r
-  GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("targa files", "*.tga"));\r
-  return (char *) PLUGIN_NAME;\r
-}\r
-\r
-extern "C" const char* QERPlug_GetName ()\r
-{\r
-  return (char *) PLUGIN_NAME;\r
-}\r
-\r
-extern "C" const char* QERPlug_GetCommandList ()\r
-{\r
-  return (char *) PLUGIN_COMMANDS;\r
-}\r
-\r
-extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)\r
-{\r
-  Sys_Printf (MSG_PREFIX "Command \"%s\"\n",p); \r
-  if(!strcmp(p, CMD_ABOUT)) {\r
-       g_FuncTable.m_pfnMessageBox(NULL, PLUGIN_ABOUT, "About", MB_OK, NULL);\r
-  } \r
-  else if(!strcmp(p,CMD_CONFIG)) {\r
-       ShowBackgroundDialog();\r
-  }\r
-}\r
-\r
-//TODO these three suck\r
-void DoBkgrndToggleXY()\r
-{\r
-  Sys_Printf (MSG_PREFIX "DoBkgrndToggleXY\n"); \r
-  // always toggle, since the buttons do\r
-  backgroundXY.m_bActive = (backgroundXY.m_bActive) ? false:true;\r
-  // if we don't have image or extents, and we activated,\r
-  // bring up the dialog with the corresponding page\r
-  // would be better to hide or grey out button, but we can't\r
-  if(backgroundXY.m_bActive && !backgroundXY.Valid())\r
-         ShowBackgroundDialogPG(0);\r
-  else\r
-         g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-}\r
-\r
-void DoBkgrndToggleXZ()\r
-{\r
-  Sys_Printf (MSG_PREFIX "DoBkgrndToggleXZ\n"); \r
-  backgroundXZ.m_bActive = (backgroundXZ.m_bActive) ? false:true;\r
-  if(backgroundXZ.m_bActive && !backgroundXZ.Valid())\r
-         ShowBackgroundDialogPG(1);\r
-  else\r
-         g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-}\r
-\r
-void DoBkgrndToggleYZ()\r
-{\r
-  Sys_Printf (MSG_PREFIX "DoBkgrndToggleYZ\n"); \r
-  backgroundYZ.m_bActive = (backgroundYZ.m_bActive) ? false:true;\r
-  if(backgroundYZ.m_bActive && !backgroundYZ.Valid())\r
-         ShowBackgroundDialogPG(2);\r
-  else\r
-         g_FuncTable.m_pfnSysUpdateWindows(W_XY);\r
-}\r
-\r
-// =============================================================================\r
-// SYNAPSE\r
-\r
-CSynapseServer* g_pSynapseServer = NULL;\r
-CSynapseClientBkgrnd2d g_SynapseClient;\r
-    \r
-extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces (const char *version, CSynapseServer *pServer)\r
-{\r
-  if (strcmp(version, SYNAPSE_VERSION))\r
-  {\r
-    Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);\r
-    return NULL;\r
-  }\r
-  g_pSynapseServer = pServer;\r
-  g_pSynapseServer->IncRef();\r
-  Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());\r
-\r
-  g_SynapseClient.AddAPI(TOOLBAR_MAJOR, BKGRND2D_MINOR, sizeof(_QERPlugToolbarTable));\r
-  g_SynapseClient.AddAPI(PLUGIN_MAJOR, BKGRND2D_MINOR, sizeof( _QERPluginTable ) );\r
-\r
-  g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable );\r
-  g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( g_QglTable ), SYN_REQUIRE, &g_QglTable );\r
-// TODO is this the right way to ask for 'whichever VFS we have loaded' ? Seems to work\r
-// for misc filename functions\r
-  g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );\r
-// get worldspawn\r
-  g_SynapseClient.AddAPI( ENTITY_MAJOR, NULL, sizeof( g_EntityTable ), SYN_REQUIRE, &g_EntityTable );\r
-// selected brushes\r
-  g_SynapseClient.AddAPI( DATA_MAJOR, NULL, sizeof( g_DataTable ), SYN_REQUIRE, &g_DataTable );\r
-\r
-  return &g_SynapseClient;\r
-}\r
-\r
-bool CSynapseClientBkgrnd2d::RequestAPI(APIDescriptor_t *pAPI)\r
-{\r
-  if (!strcmp(pAPI->major_name, PLUGIN_MAJOR))\r
-  {\r
-    _QERPluginTable* pTable= static_cast<_QERPluginTable*>(pAPI->mpTable);\r
-\r
-    pTable->m_pfnQERPlug_Init = QERPlug_Init;\r
-    pTable->m_pfnQERPlug_GetName = QERPlug_GetName;\r
-    pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;\r
-    pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;\r
-    return true;\r
-  }\r
-  if (!strcmp(pAPI->major_name, TOOLBAR_MAJOR))\r
-  {\r
-    _QERPlugToolbarTable* pTable= static_cast<_QERPlugToolbarTable*>(pAPI->mpTable);\r
-\r
-    pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount;\r
-    pTable->m_pfnGetToolbarButton = &GetToolbarButton;\r
-    return true;\r
-  }\r
-\r
-  Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());\r
-  return false;\r
-}\r
-\r
-#include "version.h"\r
-\r
-const char* CSynapseClientBkgrnd2d::GetInfo()\r
-{\r
-  return "2d Background plugin built " __DATE__ " " RADIANT_VERSION;\r
-}\r
-\r
-const char* CSynapseClientBkgrnd2d::GetName()\r
-{\r
-  return "bkgrnd2d";\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 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
+*/
+
+//
+// 2d background Plugin
+//
+// Code by reyalP aka Reed Mideke
+//
+// Based on 
+//
+
+/*
+    Overview
+    ========
+       This little plugin allows you to display an image in the background of the
+       gtkradiant XY window.
+
+    Version History
+    ===============
+
+    v0.1
+      - Initial version.
+       v0.2
+         - three views, dialog box, toolbar
+    v0.25
+      - tooltips, follow gtkradiant coding conventions
+
+    Why ?
+    -----
+      http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=88
+
+
+    How ?
+    -----
+     - textures 'n widgets 'n stuff.
+*/
+
+//#include "plugin.h"
+//TODO we just poke the objects directly
+#include "bkgrnd2d.h"
+#include "dialog.h"
+
+#define CMD_SEP "-" 
+#define CMD_CONFIG "Configure..."
+#define CMD_ABOUT "About..."
+// =============================================================================
+// Globals
+
+// function tables
+_QERFuncTable_1 g_FuncTable;
+_QERQglTable g_QglTable;
+_QERFileSystemTable g_FileSystemTable;
+_QEREntityTable g_EntityTable;
+_QERAppDataTable g_DataTable;
+
+// for the file load dialog
+void *g_pMainWidget;
+
+// =============================================================================
+// plugin implementation
+
+static const char *PLUGIN_NAME = "2d window background plugin";
+
+//backwards for some reason
+static const char *PLUGIN_COMMANDS = CMD_ABOUT ";" 
+                                     CMD_SEP ";"
+                                                                                        CMD_CONFIG
+                                     ;
+
+static const char *PLUGIN_ABOUT = "2d window background v0.25\n\n"
+                                  "By reyalP (hellsownpuppy@yahoo.com)";
+
+
+
+
+void DoBkgrndToggleXY();
+void DoBkgrndToggleXZ();
+void DoBkgrndToggleYZ();
+
+#define NUM_TOOLBAR_BUTTONS 4
+struct toolbar_button_info_s
+{
+       char *image;
+       char *text;
+       char *tip;
+       void (*func)();
+       IToolbarButton::EType type;
+};
+
+struct toolbar_button_info_s toolbar_buttons[NUM_TOOLBAR_BUTTONS] = 
+{
+       {
+               "bkgrnd2d_xy_toggle.bmp",
+               "xy background",
+    "Toggle xy background image",
+               DoBkgrndToggleXY,
+               IToolbarButton::eToggleButton
+       },
+       {
+               "bkgrnd2d_xz_toggle.bmp",
+               "xz background",
+    "Toggle xz background image",
+               DoBkgrndToggleXZ,
+               IToolbarButton::eToggleButton
+       },
+       {
+               "bkgrnd2d_yz_toggle.bmp",
+               "yz background",
+    "Toggle yz background image",
+               DoBkgrndToggleYZ,
+               IToolbarButton::eToggleButton
+       },
+       {
+               "bkgrnd2d_conf.bmp",
+               "Configure",
+    "Configure background images",
+               ShowBackgroundDialog,
+               IToolbarButton::eButton
+       },
+};
+
+class Bkgrnd2dButton : public IToolbarButton
+{
+public:
+  const toolbar_button_info_s *bi;
+  virtual const char* getImage() const
+  {
+    return bi->image;
+  }
+  virtual const char* getText() const
+  {
+    return bi->text;
+  }
+  virtual const char* getTooltip() const
+  {
+    return bi->tip;
+  }
+  virtual void activate() const
+  {
+    bi->func();
+    return ;
+  }
+  virtual EType getType() const
+  {
+    return bi->type;
+  }
+};
+
+Bkgrnd2dButton g_bkgrnd2dbuttons[NUM_TOOLBAR_BUTTONS];
+
+unsigned int ToolbarButtonCount()
+{
+  return NUM_TOOLBAR_BUTTONS;
+}
+
+const IToolbarButton* GetToolbarButton(unsigned int index)
+{
+  g_bkgrnd2dbuttons[index].bi = &toolbar_buttons[index];
+  return &g_bkgrnd2dbuttons[index];
+}
+
+extern "C" const char* QERPlug_Init (void *hApp, void* pMainWidget)
+{
+  g_pMainWidget = pMainWidget;
+
+  InitBackgroundDialog();
+  render.Register();
+
+//TODO is it right ? is it wrong ? it works
+//TODO figure out supported image types
+  GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("all files", "*.*"));
+  GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("jpeg files", "*.jpg"));
+  GetFileTypeRegistry()->addType(FILETYPE_KEY, filetype_t("targa files", "*.tga"));
+  return (char *) PLUGIN_NAME;
+}
+
+extern "C" const char* QERPlug_GetName ()
+{
+  return (char *) PLUGIN_NAME;
+}
+
+extern "C" const char* QERPlug_GetCommandList ()
+{
+  return (char *) PLUGIN_COMMANDS;
+}
+
+extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)
+{
+  Sys_Printf (MSG_PREFIX "Command \"%s\"\n",p); 
+  if(!strcmp(p, CMD_ABOUT)) {
+       g_FuncTable.m_pfnMessageBox(NULL, PLUGIN_ABOUT, "About", MB_OK, NULL);
+  } 
+  else if(!strcmp(p,CMD_CONFIG)) {
+       ShowBackgroundDialog();
+  }
+}
+
+//TODO these three suck
+void DoBkgrndToggleXY()
+{
+  Sys_Printf (MSG_PREFIX "DoBkgrndToggleXY\n"); 
+  // always toggle, since the buttons do
+  backgroundXY.m_bActive = (backgroundXY.m_bActive) ? false:true;
+  // if we don't have image or extents, and we activated,
+  // bring up the dialog with the corresponding page
+  // would be better to hide or grey out button, but we can't
+  if(backgroundXY.m_bActive && !backgroundXY.Valid())
+         ShowBackgroundDialogPG(0);
+  else
+         g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+}
+
+void DoBkgrndToggleXZ()
+{
+  Sys_Printf (MSG_PREFIX "DoBkgrndToggleXZ\n"); 
+  backgroundXZ.m_bActive = (backgroundXZ.m_bActive) ? false:true;
+  if(backgroundXZ.m_bActive && !backgroundXZ.Valid())
+         ShowBackgroundDialogPG(1);
+  else
+         g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+}
+
+void DoBkgrndToggleYZ()
+{
+  Sys_Printf (MSG_PREFIX "DoBkgrndToggleYZ\n"); 
+  backgroundYZ.m_bActive = (backgroundYZ.m_bActive) ? false:true;
+  if(backgroundYZ.m_bActive && !backgroundYZ.Valid())
+         ShowBackgroundDialogPG(2);
+  else
+         g_FuncTable.m_pfnSysUpdateWindows(W_XY);
+}
+
+// =============================================================================
+// SYNAPSE
+
+CSynapseServer* g_pSynapseServer = NULL;
+CSynapseClientBkgrnd2d 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(TOOLBAR_MAJOR, BKGRND2D_MINOR, sizeof(_QERPlugToolbarTable));
+  g_SynapseClient.AddAPI(PLUGIN_MAJOR, BKGRND2D_MINOR, sizeof( _QERPluginTable ) );
+
+  g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( g_FuncTable ), SYN_REQUIRE, &g_FuncTable );
+  g_SynapseClient.AddAPI( QGL_MAJOR, NULL, sizeof( g_QglTable ), SYN_REQUIRE, &g_QglTable );
+// TODO is this the right way to ask for 'whichever VFS we have loaded' ? Seems to work
+// for misc filename functions
+  g_SynapseClient.AddAPI( VFS_MAJOR, "*", sizeof( g_FileSystemTable ), SYN_REQUIRE, &g_FileSystemTable );
+// get worldspawn
+  g_SynapseClient.AddAPI( ENTITY_MAJOR, NULL, sizeof( g_EntityTable ), SYN_REQUIRE, &g_EntityTable );
+// selected brushes
+  g_SynapseClient.AddAPI( DATA_MAJOR, NULL, sizeof( g_DataTable ), SYN_REQUIRE, &g_DataTable );
+
+  return &g_SynapseClient;
+}
+
+bool CSynapseClientBkgrnd2d::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;
+  }
+  if (!strcmp(pAPI->major_name, TOOLBAR_MAJOR))
+  {
+    _QERPlugToolbarTable* pTable= static_cast<_QERPlugToolbarTable*>(pAPI->mpTable);
+
+    pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount;
+    pTable->m_pfnGetToolbarButton = &GetToolbarButton;
+    return true;
+  }
+
+  Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
+  return false;
+}
+
+#include "version.h"
+
+const char* CSynapseClientBkgrnd2d::GetInfo()
+{
+  return "2d Background plugin built " __DATE__ " " RADIANT_VERSION;
+}
+
+const char* CSynapseClientBkgrnd2d::GetName()
+{
+  return "bkgrnd2d";
+}
+
index 74fdacd..4721510 100644 (file)
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// BobView.cpp: implementation of the DBobView class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-#include "DBobView.h"\r
-#include "DListener.h"\r
-#include "misc.h"\r
-#include "funchandlers.h"\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DBobView::DBobView()\r
-{\r
-       nPathCount = 0;\r
-       refCount = 1;\r
-       \r
-       m_bHooked = FALSE;\r
-\r
-       path = NULL;\r
-       eyes = NULL;\r
-\r
-       boundingShow = BOUNDS_APEX;\r
-}\r
-\r
-DBobView::~DBobView()\r
-{\r
-       if(path)\r
-               delete[] path;\r
-\r
-       // oops forgot to remove our eyes, was causing access violation when it tried\r
-       // to talk to it's parent\r
-       if(eyes)\r
-               delete eyes;\r
-\r
-       if(m_bHooked)\r
-               UnRegister();\r
-\r
-       g_PathView = NULL;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Implementation\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void DBobView::Draw2D(VIEWTYPE vt)\r
-{\r
-       if(!path)\r
-               return;\r
-\r
-       g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);\r
-\r
-       g_QglTable.m_pfn_qglDisable(GL_BLEND);\r
-       g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);\r
-\r
-       g_QglTable.m_pfn_qglPushMatrix();\r
-       \r
-       switch(vt)\r
-       {\r
-       case XY:\r
-               break;\r
-       case XZ:\r
-               g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);\r
-               break;\r
-       case YZ:\r
-               g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);\r
-               g_QglTable.m_pfn_qglRotatef(270.0f, 0.0f, 0.0f, 1.0f);\r
-               break;\r
-       }\r
-\r
-       g_QglTable.m_pfn_qglLineWidth(1.0f);\r
-       g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 1.0f);\r
-\r
-       int i;\r
-\r
-       g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP);\r
-\r
-       for(i = 0; i < nPathCount; i++)\r
-               g_QglTable.m_pfn_qglVertex3fv(path[i]);\r
-\r
-       g_QglTable.m_pfn_qglEnd();\r
-\r
-       if(m_bShowExtra)\r
-       {\r
-               // +mars\r
-               // for the bounding box stuff\r
-               g_QglTable.m_pfn_qglColor4f(0.25f, 0.75f, 0.75f, 1.0f);\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( 16.0f, 16.0f, 28.0f );\r
-\r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-       \r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-       \r
-       // ---------------\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );       // back to where we were\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // move to new postion\r
-       \r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-\r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-\r
-       // --------------\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // back to where we were\r
-               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // new pos\r
-\r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-               \r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-\r
-       // ----------------\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // back to where we were\r
-\r
-/*             g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );               // new pos\r
-\r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-               \r
-               if ( boundingShow == BOUNDS_ALL )\r
-               {\r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-               }\r
-               else if ( boundingShow == BOUNDS_APEX )\r
-               {\r
-                       for ( i = (nPathCount/4); i < (nPathCount/4) * 3; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-               }\r
-\r
-               g_QglTable.m_pfn_qglEnd();*/ // djbob: er, um doesn't really seem to do anyhting\r
-       }\r
-\r
-       // -mars\r
-       \r
-       g_QglTable.m_pfn_qglPopMatrix();\r
-\r
-       g_QglTable.m_pfn_qglPopAttrib();\r
-}\r
-\r
-void DBobView::Draw3D()\r
-{\r
-       if(!path)\r
-               return;\r
-\r
-       g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);\r
-\r
-       g_QglTable.m_pfn_qglDisable(GL_BLEND);\r
-       g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);\r
-\r
-       g_QglTable.m_pfn_qglLineWidth(1.0f);\r
-       g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 1.0f);\r
-\r
-       g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP);\r
-\r
-       for(int i = 0; i < nPathCount; i++)\r
-               g_QglTable.m_pfn_qglVertex3fv(path[i]);\r
-\r
-       g_QglTable.m_pfn_qglEnd();\r
-\r
-       if(m_bShowExtra)\r
-       {\r
-               // +mars\r
-               // ahhh -- a nice C&P job :)\r
-               // for the bounding box stuff\r
-               g_QglTable.m_pfn_qglColor4f(0.25f, 0.75f, 0.75f, 1.0f);\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( 16.0f, 16.0f, 28.0f );\r
-\r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-               \r
-               int i;  \r
-               for ( i = 0; i < nPathCount; i++ )\r
-                       g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-       \r
-       // ---------------\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );       // back to where we were\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // move to new postion\r
-       \r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-               \r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-\r
-       // --------------\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // back to where we were\r
-               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // new pos\r
-\r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-               \r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-\r
-       // ----------------\r
-\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // back to where we were\r
-               g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );               // new pos\r
-\r
-               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );\r
-               \r
-                       for ( i = 0; i < nPathCount; i++ )\r
-                               g_QglTable.m_pfn_qglVertex3fv( path[i] );\r
-\r
-               g_QglTable.m_pfn_qglEnd();\r
-       }\r
-       // -mars\r
-\r
-       g_QglTable.m_pfn_qglPopAttrib();\r
-}\r
-\r
-void DBobView::Register()\r
-{\r
-       g_QglTable.m_pfnHookGL2DWindow( this );\r
-       g_QglTable.m_pfnHookGL3DWindow( this );\r
-       m_bHooked = TRUE;\r
-}\r
-\r
-void DBobView::UnRegister()\r
-{\r
-       g_QglTable.m_pfnUnHookGL2DWindow( this );\r
-       g_QglTable.m_pfnUnHookGL3DWindow( this );\r
-       m_bHooked = FALSE;\r
-}\r
-\r
-void DBobView::SetPath(vec3_t *pPath)\r
-{\r
-       if(path)\r
-               delete[] path;\r
-\r
-       path = pPath;\r
-}\r
-\r
-#define LOCAL_GRAVITY -800.0f\r
-\r
-bool DBobView::CalculateTrajectory(vec3_t start, vec3_t apex, float multiplier, int points, float varGravity)\r
-{\r
-       if(apex[2] <= start[2])\r
-       {\r
-               SetPath(NULL);\r
-               return FALSE;\r
-       }\r
-       // ----think q3a actually would allow these\r
-       //scrub that, coz the plugin wont :]\r
-\r
-       vec3_t dist, speed;\r
-       VectorSubtract(apex, start, dist);\r
-\r
-       vec_t speed_z = (float)sqrt(-2*LOCAL_GRAVITY*dist[2]);\r
-       float flight_time = -speed_z/LOCAL_GRAVITY;\r
-\r
-\r
-       VectorScale(dist, 1/flight_time, speed);\r
-       speed[2] = speed_z;\r
-\r
-//     Sys_Printf("Speed: (%.4f %.4f %.4f)\n", speed[0], speed[1], speed[2]);\r
-\r
-       vec3_t* pPath = new vec3_t[points];\r
-\r
-       float interval = multiplier*flight_time/points;\r
-       for(int i = 0; i < points; i++)\r
-       {\r
-               float ltime = interval*i;\r
-\r
-               VectorScale(speed, ltime, pPath[i]);\r
-               VectorAdd(pPath[i], start, pPath[i]);\r
-\r
-               // could do this all with vectors\r
-               // vGrav = {0, 0, -800.0f}\r
-               // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd);\r
-               // VectorScale(speed, ltime, pPath[i]);\r
-               // _VectorAdd(pPath[i], start, pPath[i])\r
-               // _VectorAdd(pPath[i], vAdd, pPath[i])\r
-\r
-               pPath[i][2] = start[2] + (speed_z*ltime) + (varGravity*0.5f*ltime*ltime);\r
-       }\r
-\r
-       SetPath(pPath);\r
-       return TRUE;\r
-}\r
-\r
-void DBobView::Begin(const char* trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra)\r
-{\r
-       strcpy(entTrigger, trigger);\r
-       strcpy(entTarget, target);\r
-\r
-       fMultiplier = multiplier;\r
-       fVarGravity = varGravity;\r
-       nPathCount = points;\r
-       m_bShowExtra = bShowExtra;\r
-\r
-       Register();\r
-\r
-       if(UpdatePath())\r
-       {\r
-               if(!bNoUpdate)\r
-               {\r
-                       eyes = new DListener;\r
-                       eyes->parent = this;\r
-                       eyes->Register();\r
-               }\r
-       }\r
-       else\r
-       {\r
-               Sys_ERROR("Initialization Failure in DBobView::Begin");\r
-               delete this;\r
-       }\r
-}\r
-\r
-bool DBobView::UpdatePath()\r
-{\r
-       vec3_t start, apex;\r
-\r
-       if(GetEntityCentre(entTrigger, start))\r
-       {\r
-               if(GetEntityCentre(entTarget, apex))\r
-               {\r
-                       CalculateTrajectory(start, apex, fMultiplier, nPathCount, fVarGravity);\r
-                       return TRUE;\r
-               }\r
-       }\r
-       return FALSE;\r
-}\r
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// BobView.cpp: implementation of the DBobView class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "StdAfx.h"
+#include "DBobView.h"
+#include "DListener.h"
+#include "misc.h"
+#include "funchandlers.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+DBobView::DBobView()
+{
+       nPathCount = 0;
+       refCount = 1;
+       
+       m_bHooked = FALSE;
+
+       path = NULL;
+       eyes = NULL;
+
+       boundingShow = BOUNDS_APEX;
+}
+
+DBobView::~DBobView()
+{
+       if(path)
+               delete[] path;
+
+       // oops forgot to remove our eyes, was causing access violation when it tried
+       // to talk to it's parent
+       if(eyes)
+               delete eyes;
+
+       if(m_bHooked)
+               UnRegister();
+
+       g_PathView = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Implementation
+//////////////////////////////////////////////////////////////////////
+
+void DBobView::Draw2D(VIEWTYPE vt)
+{
+       if(!path)
+               return;
+
+       g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);
+
+       g_QglTable.m_pfn_qglDisable(GL_BLEND);
+       g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);
+
+       g_QglTable.m_pfn_qglPushMatrix();
+       
+       switch(vt)
+       {
+       case XY:
+               break;
+       case XZ:
+               g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);
+               break;
+       case YZ:
+               g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);
+               g_QglTable.m_pfn_qglRotatef(270.0f, 0.0f, 0.0f, 1.0f);
+               break;
+       }
+
+       g_QglTable.m_pfn_qglLineWidth(1.0f);
+       g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+
+       int i;
+
+       g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP);
+
+       for(i = 0; i < nPathCount; i++)
+               g_QglTable.m_pfn_qglVertex3fv(path[i]);
+
+       g_QglTable.m_pfn_qglEnd();
+
+       if(m_bShowExtra)
+       {
+               // +mars
+               // for the bounding box stuff
+               g_QglTable.m_pfn_qglColor4f(0.25f, 0.75f, 0.75f, 1.0f);
+
+               g_QglTable.m_pfn_qglTranslatef( 16.0f, 16.0f, 28.0f );
+
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+       
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+       
+       // ---------------
+
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );       // back to where we were
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // move to new postion
+       
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+
+       // --------------
+
+               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // back to where we were
+               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // new pos
+
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+               
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+
+       // ----------------
+
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // back to where we were
+
+/*             g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );               // new pos
+
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+               
+               if ( boundingShow == BOUNDS_ALL )
+               {
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+               }
+               else if ( boundingShow == BOUNDS_APEX )
+               {
+                       for ( i = (nPathCount/4); i < (nPathCount/4) * 3; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+               }
+
+               g_QglTable.m_pfn_qglEnd();*/ // djbob: er, um doesn't really seem to do anyhting
+       }
+
+       // -mars
+       
+       g_QglTable.m_pfn_qglPopMatrix();
+
+       g_QglTable.m_pfn_qglPopAttrib();
+}
+
+void DBobView::Draw3D()
+{
+       if(!path)
+               return;
+
+       g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);
+
+       g_QglTable.m_pfn_qglDisable(GL_BLEND);
+       g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);
+
+       g_QglTable.m_pfn_qglLineWidth(1.0f);
+       g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+
+       g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP);
+
+       for(int i = 0; i < nPathCount; i++)
+               g_QglTable.m_pfn_qglVertex3fv(path[i]);
+
+       g_QglTable.m_pfn_qglEnd();
+
+       if(m_bShowExtra)
+       {
+               // +mars
+               // ahhh -- a nice C&P job :)
+               // for the bounding box stuff
+               g_QglTable.m_pfn_qglColor4f(0.25f, 0.75f, 0.75f, 1.0f);
+
+               g_QglTable.m_pfn_qglTranslatef( 16.0f, 16.0f, 28.0f );
+
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+               
+               int i;  
+               for ( i = 0; i < nPathCount; i++ )
+                       g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+       
+       // ---------------
+
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );       // back to where we were
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // move to new postion
+       
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+               
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+
+       // --------------
+
+               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // back to where we were
+               g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // new pos
+
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+               
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+
+       // ----------------
+
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // back to where we were
+               g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );               // new pos
+
+               g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
+               
+                       for ( i = 0; i < nPathCount; i++ )
+                               g_QglTable.m_pfn_qglVertex3fv( path[i] );
+
+               g_QglTable.m_pfn_qglEnd();
+       }
+       // -mars
+
+       g_QglTable.m_pfn_qglPopAttrib();
+}
+
+void DBobView::Register()
+{
+       g_QglTable.m_pfnHookGL2DWindow( this );
+       g_QglTable.m_pfnHookGL3DWindow( this );
+       m_bHooked = TRUE;
+}
+
+void DBobView::UnRegister()
+{
+       g_QglTable.m_pfnUnHookGL2DWindow( this );
+       g_QglTable.m_pfnUnHookGL3DWindow( this );
+       m_bHooked = FALSE;
+}
+
+void DBobView::SetPath(vec3_t *pPath)
+{
+       if(path)
+               delete[] path;
+
+       path = pPath;
+}
+
+#define LOCAL_GRAVITY -800.0f
+
+bool DBobView::CalculateTrajectory(vec3_t start, vec3_t apex, float multiplier, int points, float varGravity)
+{
+       if(apex[2] <= start[2])
+       {
+               SetPath(NULL);
+               return FALSE;
+       }
+       // ----think q3a actually would allow these
+       //scrub that, coz the plugin wont :]
+
+       vec3_t dist, speed;
+       VectorSubtract(apex, start, dist);
+
+       vec_t speed_z = (float)sqrt(-2*LOCAL_GRAVITY*dist[2]);
+       float flight_time = -speed_z/LOCAL_GRAVITY;
+
+
+       VectorScale(dist, 1/flight_time, speed);
+       speed[2] = speed_z;
+
+//     Sys_Printf("Speed: (%.4f %.4f %.4f)\n", speed[0], speed[1], speed[2]);
+
+       vec3_t* pPath = new vec3_t[points];
+
+       float interval = multiplier*flight_time/points;
+       for(int i = 0; i < points; i++)
+       {
+               float ltime = interval*i;
+
+               VectorScale(speed, ltime, pPath[i]);
+               VectorAdd(pPath[i], start, pPath[i]);
+
+               // could do this all with vectors
+               // vGrav = {0, 0, -800.0f}
+               // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd);
+               // VectorScale(speed, ltime, pPath[i]);
+               // _VectorAdd(pPath[i], start, pPath[i])
+               // _VectorAdd(pPath[i], vAdd, pPath[i])
+
+               pPath[i][2] = start[2] + (speed_z*ltime) + (varGravity*0.5f*ltime*ltime);
+       }
+
+       SetPath(pPath);
+       return TRUE;
+}
+
+void DBobView::Begin(const char* trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra)
+{
+       strcpy(entTrigger, trigger);
+       strcpy(entTarget, target);
+
+       fMultiplier = multiplier;
+       fVarGravity = varGravity;
+       nPathCount = points;
+       m_bShowExtra = bShowExtra;
+
+       Register();
+
+       if(UpdatePath())
+       {
+               if(!bNoUpdate)
+               {
+                       eyes = new DListener;
+                       eyes->parent = this;
+                       eyes->Register();
+               }
+       }
+       else
+       {
+               Sys_ERROR("Initialization Failure in DBobView::Begin");
+               delete this;
+       }
+}
+
+bool DBobView::UpdatePath()
+{
+       vec3_t start, apex;
+
+       if(GetEntityCentre(entTrigger, start))
+       {
+               if(GetEntityCentre(entTarget, apex))
+               {
+                       CalculateTrajectory(start, apex, fMultiplier, nPathCount, fVarGravity);
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
index e571a50..8d254a6 100644 (file)
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// DBrush.cpp: implementation of the DBrush class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-\r
-#ifdef _WIN32\r
-#pragma warning(disable : 4786)\r
-#endif\r
-\r
-#include "DBrush.h"\r
-#include "DWinding.h"\r
-#include "dialogs-gtk.h"\r
-\r
-#include "misc.h"\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DBrush::DBrush(int ID)\r
-{\r
-       m_nBrushID = ID;\r
-       bBoundsBuilt = FALSE;\r
-       QER_brush = NULL;\r
-}\r
-\r
-DBrush::~DBrush()\r
-{\r
-       ClearFaces();\r
-       ClearPoints();\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Implementation\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DPlane* DBrush::AddFace(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData)\r
-{\r
-#ifdef _DEBUG\r
-//     Sys_Printf("(%f %f %f) (%f %f %f) (%f %f %f)\n", va[0], va[1], va[2], vb[0], vb[1], vb[2], vc[0], vc[1], vc[2]);\r
-#endif\r
-       bBoundsBuilt = FALSE;\r
-       DPlane* newFace = new DPlane(va, vb, vc, texData);\r
-       faceList.push_back(newFace);\r
-       \r
-       return newFace;\r
-}\r
-\r
-int DBrush::BuildPoints()\r
-{\r
-       ClearPoints();\r
-       \r
-       if(faceList.size() <= 3)        // if less than 3 faces, there can be no points\r
-               return 0;                                       // with only 3 faces u can't have a bounded soild\r
-\r
-       for(list<DPlane *>::const_iterator p1=faceList.begin(); p1!=faceList.end(); p1++)\r
-       {\r
-               list<DPlane *>::const_iterator p2=p1;\r
-               for(p2++; p2!=faceList.end(); p2++)\r
-               {\r
-                       list<DPlane *>::const_iterator p3=p2;\r
-                       for(p3++; p3!=faceList.end(); p3++)\r
-                       {\r
-                               vec3_t pnt;\r
-                               if((*p1)->PlaneIntersection(*p2, *p3, pnt))\r
-                               {\r
-                                       int pos = PointPosition(pnt);\r
-\r
-                                       if(pos == POINT_IN_BRUSH)\r
-                                       {       // ???? shouldn't happen here\r
-                                               Sys_Printf("ERROR:: Build Brush Points: Point IN brush!!!\n");\r
-                                       }\r
-                                       else if(pos == POINT_ON_BRUSH)\r
-                                       {       // normal point\r
-                                               if(!HasPoint(pnt))\r
-                                                       AddPoint(pnt);\r
-/*                                             else\r
-                                                       Sys_Printf("Duplicate Point Found, pyramids ahoy!!!!!\n");*/\r
-                                               // point lies on more that 3 planes\r
-                                       }\r
-                                                       \r
-                                       // otherwise point is removed due to another plane..\r
-\r
-                                       // Sys_Printf("(%f, %f, %f)\n", pnt[0], pnt[1], pnt[2]);                \r
-                               }       \r
-                       }\r
-               }\r
-       }\r
-\r
-#ifdef _DEBUG\r
-//     Sys_Printf("%i points on brush\n", pointList.size());\r
-#endif\r
-\r
-       return pointList.size();\r
-}\r
-\r
-void DBrush::LoadFromBrush_t(brush_t* brush, bool textured)\r
-{\r
-       ClearFaces();\r
-       ClearPoints();\r
-\r
-       for(int i = g_FuncTable.m_pfnGetFaceCount(brush)-1; i >= 0 ; i--)\r
-       {       // running backwards so i dont have to use the count function each time (OPT)\r
-               _QERFaceData* faceData = g_FuncTable.m_pfnGetFaceData(brush, i);\r
-\r
-               if(faceData == NULL)\r
-                       DoMessageBox("Null pointer returned", "WARNING!", MB_OK);\r
-\r
-               if(textured)\r
-                       AddFace(faceData->m_v1, faceData->m_v2, faceData->m_v3, faceData);\r
-               else\r
-                       AddFace(faceData->m_v1, faceData->m_v2, faceData->m_v3, NULL);\r
-       }\r
-\r
-       QER_brush = brush;\r
-}\r
-\r
-int DBrush::PointPosition(vec3_t pnt)\r
-{\r
-       int state = POINT_IN_BRUSH;     // if nothing happens point is inside brush\r
-\r
-       for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)\r
-       {\r
-               float dist = (*chkPlane)->DistanceToPoint(pnt);\r
-\r
-               if(dist > MAX_ROUND_ERROR)\r
-                       return POINT_OUT_BRUSH;         // if point is in front of plane, it CANT be in the brush\r
-               else if(fabs(dist) < MAX_ROUND_ERROR)\r
-                       state = POINT_ON_BRUSH;         // if point is ON plane point is either ON the brush \r
-                                                                               // or outside it, it can no longer be in it\r
-       }\r
-\r
-       return state;\r
-}\r
-\r
-void DBrush::ClearPoints()\r
-{\r
-       for(list<DPoint *>::const_iterator deadPoint=pointList.begin(); deadPoint!=pointList.end(); deadPoint++) {\r
-               delete *deadPoint;\r
-       }\r
-       pointList.clear();\r
-}\r
-\r
-void DBrush::ClearFaces()\r
-{\r
-       bBoundsBuilt = FALSE;\r
-       for(list<DPlane *>::const_iterator deadPlane=faceList.begin(); deadPlane!=faceList.end(); deadPlane++)\r
-       {\r
-               delete *deadPlane;\r
-       }\r
-       faceList.clear();\r
-}\r
-\r
-void DBrush::AddPoint(vec3_t pnt)\r
-{\r
-       DPoint* newPoint = new DPoint;\r
-       VectorCopy(pnt, newPoint->_pnt);\r
-       pointList.push_back(newPoint);\r
-}\r
-\r
-bool DBrush::HasPoint(vec3_t pnt)\r
-{\r
-       for(list<DPoint *>::const_iterator chkPoint=pointList.begin(); chkPoint!=pointList.end(); chkPoint++)\r
-       {\r
-               if(**chkPoint == pnt)\r
-                       return TRUE;\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-int DBrush::RemoveRedundantPlanes()\r
-{\r
-       int cnt = 0;\r
-       list<DPlane *>::iterator chkPlane;\r
-\r
-       // find duplicate planes\r
-       list<DPlane *>::iterator p1=faceList.begin();\r
-\r
-       while( p1!=faceList.end() )\r
-       {\r
-               list<DPlane *>::iterator p2 = p1;\r
-\r
-               for(p2++; p2!=faceList.end(); p2++)\r
-               {\r
-                       if(**p1 == **p2)\r
-                       {\r
-                               if(!strcmp((*p1)->texInfo.m_TextureName, "textures/common/caulk"))\r
-                               {\r
-                                       delete *p1;\r
-                                       p1 = faceList.erase(p1);        // duplicate plane\r
-                               }\r
-                               else\r
-                               {\r
-                                       delete *p2;\r
-                                       p2 = faceList.erase(p2);        // duplicate plane\r
-                               }\r
-\r
-                               cnt++;\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               if( p2 == faceList.end() )\r
-                       p1++;\r
-       }\r
-               \r
-       //+djbob kill planes with bad normal, they are more of a nuisance than losing a brush\r
-       chkPlane=faceList.begin();\r
-       while( chkPlane!=faceList.end() )\r
-       {\r
-               if(VectorLength((*chkPlane)->normal) == 0) // plane has bad normal\r
-               {\r
-                       delete *chkPlane;\r
-                       chkPlane = faceList.erase(chkPlane);\r
-                       cnt++;\r
-               } else {\r
-                       chkPlane++;\r
-               }\r
-       }\r
-       //-djbob\r
-       \r
-       if(pointList.size() == 0) // if points may not have been built, build them\r
-/*             if(BuildPoints() == 0)  // just let the planes die if they are all bad\r
-                       return cnt;*/\r
-                       BuildPoints();\r
-\r
-       chkPlane=faceList.begin();\r
-       while(chkPlane != faceList.end())\r
-       {\r
-               if((*chkPlane)->IsRedundant(pointList)) // checks that plane "0wnz" :), 3 or more points\r
-               {\r
-                       delete *chkPlane;\r
-                       chkPlane = faceList.erase(chkPlane);\r
-                       cnt++;\r
-               } \r
-               else \r
-                       chkPlane++;\r
-       }\r
-\r
-       return cnt;\r
-}\r
-\r
-bool DBrush::GetBounds(vec3_t min, vec3_t max)\r
-{\r
-       BuildBounds();\r
-\r
-       if(!bBoundsBuilt)\r
-               return FALSE;\r
-\r
-       VectorCopy(bbox_min, min);\r
-       VectorCopy(bbox_max, max);\r
-\r
-       return TRUE;\r
-}\r
-\r
-bool DBrush::BBoxCollision(DBrush* chkBrush)\r
-{\r
-       vec3_t min1, min2;\r
-       vec3_t max1, max2;\r
-\r
-       GetBounds(min1, max1);\r
-       chkBrush->GetBounds(min2, max2);\r
-\r
-       if(min1[0] >= max2[0])\r
-               return FALSE;\r
-       if(min1[1] >= max2[1])\r
-               return FALSE;\r
-       if(min1[2] >= max2[2])\r
-               return FALSE;\r
-\r
-       if(max1[0] <= min2[0])\r
-               return FALSE;\r
-       if(max1[1] <= min2[1])\r
-               return FALSE;\r
-       if(max1[2] <= min2[2])\r
-               return FALSE;\r
-\r
-       return TRUE;\r
-}\r
-\r
-DPlane* DBrush::HasPlane(DPlane* chkPlane)\r
-{\r
-       for(list<DPlane *>::const_iterator brushPlane=faceList.begin(); brushPlane!=faceList.end(); brushPlane++)\r
-       {\r
-               if(**brushPlane == *chkPlane)\r
-                       return *brushPlane;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-bool DBrush::IsCutByPlane(DPlane *cuttingPlane)\r
-{\r
-       bool isInFront;\r
-\r
-       if(pointList.size() == 0)\r
-               if(BuildPoints() == 0)\r
-                       return FALSE;\r
-\r
-       list<DPoint *>::const_iterator chkPnt = pointList.begin();\r
-\r
-       if(chkPnt == pointList.end())\r
-               return FALSE;\r
-\r
-       float dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt);\r
-\r
-       if(dist > MAX_ROUND_ERROR)\r
-               isInFront = FALSE;\r
-       else if(dist < MAX_ROUND_ERROR)\r
-               isInFront = TRUE;\r
-       else\r
-               return TRUE;\r
-\r
-       for(chkPnt++=pointList.begin(); chkPnt!=pointList.end(); chkPnt++)\r
-       {\r
-               dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt);\r
-\r
-               if(dist > MAX_ROUND_ERROR)\r
-               {\r
-                       if(isInFront)\r
-                               return TRUE;\r
-               }\r
-               else if(dist < MAX_ROUND_ERROR)\r
-               {\r
-                       if(!isInFront)\r
-                               return TRUE;\r
-               }\r
-               else\r
-                       return TRUE;\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-brush_t* DBrush::BuildInRadiant(bool allowDestruction, int* changeCnt, entity_t* entity)\r
-{\r
-       if(allowDestruction)\r
-       {\r
-               bool kill = TRUE;\r
-               \r
-               for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)\r
-               {\r
-                       if((*chkPlane)->m_bChkOk)\r
-                       {\r
-                               kill = FALSE;\r
-                               break;\r
-                       }\r
-               }\r
-               if(kill)\r
-                       return NULL;\r
-       }\r
-\r
-       //+djbob: fixed bug when brush had no faces "phantom brush" in radiant.\r
-       if(faceList.size() < 4)\r
-       {\r
-               Sys_Printf("Possible Phantom Brush Found, will not rebuild\n");\r
-               return NULL;\r
-       }\r
-       //-djbob\r
-\r
-       QER_brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();\r
-\r
-       for(list<DPlane *>::const_iterator buildPlane=faceList.begin(); buildPlane!=faceList.end(); buildPlane++) {\r
-               if((*buildPlane)->AddToBrush_t(QER_brush) && changeCnt) {\r
-                       (*changeCnt)++;\r
-               }\r
-       }\r
-\r
-       if(entity) {\r
-               g_FuncTable.m_pfnCommitBrushHandleToEntity(QER_brush, entity);\r
-               g_BrushTable.m_pfnBrush_Build(QER_brush);\r
-               g_BrushTable.m_pfnBrush_AddToList(QER_brush, g_AppDataTable.m_pfnSelectedBrushes());\r
-       } else {\r
-               g_FuncTable.m_pfnCommitBrushHandle(QER_brush);\r
-       }\r
-\r
-       return QER_brush;\r
-}\r
-\r
-void DBrush::CutByPlane(DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2)\r
-{\r
-       if(!IsCutByPlane(cutPlane))\r
-       {\r
-               *newBrush1 = NULL;\r
-               *newBrush2 = NULL;\r
-               return;\r
-       }\r
-\r
-       DBrush* b1 = new DBrush;\r
-       DBrush* b2 = new DBrush;\r
-       \r
-       for(list<DPlane *>::const_iterator parsePlane=faceList.begin(); parsePlane!=faceList.end(); parsePlane++)\r
-       {\r
-               b1->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL);\r
-               b2->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL);\r
-       }\r
-\r
-       b1->AddFace(cutPlane->points[0], cutPlane->points[1], cutPlane->points[2], NULL);\r
-       b2->AddFace(cutPlane->points[2], cutPlane->points[1], cutPlane->points[0], NULL);\r
-\r
-       b1->RemoveRedundantPlanes();\r
-       b2->RemoveRedundantPlanes();\r
-\r
-       *newBrush1 = b1;\r
-       *newBrush2 = b2;\r
-}\r
-\r
-bool DBrush::IntersectsWith(DBrush *chkBrush)\r
-{\r
-       if(pointList.size() == 0)\r
-               if(BuildPoints() == 0)\r
-                       return FALSE;   // invalid brush!!!!\r
-\r
-       if(chkBrush->pointList.size() == 0)\r
-               if(chkBrush->BuildPoints() == 0)\r
-                       return FALSE;   // invalid brush!!!!\r
-       \r
-       if(!BBoxCollision(chkBrush))\r
-               return FALSE;\r
-\r
-       list<DPlane *>::const_iterator iplPlane;\r
-\r
-       for( iplPlane=faceList.begin(); iplPlane!=faceList.end(); iplPlane++)\r
-       {\r
-\r
-               bool allInFront = TRUE;\r
-               for(list<DPoint *>::const_iterator iPoint=chkBrush->pointList.begin(); iPoint!=chkBrush->pointList.end(); iPoint++)\r
-               {\r
-                       if((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR)\r
-                       {\r
-                               allInFront = FALSE;\r
-                               break;\r
-                       }\r
-               }\r
-               if(allInFront)\r
-                       return FALSE;\r
-       }\r
-\r
-       for( iplPlane=chkBrush->faceList.begin(); iplPlane!=chkBrush->faceList.end(); iplPlane++)\r
-       {\r
-               bool allInFront = TRUE;\r
-               for(list<DPoint *>::const_iterator iPoint=pointList.begin(); iPoint!=pointList.end(); iPoint++)\r
-               {\r
-                       if((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR)\r
-                       {\r
-                               allInFront = FALSE;\r
-                               break;\r
-                       }\r
-               }\r
-               if(allInFront)\r
-                       return FALSE;\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-bool DBrush::IntersectsWith(DPlane* p1, DPlane* p2, vec3_t v) {\r
-       vec3_t vDown = { 0, 0, -1 };\r
-\r
-       list<DPlane *>::const_iterator iplPlane;\r
-       for( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) {\r
-               DPlane* p = (*iplPlane);\r
-               \r
-               vec_t d = DotProduct( p->normal, vDown );\r
-               if( d >= 0 ) {\r
-                       continue;\r
-               }\r
-               if(p->PlaneIntersection(p1, p2, v)) {\r
-                       if(PointPosition( v ) != POINT_OUT_BRUSH) {\r
-                               return TRUE;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-void DBrush::BuildBounds()\r
-{\r
-       if(!bBoundsBuilt)\r
-       {\r
-               if(pointList.size() == 0) // if points may not have been built, build them\r
-                       if(BuildPoints() == 0)\r
-                               return;\r
-       \r
-               list<DPoint *>::const_iterator first = pointList.begin();\r
-               VectorCopy((*first)->_pnt, bbox_min);\r
-               VectorCopy((*first)->_pnt, bbox_max);\r
-\r
-               list<DPoint *>::const_iterator point=pointList.begin();\r
-               for( point++; point!=pointList.end(); point++)\r
-               {\r
-                       if((*point)->_pnt[0] > bbox_max[0])\r
-                               bbox_max[0] = (*point)->_pnt[0];\r
-                       if((*point)->_pnt[1] > bbox_max[1])\r
-                               bbox_max[1] = (*point)->_pnt[1];\r
-                       if((*point)->_pnt[2] > bbox_max[2])\r
-                               bbox_max[2] = (*point)->_pnt[2];\r
-\r
-                       if((*point)->_pnt[0] < bbox_min[0])\r
-                               bbox_min[0] = (*point)->_pnt[0];\r
-                       if((*point)->_pnt[1] < bbox_min[1])\r
-                               bbox_min[1] = (*point)->_pnt[1];\r
-                       if((*point)->_pnt[2] < bbox_min[2])\r
-                               bbox_min[2] = (*point)->_pnt[2];\r
-               }\r
-\r
-               bBoundsBuilt = TRUE;\r
-       }\r
-}\r
-\r
-bool DBrush::BBoxTouch(DBrush *chkBrush)\r
-{\r
-       vec3_t min1, min2;\r
-       vec3_t max1, max2;\r
-\r
-       GetBounds(min1, max1);\r
-       chkBrush->GetBounds(min2, max2);\r
-\r
-       if((min1[0] - max2[0]) > MAX_ROUND_ERROR)\r
-               return FALSE;\r
-       if((min1[1] - max2[1]) > MAX_ROUND_ERROR)\r
-               return FALSE;\r
-       if((min1[2] - max2[2]) > MAX_ROUND_ERROR)\r
-               return FALSE;\r
-\r
-       if((min2[0] - max1[0]) > MAX_ROUND_ERROR)\r
-               return FALSE;\r
-       if((min2[1] - max1[1]) > MAX_ROUND_ERROR)\r
-               return FALSE;\r
-       if((min2[2] - max1[2]) > MAX_ROUND_ERROR)\r
-               return FALSE;\r
-\r
-       int cnt = 0;\r
-\r
-       if((min2[0] - max1[0]) == 0)\r
-               cnt++;\r
-\r
-       if((min2[1] - max1[1]) == 0)\r
-               cnt++;\r
-\r
-       if((min2[2] - max1[2]) == 0)\r
-               cnt++;\r
-\r
-       if((min1[0] - max2[0]) == 0)\r
-               cnt++;\r
-\r
-       if((min1[1] - max2[1]) == 0)\r
-               cnt++;\r
-\r
-       if((min1[2] - max2[2]) == 0)\r
-               cnt++;\r
-\r
-       if(cnt > 1)\r
-               return FALSE;\r
-\r
-       return TRUE;\r
-}\r
-\r
-void DBrush::ResetChecks(list<Str>* exclusionList)\r
-{\r
-       for(list<DPlane *>::const_iterator resetPlane=faceList.begin(); resetPlane!=faceList.end(); resetPlane++)\r
-       {\r
-               bool set = FALSE;\r
-\r
-               if(exclusionList)\r
-               {\r
-                       for(list<Str>::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++)\r
-                       {\r
-                               if(strstr((*resetPlane)->texInfo.m_TextureName, eTexture->GetBuffer()))\r
-                               {\r
-                                       set = TRUE;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               (*resetPlane)->m_bChkOk = set;\r
-       }\r
-}\r
-\r
-DPlane* DBrush::HasPlaneInverted(DPlane *chkPlane)\r
-{\r
-       for(list<DPlane *>::const_iterator brushPlane=faceList.begin(); brushPlane!=faceList.end(); brushPlane++)\r
-       {\r
-               if(**brushPlane != *chkPlane)\r
-               {\r
-                       if(fabs((*brushPlane)->_d + chkPlane->_d) < 0.1)\r
-                               return (*brushPlane);\r
-               }\r
-       }\r
-       return NULL;\r
-}\r
-\r
-bool DBrush::HasTexture(const char *textureName)\r
-{\r
-       for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)\r
-       {\r
-               if(strstr((*chkPlane)->texInfo.m_TextureName, textureName))\r
-                       return TRUE;\r
-\r
-       }\r
-       return FALSE;\r
-}\r
-\r
-bool DBrush::IsDetail()\r
-{\r
-       for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)\r
-       {\r
-               if((*chkPlane)->texInfo.m_nContents & FACE_DETAIL)\r
-                       return TRUE;\r
-\r
-       }\r
-       return FALSE;\r
-}\r
-\r
-void DBrush::BuildFromWinding(DWinding *w)\r
-{\r
-       if(w->numpoints < 3)\r
-       {\r
-               Sys_ERROR("Winding has invalid number of points");\r
-               return;\r
-       }\r
-\r
-       DPlane* wPlane = w->WindingPlane();\r
-\r
-       DWinding* w2;\r
-       w2 = w->CopyWinding();\r
-       int i;\r
-       for(i = 0; i < w2->numpoints; i++)\r
-               VectorAdd(w2->p[i], wPlane->normal, w2->p[i]);\r
-\r
-       AddFace(w2->p[0], w2->p[1], w2->p[2], NULL);\r
-       AddFace(w->p[2], w->p[1], w->p[0], NULL);\r
-\r
-       for(i = 0; i < w->numpoints-1; i++)\r
-               AddFace(w2->p[i], w->p[i], w->p[i+1], NULL);\r
-       AddFace(w2->p[w->numpoints-1], w->p[w->numpoints-1], w->p[0], NULL);\r
-\r
-       delete wPlane;\r
-       delete w2;\r
-}\r
-\r
-void DBrush::SaveToFile(FILE *pFile)\r
-{\r
-       fprintf(pFile, "{\n");\r
-\r
-       for(list<DPlane *>::const_iterator pp=faceList.begin(); pp!=faceList.end(); pp++)\r
-       {\r
-               char buffer[512];\r
-\r
-               sprintf(buffer, "( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) %s %.0f %.0f %f %f %.0f 0 0 0\n",\r
-                       (*pp)->points[0][0], (*pp)->points[0][1], (*pp)->points[0][2], \r
-                       (*pp)->points[1][0], (*pp)->points[1][1], (*pp)->points[1][2], \r
-                       (*pp)->points[2][0], (*pp)->points[2][1], (*pp)->points[2][2], \r
-                       (*pp)->texInfo.m_TextureName,\r
-                       (*pp)->texInfo.m_fShift[0], (*pp)->texInfo.m_fShift[1], \r
-                       (*pp)->texInfo.m_fScale[0], (*pp)->texInfo.m_fScale[0], \r
-                       (*pp)->texInfo.m_fRotate);\r
-\r
-               fprintf(pFile, buffer);\r
-       }\r
-\r
-       fprintf(pFile, "}\n");\r
-}\r
-\r
-void DBrush::Rotate(vec3_t vOrigin, vec3_t vRotation)\r
-{\r
-       for(list<DPlane *>::const_iterator rotPlane=faceList.begin(); rotPlane!=faceList.end(); rotPlane++)\r
-       {\r
-               for(int i = 0; i < 3; i++)\r
-                       VectorRotate((*rotPlane)->points[i], vRotation, vOrigin);\r
-\r
-               (*rotPlane)->Rebuild();\r
-       }\r
-}\r
-\r
-void DBrush::RotateAboutCentre(vec3_t vRotation)\r
-{\r
-       vec3_t min, max, centre;\r
-       GetBounds(min, max);\r
-       VectorAdd(min, max, centre);\r
-       VectorScale(centre, 0.5f, centre);\r
-\r
-       Rotate(centre, vRotation);\r
-}\r
-\r
-bool DBrush::ResetTextures(const char* textureName, float fScale[2],    float fShift[2],    int rotation, const char* newTextureName, \r
-                           int bResetTextureName,   int bResetScale[2], int bResetShift[2], int bResetRotation)\r
-{\r
-       if(textureName)\r
-       {\r
-               bool changed = FALSE;\r
-               for(list<DPlane *>::const_iterator resetPlane=faceList.begin(); resetPlane!=faceList.end(); resetPlane++)\r
-               {\r
-                       if(!strcmp((*resetPlane)->texInfo.m_TextureName, textureName))\r
-                       {\r
-        if(bResetTextureName)\r
-                                 strcpy((*resetPlane)->texInfo.m_TextureName, newTextureName);\r
-\r
-                               if(bResetScale[0])\r
-                                       (*resetPlane)->texInfo.m_fScale[0] = fScale[0];\r
-                               if(bResetScale[1])\r
-                                       (*resetPlane)->texInfo.m_fScale[1] = fScale[1];\r
-\r
-                               if(bResetShift[0])\r
-                                       (*resetPlane)->texInfo.m_fShift[0] = fShift[0];\r
-                               if(bResetShift[1])\r
-                                       (*resetPlane)->texInfo.m_fShift[1] = fShift[1];\r
-\r
-                               if(bResetRotation)\r
-                                       (*resetPlane)->texInfo.m_fRotate = (float)rotation;\r
-\r
-                               changed = TRUE;\r
-                       }\r
-               }\r
-               return changed; // no point rebuilding unless we need to, only slows things down\r
-       }\r
-       else\r
-       {\r
-               for(list<DPlane *>::const_iterator resetPlane=faceList.begin(); resetPlane!=faceList.end(); resetPlane++)\r
-               {\r
-        if(bResetTextureName)\r
-                                 strcpy((*resetPlane)->texInfo.m_TextureName, newTextureName);\r
-\r
-                               if(bResetScale[0])\r
-                                       (*resetPlane)->texInfo.m_fScale[0] = fScale[0];\r
-                               if(bResetScale[1])\r
-                                       (*resetPlane)->texInfo.m_fScale[1] = fScale[1];\r
-\r
-                               if(bResetShift[0])\r
-                                       (*resetPlane)->texInfo.m_fShift[0] = fShift[0];\r
-                               if(bResetShift[1])\r
-                                       (*resetPlane)->texInfo.m_fShift[1] = fShift[1];\r
-\r
-                               if(bResetRotation)\r
-                                       (*resetPlane)->texInfo.m_fRotate = (float)rotation;\r
-               }\r
-               return TRUE;\r
-       }\r
-}\r
-\r
-bool DBrush::operator ==(DBrush* other)\r
-{\r
-       list<DPlane *>::const_iterator chkPlane;\r
-       \r
-       for(chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)\r
-       {\r
-               if(!other->HasPlane((*chkPlane)))\r
-                       return FALSE;\r
-       }\r
-\r
-       for(chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)\r
-       {\r
-               if(!HasPlane((*chkPlane)))\r
-                       return FALSE;\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-DPlane* DBrush::AddFace(vec3_t va, vec3_t vb, vec3_t vc, const char *textureName, bool bDetail)\r
-{\r
-       bBoundsBuilt = FALSE;\r
-       DPlane* newFace = new DPlane(va, vb, vc, textureName, bDetail);\r
-       faceList.push_back(newFace);\r
-       \r
-       return newFace;\r
-}\r
-\r
-DPlane* DBrush::FindPlaneWithClosestNormal( vec_t* normal ) {\r
-       vec_t bestDot = -2;\r
-       DPlane* bestDotPlane = NULL;\r
-       list<DPlane *>::const_iterator chkPlane;\r
-       for( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) {\r
-               DPlane* pPlane = (*chkPlane);\r
-\r
-               vec_t dot = DotProduct( pPlane->normal, normal );\r
-               if( dot > bestDot ) {\r
-                       bestDot = dot;\r
-                       bestDotPlane = pPlane;\r
-               }\r
-       }\r
-\r
-       return bestDotPlane;\r
-}\r
-\r
-int DBrush::FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts ) {\r
-       int numpnts = 0;\r
-\r
-       if(!maxpnts) {\r
-               return 0;\r
-       }\r
-\r
-       BuildPoints();\r
-\r
-       for( list<DPoint *>::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) {\r
-               DPoint* point = (*points);\r
-\r
-               if( fabs(plane->DistanceToPoint( point->_pnt )) < MAX_ROUND_ERROR ) {\r
-                       pnts[numpnts] = point;\r
-                       numpnts++;\r
-\r
-                       if(numpnts >= maxpnts) {\r
-                               return numpnts;\r
-                       }\r
-\r
-               }\r
-       }\r
-\r
-       return numpnts;\r
-}\r
-\r
-void DBrush::RemovePlane( DPlane* plane ) {\r
-       bBoundsBuilt = FALSE;\r
-       for( list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {          \r
-               if(*deadPlane == plane) {\r
-                       delete *deadPlane;\r
-                       faceList.remove( plane );\r
-               }\r
-       }\r
-}\r
-\r
-void DBrush::RemoveFromRadiant( void ) {\r
-       if(QER_brush) {\r
-               g_FuncTable.m_pfnDeleteBrushHandle(QER_brush);\r
-       }\r
-}\r
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DBrush.cpp: implementation of the DBrush class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4786)
+#endif
+
+#include "DBrush.h"
+#include "DWinding.h"
+#include "dialogs-gtk.h"
+
+#include "misc.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+DBrush::DBrush(int ID)
+{
+       m_nBrushID = ID;
+       bBoundsBuilt = FALSE;
+       QER_brush = NULL;
+}
+
+DBrush::~DBrush()
+{
+       ClearFaces();
+       ClearPoints();
+}
+
+//////////////////////////////////////////////////////////////////////
+// Implementation
+//////////////////////////////////////////////////////////////////////
+
+DPlane* DBrush::AddFace(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData)
+{
+#ifdef _DEBUG
+//     Sys_Printf("(%f %f %f) (%f %f %f) (%f %f %f)\n", va[0], va[1], va[2], vb[0], vb[1], vb[2], vc[0], vc[1], vc[2]);
+#endif
+       bBoundsBuilt = FALSE;
+       DPlane* newFace = new DPlane(va, vb, vc, texData);
+       faceList.push_back(newFace);
+       
+       return newFace;
+}
+
+int DBrush::BuildPoints()
+{
+       ClearPoints();
+       
+       if(faceList.size() <= 3)        // if less than 3 faces, there can be no points
+               return 0;                                       // with only 3 faces u can't have a bounded soild
+
+       for(list<DPlane *>::const_iterator p1=faceList.begin(); p1!=faceList.end(); p1++)
+       {
+               list<DPlane *>::const_iterator p2=p1;
+               for(p2++; p2!=faceList.end(); p2++)
+               {
+                       list<DPlane *>::const_iterator p3=p2;
+                       for(p3++; p3!=faceList.end(); p3++)
+                       {
+                               vec3_t pnt;
+                               if((*p1)->PlaneIntersection(*p2, *p3, pnt))
+                               {
+                                       int pos = PointPosition(pnt);
+
+                                       if(pos == POINT_IN_BRUSH)
+                                       {       // ???? shouldn't happen here
+                                               Sys_Printf("ERROR:: Build Brush Points: Point IN brush!!!\n");
+                                       }
+                                       else if(pos == POINT_ON_BRUSH)
+                                       {       // normal point
+                                               if(!HasPoint(pnt))
+                                                       AddPoint(pnt);
+/*                                             else
+                                                       Sys_Printf("Duplicate Point Found, pyramids ahoy!!!!!\n");*/
+                                               // point lies on more that 3 planes
+                                       }
+                                                       
+                                       // otherwise point is removed due to another plane..
+
+                                       // Sys_Printf("(%f, %f, %f)\n", pnt[0], pnt[1], pnt[2]);                
+                               }       
+                       }
+               }
+       }
+
+#ifdef _DEBUG
+//     Sys_Printf("%i points on brush\n", pointList.size());
+#endif
+
+       return pointList.size();
+}
+
+void DBrush::LoadFromBrush_t(brush_t* brush, bool textured)
+{
+       ClearFaces();
+       ClearPoints();
+
+       for(int i = g_FuncTable.m_pfnGetFaceCount(brush)-1; i >= 0 ; i--)
+       {       // running backwards so i dont have to use the count function each time (OPT)
+               _QERFaceData* faceData = g_FuncTable.m_pfnGetFaceData(brush, i);
+
+               if(faceData == NULL)
+                       DoMessageBox("Null pointer returned", "WARNING!", MB_OK);
+
+               if(textured)
+                       AddFace(faceData->m_v1, faceData->m_v2, faceData->m_v3, faceData);
+               else
+                       AddFace(faceData->m_v1, faceData->m_v2, faceData->m_v3, NULL);
+       }
+
+       QER_brush = brush;
+}
+
+int DBrush::PointPosition(vec3_t pnt)
+{
+       int state = POINT_IN_BRUSH;     // if nothing happens point is inside brush
+
+       for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)
+       {
+               float dist = (*chkPlane)->DistanceToPoint(pnt);
+
+               if(dist > MAX_ROUND_ERROR)
+                       return POINT_OUT_BRUSH;         // if point is in front of plane, it CANT be in the brush
+               else if(fabs(dist) < MAX_ROUND_ERROR)
+                       state = POINT_ON_BRUSH;         // if point is ON plane point is either ON the brush 
+                                                                               // or outside it, it can no longer be in it
+       }
+
+       return state;
+}
+
+void DBrush::ClearPoints()
+{
+       for(list<DPoint *>::const_iterator deadPoint=pointList.begin(); deadPoint!=pointList.end(); deadPoint++) {
+               delete *deadPoint;
+       }
+       pointList.clear();
+}
+
+void DBrush::ClearFaces()
+{
+       bBoundsBuilt = FALSE;
+       for(list<DPlane *>::const_iterator deadPlane=faceList.begin(); deadPlane!=faceList.end(); deadPlane++)
+       {
+               delete *deadPlane;
+       }
+       faceList.clear();
+}
+
+void DBrush::AddPoint(vec3_t pnt)
+{
+       DPoint* newPoint = new DPoint;
+       VectorCopy(pnt, newPoint->_pnt);
+       pointList.push_back(newPoint);
+}
+
+bool DBrush::HasPoint(vec3_t pnt)
+{
+       for(list<DPoint *>::const_iterator chkPoint=pointList.begin(); chkPoint!=pointList.end(); chkPoint++)
+       {
+               if(**chkPoint == pnt)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+int DBrush::RemoveRedundantPlanes()
+{
+       int cnt = 0;
+       list<DPlane *>::iterator chkPlane;
+
+       // find duplicate planes
+       list<DPlane *>::iterator p1=faceList.begin();
+
+       while( p1!=faceList.end() )
+       {
+               list<DPlane *>::iterator p2 = p1;
+
+               for(p2++; p2!=faceList.end(); p2++)
+               {
+                       if(**p1 == **p2)
+                       {
+                               if(!strcmp((*p1)->texInfo.m_TextureName, "textures/common/caulk"))
+                               {
+                                       delete *p1;
+                                       p1 = faceList.erase(p1);        // duplicate plane
+                               }
+                               else
+                               {
+                                       delete *p2;
+                                       p2 = faceList.erase(p2);        // duplicate plane
+                               }
+
+                               cnt++;
+                               break;
+                       }
+               }
+
+               if( p2 == faceList.end() )
+                       p1++;
+       }
+               
+       //+djbob kill planes with bad normal, they are more of a nuisance than losing a brush
+       chkPlane=faceList.begin();
+       while( chkPlane!=faceList.end() )
+       {
+               if(VectorLength((*chkPlane)->normal) == 0) // plane has bad normal
+               {
+                       delete *chkPlane;
+                       chkPlane = faceList.erase(chkPlane);
+                       cnt++;
+               } else {
+                       chkPlane++;
+               }
+       }
+       //-djbob
+       
+       if(pointList.size() == 0) // if points may not have been built, build them
+/*             if(BuildPoints() == 0)  // just let the planes die if they are all bad
+                       return cnt;*/
+                       BuildPoints();
+
+       chkPlane=faceList.begin();
+       while(chkPlane != faceList.end())
+       {
+               if((*chkPlane)->IsRedundant(pointList)) // checks that plane "0wnz" :), 3 or more points
+               {
+                       delete *chkPlane;
+                       chkPlane = faceList.erase(chkPlane);
+                       cnt++;
+               } 
+               else 
+                       chkPlane++;
+       }
+
+       return cnt;
+}
+
+bool DBrush::GetBounds(vec3_t min, vec3_t max)
+{
+       BuildBounds();
+
+       if(!bBoundsBuilt)
+               return FALSE;
+
+       VectorCopy(bbox_min, min);
+       VectorCopy(bbox_max, max);
+
+       return TRUE;
+}
+
+bool DBrush::BBoxCollision(DBrush* chkBrush)
+{
+       vec3_t min1, min2;
+       vec3_t max1, max2;
+
+       GetBounds(min1, max1);
+       chkBrush->GetBounds(min2, max2);
+
+       if(min1[0] >= max2[0])
+               return FALSE;
+       if(min1[1] >= max2[1])
+               return FALSE;
+       if(min1[2] >= max2[2])
+               return FALSE;
+
+       if(max1[0] <= min2[0])
+               return FALSE;
+       if(max1[1] <= min2[1])
+               return FALSE;
+       if(max1[2] <= min2[2])
+               return FALSE;
+
+       return TRUE;
+}
+
+DPlane* DBrush::HasPlane(DPlane* chkPlane)
+{
+       for(list<DPlane *>::const_iterator brushPlane=faceList.begin(); brushPlane!=faceList.end(); brushPlane++)
+       {
+               if(**brushPlane == *chkPlane)
+                       return *brushPlane;
+       }
+       return NULL;
+}
+
+bool DBrush::IsCutByPlane(DPlane *cuttingPlane)
+{
+       bool isInFront;
+
+       if(pointList.size() == 0)
+               if(BuildPoints() == 0)
+                       return FALSE;
+
+       list<DPoint *>::const_iterator chkPnt = pointList.begin();
+
+       if(chkPnt == pointList.end())
+               return FALSE;
+
+       float dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt);
+
+       if(dist > MAX_ROUND_ERROR)
+               isInFront = FALSE;
+       else if(dist < MAX_ROUND_ERROR)
+               isInFront = TRUE;
+       else
+               return TRUE;
+
+       for(chkPnt++=pointList.begin(); chkPnt!=pointList.end(); chkPnt++)
+       {
+               dist = cuttingPlane->DistanceToPoint((*chkPnt)->_pnt);
+
+               if(dist > MAX_ROUND_ERROR)
+               {
+                       if(isInFront)
+                               return TRUE;
+               }
+               else if(dist < MAX_ROUND_ERROR)
+               {
+                       if(!isInFront)
+                               return TRUE;
+               }
+               else
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+brush_t* DBrush::BuildInRadiant(bool allowDestruction, int* changeCnt, entity_t* entity)
+{
+       if(allowDestruction)
+       {
+               bool kill = TRUE;
+               
+               for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)
+               {
+                       if((*chkPlane)->m_bChkOk)
+                       {
+                               kill = FALSE;
+                               break;
+                       }
+               }
+               if(kill)
+                       return NULL;
+       }
+
+       //+djbob: fixed bug when brush had no faces "phantom brush" in radiant.
+       if(faceList.size() < 4)
+       {
+               Sys_Printf("Possible Phantom Brush Found, will not rebuild\n");
+               return NULL;
+       }
+       //-djbob
+
+       QER_brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();
+
+       for(list<DPlane *>::const_iterator buildPlane=faceList.begin(); buildPlane!=faceList.end(); buildPlane++) {
+               if((*buildPlane)->AddToBrush_t(QER_brush) && changeCnt) {
+                       (*changeCnt)++;
+               }
+       }
+
+       if(entity) {
+               g_FuncTable.m_pfnCommitBrushHandleToEntity(QER_brush, entity);
+               g_BrushTable.m_pfnBrush_Build(QER_brush);
+               g_BrushTable.m_pfnBrush_AddToList(QER_brush, g_AppDataTable.m_pfnSelectedBrushes());
+       } else {
+               g_FuncTable.m_pfnCommitBrushHandle(QER_brush);
+       }
+
+       return QER_brush;
+}
+
+void DBrush::CutByPlane(DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2)
+{
+       if(!IsCutByPlane(cutPlane))
+       {
+               *newBrush1 = NULL;
+               *newBrush2 = NULL;
+               return;
+       }
+
+       DBrush* b1 = new DBrush;
+       DBrush* b2 = new DBrush;
+       
+       for(list<DPlane *>::const_iterator parsePlane=faceList.begin(); parsePlane!=faceList.end(); parsePlane++)
+       {
+               b1->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL);
+               b2->AddFace((*parsePlane)->points[0], (*parsePlane)->points[1], (*parsePlane)->points[2], NULL);
+       }
+
+       b1->AddFace(cutPlane->points[0], cutPlane->points[1], cutPlane->points[2], NULL);
+       b2->AddFace(cutPlane->points[2], cutPlane->points[1], cutPlane->points[0], NULL);
+
+       b1->RemoveRedundantPlanes();
+       b2->RemoveRedundantPlanes();
+
+       *newBrush1 = b1;
+       *newBrush2 = b2;
+}
+
+bool DBrush::IntersectsWith(DBrush *chkBrush)
+{
+       if(pointList.size() == 0)
+               if(BuildPoints() == 0)
+                       return FALSE;   // invalid brush!!!!
+
+       if(chkBrush->pointList.size() == 0)
+               if(chkBrush->BuildPoints() == 0)
+                       return FALSE;   // invalid brush!!!!
+       
+       if(!BBoxCollision(chkBrush))
+               return FALSE;
+
+       list<DPlane *>::const_iterator iplPlane;
+
+       for( iplPlane=faceList.begin(); iplPlane!=faceList.end(); iplPlane++)
+       {
+
+               bool allInFront = TRUE;
+               for(list<DPoint *>::const_iterator iPoint=chkBrush->pointList.begin(); iPoint!=chkBrush->pointList.end(); iPoint++)
+               {
+                       if((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR)
+                       {
+                               allInFront = FALSE;
+                               break;
+                       }
+               }
+               if(allInFront)
+                       return FALSE;
+       }
+
+       for( iplPlane=chkBrush->faceList.begin(); iplPlane!=chkBrush->faceList.end(); iplPlane++)
+       {
+               bool allInFront = TRUE;
+               for(list<DPoint *>::const_iterator iPoint=pointList.begin(); iPoint!=pointList.end(); iPoint++)
+               {
+                       if((*iplPlane)->DistanceToPoint((*iPoint)->_pnt) < -MAX_ROUND_ERROR)
+                       {
+                               allInFront = FALSE;
+                               break;
+                       }
+               }
+               if(allInFront)
+                       return FALSE;
+       }
+
+       return TRUE;
+}
+
+bool DBrush::IntersectsWith(DPlane* p1, DPlane* p2, vec3_t v) {
+       vec3_t vDown = { 0, 0, -1 };
+
+       list<DPlane *>::const_iterator iplPlane;
+       for( iplPlane = faceList.begin(); iplPlane != faceList.end(); iplPlane++) {
+               DPlane* p = (*iplPlane);
+               
+               vec_t d = DotProduct( p->normal, vDown );
+               if( d >= 0 ) {
+                       continue;
+               }
+               if(p->PlaneIntersection(p1, p2, v)) {
+                       if(PointPosition( v ) != POINT_OUT_BRUSH) {
+                               return TRUE;
+                       }
+               }
+       }
+
+       return FALSE;
+}
+
+void DBrush::BuildBounds()
+{
+       if(!bBoundsBuilt)
+       {
+               if(pointList.size() == 0) // if points may not have been built, build them
+                       if(BuildPoints() == 0)
+                               return;
+       
+               list<DPoint *>::const_iterator first = pointList.begin();
+               VectorCopy((*first)->_pnt, bbox_min);
+               VectorCopy((*first)->_pnt, bbox_max);
+
+               list<DPoint *>::const_iterator point=pointList.begin();
+               for( point++; point!=pointList.end(); point++)
+               {
+                       if((*point)->_pnt[0] > bbox_max[0])
+                               bbox_max[0] = (*point)->_pnt[0];
+                       if((*point)->_pnt[1] > bbox_max[1])
+                               bbox_max[1] = (*point)->_pnt[1];
+                       if((*point)->_pnt[2] > bbox_max[2])
+                               bbox_max[2] = (*point)->_pnt[2];
+
+                       if((*point)->_pnt[0] < bbox_min[0])
+                               bbox_min[0] = (*point)->_pnt[0];
+                       if((*point)->_pnt[1] < bbox_min[1])
+                               bbox_min[1] = (*point)->_pnt[1];
+                       if((*point)->_pnt[2] < bbox_min[2])
+                               bbox_min[2] = (*point)->_pnt[2];
+               }
+
+               bBoundsBuilt = TRUE;
+       }
+}
+
+bool DBrush::BBoxTouch(DBrush *chkBrush)
+{
+       vec3_t min1, min2;
+       vec3_t max1, max2;
+
+       GetBounds(min1, max1);
+       chkBrush->GetBounds(min2, max2);
+
+       if((min1[0] - max2[0]) > MAX_ROUND_ERROR)
+               return FALSE;
+       if((min1[1] - max2[1]) > MAX_ROUND_ERROR)
+               return FALSE;
+       if((min1[2] - max2[2]) > MAX_ROUND_ERROR)
+               return FALSE;
+
+       if((min2[0] - max1[0]) > MAX_ROUND_ERROR)
+               return FALSE;
+       if((min2[1] - max1[1]) > MAX_ROUND_ERROR)
+               return FALSE;
+       if((min2[2] - max1[2]) > MAX_ROUND_ERROR)
+               return FALSE;
+
+       int cnt = 0;
+
+       if((min2[0] - max1[0]) == 0)
+               cnt++;
+
+       if((min2[1] - max1[1]) == 0)
+               cnt++;
+
+       if((min2[2] - max1[2]) == 0)
+               cnt++;
+
+       if((min1[0] - max2[0]) == 0)
+               cnt++;
+
+       if((min1[1] - max2[1]) == 0)
+               cnt++;
+
+       if((min1[2] - max2[2]) == 0)
+               cnt++;
+
+       if(cnt > 1)
+               return FALSE;
+
+       return TRUE;
+}
+
+void DBrush::ResetChecks(list<Str>* exclusionList)
+{
+       for(list<DPlane *>::const_iterator resetPlane=faceList.begin(); resetPlane!=faceList.end(); resetPlane++)
+       {
+               bool set = FALSE;
+
+               if(exclusionList)
+               {
+                       for(list<Str>::iterator eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++)
+                       {
+                               if(strstr((*resetPlane)->texInfo.m_TextureName, eTexture->GetBuffer()))
+                               {
+                                       set = TRUE;
+                                       break;
+                               }
+                       }
+               }
+
+               (*resetPlane)->m_bChkOk = set;
+       }
+}
+
+DPlane* DBrush::HasPlaneInverted(DPlane *chkPlane)
+{
+       for(list<DPlane *>::const_iterator brushPlane=faceList.begin(); brushPlane!=faceList.end(); brushPlane++)
+       {
+               if(**brushPlane != *chkPlane)
+               {
+                       if(fabs((*brushPlane)->_d + chkPlane->_d) < 0.1)
+                               return (*brushPlane);
+               }
+       }
+       return NULL;
+}
+
+bool DBrush::HasTexture(const char *textureName)
+{
+       for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)
+       {
+               if(strstr((*chkPlane)->texInfo.m_TextureName, textureName))
+                       return TRUE;
+
+       }
+       return FALSE;
+}
+
+bool DBrush::IsDetail()
+{
+       for(list<DPlane *>::const_iterator chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)
+       {
+               if((*chkPlane)->texInfo.m_nContents & FACE_DETAIL)
+                       return TRUE;
+
+       }
+       return FALSE;
+}
+
+void DBrush::BuildFromWinding(DWinding *w)
+{
+       if(w->numpoints < 3)
+       {
+               Sys_ERROR("Winding has invalid number of points");
+               return;
+       }
+
+       DPlane* wPlane = w->WindingPlane();
+
+       DWinding* w2;
+       w2 = w->CopyWinding();
+       int i;
+       for(i = 0; i < w2->numpoints; i++)
+               VectorAdd(w2->p[i], wPlane->normal, w2->p[i]);
+
+       AddFace(w2->p[0], w2->p[1], w2->p[2], NULL);
+       AddFace(w->p[2], w->p[1], w->p[0], NULL);
+
+       for(i = 0; i < w->numpoints-1; i++)
+               AddFace(w2->p[i], w->p[i], w->p[i+1], NULL);
+       AddFace(w2->p[w->numpoints-1], w->p[w->numpoints-1], w->p[0], NULL);
+
+       delete wPlane;
+       delete w2;
+}
+
+void DBrush::SaveToFile(FILE *pFile)
+{
+       fprintf(pFile, "{\n");
+
+       for(list<DPlane *>::const_iterator pp=faceList.begin(); pp!=faceList.end(); pp++)
+       {
+               char buffer[512];
+
+               sprintf(buffer, "( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) ( %.0f %.0f %.0f ) %s %.0f %.0f %f %f %.0f 0 0 0\n",
+                       (*pp)->points[0][0], (*pp)->points[0][1], (*pp)->points[0][2], 
+                       (*pp)->points[1][0], (*pp)->points[1][1], (*pp)->points[1][2], 
+                       (*pp)->points[2][0], (*pp)->points[2][1], (*pp)->points[2][2], 
+                       (*pp)->texInfo.m_TextureName,
+                       (*pp)->texInfo.m_fShift[0], (*pp)->texInfo.m_fShift[1], 
+                       (*pp)->texInfo.m_fScale[0], (*pp)->texInfo.m_fScale[0], 
+                       (*pp)->texInfo.m_fRotate);
+
+               fprintf(pFile, buffer);
+       }
+
+       fprintf(pFile, "}\n");
+}
+
+void DBrush::Rotate(vec3_t vOrigin, vec3_t vRotation)
+{
+       for(list<DPlane *>::const_iterator rotPlane=faceList.begin(); rotPlane!=faceList.end(); rotPlane++)
+       {
+               for(int i = 0; i < 3; i++)
+                       VectorRotate((*rotPlane)->points[i], vRotation, vOrigin);
+
+               (*rotPlane)->Rebuild();
+       }
+}
+
+void DBrush::RotateAboutCentre(vec3_t vRotation)
+{
+       vec3_t min, max, centre;
+       GetBounds(min, max);
+       VectorAdd(min, max, centre);
+       VectorScale(centre, 0.5f, centre);
+
+       Rotate(centre, vRotation);
+}
+
+bool DBrush::ResetTextures(const char* textureName, float fScale[2],    float fShift[2],    int rotation, const char* newTextureName, 
+                           int bResetTextureName,   int bResetScale[2], int bResetShift[2], int bResetRotation)
+{
+       if(textureName)
+       {
+               bool changed = FALSE;
+               for(list<DPlane *>::const_iterator resetPlane=faceList.begin(); resetPlane!=faceList.end(); resetPlane++)
+               {
+                       if(!strcmp((*resetPlane)->texInfo.m_TextureName, textureName))
+                       {
+        if(bResetTextureName)
+                                 strcpy((*resetPlane)->texInfo.m_TextureName, newTextureName);
+
+                               if(bResetScale[0])
+                                       (*resetPlane)->texInfo.m_fScale[0] = fScale[0];
+                               if(bResetScale[1])
+                                       (*resetPlane)->texInfo.m_fScale[1] = fScale[1];
+
+                               if(bResetShift[0])
+                                       (*resetPlane)->texInfo.m_fShift[0] = fShift[0];
+                               if(bResetShift[1])
+                                       (*resetPlane)->texInfo.m_fShift[1] = fShift[1];
+
+                               if(bResetRotation)
+                                       (*resetPlane)->texInfo.m_fRotate = (float)rotation;
+
+                               changed = TRUE;
+                       }
+               }
+               return changed; // no point rebuilding unless we need to, only slows things down
+       }
+       else
+       {
+               for(list<DPlane *>::const_iterator resetPlane=faceList.begin(); resetPlane!=faceList.end(); resetPlane++)
+               {
+        if(bResetTextureName)
+                                 strcpy((*resetPlane)->texInfo.m_TextureName, newTextureName);
+
+                               if(bResetScale[0])
+                                       (*resetPlane)->texInfo.m_fScale[0] = fScale[0];
+                               if(bResetScale[1])
+                                       (*resetPlane)->texInfo.m_fScale[1] = fScale[1];
+
+                               if(bResetShift[0])
+                                       (*resetPlane)->texInfo.m_fShift[0] = fShift[0];
+                               if(bResetShift[1])
+                                       (*resetPlane)->texInfo.m_fShift[1] = fShift[1];
+
+                               if(bResetRotation)
+                                       (*resetPlane)->texInfo.m_fRotate = (float)rotation;
+               }
+               return TRUE;
+       }
+}
+
+bool DBrush::operator ==(DBrush* other)
+{
+       list<DPlane *>::const_iterator chkPlane;
+       
+       for(chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)
+       {
+               if(!other->HasPlane((*chkPlane)))
+                       return FALSE;
+       }
+
+       for(chkPlane=faceList.begin(); chkPlane!=faceList.end(); chkPlane++)
+       {
+               if(!HasPlane((*chkPlane)))
+                       return FALSE;
+       }
+
+       return TRUE;
+}
+
+DPlane* DBrush::AddFace(vec3_t va, vec3_t vb, vec3_t vc, const char *textureName, bool bDetail)
+{
+       bBoundsBuilt = FALSE;
+       DPlane* newFace = new DPlane(va, vb, vc, textureName, bDetail);
+       faceList.push_back(newFace);
+       
+       return newFace;
+}
+
+DPlane* DBrush::FindPlaneWithClosestNormal( vec_t* normal ) {
+       vec_t bestDot = -2;
+       DPlane* bestDotPlane = NULL;
+       list<DPlane *>::const_iterator chkPlane;
+       for( chkPlane = faceList.begin(); chkPlane != faceList.end(); chkPlane++ ) {
+               DPlane* pPlane = (*chkPlane);
+
+               vec_t dot = DotProduct( pPlane->normal, normal );
+               if( dot > bestDot ) {
+                       bestDot = dot;
+                       bestDotPlane = pPlane;
+               }
+       }
+
+       return bestDotPlane;
+}
+
+int DBrush::FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts ) {
+       int numpnts = 0;
+
+       if(!maxpnts) {
+               return 0;
+       }
+
+       BuildPoints();
+
+       for( list<DPoint *>::const_iterator points = pointList.begin(); points != pointList.end(); points++ ) {
+               DPoint* point = (*points);
+
+               if( fabs(plane->DistanceToPoint( point->_pnt )) < MAX_ROUND_ERROR ) {
+                       pnts[numpnts] = point;
+                       numpnts++;
+
+                       if(numpnts >= maxpnts) {
+                               return numpnts;
+                       }
+
+               }
+       }
+
+       return numpnts;
+}
+
+void DBrush::RemovePlane( DPlane* plane ) {
+       bBoundsBuilt = FALSE;
+       for( list<DPlane *>::const_iterator deadPlane = faceList.begin(); deadPlane != faceList.end(); deadPlane++ ) {          
+               if(*deadPlane == plane) {
+                       delete *deadPlane;
+                       faceList.remove( plane );
+               }
+       }
+}
+
+void DBrush::RemoveFromRadiant( void ) {
+       if(QER_brush) {
+               g_FuncTable.m_pfnDeleteBrushHandle(QER_brush);
+       }
+}
index b52ad5c..9d5da9d 100644 (file)
@@ -1,49 +1,49 @@
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// DEPair.cpp: implementation of the DEPair class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-#include "DEPair.h"\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DEPair::DEPair()\r
-{\r
-\r
-}\r
-\r
-DEPair::~DEPair()\r
-{\r
-\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Implementation\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void DEPair::Build(char *pKey, char *pValue)\r
-{\r
-  key = pKey;\r
-  value = pValue;\r
-}\r
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DEPair.cpp: implementation of the DEPair class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "StdAfx.h"
+#include "DEPair.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+DEPair::DEPair()
+{
+
+}
+
+DEPair::~DEPair()
+{
+
+}
+
+//////////////////////////////////////////////////////////////////////
+// Implementation
+//////////////////////////////////////////////////////////////////////
+
+void DEPair::Build(char *pKey, char *pValue)
+{
+  key = pKey;
+  value = pValue;
+}
index 2c4e8a2..4d3610c 100644 (file)
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// DEntity.cpp: implementation of the DEntity class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-\r
-#ifdef _WIN32\r
-#pragma warning(disable : 4786)\r
-#endif\r
-\r
-#include "DEntity.h"\r
-\r
-#include "dialogs-gtk.h"\r
-#include "misc.h"\r
-#include "CPortals.h"\r
-\r
-const char* brushEntityList[] = {\r
-       "worldspawn",\r
-       "trigger_always",\r
-       "trigger_hurt",\r
-       "trigger_multiple",\r
-       "trigger_push",\r
-       "trigger_teleport",\r
-       "func_bobbing",\r
-       "func_button",\r
-       "func_door",\r
-       "func_group",\r
-       "func_pendulum",\r
-       "func_plat",\r
-       "func_rotating",\r
-       "func_static",\r
-       "func_timer",\r
-       "func_train",\r
-       0\r
-};\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DEntity::DEntity(char *classname, int ID)\r
-{\r
-       SetClassname(classname);\r
-       m_nID = ID;\r
-       QER_Entity = NULL;\r
-}\r
-\r
-DEntity::~DEntity()\r
-{\r
-       ClearPatches();\r
-       ClearBrushes();\r
-       ClearEPairs();\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Implementation\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-void DEntity::ClearBrushes()\r
-{\r
-       for(list<DBrush *>::const_iterator deadBrush=brushList.begin(); deadBrush!=brushList.end(); deadBrush++)\r
-       {\r
-               delete *deadBrush;\r
-       }\r
-       brushList.clear();\r
-}\r
-\r
-void DEntity::ClearPatches()\r
-{\r
-       for(list<DPatch *>::const_iterator deadPatch=patchList.begin(); deadPatch!=patchList.end(); deadPatch++)\r
-       {\r
-               delete *deadPatch;\r
-       }\r
-       patchList.clear();\r
-}\r
-\r
-DPatch* DEntity::NewPatch()\r
-{\r
-       DPatch* newPatch = new DPatch;\r
-\r
-       patchList.push_back(newPatch);\r
-\r
-       return newPatch;\r
-}\r
-\r
-DBrush* DEntity::NewBrush(int ID)\r
-{\r
-       DBrush* newBrush = new DBrush(ID);\r
-\r
-       brushList.push_back(newBrush);\r
-\r
-       return newBrush;\r
-}\r
-\r
-char* getNextBracket(char* s)\r
-{\r
-       char* p = s;\r
-       while(*p)\r
-       {\r
-               p++;\r
-               if(*p == '(')\r
-                       break;\r
-       }\r
-\r
-       return p;\r
-}\r
-\r
-bool DEntity::LoadFromPrt(char *filename)\r
-{\r
-       CPortals portals;\r
-       strcpy(portals.fn, filename);\r
-       portals.Load();\r
-\r
-       if(portals.node_count == 0)\r
-               return FALSE;\r
-\r
-       ClearBrushes();\r
-       ClearEPairs();\r
-       \r
-  bool build = false;\r
-       for(unsigned int i = 0; i < portals.node_count; i++)\r
-       {\r
-    build = false;\r
-               DBrush* brush = NewBrush();\r
-\r
-               for(unsigned int j = 0; j < portals.node[i].portal_count; j++)\r
-               {\r
-      for(unsigned int k = 0; k < portals.node[i].portal[j].point_count-2; k++) \r
-      {\r
-             vec3_t v1, v2, normal, n;\r
-             VectorSubtract(portals.node[i].portal[j].point[k+2].p, portals.node[i].portal[j].point[k+1].p, v1);\r
-             VectorSubtract(portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k+1].p, v2);\r
-             CrossProduct(v1, v2, n);\r
-        VectorNormalize(n, v2);\r
-\r
-        if(k == 0) \r
-        {\r
-          VectorCopy(v2, normal);\r
-        }\r
-        else\r
-        {\r
-          VectorSubtract(v2, normal, v1);\r
-          if(VectorLength(v1) > 0.01)\r
-          {\r
-            build = true;\r
-            break;\r
-          }\r
-        }\r
-      }\r
-\r
-      if(!build)\r
-                         brush->AddFace(portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[0].p, "textures/common/caulk", FALSE);\r
-      else\r
-                         brush->AddFace(portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[2].p, "textures/common/caulk", FALSE);\r
-               }\r
-    if(build)\r
-      brush->BuildInRadiant(FALSE, NULL);\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-DPlane* DEntity::AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID)\r
-{\r
-       DBrush* buildBrush = GetBrushForID(ID);\r
-       return buildBrush->AddFace(va, vb, vc, faceData);\r
-       // slow, dont use much\r
-}\r
-\r
-DBrush* DEntity::GetBrushForID(int ID)\r
-{\r
-       DBrush* buildBrush = NULL;\r
-\r
-       for(list<DBrush *>::const_iterator chkBrush=brushList.begin(); chkBrush!=brushList.end(); chkBrush++)\r
-       {\r
-               if((*chkBrush)->m_nBrushID == ID)\r
-               {\r
-                       buildBrush = (*chkBrush);\r
-                       break;\r
-               }\r
-       }\r
-\r
-       if(!buildBrush)\r
-               buildBrush = NewBrush(ID);\r
-\r
-       return buildBrush;\r
-}\r
-\r
-void DEntity::LoadSelectedBrushes()\r
-{\r
-       ClearBrushes();\r
-       ClearEPairs();\r
-\r
-       int count = g_FuncTable.m_pfnAllocateSelectedBrushHandles();\r
-\r
-       for(int i = 0; i < count; i++) {\r
-               brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(i);\r
-\r
-               if(brush->pPatch)\r
-                       continue;\r
-\r
-               DBrush* loadBrush = NewBrush(i);\r
-               loadBrush->LoadFromBrush_t(brush, TRUE);\r
-       }\r
-\r
-       g_FuncTable.m_pfnReleaseSelectedBrushHandles();\r
-}\r
-\r
-void DEntity::LoadSelectedPatches()\r
-{\r
-       ClearPatches();\r
-       ClearEPairs();\r
-\r
-  int count = g_FuncTable.m_pfnAllocateSelectedPatchHandles();\r
-\r
-       for(int i = 0; i < count; i++)\r
-       {\r
-    //$ FIXME: m_pfnGetPatchHandle\r
-               patchMesh_t *pmesh = (patchMesh_t*)g_FuncTable.m_pfnGetPatchData(i);\r
-\r
-               DPatch* loadPatch = NewPatch();\r
-               loadPatch->LoadFromBrush_t(pmesh->pSymbiot);\r
-       }\r
-\r
-  g_FuncTable.m_pfnReleasePatchHandles();\r
-}\r
-\r
-bool* DEntity::BuildIntersectList()\r
-{\r
-       int max = GetIDMax();\r
-       if(max == 0)\r
-               return NULL;\r
-\r
-       bool* pbIntList = new bool[max];\r
-       memset(pbIntList, 0, sizeof(bool)*(max));\r
-\r
-       for(list<DBrush *>::const_iterator pB1=brushList.begin(); pB1!=brushList.end(); pB1++)\r
-       {\r
-               list<DBrush *>::const_iterator pB2=pB1;\r
-               for(pB2++; pB2!=brushList.end(); pB2++)\r
-               {\r
-                       if((*pB1)->IntersectsWith((*pB2)))\r
-                       {\r
-                               pbIntList[(*pB1)->m_nBrushID] = TRUE;\r
-                               pbIntList[(*pB2)->m_nBrushID] = TRUE;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return pbIntList;\r
-}\r
-\r
-bool* DEntity::BuildDuplicateList()\r
-{\r
-       int max = GetIDMax();\r
-       if(max == 0)\r
-               return NULL;\r
-\r
-       bool* pbDupList = new bool[max];\r
-       memset(pbDupList, 0, sizeof(bool)*(max));\r
-\r
-       for(list<DBrush *>::const_iterator pB1=brushList.begin(); pB1!=brushList.end(); pB1++)\r
-       {\r
-               list<DBrush *>::const_iterator pB2=pB1;\r
-               for(pB2++; pB2!=brushList.end(); pB2++)\r
-               {\r
-                       if(**pB1 == *pB2)\r
-                       {\r
-                               pbDupList[(*pB1)->m_nBrushID] = TRUE;\r
-                               pbDupList[(*pB2)->m_nBrushID] = TRUE;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return pbDupList;\r
-}\r
-\r
-void DEntity::SelectBrushes(bool *selectList)\r
-{\r
-       if(selectList == NULL)\r
-               return;\r
-\r
-       g_FuncTable.m_pfnDeselectAllBrushes();\r
-\r
-       g_FuncTable.m_pfnAllocateActiveBrushHandles();\r
-\r
-       for(std::list<DBrush *>::const_iterator pBrush=brushList.begin(); pBrush!=brushList.end(); pBrush++)\r
-       {\r
-               if(selectList[(*pBrush)->m_nBrushID])\r
-                       g_FuncTable.m_pfnSelectBrush((*pBrush)->QER_brush);\r
-       }\r
-       g_FuncTable.m_pfnReleaseActiveBrushHandles();\r
-}\r
-\r
-bool DEntity::LoadFromEntity(int id, bool bLoadPatches) {\r
-       return LoadFromEntity((entity_t*)g_FuncTable.m_pfnGetEntityHandle(id), bLoadPatches);\r
-}\r
-\r
-bool DEntity::LoadFromEntity(entity_t* ent, bool bLoadPatches) {\r
-       ClearPatches();\r
-       ClearBrushes();\r
-       ClearEPairs();\r
-\r
-       QER_Entity = ent;\r
-\r
-       epair_t* epl = *g_EntityTable.m_pfnGetEntityKeyValList(QER_Entity);\r
-       LoadEPairList(epl);\r
-\r
-       bool keep = FALSE;\r
-       int i;\r
-       for(i = 0; brushEntityList[i]; i++)\r
-       {\r
-               if(!stricmp(brushEntityList[i], m_Classname))\r
-               {\r
-                       keep = TRUE;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       if(!keep)\r
-               return FALSE;\r
-\r
-       int count = g_FuncTable.m_pfnAllocateEntityBrushHandles(QER_Entity);\r
-\r
-       for(i = 0; i < count; i++)\r
-       {\r
-\r
-               brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetEntityBrushHandle(i);\r
-\r
-    if(brush == NULL) {\r
-                       DoMessageBox("GTKRadiant returned a NULL pointer, NOT a good sign", "WARNING!!!", MB_OK);\r
-      continue;\r
-    }\r
-\r
-               if(brush->pPatch)\r
-               {\r
-                       if(bLoadPatches)\r
-                       {\r
-                               DPatch* loadPatch = NewPatch();\r
-                               loadPatch->LoadFromBrush_t(brush);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       DBrush* loadBrush = NewBrush(i);\r
-                       loadBrush->LoadFromBrush_t(brush, TRUE);\r
-               }\r
-       }\r
-\r
-       g_FuncTable.m_pfnReleaseEntityBrushHandles();\r
-\r
-       return TRUE;\r
-}\r
-\r
-void DEntity::RemoveNonCheckBrushes(list<Str>* exclusionList, bool useDetail)\r
-{\r
-       list<DBrush *>::iterator chkBrush=brushList.begin();\r
-\r
-       while( chkBrush!=brushList.end() )\r
-       {\r
-               if(!useDetail)\r
-               {\r
-                       if((*chkBrush)->IsDetail())\r
-                       {\r
-                               delete *chkBrush;\r
-                               chkBrush = brushList.erase(chkBrush);\r
-                               continue;\r
-                       }\r
-               }\r
-\r
-               list<Str>::iterator eTexture;\r
-\r
-               for( eTexture=exclusionList->begin(); eTexture!=exclusionList->end(); eTexture++ )\r
-               {\r
-                       if((*chkBrush)->HasTexture((*eTexture).GetBuffer()))\r
-                       {\r
-                               delete *chkBrush;\r
-                               chkBrush = brushList.erase(chkBrush);\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               if( eTexture == exclusionList->end() )\r
-                       chkBrush++;\r
-       }\r
-}\r
-\r
-void DEntity::ResetChecks(list<Str>* exclusionList)\r
-{\r
-       for(list<DBrush *>::const_iterator resetBrush=brushList.begin(); resetBrush!=brushList.end(); resetBrush++)\r
-       {\r
-               (*resetBrush)->ResetChecks(exclusionList);\r
-       }\r
-}\r
-\r
-int DEntity::FixBrushes(bool rebuild)\r
-{\r
-       g_FuncTable.m_pfnAllocateActiveBrushHandles();\r
-\r
-       int cnt = 0;\r
-\r
-       for(list<DBrush *>::const_iterator fixBrush=brushList.begin(); fixBrush!=brushList.end(); fixBrush++)\r
-       {\r
-               int count = (*fixBrush)->RemoveRedundantPlanes();\r
-               if(count)\r
-               {\r
-                       cnt += count;\r
-                       if(rebuild)\r
-                       {\r
-                               g_FuncTable.m_pfnDeleteBrushHandle((*fixBrush)->QER_brush);\r
-\r
-                               (*fixBrush)->BuildInRadiant(FALSE, NULL);\r
-                       }\r
-               }\r
-       }\r
-\r
-       g_FuncTable.m_pfnReleaseActiveBrushHandles();\r
-\r
-       return cnt;\r
-}\r
-\r
-void DEntity::BuildInRadiant(bool allowDestruction)\r
-{\r
-       bool makeEntity = strcmp(m_Classname, "worldspawn") ? true : false;\r
-\r
-       if(makeEntity)\r
-       {\r
-               entity_t* pE = (entity_t*)g_FuncTable.m_pfnCreateEntityHandle();\r
-\r
-               epair_t* pEpS = GetNextChainItem(NULL, "classname", m_Classname);\r
-\r
-               epair_t* pEp = pEpS;\r
-\r
-               for(list<DEPair* >::const_iterator buildEPair=epairList.begin(); buildEPair!=epairList.end(); buildEPair++)\r
-               {\r
-                       pEp = GetNextChainItem(pEp, (*buildEPair)->key, (*buildEPair)->value);\r
-               }\r
-\r
-               g_EntityTable.m_pfnSetEntityKeyValList(pE, pEpS);\r
-\r
-               g_FuncTable.m_pfnCommitEntityHandleToMap(pE);\r
-\r
-               for(list<DBrush *>::const_iterator buildBrush=brushList.begin(); buildBrush!=brushList.end(); buildBrush++)\r
-                       (*buildBrush)->BuildInRadiant(allowDestruction, NULL, pE);\r
-\r
-               for(list<DPatch *>::const_iterator buildPatch=patchList.begin(); buildPatch!=patchList.end(); buildPatch++)\r
-                       (*buildPatch)->BuildInRadiant(pE);\r
-\r
-               QER_Entity = pE;\r
-       }\r
-       else\r
-       {\r
-               for(list<DBrush *>::const_iterator buildBrush=brushList.begin(); buildBrush!=brushList.end(); buildBrush++)\r
-                       (*buildBrush)->BuildInRadiant(allowDestruction, NULL);\r
-\r
-               for(list<DPatch *>::const_iterator buildPatch=patchList.begin(); buildPatch!=patchList.end(); buildPatch++)\r
-                       (*buildPatch)->BuildInRadiant();\r
-       }\r
-}\r
-\r
-\r
-\r
-int DEntity::GetIDMax( void ) {\r
-       int max = -1;\r
-       for(list<DBrush *>::const_iterator cntBrush=brushList.begin(); cntBrush!=brushList.end(); cntBrush++) {\r
-               if((*cntBrush)->m_nBrushID > max)\r
-                       max = (*cntBrush)->m_nBrushID;\r
-       }\r
-       return max+1;\r
-}\r
-\r
-void DEntity::SetClassname( char *classname ) {\r
-       m_Classname = classname;\r
-}\r
-\r
-void DEntity::SaveToFile(FILE *pFile)\r
-{\r
-       fprintf(pFile, "{\n");\r
-\r
-       fprintf(pFile, "\"classname\" \"%s\"\n", (const char *)m_Classname);\r
-\r
-       for(list<DEPair *>::const_iterator ep=epairList.begin(); ep!=epairList.end(); ep++)\r
-       {\r
-               fprintf(pFile, "\"%s\" \"%s\"\n", (const char *)(*ep)->key, (const char *)(*ep)->value);\r
-       }\r
-\r
-       for(list<DBrush *>::const_iterator bp=brushList.begin(); bp!=brushList.end(); bp++)\r
-       {\r
-               (*bp)->SaveToFile(pFile);\r
-       }\r
-\r
-       fprintf(pFile, "}\n");\r
-}\r
-\r
-void DEntity::ClearEPairs()\r
-{\r
-       for(list<DEPair *>::const_iterator deadEPair=epairList.begin(); deadEPair!=epairList.end(); deadEPair++)\r
-       {\r
-               delete (*deadEPair);\r
-       }\r
-       epairList.clear();\r
-}\r
-\r
-void DEntity::AddEPair(char *key, char *value) {       \r
-       DEPair* newEPair; \r
-       newEPair = FindEPairByKey( key );\r
-       if(!newEPair) {\r
-               newEPair = new DEPair;\r
-               newEPair->Build(key, value);\r
-               epairList.push_back(newEPair);\r
-       } else {\r
-               newEPair->Build(key, value);\r
-       }\r
-}\r
-\r
-void DEntity::LoadEPairList(epair_t *epl)\r
-{\r
-       epair_t* ep = epl;\r
-       while(ep)\r
-       {\r
-               if(!strcmp(ep->key, "classname"))\r
-                       SetClassname(ep->value);\r
-               else    \r
-                       AddEPair(ep->key, ep->value);\r
-\r
-               ep = ep->next;\r
-       }\r
-}\r
-\r
-bool DEntity::ResetTextures(const char* textureName, float fScale[2],     float fShift[2],    int rotation, const char* newTextureName, \r
-                            int bResetTextureName,    int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild)\r
-{\r
-       g_FuncTable.m_pfnDeselectAllBrushes();\r
-\r
-       g_FuncTable.m_pfnAllocateActiveBrushHandles();\r
-\r
-       bool reset = FALSE;\r
-\r
-       for(list<DBrush *>::const_iterator resetBrush=brushList.begin(); resetBrush!=brushList.end(); resetBrush++)\r
-       {\r
-               bool tmp = (*resetBrush)->ResetTextures(textureName,        fScale,       fShift,       rotation, newTextureName, \r
-                                            bResetTextureName,  bResetScale,  bResetShift,  bResetRotation);\r
-\r
-               if(tmp)\r
-               {\r
-                       reset = TRUE;\r
-\r
-                       if(rebuild)\r
-                       {\r
-        entity_t *pE = (*resetBrush)->QER_brush->owner;       \r
-                               g_FuncTable.m_pfnDeleteBrushHandle((*resetBrush)->QER_brush);\r
-        (*resetBrush)->BuildInRadiant(FALSE, NULL, pE->entityId == 0 ? NULL : pE);\r
-\r
-        if( pE->entityId == 0 ? NULL : pE )\r
-        {\r
-        }\r
-                       }\r
-               }\r
-       }\r
-\r
-  if(bResetTextureName)\r
-  {\r
-         for(list<DPatch *>::const_iterator resetPatch=patchList.begin(); resetPatch!=patchList.end(); resetPatch++)\r
-         {\r
-                 bool tmp = (*resetPatch)->ResetTextures(textureName, newTextureName);\r
-\r
-                 if(tmp)\r
-                 {\r
-                         reset = TRUE;\r
-\r
-                         if(rebuild)\r
-                         {\r
-          entity_t *pE = (*resetPatch)->QER_brush->owner;       \r
-                                 g_FuncTable.m_pfnDeleteBrushHandle((*resetPatch)->QER_brush);\r
-          (*resetPatch)->BuildInRadiant(pE->entityId == 0 ? NULL : pE);\r
-                         }\r
-                 }\r
-         }\r
-  }\r
-\r
-       g_FuncTable.m_pfnReleaseActiveBrushHandles();\r
-\r
-       return reset;\r
-}\r
-\r
-DEPair* DEntity::FindEPairByKey(const char* keyname)\r
-{\r
-       for(list<DEPair *>::const_iterator ep=epairList.begin(); ep!=epairList.end(); ep++)\r
-       {\r
-               char* c = (*ep)->key;\r
-               if(!strcmp(c, keyname))\r
-                       return *ep;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-void DEntity::RemoveFromRadiant()\r
-{\r
-       g_EntityTable.m_pfnEntity_Free( (entity_t*)QER_Entity );\r
-\r
-       QER_Entity = NULL;\r
-}\r
-\r
-void DEntity::SpawnString(const char* key, const char* defaultstring, const char** out)\r
-{\r
-       DEPair* pEP = FindEPairByKey(key);\r
-       if(pEP) {\r
-               *out = pEP->value;\r
-       } else {\r
-               *out = defaultstring;\r
-       }\r
-}\r
-\r
-void DEntity::SpawnInt(const char* key, const char* defaultstring, int* out)\r
-{\r
-       DEPair* pEP = FindEPairByKey(key);\r
-       if(pEP) {\r
-               *out = atoi(pEP->value);\r
-       } else {\r
-               *out = atoi(defaultstring);\r
-       }\r
-}\r
-\r
-void DEntity::SpawnFloat(const char* key, const char* defaultstring, float* out)\r
-{\r
-       DEPair* pEP = FindEPairByKey(key);\r
-       if(pEP) {\r
-               *out = static_cast< float >( atof( pEP->value ) );\r
-       } else {\r
-               *out = static_cast< float >( atof(defaultstring) );\r
-       }\r
-}\r
-\r
-void DEntity::SpawnVector(const char* key, const char* defaultstring, vec_t* out)\r
-{\r
-       DEPair* pEP = FindEPairByKey(key);\r
-       if(pEP) {\r
-               sscanf(pEP->value, "%f %f %f", &out[0], &out[1], &out[2]);\r
-       } else {\r
-               sscanf(defaultstring, "%f %f %f", &out[0], &out[1], &out[2]);\r
-       }\r
-}\r
-\r
-int DEntity::GetBrushCount( void ) {\r
-       return brushList.size();\r
-}\r
-\r
-DBrush* DEntity::FindBrushByPointer( brush_t* brush ) {\r
-       for(list<DBrush *>::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++) {\r
-               DBrush* pBrush = (*listBrush);\r
-               if(pBrush->QER_brush == brush) {\r
-                       return pBrush;\r
-               }\r
-       }\r
-       return NULL;\r
-}\r
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DEntity.cpp: implementation of the DEntity class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4786)
+#endif
+
+#include "DEntity.h"
+
+#include "dialogs-gtk.h"
+#include "misc.h"
+#include "CPortals.h"
+
+const char* brushEntityList[] = {
+       "worldspawn",
+       "trigger_always",
+       "trigger_hurt",
+       "trigger_multiple",
+       "trigger_push",
+       "trigger_teleport",
+       "func_bobbing",
+       "func_button",
+       "func_door",
+       "func_group",
+       "func_pendulum",
+       "func_plat",
+       "func_rotating",
+       "func_static",
+       "func_timer",
+       "func_train",
+       0
+};
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+DEntity::DEntity(char *classname, int ID)
+{
+       SetClassname(classname);
+       m_nID = ID;
+       QER_Entity = NULL;
+}
+
+DEntity::~DEntity()
+{
+       ClearPatches();
+       ClearBrushes();
+       ClearEPairs();
+}
+
+//////////////////////////////////////////////////////////////////////
+// Implementation
+//////////////////////////////////////////////////////////////////////
+
+void DEntity::ClearBrushes()
+{
+       for(list<DBrush *>::const_iterator deadBrush=brushList.begin(); deadBrush!=brushList.end(); deadBrush++)
+       {
+               delete *deadBrush;
+       }
+       brushList.clear();
+}
+
+void DEntity::ClearPatches()
+{
+       for(list<DPatch *>::const_iterator deadPatch=patchList.begin(); deadPatch!=patchList.end(); deadPatch++)
+       {
+               delete *deadPatch;
+       }
+       patchList.clear();
+}
+
+DPatch* DEntity::NewPatch()
+{
+       DPatch* newPatch = new DPatch;
+
+       patchList.push_back(newPatch);
+
+       return newPatch;
+}
+
+DBrush* DEntity::NewBrush(int ID)
+{
+       DBrush* newBrush = new DBrush(ID);
+
+       brushList.push_back(newBrush);
+
+       return newBrush;
+}
+
+char* getNextBracket(char* s)
+{
+       char* p = s;
+       while(*p)
+       {
+               p++;
+               if(*p == '(')
+                       break;
+       }
+
+       return p;
+}
+
+bool DEntity::LoadFromPrt(char *filename)
+{
+       CPortals portals;
+       strcpy(portals.fn, filename);
+       portals.Load();
+
+       if(portals.node_count == 0)
+               return FALSE;
+
+       ClearBrushes();
+       ClearEPairs();
+       
+  bool build = false;
+       for(unsigned int i = 0; i < portals.node_count; i++)
+       {
+    build = false;
+               DBrush* brush = NewBrush();
+
+               for(unsigned int j = 0; j < portals.node[i].portal_count; j++)
+               {
+      for(unsigned int k = 0; k < portals.node[i].portal[j].point_count-2; k++) 
+      {
+             vec3_t v1, v2, normal, n;
+             VectorSubtract(portals.node[i].portal[j].point[k+2].p, portals.node[i].portal[j].point[k+1].p, v1);
+             VectorSubtract(portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k+1].p, v2);
+             CrossProduct(v1, v2, n);
+        VectorNormalize(n, v2);
+
+        if(k == 0) 
+        {
+          VectorCopy(v2, normal);
+        }
+        else
+        {
+          VectorSubtract(v2, normal, v1);
+          if(VectorLength(v1) > 0.01)
+          {
+            build = true;
+            break;
+          }
+        }
+      }
+
+      if(!build)
+                         brush->AddFace(portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[0].p, "textures/common/caulk", FALSE);
+      else
+                         brush->AddFace(portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[2].p, "textures/common/caulk", FALSE);
+               }
+    if(build)
+      brush->BuildInRadiant(FALSE, NULL);
+       }
+
+       return TRUE;
+}
+
+DPlane* DEntity::AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID)
+{
+       DBrush* buildBrush = GetBrushForID(ID);
+       return buildBrush->AddFace(va, vb, vc, faceData);
+       // slow, dont use much
+}
+
+DBrush* DEntity::GetBrushForID(int ID)
+{
+       DBrush* buildBrush = NULL;
+
+       for(list<DBrush *>::const_iterator chkBrush=brushList.begin(); chkBrush!=brushList.end(); chkBrush++)
+       {
+               if((*chkBrush)->m_nBrushID == ID)
+               {
+                       buildBrush = (*chkBrush);
+                       break;
+               }
+       }
+
+       if(!buildBrush)
+               buildBrush = NewBrush(ID);
+
+       return buildBrush;
+}
+
+void DEntity::LoadSelectedBrushes()
+{
+       ClearBrushes();
+       ClearEPairs();
+
+       int count = g_FuncTable.m_pfnAllocateSelectedBrushHandles();
+
+       for(int i = 0; i < count; i++) {
+               brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(i);
+
+               if(brush->pPatch)
+                       continue;
+
+               DBrush* loadBrush = NewBrush(i);
+               loadBrush->LoadFromBrush_t(brush, TRUE);
+       }
+
+       g_FuncTable.m_pfnReleaseSelectedBrushHandles();
+}
+
+void DEntity::LoadSelectedPatches()
+{
+       ClearPatches();
+       ClearEPairs();
+
+  int count = g_FuncTable.m_pfnAllocateSelectedPatchHandles();
+
+       for(int i = 0; i < count; i++)
+       {
+    //$ FIXME: m_pfnGetPatchHandle
+               patchMesh_t *pmesh = (patchMesh_t*)g_FuncTable.m_pfnGetPatchData(i);
+
+               DPatch* loadPatch = NewPatch();
+               loadPatch->LoadFromBrush_t(pmesh->pSymbiot);
+       }
+
+  g_FuncTable.m_pfnReleasePatchHandles();
+}
+
+bool* DEntity::BuildIntersectList()
+{
+       int max = GetIDMax();
+       if(max == 0)
+               return NULL;
+
+       bool* pbIntList = new bool[max];
+       memset(pbIntList, 0, sizeof(bool)*(max));
+
+       for(list<DBrush *>::const_iterator pB1=brushList.begin(); pB1!=brushList.end(); pB1++)
+       {
+               list<DBrush *>::const_iterator pB2=pB1;
+               for(pB2++; pB2!=brushList.end(); pB2++)
+               {
+                       if((*pB1)->IntersectsWith((*pB2)))
+                       {
+                               pbIntList[(*pB1)->m_nBrushID] = TRUE;
+                               pbIntList[(*pB2)->m_nBrushID] = TRUE;
+                       }
+               }
+       }
+
+       return pbIntList;
+}
+
+bool* DEntity::BuildDuplicateList()
+{
+       int max = GetIDMax();
+       if(max == 0)
+               return NULL;
+
+       bool* pbDupList = new bool[max];
+       memset(pbDupList, 0, sizeof(bool)*(max));
+
+       for(list<DBrush *>::const_iterator pB1=brushList.begin(); pB1!=brushList.end(); pB1++)
+       {
+               list<DBrush *>::const_iterator pB2=pB1;
+               for(pB2++; pB2!=brushList.end(); pB2++)
+               {
+                       if(**pB1 == *pB2)
+                       {
+                               pbDupList[(*pB1)->m_nBrushID] = TRUE;
+                               pbDupList[(*pB2)->m_nBrushID] = TRUE;
+                       }
+               }
+       }
+
+       return pbDupList;
+}
+
+void DEntity::SelectBrushes(bool *selectList)
+{
+       if(selectList == NULL)
+               return;
+
+       g_FuncTable.m_pfnDeselectAllBrushes();
+
+       g_FuncTable.m_pfnAllocateActiveBrushHandles();
+
+       for(std::list<DBrush *>::const_iterator pBrush=brushList.begin(); pBrush!=brushList.end(); pBrush++)
+       {
+               if(selectList[(*pBrush)->m_nBrushID])
+                       g_FuncTable.m_pfnSelectBrush((*pBrush)->QER_brush);
+       }
+       g_FuncTable.m_pfnReleaseActiveBrushHandles();
+}
+
+bool DEntity::LoadFromEntity(int id, bool bLoadPatches) {
+       return LoadFromEntity((entity_t*)g_FuncTable.m_pfnGetEntityHandle(id), bLoadPatches);
+}
+
+bool DEntity::LoadFromEntity(entity_t* ent, bool bLoadPatches) {
+       ClearPatches();
+       ClearBrushes();
+       ClearEPairs();
+
+       QER_Entity = ent;
+
+       epair_t* epl = *g_EntityTable.m_pfnGetEntityKeyValList(QER_Entity);
+       LoadEPairList(epl);
+
+       bool keep = FALSE;
+       int i;
+       for(i = 0; brushEntityList[i]; i++)
+       {
+               if(!stricmp(brushEntityList[i], m_Classname))
+               {
+                       keep = TRUE;
+                       break;
+               }
+       }
+
+       if(!keep)
+               return FALSE;
+
+       int count = g_FuncTable.m_pfnAllocateEntityBrushHandles(QER_Entity);
+
+       for(i = 0; i < count; i++)
+       {
+
+               brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetEntityBrushHandle(i);
+
+    if(brush == NULL) {
+                       DoMessageBox("GTKRadiant returned a NULL pointer, NOT a good sign", "WARNING!!!", MB_OK);
+      continue;
+    }
+
+               if(brush->pPatch)
+               {
+                       if(bLoadPatches)
+                       {
+                               DPatch* loadPatch = NewPatch();
+                               loadPatch->LoadFromBrush_t(brush);
+                       }
+               }
+               else
+               {
+                       DBrush* loadBrush = NewBrush(i);
+                       loadBrush->LoadFromBrush_t(brush, TRUE);
+               }
+       }
+
+       g_FuncTable.m_pfnReleaseEntityBrushHandles();
+
+       return TRUE;
+}
+
+void DEntity::RemoveNonCheckBrushes(list<Str>* exclusionList, bool useDetail)
+{
+       list<DBrush *>::iterator chkBrush=brushList.begin();
+
+       while( chkBrush!=brushList.end() )
+       {
+               if(!useDetail)
+               {
+                       if((*chkBrush)->IsDetail())
+                       {
+                               delete *chkBrush;
+                               chkBrush = brushList.erase(chkBrush);
+                               continue;
+                       }
+               }
+
+               list<Str>::iterator eTexture;
+
+               for( eTexture=exclusionList->begin(); eTexture!=exclusionList->end(); eTexture++ )
+               {
+                       if((*chkBrush)->HasTexture((*eTexture).GetBuffer()))
+                       {
+                               delete *chkBrush;
+                               chkBrush = brushList.erase(chkBrush);
+                               break;
+                       }
+               }
+
+               if( eTexture == exclusionList->end() )
+                       chkBrush++;
+       }
+}
+
+void DEntity::ResetChecks(list<Str>* exclusionList)
+{
+       for(list<DBrush *>::const_iterator resetBrush=brushList.begin(); resetBrush!=brushList.end(); resetBrush++)
+       {
+               (*resetBrush)->ResetChecks(exclusionList);
+       }
+}
+
+int DEntity::FixBrushes(bool rebuild)
+{
+       g_FuncTable.m_pfnAllocateActiveBrushHandles();
+
+       int cnt = 0;
+
+       for(list<DBrush *>::const_iterator fixBrush=brushList.begin(); fixBrush!=brushList.end(); fixBrush++)
+       {
+               int count = (*fixBrush)->RemoveRedundantPlanes();
+               if(count)
+               {
+                       cnt += count;
+                       if(rebuild)
+                       {
+                               g_FuncTable.m_pfnDeleteBrushHandle((*fixBrush)->QER_brush);
+
+                               (*fixBrush)->BuildInRadiant(FALSE, NULL);
+                       }
+               }
+       }
+
+       g_FuncTable.m_pfnReleaseActiveBrushHandles();
+
+       return cnt;
+}
+
+void DEntity::BuildInRadiant(bool allowDestruction)
+{
+       bool makeEntity = strcmp(m_Classname, "worldspawn") ? true : false;
+
+       if(makeEntity)
+       {
+               entity_t* pE = (entity_t*)g_FuncTable.m_pfnCreateEntityHandle();
+
+               epair_t* pEpS = GetNextChainItem(NULL, "classname", m_Classname);
+
+               epair_t* pEp = pEpS;
+
+               for(list<DEPair* >::const_iterator buildEPair=epairList.begin(); buildEPair!=epairList.end(); buildEPair++)
+               {
+                       pEp = GetNextChainItem(pEp, (*buildEPair)->key, (*buildEPair)->value);
+               }
+
+               g_EntityTable.m_pfnSetEntityKeyValList(pE, pEpS);
+
+               g_FuncTable.m_pfnCommitEntityHandleToMap(pE);
+
+               for(list<DBrush *>::const_iterator buildBrush=brushList.begin(); buildBrush!=brushList.end(); buildBrush++)
+                       (*buildBrush)->BuildInRadiant(allowDestruction, NULL, pE);
+
+               for(list<DPatch *>::const_iterator buildPatch=patchList.begin(); buildPatch!=patchList.end(); buildPatch++)
+                       (*buildPatch)->BuildInRadiant(pE);
+
+               QER_Entity = pE;
+       }
+       else
+       {
+               for(list<DBrush *>::const_iterator buildBrush=brushList.begin(); buildBrush!=brushList.end(); buildBrush++)
+                       (*buildBrush)->BuildInRadiant(allowDestruction, NULL);
+
+               for(list<DPatch *>::const_iterator buildPatch=patchList.begin(); buildPatch!=patchList.end(); buildPatch++)
+                       (*buildPatch)->BuildInRadiant();
+       }
+}
+
+
+
+int DEntity::GetIDMax( void ) {
+       int max = -1;
+       for(list<DBrush *>::const_iterator cntBrush=brushList.begin(); cntBrush!=brushList.end(); cntBrush++) {
+               if((*cntBrush)->m_nBrushID > max)
+                       max = (*cntBrush)->m_nBrushID;
+       }
+       return max+1;
+}
+
+void DEntity::SetClassname( char *classname ) {
+       m_Classname = classname;
+}
+
+void DEntity::SaveToFile(FILE *pFile)
+{
+       fprintf(pFile, "{\n");
+
+       fprintf(pFile, "\"classname\" \"%s\"\n", (const char *)m_Classname);
+
+       for(list<DEPair *>::const_iterator ep=epairList.begin(); ep!=epairList.end(); ep++)
+       {
+               fprintf(pFile, "\"%s\" \"%s\"\n", (const char *)(*ep)->key, (const char *)(*ep)->value);
+       }
+
+       for(list<DBrush *>::const_iterator bp=brushList.begin(); bp!=brushList.end(); bp++)
+       {
+               (*bp)->SaveToFile(pFile);
+       }
+
+       fprintf(pFile, "}\n");
+}
+
+void DEntity::ClearEPairs()
+{
+       for(list<DEPair *>::const_iterator deadEPair=epairList.begin(); deadEPair!=epairList.end(); deadEPair++)
+       {
+               delete (*deadEPair);
+       }
+       epairList.clear();
+}
+
+void DEntity::AddEPair(char *key, char *value) {       
+       DEPair* newEPair; 
+       newEPair = FindEPairByKey( key );
+       if(!newEPair) {
+               newEPair = new DEPair;
+               newEPair->Build(key, value);
+               epairList.push_back(newEPair);
+       } else {
+               newEPair->Build(key, value);
+       }
+}
+
+void DEntity::LoadEPairList(epair_t *epl)
+{
+       epair_t* ep = epl;
+       while(ep)
+       {
+               if(!strcmp(ep->key, "classname"))
+                       SetClassname(ep->value);
+               else    
+                       AddEPair(ep->key, ep->value);
+
+               ep = ep->next;
+       }
+}
+
+bool DEntity::ResetTextures(const char* textureName, float fScale[2],     float fShift[2],    int rotation, const char* newTextureName, 
+                            int bResetTextureName,    int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild)
+{
+       g_FuncTable.m_pfnDeselectAllBrushes();
+
+       g_FuncTable.m_pfnAllocateActiveBrushHandles();
+
+       bool reset = FALSE;
+
+       for(list<DBrush *>::const_iterator resetBrush=brushList.begin(); resetBrush!=brushList.end(); resetBrush++)
+       {
+               bool tmp = (*resetBrush)->ResetTextures(textureName,        fScale,       fShift,       rotation, newTextureName, 
+                                            bResetTextureName,  bResetScale,  bResetShift,  bResetRotation);
+
+               if(tmp)
+               {
+                       reset = TRUE;
+
+                       if(rebuild)
+                       {
+        entity_t *pE = (*resetBrush)->QER_brush->owner;       
+                               g_FuncTable.m_pfnDeleteBrushHandle((*resetBrush)->QER_brush);
+        (*resetBrush)->BuildInRadiant(FALSE, NULL, pE->entityId == 0 ? NULL : pE);
+
+        if( pE->entityId == 0 ? NULL : pE )
+        {
+        }
+                       }
+               }
+       }
+
+  if(bResetTextureName)
+  {
+         for(list<DPatch *>::const_iterator resetPatch=patchList.begin(); resetPatch!=patchList.end(); resetPatch++)
+         {
+                 bool tmp = (*resetPatch)->ResetTextures(textureName, newTextureName);
+
+                 if(tmp)
+                 {
+                         reset = TRUE;
+
+                         if(rebuild)
+                         {
+          entity_t *pE = (*resetPatch)->QER_brush->owner;       
+                                 g_FuncTable.m_pfnDeleteBrushHandle((*resetPatch)->QER_brush);
+          (*resetPatch)->BuildInRadiant(pE->entityId == 0 ? NULL : pE);
+                         }
+                 }
+         }
+  }
+
+       g_FuncTable.m_pfnReleaseActiveBrushHandles();
+
+       return reset;
+}
+
+DEPair* DEntity::FindEPairByKey(const char* keyname)
+{
+       for(list<DEPair *>::const_iterator ep=epairList.begin(); ep!=epairList.end(); ep++)
+       {
+               char* c = (*ep)->key;
+               if(!strcmp(c, keyname))
+                       return *ep;
+       }
+       return NULL;
+}
+
+void DEntity::RemoveFromRadiant()
+{
+       g_EntityTable.m_pfnEntity_Free( (entity_t*)QER_Entity );
+
+       QER_Entity = NULL;
+}
+
+void DEntity::SpawnString(const char* key, const char* defaultstring, const char** out)
+{
+       DEPair* pEP = FindEPairByKey(key);
+       if(pEP) {
+               *out = pEP->value;
+       } else {
+               *out = defaultstring;
+       }
+}
+
+void DEntity::SpawnInt(const char* key, const char* defaultstring, int* out)
+{
+       DEPair* pEP = FindEPairByKey(key);
+       if(pEP) {
+               *out = atoi(pEP->value);
+       } else {
+               *out = atoi(defaultstring);
+       }
+}
+
+void DEntity::SpawnFloat(const char* key, const char* defaultstring, float* out)
+{
+       DEPair* pEP = FindEPairByKey(key);
+       if(pEP) {
+               *out = static_cast< float >( atof( pEP->value ) );
+       } else {
+               *out = static_cast< float >( atof(defaultstring) );
+       }
+}
+
+void DEntity::SpawnVector(const char* key, const char* defaultstring, vec_t* out)
+{
+       DEPair* pEP = FindEPairByKey(key);
+       if(pEP) {
+               sscanf(pEP->value, "%f %f %f", &out[0], &out[1], &out[2]);
+       } else {
+               sscanf(defaultstring, "%f %f %f", &out[0], &out[1], &out[2]);
+       }
+}
+
+int DEntity::GetBrushCount( void ) {
+       return brushList.size();
+}
+
+DBrush* DEntity::FindBrushByPointer( brush_t* brush ) {
+       for(list<DBrush *>::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++) {
+               DBrush* pBrush = (*listBrush);
+               if(pBrush->QER_brush == brush) {
+                       return pBrush;
+               }
+       }
+       return NULL;
+}
index 4927fe6..cb7b928 100644 (file)
@@ -1,93 +1,93 @@
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// DListener.cpp: implementation of the DListener class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-#include "DListener.h"\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DListener::DListener()\r
-{\r
-       refCount = 1;\r
-       m_bHooked = FALSE;\r
-}\r
-\r
-DListener::~DListener()\r
-{\r
-       UnRegister();\r
-}\r
-\r
-void DListener::Register()\r
-{\r
-       g_MessageTable.m_pfnHookWindow( this );\r
-       m_bHooked = TRUE;\r
-}\r
-\r
-void DListener::UnRegister()\r
-{\r
-       if(m_bHooked)\r
-       {\r
-               g_MessageTable.m_pfnUnHookWindow( this );\r
-               m_bHooked = FALSE;\r
-       }\r
-}\r
-\r
-bool DListener::OnMouseMove(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       if(!parent->UpdatePath())\r
-               delete parent;\r
-\r
-       return FALSE;\r
-}\r
-\r
-bool DListener::OnLButtonDown(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       return FALSE;\r
-}\r
-\r
-bool DListener::OnLButtonUp(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       return FALSE;\r
-}\r
-\r
-bool DListener::OnRButtonDown(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       return FALSE;\r
-}\r
-\r
-bool DListener::OnRButtonUp(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       return FALSE;\r
-}\r
-\r
-bool DListener::OnMButtonDown(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       return FALSE;\r
-}\r
-\r
-bool DListener::OnMButtonUp(guint32 nFlags, gdouble x, gdouble y)\r
-{\r
-       return FALSE;\r
-}\r
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DListener.cpp: implementation of the DListener class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "StdAfx.h"
+#include "DListener.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+DListener::DListener()
+{
+       refCount = 1;
+       m_bHooked = FALSE;
+}
+
+DListener::~DListener()
+{
+       UnRegister();
+}
+
+void DListener::Register()
+{
+       g_MessageTable.m_pfnHookWindow( this );
+       m_bHooked = TRUE;
+}
+
+void DListener::UnRegister()
+{
+       if(m_bHooked)
+       {
+               g_MessageTable.m_pfnUnHookWindow( this );
+               m_bHooked = FALSE;
+       }
+}
+
+bool DListener::OnMouseMove(guint32 nFlags, gdouble x, gdouble y)
+{
+       if(!parent->UpdatePath())
+               delete parent;
+
+       return FALSE;
+}
+
+bool DListener::OnLButtonDown(guint32 nFlags, gdouble x, gdouble y)
+{
+       return FALSE;
+}
+
+bool DListener::OnLButtonUp(guint32 nFlags, gdouble x, gdouble y)
+{
+       return FALSE;
+}
+
+bool DListener::OnRButtonDown(guint32 nFlags, gdouble x, gdouble y)
+{
+       return FALSE;
+}
+
+bool DListener::OnRButtonUp(guint32 nFlags, gdouble x, gdouble y)
+{
+       return FALSE;
+}
+
+bool DListener::OnMButtonDown(guint32 nFlags, gdouble x, gdouble y)
+{
+       return FALSE;
+}
+
+bool DListener::OnMButtonUp(guint32 nFlags, gdouble x, gdouble y)
+{
+       return FALSE;
+}
index e827690..bc0b066 100644 (file)
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// DMap.cpp: implementation of the DMap class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-#include "DMap.h"\r
-\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-DMap::DMap()\r
-{\r
-       m_nNextEntity = 1;\r
-       AddEntity("worldspawn", 0);\r
-}\r
-\r
-DMap::~DMap()\r
-{\r
-       ClearEntities();\r
-}\r
-\r
-DEntity* DMap::AddEntity(char *classname, int ID)\r
-{\r
-       DEntity* newEntity;\r
-       if(ID == -1)\r
-               newEntity = new DEntity(classname, m_nNextEntity++);\r
-       else\r
-               newEntity = new DEntity(classname, ID);\r
-\r
-       entityList.push_back(newEntity);\r
-       \r
-       return newEntity;\r
-}\r
-\r
-void DMap::ClearEntities()\r
-{\r
-       m_nNextEntity = 1;\r
-\r
-       for(list<DEntity *>::const_iterator deadEntity=entityList.begin(); deadEntity!=entityList.end(); deadEntity++)\r
-               delete *deadEntity;\r
-\r
-       entityList.clear();\r
-}\r
-\r
-DEntity* DMap::GetEntityForID(int ID)\r
-{\r
-       DEntity* findEntity = NULL;\r
-\r
-       for(list<DEntity *>::const_iterator chkEntity=entityList.begin(); chkEntity!=entityList.end(); chkEntity++)\r
-       {\r
-               if((*chkEntity)->m_nID == ID)\r
-               {\r
-                       findEntity = (*chkEntity);\r
-                       break;\r
-               }\r
-       }\r
-\r
-       if(!findEntity)\r
-               findEntity = AddEntity("worldspawn", ID);\r
-\r
-       return findEntity;\r
-}\r
-\r
-\r
-DEntity* DMap::GetWorldSpawn()\r
-{\r
-       return GetEntityForID(0);\r
-}\r
-\r
-void DMap::BuildInRadiant(bool bAllowDestruction)\r
-{\r
-       for(list<DEntity *>::const_iterator buildEntity=entityList.begin(); buildEntity!=entityList.end(); buildEntity++)\r
-               (*buildEntity)->BuildInRadiant(bAllowDestruction);\r
-}\r
-\r
-void DMap::LoadAll(bool bLoadPatches)\r
-{\r
-       ClearEntities();\r
-\r
-       g_FuncTable.m_pfnDeselectAllBrushes();\r
-\r
-       int count = g_FuncTable.m_pfnGetEntityCount();\r
-\r
-       for(int i = 0; i < count; i++)\r
-       {\r
-               DEntity* loadEntity;\r
-\r
-               if(i == 0)\r
-                       loadEntity = GetWorldSpawn();\r
-               else\r
-                       loadEntity = AddEntity("", m_nNextEntity++);\r
-\r
-               if(!loadEntity->LoadFromEntity(i, bLoadPatches))\r
-               {\r
-                       delete loadEntity;\r
-                       entityList.pop_back();\r
-               }\r
-       }\r
-}\r
-\r
-int DMap::FixBrushes(bool rebuild)\r
-{\r
-       int count = 0;\r
-       for(list<DEntity *>::const_iterator fixEntity=entityList.begin(); fixEntity!=entityList.end(); fixEntity++)\r
-       {\r
-               int cnt;\r
-\r
-               if(!stricmp("worldspawn", (*fixEntity)->m_Classname))\r
-                       cnt = (*fixEntity)->FixBrushes(rebuild);\r
-               else\r
-               {\r
-                       cnt = (*fixEntity)->FixBrushes(FALSE);\r
-                       \r
-                       if(cnt && rebuild)\r
-                               RebuildEntity(*fixEntity);\r
-               }\r
-\r
-               count += cnt;\r
-       }\r
-\r
-       return count;\r
-}\r
-\r
-void DMap::ResetTextures( const char* textureName, float fScale[2],      float fShift[2],      int rotation, const char* newTextureName, \r
-                          int bResetTextureName,  int bResetScale[2],  int bResetShift[2],  int bResetRotation)\r
-{\r
-       for(list<DEntity *>::const_iterator texEntity=entityList.begin(); texEntity!=entityList.end(); texEntity++)\r
-       {\r
-               if(!stricmp("worldspawn", (*texEntity)->m_Classname))\r
-                       (*texEntity)->ResetTextures(textureName,        fScale,       fShift,       rotation, newTextureName, \r
-                                  bResetTextureName,  bResetScale,  bResetShift,  bResetRotation, TRUE);\r
-               else\r
-               {\r
-                       if((*texEntity)->ResetTextures( textureName,        fScale,       fShift,       rotation, newTextureName, \r
-                                      bResetTextureName,  bResetScale,  bResetShift,  bResetRotation, FALSE))\r
-                               RebuildEntity(*texEntity);\r
-               }\r
-       }       \r
-}\r
-\r
-void DMap::RebuildEntity(DEntity *ent)\r
-{\r
-       ent->RemoveFromRadiant();\r
-       ent->BuildInRadiant(FALSE);\r
-}\r
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DMap.cpp: implementation of the DMap class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "StdAfx.h"
+#include "DMap.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+DMap::DMap()
+{
+       m_nNextEntity = 1;
+       AddEntity("worldspawn", 0);
+}
+
+DMap::~DMap()
+{
+       ClearEntities();
+}
+
+DEntity* DMap::AddEntity(char *classname, int ID)
+{
+       DEntity* newEntity;
+       if(ID == -1)
+               newEntity = new DEntity(classname, m_nNextEntity++);
+       else
+               newEntity = new DEntity(classname, ID);
+
+       entityList.push_back(newEntity);
+       
+       return newEntity;
+}
+
+void DMap::ClearEntities()
+{
+       m_nNextEntity = 1;
+
+       for(list<DEntity *>::const_iterator deadEntity=entityList.begin(); deadEntity!=entityList.end(); deadEntity++)
+               delete *deadEntity;
+
+       entityList.clear();
+}
+
+DEntity* DMap::GetEntityForID(int ID)
+{
+       DEntity* findEntity = NULL;
+
+       for(list<DEntity *>::const_iterator chkEntity=entityList.begin(); chkEntity!=entityList.end(); chkEntity++)
+       {
+               if((*chkEntity)->m_nID == ID)
+               {
+                       findEntity = (*chkEntity);
+                       break;
+               }
+       }
+
+       if(!findEntity)
+               findEntity = AddEntity("worldspawn", ID);
+
+       return findEntity;
+}
+
+
+DEntity* DMap::GetWorldSpawn()
+{
+       return GetEntityForID(0);
+}
+
+void DMap::BuildInRadiant(bool bAllowDestruction)
+{
+       for(list<DEntity *>::const_iterator buildEntity=entityList.begin(); buildEntity!=entityList.end(); buildEntity++)
+               (*buildEntity)->BuildInRadiant(bAllowDestruction);
+}
+
+void DMap::LoadAll(bool bLoadPatches)
+{
+       ClearEntities();
+
+       g_FuncTable.m_pfnDeselectAllBrushes();
+
+       int count = g_FuncTable.m_pfnGetEntityCount();
+
+       for(int i = 0; i < count; i++)
+       {
+               DEntity* loadEntity;
+
+               if(i == 0)
+                       loadEntity = GetWorldSpawn();
+               else
+                       loadEntity = AddEntity("", m_nNextEntity++);
+
+               if(!loadEntity->LoadFromEntity(i, bLoadPatches))
+               {
+                       delete loadEntity;
+                       entityList.pop_back();
+               }
+       }
+}
+
+int DMap::FixBrushes(bool rebuild)
+{
+       int count = 0;
+       for(list<DEntity *>::const_iterator fixEntity=entityList.begin(); fixEntity!=entityList.end(); fixEntity++)
+       {
+               int cnt;
+
+               if(!stricmp("worldspawn", (*fixEntity)->m_Classname))
+                       cnt = (*fixEntity)->FixBrushes(rebuild);
+               else
+               {
+                       cnt = (*fixEntity)->FixBrushes(FALSE);
+                       
+                       if(cnt && rebuild)
+                               RebuildEntity(*fixEntity);
+               }
+
+               count += cnt;
+       }
+
+       return count;
+}
+
+void DMap::ResetTextures( const char* textureName, float fScale[2],      float fShift[2],      int rotation, const char* newTextureName, 
+                          int bResetTextureName,  int bResetScale[2],  int bResetShift[2],  int bResetRotation)
+{
+       for(list<DEntity *>::const_iterator texEntity=entityList.begin(); texEntity!=entityList.end(); texEntity++)
+       {
+               if(!stricmp("worldspawn", (*texEntity)->m_Classname))
+                       (*texEntity)->ResetTextures(textureName,        fScale,       fShift,       rotation, newTextureName, 
+                                  bResetTextureName,  bResetScale,  bResetShift,  bResetRotation, TRUE);
+               else
+               {
+                       if((*texEntity)->ResetTextures( textureName,        fScale,       fShift,       rotation, newTextureName, 
+                                      bResetTextureName,  bResetScale,  bResetShift,  bResetRotation, FALSE))
+                               RebuildEntity(*texEntity);
+               }
+       }       
+}
+
+void DMap::RebuildEntity(DEntity *ent)
+{
+       ent->RemoveFromRadiant();
+       ent->BuildInRadiant(FALSE);
+}
index 161420f..36968b0 100644 (file)
-/*\r
-BobToolz plugin for GtkRadiant\r
-Copyright (C) 2001 Gordon Biggans\r
-\r
-This library is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU Lesser General Public\r
-License as published by the Free Software Foundation; either\r
-version 2.1 of the License, or (at your option) any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public\r
-License along with this library; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-*/\r
-\r
-// DPatch.cpp: implementation of the DPatch class.\r
-//\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-#include "StdAfx.h"\r
-#include "DPatch.h"\r
-#include "misc.h"\r
-#include "./dialogs/dialogs-gtk.h"\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-//             Added patch merging, wahey!\r
-\r
-//\r
-//             problem is, you cant put patches into entities as yet :(\r
-//\r
-\r
-DPatch::DPatch()\r
-{\r
-       width = MIN_PATCH_WIDTH;\r
-       height = MIN_PATCH_HEIGHT;\r
-       QER_patch = NULL;\r
-       QER_brush = NULL;\r
-}\r
-\r
-DPatch::~DPatch()\r
-{\r
-\r
-}\r
-\r
-void DPatch::SetTexture(const char *textureName)\r
-{\r
-       strcpy(texture, textureName);\r
-}\r
-\r
-void CopyDrawVert(const drawVert_t* in, drawVert_t* out)\r
-{\r
-       out->lightmap[0] = in->lightmap[0];\r
-       out->lightmap[1] = in->lightmap[1];\r
-       out->st[0] = in->st[0];\r
-       out->st[1] = in->st[1];\r
-       VectorCopy(in->normal, out->normal);\r
-       VectorCopy(in->xyz, out->xyz);\r
-}\r
-\r
-void DPatch::BuildInRadiant(void* entity)\r
-{\r
-       int nIndex = g_FuncTable.m_pfnCreatePatchHandle();\r
-    //$ FIXME: m_pfnGetPatchHandle\r
-       patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData(nIndex);\r
-\r
-       pm->height = height;\r
-       pm->width = width;\r
-\r
-       for(int x = 0; x < width; x++)\r
-               for(int y = 0; y < height; y++)\r
-                       CopyDrawVert(&points[x][y], &pm->ctrl[x][y]);\r
-\r
-       QER_patch = pm;\r
-\r
-/*     if(entity)\r
-       {\r
-//             strcpy(pm->d_texture->name, texture);\r
-\r
-               brush_t* brush = (brush_t*)g_FuncTable.m_pfnCreateBrushHandle();\r
-               brush->patchBrush = TRUE;\r
-               brush->pPatch = pm;             \r
-\r
-               pm->pSymbiot = brush;\r
-               pm->bSelected = false;\r
-               pm->bOverlay = false;   // bleh, f*cks up, just have to wait for a proper function\r
-               pm->bDirty = true;              // or get my own patch out....\r
-               pm->nListID = -1;\r
-\r
-               g_FuncTable.m_pfnCommitBrushHandleToEntity(brush, entity);\r
-       }\r
-       else*/  // patch to entity just plain dont work atm\r
-\r
-  if(entity)\r
-    g_FuncTable.m_pfnCommitPatchHandleToEntity(nIndex, pm, texture, entity);\r
-  else\r
-               g_FuncTable.m_pfnCommitPatchHandleToMap(nIndex, pm, texture);\r
-\r
-       QER_brush = pm->pSymbiot;\r
-}\r
-\r
-void DPatch::LoadFromBrush_t(brush_t* brush)\r
-{\r
-       QER_brush = brush;\r
-       QER_patch = brush->pPatch;\r
-\r
-       SetTexture(QER_patch->pShader->getName());\r
-\r
-       for(int x = 0; x < QER_patch->width; x++)\r
-               for(int y = 0; y < QER_patch->height; y++)\r
-                       CopyDrawVert(&QER_patch->ctrl[x][y], &points[x][y]);\r
-\r
-       width = QER_patch->width;\r
-       height = QER_patch->height;\r
-}\r
-\r
-void DPatch::RemoveFromRadiant()\r
-{\r
-       if(QER_brush)\r
-               g_FuncTable.m_pfnDeleteBrushHandle(QER_brush);\r
-}\r
-\r
-bool DPatch::ResetTextures(const char *oldTextureName, const char *newTextureName)\r
-{\r
-       if( !oldTextureName || !strcmp(texture, oldTextureName))\r
-       {\r
-               strcpy(texture, newTextureName);\r
-               return TRUE;\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-void Build1dArray(vec3_t* array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT], \r
-                                 int startX, int startY, int number, bool horizontal, bool inverse)\r
-{\r
-       int x = startX, y = startY, i, step;\r
-\r
-       if(inverse)\r
-               step = -1;\r
-       else\r
-               step = 1;\r
-\r
-       for(i = 0; i < number; i++)\r
-       {\r
-               VectorCopy(points[x][y].xyz, array[i]);\r
-\r
-               if(horizontal)\r
-                       x+=step;\r
-               else\r
-                       y+=step;\r
-       }\r
-}\r
-\r
-void Print1dArray(vec3_t* array, int size)\r
-{\r
-       for(int i = 0; i < size; i++)\r
-               Sys_Printf("(%.0f %.0f %.0f)\t", array[i][0], array[i][1], array[i][2]);\r
-       Sys_Printf("\n");\r
-}\r
-\r
-bool Compare1dArrays(vec3_t* a1, vec3_t* a2, int size)\r
-{\r
-       int i;\r
-       bool equal = true;\r
-\r
-       for(i = 0; i < size; i++)\r
-       {\r
-               if(!VectorCompare(a1[i], a2[size-i-1]))\r
-               {\r
-                       equal = false;\r
-                       break;\r
-               }\r
-       }\r
-       return equal;\r
-}\r
-\r
-patch_merge_t DPatch::IsMergable(DPatch *other)\r
-{\r
-       int i, j;\r
-       vec3_t p1Array[4][MAX_PATCH_HEIGHT];\r
-       vec3_t p2Array[4][MAX_PATCH_HEIGHT];\r
-\r
-       int p1ArraySizes[4];\r
-       int p2ArraySizes[4];\r
-\r
-       patch_merge_t merge_info;\r
-\r
-       Build1dArray(p1Array[0], this->points, 0,                               0,                              this->width,    true,   false);\r
-       Build1dArray(p1Array[1], this->points, this->width-1,   0,                              this->height,   false,  false);\r
-       Build1dArray(p1Array[2], this->points, this->width-1,   this->height-1, this->width,    true,   true);\r
-       Build1dArray(p1Array[3], this->points, 0,                               this->height-1, this->height,   false,  true);\r
-\r
-       Build1dArray(p2Array[0], other->points, 0,                              0,                                      other->width,   true,   false);\r
-       Build1dArray(p2Array[1], other->points, other->width-1, 0,                                      other->height,  false,  false);\r
-       Build1dArray(p2Array[2], other->points, other->width-1, other->height-1,        other->width,   true,   true);\r
-       Build1dArray(p2Array[3], other->points, 0,                              other->height-1,        other->height,  false,  true);\r
-\r
-       p1ArraySizes[0] = this->width;\r
-       p1ArraySizes[1] = this->height;\r
-       p1ArraySizes[2] = this->width;\r
-       p1ArraySizes[3] = this->height;\r
-\r
-       p2ArraySizes[0] = other->width;\r
-       p2ArraySizes[1] = other->height;\r
-       p2ArraySizes[2] = other->width;\r
-       p2ArraySizes[3] = other->height;\r
-\r
-       for(i = 0; i < 4; i++)\r
-       {\r
-               for(j = 0; j < 4; j++)\r
-               {\r
-                       if(p1ArraySizes[i] == p2ArraySizes[j])\r
-                       {\r
-                               if(Compare1dArrays(p1Array[i], p2Array[j], p1ArraySizes[i]))\r
-                               {\r
-                                       merge_info.pos1 = i;\r
-                                       merge_info.pos2 = j;\r
-                                       merge_info.mergable = true;\r
-                                       return merge_info;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       \r
-       merge_info.mergable = false;\r
-       return merge_info;\r
-}\r
-\r
-DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)\r
-{\r
-       while(merge_info.pos1 != 2)\r
-       {\r
-               p1->Transpose();\r
-               merge_info.pos1--;\r
-               if(merge_info.pos1 < 0)\r
-                       merge_info.pos1 += 4;\r
-       }\r
-\r
-       while(merge_info.pos2 != 0)\r
-       {\r
-               p2->Transpose();\r
-               merge_info.pos2--;\r
-               if(merge_info.pos2 < 0)\r
-                       merge_info.pos2 += 3;\r
-       }\r
-\r
-       int newHeight = p1->height + p2->height - 1;\r
-       if(newHeight > MAX_PATCH_HEIGHT)\r
-               return NULL;\r
-\r
-       DPatch* newPatch = new DPatch();\r
-\r
-       newPatch->height        = newHeight;\r
-       newPatch->width         = p1->width;\r
-       newPatch->SetTexture(p1->texture);\r
-\r
-       int y = 0;\r
-       int i;\r
-       for(i = 0; i < p1->height; i++, y+