Fix Eagle plugin board layer mapping issue.

The Eagle plugin layers have to be mapped differently depending on
whether a board is being imported or a footprint library is being
cached.  Footprint libraries can bypass the manual layer remapping
step that happens when importing a board.

Please note that when loading footprints in the footprint editor
and viewer, all layers that do not directly map to KiCad layers are
put on the Dwg_User layer so that there is data loss.  Users will
have to manually remap objects to the correct layer as required.
This is less than ideal but until the footprint library table parser
supports prompting users to remap unknown layers, it will have to do.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/11839
(cherry picked from commit 0bc1188897)
This commit is contained in:
Wayne Stambaugh 2022-08-21 14:56:04 -04:00
parent 9328cf42c5
commit c2c4609272
2 changed files with 48 additions and 10 deletions

View File

@ -2857,7 +2857,7 @@ std::map<wxString, PCB_LAYER_ID> EAGLE_PLUGIN::DefaultLayerMappingCallback(
} }
void EAGLE_PLUGIN::mapEagleLayersToKicad() void EAGLE_PLUGIN::mapEagleLayersToKicad( bool aIsLibraryCache )
{ {
std::vector<INPUT_LAYER_DESC> inputDescs; std::vector<INPUT_LAYER_DESC> inputDescs;
@ -2867,7 +2867,7 @@ void EAGLE_PLUGIN::mapEagleLayersToKicad()
INPUT_LAYER_DESC layerDesc; INPUT_LAYER_DESC layerDesc;
std::tie( layerDesc.AutoMapLayer, layerDesc.PermittedLayers, layerDesc.Required ) = std::tie( layerDesc.AutoMapLayer, layerDesc.PermittedLayers, layerDesc.Required ) =
defaultKicadLayer( eLayer.number ); defaultKicadLayer( eLayer.number, aIsLibraryCache );
if( layerDesc.AutoMapLayer == UNDEFINED_LAYER ) if( layerDesc.AutoMapLayer == UNDEFINED_LAYER )
continue; // Ignore unused copper layers continue; // Ignore unused copper layers
@ -2894,7 +2894,8 @@ PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
} }
std::tuple<PCB_LAYER_ID, LSET, bool> EAGLE_PLUGIN::defaultKicadLayer( int aEagleLayer ) const std::tuple<PCB_LAYER_ID, LSET, bool> EAGLE_PLUGIN::defaultKicadLayer( int aEagleLayer,
bool aIsLibraryCache ) const
{ {
// eagle copper layer: // eagle copper layer:
if( aEagleLayer >= 1 && aEagleLayer < int( arrayDim( m_cu_map ) ) ) if( aEagleLayer >= 1 && aEagleLayer < int( arrayDim( m_cu_map ) ) )
@ -3015,7 +3016,19 @@ std::tuple<PCB_LAYER_ID, LSET, bool> EAGLE_PLUGIN::defaultKicadLayer( int aEagle
case EAGLE_LAYER::BTEST: case EAGLE_LAYER::BTEST:
case EAGLE_LAYER::HOLES: case EAGLE_LAYER::HOLES:
default: default:
kiLayer = UNDEFINED_LAYER; if( aIsLibraryCache )
{
if( aEagleLayer != EAGLE_LAYER::MILLING && aEagleLayer != EAGLE_LAYER::TTEST &&
aEagleLayer != EAGLE_LAYER::BTEST && aEagleLayer != EAGLE_LAYER::HOLES )
kiLayer = Dwgs_User;
else
kiLayer = UNDEFINED_LAYER;
}
else
{
kiLayer = UNSELECTED_LAYER;
}
break; break;
} }
@ -3128,7 +3141,7 @@ void EAGLE_PLUGIN::cacheLib( const wxString& aLibPath )
m_xpath->push( "eagle.drawing.layers" ); m_xpath->push( "eagle.drawing.layers" );
wxXmlNode* layers = drawingChildren["layers"]; wxXmlNode* layers = drawingChildren["layers"];
loadLayerDefs( layers ); loadLayerDefs( layers );
mapEagleLayersToKicad(); mapEagleLayersToKicad( true );
m_xpath->pop(); m_xpath->pop();
m_xpath->push( "eagle.drawing.library" ); m_xpath->push( "eagle.drawing.library" );

View File

@ -191,15 +191,40 @@ private:
/// create a font size (fontz) from an eagle font size scalar and KiCad font thickness /// create a font size (fontz) from an eagle font size scalar and KiCad font thickness
wxSize kicad_fontz( const ECOORD& d, int aTextThickness ) const; wxSize kicad_fontz( const ECOORD& d, int aTextThickness ) const;
/// Generate mapping between Eagle na KiCad layers /**
void mapEagleLayersToKicad(); * Generate mapping between Eagle and KiCad layers.
*
* @warning It is imperative that this gets called correctly because footprint libraries
* do not get remapped by the user on load. Otherwise, Pcbnew will crash when
* attempting to load footprint libraries that contain layers that do not exist
* in the #EAGLE_LAYER definitions.
*
* @param aIsLibraryCache is the flag to indicate when mapping the footprint library cache
* layers rather than the board layers.
*/
void mapEagleLayersToKicad( bool aIsLibraryCache = false );
/// Convert an Eagle layer to a KiCad layer. /// Convert an Eagle layer to a KiCad layer.
PCB_LAYER_ID kicad_layer( int aLayer ) const; PCB_LAYER_ID kicad_layer( int aLayer ) const;
/// Get default KiCad layer corresponding to an Eagle layer of the board, /**
/// a set of sensible layer mapping options and required flag * Get the default KiCad layer corresponding to an Eagle layer of the board,
std::tuple<PCB_LAYER_ID, LSET, bool> defaultKicadLayer( int aEagleLayer ) const; * a set of sensible layer mapping options and required flag
*
* @note The Eagle MILLING, TTEST, BTEST, and HOLES layers are set to #UNDEFINED_LAYER
* for historical purposes. All other Eagle layers that do not directly map to
* KiCad layers will be set to the #Dwg_User layer when loading Eagle footprint
* libraries to prevent data loss.
*
* @see #EAGLE_LAYER and defaultKiCadLayer().
*
* @param aEagleLayer is the Eagle layer to map.
* @param aIsLibraryCache is a flag to indicate if the mapping is for board or footprint
* library cache objects.
* @return a tuple containing the mapped layer.
*/
std::tuple<PCB_LAYER_ID, LSET, bool> defaultKicadLayer( int aEagleLayer,
bool aIsLibraryCache = false ) const;
/// Get Eagle layer name by its number /// Get Eagle layer name by its number
const wxString& eagle_layer_name( int aLayer ) const; const wxString& eagle_layer_name( int aLayer ) const;