diff --git a/include/base_struct.h b/include/base_struct.h index e0c6db621d..5f219abf22 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -450,6 +450,25 @@ public: return SEARCH_CONTINUE; } + /** + * @copydoc SEARCH_RESULT IterateForward( EDA_ITEM*, INSPECTOR, void*, const KICAD_T ) + * + * This changes first parameter to avoid the DList and use std::vector instead + */ + template + static SEARCH_RESULT IterateForward( + std::vector& aList, INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) + { + for( auto it : aList ) + { + if( static_cast( it )->Visit( inspector, testData, scanTypes ) + == SEARCH_QUIT ) + return SEARCH_QUIT; + } + + return SEARCH_CONTINUE; + } + /** * Function GetClass * returns the class name. diff --git a/include/commit.h b/include/commit.h index 9498a51753..92dea81ba9 100644 --- a/include/commit.h +++ b/include/commit.h @@ -123,11 +123,11 @@ public: ///> Adds a change of the item aItem of type aChangeType to the change list. - COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ); + virtual COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ); - COMMIT& Stage( std::vector& container, CHANGE_TYPE aChangeType ); + virtual COMMIT& Stage( std::vector& container, CHANGE_TYPE aChangeType ); - COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag = UR_UNSPECIFIED ); + virtual COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag = UR_UNSPECIFIED ); ///> Executes the changes. virtual void Push( const wxString& aMessage = wxT( "A commit" ), diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index 82ba02ae06..d19b6e3dc7 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -56,6 +56,30 @@ BOARD_COMMIT::~BOARD_COMMIT() { } +COMMIT& BOARD_COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) +{ + // if aItem belongs a footprint, the full footprint will be saved + // because undo/redo does not handle "sub items" modifications + if( aItem && aItem->Type() != PCB_MODULE_T && aChangeType == CHT_MODIFY ) + { + EDA_ITEM* item = aItem->GetParent(); + + if( item && item->Type() == PCB_MODULE_T ) // means aItem belongs a footprint + aItem = item; + } + + return COMMIT::Stage( aItem, aChangeType ); +} + +COMMIT& BOARD_COMMIT::Stage( std::vector& container, CHANGE_TYPE aChangeType ) +{ + return COMMIT::Stage( container, aChangeType ); +} + +COMMIT& BOARD_COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag ) +{ + return COMMIT::Stage( aItems, aModFlag ); +} void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool aSetDirtyBit ) { diff --git a/pcbnew/board_commit.h b/pcbnew/board_commit.h index 45fe90bc0d..78b1a86312 100644 --- a/pcbnew/board_commit.h +++ b/pcbnew/board_commit.h @@ -46,6 +46,10 @@ public: bool aCreateUndoEntry = true, bool aSetDirtyBit = true ) override; virtual void Revert() override; + COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) override; + COMMIT& Stage( std::vector& container, CHANGE_TYPE aChangeType ) override; + COMMIT& Stage( + const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag = UR_UNSPECIFIED ) override; private: TOOL_MANAGER* m_toolMgr; diff --git a/pcbnew/board_item_container.h b/pcbnew/board_item_container.h index aa967b0663..3940c20033 100644 --- a/pcbnew/board_item_container.h +++ b/pcbnew/board_item_container.h @@ -28,6 +28,7 @@ #define BOARD_ITEM_CONTAINER_H #include +#include enum ADD_MODE { ADD_INSERT, ADD_APPEND }; @@ -63,6 +64,26 @@ public: Remove( aItem ); delete aItem; } + + /** + * @brief Fetch the zone settings for this container + */ + const ZONE_SETTINGS& GetZoneSettings() const + { + return m_zoneSettings; + } + + /** + * @brief Set the zone settings for this container + * @param aSettings new Zone settings for this container + */ + void SetZoneSettings( const ZONE_SETTINGS& aSettings ) + { + m_zoneSettings = aSettings; + } + +private: + ZONE_SETTINGS m_zoneSettings; }; #endif /* BOARD_ITEM_CONTAINER_H */ diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 5c77bfdb69..d7619baf96 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -1519,6 +1519,29 @@ MODULE* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer return NULL; } +std::list BOARD::GetZoneList( bool aIncludeZonesInFootprints ) +{ + std::list zones; + + for( int ii = 0; ii < GetAreaCount(); ii++ ) + { + zones.push_back( GetArea( ii ) ); + } + + if( aIncludeZonesInFootprints ) + { + for( MODULE* mod : m_modules ) + { + for( ZONE_CONTAINER* zone : mod->Zones() ) + { + zones.push_back( zone ); + } + } + } + + return zones; +} + ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch ) diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index c2ce5745eb..2a6b7d4480 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -192,7 +192,6 @@ private: std::shared_ptr m_connectivity; BOARD_DESIGN_SETTINGS m_designSettings; - ZONE_SETTINGS m_zoneSettings; PCB_GENERAL_SETTINGS* m_generalSettings; ///< reference only; I have no ownership PAGE_INFO m_paper; TITLE_BLOCK m_titles; ///< text in lower right of screen and plots @@ -561,9 +560,6 @@ public: TITLE_BLOCK& GetTitleBlock() { return m_titles; } void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) { m_titles = aTitleBlock; } - const ZONE_SETTINGS& GetZoneSettings() const { return m_zoneSettings; } - void SetZoneSettings( const ZONE_SETTINGS& aSettings ) { m_zoneSettings = aSettings; } - wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override; /** @@ -948,6 +944,12 @@ public: return -1; } + /** + * Function GetZoneList + * @return a std::list of pointers to all board zones (possibly including zones in footprints) + */ + std::list GetZoneList( bool aIncludeZonesInFootprints = false ); + /** * Function GetAreaCount * @return int - The number of Areas or ZONE_CONTAINER. diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 06ce25195b..aed02f83ec 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -108,6 +108,10 @@ MODULE::MODULE( const MODULE& aModule ) : Add( new D_PAD( *pad ) ); } + // Copy auxiliary data: Zones + for( auto item : aModule.Zones() ) + Add( static_cast( item->Clone() ) ); + // Copy auxiliary data: Drawings for( auto item : aModule.GraphicalItems() ) { @@ -152,6 +156,11 @@ MODULE::~MODULE() m_pads.clear(); + for( auto p : m_zones ) + delete p; + + m_zones.clear(); + for( auto d : m_drawings ) delete d; @@ -197,6 +206,14 @@ MODULE& MODULE::operator=( const MODULE& aOther ) Add( new D_PAD( *pad ) ); } + // Copy auxiliary data: Zones + m_zones.clear(); + + for( auto item : aOther.Zones() ) + { + Add( static_cast( item->Clone() ) ); + } + // Copy auxiliary data: Drawings m_drawings.clear(); @@ -261,6 +278,13 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode ) m_pads.push_front( static_cast( aBoardItem ) ); break; + case PCB_ZONE_AREA_T: + if( aMode == ADD_APPEND ) + m_zones.push_back( static_cast( aBoardItem ) ); + else + m_zones.insert( m_zones.begin(), static_cast( aBoardItem ) ); + break; + default: { wxString msg; @@ -313,6 +337,18 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem ) break; + case PCB_ZONE_AREA_T: + for( auto it = m_zones.begin(); it != m_zones.end(); ++it ) + { + if( *it == static_cast( aBoardItem ) ) + { + m_zones.erase( it ); + break; + } + } + + break; + default: { wxString msg; @@ -329,6 +365,9 @@ void MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset ) for( auto pad : m_pads ) pad->Print( aFrame, aDC, aOffset ); + for( auto zone : m_zones ) + zone->Print( aFrame, aDC, aOffset ); + BOARD* brd = GetBoard(); // Draw graphic items @@ -385,6 +424,9 @@ EDA_RECT MODULE::GetFootprintRect() const for( auto pad : m_pads ) area.Merge( pad->GetBoundingBox() ); + for( auto zone : m_zones ) + area.Merge( zone->GetBoundingBox() ); + return area; } @@ -590,6 +632,12 @@ bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) co return true; } + for( auto zone : m_zones ) + { + if( zone->HitTest( arect, false, 0 ) ) + return true; + } + for( auto item : m_drawings ) { if( item->HitTest( arect, false, 0 ) ) @@ -742,6 +790,11 @@ SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T ++p; break; + case PCB_ZONE_AREA_T: + result = IterateForward( m_zones, inspector, testData, p ); + ++p; + break; + case PCB_MODULE_TEXT_T: result = inspector( m_Reference, testData ); @@ -819,6 +872,9 @@ void MODULE::RunOnChildren( const std::function& aFunction ) for( auto pad : m_pads ) aFunction( static_cast( pad ) ); + for( auto zone : m_zones ) + aFunction( static_cast( zone ) ); + for( auto drawing : m_drawings ) aFunction( static_cast( drawing ) ); @@ -1023,6 +1079,10 @@ void MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) for( auto pad : m_pads ) pad->Flip( m_Pos, false ); + // Mirror zones to other side of board. + for( auto zone : m_zones ) + zone->Flip( m_Pos, aFlipLeftRight ); + // Mirror reference and value. m_Reference->Flip( m_Pos, false ); m_Value->Flip( m_Pos, false ); @@ -1068,6 +1128,9 @@ void MODULE::SetPosition( const wxPoint& newpos ) pad->SetPosition( pad->GetPosition() + delta ); } + for( auto zone : m_zones ) + zone->Move( delta ); + for( auto item : m_drawings ) { switch( item->Type() ) @@ -1167,6 +1230,11 @@ void MODULE::SetOrientation( double newangle ) pad->SetDrawCoord(); } + for( auto zone : m_zones ) + { + zone->Rotate( GetPosition(), angleChange ); + } + // Update of the reference and value. m_Reference->SetDrawCoord(); m_Value->SetDrawCoord(); @@ -1193,6 +1261,7 @@ BOARD_ITEM* MODULE::Duplicate( const BOARD_ITEM* aItem, { BOARD_ITEM* new_item = NULL; D_PAD* new_pad = NULL; + ZONE_CONTAINER* new_zone = NULL; switch( aItem->Type() ) { @@ -1207,6 +1276,17 @@ BOARD_ITEM* MODULE::Duplicate( const BOARD_ITEM* aItem, break; } + case PCB_ZONE_AREA_T: + { + new_zone = new ZONE_CONTAINER( *static_cast( aItem ) ); + + if( aAddToModule ) + m_zones.push_back( new_zone ); + + new_item = new_zone; + break; + } + case PCB_MODULE_TEXT_T: { const TEXTE_MODULE* old_text = static_cast( aItem ); diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 2b3eee9195..09d9ea59f8 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -41,8 +41,9 @@ #include #include -#include #include "zones.h" +#include +#include #include @@ -105,6 +106,7 @@ class MODULE_3D_SETTINGS DECL_DEQ_FOR_SWIG( PADS, D_PAD* ) DECL_DEQ_FOR_SWIG( DRAWINGS, BOARD_ITEM* ) +DECL_VEC_FOR_SWIG( ZONE_CONTAINERS, ZONE_CONTAINER* ) DECL_DEQ_FOR_SWIG( MODULES, MODULE* ) class MODULE : public BOARD_ITEM_CONTAINER @@ -177,6 +179,11 @@ public: return m_drawings; } + const ZONE_CONTAINERS& Zones() const + { + return m_zones; + } + const DRAWINGS& GraphicalItems() const { return m_drawings; @@ -662,8 +669,9 @@ public: #endif private: - DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer. - PADS m_pads; // D_PAD items, owned by pointer + DRAWINGS m_drawings; // BOARD_ITEMs for drawings on the board, owned by pointer. + PADS m_pads; // D_PAD items, owned by pointer + ZONE_CONTAINERS m_zones; // ZONE items, owned by pointer std::list m_3D_Drawings; // Linked list of 3D models. double m_Orient; // Orientation in tenths of a degree, 900=90.0 degrees. diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index b5aa0d1d94..454f22ec8c 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -42,8 +42,8 @@ #include -ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) : - BOARD_CONNECTED_ITEM( aBoard, PCB_ZONE_AREA_T ) +ZONE_CONTAINER::ZONE_CONTAINER( BOARD_ITEM_CONTAINER* aParent ) + : BOARD_CONNECTED_ITEM( aParent, PCB_ZONE_AREA_T ) { m_CornerSelection = nullptr; // no corner is selected m_IsFilled = false; // fill status : true when the zone is filled @@ -67,14 +67,14 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) : SetLocalFlags( 0 ); // flags tempoarry used in zone calculations m_Poly = new SHAPE_POLY_SET(); // Outlines m_FilledPolysUseThickness = true; // set the "old" way to build filled polygon areas (before 6.0.x) - aBoard->GetZoneSettings().ExportSetting( *this ); + aParent->GetZoneSettings().ExportSetting( *this ); m_needRefill = false; // True only after some edition. } -ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) : - BOARD_CONNECTED_ITEM( aZone ) +ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) + : BOARD_CONNECTED_ITEM( aZone.GetParent(), PCB_ZONE_AREA_T ) { m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly ); diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 22f7b000d9..bcc170e346 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -63,7 +63,7 @@ public: */ typedef enum HATCH_STYLE { NO_HATCH, DIAGONAL_FULL, DIAGONAL_EDGE } HATCH_STYLE; - ZONE_CONTAINER( BOARD* parent ); + ZONE_CONTAINER( BOARD_ITEM_CONTAINER* parent ); ZONE_CONTAINER( const ZONE_CONTAINER& aZone ); ZONE_CONTAINER& operator=( const ZONE_CONTAINER &aOther ); diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index 4760bbb4bc..21ac7500e3 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -107,21 +107,12 @@ const KICAD_T GENERAL_COLLECTOR::PadsOrTracks[] = { }; -const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = { - PCB_MODULE_TEXT_T, - PCB_MODULE_EDGE_T, - PCB_PAD_T, - PCB_MODULE_T, - EOT -}; +const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = { PCB_MODULE_TEXT_T, PCB_MODULE_EDGE_T, + PCB_PAD_T, PCB_MODULE_T, PCB_ZONE_AREA_T, EOT }; -const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = { - PCB_MODULE_TEXT_T, - PCB_MODULE_EDGE_T, - PCB_PAD_T, - EOT -}; +const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = { PCB_MODULE_TEXT_T, PCB_MODULE_EDGE_T, PCB_PAD_T, + PCB_ZONE_AREA_T, EOT }; const KICAD_T GENERAL_COLLECTOR::Tracks[] = { diff --git a/pcbnew/footprint_editor_utils.cpp b/pcbnew/footprint_editor_utils.cpp index 35f1909b54..f943a201e7 100644 --- a/pcbnew/footprint_editor_utils.cpp +++ b/pcbnew/footprint_editor_utils.cpp @@ -385,6 +385,38 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem ) InstallGraphicItemPropertiesDialog( aItem ); break; + case PCB_ZONE_AREA_T: + { + ZONE_CONTAINER* zone = static_cast( aItem ); + bool success = false; + if( zone ) + { + ZONE_SETTINGS zoneSettings; + zoneSettings << *zone; + if( zone->GetIsKeepout() ) + { + success = InvokeKeepoutAreaEditor( this, &zoneSettings ); + } + else if( zone->IsOnCopperLayer() ) + { + success = InvokeCopperZonesEditor( this, &zoneSettings ); + } + else + { + success = InvokeNonCopperZonesEditor( this, &zoneSettings ); + } + + if( success ) + { + BOARD_COMMIT commit( this ); + commit.Modify( zone ); + commit.Push( _( "Edit Zone" ) ); + zoneSettings.ExportSetting( *zone ); + } + } + } + break; + default: break; } diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 22a6ef34fc..10a72c0dbe 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -1140,6 +1140,10 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const for( auto pad : aModule->Pads() ) format( pad, aNestLevel+1 ); + // Save zones. + for( auto zone : aModule->Zones() ) + format( zone, aNestLevel + 1 ); + // Save 3D info. auto bs3D = aModule->Models().begin(); auto es3D = aModule->Models().end(); diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index a9d6eebac6..f236359d33 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -62,7 +62,8 @@ class TEXTE_PCB; //#define SEXPR_BOARD_FILE_VERSION 20190421 // curves in custom pads //#define SEXPR_BOARD_FILE_VERSION 20190516 // Remove segment count from zones //#define SEXPR_BOARD_FILE_VERSION 20190605 // Add layer defaults -#define SEXPR_BOARD_FILE_VERSION 20190905 // Add board physical stackup info in setup section +//#define SEXPR_BOARD_FILE_VERSION 20190905 // Add board physical stackup info in setup section +#define SEXPR_BOARD_FILE_VERSION 20190907 // Keepout areas in footprints #define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names #define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library) diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp index c9ee37f964..827f919dbd 100644 --- a/pcbnew/menubar_footprint_editor.cpp +++ b/pcbnew/menubar_footprint_editor.cpp @@ -228,15 +228,16 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar() placeMenu->AddItem( PCB_ACTIONS::placePad, haveFootprintCondition ); placeMenu->AddSeparator(); - placeMenu->AddItem( PCB_ACTIONS::placeText, haveFootprintCondition ); - placeMenu->AddItem( PCB_ACTIONS::drawArc, haveFootprintCondition ); - placeMenu->AddItem( PCB_ACTIONS::drawCircle, haveFootprintCondition ); - placeMenu->AddItem( PCB_ACTIONS::drawLine, haveFootprintCondition ); + placeMenu->AddItem( PCB_ACTIONS::placeText, haveFootprintCondition ); + placeMenu->AddItem( PCB_ACTIONS::drawArc, haveFootprintCondition ); + placeMenu->AddItem( PCB_ACTIONS::drawCircle, haveFootprintCondition ); + placeMenu->AddItem( PCB_ACTIONS::drawLine, haveFootprintCondition ); placeMenu->AddItem( PCB_ACTIONS::drawPolygon, haveFootprintCondition ); + placeMenu->AddItem( PCB_ACTIONS::drawZoneKeepout, haveFootprintCondition ); placeMenu->AddSeparator(); - placeMenu->AddItem( PCB_ACTIONS::setAnchor, haveFootprintCondition ); - placeMenu->AddItem( ACTIONS::gridSetOrigin, haveFootprintCondition ); + placeMenu->AddItem( PCB_ACTIONS::setAnchor, haveFootprintCondition ); + placeMenu->AddItem( ACTIONS::gridSetOrigin, haveFootprintCondition ); placeMenu->Resolve(); diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index fba802e853..fb2e09fc40 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -74,6 +74,7 @@ void PCB_PARSER::init() } m_layerMasks[ "*.Cu" ] = LSET::AllCuMask(); + m_layerMasks["*In.Cu"] = LSET::InternalCuMask(); m_layerMasks[ "F&B.Cu" ] = LSET( 2, F_Cu, B_Cu ); m_layerMasks[ "*.Adhes" ] = LSET( 2, B_Adhes, F_Adhes ); m_layerMasks[ "*.Paste" ] = LSET( 2, B_Paste, F_Paste ); @@ -590,7 +591,7 @@ BOARD* PCB_PARSER::parseBOARD_unchecked() break; case T_zone: - m_board->Add( parseZONE_CONTAINER(), ADD_APPEND ); + m_board->Add( parseZONE_CONTAINER( m_board ), ADD_APPEND ); break; case T_target: @@ -2511,12 +2512,21 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments ) module->Add3DModel( parse3DModel() ); break; + case T_zone: + { + ZONE_CONTAINER* zone = parseZONE_CONTAINER( module.get() ); + module->Add( zone, ADD_APPEND ); + } + break; + default: - Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, " - "autoplace_cost90, autoplace_cost180, solder_mask_margin, " - "solder_paste_margin, solder_paste_ratio, clearance, " - "zone_connect, thermal_width, thermal_gap, attr, fp_text, " - "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, or model" ); + Expecting( + "locked, placed, tedit, tstamp, at, descr, tags, path, " + "autoplace_cost90, autoplace_cost180, solder_mask_margin, " + "solder_paste_margin, solder_paste_ratio, clearance, " + "zone_connect, thermal_width, thermal_gap, attr, fp_text, " + "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, " + "zone, or model" ); } } @@ -3390,7 +3400,7 @@ VIA* PCB_PARSER::parseVIA() } -ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() +ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER( BOARD_ITEM_CONTAINER* aParent ) { wxCHECK_MSG( CurTok() == T_zone, NULL, wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + @@ -3407,7 +3417,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() // bigger scope since each filled_polygon is concatenated in here SHAPE_POLY_SET pts; - std::unique_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) ); + std::unique_ptr zone( new ZONE_CONTAINER( aParent ) ); zone->SetPriority( 0 ); diff --git a/pcbnew/pcb_parser.h b/pcbnew/pcb_parser.h index 0cbfd3cee3..cad4804433 100644 --- a/pcbnew/pcb_parser.h +++ b/pcbnew/pcb_parser.h @@ -41,6 +41,7 @@ class BOARD; class BOARD_ITEM; +class BOARD_ITEM_CONTAINER; class D_PAD; class BOARD_DESIGN_SETTINGS; class DIMENSION; @@ -156,7 +157,7 @@ class PCB_PARSER : public PCB_LEXER bool parseD_PAD_option( D_PAD* aPad ); TRACK* parseTRACK(); VIA* parseVIA(); - ZONE_CONTAINER* parseZONE_CONTAINER(); + ZONE_CONTAINER* parseZONE_CONTAINER( BOARD_ITEM_CONTAINER* aParent ); PCB_TARGET* parsePCB_TARGET(); BOARD* parseBOARD(); diff --git a/pcbnew/toolbars_footprint_editor.cpp b/pcbnew/toolbars_footprint_editor.cpp index 370350c17f..3de90325a2 100644 --- a/pcbnew/toolbars_footprint_editor.cpp +++ b/pcbnew/toolbars_footprint_editor.cpp @@ -53,7 +53,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateHToolbar() #ifdef KICAD_SCRIPTING m_mainToolBar->Add( PCB_ACTIONS::createFootprint ); #endif - + if( IsCurrentFPFromBoard() ) m_mainToolBar->Add( PCB_ACTIONS::saveToBoard ); else @@ -129,18 +129,19 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar() m_drawToolBar->Add( ACTIONS::selectionTool, ACTION_TOOLBAR::TOGGLE ); KiScaledSeparator( m_drawToolBar, this ); - m_drawToolBar->Add( PCB_ACTIONS::placePad, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawLine, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::drawPolygon, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::placePad, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawLine, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawPolygon, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawZoneKeepout, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); KiScaledSeparator( m_drawToolBar, this ); - m_drawToolBar->Add( PCB_ACTIONS::setAnchor, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( PCB_ACTIONS::gridSetOrigin, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::setAnchor, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::gridSetOrigin, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( ACTIONS::measureTool, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Realize(); } @@ -205,6 +206,7 @@ void FOOTPRINT_EDIT_FRAME::SyncToolbars() TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawCircle ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawArc ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawPolygon ); + TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::drawZoneKeepout ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::placeText ); TOGGLE_TOOL( m_drawToolBar, ACTIONS::deleteTool ); TOGGLE_TOOL( m_drawToolBar, PCB_ACTIONS::setAnchor ); diff --git a/pcbnew/tools/drc.cpp b/pcbnew/tools/drc.cpp index c6516994e5..d687b9d77c 100644 --- a/pcbnew/tools/drc.cpp +++ b/pcbnew/tools/drc.cpp @@ -882,10 +882,12 @@ void DRC::testZones() void DRC::testKeepoutAreas() { + // Get a list of all zones to inspect, from both board and footprints + std::list areasToInspect = m_pcb->GetZoneList( true ); + // Test keepout areas for vias, tracks and pads inside keepout areas - for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ ) + for( ZONE_CONTAINER* area : areasToInspect ) { - ZONE_CONTAINER* area = m_pcb->GetArea( ii ); if( !area->GetIsKeepout() ) continue; diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 58482c9730..40264de9b7 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -1461,6 +1461,14 @@ bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOn switch( aItem->Type() ) { case PCB_ZONE_AREA_T: + { + // Check to see if this keepout is part of a footprint + // If it is, and we are not editing the footprint, it should not be selectable + const bool zoneInFootprint = + aItem->GetParent() != nullptr && aItem->GetParent()->Type() == PCB_MODULE_T; + if( zoneInFootprint && !m_editModules && !checkVisibilityOnly ) + return false; + // Keepout zones can exist on multiple layers! { auto* zone = static_cast( aItem ); @@ -1481,6 +1489,7 @@ bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOn return false; } } + } break; case PCB_TRACE_T: @@ -1543,6 +1552,12 @@ bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOn return true; } + for( auto zone : module->Zones() ) + { + if( Selectable( zone, true ) ) + return true; + } + return false; } diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp index e558187a19..c5712d26c9 100644 --- a/pcbnew/tools/zone_create_helper.cpp +++ b/pcbnew/tools/zone_create_helper.cpp @@ -51,8 +51,9 @@ ZONE_CREATE_HELPER::~ZONE_CREATE_HELPER() std::unique_ptr ZONE_CREATE_HELPER::createNewZone( bool aKeepout ) { - auto& frame = *m_tool.getEditFrame(); + auto& frame = *m_tool.getEditFrame(); auto& board = *m_tool.getModel(); + BOARD_ITEM_CONTAINER* parent = m_tool.m_frame->GetModel(); KIGFX::VIEW_CONTROLS* controls = m_tool.GetManager()->GetViewControls(); // Get the current default settings for zones @@ -85,7 +86,7 @@ std::unique_ptr ZONE_CREATE_HELPER::createNewZone( bool aKeepout controls->WarpCursor( controls->GetCursorPosition(), true ); } - auto newZone = std::make_unique( &board ); + auto newZone = std::make_unique( parent ); // Apply the selected settings zoneInfo.ExportSetting( *newZone ); diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index f4f622cf35..d986632e9c 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -621,9 +621,8 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, SHAPE_ // Add zones outlines having an higher priority and keepout // - for( int ii = 0; ii < m_board->GetAreaCount(); ii++ ) + for( ZONE_CONTAINER* zone : m_board->GetZoneList( true ) ) { - ZONE_CONTAINER* zone = m_board->GetArea( ii ); // If the zones share no common layers if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )