]> de.git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge commit '7ca59bef0ae15880f51b2f68104b933e918d543c' into garux-merge
authorThomas Debesse <dev@illwieckz.net>
Mon, 25 May 2020 17:29:42 +0000 (19:29 +0200)
committerThomas Debesse <dev@illwieckz.net>
Mon, 25 May 2020 17:29:42 +0000 (19:29 +0200)
1  2 
radiant/brushmanip.cpp
radiant/csg.cpp
radiant/csg.h
radiant/mainframe.cpp
radiant/patchmanip.cpp
radiant/texwindow.cpp

index 7f71e7520b2988fad8715e5833369ab6c998edc0,36ed6a9b13cf01dfc9ba3c1afaeeca0b3fa014c0..b3b1fb8facff6b533c32e7763f8fc740505ea46b
@@@ -1266,10 -1390,10 +1266,10 @@@ void Brush_constructMenu( ui::Menu men
                if ( g_Layout_enableDetachableMenus.m_value ) {
                        menu_tearoff( menu_in_menu );
                }
-               create_menu_item_with_mnemonic( menu_in_menu, "Make _Hollow", "CSGHollow" );
-               create_menu_item_with_mnemonic( menu_in_menu, "Make _Room", "CSGRoom" );
                create_menu_item_with_mnemonic( menu_in_menu, "CSG _Subtract", "CSGSubtract" );
                create_menu_item_with_mnemonic( menu_in_menu, "CSG _Merge", "CSGMerge" );
 -              create_menu_item_with_mnemonic( menu_in_menu, "Make _Room", "CSGroom" );
++              create_menu_item_with_mnemonic( menu_in_menu, "Make _Room", "CSGRoom" );
+               create_menu_item_with_mnemonic( menu_in_menu, "CSG _Tool", "CSGTool" );
        }
        menu_separator( menu );
        {
diff --cc radiant/csg.cpp
index 24ca4035b82d3721310d91e7fb5236c485b4a8d0,1b0d6004e622366d14852a53e312386afff429b3..27f05bf5b64396d23e9eaa2d4dd1bcbce00da033
@@@ -29,7 -29,7 +29,8 @@@
  #include "brushmanip.h"
  #include "brushnode.h"
  #include "grid.h"
 +
+ /*
  void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){
        if ( face.contributes() ) {
                out.push_back( new Brush( brush ) );
@@@ -649,3 -880,313 +883,305 @@@ void CSG_Merge( void )
                SceneChangeNotify();
        }
  }
 -      GtkWindow *window;
+ /*
+    =============
+    CSG_Tool
+    =============
+  */
+ #include "mainframe.h"
+ #include <gtk/gtk.h>
+ #include "gtkutil/dialog.h"
+ #include "gtkutil/button.h"
+ #include "gtkutil/accelerator.h"
+ struct CSGToolDialog
+ {
+       GtkSpinButton* spin;
 -      if ( g_csgtool_dialog.window == NULL ) {
 -              g_csgtool_dialog.window = create_dialog_window( MainFrame_getWindow(), "CSG Tool", G_CALLBACK( CSGdlg_delete ), &g_csgtool_dialog );
++      bool allocated{false};
++      ui::Window window{ui::null};
+       GtkToggleButton *radXYZ, *radX, *radY, *radZ, *caulk, *removeInner;
+ };
+ CSGToolDialog g_csgtool_dialog;
+ DoubleVector3 getExclusion(){
+       if( gtk_toggle_button_get_active( g_csgtool_dialog.radX ) ){
+               return DoubleVector3( 1, 0, 0 );
+       }
+       else if( gtk_toggle_button_get_active( g_csgtool_dialog.radY ) ){
+               return DoubleVector3( 0, 1, 0 );
+       }
+       else if( gtk_toggle_button_get_active( g_csgtool_dialog.radZ ) ){
+               return DoubleVector3( 0, 0, 1 );
+       }
+       return DoubleVector3( 0, 0, 0 );
+ }
+ bool getCaulk(){
+               if( gtk_toggle_button_get_active( g_csgtool_dialog.caulk ) ){
+               return true;
+       }
+       return false;
+ }
+ bool getRemoveInner(){
+               if( gtk_toggle_button_get_active( g_csgtool_dialog.removeInner ) ){
+               return true;
+       }
+       return false;
+ }
+ class BrushFaceOffset
+ {
+ float offset;
+ public:
+ BrushFaceOffset( float offset )
+       : offset( offset ){
+ }
+ void operator()( BrushInstance& brush ) const {
+       double mindot = 0;
+       double maxdot = 0;
+       Brush_forEachFace( brush, FaceExclude( getExclusion(), mindot, maxdot ) );
+       Brush_forEachFace( brush, FaceOffset( offset, getExclusion(), mindot, maxdot ) );
+ }
+ };
+ //=================DLG
+ static gboolean CSGdlg_HollowDiag( GtkWidget *widget, CSGToolDialog* dialog ){
+       float offset = static_cast<float>( gtk_spin_button_get_value( dialog->spin ) );
+       UndoableCommand undo( "brushHollow::Diag" );
+       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( offset, diag ) );
+       if( getRemoveInner() )
+               GlobalSceneGraph().traverse( BrushDeleteSelected() );
+       SceneChangeNotify();
+       return TRUE;
+ }
+ static gboolean CSGdlg_HollowWrap( GtkWidget *widget, CSGToolDialog* dialog ){
+       float offset = static_cast<float>( gtk_spin_button_get_value( dialog->spin ) );
+       UndoableCommand undo( "brushHollow::Wrap" );
+       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( offset, wrap ) );
+       if( getRemoveInner() )
+               GlobalSceneGraph().traverse( BrushDeleteSelected() );
+       SceneChangeNotify();
+       return TRUE;
+ }
+ static gboolean CSGdlg_HollowExtrude( GtkWidget *widget, CSGToolDialog* dialog ){
+       float offset = static_cast<float>( gtk_spin_button_get_value( dialog->spin ) );
+       UndoableCommand undo( "brushHollow::Extrude" );
+       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( offset, extrude ) );
+       if( getRemoveInner() )
+               GlobalSceneGraph().traverse( BrushDeleteSelected() );
+       SceneChangeNotify();
+       return TRUE;
+ }
+ static gboolean CSGdlg_HollowPull( GtkWidget *widget, CSGToolDialog* dialog ){
+       float offset = static_cast<float>( gtk_spin_button_get_value( dialog->spin ) );
+       UndoableCommand undo( "brushHollow::Pull" );
+       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( offset, pull ) );
+       if( getRemoveInner() )
+               GlobalSceneGraph().traverse( BrushDeleteSelected() );
+       SceneChangeNotify();
+       return TRUE;
+ }
+ static gboolean CSGdlg_BrushShrink( GtkWidget *widget, CSGToolDialog* dialog ){
+       gtk_spin_button_update ( dialog->spin );
+       float offset = static_cast<float>( gtk_spin_button_get_value( dialog->spin ) );
+       offset *= -1;
+       UndoableCommand undo( "Shrink brush" );
+ //    GlobalSceneGraph().traverse( OffsetBrushFacesSelectedWalker( offset ) );
+       //Scene_ForEachSelectedBrush_ForEachFace( GlobalSceneGraph(), BrushFaceOffset( offset ) );
+       Scene_forEachSelectedBrush( BrushFaceOffset( offset ) );
+       SceneChangeNotify();
+       return TRUE;
+ }
+ static gboolean CSGdlg_BrushExpand( GtkWidget *widget, CSGToolDialog* dialog ){
+       gtk_spin_button_update ( dialog->spin );
+       float offset = static_cast<float>( gtk_spin_button_get_value( dialog->spin ) );
+       UndoableCommand undo( "Expand brush" );
+ //    GlobalSceneGraph().traverse( OffsetBrushFacesSelectedWalker( offset ) );
+       //Scene_ForEachSelectedBrush_ForEachFace( GlobalSceneGraph(), BrushFaceOffset( offset ) );
+       Scene_forEachSelectedBrush( BrushFaceOffset( offset ) );
+       SceneChangeNotify();
+       return TRUE;
+ }
+ static gboolean CSGdlg_grid2spin( GtkWidget *widget, CSGToolDialog* dialog ){
+       gtk_spin_button_set_value( dialog->spin, GetGridSize() );
+       return TRUE;
+ }
+ static gboolean CSGdlg_delete( GtkWidget *widget, GdkEventAny *event, CSGToolDialog* dialog ){
+       gtk_widget_hide( GTK_WIDGET( dialog->window ) );
+       return TRUE;
+ }
+ void CSG_Tool(){
 -                      GtkHBox* hbox = create_dialog_hbox( 4, 4 );
++      if ( !g_csgtool_dialog.allocated ) {
++              g_csgtool_dialog.allocated = true;
++              g_csgtool_dialog.window = MainFrame_getWindow().create_dialog_window( "CSG Tool", G_CALLBACK( CSGdlg_delete ), &g_csgtool_dialog );
+               gtk_window_set_type_hint( g_csgtool_dialog.window, GDK_WINDOW_TYPE_HINT_UTILITY );
+               //GtkAccelGroup* accel = gtk_accel_group_new();
+               //gtk_window_add_accel_group( g_csgtool_dialog.window, accel );
+               global_accel_connect_window( g_csgtool_dialog.window );
+               {
 -                              GtkTable* table = create_dialog_table( 3, 8, 4, 4 );
++                      auto hbox = create_dialog_hbox( 4, 4 );
+                       gtk_container_add( GTK_CONTAINER( g_csgtool_dialog.window ), GTK_WIDGET( hbox ) );
+                       {
 -                                      GtkWidget* button = gtk_button_new_with_label( "Grid->" );
 -                                      gtk_table_attach( table, button, 0, 1, 0, 1,
 -                                                                        (GtkAttachOptions) ( 0 ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
 -                                      gtk_widget_show( button );
++                              auto table = create_dialog_table( 3, 8, 4, 4 );
+                               gtk_box_pack_start( GTK_BOX( hbox ), GTK_WIDGET( table ), TRUE, TRUE, 0 );
+                               {
+                                       //GtkWidget* label = gtk_label_new( "<->" );
+                                       //gtk_widget_show( label );
 -                                      button_set_icon( GTK_BUTTON( button ), "f-caulk.png" );
++                                      auto button = ui::Button( "Grid->" );
++                                      table.attach( button, {0, 1, 0, 1}, {0, 0} );
++                                      button.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_grid2spin ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( 16, 0, 9999, 1, 10, 0 ) );
+                                       GtkSpinButton* spin = GTK_SPIN_BUTTON( gtk_spin_button_new( adj, 1, 3 ) );
+                                       gtk_widget_show( GTK_WIDGET( spin ) );
+                                       gtk_widget_set_tooltip_text( GTK_WIDGET( spin ), "Thickness" );
+                                       gtk_table_attach( table, GTK_WIDGET( spin ), 1, 2, 0, 1,
+                                                                         (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
+                                                                         (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       gtk_widget_set_size_request( GTK_WIDGET( spin ), 64, -1 );
+                                       gtk_spin_button_set_numeric( spin, TRUE );
+                                       g_csgtool_dialog.spin = spin;
+                               }
+                               {
+                                       //radio button group for choosing the exclude axis
+                                       GtkWidget* radXYZ = gtk_radio_button_new_with_label( NULL, "XYZ" );
+                                       GtkWidget* radX = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radXYZ), "-X" );
+                                       GtkWidget* radY = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radXYZ), "-Y" );
+                                       GtkWidget* radZ = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radXYZ), "-Z" );
+                                       gtk_widget_show( radXYZ );
+                                       gtk_widget_show( radX );
+                                       gtk_widget_show( radY );
+                                       gtk_widget_show( radZ );
+                                       gtk_table_attach( table, radXYZ, 2, 3, 0, 1,
+                                                                       (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
+                                                                       (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       gtk_table_attach( table, radX, 3, 4, 0, 1,
+                                                                       (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
+                                                                       (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       gtk_table_attach( table, radY, 4, 5, 0, 1,
+                                                                       (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
+                                                                       (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       gtk_table_attach( table, radZ, 5, 6, 0, 1,
+                                                                       (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
+                                                                       (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       g_csgtool_dialog.radXYZ = GTK_TOGGLE_BUTTON( radXYZ );
+                                       g_csgtool_dialog.radX = GTK_TOGGLE_BUTTON( radX );
+                                       g_csgtool_dialog.radY = GTK_TOGGLE_BUTTON( radY );
+                                       g_csgtool_dialog.radZ = GTK_TOGGLE_BUTTON( radZ );
+                               }
+                               {
+                                       GtkWidget* button = gtk_toggle_button_new();
 -                                      gtk_table_attach( table, button, 6, 7, 0, 1,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "f-caulk.png" );
+                                       gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE );
 -                                      gtk_widget_show( button );
++                                      table.attach( ubutton, { 6, 7, 0, 1 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Caulk some faces" );
+                                       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_removeinner.png" );
++                                      ubutton.show();
+                                       g_csgtool_dialog.caulk = GTK_TOGGLE_BUTTON( button );
+                               }
+                               {
+                                       GtkWidget* button = gtk_toggle_button_new();
 -                                      gtk_table_attach( table, button, 7, 8, 0, 1,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_removeinner.png" );
+                                       gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE );
 -                                      gtk_widget_show( button );
++                                      table.attach( ubutton, { 7, 8, 0, 1 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Remove inner brush" );
+                                       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_shrink.png" );
 -                                      gtk_table_attach( table, button, 0, 1, 2, 3,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      ubutton.show();
+                                       g_csgtool_dialog.removeInner = GTK_TOGGLE_BUTTON( button );
+                               }
+                               {
+                                       GtkWidget* sep = gtk_hseparator_new();
+                                       gtk_widget_show( sep );
+                                       gtk_table_attach( table, sep, 0, 8, 1, 2,
+                                                                       (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
+                                                                       (GtkAttachOptions) ( 0 ), 0, 0 );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
 -                                      gtk_widget_show( button );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_shrink.png" );
++                                      table.attach( ubutton, { 0, 1, 2, 3 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Shrink brush" );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_expand.png" );
 -                                      gtk_table_attach( table, button, 1, 2, 2, 3,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      ubutton.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_BrushShrink ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
 -                                      gtk_widget_show( button );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_expand.png" );
++                                      table.attach( ubutton, { 1, 2, 2, 3 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Expand brush" );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_diagonal.png" );
 -                                      gtk_table_attach( table, button, 3, 4, 2, 3,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      ubutton.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_BrushExpand ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
 -                                      gtk_widget_show( button );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_diagonal.png" );
++                                      table.attach( ubutton, { 3, 4, 2, 3 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::diagonal joints" );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_wrap.png" );
 -                                      gtk_table_attach( table, button, 4, 5, 2, 3,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      ubutton.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowDiag ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
 -                                      gtk_widget_show( button );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_wrap.png" );
++                                      table.attach( ubutton, { 4, 5, 2, 3 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::warp" );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_extrude.png" );
 -                                      gtk_table_attach( table, button, 5, 6, 2, 3,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      ubutton.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowWrap ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
 -                                      gtk_widget_show( button );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_extrude.png" );
++                                      table.attach( ubutton, { 5, 6, 2, 3 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::extrude faces" );
 -                                      button_set_icon( GTK_BUTTON( button ), "csgtool_pull.png" );
 -                                      gtk_table_attach( table, button, 6, 7, 2, 3,
 -                                                                        (GtkAttachOptions) ( GTK_EXPAND ),
 -                                                                        (GtkAttachOptions) ( 0 ), 0, 0 );
++                                      ubutton.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowExtrude ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
 -                                      gtk_widget_show( button );
++                                      auto ubutton = ui::Button::from( button );
++                                      button_set_icon( ubutton, "csgtool_pull.png" );
++                                      table.attach( ubutton, { 6, 7, 2, 3 }, { GTK_EXPAND, 0 } );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::pull faces" );
++                                      ubutton.show();
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowPull ), &g_csgtool_dialog );
+                               }
+                       }
+               }
+       }
+       gtk_widget_show( GTK_WIDGET( g_csgtool_dialog.window ) );
+       gtk_window_present( g_csgtool_dialog.window );
+ }
diff --cc radiant/csg.h
index e05c9effbb4b65ab408e9be5637cd071c6d851cd,e176422ddeb3c330d905ed18d34b7936faa3fbe3..082f7f10ff711c102b9d3093e0a66dc25d9315ca
  #if !defined( INCLUDED_CSG_H )
  #define INCLUDED_CSG_H
  
- void CSG_MakeHollow( void );
 +
  void CSG_MakeRoom( void );
 +
  void CSG_Subtract( void );
 +
  void CSG_Merge( void );
 +
+ void CSG_Tool( void );
  namespace scene
  {
  class Graph;
index 25983e110569bae9339b7ec8a3f8e2a63694eb54,4c9fc6b32a9e2425279b8fcf88d5c8e13e4929bd..9c8784b55e5fe4e80512270dfbcb98461b89e114
@@@ -1971,13 -1822,13 +1971,13 @@@ ui::MenuItem create_file_menu()
  #endif
  
        create_menu_item_with_mnemonic( menu, "_Open...", "OpenMap" );
        create_menu_item_with_mnemonic( menu, "_Import...", "ImportMap" );
+       menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "_Save", "SaveMap" );
        create_menu_item_with_mnemonic( menu, "Save _as...", "SaveMapAs" );
 -      create_menu_item_with_mnemonic( menu, "Save s_elected...", "SaveSelected" );
 +      create_menu_item_with_mnemonic( menu, "_Export selected...", "ExportSelected" );
-       menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "Save re_gion...", "SaveRegion" );
+       menu_separator( menu );
  //    menu_separator( menu );
  //    create_menu_item_with_mnemonic( menu, "_Refresh models", "RefreshReferences" );
  //    menu_separator( menu );
@@@ -2442,9 -2300,10 +2449,10 @@@ void register_shortcuts()
        SelectNudge_registerShortcuts();
  //    SnapToGrid_registerShortcuts();
  //    SelectByType_registerShortcuts();
+       TexBro_registerShortcuts();
  }
  
 -void File_constructToolbar( GtkToolbar* toolbar ){
 +void File_constructToolbar( ui::Toolbar toolbar ){
        toolbar_append_button( toolbar, "Open an existing map (CTRL + O)", "file_open.png", "OpenMap" );
        toolbar_append_button( toolbar, "Save the active map (CTRL + S)", "file_save.png", "SaveMap" );
  }
@@@ -2468,14 -2327,14 +2476,14 @@@ void Select_constructToolbar( ui::Toolb
        toolbar_append_button( toolbar, "Select inside", "selection_selectinside.png", "SelectInside" );
  }
  
 -void CSG_constructToolbar( GtkToolbar* toolbar ){
 +void CSG_constructToolbar( ui::Toolbar toolbar ){
        toolbar_append_button( toolbar, "CSG Subtract (SHIFT + U)", "selection_csgsubtract.png", "CSGSubtract" );
        toolbar_append_button( toolbar, "CSG Merge (CTRL + U)", "selection_csgmerge.png", "CSGMerge" );
-       toolbar_append_button( toolbar, "Make Hollow", "selection_makehollow.png", "CSGHollow" );
 -      toolbar_append_button( toolbar, "Room", "selection_makeroom.png", "CSGroom" );
 +      toolbar_append_button( toolbar, "Make Room", "selection_makeroom.png", "CSGRoom" );
+       toolbar_append_button( toolbar, "CSG Tool", "ellipsis.png", "CSGTool" );
  }
  
 -void ComponentModes_constructToolbar( GtkToolbar* toolbar ){
 +void ComponentModes_constructToolbar( ui::Toolbar toolbar ){
        toolbar_append_toggle_button( toolbar, "Select Vertices (V)", "modify_vertices.png", "DragVertices" );
        toolbar_append_toggle_button( toolbar, "Select Edges (E)", "modify_edges.png", "DragEdges" );
        toolbar_append_toggle_button( toolbar, "Select Faces (F)", "modify_faces.png", "DragFaces" );
@@@ -3496,10 -3340,10 +3504,10 @@@ void MainFrame_Construct()
        GlobalCommands_insert( "ChooseOrthoViewNameColor", makeCallback( g_ColoursMenu.m_viewname ) );
  
  
 -      GlobalCommands_insert( "CSGSubtract", FreeCaller<CSG_Subtract>(), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) );
 -      GlobalCommands_insert( "CSGMerge", FreeCaller<CSG_Merge>(), Accelerator( 'U', (GdkModifierType)GDK_CONTROL_MASK ) );
 -      GlobalCommands_insert( "CSGroom", FreeCaller<CSG_MakeRoom>() );
 -      GlobalCommands_insert( "CSGTool", FreeCaller<CSG_Tool>() );
 +      GlobalCommands_insert( "CSGSubtract", makeCallbackF(CSG_Subtract), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) );
 +      GlobalCommands_insert( "CSGMerge", makeCallbackF(CSG_Merge), Accelerator( 'U', (GdkModifierType) GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "CSGHollow", makeCallbackF(CSG_MakeHollow) );
 +      GlobalCommands_insert( "CSGRoom", makeCallbackF(CSG_MakeRoom) );
++      GlobalCommands_insert( "CSGTool", makeCallbackF(CSG_Tool) );
  
        Grid_registerCommands();
  
Simple merge
Simple merge