Coding policy fixes.

This is primarily to change all instances of wxLogDebug with wxLogTrace
so developers do not have to sift through debugging output that is always
dumped.  The only exception is for code blocks built in debug builds and
called on demand for dumping object states.
This commit is contained in:
Wayne Stambaugh 2024-05-23 07:59:45 -04:00
parent edae328ca6
commit 795a9eea60
18 changed files with 369 additions and 172 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -33,6 +33,14 @@
#include <wx/crt.h> #include <wx/crt.h>
/**
* Flag to enable confirmation dialog debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceConfirm[] = wxT( "KICAD_CONFIRM" );
bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage ) bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage )
{ {
#ifdef __APPLE__ #ifdef __APPLE__
@ -92,7 +100,8 @@ int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage )
// wxMessageDialog on windows invokes TaskDialogIndirect which is a native function for a dialog // wxMessageDialog on windows invokes TaskDialogIndirect which is a native function for a dialog
// As a result it skips wxWidgets for modal management...and we don't parent frames properly // As a result it skips wxWidgets for modal management...and we don't parent frames properly
// among other things for Windows to do the right thing by default // among other things for Windows to do the right thing by default
// Disable all the windows manually to avoid being able to hit this dialog from the tool frame and kicad frame at the same time // Disable all the windows manually to avoid being able to hit this dialog from the tool frame
// and kicad frame at the same time.
wxWindowDisabler disable( true ); wxWindowDisabler disable( true );
#endif #endif
@ -214,7 +223,7 @@ void DisplayInfoMessage( wxWindow* aParent, const wxString& aMessage, const wxSt
{ {
if( !wxTheApp || !wxTheApp->GetTopWindow() ) if( !wxTheApp || !wxTheApp->GetTopWindow() )
{ {
wxLogDebug( "%s %s", aMessage, aExtraInfo ); wxLogTrace( traceConfirm, wxS( "%s %s" ), aMessage, aExtraInfo );
return; return;
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2013-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2013-2023, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
@ -55,6 +55,15 @@
#include <pgm_base.h> #include <pgm_base.h>
#include <confirm.h> #include <confirm.h>
/**
* Flag to enable drawing panel debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceDrawPanel[] = wxT( "KICAD_DRAW_PANEL" );
EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
KIGFX::GAL_DISPLAY_OPTIONS& aOptions, GAL_TYPE aGalType ) : KIGFX::GAL_DISPLAY_OPTIONS& aOptions, GAL_TYPE aGalType ) :
@ -236,6 +245,7 @@ bool EDA_DRAW_PANEL_GAL::DoRePaint()
bool isDirty = false; bool isDirty = false;
cntTotal.Start(); cntTotal.Start();
try try
{ {
cntUpd.Start(); cntUpd.Start();
@ -248,9 +258,7 @@ bool EDA_DRAW_PANEL_GAL::DoRePaint()
{ {
// Don't do anything here but don't fail // Don't do anything here but don't fail
// This can happen when we don't catch `at()` calls // This can happen when we don't catch `at()` calls
wxString msg; wxLogTrace( traceDrawPanel, wxS( "Out of Range error: %s" ), err.what() );
msg.Printf( wxT( "Out of Range error: %s" ), err.what() );
wxLogDebug( msg );
} }
cntUpd.Stop(); cntUpd.Stop();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016-2017 CERN * Copyright (C) 2016-2017 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2021, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -170,13 +170,18 @@ static void GLAPIENTRY debugMsgCallback( GLenum aSource, GLenum aType, GLuint aI
{ {
switch( aSeverity ) switch( aSeverity )
{ {
case GL_DEBUG_SEVERITY_HIGH: wxLogDebug( "OpenGL ERROR: " ); break; case GL_DEBUG_SEVERITY_HIGH:
case GL_DEBUG_SEVERITY_MEDIUM: wxLogDebug( "OpenGL WARNING: " ); break; wxLogTrace( traceGalOpenGlError, wxS( "OpenGL ERROR: %s" ), aMessage );
case GL_DEBUG_SEVERITY_LOW: wxLogDebug( "OpenGL INFO: " ); break; break;
case GL_DEBUG_SEVERITY_NOTIFICATION: return; case GL_DEBUG_SEVERITY_MEDIUM:
wxLogTrace( traceGalOpenGlError, wxS( "OpenGL WARNING: %s" ), aMessage );
break;
case GL_DEBUG_SEVERITY_LOW:
wxLogTrace( traceGalOpenGlError, wxS( "OpenGL INFO: %s" ), aMessage );
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
return;
} }
wxLogDebug( "%s\n", aMessage );
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013-2016 CERN * Copyright (C) 2013-2016 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2021, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -38,6 +38,15 @@
#include <confirm.h> #include <confirm.h>
#include <wx/log.h> #include <wx/log.h>
/**
* Flag to enable #VERTEX_MANAGER debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceVertexManager[] = wxT( "KICAD_VERTEX_MANAGER" );
using namespace KIGFX; using namespace KIGFX;
VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) : VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
@ -73,7 +82,7 @@ bool VERTEX_MANAGER::Reserve( unsigned int aSize )
return true; return true;
if( m_reservedSpace != 0 || m_reserved ) if( m_reservedSpace != 0 || m_reserved )
wxLogDebug( wxT( "Did not use all previous vertices allocated" ) ); wxLogTrace( traceVertexManager, wxS( "Did not use all previous vertices allocated" ) );
// flag to avoid hanging by calling DisplayError too many times: // flag to avoid hanging by calling DisplayError too many times:
static bool show_err = true; static bool show_err = true;
@ -173,7 +182,7 @@ void VERTEX_MANAGER::SetItem( VERTEX_ITEM& aItem ) const
void VERTEX_MANAGER::FinishItem() const void VERTEX_MANAGER::FinishItem() const
{ {
if( m_reservedSpace != 0 || m_reserved ) if( m_reservedSpace != 0 || m_reserved )
wxLogDebug( wxT( "Did not use all previous vertices allocated" ) ); wxLogTrace( traceVertexManager, wxS( "Did not use all previous vertices allocated" ) );
m_container->FinishItem(); m_container->FinishItem();
} }
@ -295,6 +304,7 @@ void VERTEX_MANAGER::putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat
} }
} }
void VERTEX_MANAGER::EnableDepthTest( bool aEnabled ) void VERTEX_MANAGER::EnableDepthTest( bool aEnabled )
{ {
m_gpu->EnableDepthTest( aEnabled ); m_gpu->EnableDepthTest( aEnabled );

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. * Copyright (C) 2023, 2024 KiCad Developers, see AUTHORS.TXT for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -26,48 +26,57 @@
#include <wx/log.h> #include <wx/log.h>
#include <wx/string.h> #include <wx/string.h>
#include <trace_helpers.h>
GIT_REVERT_HANDLER::GIT_REVERT_HANDLER( git_repository* aRepository ) GIT_REVERT_HANDLER::GIT_REVERT_HANDLER( git_repository* aRepository )
{ {
m_repository = aRepository; m_repository = aRepository;
} }
GIT_REVERT_HANDLER::~GIT_REVERT_HANDLER() GIT_REVERT_HANDLER::~GIT_REVERT_HANDLER()
{ {
} }
bool GIT_REVERT_HANDLER::Revert( const wxString& aFilePath ) bool GIT_REVERT_HANDLER::Revert( const wxString& aFilePath )
{ {
m_filesToRevert.push_back( aFilePath ); m_filesToRevert.push_back( aFilePath );
return true; return true;
} }
static void checkout_progress_cb(const char *path, size_t cur, size_t tot, void *payload)
static void checkout_progress_cb( const char *path, size_t cur, size_t tot, void *payload )
{ {
wxLogDebug( "checkout_progress_cb: %s %zu/%zu", path, cur, tot ); wxLogTrace( traceGit, wxS( "checkout_progress_cb: %s %zu/%zu" ), path, cur, tot );
} }
static int checkout_notify_cb(git_checkout_notify_t why, const char *path, static int checkout_notify_cb( git_checkout_notify_t why, const char *path,
const git_diff_file *baseline, const git_diff_file *baseline,
const git_diff_file *target, const git_diff_file *target,
const git_diff_file *workdir, void *payload) const git_diff_file *workdir, void *payload )
{ {
GIT_REVERT_HANDLER* handler = static_cast<GIT_REVERT_HANDLER*>(payload); GIT_REVERT_HANDLER* handler = static_cast<GIT_REVERT_HANDLER*>(payload);
if( why & ( GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_IGNORED | GIT_CHECKOUT_NOTIFY_UPDATED ) ) if( why & ( GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_IGNORED
| GIT_CHECKOUT_NOTIFY_UPDATED ) )
handler->PushFailedFile( path ); handler->PushFailedFile( path );
return 0; return 0;
} }
void GIT_REVERT_HANDLER::PerformRevert() void GIT_REVERT_HANDLER::PerformRevert()
{ {
git_object* head_commit = NULL; git_object* head_commit = NULL;
git_checkout_options opts; git_checkout_options opts;
git_checkout_init_options(&opts, GIT_CHECKOUT_OPTIONS_VERSION); git_checkout_init_options( &opts, GIT_CHECKOUT_OPTIONS_VERSION );
// Get the HEAD commit // Get the HEAD commit
if (git_revparse_single(&head_commit, m_repository, "HEAD") != 0) { if( git_revparse_single( &head_commit, m_repository, "HEAD" ) != 0 )
{
// Handle error. If we cannot get the HEAD, then there's no point proceeding. // Handle error. If we cannot get the HEAD, then there's no point proceeding.
return; return;
} }
@ -86,15 +95,16 @@ void GIT_REVERT_HANDLER::PerformRevert()
opts.paths = arr; opts.paths = arr;
opts.progress_cb = checkout_progress_cb; opts.progress_cb = checkout_progress_cb;
opts.notify_cb = checkout_notify_cb; opts.notify_cb = checkout_notify_cb;
opts.notify_payload = static_cast<void*>(this); opts.notify_payload = static_cast<void*>( this );
// Attempt to checkout the file(s) // Attempt to checkout the file(s)
if (git_checkout_tree(m_repository, head_commit, &opts) != 0) if( git_checkout_tree(m_repository, head_commit, &opts ) != 0 )
{ {
const git_error *e = git_error_last(); const git_error *e = git_error_last();
if (e)
if( e )
{ {
wxLogError( "Checkout failed: %d: %s", e->klass, e->message ); wxLogTrace( traceGit, wxS( "Checkout failed: %d: %s" ), e->klass, e->message );
} }
} }
@ -104,6 +114,6 @@ void GIT_REVERT_HANDLER::PerformRevert()
delete[] paths; delete[] paths;
git_object_free(head_commit); git_object_free( head_commit );
} }

View File

@ -5,7 +5,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2013-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2013-2021, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -35,6 +35,15 @@
#include <wx/textctrl.h> #include <wx/textctrl.h>
#include <wx/statusbr.h> #include <wx/statusbr.h>
/**
* Flag to enable reporter debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceReporter[] = wxT( "KICAD_REPORTER" );
REPORTER& REPORTER::Report( const char* aText, SEVERITY aSeverity ) REPORTER& REPORTER::Report( const char* aText, SEVERITY aSeverity )
{ {
Report( From_UTF8( aText ) ); Report( From_UTF8( aText ) );
@ -186,14 +195,14 @@ REPORTER& WXLOG_REPORTER::Report( const wxString& aMsg, SEVERITY aSeverity )
{ {
switch( aSeverity ) switch( aSeverity )
{ {
case RPT_SEVERITY_ERROR: wxLogError( aMsg ); break; case RPT_SEVERITY_ERROR: wxLogError( aMsg ); break;
case RPT_SEVERITY_WARNING: wxLogWarning( aMsg ); break; case RPT_SEVERITY_WARNING: wxLogWarning( aMsg ); break;
case RPT_SEVERITY_UNDEFINED: wxLogMessage( aMsg ); break; case RPT_SEVERITY_UNDEFINED: wxLogMessage( aMsg ); break;
case RPT_SEVERITY_INFO: wxLogInfo( aMsg ); break; case RPT_SEVERITY_INFO: wxLogInfo( aMsg ); break;
case RPT_SEVERITY_ACTION: wxLogInfo( aMsg ); break; case RPT_SEVERITY_ACTION: wxLogInfo( aMsg ); break;
case RPT_SEVERITY_DEBUG: wxLogDebug( aMsg ); break; case RPT_SEVERITY_DEBUG: wxLogTrace( traceReporter, aMsg ); break;
case RPT_SEVERITY_EXCLUSION: break; case RPT_SEVERITY_EXCLUSION: break;
case RPT_SEVERITY_IGNORE: break; case RPT_SEVERITY_IGNORE: break;
} }
return *this; return *this;

View File

@ -56,6 +56,7 @@ const wxChar* const traceEnvVars = wxT( "KICAD_ENV_VARS" );
const wxChar* const traceGalProfile = wxT( "KICAD_GAL_PROFILE" ); const wxChar* const traceGalProfile = wxT( "KICAD_GAL_PROFILE" );
const wxChar* const traceKiCad2Step = wxT( "KICAD2STEP" ); const wxChar* const traceKiCad2Step = wxT( "KICAD2STEP" );
const wxChar* const traceUiProfile = wxT( "KICAD_UI_PROFILE" ); const wxChar* const traceUiProfile = wxT( "KICAD_UI_PROFILE" );
const wxChar* const traceGit = wxT( "KICAD_GIT" );
wxString dump( const wxArrayString& aArray ) wxString dump( const wxArrayString& aArray )

View File

@ -269,10 +269,12 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
{ {
wxBusyCursor busy; wxBusyCursor busy;
Schematic().SetRoot( pi->LoadSchematicFile( fullFileName, &Schematic() ) ); Schematic().SetRoot( pi->LoadSchematicFile( fullFileName, &Schematic() ) );
// Make ${SHEETNAME} work on the root sheet until we properly support // Make ${SHEETNAME} work on the root sheet until we properly support
// naming the root sheet // naming the root sheet
Schematic().Root().SetName( _( "Root" ) ); Schematic().Root().SetName( _( "Root" ) );
wxLogDebug( "Loaded schematic with root sheet UUID %s", Schematic().Root().m_Uuid.AsString() ); wxLogTrace( tracePathsAndFiles, wxS( "Loaded schematic with root sheet UUID %s" ),
Schematic().Root().m_Uuid.AsString() );
} }
if( !pi->GetError().IsEmpty() ) if( !pi->GetError().IsEmpty() )
@ -1388,9 +1390,9 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
try try
{ {
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) ); IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
DIALOG_HTML_REPORTER errorReporter( this ); DIALOG_HTML_REPORTER errorReporter( this );
WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 ); WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
PROJECT_CHOOSER_PLUGIN* projectChooserPlugin = PROJECT_CHOOSER_PLUGIN* projectChooserPlugin =
dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ); dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() );
@ -1422,8 +1424,8 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
errorReporter.ShowModal(); errorReporter.ShowModal();
} }
// Non-KiCad schematics do not use a drawing-sheet (or if they do, it works differently // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works
// to KiCad), so set it to an empty one // differently to KiCad), so set it to an empty one.
DS_DATA_MODEL& drawingSheet = DS_DATA_MODEL::GetTheInstance(); DS_DATA_MODEL& drawingSheet = DS_DATA_MODEL::GetTheInstance();
drawingSheet.SetEmptyLayout(); drawingSheet.SetEmptyLayout();
BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks"; BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";

View File

@ -65,6 +65,15 @@
#include <magic_enum.hpp> #include <magic_enum.hpp>
#include "sch_io_altium.h" #include "sch_io_altium.h"
/**
* Flag to enable Altium schematic debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceAltiumSch[] = wxT( "KICAD_ALTIUM_SCH" );
// Harness port object itself does not contain color information about itself // Harness port object itself does not contain color information about itself
// It seems altium is drawing harness ports using these colors // It seems altium is drawing harness ports using these colors
#define HARNESS_PORT_COLOR_DEFAULT_BACKGROUND COLOR4D( 0.92941176470588238, \ #define HARNESS_PORT_COLOR_DEFAULT_BACKGROUND COLOR4D( 0.92941176470588238, \
@ -469,7 +478,8 @@ void SCH_IO_ALTIUM::ParseAltiumSch( const wxString& aFileName )
} }
catch( const std::exception& exc ) catch( const std::exception& exc )
{ {
wxLogDebug( wxT( "Unhandled exception in Altium schematic parsers: %s." ), exc.what() ); wxLogTrace( traceAltiumSch, wxS( "Unhandled exception in Altium schematic "
"parsers: %s." ), exc.what() );
throw; throw;
} }
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -34,6 +34,14 @@
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
/**
* Flag to enable SPICE model parser debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceSpiceModelParser[] = wxT( "KICAD_SPICE_MODEL_PARSER" );
namespace SIM_MODEL_SPICE_PARSER namespace SIM_MODEL_SPICE_PARSER
{ {
using namespace SPICE_GRAMMAR; using namespace SPICE_GRAMMAR;
@ -67,7 +75,7 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
} }
catch( const tao::pegtl::parse_error& e ) catch( const tao::pegtl::parse_error& e )
{ {
wxLogDebug( "%s", e.what() ); wxLogTrace( traceSpiceModelParser, wxS( "%s" ), e.what() );
return SIM_MODEL::TYPE::NONE; return SIM_MODEL::TYPE::NONE;
} }
@ -137,7 +145,9 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadType( const SIM_LIBRARY_SPICE& aLibrary,
return ReadTypeFromSpiceStrings( typeString, level, version, false ); return ReadTypeFromSpiceStrings( typeString, level, version, false );
} }
else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotSubckt>() ) else if( node->is_type<SIM_MODEL_SPICE_PARSER::dotSubckt>() )
{
return SIM_MODEL::TYPE::SUBCKT; return SIM_MODEL::TYPE::SUBCKT;
}
else else
{ {
wxFAIL_MSG( "Unhandled parse tree node" ); wxFAIL_MSG( "Unhandled parse tree node" );

View File

@ -227,6 +227,13 @@ extern KICOMMON_API const wxChar* const traceKiCad2Step;
*/ */
extern KICOMMON_API const wxChar* const traceUiProfile; extern KICOMMON_API const wxChar* const traceUiProfile;
/**
* Flag to enable Git debugging output.
*
* Use "KICAD_GIT" to enable.
*/
extern KICOMMON_API const wxChar* const traceGit;
///@} ///@}
/** /**

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com * Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2022, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software: you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
@ -46,6 +46,14 @@
#include <wx/zipstrm.h> #include <wx/zipstrm.h>
/**
* Flag to enable PCM debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar tracePcm[] = wxT( "KICAD_PCM" );
const std::tuple<int, int, int> PLUGIN_CONTENT_MANAGER::m_kicad_version = const std::tuple<int, int, int> PLUGIN_CONTENT_MANAGER::m_kicad_version =
GetMajorMinorPatchTuple(); GetMajorMinorPatchTuple();
@ -558,7 +566,7 @@ void PLUGIN_CONTENT_MANAGER::updateInstalledPackagesMetadata( const wxString& aR
} }
catch( ... ) catch( ... )
{ {
wxLogDebug( "Invalid/Missing repository " + aRepositoryId ); wxLogTrace( tracePcm, wxS( "Invalid/Missing repository " ) + aRepositoryId );
return; return;
} }
@ -1100,7 +1108,6 @@ void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate()
if( m_updateThread.joinable() ) if( m_updateThread.joinable() )
return; return;
m_updateBackgroundJob = Pgm().GetBackgroundJobMonitor().Create( _( "PCM Update" ) ); m_updateBackgroundJob = Pgm().GetBackgroundJobMonitor().Create( _( "PCM Update" ) );
m_updateThread = std::thread( m_updateThread = std::thread(
@ -1177,6 +1184,7 @@ void PLUGIN_CONTENT_MANAGER::StopBackgroundUpdate()
{ {
if( m_updateBackgroundJob ) if( m_updateBackgroundJob )
m_updateBackgroundJob->m_reporter->Cancel(); m_updateBackgroundJob->m_reporter->Cancel();
m_updateThread.join(); m_updateThread.join();
} }
} }

View File

@ -66,7 +66,6 @@
#include <git/git_clone_handler.h> #include <git/git_clone_handler.h>
#include <git/kicad_git_compat.h> #include <git/kicad_git_compat.h>
#include <dialogs/git/dialog_git_repository.h> #include <dialogs/git/dialog_git_repository.h>
#include "project_tree_item.h" #include "project_tree_item.h"
@ -359,6 +358,7 @@ std::vector<wxString> getProjects( const wxDir& dir )
return projects; return projects;
} }
static git_repository* get_git_repository_for_file( const char* filename ) static git_repository* get_git_repository_for_file( const char* filename )
{ {
git_repository* repo = nullptr; git_repository* repo = nullptr;
@ -367,9 +367,9 @@ static git_repository* get_git_repository_for_file( const char* filename )
// Find the repository path for the given file // Find the repository path for the given file
if( git_repository_discover( &repo_path, filename, 0, NULL ) ) if( git_repository_discover( &repo_path, filename, 0, NULL ) )
{ {
#if 0 #if 0
printf( "get_git_repository_for_file: %s\n", git_error_last()->message ); fflush( 0 ); printf( "get_git_repository_for_file: %s\n", git_error_last()->message ); fflush( 0 );
#endif #endif
return nullptr; return nullptr;
} }
@ -431,7 +431,7 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
continue; continue;
if( reg.Compile( wxString::FromAscii( "^.*\\." ) + ext + wxString::FromAscii( "$" ), if( reg.Compile( wxString::FromAscii( "^.*\\." ) + ext + wxString::FromAscii( "$" ),
wxRE_ICASE ) && reg.Matches( aName ) ) wxRE_ICASE ) && reg.Matches( aName ) )
{ {
type = (TREE_FILE_TYPE) i; type = (TREE_FILE_TYPE) i;
break; break;
@ -683,6 +683,7 @@ void PROJECT_TREE_PANE::ReCreateTreePrj()
if( filename != fn.GetFullName() ) if( filename != fn.GetFullName() )
{ {
wxString name = dir.GetName() + wxFileName::GetPathSeparator() + filename; wxString name = dir.GetName() + wxFileName::GetPathSeparator() + filename;
// Add items living in the project directory, and populate the item // Add items living in the project directory, and populate the item
// if it is a directory (sub directories will be not populated) // if it is a directory (sub directories will be not populated)
addItemToProjectTree( name, m_root, &projects, true ); addItemToProjectTree( name, m_root, &projects, true );
@ -1169,9 +1170,11 @@ std::vector<PROJECT_TREE_ITEM*> PROJECT_TREE_PANE::GetSelectedData()
for( auto it = selection.begin(); it != selection.end(); it++ ) for( auto it = selection.begin(); it != selection.end(); it++ )
{ {
PROJECT_TREE_ITEM* item = GetItemIdData( *it ); PROJECT_TREE_ITEM* item = GetItemIdData( *it );
if( !item ) if( !item )
{ {
wxLogDebug( "Null tree item returned for selection, dynamic_cast failed?" ); wxLogTrace( traceGit, wxS( "Null tree item returned for selection, dynamic_cast "
"failed?" ) );
continue; continue;
} }
@ -1413,14 +1416,16 @@ void PROJECT_TREE_PANE::FileWatcherReset()
#ifdef __WINDOWS__ #ifdef __WINDOWS__
if( ! m_watcher->AddTree( fn ) ) if( ! m_watcher->AddTree( fn ) )
{ {
wxLogTrace( tracePathsAndFiles, "%s: failed to add '%s'\n", __func__, TO_UTF8( fn.GetFullPath() ) ); wxLogTrace( tracePathsAndFiles, "%s: failed to add '%s'\n", __func__,
TO_UTF8( fn.GetFullPath() ) );
return; return;
} }
} }
#else #else
if( !m_watcher->Add( fn ) ) if( !m_watcher->Add( fn ) )
{ {
wxLogTrace( tracePathsAndFiles, "%s: failed to add '%s'\n", __func__, TO_UTF8( fn.GetFullPath() ) ); wxLogTrace( tracePathsAndFiles, "%s: failed to add '%s'\n", __func__,
TO_UTF8( fn.GetFullPath() ) );
return; return;
} }
} }
@ -1975,7 +1980,7 @@ void PROJECT_TREE_PANE::updateGitStatusIcons()
if( git_repository_index( &index, repo ) != GIT_OK ) if( git_repository_index( &index, repo ) != GIT_OK )
{ {
m_gitLastError = giterr_last()->klass; m_gitLastError = giterr_last()->klass;
wxLogDebug( "Failed to get git index: %s", giterr_last()->message ); wxLogTrace( traceGit, wxS( "Failed to get git index: %s" ), giterr_last()->message );
return; return;
} }
@ -1983,7 +1988,7 @@ void PROJECT_TREE_PANE::updateGitStatusIcons()
if( git_status_list_new( &status_list, repo, &status_options ) != GIT_OK ) if( git_status_list_new( &status_list, repo, &status_options ) != GIT_OK )
{ {
wxLogDebug( "Failed to get git status list: %s", giterr_last()->message ); wxLogTrace( traceGit, wxS( "Failed to get git status list: %s" ), giterr_last()->message );
git_index_free( index ); git_index_free( index );
return; return;
} }
@ -2283,6 +2288,7 @@ void PROJECT_TREE_PANE::onGitCommit( wxCommandEvent& aEvent )
} }
} }
void PROJECT_TREE_PANE::onGitAddToIndex( wxCommandEvent& aEvent ) void PROJECT_TREE_PANE::onGitAddToIndex( wxCommandEvent& aEvent )
{ {
@ -2337,6 +2343,7 @@ void PROJECT_TREE_PANE::onGitFetch( wxCommandEvent& aEvent )
handler.PerformFetch(); handler.PerformFetch();
} }
void PROJECT_TREE_PANE::onGitResolveConflict( wxCommandEvent& aEvent ) void PROJECT_TREE_PANE::onGitResolveConflict( wxCommandEvent& aEvent )
{ {
git_repository* repo = m_TreeProject->GetGitRepo(); git_repository* repo = m_TreeProject->GetGitRepo();
@ -2348,6 +2355,7 @@ void PROJECT_TREE_PANE::onGitResolveConflict( wxCommandEvent& aEvent )
handler.PerformResolveConflict(); handler.PerformResolveConflict();
} }
void PROJECT_TREE_PANE::onGitRevertLocal( wxCommandEvent& aEvent ) void PROJECT_TREE_PANE::onGitRevertLocal( wxCommandEvent& aEvent )
{ {
git_repository* repo = m_TreeProject->GetGitRepo(); git_repository* repo = m_TreeProject->GetGitRepo();
@ -2359,6 +2367,7 @@ void PROJECT_TREE_PANE::onGitRevertLocal( wxCommandEvent& aEvent )
handler.PerformRevert(); handler.PerformRevert();
} }
void PROJECT_TREE_PANE::onGitRemoveFromIndex( wxCommandEvent& aEvent ) void PROJECT_TREE_PANE::onGitRemoveFromIndex( wxCommandEvent& aEvent )
{ {
git_repository* repo = m_TreeProject->GetGitRepo(); git_repository* repo = m_TreeProject->GetGitRepo();

View File

@ -3,7 +3,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2016-2018 CERN * Copyright (C) 2016-2018 CERN
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2022, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
@ -84,7 +84,7 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
void CN_ITEM::Dump() void CN_ITEM::Dump()
{ {
wxLogDebug(" valid: %d, connected: \n", !!Valid()); wxLogDebug( " valid: %d, connected: \n", !!Valid() );
for( CN_ITEM* i : m_connected ) for( CN_ITEM* i : m_connected )
{ {
@ -146,7 +146,7 @@ void CN_ITEM::RemoveInvalidRefs()
CN_ITEM* CN_LIST::Add( PAD* pad ) CN_ITEM* CN_LIST::Add( PAD* pad )
{ {
if( !pad->IsOnCopperLayer() ) if( !pad->IsOnCopperLayer() )
return nullptr; return nullptr;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2020 BeagleBoard Foundation * Copyright (C) 2020 BeagleBoard Foundation
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2023, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Seth Hillbrand <hillbrand@kipro-pcb.com> * Author: Seth Hillbrand <hillbrand@kipro-pcb.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -56,6 +56,14 @@
#include <wx/filename.h> #include <wx/filename.h>
/**
* Flag to enable #FABMASTER plugin debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceFabmaster[] = wxT( "KICAD_FABMASTER" );
void FABMASTER::checkpoint() void FABMASTER::checkpoint()
{ {
const unsigned PROGRESS_DELTA = 250; const unsigned PROGRESS_DELTA = 250;
@ -181,9 +189,11 @@ bool FABMASTER::Read( const std::string& aFile )
return true; return true;
} }
FABMASTER::section_type FABMASTER::detectType( size_t aOffset ) FABMASTER::section_type FABMASTER::detectType( size_t aOffset )
{ {
single_row row; single_row row;
try try
{ {
row = rows.at( aOffset ); row = rows.at( aOffset );
@ -203,7 +213,8 @@ FABMASTER::section_type FABMASTER::detectType( size_t aOffset )
std::string row2 = row[2]; std::string row2 = row[2];
std::string row3{}; std::string row3{};
/// We strip the underscores from all column names as some export variants use them and some do not /// We strip the underscores from all column names as some export variants use them and
// some do not
alg::delete_if( row1, []( char c ){ return c == '_'; } ); alg::delete_if( row1, []( char c ){ return c == '_'; } );
alg::delete_if( row2, []( char c ){ return c == '_'; } ); alg::delete_if( row2, []( char c ){ return c == '_'; } );
@ -254,6 +265,7 @@ FABMASTER::section_type FABMASTER::detectType( size_t aOffset )
} }
double FABMASTER::processScaleFactor( size_t aRow ) double FABMASTER::processScaleFactor( size_t aRow )
{ {
double retval = 0.0; double retval = 0.0;
@ -293,6 +305,7 @@ double FABMASTER::processScaleFactor( size_t aRow )
return retval; return retval;
} }
int FABMASTER::getColFromName( size_t aRow, const std::string& aStr ) int FABMASTER::getColFromName( size_t aRow, const std::string& aStr )
{ {
if( aRow >= rows.size() ) if( aRow >= rows.size() )
@ -505,8 +518,8 @@ size_t FABMASTER::processPadStacks( size_t aRow )
pad->drill = true; pad->drill = true;
/// This is to account for broken fabmaster outputs where circle drill hits don't actually get the // This is to account for broken fabmaster outputs where circle drill hits don't
/// drill hit value. // actually get the drill hit value.
if( drill_x == drill_y ) if( drill_x == drill_y )
{ {
pad->drill_size_x = drill_hit; pad->drill_size_x = drill_hit;
@ -983,9 +996,9 @@ size_t FABMASTER::processCustomPads( size_t aRow )
custom_pad.refdes = pad_refdes; custom_pad.refdes = pad_refdes;
} }
// At this point we extract the individual graphical elements for processing the complex pad. The // At this point we extract the individual graphical elements for processing the complex
// coordinates are in board origin format, so we'll need to fix the offset later when we assign them // pad. The coordinates are in board origin format, so we'll need to fix the offset later
// to the modules. // when we assign them to the modules.
auto gr_item = std::unique_ptr<GRAPHIC_ITEM>( processGraphic( gr_data, scale_factor ) ); auto gr_item = std::unique_ptr<GRAPHIC_ITEM>( processGraphic( gr_data, scale_factor ) );
@ -996,7 +1009,8 @@ size_t FABMASTER::processCustomPads( size_t aRow )
gr_item->seq = seq; gr_item->seq = seq;
gr_item->subseq = 0; gr_item->subseq = 0;
/// emplace may fail here, in which case, it returns the correct position to use for the existing map // emplace may fail here, in which case, it returns the correct position to use for
// the existing map
auto pad_it = custom_pad.elements.emplace( id, graphic_element{} ); auto pad_it = custom_pad.elements.emplace( id, graphic_element{} );
auto retval = pad_it.first->second.insert( std::move(gr_item ) ); auto retval = pad_it.first->second.insert( std::move(gr_item ) );
@ -1019,7 +1033,8 @@ size_t FABMASTER::processCustomPads( size_t aRow )
} }
FABMASTER::GRAPHIC_LINE* FABMASTER::processLine( const FABMASTER::GRAPHIC_DATA& aData, double aScale ) FABMASTER::GRAPHIC_LINE* FABMASTER::processLine( const FABMASTER::GRAPHIC_DATA& aData,
double aScale )
{ {
GRAPHIC_LINE* new_line = new GRAPHIC_LINE ; GRAPHIC_LINE* new_line = new GRAPHIC_LINE ;
@ -1033,6 +1048,7 @@ FABMASTER::GRAPHIC_LINE* FABMASTER::processLine( const FABMASTER::GRAPHIC_DATA&
return new_line; return new_line;
} }
FABMASTER::GRAPHIC_ARC* FABMASTER::processArc( const FABMASTER::GRAPHIC_DATA& aData, double aScale ) FABMASTER::GRAPHIC_ARC* FABMASTER::processArc( const FABMASTER::GRAPHIC_DATA& aData, double aScale )
{ {
GRAPHIC_ARC* new_arc = new GRAPHIC_ARC ; GRAPHIC_ARC* new_arc = new GRAPHIC_ARC ;
@ -1083,7 +1099,9 @@ FABMASTER::GRAPHIC_ARC* FABMASTER::processArc( const FABMASTER::GRAPHIC_DATA& aD
return new_arc; return new_arc;
} }
FABMASTER::GRAPHIC_RECTANGLE* FABMASTER::processRectangle( const FABMASTER::GRAPHIC_DATA& aData, double aScale )
FABMASTER::GRAPHIC_RECTANGLE* FABMASTER::processRectangle( const FABMASTER::GRAPHIC_DATA& aData,
double aScale )
{ {
GRAPHIC_RECTANGLE* new_rect = new GRAPHIC_RECTANGLE; GRAPHIC_RECTANGLE* new_rect = new GRAPHIC_RECTANGLE;
@ -1098,7 +1116,9 @@ FABMASTER::GRAPHIC_RECTANGLE* FABMASTER::processRectangle( const FABMASTER::GRAP
return new_rect; return new_rect;
} }
FABMASTER::GRAPHIC_TEXT* FABMASTER::processText( const FABMASTER::GRAPHIC_DATA& aData, double aScale )
FABMASTER::GRAPHIC_TEXT* FABMASTER::processText( const FABMASTER::GRAPHIC_DATA& aData,
double aScale )
{ {
GRAPHIC_TEXT* new_text = new GRAPHIC_TEXT; GRAPHIC_TEXT* new_text = new GRAPHIC_TEXT;
@ -1454,7 +1474,7 @@ size_t FABMASTER::processTraces( size_t aRow )
if( !gr_item ) if( !gr_item )
{ {
wxLogDebug( _( "Unhandled graphic item '%s' in row %zu." ), wxLogTrace( traceFabmaster, _( "Unhandled graphic item '%s' in row %zu." ),
gr_data.graphic_dataname.c_str(), gr_data.graphic_dataname.c_str(),
rownum ); rownum );
continue; continue;
@ -1539,6 +1559,7 @@ FABMASTER::COMPCLASS FABMASTER::parseCompClass( const std::string& aCmpClass )
return COMPCLASS_NONE; return COMPCLASS_NONE;
} }
/** /**
* A!REFDES!COMP_CLASS!COMP_PART_NUMBER!COMP_HEIGHT!COMP_DEVICE_LABEL!COMP_INSERTION_CODE!SYM_TYPE! * A!REFDES!COMP_CLASS!COMP_PART_NUMBER!COMP_HEIGHT!COMP_DEVICE_LABEL!COMP_INSERTION_CODE!SYM_TYPE!
* SYM_NAME!SYM_MIRROR!SYM_ROTATE!SYM_X!SYM_Y!COMP_VALUE!COMP_TOL!COMP_VOLTAGE! * SYM_NAME!SYM_MIRROR!SYM_ROTATE!SYM_X!SYM_Y!COMP_VALUE!COMP_TOL!COMP_VOLTAGE!
@ -1626,7 +1647,8 @@ size_t FABMASTER::processFootprints( size_t aRow )
/** /**
* A!SYM_NAME!SYM_MIRROR!PIN_NAME!PIN_NUMBER!PIN_X!PIN_Y!PAD_STACK_NAME!REFDES!PIN_ROTATION!TEST_POINT! * A!SYM_NAME!SYM_MIRROR!PIN_NAME!PIN_NUMBER!PIN_X!PIN_Y!PAD_STACK_NAME!REFDES!PIN_ROTATION!
* TEST_POINT!
*/ */
size_t FABMASTER::processPins( size_t aRow ) size_t FABMASTER::processPins( size_t aRow )
{ {
@ -1686,7 +1708,8 @@ size_t FABMASTER::processPins( size_t aRow )
if( map_it == pins.end() ) if( map_it == pins.end() )
{ {
auto retval = pins.insert( std::make_pair( pin->refdes, std::set<std::unique_ptr<PIN>, PIN::BY_NUM>{} ) ); auto retval = pins.insert( std::make_pair( pin->refdes, std::set<std::unique_ptr<PIN>,
PIN::BY_NUM>{} ) );
map_it = retval.first; map_it = retval.first;
} }
@ -2002,7 +2025,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
fp->SetOrientationDegrees( -src->rotate ); fp->SetOrientationDegrees( -src->rotate );
// KiCad netlisting requires parts to have non-digit + digit annotation. // KiCad netlisting requires parts to have non-digit + digit annotation.
// If the reference begins with a number, we prepend 'UNK' (unknown) for the source designator // If the reference begins with a number, we prepend 'UNK' (unknown) for the source
// designator
wxString reference = src->refdes; wxString reference = src->refdes;
if( !std::isalpha( src->refdes[0] ) ) if( !std::isalpha( src->refdes[0] ) )
@ -2026,7 +2050,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
if( !IsPcbLayer( layer ) ) if( !IsPcbLayer( layer ) )
{ {
wxLogDebug("The layer %s is not mapped?\n", ref->layer.c_str() ); wxLogTrace( traceFabmaster, wxS( "The layer %s is not mapped?" ),
ref->layer.c_str() );
continue; continue;
} }
@ -2038,12 +2063,14 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
if( src->mirror ) if( src->mirror )
{ {
txt->SetLayer( FlipLayer( layer ) ); txt->SetLayer( FlipLayer( layer ) );
txt->SetTextPos( VECTOR2I( lsrc->start_x, 2 * src->y - ( lsrc->start_y - lsrc->height / 2 ) ) ); txt->SetTextPos( VECTOR2I( lsrc->start_x,
2 * src->y - ( lsrc->start_y - lsrc->height / 2 ) ) );
} }
else else
{ {
txt->SetLayer( layer ); txt->SetLayer( layer );
txt->SetTextPos( VECTOR2I( lsrc->start_x, lsrc->start_y - lsrc->height / 2 ) ); txt->SetTextPos( VECTOR2I( lsrc->start_x,
lsrc->start_y - lsrc->height / 2 ) );
} }
txt->SetText( lsrc->text ); txt->SetText( lsrc->text );
@ -2189,12 +2216,14 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
if( src->mirror ) if( src->mirror )
{ {
txt->SetLayer( FlipLayer( layer ) ); txt->SetLayer( FlipLayer( layer ) );
txt->SetTextPos( VECTOR2I( lsrc->start_x, 2 * src->y - ( lsrc->start_y - lsrc->height / 2 ) ) ); txt->SetTextPos( VECTOR2I( lsrc->start_x,
2 * src->y - ( lsrc->start_y - lsrc->height / 2 ) ) );
} }
else else
{ {
txt->SetLayer( layer ); txt->SetLayer( layer );
txt->SetTextPos( VECTOR2I( lsrc->start_x, lsrc->start_y - lsrc->height / 2 ) ); txt->SetTextPos( VECTOR2I( lsrc->start_x,
lsrc->start_y - lsrc->height / 2 ) );
} }
txt->SetText( lsrc->text ); txt->SetText( lsrc->text );
@ -2204,8 +2233,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
txt->SetTextWidth( lsrc->width ); txt->SetTextWidth( lsrc->width );
txt->SetHorizJustify( lsrc->orient ); txt->SetHorizJustify( lsrc->orient );
// FABMASTER doesn't have visibility flags but layers that are not silk should be hidden // FABMASTER doesn't have visibility flags but layers that are not silk
// by default to prevent clutter. // should be hidden by default to prevent clutter.
if( txt->GetLayer() != F_SilkS && txt->GetLayer() != B_SilkS ) if( txt->GetLayer() != F_SilkS && txt->GetLayer() != B_SilkS )
txt->SetVisible( false ); txt->SetVisible( false );
@ -2224,7 +2253,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
{ {
for( auto& pin : pin_it->second ) for( auto& pin : pin_it->second )
{ {
auto pin_net_it = pin_nets.find( std::make_pair( pin->refdes, pin->pin_number ) ); auto pin_net_it = pin_nets.find( std::make_pair( pin->refdes,
pin->pin_number ) );
auto padstack = pads.find( pin->padstack ); auto padstack = pads.find( pin->padstack );
std::string netname = ""; std::string netname = "";
@ -2269,7 +2299,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
newpad->SetSize( VECTOR2I( pad_size / 2, pad_size / 2 ) ); newpad->SetSize( VECTOR2I( pad_size / 2, pad_size / 2 ) );
std::string custom_name = pad.custom_name + "_" + pin->refdes + "_" + pin->pin_number; std::string custom_name = pad.custom_name + "_" + pin->refdes + "_" +
pin->pin_number;
auto custom_it = pad_shapes.find( custom_name ); auto custom_it = pad_shapes.find( custom_name );
if( custom_it != pad_shapes.end() ) if( custom_it != pad_shapes.end() )
@ -2285,7 +2316,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
// that are a list of graphical polygons // that are a list of graphical polygons
for( const auto& el : (*custom_it).second.elements ) for( const auto& el : (*custom_it).second.elements )
{ {
// For now, we are only processing the custom pad for the top layer // For now, we are only processing the custom pad for the
// top layer
// TODO: Use full padstacks when implementing in KiCad // TODO: Use full padstacks when implementing in KiCad
PCB_LAYER_ID primary_layer = src->mirror ? B_Cu : F_Cu; PCB_LAYER_ID primary_layer = src->mirror ? B_Cu : F_Cu;
@ -2305,9 +2337,11 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() ); const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
if( poly_outline.VertexCount( 0, hole_idx ) == 0 ) if( poly_outline.VertexCount( 0, hole_idx ) == 0 )
poly_outline.Append( src->start_x, src->start_y, 0, hole_idx ); poly_outline.Append( src->start_x, src->start_y,
0, hole_idx );
poly_outline.Append( src->end_x, src->end_y, 0, hole_idx ); poly_outline.Append( src->end_x, src->end_y, 0,
hole_idx );
} }
else if( seg->shape == GR_SHAPE_ARC ) else if( seg->shape == GR_SHAPE_ARC )
{ {
@ -2335,12 +2369,15 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
if( src->mirror ) if( src->mirror )
{ {
poly_outline.Mirror( false, true, VECTOR2I( 0, ( pin->pin_y - src->y ) ) ); poly_outline.Mirror( false, true,
poly_outline.Rotate( EDA_ANGLE( src->rotate - pin->rotation, DEGREES_T ) ); VECTOR2I( 0, ( pin->pin_y - src->y ) ) );
poly_outline.Rotate( EDA_ANGLE( src->rotate - pin->rotation,
DEGREES_T ) );
} }
else else
{ {
poly_outline.Rotate( EDA_ANGLE( -src->rotate + pin->rotation, DEGREES_T ) ); poly_outline.Rotate( EDA_ANGLE( -src->rotate + pin->rotation,
DEGREES_T ) );
} }
newpad->AddPrimitivePoly( poly_outline, 0, true ); newpad->AddPrimitivePoly( poly_outline, 0, true );
@ -2364,7 +2401,9 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
} }
} }
else else
{
newpad->SetSize( VECTOR2I( pad.width, pad.height ) ); newpad->SetSize( VECTOR2I( pad.width, pad.height ) );
}
if( pad.drill ) if( pad.drill )
{ {
@ -2398,9 +2437,11 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
} }
if( src->mirror ) if( src->mirror )
newpad->SetOrientation( EDA_ANGLE( -src->rotate + pin->rotation, DEGREES_T ) ); newpad->SetOrientation( EDA_ANGLE( -src->rotate + pin->rotation,
DEGREES_T ) );
else else
newpad->SetOrientation( EDA_ANGLE( src->rotate - pin->rotation, DEGREES_T ) ); newpad->SetOrientation( EDA_ANGLE( src->rotate - pin->rotation,
DEGREES_T ) );
if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 ) if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 )
{ {
@ -2519,7 +2560,7 @@ bool FABMASTER::loadNets( BOARD* aBoard )
} }
bool FABMASTER::loadEtch( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRACE>& aLine) bool FABMASTER::loadEtch( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRACE>& aLine )
{ {
const NETNAMES_MAP& netinfo = aBoard->GetNetInfo().NetsByName(); const NETNAMES_MAP& netinfo = aBoard->GetNetInfo().NetsByName();
auto net_it = netinfo.find( aLine->netname ); auto net_it = netinfo.find( aLine->netname );
@ -2795,7 +2836,8 @@ bool FABMASTER::loadZone( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRACE>
{ {
if( seg->subseq > 0 && seg->subseq != last_subseq ) if( seg->subseq > 0 && seg->subseq != last_subseq )
{ {
/// Don't knock holes in the BOUNDARY systems. These are the outer layers for zone fills. // Don't knock holes in the BOUNDARY systems. These are the outer layers for
// zone fills.
if( aLine->lclass == "BOUNDARY" ) if( aLine->lclass == "BOUNDARY" )
break; break;

View File

@ -1,7 +1,7 @@
/** /**
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2023, 2024 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software: you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
@ -55,6 +55,15 @@
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/xml/xml.h> #include <wx/xml/xml.h>
/**
* Flag to enable IPC-2581 debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar traceIpc2581[] = wxT( "KICAD_IPC_2581" );
PCB_IO_IPC2581::~PCB_IO_IPC2581() PCB_IO_IPC2581::~PCB_IO_IPC2581()
{ {
clearLoadedFootprints(); clearLoadedFootprints();
@ -298,15 +307,18 @@ wxXmlNode* PCB_IO_IPC2581::generateXmlHeader()
addAttribute( xmlHeaderNode, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); addAttribute( xmlHeaderNode, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
if( m_version == 'B' ) if( m_version == 'B' )
addAttribute( xmlHeaderNode, "xsi:schemaLocation", "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd"); addAttribute( xmlHeaderNode, "xsi:schemaLocation",
"http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
else else
addAttribute( xmlHeaderNode, "xsi:schemaLocation", "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd"); addAttribute( xmlHeaderNode, "xsi:schemaLocation",
"http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
m_xml_doc->SetRoot(xmlHeaderNode); m_xml_doc->SetRoot( xmlHeaderNode );
return xmlHeaderNode; return xmlHeaderNode;
} }
wxXmlNode* PCB_IO_IPC2581::generateContentSection() wxXmlNode* PCB_IO_IPC2581::generateContentSection()
{ {
if( m_progressReporter ) if( m_progressReporter )
@ -332,27 +344,27 @@ wxXmlNode* PCB_IO_IPC2581::generateContentSection()
{ {
contentNode->AddChild( color_node ); contentNode->AddChild( color_node );
m_line_node = appendNode( contentNode, "DictionaryLineDesc" ); m_line_node = appendNode( contentNode, "DictionaryLineDesc" );
addAttribute( m_line_node, "units", m_units_str ); addAttribute( m_line_node, "units", m_units_str );
wxXmlNode* fillNode = appendNode( contentNode, "DictionaryFillDesc" ); wxXmlNode* fillNode = appendNode( contentNode, "DictionaryFillDesc" );
addAttribute( fillNode, "units", m_units_str ); addAttribute( fillNode, "units", m_units_str );
m_shape_std_node = appendNode( contentNode, "DictionaryStandard" ); m_shape_std_node = appendNode( contentNode, "DictionaryStandard" );
addAttribute( m_shape_std_node, "units", m_units_str ); addAttribute( m_shape_std_node, "units", m_units_str );
m_shape_user_node = appendNode( contentNode, "DictionaryUser" ); m_shape_user_node = appendNode( contentNode, "DictionaryUser" );
addAttribute( m_shape_user_node, "units", m_units_str ); addAttribute( m_shape_user_node, "units", m_units_str );
} }
else else
{ {
m_shape_std_node = appendNode( contentNode, "DictionaryStandard" ); m_shape_std_node = appendNode( contentNode, "DictionaryStandard" );
addAttribute( m_shape_std_node, "units", m_units_str ); addAttribute( m_shape_std_node, "units", m_units_str );
m_shape_user_node = appendNode( contentNode, "DictionaryUser" ); m_shape_user_node = appendNode( contentNode, "DictionaryUser" );
addAttribute( m_shape_user_node, "units", m_units_str ); addAttribute( m_shape_user_node, "units", m_units_str );
m_line_node = appendNode( contentNode, "DictionaryLineDesc" ); m_line_node = appendNode( contentNode, "DictionaryLineDesc" );
addAttribute( m_line_node, "units", m_units_str ); addAttribute( m_line_node, "units", m_units_str );
contentNode->AddChild( color_node ); contentNode->AddChild( color_node );
} }
@ -367,6 +379,7 @@ void PCB_IO_IPC2581::addLocationNode( wxXmlNode* aNode, double aX, double aY )
addXY( location_node, VECTOR2I( aX, aY ) ); addXY( location_node, VECTOR2I( aX, aY ) );
} }
void PCB_IO_IPC2581::addLocationNode( wxXmlNode* aNode, const PAD& aPad, bool aRelative ) void PCB_IO_IPC2581::addLocationNode( wxXmlNode* aNode, const PAD& aPad, bool aRelative )
{ {
VECTOR2D pos{}; VECTOR2D pos{};
@ -423,6 +436,7 @@ size_t PCB_IO_IPC2581::lineHash( int aWidth, LINE_STYLE aDashType )
return hash; return hash;
} }
size_t PCB_IO_IPC2581::shapeHash( const PCB_SHAPE& aShape ) size_t PCB_IO_IPC2581::shapeHash( const PCB_SHAPE& aShape )
{ {
return hash_fp_item( &aShape, HASH_POS | REL_COORD ); return hash_fp_item( &aShape, HASH_POS | REL_COORD );
@ -482,9 +496,12 @@ wxXmlNode* PCB_IO_IPC2581::generateContentStackup( wxXmlNode* aContentNode )
// not in standard color list. // not in standard color list.
{ {
COLOR4D layer_color( colorName ); COLOR4D layer_color( colorName );
addAttribute( color, "r", wxString::Format( "%d", KiROUND( layer_color.r * 255 ) ) ); addAttribute( color, "r", wxString::Format( "%d",
addAttribute( color, "g", wxString::Format( "%d", KiROUND( layer_color.g * 255 ) ) ); KiROUND( layer_color.r * 255 ) ) );
addAttribute( color, "b", wxString::Format( "%d", KiROUND( layer_color.b * 255 ) ) ); addAttribute( color, "g", wxString::Format( "%d",
KiROUND( layer_color.g * 255 ) ) );
addAttribute( color, "b", wxString::Format( "%d",
KiROUND( layer_color.b * 255 ) ) );
} }
else else
{ {
@ -563,25 +580,26 @@ void PCB_IO_IPC2581::addLineDesc( wxXmlNode* aNode, int aWidth, LINE_STYLE aDash
switch( aDashType ) switch( aDashType )
{ {
case LINE_STYLE::DOT: case LINE_STYLE::DOT:
addAttribute( line_node, "lineProperty", "DOTTED" ); addAttribute( line_node, "lineProperty", "DOTTED" );
break; break;
case LINE_STYLE::DASH: case LINE_STYLE::DASH:
addAttribute( line_node, "lineProperty", "DASHED" ); addAttribute( line_node, "lineProperty", "DASHED" );
break; break;
case LINE_STYLE::DASHDOT: case LINE_STYLE::DASHDOT:
addAttribute( line_node, "lineProperty", "CENTER" ); addAttribute( line_node, "lineProperty", "CENTER" );
break; break;
case LINE_STYLE::DASHDOTDOT: case LINE_STYLE::DASHDOTDOT:
addAttribute( line_node, "lineProperty", "PHANTOM" ); addAttribute( line_node, "lineProperty", "PHANTOM" );
break; break;
default: default:
break; break;
} }
} }
void PCB_IO_IPC2581::addText( wxXmlNode* aContentNode, EDA_TEXT* aText, const KIFONT::METRICS& aFontMetrics ) void PCB_IO_IPC2581::addText( wxXmlNode* aContentNode, EDA_TEXT* aText,
const KIFONT::METRICS& aFontMetrics )
{ {
if( !aText->IsVisible() ) if( !aText->IsVisible() )
return; return;
@ -631,6 +649,7 @@ void PCB_IO_IPC2581::addText( wxXmlNode* aContentNode, EDA_TEXT* aText, const KI
} }
} }
addLineDesc( line_node, attrs.m_StrokeWidth, LINE_STYLE::SOLID ); addLineDesc( line_node, attrs.m_StrokeWidth, LINE_STYLE::SOLID );
pts.clear(); pts.clear();
}; };
@ -689,7 +708,8 @@ void PCB_IO_IPC2581::addText( wxXmlNode* aContentNode, EDA_TEXT* aText, const KI
//TODO: handle knockout text and multiline //TODO: handle knockout text and multiline
font->Draw( &callback_gal, aText->GetShownText( true ), aText->GetTextPos(), attrs, aFontMetrics ); font->Draw( &callback_gal, aText->GetShownText( true ), aText->GetTextPos(), attrs,
aFontMetrics );
if( !pts.empty() ) if( !pts.empty() )
push_pts(); push_pts();
@ -957,7 +977,8 @@ void PCB_IO_IPC2581::addShape( wxXmlNode* aContentNode, const PCB_SHAPE& aShape
LINE_STYLE dash = aShape.GetStroke().GetLineStyle(); LINE_STYLE dash = aShape.GetStroke().GetLineStyle();
wxXmlNode* rect_node = appendNode( special_node, "RectRound" ); wxXmlNode* rect_node = appendNode( special_node, "RectRound" );
addLineDesc( rect_node, aShape.GetStroke().GetWidth(), aShape.GetStroke().GetLineStyle(), true ); addLineDesc( rect_node, aShape.GetStroke().GetWidth(), aShape.GetStroke().GetLineStyle(),
true );
if( aShape.GetFillMode() == FILL_T::NO_FILL ) if( aShape.GetFillMode() == FILL_T::NO_FILL )
{ {
@ -1094,7 +1115,8 @@ void PCB_IO_IPC2581::addSlotCavity( wxXmlNode* aNode, const PAD& aPad, const wxS
{ {
wxXmlNode* slotNode = appendNode( aNode, "SlotCavity" ); wxXmlNode* slotNode = appendNode( aNode, "SlotCavity" );
addAttribute( slotNode, "name", aName ); addAttribute( slotNode, "name", aName );
addAttribute( slotNode, "platingStatus", aPad.GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NONPLATED" ); addAttribute( slotNode, "platingStatus",
aPad.GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NONPLATED" );
addAttribute( slotNode, "plusTol", "0.0" ); addAttribute( slotNode, "plusTol", "0.0" );
addAttribute( slotNode, "minusTol", "0.0" ); addAttribute( slotNode, "minusTol", "0.0" );
@ -1156,6 +1178,7 @@ wxXmlNode* PCB_IO_IPC2581::generateHistorySection()
return historyNode; return historyNode;
} }
wxXmlNode* PCB_IO_IPC2581::generateBOMSection( wxXmlNode* aEcadNode ) wxXmlNode* PCB_IO_IPC2581::generateBOMSection( wxXmlNode* aEcadNode )
{ {
if( m_progressReporter ) if( m_progressReporter )
@ -1168,6 +1191,7 @@ wxXmlNode* PCB_IO_IPC2581::generateBOMSection( wxXmlNode* aEcadNode )
bool m_populate; bool m_populate;
wxString m_layer; wxString m_layer;
}; };
struct BOM_ENTRY struct BOM_ENTRY
{ {
BOM_ENTRY() BOM_ENTRY()
@ -1192,8 +1216,11 @@ wxXmlNode* PCB_IO_IPC2581::generateBOMSection( wxXmlNode* aEcadNode )
std::map<wxString, wxString>* m_props; std::map<wxString, wxString>* m_props;
}; };
std::set<std::unique_ptr<struct BOM_ENTRY>, std::function<bool( const std::unique_ptr<struct BOM_ENTRY>&, const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries( std::set<std::unique_ptr<struct BOM_ENTRY>,
[]( const std::unique_ptr<struct BOM_ENTRY>& a, const std::unique_ptr<struct BOM_ENTRY>& b ) std::function<bool( const std::unique_ptr<struct BOM_ENTRY>&,
const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
[]( const std::unique_ptr<struct BOM_ENTRY>& a,
const std::unique_ptr<struct BOM_ENTRY>& b )
{ {
return a->m_OEMDesignRef < b->m_OEMDesignRef; return a->m_OEMDesignRef < b->m_OEMDesignRef;
} ); } );
@ -1214,7 +1241,8 @@ wxXmlNode* PCB_IO_IPC2581::generateBOMSection( wxXmlNode* aEcadNode )
if( iter == m_footprint_dict.end() ) if( iter == m_footprint_dict.end() )
{ {
wxLogError( "Footprint %s not found in dictionary", fp->GetFPID().GetLibItemName().wx_str() ); wxLogError( "Footprint %s not found in dictionary",
fp->GetFPID().GetLibItemName().wx_str() );
continue; continue;
} }
@ -1228,7 +1256,8 @@ wxXmlNode* PCB_IO_IPC2581::generateBOMSection( wxXmlNode* aEcadNode )
} }
else else
{ {
wxLogError( "Footprint %s not found in OEMRef dictionary", fp->GetFPID().GetLibItemName().wx_str() ); wxLogError( "Footprint %s not found in OEMRef dictionary",
fp->GetFPID().GetLibItemName().wx_str() );
} }
entry->m_OEMDesignRef = genString( entry->m_OEMDesignRef, "REF" ); entry->m_OEMDesignRef = genString( entry->m_OEMDesignRef, "REF" );
@ -1458,7 +1487,8 @@ void PCB_IO_IPC2581::generateCadLayers( wxXmlNode* aCadLayerNode )
ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() ); ly_name = m_board->GetLayerName( stackup_item->GetBrdLayerId() );
if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC ) if( ly_name.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
ly_name = wxString::Format( "DIELECTRIC_%d", stackup_item->GetDielectricLayerId() ); ly_name = wxString::Format( "DIELECTRIC_%d",
stackup_item->GetDielectricLayerId() );
} }
ly_name = genString( ly_name, "LAYER" ); ly_name = genString( ly_name, "LAYER" );
@ -1536,8 +1566,10 @@ void PCB_IO_IPC2581::generateDrillLayers( wxXmlNode* aCadLayerNode )
addAttribute( drillNode, "side", "ALL" ); addAttribute( drillNode, "side", "ALL" );
wxXmlNode* spanNode = appendNode( drillNode, "Span" ); wxXmlNode* spanNode = appendNode( drillNode, "Span" );
addAttribute( spanNode, "fromLayer", genString( m_board->GetLayerName( layer_pair.first ), "LAYER" ) ); addAttribute( spanNode, "fromLayer",
addAttribute( spanNode, "toLayer", genString( m_board->GetLayerName( layer_pair.second ), "LAYER" ) ); genString( m_board->GetLayerName( layer_pair.first ), "LAYER" ) );
addAttribute( spanNode, "toLayer", genString( m_board->GetLayerName( layer_pair.second ),
"LAYER" ) );
} }
for( const auto& [layer_pair, vec] : m_slot_holes ) for( const auto& [layer_pair, vec] : m_slot_holes )
@ -1552,8 +1584,10 @@ void PCB_IO_IPC2581::generateDrillLayers( wxXmlNode* aCadLayerNode )
addAttribute( drillNode, "side", "ALL" ); addAttribute( drillNode, "side", "ALL" );
wxXmlNode* spanNode = appendNode( drillNode, "Span" ); wxXmlNode* spanNode = appendNode( drillNode, "Span" );
addAttribute( spanNode, "fromLayer", genString( m_board->GetLayerName( layer_pair.first ), "LAYER" ) ); addAttribute( spanNode, "fromLayer",
addAttribute( spanNode, "toLayer", genString( m_board->GetLayerName( layer_pair.second ), "LAYER" ) ); genString( m_board->GetLayerName( layer_pair.first ), "LAYER" ) );
addAttribute( spanNode, "toLayer",
genString( m_board->GetLayerName( layer_pair.second ), "LAYER" ) );
} }
} }
@ -1577,7 +1611,8 @@ void PCB_IO_IPC2581::generateStepSection( wxXmlNode* aCadNode )
m_last_padstack = insertNode( stepNode, "NonstandardAttribute" ); m_last_padstack = insertNode( stepNode, "NonstandardAttribute" );
addAttribute( m_last_padstack, "name", "FOOTPRINT_COUNT" ); addAttribute( m_last_padstack, "name", "FOOTPRINT_COUNT" );
addAttribute( m_last_padstack, "type", "INTEGER" ); addAttribute( m_last_padstack, "type", "INTEGER" );
addAttribute( m_last_padstack, "value", wxString::Format( "%zu", m_board->Footprints().size() ) ); addAttribute( m_last_padstack, "value",
wxString::Format( "%zu", m_board->Footprints().size() ) );
generateLayerFeatures( stepNode ); generateLayerFeatures( stepNode );
generateLayerSetDrill( stepNode ); generateLayerSetDrill( stepNode );
@ -1613,6 +1648,7 @@ void PCB_IO_IPC2581::addPad( wxXmlNode* aContentNode, const PAD* aPad, PCB_LAYER
} }
} }
void PCB_IO_IPC2581::addVia( wxXmlNode* aContentNode, const PCB_VIA* aVia, PCB_LAYER_ID aLayer ) void PCB_IO_IPC2581::addVia( wxXmlNode* aContentNode, const PCB_VIA* aVia, PCB_LAYER_ID aLayer )
{ {
if( !aVia->FlashLayer( aLayer ) ) if( !aVia->FlashLayer( aLayer ) )
@ -1632,6 +1668,7 @@ void PCB_IO_IPC2581::addVia( wxXmlNode* aContentNode, const PCB_VIA* aVia, PCB_L
addShape( padNode, dummy, aLayer ); addShape( padNode, dummy, aLayer );
} }
void PCB_IO_IPC2581::addPadStack( wxXmlNode* aPadNode, const PAD* aPad ) void PCB_IO_IPC2581::addPadStack( wxXmlNode* aPadNode, const PAD* aPad )
{ {
size_t hash = hash_fp_item( aPad, 0 ); size_t hash = hash_fp_item( aPad, 0 );
@ -1659,7 +1696,8 @@ void PCB_IO_IPC2581::addPadStack( wxXmlNode* aPadNode, const PAD* aPad )
aPad->GetDrillSizeX(), aPad->GetDrillSizeY() ) ); aPad->GetDrillSizeX(), aPad->GetDrillSizeY() ) );
addAttribute( padStackHoleNode, "diameter", floatVal( m_scale * aPad->GetDrillSizeX() ) ); addAttribute( padStackHoleNode, "diameter", floatVal( m_scale * aPad->GetDrillSizeX() ) );
addAttribute( padStackHoleNode, "platingStatus", aPad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NONPLATED" ); addAttribute( padStackHoleNode, "platingStatus",
aPad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NONPLATED" );
addAttribute( padStackHoleNode, "plusTol", "0.0" ); addAttribute( padStackHoleNode, "plusTol", "0.0" );
addAttribute( padStackHoleNode, "minusTol", "0.0" ); addAttribute( padStackHoleNode, "minusTol", "0.0" );
addXY( padStackHoleNode, aPad->GetOffset() ); addXY( padStackHoleNode, aPad->GetOffset() );
@ -1693,6 +1731,7 @@ void PCB_IO_IPC2581::addPadStack( wxXmlNode* aPadNode, const PAD* aPad )
} }
} }
void PCB_IO_IPC2581::addPadStack( wxXmlNode* aContentNode, const PCB_VIA* aVia ) void PCB_IO_IPC2581::addPadStack( wxXmlNode* aContentNode, const PCB_VIA* aVia )
{ {
size_t hash = hash_fp_item( aVia, 0 ); size_t hash = hash_fp_item( aVia, 0 );
@ -1794,7 +1833,8 @@ bool PCB_IO_IPC2581::addPolygonNode( wxXmlNode* aParentNode,
} }
bool PCB_IO_IPC2581::addPolygonCutouts( wxXmlNode* aParentNode, const SHAPE_POLY_SET::POLYGON& aPolygon ) bool PCB_IO_IPC2581::addPolygonCutouts( wxXmlNode* aParentNode,
const SHAPE_POLY_SET::POLYGON& aPolygon )
{ {
for( size_t ii = 1; ii < aPolygon.size(); ++ii ) for( size_t ii = 1; ii < aPolygon.size(); ++ii )
{ {
@ -1820,7 +1860,8 @@ bool PCB_IO_IPC2581::addPolygonCutouts( wxXmlNode* aParentNode, const SHAPE_POLY
} }
bool PCB_IO_IPC2581::addOutlineNode( wxXmlNode* aParentNode, const SHAPE_POLY_SET& aPolySet, int aWidth, LINE_STYLE aDashType ) bool PCB_IO_IPC2581::addOutlineNode( wxXmlNode* aParentNode, const SHAPE_POLY_SET& aPolySet,
int aWidth, LINE_STYLE aDashType )
{ {
if( aPolySet.OutlineCount() == 0 ) if( aPolySet.OutlineCount() == 0 )
return false; return false;
@ -1832,7 +1873,7 @@ bool PCB_IO_IPC2581::addOutlineNode( wxXmlNode* aParentNode, const SHAPE_POLY_SE
wxCHECK2( aPolySet.Outline( ii ).PointCount() >= 3, continue ); wxCHECK2( aPolySet.Outline( ii ).PointCount() >= 3, continue );
if( !addPolygonNode( outlineNode, aPolySet.Polygon( ii ) ) ) if( !addPolygonNode( outlineNode, aPolySet.Polygon( ii ) ) )
wxLogDebug( "Failed to add polygon to outline" ); wxLogTrace( traceIpc2581, wxS( "Failed to add polygon to outline" ) );
} }
if( !outlineNode->GetChildren() ) if( !outlineNode->GetChildren() )
@ -1885,9 +1926,10 @@ void PCB_IO_IPC2581::generateProfile( wxXmlNode* aStepNode )
} }
wxXmlNode* profileNode = appendNode( aStepNode, "Profile" ); wxXmlNode* profileNode = appendNode( aStepNode, "Profile" );
if( !addPolygonNode( profileNode, board_outline.Polygon( 0 ) ) ) if( !addPolygonNode( profileNode, board_outline.Polygon( 0 ) ) )
{ {
wxLogDebug( "Failed to add polygon to profile" ); wxLogTrace( traceIpc2581, wxS( "Failed to add polygon to profile" ) );
aStepNode->RemoveChild( profileNode ); aStepNode->RemoveChild( profileNode );
delete profileNode; delete profileNode;
} }
@ -1905,7 +1947,6 @@ wxXmlNode* PCB_IO_IPC2581::addPackage( wxXmlNode* aContentNode, FOOTPRINT* aFp )
fp->SetOrientation( ANGLE_0 ); fp->SetOrientation( ANGLE_0 );
size_t hash = hash_fp_item( fp.get(), HASH_POS | REL_COORD ); size_t hash = hash_fp_item( fp.get(), HASH_POS | REL_COORD );
wxString name = genString( wxString::Format( "%s_%zu", fp->GetFPID().GetLibItemName().wx_str(), wxString name = genString( wxString::Format( "%s_%zu", fp->GetFPID().GetLibItemName().wx_str(),
m_footprint_dict.size() + 1 ) ); m_footprint_dict.size() + 1 ) );
@ -1953,7 +1994,8 @@ wxXmlNode* PCB_IO_IPC2581::addPackage( wxXmlNode* aContentNode, FOOTPRINT* aFp )
if( courtyard_back.OutlineCount() > 0 ) if( courtyard_back.OutlineCount() > 0 )
{ {
otherSideViewNode = appendNode( packageNode, "OtherSideView" ); otherSideViewNode = appendNode( packageNode, "OtherSideView" );
addOutlineNode( otherSideViewNode, courtyard_back, courtyard_back.Outline( 0 ).Width(), LINE_STYLE::SOLID ); addOutlineNode( otherSideViewNode, courtyard_back, courtyard_back.Outline( 0 ).Width(),
LINE_STYLE::SOLID );
} }
if( !courtyard.OutlineCount() && !courtyard_back.OutlineCount() ) if( !courtyard.OutlineCount() && !courtyard_back.OutlineCount() )
@ -2117,7 +2159,7 @@ wxXmlNode* PCB_IO_IPC2581::addPackage( wxXmlNode* aContentNode, FOOTPRINT* aFp )
} }
} }
for( auto&[layer, bbox] : layer_bbox) for( auto&[layer, bbox] : layer_bbox )
{ {
if( bbox.GetWidth() > 0 ) if( bbox.GetWidth() > 0 )
{ {
@ -2172,8 +2214,8 @@ wxXmlNode* PCB_IO_IPC2581::addPackage( wxXmlNode* aContentNode, FOOTPRINT* aFp )
addLocationNode( pinNode, *pad, true ); addLocationNode( pinNode, *pad, true );
addShape( pinNode, *pad, pad->GetLayer() ); addShape( pinNode, *pad, pad->GetLayer() );
// We just need the padstack, we don't need the reference here. The reference will be created // We just need the padstack, we don't need the reference here. The reference will be
// in the LayerFeature set // created in the LayerFeature set
wxXmlNode dummy; wxXmlNode dummy;
addPadStack( &dummy, pad ); addPadStack( &dummy, pad );
} }
@ -2235,7 +2277,8 @@ void PCB_IO_IPC2581::generateComponents( wxXmlNode* aStepNode )
wxXmlNode* xformNode = appendNode( componentNode, "Xform" ); wxXmlNode* xformNode = appendNode( componentNode, "Xform" );
if( fp->GetOrientation() != ANGLE_0 ) if( fp->GetOrientation() != ANGLE_0 )
addAttribute( xformNode, "rotation", floatVal( fp->GetOrientation().Normalize().AsDegrees() ) ); addAttribute( xformNode, "rotation",
floatVal( fp->GetOrientation().Normalize().AsDegrees() ) );
if( fp->GetLayer() != F_Cu ) if( fp->GetLayer() != F_Cu )
addAttribute( xformNode, "mirror", "true" ); addAttribute( xformNode, "mirror", "true" );
@ -2259,12 +2302,14 @@ void PCB_IO_IPC2581::generateComponents( wxXmlNode* aStepNode )
aStepNode->AddChild( cmp ); aStepNode->AddChild( cmp );
} }
void PCB_IO_IPC2581::generateLogicalNets( wxXmlNode* aStepNode ) void PCB_IO_IPC2581::generateLogicalNets( wxXmlNode* aStepNode )
{ {
for( auto& [ net, pin_pair] : m_net_pin_dict ) for( auto& [ net, pin_pair] : m_net_pin_dict )
{ {
wxXmlNode* netNode = appendNode( aStepNode, "LogicalNet" ); wxXmlNode* netNode = appendNode( aStepNode, "LogicalNet" );
addAttribute( netNode, "name", genString( m_board->GetNetInfo().GetNetItem( net )->GetNetname(), "NET" ) ) ; addAttribute( netNode, "name",
genString( m_board->GetNetInfo().GetNetItem( net )->GetNetname(), "NET" ) ) ;
for( auto& [cmp, pin] : pin_pair ) for( auto& [cmp, pin] : pin_pair )
{ {
@ -2394,6 +2439,7 @@ void PCB_IO_IPC2581::generateLayerFeatures( wxXmlNode* aStepNode )
void PCB_IO_IPC2581::generateLayerSetDrill( wxXmlNode* aLayerNode ) void PCB_IO_IPC2581::generateLayerSetDrill( wxXmlNode* aLayerNode )
{ {
int hole_count = 1; int hole_count = 1;
for( const auto& [layer_pair, vec] : m_drill_layers ) for( const auto& [layer_pair, vec] : m_drill_layers )
{ {
wxXmlNode* layerNode = appendNode( aLayerNode, "LayerFeature" ); wxXmlNode* layerNode = appendNode( aLayerNode, "LayerFeature" );
@ -2430,7 +2476,6 @@ void PCB_IO_IPC2581::generateLayerSetDrill( wxXmlNode* aLayerNode )
addAttribute( holeNode, "minusTol", "0.0" ); addAttribute( holeNode, "minusTol", "0.0" );
addXY( holeNode, via->GetPosition() ); addXY( holeNode, via->GetPosition() );
} }
else if( item->Type() == PCB_PAD_T ) else if( item->Type() == PCB_PAD_T )
{ {
PAD* pad = static_cast<PAD*>( item ); PAD* pad = static_cast<PAD*>( item );
@ -2451,7 +2496,8 @@ void PCB_IO_IPC2581::generateLayerSetDrill( wxXmlNode* aLayerNode )
wxXmlNode* holeNode = appendNode( padNode, "Hole" ); wxXmlNode* holeNode = appendNode( padNode, "Hole" );
addAttribute( holeNode, "name", wxString::Format( "H%d", hole_count++ ) ); addAttribute( holeNode, "name", wxString::Format( "H%d", hole_count++ ) );
addAttribute( holeNode, "diameter", floatVal( m_scale * pad->GetDrillSizeX() ) ); addAttribute( holeNode, "diameter", floatVal( m_scale * pad->GetDrillSizeX() ) );
addAttribute( holeNode, "platingStatus", pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NONPLATED" ); addAttribute( holeNode, "platingStatus",
pad->GetAttribute() == PAD_ATTRIB::PTH ? "PLATED" : "NONPLATED" );
addAttribute( holeNode, "plusTol", "0.0" ); addAttribute( holeNode, "plusTol", "0.0" );
addAttribute( holeNode, "minusTol", "0.0" ); addAttribute( holeNode, "minusTol", "0.0" );
addXY( holeNode, pad->GetPosition() ); addXY( holeNode, pad->GetPosition() );
@ -2460,6 +2506,7 @@ void PCB_IO_IPC2581::generateLayerSetDrill( wxXmlNode* aLayerNode )
} }
hole_count = 1; hole_count = 1;
for( const auto& [layer_pair, vec] : m_slot_holes ) for( const auto& [layer_pair, vec] : m_slot_holes )
{ {
wxXmlNode* layerNode = appendNode( aLayerNode, "LayerFeature" ); wxXmlNode* layerNode = appendNode( aLayerNode, "LayerFeature" );
@ -2476,7 +2523,7 @@ void PCB_IO_IPC2581::generateLayerSetDrill( wxXmlNode* aLayerNode )
if( pad->GetNetCode() > 0 ) if( pad->GetNetCode() > 0 )
addAttribute( padNode, "net", genString( pad->GetNetname(), "NET" ) ); addAttribute( padNode, "net", genString( pad->GetNetname(), "NET" ) );
addSlotCavity( padNode, *pad, wxString::Format( "SLOT%d", hole_count++ ) ); addSlotCavity( padNode, *pad, wxString::Format( "SLOT%d", hole_count++ ) );
} }
} }
} }
@ -2500,11 +2547,13 @@ void PCB_IO_IPC2581::generateLayerSetNet( wxXmlNode* aLayerNode, PCB_LAYER_ID aL
wxXmlNode* teardropLayerSetNode = nullptr; wxXmlNode* teardropLayerSetNode = nullptr;
wxXmlNode* teardropFeatureSetNode = nullptr; wxXmlNode* teardropFeatureSetNode = nullptr;
if( BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( *it ); IsCopperLayer( aLayer ) && item ) if( BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( *it );
IsCopperLayer( aLayer ) && item )
{ {
if( item->GetNetCode() > 0 ) if( item->GetNetCode() > 0 )
addAttribute( layerSetNode, "net", genString( item->GetNetname(), "NET" ) ); addAttribute( layerSetNode, "net", genString( item->GetNetname(), "NET" ) );
} }
auto add_track = [&]( PCB_TRACK* track ) auto add_track = [&]( PCB_TRACK* track )
{ {
if( track->Type() == PCB_TRACE_T ) if( track->Type() == PCB_TRACE_T )
@ -2559,7 +2608,8 @@ void PCB_IO_IPC2581::generateLayerSetNet( wxXmlNode* aLayerNode, PCB_LAYER_ID aL
addAttribute( teardropLayerSetNode, "geometryUsage", "TEARDROP" ); addAttribute( teardropLayerSetNode, "geometryUsage", "TEARDROP" );
if( zone->GetNetCode() > 0 ) if( zone->GetNetCode() > 0 )
addAttribute( teardropLayerSetNode, "net", genString( zone->GetNetname(), "NET" ) ); addAttribute( teardropLayerSetNode, "net",
genString( zone->GetNetname(), "NET" ) );
wxXmlNode* new_teardrops = appendNode( teardropLayerSetNode, "Features" ); wxXmlNode* new_teardrops = appendNode( teardropLayerSetNode, "Features" );
addLocationNode( new_teardrops, 0.0, 0.0 ); addLocationNode( new_teardrops, 0.0, 0.0 );
@ -2605,7 +2655,8 @@ void PCB_IO_IPC2581::generateLayerSetNet( wxXmlNode* aLayerNode, PCB_LAYER_ID aL
addShape( tempFeature, *shape ); addShape( tempFeature, *shape );
} }
else if( shape->GetShape() == SHAPE_T::CIRCLE || shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::POLY ) else if( shape->GetShape() == SHAPE_T::CIRCLE || shape->GetShape() == SHAPE_T::RECTANGLE
|| shape->GetShape() == SHAPE_T::POLY )
{ {
wxXmlNode* tempSetNode = appendNode( aLayerNode, "Set" ); wxXmlNode* tempSetNode = appendNode( aLayerNode, "Set" );
@ -2726,7 +2777,7 @@ void PCB_IO_IPC2581::generateLayerSetNet( wxXmlNode* aLayerNode, PCB_LAYER_ID aL
break; break;
default: default:
wxLogDebug( "Unhandled type %s", wxLogTrace( traceIpc2581, wxS( "Unhandled type %s" ),
ENUM_MAP<KICAD_T>::Instance().ToString( item->Type() ) ); ENUM_MAP<KICAD_T>::Instance().ToString( item->Type() ) );
} }
} }
@ -2950,5 +3001,4 @@ void PCB_IO_IPC2581::SaveBoard( const wxString& aFileName, BOARD* aBoard,
} }
size_t size = out_stream.GetSize(); size_t size = out_stream.GetSize();
} }

View File

@ -1,8 +1,8 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com> * Copyright (C) 2015, 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.TXT for contributors. * Copyright (C) 2020, 2021, 2024 KiCad Developers, see AUTHORS.TXT for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -204,14 +204,15 @@ SCENEGRAPH* LoadVRML( const wxString& aFileName, bool useInline )
} }
catch( std::runtime_error& e ) catch( std::runtime_error& e )
{ {
wxLogDebug( wxT( " * [INFO] wrz load failed: %s" ), wxString::FromUTF8Unchecked( e.what() ) ); wxLogTrace( traceVrmlPlugin, wxS( " * [INFO] wrz load failed: %s" ),
wxString::FromUTF8Unchecked( e.what() ) );
delete[] buffer; delete[] buffer;
return nullptr; return nullptr;
} }
catch( ... ) catch( ... )
{ {
wxLogDebug( wxT( " * [INFO] wrz load failed: unknown error" ) ); wxLogTrace( traceVrmlPlugin, wxS( " * [INFO] wrz load failed: unknown error" ) );
delete[] buffer; delete[] buffer;
return nullptr; return nullptr;

View File

@ -35,6 +35,14 @@
#include <pad.h> #include <pad.h>
/**
* Flag to enable PNS playground debugging output.
*
* @ingroup trace_env_vars
*/
static const wxChar tracePnsPlayground[] = wxT( "KICAD_PNS_PLAYGROUND" );
std::shared_ptr<PNS_LOG_VIEWER_OVERLAY> overlay; std::shared_ptr<PNS_LOG_VIEWER_OVERLAY> overlay;
@ -363,19 +371,17 @@ int playground_main_func( int argc, char* argv[] )
overlay->AnnotatedPolyset( xorPad1ToPad2, "XOR Pads" ); overlay->AnnotatedPolyset( xorPad1ToPad2, "XOR Pads" );
overlay->AnnotatedPolyset( andPad1ToPad2, "AND Pads" ); overlay->AnnotatedPolyset( andPad1ToPad2, "AND Pads" );
wxLogDebug( wxS( "Pad 1 has %d outlines." ), wxLogTrace( tracePnsPlayground, wxS( "Pad 1 has %d outlines." ), pad1Outline.OutlineCount() );
pad1Outline.OutlineCount() );
wxLogDebug( wxS( "Pad 2 has %d outlines." ), wxLogTrace( tracePnsPlayground, wxS( "Pad 2 has %d outlines." ), pad2Outline.OutlineCount() );
pad2Outline.OutlineCount() );
VECTOR2I pt1, pt2; VECTOR2I pt1, pt2;
int dist = std::numeric_limits<int>::max(); int dist = std::numeric_limits<int>::max();
collide( pad1Outline, pad2Outline.Outline( 0 ), dist, &dist, &pt1 ); collide( pad1Outline, pad2Outline.Outline( 0 ), dist, &dist, &pt1 );
wxLogDebug( wxS( "Nearest distance between pad 1 and pad 2 is %0.6f mm at X=%0.6f mm, " wxLogDebug( tracePnsPlayground, wxS( "Nearest distance between pad 1 and pad 2 is %0.6f mm "
"Y=%0.6f mm." ), "at X=%0.6f mm, Y=%0.6f mm." ),
pcbIUScale.IUTomm( dist ), pcbIUScale.IUTomm( pt1.x ), pcbIUScale.IUTomm( dist ), pcbIUScale.IUTomm( pt1.x ),
pcbIUScale.IUTomm( pt1.y ) ); pcbIUScale.IUTomm( pt1.y ) );