diff --git a/gerbview/select_layers_to_pcb.cpp b/gerbview/select_layers_to_pcb.cpp index 08787df517..b70a7fa5a8 100644 --- a/gerbview/select_layers_to_pcb.cpp +++ b/gerbview/select_layers_to_pcb.cpp @@ -27,13 +27,14 @@ */ #include -#include +#include +#include #include #include #include #include -#include -#include +#include +#include #include @@ -204,6 +205,46 @@ void LAYERS_MAP_DIALOG::initDialog() m_layersList[ii] = text; } + + std::vector gerber2KicadMapping; + + // See how many of the loaded Gerbers have Altium file extensions + int numAltiumGerbers = findNumAltiumGerbersLoaded( gerber2KicadMapping ); + + if( numAltiumGerbers > 0 ) + { + // See if the user wants to map the Altium Gerbers to known KiCad PCB layers + int returnVal = wxMessageBox( + _( "Gerbers with known layers: " + wxString::Format( wxT( "%i" ), numAltiumGerbers ) + + "\n\nAssign to matching KiCad PCB layers?" ), + _( "Automatic Layer Assignment" ), wxOK | wxCANCEL | wxOK_DEFAULT ); + + if( returnVal == wxOK ) + { + for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ ) + { + int currLayer = gerber2KicadMapping[ii]; + + // Default to "Do Not Export" for unselected or undefined layer + if( ( currLayer == UNSELECTED_LAYER ) || ( currLayer == UNDEFINED_LAYER ) ) + { + m_layersList[ii]->SetLabel( _( "Do not export" ) ); + m_layersList[ii]->SetForegroundColour( *wxBLUE ); + + // Set the layer internally to unselected + m_layersLookUpTable[ii] = UNSELECTED_LAYER; + } + else + { + m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( currLayer ) ); + m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) ); + + // Set the layer internally to the matching KiCad layer + m_layersLookUpTable[ii] = currLayer; + } + } + } + } } /* Ensure m_exportBoardCopperLayersCount = 2 to BOARD_COPPER_LAYERS_MAX_COUNT @@ -383,3 +424,92 @@ void LAYERS_MAP_DIALOG::OnOkClick( wxCommandEvent& event ) EndModal( wxID_OK ); } + +int LAYERS_MAP_DIALOG::findNumAltiumGerbersLoaded( std::vector& aGerber2KicadMapping ) +{ + // The next comment preserves initializer formatting below it + // clang-format off + // This map contains the known Altium file extensions for Gerbers that we care about, + // along with their corresponding KiCad layer + std::map altiumExt{ + { "GTL", F_Cu }, // Top copper + { "G1", In1_Cu }, // Inner layers 1 - 30 + { "G2", In2_Cu }, + { "G3", In3_Cu }, + { "G4", In4_Cu }, + { "G5", In5_Cu }, + { "G6", In6_Cu }, + { "G7", In7_Cu }, + { "G8", In8_Cu }, + { "G9", In9_Cu }, + { "G10", In10_Cu }, + { "G11", In11_Cu }, + { "G12", In12_Cu }, + { "G13", In13_Cu }, + { "G14", In14_Cu }, + { "G15", In15_Cu }, + { "G16", In16_Cu }, + { "G17", In17_Cu }, + { "G18", In18_Cu }, + { "G19", In19_Cu }, + { "G20", In20_Cu }, + { "G21", In21_Cu }, + { "G22", In22_Cu }, + { "G23", In23_Cu }, + { "G24", In24_Cu }, + { "G25", In25_Cu }, + { "G26", In26_Cu }, + { "G27", In27_Cu }, + { "G28", In28_Cu }, + { "G29", In29_Cu }, + { "G30", In30_Cu }, + { "GBL", B_Cu }, // Bottom copper + { "GTP", F_Paste }, // Paste top + { "GBP", B_Paste }, // Paste bottom + { "GTO", F_SilkS }, // Silkscreen top + { "GBO", B_SilkS }, // Silkscreen bottom + { "GTS", F_Mask }, // Soldermask top + { "GBS", B_Mask }, // Soldermask bottom + { "GM1", Eco1_User }, // Altium mechanical layer 1 + { "GM2", Eco2_User }, // Altium mechanical layer 2 + { "GKO", Edge_Cuts } // PCB Outline + }; + // clang-format on + + std::map::iterator it; + + int numAltiumMatches = 0; // Assume we won't find Altium Gerbers + + GERBER_FILE_IMAGE_LIST* images = m_Parent->GetGerberLayout()->GetImagesList(); + + // Loop through all loaded Gerbers looking for any with Altium specific extensions + for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ ) + { + // Get file name of Gerber loaded on this layer. + wxFileName fn( images->GetGbrImage( ii )->m_FileName ); + + // Get uppercase version of file extension + wxString FileExt = fn.GetExt(); + FileExt.MakeUpper(); + + // Check for matching Altium Gerber file extension we'll handle + it = altiumExt.find( FileExt ); + + if( it != altiumExt.end() ) + { + // We got a match, so store the KiCad layer number + aGerber2KicadMapping.push_back( it->second ); + numAltiumMatches++; + } + else + { + // If there's no Altium match, then note the layer as unselected + aGerber2KicadMapping.push_back( UNSELECTED_LAYER ); + } + } + + // Return number of Altium Gerbers we found. Each index in the passed vector corresponds to + // a loaded Gerber layer, and the entry will contain the index to the matching + // KiCad layer for Altium Gerbers, or "UNSELECTED_LAYER" for the rest. + return numAltiumMatches; +} diff --git a/gerbview/select_layers_to_pcb.h b/gerbview/select_layers_to_pcb.h index 858cc02afe..8710b50da3 100644 --- a/gerbview/select_layers_to_pcb.h +++ b/gerbview/select_layers_to_pcb.h @@ -63,6 +63,21 @@ private: void OnGetSetup( wxCommandEvent& event ) override; void OnResetClick( wxCommandEvent& event ) override; + /** + * Finds number of loaded Gerbers using Altium file extensions + * + * The passed vector will be returned with the same number of elements + * as there are Gerber files. The indices into it are 1:1 with the loaded Gerber + * files. Any Gerber that maps will have it's entry set to the KiCad PCB layer + * number. Gerbers that aren't using Altium extensions or which don't map to an + * equivalent KiCad PCB layer will be set to UNSELECTED_LAYER. + * + * @param aGerber2KicadMapping passed to return KiCad PCB layer number for each Gerber + * + * @return int - The number of loaded Gerbers that have Altium extensions + */ + int findNumAltiumGerbersLoaded( std::vector& aGerber2KicadMapping ); + DECLARE_EVENT_TABLE() };