2012-05-20 13:14:46 +00:00
|
|
|
#ifndef EAGLE_PLUGIN_H_
|
|
|
|
#define EAGLE_PLUGIN_H_
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
2021-01-27 22:15:38 +00:00
|
|
|
* Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
2012-05-20 13:14:46 +00:00
|
|
|
*
|
|
|
|
* 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 2
|
|
|
|
* 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, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2021-03-20 15:35:37 +00:00
|
|
|
#include <convert_to_biu.h>
|
2012-05-20 13:14:46 +00:00
|
|
|
#include <io_mgr.h>
|
2021-07-29 09:47:43 +00:00
|
|
|
#include <layer_ids.h>
|
2020-10-03 20:48:58 +00:00
|
|
|
#include <plugins/eagle/eagle_parser.h>
|
2020-10-09 16:58:21 +00:00
|
|
|
#include <plugins/common/plugin_common_layer_mapping.h>
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2012-05-24 15:00:59 +00:00
|
|
|
#include <map>
|
2020-10-09 16:58:21 +00:00
|
|
|
#include <tuple>
|
2017-04-07 11:40:34 +00:00
|
|
|
#include <wx/xml/xml.h>
|
2012-05-24 01:18:30 +00:00
|
|
|
|
2020-11-12 22:30:02 +00:00
|
|
|
class PAD;
|
2020-10-04 23:34:59 +00:00
|
|
|
class FP_TEXT;
|
2020-11-11 23:05:59 +00:00
|
|
|
class ZONE;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2020-11-13 15:15:52 +00:00
|
|
|
typedef std::map<wxString, FOOTPRINT*> FOOTPRINT_MAP;
|
|
|
|
typedef std::vector<ZONE*> ZONES;
|
|
|
|
typedef std::map<wxString, ENET> NET_MAP;
|
|
|
|
typedef NET_MAP::const_iterator NET_MAP_CITER;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
|
|
|
|
2017-04-07 11:40:34 +00:00
|
|
|
/// subset of eagle.drawing.board.designrules in the XML document
|
|
|
|
struct ERULES
|
2012-05-24 15:00:59 +00:00
|
|
|
{
|
2021-01-27 22:15:38 +00:00
|
|
|
ERULES() :
|
|
|
|
psElongationLong ( 100 ),
|
|
|
|
psElongationOffset ( 0 ),
|
|
|
|
|
|
|
|
mvStopFrame ( 1.0 ),
|
|
|
|
mvCreamFrame ( 0.0 ),
|
|
|
|
mlMinStopFrame ( Mils2iu( 4.0 ) ),
|
|
|
|
mlMaxStopFrame ( Mils2iu( 4.0 ) ),
|
|
|
|
mlMinCreamFrame ( Mils2iu( 0.0 ) ),
|
|
|
|
mlMaxCreamFrame ( Mils2iu( 0.0 ) ),
|
|
|
|
|
|
|
|
psTop ( EPAD::UNDEF ),
|
|
|
|
psBottom ( EPAD::UNDEF ),
|
|
|
|
psFirst ( EPAD::UNDEF ),
|
|
|
|
|
|
|
|
srRoundness ( 0.0 ),
|
|
|
|
srMinRoundness ( Mils2iu( 0.0 ) ),
|
|
|
|
srMaxRoundness ( Mils2iu( 0.0 ) ),
|
|
|
|
|
|
|
|
rvPadTop ( 0.25 ),
|
|
|
|
// rvPadBottom ( 0.25 ),
|
|
|
|
rlMinPadTop ( Mils2iu( 10 ) ),
|
|
|
|
rlMaxPadTop ( Mils2iu( 20 ) ),
|
|
|
|
|
|
|
|
rvViaOuter ( 0.25 ),
|
|
|
|
rlMinViaOuter ( Mils2iu( 10 ) ),
|
|
|
|
rlMaxViaOuter ( Mils2iu( 20 ) ),
|
|
|
|
mdWireWire ( 0 )
|
|
|
|
{}
|
|
|
|
|
2021-06-23 22:53:08 +00:00
|
|
|
void parse( wxXmlNode* aRules, std::function<void()> aCheckpoint );
|
2021-01-27 22:15:38 +00:00
|
|
|
|
2020-12-18 15:40:13 +00:00
|
|
|
///< percent over 100%. 0-> not elongated, 100->twice as wide as is tall
|
|
|
|
///< Goes into making a scaling factor for "long" pads.
|
|
|
|
int psElongationLong;
|
2012-05-24 15:00:59 +00:00
|
|
|
|
2018-03-13 12:37:30 +00:00
|
|
|
int psElongationOffset; ///< the offset of the hole within the "long" pad.
|
2012-05-24 15:00:59 +00:00
|
|
|
|
2020-12-18 15:40:13 +00:00
|
|
|
///< solder mask, expressed as percentage of the smaller pad/via dimension
|
|
|
|
double mvStopFrame;
|
|
|
|
|
|
|
|
///< solderpaste mask, expressed as percentage of the smaller pad/via dimension
|
|
|
|
double mvCreamFrame;
|
2018-03-14 08:54:41 +00:00
|
|
|
int mlMinStopFrame; ///< solder mask, minimum size (Eagle mils, here nanometers)
|
|
|
|
int mlMaxStopFrame; ///< solder mask, maximum size (Eagle mils, here nanometers)
|
|
|
|
int mlMinCreamFrame; ///< solder paste mask, minimum size (Eagle mils, here nanometers)
|
|
|
|
int mlMaxCreamFrame; ///< solder paste mask, maximum size (Eagle mils, here nanometers)
|
2012-05-24 15:00:59 +00:00
|
|
|
|
2019-02-04 01:46:10 +00:00
|
|
|
int psTop; ///< Shape of the top pads
|
|
|
|
int psBottom; ///< Shape of the bottom pads
|
|
|
|
int psFirst; ///< Shape of the first pads
|
|
|
|
|
2018-03-14 09:06:40 +00:00
|
|
|
double srRoundness; ///< corner rounding ratio for SMD pads (percentage)
|
2020-12-18 15:40:13 +00:00
|
|
|
|
|
|
|
///< corner rounding radius, minimum size (Eagle mils, here nanometers)
|
|
|
|
int srMinRoundness;
|
|
|
|
|
|
|
|
///< corner rounding radius, maximum size (Eagle mils, here nanometers)
|
|
|
|
int srMaxRoundness;
|
2018-03-14 09:06:40 +00:00
|
|
|
|
2018-03-13 12:37:30 +00:00
|
|
|
double rvPadTop; ///< top pad size as percent of drill size
|
|
|
|
// double rvPadBottom; ///< bottom pad size as percent of drill size
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2018-03-13 12:37:30 +00:00
|
|
|
double rlMinPadTop; ///< minimum copper annulus on through hole pads
|
|
|
|
double rlMaxPadTop; ///< maximum copper annulus on through hole pads
|
|
|
|
|
|
|
|
double rvViaOuter; ///< copper annulus is this percent of via hole
|
|
|
|
double rlMinViaOuter; ///< minimum copper annulus on via
|
|
|
|
double rlMaxViaOuter; ///< maximum copper annulus on via
|
|
|
|
double mdWireWire; ///< wire to wire spacing I presume.
|
2017-04-07 11:40:34 +00:00
|
|
|
};
|
2012-06-02 17:07:30 +00:00
|
|
|
|
2020-12-18 15:40:13 +00:00
|
|
|
|
2012-05-20 13:14:46 +00:00
|
|
|
/**
|
2020-12-18 15:40:13 +00:00
|
|
|
* Works with Eagle 6.x XML board files and footprints to implement the Pcbnew #PLUGIN API
|
|
|
|
* or a portion of it.
|
2012-05-20 13:14:46 +00:00
|
|
|
*/
|
2020-10-09 16:58:21 +00:00
|
|
|
class EAGLE_PLUGIN : public PLUGIN, public LAYER_REMAPPABLE_PLUGIN
|
2012-05-20 13:14:46 +00:00
|
|
|
{
|
|
|
|
public:
|
2016-09-24 18:53:15 +00:00
|
|
|
const wxString PluginName() const override;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2017-06-11 20:20:44 +00:00
|
|
|
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
|
2021-06-23 22:53:08 +00:00
|
|
|
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
|
|
|
|
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2021-01-31 21:55:51 +00:00
|
|
|
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override;
|
|
|
|
|
2016-09-24 18:53:15 +00:00
|
|
|
const wxString GetFileExtension() const override;
|
2012-05-24 15:00:59 +00:00
|
|
|
|
2017-06-11 20:20:44 +00:00
|
|
|
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
|
2020-12-18 15:40:13 +00:00
|
|
|
bool aBestEfforts, const PROPERTIES* aProperties = nullptr) override;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2020-11-13 15:15:52 +00:00
|
|
|
FOOTPRINT* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
2021-03-30 09:38:03 +00:00
|
|
|
bool aKeepUUID = false,
|
2020-12-18 15:40:13 +00:00
|
|
|
const PROPERTIES* aProperties = nullptr ) override;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2018-03-04 01:13:09 +00:00
|
|
|
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
|
2018-03-02 20:41:37 +00:00
|
|
|
{
|
2018-03-04 01:13:09 +00:00
|
|
|
return getModificationTime( aLibraryPath ).GetValue().GetValue();
|
2018-03-02 20:41:37 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
bool IsFootprintLibWritable( const wxString& aLibraryPath ) override
|
2013-01-02 04:05:48 +00:00
|
|
|
{
|
|
|
|
return false; // until someone writes others like FootprintSave(), etc.
|
|
|
|
}
|
|
|
|
|
2016-09-24 18:53:15 +00:00
|
|
|
void FootprintLibOptions( PROPERTIES* aProperties ) const override;
|
2013-11-20 16:35:03 +00:00
|
|
|
|
2012-06-02 17:07:30 +00:00
|
|
|
typedef int BIU;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
|
|
|
EAGLE_PLUGIN();
|
|
|
|
~EAGLE_PLUGIN();
|
|
|
|
|
2020-10-09 16:58:21 +00:00
|
|
|
/**
|
2020-12-18 15:40:13 +00:00
|
|
|
* Return the automapped layers.
|
2020-10-09 16:58:21 +00:00
|
|
|
*
|
|
|
|
* 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 );
|
|
|
|
|
2012-05-20 13:14:46 +00:00
|
|
|
private:
|
|
|
|
/// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
|
2021-06-23 22:53:08 +00:00
|
|
|
void init( const PROPERTIES* aProperties );
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2021-06-23 22:53:08 +00:00
|
|
|
void checkpoint();
|
|
|
|
|
|
|
|
void clear_cu_map();
|
2013-03-13 16:38:54 +00:00
|
|
|
|
2012-06-02 17:07:30 +00:00
|
|
|
/// Convert an Eagle distance to a KiCad distance.
|
2018-03-13 13:34:53 +00:00
|
|
|
int kicad_y( const ECOORD& y ) const { return -y.ToPcbUnits(); }
|
|
|
|
int kicad_x( const ECOORD& x ) const { return x.ToPcbUnits(); }
|
2012-05-24 01:18:30 +00:00
|
|
|
|
2020-12-18 15:40:13 +00:00
|
|
|
/// create a font size (fontz) from an eagle font size scalar and KiCad font thickness
|
2020-06-09 07:32:52 +00:00
|
|
|
wxSize kicad_fontz( const ECOORD& d, int aTextThickness ) const;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
/// Generate mapping between Eagle na KiCad layers
|
2020-10-09 16:58:21 +00:00
|
|
|
void mapEagleLayersToKicad();
|
|
|
|
|
2012-06-02 17:07:30 +00:00
|
|
|
/// Convert an Eagle layer to a KiCad layer.
|
2017-03-13 03:19:33 +00:00
|
|
|
PCB_LAYER_ID kicad_layer( int aLayer ) const;
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
/// Get default KiCad layer corresponding to an Eagle layer of the board,
|
2020-10-09 16:58:21 +00:00
|
|
|
/// a set of sensible layer mapping options and required flag
|
|
|
|
std::tuple<PCB_LAYER_ID, LSET, bool> defaultKicadLayer( int aEagleLayer ) const;
|
|
|
|
|
2017-10-18 16:02:36 +00:00
|
|
|
/// Get Eagle layer name by its number
|
2017-12-14 09:37:32 +00:00
|
|
|
const wxString& eagle_layer_name( int aLayer ) const;
|
2017-10-18 16:02:36 +00:00
|
|
|
|
2020-12-18 15:40:13 +00:00
|
|
|
/// Get Eagle layer number by its name
|
2020-10-09 16:58:21 +00:00
|
|
|
int eagle_layer_id( const wxString& aLayerName ) const;
|
|
|
|
|
2013-01-02 04:05:48 +00:00
|
|
|
/// This PLUGIN only caches one footprint library, this determines which one.
|
|
|
|
void cacheLib( const wxString& aLibraryPath );
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2013-01-02 04:05:48 +00:00
|
|
|
/// get a file's or dir's modification time.
|
|
|
|
static wxDateTime getModificationTime( const wxString& aPath );
|
2012-05-20 13:14:46 +00:00
|
|
|
|
|
|
|
// all these loadXXX() throw IO_ERROR or ptree_error exceptions:
|
|
|
|
|
2017-04-07 11:40:34 +00:00
|
|
|
void loadAllSections( wxXmlNode* aDocument );
|
|
|
|
void loadDesignRules( wxXmlNode* aDesignRules );
|
|
|
|
void loadLayerDefs( wxXmlNode* aLayers );
|
|
|
|
void loadPlain( wxXmlNode* aPlain );
|
|
|
|
void loadSignals( wxXmlNode* aSignals );
|
2013-01-02 04:05:48 +00:00
|
|
|
|
|
|
|
/**
|
2020-12-18 15:40:13 +00:00
|
|
|
* Load the Eagle "library" XML element, which can occur either under a "libraries"
|
|
|
|
* element (if a *.brd file) or under a "drawing" element if a *.lbr file.
|
|
|
|
*
|
2013-01-02 04:05:48 +00:00
|
|
|
* @param aLib is the portion of the loaded XML document tree that is the "library"
|
2020-12-18 15:40:13 +00:00
|
|
|
* element.
|
2013-01-02 04:05:48 +00:00
|
|
|
* @param aLibName is a pointer to the library name or NULL. If NULL this means
|
2020-12-18 15:40:13 +00:00
|
|
|
* we are loading a *.lbr not a *.brd file and the key used in m_templates
|
|
|
|
* is to exclude the library name.
|
2013-01-02 04:05:48 +00:00
|
|
|
*/
|
2017-12-14 09:37:32 +00:00
|
|
|
void loadLibrary( wxXmlNode* aLib, const wxString* aLibName );
|
2013-01-02 04:05:48 +00:00
|
|
|
|
2017-04-07 11:40:34 +00:00
|
|
|
void loadLibraries( wxXmlNode* aLibs );
|
|
|
|
void loadElements( wxXmlNode* aElements );
|
2012-05-20 13:14:46 +00:00
|
|
|
|
2020-12-18 15:40:13 +00:00
|
|
|
/**
|
|
|
|
* Load a copper or keepout polygon and adds it to the board.
|
2018-05-18 16:14:54 +00:00
|
|
|
*
|
|
|
|
* @return The loaded zone or nullptr if was not processed.
|
|
|
|
*/
|
2020-11-11 23:05:59 +00:00
|
|
|
ZONE* loadPolygon( wxXmlNode* aPolyNode );
|
2018-05-18 16:14:54 +00:00
|
|
|
|
2020-11-13 15:15:52 +00:00
|
|
|
void orientFootprintAndText( FOOTPRINT* aFootprint, const EELEMENT& e, const EATTR* aNameAttr,
|
|
|
|
const EATTR* aValueAttr );
|
2020-11-13 01:12:36 +00:00
|
|
|
|
2020-11-13 15:15:52 +00:00
|
|
|
void orientFPText( FOOTPRINT* aFootprint, const EELEMENT& e, FP_TEXT* aFPText,
|
|
|
|
const EATTR* aAttr );
|
2012-06-07 01:49:43 +00:00
|
|
|
|
|
|
|
|
2012-06-02 17:07:30 +00:00
|
|
|
/// move the BOARD into the center of the page
|
|
|
|
void centerBoard();
|
|
|
|
|
2012-05-20 13:14:46 +00:00
|
|
|
/**
|
2020-12-18 15:40:13 +00:00
|
|
|
* Create a FOOTPRINT from an Eagle package.
|
2012-05-20 13:14:46 +00:00
|
|
|
*/
|
2020-11-13 15:15:52 +00:00
|
|
|
FOOTPRINT* makeFootprint( wxXmlNode* aPackage, const wxString& aPkgName );
|
2017-04-07 11:40:34 +00:00
|
|
|
|
2020-11-13 15:15:52 +00:00
|
|
|
void packageWire( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const;
|
|
|
|
void packagePad( FOOTPRINT* aFootprint, wxXmlNode* aTree );
|
|
|
|
void packageText( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const;
|
|
|
|
void packageRectangle( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const;
|
|
|
|
void packagePolygon( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const;
|
|
|
|
void packageCircle( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const;
|
2018-09-09 03:40:24 +00:00
|
|
|
|
|
|
|
/**
|
2020-12-18 15:40:13 +00:00
|
|
|
* @param aFootprint The KiCad footprint to which to assign the hole.
|
|
|
|
* @param aTree The Eagle XML node that is of type "hole".
|
|
|
|
* @param aCenter If true, center the hole in the footprint and offset the footprint position.
|
2018-09-09 03:40:24 +00:00
|
|
|
*/
|
2020-11-13 15:15:52 +00:00
|
|
|
void packageHole( FOOTPRINT* aFootprint, wxXmlNode* aTree, bool aCenter ) const;
|
|
|
|
void packageSMD( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const;
|
2017-07-10 09:44:56 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Handles common pad properties
|
2020-11-12 22:30:02 +00:00
|
|
|
void transferPad( const EPAD_COMMON& aEaglePad, PAD* aPad ) const;
|
2018-03-13 13:34:53 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Deletes the footprint templates list
|
2017-07-10 09:44:56 +00:00
|
|
|
void deleteTemplates();
|
2021-01-27 22:15:38 +00:00
|
|
|
|
|
|
|
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 layer data stored by layer number
|
|
|
|
std::map<wxString, int> m_eagleLayersIds; ///< Eagle layer ids stored by layer name
|
|
|
|
std::map<wxString, PCB_LAYER_ID> m_layer_map; ///< Map of Eagle layers to KiCad layers
|
|
|
|
|
|
|
|
ERULES* m_rules; ///< Eagle design rules.
|
|
|
|
XPATH* m_xpath; ///< keeps track of what we are working on within
|
|
|
|
///< XML document during a Load().
|
|
|
|
|
|
|
|
int m_hole_count; ///< generates unique footprint names from eagle "hole"s.
|
|
|
|
|
|
|
|
NET_MAP m_pads_to_nets; ///< net list
|
|
|
|
|
|
|
|
FOOTPRINT_MAP m_templates; ///< is part of a FOOTPRINT factory that operates using copy
|
|
|
|
///< construction.
|
|
|
|
///< lookup key is either libname.packagename or simply
|
|
|
|
///< packagename if FootprintLoad() or FootprintEnumberate()
|
|
|
|
|
|
|
|
const PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
|
|
|
|
BOARD* m_board; ///< which BOARD is being worked on, no ownership here
|
|
|
|
|
2021-06-23 22:53:08 +00:00
|
|
|
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr
|
|
|
|
unsigned m_doneCount;
|
|
|
|
unsigned m_lastProgressCount;
|
|
|
|
unsigned m_totalCount; ///< for progress reporting
|
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
int m_min_trace; ///< smallest trace we find on Load(), in BIU.
|
|
|
|
int m_min_hole; ///< smallest diameter hole we find on Load(), in BIU.
|
|
|
|
int m_min_via; ///< smallest via we find on Load(), in BIU.
|
|
|
|
int m_min_annulus; ///< smallest via annulus we find on Load(), in BIU.
|
|
|
|
|
|
|
|
wxString m_lib_path;
|
|
|
|
wxDateTime m_mod_time;
|
2012-05-20 13:14:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // EAGLE_PLUGIN_H_
|