diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index cf09660ab6..189e075b58 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -2162,7 +2162,7 @@ void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer ) #endif } - if( aLayer == LAYER_CONFLICTS_SHADOW ) // happens only if locked + if( aLayer == LAYER_CONFLICTS_SHADOW ) { const SHAPE_POLY_SET& frontpoly = aFootprint->GetCourtyard( F_CrtYd ); const SHAPE_POLY_SET& backpoly = aFootprint->GetCourtyard( B_CrtYd ); @@ -2251,6 +2251,18 @@ void PCB_PAINTER::draw( const PCB_GROUP* aGroup, int aLayer ) void PCB_PAINTER::draw( const ZONE* aZone, int aLayer ) { + if( aLayer == LAYER_CONFLICTS_SHADOW ) + { + COLOR4D color = m_pcbSettings.GetColor( aZone, aLayer ); + + m_gal->SetIsFill( true ); + m_gal->SetIsStroke( false ); + m_gal->SetFillColor( color ); + + m_gal->DrawPolygon( aZone->Outline()->Outline( 0 ) ); + return; + } + /* * aLayer will be the virtual zone layer (LAYER_ZONE_START, ... in GAL_LAYER_ID) * This is used for draw ordering in the GAL. diff --git a/pcbnew/tools/edit_tool_move_fct.cpp b/pcbnew/tools/edit_tool_move_fct.cpp index bbfad05c68..981c7a8ac8 100644 --- a/pcbnew/tools/edit_tool_move_fct.cpp +++ b/pcbnew/tools/edit_tool_move_fct.cpp @@ -105,8 +105,8 @@ public: return wxT( "Tests footprints' courtyard clearance" ); } - // The list of footprints having issues - std::set m_FpInConflict; + // The list of items in collision + std::set m_ItemsInConflict; // The list of moved footprints std::vector m_FpInMove; @@ -163,8 +163,8 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances() if( frontA.Collide( &frontB, clearance, &actual, &pos ) ) { - m_FpInConflict.insert( fpA ); - m_FpInConflict.insert( fpB ); + m_ItemsInConflict.insert( fpA ); + m_ItemsInConflict.insert( fpB ); } } @@ -176,11 +176,10 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances() // constraint.GetValue().Min(); clearance = 0; - if( backA.Collide( &backB, clearance, &actual, &pos ) ) { - m_FpInConflict.insert( fpA ); - m_FpInConflict.insert( fpB ); + m_ItemsInConflict.insert( fpA ); + m_ItemsInConflict.insert( fpB ); } } @@ -213,8 +212,8 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances() { if( testPadAgainstCourtyards( padB, fpA ) ) { - m_FpInConflict.insert( fpA ); - m_FpInConflict.insert( fpB ); + m_ItemsInConflict.insert( fpA ); + m_ItemsInConflict.insert( fpB ); skipNextCmp = true; break; } @@ -231,8 +230,50 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances() { if( testPadAgainstCourtyards( padA, fpB ) ) { - m_FpInConflict.insert( fpA ); - m_FpInConflict.insert( fpB ); + m_ItemsInConflict.insert( fpA ); + m_ItemsInConflict.insert( fpB ); + break; + } + } + } + } + } + + for( ZONE* zone : m_board->Zones() ) + { + if( !zone->GetIsRuleArea() || !zone->GetDoNotAllowFootprints() ) + continue; + + bool disallowFront = ( zone->GetLayerSet() | LSET::FrontMask() ).any(); + bool disallowBack = ( zone->GetLayerSet() | LSET::BackMask() ).any(); + + for( FOOTPRINT* fp : m_FpInMove ) + { + if( disallowFront ) + { + const SHAPE_POLY_SET& frontCourtyard = fp->GetCourtyard( F_CrtYd ); + + if( !frontCourtyard.IsEmpty() ) + { + if( zone->Outline()->Collide( &frontCourtyard.Outline( 0 ) ) ) + { + m_ItemsInConflict.insert( fp ); + m_ItemsInConflict.insert( zone ); + break; + } + } + } + + if( disallowBack ) + { + const SHAPE_POLY_SET& backCourtyard = fp->GetCourtyard( B_CrtYd ); + + if( !backCourtyard.IsEmpty() ) + { + if( zone->Outline()->Collide( &backCourtyard.Outline( 0 ) ) ) + { + m_ItemsInConflict.insert( fp ); + m_ItemsInConflict.insert( zone ); break; } } @@ -257,7 +298,7 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::Init( BOARD* aBoard ) bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::Run() { - m_FpInConflict.clear(); + m_ItemsInConflict.clear(); m_largestCourtyardClearance = 0; DRC_CONSTRAINT constraint; @@ -593,9 +634,9 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) : wxT( "" ) ); }; - std::vector sel_items; // All the items operated on by the move below - std::vector orig_items; // All the original items in the selection - std::vector lastFpInConflict; // last footprints with courtyard overlapping + std::vector sel_items; // All the items operated on by the move below + std::vector orig_items; // All the original items in the selection + std::vector lastItemsInConflict; // last footprints with courtyard overlapping for( EDA_ITEM* item : selection ) { @@ -758,25 +799,25 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) // has changed // Ensure the "old" conflicts are cleared - for( FOOTPRINT* fp: lastFpInConflict ) + for( BOARD_ITEM* item: lastItemsInConflict ) { - fp->ClearFlags( COURTYARD_CONFLICT ); - m_toolMgr->GetView()->Update( fp ); + item->ClearFlags( COURTYARD_CONFLICT ); + m_toolMgr->GetView()->Update( item ); need_redraw = true; } - lastFpInConflict.clear(); + lastItemsInConflict.clear(); - for( FOOTPRINT* fp: drc_on_move.m_FpInConflict ) + for( BOARD_ITEM* item: drc_on_move.m_ItemsInConflict ) { - if( !fp->HasFlag( COURTYARD_CONFLICT ) ) + if( !item->HasFlag( COURTYARD_CONFLICT ) ) { - fp->SetFlags( COURTYARD_CONFLICT ); - m_toolMgr->GetView()->Update( fp ); + item->SetFlags( COURTYARD_CONFLICT ); + m_toolMgr->GetView()->Update( item ); need_redraw = true; } - lastFpInConflict.push_back( fp ); + lastItemsInConflict.push_back( item ); } if( need_redraw ) @@ -976,10 +1017,10 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) } while( ( evt = Wait() ) ); // Assignment (instead of equality test) is intentional // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared - for( FOOTPRINT* fp: lastFpInConflict ) + for( BOARD_ITEM* item: lastItemsInConflict ) { - m_toolMgr->GetView()->Update( fp ); - fp->ClearFlags( COURTYARD_CONFLICT ); + m_toolMgr->GetView()->Update( item ); + item->ClearFlags( COURTYARD_CONFLICT ); } controls->ForceCursorPosition( false ); diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp index 0c16a5bfd1..94618ba6ca 100644 --- a/pcbnew/zone.cpp +++ b/pcbnew/zone.cpp @@ -221,6 +221,12 @@ bool ZONE::UnFill() } +bool ZONE::IsConflicting() const +{ + return HasFlag( COURTYARD_CONFLICT ); +} + + VECTOR2I ZONE::GetPosition() const { return GetCornerPosition( 0 ); @@ -289,6 +295,9 @@ void ZONE::ViewGetLayers( int aLayers[], int& aCount ) const aLayers[idx] = LAYER_ZONE_START + layers[idx]; aCount = layers.size(); + + if( IsConflicting() ) + aLayers[ aCount++ ] = LAYER_CONFLICTS_SHADOW; } diff --git a/pcbnew/zone.h b/pcbnew/zone.h index 439bf36152..530b1747d3 100644 --- a/pcbnew/zone.h +++ b/pcbnew/zone.h @@ -89,6 +89,12 @@ public: */ void InitDataFromSrcInCopyCtor( const ZONE& aZone ); + /** + * For rule areas which exclude footprints (and therefore participate in courtyard conflicts + * during move). + */ + bool IsConflicting() const; + /** * @return a VECTOR2I, position of the first point of the outline */