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 | 151 +++++++++++++----- 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, 220 insertions(+), 74 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 ); - } - else if( gtk_toggle_button_get_active( g_csgtool_dialog.radY ) ){ - return DoubleVector3( 0, 1, 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.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 ); - - 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, + 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_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, radY, 4, 5, 0, 1, + gtk_table_attach( table, radProj, 3, 4, 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 zcmV;340rR1P)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 Hu0mjf(|H^% 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 zcmV-L0=oT)P)LN~Su+6fV@T()fCMxu>DD;J@-(1p-KM1s(b zBN|DXh$z&cXa#DN7C}0GEc}Qx5hiqQ|3?`K^I=^$Jh=D#f9LZ-avz0AX@k-DH7C_! z5pNe*A9QYUA(J_vER$18VOhIs<1DcBN#tZ%#4XZZ)20-A1J-mkc{Y{}fHI)+IWV-z z2wx~zp}hstN#O7mkeM>ZjeFJ&`F^S+jcT-1q`bkH z+D>ab5+Q#-5iW9l#o^t*0baY}!B+~m82zQ{eP&~`r0LaLd%e3jy!Iqg;{LpcL@uqc zNqa%PKsS||ufex{|0)3wPknG#afhu9q8~i6HkwDA^~oOq9tVKWz%V`7j(uoEoOM_}}SMrm%UUP&t2o*8rbywQIGW=5FA TJGd=900000NkvXXu0mjfmPPkB literal 0 HcmV?d00001 diff --git a/setup/data/tools/bitmaps/brush_rotate_clock.png b/setup/data/tools/bitmaps/brush_rotate_clock.png new file mode 100644 index 0000000000000000000000000000000000000000..7c6b0ba278c7c44910d27bbd2d219c9ae572337a GIT binary patch literal 592 zcmV-W0eMteM;Y1yhbX_%0lH?|l5ux#yk(`G2%V_4HMsy2QDP zJ&|7t$Xq;?UT`8m>6Sj=oBesivt>Qjv<)lPr$yWh`qLq(yNz z%a4Hj*L=U8O3l?IOWO?4u};7&uo4kDo3o+04DHsIvWo3(LT)OqAL&I1BIbeK0MG+G zqQ4&^=AR31A(0P?ds_s&0*3fs5DIYHvw56_!KXm?5YW6yzz8tH;KERVF3+p@$QR&H z{T=`k0e~~nciEWAN=4a;kYYgJ0#i#2T!EziUP1ACS7e9!i4y^V!?^0L%rFH_+^29q z+Uru+M*jzIh?&Gvx&fd70000sc$jaK8 zy?Zav6L5eG9HPf<`BIHuZHFi-QiS0<&!11urIgcOmjGCot$u&k>NNEQotstP0C*&T zpnHHenFBR9b>AS{2Dm1GpnHIA*4=A*4mz7Okqt-nVgm?ZKrPTc12DiAV9Ee5e1iT& zx6dHe+0-4Nh8TbW?g7C?RX4y4`>MTt>U)56@C0B?09D;4F`%Il;E$f2wyt*{WO~4| T#{FyX00000NkvXXu0mjfAI@P? delta 220 zcmV<203-j-0?`7HSPJR@00!y-o_2h$kzy%-u}MThR5(wil06QDAP`2^6KrQ`x$U;r z*4TRiPq0Vu5FQtQ!r&7=LN=OAV))=OyiDW0e?9sRfR%Hu-OGnsm>vHrkB7sC9)L*z zvOEP$0Q3ToO7S?_SC4hozfKdS`s0R2dz>0Q9 zTOm;9e8S%X&nXTAM1fHd>=$zb3}}B4?K6)8*})9JM*xbsbwEMyiojcbn?yBzwY3e# WCoYM!wkq%d0000Z;vG=;X{*frSJbv4=C;GX=5$5efI3)d5#PCkmIlgVn5qw*XPSvIL$0A`vk$Ss{W` z?A;8sVk@&?0c0)_oHa-sI7=lAO%MmCOo?aex%!L{%)W47jr_Fu;WJ i70f?bVo^u=^Z5YUvc}i>u#UI@0000Gy+_?bRU;59VzLe74dUDPki||S*J!zGbwNh=8{d;qK zq2kyO5OEdp0`oF0VAnzl>n(@hsCjBxH#P$30wuZk=P?+ z5@-SBgS)Q`0aVjg;DtQe60000