mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Dirty clearance lines when rule areas change.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/20734 (cherry picked from commit e2cf94491529ae73739c9f8d16a8d744a666b50a)
This commit is contained in:
parent
f21a801545
commit
8202388aa8
@ -24,6 +24,8 @@
|
||||
*/
|
||||
|
||||
#include <macros.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
#include <lset.h>
|
||||
@ -125,37 +127,46 @@ COMMIT& BOARD_COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag
|
||||
}
|
||||
|
||||
|
||||
void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType )
|
||||
void BOARD_COMMIT::propagateDamage( BOARD_ITEM* aChangedItem, std::vector<ZONE*>* aStaleZones,
|
||||
std::vector<BOX2I>& aStaleRuleAreas )
|
||||
{
|
||||
wxCHECK( item, /* void */ );
|
||||
wxCHECK( aChangedItem, /* void */ );
|
||||
|
||||
ZONE_FILLER_TOOL* zoneFillerTool = m_toolMgr->GetTool<ZONE_FILLER_TOOL>();
|
||||
if( aStaleZones && aChangedItem->Type() == PCB_ZONE_T )
|
||||
aStaleZones->push_back( static_cast<ZONE*>( aChangedItem ) );
|
||||
|
||||
if( item->Type() == PCB_ZONE_T )
|
||||
zoneFillerTool->DirtyZone( static_cast<ZONE*>( item ) );
|
||||
|
||||
item->RunOnChildren( std::bind( &BOARD_COMMIT::dirtyIntersectingZones, this, _1, aChangeType ) );
|
||||
aChangedItem->RunOnChildren( std::bind( &BOARD_COMMIT::propagateDamage, this, _1, aStaleZones, aStaleRuleAreas ) );
|
||||
|
||||
BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
|
||||
BOX2I bbox = item->GetBoundingBox();
|
||||
LSET layers = item->GetLayerSet();
|
||||
BOX2I damageBBox = aChangedItem->GetBoundingBox();
|
||||
LSET damageLayers = aChangedItem->GetLayerSet();
|
||||
|
||||
if( layers.test( Edge_Cuts ) || layers.test( Margin ) )
|
||||
layers = LSET::PhysicalLayersMask();
|
||||
else
|
||||
layers &= LSET::AllCuMask();
|
||||
|
||||
if( layers.any() )
|
||||
if( m_isBoardEditor && aChangedItem->Type() == PCB_ZONE_T )
|
||||
{
|
||||
for( ZONE* zone : board->Zones() )
|
||||
{
|
||||
if( zone->GetIsRuleArea() )
|
||||
continue;
|
||||
// A named zone can have custom DRC rules targetting it.
|
||||
if( !static_cast<ZONE*>( aChangedItem )->GetZoneName().IsEmpty() )
|
||||
aStaleRuleAreas.push_back( damageBBox );
|
||||
}
|
||||
|
||||
if( ( zone->GetLayerSet() & layers ).any()
|
||||
&& zone->GetBoundingBox().Intersects( bbox ) )
|
||||
if( aStaleZones )
|
||||
{
|
||||
if( damageLayers.test( Edge_Cuts ) || damageLayers.test( Margin ) )
|
||||
damageLayers = LSET::PhysicalLayersMask();
|
||||
else
|
||||
damageLayers &= LSET::AllCuMask();
|
||||
|
||||
if( damageLayers.any() )
|
||||
{
|
||||
for( ZONE* zone : board->Zones() )
|
||||
{
|
||||
zoneFillerTool->DirtyZone( zone );
|
||||
if( zone->GetIsRuleArea() )
|
||||
continue;
|
||||
|
||||
if( ( zone->GetLayerSet() & damageLayers ).any()
|
||||
&& zone->GetBoundingBox().Intersects( damageBBox ) )
|
||||
{
|
||||
aStaleZones->push_back( zone );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,7 +175,7 @@ void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType )
|
||||
|
||||
void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
{
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
KIGFX::PCB_VIEW* view = static_cast<KIGFX::PCB_VIEW*>( m_toolMgr->GetView() );
|
||||
BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
|
||||
PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
@ -179,6 +190,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
bool autofillZones = false;
|
||||
std::vector<BOARD_ITEM*> staleTeardropPadsAndVias;
|
||||
std::set<PCB_TRACK*> staleTeardropTracks;
|
||||
std::vector<ZONE*> staleZonesStorage;
|
||||
std::vector<ZONE*>* staleZones = nullptr;
|
||||
std::vector<BOX2I> staleRuleAreas;
|
||||
PCB_GROUP* addedGroup = nullptr;
|
||||
|
||||
if( Empty() )
|
||||
@ -200,6 +214,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
&& ( frame && frame->GetPcbNewSettings()->m_AutoRefillZones ) )
|
||||
{
|
||||
autofillZones = true;
|
||||
staleZones = &staleZonesStorage;
|
||||
|
||||
for( ZONE* zone : board->Zones() )
|
||||
zone->CacheBoundingBox();
|
||||
@ -303,8 +318,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
if( boardItem->Type() == PCB_GROUP_T || boardItem->Type() == PCB_GENERATOR_T )
|
||||
addedGroup = static_cast<PCB_GROUP*>( boardItem );
|
||||
|
||||
if( m_isBoardEditor && autofillZones && boardItem->Type() != PCB_MARKER_T )
|
||||
dirtyIntersectingZones( boardItem, changeType );
|
||||
if( boardItem->Type() != PCB_MARKER_T )
|
||||
propagateDamage( boardItem, staleZones, staleRuleAreas );
|
||||
|
||||
if( view && boardItem->Type() != PCB_NETINFO_T )
|
||||
view->Add( boardItem );
|
||||
@ -333,8 +348,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
if( parentFP && !( parentFP->GetFlags() & STRUCT_DELETED ) )
|
||||
ent.m_parent = parentFP->m_Uuid;
|
||||
|
||||
if( m_isBoardEditor && autofillZones && boardItem->Type() != PCB_MARKER_T )
|
||||
dirtyIntersectingZones( boardItem, changeType );
|
||||
if( boardItem->Type() != PCB_MARKER_T )
|
||||
propagateDamage( boardItem, staleZones, staleRuleAreas );
|
||||
|
||||
switch( boardItem->Type() )
|
||||
{
|
||||
@ -446,10 +461,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
connectivity->Update( boardItem );
|
||||
}
|
||||
|
||||
if( m_isBoardEditor && autofillZones && boardItem->Type() != PCB_MARKER_T )
|
||||
if( boardItem->Type() != PCB_MARKER_T )
|
||||
{
|
||||
dirtyIntersectingZones( boardItemCopy, changeType ); // before
|
||||
dirtyIntersectingZones( boardItem, changeType ); // after
|
||||
propagateDamage( boardItemCopy, staleZones, staleRuleAreas ); // before
|
||||
propagateDamage( boardItem, staleZones, staleRuleAreas ); // after
|
||||
}
|
||||
|
||||
if( view )
|
||||
@ -504,6 +519,14 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
frame->HideSolderMask();
|
||||
}
|
||||
|
||||
PCBNEW_SETTINGS* settings = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
|
||||
|
||||
if( !staleRuleAreas.empty() && ( settings->m_Display.m_TrackClearance == SHOW_WITH_VIA_ALWAYS
|
||||
|| settings->m_Display.m_PadClearance ) )
|
||||
{
|
||||
view->UpdateCollidingItems( staleRuleAreas, { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T } );
|
||||
}
|
||||
|
||||
if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
|
||||
{
|
||||
teardropMgr.UpdateTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
|
||||
@ -570,7 +593,14 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
m_toolMgr->PostEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
if( autofillZones )
|
||||
{
|
||||
ZONE_FILLER_TOOL* zoneFillerTool = m_toolMgr->GetTool<ZONE_FILLER_TOOL>();
|
||||
|
||||
for( ZONE* zone : *staleZones )
|
||||
zoneFillerTool->DirtyZone( zone );
|
||||
|
||||
m_toolMgr->PostAction( PCB_ACTIONS::zoneFillDirty );
|
||||
}
|
||||
|
||||
if( selectedModified )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedItemsModified );
|
||||
|
@ -27,8 +27,10 @@
|
||||
#define BOARD_COMMIT_H
|
||||
|
||||
#include <commit.h>
|
||||
#include <math/box2.h>
|
||||
|
||||
class BOARD_ITEM;
|
||||
class ZONE;
|
||||
class BOARD;
|
||||
class PICKED_ITEMS_LIST;
|
||||
class PCB_TOOL_BASE;
|
||||
@ -73,7 +75,8 @@ private:
|
||||
|
||||
EDA_ITEM* makeImage( EDA_ITEM* aItem ) const override;
|
||||
|
||||
void dirtyIntersectingZones( BOARD_ITEM* item, int aChangeType );
|
||||
void propagateDamage( BOARD_ITEM* aItem, std::vector<ZONE*>* aStaleZones,
|
||||
std::vector<BOX2I>& aStaleRuleAreas );
|
||||
|
||||
private:
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
|
@ -118,6 +118,33 @@ void PCB_VIEW::Update( const KIGFX::VIEW_ITEM* aItem ) const
|
||||
}
|
||||
|
||||
|
||||
void PCB_VIEW::UpdateCollidingItems( const std::vector<BOX2I>& aStaleAreas,
|
||||
std::initializer_list<KICAD_T> aTypes )
|
||||
{
|
||||
UpdateAllItemsConditionally(
|
||||
[&]( KIGFX::VIEW_ITEM* aItem ) -> int
|
||||
{
|
||||
if( aItem->IsBOARD_ITEM() )
|
||||
{
|
||||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aItem );
|
||||
|
||||
if( item->IsType( aTypes ) )
|
||||
{
|
||||
BOX2I itemBBox = item->GetBoundingBox();
|
||||
|
||||
for( const BOX2I& bbox : aStaleAreas )
|
||||
{
|
||||
if( itemBBox.Intersects( bbox ) )
|
||||
return KIGFX::REPAINT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void PCB_VIEW::UpdateDisplayOptions( const PCB_DISPLAY_OPTIONS& aOptions )
|
||||
{
|
||||
KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( GetPainter() );
|
||||
|
@ -22,8 +22,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __PCB_VIEW_H
|
||||
#define __PCB_VIEW_H
|
||||
#pragma once
|
||||
|
||||
#include <layer_ids.h>
|
||||
#include <view/view.h>
|
||||
@ -51,9 +50,13 @@ public:
|
||||
/// @copydoc VIEW::Update()
|
||||
virtual void Update( const VIEW_ITEM* aItem ) const override;
|
||||
|
||||
/**
|
||||
* Sets the KIGFX::REPAINT on all items matching \a aTypes which intersect \a aStaleAreas.
|
||||
*/
|
||||
void UpdateCollidingItems( const std::vector<BOX2I>& aStaleAreas,
|
||||
std::initializer_list<KICAD_T> aTypes );
|
||||
|
||||
void UpdateDisplayOptions( const PCB_DISPLAY_OPTIONS& aOptions );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -261,9 +261,10 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
bool reBuild_ratsnest = false;
|
||||
bool deep_reBuild_ratsnest = false; // true later if pointers must be rebuilt
|
||||
bool solder_mask_dirty = false;
|
||||
std::vector<BOX2I> dirty_rule_areas;
|
||||
|
||||
auto view = GetCanvas()->GetView();
|
||||
auto connectivity = GetBoard()->GetConnectivity();
|
||||
KIGFX::PCB_VIEW* view = GetCanvas()->GetView();
|
||||
std::shared_ptr<CONNECTIVITY_DATA> connectivity = GetBoard()->GetConnectivity();
|
||||
|
||||
GetBoard()->IncrementTimeStamp(); // clear caches
|
||||
|
||||
@ -471,6 +472,12 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
if( parentGroup )
|
||||
parentGroup->AddItem( item );
|
||||
|
||||
if( item->Type() == PCB_ZONE_T && static_cast<ZONE*>( item )->GetIsRuleArea() )
|
||||
{
|
||||
dirty_rule_areas.push_back( item->GetBoundingBox() );
|
||||
dirty_rule_areas.push_back( image->GetBoundingBox() );
|
||||
}
|
||||
|
||||
update_item_change_state( item, ITEM_CHANGE_TYPE::CHANGED );
|
||||
break;
|
||||
}
|
||||
@ -485,6 +492,9 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
|
||||
eda_item->SetFlags( UR_TRANSIENT );
|
||||
|
||||
if( eda_item->Type() == PCB_ZONE_T && static_cast<ZONE*>( eda_item )->GetIsRuleArea() )
|
||||
dirty_rule_areas.push_back( eda_item->GetBoundingBox() );
|
||||
|
||||
break;
|
||||
|
||||
case UNDO_REDO::DELETED: /* deleted items are put in List, as new items */
|
||||
@ -498,6 +508,9 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
if( eda_item->Type() != PCB_NETINFO_T )
|
||||
view->Add( eda_item );
|
||||
|
||||
if( eda_item->Type() == PCB_ZONE_T && static_cast<ZONE*>( eda_item )->GetIsRuleArea() )
|
||||
dirty_rule_areas.push_back( eda_item->GetBoundingBox() );
|
||||
|
||||
break;
|
||||
|
||||
case UNDO_REDO::REGROUP: /* grouped items are ungrouped */
|
||||
@ -572,6 +585,12 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
|
||||
if( IsType( FRAME_PCB_EDITOR ) )
|
||||
{
|
||||
if( !dirty_rule_areas.empty() && ( GetPcbNewSettings()->m_Display.m_TrackClearance == SHOW_WITH_VIA_ALWAYS
|
||||
|| GetPcbNewSettings()->m_Display.m_PadClearance ) )
|
||||
{
|
||||
view->UpdateCollidingItems( dirty_rule_areas, { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T } );
|
||||
}
|
||||
|
||||
if( reBuild_ratsnest || deep_reBuild_ratsnest )
|
||||
{
|
||||
// Connectivity may have changed; rebuild internal caches to remove stale items
|
||||
|
Loading…
x
Reference in New Issue
Block a user