From: Garux Date: Tue, 1 Aug 2017 11:26:18 +0000 (+0300) Subject: Radiant: X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=7ca59bef0ae15880f51b2f68104b933e918d543c;p=xonotic%2Fnetradiant.git Radiant: misc... * CSG Tool * fix: texbro: blured stipple with green and red borders --- diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index 090ab4cf..36ed6a9b 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -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 ); { diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 68349f24..1b0d6004 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -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 +#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( 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( 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( 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( 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( 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( 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 ); +} + diff --git a/radiant/csg.h b/radiant/csg.h index 68e907c0..e176422d 100644 --- a/radiant/csg.h +++ b/radiant/csg.h @@ -22,10 +22,10 @@ #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 { diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index c801ccd9..4c9fc6b3 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -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(), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) ); GlobalCommands_insert( "CSGMerge", FreeCaller(), Accelerator( 'U', (GdkModifierType)GDK_CONTROL_MASK ) ); - GlobalCommands_insert( "CSGHollow", FreeCaller() ); GlobalCommands_insert( "CSGroom", FreeCaller() ); + GlobalCommands_insert( "CSGTool", FreeCaller() ); Grid_registerCommands(); diff --git a/radiant/patchmanip.cpp b/radiant/patchmanip.cpp index 7ca446c1..4a7e72ab 100644 --- a/radiant/patchmanip.cpp +++ b/radiant/patchmanip.cpp @@ -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 ); } } } diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index afdba811..ea928af8 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -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 index 00000000..6216152a 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 index 00000000..ee29803c 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 index 00000000..680338d3 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 index 00000000..cabdd676 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 index 00000000..5161b479 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 index 00000000..2cb24580 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 index 00000000..569b8bc5 Binary files /dev/null and b/setup/data/tools/bitmaps/csgtool_wrap.png differ