Merge branch 'osxnetradiant'
authorRudolf Polzer <rpolzer@grawp.(none)>
Sun, 28 Mar 2010 17:32:53 +0000 (19:32 +0200)
committerRudolf Polzer <rpolzer@grawp.(none)>
Sun, 28 Mar 2010 17:32:53 +0000 (19:32 +0200)
Conflicts:
contrib/bobtoolz/DPatch.cpp
contrib/bobtoolz/bobToolz-GTK.cpp
contrib/bobtoolz/funchandlers-GTK.cpp
install-dylibs.sh
setup/data/osx/NetRadiant.app/Contents/MacOS/netradiant.sh

1  2 
Makefile
contrib/bobtoolz/bobToolz-GTK.cpp
contrib/bobtoolz/funchandlers-GTK.cpp

diff --combined Makefile
+++ b/Makefile
@@@ -192,7 -192,8 +192,8 @@@ ifeq ($(OS),Darwin
        A = a
        DLL = dylib
        MWINDOWS =
+       MACVERSION ?= 16
+       CPPFLAGS_COMMON += -DMACVERSION="$(MACVERSION)"
        # workaround for weird prints
        ECHO_NOLF = /bin/echo -n
  
@@@ -376,6 -377,7 +377,7 @@@ endi
  %.o: %.c $(if $(findstring $(DEPEND_ON_MAKEFILE),yes),$(wildcard Makefile*),)
        $(CC) $< $(CFLAGS) $(CFLAGS_COMMON) $(CPPFLAGS_EXTRA) $(CPPFLAGS_COMMON) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@
  
  $(INSTALLDIR)/q3map2.$(EXE): LIBS_EXTRA := $(LIBS_XML) $(LIBS_GLIB) $(LIBS_PNG) $(LIBS_ZLIB)
  $(INSTALLDIR)/q3map2.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) $(CPPFLAGS_GLIB) $(CPPFLAGS_PNG) -Itools/quake3/common -Ilibs -Iinclude
  $(INSTALLDIR)/q3map2.$(EXE): \
@@@ -908,12 -910,12 +910,12 @@@ $(INSTALLDIR)/plugins/ufoaiplug.$(DLL)
        contrib/ufoaiplug/ufoai_level.o \
        contrib/ufoaiplug/ufoai.o \
  
 -#$(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): LIBS_EXTRA := $(LIBS_GLIB) $(LIBS_GTK)
 -#$(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): CPPFLAGS_EXTRA := $(CPPFLAGS_GLIB) $(CPPFLAGS_GTK) -Ilibs -Iinclude
 -#$(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): \
 -#     contrib/bkgrnd2d/bkgrnd2d.o \
 -#     contrib/bkgrnd2d/dialog.o \
 -#     contrib/bkgrnd2d/plugin.o \
 +$(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): LIBS_EXTRA := $(LIBS_GLIB) $(LIBS_GTK)
 +$(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): CPPFLAGS_EXTRA := $(CPPFLAGS_GLIB) $(CPPFLAGS_GTK) -Ilibs -Iinclude
 +$(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): \
 +      contrib/bkgrnd2d/bkgrnd2d.o \
 +      contrib/bkgrnd2d/dialog.o \
 +      contrib/bkgrnd2d/plugin.o \
  
  $(INSTALLDIR)/heretic2/h2data.$(EXE): LIBS_EXTRA := $(LIBS_XML)
  $(INSTALLDIR)/heretic2/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/quake2/qdata_heretic2/common -Itools/quake2/qdata_heretic2/qcommon -Itools/quake2/qdata_heretic2 -Itools/quake2/common -Ilibs -Iinclude
@@@ -958,17 -960,21 +960,19 @@@ install-data: binarie
        [ "$(OS)" != "Darwin" ] || $(CP_R) setup/data/osx/NetRadiant.app/* $(INSTALLDIR_BASE)/NetRadiant.app/
        set -ex; \
        for GAME in games/*; do \
 -              if [ -d "$$GAME/tools" ]; then \
 -                      GAME=$$GAME/tools; \
 +              if [ "$$GAME" = "games/*" ]; then \
 +                      $(ECHO) "Game packs not found, please run"; \
 +                      $(ECHO) "  ./download-gamepacks.sh"; \
 +                      $(ECHO) "and then try again!"; \
 +              else \
 +                      CP="$(CP)" CP_R="$(CP_R)" $(SH) install-gamepack.sh "$$GAME" "$(INSTALLDIR)"; \
                fi; \
 -              for GAMEFILE in $$GAME/games/*.game; do \
 -                      $(CP) "$$GAMEFILE" $(INSTALLDIR)/games/; \
 -              done; \
 -              for GAMEDIR in $$GAME/*.game; do \
 -                      $(CP_R) "$$GAMEDIR" $(INSTALLDIR)/; \
 -              done; \
        done
        $(ECHO) $(RADIANT_MINOR_VERSION) > $(INSTALLDIR)/RADIANT_MINOR
        $(ECHO) $(RADIANT_MAJOR_VERSION) > $(INSTALLDIR)/RADIANT_MAJOR
        $(CP_R) setup/data/tools/* $(INSTALLDIR)/
+       $(MKDIR) $(INSTALLDIR)/docs
+       $(CP_R) docs/* $(INSTALLDIR)/docs/
        $(FIND) $(INSTALLDIR_BASE)/ -name .svn -exec $(RM_R) {} \; -prune
  
  .PHONY: install-dll
@@@ -62,7 -62,7 +62,7 @@@ void BobToolz_destroy(
  char* PLUGIN_NAME = "bobToolz";
  
  // commands in the menu
 -static char* PLUGIN_COMMANDS = "About...,-,Vis Viewer,Path Plotter...,-,Stair Builder...,PitOMatic,Make Chain...,Door Builder...,-,Texture Reset...,Intersect...";
 +static char* PLUGIN_COMMANDS = "About...,-,Reset Textures...,PitOMatic,-,Vis Viewer,Brush Cleanup,Polygon Builder,Caulk Selection,-,Tree Planter,Drop Entity,Plot Splines,-,Merge Patches,Split patches,Split patches cols,Split patches rows,Turn edge";
  
  // globals
  GtkWidget *g_pRadiantWnd = NULL;
@@@ -90,34 -90,22 +90,44 @@@ extern "C" const char* QERPlug_GetComma
  extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) {
        LoadLists();
  
 -      if( string_equal_nocase(p, "texture reset...") ) {
 +      if( string_equal_nocase( p, "brush cleanup" ) ) {
 +    DoFixBrushes();
 +  } else if( string_equal_nocase( p, "polygon builder" ) ) {
 +    DoPolygonsTB();
 +  } else if( string_equal_nocase( p, "caulk selection" ) ) {
 +    DoCaulkSelection();
 +  } else if( string_equal_nocase( p, "tree planter" ) ) {
 +    DoTreePlanter();
 +  } else if( string_equal_nocase( p, "plot splines" ) ) {
 +    DoTrainPathPlot();
 +  } else if( string_equal_nocase( p, "drop entity" ) ) {
 +    DoDropEnts();
 +  } else if( string_equal_nocase( p, "merge patches" ) ) {
 +    DoMergePatches();
 +  } else if( string_equal_nocase( p, "split patches" ) ) {
 +    DoSplitPatch();
 +  } else if( string_equal_nocase( p, "split patches rows" ) ) {
 +      DoSplitPatchRows();
 +  } else if( string_equal_nocase( p, "split patches cols" ) ) {
 +      DoSplitPatchCols();
 +  } else if( string_equal_nocase( p, "turn edge" ) ) {
 +    DoFlipTerrain();
 +  } else if( string_equal_nocase(p, "reset textures...") ) {
                DoResetTextures();
        } else if( string_equal_nocase(p, "pitomatic") ) {
                DoPitBuilder();
        } else if( string_equal_nocase(p, "vis viewer") ) {
                DoVisAnalyse();
+       } else if( string_equal_nocase(p, "stair builder...") ) {
+               DoBuildStairs();
+       } else if( string_equal_nocase(p, "door builder...") ) {
+               DoBuildDoors();
+       } else if( string_equal_nocase(p, "intersect...") ) {
+               DoIntersect();
+       } else if( string_equal_nocase(p, "make chain...") ) {
+               DoMakeChain();
+       } else if( string_equal_nocase(p, "path plotter...") ) {
+               DoPathPlotter();
        } else if( string_equal_nocase(p, "about...") ) {
                DoMessageBox(PLUGIN_ABOUT, "About", eMB_OK);
        }
@@@ -129,7 -117,7 +139,7 @@@ const char* QERPlug_GetCommandTitleList
  }
  
  
- #define NUM_TOOLBARBUTTONS 9
+ #define NUM_TOOLBARBUTTONS 14
  
  std::size_t ToolbarButtonCount( void ) {
        return NUM_TOOLBARBUTTONS;
@@@ -141,22 -129,30 +151,30 @@@ public
    virtual const char* getImage() const
    {
      switch( mIndex ) {
-       case 0: return "bobtoolz_cleanup.bmp";
-       case 1: return "bobtoolz_poly.bmp";
-       case 2: return "bobtoolz_caulk.bmp";
-       case 3: return "bobtoolz_treeplanter.bmp";
-       case 4: return "bobtoolz_trainpathplot.bmp";
-       case 5: return "bobtoolz_dropent.bmp";
-       case 6: return "bobtoolz_merge.bmp";
-       case 7: return "bobtoolz_split.bmp";
-       case 8: return "bobtoolz_turnedge.bmp";
+               case 0: return "bobtoolz_cleanup.bmp";
+               case 1: return "bobtoolz_poly.bmp";
+               case 2: return "bobtoolz_caulk.bmp";
+               case 3: return "";
+               case 4: return "bobtoolz_treeplanter.bmp";
+               case 5: return "bobtoolz_trainpathplot.bmp";
+               case 6: return "bobtoolz_dropent.bmp";
+               case 7: return "";
+               case 8: return "bobtoolz_merge.bmp";
+               case 9: return "bobtoolz_split.bmp";
+               case 10: return "bobtoolz_splitrow.bmp";
+               case 11: return "bobtoolz_splitcol.bmp";
+         case 12: return "";
+               case 13: return "bobtoolz_turnedge.bmp";
      }
      return NULL;
    }
    virtual EType getType() const
    {
      switch( mIndex ) {
-       case 3: return eToggleButton;
+               case 3: return eSpace;
+       case 4: return eToggleButton;
+               case 7: return eSpace;
+               case 12: return eSpace;
        default: return eButton;
      }    
    }
        case 0: return "Cleanup";
        case 1: return "Polygons";
        case 2: return "Caulk";
-       case 3: return "Tree Planter";
-       case 4: return "Plot Splines";
-       case 5: return "Drop Entity";
-       case 6: return "Merge Patches";
-       case 7: return "Split Patches";
-       case 8: return "Flip Terrain";
+       case 4: return "Tree Planter";
+       case 5: return "Plot Splines";
+       case 6: return "Drop Entity";
+       case 8: return "Merge 2 Patches";
+       case 9: return "Split Patch";
+       case 10: return "Split Patch Rows";
+       case 11: return "Split Patch Columns";
+       case 13: return "Flip Terrain";
      }
      return NULL;
    }
        case 0: return "Brush Cleanup";
        case 1: return "Polygons";
        case 2: return "Caulk selection";
-       case 3: return "Tree Planter";
-       case 4: return "Plot Splines";
-       case 5: return "Drop Entity";
-       case 6: return "Merge Patches";
-       case 7: return "Split Patches";
-       case 8: return "Flip Terrain";
+       case 4: return "Tree Planter";
+       case 5: return "Plot Splines";
+       case 6: return "Drop Entity";
+       case 8: return "Merge 2 Patches";
+       case 9: return "Split Patch";
+         case 10: return "Split Patch Rows";
+         case 11: return "Split Patch Columns";
+       case 13: return "Flip Terrain (Turn Edge)";
      }
      return NULL;
    }
        case 0: DoFixBrushes(); break;
        case 1: DoPolygonsTB(); break;
        case 2: DoCaulkSelection(); break;
-       case 3: DoTreePlanter(); break;
-       case 4: DoTrainPathPlot(); break;
-       case 5: DoDropEnts(); break;
-       case 6: DoMergePatches(); break;
-       case 7: DoSplitPatch(); break;
-       case 8: DoFlipTerrain(); break;
+       case 4: DoTreePlanter(); break;
+       case 5: DoTrainPathPlot(); break;
+       case 6: DoDropEnts(); break;
+       case 8: DoMergePatches(); break;
+       case 9: DoSplitPatch(); break;
+         case 10: DoSplitPatchRows(); break;
+         case 11: DoSplitPatchCols(); break;
+       case 13: DoFlipTerrain(); break;
      }
    }
  
@@@ -263,7 -265,7 +287,7 @@@ class BobToolzPluginModule : public Typ
    _QERPluginTable m_plugin;
  public:
    typedef _QERPluginTable Type;
-   STRING_CONSTANT(Name, "bobtoolz");
+   STRING_CONSTANT(Name, "bobToolz");
  
    BobToolzPluginModule()
    {
@@@ -295,7 -297,7 +319,7 @@@ class BobToolzToolbarDependencies 
  {
  public:
    BobToolzToolbarDependencies() :
-     ModuleRef<_QERPluginTable>("bobtoolz")
+     ModuleRef<_QERPluginTable>("bobToolz")
    {
    }
  };
@@@ -305,7 -307,7 +329,7 @@@ class BobToolzToolbarModule : public Ty
    _QERPlugToolbarTable m_table;
  public:
    typedef _QERPlugToolbarTable Type;
-   STRING_CONSTANT(Name, "bobtoolz");
+   STRING_CONSTANT(Name, "bobToolz");
  
    BobToolzToolbarModule()
    {
@@@ -102,17 -102,19 +102,19 @@@ void DoIntersect(
        {
                if( GlobalSelectionSystem().countSelected() < 2 )
                {
-                       DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK);
+                       //DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK);
+                       globalErrorStream() << "bobToolz Intersect: Invalid number of brushes selected, choose at least 2.\n";
                        return; 
                }
        }
  
        DEntity world;
        switch(rs.nBrushOptions)
        {
        case BRUSH_OPT_SELECTED:
                {
+                       
+                       world.LoadFromEntity(GlobalRadiant().getMapWorldEntity(), false);
                        world.LoadSelectedBrushes();
                        break;
                }
                        break;
                }
        }
        world.RemoveNonCheckBrushes(&exclusionList, rs.bUseDetail);
  
        bool* pbSelectList;
                pbSelectList = world.BuildIntersectList();
  
        world.SelectBrushes(pbSelectList);
+       int brushCount = GlobalSelectionSystem().countSelected();
+       globalOutputStream() << "bobToolz Intersect: " << brushCount << " intersecting brushes found.\n";
        delete[] pbSelectList;
  }
  
@@@ -147,12 -149,18 +149,18 @@@ void DoPolygons(
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz Polygons: Invalid number of brushes selected, choose 1 only.\n";
                return; 
        }
  
        PolygonRS rs;
+       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+       if( !Node_isBrush(instance.path().top()) ) {
+               //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz Polygons: No brush selected, select ONLY one brush.\n";
+               return; 
+       }
        // ask user for type, size, etc....
        if(DoPolygonBox(&rs) == eIDOK)
        {
      vec3_t vMin, vMax;
  
      {
-       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
        VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
        VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
  
@@@ -191,7 -199,7 +199,7 @@@ void DoFixBrushes(
  
        int count = world.FixBrushes();
        
-       globalOutputStream() << count << " invalid/duplicate planes removed\n";
+       globalOutputStream() << "bobToolz FixBrushes: " << count << " invalid/duplicate planes removed.\n";
  }
  
  void DoResetTextures()
@@@ -243,7 -251,8 +251,8 @@@ void DoBuildStairs(
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz BuildStairs: Invalid number of brushes selected, choose 1 only.\n";
                return; 
        }
  
                if(((int)size[2] % rs.stairHeight) != 0)
                {
                        // stairs must fit evenly into brush
-                       DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK);
+                       //DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK);
+                       globalErrorStream() << "bobToolz BuildStairs: Invalid stair height. Height of block must be divisable by stair height.\n";
                }
                else
                {
@@@ -328,7 -338,8 +338,8 @@@ void DoBuildDoors(
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz BuildDoors: Invalid number of brushes selected, choose 1 only.\n";
                return; 
        }
  
@@@ -369,88 -380,104 +380,104 @@@ void DoPathPlotter(
        }
  
        // ensure we have something selected
-       if( GlobalSelectionSystem().countSelected() != 1 )
+       /*
+        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               globalOutputStream() << "bobToolz PathPlotter: Invalid number of entities selected, choose 1 trigger_push entity only.\n";
                return; 
        }
+        */
    Entity* entity = Node_getEntity(GlobalSelectionSystem().ultimateSelected().path().top());
    if(entity != 0)
    {
      DBobView_setEntity(*entity, rs.fMultiplier, rs.nPoints, rs.fGravity, rs.bNoUpdate, rs.bShowExtra);
-   }
+   } 
+   else globalErrorStream() << "bobToolz PathPlotter: No trigger_push entitity selected, select 1 only (Use list to select it).\n";
+       return;
  }
  
  void DoPitBuilder()
  {
-   UndoableCommand undo("bobToolz.pitBuilder");
+       UndoableCommand undo("bobToolz.pitBuilder");
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz PitBuilder: Invalid number of brushes selected, choose 1 only.\n";
                return; 
        }
  
-   vec3_t vMin, vMax;
+       vec3_t vMin, vMax;
  
-   scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-   VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
-   VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
+       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+       //seems it does this also with a patch with valid dimensions.. but probably better to enforce a brush.
+       if( !Node_isBrush(instance.path().top()) ) {
+               //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz PitBuilder: No brush selected, select ONLY 1 brush.\n";
+               return; 
+       }
+       
+       VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
+       VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
  
        DShape pit;
  
        if(pit.BuildPit(vMin, vMax))
        {
                pit.Commit();
-     Path_deleteTop(instance.path());
+               Path_deleteTop(instance.path());
        }
        else
-               DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK);
+       {
+               //DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz PitBuilder: Failed to make Pit, try making the brush bigger.\n";
+       }
  }
  
  void DoMergePatches()
  {
-   UndoableCommand undo("bobToolz.mergePatch");
-   patch_merge_t merge_info;
-   DPatch mrgPatches[2];
-   int i;
+       UndoableCommand undo("bobToolz.mergePatches");
+       patch_merge_t merge_info;
+       DPatch mrgPatches[2];
+       int i;
  
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 2 )
        {
-               DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 only.\n";
+               //DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK);
                return; 
        }
  
-   scene::Instance* patches[2];
-   patches[0] = &GlobalSelectionSystem().ultimateSelected();
-   patches[1] = &GlobalSelectionSystem().penultimateSelected();
+       scene::Instance* patches[2];
+       patches[0] = &GlobalSelectionSystem().ultimateSelected();
+       patches[1] = &GlobalSelectionSystem().penultimateSelected();
  
-   for (i = 0; i < 2; i++)
-   {
-     if (!Node_isPatch(patches[i]->path().top()))
-     {
-       DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
-       return; 
-     }
+       for (i = 0; i < 2; i++)
+       {
+               if (!Node_isPatch(patches[i]->path().top()))
+               {
+                       //DoMessageBox("No patches selected, select ONLY patches", "Error", eMB_OK);
+                       globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose ONLY 2 patches.\n";
+                       return; 
+               }
  
-     mrgPatches[i].LoadFromPatch(*patches[i]);
-   }
+               mrgPatches[i].LoadFromPatch(*patches[i]);
+       }
  
    /*  mrgPatches[0].Transpose();
        mrgPatches[0].RemoveFromRadiant();
        mrgPatches[0].BuildInRadiant();*/
  
-   merge_info = mrgPatches[0].IsMergable(&mrgPatches[1]);
-   if (merge_info.mergable)
-   {
-     globalOutputStream() << merge_info.pos1 << " " <<  merge_info.pos2;
+       merge_info = mrgPatches[0].IsMergable(&mrgPatches[1]);
  
-     globalOutputStream() << "Patches Mergable\n";
-     DPatch* newPatch = mrgPatches[0].MergePatches(merge_info, &mrgPatches[0], &mrgPatches[1]);
+       if (merge_info.mergable)
+       {
+               globalOutputStream() << merge_info.pos1 << " " <<  merge_info.pos2;
+               //Message removed, No tools give feedback on success.
+               //globalOutputStream() << "bobToolz MergePatches: Patches Mergable.\n";
+               DPatch* newPatch = mrgPatches[0].MergePatches(merge_info, &mrgPatches[0], &mrgPatches[1]);
  
      /*                mrgPatches[0].RemoveFromRadiant();
      mrgPatches[0].BuildInRadiant();
          
      delete newPatch;*/
  
-     if (!newPatch)
-     {
-     } else
-     {
-       Path_deleteTop(patches[0]->path());
-       Path_deleteTop(patches[1]->path());
+               if (!newPatch)
+               {
+               } else
+               {
+                       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";
-   }
+                       newPatch->BuildInRadiant();
+                       delete newPatch;
+               }
+       }
+       else
+       {
+               globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n";
+               
+       }
  }
  
  void DoSplitPatch() {
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz SplitPatch: Invalid number of patches selected, choose only 1 patch.\n";
                return; 
        }
  
    scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
  
        if( !Node_isPatch(instance.path().top()) ) {
-               DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
+               //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz SplitPatch: No patch selected, select ONLY 1 patch.\n";
                return; 
        }
  
@@@ -515,62 -545,67 +545,125 @@@ void DoSplitPatchCols() 
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
+               //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz SplitPatchCols: Invalid number of patches selected, choose 1 only.\n";
+               return; 
+       }
+       
+       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+       
+       if( !Node_isPatch(instance.path().top()) ) {
+               //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz SplitPatchCols: No patch selected, select ONLY 1 patch.\n";
+               return; 
+       }
+       
+       patch.LoadFromPatch(instance);
+       
+       std::list<DPatch> patchList = patch.SplitCols();
+       for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
+               (*patches).BuildInRadiant();
+       }
+       
+       Path_deleteTop(instance.path());
+ }
+ void DoSplitPatchRows() {
+       UndoableCommand undo("bobToolz.splitPatchRows");
+       
+       DPatch patch;
+       
+       // ensure we have something selected
+       if( GlobalSelectionSystem().countSelected() != 1 )
+       {
+               //DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz SplitPatchRows: Invalid number of patches selected, choose 1 only.\n";
+               return; 
+       }
+       
+       scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+       
+       if( !Node_isPatch(instance.path().top()) ) {
+               //DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz SplitPatchRows: No patch selected, select ONLY 1 patch.\n";
+               return; 
+       }
+       
+       patch.LoadFromPatch(instance);
+       
+       std::list<DPatch> patchList = patch.SplitRows();
+       for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
+               (*patches).BuildInRadiant();
+       }
+       
+       Path_deleteTop(instance.path());
+ }
++void DoSplitPatchCols() {
++      UndoableCommand undo("bobToolz.splitPatchCols");
++      
++      DPatch patch;
++      
++      // ensure we have something selected
++      if( GlobalSelectionSystem().countSelected() != 1 )
++      {
 +              DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
 +              return; 
 +      }
 +      
 +      scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
 +      
 +      if( !Node_isPatch(instance.path().top()) ) {
 +              DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
 +              return; 
 +      }
 +      
 +      patch.LoadFromPatch(instance);
 +      
 +      std::list<DPatch> patchList = patch.SplitCols();
 +      for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
 +              (*patches).BuildInRadiant();
 +      }
 +      
 +      Path_deleteTop(instance.path());
 +}
 +
 +void DoSplitPatchRows() {
 +      UndoableCommand undo("bobToolz.splitPatchRows");
 +      
 +      DPatch patch;
 +      
 +      // ensure we have something selected
 +      if( GlobalSelectionSystem().countSelected() != 1 )
 +      {
 +              DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
 +              return; 
 +      }
 +      
 +      scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
 +      
 +      if( !Node_isPatch(instance.path().top()) ) {
 +              DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
 +              return; 
 +      }
 +      
 +      patch.LoadFromPatch(instance);
 +      
 +      std::list<DPatch> patchList = patch.SplitRows();
 +      for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
 +              (*patches).BuildInRadiant();
 +      }
 +      
 +      Path_deleteTop(instance.path());
 +}
 +
  void DoVisAnalyse()
  {
        char filename[1024];
  
        if( GlobalSelectionSystem().countSelected() == 0 )
        {
+               globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n";
                if(g_VisView) 
                {
                        delete g_VisView;
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 1 )
        {
-               DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n";
+               return; 
+       }
+       
+       scene::Instance& brush = GlobalSelectionSystem().ultimateSelected();
+       //ensure we have a brush selected
+       if( !Node_isBrush(brush.path().top()) ) {
+               //DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz VisAnalyse: No brush selected, select ONLY 1 brush.\n";
                return; 
        }
-   scene::Instance& brush = GlobalSelectionSystem().ultimateSelected();
        DBrush orgBrush;
        orgBrush.LoadFromBrush(brush, false);
  
    const char* rad_filename = GlobalRadiant().getMapName();
        if(!rad_filename)
        {
-               DoMessageBox("An Error Occurred While Trying\n To Get The Map Filename", "Error", eMB_OK);
+               //DoMessageBox("An ERROR occurred while trying\n to get the map filename", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz VisAnalyse: An ERROR occurred while trying to get the map filename.\n";
                return;
        }
  
@@@ -662,9 -704,17 +762,17 @@@ void DoDropEnts() 
  }
  
  void DoMakeChain() {
-   UndoableCommand undo("bobToolz.makeChain");
-       DTreePlanter pl;
-       pl.MakeChain();
+       MakeChainRS rs;
+       if(DoMakeChainBox(&rs) == eIDOK)
+       {
+               if ( rs.linkNum > 1001 ) {
+                       globalErrorStream() << "bobToolz MakeChain: " << rs.linkNum << " to many Elemets, limited to 1000.\n";
+                       return;
+               }
+               UndoableCommand undo("bobToolz.makeChain");
+               DTreePlanter pl;
+               pl.MakeChain(rs.linkNum,rs.linkName);
+       }
  }
  
  typedef DPoint* pntTripple[3];
@@@ -679,21 -729,31 +787,31 @@@ void DoFlipTerrain() 
        // ensure we have something selected
        if( GlobalSelectionSystem().countSelected() != 2 )
        {
-               DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK);
+               //DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz FlipTerrain: Invalid number of objects selected, choose 2 only.\n";
                return; 
        }
  
    scene::Instance* brushes[2];
        brushes[0] = &GlobalSelectionSystem().ultimateSelected();
        brushes[1] = &GlobalSelectionSystem().penultimateSelected();
+       //ensure we have only Brushes selected.
+       for (i = 0; i < 2; i++)
+       {
+               if( !Node_isBrush(brushes[i]->path().top()) ) {
+                       //DoMessageBox("No brushes selected, select ONLY brushes", "Error", eMB_OK);
+                       globalErrorStream() << "bobToolz FlipTerrain: No brushes selected, select ONLY 2 brushes.\n";
+                       return; 
+               }
+       }
        DBrush Brushes[2];
        DPlane* Planes[2];
        pntTripple Points[2];
        for( i = 0; i < 2; i++ ) {
                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);
+                       //DoMessageBox("Error", "Error", eMB_OK);
+                       globalErrorStream() << "bobToolz FlipTerrain: ERROR (FindPlaneWithClosestNormal/FindPointsForPlane).\n";
                        return;
                }
        }
                found = false;
        }
        if(dontmatch[0] == -1) {
-               DoMessageBox("Error", "Error", eMB_OK);
+               //DoMessageBox("Error", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[0]).\n";
                return;
        }
  
                found = false;
        }
        if(dontmatch[1] == -1) {
-               DoMessageBox("Error", "Error", eMB_OK);
+               //DoMessageBox("Error", "Error", eMB_OK);
+               globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[1]).\n";
                return;
        }