diff --git a/api/proto/board/board_commands.proto b/api/proto/board/board_commands.proto index 3021a71514..e5438182a1 100644 --- a/api/proto/board/board_commands.proto +++ b/api/proto/board/board_commands.proto @@ -189,6 +189,42 @@ message PadShapeAsPolygonResponse repeated kiapi.common.types.PolygonWithHoles polygons = 2; } +// Tests if the given set of items with padstacks (pads or vias) has content on the given set of layers. +// This is a dynamic call rather than a property of the padstack because pads and vias can be set to only include +// shapes on connected copper layers, and whether or not the pad is connected can't be determined in isolation. +// To optimize API call performance, multiple items and multiple layers to test may be passed in with this +// command message. The return will include the results for each valid item on each valid layer. +// Note that not all layers make sense for a given item (for example, testing against BL_UNDEFINED never makes +// sense). In general, the internal KiCad APIs will not return an error when testing non-sensical layers for a given +// item, and instead will return a default of "true" for any such layers. +message CheckPadstackPresenceOnLayers +{ + kiapi.common.types.DocumentSpecifier board = 1; + + repeated kiapi.common.types.KIID items = 2; + + repeated kiapi.board.types.BoardLayer layers = 3; +} + +enum PadstackPresence +{ + PSP_UNKNOWN = 0; + PSP_PRESENT = 1; // The padstack has a shape on a given layer (is flashed) + PSP_NOT_PRESENT = 2; // The padstack has no shape on a given layer (is not flashed) +} + +message PadstackPresenceEntry +{ + kiapi.common.types.KIID item = 1; + kiapi.board.types.BoardLayer layer = 2; + PadstackPresence presence = 3; +} + +message PadstackPresenceResponse +{ + repeated PadstackPresenceEntry entries = 1; +} + // PCB editor commands // returns BoardLayers diff --git a/pcbnew/api/api_handler_pcb.cpp b/pcbnew/api/api_handler_pcb.cpp index bd6c0fbf0d..d47b8b12fd 100644 --- a/pcbnew/api/api_handler_pcb.cpp +++ b/pcbnew/api/api_handler_pcb.cpp @@ -78,6 +78,8 @@ API_HANDLER_PCB::API_HANDLER_PCB( PCB_EDIT_FRAME* aFrame ) : &API_HANDLER_PCB::handleGetBoundingBox ); registerHandler( &API_HANDLER_PCB::handleGetPadShapeAsPolygon ); + registerHandler( + &API_HANDLER_PCB::handleCheckPadstackPresenceOnLayers ); registerHandler( &API_HANDLER_PCB::handleGetTitleBlockInfo ); registerHandler( @@ -1056,6 +1058,73 @@ HANDLER_RESULT API_HANDLER_PCB::handleGetPadShapeAsPo } +HANDLER_RESULT API_HANDLER_PCB::handleCheckPadstackPresenceOnLayers( + const HANDLER_CONTEXT& aCtx ) +{ + using board::types::BoardLayer; + + if( HANDLER_RESULT documentValidation = validateDocument( aCtx.Request.board() ); + !documentValidation ) + { + return tl::unexpected( documentValidation.error() ); + } + + PadstackPresenceResponse response; + + LSET layers; + + for( const int layer : aCtx.Request.layers() ) + layers.set( FromProtoEnum( static_cast( layer ) ) ); + + for( const types::KIID& padRequest : aCtx.Request.items() ) + { + KIID id( padRequest.value() ); + std::optional optItem = getItemById( id ); + + if( !optItem ) + continue; + + switch( ( *optItem )->Type() ) + { + case PCB_PAD_T: + { + PAD* pad = static_cast( *optItem ); + + for( PCB_LAYER_ID layer : layers ) + { + PadstackPresenceEntry* entry = response.add_entries(); + entry->mutable_item()->set_value( pad->m_Uuid.AsStdString() ); + entry->set_layer( ToProtoEnum( layer ) ); + entry->set_presence( pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT ); + } + + break; + } + + case PCB_VIA_T: + { + PCB_VIA* via = static_cast( *optItem ); + + for( PCB_LAYER_ID layer : layers ) + { + PadstackPresenceEntry* entry = response.add_entries(); + entry->mutable_item()->set_value( via->m_Uuid.AsStdString() ); + entry->set_layer( ToProtoEnum( layer ) ); + entry->set_presence( via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT ); + } + + break; + } + + default: + break; + } + } + + return response; +} + + HANDLER_RESULT API_HANDLER_PCB::handleGetTitleBlockInfo( const HANDLER_CONTEXT& aCtx ) { diff --git a/pcbnew/api/api_handler_pcb.h b/pcbnew/api/api_handler_pcb.h index e02626dfd5..c44b0a0a36 100644 --- a/pcbnew/api/api_handler_pcb.h +++ b/pcbnew/api/api_handler_pcb.h @@ -103,6 +103,9 @@ private: HANDLER_RESULT handleGetPadShapeAsPolygon( const HANDLER_CONTEXT& aCtx ); + HANDLER_RESULT handleCheckPadstackPresenceOnLayers( + const HANDLER_CONTEXT& aCtx ); + HANDLER_RESULT handleGetTitleBlockInfo( const HANDLER_CONTEXT& aCtx );