]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Radiant:
authorGarux <garux@mail.ru>
Tue, 1 Aug 2017 11:26:18 +0000 (14:26 +0300)
committerGarux <garux@mail.ru>
Tue, 1 Aug 2017 11:26:18 +0000 (14:26 +0300)
misc...
* CSG Tool
* fix: texbro: blured stipple with green and red borders

13 files changed:
radiant/brushmanip.cpp
radiant/csg.cpp
radiant/csg.h
radiant/mainframe.cpp
radiant/patchmanip.cpp
radiant/texwindow.cpp
setup/data/tools/bitmaps/csgtool_diagonal.png [new file with mode: 0644]
setup/data/tools/bitmaps/csgtool_expand.png [new file with mode: 0644]
setup/data/tools/bitmaps/csgtool_extrude.png [new file with mode: 0644]
setup/data/tools/bitmaps/csgtool_pull.png [new file with mode: 0644]
setup/data/tools/bitmaps/csgtool_removeinner.png [new file with mode: 0644]
setup/data/tools/bitmaps/csgtool_shrink.png [new file with mode: 0644]
setup/data/tools/bitmaps/csgtool_wrap.png [new file with mode: 0644]

index 090ab4cf832b2eb5c5ed6321721122761af8e1a7..36ed6a9b13cf01dfc9ba3c1afaeeca0b3fa014c0 100644 (file)
@@ -1390,9 +1390,10 @@ void Brush_constructMenu( GtkMenu* menu ){
                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, "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, "CSG _Tool", "CSGTool" );
        }
        menu_separator( menu );
        {
index 68349f240ec910697f6f450310fbc98c57062ecf..1b0d6004e622366d14852a53e312386afff429b3 100644 (file)
@@ -29,7 +29,7 @@
 #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 ) );
@@ -56,39 +56,248 @@ void Face_extrude( Face& face, const Brush& brush, brush_vector_t& out, float of
                }
        }
 }
+*/
+#include "preferences.h"
+#include "texwindow.h"
+
+
+enum eHollowType
+{
+       diag = 0,
+       wrap = 1,
+       extrude = 2,
+       pull = 3,
+       room = 4,
+};
 
+const char* getCaulkShader(){
+       const char* gotShader = g_pGameDescription->getKeyValue( "shader_caulk" );
+       if ( gotShader && *gotShader ){
+               return gotShader;
+       }
+       return "textures/common/caulk";
+}
+
+class CaulkFace
+{
+DoubleVector3 ExclusionAxis;
+double &mindot;
+double &maxdot;
+public:
+CaulkFace( DoubleVector3 ExclusionAxis,
+                       double &mindot,
+                       double &maxdot ):
+                       ExclusionAxis( ExclusionAxis ),
+                       mindot( mindot ),
+                       maxdot( maxdot ){}
+void operator()( Face& face ) const {
+       double dot = vector3_dot( face.getPlane().plane3().normal(), ExclusionAxis );
+       if( dot == 0 || ( dot > mindot + 0.005 && dot < maxdot - 0.005 ) )
+               face.SetShader( getCaulkShader() );
+}
+};
 
 class FaceMakeBrush
 {
 const Brush& brush;
 brush_vector_t& out;
 float offset;
-bool room;
+eHollowType HollowType;
+DoubleVector3 ExclusionAxis;
+double &mindot;
+double &maxdot;
+bool caulk;
+bool RemoveInner;
 public:
-FaceMakeBrush( const Brush& brush, brush_vector_t& out, float offset, bool room )
-       : brush( brush ), out( out ), offset( offset ), room( room ){
+FaceMakeBrush( const Brush& brush,
+                       brush_vector_t& out,
+                       float offset,
+                       eHollowType HollowType,
+                       DoubleVector3 ExclusionAxis,
+                       double &mindot,
+                       double &maxdot,
+                       bool caulk,
+                       bool RemoveInner )
+       : brush( brush ),
+       out( out ),
+       offset( offset ),
+       HollowType( HollowType ),
+       ExclusionAxis( ExclusionAxis ),
+       mindot( mindot ),
+       maxdot( maxdot ),
+       caulk( caulk ),
+       RemoveInner( RemoveInner ){
 }
 void operator()( Face& face ) const {
-       if( room ){
-               Face_extrude( face, brush, out, offset );
+       double dot = vector3_dot( face.getPlane().plane3().normal(), ExclusionAxis );
+       if( dot == 0 || ( dot > mindot + 0.005 && dot < maxdot - 0.005 ) ){
+               if( HollowType == pull ){
+                       if ( face.contributes() ) {
+                               face.getPlane().offset( offset );
+                               face.planeChanged();
+                               out.push_back( new Brush( brush ) );
+                               face.getPlane().offset( -offset );
+                               face.planeChanged();
+
+                               if( caulk ){
+                                       Brush_forEachFace( *out.back(), CaulkFace( ExclusionAxis, mindot, maxdot ) );
+                               }
+                               Face* newFace = out.back()->addFace( face );
+                               if ( newFace != 0 ) {
+                                       newFace->flipWinding();
+                               }
+                       }
+               }
+               else if( HollowType == wrap ){
+                       //Face_makeBrush( face, brush, out, offset );
+                       if ( face.contributes() ) {
+                               face.undoSave();
+                               out.push_back( new Brush( brush ) );
+                               if( !RemoveInner && caulk )
+                                       face.SetShader( getCaulkShader() );
+                               Face* newFace = out.back()->addFace( face );
+                               face.getPlane().offset( -offset );
+                               face.planeChanged();
+                               if( caulk )
+                                       face.SetShader( getCaulkShader() );
+                               if ( newFace != 0 ) {
+                                       newFace->flipWinding();
+                                       newFace->getPlane().offset( offset );
+                                       newFace->planeChanged();
+                               }
+                       }
+               }
+               else if( HollowType == extrude ){
+                       if ( face.contributes() ) {
+                               //face.undoSave();
+                               out.push_back( new Brush( brush ) );
+                               out.back()->clear();
+
+                               Face* newFace = out.back()->addFace( face );
+                               if ( newFace != 0 ) {
+                                       newFace->getPlane().offset( offset );
+                                       newFace->planeChanged();
+                               }
+
+                               if( !RemoveInner && caulk )
+                                       face.SetShader( getCaulkShader() );
+                               newFace = out.back()->addFace( face );
+                               if ( newFace != 0 ) {
+                                       newFace->flipWinding();
+                               }
+                               Winding& winding = face.getWinding();
+                               TextureProjection projection;
+                               TexDef_Construct_Default( projection );
+                               for ( Winding::iterator j = winding.begin(); j != winding.end(); ++j ){
+                                       std::size_t index = std::distance( winding.begin(), j );
+                                       std::size_t next = Winding_next( winding, index );
+
+                                       out.back()->addPlane( winding[index].vertex, winding[next].vertex, winding[next].vertex + face.getPlane().plane3().normal() * offset, TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), projection );
+                               }
+                       }
+               }
+               else if( HollowType == diag ){
+                       if ( face.contributes() ) {
+                               out.push_back( new Brush( brush ) );
+                               out.back()->clear();
+
+                               Face* newFace = out.back()->addFace( face );
+                               if ( newFace != 0 ) {
+
+                                       newFace->planeChanged();
+                               }
+                               newFace = out.back()->addFace( face );
+
+                               if ( newFace != 0 ) {
+                                       if( !RemoveInner && caulk )
+                                               newFace->SetShader( getCaulkShader() );
+                                       newFace->flipWinding();
+                                       newFace->getPlane().offset( offset );
+                                       newFace->planeChanged();
+                               }
+
+                               Winding& winding = face.getWinding();
+                               TextureProjection projection;
+                               TexDef_Construct_Default( projection );
+                               for ( Winding::iterator i = winding.begin(); i != winding.end(); ++i ){
+                                       std::size_t index = std::distance( winding.begin(), i );
+                                       std::size_t next = Winding_next( winding, index );
+                                       Vector3 BestPoint;
+                                       float bestdist = 999999;
+
+                                       for( Brush::const_iterator j = brush.begin(); j != brush.end(); ++j ){
+                                               Winding& winding2 = ( *j )->getWinding();
+                                               for ( Winding::iterator k = winding2.begin(); k != winding2.end(); ++k ){
+                                                       std::size_t index2 = std::distance( winding2.begin(), k );
+                                                       float testdist = vector3_length( winding[index].vertex - winding2[index2].vertex );
+                                                       if( testdist < bestdist ){
+                                                               bestdist = testdist;
+                                                               BestPoint = winding2[index2].vertex;
+                                                       }
+                                               }
+                                       }
+                                       out.back()->addPlane( winding[next].vertex, winding[index].vertex, BestPoint, caulk? getCaulkShader() : TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), projection );
+                               }
+                       }
+               }
        }
-       else{
-               Face_makeBrush( face, brush, out, offset );
+}
+};
+
+class FaceExclude
+{
+DoubleVector3 ExclusionAxis;
+double &mindot;
+double &maxdot;
+public:
+FaceExclude( DoubleVector3 ExclusionAxis, double &mindot, double &maxdot )
+       : ExclusionAxis( ExclusionAxis ), mindot( mindot ), maxdot( maxdot ){
+}
+void operator()( Face& face ) const {
+       if( vector3_length_squared( ExclusionAxis ) != 0 ){
+               double dot = vector3_dot( face.getPlane().plane3().normal(), ExclusionAxis );
+               if( dot < mindot ){
+                       mindot = dot;
+               }
+               else if( dot > maxdot ){
+                       maxdot = dot;
+               }
        }
 }
 };
 
-void Brush_makeHollow( const Brush& brush, brush_vector_t& out, float offset, bool room ){
-       Brush_forEachFace( brush, FaceMakeBrush( brush, out, offset, room ) );
+class FaceOffset
+{
+float offset;
+DoubleVector3 ExclusionAxis;
+double &mindot;
+double &maxdot;
+public:
+FaceOffset( float offset, DoubleVector3 ExclusionAxis, double &mindot, double &maxdot )
+       : offset( offset ), ExclusionAxis( ExclusionAxis ), mindot( mindot ), maxdot( maxdot ){
+}
+void operator()( Face& face ) const {
+       double dot = vector3_dot( face.getPlane().plane3().normal(), ExclusionAxis );
+       if( dot == 0 || ( dot > mindot + 0.005 && dot < maxdot - 0.005 ) ){
+               face.undoSave();
+               face.getPlane().offset( offset );
+               face.planeChanged();
+       }
 }
+};
+
+
+DoubleVector3 getExclusion();
+bool getCaulk();
+bool getRemoveInner();
 
 class BrushHollowSelectedWalker : public scene::Graph::Walker
 {
-float m_offset;
-bool room;
+float offset;
+eHollowType HollowType;
 public:
-BrushHollowSelectedWalker( float offset, bool room )
-       : m_offset( offset ), room( room ){
+BrushHollowSelectedWalker( float offset, eHollowType HollowType )
+       : offset( offset ), HollowType( HollowType ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        if ( path.top().get().visible() ) {
@@ -97,14 +306,52 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                         && Instance_getSelectable( instance )->isSelected()
                         && path.size() > 1 ) {
                        brush_vector_t out;
-                       Brush_makeHollow( *brush, out, m_offset, room );
+                       double mindot = 0;
+                       double maxdot = 0;
+                       if( HollowType != room ){
+                               Brush_forEachFace( *brush, FaceExclude( getExclusion(), mindot, maxdot ) );
+                       }
+                       if( HollowType == room ){
+                               Brush* tmpbrush = new Brush( *brush );
+                               tmpbrush->removeEmptyFaces();
+                               Brush_forEachFace( *brush, FaceMakeBrush( *brush, out, offset, pull, DoubleVector3( 0, 0, 0 ), mindot, maxdot, true, true ) );
+                               delete tmpbrush;
+                       }
+                       else if( HollowType == pull ){
+                               if( !getRemoveInner() && getCaulk() ){
+                                       Brush_forEachFace( *brush, CaulkFace( getExclusion(), mindot, maxdot ) );
+                               }
+                               Brush* tmpbrush = new Brush( *brush );
+                               tmpbrush->removeEmptyFaces();
+                               Brush_forEachFace( *tmpbrush, FaceMakeBrush( *tmpbrush, out, offset, HollowType, getExclusion(), mindot, maxdot, getCaulk(), getRemoveInner() ) );
+                               delete tmpbrush;
+                       }
+                       else if( HollowType == diag ){
+                               Brush* tmpbrush = new Brush( *brush );
+                               Brush_forEachFace( *tmpbrush, FaceOffset( offset, getExclusion(), mindot, maxdot ) );
+                               tmpbrush->removeEmptyFaces();
+                               Brush_forEachFace( *tmpbrush, FaceMakeBrush( *brush, out, offset, HollowType, getExclusion(), mindot, maxdot, getCaulk(), getRemoveInner() ) );
+                               delete tmpbrush;
+                               if( !getRemoveInner() && getCaulk() ){
+                                       Brush_forEachFace( *brush, CaulkFace( getExclusion(), mindot, maxdot ) );
+                               }
+                       }
+                       else{
+                               Brush_forEachFace( *brush, FaceMakeBrush( *brush, out, offset, HollowType, getExclusion(), mindot, maxdot, getCaulk(), getRemoveInner() ) );
+                       }
                        for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i )
                        {
                                ( *i )->removeEmptyFaces();
-                               NodeSmartReference node( ( new BrushNode() )->node() );
-                               Node_getBrush( node )->copy( *( *i ) );
-                               delete ( *i );
-                               Node_getTraversable( path.parent() )->insert( node );
+                               if( ( *i )->hasContributingFaces() ){
+                                       NodeSmartReference node( ( new BrushNode() )->node() );
+                                       Node_getBrush( node )->copy( *( *i ) );
+                                       delete ( *i );
+                                       Node_getTraversable( path.parent() )->insert( node );
+                                       //path.push( makeReference( node.get() ) );
+                                       //selectPath( path, true );
+                                       //Instance_getSelectable( *GlobalSceneGraph().find( path ) )->setSelected( true );
+                                       //Path_deleteTop( path );
+                               }
                        }
                }
        }
@@ -151,30 +398,16 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
 }
 };
 
-void Scene_BrushMakeHollow_Selected( scene::Graph& graph, bool room ){
-       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( GetGridSize(), room ) );
-       GlobalSceneGraph().traverse( BrushDeleteSelected() );
-}
 
 /*
    =============
-   CSG_MakeHollow
+   CSG_MakeRoom
    =============
  */
-
-void CSG_MakeHollow( void ){
-       UndoableCommand undo( "brushHollow" );
-
-       Scene_BrushMakeHollow_Selected( GlobalSceneGraph(), false );
-
-       SceneChangeNotify();
-}
-
 void CSG_MakeRoom( void ){
        UndoableCommand undo( "makeRoom" );
-
-       Scene_BrushMakeHollow_Selected( GlobalSceneGraph(), true );
-
+       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( GetGridSize(), room ) );
+       GlobalSceneGraph().traverse( BrushDeleteSelected() );
        SceneChangeNotify();
 }
 
@@ -647,3 +880,313 @@ void CSG_Merge( void ){
                SceneChangeNotify();
        }
 }
+
+
+
+
+
+
+/*
+   =============
+   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;
+       GtkWindow *window;
+       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(){
+       if ( g_csgtool_dialog.window == NULL ) {
+               g_csgtool_dialog.window = create_dialog_window( MainFrame_getWindow(), "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 );
+
+               {
+                       GtkHBox* hbox = create_dialog_hbox( 4, 4 );
+                       gtk_container_add( GTK_CONTAINER( g_csgtool_dialog.window ), GTK_WIDGET( hbox ) );
+                       {
+                               GtkTable* 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 );
+                                       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 );
+                                       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();
+                                       button_set_icon( GTK_BUTTON( button ), "f-caulk.png" );
+                                       gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE );
+                                       gtk_table_attach( table, button, 6, 7, 0, 1,
+                                                                         (GtkAttachOptions) ( GTK_EXPAND ),
+                                                                         (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       gtk_widget_set_tooltip_text( button, "Caulk some faces" );
+                                       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
+                                       gtk_widget_show( button );
+                                       g_csgtool_dialog.caulk = GTK_TOGGLE_BUTTON( button );
+                               }
+                               {
+                                       GtkWidget* button = gtk_toggle_button_new();
+                                       button_set_icon( GTK_BUTTON( button ), "csgtool_removeinner.png" );
+                                       gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE );
+                                       gtk_table_attach( table, button, 7, 8, 0, 1,
+                                                                         (GtkAttachOptions) ( GTK_EXPAND ),
+                                                                         (GtkAttachOptions) ( 0 ), 0, 0 );
+                                       gtk_widget_set_tooltip_text( button, "Remove inner brush" );
+                                       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
+                                       gtk_widget_show( button );
+                                       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();
+                                       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 );
+                                       gtk_widget_set_tooltip_text( button, "Shrink brush" );
+                                       gtk_widget_show( button );
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_BrushShrink ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
+                                       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 );
+                                       gtk_widget_set_tooltip_text( button, "Expand brush" );
+                                       gtk_widget_show( button );
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_BrushExpand ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
+                                       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 );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::diagonal joints" );
+                                       gtk_widget_show( button );
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowDiag ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
+                                       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 );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::warp" );
+                                       gtk_widget_show( button );
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowWrap ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
+                                       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 );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::extrude faces" );
+                                       gtk_widget_show( button );
+                                       g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( CSGdlg_HollowExtrude ), &g_csgtool_dialog );
+                               }
+                               {
+                                       GtkWidget* button = gtk_button_new();
+                                       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 );
+                                       gtk_widget_set_tooltip_text( button, "Hollow::pull faces" );
+                                       gtk_widget_show( button );
+                                       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 );
+}
+
index 68e907c048216359a8c7ea134aeb909b5e1f8a84..e176422ddeb3c330d905ed18d34b7936faa3fbe3 100644 (file)
 #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
 {
index c801ccd937ec294ae4c20b81fb390f4e543237bb..4c9fc6b32a9e2425279b8fcf88d5c8e13e4929bd 100644 (file)
@@ -1822,18 +1822,18 @@ GtkMenuItem* 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" );
-       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 );
        create_menu_item_with_mnemonic( menu, "Pro_ject settings...", "ProjectSettings" );
-       menu_separator( menu );
+       //menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "_Pointfile...", "TogglePointfile" );
        menu_separator( menu );
        MRU_constructMenu( menu );
@@ -2281,9 +2281,16 @@ void SurfaceInspector_registerShortcuts(){
 }
 
 
+void TexBro_registerShortcuts(){
+       command_connect_accelerator( "FindReplaceTextures" );
+       command_connect_accelerator( "RefreshShaders" );
+       //refresh models
+       command_connect_accelerator( "RefreshReferences" );
+}
+
 void register_shortcuts(){
 //     PatchInspector_registerShortcuts();
-       Patch_registerShortcuts();
+       //Patch_registerShortcuts();
        Grid_registerShortcuts();
 //     XYWnd_registerShortcuts();
        CamWnd_registerShortcuts();
@@ -2293,6 +2300,7 @@ void register_shortcuts(){
        SelectNudge_registerShortcuts();
 //     SnapToGrid_registerShortcuts();
 //     SelectByType_registerShortcuts();
+       TexBro_registerShortcuts();
 }
 
 void File_constructToolbar( GtkToolbar* toolbar ){
@@ -2322,8 +2330,8 @@ void Select_constructToolbar( GtkToolbar* toolbar ){
 void CSG_constructToolbar( GtkToolbar* 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, "Hollow", "selection_makehollow.png", "CSGHollow" );
        toolbar_append_button( toolbar, "Room", "selection_makeroom.png", "CSGroom" );
+       toolbar_append_button( toolbar, "CSG Tool", "ellipsis.png", "CSGTool" );
 }
 
 void ComponentModes_constructToolbar( GtkToolbar* toolbar ){
@@ -3334,8 +3342,8 @@ void MainFrame_Construct(){
 
        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( "CSGHollow", FreeCaller<CSG_MakeHollow>() );
        GlobalCommands_insert( "CSGroom", FreeCaller<CSG_MakeRoom>() );
+       GlobalCommands_insert( "CSGTool", FreeCaller<CSG_Tool>() );
 
        Grid_registerCommands();
 
index 7ca446c1f3aeb4ee870daab125b28670bf8714e1..4a7e72abed0c1b365f5958207e383f11f35a459b 100644 (file)
@@ -199,27 +199,27 @@ void Scene_PatchDeform( scene::Graph& graph, const int deform )
 void Patch_thicken( Patch& patch, scene::Instance& instance, const float thickness, bool seams, const int axis ){
 
                // Create a new patch node
-               NodeSmartReference node(g_patchCreator->createPatch());
+               NodeSmartReference node( g_patchCreator->createPatch() );
                // Insert the node into worldspawn
-               Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(node);
+               Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( node );
 
                // Retrieve the contained patch from the node
-               Patch* targetPatch = Node_getPatch(node);
+               Patch* targetPatch = Node_getPatch( node );
 
                // Create the opposite patch with the given thickness = distance
                bool no12 = true;
                bool no34 = true;
-               targetPatch->createThickenedOpposite(patch, thickness, axis, no12, no34);
+               targetPatch->createThickenedOpposite( patch, thickness, axis, no12, no34 );
 
                // Now select the newly created patches
                {
-                       scene::Path patchpath(makeReference(GlobalSceneGraph().root()));
-                       patchpath.push(makeReference(*Map_GetWorldspawn(g_map)));
-                       patchpath.push(makeReference(node.get()));
-                       Instance_getSelectable(*GlobalSceneGraph().find(patchpath))->setSelected(true);
+                       scene::Path patchpath( makeReference( GlobalSceneGraph().root() ) );
+                       patchpath.push( makeReference( *Map_GetWorldspawn( g_map ) ) );
+                       patchpath.push( makeReference( node.get() ) );
+                       Instance_getSelectable( *GlobalSceneGraph().find( patchpath ) )->setSelected( true );
                }
 
-               if (seams && thickness != 0.0f) {
+               if( seams && thickness != 0.0f){
                        int i = 0;
                        if ( no12 ){
                                i = 2;
@@ -229,31 +229,31 @@ void Patch_thicken( Patch& patch, scene::Instance& instance, const float thickne
                                iend = 2;
                        }
                        // Now create the four walls
-                       for ( ; i < iend; i++ ) {
+                       for ( ; i < iend; i++ ){
                                // Allocate new patch
-                               NodeSmartReference node = NodeSmartReference(g_patchCreator->createPatch());
+                               NodeSmartReference node = NodeSmartReference( g_patchCreator->createPatch() );
                                // Insert each node into worldspawn
-                               Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(node);
+                               Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( node );
 
                                // Retrieve the contained patch from the node
-                               Patch* wallPatch = Node_getPatch(node);
+                               Patch* wallPatch = Node_getPatch( node );
 
                                // Create the wall patch by passing i as wallIndex
-                               wallPatch->createThickenedWall( patch, *targetPatch, i);
+                               wallPatch->createThickenedWall( patch, *targetPatch, i );
 
                                if( ( wallPatch->localAABB().extents[0] <= 0.00005 && wallPatch->localAABB().extents[1] <= 0.00005 ) ||
                                        ( wallPatch->localAABB().extents[1] <= 0.00005 && wallPatch->localAABB().extents[2] <= 0.00005 ) ||
                                        ( wallPatch->localAABB().extents[0] <= 0.00005 && wallPatch->localAABB().extents[2] <= 0.00005 ) ){
                                        //globalOutputStream() << "Thicken: Discarding degenerate patch.\n";
-                                       Node_getTraversable( Map_FindOrInsertWorldspawn(g_map) )->erase( node );
+                                       Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->erase( node );
                                }
                                else
                                // Now select the newly created patches
                                {
-                                       scene::Path patchpath(makeReference(GlobalSceneGraph().root()));
-                                       patchpath.push(makeReference(*Map_GetWorldspawn(g_map)));
-                                       patchpath.push(makeReference(node.get()));
-                                       Instance_getSelectable(*GlobalSceneGraph().find(patchpath))->setSelected(true);
+                                       scene::Path patchpath( makeReference( GlobalSceneGraph().root() ) );
+                                       patchpath.push( makeReference( *Map_GetWorldspawn(g_map) ) );
+                                       patchpath.push( makeReference( node.get() ) );
+                                       Instance_getSelectable( *GlobalSceneGraph().find( patchpath ) )->setSelected( true );
                                }
                        }
                }
index afdba8111c61a50da39f79cc87858570775ccd14..ea928af8d91576b5283a42d2c7e6432340da5c4a 100644 (file)
@@ -1166,12 +1166,14 @@ void Texture_Draw( TextureBrowser& textureBrowser ){
                                glVertex2f( xfMax ,yfMin );
                                glVertex2f( xfMax ,yfMax );
                                glEnd();
+                               glEnable( GL_TEXTURE_2D );
                        }
 
                        // shader stipple:
                        if ( !shader->IsDefault() ) {
                                glEnable( GL_LINE_STIPPLE );
                                glLineStipple( 1, 0xF000 );
+                               glDisable( GL_TEXTURE_2D );
                                glBegin( GL_LINE_LOOP );
                                glColor3f( 0, 0, 0 );
                                glVertex2f( xfMin ,yfMax );
diff --git a/setup/data/tools/bitmaps/csgtool_diagonal.png b/setup/data/tools/bitmaps/csgtool_diagonal.png
new file mode 100644 (file)
index 0000000..6216152
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_diagonal.png differ
diff --git a/setup/data/tools/bitmaps/csgtool_expand.png b/setup/data/tools/bitmaps/csgtool_expand.png
new file mode 100644 (file)
index 0000000..ee29803
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_expand.png differ
diff --git a/setup/data/tools/bitmaps/csgtool_extrude.png b/setup/data/tools/bitmaps/csgtool_extrude.png
new file mode 100644 (file)
index 0000000..680338d
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_extrude.png differ
diff --git a/setup/data/tools/bitmaps/csgtool_pull.png b/setup/data/tools/bitmaps/csgtool_pull.png
new file mode 100644 (file)
index 0000000..cabdd67
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_pull.png differ
diff --git a/setup/data/tools/bitmaps/csgtool_removeinner.png b/setup/data/tools/bitmaps/csgtool_removeinner.png
new file mode 100644 (file)
index 0000000..5161b47
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_removeinner.png differ
diff --git a/setup/data/tools/bitmaps/csgtool_shrink.png b/setup/data/tools/bitmaps/csgtool_shrink.png
new file mode 100644 (file)
index 0000000..2cb2458
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_shrink.png differ
diff --git a/setup/data/tools/bitmaps/csgtool_wrap.png b/setup/data/tools/bitmaps/csgtool_wrap.png
new file mode 100644 (file)
index 0000000..569b8bc
Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_wrap.png differ