]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/brushmanip.cpp
plugins: unify About window wording
[xonotic/netradiant.git] / radiant / brushmanip.cpp
index c49464bed1e438537e6a29dcc7bd89b20b7f8bd3..fc3054e1516d6e308656587e729fadb3b523143f 100644 (file)
@@ -36,6 +36,7 @@
 #include "preferences.h"
 
 #include <list>
+#include <gdk/gdkkeysyms.h>
 
 void Brush_ConstructCuboid( Brush& brush, const AABB& bounds, const char* shader, const TextureProjection& projection ){
        const unsigned char box[3][2] = { { 0, 1 }, { 2, 0 }, { 1, 2 } };
@@ -404,146 +405,96 @@ void ConstructRegionBrushes( scene::Node* brushes[6], const Vector3& region_mins
 }
 
 
-class FaceSetTexdef
-{
-const TextureProjection& m_projection;
-public:
-FaceSetTexdef( const TextureProjection& projection ) : m_projection( projection ){
-}
-void operator()( Face& face ) const {
-       face.SetTexdef( m_projection );
-}
-};
-
 void Scene_BrushSetTexdef_Selected( scene::Graph& graph, const TextureProjection& projection ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceSetTexdef( projection ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.SetTexdef(projection);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const TextureProjection& projection ){
-       Scene_ForEachSelectedBrushFace( graph, FaceSetTexdef( projection ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.SetTexdef(projection);
+       });
        SceneChangeNotify();
 }
 
 
-class FaceSetFlags
-{
-const ContentsFlagsValue& m_projection;
-public:
-FaceSetFlags( const ContentsFlagsValue& flags ) : m_projection( flags ){
-}
-void operator()( Face& face ) const {
-       face.SetFlags( m_projection );
-}
-};
-
 void Scene_BrushSetFlags_Selected( scene::Graph& graph, const ContentsFlagsValue& flags ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceSetFlags( flags ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.SetFlags(flags);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushSetFlags_Component_Selected( scene::Graph& graph, const ContentsFlagsValue& flags ){
-       Scene_ForEachSelectedBrushFace( graph, FaceSetFlags( flags ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.SetFlags(flags);
+       });
        SceneChangeNotify();
 }
 
-class FaceShiftTexdef
-{
-float m_s, m_t;
-public:
-FaceShiftTexdef( float s, float t ) : m_s( s ), m_t( t ){
-}
-void operator()( Face& face ) const {
-       face.ShiftTexdef( m_s, m_t );
-}
-};
-
 void Scene_BrushShiftTexdef_Selected( scene::Graph& graph, float s, float t ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceShiftTexdef( s, t ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.ShiftTexdef(s, t);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushShiftTexdef_Component_Selected( scene::Graph& graph, float s, float t ){
-       Scene_ForEachSelectedBrushFace( graph, FaceShiftTexdef( s, t ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.ShiftTexdef(s, t);
+       });
        SceneChangeNotify();
 }
 
-class FaceScaleTexdef
-{
-float m_s, m_t;
-public:
-FaceScaleTexdef( float s, float t ) : m_s( s ), m_t( t ){
-}
-void operator()( Face& face ) const {
-       face.ScaleTexdef( m_s, m_t );
-}
-};
-
 void Scene_BrushScaleTexdef_Selected( scene::Graph& graph, float s, float t ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceScaleTexdef( s, t ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.ScaleTexdef(s, t);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushScaleTexdef_Component_Selected( scene::Graph& graph, float s, float t ){
-       Scene_ForEachSelectedBrushFace( graph, FaceScaleTexdef( s, t ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.ScaleTexdef(s, t);
+       });
        SceneChangeNotify();
 }
 
-class FaceRotateTexdef
-{
-float m_angle;
-public:
-FaceRotateTexdef( float angle ) : m_angle( angle ){
-}
-void operator()( Face& face ) const {
-       face.RotateTexdef( m_angle );
-}
-};
-
 void Scene_BrushRotateTexdef_Selected( scene::Graph& graph, float angle ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceRotateTexdef( angle ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.RotateTexdef(angle);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushRotateTexdef_Component_Selected( scene::Graph& graph, float angle ){
-       Scene_ForEachSelectedBrushFace( graph, FaceRotateTexdef( angle ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.RotateTexdef(angle);
+       });
        SceneChangeNotify();
 }
 
 
-class FaceSetShader
-{
-const char* m_name;
-public:
-FaceSetShader( const char* name ) : m_name( name ) {}
-void operator()( Face& face ) const {
-       face.SetShader( m_name );
-}
-};
-
 void Scene_BrushSetShader_Selected( scene::Graph& graph, const char* name ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceSetShader( name ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.SetShader(name);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushSetShader_Component_Selected( scene::Graph& graph, const char* name ){
-       Scene_ForEachSelectedBrushFace( graph, FaceSetShader( name ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.SetShader(name);
+       });
        SceneChangeNotify();
 }
 
-class FaceSetDetail
-{
-bool m_detail;
-public:
-FaceSetDetail( bool detail ) : m_detail( detail ){
-}
-void operator()( Face& face ) const {
-       face.setDetail( m_detail );
-}
-};
-
 void Scene_BrushSetDetail_Selected( scene::Graph& graph, bool detail ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceSetDetail( detail ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.setDetail(detail);
+       });
        SceneChangeNotify();
 }
 
@@ -555,55 +506,37 @@ bool Face_FindReplaceShader( Face& face, const char* find, const char* replace )
        return false;
 }
 
-class FaceFindReplaceShader
-{
-const char* m_find;
-const char* m_replace;
-public:
-FaceFindReplaceShader( const char* find, const char* replace ) : m_find( find ), m_replace( replace ){
-}
-void operator()( Face& face ) const {
-       Face_FindReplaceShader( face, m_find, m_replace );
-}
-};
-
-class FaceFindShader
-{
-const char* m_find;
-const char* m_replace;
-public:
-FaceFindShader( const char* find ) : m_find( find ){
-}
-void operator()( FaceInstance& faceinst ) const {
-       if ( shader_equal( faceinst.getFace().GetShader(), m_find ) ) {
-               faceinst.setSelected( SelectionSystem::eFace, true );
-       }
-}
-};
-
 bool DoingSearch( const char *repl ){
        return ( repl == NULL || ( strcmp( "textures/", repl ) == 0 ) );
 }
 
 void Scene_BrushFindReplaceShader( scene::Graph& graph, const char* find, const char* replace ){
        if ( DoingSearch( replace ) ) {
-               Scene_ForEachBrush_ForEachFaceInstance( graph, FaceFindShader( find ) );
+               Scene_ForEachBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) {
+                       if (shader_equal(faceinst.getFace().GetShader(), find)) {
+                               faceinst.setSelected(SelectionSystem::eFace, true);
+                       }
+               });
        }
        else
        {
-               Scene_ForEachBrush_ForEachFace( graph, FaceFindReplaceShader( find, replace ) );
+               Scene_ForEachBrush_ForEachFace(graph, [&](Face &face) { Face_FindReplaceShader(face, find, replace); });
        }
 }
 
 void Scene_BrushFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace ){
        if ( DoingSearch( replace ) ) {
-               Scene_ForEachSelectedBrush_ForEachFaceInstance( graph,
-                                                                                                               FaceFindShader( find ) );
+               Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) {
+                       if (shader_equal(faceinst.getFace().GetShader(), find)) {
+                               faceinst.setSelected(SelectionSystem::eFace, true);
+                       }
+               });
        }
        else
        {
-               Scene_ForEachSelectedBrush_ForEachFace( graph,
-                                                                                               FaceFindReplaceShader( find, replace ) );
+               Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+                       Face_FindReplaceShader(face, find, replace);
+               });
        }
 }
 
@@ -615,33 +548,29 @@ void Scene_BrushFindReplaceShader_Component_Selected( scene::Graph& graph, const
        }
        else
        {
-               Scene_ForEachSelectedBrushFace( graph, FaceFindReplaceShader( find, replace ) );
+               Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+                       Face_FindReplaceShader(face, find, replace);
+               });
        }
 }
 
 
-class FaceFitTexture
-{
-float m_s_repeat, m_t_repeat;
-public:
-FaceFitTexture( float s_repeat, float t_repeat ) : m_s_repeat( s_repeat ), m_t_repeat( t_repeat ){
-}
-void operator()( Face& face ) const {
-       face.FitTexture( m_s_repeat, m_t_repeat );
-}
-};
-
 void Scene_BrushFitTexture_Selected( scene::Graph& graph, float s_repeat, float t_repeat ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceFitTexture( s_repeat, t_repeat ) );
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               face.FitTexture(s_repeat, t_repeat);
+       });
        SceneChangeNotify();
 }
 
 void Scene_BrushFitTexture_Component_Selected( scene::Graph& graph, float s_repeat, float t_repeat ){
-       Scene_ForEachSelectedBrushFace( graph, FaceFitTexture( s_repeat, t_repeat ) );
+       Scene_ForEachSelectedBrushFace(graph, [&](Face &face) {
+               face.FitTexture(s_repeat, t_repeat);
+       });
        SceneChangeNotify();
 }
 
 TextureProjection g_defaultTextureProjection;
+
 const TextureProjection& TextureTransform_getDefault(){
        TexDef_Construct_Default( g_defaultTextureProjection );
        return g_defaultTextureProjection;
@@ -689,6 +618,7 @@ public:
 BrushSelectByShaderWalker( const char* name )
        : m_name( name ){
 }
+
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        if ( path.top().get().visible() ) {
                Brush* brush = Node_getBrush( path.top() );
@@ -704,44 +634,23 @@ void Scene_BrushSelectByShader( scene::Graph& graph, const char* name ){
        graph.traverse( BrushSelectByShaderWalker( name ) );
 }
 
-class FaceSelectByShader
-{
-const char* m_name;
-public:
-FaceSelectByShader( const char* name )
-       : m_name( name ){
-}
-void operator()( FaceInstance& face ) const {
-       printf( "checking %s = %s\n", face.getFace().GetShader(), m_name );
-       if ( shader_equal( face.getFace().GetShader(), m_name ) ) {
-               face.setSelected( SelectionSystem::eFace, true );
-       }
-}
-};
-
 void Scene_BrushSelectByShader_Component( scene::Graph& graph, const char* name ){
-       Scene_ForEachSelectedBrush_ForEachFaceInstance( graph, FaceSelectByShader( name ) );
-}
-
-class FaceGetTexdef
-{
-TextureProjection& m_projection;
-mutable bool m_done;
-public:
-FaceGetTexdef( TextureProjection& projection )
-       : m_projection( projection ), m_done( false ){
-}
-void operator()( Face& face ) const {
-       if ( !m_done ) {
-               m_done = true;
-               face.GetTexdef( m_projection );
-       }
+       Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &face) {
+               printf("checking %s = %s\n", face.getFace().GetShader(), name);
+               if (shader_equal(face.getFace().GetShader(), name)) {
+                       face.setSelected(SelectionSystem::eFace, true);
+               }
+       });
 }
-};
-
 
 void Scene_BrushGetTexdef_Selected( scene::Graph& graph, TextureProjection& projection ){
-       Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetTexdef( projection ) );
+       bool done = false;
+       Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) {
+               if (!done) {
+                       done = true;
+                       face.GetTexdef(projection);
+               }
+       });
 }
 
 void Scene_BrushGetTexdef_Component_Selected( scene::Graph& graph, TextureProjection& projection ){
@@ -765,29 +674,18 @@ void Scene_BrushGetShaderSize_Component_Selected( scene::Graph& graph, size_t& w
 }
 
 
-class FaceGetFlags
-{
-ContentsFlagsValue& m_flags;
-mutable bool m_done;
-public:
-FaceGetFlags( ContentsFlagsValue& flags )
-       : m_flags( flags ), m_done( false ){
-}
-void operator()( Face& face ) const {
-       if ( !m_done ) {
-               m_done = true;
-               face.GetFlags( m_flags );
-       }
-}
-};
-
-
 void Scene_BrushGetFlags_Selected( scene::Graph& graph, ContentsFlagsValue& flags ){
 #if 1
        if ( GlobalSelectionSystem().countSelected() != 0 ) {
                BrushInstance* brush = Instance_getBrush( GlobalSelectionSystem().ultimateSelected() );
                if ( brush != 0 ) {
-                       Brush_forEachFace( *brush, FaceGetFlags( flags ) );
+                       bool done = false;
+                       Brush_forEachFace(*brush, [&](Face &face) {
+                               if (!done) {
+                                       done = true;
+                                       face.GetFlags(flags);
+                               }
+                       });
                }
        }
 #else
@@ -807,28 +705,18 @@ void Scene_BrushGetFlags_Component_Selected( scene::Graph& graph, ContentsFlagsV
 }
 
 
-class FaceGetShader
-{
-CopiedString& m_shader;
-mutable bool m_done;
-public:
-FaceGetShader( CopiedString& shader )
-       : m_shader( shader ), m_done( false ){
-}
-void operator()( Face& face ) const {
-       if ( !m_done ) {
-               m_done = true;
-               m_shader = face.GetShader();
-       }
-}
-};
-
 void Scene_BrushGetShader_Selected( scene::Graph& graph, CopiedString& shader ){
 #if 1
        if ( GlobalSelectionSystem().countSelected() != 0 ) {
                BrushInstance* brush = Instance_getBrush( GlobalSelectionSystem().ultimateSelected() );
                if ( brush != 0 ) {
-                       Brush_forEachFace( *brush, FaceGetShader( shader ) );
+                       bool done = false;
+                       Brush_forEachFace(*brush, [&](Face &face) {
+                               if (!done) {
+                                       done = true;
+                                       shader = face.GetShader();
+                               }
+                       });
                }
        }
 #else
@@ -855,6 +743,7 @@ const char* m_shader;
 public:
 filter_face_shader( const char* shader ) : m_shader( shader ){
 }
+
 bool filter( const Face& face ) const {
        return shader_equal( face.GetShader(), m_shader );
 }
@@ -866,6 +755,7 @@ const char* m_prefix;
 public:
 filter_face_shader_prefix( const char* prefix ) : m_prefix( prefix ){
 }
+
 bool filter( const Face& face ) const {
        return shader_equal_n( face.GetShader(), m_prefix, strlen( m_prefix ) );
 }
@@ -877,6 +767,7 @@ int m_flags;
 public:
 filter_face_flags( int flags ) : m_flags( flags ){
 }
+
 bool filter( const Face& face ) const {
        return ( face.getShader().shaderFlags() & m_flags ) != 0;
 }
@@ -888,6 +779,7 @@ int m_contents;
 public:
 filter_face_contents( int contents ) : m_contents( contents ){
 }
+
 bool filter( const Face& face ) const {
        return ( face.getShader().m_flags.m_contentFlags & m_contents ) != 0;
 }
@@ -895,49 +787,24 @@ bool filter( const Face& face ) const {
 
 
 
-class FaceFilterAny
-{
-FaceFilter* m_filter;
-bool& m_filtered;
-public:
-FaceFilterAny( FaceFilter* filter, bool& filtered ) : m_filter( filter ), m_filtered( filtered ){
-       m_filtered = false;
-}
-void operator()( Face& face ) const {
-       if ( m_filter->filter( face ) ) {
-               m_filtered = true;
-       }
-}
-};
-
 class filter_brush_any_face : public BrushFilter
 {
 FaceFilter* m_filter;
 public:
 filter_brush_any_face( FaceFilter* filter ) : m_filter( filter ){
 }
+
 bool filter( const Brush& brush ) const {
-       bool filtered;
-       Brush_forEachFace( brush, FaceFilterAny( m_filter, filtered ) );
+       bool filtered = false;
+       Brush_forEachFace(brush, [&](Face &face) {
+               if (m_filter->filter(face)) {
+                       filtered = true;
+               }
+       });
        return filtered;
 }
 };
 
-class FaceFilterAll
-{
-FaceFilter* m_filter;
-bool& m_filtered;
-public:
-FaceFilterAll( FaceFilter* filter, bool& filtered ) : m_filter( filter ), m_filtered( filtered ){
-       m_filtered = true;
-}
-void operator()( Face& face ) const {
-       if ( !m_filter->filter( face ) ) {
-               m_filtered = false;
-       }
-}
-};
-
 class filter_brush_all_faces : public BrushFilter
 {
 FaceFilter* m_filter;
@@ -945,8 +812,12 @@ public:
 filter_brush_all_faces( FaceFilter* filter ) : m_filter( filter ){
 }
 bool filter( const Brush& brush ) const {
-       bool filtered;
-       Brush_forEachFace( brush, FaceFilterAll( m_filter, filtered ) );
+       bool filtered = true;
+       Brush_forEachFace(brush, [&](Face &face) {
+               if (!m_filter->filter(face)) {
+                       filtered = false;
+               }
+       });
        return filtered;
 }
 };
@@ -1264,10 +1135,12 @@ public:
 BrushMakeSided( std::size_t count )
        : m_count( count ){
 }
+
 void set(){
        Scene_BrushConstructPrefab( GlobalSceneGraph(), eBrushPrism, m_count, TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
 }
-typedef MemberCaller<BrushMakeSided, &BrushMakeSided::set> SetCaller;
+
+typedef MemberCaller<BrushMakeSided, void(), &BrushMakeSided::set> SetCaller;
 };
 
 
@@ -1299,10 +1172,12 @@ public:
 BrushPrefab( EBrushPrefab type )
        : m_type( type ){
 }
+
 void set(){
        DoSides( m_type, axis_for_viewtype( GetViewAxis() ) );
 }
-typedef MemberCaller<BrushPrefab, &BrushPrefab::set> SetCaller;
+
+typedef MemberCaller<BrushPrefab, void(), &BrushPrefab::set> SetCaller;
 };
 
 BrushPrefab g_brushprism( eBrushPrism );
@@ -1312,9 +1187,13 @@ BrushPrefab g_brushrock( eBrushRock );
 
 
 void FlipClip();
+
 void SplitClip();
+
 void Clip();
+
 void OnClipMode( bool enable );
+
 bool ClipMode();
 
 
@@ -1337,8 +1216,8 @@ void FlipClipper(){
 }
 
 
-Callback g_texture_lock_status_changed;
-BoolExportCaller g_texdef_movelock_caller( g_brush_texturelock_enabled );
+Callback<void()> g_texture_lock_status_changed;
+ConstReferenceCaller<bool, void(const Callback<void(bool)> &), PropertyImpl<bool>::Export> g_texdef_movelock_caller( g_brush_texturelock_enabled );
 ToggleItem g_texdef_movelock_item( g_texdef_movelock_caller );
 
 void Texdef_ToggleMoveLock(){
@@ -1348,11 +1227,8 @@ void Texdef_ToggleMoveLock(){
 }
 
 
-
-
-
 void Brush_registerCommands(){
-       GlobalToggles_insert( "TogTexLock", FreeCaller<Texdef_ToggleMoveLock>(), ToggleItem::AddCallbackCaller( g_texdef_movelock_item ), Accelerator( 'T', (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalToggles_insert( "TogTexLock", makeCallbackF(Texdef_ToggleMoveLock), ToggleItem::AddCallbackCaller( g_texdef_movelock_item ), Accelerator( 'T', (GdkModifierType)GDK_SHIFT_MASK ) );
 
        GlobalCommands_insert( "BrushPrism", BrushPrefab::SetCaller( g_brushprism ) );
        GlobalCommands_insert( "BrushCone", BrushPrefab::SetCaller( g_brushcone ) );
@@ -1367,32 +1243,33 @@ void Brush_registerCommands(){
        GlobalCommands_insert( "Brush8Sided", BrushMakeSided::SetCaller( g_brushmakesided8 ), Accelerator( '8', (GdkModifierType)GDK_CONTROL_MASK ) );
        GlobalCommands_insert( "Brush9Sided", BrushMakeSided::SetCaller( g_brushmakesided9 ), Accelerator( '9', (GdkModifierType)GDK_CONTROL_MASK ) );
 
-       GlobalCommands_insert( "ClipSelected", FreeCaller<ClipSelected>(), Accelerator( GDK_Return ) );
-       GlobalCommands_insert( "SplitSelected", FreeCaller<SplitSelected>(), Accelerator( GDK_Return, (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalCommands_insert( "FlipClip", FreeCaller<FlipClipper>(), Accelerator( GDK_Return, (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "ClipSelected", makeCallbackF(ClipSelected), Accelerator( GDK_KEY_Return ) );
+       GlobalCommands_insert( "SplitSelected", makeCallbackF(SplitSelected), Accelerator( GDK_KEY_Return, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "FlipClip", makeCallbackF(FlipClipper), Accelerator( GDK_KEY_Return, (GdkModifierType)GDK_CONTROL_MASK ) );
 
-       GlobalCommands_insert( "MakeDetail", FreeCaller<Select_MakeDetail>(), Accelerator( 'M', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "MakeStructural", FreeCaller<Select_MakeStructural>(), Accelerator( 'S', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "MakeDetail", makeCallbackF(Select_MakeDetail), Accelerator( 'M', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "MakeStructural", makeCallbackF(Select_MakeStructural), Accelerator( 'S', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
 }
 
-void Brush_constructMenu( GtkMenu* menu ){
+void Brush_constructMenu( ui::Menu menu ){
        create_menu_item_with_mnemonic( menu, "Prism...", "BrushPrism" );
        create_menu_item_with_mnemonic( menu, "Cone...", "BrushCone" );
        create_menu_item_with_mnemonic( menu, "Sphere...", "BrushSphere" );
        create_menu_item_with_mnemonic( menu, "Rock...", "BrushRock" );
        menu_separator( menu );
        {
-               GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic( menu, "CSG" );
+               auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "CSG" );
                if ( g_Layout_enableDetachableMenus.m_value ) {
                        menu_tearoff( menu_in_menu );
                }
-               create_menu_item_with_mnemonic( menu_in_menu, "Make _Hollow", "CSGHollow" );
+               create_menu_item_with_mnemonic( menu_in_menu, "Make _Hollow", "CSGMakeHollow" );
+               create_menu_item_with_mnemonic( menu_in_menu, "Make _Room", "CSGMakeRoom" );
                create_menu_item_with_mnemonic( menu_in_menu, "CSG _Subtract", "CSGSubtract" );
                create_menu_item_with_mnemonic( menu_in_menu, "CSG _Merge", "CSGMerge" );
        }
        menu_separator( menu );
        {
-               GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic( menu, "Clipper" );
+               auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Clipper" );
                if ( g_Layout_enableDetachableMenus.m_value ) {
                        menu_tearoff( menu_in_menu );
                }