X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=radiant%2Fcsg.cpp;h=f28bdc98d202d0465f8bac6654f4e05b2abbfe4b;hb=fda66ae00e9a2ab6d3ebaede13b12fa6767cf856;hp=2538359fc96a8ac5d8e9b7285c22058368d940db;hpb=3df6d45c403dbfbb0c772e8fc7a661a52c1d3244;p=xonotic%2Fnetradiant.git diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 2538359f..f28bdc98 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -33,7 +33,7 @@ void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){ if ( face.contributes() ) { out.push_back( new Brush( brush ) ); - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->flipWinding(); newFace->getPlane().offset( offset ); @@ -42,31 +42,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 ); + std::shared_ptr 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() ); @@ -74,7 +83,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(); @@ -98,6 +115,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() ); @@ -128,8 +146,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() ); } @@ -142,7 +160,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(); } @@ -178,15 +204,6 @@ inline Dereference makeDereference( const Functor& functor ){ return Dereference( functor ); } -typedef Face* FacePointer; -const FacePointer c_nullFacePointer = 0; - -template -Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){ - Brush::const_iterator i = std::find_if( brush.begin(), brush.end(), makeDereference( predicate ) ); - return i == brush.end() ? c_nullFacePointer : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int -} - template class BindArguments1 { @@ -196,6 +213,7 @@ public: BindArguments1( FirstBound firstBound ) : firstBound( firstBound ){ } + get_result_type operator()( get_argument firstArgument ) const { return Caller::call( firstArgument, firstBound ); } @@ -212,6 +230,7 @@ public: BindArguments2( FirstBound firstBound, SecondBound secondBound ) : firstBound( firstBound ), secondBound( secondBound ){ } + get_result_type operator()( get_argument firstArgument ) const { return Caller::call( firstArgument, firstBound, secondBound ); } @@ -225,8 +244,8 @@ BindArguments2 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 FaceTestPlane; +typedef Function FaceTestPlane; /// \brief Returns true if @@ -234,7 +253,6 @@ typedef Function3 FaceTe /// \li flipped && brush is FRONT or ON bool Brush_testPlane( const Brush& brush, const Plane3& plane, bool flipped ){ brush.evaluateBRep(); -#if 1 for ( Brush::const_iterator i( brush.begin() ); i != brush.end(); ++i ) { if ( Face_testPlane( *( *i ), plane, flipped ) ) { @@ -242,9 +260,6 @@ bool Brush_testPlane( const Brush& brush, const Plane3& plane, bool flipped ){ } } return true; -#else - return Brush_findIf( brush, bindArguments( FaceTestPlane(), makeReference( plane ), flipped ) ) == 0; -#endif } brushsplit_t Brush_classifyPlane( const Brush& brush, const Plane3& plane ){ @@ -265,24 +280,24 @@ bool Brush_subtract( const Brush& brush, const Brush& other, brush_vector_t& ret fragments.reserve( other.size() ); Brush back( brush ); - for ( Brush::const_iterator i( other.begin() ); i != other.end(); ++i ) + for ( const std::shared_ptr& b : other ) { - if ( ( *i )->contributes() ) { - brushsplit_t split = Brush_classifyPlane( back, ( *i )->plane3() ); + if ( b->contributes() ) { + brushsplit_t split = Brush_classifyPlane( back, b->plane3() ); if ( split.counts[ePlaneFront] != 0 && split.counts[ePlaneBack] != 0 ) { fragments.push_back( new Brush( back ) ); - Face* newFace = fragments.back()->addFace( *( *i ) ); - if ( newFace != 0 ) { + std::shared_ptr newFace = fragments.back()->addFace( *b ); + if ( newFace != nullptr ) { newFace->flipWinding(); } - back.addFace( *( *i ) ); + back.addFace( *b ); } else if ( split.counts[ePlaneBack] == 0 ) { - for ( brush_vector_t::iterator i = fragments.begin(); i != fragments.end(); ++i ) - { - delete( *i ); + for ( Brush *i : fragments ) { + delete( i ); } + fragments.clear(); return false; } } @@ -302,9 +317,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() ); @@ -341,19 +358,15 @@ void post( const scene::Path& path, scene::Instance& instance ) const { else { ++m_before; - for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i ) - { + for ( Brush *b : out ) { ++m_after; - ( *i )->removeEmptyFaces(); - if ( !( *i )->empty() ) { + b->removeEmptyFaces(); + if ( !b->empty() ) { NodeSmartReference node( ( new BrushNode() )->node() ); - Node_getBrush( node )->copy( *( *i ) ); - delete ( *i ); + Node_getBrush( node )->copy( *b ); Node_getTraversable( path.parent() )->insert( node ); } - else{ - delete ( *i ); - } + delete b; } Path_deleteTop( path ); } @@ -368,9 +381,7 @@ void CSG_Subtract(){ if ( selected_brushes.empty() ) { globalOutputStream() << "CSG Subtract: No brushes selected.\n"; - } - else - { + } else { globalOutputStream() << "CSG Subtract: Subtracting " << Unsigned( selected_brushes.size() ) << " brushes.\n"; UndoableCommand undo( "brushSubtract" ); @@ -399,53 +410,61 @@ 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() ); - if ( brush != 0 - && Instance_getSelectable( instance )->isSelected() ) { - Plane3 plane( plane3_for_points( m_p0, m_p1, m_p2 ) ); - if ( plane3_valid( plane ) ) { - brushsplit_t split = Brush_classifyPlane( *brush, m_split == eFront ? plane3_flipped( plane ) : plane ); - if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) { - // the plane intersects this brush - if ( m_split == eFrontAndBack ) { - NodeSmartReference node( ( new BrushNode() )->node() ); - Brush* fragment = Node_getBrush( node ); - fragment->copy( *brush ); - Face* newFace = fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); - if ( newFace != 0 && m_split != eFront ) { - newFace->flipWinding(); - } - fragment->removeEmptyFaces(); - ASSERT_MESSAGE( !fragment->empty(), "brush left with no faces after split" ); + if ( !path.top().get().visible() ) { + return; + } - Node_getTraversable( path.parent() )->insert( node ); - { - scene::Path fragmentPath = path; - fragmentPath.top() = makeReference( node.get() ); - selectPath( fragmentPath, true ); - } - } + Brush* brush = Node_getBrush( path.top() ); + if ( brush == nullptr || !Instance_getSelectable( instance )->isSelected() ) { + return; + } - Face* newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); - if ( newFace != 0 && m_split == eFront ) { - newFace->flipWinding(); - } - brush->removeEmptyFaces(); - ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after split" ); - } - else - // the plane does not intersect this brush - if ( m_split != eFrontAndBack && split.counts[ePlaneBack] != 0 ) { - // the brush is "behind" the plane - Path_deleteTop( path ); - } + Plane3 plane( plane3_for_points( m_p0, m_p1, m_p2 ) ); + if ( !plane3_valid( plane ) ) { + return; + } + + brushsplit_t split = Brush_classifyPlane( *brush, m_split == eFront ? plane3_flipped( plane ) : plane ); + if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) { + // the plane intersects this brush + if ( m_split == eFrontAndBack ) { + NodeSmartReference node( ( new BrushNode() )->node() ); + Brush* fragment = Node_getBrush( node ); + fragment->copy( *brush ); + std::shared_ptr newFace = + fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); + if ( newFace != 0 && m_split != eFront ) { + newFace->flipWinding(); } + fragment->removeEmptyFaces(); + ASSERT_MESSAGE( !fragment->empty(), "brush left with no faces after split" ); + + Node_getTraversable( path.parent() )->insert( node ); + { + scene::Path fragmentPath = path; + fragmentPath.top() = makeReference( node.get() ); + selectPath( fragmentPath, true ); + } + } + + std::shared_ptr newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); + if ( newFace != 0 && m_split == eFront ) { + newFace->flipWinding(); } + brush->removeEmptyFaces(); + ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after split" ); + } + else + // the plane does not intersect this brush + if ( m_split != eFrontAndBack && split.counts[ePlaneBack] != 0 ) { + // the brush is "behind" the plane + Path_deleteTop( path ); } } }; @@ -465,6 +484,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