mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-20 00:21:31 +00:00
Implement ODB++ export
ADDED: Add support in Pcbnew for exporting ODB++ files under Fabrication Outputs, base on ODB++Design Format Specification (Release v8.1 Update 3 February 2021). Note: There is still a lot of work to do if we will make the feature as complete as the ODB++ spec. However, the current functionality's completeness is already sufficient to cover general production scenarios. I have compared the output results with Gerber files by DFM tool and the accuracy at the graphic level should be able to cover most usage scenarios. Additionally, I am very grateful to the great open-source project Horizon EDA for giving me a lot of inspiration in terms of ideas. The feature can be enabled by adding "EnableODB=1" to the kicad_advanced configuration file. Fixes https://gitlab.com/kicad/code/kicad/-/issues/2019
This commit is contained in:
parent
d2cb868829
commit
1506beecbc
common
include
pcbnew
CMakeLists.txtpcbnew_settings.h
dialogs
dialog_export_odbpp.cppdialog_export_odbpp.fbpdialog_export_odbpp.hdialog_export_odbpp_base.cppdialog_export_odbpp_base.h
files.cppmenubar_pcb_editor.cpppcb_edit_frame.hpcb_io
odbpp
CMakeLists.txtodb_attribute.cppodb_attribute.hodb_component.cppodb_component.hodb_defines.hodb_eda_data.cppodb_eda_data.hodb_entity.cppodb_entity.hodb_feature.cppodb_feature.hodb_fonts.cppodb_netlist.cppodb_netlist.hodb_util.cppodb_util.hpcb_io_odbpp.cpppcb_io_odbpp.h
pcb_io_mgr.cpppcb_io_mgr.htools
resources/bitmaps_png
@ -119,6 +119,7 @@ static const wxChar MinorSchematicGraphSize[] = wxT( "MinorSchematicGraphSize" )
|
||||
static const wxChar ResolveTextRecursionDepth[] = wxT( "ResolveTextRecursionDepth" );
|
||||
static const wxChar EnableExtensionSnaps[] = wxT( "EnableExtensionSnaps" );
|
||||
static const wxChar EnableSnapAnchorsDebug[] = wxT( "EnableSnapAnchorsDebug" );
|
||||
static const wxChar EnableODB[] = wxT( "EnableODB" );
|
||||
} // namespace KEYS
|
||||
|
||||
|
||||
@ -527,6 +528,9 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::ResolveTextRecursionDepth,
|
||||
&m_ResolveTextRecursionDepth,
|
||||
m_ResolveTextRecursionDepth, 0, 10 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableODB,
|
||||
&m_EnableODB, m_EnableODB ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableExtensionSnaps,
|
||||
&m_EnableExtensionSnaps,
|
||||
|
@ -647,6 +647,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_24.png" ), 24, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_24.png" ), 24, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_24.png" ), 24, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_24.png" ), 24, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_24.png" ), 24, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_24.png" ), 24, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_24.png" ), 24, wxT( "light" ) );
|
||||
@ -1063,6 +1064,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_dark_24.png" ), 24, wxT( "dark" ) );
|
||||
@ -1479,6 +1481,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_16.png" ), 16, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_16.png" ), 16, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_16.png" ), 16, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_16.png" ), 16, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_16.png" ), 16, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_16.png" ), 16, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_16.png" ), 16, wxT( "light" ) );
|
||||
@ -1895,6 +1898,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_dark_16.png" ), 16, wxT( "dark" ) );
|
||||
@ -2311,6 +2315,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_32.png" ), 32, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_32.png" ), 32, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_32.png" ), 32, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_32.png" ), 32, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_32.png" ), 32, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_32.png" ), 32, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_32.png" ), 32, wxT( "light" ) );
|
||||
@ -2727,6 +2732,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_dark_32.png" ), 32, wxT( "dark" ) );
|
||||
@ -3143,6 +3149,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_48.png" ), 48, wxT( "light" ) );
|
||||
@ -3559,6 +3566,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_dark_48.png" ), 48, wxT( "dark" ) );
|
||||
@ -3975,6 +3983,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_64.png" ), 64, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_64.png" ), 64, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_64.png" ), 64, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_64.png" ), 64, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_64.png" ), 64, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_64.png" ), 64, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_64.png" ), 64, wxT( "light" ) );
|
||||
@ -4391,6 +4400,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::post_gerber].emplace_back( BITMAPS::post_gerber, wxT( "post_gerber_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_rpt].emplace_back( BITMAPS::post_rpt, wxT( "post_rpt_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_xml].emplace_back( BITMAPS::post_xml, wxT( "post_xml_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::post_odb].emplace_back( BITMAPS::post_odb, wxT( "post_odb_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::preference].emplace_back( BITMAPS::preference, wxT( "preference_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::print_button].emplace_back( BITMAPS::print_button, wxT( "print_button_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::project].emplace_back( BITMAPS::project, wxT( "project_dark_64.png" ), 64, wxT( "dark" ) );
|
||||
|
@ -71,8 +71,8 @@ public:
|
||||
*/
|
||||
static const ADVANCED_CFG& GetCfg();
|
||||
|
||||
///@{
|
||||
/// \ingroup advanced_config
|
||||
///@{
|
||||
/// \ingroup advanced_config
|
||||
|
||||
/**
|
||||
* Distance from an arc end point and the estimated end point, when rotating from the
|
||||
@ -660,6 +660,11 @@ public:
|
||||
*/
|
||||
bool m_EnableSnapAnchorsDebug;
|
||||
|
||||
/**
|
||||
* When true, enable output to odb++
|
||||
*/
|
||||
bool m_EnableODB;
|
||||
|
||||
///@}
|
||||
|
||||
private:
|
||||
|
@ -464,6 +464,7 @@ enum class BITMAPS : unsigned int
|
||||
post_module,
|
||||
post_rpt,
|
||||
post_xml,
|
||||
post_odb,
|
||||
preference,
|
||||
primitives_to_custom_pad,
|
||||
print_button,
|
||||
|
@ -57,6 +57,7 @@ enum LAST_PATH_TYPE : unsigned int
|
||||
LAST_PATH_SVG,
|
||||
LAST_PATH_PLOT,
|
||||
LAST_PATH_2581,
|
||||
LAST_PATH_ODBPP,
|
||||
|
||||
LAST_PATH_SIZE
|
||||
};
|
||||
|
@ -68,6 +68,8 @@ set( PCBNEW_DIALOGS
|
||||
dialogs/dialog_export_idf.cpp
|
||||
dialogs/dialog_export_idf_base.cpp
|
||||
dialogs/dialog_export_step.cpp
|
||||
dialogs/dialog_export_odbpp.cpp
|
||||
dialogs/dialog_export_odbpp_base.cpp
|
||||
dialogs/dialog_export_step_base.cpp
|
||||
dialogs/dialog_export_step_process.cpp
|
||||
dialogs/dialog_export_step_process_base.cpp
|
||||
@ -633,8 +635,9 @@ add_subdirectory( pcb_io/easyeda )
|
||||
add_subdirectory( pcb_io/easyedapro )
|
||||
add_subdirectory( pcb_io/fabmaster )
|
||||
add_subdirectory( pcb_io/ipc2581 )
|
||||
add_subdirectory( pcb_io/odbpp )
|
||||
|
||||
set( PCBNEW_IO_LIBRARIES pcad2kicadpcb altium2pcbnew cadstar2pcbnew easyeda easyedapro fabmaster ipc2581 CACHE INTERNAL "")
|
||||
set( PCBNEW_IO_LIBRARIES pcad2kicadpcb altium2pcbnew cadstar2pcbnew easyeda easyedapro fabmaster ipc2581 odbpp CACHE INTERNAL "")
|
||||
|
||||
# a very small program launcher for pcbnew_kiface
|
||||
add_executable( pcbnew WIN32 MACOSX_BUNDLE
|
||||
|
112
pcbnew/dialogs/dialog_export_odbpp.cpp
Normal file
112
pcbnew/dialogs/dialog_export_odbpp.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2023 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/>.
|
||||
*/
|
||||
|
||||
#include <dialogs/dialog_export_odbpp.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
#include <kiway_holder.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <pcbnew_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
#include <project/board_project_settings.h>
|
||||
#include <project/project_file.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <wx/dirdlg.h>
|
||||
|
||||
static wxString s_oemColumn = wxEmptyString;
|
||||
|
||||
DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent ) :
|
||||
DIALOG_EXPORT_ODBPP_BASE( aParent ), m_parent( aParent )
|
||||
{
|
||||
m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
|
||||
|
||||
SetupStandardButtons( { { wxID_OK, _( "Export" ) }, { wxID_CANCEL, _( "Close" ) } } );
|
||||
|
||||
wxString path = m_parent->GetLastPath( LAST_PATH_ODBPP );
|
||||
|
||||
if( path.IsEmpty() )
|
||||
{
|
||||
wxFileName brdFile( m_parent->GetBoard()->GetFileName() );
|
||||
path = brdFile.GetPath();
|
||||
}
|
||||
|
||||
m_outputFileName->SetValue( path );
|
||||
|
||||
// Fill wxChoice (and others) items with data before calling finishDialogSettings()
|
||||
// to calculate suitable widgets sizes
|
||||
Init();
|
||||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_EXPORT_ODBPP::onBrowseClicked( wxCommandEvent& event )
|
||||
{
|
||||
// Build the absolute path of current output directory to preselect it in the file browser.
|
||||
wxString path = ExpandEnvVarSubstitutions( m_outputFileName->GetValue(), &Prj() );
|
||||
wxFileName fn( Prj().AbsolutePath( path ) );
|
||||
|
||||
wxDirDialog dlg( this, _( "Export ODB++ File" ), fn.GetPath() );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
m_outputFileName->SetValue( dlg.GetPath() );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_EXPORT_ODBPP::onOKClick( wxCommandEvent& event )
|
||||
{
|
||||
m_parent->SetLastPath( LAST_PATH_ODBPP, m_outputFileName->GetValue() );
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_EXPORT_ODBPP::Init()
|
||||
{
|
||||
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
|
||||
|
||||
BOARD* board = m_parent->GetBoard();
|
||||
|
||||
m_choiceUnits->SetSelection( cfg->m_ExportODBPP.units );
|
||||
m_precision->SetValue( cfg->m_ExportODBPP.precision );
|
||||
m_cbCompress->SetValue( cfg->m_ExportODBPP.compress );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_EXPORT_ODBPP::TransferDataFromWindow()
|
||||
{
|
||||
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
|
||||
|
||||
cfg->m_ExportODBPP.units = m_choiceUnits->GetSelection();
|
||||
cfg->m_ExportODBPP.precision = m_precision->GetValue();
|
||||
cfg->m_ExportODBPP.compress = m_cbCompress->GetValue();
|
||||
|
||||
return true;
|
||||
}
|
671
pcbnew/dialogs/dialog_export_odbpp.fbp
Normal file
671
pcbnew/dialogs/dialog_export_odbpp.fbp
Normal file
@ -0,0 +1,671 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="17"/>
|
||||
<object class="Project" expanded="true">
|
||||
<property name="class_decoration"></property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">dialog_export_odbpp_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">DIALOG_EXPORT_ODBPP_BASE</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">.</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_array_enum">0</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="true">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="center">wxBOTH</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="extra_style"></property>
|
||||
<property name="fg"></property>
|
||||
<property name="font"></property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">DIALOG_EXPORT_ODBPP_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">380,300</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Export ODB++</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bMainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">15</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxTOP</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizerTop</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">protected</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">File:</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_lblBrdFile</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxTextCtrl" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="maxlength">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">350,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_outputFileName</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">Enter a filename if you do not want to use default file names
Can be used only when printing the current sheet</property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">MyButton</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_browseButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">onBrowseClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer3</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">10</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStaticBoxSizer" expanded="true">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">File Format</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizer1</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="proportion">3</property>
|
||||
<object class="wxFlexGridSizer" expanded="false">
|
||||
<property name="cols">2</property>
|
||||
<property name="flexible_direction">wxBOTH</property>
|
||||
<property name="growablecols">1</property>
|
||||
<property name="growablerows"></property>
|
||||
<property name="hgap">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">fgSizer</property>
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">none</property>
|
||||
<property name="rows">0</property>
|
||||
<property name="vgap">0</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Units:</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_lblUnits</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_RIGHT|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxChoice" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="choices">"Millimeters" "Inches"</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_choiceUnits</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="selection">0</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size">130,30</property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Precision:</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_lblPrecision</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">The number of values following the decimal separator</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_RIGHT|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxSpinCtrl" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="initial">7</property>
|
||||
<property name="max">16</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min">2</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_precision</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size">130,30</property>
|
||||
<property name="style">wxSP_ARROW_KEYS</property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">The number of values following the decimal separator</property>
|
||||
<property name="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Compress output</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_cbCompress</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">Compress output into 'zip' file</property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnCheckBox">onCompressCheck</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="false">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="false">
|
||||
<property name="Apply">0</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_stdButtons</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnOKButtonClick">onOKClick</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
56
pcbnew/dialogs/dialog_export_odbpp.h
Normal file
56
pcbnew/dialogs/dialog_export_odbpp.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2023 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 ODBPP_EXPORT_DIALOG_H
|
||||
#define ODBPP_EXPORT_DIALOG_H
|
||||
#include "dialog_export_odbpp_base.h"
|
||||
|
||||
class PCB_EDIT_FRAME;
|
||||
|
||||
class DIALOG_EXPORT_ODBPP : public DIALOG_EXPORT_ODBPP_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_EXPORT_ODBPP( PCB_EDIT_FRAME* aParent );
|
||||
|
||||
wxString GetOutputPath() const { return m_outputFileName->GetValue(); }
|
||||
|
||||
wxString GetUnitsString() const
|
||||
{
|
||||
if( m_choiceUnits->GetSelection() == 0 )
|
||||
return wxT( "mm" );
|
||||
else
|
||||
return wxT( "inch" );
|
||||
}
|
||||
|
||||
wxString GetPrecision() const { return wxString::Format( "%d", m_precision->GetValue() ); }
|
||||
|
||||
|
||||
bool GetCompress() const { return m_cbCompress->GetValue(); }
|
||||
|
||||
private:
|
||||
void onBrowseClicked( wxCommandEvent& event ) override;
|
||||
void onOKClick( wxCommandEvent& event ) override;
|
||||
|
||||
bool Init();
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
PCB_EDIT_FRAME* m_parent;
|
||||
};
|
||||
|
||||
#endif // ODBPP_EXPORT_DIALOG_H
|
117
pcbnew/dialogs/dialog_export_odbpp_base.cpp
Normal file
117
pcbnew/dialogs/dialog_export_odbpp_base.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
|
||||
#include "dialog_export_odbpp_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_EXPORT_ODBPP_BASE::DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bMainSizer;
|
||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
bSizerTop = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_lblBrdFile = new wxStaticText( this, wxID_ANY, _("File:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_lblBrdFile->Wrap( -1 );
|
||||
bSizerTop->Add( m_lblBrdFile, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_outputFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_outputFileName->SetToolTip( _("Enter a filename if you do not want to use default file names\nCan be used only when printing the current sheet") );
|
||||
m_outputFileName->SetMinSize( wxSize( 350,-1 ) );
|
||||
|
||||
bSizerTop->Add( m_outputFileName, 1, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_browseButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizerTop->Add( m_browseButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bSizerTop, 0, wxBOTTOM|wxEXPAND|wxTOP, 15 );
|
||||
|
||||
wxBoxSizer* bSizer3;
|
||||
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxStaticBoxSizer* sbSizer1;
|
||||
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("File Format") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizer;
|
||||
fgSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
fgSizer->AddGrowableCol( 1 );
|
||||
fgSizer->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_lblUnits = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_lblUnits->Wrap( -1 );
|
||||
fgSizer->Add( m_lblUnits, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
wxString m_choiceUnitsChoices[] = { _("Millimeters"), _("Inches") };
|
||||
int m_choiceUnitsNChoices = sizeof( m_choiceUnitsChoices ) / sizeof( wxString );
|
||||
m_choiceUnits = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( 130,30 ), m_choiceUnitsNChoices, m_choiceUnitsChoices, 0 );
|
||||
m_choiceUnits->SetSelection( 0 );
|
||||
fgSizer->Add( m_choiceUnits, 0, wxALIGN_RIGHT|wxALL, 5 );
|
||||
|
||||
m_lblPrecision = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Precision:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_lblPrecision->Wrap( -1 );
|
||||
m_lblPrecision->SetToolTip( _("The number of values following the decimal separator") );
|
||||
|
||||
fgSizer->Add( m_lblPrecision, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_precision = new wxSpinCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 130,30 ), wxSP_ARROW_KEYS, 2, 16, 3 );
|
||||
m_precision->SetToolTip( _("The number of values following the decimal separator") );
|
||||
|
||||
fgSizer->Add( m_precision, 0, wxALIGN_RIGHT|wxALL, 5 );
|
||||
|
||||
m_cbCompress = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Compress output"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbCompress->SetToolTip( _("Compress output into 'zip' file") );
|
||||
|
||||
fgSizer->Add( m_cbCompress, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
sbSizer1->Add( fgSizer, 3, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
bSizer3->Add( sbSizer1, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 10 );
|
||||
|
||||
|
||||
bMainSizer->Add( bSizer3, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_stdButtons = new wxStdDialogButtonSizer();
|
||||
m_stdButtonsOK = new wxButton( this, wxID_OK );
|
||||
m_stdButtons->AddButton( m_stdButtonsOK );
|
||||
m_stdButtonsCancel = new wxButton( this, wxID_CANCEL );
|
||||
m_stdButtons->AddButton( m_stdButtonsCancel );
|
||||
m_stdButtons->Realize();
|
||||
|
||||
bMainSizer->Add( m_stdButtons, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
this->Layout();
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onBrowseClicked ), NULL, this );
|
||||
m_cbCompress->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onCompressCheck ), NULL, this );
|
||||
m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onOKClick ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_EXPORT_ODBPP_BASE::~DIALOG_EXPORT_ODBPP_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onBrowseClicked ), NULL, this );
|
||||
m_cbCompress->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onCompressCheck ), NULL, this );
|
||||
m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXPORT_ODBPP_BASE::onOKClick ), NULL, this );
|
||||
|
||||
}
|
72
pcbnew/dialogs/dialog_export_odbpp_base.h
Normal file
72
pcbnew/dialogs/dialog_export_odbpp_base.h
Normal file
@ -0,0 +1,72 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class STD_BITMAP_BUTTON;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_EXPORT_ODBPP_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_EXPORT_ODBPP_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxBoxSizer* bSizerTop;
|
||||
wxStaticText* m_lblBrdFile;
|
||||
wxTextCtrl* m_outputFileName;
|
||||
STD_BITMAP_BUTTON* m_browseButton;
|
||||
wxStaticText* m_lblUnits;
|
||||
wxChoice* m_choiceUnits;
|
||||
wxStaticText* m_lblPrecision;
|
||||
wxSpinCtrl* m_precision;
|
||||
wxCheckBox* m_cbCompress;
|
||||
wxStdDialogButtonSizer* m_stdButtons;
|
||||
wxButton* m_stdButtonsOK;
|
||||
wxButton* m_stdButtonsCancel;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void onBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onCompressCheck( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onOKClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_EXPORT_ODBPP_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Export ODB++"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 380,300 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
|
||||
~DIALOG_EXPORT_ODBPP_BASE();
|
||||
|
||||
};
|
||||
|
143
pcbnew/files.cpp
143
pcbnew/files.cpp
@ -63,6 +63,7 @@
|
||||
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
|
||||
#include <dialogs/dialog_export_2581.h>
|
||||
#include <dialogs/dialog_map_layers.h>
|
||||
#include <dialogs/dialog_export_odbpp.h>
|
||||
#include <dialogs/dialog_import_choose_project.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include "footprint_info_impl.h"
|
||||
@ -80,6 +81,7 @@
|
||||
#include <wx/txtstrm.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/zipstrm.h>
|
||||
#include <wx/dir.h>
|
||||
|
||||
#include "widgets/filedlg_hook_save_project.h"
|
||||
|
||||
@ -1404,3 +1406,144 @@ void PCB_EDIT_FRAME::GenIPC2581File( wxCommandEvent& event )
|
||||
|
||||
GetScreen()->SetContentModified( false );
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::GenODBPPFiles( wxCommandEvent& event )
|
||||
{
|
||||
DIALOG_EXPORT_ODBPP dlg( this );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
wxFileName pcbFileName = dlg.GetOutputPath();
|
||||
|
||||
// Write through symlinks, don't replace them
|
||||
WX_FILENAME::ResolvePossibleSymlinks( pcbFileName );
|
||||
|
||||
if( !IsWritable( pcbFileName ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
|
||||
pcbFileName.GetFullPath() );
|
||||
|
||||
DisplayErrorMessage( this, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !wxFileName::DirExists( pcbFileName.GetFullPath() ) )
|
||||
{
|
||||
// Make every directory provided when the provided path doesn't exist
|
||||
if( !wxFileName::Mkdir( pcbFileName.GetFullPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( _( "Cannot create output directory '%s'." ), pcbFileName.GetFullPath() );
|
||||
|
||||
DisplayErrorMessage( this, msg );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxFileName tempFile( pcbFileName.GetFullPath(), "" );
|
||||
tempFile.AppendDir( "odb" );
|
||||
|
||||
wxString upperTxt;
|
||||
wxString lowerTxt;
|
||||
std::map<std::string, UTF8> props;
|
||||
|
||||
props["units"] = dlg.GetUnitsString();
|
||||
props["sigfig"] = dlg.GetPrecision();
|
||||
WX_PROGRESS_REPORTER reporter( this, _( "Generating ODB++ output files" ), 5 );
|
||||
|
||||
auto saveFile = [&]() -> bool
|
||||
{
|
||||
try
|
||||
{
|
||||
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::ODBPP ) );
|
||||
pi->SetProgressReporter( &reporter );
|
||||
pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), &props );
|
||||
return true;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, wxString::Format( _( "Error generating ODBPP files '%s'.\n%s" ),
|
||||
tempFile.GetFullPath(), ioe.What() ) );
|
||||
|
||||
lowerTxt.Printf( _( "Failed to create directory '%s'." ), tempFile.GetFullPath() );
|
||||
|
||||
SetMsgPanel( upperTxt, lowerTxt );
|
||||
|
||||
// In case we started a file but didn't fully write it, clean up
|
||||
wxFileName::Rmdir( tempFile.GetFullPath() );
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
auto ret = tp.submit( saveFile );
|
||||
|
||||
std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
|
||||
while( status != std::future_status::ready )
|
||||
{
|
||||
reporter.KeepRefreshing();
|
||||
status = ret.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if( !ret.get() )
|
||||
return;
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
wxLogError( "Exception in ODB++ generation: %s", e.what() );
|
||||
GetScreen()->SetContentModified( false );
|
||||
return;
|
||||
}
|
||||
|
||||
if( dlg.GetCompress() )
|
||||
{
|
||||
wxFileName zipFileName( pcbFileName.GetFullPath(), "odb.zip" );
|
||||
|
||||
wxFFileOutputStream fnout( zipFileName.GetFullPath() );
|
||||
wxZipOutputStream zipStream( fnout );
|
||||
|
||||
std::function<void( const wxString&, const wxString& )> addDirToZip =
|
||||
[&]( const wxString& dirPath, const wxString& parentPath )
|
||||
{
|
||||
wxDir dir( dirPath );
|
||||
wxString fileName;
|
||||
|
||||
bool cont = dir.GetFirst( &fileName, wxEmptyString, wxDIR_DEFAULT );
|
||||
while( cont )
|
||||
{
|
||||
wxFileName fileInZip( dirPath, fileName );
|
||||
wxString relativePath =
|
||||
parentPath.IsEmpty()
|
||||
? fileName
|
||||
: parentPath + wxString( wxFileName::GetPathSeparator() )
|
||||
+ fileName;
|
||||
|
||||
if( wxFileName::DirExists( fileInZip.GetFullPath() ) )
|
||||
{
|
||||
zipStream.PutNextDirEntry( relativePath );
|
||||
addDirToZip( fileInZip.GetFullPath(), relativePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFFileInputStream fileStream( fileInZip.GetFullPath() );
|
||||
zipStream.PutNextEntry( relativePath );
|
||||
fileStream.Read( zipStream );
|
||||
}
|
||||
cont = dir.GetNext( &fileName );
|
||||
}
|
||||
};
|
||||
|
||||
addDirToZip( tempFile.GetFullPath(), wxEmptyString );
|
||||
|
||||
zipStream.Close();
|
||||
fnout.Close();
|
||||
}
|
||||
|
||||
GetScreen()->SetContentModified( false );
|
||||
}
|
||||
|
@ -168,6 +168,10 @@ void PCB_EDIT_FRAME::doReCreateMenuBar()
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generateGerbers );
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generateDrillFiles );
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generateIPC2581File );
|
||||
|
||||
if( ADVANCED_CFG::GetCfg().m_EnableODB )
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generateODBPPFile );
|
||||
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generatePosFile );
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generateReportFile );
|
||||
submenuFabOutputs->Add( PCB_ACTIONS::generateD356File );
|
||||
|
@ -346,6 +346,11 @@ public:
|
||||
*/
|
||||
void GenIPC2581File( wxCommandEvent& event );
|
||||
|
||||
/**
|
||||
* Create and Generate ODB++ output files
|
||||
*/
|
||||
void GenODBPPFiles( wxCommandEvent& event );
|
||||
|
||||
/**
|
||||
* Create an ASCII footprint report file giving some infos on footprints and board outlines.
|
||||
*
|
||||
|
38
pcbnew/pcb_io/odbpp/CMakeLists.txt
Normal file
38
pcbnew/pcb_io/odbpp/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# This program source code file is part of KiCad, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2024 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
# Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# Sources for the pcbnew pcb_io called ODB++
|
||||
|
||||
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
||||
|
||||
set( ODBPP_SRCS
|
||||
odb_util.cpp
|
||||
odb_attribute.cpp
|
||||
odb_feature.cpp
|
||||
odb_component.cpp
|
||||
odb_netlist.cpp
|
||||
odb_eda_data.cpp
|
||||
odb_fonts.cpp
|
||||
odb_entity.cpp
|
||||
pcb_io_odbpp.cpp
|
||||
)
|
||||
|
||||
add_library( odbpp STATIC ${ODBPP_SRCS} )
|
||||
|
||||
target_link_libraries( odbpp pcbcommon )
|
101
pcbnew/pcb_io/odbpp/odb_attribute.cpp
Normal file
101
pcbnew/pcb_io/odbpp/odb_attribute.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "odb_attribute.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
size_t ATTR_MANAGER::GetTextIndex( std::unordered_map<std::string, size_t>& aMap,
|
||||
std::vector<std::pair<size_t, std::string>>& aVec,
|
||||
const std::string& aText )
|
||||
{
|
||||
if( aMap.count( aText ) )
|
||||
{
|
||||
return aMap.at( aText );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto index = aMap.size();
|
||||
aMap.emplace( aText, index );
|
||||
aVec.emplace_back( index, aText );
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t ATTR_MANAGER::GetAttrNameNumber( const wxString& aName )
|
||||
{
|
||||
return GetTextIndex( m_attrNames, m_attrNameVec, aName.Lower().ToStdString() );
|
||||
}
|
||||
|
||||
|
||||
size_t ATTR_MANAGER::GetAttrTextNumber( const wxString& aText )
|
||||
{
|
||||
return GetTextIndex( m_attrTexts, m_attrTextVec, aText.Upper().ToStdString() );
|
||||
}
|
||||
|
||||
|
||||
void ATTR_RECORD_WRITER::WriteAttributes( std::ostream& ost ) const
|
||||
{
|
||||
ODB::CHECK_ONCE once;
|
||||
|
||||
for( const auto& attr : attributes )
|
||||
{
|
||||
if( once() )
|
||||
ost << ";";
|
||||
else
|
||||
ost << ",";
|
||||
ost << attr.first;
|
||||
if( attr.second.size() )
|
||||
ost << "=" << attr.second;
|
||||
}
|
||||
|
||||
ost << ";";
|
||||
}
|
||||
|
||||
|
||||
void ATTR_MANAGER::WriteAttributesName( std::ostream& ost, const std::string& prefix ) const
|
||||
{
|
||||
for( const auto& [n, name] : m_attrNameVec )
|
||||
{
|
||||
ost << prefix << "@" << n << " " << name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ATTR_MANAGER::WriteAttributesText( std::ostream& ost, const std::string& prefix ) const
|
||||
{
|
||||
for( const auto& [n, name] : m_attrTextVec )
|
||||
{
|
||||
ost << prefix << "&" << n << " " << name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ATTR_MANAGER::WriteAttributes( std::ostream& ost, const std::string& prefix ) const
|
||||
{
|
||||
ost << std::endl << "#\n#Feature attribute names\n#" << std::endl;
|
||||
WriteAttributesName( ost );
|
||||
|
||||
ost << std::endl << "#\n#Feature attribute text strings\n#" << std::endl;
|
||||
WriteAttributesText( ost );
|
||||
}
|
352
pcbnew/pcb_io/odbpp/odb_attribute.h
Normal file
352
pcbnew/pcb_io/odbpp/odb_attribute.h
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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 _ATTRIBUTE_PROVIDER_H_
|
||||
#define _ATTRIBUTE_PROVIDER_H_
|
||||
|
||||
#include "odb_util.h"
|
||||
#include "stroke_params.h"
|
||||
#include <wx/string.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace ODB_ATTR
|
||||
{
|
||||
|
||||
enum class TYPE
|
||||
{
|
||||
FLOAT,
|
||||
BOOLEAN,
|
||||
TEXT,
|
||||
OPTION,
|
||||
INTEGER
|
||||
};
|
||||
|
||||
// Base class template for attributes
|
||||
template <typename T, TYPE AttrType>
|
||||
struct AttributeBase
|
||||
{
|
||||
using ValueType = T;
|
||||
static constexpr TYPE type = AttrType;
|
||||
constexpr AttributeBase( T v ) : value( v ) {}
|
||||
T value;
|
||||
};
|
||||
|
||||
// Specialized attribute types
|
||||
template <typename T, unsigned int N>
|
||||
struct FloatAttribute : AttributeBase<double, TYPE::FLOAT>
|
||||
{
|
||||
static constexpr unsigned int digits = N;
|
||||
using AttributeBase<double, TYPE::FLOAT>::AttributeBase;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BooleanAttribute : AttributeBase<bool, TYPE::BOOLEAN>
|
||||
{
|
||||
using AttributeBase<bool, TYPE::BOOLEAN>::AttributeBase;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TextAttribute : AttributeBase<std::string, TYPE::TEXT>
|
||||
{
|
||||
constexpr TextAttribute( const std::string& t ) :
|
||||
AttributeBase<std::string, TYPE::TEXT>( ODB::GenLegalEntityName( t ).ToStdString() )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OPTION_Attribute : AttributeBase<int, TYPE::OPTION>
|
||||
{
|
||||
using AttributeBase<int, TYPE::OPTION>::AttributeBase;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct AttributeName
|
||||
{
|
||||
};
|
||||
|
||||
// Attribute name and type definitions
|
||||
template <typename Tag, template <typename, unsigned int> class Attr, TYPE AttrType, unsigned int N>
|
||||
struct Attribute
|
||||
{
|
||||
using TYPE = Attr<Tag, N>;
|
||||
};
|
||||
|
||||
template <typename Tag, template <typename> class Attr, TYPE AttrType>
|
||||
struct AttributeSimple
|
||||
{
|
||||
using TYPE = Attr<Tag>;
|
||||
};
|
||||
|
||||
// TYPE traits for attributes
|
||||
template <typename T>
|
||||
struct IsFeature : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsNet : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsPkg : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsLayer : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsStep : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsComp : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsProductModel : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct IsSymbol : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
#define DEFINE_ATTR( Tag, Attr, AttrType, AttrName, ... ) \
|
||||
struct Tag##_t \
|
||||
{ \
|
||||
}; \
|
||||
constexpr const char Tag##_name[] = AttrName; \
|
||||
using Tag = Attribute<Tag##_t, Attr, AttrType, __VA_ARGS__>::TYPE; \
|
||||
template <> \
|
||||
struct AttributeName<Tag> \
|
||||
{ \
|
||||
static constexpr const char* name = Tag##_name; \
|
||||
};
|
||||
|
||||
#define DEFINE_ATTR_SIMPLE( Tag, Attr, AttrType, AttrName ) \
|
||||
struct Tag##_t \
|
||||
{ \
|
||||
}; \
|
||||
constexpr const char Tag##_name[] = AttrName; \
|
||||
using Tag = AttributeSimple<Tag##_t, Attr, AttrType>::TYPE; \
|
||||
template <> \
|
||||
struct AttributeName<Tag> \
|
||||
{ \
|
||||
static constexpr const char* name = Tag##_name; \
|
||||
};
|
||||
|
||||
|
||||
#define DEFINE_FLOAT_ATTR( NAME, N ) DEFINE_ATTR( NAME, FloatAttribute, TYPE::FLOAT, #NAME, N )
|
||||
|
||||
#define DEFINE_BOOLEAN_ATTR( NAME ) \
|
||||
DEFINE_ATTR_SIMPLE( NAME, BooleanAttribute, TYPE::BOOLEAN, #NAME )
|
||||
|
||||
#define DEFINE_TEXT_ATTR( NAME ) DEFINE_ATTR_SIMPLE( NAME, TextAttribute, TYPE::TEXT, #NAME )
|
||||
|
||||
#define DEFINE_OPTION_ATTR( NAME ) \
|
||||
struct NAME##_t \
|
||||
{ \
|
||||
}; \
|
||||
template <> \
|
||||
struct AttributeSimple<NAME##_t, OPTION_Attribute, TYPE::OPTION>; \
|
||||
template <> \
|
||||
struct AttributeName<NAME> \
|
||||
{ \
|
||||
static constexpr const char* name = #NAME; \
|
||||
};
|
||||
|
||||
|
||||
// used by which entity
|
||||
#define USED_BY_FEATURE_ENTITY( NAME ) \
|
||||
template <> \
|
||||
struct IsFeature<NAME> : std::true_type \
|
||||
{ \
|
||||
};
|
||||
|
||||
#define USED_BY_NET_ENTITY( NAME ) \
|
||||
template <> \
|
||||
struct IsNet<NAME> : std::true_type \
|
||||
{ \
|
||||
};
|
||||
|
||||
#define USED_BY_PKG_ENTITY( NAME ) \
|
||||
template <> \
|
||||
struct IsPkg<NAME> : std::true_type \
|
||||
{ \
|
||||
};
|
||||
|
||||
// Attribute definitions
|
||||
// BOOLEAN ATTRIBUTES
|
||||
DEFINE_BOOLEAN_ATTR( SMD )
|
||||
USED_BY_FEATURE_ENTITY( SMD )
|
||||
|
||||
DEFINE_BOOLEAN_ATTR( NET_POINT )
|
||||
USED_BY_FEATURE_ENTITY( NET_POINT )
|
||||
|
||||
DEFINE_BOOLEAN_ATTR( ROUT_PLATED )
|
||||
USED_BY_FEATURE_ENTITY( ROUT_PLATED )
|
||||
|
||||
DEFINE_BOOLEAN_ATTR( MECHANICAL )
|
||||
|
||||
DEFINE_BOOLEAN_ATTR( MOUNT_HOLE )
|
||||
USED_BY_FEATURE_ENTITY( MOUNT_HOLE )
|
||||
|
||||
DEFINE_BOOLEAN_ATTR( TEAR_DROP )
|
||||
USED_BY_FEATURE_ENTITY( TEAR_DROP )
|
||||
|
||||
DEFINE_BOOLEAN_ATTR( TEST_POINT )
|
||||
USED_BY_FEATURE_ENTITY( TEST_POINT )
|
||||
|
||||
// TEXT ATTRIBUTES
|
||||
DEFINE_TEXT_ATTR( STRING )
|
||||
USED_BY_FEATURE_ENTITY( STRING )
|
||||
|
||||
DEFINE_TEXT_ATTR( GEOMETRY )
|
||||
USED_BY_FEATURE_ENTITY( GEOMETRY )
|
||||
|
||||
DEFINE_TEXT_ATTR( NET_NAME )
|
||||
USED_BY_FEATURE_ENTITY( NET_NAME )
|
||||
|
||||
|
||||
// FLOAT ATTRIBUTES
|
||||
DEFINE_FLOAT_ATTR( BOARD_THICKNESS, 1 ) // 0.0~10.0
|
||||
|
||||
DEFINE_FLOAT_ATTR( STRING_ANGLE, 1 ) // 0.0~360.0
|
||||
USED_BY_FEATURE_ENTITY( STRING_ANGLE )
|
||||
|
||||
|
||||
// OPTION ATTRIBUTES
|
||||
enum class DRILL
|
||||
{
|
||||
PLATED,
|
||||
NON_PLATED,
|
||||
VIA
|
||||
};
|
||||
DEFINE_OPTION_ATTR( DRILL )
|
||||
USED_BY_FEATURE_ENTITY( DRILL )
|
||||
|
||||
enum class PAD_USAGE
|
||||
{
|
||||
TOEPRINT,
|
||||
VIA,
|
||||
G_FIDUCIAL,
|
||||
L_FIDUCIAL,
|
||||
TOOLING_HOLE,
|
||||
BOND_FINGER
|
||||
};
|
||||
DEFINE_OPTION_ATTR( PAD_USAGE )
|
||||
USED_BY_FEATURE_ENTITY( PAD_USAGE )
|
||||
|
||||
enum class PLATED_TYPE
|
||||
{
|
||||
STANDARD,
|
||||
PRESS_FIT
|
||||
};
|
||||
DEFINE_OPTION_ATTR( PLATED_TYPE )
|
||||
USED_BY_FEATURE_ENTITY( PLATED_TYPE )
|
||||
|
||||
enum class VIA_TYPE
|
||||
{
|
||||
DRILLED,
|
||||
LASER,
|
||||
PHOTO
|
||||
};
|
||||
DEFINE_OPTION_ATTR( VIA_TYPE )
|
||||
USED_BY_FEATURE_ENTITY( VIA_TYPE )
|
||||
|
||||
} // namespace ODB_ATTR
|
||||
|
||||
|
||||
class ATTR_MANAGER
|
||||
{
|
||||
public:
|
||||
ATTR_MANAGER() = default;
|
||||
virtual ~ATTR_MANAGER() = default;
|
||||
|
||||
template <typename Tr, typename Ta>
|
||||
void AddFeatureAttribute( Tr& r, Ta v )
|
||||
{
|
||||
const auto id = GetAttrNameNumber( ODB_ATTR::AttributeName<Ta>::name );
|
||||
|
||||
if constexpr( std::is_enum_v<Ta> )
|
||||
r.attributes.emplace( id, std::to_string( static_cast<int>( v ) ) );
|
||||
else
|
||||
r.attributes.emplace( id, AttrValue2String( v ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t GetAttrNameNumber( const wxString& name );
|
||||
|
||||
void WriteAttributes( std::ostream& ost, const std::string& prefix = "" ) const;
|
||||
void WriteAttributesName( std::ostream& ost, const std::string& prefix = "" ) const;
|
||||
void WriteAttributesText( std::ostream& ost, const std::string& prefix = "" ) const;
|
||||
|
||||
|
||||
private:
|
||||
size_t GetAttrTextNumber( const wxString& aName );
|
||||
size_t GetTextIndex( std::unordered_map<std::string, size_t>& aMap,
|
||||
std::vector<std::pair<size_t, std::string>>& aVec,
|
||||
const std::string& aText );
|
||||
|
||||
template <typename T, unsigned int n>
|
||||
std::string AttrValue2String( ODB_ATTR::FloatAttribute<T, n> a )
|
||||
{
|
||||
return ODB::Double2String( a.value, a.digits );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string AttrValue2String( ODB_ATTR::BooleanAttribute<T> a )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string AttrValue2String( ODB_ATTR::TextAttribute<T> a )
|
||||
{
|
||||
return std::to_string( GetAttrTextNumber( a.value ) );
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<std::string, size_t> m_attrNames;
|
||||
std::vector<std::pair<size_t, std::string>> m_attrNameVec;
|
||||
|
||||
std::unordered_map<std::string, size_t> m_attrTexts;
|
||||
std::vector<std::pair<size_t, std::string>> m_attrTextVec;
|
||||
};
|
||||
|
||||
class ATTR_RECORD_WRITER
|
||||
{
|
||||
public:
|
||||
ATTR_RECORD_WRITER() = default;
|
||||
virtual ~ATTR_RECORD_WRITER() = default;
|
||||
|
||||
void WriteAttributes( std::ostream& ost ) const;
|
||||
|
||||
public:
|
||||
std::map<unsigned int, std::string> attributes;
|
||||
};
|
||||
|
||||
|
||||
#endif // ATTRIBUTE_PROVIDER_H_
|
94
pcbnew/pcb_io/odbpp/odb_component.cpp
Normal file
94
pcbnew/pcb_io/odbpp/odb_component.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "odb_component.h"
|
||||
#include "odb_util.h"
|
||||
#include "hash_eda.h"
|
||||
#include "pcb_io_odbpp.h"
|
||||
|
||||
|
||||
ODB_COMPONENT& COMPONENTS_MANAGER::AddComponent( const FOOTPRINT* aFp,
|
||||
const EDA_DATA::PACKAGE& aPkg )
|
||||
{
|
||||
auto& comp = m_compList.emplace_back( m_compList.size(), aPkg.m_index );
|
||||
|
||||
comp.m_center = ODB::AddXY( aFp->GetPosition() );
|
||||
|
||||
if( aFp->GetOrientation() != ANGLE_0 )
|
||||
{
|
||||
// odb Rotation is expressed in degrees and is always clockwise.
|
||||
// while kicad EDA_ANGLE is anticlockwise.
|
||||
|
||||
comp.m_rot =
|
||||
ODB::Double2String( ( ANGLE_360 - aFp->GetOrientation() ).Normalize().AsDegrees() );
|
||||
}
|
||||
|
||||
if( aFp->GetLayer() != F_Cu )
|
||||
{
|
||||
comp.m_mirror = wxT( "M" );
|
||||
}
|
||||
|
||||
comp.m_comp_name = aFp->GetReference().ToAscii();
|
||||
comp.m_part_name =
|
||||
wxString::Format( "%s_%s_%s", aFp->GetFPID().GetFullLibraryName(),
|
||||
aFp->GetFPID().GetLibItemName().wx_str(), aFp->GetValue() );
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENTS_MANAGER::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
|
||||
|
||||
WriteAttributes( ost );
|
||||
|
||||
for( const auto& comp : m_compList )
|
||||
{
|
||||
comp.Write( ost );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_COMPONENT::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "# CMP " << m_index << std::endl;
|
||||
ost << "CMP " << m_pkg_ref << " " << m_center.first << " " << m_center.second << " " << m_rot
|
||||
<< " " << m_mirror << " " << m_comp_name << " " << m_part_name;
|
||||
|
||||
WriteAttributes( ost );
|
||||
|
||||
ost << std::endl;
|
||||
|
||||
for( const auto& toep : m_toeprints )
|
||||
{
|
||||
toep.Write( ost );
|
||||
}
|
||||
|
||||
ost << "#" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void ODB_COMPONENT::TOEPRINT::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "TOP " << m_pin_num << " " << m_center.first << " " << m_center.second << " " << m_rot
|
||||
<< " " << m_mirror << " " << m_net_num << " " << m_subnet_num << " " << m_toeprint_name
|
||||
<< std::endl;
|
||||
}
|
99
pcbnew/pcb_io/odbpp/odb_component.h
Normal file
99
pcbnew/pcb_io/odbpp/odb_component.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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 _ODB_COMPONENT_H_
|
||||
#define _ODB_COMPONENT_H_
|
||||
|
||||
#include "odb_util.h"
|
||||
#include <list>
|
||||
#include <wx/string.h>
|
||||
#include "odb_attribute.h"
|
||||
#include "odb_eda_data.h"
|
||||
|
||||
class ODB_COMPONENT;
|
||||
class COMPONENTS_MANAGER : public ATTR_MANAGER
|
||||
{
|
||||
public:
|
||||
COMPONENTS_MANAGER() = default;
|
||||
|
||||
virtual ~COMPONENTS_MANAGER() { m_compList.clear(); }
|
||||
|
||||
ODB_COMPONENT& AddComponent( const FOOTPRINT* aFp, const EDA_DATA::PACKAGE& aPkg );
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
|
||||
private:
|
||||
std::list<ODB_COMPONENT> m_compList;
|
||||
};
|
||||
|
||||
|
||||
class ODB_COMPONENT : public ATTR_RECORD_WRITER
|
||||
{
|
||||
public:
|
||||
ODB_COMPONENT( size_t aIndex, size_t r ) : m_index( aIndex ), m_pkg_ref( r ) {}
|
||||
|
||||
const size_t m_index; ///<! CMP index number on board to be used in SNT(TOP), 0~n-1
|
||||
size_t m_pkg_ref; ///<! package ref number from PKG in eda/data file, 0~n-1
|
||||
std::pair<wxString, wxString> m_center;
|
||||
wxString m_rot = wxT( "0" );
|
||||
wxString m_mirror = wxT( "N" );
|
||||
|
||||
wxString m_comp_name; ///<! Unique reference designator (component name)
|
||||
|
||||
wxString
|
||||
m_part_name; ///<! Part identification is a single string of ASCII characters without spaces
|
||||
|
||||
std::vector<std::pair<wxString, wxString>> m_prp; // !< Component Property Record
|
||||
|
||||
struct TOEPRINT
|
||||
{
|
||||
public:
|
||||
TOEPRINT( const EDA_DATA::PIN& pin ) :
|
||||
m_pin_num( pin.m_index ), m_toeprint_name( pin.m_name )
|
||||
{
|
||||
}
|
||||
|
||||
const size_t m_pin_num; ///<! index of PIN record in the eda/data file, 0~n-1.
|
||||
|
||||
std::pair<wxString, wxString> m_center; ///<! Board location of the pin.
|
||||
|
||||
wxString m_rot; ///<! Rotation, clockwise, it equals to the actual PAD rotation,
|
||||
///<! not CMP m_rot.
|
||||
|
||||
wxString m_mirror; ///<! equal to CMP m_mirror.
|
||||
|
||||
size_t m_net_num = 0; ///<! Number of NET record in the eda/data file.
|
||||
|
||||
size_t m_subnet_num = 0; ///<! Number of subnet (SNT record TOP) in the referenced net
|
||||
|
||||
wxString m_toeprint_name; ///<! Name of the pad in PIN record
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
};
|
||||
|
||||
|
||||
std::list<TOEPRINT> m_toeprints;
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // _ODB_COMPONENT_H_
|
34
pcbnew/pcb_io/odbpp/odb_defines.h
Normal file
34
pcbnew/pcb_io/odbpp/odb_defines.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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 _ODB_DEFINES_H_
|
||||
#define _ODB_DEFINES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#define ODB_JOB_NAME "JOB_NAME"
|
||||
#define ODB_UNITS "UNITS"
|
||||
#define ODB_DIM_X "x"
|
||||
#define ODB_DIM_R "r"
|
||||
#define ODB_DIM_C "c"
|
||||
#define ODB_NONE "NONE"
|
||||
|
||||
#endif // _ODB_DEFINES_H_
|
420
pcbnew/pcb_io/odbpp/odb_eda_data.cpp
Normal file
420
pcbnew/pcb_io/odbpp/odb_eda_data.cpp
Normal file
@ -0,0 +1,420 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "odb_eda_data.h"
|
||||
#include "hash_eda.h"
|
||||
#include "netinfo.h"
|
||||
#include "odb_feature.h"
|
||||
#include "base_units.h"
|
||||
#include "pcb_io_odbpp.h"
|
||||
|
||||
|
||||
EDA_DATA::EDA_DATA()
|
||||
{
|
||||
auto& x = nets_map.emplace( std::piecewise_construct, std::forward_as_tuple( 0 ),
|
||||
std::forward_as_tuple( nets.size(), "$NONE$" ) )
|
||||
.first->second;
|
||||
|
||||
nets.push_back( &x );
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::NET::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "NET " << m_name;
|
||||
|
||||
WriteAttributes( ost );
|
||||
|
||||
ost << std::endl;
|
||||
|
||||
for( const auto& subnet : subnets )
|
||||
{
|
||||
subnet->Write( ost );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::AddNET( const NETINFO_ITEM* aNet )
|
||||
{
|
||||
if( nets_map.end() == nets_map.find( aNet->GetNetCode() ) )
|
||||
{
|
||||
auto& net = nets_map.emplace( std::piecewise_construct,
|
||||
std::forward_as_tuple( aNet->GetNetCode() ),
|
||||
std::forward_as_tuple( nets.size(), aNet->GetNetname() ) )
|
||||
.first->second;
|
||||
|
||||
nets.push_back( &net );
|
||||
|
||||
//TODO: netname check
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::SUB_NET::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "SNT ";
|
||||
|
||||
WriteSubnet( ost );
|
||||
|
||||
ost << std::endl;
|
||||
|
||||
for( const auto& fid : feature_ids )
|
||||
{
|
||||
fid.Write( ost );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::FEATURE_ID::Write( std::ostream& ost ) const
|
||||
{
|
||||
static const std::map<TYPE, std::string> type_map = {
|
||||
{ TYPE::COPPER, "C" },
|
||||
{ TYPE::HOLE, "H" },
|
||||
};
|
||||
|
||||
ost << "FID " << type_map.at( type ) << " " << layer << " " << feature_id << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::SUB_NET_VIA::WriteSubnet( std::ostream& ost ) const
|
||||
{
|
||||
ost << "VIA";
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::SUB_NET_TRACE::WriteSubnet( std::ostream& ost ) const
|
||||
{
|
||||
ost << "TRC";
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::SUB_NET_PLANE::WriteSubnet( std::ostream& ost ) const
|
||||
{
|
||||
static const std::map<FILL_TYPE, std::string> fill_type_map = { { FILL_TYPE::SOLID, "S" },
|
||||
{ FILL_TYPE::OUTLINE, "O" } };
|
||||
|
||||
static const std::map<CUTOUT_TYPE, std::string> cutout_type_map = {
|
||||
{ CUTOUT_TYPE::CIRCLE, "C" },
|
||||
{ CUTOUT_TYPE::RECT, "R" },
|
||||
{ CUTOUT_TYPE::OCTAGON, "O" },
|
||||
{ CUTOUT_TYPE::EXACT, "E" }
|
||||
};
|
||||
|
||||
ost << "PLN " << fill_type_map.at( fill_type ) << " " << cutout_type_map.at( cutout_type )
|
||||
<< " " << fill_size;
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::SUB_NET_TOEPRINT::WriteSubnet( std::ostream& ost ) const
|
||||
{
|
||||
static const std::map<SIDE, std::string> side_map = {
|
||||
{ SIDE::BOTTOM, "B" },
|
||||
{ SIDE::TOP, "T" },
|
||||
};
|
||||
ost << "TOP " << side_map.at( side ) << " " << comp_num << " " << toep_num;
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::SUB_NET::AddFeatureID( FEATURE_ID::TYPE type, const wxString& layer,
|
||||
size_t feature_id )
|
||||
{
|
||||
feature_ids.emplace_back( type, m_edadata->GetLyrIdx( layer ), feature_id );
|
||||
}
|
||||
|
||||
|
||||
size_t EDA_DATA::GetLyrIdx( const wxString& aLayer )
|
||||
{
|
||||
if( layers_map.count( aLayer ) )
|
||||
{
|
||||
return layers_map.at( aLayer );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto idx = layers_map.size();
|
||||
layers_map.emplace( aLayer, idx );
|
||||
layers.push_back( aLayer );
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OUTLINE_SQUARE::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "SQ " << ODB::Data2String( m_center.x ) << " " << ODB::Data2String( m_center.y ) << " "
|
||||
<< ODB::Data2String( m_halfSide ) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void OUTLINE_CIRCLE::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "CR " << ODB::Data2String( m_center.x ) << " " << ODB::Data2String( m_center.y ) << " "
|
||||
<< ODB::Data2String( m_radius ) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void OUTLINE_RECT::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "RC " << ODB::Data2String( m_lower_left.x ) << " " << ODB::Data2String( m_lower_left.y )
|
||||
<< " " << ODB::Data2String( m_width ) << " " << ODB::Data2String( m_height ) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void OUTLINE_CONTOUR::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "CT" << std::endl;
|
||||
m_surfaces->WriteData( ost );
|
||||
ost << "CE" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::AddPackage( const FOOTPRINT* aFp )
|
||||
{
|
||||
// ODBPP only need unique PACKAGE in PKG record in eda/data file.
|
||||
// the PKG index can repeat to be ref in CMP record in component file.
|
||||
|
||||
std::shared_ptr<FOOTPRINT> fp( static_cast<FOOTPRINT*>( aFp->Clone() ) );
|
||||
m_eda_footprints.emplace_back( fp );
|
||||
fp->SetParentGroup( nullptr );
|
||||
fp->SetPosition( { 0, 0 } );
|
||||
|
||||
if( fp->GetLayer() != F_Cu )
|
||||
fp->Flip( fp->GetPosition(), false );
|
||||
|
||||
fp->SetOrientation( ANGLE_0 );
|
||||
|
||||
size_t hash = hash_fp_item( fp.get(), HASH_POS | REL_COORD );
|
||||
size_t pkg_index = packages_map.size();
|
||||
wxString fp_name = fp->GetFPID().GetLibItemName().wx_str();
|
||||
|
||||
auto [iter, success] = packages_map.emplace( hash, PACKAGE( pkg_index, fp_name ) );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PACKAGE* pkg = &( iter->second );
|
||||
|
||||
packages.push_back( pkg );
|
||||
|
||||
BOX2I bbox = fp->GetBoundingBox();
|
||||
pkg->m_xmin = bbox.GetPosition().x;
|
||||
pkg->m_ymin = bbox.GetPosition().y;
|
||||
pkg->m_xmax = bbox.GetEnd().x;
|
||||
pkg->m_ymax = bbox.GetEnd().y;
|
||||
pkg->m_pitch = UINT64_MAX;
|
||||
|
||||
if( fp->Pads().size() < 2 )
|
||||
pkg->m_pitch = pcbIUScale.mmToIU( 1.0 ); // placeholder value
|
||||
|
||||
for( size_t i = 0; i < fp->Pads().size(); ++i )
|
||||
{
|
||||
const PAD* pad1 = fp->Pads()[i];
|
||||
for( size_t j = i + 1; j < fp->Pads().size(); ++j )
|
||||
{
|
||||
const PAD* pad2 = fp->Pads()[j];
|
||||
const uint64_t pin_dist = ( pad1->GetCenter() - pad2->GetCenter() ).EuclideanNorm();
|
||||
pkg->m_pitch = std::min( pkg->m_pitch, pin_dist );
|
||||
}
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& courtyard = fp->GetCourtyard( F_CrtYd );
|
||||
const SHAPE_POLY_SET& courtyard_back = fp->GetCourtyard( B_CrtYd );
|
||||
SHAPE_POLY_SET pkg_outline;
|
||||
|
||||
if( courtyard.OutlineCount() > 0 )
|
||||
pkg_outline = courtyard;
|
||||
|
||||
if( courtyard_back.OutlineCount() > 0 )
|
||||
{
|
||||
pkg_outline = courtyard_back;
|
||||
}
|
||||
|
||||
if( !courtyard.OutlineCount() && !courtyard_back.OutlineCount() )
|
||||
{
|
||||
pkg_outline = fp->GetBoundingHull();
|
||||
}
|
||||
|
||||
// TODO: Here we put rect, square, and circle, all as polygon
|
||||
|
||||
if( pkg_outline.OutlineCount() > 0 )
|
||||
{
|
||||
for( int ii = 0; ii < pkg_outline.OutlineCount(); ++ii )
|
||||
{
|
||||
pkg->m_pkgOutlines.push_back(
|
||||
std::make_unique<OUTLINE_CONTOUR>( pkg_outline.Polygon( ii ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < fp->Pads().size(); ++i )
|
||||
{
|
||||
const PAD* pad = fp->Pads()[i];
|
||||
pkg->AddPin( pad, i );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::PACKAGE::AddPin( const PAD* aPad, size_t aPinNum )
|
||||
{
|
||||
wxString name = aPad->GetNumber();
|
||||
|
||||
// Pins are required to have names, so if our pad doesn't have a name, we need to
|
||||
// generate one that is unique
|
||||
|
||||
if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
name = wxString::Format( "NPTH%zu", aPinNum );
|
||||
else if( name.empty() )
|
||||
name = wxString::Format( "PAD%zu", aPinNum );
|
||||
|
||||
// // for SNT record, pad, net, pin
|
||||
std::shared_ptr<PIN> pin = std::make_shared<PIN>( m_pinsVec.size(), name );
|
||||
m_pinsVec.push_back( pin );
|
||||
|
||||
VECTOR2D relpos = aPad->GetFPRelativePosition();
|
||||
|
||||
// TODO: is odb pkg pin center means center of pad hole or center of pad shape?
|
||||
|
||||
if( aPad->GetOffset().x != 0 || aPad->GetOffset().y != 0 )
|
||||
relpos += aPad->GetOffset();
|
||||
|
||||
pin->m_center = ODB::AddXY( relpos );
|
||||
|
||||
if( aPad->HasHole() )
|
||||
{
|
||||
pin->type = PIN::TYPE::THROUGH_HOLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pin->type = PIN::TYPE::SURFACE;
|
||||
}
|
||||
|
||||
if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
pin->etype = PIN::ELECTRICAL_TYPE::MECHANICAL;
|
||||
else if( aPad->IsOnCopperLayer() )
|
||||
pin->etype = PIN::ELECTRICAL_TYPE::ELECTRICAL;
|
||||
else
|
||||
pin->etype = PIN::ELECTRICAL_TYPE::UNDEFINED;
|
||||
|
||||
|
||||
if( ( aPad->HasHole() && aPad->IsOnCopperLayer() ) || aPad->GetAttribute() == PAD_ATTRIB::PTH )
|
||||
{
|
||||
pin->mtype = PIN::MOUNT_TYPE::THROUGH_HOLE;
|
||||
}
|
||||
else if( aPad->HasHole() && aPad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
{
|
||||
pin->mtype = PIN::MOUNT_TYPE::HOLE;
|
||||
}
|
||||
else if( aPad->GetAttribute() == PAD_ATTRIB::SMD )
|
||||
{
|
||||
pin->mtype = PIN::MOUNT_TYPE::SMT;
|
||||
}
|
||||
else
|
||||
{
|
||||
pin->mtype = PIN::MOUNT_TYPE::UNDEFINED;
|
||||
}
|
||||
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& polygons = aPad->GetEffectivePolygon( ERROR_INSIDE );
|
||||
|
||||
// TODO: Here we put all pad shapes as polygonl, we should switch by pad shape
|
||||
// Note:pad only use polygons->Polygon(0),
|
||||
if( polygons->OutlineCount() > 0 )
|
||||
{
|
||||
pin->m_pinOutlines.push_back( std::make_unique<OUTLINE_CONTOUR>( polygons->Polygon( 0 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::PIN::Write( std::ostream& ost ) const
|
||||
{
|
||||
static const std::map<TYPE, std::string> type_map = { { TYPE::SURFACE, "S" },
|
||||
{ TYPE::THROUGH_HOLE, "T" },
|
||||
{ TYPE::BLIND, "B" } };
|
||||
|
||||
static const std::map<ELECTRICAL_TYPE, std::string> etype_map = {
|
||||
{ ELECTRICAL_TYPE::ELECTRICAL, "E" },
|
||||
{ ELECTRICAL_TYPE::MECHANICAL, "M" },
|
||||
{ ELECTRICAL_TYPE::UNDEFINED, "U" }
|
||||
};
|
||||
static const std::map<MOUNT_TYPE, std::string> mtype_map = { { MOUNT_TYPE::THROUGH_HOLE, "T" },
|
||||
{ MOUNT_TYPE::HOLE, "H" },
|
||||
{ MOUNT_TYPE::SMT, "S" },
|
||||
{ MOUNT_TYPE::UNDEFINED, "U" } };
|
||||
|
||||
ost << "PIN " << m_name << " " << type_map.at( type ) << " " << m_center.first << " "
|
||||
<< m_center.second << " 0 " << etype_map.at( etype ) << " " << mtype_map.at( mtype )
|
||||
<< std::endl;
|
||||
|
||||
for( const auto& outline : m_pinOutlines )
|
||||
{
|
||||
outline->Write( ost );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::PACKAGE::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "PKG " << m_name << " " << ODB::Data2String( m_pitch ) << " "
|
||||
<< ODB::Data2String( m_xmin ) << " " << ODB::Data2String( m_ymin ) << " "
|
||||
<< ODB::Data2String( m_xmax ) << " " << ODB::Data2String( m_ymax ) << std::endl;
|
||||
|
||||
for( const auto& outline : m_pkgOutlines )
|
||||
{
|
||||
outline->Write( ost );
|
||||
}
|
||||
|
||||
for( const auto& pin : m_pinsVec )
|
||||
{
|
||||
pin->Write( ost );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_DATA::Write( std::ostream& ost ) const
|
||||
{
|
||||
ost << "# " << wxDateTime::Now().FormatISOCombined() << std::endl;
|
||||
ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
|
||||
ost << "LYR";
|
||||
|
||||
for( const auto& layer : layers )
|
||||
{
|
||||
ost << " " << layer;
|
||||
}
|
||||
|
||||
ost << std::endl;
|
||||
|
||||
WriteAttributes( ost, "#" );
|
||||
|
||||
for( const auto& net : nets )
|
||||
{
|
||||
ost << "#NET " << net->m_index << std::endl;
|
||||
net->Write( ost );
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for( const auto* pkg : packages )
|
||||
{
|
||||
ost << "# PKG " << i << std::endl;
|
||||
i++;
|
||||
pkg->Write( ost );
|
||||
ost << "#" << std::endl;
|
||||
}
|
||||
}
|
340
pcbnew/pcb_io/odbpp/odb_eda_data.h
Normal file
340
pcbnew/pcb_io/odbpp/odb_eda_data.h
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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 _ODB_EDA_DATA_H_
|
||||
#define _ODB_EDA_DATA_H_
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include "odb_attribute.h"
|
||||
#include "odb_feature.h"
|
||||
|
||||
|
||||
class PKG_OUTLINE;
|
||||
class EDA_DATA : public ATTR_MANAGER
|
||||
{
|
||||
public:
|
||||
EDA_DATA();
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
size_t GetLyrIdx( const wxString& aLayerName );
|
||||
std::vector<std::shared_ptr<FOOTPRINT>> GetEdaFootprints() const { return m_eda_footprints; }
|
||||
|
||||
class FEATURE_ID
|
||||
{
|
||||
friend EDA_DATA;
|
||||
|
||||
public:
|
||||
enum class TYPE
|
||||
{
|
||||
COPPER,
|
||||
LAMINATE,
|
||||
HOLE
|
||||
};
|
||||
|
||||
FEATURE_ID( TYPE t, size_t l, size_t fid ) : type( t ), layer( l ), feature_id( fid ) {}
|
||||
|
||||
TYPE type;
|
||||
size_t layer;
|
||||
size_t feature_id;
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
};
|
||||
|
||||
class SUB_NET
|
||||
{
|
||||
public:
|
||||
SUB_NET( size_t aIndex, EDA_DATA* aEda ) : m_index( aIndex ), m_edadata( aEda ) {}
|
||||
const size_t m_index;
|
||||
void Write( std::ostream& ost ) const;
|
||||
|
||||
std::list<FEATURE_ID> feature_ids;
|
||||
void AddFeatureID( FEATURE_ID::TYPE type, const wxString& layer, size_t feature_id );
|
||||
|
||||
virtual ~SUB_NET() {}
|
||||
|
||||
protected:
|
||||
virtual void WriteSubnet( std::ostream& ost ) const = 0;
|
||||
EDA_DATA* m_edadata;
|
||||
};
|
||||
|
||||
class SUB_NET_VIA : public SUB_NET
|
||||
{
|
||||
public:
|
||||
SUB_NET_VIA( size_t aIndex, EDA_DATA* aEda ) : SUB_NET( aIndex, aEda ) {}
|
||||
void WriteSubnet( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class SUB_NET_TRACE : public SUB_NET
|
||||
{
|
||||
public:
|
||||
SUB_NET_TRACE( size_t aIndex, EDA_DATA* aEda ) : SUB_NET( aIndex, aEda ) {}
|
||||
void WriteSubnet( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class SUB_NET_PLANE : public SUB_NET
|
||||
{
|
||||
public:
|
||||
enum class FILL_TYPE
|
||||
{
|
||||
SOLID,
|
||||
OUTLINE
|
||||
};
|
||||
|
||||
enum class CUTOUT_TYPE
|
||||
{
|
||||
CIRCLE,
|
||||
RECT,
|
||||
OCTAGON,
|
||||
EXACT
|
||||
};
|
||||
|
||||
SUB_NET_PLANE( size_t aIndex, EDA_DATA* aEda, FILL_TYPE aFill, CUTOUT_TYPE aCutout,
|
||||
size_t aFillSize ) :
|
||||
SUB_NET( aIndex, aEda ), fill_type( aFill ), cutout_type( aCutout ),
|
||||
fill_size( aFillSize )
|
||||
{
|
||||
}
|
||||
|
||||
FILL_TYPE fill_type;
|
||||
CUTOUT_TYPE cutout_type;
|
||||
size_t fill_size;
|
||||
|
||||
void WriteSubnet( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class SUB_NET_TOEPRINT : public SUB_NET
|
||||
{
|
||||
public:
|
||||
enum class SIDE
|
||||
{
|
||||
TOP,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
SUB_NET_TOEPRINT( size_t aIndex, EDA_DATA* aEda, SIDE aSide, size_t aCompNum,
|
||||
size_t aToepNum ) :
|
||||
SUB_NET( aIndex, aEda ), side( aSide ), comp_num( aCompNum ), toep_num( aToepNum )
|
||||
{
|
||||
}
|
||||
|
||||
~SUB_NET_TOEPRINT() {}
|
||||
|
||||
SIDE side;
|
||||
|
||||
size_t comp_num;
|
||||
size_t toep_num;
|
||||
|
||||
void WriteSubnet( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class NET : public ATTR_RECORD_WRITER
|
||||
{
|
||||
public:
|
||||
NET( size_t aIndex, const wxString& aName ) : m_index( aIndex ), m_name( aName ) {}
|
||||
|
||||
const size_t m_index;
|
||||
wxString m_name;
|
||||
std::list<std::unique_ptr<SUB_NET>> subnets;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T& AddSubnet( Args&&... args )
|
||||
{
|
||||
auto f = std::make_unique<T>( subnets.size(), std::forward<Args>( args )... );
|
||||
auto& r = *f;
|
||||
subnets.push_back( std::move( f ) );
|
||||
return r;
|
||||
}
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
};
|
||||
|
||||
void AddNET( const NETINFO_ITEM* aNet );
|
||||
NET& GetNet( size_t aNetcode ) { return nets_map.at( aNetcode ); }
|
||||
|
||||
class PIN
|
||||
{
|
||||
public:
|
||||
PIN( const size_t aIndex, const wxString& aName ) : m_index( aIndex ), m_name( aName ) {}
|
||||
|
||||
const size_t m_index;
|
||||
wxString m_name;
|
||||
|
||||
std::pair<wxString, wxString> m_center;
|
||||
|
||||
enum class TYPE
|
||||
{
|
||||
THROUGH_HOLE,
|
||||
BLIND,
|
||||
SURFACE
|
||||
};
|
||||
|
||||
TYPE type = TYPE::SURFACE;
|
||||
|
||||
enum class ELECTRICAL_TYPE
|
||||
{
|
||||
ELECTRICAL,
|
||||
MECHANICAL,
|
||||
UNDEFINED
|
||||
};
|
||||
|
||||
ELECTRICAL_TYPE etype = ELECTRICAL_TYPE::UNDEFINED;
|
||||
|
||||
enum class MOUNT_TYPE
|
||||
{
|
||||
SMT,
|
||||
SMT_RECOMMENDED,
|
||||
THROUGH_HOLE,
|
||||
THROUGH_RECOMMENDED,
|
||||
PRESSFIT,
|
||||
NON_BOARD,
|
||||
HOLE,
|
||||
UNDEFINED
|
||||
};
|
||||
MOUNT_TYPE mtype = MOUNT_TYPE::UNDEFINED;
|
||||
|
||||
std::list<std::unique_ptr<PKG_OUTLINE>> m_pinOutlines;
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
};
|
||||
|
||||
class PACKAGE : public ATTR_RECORD_WRITER
|
||||
{
|
||||
public:
|
||||
PACKAGE( const size_t aIndex, const wxString& afpName ) :
|
||||
m_index( aIndex ), m_name( afpName )
|
||||
{
|
||||
}
|
||||
|
||||
const size_t m_index; /// <! Reference number of the package to be used in CMP.
|
||||
wxString m_name;
|
||||
|
||||
size_t m_pitch;
|
||||
int64_t m_xmin, m_ymin, m_xmax, m_ymax; // Box points: leftlow, rightup
|
||||
|
||||
std::list<std::unique_ptr<PKG_OUTLINE>> m_pkgOutlines;
|
||||
|
||||
void AddPin( const PAD* aPad, size_t aPinNum );
|
||||
const std::shared_ptr<PIN> GetEdaPkgPin( size_t aPadIndex ) const
|
||||
{
|
||||
return m_pinsVec.at( aPadIndex );
|
||||
}
|
||||
|
||||
void Write( std::ostream& ost ) const;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<PIN>> m_pinsVec;
|
||||
};
|
||||
|
||||
void AddPackage( const FOOTPRINT* aFp );
|
||||
const PACKAGE& GetPackage( size_t aHash ) const { return packages_map.at( aHash ); }
|
||||
|
||||
private:
|
||||
std::map<size_t, NET> nets_map;
|
||||
std::list<const NET*> nets;
|
||||
|
||||
std::map<size_t, PACKAGE> packages_map; //hash value, package
|
||||
std::list<const PACKAGE*> packages;
|
||||
|
||||
std::map<wxString, size_t> layers_map;
|
||||
std::vector<wxString> layers;
|
||||
std::vector<std::shared_ptr<FOOTPRINT>> m_eda_footprints;
|
||||
};
|
||||
|
||||
class PKG_OUTLINE
|
||||
{
|
||||
public:
|
||||
virtual void Write( std::ostream& ost ) const = 0;
|
||||
|
||||
virtual ~PKG_OUTLINE() = default;
|
||||
};
|
||||
|
||||
class OUTLINE_RECT : public PKG_OUTLINE
|
||||
{
|
||||
public:
|
||||
OUTLINE_RECT( const VECTOR2I& aLowerLeft, size_t aWidth, size_t aHeight ) :
|
||||
m_lower_left( aLowerLeft ), m_width( aWidth ), m_height( aHeight )
|
||||
{
|
||||
}
|
||||
|
||||
OUTLINE_RECT( const BOX2I& aBox ) :
|
||||
OUTLINE_RECT( aBox.GetPosition(), aBox.GetWidth(), aBox.GetHeight() )
|
||||
{
|
||||
}
|
||||
|
||||
VECTOR2I m_lower_left;
|
||||
size_t m_width;
|
||||
size_t m_height;
|
||||
|
||||
void Write( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class ODB_SURFACE_DATA;
|
||||
class OUTLINE_CONTOUR : public PKG_OUTLINE
|
||||
{
|
||||
public:
|
||||
OUTLINE_CONTOUR( const SHAPE_POLY_SET::POLYGON& aPolygon,
|
||||
FILL_T aFillType = FILL_T::FILLED_SHAPE )
|
||||
{
|
||||
if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 )
|
||||
{
|
||||
m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon );
|
||||
if( aFillType != FILL_T::NO_FILL )
|
||||
{
|
||||
m_surfaces->AddPolygonHoles( aPolygon );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ODB_SURFACE_DATA> m_surfaces;
|
||||
|
||||
void Write( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class OUTLINE_SQUARE : public PKG_OUTLINE
|
||||
{
|
||||
public:
|
||||
OUTLINE_SQUARE( const VECTOR2I& aCenter, size_t aHalfSide ) :
|
||||
m_center( aCenter ), m_halfSide( aHalfSide )
|
||||
{
|
||||
}
|
||||
VECTOR2I m_center;
|
||||
size_t m_halfSide;
|
||||
|
||||
void Write( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
class OUTLINE_CIRCLE : public PKG_OUTLINE
|
||||
{
|
||||
public:
|
||||
OUTLINE_CIRCLE( const VECTOR2I& aCenter, size_t aRadius ) :
|
||||
m_center( aCenter ), m_radius( aRadius )
|
||||
{
|
||||
}
|
||||
VECTOR2I m_center;
|
||||
size_t m_radius;
|
||||
|
||||
void Write( std::ostream& ost ) const override;
|
||||
};
|
||||
|
||||
|
||||
#endif // _ODB_EDA_DATA_H_
|
975
pcbnew/pcb_io/odbpp/odb_entity.cpp
Normal file
975
pcbnew/pcb_io/odbpp/odb_entity.cpp
Normal file
@ -0,0 +1,975 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <base_units.h>
|
||||
#include <board_stackup_manager/stackup_predefined_prms.h>
|
||||
#include <build_version.h>
|
||||
#include <callback_gal.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <connectivity/connectivity_algo.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <font/font.h>
|
||||
#include <footprint.h>
|
||||
#include <hash_eda.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_dimension.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <pcb_text.h>
|
||||
#include <pcb_textbox.h>
|
||||
#include <pcb_track.h>
|
||||
#include <pcbnew_settings.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <progress_reporter.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <wx_fstream_progress.h>
|
||||
|
||||
#include <geometry/shape_circle.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/numformatter.h>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
#include "odb_attribute.h"
|
||||
#include "odb_entity.h"
|
||||
#include "odb_defines.h"
|
||||
#include "odb_feature.h"
|
||||
#include "odb_util.h"
|
||||
#include "pcb_io_odbpp.h"
|
||||
|
||||
|
||||
bool ODB_ENTITY_BASE::CreateDirectiryTree( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.CreateEntityDirectory( writer.GetRootPath(), GetEntityName() );
|
||||
return true;
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ODB_MISC_ENTITY::ODB_MISC_ENTITY()
|
||||
{
|
||||
m_info = { { wxS( ODB_JOB_NAME ), wxS( "job" ) },
|
||||
{ wxS( ODB_UNITS ), PCB_IO_ODBPP::m_unitsStr },
|
||||
{ wxS( "ODB_VERSION_MAJOR" ), wxS( "8" ) },
|
||||
{ wxS( "ODB_VERSION_MINOR" ), wxS( "1" ) },
|
||||
{ wxS( "ODB_SOURCE" ), wxS( "KiCad EDA" + GetMajorMinorPatchVersion() ) },
|
||||
{ wxS( "CREATION_DATE" ), wxDateTime::Now().FormatISOCombined() },
|
||||
{ wxS( "SAVE_DATE" ), wxDateTime::Now().FormatISOCombined() },
|
||||
{ wxS( "SAVE_APP" ), wxS( "Pcbnew" ) },
|
||||
{ wxS( "SAVE_USER" ), wxS( "" ) },
|
||||
{ wxS( "MAX_UID" ), wxS( "" ) } };
|
||||
}
|
||||
|
||||
|
||||
void ODB_MISC_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "info" );
|
||||
|
||||
ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
|
||||
|
||||
for( auto& info : m_info )
|
||||
{
|
||||
twriter.WriteEquationLine( info.first, info.second );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::AddStep( const wxString& aStepName )
|
||||
{
|
||||
m_matrixSteps.emplace( aStepName.Upper(), m_col++ );
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::InitEntityData()
|
||||
{
|
||||
AddStep( "PCB" );
|
||||
|
||||
InitMatrixLayerData();
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::InitMatrixLayerData()
|
||||
{
|
||||
BOARD_DESIGN_SETTINGS& dsnSettings = m_board->GetDesignSettings();
|
||||
BOARD_STACKUP& stackup = dsnSettings.GetStackupDescriptor();
|
||||
stackup.SynchronizeWithBoard( &dsnSettings );
|
||||
|
||||
std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
|
||||
std::set<PCB_LAYER_ID> added_layers;
|
||||
|
||||
for( int i = 0; i < stackup.GetCount(); i++ )
|
||||
{
|
||||
BOARD_STACKUP_ITEM* stackup_item = layers.at( i );
|
||||
|
||||
for( int sublayer_id = 0; sublayer_id < stackup_item->GetSublayersCount(); sublayer_id++ )
|
||||
{
|
||||
wxString ly_name = stackup_item->GetLayerName();
|
||||
|
||||
if( ly_name.IsEmpty() )
|
||||
{
|
||||
if( IsValidLayer( stackup_item->GetBrdLayerId() ) )
|
||||
ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() );
|
||||
|
||||
if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
|
||||
ly_name = wxString::Format( "DIELECTRIC_%d",
|
||||
stackup_item->GetDielectricLayerId() );
|
||||
}
|
||||
|
||||
MATRIX_LAYER matrix( m_row++, ly_name );
|
||||
|
||||
if( stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
|
||||
{
|
||||
if( stackup_item->GetTypeName() == KEY_CORE )
|
||||
matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::CORE );
|
||||
else
|
||||
matrix.m_diType.emplace( ODB_DIELECTRIC_TYPE::PREPREG );
|
||||
|
||||
matrix.m_type = ODB_TYPE::DIELECTRIC;
|
||||
matrix.m_context = ODB_CONTEXT::BOARD;
|
||||
matrix.m_polarity = ODB_POLARITY::POSITIVE;
|
||||
m_matrixLayers.push_back( matrix );
|
||||
m_plugin->GetLayerNameList().emplace_back(
|
||||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
added_layers.insert( stackup_item->GetBrdLayerId() );
|
||||
AddMatrixLayerField( matrix, stackup_item->GetBrdLayerId() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LSEQ layer_seq = m_board->GetEnabledLayers().Seq();
|
||||
|
||||
for( PCB_LAYER_ID layer : layer_seq )
|
||||
{
|
||||
if( added_layers.find( layer ) != added_layers.end() )
|
||||
continue;
|
||||
|
||||
MATRIX_LAYER matrix( m_row++, m_board->GetLayerName( layer ) );
|
||||
added_layers.insert( layer );
|
||||
AddMatrixLayerField( matrix, layer );
|
||||
}
|
||||
|
||||
AddDrillMatrixLayer();
|
||||
|
||||
AddCOMPMatrixLayer();
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::AddMatrixLayerField( MATRIX_LAYER& aMLayer, PCB_LAYER_ID aLayer )
|
||||
{
|
||||
aMLayer.m_polarity = ODB_POLARITY::POSITIVE;
|
||||
aMLayer.m_context = ODB_CONTEXT::BOARD;
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Paste:
|
||||
case B_Paste: aMLayer.m_type = ODB_TYPE::SOLDER_PASTE; break;
|
||||
case F_SilkS:
|
||||
case B_SilkS: aMLayer.m_type = ODB_TYPE::SILK_SCREEN; break;
|
||||
case F_Mask:
|
||||
case B_Mask: aMLayer.m_type = ODB_TYPE::SOLDER_MASK; break;
|
||||
case B_CrtYd:
|
||||
case F_CrtYd:
|
||||
case Edge_Cuts:
|
||||
case B_Fab:
|
||||
case F_Fab:
|
||||
case F_Adhes:
|
||||
case B_Adhes:
|
||||
case Dwgs_User:
|
||||
case Cmts_User:
|
||||
case Eco1_User:
|
||||
case Eco2_User:
|
||||
case Margin:
|
||||
case User_1:
|
||||
case User_2:
|
||||
case User_3:
|
||||
case User_4:
|
||||
case User_5:
|
||||
case User_6:
|
||||
case User_7:
|
||||
case User_8:
|
||||
case User_9:
|
||||
aMLayer.m_context = ODB_CONTEXT::MISC;
|
||||
aMLayer.m_type = ODB_TYPE::DOCUMENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( IsCopperLayer( aLayer ) )
|
||||
{
|
||||
aMLayer.m_type = ODB_TYPE::SIGNAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not handle other layers :
|
||||
aMLayer.m_type = ODB_TYPE::UNDEFINED;
|
||||
m_row--;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( aMLayer.m_type != ODB_TYPE::UNDEFINED )
|
||||
{
|
||||
m_matrixLayers.push_back( aMLayer );
|
||||
m_plugin->GetLayerNameList().emplace_back( std::make_pair( aLayer, aMLayer.m_layerName ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::AddDrillMatrixLayer()
|
||||
{
|
||||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers =
|
||||
m_plugin->GetDrillLayerItemsMap();
|
||||
|
||||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
|
||||
m_plugin->GetSlotHolesMap();
|
||||
|
||||
bool has_pth_layer = false;
|
||||
bool has_npth_layer = false;
|
||||
|
||||
for( BOARD_ITEM* item : m_board->Tracks() )
|
||||
{
|
||||
if( item->Type() == PCB_VIA_T )
|
||||
{
|
||||
PCB_VIA* via = static_cast<PCB_VIA*>( item );
|
||||
drill_layers[std::make_pair( via->TopLayer(), via->BottomLayer() )].push_back( via );
|
||||
}
|
||||
}
|
||||
|
||||
for( FOOTPRINT* fp : m_board->Footprints() )
|
||||
{
|
||||
// std::shared_ptr<FOOTPRINT> fp( static_cast<FOOTPRINT*>( it_fp->Clone() ) );
|
||||
|
||||
if( fp->IsFlipped() )
|
||||
{
|
||||
m_hasBotComp = true;
|
||||
}
|
||||
|
||||
for( PAD* pad : fp->Pads() )
|
||||
{
|
||||
if( !has_pth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
|
||||
has_pth_layer = true;
|
||||
if( !has_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
has_npth_layer = true;
|
||||
|
||||
if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() )
|
||||
slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
||||
else if( pad->HasHole() )
|
||||
drill_layers[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
||||
}
|
||||
|
||||
// m_plugin->GetLoadedFootprintList().push_back( std::move( fp ) );
|
||||
}
|
||||
|
||||
auto InitDrillMatrix =
|
||||
[&]( const wxString& aHasPlated, std::pair<PCB_LAYER_ID, PCB_LAYER_ID> aLayerPair )
|
||||
{
|
||||
wxString dLayerName = wxString::Format( "drill_%s_%s-%s", aHasPlated,
|
||||
m_board->GetLayerName( aLayerPair.first ),
|
||||
m_board->GetLayerName( aLayerPair.second ) );
|
||||
MATRIX_LAYER matrix( m_row++, dLayerName );
|
||||
|
||||
matrix.m_type = ODB_TYPE::DRILL;
|
||||
matrix.m_context = ODB_CONTEXT::BOARD;
|
||||
matrix.m_polarity = ODB_POLARITY::POSITIVE;
|
||||
matrix.m_span.emplace( std::make_pair(
|
||||
ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.first ) ),
|
||||
ODB::GenLegalEntityName( m_board->GetLayerName( aLayerPair.second ) ) ) );
|
||||
m_matrixLayers.push_back( matrix );
|
||||
m_plugin->GetLayerNameList().emplace_back(
|
||||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
|
||||
};
|
||||
|
||||
if( drill_layers.find( std::make_pair( F_Cu, B_Cu ) ) != drill_layers.end()
|
||||
|| !slot_holes.empty() )
|
||||
{
|
||||
// for pad has hole
|
||||
if( has_pth_layer )
|
||||
InitDrillMatrix( "plated", std::make_pair( F_Cu, B_Cu ) );
|
||||
if( has_npth_layer )
|
||||
InitDrillMatrix( "non-plated", std::make_pair( F_Cu, B_Cu ) );
|
||||
}
|
||||
|
||||
for( const auto& [layer_pair, vec] : drill_layers )
|
||||
{
|
||||
if( layer_pair != std::make_pair( F_Cu, B_Cu ) ) // pad has initialized above
|
||||
InitDrillMatrix( "plated", layer_pair ); // for via
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::AddCOMPMatrixLayer()
|
||||
{
|
||||
MATRIX_LAYER matrix( m_row++, "COMP_+_TOP" );
|
||||
matrix.m_type = ODB_TYPE::COMPONENT;
|
||||
matrix.m_context = ODB_CONTEXT::BOARD;
|
||||
|
||||
m_matrixLayers.push_back( matrix );
|
||||
m_plugin->GetLayerNameList().emplace_back(
|
||||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
|
||||
|
||||
if( m_hasBotComp )
|
||||
{
|
||||
matrix.m_layerName = ODB::GenLegalEntityName( "COMP_+_BOT" );
|
||||
matrix.m_rowNumber = m_row++;
|
||||
m_matrixLayers.push_back( matrix );
|
||||
m_plugin->GetLayerNameList().emplace_back(
|
||||
std::make_pair( PCB_LAYER_ID::UNDEFINED_LAYER, matrix.m_layerName ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_MATRIX_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "matrix" );
|
||||
|
||||
ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
|
||||
|
||||
for( const auto& [step_name, column] : m_matrixSteps )
|
||||
{
|
||||
const auto array_proxy = twriter.MakeArrayProxy( "STEP" );
|
||||
twriter.WriteEquationLine( "COL", column );
|
||||
twriter.WriteEquationLine( "NAME", step_name );
|
||||
}
|
||||
|
||||
for( const auto& layer : m_matrixLayers )
|
||||
{
|
||||
const auto array_proxy = twriter.MakeArrayProxy( "LAYER" );
|
||||
twriter.WriteEquationLine( "ROW", layer.m_rowNumber );
|
||||
twriter.write_line_enum( "CONTEXT", layer.m_context );
|
||||
twriter.write_line_enum( "TYPE", layer.m_type );
|
||||
|
||||
if( layer.m_addType.has_value() )
|
||||
{
|
||||
twriter.write_line_enum( "ADD_TYPE", layer.m_addType.value() );
|
||||
}
|
||||
|
||||
twriter.WriteEquationLine( "NAME", layer.m_layerName.Upper() );
|
||||
twriter.WriteEquationLine( "OLD_NAME", wxEmptyString );
|
||||
twriter.write_line_enum( "POLARITY", layer.m_polarity );
|
||||
|
||||
if( layer.m_diType.has_value() )
|
||||
{
|
||||
twriter.write_line_enum( "DIELECTRIC_TYPE", layer.m_diType.value() );
|
||||
}
|
||||
|
||||
twriter.WriteEquationLine( "DIELECTRIC_NAME", wxEmptyString );
|
||||
twriter.WriteEquationLine( "CU_TOP", wxEmptyString );
|
||||
twriter.WriteEquationLine( "CU_BOTTOM", wxEmptyString );
|
||||
twriter.WriteEquationLine( "REF", wxEmptyString );
|
||||
|
||||
if( layer.m_span.has_value() )
|
||||
{
|
||||
twriter.WriteEquationLine( "START_NAME", layer.m_span->first.Upper() );
|
||||
twriter.WriteEquationLine( "END_NAME", layer.m_span->second.Upper() );
|
||||
}
|
||||
else
|
||||
{
|
||||
twriter.WriteEquationLine( "START_NAME", wxEmptyString );
|
||||
twriter.WriteEquationLine( "END_NAME", wxEmptyString );
|
||||
}
|
||||
twriter.WriteEquationLine( "COLOR", wxEmptyString );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ODB_LAYER_ENTITY::ODB_LAYER_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin,
|
||||
std::map<int, std::vector<BOARD_ITEM*>>& aMap,
|
||||
const PCB_LAYER_ID& aLayerID, const wxString& aLayerName ) :
|
||||
ODB_ENTITY_BASE( aBoard, aPlugin ), m_layerItems( aMap ), m_layerID( aLayerID ),
|
||||
m_matrixLayerName( aLayerName )
|
||||
{
|
||||
m_featuresMgr = std::make_unique<FEATURES_MANAGER>( aBoard, aPlugin, aLayerName );
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::InitEntityData()
|
||||
{
|
||||
if( m_matrixLayerName.Contains( "drill" ) )
|
||||
{
|
||||
InitDrillData();
|
||||
InitFeatureData();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_layerID != PCB_LAYER_ID::UNDEFINED_LAYER )
|
||||
{
|
||||
InitFeatureData();
|
||||
}
|
||||
}
|
||||
|
||||
void ODB_LAYER_ENTITY::InitFeatureData()
|
||||
{
|
||||
if( m_layerItems.empty() )
|
||||
return;
|
||||
|
||||
const NETINFO_LIST& nets = m_board->GetNetInfo();
|
||||
|
||||
for( const NETINFO_ITEM* net : nets )
|
||||
{
|
||||
std::vector<BOARD_ITEM*>& vec = m_layerItems[net->GetNetCode()];
|
||||
|
||||
std::stable_sort( vec.begin(), vec.end(),
|
||||
[]( BOARD_ITEM* a, BOARD_ITEM* b )
|
||||
{
|
||||
if( a->GetParentFootprint() == b->GetParentFootprint() )
|
||||
return a->Type() < b->Type();
|
||||
|
||||
return a->GetParentFootprint() < b->GetParentFootprint();
|
||||
} );
|
||||
|
||||
if( vec.empty() )
|
||||
continue;
|
||||
|
||||
m_featuresMgr->InitFeatureList( m_layerID, vec );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ODB_COMPONENT& ODB_LAYER_ENTITY::InitComponentData( const FOOTPRINT* aFp,
|
||||
const EDA_DATA::PACKAGE& aPkg )
|
||||
{
|
||||
if( m_matrixLayerName == "COMP_+_BOT" )
|
||||
{
|
||||
if( !m_compBot.has_value() )
|
||||
{
|
||||
m_compBot.emplace();
|
||||
}
|
||||
return m_compBot.value().AddComponent( aFp, aPkg );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_compTop.has_value() )
|
||||
{
|
||||
m_compTop.emplace();
|
||||
}
|
||||
|
||||
return m_compTop.value().AddComponent( aFp, aPkg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::InitDrillData()
|
||||
{
|
||||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& drill_layers =
|
||||
m_plugin->GetDrillLayerItemsMap();
|
||||
|
||||
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>& slot_holes =
|
||||
m_plugin->GetSlotHolesMap();
|
||||
|
||||
if( !m_layerItems.empty() )
|
||||
{
|
||||
m_layerItems.clear();
|
||||
}
|
||||
|
||||
m_tools.emplace( PCB_IO_ODBPP::m_unitsStr );
|
||||
|
||||
bool is_npth_layer = false;
|
||||
wxString plated_name = "plated";
|
||||
|
||||
if( m_matrixLayerName.Contains( "non-plated" ) )
|
||||
{
|
||||
is_npth_layer = true;
|
||||
plated_name = "non-plated";
|
||||
}
|
||||
|
||||
|
||||
for( const auto& [layer_pair, vec] : slot_holes )
|
||||
{
|
||||
wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name,
|
||||
m_board->GetLayerName( layer_pair.first ),
|
||||
m_board->GetLayerName( layer_pair.second ) );
|
||||
|
||||
if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
|
||||
{
|
||||
for( BOARD_ITEM* item : vec )
|
||||
{
|
||||
if( item->Type() == PCB_PAD_T )
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( item );
|
||||
|
||||
if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
|
||||
|| ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_tools.value().AddDrillTools(
|
||||
pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED",
|
||||
ODB::SymDouble2String(
|
||||
std::min( pad->GetDrillSizeX(), pad->GetDrillSizeY() ) ) );
|
||||
|
||||
// for drill features
|
||||
m_layerItems[pad->GetNetCode()].push_back( item );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( const auto& [layer_pair, vec] : drill_layers )
|
||||
{
|
||||
wxString dLayerName = wxString::Format( "drill_%s_%s-%s", plated_name,
|
||||
m_board->GetLayerName( layer_pair.first ),
|
||||
m_board->GetLayerName( layer_pair.second ) );
|
||||
|
||||
if( ODB::GenLegalEntityName( dLayerName ) == m_matrixLayerName )
|
||||
{
|
||||
for( BOARD_ITEM* item : vec )
|
||||
{
|
||||
if( item->Type() == PCB_VIA_T && !is_npth_layer )
|
||||
{
|
||||
PCB_VIA* via = static_cast<PCB_VIA*>( item );
|
||||
|
||||
m_tools.value().AddDrillTools( "VIA",
|
||||
ODB::SymDouble2String( via->GetDrillValue() ) );
|
||||
|
||||
// for drill features
|
||||
m_layerItems[via->GetNetCode()].push_back( item );
|
||||
}
|
||||
else if( item->Type() == PCB_PAD_T )
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( item );
|
||||
|
||||
if( ( is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::PTH )
|
||||
|| ( !is_npth_layer && pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_tools.value().AddDrillTools(
|
||||
pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NON_PLATED",
|
||||
ODB::SymDouble2String( pad->GetDrillSizeX() ) );
|
||||
|
||||
// for drill features
|
||||
m_layerItems[pad->GetNetCode()].push_back( item );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::InitEntityData()
|
||||
{
|
||||
MakeLayerEntity();
|
||||
|
||||
InitEdaData();
|
||||
|
||||
// Init Layer Entity Data
|
||||
for( const auto& [layerName, layer_entity_ptr] : m_layerEntityMap )
|
||||
{
|
||||
layer_entity_ptr->InitEntityData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
GenAttrList( writer );
|
||||
|
||||
GenFeatures( writer );
|
||||
|
||||
if( m_compTop.has_value() || m_compBot.has_value() )
|
||||
{
|
||||
GenComponents( writer );
|
||||
}
|
||||
|
||||
if( m_tools.has_value() )
|
||||
{
|
||||
GenTools( writer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::GenComponents( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "components" );
|
||||
|
||||
if( m_compTop.has_value() )
|
||||
{
|
||||
m_compTop->Write( fileproxy.GetStream() );
|
||||
}
|
||||
else if( m_compBot.has_value() )
|
||||
{
|
||||
m_compBot->Write( fileproxy.GetStream() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::GenFeatures( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "features" );
|
||||
|
||||
m_featuresMgr->GenerateFeatureFile( fileproxy.GetStream() );
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::GenAttrList( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "attrlist" );
|
||||
}
|
||||
|
||||
|
||||
void ODB_LAYER_ENTITY::GenTools( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "tools" );
|
||||
|
||||
m_tools.value().GenerateFile( fileproxy.GetStream() );
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::InitEdaData()
|
||||
{
|
||||
//InitPackage
|
||||
for( const FOOTPRINT* fp : m_board->Footprints() )
|
||||
{
|
||||
m_edaData.AddPackage( fp );
|
||||
}
|
||||
|
||||
// for NET
|
||||
const NETINFO_LIST& nets = m_board->GetNetInfo();
|
||||
|
||||
for( const NETINFO_ITEM* net : nets )
|
||||
{
|
||||
m_edaData.AddNET( net );
|
||||
}
|
||||
|
||||
// for CMP
|
||||
size_t j = 0;
|
||||
|
||||
for( const FOOTPRINT* fp : m_board->Footprints() )
|
||||
{
|
||||
wxString compName = ODB::GenLegalEntityName( "COMP_+_TOP" );
|
||||
if( fp->IsFlipped() )
|
||||
compName = ODB::GenLegalEntityName( "COMP_+_BOT" );
|
||||
|
||||
auto iter = m_layerEntityMap.find( compName );
|
||||
|
||||
if( iter == m_layerEntityMap.end() )
|
||||
{
|
||||
wxLogError( _( "Failed to add component data" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// ODBPP only need unique PACKAGE in PKG record in eda/data file.
|
||||
// the PKG index can repeat to be ref in CMP record in component file.
|
||||
std::shared_ptr<FOOTPRINT> fp_pkg = m_edaData.GetEdaFootprints().at( j );
|
||||
++j;
|
||||
|
||||
const EDA_DATA::PACKAGE& eda_pkg =
|
||||
m_edaData.GetPackage( hash_fp_item( fp_pkg.get(), HASH_POS | REL_COORD ) );
|
||||
|
||||
ODB_COMPONENT& comp = iter->second->InitComponentData( fp, eda_pkg );
|
||||
|
||||
for( int i = 0; i < fp->Pads().size(); ++i )
|
||||
{
|
||||
PAD* pad = fp->Pads()[i];
|
||||
auto& eda_net = m_edaData.GetNet( pad->GetNetCode() );
|
||||
|
||||
auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_TOEPRINT>(
|
||||
&m_edaData,
|
||||
fp->IsFlipped() ? EDA_DATA::SUB_NET_TOEPRINT::SIDE::BOTTOM
|
||||
: EDA_DATA::SUB_NET_TOEPRINT::SIDE::TOP,
|
||||
comp.m_index, comp.m_toeprints.size() );
|
||||
|
||||
m_plugin->GetPadSubnetMap().emplace( pad, &subnet );
|
||||
|
||||
const std::shared_ptr<EDA_DATA::PIN> pin = eda_pkg.GetEdaPkgPin( i );
|
||||
const EDA_DATA::PIN& pin_ref = *pin;
|
||||
auto& toep = comp.m_toeprints.emplace_back( pin_ref );
|
||||
|
||||
toep.m_net_num = eda_net.m_index;
|
||||
toep.m_subnet_num = subnet.m_index;
|
||||
|
||||
toep.m_center = ODB::AddXY( pad->GetPosition() );
|
||||
|
||||
toep.m_rot = ODB::Double2String(
|
||||
( ANGLE_360 - pad->GetOrientation() ).Normalize().AsDegrees() );
|
||||
|
||||
if( pad->IsFlipped() )
|
||||
toep.m_mirror = wxT( "M" );
|
||||
else
|
||||
toep.m_mirror = wxT( "N" );
|
||||
}
|
||||
}
|
||||
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
auto& eda_net = m_edaData.GetNet( track->GetNetCode() );
|
||||
EDA_DATA::SUB_NET* subnet = nullptr;
|
||||
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_VIA>( &m_edaData ) );
|
||||
else
|
||||
subnet = &( eda_net.AddSubnet<EDA_DATA::SUB_NET_TRACE>( &m_edaData ) );
|
||||
|
||||
m_plugin->GetViaTraceSubnetMap().emplace( track, subnet );
|
||||
}
|
||||
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||
{
|
||||
auto& eda_net = m_edaData.GetNet( zone->GetNetCode() );
|
||||
auto& subnet = eda_net.AddSubnet<EDA_DATA::SUB_NET_PLANE>(
|
||||
&m_edaData, EDA_DATA::SUB_NET_PLANE::FILL_TYPE::SOLID,
|
||||
EDA_DATA::SUB_NET_PLANE::CUTOUT_TYPE::EXACT, 0 );
|
||||
m_plugin->GetPlaneSubnetMap().emplace( std::piecewise_construct,
|
||||
std::forward_as_tuple( layer, zone ),
|
||||
std::forward_as_tuple( &subnet ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::GenerateFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
wxString step_root = writer.GetCurrentPath();
|
||||
|
||||
writer.CreateEntityDirectory( step_root, "layers" );
|
||||
GenerateLayerFiles( writer );
|
||||
|
||||
writer.CreateEntityDirectory( step_root, "eda" );
|
||||
GenerateEdaFiles( writer );
|
||||
|
||||
writer.CreateEntityDirectory( step_root, "netlists/cadnet" );
|
||||
GenerateNetlistsFiles( writer );
|
||||
|
||||
writer.SetCurrentPath( step_root );
|
||||
GenerateProfileFile( writer );
|
||||
|
||||
GenerateStepHeaderFile( writer );
|
||||
|
||||
//TODO: system attributes
|
||||
// GenerateAttrListFile( writer );
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::GenerateProfileFile( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "profile" );
|
||||
|
||||
m_profile = std::make_unique<FEATURES_MANAGER>( m_board, m_plugin, wxEmptyString );
|
||||
|
||||
SHAPE_POLY_SET board_outline;
|
||||
|
||||
if( !m_board->GetBoardPolygonOutlines( board_outline ) )
|
||||
{
|
||||
wxLogError( "Failed to get board outline" );
|
||||
}
|
||||
|
||||
if( !m_profile->AddContour( board_outline, 0 ) )
|
||||
{
|
||||
wxLogError( "Failed to add polygon to profile" );
|
||||
}
|
||||
|
||||
m_profile->GenerateProfileFeatures( fileproxy.GetStream() );
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::GenerateStepHeaderFile( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "stephdr" );
|
||||
|
||||
m_stephdr = {
|
||||
{ ODB_UNITS, PCB_IO_ODBPP::m_unitsStr },
|
||||
{ "X_DATUM", "0" },
|
||||
{ "Y_DATUM", "0" },
|
||||
{ "X_ORIGIN", "0" },
|
||||
{ "Y_ORIGIN", "0" },
|
||||
{ "TOP_ACTIVE", "0" },
|
||||
{ "BOTTOM_ACTIVE", "0" },
|
||||
{ "RIGHT_ACTIVE", "0" },
|
||||
{ "LEFT_ACTIVE", "0" },
|
||||
{ "AFFECTING_BOM", "" },
|
||||
{ "AFFECTING_BOM_CHANGED", "0" },
|
||||
};
|
||||
|
||||
ODB_TEXT_WRITER twriter( fileproxy.GetStream() );
|
||||
|
||||
for( const auto& [key, value] : m_stephdr )
|
||||
{
|
||||
twriter.WriteEquationLine( key, value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::GenerateLayerFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
wxString layers_root = writer.GetCurrentPath();
|
||||
|
||||
for( auto& [layerName, layerEntity] : m_layerEntityMap )
|
||||
{
|
||||
writer.CreateEntityDirectory( layers_root, layerName );
|
||||
|
||||
layerEntity->GenerateFiles( writer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::GenerateEdaFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "data" );
|
||||
|
||||
m_edaData.Write( fileproxy.GetStream() );
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::GenerateNetlistsFiles( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
auto fileproxy = writer.CreateFileProxy( "netlist" );
|
||||
|
||||
m_netlist.Write( fileproxy.GetStream() );
|
||||
}
|
||||
|
||||
|
||||
bool ODB_STEP_ENTITY::CreateDirectiryTree( ODB_TREE_WRITER& writer )
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.CreateEntityDirectory( writer.GetRootPath(), "steps" );
|
||||
writer.CreateEntityDirectory( writer.GetCurrentPath(), GetEntityName() );
|
||||
return true;
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODB_STEP_ENTITY::MakeLayerEntity()
|
||||
{
|
||||
LSEQ layers = m_board->GetEnabledLayers().Seq();
|
||||
const NETINFO_LIST& nets = m_board->GetNetInfo();
|
||||
|
||||
// To avoid the overhead of repeatedly cycling through the layers and nets,
|
||||
// we pre-sort the board items into a map of layer -> net -> items
|
||||
std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>>& elements =
|
||||
m_plugin->GetLayerElementsMap();
|
||||
|
||||
std::for_each( m_board->Tracks().begin(), m_board->Tracks().end(),
|
||||
[&layers, &elements]( PCB_TRACK* aTrack )
|
||||
{
|
||||
if( aTrack->Type() == PCB_VIA_T )
|
||||
{
|
||||
PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
|
||||
|
||||
for( PCB_LAYER_ID layer : layers )
|
||||
{
|
||||
if( via->FlashLayer( layer ) )
|
||||
elements[layer][via->GetNetCode()].push_back( via );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
|
||||
}
|
||||
} );
|
||||
|
||||
std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
|
||||
[&elements]( ZONE* zone )
|
||||
{
|
||||
LSEQ zone_layers = zone->GetLayerSet().Seq();
|
||||
|
||||
for( PCB_LAYER_ID layer : zone_layers )
|
||||
{
|
||||
elements[layer][zone->GetNetCode()].push_back( zone );
|
||||
}
|
||||
} );
|
||||
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
{
|
||||
if( BOARD_CONNECTED_ITEM* conn_it = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
|
||||
elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
|
||||
else
|
||||
elements[item->GetLayer()][0].push_back( item );
|
||||
}
|
||||
|
||||
for( FOOTPRINT* fp : m_board->Footprints() )
|
||||
{
|
||||
for( PCB_FIELD* field : fp->GetFields() )
|
||||
elements[field->GetLayer()][0].push_back( field );
|
||||
|
||||
for( BOARD_ITEM* item : fp->GraphicalItems() )
|
||||
elements[item->GetLayer()][0].push_back( item );
|
||||
|
||||
for( PAD* pad : fp->Pads() )
|
||||
{
|
||||
LSEQ pad_layers = pad->GetLayerSet().Seq();
|
||||
VECTOR2I margin;
|
||||
|
||||
for( PCB_LAYER_ID layer : pad_layers )
|
||||
{
|
||||
bool onCopperLayer = ( LSET::AllCuMask() & LSET( { layer } ) ).any();
|
||||
bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & LSET( { layer } ) ).any();
|
||||
bool onSolderPasteLayer =
|
||||
( LSET( { F_Paste, B_Paste } ) & LSET( { layer } ) ).any();
|
||||
|
||||
if( onSolderMaskLayer )
|
||||
margin.x = margin.y = pad->GetSolderMaskExpansion();
|
||||
|
||||
if( onSolderPasteLayer )
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
|
||||
VECTOR2I padPlotsSize = pad->GetSize() + margin * 2;
|
||||
|
||||
if( onCopperLayer && !pad->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
if( onCopperLayer && !pad->FlashLayer( layer ) )
|
||||
continue;
|
||||
|
||||
if( pad->GetShape() != PAD_SHAPE::CUSTOM
|
||||
&& ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
|
||||
continue;
|
||||
|
||||
elements[layer][pad->GetNetCode()].push_back( pad );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( const auto& [layerID, layerName] : m_plugin->GetLayerNameList() )
|
||||
{
|
||||
std::shared_ptr<ODB_LAYER_ENTITY> layer_entity_ptr = std::make_shared<ODB_LAYER_ENTITY>(
|
||||
m_board, m_plugin, elements[layerID], layerID, layerName );
|
||||
|
||||
m_layerEntityMap.emplace( layerName, layer_entity_ptr );
|
||||
}
|
||||
}
|
273
pcbnew/pcb_io/odbpp/odb_entity.h
Normal file
273
pcbnew/pcb_io/odbpp/odb_entity.h
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: SYSUEric <jzzhuang666@gmail.com>.
|
||||
*
|
||||
* 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 _ODB_ENTITY_H_
|
||||
#define _ODB_ENTITY_H_
|
||||
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <wx/string.h>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include "odb_feature.h"
|
||||
#include "odb_eda_data.h"
|
||||
#include "odb_netlist.h"
|
||||
#include "odb_component.h"
|
||||
|
||||
|
||||
class BOARD;
|
||||
class ODB_TREE_WRITER;
|
||||
class BOARD_ITEM;
|
||||
class PCB_IO_ODBPP;
|
||||
|
||||
class ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_ENTITY_BASE( BOARD* aBoard, PCB_IO_ODBPP* aPlugin ) : m_board( aBoard ), m_plugin( aPlugin )
|
||||
{
|
||||
}
|
||||
|
||||
ODB_ENTITY_BASE() : m_board( nullptr ), m_plugin( nullptr ) {}
|
||||
|
||||
virtual ~ODB_ENTITY_BASE() = default;
|
||||
virtual void GenerateFiles( ODB_TREE_WRITER& writer ) {}
|
||||
virtual bool CreateDirectiryTree( ODB_TREE_WRITER& writer );
|
||||
virtual std::string GetEntityName() = 0;
|
||||
virtual void InitEntityData() {}
|
||||
|
||||
|
||||
protected:
|
||||
BOARD* m_board;
|
||||
std::vector<std::string> m_fileName;
|
||||
PCB_IO_ODBPP* m_plugin;
|
||||
};
|
||||
|
||||
enum class ODB_SUBTYPE;
|
||||
enum class ODB_POLARITY;
|
||||
enum class ODB_CONTEXT;
|
||||
enum class ODB_TYPE;
|
||||
|
||||
class ODB_MATRIX_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_MATRIX_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin ) : ODB_ENTITY_BASE( aBoard, aPlugin )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ODB_MATRIX_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "matrix"; }
|
||||
|
||||
struct MATRIX_LAYER
|
||||
{
|
||||
std::optional<std::pair<wxString, wxString>> m_span; // !< start, end
|
||||
std::optional<ODB_SUBTYPE> m_addType;
|
||||
std::optional<ODB_DIELECTRIC_TYPE> m_diType;
|
||||
|
||||
uint32_t m_rowNumber;
|
||||
wxString m_layerName;
|
||||
ODB_CONTEXT m_context;
|
||||
ODB_TYPE m_type;
|
||||
ODB_POLARITY m_polarity = ODB_POLARITY::POSITIVE;
|
||||
|
||||
MATRIX_LAYER( uint32_t aRow, const wxString& aLayerName ) :
|
||||
m_rowNumber( aRow ), m_layerName( ODB::GenLegalEntityName( aLayerName ) )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
virtual void InitEntityData();
|
||||
void InitMatrixLayerData();
|
||||
|
||||
void AddStep( const wxString& aStepName );
|
||||
void AddMatrixLayerField( MATRIX_LAYER& aMLayer, PCB_LAYER_ID aLayer );
|
||||
void AddDrillMatrixLayer();
|
||||
void AddCOMPMatrixLayer();
|
||||
|
||||
private:
|
||||
std::map<wxString, unsigned int> m_matrixSteps;
|
||||
std::vector<MATRIX_LAYER> m_matrixLayers;
|
||||
unsigned int m_row = 1;
|
||||
unsigned int m_col = 1;
|
||||
bool m_hasBotComp = false;
|
||||
};
|
||||
|
||||
class ODB_MISC_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_MISC_ENTITY();
|
||||
virtual ~ODB_MISC_ENTITY() = default;
|
||||
inline virtual std::string GetEntityName() { return "misc"; }
|
||||
|
||||
//TODO
|
||||
// bool AddAttrList();
|
||||
// bool AddSysAttrFiles();
|
||||
virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
|
||||
private:
|
||||
std::map<wxString, wxString> m_info;
|
||||
// ODB_ATTRLIST m_attrlist;
|
||||
};
|
||||
|
||||
class FEATURES_MANAGER;
|
||||
class ODB_LAYER_ENTITY;
|
||||
class ODB_STEP_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_STEP_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin ) :
|
||||
ODB_ENTITY_BASE( aBoard, aPlugin ), m_profile( nullptr ), m_netlist( aBoard )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ODB_STEP_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "pcb"; }
|
||||
|
||||
void InitEdaData();
|
||||
void InitPackage();
|
||||
void InitNetListData();
|
||||
void MakeLayerEntity();
|
||||
bool AddNetList();
|
||||
bool AddProfile();
|
||||
bool AddStepHeader();
|
||||
|
||||
virtual bool CreateDirectiryTree( ODB_TREE_WRITER& writer );
|
||||
|
||||
virtual void InitEntityData();
|
||||
void GenerateLayerFiles( ODB_TREE_WRITER& writer );
|
||||
void GenerateEdaFiles( ODB_TREE_WRITER& writer );
|
||||
void GenerateNetlistsFiles( ODB_TREE_WRITER& writer );
|
||||
void GenerateProfileFile( ODB_TREE_WRITER& writer );
|
||||
void GenerateStepHeaderFile( ODB_TREE_WRITER& writer );
|
||||
|
||||
virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
|
||||
private:
|
||||
// ODB_ATTRLIST m_attrList;
|
||||
std::map<wxString, std::shared_ptr<ODB_LAYER_ENTITY>> m_layerEntityMap;
|
||||
std::unique_ptr<FEATURES_MANAGER> m_profile;
|
||||
|
||||
EDA_DATA m_edaData;
|
||||
std::unordered_map<wxString, wxString> m_stephdr;
|
||||
ODB_NET_LIST m_netlist;
|
||||
};
|
||||
|
||||
|
||||
class ODB_LAYER_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_LAYER_ENTITY( BOARD* aBoard, PCB_IO_ODBPP* aPlugin,
|
||||
std::map<int, std::vector<BOARD_ITEM*>>& aMap, const PCB_LAYER_ID& aLayerID,
|
||||
const wxString& aLayerName );
|
||||
|
||||
virtual ~ODB_LAYER_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "layers"; }
|
||||
virtual void InitEntityData();
|
||||
void InitFeatureData();
|
||||
ODB_COMPONENT& InitComponentData( const FOOTPRINT* aFp, const EDA_DATA::PACKAGE& aPkg );
|
||||
void InitDrillData();
|
||||
|
||||
void AddLayerFeatures();
|
||||
|
||||
|
||||
void GenAttrList( ODB_TREE_WRITER& writer );
|
||||
void GenComponents( ODB_TREE_WRITER& writer );
|
||||
void GenTools( ODB_TREE_WRITER& writer );
|
||||
|
||||
void GenFeatures( ODB_TREE_WRITER& writer );
|
||||
|
||||
virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
|
||||
private:
|
||||
std::map<int, std::vector<BOARD_ITEM*>> m_layerItems;
|
||||
PCB_LAYER_ID m_layerID;
|
||||
wxString m_matrixLayerName;
|
||||
// ODB_ATTRLIST m_attrList;
|
||||
std::optional<ODB_DRILL_TOOLS> m_tools;
|
||||
std::optional<COMPONENTS_MANAGER> m_compTop;
|
||||
std::optional<COMPONENTS_MANAGER> m_compBot;
|
||||
std::unique_ptr<FEATURES_MANAGER> m_featuresMgr;
|
||||
};
|
||||
|
||||
class ODB_SYMBOLS_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_SYMBOLS_ENTITY() = default;
|
||||
|
||||
virtual ~ODB_SYMBOLS_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "symbols"; }
|
||||
|
||||
//TODO
|
||||
// virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
};
|
||||
|
||||
class ODB_FONTS_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_FONTS_ENTITY() = default;
|
||||
virtual ~ODB_FONTS_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "fonts"; }
|
||||
|
||||
virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
};
|
||||
|
||||
class ODB_WHEELS_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_WHEELS_ENTITY() = default;
|
||||
virtual ~ODB_WHEELS_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "wheels"; }
|
||||
|
||||
// TODO
|
||||
// virtual void GenerateFiles( ODB_TREE_WRITER& writer );
|
||||
};
|
||||
|
||||
class ODB_INPUT_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_INPUT_ENTITY() = default;
|
||||
virtual ~ODB_INPUT_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "input"; }
|
||||
|
||||
// TODO
|
||||
// virtual void GenerateFiles( ODB_TREE_WRITER &writer );
|
||||
};
|
||||
|
||||
class ODB_USER_ENTITY : public ODB_ENTITY_BASE
|
||||
{
|
||||
public:
|
||||
ODB_USER_ENTITY() = default;
|
||||
virtual ~ODB_USER_ENTITY() = default;
|
||||
|
||||
inline virtual std::string GetEntityName() { return "user"; }
|
||||
|
||||
// TODO
|
||||
// virtual void GenerateFiles( ODB_TREE_WRITER &writer );
|
||||
};
|
||||
|
||||
#endif // _ODB_ENTITY_H_
|
1002
pcbnew/pcb_io/odbpp/odb_feature.cpp
Normal file
1002
pcbnew/pcb_io/odbpp/odb_feature.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user