diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 9be6d1cfb3..e616f25a34 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -165,11 +165,11 @@ void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2 { KIGFX::GAL_DISPLAY_OPTIONS empty_opts; - if( aFootprint->Reference().GetLayer() == aLayerId && aFootprint->Reference().IsVisible() ) - addText( &aFootprint->Reference(), aContainer, &aFootprint->Reference() ); - - if( aFootprint->Value().GetLayer() == aLayerId && aFootprint->Value().IsVisible() ) - addText( &aFootprint->Value(), aContainer, &aFootprint->Value() ); + for( PCB_FIELD* field : aFootprint->GetFields() ) + { + if( field->GetLayer() == aLayerId && field->IsVisible() ) + addText( field, aContainer, field ); + } for( BOARD_ITEM* item : aFootprint->GraphicalItems() ) { diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index c5257a2e22..a577c16eab 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -599,7 +599,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) addShape( static_cast( item ), layerContainer, item ); break; - case PCB_FIELD_T: case PCB_TEXT_T: addText( static_cast( item ), layerContainer, item ); break; @@ -646,7 +645,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE ); break; - case PCB_FIELD_T: case PCB_TEXT_T: { PCB_TEXT* text = static_cast( item ); @@ -920,7 +918,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) addShape( static_cast( item ), layerContainer, item ); break; - case PCB_FIELD_T: case PCB_TEXT_T: addText( static_cast( item ), layerContainer, item ); break; @@ -957,7 +954,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE ); break; - case PCB_FIELD_T: case PCB_TEXT_T: { PCB_TEXT* text = static_cast( item ); diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index d6def1640b..4a2c005544 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -429,6 +429,7 @@ constexpr bool IsPcbnewType( const KICAD_T aType ) case PCB_PAD_T: case PCB_SHAPE_T: case PCB_BITMAP_T: + case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: case PCB_TRACE_T: diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index e154b777d3..e4ab0a67c8 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -431,6 +431,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) switch( boardItem->Type() ) { + case PCB_FIELD_T: case PCB_TEXT_T: case PCB_PAD_T: case PCB_SHAPE_T: // a shape (normally not on copper layers) diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index d695061b36..b35745fe76 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -180,6 +180,7 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) breakhere++; break; + case PCB_FIELD_T: case PCB_TEXT_T: breakhere++; break; @@ -296,16 +297,6 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) if( m_Guide->IgnoreFPTextOnFront() && IsFrontLayer( layer ) ) return INSPECT_RESULT::CONTINUE; - - /* - * The three text types have different criteria: reference and value have their own - * ignore flags; user text instead follows their layer visibility. Checking this here - * is simpler than later (when layer visibility is checked for other entities) - * - * Note: we fallthrough from PCB_FIELD_T above, hence the type check. - */ - if( text->Type() == PCB_TEXT_T && !m_Guide->IsLayerVisible( layer ) ) - return INSPECT_RESULT::CONTINUE; } break; diff --git a/pcbnew/drc/drc_test_provider.cpp b/pcbnew/drc/drc_test_provider.cpp index 6aedc3e3c2..ec0f64d1dd 100644 --- a/pcbnew/drc/drc_test_provider.cpp +++ b/pcbnew/drc/drc_test_provider.cpp @@ -249,20 +249,15 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector& aTypes, { if( typeMask[PCB_FIELD_T] ) { - if( ( footprint->Reference().GetLayerSet() & aLayers ).any() ) + for( PCB_FIELD* field : footprint->GetFields() ) { - if( !aFunc( &footprint->Reference() ) ) - return n; - - n++; - } - - if( ( footprint->Value().GetLayerSet() & aLayers ).any() ) - { - if( !aFunc( &footprint->Value() ) ) - return n; + if( ( field->GetLayerSet() & aLayers ).any() ) + { + if( !aFunc( field ) ) + return n; - n++; + n++; + } } } diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index cf2d776e95..1a76fd1d6d 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -720,6 +720,9 @@ static size_t hashFootprint( const FOOTPRINT* aFootprint ) constexpr int flags = HASH_FLAGS::HASH_POS | HASH_FLAGS::REL_COORD | HASH_FLAGS::HASH_ROT | HASH_FLAGS::HASH_LAYER; + for( PCB_FIELD* i : aFootprint->Fields() ) + ret += hash_fp_item( i, flags ); + for( BOARD_ITEM* i : aFootprint->GraphicalItems() ) ret += hash_fp_item( i, flags ); diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 4a09457bba..8b83efa374 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -954,6 +954,7 @@ const BOX2I FOOTPRINT::GetBoundingBox() const const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const { + std::vector texts; const BOARD* board = GetBoard(); bool isFPEdit = board && board->IsFootprintHolder(); @@ -991,7 +992,10 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisible // Handle text separately if( item->Type() == PCB_TEXT_T ) + { + texts.push_back( static_cast( item ) ); continue; + } // Treat dimension objects as text if( !aIncludeText && BaseType( item->Type() ) == PCB_DIMENSION_T ) @@ -1000,6 +1004,9 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisible bbox.Merge( item->GetBoundingBox() ); } + for( PCB_FIELD* field : m_fields ) + texts.push_back( field ); + for( PAD* pad : m_pads ) bbox.Merge( pad->GetBoundingBox() ); @@ -1011,15 +1018,14 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisible // Groups do not contribute to the rect, only their members if( aIncludeText || noDrawItems ) { - for( BOARD_ITEM* item : m_drawings ) + // Only PCB_TEXT and PCB_FIELD items are independently selectable; + // PCB_TEXTBOX items go in with other graphic items above. + for( PCB_TEXT* text : texts ) { - if( !isFPEdit && m_privateLayers.test( item->GetLayer() ) ) + if( !isFPEdit && m_privateLayers.test( text->GetLayer() ) ) continue; - // Only PCB_TEXT items are independently selectable; PCB_TEXTBOX items go in with - // other graphic items above. - if( item->Type() == PCB_TEXT_T ) - bbox.Merge( item->GetBoundingBox() ); + bbox.Merge( text->GetBoundingBox() ); } // This can be further optimized when aIncludeInvisibleText is true, but currently @@ -1310,18 +1316,14 @@ bool FOOTPRINT::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co return true; } - for( PCB_FIELD* field : m_fields ) - { - if( field->HitTest( arect, false, 0 ) ) - return true; - } - for( ZONE* zone : m_zones ) { if( zone->HitTest( arect, false, 0 ) ) return true; } + // PCB fields are selectable on their own, so they don't get tested + for( BOARD_ITEM* item : m_drawings ) { // Text items are selectable on their own, and are therefore excluded from this @@ -1474,11 +1476,11 @@ INSPECT_RESULT FOOTPRINT::Visit( INSPECTOR inspector, void* testData, break; case PCB_FIELD_T: - if( inspector( &Reference(), testData ) == INSPECT_RESULT::QUIT ) - return INSPECT_RESULT::QUIT; - - if( inspector( &Value(), testData ) == INSPECT_RESULT::QUIT ) + if( IterateForward( m_fields, inspector, testData, { scanType } ) + == INSPECT_RESULT::QUIT ) + { return INSPECT_RESULT::QUIT; + } break; diff --git a/pcbnew/pcb_field.cpp b/pcbnew/pcb_field.cpp index 689b13ad6e..c1b6ddc34f 100644 --- a/pcbnew/pcb_field.cpp +++ b/pcbnew/pcb_field.cpp @@ -128,6 +128,10 @@ wxString PCB_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const return wxString::Format( _( "Datasheet '%s' of %s" ), KIUI::EllipsizeMenuText( GetText() ), GetParentFootprint()->GetReference() ); + default: + return wxString::Format( _( "Field '%s' of %s" ), + KIUI::EllipsizeMenuText( GetText() ), + GetParentFootprint()->GetReference() ); } // Can't get here, but gcc doesn't seem to know that.... diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 4e8bbf6a4f..a3e654a47e 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -278,7 +278,7 @@ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) const PCB_TEXT* textItem = &aFootprint->Reference(); PCB_LAYER_ID textLayer = textItem->GetLayer(); - // Reference and value are specific items, not in graphic items list + // Reference and value have special controls for forcing their plotting if( GetPlotReference() && m_layerMask[textLayer] && ( textItem->IsVisible() || GetPlotInvisibleText() ) ) { @@ -294,17 +294,32 @@ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) PlotText( textItem, textLayer, textItem->IsKnockout() ); } - for( const BOARD_ITEM* item : aFootprint->GraphicalItems() ) + + std::vector texts; + + // Skip the reference and value texts that are handled specially + for( PCB_FIELD* field : aFootprint->Fields() ) + { + if( field->IsReference() || field->IsValue() ) + continue; + + texts.push_back( field ); + } + + for( BOARD_ITEM* item : aFootprint->GraphicalItems() ) { textItem = dyn_cast( item ); - if( !textItem ) - continue; + if( textItem ) + texts.push_back( static_cast( item ) ); + } - if( !textItem->IsVisible() ) + for( const PCB_TEXT* text : texts ) + { + if( !text->IsVisible() ) continue; - textLayer = textItem->GetLayer(); + textLayer = text->GetLayer(); if( textLayer == Edge_Cuts || textLayer >= PCB_LAYER_ID_COUNT ) continue; @@ -312,13 +327,13 @@ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) if( !m_layerMask[textLayer] || aFootprint->GetPrivateLayers().test( textLayer ) ) continue; - if( textItem->GetText() == wxT( "${REFERENCE}" ) && !GetPlotReference() ) + if( text->GetText() == wxT( "${REFERENCE}" ) && !GetPlotReference() ) continue; - if( textItem->GetText() == wxT( "${VALUE}" ) && !GetPlotValue() ) + if( text->GetText() == wxT( "${VALUE}" ) && !GetPlotValue() ) continue; - PlotText( textItem, textLayer, textItem->IsKnockout() ); + PlotText( text, textLayer, textItem->IsKnockout() ); } } @@ -519,7 +534,6 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItems( const FOOTPRINT* aFootprint ) break; } - case PCB_FIELD_T: case PCB_TEXT_T: // Plotted in PlotFootprintTextItems() break; diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index a6774eafb1..31d3566291 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -3837,13 +3837,14 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments field = new PCB_FIELD( footprint.get(), footprint->GetFieldCount(), pName ); field->SetText( pValue ); - field->SetVisible( false ); field->SetLayer( footprint->GetLayer() == F_Cu ? F_Fab : B_Fab ); field->StyleFromSettings( m_board->GetDesignSettings() ); footprint->AddField( field ); } + field->SetVisible( true ); + parsePCB_TEXT_effects( field ); } break; diff --git a/qa/pcbnew_utils/board_test_utils.cpp b/qa/pcbnew_utils/board_test_utils.cpp index e7ad876106..b51590f7f3 100644 --- a/qa/pcbnew_utils/board_test_utils.cpp +++ b/qa/pcbnew_utils/board_test_utils.cpp @@ -153,7 +153,6 @@ struct kitest_cmp_drawings const PCB_TEXT* textA = static_cast( itemA ); const PCB_TEXT* textB = static_cast( itemB ); - TEST( textA->GetType(), textB->GetType() ); TEST_PT( textA->GetPosition(), textB->GetPosition() ); TEST( textA->GetTextAngle(), textB->GetTextAngle() ); } @@ -325,8 +324,6 @@ void CheckFpText( const PCB_TEXT* expected, const PCB_TEXT* text ) { CHECK_ENUM_CLASS_EQUAL( expected->Type(), text->Type() ); - CHECK_ENUM_CLASS_EQUAL( expected->GetType(), text->GetType() ); - BOOST_CHECK_EQUAL( expected->IsLocked(), text->IsLocked() ); BOOST_CHECK_EQUAL( expected->GetText(), text->GetText() ); diff --git a/qa/tests/pcbnew/test_board_item.cpp b/qa/tests/pcbnew/test_board_item.cpp index 4f5a016322..9641dd1a23 100644 --- a/qa/tests/pcbnew/test_board_item.cpp +++ b/qa/tests/pcbnew/test_board_item.cpp @@ -75,6 +75,7 @@ public: { case PCB_FOOTPRINT_T: return new FOOTPRINT( &m_board ); case PCB_PAD_T: return new PAD( &m_footprint ); + case PCB_FIELD_T: return new PCB_FIELD( &m_footprint, m_footprint.GetFieldCount() ); case PCB_SHAPE_T: return new PCB_SHAPE( &m_board ); case PCB_TEXT_T: return new PCB_TEXT( &m_board ); case PCB_TEXTBOX_T: return new PCB_TEXTBOX( &m_board );