]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/csg.cpp
Merge commit 'f73cc19a6166fc04269f953c980175779f81b9b0' into garux-merge
[xonotic/netradiant.git] / radiant / csg.cpp
index aab9caa573972a18d36e6ac677f1d095b168dd50..9de2dca24f705960f6adc8f5c24b14e0818f093a 100644 (file)
@@ -57,31 +57,40 @@ void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float
        }
 }
 
-class FaceMakeBrush
-{
-const Brush& brush;
-brush_vector_t& out;
-float offset;
-public:
-FaceMakeBrush( const Brush& brush, brush_vector_t& out, float offset )
-       : brush( brush ), out( out ), offset( offset ){
+void Face_makeRoom( Face &face, const Brush &brush, brush_vector_t &out, float offset ){
+       if ( face.contributes() ) {
+               face.getPlane().offset( offset );
+               out.push_back( new Brush( brush ) );
+               face.getPlane().offset( -offset );
+               Face* newFace = out.back()->addFace( face );
+               if ( newFace != 0 ) {
+                       newFace->flipWinding();
+                       newFace->planeChanged();
+               }
+       }
 }
-void operator()( Face& face ) const {
-       Face_makeBrush( face, brush, out, offset );
+
+void Brush_makeHollow( const Brush &brush, brush_vector_t &out, float offset ){
+       Brush_forEachFace( brush, [&]( Face &face ) {
+               Face_makeBrush( face, brush, out, offset );
+       } );
 }
-};
 
-void Brush_makeHollow( const Brush& brush, brush_vector_t& out, float offset ){
-       Brush_forEachFace( brush, FaceMakeBrush( brush, out, offset ) );
+void Brush_makeRoom( const Brush &brush, brush_vector_t &out, float offset ){
+       Brush_forEachFace( brush, [&]( Face &face ) {
+               Face_makeRoom( face, brush, out, offset );
+       } );
 }
 
 class BrushHollowSelectedWalker : public scene::Graph::Walker
 {
 float m_offset;
+bool m_makeRoom;
 public:
-BrushHollowSelectedWalker( float offset )
-       : m_offset( offset ){
+BrushHollowSelectedWalker( float offset, bool makeRoom )
+       : m_offset( offset ), m_makeRoom( makeRoom ){
 }
+
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        if ( path.top().get().visible() ) {
                Brush* brush = Node_getBrush( path.top() );
@@ -89,7 +98,15 @@ 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 );
+
+                       if ( m_makeRoom ) {
+                               Brush_makeRoom(* brush, out, m_offset );
+                       }
+                       else
+                       {
+                               Brush_makeHollow(* brush, out, m_offset );
+                       }
+
                        for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i )
                        {
                                ( *i )->removeEmptyFaces();
@@ -113,6 +130,7 @@ public:
 BrushGatherSelected( brush_vector_t& brushlist )
        : m_brushlist( brushlist ){
 }
+
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        if ( path.top().get().visible() ) {
                Brush* brush = Node_getBrush( path.top() );
@@ -143,8 +161,8 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
 }
 };
 
-void Scene_BrushMakeHollow_Selected( scene::Graph& graph ){
-       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( GetGridSize() ) );
+void Scene_BrushMakeHollow_Selected( scene::Graph& graph, bool makeRoom ){
+       GlobalSceneGraph().traverse( BrushHollowSelectedWalker( GetGridSize(), makeRoom ) );
        GlobalSceneGraph().traverse( BrushDeleteSelected() );
 }
 
@@ -157,7 +175,15 @@ void Scene_BrushMakeHollow_Selected( scene::Graph& graph ){
 void CSG_MakeHollow( void ){
        UndoableCommand undo( "brushHollow" );
 
-       Scene_BrushMakeHollow_Selected( GlobalSceneGraph() );
+       Scene_BrushMakeHollow_Selected( GlobalSceneGraph(), false );
+
+       SceneChangeNotify();
+}
+
+void CSG_MakeRoom( void ){
+       UndoableCommand undo( "brushRoom" );
+
+       Scene_BrushMakeHollow_Selected( GlobalSceneGraph(), true );
 
        SceneChangeNotify();
 }
@@ -181,11 +207,9 @@ class Dereference
 {
 const Functor& functor;
 public:
-typedef typename RemoveReference<typename Functor::first_argument_type>::type* first_argument_type;
-typedef typename Functor::result_type result_type;
 Dereference( const Functor& functor ) : functor( functor ){
 }
-result_type operator()( first_argument_type firstArgument ) const {
+get_result_type<Functor> operator()( typename RemoveReference<get_argument<Functor, 0>>::type *firstArgument ) const {
        return functor( *firstArgument );
 }
 };
@@ -207,15 +231,14 @@ Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){
 template<typename Caller>
 class BindArguments1
 {
-typedef typename Caller::second_argument_type FirstBound;
+typedef get_argument<Caller, 1> FirstBound;
 FirstBound firstBound;
 public:
-typedef typename Caller::result_type result_type;
-typedef typename Caller::first_argument_type first_argument_type;
 BindArguments1( FirstBound firstBound )
        : firstBound( firstBound ){
 }
-result_type operator()( first_argument_type firstArgument ) const {
+
+get_result_type<Caller> operator()( get_argument<Caller, 0> firstArgument ) const {
        return Caller::call( firstArgument, firstBound );
 }
 };
@@ -223,17 +246,16 @@ result_type operator()( first_argument_type firstArgument ) const {
 template<typename Caller>
 class BindArguments2
 {
-typedef typename Caller::second_argument_type FirstBound;
-typedef typename Caller::third_argument_type SecondBound;
+typedef get_argument<Caller, 1> FirstBound;
+typedef get_argument<Caller, 2> SecondBound;
 FirstBound firstBound;
 SecondBound secondBound;
 public:
-typedef typename Caller::result_type result_type;
-typedef typename Caller::first_argument_type first_argument_type;
 BindArguments2( FirstBound firstBound, SecondBound secondBound )
        : firstBound( firstBound ), secondBound( secondBound ){
 }
-result_type operator()( first_argument_type firstArgument ) const {
+
+get_result_type<Caller> operator()( get_argument<Caller, 0> firstArgument ) const {
        return Caller::call( firstArgument, firstBound, secondBound );
 }
 };
@@ -246,8 +268,8 @@ BindArguments2<Caller> bindArguments( const Caller& caller, FirstBound firstBoun
 inline bool Face_testPlane( const Face& face, const Plane3& plane, bool flipped ){
        return face.contributes() && !Winding_TestPlane( face.getWinding(), plane, flipped );
 }
-typedef Function3<const Face&, const Plane3&, bool, bool, Face_testPlane> FaceTestPlane;
 
+typedef Function<bool ( const Face &, const Plane3 &, bool ), Face_testPlane> FaceTestPlane;
 
 
 /// \brief Returns true if
@@ -323,9 +345,11 @@ public:
 SubtractBrushesFromUnselected( const brush_vector_t& brushlist, std::size_t& before, std::size_t& after )
        : m_brushlist( brushlist ), m_before( before ), m_after( after ){
 }
+
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        return true;
 }
+
 void post( const scene::Path& path, scene::Instance& instance ) const {
        if ( path.top().get().visible() ) {
                Brush* brush = Node_getBrush( path.top() );
@@ -420,9 +444,11 @@ public:
 BrushSplitByPlaneSelected( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection, EBrushSplit split )
        : m_p0( p0 ), m_p1( p1 ), m_p2( p2 ), m_shader( shader ), m_projection( projection ), m_split( split ){
 }
+
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        return true;
 }
+
 void post( const scene::Path& path, scene::Instance& instance ) const {
        if ( path.top().get().visible() ) {
                Brush* brush = Node_getBrush( path.top() );
@@ -486,6 +512,7 @@ public:
 BrushInstanceSetClipPlane( const Plane3& plane )
        : m_plane( plane ){
 }
+
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        BrushInstance* brush = Instance_getBrush( instance );
        if ( brush != 0