ported bobtoolz
authorspog <spog>
Sun, 30 Apr 2006 22:28:39 +0000 (22:28 +0000)
committerspog <spog>
Sun, 30 Apr 2006 22:28:39 +0000 (22:28 +0000)
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@58 8a3a26a2-13c4-0310-b231-cf6edde360e5

68 files changed:
CHANGES
SConscript
contrib/bobtoolz/DBobView.cpp
contrib/bobtoolz/DBrush.cpp
contrib/bobtoolz/DBrush.h
contrib/bobtoolz/DEntity.cpp
contrib/bobtoolz/DListener.cpp [deleted file]
contrib/bobtoolz/DListener.h [deleted file]
contrib/bobtoolz/DPatch.cpp
contrib/bobtoolz/DPatch.h
contrib/bobtoolz/DPlane.cpp
contrib/bobtoolz/DTrainDrawer.cpp
contrib/bobtoolz/DTreePlanter.cpp
contrib/bobtoolz/DTreePlanter.h
contrib/bobtoolz/ScriptParser.cpp
contrib/bobtoolz/bitmaps/bobtoolz_caulk.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_cleanup.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_dropent.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_merge.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_poly.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_split.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_trainpathplot.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_treeplanter.bmp [new file with mode: 0644]
contrib/bobtoolz/bitmaps/bobtoolz_turnedge.bmp [new file with mode: 0644]
contrib/bobtoolz/bobToolz-GTK.cpp
contrib/bobtoolz/bobtoolz.vcproj [new file with mode: 0644]
contrib/bobtoolz/dialogs/dialogs-gtk.cpp
contrib/bobtoolz/funchandlers-GTK.cpp
contrib/bobtoolz/funchandlers.cpp
contrib/bobtoolz/lists.cpp
contrib/bobtoolz/misc.cpp
contrib/bobtoolz/misc.h
contrib/bobtoolz/shapes.cpp
contrib/bobtoolz/shapes.h
include/ibrush.h
include/ientity.h
include/ipatch.h
include/qerplugin.h
libs/generic/reference.h
libs/gtkutil/accelerator.cpp
libs/gtkutil/accelerator.h
libs/scenelib.h
radiant/brushmodule.cpp
radiant/commands.cpp
radiant/mainframe.cpp
radiant/mainframe.h
radiant/map.h
radiant/patch.cpp
radiant/patch.h
radiant/patchmodule.cpp
radiant/plugin.cpp
radiant/scenegraph.cpp
radiant/xywindow.cpp
radiant/xywindow.h
setup/data/tools/plugins/bitmaps/bobtoolz_caulk.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_dropent.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_trainpathplot.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp [new file with mode: 0644]
setup/data/tools/plugins/bitmaps/bobtoolz_turnedge.bmp [new file with mode: 0644]
setup/data/tools/plugins/bt/bt-el1.txt [new file with mode: 0644]
setup/data/tools/plugins/bt/bt-el2.txt [new file with mode: 0644]
setup/data/tools/plugins/bt/door-tex-trim.txt [new file with mode: 0644]
setup/data/tools/plugins/bt/door-tex.txt [new file with mode: 0644]
setup/data/tools/plugins/bt/tp_ent.txt [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 4c4c2e0..82829e3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,7 @@ that we distribute with the binaries. (see changelog)
 30/04/2006
 SPoG
 - Fixed memory leak in signals library.
+- Ported bobtoolz to use new module APIs.
 
 01/04/2006
 SPoG
index 46b34f6..c025189 100644 (file)
@@ -445,18 +445,19 @@ entity_lst = build_list('plugins/entity', 'plugin.cpp entity.cpp eclassmodel.cpp
 entity_lib = module_env.SharedLibrarySafe(target='entity', source=entity_lst)
 module_env.Install(INSTALL + '/modules', entity_lib)
 
-#bob_env = module_env.Copy()
-#bob_env.useGtk2()
-#bob_lst = build_list('contrib/bobtoolz/',
-#'dialogs/dialogs-gtk.cpp bobToolz-GTK.cpp bsploader.cpp cportals.cpp DBobView.cpp \
-#DBrush.cpp DEntity.cpp DEPair.cpp DListener.cpp DMap.cpp DPatch.cpp DPlane.cpp DPoint.cpp \
-#DShape.cpp DTrainDrawer.cpp DTreePlanter.cpp DVisDrawer.cpp DWinding.cpp funchandlers-GTK.cpp \
-#lists.cpp misc.cpp ScriptParser.cpp shapes.cpp visfind.cpp')
-#bob_lst.append('libs/libmathlib.a')
-#bob_lst.append('libs/libcmdlib.a')
-#bob_env['CPPPATH'].append('contrib/bobtoolz/dialogs')
-#bob_env.SharedLibrarySafe(target='bobtoolz', source=bob_lst)
-#bob_env.Install(INSTALL + '/plugins', 'bobtoolz.so')
+bob_env = module_env.Copy()
+bob_lst = build_list('contrib/bobtoolz/',
+'dialogs/dialogs-gtk.cpp bobToolz-GTK.cpp bsploader.cpp cportals.cpp DBobView.cpp \
+DBrush.cpp DEntity.cpp DEPair.cpp DMap.cpp DPatch.cpp DPlane.cpp DPoint.cpp \
+DShape.cpp DTrainDrawer.cpp DTreePlanter.cpp DVisDrawer.cpp DWinding.cpp funchandlers-GTK.cpp \
+lists.cpp misc.cpp ScriptParser.cpp shapes.cpp visfind.cpp')
+bob_lib = bob_env.SharedLibrarySafe(target='bobtoolz', source=bob_lst, LIBS=['mathlib', 'cmdlib', 'profile'], LIBPATH='libs')
+bob_env.Depends(bob_lib, mathlib_lib)
+bob_env.Depends(bob_lib, cmdlib_lib)
+bob_env.Depends(bob_lib, profile_lib)
+bob_env.useGlib2()
+bob_env.useGtk2()
+bob_env.Install(INSTALL + '/plugins', bob_lib)
 
 #camera_lst = build_list('contrib/camera', 
 #'camera.cpp dialogs.cpp dialogs_common.cpp funchandlers.cpp listener.cpp misc.cpp renderer.cpp')
index c5de46f..688dd7e 100644 (file)
@@ -122,14 +122,14 @@ void DBobView::renderSolid(Renderer& renderer, const VolumeTest& volume) const
        if(!path)
                return;
 
-  renderer.SetState(m_shader_line, eWireframeOnly);
-  renderer.SetState(m_shader_line, eFullMaterials);
+  renderer.SetState(m_shader_line, Renderer::eWireframeOnly);
+  renderer.SetState(m_shader_line, Renderer::eFullMaterials);
   renderer.addRenderable(*this, g_matrix4_identity);
 
        if(m_bShowExtra)
        {
-    renderer.SetState(m_shader_box, eWireframeOnly);
-    renderer.SetState(m_shader_box, eFullMaterials);
+    renderer.SetState(m_shader_box, Renderer::eWireframeOnly);
+    renderer.SetState(m_shader_box, Renderer::eFullMaterials);
     renderer.addRenderable(*this, g_transform_box1);
     renderer.addRenderable(*this, g_transform_box2);
     renderer.addRenderable(*this, g_transform_box3);
@@ -243,7 +243,7 @@ void DBobView_setEntity(Entity& entity, float multiplier, int points, float varG
                        DEPair* target_ep = trigger.FindEPairByKey("target");
                        if(target_ep)
                        {
-        scene::Path* entTarget = FindEntityFromTargetname(target_ep->value, NULL);
+        const scene::Path* entTarget = FindEntityFromTargetname(target_ep->value);
                                if(entTarget)
                                {
                                        if(g_PathView)
index 75b2a6e..6c03fb8 100644 (file)
@@ -55,6 +55,7 @@ DBrush::DBrush(int ID)
 {
        m_nBrushID = ID;
        bBoundsBuilt = false;
+       QER_entity = NULL;
        QER_brush = NULL;
 }
 
@@ -140,14 +141,15 @@ void DBrush_addFaceTextured(DBrush& brush, const _QERFaceData& faceData)
 }
 typedef ReferenceCaller1<DBrush, const _QERFaceData&, DBrush_addFaceTextured> DBrushAddFaceTexturedCaller;
 
-void DBrush::LoadFromBrush(scene::Node& brush, bool textured)
+void DBrush::LoadFromBrush(scene::Instance& brush, bool textured)
 {
        ClearFaces();
        ClearPoints();
 
-  GlobalBrushCreator().forEachBrushFace(brush, textured ? BrushFaceDataCallback(DBrushAddFaceTexturedCaller(*this)) : BrushFaceDataCallback(DBrushAddFaceCaller(*this)));
+  GlobalBrushCreator().Brush_forEachFace(brush.path().top(), textured ? BrushFaceDataCallback(DBrushAddFaceTexturedCaller(*this)) : BrushFaceDataCallback(DBrushAddFaceCaller(*this)));
 
-       QER_brush = &brush;
+  QER_entity = brush.path().parent().get_pointer();
+       QER_brush = brush.path().top().get_pointer();
 }
 
 int DBrush::PointPosition(vec3_t pnt)
@@ -394,7 +396,7 @@ scene::Node* DBrush::BuildInRadiant(bool allowDestruction, int* changeCnt, scene
        }
        //-djbob
 
-  scene::Node& node = GlobalBrushCreator().createBrush();
+  NodeSmartReference node(GlobalBrushCreator().createBrush());
 
        for(std::list<DPlane *>::const_iterator buildPlane=faceList.begin(); buildPlane!=faceList.end(); buildPlane++) {
                if((*buildPlane)->AddToBrush(node) && changeCnt) {
@@ -408,7 +410,10 @@ scene::Node* DBrush::BuildInRadiant(bool allowDestruction, int* changeCnt, scene
                Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(node);
        }
 
-       return &node;
+  QER_entity = entity;
+  QER_brush = node.get_pointer();
+
+       return node.get_pointer();
 }
 
 void DBrush::CutByPlane(DPlane *cutPlane, DBrush **newBrush1, DBrush **newBrush2)
index 9915d0f..112f229 100644 (file)
@@ -41,6 +41,7 @@ class _QERFaceData;
 namespace scene
 {
   class Node;
+  class Instance;
 }
 
 #define POINT_IN_BRUSH 0
@@ -88,7 +89,7 @@ public:
        
        void CutByPlane(DPlane* cutPlane, DBrush** newBrush1, DBrush** newBrush2);
 
-       void LoadFromBrush(scene::Node& brush, bool textured);
+       void LoadFromBrush(scene::Instance& brush, bool textured);
        void AddPoint(vec3_t pnt);
 
        DPlane* FindPlaneWithClosestNormal( vec_t* normal );
@@ -100,6 +101,7 @@ public:
        bool operator== (DBrush* other);
 
 //     members
+  scene::Node* QER_entity;
   scene::Node* QER_brush;
        std::list<DPlane*> faceList;
        std::list<DPoint*> pointList;
index f69b358..6dafc93 100644 (file)
@@ -238,7 +238,7 @@ public:
   {
     if(Node_isBrush(instance.path().top()))
     {
-      m_functor(*instance.path().top());
+      m_functor(instance);
     }
   }
 };
@@ -250,12 +250,12 @@ inline const Functor& Scene_forEachSelectedBrush(const Functor& functor)
   return functor;
 }
 
-void DEntity_loadBrush(DEntity& entity, scene::Node& brush)
+void DEntity_loadBrush(DEntity& entity, scene::Instance& brush)
 {
   DBrush* loadBrush = entity.NewBrush(entity.brushList.size());
        loadBrush->LoadFromBrush(brush, true);
 }
-typedef ReferenceCaller1<DEntity, scene::Node&, DEntity_loadBrush> DEntityLoadBrushCaller;
+typedef ReferenceCaller1<DEntity, scene::Instance&, DEntity_loadBrush> DEntityLoadBrushCaller;
 
 void DEntity::LoadSelectedBrushes()
 {
@@ -277,7 +277,7 @@ public:
   {
     if(Node_isPatch(instance.path().top()))
     {
-      m_functor(*instance.path().top());
+      m_functor(instance);
     }
   }
 };
@@ -289,12 +289,12 @@ inline const Functor& Scene_forEachSelectedPatch(const Functor& functor)
   return functor;
 }
 
-void DEntity_loadPatch(DEntity& entity, scene::Node& patch)
+void DEntity_loadPatch(DEntity& entity, scene::Instance& patch)
 {
   DPatch* loadPatch = entity.NewPatch();
-       loadPatch->LoadFromBrush(patch);
+       loadPatch->LoadFromPatch(patch);
 }
-typedef ReferenceCaller1<DEntity, scene::Node&, DEntity_loadPatch> DEntityLoadPatchCaller;
+typedef ReferenceCaller1<DEntity, scene::Instance&, DEntity_loadPatch> DEntityLoadPatchCaller;
 
 void DEntity::LoadSelectedPatches()
 {
@@ -411,15 +411,21 @@ bool DEntity::LoadFromEntity(scene::Node& ent, bool bLoadPatches) {
       }
       bool pre(scene::Node& node) const
       {
+        scene::Path path(NodeReference(GlobalSceneGraph().root()));
+        path.push(NodeReference(*m_entity->QER_Entity));
+        path.push(NodeReference(node));
+        scene::Instance* instance = GlobalSceneGraph().find(path);
+        ASSERT_MESSAGE(instance != 0, "");
+
         if(Node_isPatch(node))
         {
           DPatch* loadPatch = m_entity->NewPatch();
-                                 loadPatch->LoadFromBrush(node);
+                                 loadPatch->LoadFromPatch(*instance);
         }
         else if(Node_isBrush(node))
         {
                            DBrush* loadBrush = m_entity->NewBrush(m_count++);
-                           loadBrush->LoadFromBrush(node, true);
+                           loadBrush->LoadFromBrush(*instance, true);
         }
         return false;
       }
@@ -490,7 +496,7 @@ void DEntity::BuildInRadiant(bool allowDestruction)
 
        if(makeEntity)
        {
-    NodeReference node(GlobalEntityCreator().createEntity(GlobalEntityClassManager().findOrInsert(m_Classname.GetBuffer(), !brushList.empty() || !patchList.empty())));
+    NodeSmartReference node(GlobalEntityCreator().createEntity(GlobalEntityClassManager().findOrInsert(m_Classname.GetBuffer(), !brushList.empty() || !patchList.empty())));
 
                for(std::list<DEPair* >::const_iterator buildEPair=epairList.begin(); buildEPair!=epairList.end(); buildEPair++)
                {
@@ -608,6 +614,11 @@ bool DEntity::ResetTextures(const char* textureName, float fScale[2],     float
                if(tmp)
                {
                        reset = true;
+                       if(rebuild)
+                       {
+        Node_getTraversable(*(*resetBrush)->QER_entity)->erase(*(*resetBrush)->QER_brush);      
+        (*resetBrush)->BuildInRadiant(false, NULL, (*resetBrush)->QER_entity);
+                       }
                }
        }
 
@@ -620,6 +631,11 @@ bool DEntity::ResetTextures(const char* textureName, float fScale[2],     float
                  if(tmp)
                  {
                          reset = true;
+                         if(rebuild)
+                         {
+          Node_getTraversable(*(*resetPatch)->QER_entity)->erase(*(*resetPatch)->QER_brush);      
+          (*resetPatch)->BuildInRadiant((*resetPatch)->QER_entity);
+                         }
                  }
          }
   }
diff --git a/contrib/bobtoolz/DListener.cpp b/contrib/bobtoolz/DListener.cpp
deleted file mode 100644 (file)
index 3d04a42..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-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 "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(unsigned int nFlags, double x, double y)
-{
-       if(!parent->UpdatePath())
-               delete parent;
-
-       return FALSE;
-}
-
-bool DListener::OnLButtonDown(unsigned int nFlags, double x, double y)
-{
-       return FALSE;
-}
-
-bool DListener::OnLButtonUp(unsigned int nFlags, double x, double y)
-{
-       return FALSE;
-}
-
-bool DListener::OnRButtonDown(unsigned int nFlags, double x, double y)
-{
-       return FALSE;
-}
-
-bool DListener::OnRButtonUp(unsigned int nFlags, double x, double y)
-{
-       return FALSE;
-}
-
-bool DListener::OnMButtonDown(unsigned int nFlags, double x, double y)
-{
-       return FALSE;
-}
-
-bool DListener::OnMButtonUp(unsigned int nFlags, double x, double y)
-{
-       return FALSE;
-}
diff --git a/contrib/bobtoolz/DListener.h b/contrib/bobtoolz/DListener.h
deleted file mode 100644 (file)
index d216699..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-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.h: interface for the DListener class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include "DBobView.h"
-
-class DListener : public IWindowListener  
-{
-public:
-       DBobView* parent;
-       
-       bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
-       bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
-       bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
-       bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
-       bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
-       bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
-       bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
-       bool OnKeyPressed(char *s) { return false; }
-       bool Paint() { return true; }
-       void Close() { }
-       
-       void UnRegister();
-       void Register();
-       DListener();
-       virtual ~DListener();
-
-       void IncRef() { refCount++; }
-       void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-private:
-       bool m_bHooked;
-       int refCount;
-};
-
-#endif // !defined(AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_)
index 2158eff..4698c61 100644 (file)
@@ -46,6 +46,7 @@ DPatch::DPatch()
 {
        width = MIN_PATCH_WIDTH;
        height = MIN_PATCH_HEIGHT;
+       QER_entity = NULL;
        QER_brush = NULL;
 }
 
@@ -71,46 +72,45 @@ void CopyDrawVert(const drawVert_t* in, drawVert_t* out)
 
 void DPatch::BuildInRadiant(scene::Node* entity)
 {
-       NodeSmartReference node(GlobalPatchCreator().createPatch());
+       NodeSmartReference patch(GlobalPatchCreator().createPatch());
 
-       if(entity) {
-               Node_getTraversable(*entity)->insert(node);
-       } else {
-               Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(node);
-       }
-#if 0
-       int nIndex = g_FuncTable.m_pfnCreatePatchHandle();
-    //$ FIXME: m_pfnGetPatchHandle
-       patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData(nIndex);
-
-  b->patchBrush = true;
-  b->pPatch = Patch_Alloc();
-       b->pPatch->setDims(width,height);
+  scene::Node& parent = entity != 0 ? *entity : GlobalRadiant().getMapWorldEntity();
+  Node_getTraversable(parent)->insert(patch);
 
+  GlobalPatchCreator().Patch_setShader(patch, texture);
+  GlobalPatchCreator().Patch_resize(patch, height, width);
+  PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch);
        for(int x = 0; x < height; x++)
   {
                for(int y = 0; y < width; y++)
     {
-      float *p = b->pPatch->ctrlAt(ROW,x,y);
-      p[0] = points[x][y].xyz[0];
-      p[1] = points[x][y].xyz[1];
-      p[2] = points[x][y].xyz[2];
-      p[3] = points[x][y].st[0];
-      p[4] = points[x][y].st[1];
+      PatchControl& p = matrix(y, x);
+      p.m_vertex[0] = points[x][y].xyz[0];
+      p.m_vertex[1] = points[x][y].xyz[1];
+      p.m_vertex[2] = points[x][y].xyz[2];
+      p.m_texcoord[0] = points[x][y].st[0];
+      p.m_texcoord[1] = points[x][y].st[1];
     }
   }
+  GlobalPatchCreator().Patch_controlPointsChanged(patch);
+  
+  QER_entity = entity;
+       QER_brush = patch.get_pointer();
 
-       if(entity)
-               g_FuncTable.m_pfnCommitBrushHandleToEntity(QER_brush, entity);
-       else
-               g_FuncTable.m_pfnCommitBrushHandle(QER_brush);
+
+#if 0
+       int nIndex = g_FuncTable.m_pfnCreatePatchHandle();
+    //$ FIXME: m_pfnGetPatchHandle
+       patchMesh_t* pm = g_FuncTable.m_pfnGetPatchData(nIndex);
+
+  b->patchBrush = true;
+  b->pPatch = Patch_Alloc();
+       b->pPatch->setDims(width,height);
 
        for(int x = 0; x < width; x++)
                for(int y = 0; y < height; y++)
                        CopyDrawVert(&points[x][y], &pm->ctrl[x][y]);
 
-       QER_patch = pm;
-
 /*     if(entity)
        {
 //             strcpy(pm->d_texture->name, texture);
@@ -138,9 +138,29 @@ void DPatch::BuildInRadiant(scene::Node* entity)
 #endif
 }
 
-void DPatch::LoadFromBrush(scene::Node& brush)
+void DPatch::LoadFromPatch(scene::Instance& patch)
 {
-       QER_brush = &brush;
+  QER_entity = patch.path().parent().get_pointer();
+       QER_brush = patch.path().top().get_pointer();
+
+  PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch.path().top());
+
+  width = matrix.x();
+       height = matrix.y();
+
+  for(int x = 0; x < height; x++)
+  {
+               for(int y = 0; y < width; y++)
+    {
+      PatchControl& p = matrix(y, x);
+      points[x][y].xyz[0] = p.m_vertex[0];
+      points[x][y].xyz[1] = p.m_vertex[1];
+      points[x][y].xyz[2] = p.m_vertex[2];
+      points[x][y].st[0] = p.m_texcoord[0];
+      points[x][y].st[1] = p.m_texcoord[1];
+    }
+  }
+       SetTexture(GlobalPatchCreator().Patch_getShader(patch.path().top()));
 
 #if 0
        SetTexture(brush->pPatch->GetShader());
@@ -302,11 +322,11 @@ DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
        int i;
        for(i = 0; i < p1->height; i++, y++)
                for(int x = 0; x < p1->width; x++)
-                       memcpy(&newPatch->points[x][y], &p1->points[x][i],      sizeof(drawVert_t));
+                       newPatch->points[x][y] = p1->points[x][i];
 
        for(i = 1; i < p2->height; i++, y++)
                for(int x = 0; x < p2->width; x++)
-                       memcpy(&newPatch->points[x][y], &p2->points[x][i],      sizeof(drawVert_t));
+                       newPatch->points[x][y] = p2->points[x][i];
 
 //     newPatch->Invert();
 
@@ -315,16 +335,13 @@ DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
 
 void DPatch::Invert()
 {
-       drawVert_t vertTemp;
        int i, j;
 
        for(i = 0 ; i < width ; i++ ) 
        {
                for(j = 0; j < height / 2; j++)
                {
-                       memcpy(&vertTemp, &points[i][height - 1- j], sizeof (drawVert_t));
-                       memcpy(&points[i][height - 1 - j], &points[i][j], sizeof(drawVert_t));
-                       memcpy(&points[i][j], &vertTemp, sizeof(drawVert_t));
+      std::swap(points[i][height - 1- j], points[i][j]);
                }
        }
 }
@@ -332,7 +349,6 @@ void DPatch::Invert()
 void DPatch::Transpose()
 {
        int             i, j, w;
-       drawVert_t dv;
 
        if ( width > height ) 
        {
@@ -343,14 +359,12 @@ void DPatch::Transpose()
                                if ( j < height ) 
                                {
                                        // swap the value
-                                       memcpy(&dv,                             &points[j][i],  sizeof(drawVert_t));
-                                       memcpy(&points[j][i],   &points[i][j],  sizeof(drawVert_t));
-                                       memcpy(&points[i][j],   &dv,                    sizeof(drawVert_t));
+          std::swap(points[j][i], points[i][j]);
                                } 
                                else 
                                {
                                // just copy
-                                       memcpy(&points[i][j],   &points[j][i],  sizeof(drawVert_t));
+                                       points[i][j] = points[j][i];
                        }
                }
                 }
@@ -364,14 +378,12 @@ void DPatch::Transpose()
                        if ( j < width ) 
                                {
                                        // swap the value
-                                       memcpy(&dv,                             &points[i][j],  sizeof(drawVert_t));
-                                       memcpy(&points[i][j],   &points[j][i],  sizeof(drawVert_t));
-                               memcpy(&points[j][i],   &dv,                    sizeof(drawVert_t));
+          std::swap(points[i][j], points[j][i]);
                        } 
                                else 
                                {
                                // just copy
-                                       memcpy(&points[j][i],   &points[i][j],  sizeof(drawVert_t));
+                                       points[j][i] = points[i][j];
                        }
                }
        }
@@ -404,7 +416,7 @@ std::list<DPatch> DPatch::Split(bool rows, bool cols)
                        {
                                for(x = 0; x < p.width; x++)
                                {
-                                       memcpy(&p.points[x][y], &points[x][(i*2)+y],    sizeof(drawVert_t));
+                                       p.points[x][y] = points[x][(i*2)+y];
                                }
                        }
                        patchList.push_back(p);
@@ -439,7 +451,7 @@ std::list<DPatch> DPatch::Split(bool rows, bool cols)
                        {
                                for(y = 0; y < p.height; y++)
                                {
-                                       memcpy(&p.points[x][y], &points[(i*2)+x][y],    sizeof(drawVert_t));
+                                       p.points[x][y] = points[(i*2)+x][y];
                                }
                        }
 
index d1442ce..3243918 100644 (file)
@@ -43,6 +43,7 @@ typedef struct {
 namespace scene
 {
   class Node;
+  class Instance;
 }
 
 #define MAX_PATCH_WIDTH 16
@@ -59,8 +60,9 @@ public:
        DPatch* MergePatches(patch_merge_t merge_info, DPatch* p1, DPatch* p2);
        patch_merge_t IsMergable(DPatch* other);
   bool ResetTextures(const char *oldTextureName, const char *newTextureName);
+  scene::Node* QER_entity;
        scene::Node* QER_brush;
-       void LoadFromBrush(scene::Node& brush);
+       void LoadFromPatch(scene::Instance& patch);
        void BuildInRadiant(scene::Node* entity = NULL);
        void SetTexture(const char* textureName);
        char texture[256];
index c9c7b67..c16db74 100644 (file)
@@ -236,7 +236,7 @@ bool DPlane::AddToBrush(scene::Node& brush)
   faceData.m_p2 = vector3_from_array(points[2]);
   faceData.m_texdef = texInfo.m_texdef;
   faceData.m_shader = m_shader.c_str();
-  GlobalBrushCreator().addBrushFace(brush, faceData);
+  GlobalBrushCreator().Brush_addFace(brush, faceData);
 
        return changed;
 }
index 38abb65..c0831bf 100644 (file)
@@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #include "funchandlers.h"
 
 #include "iglrender.h"
+#include "ientity.h"
 #include "math/matrix.h"
 
 #include "dialogs/dialogs-gtk.h"
@@ -169,16 +170,18 @@ void AddSplineControl(const char* control, splinePoint_t* pSP) {
        pSP->m_pointList.push_front(cp);
 }
 
-void DTrainDrawer::BuildPaths() {
-#if 0
-       int count = g_FuncTable.m_pfnGetEntityCount();
-
-       DEntity e;
-
-       for(int i = 0; i < count; i++) {
-               entity_s* ent = (entity_s*)g_FuncTable.m_pfnGetEntityHandle(i);
+class EntityBuildPaths
+{
+       mutable DEntity e;
+  DTrainDrawer& drawer;
+public:
+  EntityBuildPaths(DTrainDrawer& drawer) : drawer(drawer)
+  {
+  }
+  void operator()(scene::Instance& instance) const
+  {
                e.ClearEPairs();
-               e.LoadEPairList(*g_EntityTable.m_pfnGetEntityKeyValList(ent));
+               e.LoadEPairList(Node_getEntity(instance.path().top()));
 
                const char* classname = e.m_Classname.GetBuffer();
                const char* target;
@@ -191,16 +194,16 @@ void DTrainDrawer::BuildPaths() {
 
                if(!strcmp(classname, "info_train_spline_main")) {
                        if(!targetname) {
-                               Sys_Printf( "info_train_spline_main with no targetname" );
+                               globalOutputStream() << "info_train_spline_main with no targetname";
                                return;
                        }
 
                        e.SpawnString("target", NULL, &target);
 
                        if(!target) {
-                               AddControlPoint( targetname, vOrigin );
+                               drawer.AddControlPoint( targetname, vOrigin );
                        } else {
-                               splinePoint_t* pSP = AddSplinePoint( targetname, target, vOrigin );
+                               splinePoint_t* pSP = drawer.AddSplinePoint( targetname, target, vOrigin );
 
                                e.SpawnString("control", NULL, &control);
 
@@ -215,20 +218,24 @@ void DTrainDrawer::BuildPaths() {
                                                if(!control) {
                                                        break;
                                                }
-                                       
+                               
                                                AddSplineControl( control, pSP );
                                        }
                                }
                        }
                } else if(!strcmp(classname, "info_train_spline_control")) {
                        if(!targetname) {
-                               Sys_Printf( "info_train_spline_control with no targetname" );
+                               globalOutputStream() << "info_train_spline_control with no targetname";
                                return;
                        }
 
-                       AddControlPoint( targetname, vOrigin );
+                       drawer.AddControlPoint( targetname, vOrigin );
                }
-       }
+  }
+};
+
+void DTrainDrawer::BuildPaths() {
+  Scene_forEachEntity(EntityBuildPaths(*this));
 
   std::list<splinePoint_t* >::const_iterator sp;
        for(sp = m_splineList.begin(); sp != m_splineList.end(); sp++) {
@@ -237,7 +244,7 @@ void DTrainDrawer::BuildPaths() {
                controlPoint_t* pTarget = FindControlPoint( pSP->strTarget );
 
                if(!pTarget) {
-                       Sys_Printf( "couldn't find target %s", pSP->strTarget );
+                       globalOutputStream() << "couldn't find target " << pSP->strTarget;
                        return;
 //                     continue;
                }
@@ -248,7 +255,7 @@ void DTrainDrawer::BuildPaths() {
                for(std::list<controlPoint_t >::iterator cp = pSP->m_pointList.begin(); cp != pSP->m_pointList.end(); cp++) {                   
                        controlPoint_t* pControl = FindControlPoint( (*cp).strName );
                        if(!pControl) {
-                               Sys_Printf( "couldn't find control %s", (*cp).strName );
+                               globalOutputStream() << "couldn't find control " << (*cp).strName;
                                return;
                        }
 
@@ -256,8 +263,7 @@ void DTrainDrawer::BuildPaths() {
                }
        }
 
-       m_bDisplay = TRUE;
-       Register();
+       m_bDisplay = true;
 
        for(sp = m_splineList.begin(); sp != m_splineList.end(); sp++) {
                splinePoint_t* pSP = (*sp);
@@ -290,7 +296,7 @@ void DTrainDrawer::BuildPaths() {
                pSP->m_vertexList.push_front(out);
        }
 
-#endif
+  SceneChangeNotify();
 }
 
 void DTrainDrawer::AddControlPoint(const char* name, vec_t* origin)
index 54850ce..958bcf8 100644 (file)
@@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 #include "ScriptParser.h"
 #include "misc.h"
+#include "scenelib.h"
 
 
 
@@ -55,7 +56,7 @@ SignalHandlerResult DTreePlanter::mouseDown(const WindowVector& position, Button
 
        Vector3 pt, vhit;
 
-  pt = vector3_snapped(GlobalRadiant().XYWindow_windowToWorld(position));
+  pt = vector3_snapped(GlobalRadiant().XYWindow_windowToWorld(position), GlobalRadiant().getGridSize());
 
        if(FindDropPoint(vector3_to_array(pt), vector3_to_array(vhit))) {
                vhit[2] += m_offset;
@@ -67,18 +68,17 @@ SignalHandlerResult DTreePlanter::mouseDown(const WindowVector& position, Button
                e.AddEPair("origin", buffer);
 
                if(m_autoLink) {
-#if 0
-                       entity_t* pLastEntity = NULL;
-                       entity_t* pThisEntity = NULL;
 
-                       int entNum = -1, lastEntNum = -1, entpos;
+      const scene::Path* pLastEntity = NULL;
+                       const scene::Path* pThisEntity = NULL;
+
+                       int entpos;
                        for(int i = 0; i < 256; i++) {
                                sprintf(buffer, m_linkName, i);
-                               pThisEntity = FindEntityFromTargetname( buffer, &entNum );
+        pThisEntity = FindEntityFromTargetname( buffer );
 
                                if(pThisEntity) {
                                        entpos = i;
-                                       lastEntNum = entNum;
                                        pLastEntity = pThisEntity;
                                }
                        }
@@ -93,12 +93,12 @@ SignalHandlerResult DTreePlanter::mouseDown(const WindowVector& position, Button
 
                        if(pLastEntity) {
                                DEntity e2;
-                               e2.LoadFromEntity(lastEntNum, TRUE);
+                               e2.LoadFromEntity(pLastEntity->top(), true);
                                e2.AddEPair("target", buffer);
                                e2.RemoveFromRadiant();
                                e2.BuildInRadiant(false);
                        }
-#endif
+
                }
 
                if(m_setAngles) {
@@ -179,38 +179,42 @@ bool DTreePlanter::FindDropPoint(vec3_t in, vec3_t out) {
        return found;
 }
 
-void DTreePlanter::DropEntsToGround( void ) {
-#if 0
-       // tell Radiant we want to access the selected brushes
-       g_FuncTable.m_pfnAllocateSelectedBrushHandles();
-                       
-       DEntity ent;
-
-       int cnt = g_FuncTable.m_pfnSelectedBrushCount();
-       for(int i = 0; i < cnt; i++) {
-               brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(i);
-
-               ent.LoadFromEntity(brush->owner, TRUE);
+class TreePlanterDropEntityIfSelected
+{
+  mutable DEntity ent;
+  DTreePlanter& planter;
+public:
+  TreePlanterDropEntityIfSelected(DTreePlanter& planter) : planter(planter)
+  {
+  }
+  void operator()(scene::Instance& instance) const
+  {
+    if(!instance.isSelected())
+    {
+      return;
+    }
+               ent.LoadFromEntity(instance.path().top());
 
                DEPair* pEpair = ent.FindEPairByKey("origin");
                if(!pEpair) {
-                       continue;
+                       return;
                }
 
                vec3_t vec, out;
                sscanf( pEpair->value.GetBuffer(), "%f %f %f", &vec[0], &vec[1], &vec[2]);
 
-               FindDropPoint( vec, out );
+               planter.FindDropPoint( vec, out );
 
                char buffer[256];
                sprintf( buffer, "%f %f %f", out[0], out[1], out[2] );
                ent.AddEPair( "origin", buffer );
                ent.RemoveFromRadiant();
                ent.BuildInRadiant(false);
-       }
+  }
+};
 
-       g_FuncTable.m_pfnReleaseSelectedBrushHandles();
-#endif
+void DTreePlanter::DropEntsToGround( void ) {
+  Scene_forEachEntity(TreePlanterDropEntityIfSelected(*this));
 }
 
 void DTreePlanter::MakeChain( void ) {
index 61bc1e8..7fceba3 100644 (file)
@@ -39,9 +39,16 @@ typedef struct treeModel_s {
 
 class DTreePlanter {
   MouseEventHandlerId m_mouseDown;
+  SignalHandlerId m_destroyed;
 public:
        SignalHandlerResult mouseDown(const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers);
   typedef Member3<DTreePlanter, const WindowVector&, ButtonIdentifier, ModifierFlags, SignalHandlerResult, &DTreePlanter::mouseDown> MouseDownCaller;
+       void destroyed()
+  {
+    m_mouseDown = MouseEventHandlerId();
+    m_destroyed = SignalHandlerId();
+  }
+  typedef Member<DTreePlanter, void, &DTreePlanter::destroyed> DestroyedCaller;
 
   DTreePlanter() {
                m_numModels =   0;
@@ -83,11 +90,19 @@ public:
                }
 
     m_mouseDown = GlobalRadiant().XYWindowMouseDown_connect(makeSignalHandler3(MouseDownCaller(), *this));
+    m_destroyed = GlobalRadiant().XYWindowDestroyed_connect(makeSignalHandler(DestroyedCaller(), *this));
        }
 
   virtual ~DTreePlanter()
   {
-    GlobalRadiant().XYWindowMouseDown_disconnect(m_mouseDown);
+    if(!m_mouseDown.isNull())
+    {
+      GlobalRadiant().XYWindowMouseDown_disconnect(m_mouseDown);
+    }
+    if(!m_destroyed.isNull())
+    {
+      GlobalRadiant().XYWindowDestroyed_disconnect(m_destroyed);
+    }
   }
 
 #define MT(t)  string_equal_nocase( pToken, t )
index b5d8859..826613e 100644 (file)
@@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
 #include "ScriptParser.h"
+#include <string.h>
 
 CScriptParser::CScriptParser(void): 
        m_pScript(NULL),
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_caulk.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_caulk.bmp
new file mode 100644 (file)
index 0000000..5223950
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_caulk.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_cleanup.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_cleanup.bmp
new file mode 100644 (file)
index 0000000..33cc949
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_cleanup.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_dropent.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_dropent.bmp
new file mode 100644 (file)
index 0000000..2fcdcba
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_dropent.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_merge.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_merge.bmp
new file mode 100644 (file)
index 0000000..cc5e272
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_merge.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_poly.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_poly.bmp
new file mode 100644 (file)
index 0000000..ed720e9
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_poly.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_split.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_split.bmp
new file mode 100644 (file)
index 0000000..fbb1571
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_split.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_trainpathplot.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_trainpathplot.bmp
new file mode 100644 (file)
index 0000000..66537dc
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_trainpathplot.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_treeplanter.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_treeplanter.bmp
new file mode 100644 (file)
index 0000000..08f55f3
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_treeplanter.bmp differ
diff --git a/contrib/bobtoolz/bitmaps/bobtoolz_turnedge.bmp b/contrib/bobtoolz/bitmaps/bobtoolz_turnedge.bmp
new file mode 100644 (file)
index 0000000..b72cb2a
Binary files /dev/null and b/contrib/bobtoolz/bitmaps/bobtoolz_turnedge.bmp differ
index b0940e0..c32a027 100644 (file)
@@ -17,12 +17,19 @@ License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#include "libxml/parser.h"
 
 
 #include "str.h"
+#include "qerplugin.h"
+#include "mathlib.h"
+#include "string/string.h"
+#include "itoolbar.h"
 
 #include "funchandlers.h"
+#include "DBobView.h"
+#include "DVisDrawer.h"
+#include "DTrainDrawer.h"
+#include "DTreePlanter.h"
 
 #include "dialogs/dialogs-gtk.h"
 #include "../../libs/cmdlib.h"
@@ -33,17 +40,24 @@ void BobToolz_construct()
 
 void BobToolz_destroy()
 {
+       if(g_PathView) {
+               delete g_PathView;
+               g_PathView = NULL;
+       }
+       if(g_VisView) {
+               delete g_VisView;
+               g_VisView = NULL;
+       }
+       if(g_TrainView) {
+               delete g_TrainView;
+               g_TrainView = NULL;
+       }
+       if(g_TreePlanter) {
+               delete g_TreePlanter;
+               g_TreePlanter = NULL;
+       }
 }
 
-// Radiant function table
-_QERFuncTable_1                          __QERTABLENAME;
-_QERShadersTable                 __SHADERSTABLENAME;                   // vvvvvvvvvvvvvvvvvvvv
-_QERQglTable                             __QGLTABLENAME;                               // for path plotting (hooking to DBobView)
-_QERUITable                                      g_MessageTable;                       // for path plotting (listening for update)
-_QEREntityTable                          __ENTITYTABLENAME;
-_QERBrushTable                   __BRUSHTABLENAME;
-_QERPatchTable                   __PATCHTABLENAME;
-
 // plugin name
 char* PLUGIN_NAME = "bobToolz";
 
@@ -105,27 +119,18 @@ extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool
        }
 }
 
+const char* QERPlug_GetCommandTitleList()
+{
+  return "";
+}
+
+
 #define NUM_TOOLBARBUTTONS 9
 
 unsigned int ToolbarButtonCount( void ) {
        return NUM_TOOLBARBUTTONS;
 }
 
-// Load a xpm file and return a pixmap widget.
-GtkWidget* new_pixmap (char* filename) {
-       GdkPixmap *gdkpixmap;
-       GdkBitmap *mask;
-       GtkWidget *pixmap;
-
-       g_FuncTable.m_pfnLoadBitmap(filename, (void **)&gdkpixmap, (void **)&mask);     
-       pixmap = gtk_pixmap_new (gdkpixmap, mask);
-
-       gdk_pixmap_unref (gdkpixmap);
-       gdk_pixmap_unref (mask);
-
-       return pixmap;
-} 
-
 class CBobtoolzToolbarButton : public IToolbarButton
 {
 public:
@@ -210,87 +215,114 @@ const IToolbarButton* GetToolbarButton(unsigned int index)
   return &g_bobtoolzToolbarButtons[index];
 }
 
-// =============================================================================
-// SYNAPSE
-
-#include "synapse.h"
 
-class CSynapseClientBobtoolz : public CSynapseClient
+#include "modulesystem/singletonmodule.h"
+
+#include "iscenegraph.h"
+#include "irender.h"
+#include "iundo.h"
+#include "ishaders.h"
+#include "ipatch.h"
+#include "ibrush.h"
+#include "ientity.h"
+#include "ieclass.h"
+#include "iglrender.h"
+#include "iplugin.h"
+
+class BobToolzPluginDependencies :
+  public GlobalRadiantModuleRef,
+  public GlobalUndoModuleRef,
+  public GlobalSceneGraphModuleRef,
+  public GlobalSelectionModuleRef,
+  public GlobalEntityModuleRef,
+  public GlobalEntityClassManagerModuleRef,
+  public GlobalShadersModuleRef,
+  public GlobalShaderCacheModuleRef,
+  public GlobalBrushModuleRef,
+  public GlobalPatchModuleRef,
+  public GlobalOpenGLModuleRef, 
+  public GlobalOpenGLStateLibraryModuleRef
 {
 public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  
-  CSynapseClientBobtoolz() { }
-  virtual ~CSynapseClientBobtoolz() { }
+  BobToolzPluginDependencies() :
+    GlobalEntityModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entities")),
+    GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")),
+    GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")),
+    GlobalPatchModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("patchtypes")),
+    GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass"))
+  {
+  }
 };
 
-#define BOBTOOLZ_MINOR "bobtoolz"
+class BobToolzPluginModule : public TypeSystemRef
+{
+  _QERPluginTable m_plugin;
+public:
+  typedef _QERPluginTable Type;
+  STRING_CONSTANT(Name, "bobtoolz");
 
-CSynapseServer* g_pSynapseServer = NULL;
-CSynapseClientBobtoolz g_SynapseClient;
+  BobToolzPluginModule()
+  {
+    m_plugin.m_pfnQERPlug_Init = QERPlug_Init;
+    m_plugin.m_pfnQERPlug_GetName = QERPlug_GetName;
+    m_plugin.m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
+    m_plugin.m_pfnQERPlug_GetCommandTitleList = QERPlug_GetCommandTitleList;
+    m_plugin.m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
 
-extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces (const char *version, CSynapseServer *pServer)
-{
-  if (strcmp(version, SYNAPSE_VERSION))
+    BobToolz_construct();
+  }
+  ~BobToolzPluginModule()
   {
-    Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
-    return NULL;
+    BobToolz_destroy();
   }
-  g_pSynapseServer = pServer;
-  g_pSynapseServer->IncRef();
-  Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());
-    
-  g_SynapseClient.AddAPI(TOOLBAR_MAJOR, BOBTOOLZ_MINOR, sizeof(_QERPlugToolbarTable));
-  g_SynapseClient.AddAPI(PLUGIN_MAJOR, BOBTOOLZ_MINOR, sizeof(_QERPluginTable));
-
-  g_SynapseClient.AddAPI(BRUSH_MAJOR, NULL, sizeof(__BRUSHTABLENAME), SYN_REQUIRE, &g_BrushTable);
-  g_SynapseClient.AddAPI(PATCH_MAJOR, NULL, sizeof(__PATCHTABLENAME), SYN_REQUIRE, &g_BrushTable);
-  g_SynapseClient.AddAPI(SHADERS_MAJOR, "*", sizeof(g_ShadersTable), SYN_REQUIRE, &g_ShadersTable);
-  g_SynapseClient.AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);
-  g_SynapseClient.AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(g_SelectedFaceTable), SYN_REQUIRE, &g_SelectedFaceTable);
-  g_SynapseClient.AddAPI(UI_MAJOR, NULL, sizeof(g_MessageTable), SYN_REQUIRE, &g_MessageTable);
-  g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(__QERTABLENAME), SYN_REQUIRE, &g_FuncTable);
-  g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable);
-
-  return &g_SynapseClient;
-}
-
-bool CSynapseClientBobtoolz::RequestAPI(APIDescriptor_t *pAPI)
-{
-  if( !strcmp(pAPI->minor_name, BOBTOOLZ_MINOR) )
+  _QERPluginTable* getTable()
   {
-    if( !strcmp(pAPI->major_name, PLUGIN_MAJOR) )
-    {
-      _QERPluginTable* pTable= static_cast<_QERPluginTable*>(pAPI->mpTable);
+    return &m_plugin;
+  }
+};
 
-      pTable->m_pfnQERPlug_Init = QERPlug_Init;
-      pTable->m_pfnQERPlug_GetName = QERPlug_GetName;
-      pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
-      pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
+typedef SingletonModule<BobToolzPluginModule, BobToolzPluginDependencies> SingletonBobToolzPluginModule;
 
-      return true;
-    }
-    else if( !strcmp(pAPI->major_name, TOOLBAR_MAJOR) )
-    {
-      _QERPlugToolbarTable* pTable= static_cast<_QERPlugToolbarTable*>(pAPI->mpTable);
+SingletonBobToolzPluginModule g_BobToolzPluginModule;
 
-      pTable->m_pfnToolbarButtonCount = &ToolbarButtonCount;
-      pTable->m_pfnGetToolbarButton = &GetToolbarButton;
 
-      return true;
-    }
+class BobToolzToolbarDependencies :
+  public ModuleRef<_QERPluginTable>
+{
+public:
+  BobToolzToolbarDependencies() :
+    ModuleRef<_QERPluginTable>("bobtoolz")
+  {
   }
+};
 
-  Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
-  return false;
-}
+class BobToolzToolbarModule : public TypeSystemRef
+{
+  _QERPlugToolbarTable m_table;
+public:
+  typedef _QERPlugToolbarTable Type;
+  STRING_CONSTANT(Name, "bobtoolz");
 
-#include "version.h"
+  BobToolzToolbarModule()
+  {
+    m_table.m_pfnToolbarButtonCount = ToolbarButtonCount;
+    m_table.m_pfnGetToolbarButton = GetToolbarButton;
+  }
+  _QERPlugToolbarTable* getTable()
+  {
+    return &m_table;
+  }
+};
+
+typedef SingletonModule<BobToolzToolbarModule, BobToolzToolbarDependencies> SingletonBobToolzToolbarModule;
+
+SingletonBobToolzToolbarModule g_BobToolzToolbarModule;
 
-const char* CSynapseClientBobtoolz::GetInfo()
+
+extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
 {
-  return "bobToolz module built " __DATE__ " " RADIANT_VERSION;
-}
+  initialiseModule(server);
 
+  g_BobToolzPluginModule.selfRegister();
+  g_BobToolzToolbarModule.selfRegister();
+}
\ No newline at end of file
diff --git a/contrib/bobtoolz/bobtoolz.vcproj b/contrib/bobtoolz/bobtoolz.vcproj
new file mode 100644 (file)
index 0000000..365a96c
--- /dev/null
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="bobtoolz"\r
+       ProjectGUID="{B20364D1-4329-4D4E-B9CE-C9767618FDD6}"\r
+       Keyword="MFCProj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug"\r
+                       IntermediateDirectory=".\Debug"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="2"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../../include;../../libs;&quot;../../../STLPort-4.6/stlport&quot;;&quot;../../../gtk2-2.4/lib/glib-2.0/include&quot;;&quot;../../../gtk2-2.4/include/glib-2.0&quot;;&quot;../../../gtk2-2.4/lib/gtk-2.0/include&quot;;&quot;../../../gtk2-2.4/include/gtk-2.0&quot;;&quot;../../../gtk2-2.4/include/gtk-2.0/gdk&quot;;&quot;../../../gtk2-2.4/include/pango-1.0&quot;;&quot;../../../gtk2-2.4/include/atk-1.0&quot;"\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL"\r
+                               StringPooling="TRUE"\r
+                               MinimalRebuild="TRUE"\r
+                               ExceptionHandling="FALSE"\r
+                               RuntimeLibrary="3"\r
+                               BufferSecurityCheck="FALSE"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderThrough=""\r
+                               PrecompiledHeaderFile=" "\r
+                               AssemblerListingLocation=".\Debug/"\r
+                               ObjectFile=".\Debug/"\r
+                               ProgramDataBaseFileName=".\Debug/"\r
+                               BrowseInformation="0"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="2"\r
+                               DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/MACHINE:I386"\r
+                               AdditionalDependencies="glib-2.0.lib gobject-2.0.lib gdk-win32-2.0.lib gtk-win32-2.0.lib pango-1.0.lib profile.lib mathlib.lib"\r
+                               OutputFile="./Debug/$(ProjectName).dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               AdditionalLibraryDirectories="&quot;../../../gtk2-2.4/lib&quot;;../../libs/profile/debug;../../libs/mathlib/debug"\r
+                               IgnoreDefaultLibraryNames="msvcprtd.lib"\r
+                               ModuleDefinitionFile="./$(ProjectName).def"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               ImportLibrary="./Debug/$(ProjectName).lib"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="TRUE"\r
+                               SuppressStartupBanner="TRUE"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="./Debug/$(ProjectName).tlb"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="copy &quot;$(TargetPath)&quot; &quot;$(SolutionDir)install\plugins&quot;\r
+copy &quot;$(TargetDir)$(TargetName).pdb&quot; &quot;$(SolutionDir)install\plugins&quot;\r
+"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_AFXDLL;_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release"\r
+                       IntermediateDirectory=".\Release"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="2"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               GlobalOptimizations="TRUE"\r
+                               InlineFunctionExpansion="2"\r
+                               EnableIntrinsicFunctions="TRUE"\r
+                               FavorSizeOrSpeed="1"\r
+                               AdditionalIncludeDirectories="../../include;../../libs;&quot;../../../STLPort-4.6/stlport&quot;;&quot;../../../gtk2-2.4/lib/glib-2.0/include&quot;;&quot;../../../gtk2-2.4/include/glib-2.0&quot;;&quot;../../../gtk2-2.4/lib/gtk-2.0/include&quot;;&quot;../../../gtk2-2.4/include/gtk-2.0&quot;;&quot;../../../gtk2-2.4/include/gtk-2.0/gdk&quot;;&quot;../../../gtk2-2.4/include/pango-1.0&quot;;&quot;../../../gtk2-2.4/include/atk-1.0&quot;"\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL"\r
+                               StringPooling="TRUE"\r
+                               ExceptionHandling="FALSE"\r
+                               RuntimeLibrary="2"\r
+                               BufferSecurityCheck="FALSE"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="0"\r
+                               PrecompiledHeaderThrough=""\r
+                               PrecompiledHeaderFile=" "\r
+                               AssemblerListingLocation=".\Release/"\r
+                               ObjectFile=".\Release/"\r
+                               ProgramDataBaseFileName=".\Release/"\r
+                               BrowseInformation="0"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="2"\r
+                               DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalOptions="/MACHINE:I386"\r
+                               AdditionalDependencies="glib-2.0.lib gobject-2.0.lib gdk-win32-2.0.lib gtk-win32-2.0.lib pango-1.0.lib profile.lib mathlib.lib"\r
+                               OutputFile="./Release/$(ProjectName).dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               AdditionalLibraryDirectories="&quot;../../../gtk2-2.4/lib&quot;;../../libs/profile/release;../../libs/mathlib/release"\r
+                               IgnoreDefaultLibraryNames="msvcprt.lib"\r
+                               ModuleDefinitionFile="./$(ProjectName).def"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               ImportLibrary="./Release/$(ProjectName).lib"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="TRUE"\r
+                               SuppressStartupBanner="TRUE"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName="./Release/$(ProjectName).tlb"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               CommandLine="copy &quot;$(TargetPath)&quot; &quot;$(SolutionDir)install\plugins&quot;\r
+copy &quot;$(TargetDir)$(TargetName).pdb&quot; &quot;$(SolutionDir)install\plugins&quot;\r
+"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_AFXDLL;NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="src"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath=".\bobToolz-GTK.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\bsploader.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\bsploader.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\cportals.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\CPortals.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DBobView.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DBobView.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DBrush.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DBrush.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DEntity.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DEntity.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DEPair.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DEPair.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DMap.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DMap.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DPatch.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DPatch.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DPlane.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DPlane.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DPoint.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DPoint.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DShape.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DShape.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DTrainDrawer.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DTrainDrawer.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DTreePlanter.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DTreePlanter.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DVisDrawer.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DVisDrawer.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DWinding.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\DWinding.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\funchandlers-GTK.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\funchandlers.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\lists.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\lists.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\misc.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\misc.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\resource-gtk.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ScriptParser.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ScriptParser.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\shapes.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\shapes.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\visfind.cpp">\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\visfind.h">\r
+                       </File>\r
+                       <Filter\r
+                               Name="dialogs"\r
+                               Filter="">\r
+                               <File\r
+                                       RelativePath=".\dialogs\dialogs-gtk.cpp">\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\dialogs\dialogs-gtk.h">\r
+                               </File>\r
+                       </Filter>\r
+               </Filter>\r
+               <File\r
+                       RelativePath="bobtoolz.def">\r
+                       <FileConfiguration\r
+                               Name="Debug|Win32">\r
+                               <Tool\r
+                                       Name="VCCustomBuildTool"\r
+                                       CommandLine="python &quot;$(SolutionDir)touch.py&quot; &quot;$(TargetPath)&quot;\r
+"\r
+                                       AdditionalDependencies="&quot;$(SolutionDir)install\modules\$(TargetFileName)&quot;"\r
+                                       Outputs="&quot;$(TargetPath)&quot;"/>\r
+                       </FileConfiguration>\r
+                       <FileConfiguration\r
+                               Name="Release|Win32">\r
+                               <Tool\r
+                                       Name="VCCustomBuildTool"\r
+                                       CommandLine="python &quot;$(SolutionDir)touch.py&quot; &quot;$(TargetPath)&quot;\r
+"\r
+                                       AdditionalDependencies="&quot;$(SolutionDir)install\modules\$(TargetFileName)&quot;"\r
+                                       Outputs="&quot;$(TargetPath)&quot;"/>\r
+                       </FileConfiguration>\r
+               </File>\r
+               <File\r
+                       RelativePath="..\..\debug.py">\r
+                       <FileConfiguration\r
+                               Name="Debug|Win32">\r
+                               <Tool\r
+                                       Name="VCCustomBuildTool"\r
+                                       CommandLine="python &quot;$(SolutionDir)debug.py&quot;\r
+"\r
+                                       AdditionalDependencies="&quot;$(SolutionDir)install\plugins\$(TargetName).pdb&quot;"\r
+                                       Outputs="&quot;$(TargetDir)$(TargetName).pdb&quot;"/>\r
+                       </FileConfiguration>\r
+                       <FileConfiguration\r
+                               Name="Release|Win32">\r
+                               <Tool\r
+                                       Name="VCCustomBuildTool"\r
+                                       CommandLine="python &quot;$(SolutionDir)debug.py&quot;\r
+"\r
+                                       AdditionalDependencies="&quot;$(SolutionDir)install\plugins\$(TargetName).pdb&quot;"\r
+                                       Outputs="&quot;$(TargetDir)$(TargetName).pdb&quot;"/>\r
+                       </FileConfiguration>\r
+               </File>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
index 0058ea7..cdfc54f 100644 (file)
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 #include "str.h"
 #include <list>
+#include <gtk/gtk.h>
 
 #include "../lists.h"
 #include "../misc.h"
@@ -1349,12 +1350,8 @@ EMessageBoxReturn DoResetTextureBox (ResetTextureRS* rs)
        
        // ---- hbox ----
 
-       texSelected = "Currently Selected Face:   ";
-#if 0
-       if(g_SelectedFaceTable.m_pfnGetSelectedFaceCount() == 1) {
-               texSelected += GetCurrentTexture();
-       }
-#endif
+       texSelected = "Currently Selected Texture:   ";
+  texSelected += GetCurrentTexture();
 
        w = gtk_label_new (texSelected);
        gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 2);
index d492d74..577bdaf 100644 (file)
@@ -60,10 +60,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 std::list<Str> exclusionList;          // whole brush exclusion
 std::list<Str> exclusionList_Face;     // single face exclusion
 
-bool el1Loaded =               FALSE;
-bool el2Loaded =               FALSE;
-bool clrLst1Loaded =   FALSE;
-bool clrLst2Loaded =   FALSE;
+bool el1Loaded =               false;
+bool el2Loaded =               false;
+bool clrLst1Loaded =   false;
+bool clrLst2Loaded =   false;
 
 DBobView*              g_PathView =            NULL;
 DVisDrawer*            g_VisView =                     NULL;
@@ -92,6 +92,7 @@ void LoadLists()
 
 void DoIntersect()
 {
+  UndoableCommand undo("bobToolz.intersect");
        IntersectRS rs;
 
        if(DoIntersectBox(&rs) == eIDCANCEL)
@@ -117,7 +118,7 @@ void DoIntersect()
                }
        case BRUSH_OPT_WHOLE_MAP:
                {
-                       world.LoadFromEntity(0, FALSE);
+                       world.LoadFromEntity(GlobalRadiant().getMapWorldEntity(), false);
                        break;
                }
        }
@@ -142,6 +143,7 @@ void DoPolygonsTB()
 
 void DoPolygons()
 {
+  UndoableCommand undo("bobToolz.polygons");
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
@@ -160,10 +162,10 @@ void DoPolygons()
 
     {
       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-      VectorSubtract(instance.aabb_world().origin, instance.aabb_world().extents, vMin);
-      VectorAdd(instance.aabb_world().origin, instance.aabb_world().extents, vMax);
+      VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
+      VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
 
-      Node_getTraversable(instance.path().parent())->erase(instance.path().top());
+      Path_deleteTop(instance.path());
     }
 
                if(rs.bInverse)
@@ -183,16 +185,18 @@ void DoPolygons()
 
 void DoFixBrushes()
 {
+  UndoableCommand undo("bobToolz.fixBrushes");
        DMap world;
        world.LoadAll();
 
        int count = world.FixBrushes();
        
-       Sys_Printf("%i invalid/duplicate planes removed\n", count);
+       globalOutputStream() << count << " invalid/duplicate planes removed\n";
 }
 
 void DoResetTextures()
 {
+  UndoableCommand undo("bobToolz.resetTextures");
        static ResetTextureRS rs;
 
   const char* texName;
@@ -218,12 +222,12 @@ void DoResetTextures()
          DEntity world;
          world.LoadSelectedBrushes();
          world.ResetTextures(texName,              rs.fScale,      rs.fShift,      rs.rotation, rs.newTextureName, 
-                        rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation, TRUE);
+                        rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation, true);
   }
   else
   {
          DMap world;
-    world.LoadAll(TRUE);
+    world.LoadAll(true);
     world.ResetTextures(texName,              rs.fScale,      rs.fShift,      rs.rotation, rs.newTextureName, 
                         rs.bResetTextureName, rs.bResetScale, rs.bResetShift, rs.bResetRotation);
   }
@@ -231,6 +235,7 @@ void DoResetTextures()
 
 void DoBuildStairs()
 {
+  UndoableCommand undo("bobToolz.buildStairs");
        BuildStairsRS rs;
 
        strcpy(rs.mainTexture, GetCurrentTexture());
@@ -249,8 +254,8 @@ void DoBuildStairs()
 
     {
       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-      VectorSubtract(instance.aabb_world().origin, instance.aabb_world().extents, vMin);
-      VectorAdd(instance.aabb_world().origin, instance.aabb_world().extents, vMax);
+      VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
+      VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
     }
 
                // calc brush size
@@ -266,7 +271,7 @@ void DoBuildStairs()
                {
       {
         scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-        Node_getTraversable(instance.path().parent())->erase(instance.path().top());
+        Path_deleteTop(instance.path());
       }
                                                
                        // Get Step Count
@@ -290,7 +295,7 @@ void DoBuildStairs()
 
                                // Build Base For Stair (bob's style)
                                if(rs.style == STYLE_BOB)
-                                       Build_Wedge(rs.direction, vMin, vMax, TRUE);
+                                       Build_Wedge(rs.direction, vMin, vMax, true);
 
 
                                // Set First Step Starting Position
@@ -319,6 +324,7 @@ void DoBuildStairs()
 
 void DoBuildDoors()
 {
+  UndoableCommand undo("bobToolz.buildDoors");
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
@@ -335,9 +341,9 @@ void DoBuildDoors()
 
     {
       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-      VectorSubtract(instance.aabb_world().origin, instance.aabb_world().extents, vMin);
-      VectorAdd(instance.aabb_world().origin, instance.aabb_world().extents, vMax);
-      Node_getTraversable(instance.path().parent())->erase(instance.path().top());
+      VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
+      VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
+      Path_deleteTop(instance.path());
     }
 
                BuildDoorsX2(vMin, vMax, 
@@ -350,6 +356,7 @@ void DoBuildDoors()
 
 void DoPathPlotter()
 {
+  UndoableCommand undo("bobToolz.pathPlotter");
        PathPlotterRS rs;
        EMessageBoxReturn ret = DoPathPlotterBox(&rs);
        if(ret == eIDCANCEL)
@@ -377,6 +384,7 @@ void DoPathPlotter()
 
 void DoPitBuilder()
 {
+  UndoableCommand undo("bobToolz.pitBuilder");
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
@@ -387,8 +395,8 @@ void DoPitBuilder()
   vec3_t vMin, vMax;
 
   scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-  VectorSubtract(instance.aabb_world().origin, instance.aabb_world().extents, vMin);
-  VectorAdd(instance.aabb_world().origin, instance.aabb_world().extents, vMax);
+  VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
+  VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
 
        DShape pit;
 
@@ -396,7 +404,7 @@ void DoPitBuilder()
        {
                pit.Commit();
 
-    Node_getTraversable(instance.path().parent())->erase(instance.path().top());
+    Path_deleteTop(instance.path());
        }
        else
                DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK);
@@ -404,6 +412,7 @@ void DoPitBuilder()
 
 void DoMergePatches()
 {
+  UndoableCommand undo("bobToolz.mergePatch");
   patch_merge_t merge_info;
   DPatch mrgPatches[2];
   int i;
@@ -415,22 +424,19 @@ void DoMergePatches()
                return; 
        }
 
-  scene::Node* patches[2];
-  patches[0] = GlobalSelectionSystem().ultimateSelected().path().top();
-  patches[1] = GlobalSelectionSystem().penultimateSelected().path().top();
-  scene::Node* ents[2];
-  ents[0] = GlobalSelectionSystem().ultimateSelected().path().parent();
-  ents[1] = GlobalSelectionSystem().penultimateSelected().path().parent();
+  scene::Instance* patches[2];
+  patches[0] = &GlobalSelectionSystem().ultimateSelected();
+  patches[1] = &GlobalSelectionSystem().penultimateSelected();
 
   for (i = 0; i < 2; i++)
   {
-    if (!patches[i]->m_patch)
+    if (!Node_isPatch(patches[i]->path().top()))
     {
       DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
       return; 
     }
 
-    mrgPatches[0].LoadFromBrush(patches[i]);
+    mrgPatches[i].LoadFromPatch(*patches[i]);
   }
 
   /*  mrgPatches[0].Transpose();
@@ -441,9 +447,9 @@ void DoMergePatches()
 
   if (merge_info.mergable)
   {
-    Sys_Printf("%i %i", merge_info.pos1, merge_info.pos2);
+    globalOutputStream() << merge_info.pos1 << " " <<  merge_info.pos2;
 
-    Sys_Printf("Patches Mergable\n");
+    globalOutputStream() << "Patches Mergable\n";
     DPatch* newPatch = mrgPatches[0].MergePatches(merge_info, &mrgPatches[0], &mrgPatches[1]);
 
     /*                mrgPatches[0].RemoveFromRadiant();
@@ -459,16 +465,22 @@ void DoMergePatches()
     {
     } else
     {
-      Node_getTraversable(*ents[0])->erase(*patches[0]);
-      Node_getTraversable(*ents[1])->erase(*patches[1]);
+      Path_deleteTop(patches[0]->path());
+      Path_deleteTop(patches[1]->path());
 
       newPatch->BuildInRadiant();
       delete newPatch;
     }
   }
+  else
+  {
+    globalOutputStream() << "bobToolz.mergePatch: the selected patches are not mergable\n";
+  }
 }
 
 void DoSplitPatch() {
+  UndoableCommand undo("bobToolz.splitPatch");
+
        DPatch patch;
 
        // ensure we have something selected
@@ -478,21 +490,21 @@ void DoSplitPatch() {
                return; 
        }
 
-  scene::Node* node = GlobalSelectionSystem().ultimateSelected().path().top();
+  scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
 
-       if( !node->m_patch ) {
+       if( !Node_isPatch(instance.path().top()) ) {
                DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
                return; 
        }
 
-       patch.LoadFromBrush(node);
+       patch.LoadFromPatch(instance);
 
        std::list<DPatch> patchList = patch.Split( true, true );
        for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
                (*patches).BuildInRadiant();
        }
 
-       patch.RemoveFromRadiant();
+       Path_deleteTop(instance.path());
 }
 
 void DoVisAnalyse()
@@ -515,7 +527,7 @@ void DoVisAnalyse()
                return; 
        }
 
-  scene::Node* brush = GlobalSelectionSystem().ultimateSelected().path().top();
+  scene::Instance& brush = GlobalSelectionSystem().ultimateSelected();
 
        DBrush orgBrush;
        orgBrush.LoadFromBrush(brush, false);
@@ -527,7 +539,7 @@ void DoVisAnalyse()
        origin[2] = (orgBrush.bbox_max[2] + orgBrush.bbox_min[2])/2.f;
 
 
-  const char* rad_filename = g_FuncTable.m_pfnGetMapName();
+  const char* rad_filename = GlobalRadiant().getMapName();
        if(!rad_filename)
        {
                DoMessageBox("An Error Occurred While Trying\n To Get The Map Filename", "Error", eMB_OK);
@@ -544,7 +556,6 @@ void DoVisAnalyse()
        if(!g_VisView)
        {
                g_VisView = new DVisDrawer;
-               g_VisView->Register();
        }
        
        g_VisView->SetList(pointList);
@@ -560,6 +571,7 @@ void DoTrainPathPlot() {
 }
 
 void DoCaulkSelection() {
+  UndoableCommand undo("bobToolz.caulkSelection");
        DEntity world;
        
        float fScale[2] = { 0.5f, 0.5f };
@@ -574,6 +586,7 @@ void DoCaulkSelection() {
 }
 
 void DoTreePlanter() {
+  UndoableCommand undo("bobToolz.treePlanter");
        if(g_TreePlanter) {
                delete g_TreePlanter;
                g_TreePlanter = NULL;
@@ -584,12 +597,14 @@ void DoTreePlanter() {
 }
 
 void DoDropEnts() {
+  UndoableCommand undo("bobToolz.dropEntities");
        if(g_TreePlanter) {
                g_TreePlanter->DropEntsToGround();
        }
 }
 
 void DoMakeChain() {
+  UndoableCommand undo("bobToolz.makeChain");
        DTreePlanter pl;
        pl.MakeChain();
 }
@@ -599,6 +614,7 @@ typedef DPoint* pntTripple[3];
 bool bFacesNoTop[6] = {true, true, true, true, true, false};
 
 void DoFlipTerrain() {
+  UndoableCommand undo("bobToolz.flipTerrain");
        vec3_t vUp = { 0.f, 0.f, 1.f };
   int i;
 
@@ -609,15 +625,15 @@ void DoFlipTerrain() {
                return; 
        }
 
-  scene::Node* brushes[2];
-       brushes[0] = GlobalSelectionSystem().ultimateSelected().path().top();
-       brushes[1] = GlobalSelectionSystem().penultimateSelected().path().top();
+  scene::Instance* brushes[2];
+       brushes[0] = &GlobalSelectionSystem().ultimateSelected();
+       brushes[1] = &GlobalSelectionSystem().penultimateSelected();
 
        DBrush Brushes[2];
        DPlane* Planes[2];
        pntTripple Points[2];
        for( i = 0; i < 2; i++ ) {
-               Brushes[i].LoadFromBrush( brushes[i], false );
+               Brushes[i].LoadFromBrush( *brushes[i], false );
                if(!(Planes[i] = Brushes[i].FindPlaneWithClosestNormal( vUp )) || Brushes[i].FindPointsForPlane( Planes[i], Points[i], 3 ) != 3) {
                        DoMessageBox("Error", "Error", eMB_OK);
                        return;
@@ -628,14 +644,6 @@ void DoFlipTerrain() {
        Brushes[0].GetBounds( mins1, maxs1 );
        Brushes[1].GetBounds( mins2, maxs2 );
 
-  scene::Node* ents[2];
-       ents[0] = GlobalSelectionSystem().ultimateSelected().path().parent();
-       ents[1] = GlobalSelectionSystem().penultimateSelected().path().parent();
-
-       for( i = 0; i < 2; i++ ) {
-               Node_getTraversable(*ents[i])->erase(*brushes[i]);
-       }
-
 
 
        int dontmatch[2] = { -1, -1 };
@@ -754,7 +762,8 @@ void DoFlipTerrain() {
 
        for( i = 0; i < 2; i++ ) {
                newBrushes[i]->RemoveRedundantPlanes();
-               newBrushes[i]->BuildInRadiant( false, NULL, ents[i] );
+               newBrushes[i]->BuildInRadiant( false, NULL, brushes[i]->path().parent().get_pointer() );
+               Path_deleteTop(brushes[i]->path());
                delete newBrushes[i];
        }
 
index ca218f5..a429b78 100644 (file)
@@ -309,6 +309,8 @@ void FixBrushes()
 
 void AutoCaulk()
 {
+  UndoableCommand undo("bobToolz.autoCaulk");
+
        if(!el1Loaded)
                autocaulkDlg.m_Warning1 = "WARNING: Brush exclusion list not found\n, ALL BRUSHES WILL BE USED";
 
index faacbb7..9823b05 100644 (file)
@@ -81,6 +81,6 @@ bool LoadGList(char* filename, GList** loadlist)
                return TRUE;
        }
 
-       Sys_ERROR("Failed To Load GList: %s\n", filename);
+       globalErrorStream() << "Failed To Load GList: " << filename << "\n";
        return FALSE;
 }
index e56c4d8..e074796 100644 (file)
@@ -37,6 +37,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #endif
 
 #include "iundo.h"
+#include "ientity.h"
+#include "iscenegraph.h"
 #include "qerplugin.h"
 
 #include <vector>
@@ -251,7 +253,7 @@ void StartBSP()
        UnixToDosPath(exename); // do we want this done in linux version?
 
        char mapname[256];  
-  const char *pn = g_FuncTable.m_pfnReadProjectKey("mapspath");
+  const char *pn = GlobalRadiant().getMapsPath();
   
        strcpy( mapname, pn );
        strcat( mapname, "/ac_prt.map" );
@@ -263,16 +265,46 @@ void StartBSP()
        Q_Exec( command, TRUE );
 }
 
+class EntityWriteMiniPrt
+{
+       mutable DEntity world;
+  FILE* pFile;
+  std::list<Str>* exclusionList;
+public:
+  EntityWriteMiniPrt(FILE* pFile, std::list<Str>* exclusionList)
+    : pFile(pFile), exclusionList(exclusionList)
+  {
+  }
+  void operator()(scene::Instance& instance) const
+  {
+               const char* classname = Node_getEntity(instance.path().top())->getKeyValue("classname");
+
+               if(!strcmp(classname, "worldspawn"))
+               {
+                       world.LoadFromEntity(instance.path().top(), FALSE);
+                       world.RemoveNonCheckBrushes(exclusionList, TRUE);
+                       world.SaveToFile(pFile);
+               }
+               else if(strstr(classname, "info_"))
+               {
+                       world.ClearBrushes();
+                       world.ClearEPairs();
+                       world.LoadEPairList(Node_getEntity(instance.path().top()));
+                       world.SaveToFile(pFile);
+               }
+  }
+};
 void BuildMiniPrt(std::list<Str>* exclusionList)
 {
        // yes, we could just use -fulldetail option, but, as SPOG said
        // it'd be faster without all the hint, donotenter etc textures and
        // doors, etc
 
-       DEntity world;
+       
        
        char buffer[128];
-  const char *pn = g_FuncTable.m_pfnReadProjectKey("mapspath");
+  const char *pn = GlobalRadiant().getMapsPath();
 
        strcpy( buffer, pn );
        strcat( buffer, "/ac_prt.map" );
@@ -282,98 +314,39 @@ void BuildMiniPrt(std::list<Str>* exclusionList)
        if(!pFile)
                return;
 
-#if 0
-  int count = g_FuncTable.m_pfnGetEntityCount();
-       for(int i = 0; i < count; i++)
-       {
-               entity_t* ent = (entity_t*)g_FuncTable.m_pfnGetEntityHandle(i);
-
-               epair_t* epl = *g_EntityTable.m_pfnGetEntityKeyValList(ent);
-
-               epair_t* ep = epl;
-               while(ep)
-               {
-                       if(!strcmp(ep->key, "classname"))
-                       {
-                               if(!strcmp(ep->value, "worldspawn"))
-                               {
-                                       world.LoadFromEntity(i, FALSE);
-                                       world.RemoveNonCheckBrushes(exclusionList, TRUE);
-                                       world.SaveToFile(pFile);
-                               }
-                               else if(strstr(ep->value, "info_"))
-                               {
-                                       world.ClearBrushes();
-                                       world.ClearEPairs();
-                                       world.LoadEPairList(epl);
-                                       world.SaveToFile(pFile);
-                               }
-                               break;
-                       }
-
-                       ep = ep->next;
-               }
-       }
-#endif
+  Scene_forEachEntity(EntityWriteMiniPrt(pFile, exclusionList));
 
        fclose(pFile);
 
        StartBSP();
 }
 
-template<typename Functor>
-class EntityWalker
+class EntityFindByTargetName
 {
-  const Functor& functor;
+  const char* targetname;
 public:
-  EntityWalker(const Functor& functor) : functor(functor)
+       mutable const scene::Path* result;
+  EntityFindByTargetName(const char* targetname)
+    : targetname(targetname), result(0)
   {
   }
-  bool pre(const Path& path, Instance& instance) const
+  void operator()(scene::Instance& instance) const
   {
-    if(Node_isEntity(path.top()))
+    if(result == 0)
     {
-      functor(path.top());
+                 const char* value = Node_getEntity(instance.path().top())->getKeyValue("targetname");
+
+                 if(!strcmp(value, targetname))
+                 {
+                         result = &instance.path();
+                 }
     }
   }
 };
-
-template<typename Functor>
-const Functor& Scene_forEachEntity(const Functor& functor)
+const scene::Path* FindEntityFromTargetname(const char* targetname)
 {
-  GlobalSceneGraph().traverse(EntityWalker<Functor>(functor));
-}
-
-void 
-
-scene::Path* FindEntityFromTargetname(const char* targetname, int* entNum)
-{
-#if 0
-       DEntity world;
-
-       int count = g_FuncTable.m_pfnGetEntityCount();
-       for(int i = 0; i < count; i++)
-       {
-               world.ClearEPairs();
-
-               entity_s* ent = (entity_s*)g_FuncTable.m_pfnGetEntityHandle(i);
-
-               world.LoadEPairList(*g_EntityTable.m_pfnGetEntityKeyValList(ent));
-
-               DEPair* tn = world.FindEPairByKey("targetname");
-               if(tn)
-               {
-                       if(string_equal_nocase(tn->value, targetname)) {
-                               if(entNum) {
-                                       *entNum = i;
-                               }
-                               return ent;
-                       }
-               }
-       }
-
-#endif
-       return NULL;
+  return Scene_forEachEntity(EntityFindByTargetName(targetname)).result;
 }
 
 void FillDefaultTexture(_QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture)
@@ -383,9 +356,9 @@ void FillDefaultTexture(_QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc,
        faceData->m_texdef.scale[1] = 0.5;
        faceData->m_texdef.shift[0] = 0;
        faceData->m_texdef.shift[1] = 0;
-       faceData->m_texdef.contents = 0;
-       faceData->m_texdef.flags = 0;
-       faceData->m_texdef.value = 0;
+       faceData->contents = 0;
+       faceData->flags = 0;
+       faceData->value = 0;
        if(*texture)
                faceData->m_shader = texture;
        else
@@ -404,12 +377,12 @@ float Determinant3x3(float a1, float a2, float a3,
 
 bool GetEntityCentre(const char* entity, vec3_t centre)
 {
-  const scene::Path* ent = FindEntityFromTargetname(entity, NULL);
+  const scene::Path* ent = FindEntityFromTargetname(entity);
        if(!ent)
                return FALSE;
 
   scene::Instance& instance = *GlobalSceneGraph().find(*ent);
-  VectorCopy(instance.aabb_world().origin, centre);
+  VectorCopy(instance.worldAABB().origin, centre);
 
        return TRUE;
 }
@@ -429,11 +402,9 @@ void MakeNormal( const vec_t* va, const vec_t* vb, const vec_t* vc, vec_t* out )
 }
 
 char* GetFilename(char* buffer, const char* filename) {
-       strcpy(buffer, g_pSynapseServer->GetModuleFilename(&g_SynapseClient));
-       StripFilename( buffer );
-       strcat(buffer, "/");
+       strcpy(buffer, GlobalRadiant().getAppPath());
+       strcat(buffer, "plugins/");
        strcat(buffer, filename);
-       //buffer = UnixToDosPath(buffer);
        return buffer;
 }
 
index e011b67..61faee5 100644 (file)
@@ -32,14 +32,15 @@ vec_t Min(vec_t a, vec_t b);
 // reads current texture into global, returns pointer to it
 const char* GetCurrentTexture();
 
-void FillDefaultTexture(void* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture);
+class _QERFaceData;
+void FillDefaultTexture(_QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture);
 
 void BuildMiniPrt(std::list<Str>* exclusionList);
 
 void MoveBlock(int dir, vec3_t min, vec3_t max, float dist);
 void SetInitialStairPos(int dir, vec3_t min, vec3_t max, float width);
 
-scene::Path* FindEntityFromTargetname(const char* targetname, int* entNum);
+const scene::Path* FindEntityFromTargetname(const char* targetname);
 
 char* UnixToDosPath(char* path);
 
index 3c5e373..7385b6f 100644 (file)
@@ -30,15 +30,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #include "funchandlers.h"
 
 #include "iundo.h"
-
-#include "refcounted_ptr.h"
+#include "ishaders.h"
+#include "ientity.h"
+#include "ieclass.h"
+#include "ipatch.h"
+#include "qerplugin.h"
 
 #include <vector>
 #include <list>
 #include <map>
 #include <algorithm>
+#include <time.h>
 
 #include "scenelib.h"
+#include "texturelib.h"
 
 //#include "dialogs-gtk.h"
 
@@ -83,8 +88,8 @@ void AddFaceWithTexture(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, con
        _QERFaceData faceData;
        FillDefaultTexture(&faceData, va, vb, vc, texture);
        if(detail)
-               faceData.m_texdef.contents |= FACE_DETAIL;
-  GlobalBrushCreator().addBrushFace(brush, faceData);
+               faceData.contents |= FACE_DETAIL;
+  GlobalBrushCreator().Brush_addFace(brush, faceData);
 }
 
 void AddFaceWithTextureScaled(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, 
@@ -98,7 +103,7 @@ void AddFaceWithTextureScaled(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t v
   //   If a texture doesn't have a shader script, a default shader object is used.
   // The IShader object was leaking also
        // collect texture info: sizes, etc
-       IShader* i = QERApp_Shader_ForName(texture);
+       IShader* i = GlobalShaderSystem().getShaderForName(texture);
   pqtTexInfo = i->getTexture();        // shader width/height doesn't come out properly
 
        if(pqtTexInfo)
@@ -131,14 +136,14 @@ void AddFaceWithTextureScaled(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t v
                addFace.m_texdef.shift[0] = shift[0];
                addFace.m_texdef.shift[1] = shift[1];
 
-    GlobalBrushCreator().addBrushFace(brush, addFace);
+    GlobalBrushCreator().Brush_addFace(brush, addFace);
        }
        else
        {
                // shouldn't even get here, as default missing texture should be returned if
                // texture doesn't exist, but just in case
-               AddFaceWithTexture(brush, va, vb, vc, texture, FALSE);
-               Sys_ERROR("BobToolz::Invalid Texture Name-> %s", texture);
+               AddFaceWithTexture(brush, va, vb, vc, texture, false);
+               globalErrorStream() << "BobToolz::Invalid Texture Name-> " << texture;
        }
   // the IShader is not kept referenced, DecRef it
   i->DecRef();
@@ -172,62 +177,62 @@ void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp)
        {
 
                if(dir != MOVE_EAST)
-                       AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false);
 
                if(dir != MOVE_WEST)
-                       AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", false);
 
                if(dir != MOVE_NORTH)
-                       AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false);
 
                if(dir != MOVE_SOUTH)
-                       AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", false);
 
-               AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", false);
 
                if(dir == MOVE_EAST)
-                       AddFaceWithTexture(newBrush, v1, v3, v5, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v3, v5, "textures/common/caulk", false);
 
                if(dir == MOVE_WEST)
-                       AddFaceWithTexture(newBrush, v2, v6, v8, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v2, v6, v8, "textures/common/caulk", false);
 
                if(dir == MOVE_NORTH)
-                       AddFaceWithTexture(newBrush, v1, v6, v5, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v6, v5, "textures/common/caulk", false);
 
                if(dir == MOVE_SOUTH)
-                       AddFaceWithTexture(newBrush, v7, v3, v8, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v7, v3, v8, "textures/common/caulk", false);
        }
        else
        {
                if(dir != MOVE_WEST)
-                       AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v7, v5, v8, "textures/common/caulk", false);
 
                if(dir != MOVE_EAST)
-                       AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false);
 
                if(dir != MOVE_NORTH)
-                       AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v3, v8, v6, "textures/common/caulk", false);
 
                if(dir != MOVE_SOUTH)
-                       AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false);
 
                
-               AddFaceWithTexture(newBrush, v6, v5, v7, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush, v6, v5, v7, "textures/common/caulk", false);
 
                if(dir == MOVE_WEST)
-                       AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v5, v3, "textures/common/caulk", false);
 
                if(dir == MOVE_EAST)
-                       AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v2, v8, v6, "textures/common/caulk", false);
 
                if(dir == MOVE_NORTH)
-                       AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v1, v5, v6, "textures/common/caulk", false);
 
                if(dir == MOVE_SOUTH)
-                       AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", FALSE);
+                       AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", false);
        }
 
-       Node_getTraversable(GetWorldspawn())->insert(newBrush);
+       Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush);
 }
 
 //-----------------------------------------------------------------------------------
@@ -306,7 +311,7 @@ void Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char* mainText
        if(dir == MOVE_SOUTH)
                AddFaceWithTexture(newBrush, v7, v8, v3, "textures/common/caulk", detail);
 
-  Node_getTraversable(GetWorldspawn())->insert(newBrush);
+  Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush);
 }
 
 //-----------------------------------------------------------------------------------
@@ -315,7 +320,7 @@ void Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char* mainText
 // internal use only, to get a box without finishing construction
 scene::Node& Build_Get_BoundingCube_Selective(vec3_t min, vec3_t max, char* texture, bool* useFaces)
 {
-  scene::Node& newBrush(GlobalBrushCreator().createBrush());
+  NodeSmartReference newBrush(GlobalBrushCreator().createBrush());
 
        //----- Build Outer Bounds ---------
 
@@ -338,18 +343,18 @@ scene::Node& Build_Get_BoundingCube_Selective(vec3_t min, vec3_t max, char* text
        //----- Add Six Cube Faces ---------
 
        if(useFaces[0])
-               AddFaceWithTexture(newBrush, v1, v2, v3, texture, FALSE);
+               AddFaceWithTexture(newBrush, v1, v2, v3, texture, false);
        if(useFaces[1])
-               AddFaceWithTexture(newBrush, v1, v3, v6, texture, FALSE);
+               AddFaceWithTexture(newBrush, v1, v3, v6, texture, false);
        if(useFaces[2])
-               AddFaceWithTexture(newBrush, v1, v7, v2, texture, FALSE);
+               AddFaceWithTexture(newBrush, v1, v7, v2, texture, false);
 
        if(useFaces[3])
-               AddFaceWithTexture(newBrush, v5, v6, v3, texture, FALSE);
+               AddFaceWithTexture(newBrush, v5, v6, v3, texture, false);
        if(useFaces[4])
-               AddFaceWithTexture(newBrush, v5, v2, v7, texture, FALSE);
+               AddFaceWithTexture(newBrush, v5, v2, v7, texture, false);
        if(useFaces[5])
-               AddFaceWithTexture(newBrush, v5, v7, v6, texture, FALSE);
+               AddFaceWithTexture(newBrush, v5, v7, v6, texture, false);
 
        //----------------------------------
 
@@ -366,7 +371,7 @@ scene::Node& Build_Get_BoundingCube(vec3_t min, vec3_t max, char* texture)
 
 void Build_StairStep(vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction)
 {
-  scene::Node& newBrush(GlobalBrushCreator().createBrush());
+  NodeSmartReference newBrush(GlobalBrushCreator().createBrush());
 
        //----- Build Outer Bounds ---------
 
@@ -386,37 +391,37 @@ void Build_StairStep(vec3_t min, vec3_t max, const char* mainTexture, const char
 
        //----------------------------------
 
-       AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, FALSE);
+       AddFaceWithTexture(newBrush, v6, v5, v7, mainTexture, false);
        // top gets current texture
 
 
        if(direction == MOVE_EAST)
-               AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, FALSE);
+               AddFaceWithTexture(newBrush, v1, v3, v6, riserTexture, false);
        else
-               AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush, v1, v3, v6, "textures/common/caulk", false);
        // west facing side, etc...
 
        
        if(direction == MOVE_NORTH)
-               AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, FALSE);
+               AddFaceWithTexture(newBrush, v1, v7, v2, riserTexture, false);
        else
-               AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush, v1, v7, v2, "textures/common/caulk", false);
 
        if(direction == MOVE_SOUTH)
-               AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, FALSE);
+               AddFaceWithTexture(newBrush, v3, v5, v6, riserTexture, false);
        else
-               AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush, v3, v5, v6, "textures/common/caulk", false);
        
        if(direction == MOVE_WEST)
-               AddFaceWithTexture(newBrush, v7, v5, v2, riserTexture, FALSE);
+               AddFaceWithTexture(newBrush, v7, v5, v2, riserTexture, false);
        else
-               AddFaceWithTexture(newBrush, v7, v5, v2, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush, v7, v5, v2, "textures/common/caulk", false);
 
 
-       AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", FALSE);
+       AddFaceWithTexture(newBrush, v1, v2, v3, "textures/common/caulk", false);
        // base is caulked
 
-       Node_getTraversable(GetWorldspawn())->insert(newBrush);
+       Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(newBrush);
        // finish brush
 }
 
@@ -475,21 +480,21 @@ void BuildDoorsX2(vec3_t min, vec3_t max,
   NodeSmartReference newBrush1(GlobalBrushCreator().createBrush());
        NodeSmartReference newBrush2(GlobalBrushCreator().createBrush());
 
-       AddFaceWithTexture(newBrush1, v1, v2, v3, "textures/common/caulk", FALSE);
-       AddFaceWithTexture(newBrush1, v5, v7, v6, "textures/common/caulk", FALSE);
+       AddFaceWithTexture(newBrush1, v1, v2, v3, "textures/common/caulk", false);
+       AddFaceWithTexture(newBrush1, v5, v7, v6, "textures/common/caulk", false);
 
-       AddFaceWithTexture(newBrush2, v1, v2, v3, "textures/common/caulk", FALSE);
-       AddFaceWithTexture(newBrush2, v5, v7, v6, "textures/common/caulk", FALSE);
+       AddFaceWithTexture(newBrush2, v1, v2, v3, "textures/common/caulk", false);
+       AddFaceWithTexture(newBrush2, v5, v7, v6, "textures/common/caulk", false);
 
        if(direction == 0)
        {
-               AddFaceWithTexture(newBrush1, v1, v3, v6, "textures/common/caulk", FALSE);
-               AddFaceWithTexture(newBrush2, v5, v2, v7, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush1, v1, v3, v6, "textures/common/caulk", false);
+               AddFaceWithTexture(newBrush2, v5, v2, v7, "textures/common/caulk", false);
        }
        else
        {
-               AddFaceWithTexture(newBrush1, v1, v7, v2, "textures/common/caulk", FALSE);
-               AddFaceWithTexture(newBrush2, v5, v6, v3, "textures/common/caulk", FALSE);
+               AddFaceWithTexture(newBrush1, v1, v7, v2, "textures/common/caulk", false);
+               AddFaceWithTexture(newBrush2, v5, v6, v3, "textures/common/caulk", false);
        }
 
        if(direction == 0)
@@ -537,26 +542,27 @@ void BuildDoorsX2(vec3_t min, vec3_t max,
        //----------------------------------
        
 
-  NodeSmartReference pEDoor1 = GlobalEntityCreator().createEntity("func_door");
-       NodeSmartReference pEDoor2 = GlobalEntityCreator().createEntity("func_door");
+  EntityClass* doorClass = GlobalEntityClassManager().findOrInsert("func_door", true);
+  NodeSmartReference pEDoor1(GlobalEntityCreator().createEntity(doorClass));
+       NodeSmartReference pEDoor2(GlobalEntityCreator().createEntity(doorClass));
 
        if(direction == 0)
        {
-    pEDoor1->m_entity->setkeyvalue("angle", "180");
-    pEDoor2->m_entity->setkeyvalue("angle", "360");
+    Node_getEntity(pEDoor1)->setKeyValue("angle", "180");
+    Node_getEntity(pEDoor2)->setKeyValue("angle", "360");
        }
        else
        {
-    pEDoor1->m_entity->setkeyvalue("angle", "270");
-    pEDoor2->m_entity->setkeyvalue("angle", "90");
+    Node_getEntity(pEDoor1)->setKeyValue("angle", "270");
+    Node_getEntity(pEDoor2)->setKeyValue("angle", "90");
        }
 
        srand((unsigned)time(NULL));
 
        char teamname[256];
        sprintf(teamname, "t%i", rand());
-  pEDoor1->m_entity->setkeyvalue("team", teamname);
-  pEDoor2->m_entity->setkeyvalue("team", teamname);
+  Node_getEntity(pEDoor1)->setKeyValue("team", teamname);
+  Node_getEntity(pEDoor2)->setKeyValue("team", teamname);
 
        Node_getTraversable(pEDoor1)->insert(newBrush1);
        Node_getTraversable(pEDoor2)->insert(newBrush2);
@@ -573,13 +579,31 @@ void BuildDoorsX2(vec3_t min, vec3_t max,
 void MakeBevel(vec3_t vMin, vec3_t vMax)
 {
   NodeSmartReference patch(GlobalPatchCreator().createPatch());
-  aabb_t aabb;
-  aabb_construct_for_vec3(&aabb, vMin, vMax);
-#if 0
-  patch->m_patch->ConstructPrefab(&aabb, eBevel, 2); // 2 == XY view
-#endif
+  PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch);
+
+  GlobalPatchCreator().Patch_setShader(patch, "textures/common/caulk");
+  GlobalPatchCreator().Patch_resize(patch, 3, 3);
+       
+       vec3_t x_3, y_3, z_3;
+       x_3[0] = vMin[0];       x_3[1] = vMin[0];                               x_3[2] = vMax[0];
+       y_3[0] = vMin[1];       y_3[1] = vMax[1];                               y_3[2] = vMax[1];
+       z_3[0] = vMin[2];       z_3[1] = (vMax[2] + vMin[2])/2; z_3[2] = vMax[2];
+
+/*     x_3[0] = 0;             x_3[1] = 0;             x_3[2] = 64;
+       y_3[0] = 0;             y_3[1] = 64;    y_3[2] = 64;
+       z_3[0] = 0;             z_3[1] = 32;    z_3[2] = 64;*/
+
+       for(int i = 0; i < 3; i++)
+       {
+               for(int j = 0; j < 3; j++)
+               {
+                       matrix(i, j).m_vertex[0] = x_3[i];
+                       matrix(i, j).m_vertex[1] = y_3[i];
+                       matrix(i, j).m_vertex[2] = z_3[j];
+               }
+       }
 
-  Node_getTraversable(GetWorldspawn())->insert(patch);
+  Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(patch);
 }
 
 void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex)
@@ -587,7 +611,7 @@ void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTex
        vec3_t* topPoints = new vec3_t[nSteps+1];
        vec3_t* botPoints = new vec3_t[nSteps+1];
 
-       bool bFacesUse[6] = {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE};
+       bool bFacesUse[6] = {true, true, false, true, false, false};
 
        vec3_t centre;
        VectorCopy(vMin, centre);
@@ -627,12 +651,12 @@ void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTex
                for(int j = 0; j < 3; j++)
                        tp[j][2] = vTop[2];
 
-               AddFaceWithTexture(brush, tp[2], tp[1], tp[0], mainTexture, FALSE);
+               AddFaceWithTexture(brush, tp[2], tp[1], tp[0], mainTexture, false);
 
-               AddFaceWithTexture(brush, centre, botPoints[i+1], topPoints[i+1], "textures/common/caulk", FALSE);
-               AddFaceWithTexture(brush, centre, topPoints[i], botPoints[i], riserTex, FALSE);
+               AddFaceWithTexture(brush, centre, botPoints[i+1], topPoints[i+1], "textures/common/caulk", false);
+               AddFaceWithTexture(brush, centre, topPoints[i], botPoints[i], riserTex, false);
 
-               Node_getTraversable(GetWorldspawn())->insert(brush);
+               Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(brush);
 
                vTop[2] += height;
                vBot[2] += height;
index c277d42..0fa9265 100644 (file)
@@ -26,6 +26,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 // defines for polygon stuff
 #define MAX_POLYGON_FACES      128
 
+namespace scene
+{
+  class Node;
+}
+
+#include "mathlib.h"
+
 // generic (detail added 12/01/01, for AC+)
 void AddFaceWithTexture(scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail);
 
index 187ebcc..f7a58f5 100644 (file)
@@ -105,8 +105,8 @@ public:
   STRING_CONSTANT(Name, "brush");
   virtual scene::Node& createBrush() = 0;
   virtual bool useAlternativeTextureProjection() const = 0;
-  virtual void forEachBrushFace(scene::Node& brush, const BrushFaceDataCallback& callback) = 0;
-  virtual bool addBrushFace(scene::Node& brush, const _QERFaceData& faceData) = 0;
+  virtual void Brush_forEachFace(scene::Node& brush, const BrushFaceDataCallback& callback) = 0;
+  virtual bool Brush_addFace(scene::Node& brush, const _QERFaceData& faceData) = 0;
 };
 
 #include "modulesystem.h"
index f96e049..444e377 100644 (file)
@@ -64,8 +64,8 @@ public:
   virtual void setKeyValue(const char* key, const char* value) = 0;
   virtual const char* getKeyValue(const char* key) const = 0;
   virtual bool isContainer() const = 0;
-  void attach(Observer& observer);
-  void detach(Observer& observer);
+  virtual void attach(Observer& observer) = 0;
+  virtual void detach(Observer& observer) = 0;
 };
 
 class EntityCopyingVisitor : public Entity::Visitor
index 7069287..eee123e 100644 (file)
@@ -23,18 +23,251 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define INCLUDED_IPATCH_H
 
 #include "generic/constant.h"
+#include "math/vector.h"
 
 namespace scene
 {
   class Node;
 }
 
+template<typename Element>
+class ArrayReference
+{
+  std::size_t m_size;
+  Element* m_data;
+public:
+  typedef Element value_type;
+  typedef value_type* iterator;
+  typedef const value_type* const_iterator;
+
+  ArrayReference()
+    : m_size(0), m_data(0)
+  {
+  }
+  ArrayReference(std::size_t size, Element* data)
+    : m_size(size), m_data(data)
+  {
+  }
+
+  iterator begin()
+  {
+    return m_data;
+  }
+  const_iterator begin() const
+  {
+    return m_data;
+  }
+  iterator end()
+  {
+    return m_data + m_size;
+  }
+  const_iterator end() const
+  {
+    return m_data + m_size;
+  }
+
+  value_type& operator[](std::size_t index)
+  {
+#if defined(_DEBUG)
+    ASSERT_MESSAGE(index < size(), "array index out of bounds");
+#endif
+    return m_data[index];
+  }
+  const value_type& operator[](std::size_t index) const
+  {
+#if defined(_DEBUG)
+    ASSERT_MESSAGE(index < size(), "array index out of bounds");
+#endif
+    return m_data[index];
+  }
+  value_type* data()
+  {
+    return m_data;
+  }
+  const value_type* data() const
+  {
+    return m_data;
+  }
+  std::size_t size() const
+  {
+    return m_size;
+  }
+  bool empty() const
+  {
+    return m_size == 0;
+  }
+};
+
+#if 0
+template<typename Element>
+class MatrixIterator
+{
+  Element* m_position;
+
+  void increment()
+  {
+    ++m_position;
+  }
+
+public:
+  typedef std::bidirectional_iterator_tag iterator_category;
+  typedef std::ptrdiff_t difference_type;
+  typedef difference_type distance_type;
+  typedef KeyValue<Key, Value> value_type;
+  typedef value_type* pointer;
+  typedef value_type& reference;
+
+  MatrixIterator(Element* position) : m_position(position)
+  {
+  }
+
+  Element* position()
+  {
+    return m_position;
+  }
+
+  bool operator==(const MatrixIterator& other) const
+  {
+    return m_position == other.m_position;
+  }
+  bool operator!=(const MatrixIterator& other) const
+  {
+    return !operator==(other);
+  }
+  MatrixIterator& operator++()
+  {
+    increment();
+    return *this;
+  }
+  MatrixIterator operator++(int)
+  {
+    MatrixIterator tmp = *this;
+    increment();
+    return tmp;
+  }
+  value_type& operator*() const
+  {
+    return m_position->m_value;
+  }
+  value_type* operator->() const
+  {
+    return &(operator*());
+  }
+};
+#endif
+
+template<typename Element>
+class Matrix
+{
+  std::size_t m_x, m_y;
+  Element* m_data;
+public:
+  typedef Element value_type;
+  typedef value_type* iterator;
+  typedef const value_type* const_iterator;
+
+  Matrix()
+    : m_x(0), m_y(0), m_data(0)
+  {
+  }
+  Matrix(std::size_t x, std::size_t y, Element* data)
+    : m_x(x), m_y(y), m_data(data)
+  {
+  }
+
+  iterator begin()
+  {
+    return m_data;
+  }
+  const_iterator begin() const
+  {
+    return m_data;
+  }
+  iterator end()
+  {
+    return m_data + size();
+  }
+  const_iterator end() const
+  {
+    return m_data + size();
+  }
+
+  value_type& operator[](std::size_t index)
+  {
+#if defined(_DEBUG)
+    ASSERT_MESSAGE(index < size(), "array index out of bounds");
+#endif
+    return m_data[index];
+  }
+  const value_type& operator[](std::size_t index) const
+  {
+#if defined(_DEBUG)
+    ASSERT_MESSAGE(index < size(), "array index out of bounds");
+#endif
+    return m_data[index];
+  }
+  value_type& operator()(std::size_t x, std::size_t y)
+  {
+#if defined(_DEBUG)
+    ASSERT_MESSAGE(x < m_x && y < m_y, "array index out of bounds");
+#endif
+    return m_data[x * m_y + y];
+  }
+  const value_type& operator()(std::size_t x, std::size_t y) const
+  {
+#if defined(_DEBUG)
+    ASSERT_MESSAGE(x < m_x && y < m_y, "array index out of bounds");
+#endif
+    return m_data[x * m_y + y];
+  }
+  value_type* data()
+  {
+    return m_data;
+  }
+  const value_type* data() const
+  {
+    return m_data;
+  }
+  std::size_t x() const
+  {
+    return m_x;
+  }
+  std::size_t y() const
+  {
+    return m_y;
+  }
+  std::size_t size() const
+  {
+    return m_x * m_y;
+  }
+  bool empty() const
+  {
+    return m_x == 0;
+  }
+};
+
+class PatchControl
+{
+public:
+  Vector3 m_vertex;
+  Vector2 m_texcoord;
+};
+
+typedef Matrix<PatchControl> PatchControlMatrix;
+
+
 class PatchCreator
 {
 public:
   INTEGER_CONSTANT(Version, 1);
   STRING_CONSTANT(Name, "patch");
   virtual scene::Node& createPatch() = 0;
+  virtual void Patch_undoSave(scene::Node& patch) const = 0;
+  virtual void Patch_resize(scene::Node& patch, std::size_t width, std::size_t height) const = 0;
+  virtual PatchControlMatrix Patch_getControlPoints(scene::Node& patch) const = 0;
+  virtual void Patch_controlPointsChanged(scene::Node& patch) const = 0;
+  virtual const char* Patch_getShader(scene::Node& patch) const = 0;
+  virtual void Patch_setShader(scene::Node& patch, const char* shader) const = 0;
 };
 
 #include "modulesystem.h"
index 3e352e5..861593f 100644 (file)
@@ -121,6 +121,7 @@ struct _QERFuncTable_1
   const char* (*getGameToolsPath)();
   const char* (*getAppPath)();
   const char* (*getSettingsPath)();
+  const char* (*getMapsPath)();
 
   const char* (*getGameName)();
   const char* (*getGameMode)();
@@ -141,6 +142,8 @@ struct _QERFuncTable_1
   void (*attachGameModeObserver)(ModuleObserver& observer);
   void (*detachGameModeObserver)(ModuleObserver& observer);
 
+  SignalHandlerId (*XYWindowDestroyed_connect)(const SignalHandler& handler);
+  void (*XYWindowDestroyed_disconnect)(SignalHandlerId id);
   MouseEventHandlerId (*XYWindowMouseDown_connect)(const MouseEventHandler& handler);
   void (*XYWindowMouseDown_disconnect)(MouseEventHandlerId id);
   VIEWTYPE (*XYWindow_getViewType)();
index 2d96634..62e2c23 100644 (file)
@@ -36,14 +36,6 @@ public:
   explicit Reference(Type& contained) : m_contained(&contained)
   {
   }
-  Type& operator*() const
-  {
-    return *m_contained;
-  }
-  Type* operator->() const
-  {
-    return m_contained;
-  }
   operator Type&() const
   {
     return *m_contained;
@@ -87,14 +79,6 @@ public:
   explicit ConstReference(const Type& contained) : m_contained(&contained)
   {
   }
-  const Type& operator*() const
-  {
-    return *m_contained;
-  }
-  const Type* operator->() const
-  {
-    return m_contained;
-  }
   operator const Type&() const
   {
     return *m_contained;
index 6a63fdd..778da6f 100644 (file)
@@ -30,30 +30,145 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include "generic/callback.h"
 #include "generic/bitfield.h"
+#include "string/string.h"
 
 #include "pointer.h"
 #include "closure.h"
 
+#include <gdk/gdkkeysyms.h>
 
 
+
+struct SKeyInfo
+{
+  const char* m_strName;
+  unsigned int m_nVKKey;
+};
+
+SKeyInfo g_Keys[] =
+{
+  {"Space", GDK_space},
+  {"Backspace", GDK_BackSpace},
+  {"Escape", GDK_Escape},
+  {"End", GDK_End},
+  {"Insert", GDK_Insert},
+  {"Delete", GDK_Delete},
+  {"PageUp", GDK_Prior},
+  {"PageDown", GDK_Next},
+  {"Up", GDK_Up},
+  {"Down", GDK_Down},
+  {"Left", GDK_Left},
+  {"Right", GDK_Right},
+  {"F1", GDK_F1},
+  {"F2", GDK_F2},
+  {"F3", GDK_F3},
+  {"F4", GDK_F4},
+  {"F5", GDK_F5},
+  {"F6", GDK_F6},
+  {"F7", GDK_F7},
+  {"F8", GDK_F8},
+  {"F9", GDK_F9},
+  {"F10", GDK_F10},
+  {"F11", GDK_F11},
+  {"F12", GDK_F12},
+  {"Tab", GDK_Tab},
+  {"Return", GDK_Return},                           
+  {"Comma", GDK_comma},
+  {"Period", GDK_period},
+  {"Plus", GDK_KP_Add},
+  {"Multiply", GDK_multiply},
+  {"Minus", GDK_KP_Subtract},
+  {"NumPad0", GDK_KP_0},
+  {"NumPad1", GDK_KP_1},
+  {"NumPad2", GDK_KP_2},
+  {"NumPad3", GDK_KP_3},
+  {"NumPad4", GDK_KP_4},
+  {"NumPad5", GDK_KP_5},
+  {"NumPad6", GDK_KP_6},
+  {"NumPad7", GDK_KP_7},
+  {"NumPad8", GDK_KP_8},
+  {"NumPad9", GDK_KP_9},
+  {"[", 219},
+  {"]", 221},
+  {"\\", 220},
+  {"Home", GDK_Home}
+};
+
+int g_nKeyCount = sizeof(g_Keys) / sizeof(SKeyInfo);
+
+const char* global_keys_find(unsigned int key)
+{
+  for(int i = 0; i < g_nKeyCount; ++i)
+  {
+    if(g_Keys[i].m_nVKKey == key)
+    {
+      return g_Keys[i].m_strName;
+    }
+  }
+  return "";
+}
+
+unsigned int global_keys_find(const char* name)
+{
+  for(int i = 0; i < g_nKeyCount; ++i)
+  {
+    if(string_equal_nocase(g_Keys[i].m_strName, name))
+    {
+      return g_Keys[i].m_nVKKey;
+    }
+  }
+  return 0;
+}
+
+void accelerator_write(const Accelerator& accelerator, TextOutputStream& ostream)
+{
+  if(accelerator.modifiers & GDK_SHIFT_MASK)
+  {
+    ostream << "Shift + ";
+  }
+  if(accelerator.modifiers & GDK_MOD1_MASK)
+  {
+    ostream << "Alt + ";
+  }
+  if(accelerator.modifiers & GDK_CONTROL_MASK)
+  {
+    ostream << "Control + ";
+  }
+
+  const char* keyName = global_keys_find(accelerator.key);
+  if(!string_empty(keyName))
+  {
+    ostream << keyName;
+  }
+  else
+  {
+    ostream << static_cast<char>(accelerator.key);
+  }
+}
+
 typedef std::map<Accelerator, Callback> AcceleratorMap;
 
-void accelerator_map_insert(AcceleratorMap& acceleratorMap, Accelerator accelerator, const Callback& callback)
+bool accelerator_map_insert(AcceleratorMap& acceleratorMap, Accelerator accelerator, const Callback& callback)
 {
   if(accelerator.key != 0)
   {
-    ASSERT_MESSAGE(acceleratorMap.find(accelerator) == acceleratorMap.end(), "failed to add accelerator");
-    acceleratorMap.insert(AcceleratorMap::value_type(accelerator, callback));
+    return acceleratorMap.insert(AcceleratorMap::value_type(accelerator, callback)).second;
   }
+  return true;
 }
 
-void accelerator_map_erase(AcceleratorMap& acceleratorMap, Accelerator accelerator)
+bool accelerator_map_erase(AcceleratorMap& acceleratorMap, Accelerator accelerator)
 {
   if(accelerator.key != 0)
   {
-    ASSERT_MESSAGE(acceleratorMap.find(accelerator) != acceleratorMap.end(), "failed to remove accelerator");
-    acceleratorMap.erase(accelerator);
+    AcceleratorMap::iterator i = acceleratorMap.find(accelerator);
+    if(i == acceleratorMap.end())
+    {
+      return false;
+    }
+    acceleratorMap.erase(i);
   }
+  return true;
 }
 
 Accelerator accelerator_for_event_key(guint keyval, guint state)
@@ -381,29 +496,47 @@ void GlobalPressedKeys_disconnect(GtkWindow* window)
 
 void special_accelerators_add(Accelerator accelerator, const Callback& callback)
 {
-  accelerator_map_insert(g_special_accelerators, accelerator, callback);
+  if(!accelerator_map_insert(g_special_accelerators, accelerator, callback))
+  {
+    globalErrorStream() << "special_accelerators_add: already exists: " << makeQuoted(accelerator);
+  }
 }
 void special_accelerators_remove(Accelerator accelerator)
 {
-  accelerator_map_erase(g_special_accelerators, accelerator);
+  if(!accelerator_map_erase(g_special_accelerators, accelerator))
+  {
+    globalErrorStream() << "special_accelerators_remove: not found: " << makeQuoted(accelerator);
+  }
 }
 
 void keydown_accelerators_add(Accelerator accelerator, const Callback& callback)
 {
-  accelerator_map_insert(g_keydown_accelerators, accelerator, callback);
+  if(!accelerator_map_insert(g_keydown_accelerators, accelerator, callback))
+  {
+    globalErrorStream() << "keydown_accelerators_add: already exists: " << makeQuoted(accelerator);
+  }
 }
 void keydown_accelerators_remove(Accelerator accelerator)
 {
-  accelerator_map_erase(g_keydown_accelerators, accelerator);
+  if(!accelerator_map_erase(g_keydown_accelerators, accelerator))
+  {
+    globalErrorStream() << "keydown_accelerators_remove: not found: " << makeQuoted(accelerator);
+  }
 }
 
 void keyup_accelerators_add(Accelerator accelerator, const Callback& callback)
 {
-  accelerator_map_insert(g_keyup_accelerators, accelerator, callback);
+  if(!accelerator_map_insert(g_keyup_accelerators, accelerator, callback))
+  {
+    globalErrorStream() << "keyup_accelerators_add: already exists: " << makeQuoted(accelerator);
+  }
 }
 void keyup_accelerators_remove(Accelerator accelerator)
 {
-  accelerator_map_erase(g_keyup_accelerators, accelerator);
+  if(!accelerator_map_erase(g_keyup_accelerators, accelerator))
+  {
+    globalErrorStream() << "keyup_accelerators_remove: not found: " << makeQuoted(accelerator);
+  }
 }
 
 
index e4bd5a8..4f7085a 100644 (file)
@@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include "generic/callback.h"
 
-
 struct Accelerator
 {
   Accelerator(guint _key)
@@ -51,6 +50,18 @@ inline Accelerator accelerator_null()
   return Accelerator(0, (GdkModifierType)0);
 }
 
+const char* global_keys_find(unsigned int key);
+unsigned int global_keys_find(const char* name);
+
+class TextOutputStream;
+void accelerator_write(const Accelerator& accelerator, TextOutputStream& ostream);
+
+template<typename TextOutputStreamType>
+TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Accelerator& accelerator)
+{
+  accelerator_write(accelerator, ostream);
+  return ostream;
+}
 
 void keydown_accelerators_add(Accelerator accelerator, const Callback& callback);
 void keydown_accelerators_remove(Accelerator accelerator);
index a5be241..9a5c055 100644 (file)
@@ -365,6 +365,32 @@ inline bool Node_isEntity(scene::Node& node)
   return NodeTypeCast<EntityUndefined>::cast(node) != 0;
 }
 
+template<typename Functor>
+class EntityWalker : public scene::Graph::Walker
+{
+  const Functor& functor;
+public:
+  EntityWalker(const Functor& functor) : functor(functor)
+  {
+  }
+  bool pre(const scene::Path& path, scene::Instance& instance) const
+  {
+    if(Node_isEntity(path.top()))
+    {
+      functor(instance);
+      return false;
+    }
+    return true;
+  }
+};
+
+template<typename Functor>
+inline const Functor& Scene_forEachEntity(const Functor& functor)
+{
+  GlobalSceneGraph().traverse(EntityWalker<Functor>(functor));
+  return functor;
+}
+
 class BrushUndefined
 {
 public:
index e289f3c..cbc4c0a 100644 (file)
@@ -184,12 +184,13 @@ public:
   {
     return g_useAlternativeTextureProjection.m_value;
   }
-  void forEachBrushFace(scene::Node& brush, const BrushFaceDataCallback& callback)
+  void Brush_forEachFace(scene::Node& brush, const BrushFaceDataCallback& callback)
   {
-    Brush_forEachFace(*Node_getBrush(brush), FaceCallback(BrushFaceDataFromFaceCaller(callback)));
+    ::Brush_forEachFace(*Node_getBrush(brush), FaceCallback(BrushFaceDataFromFaceCaller(callback)));
   }
-  bool addBrushFace(scene::Node& brush, const _QERFaceData& faceData)
+  bool Brush_addFace(scene::Node& brush, const _QERFaceData& faceData)
   {
+    Node_getBrush(brush)->undoSave();
     return Node_getBrush(brush)->addPlane(faceData.m_p0, faceData.m_p1, faceData.m_p2, faceData.m_shader, TextureProjection(faceData.m_texdef, brushprimit_texdef_t(), Vector3(0, 0, 0), Vector3(0, 0, 0))) != 0;
   }
 };
index 3015414..2c1b49e 100644 (file)
@@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <map>
 #include "string/string.h"
 #include "versionlib.h"
+#include "gtkutil/accelerator.h"
 
 typedef std::pair<Accelerator, bool> ShortcutValue; // accelerator, isRegistered
 typedef std::map<CopiedString, ShortcutValue> Shortcuts;
@@ -125,7 +126,6 @@ const KeyEvent& GlobalKeyEvents_find(const char* name)
 
 
 
-#include <gdk/gdkkeysyms.h>
 #include <ctype.h>
 
 #ifdef __APPLE__
@@ -139,88 +139,6 @@ inline char ascii_for_keyval(int keyval)
 
 
 
-struct SKeyInfo
-{
-  const char* m_strName;
-  unsigned int m_nVKKey;
-};
-
-SKeyInfo g_Keys[] =
-{
-  {"Space", GDK_space},
-  {"Backspace", GDK_BackSpace},
-  {"Escape", GDK_Escape},
-  {"End", GDK_End},
-  {"Insert", GDK_Insert},
-  {"Delete", GDK_Delete},
-  {"PageUp", GDK_Prior},
-  {"PageDown", GDK_Next},
-  {"Up", GDK_Up},
-  {"Down", GDK_Down},
-  {"Left", GDK_Left},
-  {"Right", GDK_Right},
-  {"F1", GDK_F1},
-  {"F2", GDK_F2},
-  {"F3", GDK_F3},
-  {"F4", GDK_F4},
-  {"F5", GDK_F5},
-  {"F6", GDK_F6},
-  {"F7", GDK_F7},
-  {"F8", GDK_F8},
-  {"F9", GDK_F9},
-  {"F10", GDK_F10},
-  {"F11", GDK_F11},
-  {"F12", GDK_F12},
-  {"Tab", GDK_Tab},
-  {"Return", GDK_Return},                           
-  {"Comma", GDK_comma},
-  {"Period", GDK_period},
-  {"Plus", GDK_KP_Add},
-  {"Multiply", GDK_multiply},
-  {"Minus", GDK_KP_Subtract},
-  {"NumPad0", GDK_KP_0},
-  {"NumPad1", GDK_KP_1},
-  {"NumPad2", GDK_KP_2},
-  {"NumPad3", GDK_KP_3},
-  {"NumPad4", GDK_KP_4},
-  {"NumPad5", GDK_KP_5},
-  {"NumPad6", GDK_KP_6},
-  {"NumPad7", GDK_KP_7},
-  {"NumPad8", GDK_KP_8},
-  {"NumPad9", GDK_KP_9},
-  {"[", 219},
-  {"]", 221},
-  {"\\", 220},
-  {"Home", GDK_Home}
-};
-
-int g_nKeyCount = sizeof(g_Keys) / sizeof(SKeyInfo);
-
-const char* global_keys_find(unsigned int key)
-{
-  for(int i = 0; i < g_nKeyCount; ++i)
-  {
-    if(g_Keys[i].m_nVKKey == key)
-    {
-      return g_Keys[i].m_strName;
-    }
-  }
-  return "";
-}
-
-unsigned int global_keys_find(const char* name)
-{
-  for(int i = 0; i < g_nKeyCount; ++i)
-  {
-    if(string_equal_nocase(g_Keys[i].m_strName, name))
-    {
-      return g_Keys[i].m_nVKKey;
-    }
-  }
-  return 0;
-}
-
-
 #include <gtk/gtkbox.h>
 #include <gtk/gtkliststore.h>
 #include <gtk/gtktreemodel.h>
@@ -243,35 +161,6 @@ struct command_list_dialog_t : public ModalDialog
   ModalDialogButton m_close_button;
 };
 
-template<typename TextOutputStreamType>
-TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Accelerator& accelerator)
-{
-  if(accelerator.modifiers & GDK_SHIFT_MASK)
-  {
-    ostream << "Shift + ";
-  }
-  if(accelerator.modifiers & GDK_MOD1_MASK)
-  {
-    ostream << "Alt + ";
-  }
-  if(accelerator.modifiers & GDK_CONTROL_MASK)
-  {
-    ostream << "Control + ";
-  }
-
-  const char* keyName = global_keys_find(accelerator.key);
-  if(!string_empty(keyName))
-  {
-    ostream << keyName;
-  }
-  else
-  {
-    ostream << static_cast<char>(accelerator.key);
-  }
-
-  return ostream;
-}
-
 void DoCommandListDlg()
 {
   command_list_dialog_t dialog;
index ee4f8cb..e49d7fd 100644 (file)
@@ -2631,6 +2631,16 @@ public:
 
 MainWindowActive g_MainWindowActive;
 
+SignalHandlerId XYWindowDestroyed_connect(const SignalHandler& handler)
+{
+  return g_pParentWnd->GetXYWnd()->onDestroyed.connectFirst(handler);
+}
+
+void XYWindowDestroyed_disconnect(SignalHandlerId id)
+{
+  g_pParentWnd->GetXYWnd()->onDestroyed.disconnect(id);
+}
+
 MouseEventHandlerId XYWindowMouseDown_connect(const MouseEventHandler& handler)
 {
   return g_pParentWnd->GetXYWnd()->onMouseDown.connectFirst(handler);
index 4fadaae..840341c 100644 (file)
@@ -276,6 +276,8 @@ extern int (*GridStatus_getFarClipDistance)();
 extern bool (*GridStatus_getTextureLockEnabled)();
 void GridStatus_onTextureLockEnabledChanged();
 
+SignalHandlerId XYWindowDestroyed_connect(const SignalHandler& handler);
+void XYWindowDestroyed_disconnect(SignalHandlerId id);
 MouseEventHandlerId XYWindowMouseDown_connect(const MouseEventHandler& handler);
 void XYWindowMouseDown_disconnect(MouseEventHandlerId id);
 
index e74d898..2529bd2 100644 (file)
@@ -167,4 +167,7 @@ void Map_Destroy();
 void Map_gatherNamespaced(scene::Node& root);
 void Map_mergeClonedNames();
 
+
+const char* getMapsPath();
+
 #endif
index 80ffe35..c7b6344 100644 (file)
@@ -118,7 +118,9 @@ void BezierInterpolate(BezierCurve *pCurve)
   pCurve->crd = vector3_mid(pCurve->left, pCurve->right);
 }
 
-void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList)
+const std::size_t PATCH_MAX_SUBDIVISION_DEPTH = 16;
+
+void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList, std::size_t depth = 0)
 {
   GSList *pLeftList = 0;
   GSList *pRightList = 0;
@@ -146,19 +148,20 @@ void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList)
     }
   }
 
-  if(pLeftList != 0 && pRightList != 0)
+  if(pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH)
   {
     pTree->left = new BezierCurveTree;
     pTree->right = new BezierCurveTree;
-    BezierCurveTree_FromCurveList(pTree->left, pLeftList);
-    BezierCurveTree_FromCurveList(pTree->right, pRightList);
+    BezierCurveTree_FromCurveList(pTree->left, pLeftList, depth + 1);
+    BezierCurveTree_FromCurveList(pTree->right, pRightList, depth + 1);
 
+    for(GSList* l = pLeftList; l != 0; l = g_slist_next(l))
     {
-    GSList *l;
-    for (l = pLeftList; l != 0; l = g_slist_next(l))
       delete (BezierCurve*)l->data;
+    }
 
-    for (l = pRightList; l != 0; l = g_slist_next(l))
+    for(GSList* l = pRightList; l != 0; l = g_slist_next(l))
+    {
       delete (BezierCurve*)l->data;
     }
     
@@ -208,10 +211,54 @@ inline const Colour4b& colour_for_index(std::size_t i, std::size_t width)
   return (i%2 || (i/width)%2) ? colour_inside : colour_corner;
 }
 
-void Patch::UpdateCachedData()
+inline bool float_valid(float f)
+{
+  return f == f;
+}
+
+bool Patch::isValid() const
 {
   if(!m_width || !m_height)
+  {
+    return false;
+  }
+
+  for(const_iterator i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+  {
+    if(!float_valid((*i).m_vertex.x())
+      || !float_valid((*i).m_vertex.y())
+      || !float_valid((*i).m_vertex.z())
+      || !float_valid((*i).m_texcoord.x())
+      || !float_valid((*i).m_texcoord.y()))
+    {
+      globalErrorStream() << "patch has invalid control points\n";
+      return false;
+    }
+  }
+  return true;
+}
+
+void Patch::UpdateCachedData()
+{
+  m_ctrl_vertices.clear();
+  m_lattice_indices.clear();
+
+  if(!isValid())
+  {
+    m_tess.m_numStrips = 0;
+    m_tess.m_lenStrips = 0;
+    m_tess.m_nArrayHeight = 0;
+    m_tess.m_nArrayWidth = 0;
+    m_tess.m_curveTreeU.resize(0);
+    m_tess.m_curveTreeV.resize(0);
+    m_tess.m_indices.resize(0);
+    m_tess.m_vertices.resize(0);
+    m_tess.m_arrayHeight.resize(0);
+    m_tess.m_arrayWidth.resize(0);
+    m_aabb_local = AABB();
     return;
+  }
+
   BuildTesselationCurves(ROW);
   BuildTesselationCurves(COL);
   BuildVertexArray();
@@ -219,9 +266,6 @@ void Patch::UpdateCachedData()
 
   IndexBuffer ctrl_indices;
 
-  m_ctrl_vertices.clear();
-  m_lattice_indices.clear();
-
   m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
   ctrl_indices.reserve(m_ctrlTransformed.size());
   {
@@ -2424,6 +2468,8 @@ void Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6],
   }
 }
 
+const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576;
+
 void Patch::BuildVertexArray()
 {
   const std::size_t strideU = 1;
index 614a4eb..bea3311 100644 (file)
@@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include "nameable.h"
 #include "ifilter.h"
 #include "imap.h"
+#include "ipatch.h"
 #include "cullable.h"
 #include "renderable.h"
 #include "editable.h"
@@ -136,13 +137,6 @@ inline VertexPointer vertexpointer_arbitrarymeshvertex(const ArbitraryMeshVertex
   return VertexPointer(VertexPointer::pointer(&array->vertex), sizeof(ArbitraryMeshVertex));
 }
 
-class PatchControl
-{
-public:
-  Vector3 m_vertex;
-  Vector2 m_texcoord;
-};
-
 typedef PatchControl* PatchControlIter;
 typedef const PatchControl* PatchControlConstIter;
 
@@ -193,6 +187,10 @@ inline void PatchControlArray_invert(Array<PatchControl>& ctrl, std::size_t widt
 class PatchTesselation
 {
 public:
+  PatchTesselation()
+    : m_numStrips(0), m_lenStrips(0), m_nArrayWidth(0), m_nArrayHeight(0)
+  {
+  }
   Array<ArbitraryMeshVertex> m_vertices;
   Array<RenderIndex> m_indices;
   std::size_t m_numStrips;
@@ -747,6 +745,7 @@ public:
     evaluateTransform();
     UpdateCachedData();
   }
+  bool isValid() const;
 
   void snapto(float snap)
   {
@@ -940,6 +939,10 @@ public:
     return m_ctrl.data() + m_ctrl.size();
   }
 
+  PatchControlArray& getControlPoints()
+  {
+    return m_ctrl;
+  }
   PatchControlArray& getControlPointsTransformed()
   {
     return m_ctrlTransformed;
index 7080382..713d212 100644 (file)
@@ -69,7 +69,37 @@ void Patch_Destroy()
   PatchInstance::destroyStatic();
 }
 
-class Quake3PatchCreator : public PatchCreator
+class CommonPatchCreator : public PatchCreator
+{
+public:
+  void Patch_undoSave(scene::Node& patch) const
+  {
+    Node_getPatch(patch)->undoSave();
+  }
+  void Patch_resize(scene::Node& patch, std::size_t width, std::size_t height) const
+  {
+    Node_getPatch(patch)->setDims(width, height);
+  }
+  PatchControlMatrix Patch_getControlPoints(scene::Node& node) const
+  {
+    Patch& patch = *Node_getPatch(node);
+    return PatchControlMatrix(patch.getHeight(), patch.getWidth(), patch.getControlPoints().data());
+  }
+  void Patch_controlPointsChanged(scene::Node& patch) const
+  {
+    return Node_getPatch(patch)->controlPointsChanged();
+  }
+  const char* Patch_getShader(scene::Node& patch) const
+  {
+    return Node_getPatch(patch)->GetShader();
+  }
+  void Patch_setShader(scene::Node& patch, const char* shader) const
+  {
+    Node_getPatch(patch)->SetShader(shader);
+  }
+};
+
+class Quake3PatchCreator : public CommonPatchCreator
 {
 public:
   scene::Node& createPatch()
@@ -85,7 +115,7 @@ PatchCreator& GetQuake3PatchCreator()
   return g_Quake3PatchCreator;
 }
 
-class Doom3PatchCreator : public PatchCreator
+class Doom3PatchCreator : public CommonPatchCreator
 {
 public:
   scene::Node& createPatch()
@@ -101,7 +131,7 @@ PatchCreator& GetDoom3PatchCreator()
   return g_Doom3PatchCreator;
 }
 
-class Doom3PatchDef2Creator : public PatchCreator
+class Doom3PatchDef2Creator : public CommonPatchCreator
 {
 public:
   scene::Node& createPatch()
index 1e57eeb..b4816b3 100644 (file)
@@ -133,6 +133,7 @@ public:
     m_radiantcore.getAppPath = &AppPath_get;
     m_radiantcore.getGameToolsPath = &GameToolsPath_get;
     m_radiantcore.getSettingsPath = &SettingsPath_get;
+    m_radiantcore.getMapsPath = &getMapsPath;
 
     m_radiantcore.getGameName = &gamename_get;
     m_radiantcore.getGameMode = &gamemode_get;
@@ -153,6 +154,8 @@ public:
     m_radiantcore.attachGameModeObserver = Radiant_attachGameModeObserver;
     m_radiantcore.detachGameModeObserver = Radiant_detachGameModeObserver;
 
+    m_radiantcore.XYWindowDestroyed_connect = XYWindowDestroyed_connect;
+    m_radiantcore.XYWindowDestroyed_disconnect = XYWindowDestroyed_disconnect;
     m_radiantcore.XYWindowMouseDown_connect = XYWindowMouseDown_connect;
     m_radiantcore.XYWindowMouseDown_disconnect = XYWindowMouseDown_disconnect;
     m_radiantcore.XYWindow_getViewType = XYWindow_getViewType;
index b58cea4..cb83691 100644 (file)
@@ -102,7 +102,7 @@ public:
   scene::Node& root()
   {
     ASSERT_MESSAGE(!m_rootpath.empty(), "scenegraph root does not exist");
-    return *m_rootpath.top();
+    return m_rootpath.top();
   }
   void insert_root(scene::Node& root)
   {
@@ -122,7 +122,7 @@ public:
 
     ASSERT_MESSAGE(!m_rootpath.empty(), "scenegraph root does not exist");
 
-    scene::Node& root = *m_rootpath.top();
+    scene::Node& root = m_rootpath.top();
 
     m_rootpath.pop();
 
index 9000601..b59384b 100644 (file)
@@ -888,6 +888,8 @@ XYWnd::XYWnd() :
 
 XYWnd::~XYWnd()
 {
+  onDestroyed();
+
   if(m_mnuDrop != 0)
   {
     gtk_widget_destroy(GTK_WIDGET(m_mnuDrop));
index 317ec59..bf87ad3 100644 (file)
@@ -228,6 +228,7 @@ public:
     return m_nHeight;
   }
 
+  Signal0 onDestroyed;
   Signal3<const WindowVector&, ButtonIdentifier, ModifierFlags> onMouseDown;
   void mouseDown(const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers);
   typedef Member3<XYWnd, const WindowVector&, ButtonIdentifier, ModifierFlags, void, &XYWnd::mouseDown> MouseDownCaller;
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_caulk.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_caulk.bmp
new file mode 100644 (file)
index 0000000..5223950
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_caulk.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp
new file mode 100644 (file)
index 0000000..33cc949
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_dropent.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_dropent.bmp
new file mode 100644 (file)
index 0000000..2fcdcba
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_dropent.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp
new file mode 100644 (file)
index 0000000..cc5e272
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp
new file mode 100644 (file)
index 0000000..ed720e9
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp
new file mode 100644 (file)
index 0000000..fbb1571
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_trainpathplot.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_trainpathplot.bmp
new file mode 100644 (file)
index 0000000..66537dc
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_trainpathplot.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp
new file mode 100644 (file)
index 0000000..08f55f3
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_turnedge.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_turnedge.bmp
new file mode 100644 (file)
index 0000000..b72cb2a
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_turnedge.bmp differ
diff --git a/setup/data/tools/plugins/bt/bt-el1.txt b/setup/data/tools/plugins/bt/bt-el1.txt
new file mode 100644 (file)
index 0000000..ccac5e6
--- /dev/null
@@ -0,0 +1,17 @@
+common/areaportal\r
+common/clip\r
+common/clusterportal\r
+common/cushion\r
+common/donotenter\r
+common/full_clip\r
+common/hint\r
+common/missileclip\r
+common/nodraw\r
+common/nodrawnonsolid\r
+common/nodrop\r
+common/noimpact\r
+common/origin\r
+common/trigger\r
+common/weapclip\r
+liquid\r
+fog
\ No newline at end of file
diff --git a/setup/data/tools/plugins/bt/bt-el2.txt b/setup/data/tools/plugins/bt/bt-el2.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/setup/data/tools/plugins/bt/door-tex-trim.txt b/setup/data/tools/plugins/bt/door-tex-trim.txt
new file mode 100644 (file)
index 0000000..5211a98
--- /dev/null
@@ -0,0 +1,5 @@
+base_support/support1rust\r
+base_support/support1shiny\r
+base_support/support2rust\r
+base_support/wplat1_1\r
+base_support/plate2_5
\ No newline at end of file
diff --git a/setup/data/tools/plugins/bt/door-tex.txt b/setup/data/tools/plugins/bt/door-tex.txt
new file mode 100644 (file)
index 0000000..94b352f
--- /dev/null
@@ -0,0 +1,10 @@
+base_door/shinymetaldoor\r
+base_door/shinymetaldoor_outside\r
+gothic_door/door02_bred\r
+gothic_door/door02_bred2_shiny\r
+gothic_door/door02_eblue2_shiny\r
+gothic_door/door02_i_ornate5_fin\r
+gothic_door/door02_j\r
+gothic_door/door02_j3\r
+gothic_door/door02_j4\r
+gothic_door/door02_k2b
\ No newline at end of file
diff --git a/setup/data/tools/plugins/bt/tp_ent.txt b/setup/data/tools/plugins/bt/tp_ent.txt
new file mode 100644 (file)
index 0000000..09488da
--- /dev/null
@@ -0,0 +1,14 @@
+{\r
+       "entity" "misc_model"\r
+\r
+       "offset" "-16"\r
+\r
+       "model" "models/mapobjects/trees_sd/tree_a.md3"\r
+       "model" "models/mapobjects/trees_sd/tree_b.md3"\r
+       "model" "models/mapobjects/trees_sd/tree_c.md3"\r
+       "model" "models/mapobjects/trees_sd/tree_d.md3"\r
+\r
+       "pitch" "-5" "5"\r
+       "yaw" "0" "360"\r
+       "scale" "1" "1.3"\r
+}
\ No newline at end of file