From 322b0c2ee485a5d787c60bfd34e5ed5567d98ec8 Mon Sep 17 00:00:00 2001 From: Garux Date: Wed, 2 Aug 2017 09:09:20 +0300 Subject: [PATCH] Radiant: misc... * shader editor lives on top of main window * csg tool: 'active projection' exclusion method instead of axis selection * csg tool: new 'selected faces' & 'cam direction' exclusion methods * new active projection dependent commands MirrorSelectionHorizontally, MirrorSelectionVertically, RotateSelectionClockwise, RotateSelectionAnticlockwise + toolbar buttons --- radiant/csg.cpp | 149 +++++++++++++----- radiant/gtkdlgs.cpp | 7 +- radiant/mainframe.cpp | 34 ++-- radiant/select.cpp | 88 ++++++++++- radiant/select.h | 14 +- setup/data/tools/bitmaps/brush_flip_hor.png | Bin 0 -> 3208 bytes setup/data/tools/bitmaps/brush_flip_vert.png | Bin 0 -> 3221 bytes .../data/tools/bitmaps/brush_rotate_anti.png | Bin 0 -> 581 bytes .../data/tools/bitmaps/brush_rotate_clock.png | Bin 0 -> 592 bytes setup/data/tools/bitmaps/f-hide.png | Bin 337 -> 334 bytes setup/data/tools/bitmaps/f-region.png | Bin 365 -> 349 bytes 11 files changed, 219 insertions(+), 73 deletions(-) create mode 100644 setup/data/tools/bitmaps/brush_flip_hor.png create mode 100644 setup/data/tools/bitmaps/brush_flip_vert.png create mode 100644 setup/data/tools/bitmaps/brush_rotate_anti.png create mode 100644 setup/data/tools/bitmaps/brush_rotate_clock.png diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 5b9eb44a..603f6083 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -60,6 +60,7 @@ void Face_extrude( Face& face, const Brush& brush, brush_vector_t& out, float of #include "preferences.h" #include "texwindow.h" +typedef std::vector doublevector_vector_t; enum eHollowType { @@ -83,17 +84,28 @@ class CaulkFace DoubleVector3 ExclusionAxis; double &mindot; double &maxdot; +doublevector_vector_t &exclude_vec; public: CaulkFace( DoubleVector3 ExclusionAxis, double &mindot, - double &maxdot ): + double &maxdot, + doublevector_vector_t &exclude_vec ): ExclusionAxis( ExclusionAxis ), mindot( mindot ), - maxdot( maxdot ){} + maxdot( maxdot ), + exclude_vec( exclude_vec ){} 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 ) ) + if( dot == 0 || ( dot > mindot + 0.005 && dot < maxdot - 0.005 ) ){ + if( !exclude_vec.empty() ){ + for ( doublevector_vector_t::const_iterator i = exclude_vec.begin(); i != exclude_vec.end(); ++i ){ + if( ( *i ) == face.getPlane().plane3().normal() ){ + return; + } + } + } face.SetShader( getCaulkShader() ); + } } }; @@ -106,6 +118,7 @@ eHollowType HollowType; DoubleVector3 ExclusionAxis; double &mindot; double &maxdot; +doublevector_vector_t &exclude_vec; bool caulk; bool RemoveInner; public: @@ -116,6 +129,7 @@ FaceMakeBrush( const Brush& brush, DoubleVector3 ExclusionAxis, double &mindot, double &maxdot, + doublevector_vector_t &exclude_vec, bool caulk, bool RemoveInner ) : brush( brush ), @@ -125,12 +139,21 @@ FaceMakeBrush( const Brush& brush, ExclusionAxis( ExclusionAxis ), mindot( mindot ), maxdot( maxdot ), + exclude_vec( exclude_vec ), caulk( caulk ), RemoveInner( RemoveInner ){ } 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 ) ){ + if( !exclude_vec.empty() ){ + for ( doublevector_vector_t::const_iterator i = exclude_vec.begin(); i != exclude_vec.end(); ++i ){ + if( ( *i ) == face.getPlane().plane3().normal() ){ + return; + } + } + } + if( HollowType == pull ){ if ( face.contributes() ) { face.getPlane().offset( offset ); @@ -140,7 +163,7 @@ void operator()( Face& face ) const { face.planeChanged(); if( caulk ){ - Brush_forEachFace( *out.back(), CaulkFace( ExclusionAxis, mindot, maxdot ) ); + Brush_forEachFace( *out.back(), CaulkFace( ExclusionAxis, mindot, maxdot, exclude_vec ) ); } Face* newFace = out.back()->addFace( face ); if ( newFace != 0 ) { @@ -272,13 +295,21 @@ float offset; DoubleVector3 ExclusionAxis; double &mindot; double &maxdot; +doublevector_vector_t &exclude_vec; public: -FaceOffset( float offset, DoubleVector3 ExclusionAxis, double &mindot, double &maxdot ) - : offset( offset ), ExclusionAxis( ExclusionAxis ), mindot( mindot ), maxdot( maxdot ){ +FaceOffset( float offset, DoubleVector3 ExclusionAxis, double &mindot, double &maxdot, doublevector_vector_t &exclude_vec ) + : offset( offset ), ExclusionAxis( ExclusionAxis ), mindot( mindot ), maxdot( maxdot ), exclude_vec( exclude_vec ){ } 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 ) ){ + if( !exclude_vec.empty() ){ + for ( doublevector_vector_t::const_iterator i = exclude_vec.begin(); i != exclude_vec.end(); ++i ){ + if( ( *i ) == face.getPlane().plane3().normal() ){ + return; + } + } + } face.undoSave(); face.getPlane().offset( offset ); face.planeChanged(); @@ -286,6 +317,19 @@ void operator()( Face& face ) const { } }; +class FaceExcludeSelected +{ +doublevector_vector_t &outvec; +public: +FaceExcludeSelected( doublevector_vector_t &outvec ): outvec( outvec ){ +} +void operator()( FaceInstance& face ) const { + if( face.isSelected() ){ + outvec.push_back( face.getFace().getPlane().plane3().normal() ); + } +} +}; + DoubleVector3 getExclusion(); bool getCaulk(); @@ -306,38 +350,42 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { && Instance_getSelectable( instance )->isSelected() && path.size() > 1 ) { brush_vector_t out; + doublevector_vector_t exclude_vec; double mindot = 0; double maxdot = 0; if( HollowType != room ){ Brush_forEachFace( *brush, FaceExclude( getExclusion(), mindot, maxdot ) ); + if( mindot == 0 && maxdot == 0 ){ + Brush_ForEachFaceInstance( *Instance_getBrush( instance ), FaceExcludeSelected( exclude_vec ) ); + } } 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 ) ); + Brush_forEachFace( *brush, FaceMakeBrush( *brush, out, offset, pull, DoubleVector3( 0, 0, 0 ), mindot, maxdot, exclude_vec, true, true ) ); delete tmpbrush; } else if( HollowType == pull ){ if( !getRemoveInner() && getCaulk() ){ - Brush_forEachFace( *brush, CaulkFace( getExclusion(), mindot, maxdot ) ); + Brush_forEachFace( *brush, CaulkFace( getExclusion(), mindot, maxdot, exclude_vec ) ); } Brush* tmpbrush = new Brush( *brush ); tmpbrush->removeEmptyFaces(); - Brush_forEachFace( *tmpbrush, FaceMakeBrush( *tmpbrush, out, offset, HollowType, getExclusion(), mindot, maxdot, getCaulk(), getRemoveInner() ) ); + Brush_forEachFace( *tmpbrush, FaceMakeBrush( *tmpbrush, out, offset, HollowType, getExclusion(), mindot, maxdot, exclude_vec, getCaulk(), getRemoveInner() ) ); delete tmpbrush; } else if( HollowType == diag ){ Brush* tmpbrush = new Brush( *brush ); - Brush_forEachFace( *tmpbrush, FaceOffset( offset, getExclusion(), mindot, maxdot ) ); + Brush_forEachFace( *tmpbrush, FaceOffset( offset, getExclusion(), mindot, maxdot, exclude_vec ) ); tmpbrush->removeEmptyFaces(); - Brush_forEachFace( *tmpbrush, FaceMakeBrush( *brush, out, offset, HollowType, getExclusion(), mindot, maxdot, getCaulk(), getRemoveInner() ) ); + Brush_forEachFace( *tmpbrush, FaceMakeBrush( *brush, out, offset, HollowType, getExclusion(), mindot, maxdot, exclude_vec, getCaulk(), getRemoveInner() ) ); delete tmpbrush; if( !getRemoveInner() && getCaulk() ){ - Brush_forEachFace( *brush, CaulkFace( getExclusion(), mindot, maxdot ) ); + Brush_forEachFace( *brush, CaulkFace( getExclusion(), mindot, maxdot, exclude_vec ) ); } } else{ - Brush_forEachFace( *brush, FaceMakeBrush( *brush, out, offset, HollowType, getExclusion(), mindot, maxdot, getCaulk(), getRemoveInner() ) ); + Brush_forEachFace( *brush, FaceMakeBrush( *brush, out, offset, HollowType, getExclusion(), mindot, maxdot, exclude_vec, getCaulk(), getRemoveInner() ) ); } for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i ) { @@ -953,25 +1001,44 @@ void CSG_Merge( void ){ #include "gtkutil/dialog.h" #include "gtkutil/button.h" #include "gtkutil/accelerator.h" +#include "xywindow.h" +#include "camwindow.h" struct CSGToolDialog { GtkSpinButton* spin; GtkWindow *window; - GtkToggleButton *radXYZ, *radX, *radY, *radZ, *caulk, *removeInner; + GtkToggleButton *radFaces, *radProj, *radCam, *caulk, *removeInner; }; CSGToolDialog g_csgtool_dialog; DoubleVector3 getExclusion(){ - if( gtk_toggle_button_get_active( g_csgtool_dialog.radX ) ){ - return DoubleVector3( 1, 0, 0 ); + if( gtk_toggle_button_get_active( g_csgtool_dialog.radProj ) ){ + if( GlobalXYWnd_getCurrentViewType() == YZ ){ + return DoubleVector3( 1, 0, 0 ); + } + else if( GlobalXYWnd_getCurrentViewType() == XZ ){ + return DoubleVector3( 0, 1, 0 ); + } + else if( GlobalXYWnd_getCurrentViewType() == XY ){ + return DoubleVector3( 0, 0, 1 ); + } } - 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 ); + if( gtk_toggle_button_get_active( g_csgtool_dialog.radCam ) ){ + Vector3 angles( Camera_getAngles( *g_pParentWnd->GetCamWnd() ) ); +// globalOutputStream() << angles << " angles\n"; + DoubleVector3 radangles( degrees_to_radians( angles[0] ), degrees_to_radians( angles[1] ), degrees_to_radians( angles[2] ) ); +// globalOutputStream() << radangles << " radangles\n"; +// x = cos(yaw)*cos(pitch) +// y = sin(yaw)*cos(pitch) +// z = sin(pitch) + DoubleVector3 viewvector; + viewvector[0] = cos( radangles[1] ) * cos( radangles[0] ); + viewvector[1] = sin( radangles[1] ) * cos( radangles[0] ); + viewvector[2] = sin( radangles[0] ); +// globalOutputStream() << viewvector << " viewvector\n"; + return viewvector; } return DoubleVector3( 0, 0, 0 ); } @@ -1000,8 +1067,12 @@ BrushFaceOffset( float offset ) void operator()( BrushInstance& brush ) const { double mindot = 0; double maxdot = 0; + doublevector_vector_t exclude_vec; Brush_forEachFace( brush, FaceExclude( getExclusion(), mindot, maxdot ) ); - Brush_forEachFace( brush, FaceOffset( offset, getExclusion(), mindot, maxdot ) ); + if( mindot == 0 && maxdot == 0 ){ + Brush_ForEachFaceInstance( brush, FaceExcludeSelected( exclude_vec ) ); + } + Brush_forEachFace( brush, FaceOffset( offset, getExclusion(), mindot, maxdot, exclude_vec ) ); } }; @@ -1120,32 +1191,30 @@ void CSG_Tool(){ } { //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 ); + GtkWidget* radFaces = gtk_radio_button_new_with_label( NULL, "-faces" ); + gtk_widget_set_tooltip_text( radFaces, "Exclude selected faces" ); + GtkWidget* radProj = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radFaces), "-proj" ); + gtk_widget_set_tooltip_text( radProj, "Exclude faces, most orthogonal to active projection" ); + GtkWidget* radCam = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radFaces), "-cam" ); + gtk_widget_set_tooltip_text( radCam, "Exclude faces, most orthogonal to camera view" ); - gtk_table_attach( table, radXYZ, 2, 3, 0, 1, + gtk_widget_show( radFaces ); + gtk_widget_show( radProj ); + gtk_widget_show( radCam ); + + gtk_table_attach( table, radFaces, 2, 3, 0, 1, (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ), (GtkAttachOptions) ( 0 ), 0, 0 ); - gtk_table_attach( table, radX, 3, 4, 0, 1, + gtk_table_attach( table, radProj, 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, + gtk_table_attach( table, radCam, 4, 5, 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 ); + g_csgtool_dialog.radFaces = GTK_TOGGLE_BUTTON( radFaces ); + g_csgtool_dialog.radProj = GTK_TOGGLE_BUTTON( radProj ); + g_csgtool_dialog.radCam = GTK_TOGGLE_BUTTON( radCam ); } { GtkWidget* button = gtk_toggle_button_new(); diff --git a/radiant/gtkdlgs.cpp b/radiant/gtkdlgs.cpp index e7e60891..d4473b40 100644 --- a/radiant/gtkdlgs.cpp +++ b/radiant/gtkdlgs.cpp @@ -794,11 +794,8 @@ static void CreateGtkTextEditor(){ GtkWidget *dlg; GtkWidget *vbox, *hbox, *button, *scr, *text; - dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - - g_signal_connect( G_OBJECT( dlg ), "delete_event", - G_CALLBACK( editor_delete ), 0 ); - gtk_window_set_default_size( GTK_WINDOW( dlg ), 400, 600 ); + GtkWindow* dlg_wnd = create_dialog_window( MainFrame_getWindow(), "", G_CALLBACK( editor_delete ), 0, 400, 600 ); + dlg = GTK_WIDGET( dlg_wnd ); vbox = gtk_vbox_new( FALSE, 5 ); gtk_widget_show( vbox ); diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 233a9133..5442a8e5 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -2068,6 +2068,9 @@ GtkMenuItem* create_selection_menu(){ create_menu_item_with_mnemonic( menu_in_menu, "Rotate X", "RotateSelectionX" ); create_menu_item_with_mnemonic( menu_in_menu, "Rotate Y", "RotateSelectionY" ); create_menu_item_with_mnemonic( menu_in_menu, "Rotate Z", "RotateSelectionZ" ); + menu_separator( menu_in_menu ); + create_menu_item_with_mnemonic( menu_in_menu, "Rotate Clockwise", "RotateSelectionClockwise" ); + create_menu_item_with_mnemonic( menu_in_menu, "Rotate Anticlockwise", "RotateSelectionAnticlockwise" ); } { GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic( menu, "Flip" ); @@ -2077,6 +2080,9 @@ GtkMenuItem* create_selection_menu(){ create_menu_item_with_mnemonic( menu_in_menu, "Flip _X", "MirrorSelectionX" ); create_menu_item_with_mnemonic( menu_in_menu, "Flip _Y", "MirrorSelectionY" ); create_menu_item_with_mnemonic( menu_in_menu, "Flip _Z", "MirrorSelectionZ" ); + menu_separator( menu_in_menu ); + create_menu_item_with_mnemonic( menu_in_menu, "Flip Horizontally", "MirrorSelectionHorizontally" ); + create_menu_item_with_mnemonic( menu_in_menu, "Flip Vertically", "MirrorSelectionVertically" ); } menu_separator( menu ); create_menu_item_with_mnemonic( menu, "Arbitrary rotation...", "ArbitraryRotation" ); @@ -2322,12 +2328,17 @@ void UndoRedo_constructToolbar( GtkToolbar* toolbar ){ } void RotateFlip_constructToolbar( GtkToolbar* toolbar ){ - toolbar_append_button( toolbar, "x-axis Flip", "brush_flipx.png", "MirrorSelectionX" ); - toolbar_append_button( toolbar, "x-axis Rotate", "brush_rotatex.png", "RotateSelectionX" ); - toolbar_append_button( toolbar, "y-axis Flip", "brush_flipy.png", "MirrorSelectionY" ); - toolbar_append_button( toolbar, "y-axis Rotate", "brush_rotatey.png", "RotateSelectionY" ); - toolbar_append_button( toolbar, "z-axis Flip", "brush_flipz.png", "MirrorSelectionZ" ); - toolbar_append_button( toolbar, "z-axis Rotate", "brush_rotatez.png", "RotateSelectionZ" ); +// toolbar_append_button( toolbar, "x-axis Flip", "brush_flipx.png", "MirrorSelectionX" ); +// toolbar_append_button( toolbar, "x-axis Rotate", "brush_rotatex.png", "RotateSelectionX" ); +// toolbar_append_button( toolbar, "y-axis Flip", "brush_flipy.png", "MirrorSelectionY" ); +// toolbar_append_button( toolbar, "y-axis Rotate", "brush_rotatey.png", "RotateSelectionY" ); +// toolbar_append_button( toolbar, "z-axis Flip", "brush_flipz.png", "MirrorSelectionZ" ); +// toolbar_append_button( toolbar, "z-axis Rotate", "brush_rotatez.png", "RotateSelectionZ" ); + toolbar_append_button( toolbar, "Flip Horizontally", "brush_flip_hor.png", "MirrorSelectionHorizontally" ); + toolbar_append_button( toolbar, "Flip Vertically", "brush_flip_vert.png", "MirrorSelectionVertically" ); + + toolbar_append_button( toolbar, "Rotate Clockwise", "brush_rotate_clock.png", "RotateSelectionClockwise" ); + toolbar_append_button( toolbar, "Rotate Anticlockwise", "brush_rotate_anti.png", "RotateSelectionAnticlockwise" ); } void Select_constructToolbar( GtkToolbar* toolbar ){ @@ -2393,7 +2404,7 @@ GtkToolbar* create_main_toolbar( MainFrame::EViewStyle style ){ ComponentModes_constructToolbar( toolbar ); gtk_toolbar_append_space( toolbar ); - if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft ) { + if ( style != MainFrame::eSplit ) { XYWnd_constructToolbar( toolbar ); gtk_toolbar_append_space( toolbar ); } @@ -3384,19 +3395,12 @@ void MainFrame_Construct(){ // GlobalCommands_insert( "ShowHidden", FreeCaller(), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) ); // GlobalCommands_insert( "HideSelected", FreeCaller(), Accelerator( 'H' ) ); - Hide_registerCommands(); + Select_registerCommands(); GlobalToggles_insert( "DragVertices", FreeCaller(), ToggleItem::AddCallbackCaller( g_vertexMode_button ), Accelerator( 'V' ) ); GlobalToggles_insert( "DragEdges", FreeCaller(), ToggleItem::AddCallbackCaller( g_edgeMode_button ), Accelerator( 'E' ) ); GlobalToggles_insert( "DragFaces", FreeCaller(), ToggleItem::AddCallbackCaller( g_faceMode_button ), Accelerator( 'F' ) ); - GlobalCommands_insert( "MirrorSelectionX", FreeCaller() ); - GlobalCommands_insert( "RotateSelectionX", FreeCaller() ); - GlobalCommands_insert( "MirrorSelectionY", FreeCaller() ); - GlobalCommands_insert( "RotateSelectionY", FreeCaller() ); - GlobalCommands_insert( "MirrorSelectionZ", FreeCaller() ); - GlobalCommands_insert( "RotateSelectionZ", FreeCaller() ); - GlobalCommands_insert( "ArbitraryRotation", FreeCaller(), Accelerator( 'R', (GdkModifierType)GDK_SHIFT_MASK ) ); GlobalCommands_insert( "ArbitraryScale", FreeCaller(), Accelerator( 'S', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); diff --git a/radiant/select.cpp b/radiant/select.cpp index 178b84a1..beac6a18 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -778,12 +778,6 @@ void Select_ShowAllHidden(){ g_hidden_item.update(); } -void Hide_registerCommands(){ - GlobalCommands_insert( "ShowHidden", FreeCaller(), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) ); - GlobalToggles_insert( "HideSelected", FreeCaller(), ToggleItem::AddCallbackCaller( g_hidden_item ), Accelerator( 'H' ) ); -} - - void Selection_Flipx(){ UndoableCommand undo( "mirrorSelected -axis x" ); @@ -814,7 +808,89 @@ void Selection_Rotatez(){ UndoableCommand undo( "rotateSelected -axis z -angle -90" ); Select_RotateAxis( 2,-90 ); } +#include "xywindow.h" +void Selection_FlipHorizontally(){ + VIEWTYPE viewtype = GlobalXYWnd_getCurrentViewType(); + switch ( viewtype ) + { + case XY: + case XZ: + Selection_Flipx(); + break; + default: + Selection_Flipy(); + break; + } +} +void Selection_FlipVertically(){ + VIEWTYPE viewtype = GlobalXYWnd_getCurrentViewType(); + switch ( viewtype ) + { + case XZ: + case YZ: + Selection_Flipz(); + break; + default: + Selection_Flipy(); + break; + } +} + +void Selection_RotateClockwise(){ + UndoableCommand undo( "rotateSelected Clockwise 90" ); + VIEWTYPE viewtype = GlobalXYWnd_getCurrentViewType(); + switch ( viewtype ) + { + case XY: + Select_RotateAxis( 2, -90 ); + break; + case XZ: + Select_RotateAxis( 1, 90 ); + break; + default: + Select_RotateAxis( 0, -90 ); + break; + } +} + +void Selection_RotateAnticlockwise(){ + UndoableCommand undo( "rotateSelected Anticlockwise 90" ); + VIEWTYPE viewtype = GlobalXYWnd_getCurrentViewType(); + switch ( viewtype ) + { + case XY: + Select_RotateAxis( 2, 90 ); + break; + case XZ: + Select_RotateAxis( 1, -90 ); + break; + default: + Select_RotateAxis( 0, 90 ); + break; + } + +} + + + +void Select_registerCommands(){ + GlobalCommands_insert( "ShowHidden", FreeCaller(), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalToggles_insert( "HideSelected", FreeCaller(), ToggleItem::AddCallbackCaller( g_hidden_item ), Accelerator( 'H' ) ); + + GlobalCommands_insert( "MirrorSelectionX", FreeCaller() ); + GlobalCommands_insert( "RotateSelectionX", FreeCaller() ); + GlobalCommands_insert( "MirrorSelectionY", FreeCaller() ); + GlobalCommands_insert( "RotateSelectionY", FreeCaller() ); + GlobalCommands_insert( "MirrorSelectionZ", FreeCaller() ); + GlobalCommands_insert( "RotateSelectionZ", FreeCaller() ); + + GlobalCommands_insert( "MirrorSelectionHorizontally", FreeCaller() ); + GlobalCommands_insert( "MirrorSelectionVertically", FreeCaller() ); + + GlobalCommands_insert( "RotateSelectionClockwise", FreeCaller() ); + GlobalCommands_insert( "RotateSelectionAnticlockwise", FreeCaller() ); +} void Nudge( int nDim, float fNudge ){ diff --git a/radiant/select.h b/radiant/select.h index 2a4a2289..5a602742 100644 --- a/radiant/select.h +++ b/radiant/select.h @@ -33,12 +33,12 @@ void Select_Inside(); void Select_Touching(); void Scene_ExpandSelectionToEntities(); -void Selection_Flipx(); -void Selection_Flipy(); -void Selection_Flipz(); -void Selection_Rotatex(); -void Selection_Rotatey(); -void Selection_Rotatez(); +//void Selection_Flipx(); +//void Selection_Flipy(); +//void Selection_Flipz(); +//void Selection_Rotatex(); +//void Selection_Rotatey(); +//void Selection_Rotatez(); void Selection_MoveDown(); @@ -66,7 +66,7 @@ void FindReplaceTextures( const char* pFind, const char* pReplace, bool bSelecte void HideSelected(); void Select_ShowAllHidden(); -void Hide_registerCommands(); +void Select_registerCommands(); // updating workzone to a given brush (depends on current view) diff --git a/setup/data/tools/bitmaps/brush_flip_hor.png b/setup/data/tools/bitmaps/brush_flip_hor.png new file mode 100644 index 0000000000000000000000000000000000000000..5d16a6f3a5028c51492b06474ed40b983f82311e GIT binary patch literal 3208 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 N!PC{xWt~$(69ChB94!C< literal 0 HcmV?d00001 diff --git a/setup/data/tools/bitmaps/brush_rotate_anti.png b/setup/data/tools/bitmaps/brush_rotate_anti.png new file mode 100644 index 0000000000000000000000000000000000000000..48976209498fce2b7c0c708c339be0ec6e98a7d6 GIT binary patch literal 581 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7SkfJR9T^zbpD<_bdda}R zAXVZTQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L0m@TF)W0|VnVPZ!4!3;(&3eLX?~ zMUJ2Uf9Ll-3oE6L!vZ%J3FcgNGT+8=i&JoI%(k3|Zi{*ywZ#|ixX^mR$))K+udumVq`6MOsi0-Ah%gaQnnXi?YR+>%YZ7^E!$+W^D;s zvghE8TYlNrLW=eFf_g=@M<3qZ<D+(ZO)8?Gk^NzN$@2-n``H)#&QIyDj#7Qwe(X zZ%@06-r5bG)sA}|%%{#;e{g&4e=SCS|Js7^!uGYii{x!Knay&a^Yx@WgB*Lq`2z;F zH~Q+WRVN=fV#oMiRCmfIrITUxepx9}Gyb_9V7Xw$@uisk*lgSA5QF|5N@b^KSfu|q zVd!D-)I0x?-EYzL&w64kIt-iLmD(qFnLBd6o-o<8uF^i9@5$^V`roV*`VN=aXE+M` zPtS1s8h7wTqcd-SDYMF@J3rsEytxqOddc=$oQ3#;%c+vIU^W5czM zc=7LlpE{o3m6&`-VuBxob$-JW9mRN!_?dqt1@xKD2{>JA{H$XCOIhq}@y3q*UoYIc zrhP2NLNzF6b=0lYGe+Dq(@7p{VHu@dV*&rlnIeYWMojh-^P21GuAI|)aJj>GfeU*)4{#V9 zdT=P9LGS$PA1A~g1pJj_5MpdFzF2;9#wjn?o1GJq9PTp(d-KFJF8LSd_^~QHrTtf@ zFk|E49k14&F<|w*v%J9mPIZEj$b!qaKDkbOBGtSjRPUs$Bzw}<13Lp69-OsjKHuyZ z#d_`5j+lkBXPmr{?-T0u@xi25m9Ko<{GgPQF zEU0cUo5^fyUV2~QHroz05I^_Y-RvqptJx+KdELJzF>@q1=w7g8HaH-baEd{{rsS?QYpD4Fp5LqX*1oE4DEYvW;KLAlSIuz2Lcs_9^X6__S1zAY Ybzsx6zu6xc7#J8lUHx3vIVCg!03Xg_QUCw| delta 220 zcmX@dbdhO71lKDD2DVp>^U7-0O-$0P-{|S$7-HeSbdoJ!i-LgLb>W=!%$;wyUAuOp zn$drQ`v(Cz@%lp#gzcQnX89!jcwo54=keZp+h2SQQ;XN#J>4EPL-xN`fBWG!xdu;$ zO*X7P3}2WgJk?BKTp-+_XD)WFj!m_pDXSrnQDX($53K`T zW$w|60ncg<-Df(l$;a%{7%1>YyqK9Mqh8>xaX-_|gFFY^8M=0sIyk=XIuKnq+r_kY c>sH=l>Uy19wrPD}U|?YIboFyt=akR{05)1(wEzGB diff --git a/setup/data/tools/bitmaps/f-region.png b/setup/data/tools/bitmaps/f-region.png index d15bebc4e15557af0b40a7fc79c9027ab408b9ec..a16c7acbd8a711eb1782b04a4abab8aa18253fcc 100644 GIT binary patch delta 232 zcmaFMbeCyD1lLOj2DX=s#^+-XPfXIR-|Ok(7-HeSbn0%GJ&^G`wy$1*<58ds z>#^xfFP@wUZER(c+SqP<+n99|gCOVk*;g6E9n`s|?{2=jrg=L<;NDFv^B9x_4Gkj| zn}Xlm<=K*?y*Ys~MNe>!sfUb(wSMFAq01PYT>C6d^U7-0O-$0PKkMn@7-HeSbn-^QW&;9zm`#XW&Tu#mC5Z#Hzw||xGTdM!@6VQ z4drB^48|wTd))bFXD?y8|1pv+PEedDko7`gU_t1FJIB^DTO3STJl{#FXSPpBf5+zf zc>&BR3PBH