From a9ac108152b690304c1d8ff074284aed10fbf567 Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Thu, 20 Nov 2025 19:57:50 -0500 Subject: [PATCH] API: Preserve linked symbol properties in footprints Fixes https://gitlab.com/kicad/code/kicad/-/issues/21655 (cherry picked from commit 949be9a63ac07df5adbb58d9f57b9ab456dc7b14) Co-authored-by: Jon Evans --- api/proto/board/board_types.proto | 12 + common/api/api_utils.cpp | 10 + include/api/api_utils.h | 2 + pcbnew/footprint.cpp | 11 +- qa/data/pcbnew/api_kitchen_sink.kicad_pcb | 264 ++++++++++++++++++---- qa/data/pcbnew/api_kitchen_sink.kicad_pro | 5 +- 6 files changed, 253 insertions(+), 51 deletions(-) diff --git a/api/proto/board/board_types.proto b/api/proto/board/board_types.proto index 00398ceadc..b46928ecc6 100644 --- a/api/proto/board/board_types.proto +++ b/api/proto/board/board_types.proto @@ -983,4 +983,16 @@ message FootprintInstance // The sheet path to the associated symbol for this footprint instance, if one exists kiapi.common.types.SheetPath symbol_path = 13; + + // The name of the hierarchical sheet the associated symbol for this footprint exists on, + // or the empty string if there is no associated symbol + string symbol_sheet_name = 14; + + // The filename of the hierarchical sheet the associated symbol for this footprint exists on, + // or the empty string if there is no associated symbol + string symbol_sheet_filename = 15; + + // The the footprint filters given by the symbol this footprint is associated with, + // or the empty string if there is no associated symbol + string symbol_footprint_filters = 16; } diff --git a/common/api/api_utils.cpp b/common/api/api_utils.cpp index 572a6fc9b8..779d8b4ffa 100644 --- a/common/api/api_utils.cpp +++ b/common/api/api_utils.cpp @@ -242,4 +242,14 @@ KICOMMON_API void PackSheetPath( types::SheetPath& aOutput, const KIID_PATH& aIn aOutput.add_path()->set_value( entry.AsStdString() ); } +KICOMMON_API KIID_PATH UnpackSheetPath( const types::SheetPath& aInput ) +{ + KIID_PATH output; + + for( const types::KIID& sheet : aInput.path() ) + output.push_back( KIID( sheet.value() ) ); + + return output; +} + } // namespace kiapi::common diff --git a/include/api/api_utils.h b/include/api/api_utils.h index 3c0c8c7f00..096659c177 100644 --- a/include/api/api_utils.h +++ b/include/api/api_utils.h @@ -80,6 +80,8 @@ KICOMMON_API KIGFX::COLOR4D UnpackColor( const types::Color& aInput ); KICOMMON_API void PackSheetPath( types::SheetPath& aOutput, const KIID_PATH& aInput ); +KICOMMON_API KIID_PATH UnpackSheetPath( const types::SheetPath& aInput ); + } // namespace kiapi::common #endif //KICAD_API_UTILS_H diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index d1624a1448..8a8d5fb345 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -412,10 +412,12 @@ void FOOTPRINT::Serialize( google::protobuf::Any &aContainer ) const modelMsg.set_opacity( model.m_Opacity ); itemMsg->PackFrom( modelMsg ); } - - // Serialized only (can't modify this from the API to change the symbol mapping) kiapi::common::PackSheetPath( *footprint.mutable_symbol_path(), m_path ); + footprint.set_symbol_sheet_name( m_sheetname.ToUTF8() ); + footprint.set_symbol_sheet_filename( m_sheetfile.ToUTF8() ); + footprint.set_symbol_footprint_filters( m_filters.ToUTF8() ); + aContainer.PackFrom( footprint ); } @@ -549,6 +551,11 @@ bool FOOTPRINT::Deserialize( const google::protobuf::Any &aContainer ) SetPrivateLayers( privateLayers ); + m_path = kiapi::common::UnpackSheetPath( footprint.symbol_path() ); + m_sheetname = wxString::FromUTF8( footprint.symbol_sheet_name() ); + m_sheetfile = wxString::FromUTF8( footprint.symbol_sheet_filename() ); + m_filters = wxString::FromUTF8( footprint.symbol_footprint_filters() ); + // Footprint items for( PCB_FIELD* field : m_fields ) { diff --git a/qa/data/pcbnew/api_kitchen_sink.kicad_pcb b/qa/data/pcbnew/api_kitchen_sink.kicad_pcb index 1057b99f55..0f21e68999 100644 --- a/qa/data/pcbnew/api_kitchen_sink.kicad_pcb +++ b/qa/data/pcbnew/api_kitchen_sink.kicad_pcb @@ -1,7 +1,7 @@ (kicad_pcb - (version 20241129) + (version 20241229) (generator "pcbnew") - (generator_version "8.99") + (generator_version "9.0") (general (thickness 1.6) (legacy_teardrops no) @@ -28,23 +28,23 @@ (29 "B.CrtYd" user "B.Courtyard") (35 "F.Fab" user) (33 "B.Fab" user) - (39 "User.1" signal) - (41 "User.2" signal) - (43 "User.3" signal) - (45 "User.4" signal) - (47 "User.5" signal) - (49 "User.6" signal) - (51 "User.7" signal) - (53 "User.8" signal) - (55 "User.9" signal) + (39 "User.1" user) + (41 "User.2" user) + (43 "User.3" user) + (45 "User.4" user) + (47 "User.5" user) + (49 "User.6" user) + (51 "User.7" user) + (53 "User.8" user) + (55 "User.9" user) ) (setup (pad_to_mask_clearance 0) (allow_soldermask_bridges_in_footprints no) (tenting front back) (pcbplotparams - (layerselection 0x000010fc_ffffffff) - (plot_on_all_layers_selection 0x00000000_00000000) + (layerselection 0x00000000_00000000_000010fc_ffffffff) + (plot_on_all_layers_selection 0x00000000_00000000_00000000_00000000) (disableapertmacros no) (usegerberextensions no) (usegerberattributes yes) @@ -62,12 +62,13 @@ (pdf_front_fp_property_popups yes) (pdf_back_fp_property_popups yes) (pdf_metadata yes) + (pdf_single_document no) (dxfpolygonmode yes) (dxfimperialunits yes) (dxfusepcbnewfont yes) (psnegative no) (psa4output no) - (plotinvisibletext no) + (plot_black_and_white yes) (sketchpadsonfab no) (plotpadnumbers no) (hidednponfab no) @@ -83,6 +84,199 @@ ) (net 0 "") (net 1 "A") + (footprint "Resistor_SMD:R_0603_1608Metric" + (layer "F.Cu") + (uuid "0b9cc5a8-6a75-47df-9617-9721c2785946") + (at 125.2 90.9) + (descr "Resistor SMD 0603 (1608 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator") + (tags "resistor") + (property "Reference" "R1" + (at 0 -1.43 0) + (layer "F.SilkS") + (uuid "7d789367-57eb-4a89-8956-2169b84c120e") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "R" + (at 0 1.43 0) + (layer "F.Fab") + (uuid "4903d9e1-b4cb-4af4-88f1-c8e9c590c117") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "~" + (at 0 0 0) + (layer "F.Fab") + (hide yes) + (uuid "cbed5a6d-7fcc-436a-9cd5-87de1585dac3") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "Resistor" + (at 0 0 0) + (layer "F.Fab") + (hide yes) + (uuid "1af7c912-d321-4ec8-98e4-b6bbecf08906") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (attr smd) + (fp_line + (start -0.237258 -0.5225) + (end 0.237258 -0.5225) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "df5c5654-8573-47a8-9a9c-5539d490ddd6") + ) + (fp_line + (start -0.237258 0.5225) + (end 0.237258 0.5225) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "663c3985-2c0d-46c4-9cba-5ffb00711463") + ) + (fp_line + (start -1.48 -0.73) + (end 1.48 -0.73) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "4c286dfe-1c56-4b9e-a3fb-254f7a011f54") + ) + (fp_line + (start -1.48 0.73) + (end -1.48 -0.73) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "aacdfada-abc9-4dca-a142-098910ef78f2") + ) + (fp_line + (start 1.48 -0.73) + (end 1.48 0.73) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "83cbe7d1-69f6-459c-89a1-b9d95099efd3") + ) + (fp_line + (start 1.48 0.73) + (end -1.48 0.73) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "89ca1f58-89f9-4a8b-941d-1e8dc70fe848") + ) + (fp_line + (start -0.8 -0.4125) + (end 0.8 -0.4125) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "6514aa8a-0390-445d-b193-3f6b365040b2") + ) + (fp_line + (start -0.8 0.4125) + (end -0.8 -0.4125) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "f213648a-6c78-4743-a4b3-4dab8d1bfc17") + ) + (fp_line + (start 0.8 -0.4125) + (end 0.8 0.4125) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "4b471b6f-70ab-4004-a645-901dfdcb5dbb") + ) + (fp_line + (start 0.8 0.4125) + (end -0.8 0.4125) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "b802aff4-eff0-4f6b-8129-eeca76a49775") + ) + (fp_text user "${REFERENCE}" + (at 0 0 0) + (layer "F.Fab") + (uuid "a48833d5-ab4e-4078-b8bb-a25d30378127") + (effects + (font + (size 0.4 0.4) + (thickness 0.06) + ) + ) + ) + (pad "1" smd roundrect + (at -0.825 0) + (size 0.8 0.95) + (layers "F.Cu" "F.Mask" "F.Paste") + (roundrect_rratio 0.25) + (pintype "passive+no_connect") + (uuid "68a6e277-4040-4944-ac54-a820abcdc41f") + ) + (pad "2" smd roundrect + (at 0.825 0) + (size 0.8 0.95) + (layers "F.Cu" "F.Mask" "F.Paste") + (roundrect_rratio 0.25) + (pintype "passive+no_connect") + (uuid "dae62be7-5b36-462f-8f68-44e6e11e6733") + ) + (embedded_fonts no) + (model "${KICAD9_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0603_1608Metric.step" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) (footprint "D5" (layer "F.Cu") (uuid "15a9bad1-3969-483f-a7df-b8dcfd5c5be8") @@ -112,19 +306,6 @@ ) ) ) - (property "Footprint" "D5" - (at 0 0 0) - (unlocked yes) - (layer "F.Fab") - (hide yes) - (uuid "9fa72c1a-74e4-4181-a5c3-f6dc09430202") - (effects - (font - (size 1.27 1.27) - (thickness 0.15) - ) - ) - ) (property "Datasheet" "" (at 0 0 0) (unlocked yes) @@ -280,7 +461,7 @@ (max_length 2) (best_width_ratio 0.95) (max_width 3) - (curve_points 0) + (curved_edges no) (filter_ratio 0.8) (enabled yes) (allow_two_segments no) @@ -308,7 +489,7 @@ (descr "Bornier d'alimentation 2 pins") (tags "DEV") (property "Reference" "P2" - (at 0 -5.08 -90) + (at 0 -5.08 270) (layer "F.SilkS") (uuid "ba42dcaf-4533-4d88-b1fa-fdb993574d72") (effects @@ -319,7 +500,7 @@ ) ) (property "Value" "CONN_2" - (at 0 5.08 -90) + (at 0 5.08 270) (layer "F.SilkS") (uuid "66aeb929-e503-4d95-8f48-82e9d57c9ad0") (effects @@ -329,21 +510,8 @@ ) ) ) - (property "Footprint" "bornier2" - (at 0 0 -90) - (unlocked yes) - (layer "F.Fab") - (hide yes) - (uuid "f4c1f82d-5e51-4256-ba8d-645c67392576") - (effects - (font - (size 1.27 1.27) - (thickness 0.15) - ) - ) - ) (property "Datasheet" "" - (at 0 0 -90) + (at 0 0 270) (unlocked yes) (layer "F.Fab") (hide yes) @@ -356,7 +524,7 @@ ) ) (property "Description" "" - (at 0 0 -90) + (at 0 0 270) (unlocked yes) (layer "F.Fab") (hide yes) @@ -908,7 +1076,7 @@ (net 0) (net_name "") (locked yes) - (layers "F&B.Cu") + (layers "F.Cu" "B.Cu") (uuid "0f5227b8-34f3-4302-949f-9de38b16fecf") (name "MyKeepout") (hatch full 0.65) @@ -941,7 +1109,7 @@ (zone (net 0) (net_name "") - (layers "F&B.Cu") + (layers "F.Cu" "B.Cu") (uuid "9c3e186b-0f1d-48ef-8724-baad4fa44742") (hatch edge 1) (connect_pads @@ -978,7 +1146,7 @@ (zone (net 0) (net_name "") - (layers "F&B.Cu") + (layers "F.Cu" "B.Cu") (uuid "f52cce18-23b9-4645-b87a-21d0716548c2") (hatch none 0.65) (connect_pads diff --git a/qa/data/pcbnew/api_kitchen_sink.kicad_pro b/qa/data/pcbnew/api_kitchen_sink.kicad_pro index 7d10d60412..2d7b20255d 100644 --- a/qa/data/pcbnew/api_kitchen_sink.kicad_pro +++ b/qa/data/pcbnew/api_kitchen_sink.kicad_pro @@ -86,9 +86,11 @@ "lib_footprint_mismatch": "warning", "malformed_courtyard": "error", "microvia_drill_out_of_range": "error", + "mirrored_text_on_front_layer": "warning", "missing_courtyard": "ignore", "missing_footprint": "warning", "net_conflict": "warning", + "nonmirrored_text_on_back_layer": "warning", "npth_inside_courtyard": "ignore", "padstack": "warning", "pth_inside_courtyard": "ignore", @@ -100,6 +102,7 @@ "solder_mask_bridge": "error", "starved_thermal": "error", "text_height": "warning", + "text_on_edge_cuts": "error", "text_thickness": "warning", "through_hole_pad_without_hole": "error", "too_many_vias": "error", @@ -229,7 +232,7 @@ }, "meta": { "filename": "api_kitchen_sink.kicad_pro", - "version": 2 + "version": 3 }, "net_settings": { "classes": [