Allow a user to remap layers in Eagle import
ADDED Allow for user mapping of layers in Eagle import ADDED Support required and optional layers in the layer mapping dialog ADDED Add base class for plugins supporting remappable layers
This commit is contained in:
parent
f7333ad64a
commit
fc8bf6f0fe
|
@ -24,6 +24,30 @@
|
|||
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
wxString DIALOG_IMPORTED_LAYERS::WrapRequired( const wxString& aLayerName )
|
||||
{
|
||||
return aLayerName + " *";
|
||||
}
|
||||
|
||||
wxString DIALOG_IMPORTED_LAYERS::UnwrapRequired( const wxString& aLayerName )
|
||||
{
|
||||
if( !aLayerName.EndsWith( " *" ) )
|
||||
return aLayerName;
|
||||
return aLayerName.Left( aLayerName.Length() - 2 );
|
||||
}
|
||||
|
||||
const INPUT_LAYER_DESC* DIALOG_IMPORTED_LAYERS::GetLayerDescription(
|
||||
const wxString& aLayerName ) const
|
||||
{
|
||||
wxString layerName = UnwrapRequired( aLayerName );
|
||||
for( const INPUT_LAYER_DESC& layerDescription : m_input_layers )
|
||||
{
|
||||
if( layerDescription.Name == layerName )
|
||||
return &layerDescription;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
PCB_LAYER_ID DIALOG_IMPORTED_LAYERS::GetSelectedLayerID()
|
||||
{
|
||||
|
@ -58,11 +82,15 @@ PCB_LAYER_ID DIALOG_IMPORTED_LAYERS::GetSelectedLayerID()
|
|||
|
||||
PCB_LAYER_ID DIALOG_IMPORTED_LAYERS::GetAutoMatchLayerID( wxString aInputLayerName )
|
||||
{
|
||||
wxString pureInputLayerName = UnwrapRequired( aInputLayerName );
|
||||
for( INPUT_LAYER_DESC inputLayerDesc : m_input_layers )
|
||||
{
|
||||
if( inputLayerDesc.Name == aInputLayerName )
|
||||
if( inputLayerDesc.Name == pureInputLayerName
|
||||
&& inputLayerDesc.AutoMapLayer != PCB_LAYER_ID::UNSELECTED_LAYER )
|
||||
{
|
||||
return inputLayerDesc.AutoMapLayer;
|
||||
}
|
||||
}
|
||||
|
||||
return PCB_LAYER_ID::UNDEFINED_LAYER;
|
||||
}
|
||||
|
@ -90,7 +118,8 @@ void DIALOG_IMPORTED_LAYERS::AddMappings()
|
|||
long newItemIndex = m_matched_layers_list->InsertItem( 0, selectedLayerName );
|
||||
m_matched_layers_list->SetItem( newItemIndex, 1, kiName );
|
||||
|
||||
m_matched_layers_map.insert( { selectedLayerName, selectedKiCadLayerID } );
|
||||
m_matched_layers_map.insert(
|
||||
{ UnwrapRequired( selectedLayerName ), selectedKiCadLayerID } );
|
||||
|
||||
// remove selected layer from vector and also GUI list
|
||||
for( auto iter = m_unmatched_layer_names.begin(); iter != m_unmatched_layer_names.end();
|
||||
|
@ -122,11 +151,12 @@ void DIALOG_IMPORTED_LAYERS::RemoveMappings( int aStatus )
|
|||
!= wxNOT_FOUND )
|
||||
{
|
||||
wxString selectedLayerName = m_matched_layers_list->GetItemText( itemIndex, 0 );
|
||||
wxString pureSelectedLayerName = UnwrapRequired( selectedLayerName );
|
||||
|
||||
wxCHECK( m_matched_layers_map.find( selectedLayerName ) != m_matched_layers_map.end(),
|
||||
wxCHECK( m_matched_layers_map.find( pureSelectedLayerName ) != m_matched_layers_map.end(),
|
||||
/*void*/ );
|
||||
|
||||
m_matched_layers_map.erase( selectedLayerName );
|
||||
m_matched_layers_map.erase( pureSelectedLayerName );
|
||||
rowsToDelete.Add( itemIndex );
|
||||
|
||||
m_unmatched_layers_list->InsertItem( 0, selectedLayerName );
|
||||
|
@ -169,7 +199,7 @@ void DIALOG_IMPORTED_LAYERS::OnAutoMatchLayersClicked( wxCommandEvent& event )
|
|||
long newItemIndex = m_matched_layers_list->InsertItem( 0, layerName );
|
||||
m_matched_layers_list->SetItem( newItemIndex, 1, kiName );
|
||||
|
||||
m_matched_layers_map.insert( { layerName, autoMatchLayer } );
|
||||
m_matched_layers_map.insert( { UnwrapRequired( layerName ), autoMatchLayer } );
|
||||
|
||||
// remove selected layer from vector and also GUI list
|
||||
for( auto iter = m_unmatched_layer_names.begin(); iter != m_unmatched_layer_names.end();
|
||||
|
@ -199,11 +229,12 @@ DIALOG_IMPORTED_LAYERS::DIALOG_IMPORTED_LAYERS( wxWindow* aParent,
|
|||
for( INPUT_LAYER_DESC inLayer : aLayerDesc )
|
||||
{
|
||||
m_input_layers.push_back( inLayer );
|
||||
m_unmatched_layer_names.push_back( inLayer.Name );
|
||||
wxString layerName = inLayer.Required ? WrapRequired( inLayer.Name ) : inLayer.Name;
|
||||
m_unmatched_layer_names.push_back( layerName );
|
||||
kiCadLayers |= inLayer.PermittedLayers;
|
||||
}
|
||||
|
||||
int maxTextWidth = 0;
|
||||
int maxTextWidth = GetTextExtent( _( "Imported Layer" ) ).x;
|
||||
|
||||
for( const INPUT_LAYER_DESC& layer : m_input_layers )
|
||||
maxTextWidth = std::max( maxTextWidth, GetTextExtent( layer.Name ).x );
|
||||
|
@ -268,8 +299,21 @@ DIALOG_IMPORTED_LAYERS::DIALOG_IMPORTED_LAYERS( wxWindow* aParent,
|
|||
FinishDialogSettings();
|
||||
}
|
||||
|
||||
std::vector<wxString> DIALOG_IMPORTED_LAYERS::GetUnmappedRequiredLayers() const
|
||||
{
|
||||
std::vector<wxString> unmappedLayers;
|
||||
for( const wxString& layerName : m_unmatched_layer_names )
|
||||
{
|
||||
const INPUT_LAYER_DESC* layerDesc = GetLayerDescription( layerName );
|
||||
wxASSERT_MSG( layerDesc != nullptr, "Expected to find layer decription" );
|
||||
if( layerDesc->Required )
|
||||
unmappedLayers.push_back( layerDesc->Name );
|
||||
}
|
||||
return unmappedLayers;
|
||||
}
|
||||
|
||||
LAYER_MAP DIALOG_IMPORTED_LAYERS::GetMapModal( wxWindow* aParent,
|
||||
|
||||
std::map<wxString, PCB_LAYER_ID> DIALOG_IMPORTED_LAYERS::GetMapModal( wxWindow* aParent,
|
||||
const std::vector<INPUT_LAYER_DESC>& aLayerDesc )
|
||||
{
|
||||
DIALOG_IMPORTED_LAYERS dlg( aParent, aLayerDesc );
|
||||
|
@ -279,10 +323,11 @@ LAYER_MAP DIALOG_IMPORTED_LAYERS::GetMapModal( wxWindow* aParent,
|
|||
{
|
||||
dlg.ShowModal();
|
||||
|
||||
if( dlg.m_unmatched_layer_names.size() > 0 )
|
||||
if( dlg.GetUnmappedRequiredLayers().size() > 0 )
|
||||
{
|
||||
wxMessageBox( _( "All layers must be matched. Please click on 'Auto-Matched Layers' "
|
||||
"to automatically match the remaining layers." ),
|
||||
wxMessageBox( _( "All required layers (marked with '*') must be matched. "
|
||||
"Please click on 'Auto-Match Layers' to "
|
||||
"automatically match the remaining layers" ),
|
||||
_( "Unmatched Layers" ), wxICON_ERROR | wxOK );
|
||||
}
|
||||
else
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define DIALOG_IMPORTED_LAYERS_H
|
||||
|
||||
#include <dialog_imported_layers_base.h>
|
||||
#include <plugins/cadstar/cadstar_pcb_archive_plugin.h> // INPUT_LAYER_DESC
|
||||
#include <plugins/common/plugin_common_layer_mapping.h>
|
||||
|
||||
|
||||
class DIALOG_IMPORTED_LAYERS : public DIALOG_IMPORTED_LAYERS_BASE
|
||||
|
@ -33,15 +33,21 @@ private:
|
|||
|
||||
std::vector<INPUT_LAYER_DESC> m_input_layers;
|
||||
std::vector<wxString> m_unmatched_layer_names;
|
||||
LAYER_MAP m_matched_layers_map;
|
||||
std::map<wxString, PCB_LAYER_ID> m_matched_layers_map;
|
||||
|
||||
//Helper functions
|
||||
PCB_LAYER_ID GetSelectedLayerID();
|
||||
PCB_LAYER_ID GetAutoMatchLayerID( wxString aInputLayerName );
|
||||
|
||||
void AddMappings();
|
||||
void RemoveMappings( int aStatus );
|
||||
void DeleteListItems( const wxArrayInt& aRowsToDelete, wxListCtrl* aListCtrl );
|
||||
|
||||
const INPUT_LAYER_DESC* GetLayerDescription( const wxString& aLayerName ) const;
|
||||
|
||||
static wxString WrapRequired( const wxString& aLayerName );
|
||||
static wxString UnwrapRequired( const wxString& aLayerName );
|
||||
|
||||
//Event Handlers
|
||||
void OnAutoMatchLayersClicked( wxCommandEvent& event ) override;
|
||||
|
||||
|
@ -55,13 +61,19 @@ public:
|
|||
DIALOG_IMPORTED_LAYERS( wxWindow* aParent, const std::vector<INPUT_LAYER_DESC>& aLayerDesc );
|
||||
|
||||
/**
|
||||
* @brief Creates and shows a dialog (modal) and returns the data from it after completion.
|
||||
* If the dialog is closed or cancel is pressed, returns an empty LAYER_MAP
|
||||
* @brief Return a list of layers names that are required, but they are not mapped
|
||||
*/
|
||||
std::vector<wxString> GetUnmappedRequiredLayers() const;
|
||||
|
||||
/**
|
||||
* @brief Creates and shows a dialog (modal) and returns the data from it
|
||||
* after completion. If the dialog is closed or cancel is pressed, returns
|
||||
* an empty map
|
||||
* @param aParent Parent window for the invoked dialog.
|
||||
* @param aLayerDesc
|
||||
* @return Mapped layers
|
||||
*/
|
||||
static LAYER_MAP GetMapModal( wxWindow* aParent,
|
||||
static std::map<wxString, PCB_LAYER_ID> GetMapModal( wxWindow* aParent,
|
||||
const std::vector<INPUT_LAYER_DESC>& aLayerDesc );
|
||||
};
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <project/project_file.h>
|
||||
#include <project/project_local_settings.h>
|
||||
#include <plugins/cadstar/cadstar_pcb_archive_plugin.h>
|
||||
#include <plugins/eagle/eagle_plugin.h>
|
||||
#include <dialogs/dialog_imported_layers.h>
|
||||
|
||||
|
||||
|
@ -621,18 +622,13 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
|
||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
|
||||
|
||||
|
||||
if( pluginType == IO_MGR::CADSTAR_PCB_ARCHIVE )
|
||||
LAYER_REMAPPABLE_PLUGIN* layerRemappable =
|
||||
dynamic_cast< LAYER_REMAPPABLE_PLUGIN* >( (PLUGIN*) pi );
|
||||
if ( layerRemappable )
|
||||
{
|
||||
// TODO: Generalise this so that it is applicable to all non-kicad plugins
|
||||
CADSTAR_PCB_ARCHIVE_PLUGIN* cadstarPlugin = nullptr;
|
||||
|
||||
cadstarPlugin = dynamic_cast<CADSTAR_PCB_ARCHIVE_PLUGIN*>( (PLUGIN*) pi );
|
||||
|
||||
wxCHECK( cadstarPlugin, false );
|
||||
|
||||
cadstarPlugin->RegisterLayerMappingCallback(
|
||||
std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) );
|
||||
using namespace std::placeholders;
|
||||
layerRemappable->RegisterLayerMappingCallback(
|
||||
std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, _1 ) );
|
||||
}
|
||||
|
||||
// This will rename the file if there is an autosave and the user want to recover
|
||||
|
|
|
@ -537,7 +537,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::remapUnsureLayers()
|
|||
return;
|
||||
|
||||
// Callback:
|
||||
LAYER_MAP reMappedLayers = mLayerMappingHandler( inputLayers );
|
||||
std::map<wxString, PCB_LAYER_ID> reMappedLayers = mLayerMappingHandler( inputLayers );
|
||||
|
||||
for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define CADSTAR_PCB_ARCHIVE_LOADER_H_
|
||||
|
||||
#include <cadstar_pcb_archive_parser.h>
|
||||
#include <cadstar_pcb_archive_plugin.h> // LAYER_MAPPING_HANDLER definition
|
||||
#include <cadstar_pcb_archive_plugin.h>
|
||||
#include <class_board.h>
|
||||
#include <set>
|
||||
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
#include <properties.h>
|
||||
|
||||
|
||||
LAYER_MAP CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback(
|
||||
std::map<wxString, PCB_LAYER_ID> CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback(
|
||||
const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
|
||||
{
|
||||
LAYER_MAP retval;
|
||||
std::map<wxString, PCB_LAYER_ID> retval;
|
||||
|
||||
// Just return a the auto-mapped layers
|
||||
for( INPUT_LAYER_DESC layerDesc : aInputLayerDescriptionVector )
|
||||
|
@ -48,7 +48,7 @@ LAYER_MAP CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback(
|
|||
void CADSTAR_PCB_ARCHIVE_PLUGIN::RegisterLayerMappingCallback(
|
||||
LAYER_MAPPING_HANDLER aLayerMappingHandler )
|
||||
{
|
||||
m_layer_mapping_handler = aLayerMappingHandler;
|
||||
LAYER_REMAPPABLE_PLUGIN::RegisterLayerMappingCallback( aLayerMappingHandler );
|
||||
m_show_layer_mapping_warnings = false; // only show warnings with default callback
|
||||
}
|
||||
|
||||
|
@ -57,8 +57,9 @@ CADSTAR_PCB_ARCHIVE_PLUGIN::CADSTAR_PCB_ARCHIVE_PLUGIN()
|
|||
{
|
||||
m_board = nullptr;
|
||||
m_props = nullptr;
|
||||
m_layer_mapping_handler = CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback;
|
||||
m_show_layer_mapping_warnings = true;
|
||||
LAYER_REMAPPABLE_PLUGIN::RegisterLayerMappingCallback(
|
||||
CADSTAR_PCB_ARCHIVE_PLUGIN::DefaultLayerMappingCallback );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,45 +30,10 @@
|
|||
|
||||
#include <io_mgr.h>
|
||||
#include <layers_id_colors_and_visibility.h> // PCB_LAYER_ID
|
||||
#include <plugins/common/plugin_common_layer_mapping.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Describes an imported layer and how it could be mapped to KiCad Layers
|
||||
*/
|
||||
struct INPUT_LAYER_DESC
|
||||
{
|
||||
wxString Name; ///< Imported layer name as displayed in original application.
|
||||
LSET PermittedLayers; ///< KiCad layers that the imported layer can be mapped onto.
|
||||
PCB_LAYER_ID AutoMapLayer; ///< Best guess as to what the equivalent KiCad layer might be.
|
||||
|
||||
INPUT_LAYER_DESC()
|
||||
{
|
||||
Name = wxEmptyString;
|
||||
PermittedLayers = LSET();
|
||||
AutoMapLayer = PCB_LAYER_ID::UNDEFINED_LAYER;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A CADSTAR layer name.
|
||||
*/
|
||||
typedef wxString INPUT_LAYER_NAME;
|
||||
|
||||
/**
|
||||
* @brief Map of CADSTAR (INPUT_LAYER_NAME) to KiCad Layers.
|
||||
* If the mapped KiCad layer is UNDEFINED_LAYER, then the CADSTAR layer will not
|
||||
* be imported
|
||||
*/
|
||||
typedef std::map<INPUT_LAYER_NAME, PCB_LAYER_ID> LAYER_MAP;
|
||||
|
||||
/**
|
||||
* @brief Pointer to a function that takes a map of Cadstar and KiCad layers
|
||||
* and returns a re-mapped version. If the re-mapped layer
|
||||
*/
|
||||
typedef std::function<LAYER_MAP( const std::vector<INPUT_LAYER_DESC>& )> LAYER_MAPPING_HANDLER;
|
||||
|
||||
|
||||
class CADSTAR_PCB_ARCHIVE_PLUGIN : public PLUGIN
|
||||
class CADSTAR_PCB_ARCHIVE_PLUGIN : public PLUGIN, public LAYER_REMAPPABLE_PLUGIN
|
||||
{
|
||||
public:
|
||||
// -----<PUBLIC PLUGIN API>--------------------------------------------------
|
||||
|
@ -93,7 +58,7 @@ public:
|
|||
* @param aInputLayerDescriptionVector
|
||||
* @return Auto-mapped layers
|
||||
*/
|
||||
static LAYER_MAP DefaultLayerMappingCallback(
|
||||
static std::map<wxString, PCB_LAYER_ID> DefaultLayerMappingCallback(
|
||||
const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector );
|
||||
|
||||
/**
|
||||
|
@ -101,7 +66,7 @@ public:
|
|||
* layers occurs
|
||||
* @param aLayerMappingHandler
|
||||
*/
|
||||
void RegisterLayerMappingCallback( LAYER_MAPPING_HANDLER aLayerMappingHandler );
|
||||
void RegisterLayerMappingCallback( LAYER_MAPPING_HANDLER aLayerMappingHandler ) override;
|
||||
|
||||
CADSTAR_PCB_ARCHIVE_PLUGIN();
|
||||
~CADSTAR_PCB_ARCHIVE_PLUGIN();
|
||||
|
@ -109,7 +74,6 @@ public:
|
|||
private:
|
||||
const PROPERTIES* m_props;
|
||||
BOARD* m_board;
|
||||
LAYER_MAPPING_HANDLER m_layer_mapping_handler;
|
||||
bool m_show_layer_mapping_warnings;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 Jan Mrázek <email@honzamrazek.cz>
|
||||
* Copyright (C) 2020 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
|
||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_COMMON_LAYER_MAPPING_H
|
||||
#define PLUGIN_COMMON_LAYER_MAPPING_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <io_mgr.h>
|
||||
#include <layers_id_colors_and_visibility.h> // PCB_LAYER_ID
|
||||
|
||||
/**
|
||||
* @brief Describes an imported layer and how it could be mapped to KiCad Layers
|
||||
*/
|
||||
struct INPUT_LAYER_DESC
|
||||
{
|
||||
wxString Name; ///< Imported layer name as displayed in original application.
|
||||
LSET PermittedLayers; ///< KiCad layers that the imported layer can be mapped onto.
|
||||
PCB_LAYER_ID AutoMapLayer; ///< Best guess as to what the equivalent KiCad layer might be.
|
||||
bool Required; ///< Should we require the layer to be assigned?
|
||||
|
||||
INPUT_LAYER_DESC()
|
||||
: Name( wxEmptyString ),
|
||||
PermittedLayers(),
|
||||
AutoMapLayer( PCB_LAYER_ID::UNDEFINED_LAYER ),
|
||||
Required( true )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Pointer to a function that takes a map of source and KiCad layers
|
||||
* and returns a re-mapped version. If the re-mapped layer is UNDEFINED_LAYER,
|
||||
* then the source layer will not be imported
|
||||
*/
|
||||
using LAYER_MAPPING_HANDLER = std::function<std::map<wxString, PCB_LAYER_ID>( const std::vector<INPUT_LAYER_DESC>& )>;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Plugin class for import plugins that support remappable layers
|
||||
*/
|
||||
class LAYER_REMAPPABLE_PLUGIN
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Register a different handler to be called when mapping of input
|
||||
* layers to KiCad layers occurs
|
||||
*
|
||||
* The function is marked as virtual, so the plugins can implement extra
|
||||
* logic (e.g., enable warnings or checks)
|
||||
*
|
||||
* @param aLayerMappingHandler
|
||||
*/
|
||||
virtual void RegisterLayerMappingCallback( LAYER_MAPPING_HANDLER aLayerMappingHandler )
|
||||
{
|
||||
m_layer_mapping_handler = aLayerMappingHandler;
|
||||
}
|
||||
protected:
|
||||
LAYER_MAPPING_HANDLER m_layer_mapping_handler; ///< Callback to get layer mapping
|
||||
};
|
||||
|
||||
#endif // PLUGIN_COMMON_LAYER_MAPPING_H
|
|
@ -274,8 +274,12 @@ EAGLE_PLUGIN::EAGLE_PLUGIN() :
|
|||
m_xpath( new XPATH() ),
|
||||
m_mod_time( wxDateTime::Now() )
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
|
||||
init( NULL );
|
||||
clear_cu_map();
|
||||
RegisterLayerMappingCallback( std::bind(
|
||||
&EAGLE_PLUGIN::DefaultLayerMappingCallback, this, _1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -298,7 +302,6 @@ const wxString EAGLE_PLUGIN::GetFileExtension() const
|
|||
return wxT( "brd" );
|
||||
}
|
||||
|
||||
|
||||
wxSize inline EAGLE_PLUGIN::kicad_fontz( const ECOORD& d, int aTextThickness ) const
|
||||
{
|
||||
// Eagle includes stroke thickness in the text size, KiCAD does not
|
||||
|
@ -453,6 +456,7 @@ void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
|
|||
|
||||
wxXmlNode* layers = drawingChildren["layers"];
|
||||
loadLayerDefs( layers );
|
||||
mapEagleLayersToKicad();
|
||||
|
||||
m_xpath->pop();
|
||||
}
|
||||
|
@ -501,11 +505,13 @@ void EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers )
|
|||
wxXmlNode* layerNode = aLayers->GetChildren();
|
||||
|
||||
m_eagleLayers.clear();
|
||||
m_eagleLayersIds.clear();
|
||||
|
||||
while( layerNode )
|
||||
{
|
||||
ELAYER elayer( layerNode );
|
||||
m_eagleLayers.insert( std::make_pair( elayer.number, elayer ) );
|
||||
m_eagleLayersIds.insert( std::make_pair( elayer.name, elayer.number ) );
|
||||
|
||||
// find the subset of layers that are copper and active
|
||||
if( elayer.number >= 1 && elayer.number <= 16 && ( !elayer.active || *elayer.active ) )
|
||||
|
@ -1245,6 +1251,15 @@ ZONE* EAGLE_PLUGIN::loadPolygon( wxXmlNode* aPolyNode )
|
|||
|| p.layer == EAGLE_LAYER::BRESTRICT
|
||||
|| p.layer == EAGLE_LAYER::VRESTRICT );
|
||||
|
||||
if( layer == UNDEFINED_LAYER ) {
|
||||
wxLogMessage( wxString::Format(
|
||||
_( "Ignoring a polygon since Eagle layer '%s' (%d) "
|
||||
"was not mapped" ),
|
||||
eagle_layer_name( p.layer ),
|
||||
p.layer ) );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if( !IsCopperLayer( layer ) && !keepout )
|
||||
return nullptr;
|
||||
|
||||
|
@ -1583,6 +1598,15 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
|
||||
int width = w.width.ToPcbUnits();
|
||||
|
||||
if( layer == UNDEFINED_LAYER ) {
|
||||
wxLogMessage( wxString::Format(
|
||||
_( "Ignoring a wire since Eagle layer '%s' (%d) "
|
||||
"was not mapped" ),
|
||||
eagle_layer_name( w.layer ),
|
||||
w.layer ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// KiCad cannot handle zero or negative line widths which apparently have meaning in Eagle.
|
||||
if( width <= 0 )
|
||||
{
|
||||
|
@ -1747,8 +1771,14 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
ETEXT t( aTree );
|
||||
PCB_LAYER_ID layer = kicad_layer( t.layer );
|
||||
|
||||
if( layer == UNDEFINED_LAYER )
|
||||
layer = Cmts_User;
|
||||
if( layer == UNDEFINED_LAYER ) {
|
||||
wxLogMessage( wxString::Format(
|
||||
_( "Ignoring a text since Eagle layer '%s' (%d) "
|
||||
"was not mapped" ),
|
||||
eagle_layer_name( t.layer ),
|
||||
t.layer ) );
|
||||
return;
|
||||
}
|
||||
|
||||
FP_TEXT* txt;
|
||||
|
||||
|
@ -1878,6 +1908,15 @@ void EAGLE_PLUGIN::packageRectangle( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
else
|
||||
{
|
||||
PCB_LAYER_ID layer = kicad_layer( r.layer );
|
||||
if( layer == UNDEFINED_LAYER ) {
|
||||
wxLogMessage( wxString::Format(
|
||||
_( "Ignoring a rectange since Eagle layer '%s' (%d) "
|
||||
"was not mapped" ),
|
||||
eagle_layer_name( r.layer ),
|
||||
r.layer ) );
|
||||
return;
|
||||
}
|
||||
|
||||
FP_SHAPE* dwg = new FP_SHAPE( aModule, S_POLYGON );
|
||||
|
||||
aModule->Add( dwg );
|
||||
|
@ -1983,6 +2022,15 @@ void EAGLE_PLUGIN::packagePolygon( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
else
|
||||
{
|
||||
PCB_LAYER_ID layer = kicad_layer( p.layer );
|
||||
if( layer == UNDEFINED_LAYER ) {
|
||||
wxLogMessage( wxString::Format(
|
||||
_( "Ignoring a polygon since Eagle layer '%s' (%d) "
|
||||
"was not mapped" ),
|
||||
eagle_layer_name( p.layer ),
|
||||
p.layer ) );
|
||||
return;
|
||||
}
|
||||
|
||||
FP_SHAPE* dwg = new FP_SHAPE( aModule, S_POLYGON );
|
||||
|
||||
aModule->Add( dwg );
|
||||
|
@ -2043,6 +2091,15 @@ void EAGLE_PLUGIN::packageCircle( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
else
|
||||
{
|
||||
PCB_LAYER_ID layer = kicad_layer( e.layer );
|
||||
if( layer == UNDEFINED_LAYER ) {
|
||||
wxLogMessage( wxString::Format(
|
||||
_( "Ignoring a cricle since Eagle layer '%s' (%d) "
|
||||
"was not mapped" ),
|
||||
eagle_layer_name( e.layer ),
|
||||
e.layer ) );
|
||||
return;
|
||||
}
|
||||
|
||||
FP_SHAPE* gr = new FP_SHAPE( aModule, S_CIRCLE );
|
||||
|
||||
// with == 0 means filled circle
|
||||
|
@ -2451,78 +2508,172 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
m_xpath->pop(); // "signals.signal"
|
||||
}
|
||||
|
||||
std::map<wxString, PCB_LAYER_ID> EAGLE_PLUGIN::DefaultLayerMappingCallback(
|
||||
const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
|
||||
{
|
||||
std::map<wxString, PCB_LAYER_ID> layer_map;
|
||||
|
||||
for ( const INPUT_LAYER_DESC& layer : aInputLayerDescriptionVector )
|
||||
{
|
||||
PCB_LAYER_ID layerId = std::get<0>( defaultKicadLayer( eagle_layer_id( layer.Name ) ) );
|
||||
layer_map.emplace( layer.Name, layerId );
|
||||
}
|
||||
|
||||
return layer_map;
|
||||
}
|
||||
|
||||
void EAGLE_PLUGIN::mapEagleLayersToKicad()
|
||||
{
|
||||
std::vector<INPUT_LAYER_DESC> inputDescs;
|
||||
|
||||
for ( const std::pair<int, ELAYER>& layerPair : m_eagleLayers )
|
||||
{
|
||||
const ELAYER& eLayer = layerPair.second;
|
||||
|
||||
INPUT_LAYER_DESC layerDesc;
|
||||
std::tie( layerDesc.AutoMapLayer, layerDesc.PermittedLayers, layerDesc.Required ) =
|
||||
defaultKicadLayer( eLayer.number );
|
||||
if( layerDesc.AutoMapLayer == UNDEFINED_LAYER )
|
||||
continue; // Ignore unused copper layers
|
||||
layerDesc.Name = eLayer.name;
|
||||
|
||||
inputDescs.push_back( layerDesc );
|
||||
}
|
||||
|
||||
m_layer_map = m_layer_mapping_handler( inputDescs );
|
||||
}
|
||||
|
||||
PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
|
||||
{
|
||||
int kiLayer;
|
||||
auto result = m_layer_map.find( eagle_layer_name( aEagleLayer ) );
|
||||
return result == m_layer_map.end() ? UNDEFINED_LAYER : result->second;
|
||||
}
|
||||
|
||||
std::tuple<PCB_LAYER_ID, LSET, bool> EAGLE_PLUGIN::defaultKicadLayer( int aEagleLayer ) const
|
||||
{
|
||||
// eagle copper layer:
|
||||
if( aEagleLayer >= 1 && aEagleLayer < int( arrayDim( m_cu_map ) ) )
|
||||
{
|
||||
kiLayer = m_cu_map[aEagleLayer];
|
||||
LSET copperLayers;
|
||||
for( int copperLayer : m_cu_map )
|
||||
{
|
||||
if( copperLayer >= 0 )
|
||||
copperLayers[copperLayer] = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return { PCB_LAYER_ID( m_cu_map[aEagleLayer] ), copperLayers, true };
|
||||
}
|
||||
|
||||
int kiLayer = UNSELECTED_LAYER;
|
||||
bool required = false;
|
||||
LSET permittedLayers;
|
||||
|
||||
permittedLayers.set();
|
||||
|
||||
// translate non-copper eagle layer to pcbnew layer
|
||||
switch( aEagleLayer )
|
||||
{
|
||||
// Eagle says "Dimension" layer, but it's for board perimeter
|
||||
case EAGLE_LAYER::DIMENSION: kiLayer = Edge_Cuts; break;
|
||||
case EAGLE_LAYER::DIMENSION:
|
||||
kiLayer = Edge_Cuts;
|
||||
required = true;
|
||||
permittedLayers = LSET( 1, Edge_Cuts );
|
||||
break;
|
||||
|
||||
case EAGLE_LAYER::TPLACE: kiLayer = F_SilkS; break;
|
||||
case EAGLE_LAYER::BPLACE: kiLayer = B_SilkS; break;
|
||||
case EAGLE_LAYER::TNAMES: kiLayer = F_SilkS; break;
|
||||
case EAGLE_LAYER::BNAMES: kiLayer = B_SilkS; break;
|
||||
case EAGLE_LAYER::TVALUES: kiLayer = F_Fab; break;
|
||||
case EAGLE_LAYER::BVALUES: kiLayer = B_Fab; break;
|
||||
case EAGLE_LAYER::TSTOP: kiLayer = F_Mask; break;
|
||||
case EAGLE_LAYER::BSTOP: kiLayer = B_Mask; break;
|
||||
case EAGLE_LAYER::TCREAM: kiLayer = F_Paste; break;
|
||||
case EAGLE_LAYER::BCREAM: kiLayer = B_Paste; break;
|
||||
case EAGLE_LAYER::TFINISH: kiLayer = F_Mask; break;
|
||||
case EAGLE_LAYER::BFINISH: kiLayer = B_Mask; break;
|
||||
case EAGLE_LAYER::TGLUE: kiLayer = F_Adhes; break;
|
||||
case EAGLE_LAYER::BGLUE: kiLayer = B_Adhes; break;
|
||||
case EAGLE_LAYER::DOCUMENT: kiLayer = Cmts_User; break;
|
||||
case EAGLE_LAYER::REFERENCELC: kiLayer = Cmts_User; break;
|
||||
case EAGLE_LAYER::REFERENCELS: kiLayer = Cmts_User; break;
|
||||
case EAGLE_LAYER::TPLACE:
|
||||
kiLayer = F_SilkS;
|
||||
break;
|
||||
case EAGLE_LAYER::BPLACE:
|
||||
kiLayer = B_SilkS;
|
||||
break;
|
||||
case EAGLE_LAYER::TNAMES:
|
||||
kiLayer = F_SilkS;
|
||||
break;
|
||||
case EAGLE_LAYER::BNAMES:
|
||||
kiLayer = B_SilkS;
|
||||
break;
|
||||
case EAGLE_LAYER::TVALUES:
|
||||
kiLayer = F_Fab;
|
||||
break;
|
||||
case EAGLE_LAYER::BVALUES:
|
||||
kiLayer = B_Fab;
|
||||
break;
|
||||
case EAGLE_LAYER::TSTOP:
|
||||
kiLayer = F_Mask;
|
||||
break;
|
||||
case EAGLE_LAYER::BSTOP:
|
||||
kiLayer = B_Mask;
|
||||
break;
|
||||
case EAGLE_LAYER::TCREAM:
|
||||
kiLayer = F_Paste;
|
||||
break;
|
||||
case EAGLE_LAYER::BCREAM:
|
||||
kiLayer = B_Paste;
|
||||
break;
|
||||
case EAGLE_LAYER::TFINISH:
|
||||
kiLayer = F_Mask;
|
||||
break;
|
||||
case EAGLE_LAYER::BFINISH:
|
||||
kiLayer = B_Mask;
|
||||
break;
|
||||
case EAGLE_LAYER::TGLUE:
|
||||
kiLayer = F_Adhes;
|
||||
break;
|
||||
case EAGLE_LAYER::BGLUE:
|
||||
kiLayer = B_Adhes;
|
||||
break;
|
||||
case EAGLE_LAYER::DOCUMENT:
|
||||
kiLayer = Cmts_User;
|
||||
break;
|
||||
case EAGLE_LAYER::REFERENCELC:
|
||||
kiLayer = Cmts_User;
|
||||
break;
|
||||
case EAGLE_LAYER::REFERENCELS:
|
||||
kiLayer = Cmts_User;
|
||||
break;
|
||||
|
||||
// Packages show the future chip pins on SMD parts using layer 51.
|
||||
// This is an area slightly smaller than the PAD/SMD copper area.
|
||||
// Carry those visual aids into the MODULE on the fabrication layer,
|
||||
// not silkscreen. This is perhaps not perfect, but there is not a lot
|
||||
// of other suitable paired layers
|
||||
case EAGLE_LAYER::TDOCU: kiLayer = F_Fab; break;
|
||||
case EAGLE_LAYER::BDOCU: kiLayer = B_Fab; break;
|
||||
case EAGLE_LAYER::TDOCU:
|
||||
kiLayer = F_Fab;
|
||||
break;
|
||||
case EAGLE_LAYER::BDOCU:
|
||||
kiLayer = B_Fab;
|
||||
break;
|
||||
|
||||
// these layers are defined as user layers. put them on ECO layers
|
||||
case EAGLE_LAYER::USERLAYER1: kiLayer = Eco1_User; break;
|
||||
case EAGLE_LAYER::USERLAYER2: kiLayer = Eco2_User; break;
|
||||
case EAGLE_LAYER::USERLAYER1:
|
||||
kiLayer = Eco1_User;
|
||||
break;
|
||||
case EAGLE_LAYER::USERLAYER2:
|
||||
kiLayer = Eco2_User;
|
||||
break;
|
||||
|
||||
// these will also appear in the ratsnest, so there's no need for a warning
|
||||
case EAGLE_LAYER::UNROUTED: kiLayer = Dwgs_User; break;
|
||||
case EAGLE_LAYER::UNROUTED:
|
||||
kiLayer = Dwgs_User;
|
||||
break;
|
||||
|
||||
case EAGLE_LAYER::TKEEPOUT: kiLayer = F_CrtYd; break;
|
||||
case EAGLE_LAYER::BKEEPOUT: kiLayer = B_CrtYd; break;
|
||||
case EAGLE_LAYER::TKEEPOUT:
|
||||
kiLayer = F_CrtYd;
|
||||
break;
|
||||
case EAGLE_LAYER::BKEEPOUT:
|
||||
kiLayer = B_CrtYd;
|
||||
break;
|
||||
|
||||
case EAGLE_LAYER::MILLING:
|
||||
case EAGLE_LAYER::TTEST:
|
||||
case EAGLE_LAYER::BTEST:
|
||||
case EAGLE_LAYER::HOLES:
|
||||
default:
|
||||
// some layers do not map to KiCad
|
||||
wxLogMessage( wxString::Format( _( "Unsupported Eagle layer '%s' (%d), "
|
||||
"converted to Dwgs.User layer" ),
|
||||
eagle_layer_name( aEagleLayer ),
|
||||
aEagleLayer ) );
|
||||
|
||||
kiLayer = Dwgs_User;
|
||||
kiLayer = UNSELECTED_LAYER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return PCB_LAYER_ID( kiLayer );
|
||||
return { PCB_LAYER_ID( kiLayer ), permittedLayers, required };
|
||||
}
|
||||
|
||||
|
||||
|
@ -2534,6 +2685,14 @@ const wxString& EAGLE_PLUGIN::eagle_layer_name( int aLayer ) const
|
|||
}
|
||||
|
||||
|
||||
int EAGLE_PLUGIN::eagle_layer_id( const wxString& aLayerName ) const
|
||||
{
|
||||
static const int unknown = -1;
|
||||
auto it = m_eagleLayersIds.find( aLayerName );
|
||||
return it == m_eagleLayersIds.end() ? unknown : it->second;
|
||||
}
|
||||
|
||||
|
||||
void EAGLE_PLUGIN::centerBoard()
|
||||
{
|
||||
if( m_props )
|
||||
|
|
|
@ -28,8 +28,10 @@
|
|||
#include <io_mgr.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <plugins/eagle/eagle_parser.h>
|
||||
#include <plugins/common/plugin_common_layer_mapping.h>
|
||||
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <wx/xml/xml.h>
|
||||
|
||||
class D_PAD;
|
||||
|
@ -115,7 +117,7 @@ struct ERULES
|
|||
* works with Eagle 6.x XML board files and footprints to implement the
|
||||
* Pcbnew PLUGIN API, or a portion of it.
|
||||
*/
|
||||
class EAGLE_PLUGIN : public PLUGIN
|
||||
class EAGLE_PLUGIN : public PLUGIN, public LAYER_REMAPPABLE_PLUGIN
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -164,12 +166,27 @@ public:
|
|||
EAGLE_PLUGIN();
|
||||
~EAGLE_PLUGIN();
|
||||
|
||||
/**
|
||||
* @brief Default callback - just returns the automapped layers
|
||||
*
|
||||
* The callback needs to have the context of the current board so it can
|
||||
* correctly determine copper layer mapping. Thus, it is not static and is
|
||||
* expected to be bind to an instance of EAGLE_PLUGIN.
|
||||
*
|
||||
* @param aInputLayerDescriptionVector
|
||||
* @return Auto-mapped layers
|
||||
*/
|
||||
std::map<wxString, PCB_LAYER_ID> DefaultLayerMappingCallback(
|
||||
const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector );
|
||||
|
||||
private:
|
||||
typedef std::vector<ELAYER> ELAYERS;
|
||||
typedef ELAYERS::const_iterator EITER;
|
||||
|
||||
int m_cu_map[17]; ///< map eagle to kicad, cu layers only.
|
||||
std::map<int, ELAYER> m_eagleLayers; ///< Eagle layers data stored by the layer number
|
||||
std::map<wxString, int> m_eagleLayersIds; ///< Eagle layers id stored by the layer name
|
||||
std::map<wxString, PCB_LAYER_ID> m_layer_map; ///< Mapping of Eagle layers to KiCAD layers
|
||||
|
||||
ERULES* m_rules; ///< Eagle design rules.
|
||||
XPATH* m_xpath; ///< keeps track of what we are working on within
|
||||
|
@ -207,12 +224,22 @@ private:
|
|||
/// create a font size (fontz) from an eagle font size scalar and KiCAD font thickness
|
||||
wxSize kicad_fontz( const ECOORD& d, int aTextThickness ) const;
|
||||
|
||||
/// Generate mapping between Eagle na KiCAD layers
|
||||
void mapEagleLayersToKicad();
|
||||
|
||||
/// Convert an Eagle layer to a KiCad layer.
|
||||
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
|
||||
std::tuple<PCB_LAYER_ID, LSET, bool> defaultKicadLayer( int aEagleLayer ) const;
|
||||
|
||||
/// Get Eagle layer name by its number
|
||||
const wxString& eagle_layer_name( int aLayer ) const;
|
||||
|
||||
/// Get Eagle leayer number by its name
|
||||
int eagle_layer_id( const wxString& aLayerName ) const;
|
||||
|
||||
/// This PLUGIN only caches one footprint library, this determines which one.
|
||||
void cacheLib( const wxString& aLibraryPath );
|
||||
|
||||
|
|
Loading…
Reference in New Issue