Move PCBNew overrides to nullable properties.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/5562
This commit is contained in:
Jeff Young 2024-01-10 11:28:29 +00:00
parent 7c77266f12
commit ee3be0802c
38 changed files with 654 additions and 378 deletions

View File

@ -5,7 +5,7 @@
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
* *
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -775,18 +775,21 @@ int BOARD::GetMaxClearanceValue() const
{ {
int worstClearance = m_designSettings->GetBiggestClearanceValue(); int worstClearance = m_designSettings->GetBiggestClearanceValue();
for( ZONE* zone : m_zones ) for( ZONE* zone : m_zones )
worstClearance = std::max( worstClearance, zone->GetLocalClearance() ); worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
for( FOOTPRINT* footprint : m_footprints ) for( FOOTPRINT* footprint : m_footprints )
{ {
worstClearance = std::max( worstClearance, footprint->GetLocalClearance() );
for( PAD* pad : footprint->Pads() ) for( PAD* pad : footprint->Pads() )
worstClearance = std::max( worstClearance, pad->GetLocalClearance() ); {
std::optional<int> override = pad->GetClearanceOverrides( nullptr );
if( override.has_value() )
worstClearance = std::max( worstClearance, override.value() );
}
for( ZONE* zone : footprint->Zones() ) for( ZONE* zone : footprint->Zones() )
worstClearance = std::max( worstClearance, zone->GetLocalClearance() ); worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
} }
return worstClearance; return worstClearance;

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -141,21 +141,36 @@ public:
virtual int GetOwnClearance( PCB_LAYER_ID aLayer, wxString* aSource = nullptr ) const; virtual int GetOwnClearance( PCB_LAYER_ID aLayer, wxString* aSource = nullptr ) const;
/** /**
* Return any local clearance overrides set in the "classic" (ie: pre-rule) system. * Return any clearance overrides set in the "classic" (ie: pre-rule) system.
* *
* @param aSource [out] optionally reports the source as a user-readable string. * @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance in internal units. * @return the clearance in internal units.
*/ */
virtual int GetLocalClearanceOverrides( wxString* aSource ) const { return 0; } virtual std::optional<int> GetClearanceOverrides( wxString* aSource ) const
{
return std::optional<int>();
}
/** /**
* Return any local clearances set in the "classic" (ie: pre-rule) system. These are * Return any local clearances set in the "classic" (ie: pre-rule) system.
* things like zone clearance which are **not** an override.
* *
* @param aSource [out] optionally reports the source as a user readable string. * @return the clearance (if any is specified) in internal units.
* @return the clearance in internal units.
*/ */
virtual int GetLocalClearance( wxString* aSource ) const { return 0; } virtual std::optional<int> GetLocalClearance() const
{
return std::optional<int>();
}
/**
* Return any local clearances set in the "classic" (ie: pre-rule) system.
*
* @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance (if any is specified) in internal units.
*/
virtual std::optional<int> GetLocalClearance( wxString* aSource ) const
{
return std::optional<int>();
}
/** /**
* Return the #NETCLASS for this item. * Return the #NETCLASS for this item.

View File

@ -4,7 +4,7 @@
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt> * Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 Dick Hollenbeck, dick@softplc.com * Copyright (C) 2015 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-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
@ -304,13 +304,29 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataToWindow()
// Local Clearances // Local Clearances
m_netClearance.SetValue( m_footprint->GetLocalClearance() ); if( m_footprint->GetLocalClearance().has_value() )
m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin() ); m_netClearance.SetValue( m_footprint->GetLocalClearance().value() );
m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin() ); else
m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio() * 100.0 ); m_netClearance.SetValue( wxEmptyString );
if( m_footprint->GetLocalSolderMaskMargin().has_value() )
m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin().value() );
else
m_solderMask.SetValue( wxEmptyString );
if( m_footprint->GetLocalSolderPasteMargin().has_value() )
m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin().value() );
else
m_solderPaste.SetValue( wxEmptyString );
if( m_footprint->GetLocalSolderPasteMarginRatio().has_value() )
m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio().value() * 100.0 );
else
m_solderPasteRatio.SetValue( wxEmptyString );
m_allowSolderMaskBridges->SetValue( m_footprint->GetAttributes() & FP_ALLOW_SOLDERMASK_BRIDGES ); m_allowSolderMaskBridges->SetValue( m_footprint->GetAttributes() & FP_ALLOW_SOLDERMASK_BRIDGES );
switch( m_footprint->GetZoneConnection() ) switch( m_footprint->GetLocalZoneConnection() )
{ {
default: default:
case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break; case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
@ -506,18 +522,33 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataFromWindow()
} }
// Initialize masks clearances // Initialize masks clearances
m_footprint->SetLocalClearance( m_netClearance.GetValue() ); if( m_netClearance.IsNull() )
m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() ); m_footprint->SetLocalClearance( {} );
m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() ); else
m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 ); m_footprint->SetLocalClearance( m_netClearance.GetValue() );
if( m_solderMask.IsNull() )
m_footprint->SetLocalSolderMaskMargin( {} );
else
m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
if( m_solderPaste.IsNull() )
m_footprint->SetLocalSolderPasteMargin( {} );
else
m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
if( m_solderPasteRatio.IsNull() )
m_footprint->SetLocalSolderPasteMarginRatio( {} );
else
m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
switch( m_ZoneConnectionChoice->GetSelection() ) switch( m_ZoneConnectionChoice->GetSelection() )
{ {
default: default:
case 0: m_footprint->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break; case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
case 1: m_footprint->SetZoneConnection( ZONE_CONNECTION::FULL ); break; case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
case 2: m_footprint->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break; case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
case 3: m_footprint->SetZoneConnection( ZONE_CONNECTION::NONE ); break; case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
} }
// Set Footprint Position // Set Footprint Position

View File

@ -258,7 +258,7 @@ DIALOG_FOOTPRINT_PROPERTIES_BASE::DIALOG_FOOTPRINT_PROPERTIES_BASE( wxWindow* pa
m_PanelGeneral->SetSizer( m_PanelPropertiesBoxSizer ); m_PanelGeneral->SetSizer( m_PanelPropertiesBoxSizer );
m_PanelGeneral->Layout(); m_PanelGeneral->Layout();
m_PanelPropertiesBoxSizer->Fit( m_PanelGeneral ); m_PanelPropertiesBoxSizer->Fit( m_PanelGeneral );
m_NoteBook->AddPage( m_PanelGeneral, _("General"), true ); m_NoteBook->AddPage( m_PanelGeneral, _("General"), false );
m_PanelClearances = new wxPanel( m_NoteBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_PanelClearances = new wxPanel( m_NoteBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerPanelClearances; wxBoxSizer* bSizerPanelClearances;
bSizerPanelClearances = new wxBoxSizer( wxVERTICAL ); bSizerPanelClearances = new wxBoxSizer( wxVERTICAL );
@ -266,7 +266,7 @@ DIALOG_FOOTPRINT_PROPERTIES_BASE::DIALOG_FOOTPRINT_PROPERTIES_BASE( wxWindow* pa
wxStaticBoxSizer* sbSizerLocalProperties; wxStaticBoxSizer* sbSizerLocalProperties;
sbSizerLocalProperties = new wxStaticBoxSizer( new wxStaticBox( m_PanelClearances, wxID_ANY, _("Clearances") ), wxVERTICAL ); sbSizerLocalProperties = new wxStaticBoxSizer( new wxStaticBox( m_PanelClearances, wxID_ANY, _("Clearances") ), wxVERTICAL );
m_staticTextInfo = new wxStaticText( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("Set values to 0 to use Board Setup values."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextInfo = new wxStaticText( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("Leave values blank to use Board Setup values."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextInfo->Wrap( -1 ); m_staticTextInfo->Wrap( -1 );
sbSizerLocalProperties->Add( m_staticTextInfo, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); sbSizerLocalProperties->Add( m_staticTextInfo, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
@ -374,7 +374,7 @@ DIALOG_FOOTPRINT_PROPERTIES_BASE::DIALOG_FOOTPRINT_PROPERTIES_BASE( wxWindow* pa
m_PanelClearances->SetSizer( bSizerPanelClearances ); m_PanelClearances->SetSizer( bSizerPanelClearances );
m_PanelClearances->Layout(); m_PanelClearances->Layout();
bSizerPanelClearances->Fit( m_PanelClearances ); bSizerPanelClearances->Fit( m_PanelClearances );
m_NoteBook->AddPage( m_PanelClearances, _("Clearance Overrides and Settings"), false ); m_NoteBook->AddPage( m_PanelClearances, _("Clearance Overrides and Settings"), true );
m_GeneralBoxSizer->Add( m_NoteBook, 1, wxEXPAND|wxALL, 10 ); m_GeneralBoxSizer->Add( m_NoteBook, 1, wxEXPAND|wxALL, 10 );

View File

@ -124,7 +124,7 @@
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">General</property> <property name="label">General</property>
<property name="select">1</property> <property name="select">0</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
@ -2049,7 +2049,7 @@
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">Clearance Overrides and Settings</property> <property name="label">Clearance Overrides and Settings</property>
<property name="select">0</property> <property name="select">1</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
@ -2150,7 +2150,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Set values to 0 to use Board Setup values.</property> <property name="label">Leave values blank to use Board Setup values.</property>
<property name="markup">0</property> <property name="markup">0</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>

View File

@ -4,7 +4,7 @@
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 Dick Hollenbeck, dick@softplc.com * Copyright (C) 2015 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-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
@ -313,13 +313,29 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataToWindow()
// Local Clearances // Local Clearances
m_netClearance.SetValue( m_footprint->GetLocalClearance() ); if( m_footprint->GetLocalClearance().has_value() )
m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin() ); m_netClearance.SetValue( m_footprint->GetLocalClearance().value() );
m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin() ); else
m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio() * 100.0 ); m_netClearance.SetValue( wxEmptyString );
if( m_footprint->GetLocalSolderMaskMargin().has_value() )
m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin().value() );
else
m_solderMask.SetValue( wxEmptyString );
if( m_footprint->GetLocalSolderPasteMargin().has_value() )
m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin().value() );
else
m_solderPaste.SetValue( wxEmptyString );
if( m_footprint->GetLocalSolderPasteMarginRatio().has_value() )
m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio().value() * 100.0 );
else
m_solderPasteRatio.SetValue( wxEmptyString );
m_allowBridges->SetValue( m_footprint->GetAttributes() & FP_ALLOW_SOLDERMASK_BRIDGES ); m_allowBridges->SetValue( m_footprint->GetAttributes() & FP_ALLOW_SOLDERMASK_BRIDGES );
switch( m_footprint->GetZoneConnection() ) switch( m_footprint->GetLocalZoneConnection() )
{ {
default: default:
case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break; case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
@ -575,19 +591,34 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataFromWindow()
m_footprint->SetAttributes( attributes ); m_footprint->SetAttributes( attributes );
// Initialize masks clearances // Initialize mask clearances
m_footprint->SetLocalClearance( m_netClearance.GetValue() ); if( m_netClearance.IsNull() )
m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() ); m_footprint->SetLocalClearance( {} );
m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() ); else
m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 ); m_footprint->SetLocalClearance( m_netClearance.GetValue() );
if( m_solderMask.IsNull() )
m_footprint->SetLocalSolderMaskMargin( {} );
else
m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
if( m_solderPaste.IsNull() )
m_footprint->SetLocalSolderPasteMargin( {} );
else
m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
if( m_solderPasteRatio.IsNull() )
m_footprint->SetLocalSolderPasteMarginRatio( {} );
else
m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
switch( m_ZoneConnectionChoice->GetSelection() ) switch( m_ZoneConnectionChoice->GetSelection() )
{ {
default: default:
case 0: m_footprint->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break; case 0: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
case 1: m_footprint->SetZoneConnection( ZONE_CONNECTION::FULL ); break; case 1: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
case 2: m_footprint->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break; case 2: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
case 3: m_footprint->SetZoneConnection( ZONE_CONNECTION::NONE ); break; case 3: m_footprint->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
} }
m_footprint->ClearNetTiePadGroups(); m_footprint->ClearNetTiePadGroups();

View File

@ -234,7 +234,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITO
wxStaticBoxSizer* sbSizerLocalProperties; wxStaticBoxSizer* sbSizerLocalProperties;
sbSizerLocalProperties = new wxStaticBoxSizer( new wxStaticBox( m_PanelClearances, wxID_ANY, _("Clearances") ), wxVERTICAL ); sbSizerLocalProperties = new wxStaticBoxSizer( new wxStaticBox( m_PanelClearances, wxID_ANY, _("Clearances") ), wxVERTICAL );
m_staticTextInfo = new wxStaticText( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("Set values to 0 to use netclass values."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextInfo = new wxStaticText( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("Leave values blank to use netclass values."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextInfo->Wrap( -1 ); m_staticTextInfo->Wrap( -1 );
sbSizerLocalProperties->Add( m_staticTextInfo, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); sbSizerLocalProperties->Add( m_staticTextInfo, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
@ -250,7 +250,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITO
gbSizer1->Add( m_NetClearanceLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); gbSizer1->Add( m_NetClearanceLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_NetClearanceCtrl = new wxTextCtrl( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 ); m_NetClearanceCtrl = new wxTextCtrl( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_NetClearanceCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); gbSizer1->Add( m_NetClearanceCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_NetClearanceUnits = new wxStaticText( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); m_NetClearanceUnits = new wxStaticText( sbSizerLocalProperties->GetStaticBox(), wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );

View File

@ -123,7 +123,7 @@
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">General</property> <property name="label">General</property>
<property name="select">1</property> <property name="select">0</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
@ -1605,7 +1605,7 @@
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">Clearance Overrides and Settings</property> <property name="label">Clearance Overrides and Settings</property>
<property name="select">0</property> <property name="select">1</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
@ -1706,7 +1706,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Set values to 0 to use netclass values.</property> <property name="label">Leave values blank to use netclass values.</property>
<property name="markup">0</property> <property name="markup">0</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
@ -1875,7 +1875,7 @@
<property name="validator_style">wxFILTER_NONE</property> <property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property> <property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property> <property name="validator_variable"></property>
<property name="value">0</property> <property name="value"></property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>

View File

@ -4,7 +4,7 @@
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com * Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -606,13 +606,29 @@ void DIALOG_PAD_PROPERTIES::initValues()
m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 ); m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
m_padToDie.ChangeValue( m_previewPad->GetPadToDieLength() ); m_padToDie.ChangeValue( m_previewPad->GetPadToDieLength() );
m_clearance.ChangeValue( m_previewPad->GetLocalClearance() ); if( m_previewPad->GetLocalClearance().has_value() )
m_maskMargin.ChangeValue( m_previewPad->GetLocalSolderMaskMargin() ); m_clearance.ChangeValue( m_previewPad->GetLocalClearance().value() );
else
m_clearance.ChangeValue( wxEmptyString );
if( m_previewPad->GetLocalSolderMaskMargin().has_value() )
m_maskMargin.ChangeValue( m_previewPad->GetLocalSolderMaskMargin().value() );
else
m_maskMargin.ChangeValue( wxEmptyString );
if( m_previewPad->GetLocalSolderPasteMargin().has_value() )
m_pasteMargin.ChangeValue( m_previewPad->GetLocalSolderPasteMargin().value() );
else
m_pasteMargin.ChangeValue( wxEmptyString );
if( m_previewPad->GetLocalSolderPasteMarginRatio().has_value() )
m_pasteMarginRatio.ChangeDoubleValue( m_previewPad->GetLocalSolderPasteMarginRatio().value() * 100.0 );
else
m_pasteMarginRatio.ChangeValue( wxEmptyString );
m_spokeWidth.ChangeValue( m_previewPad->GetThermalSpokeWidth() ); m_spokeWidth.ChangeValue( m_previewPad->GetThermalSpokeWidth() );
m_spokeAngle.ChangeAngleValue( m_previewPad->GetThermalSpokeAngle() ); m_spokeAngle.ChangeAngleValue( m_previewPad->GetThermalSpokeAngle() );
m_thermalGap.ChangeValue( m_previewPad->GetThermalGap() ); m_thermalGap.ChangeValue( m_previewPad->GetThermalGap() );
m_pasteMargin.ChangeValue( m_previewPad->GetLocalSolderPasteMargin() );
m_pasteMarginRatio.ChangeDoubleValue( m_previewPad->GetLocalSolderPasteMarginRatio() * 100.0 );
m_pad_orientation.ChangeAngleValue( m_previewPad->GetOrientation() ); m_pad_orientation.ChangeAngleValue( m_previewPad->GetOrientation() );
m_cbTeardrops->SetValue( m_previewPad->GetTeardropParams().m_Enabled ); m_cbTeardrops->SetValue( m_previewPad->GetTeardropParams().m_Enabled );
@ -631,7 +647,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
else else
m_curvePointsCtrl->SetValue( 5 ); m_curvePointsCtrl->SetValue( 5 );
switch( m_previewPad->GetZoneConnection() ) switch( m_previewPad->GetLocalZoneConnection() )
{ {
default: default:
case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break; case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
@ -1269,9 +1285,11 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK()
// Some pads need a negative solder mask clearance (mainly for BGA with small pads) // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
// However the negative solder mask clearance must not create negative mask size // However the negative solder mask clearance must not create negative mask size
// Therefore test for minimal acceptable negative value // Therefore test for minimal acceptable negative value
if( m_previewPad->GetLocalSolderMaskMargin() < 0 ) std::optional<int> solderMaskMargin = m_previewPad->GetLocalSolderMaskMargin();
if( solderMaskMargin.has_value() && solderMaskMargin.value() < 0 )
{ {
int absMargin = abs( m_previewPad->GetLocalSolderMaskMargin() ); int absMargin = abs( solderMaskMargin.value() );
if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM ) if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
{ {
@ -1301,8 +1319,8 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK()
// So we could ask for user to confirm the choice // So we could ask for user to confirm the choice
// For now we just check for disappearing paste // For now we just check for disappearing paste
wxSize paste_size; wxSize paste_size;
int paste_margin = m_previewPad->GetLocalSolderPasteMargin(); int paste_margin = m_previewPad->GetLocalSolderPasteMargin().value_or( 0 );
double paste_ratio = m_previewPad->GetLocalSolderPasteMarginRatio(); double paste_ratio = m_previewPad->GetLocalSolderPasteMarginRatio().value_or( 0 );
paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio ); paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio ); paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
@ -1590,7 +1608,7 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
m_currentPad->SetRoundRectRadiusRatio( m_masterPad->GetRoundRectRadiusRatio() ); m_currentPad->SetRoundRectRadiusRatio( m_masterPad->GetRoundRectRadiusRatio() );
m_currentPad->SetChamferRectRatio( m_masterPad->GetChamferRectRatio() ); m_currentPad->SetChamferRectRatio( m_masterPad->GetChamferRectRatio() );
m_currentPad->SetChamferPositions( m_masterPad->GetChamferPositions() ); m_currentPad->SetChamferPositions( m_masterPad->GetChamferPositions() );
m_currentPad->SetZoneConnection( m_masterPad->GetZoneConnection() ); m_currentPad->SetLocalZoneConnection( m_masterPad->GetLocalZoneConnection() );
m_currentPad->GetTeardropParams() = m_masterPad->GetTeardropParams(); m_currentPad->GetTeardropParams() = m_masterPad->GetTeardropParams();
@ -1735,10 +1753,26 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
aPad->GetTeardropParams().m_WidthtoSizeFilterRatio = m_spTeardropHDPercent->GetValue() / 100; aPad->GetTeardropParams().m_WidthtoSizeFilterRatio = m_spTeardropHDPercent->GetValue() / 100;
// Read pad clearances values: // Read pad clearances values:
aPad->SetLocalClearance( m_clearance.GetIntValue() ); if( m_clearance.IsNull() )
aPad->SetLocalSolderMaskMargin( m_maskMargin.GetIntValue() ); aPad->SetLocalClearance( {} );
aPad->SetLocalSolderPasteMargin( m_pasteMargin.GetIntValue() ); else
aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 ); aPad->SetLocalClearance( m_clearance.GetIntValue() );
if( m_maskMargin.IsNull() )
aPad->SetLocalSolderMaskMargin( {} );
else
aPad->SetLocalSolderMaskMargin( m_maskMargin.GetIntValue() );
if( m_pasteMargin.IsNull() )
aPad->SetLocalSolderPasteMargin( {} );
else
aPad->SetLocalSolderPasteMargin( m_pasteMargin.GetIntValue() );
if( m_pasteMarginRatio.IsNull() )
aPad->SetLocalSolderPasteMarginRatio( {} );
else
aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 );
aPad->SetThermalSpokeWidth( m_spokeWidth.GetIntValue() ); aPad->SetThermalSpokeWidth( m_spokeWidth.GetIntValue() );
aPad->SetThermalSpokeAngle( m_spokeAngle.GetAngleValue() ); aPad->SetThermalSpokeAngle( m_spokeAngle.GetAngleValue() );
aPad->SetThermalGap( m_thermalGap.GetIntValue() ); aPad->SetThermalGap( m_thermalGap.GetIntValue() );
@ -1749,10 +1783,10 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
switch( m_ZoneConnectionChoice->GetSelection() ) switch( m_ZoneConnectionChoice->GetSelection() )
{ {
default: default:
case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break; case 0: aPad->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break; case 1: aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break; case 2: aPad->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break; case 3: aPad->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
} }
aPad->SetPosition( VECTOR2I( m_posX.GetIntValue(), m_posY.GetIntValue() ) ); aPad->SetPosition( VECTOR2I( m_posX.GetIntValue(), m_posY.GetIntValue() ) );

View File

@ -928,7 +928,7 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind
sbClearancesSizer = new wxStaticBoxSizer( new wxStaticBox( m_localSettingsPanel, wxID_ANY, _("Clearance Overrides") ), wxVERTICAL ); sbClearancesSizer = new wxStaticBoxSizer( new wxStaticBox( m_localSettingsPanel, wxID_ANY, _("Clearance Overrides") ), wxVERTICAL );
wxStaticText* m_staticTextHint; wxStaticText* m_staticTextHint;
m_staticTextHint = new wxStaticText( sbClearancesSizer->GetStaticBox(), wxID_ANY, _("Set values to 0 to use parent footprint or netclass values."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextHint = new wxStaticText( sbClearancesSizer->GetStaticBox(), wxID_ANY, _("Leave values blank to use parent footprint or netclass values."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextHint->Wrap( -1 ); m_staticTextHint->Wrap( -1 );
sbClearancesSizer->Add( m_staticTextHint, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 ); sbClearancesSizer->Add( m_staticTextHint, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project> <wxFormBuilder_Project>
<FileVersion major="1" minor="17"/> <FileVersion major="1" minor="16"/>
<object class="Project" expanded="true"> <object class="Project" expanded="true">
<property name="class_decoration"></property> <property name="class_decoration"></property>
<property name="code_generation">C++</property> <property name="code_generation">C++</property>
@ -10378,7 +10378,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Set values to 0 to use parent footprint or netclass values.</property> <property name="label">Leave values blank to use parent footprint or netclass values.</property>
<property name="markup">0</property> <property name="markup">0</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com * Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017-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
@ -739,39 +739,39 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
// Local overrides take precedence over everything *except* board min clearance // Local overrides take precedence over everything *except* board min clearance
if( aConstraintType == CLEARANCE_CONSTRAINT || aConstraintType == HOLE_CLEARANCE_CONSTRAINT ) if( aConstraintType == CLEARANCE_CONSTRAINT || aConstraintType == HOLE_CLEARANCE_CONSTRAINT )
{ {
int override_val = 0; int override_val = 0;
int overrideA = 0; std::optional<int> overrideA;
int overrideB = 0; std::optional<int> overrideB;
if( ac && !b_is_non_copper ) if( ac && !b_is_non_copper )
overrideA = ac->GetLocalClearanceOverrides( nullptr ); overrideA = ac->GetClearanceOverrides( nullptr );
if( bc && !a_is_non_copper ) if( bc && !a_is_non_copper )
overrideB = bc->GetLocalClearanceOverrides( nullptr ); overrideB = bc->GetClearanceOverrides( nullptr );
if( overrideA > 0 || overrideB > 0 ) if( overrideA.has_value() || overrideB.has_value() )
{ {
wxString msg; wxString msg;
if( overrideA > 0 ) if( overrideA.has_value() )
{ {
REPORT( "" ) REPORT( "" )
REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ), REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
EscapeHTML( a->GetItemDescription( this ) ), EscapeHTML( a->GetItemDescription( this ) ),
MessageTextFromValue( overrideA ) ) ) MessageTextFromValue( overrideA.value() ) ) )
override_val = ac->GetLocalClearanceOverrides( &msg ); override_val = ac->GetClearanceOverrides( &msg ).value();
} }
if( overrideB > 0 ) if( overrideB.has_value() )
{ {
REPORT( "" ) REPORT( "" )
REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ), REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
EscapeHTML( b->GetItemDescription( this ) ), EscapeHTML( b->GetItemDescription( this ) ),
EscapeHTML( MessageTextFromValue( overrideB ) ) ) ) EscapeHTML( MessageTextFromValue( overrideB.value() ) ) ) )
if( overrideB > override_val ) if( overrideB > override_val )
override_val = bc->GetLocalClearanceOverrides( &msg ); override_val = bc->GetClearanceOverrides( &msg ).value();
} }
if( override_val ) if( override_val )
@ -809,10 +809,10 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
} }
else if( aConstraintType == ZONE_CONNECTION_CONSTRAINT ) else if( aConstraintType == ZONE_CONNECTION_CONSTRAINT )
{ {
if( pad && pad->GetLocalZoneConnectionOverride( nullptr ) != ZONE_CONNECTION::INHERITED ) if( pad && pad->GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED )
{ {
wxString msg; wxString msg;
ZONE_CONNECTION override = pad->GetLocalZoneConnectionOverride( &msg ); ZONE_CONNECTION override = pad->GetZoneConnectionOverrides( &msg );
REPORT( "" ) REPORT( "" )
REPORT( wxString::Format( _( "Local override on %s; zone connection: %s." ), REPORT( wxString::Format( _( "Local override on %s; zone connection: %s." ),
@ -1326,13 +1326,13 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
if( aConstraintType == CLEARANCE_CONSTRAINT ) if( aConstraintType == CLEARANCE_CONSTRAINT )
{ {
int global = constraint.m_Value.Min(); int global = constraint.m_Value.Min();
int localA = ac ? ac->GetLocalClearance( nullptr ) : 0;
int localB = bc ? bc->GetLocalClearance( nullptr ) : 0;
int clearance = global; int clearance = global;
bool needBlankLine = true; bool needBlankLine = true;
if( localA > 0 ) if( ac && ac->GetLocalClearance().has_value() )
{ {
int localA = ac->GetLocalClearance().value();
if( needBlankLine ) if( needBlankLine )
{ {
REPORT( "" ) REPORT( "" )
@ -1346,15 +1346,17 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
if( localA > clearance ) if( localA > clearance )
{ {
wxString msg; wxString msg;
clearance = ac->GetLocalClearance( &msg ); clearance = ac->GetLocalClearance( &msg ).value();
constraint.SetParentRule( nullptr ); constraint.SetParentRule( nullptr );
constraint.SetName( msg ); constraint.SetName( msg );
constraint.m_Value.SetMin( clearance ); constraint.m_Value.SetMin( clearance );
} }
} }
if( localB > 0 ) if( bc && bc->GetLocalClearance().has_value() )
{ {
int localB = bc->GetLocalClearance().value();
if( needBlankLine ) if( needBlankLine )
{ {
REPORT( "" ) REPORT( "" )
@ -1368,7 +1370,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
if( localB > clearance ) if( localB > clearance )
{ {
wxString msg; wxString msg;
clearance = bc->GetLocalClearance( &msg ); clearance = bc->GetLocalClearance( &msg ).value();
constraint.SetParentRule( nullptr ); constraint.SetParentRule( nullptr );
constraint.SetName( msg ); constraint.SetName( msg );
constraint.m_Value.SetMin( clearance ); constraint.m_Value.SetMin( clearance );
@ -1415,7 +1417,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
{ {
if( pad && parentFootprint ) if( pad && parentFootprint )
{ {
ZONE_CONNECTION local = parentFootprint->GetZoneConnection(); ZONE_CONNECTION local = parentFootprint->GetLocalZoneConnection();
if( local != ZONE_CONNECTION::INHERITED ) if( local != ZONE_CONNECTION::INHERITED )
{ {

View File

@ -192,29 +192,70 @@ bool primitiveNeedsUpdate( const std::shared_ptr<PCB_SHAPE>& a,
} }
bool padHasOverrides( const PAD* a, const PAD* b, REPORTER* aReporter ) bool padHasOverrides( const PAD* a, const PAD* b, REPORTER& aReporter )
{ {
bool diff = false; bool diff = false;
TEST( a->GetLocalClearance(), b->GetLocalClearance(), #define REPORT_MSG( s, p ) aReporter.Report( wxString::Format( s, p ) )
wxString::Format( _( "%s has clearance override." ), PAD_DESC( a ) ) );
TEST( a->GetLocalSolderMaskMargin(), b->GetLocalSolderMaskMargin(),
wxString::Format( _( "%s has solder mask expansion override." ), PAD_DESC( a ) ) );
TEST( a->GetLocalSolderPasteMargin(), b->GetLocalSolderPasteMargin(),
wxString::Format( _( "%s has solder paste clearance override." ), PAD_DESC( a ) ) );
TEST_D( a->GetLocalSolderPasteMarginRatio(), b->GetLocalSolderPasteMarginRatio(),
wxString::Format( _( "%s has solder paste clearance override." ), PAD_DESC( a ) ) );
TEST( a->GetZoneConnection(), b->GetZoneConnection(), if( a->GetLocalClearance().has_value() && a->GetLocalClearance() != b->GetLocalClearance() )
wxString::Format( _( "%s has zone connection override." ), PAD_DESC( a ) ) ); {
TEST( a->GetThermalGap(), b->GetThermalGap(), diff = true;
wxString::Format( _( "%s has thermal relief gap override." ), PAD_DESC( a ) ) ); REPORT_MSG( _( "%s has clearance override." ), PAD_DESC( a ) );
TEST( a->GetThermalSpokeWidth(), b->GetThermalSpokeWidth(), }
wxString::Format( _( "%s has thermal relief spoke width override." ), PAD_DESC( a ) ) );
TEST_D( a->GetThermalSpokeAngle().AsDegrees(), b->GetThermalSpokeAngle().AsDegrees(), if( a->GetLocalSolderMaskMargin().has_value()
wxString::Format( _( "%s has thermal relief spoke angle override." ), PAD_DESC( a ) ) ); && a->GetLocalSolderMaskMargin() != b->GetLocalSolderMaskMargin() )
TEST( a->GetCustomShapeInZoneOpt(), b->GetCustomShapeInZoneOpt(), {
wxString::Format( _( "%s has zone knockout setting override." ), PAD_DESC( a ) ) ); diff = true;
REPORT_MSG( _( "%s has solder mask expansion override." ), PAD_DESC( a ) );
}
if( a->GetLocalSolderPasteMargin().has_value()
&& a->GetLocalSolderPasteMargin() != b->GetLocalSolderPasteMargin() )
{
diff = true;
REPORT_MSG( _( "%s has solder paste clearance override." ), PAD_DESC( a ) );
}
if( a->GetLocalSolderPasteMarginRatio()
&& a->GetLocalSolderPasteMarginRatio() != b->GetLocalSolderPasteMarginRatio() )
{
diff = true;
REPORT_MSG( _( "%s has solder paste clearance override." ), PAD_DESC( a ) );
}
if( a->GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED
&& a->GetLocalZoneConnection() != b->GetLocalZoneConnection() )
{
diff = true;
REPORT_MSG( _( "%s has zone connection override." ), PAD_DESC( a ) );
}
if( a->GetThermalGap() != b->GetThermalGap() )
{
diff = true;
REPORT_MSG( _( "%s has thermal relief gap override." ), PAD_DESC( a ) );
}
if( a->GetThermalSpokeWidth() != b->GetThermalSpokeWidth() )
{
diff = true;
REPORT_MSG( _( "%s has thermal relief spoke width override." ), PAD_DESC( a ) );
}
if( a->GetThermalSpokeAngle() != b->GetThermalSpokeAngle() )
{
diff = true;
REPORT_MSG( _( "%s has thermal relief spoke angle override." ), PAD_DESC( a ) );
}
if( a->GetCustomShapeInZoneOpt() != b->GetCustomShapeInZoneOpt() )
{
diff = true;
REPORT_MSG( _( "%s has zone knockout setting override." ), PAD_DESC( a ) );
}
return diff; return diff;
} }
@ -315,7 +356,7 @@ bool padNeedsUpdate( const PAD* a, const PAD* b, REPORTER* aReporter )
// going to be VERY noisy. // going to be VERY noisy.
// //
// So we just do it when we have a reporter. // So we just do it when we have a reporter.
if( aReporter && padHasOverrides( a, b, aReporter ) ) if( aReporter && padHasOverrides( a, b, *aReporter ) )
diff = true; diff = true;
bool primitivesDiffer = false; bool primitivesDiffer = false;
@ -594,17 +635,40 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, REPORTER* aReport
// For now we report them if there's a reporter, but we DON'T generate DRC errors on them. // For now we report them if there's a reporter, but we DON'T generate DRC errors on them.
if( aReporter ) if( aReporter )
{ {
TEST( GetLocalClearance(), aLibFP->GetLocalClearance(), if( GetLocalClearance().has_value() && GetLocalClearance() != aLibFP->GetLocalClearance() )
_( "Pad clearance overridden." ) ); {
TEST( GetLocalSolderMaskMargin(), aLibFP->GetLocalSolderMaskMargin(), diff = true;
_( "Solder mask expansion overridden." ) ); aReporter->Report( _( "Pad clearance overridden." ) );
TEST( GetLocalSolderPasteMargin(), aLibFP->GetLocalSolderPasteMargin(), }
_( "Solder paste absolute clearance overridden." ) );
TEST_D( GetLocalSolderPasteMarginRatio(), aLibFP->GetLocalSolderPasteMarginRatio(),
_( "Solder paste relative clearance overridden." ) );
TEST( GetZoneConnection(), aLibFP->GetZoneConnection(), if( GetLocalSolderMaskMargin().has_value()
_( "Zone connection overridden." ) ); && GetLocalSolderMaskMargin() != aLibFP->GetLocalSolderMaskMargin() )
{
diff = true;
aReporter->Report( _( "Solder mask expansion overridden." ) );
}
if( GetLocalSolderPasteMargin().has_value()
&& GetLocalSolderPasteMargin() != aLibFP->GetLocalSolderPasteMargin() )
{
diff = true;
aReporter->Report( _( "Solder paste absolute clearance overridden." ) );
}
if( GetLocalSolderPasteMarginRatio()
&& GetLocalSolderPasteMarginRatio() != aLibFP->GetLocalSolderPasteMarginRatio() )
{
diff = true;
aReporter->Report( _( "\"Solder paste relative clearance overridden." ) );
}
if( GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED
&& GetLocalZoneConnection() != aLibFP->GetLocalZoneConnection() )
{
diff = true;
aReporter->Report( _( "Zone connection overridden." ) );
}
} }
TEST( GetNetTiePadGroups().size(), aLibFP->GetNetTiePadGroups().size(), TEST( GetNetTiePadGroups().size(), aLibFP->GetNetTiePadGroups().size(),
@ -698,7 +762,7 @@ bool FOOTPRINT::FootprintNeedsUpdate( const FOOTPRINT* aLibFP, REPORTER* aReport
{ {
if( padNeedsUpdate( *aIt, *bIt, aReporter ) ) if( padNeedsUpdate( *aIt, *bIt, aReporter ) )
diff = true; diff = true;
else if( aReporter && padHasOverrides( *aIt, *bIt, aReporter ) ) else if( aReporter && padHasOverrides( *aIt, *bIt, *aReporter ) )
diff = true; diff = true;
} }
} }

View File

@ -4,7 +4,7 @@
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -70,12 +70,8 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) :
m_arflag = 0; m_arflag = 0;
m_link = 0; m_link = 0;
m_lastEditTime = 0; m_lastEditTime = 0;
m_localClearance = 0; m_zoneConnection = ZONE_CONNECTION::INHERITED;
m_localSolderMaskMargin = 0; m_fileFormatVersionAtLoad = 0;
m_localSolderPasteMargin = 0;
m_localSolderPasteMarginRatio = 0.0;
m_zoneConnection = ZONE_CONNECTION::INHERITED;
m_fileFormatVersionAtLoad = 0;
// These are the mandatory fields for the editor to work // These are the mandatory fields for the editor to work
for( int i = 0; i < MANDATORY_FIELDS; i++ ) for( int i = 0; i < MANDATORY_FIELDS; i++ )
@ -125,10 +121,10 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
m_cachedHull = aFootprint.m_cachedHull; m_cachedHull = aFootprint.m_cachedHull;
m_hullCacheTimeStamp = aFootprint.m_hullCacheTimeStamp; m_hullCacheTimeStamp = aFootprint.m_hullCacheTimeStamp;
m_localClearance = aFootprint.m_localClearance; m_clearance = aFootprint.m_clearance;
m_localSolderMaskMargin = aFootprint.m_localSolderMaskMargin; m_solderMaskMargin = aFootprint.m_solderMaskMargin;
m_localSolderPasteMargin = aFootprint.m_localSolderPasteMargin; m_solderPasteMargin = aFootprint.m_solderPasteMargin;
m_localSolderPasteMarginRatio = aFootprint.m_localSolderPasteMarginRatio; m_solderPasteMarginRatio = aFootprint.m_solderPasteMarginRatio;
m_zoneConnection = aFootprint.m_zoneConnection; m_zoneConnection = aFootprint.m_zoneConnection;
m_netTiePadGroups = aFootprint.m_netTiePadGroups; m_netTiePadGroups = aFootprint.m_netTiePadGroups;
m_fileFormatVersionAtLoad = aFootprint.m_fileFormatVersionAtLoad; m_fileFormatVersionAtLoad = aFootprint.m_fileFormatVersionAtLoad;
@ -448,10 +444,10 @@ FOOTPRINT& FOOTPRINT::operator=( FOOTPRINT&& aOther )
m_cachedHull = aOther.m_cachedHull; m_cachedHull = aOther.m_cachedHull;
m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp; m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp;
m_localClearance = aOther.m_localClearance; m_clearance = aOther.m_clearance;
m_localSolderMaskMargin = aOther.m_localSolderMaskMargin; m_solderMaskMargin = aOther.m_solderMaskMargin;
m_localSolderPasteMargin = aOther.m_localSolderPasteMargin; m_solderPasteMargin = aOther.m_solderPasteMargin;
m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio; m_solderPasteMarginRatio = aOther.m_solderPasteMarginRatio;
m_zoneConnection = aOther.m_zoneConnection; m_zoneConnection = aOther.m_zoneConnection;
m_netTiePadGroups = aOther.m_netTiePadGroups; m_netTiePadGroups = aOther.m_netTiePadGroups;
@ -542,10 +538,10 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
m_cachedHull = aOther.m_cachedHull; m_cachedHull = aOther.m_cachedHull;
m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp; m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp;
m_localClearance = aOther.m_localClearance; m_clearance = aOther.m_clearance;
m_localSolderMaskMargin = aOther.m_localSolderMaskMargin; m_solderMaskMargin = aOther.m_solderMaskMargin;
m_localSolderPasteMargin = aOther.m_localSolderPasteMargin; m_solderPasteMargin = aOther.m_solderPasteMargin;
m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio; m_solderPasteMarginRatio = aOther.m_solderPasteMarginRatio;
m_zoneConnection = aOther.m_zoneConnection; m_zoneConnection = aOther.m_zoneConnection;
m_netTiePadGroups = aOther.m_netTiePadGroups; m_netTiePadGroups = aOther.m_netTiePadGroups;
@ -3528,22 +3524,25 @@ static struct FOOTPRINT_DESC
_HKI( "Exempt From Courtyard Requirement" ), _HKI( "Exempt From Courtyard Requirement" ),
&FOOTPRINT::SetAllowMissingCourtyard, &FOOTPRINT::AllowMissingCourtyard ), &FOOTPRINT::SetAllowMissingCourtyard, &FOOTPRINT::AllowMissingCourtyard ),
groupOverrides ); groupOverrides );
propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Clearance Override" ), propMgr.AddProperty( new PROPERTY<FOOTPRINT, std::optional<int>>(
_HKI( "Clearance Override" ),
&FOOTPRINT::SetLocalClearance, &FOOTPRINT::GetLocalClearance, &FOOTPRINT::SetLocalClearance, &FOOTPRINT::GetLocalClearance,
PROPERTY_DISPLAY::PT_SIZE ), PROPERTY_DISPLAY::PT_SIZE ),
groupOverrides ); groupOverrides );
propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Solderpaste Margin Override" ), propMgr.AddProperty( new PROPERTY<FOOTPRINT, std::optional<int>>(
_HKI( "Solderpaste Margin Override" ),
&FOOTPRINT::SetLocalSolderPasteMargin, &FOOTPRINT::GetLocalSolderPasteMargin, &FOOTPRINT::SetLocalSolderPasteMargin, &FOOTPRINT::GetLocalSolderPasteMargin,
PROPERTY_DISPLAY::PT_SIZE ), PROPERTY_DISPLAY::PT_SIZE ),
groupOverrides ); groupOverrides );
propMgr.AddProperty( new PROPERTY<FOOTPRINT, double>( propMgr.AddProperty( new PROPERTY<FOOTPRINT, std::optional<double>>(
_HKI( "Solderpaste Margin Ratio Override" ), _HKI( "Solderpaste Margin Ratio Override" ),
&FOOTPRINT::SetLocalSolderPasteMarginRatio, &FOOTPRINT::SetLocalSolderPasteMarginRatio,
&FOOTPRINT::GetLocalSolderPasteMarginRatio ), &FOOTPRINT::GetLocalSolderPasteMarginRatio,
PROPERTY_DISPLAY::PT_RATIO ),
groupOverrides ); groupOverrides );
propMgr.AddProperty( new PROPERTY_ENUM<FOOTPRINT, ZONE_CONNECTION>( propMgr.AddProperty( new PROPERTY_ENUM<FOOTPRINT, ZONE_CONNECTION>(
_HKI( "Zone Connection Style" ), _HKI( "Zone Connection Style" ),
&FOOTPRINT::SetZoneConnection, &FOOTPRINT::GetZoneConnection ), &FOOTPRINT::SetLocalZoneConnection, &FOOTPRINT::GetLocalZoneConnection ),
groupOverrides ); groupOverrides );
} }
} _FOOTPRINT_DESC; } _FOOTPRINT_DESC;

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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -251,28 +251,20 @@ public:
wxString GetFilters() const { return m_filters; } wxString GetFilters() const { return m_filters; }
void SetFilters( const wxString& aFilters ) { m_filters = aFilters; } void SetFilters( const wxString& aFilters ) { m_filters = aFilters; }
int GetLocalSolderMaskMargin() const { return m_localSolderMaskMargin; } std::optional<int> GetLocalClearance() const { return m_clearance; }
void SetLocalSolderMaskMargin( int aMargin ) { m_localSolderMaskMargin = aMargin; } void SetLocalClearance( std::optional<int> aClearance ) { m_clearance = aClearance; }
int GetLocalClearance() const { return m_localClearance; } std::optional<int> GetLocalSolderMaskMargin() const { return m_solderMaskMargin; }
void SetLocalClearance( int aClearance ) { m_localClearance = aClearance; } void SetLocalSolderMaskMargin( std::optional<int> aMargin ) { m_solderMaskMargin = aMargin; }
int GetLocalClearance( wxString* aSource ) const std::optional<int> GetLocalSolderPasteMargin() const { return m_solderPasteMargin; }
{ void SetLocalSolderPasteMargin( std::optional<int> aMargin ) { m_solderPasteMargin = aMargin; }
if( aSource )
*aSource = wxString::Format( _( "footprint %s" ), GetReference() );
return m_localClearance; std::optional<double> GetLocalSolderPasteMarginRatio() const { return m_solderPasteMarginRatio; }
} void SetLocalSolderPasteMarginRatio( std::optional<double> aRatio ) { m_solderPasteMarginRatio = aRatio; }
int GetLocalSolderPasteMargin() const { return m_localSolderPasteMargin; } void SetLocalZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; }
void SetLocalSolderPasteMargin( int aMargin ) { m_localSolderPasteMargin = aMargin; } ZONE_CONNECTION GetLocalZoneConnection() const { return m_zoneConnection; }
double GetLocalSolderPasteMarginRatio() const { return m_localSolderPasteMarginRatio; }
void SetLocalSolderPasteMarginRatio( double aRatio ) { m_localSolderPasteMarginRatio = aRatio; }
void SetZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; }
ZONE_CONNECTION GetZoneConnection() const { return m_zoneConnection; }
int GetAttributes() const { return m_attributes; } int GetAttributes() const { return m_attributes; }
void SetAttributes( int aAttributes ) { m_attributes = aAttributes; } void SetAttributes( int aAttributes ) { m_attributes = aAttributes; }
@ -292,6 +284,33 @@ public:
return false; return false;
} }
std::optional<int> GetLocalClearance( wxString* aSource ) const
{
if( m_clearance.has_value() && aSource )
*aSource = wxString::Format( _( "footprint %s" ), GetReference() );
return m_clearance;
}
/**
* Return any local clearance overrides set in the "classic" (ie: pre-rule) system.
*
* @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance in internal units.
*/
std::optional<int> GetClearanceOverrides( wxString* aSource ) const
{
return GetLocalClearance( aSource );
}
ZONE_CONNECTION GetZoneConnectionOverrides( wxString* aSource ) const
{
if( m_zoneConnection != ZONE_CONNECTION::INHERITED && aSource )
*aSource = wxString::Format( _( "footprint %s" ), GetReference() );
return m_zoneConnection;
}
/** /**
* @return a list of pad groups, each of which is allowed to short nets within their group. * @return a list of pad groups, each of which is allowed to short nets within their group.
* A pad group is a comma-separated list of pad numbers. * A pad group is a comma-separated list of pad numbers.
@ -991,11 +1010,13 @@ private:
// A pad group is a comma-separated list of pad numbers. // A pad group is a comma-separated list of pad numbers.
std::vector<wxString> m_netTiePadGroups; std::vector<wxString> m_netTiePadGroups;
ZONE_CONNECTION m_zoneConnection; // Optional overrides
int m_localClearance; ZONE_CONNECTION m_zoneConnection;
int m_localSolderMaskMargin; // Solder mask margin std::optional<int> m_clearance;
int m_localSolderPasteMargin; // Solder paste margin absolute value std::optional<int> m_solderMaskMargin; // Solder mask margin
double m_localSolderPasteMarginRatio; // Solder mask margin ratio value of pad size std::optional<int> m_solderPasteMargin; // Solder paste margin absolute value
std::optional<double> m_solderPasteMarginRatio; // Solder mask margin ratio of pad size
// The final margin is the sum of these 2 values
wxString m_libDescription; // File name and path for documentation file. wxString m_libDescription; // File name and path for documentation file.
wxString m_keywords; // Search keywords to find footprint in library. wxString m_keywords; // Search keywords to find footprint in library.

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -77,10 +77,6 @@ PAD::PAD( FOOTPRINT* parent ) :
SetDrillShape( PAD_DRILL_SHAPE_CIRCLE ); // Default pad drill shape is a circle. SetDrillShape( PAD_DRILL_SHAPE_CIRCLE ); // Default pad drill shape is a circle.
m_attribute = PAD_ATTRIB::PTH; // Default pad type is plated through hole m_attribute = PAD_ATTRIB::PTH; // Default pad type is plated through hole
SetProperty( PAD_PROP::NONE ); // no special fabrication property SetProperty( PAD_PROP::NONE ); // no special fabrication property
m_localClearance = 0;
m_localSolderMaskMargin = 0;
m_localSolderPasteMargin = 0;
m_localSolderPasteMarginRatio = 0.0;
// Parameters for round rect only: // Parameters for round rect only:
m_roundedCornerScale = 0.25; // from IPC-7351C standard m_roundedCornerScale = 0.25; // from IPC-7351C standard
@ -805,26 +801,24 @@ bool PAD::IsOnCopperLayer() const
} }
int PAD::GetLocalClearanceOverrides( wxString* aSource ) const std::optional<int> PAD::GetLocalClearance( wxString* aSource ) const
{ {
// A pad can have specific clearance that overrides its NETCLASS clearance value if( m_clearance.has_value() && aSource )
if( GetLocalClearance() ) *aSource = _( "pad" );
return GetLocalClearance( aSource );
// A footprint can have a specific clearance value return m_clearance;
if( GetParentFootprint() && GetParentFootprint()->GetLocalClearance() )
return GetParentFootprint()->GetLocalClearance( aSource );
return 0;
} }
int PAD::GetLocalClearance( wxString* aSource ) const std::optional<int> PAD::GetClearanceOverrides( wxString* aSource ) const
{ {
if( aSource ) if( m_clearance.has_value() )
*aSource = _( "pad" ); return GetLocalClearance( aSource );
return m_localClearance; if( FOOTPRINT* parentFootprint = GetParentFootprint() )
return parentFootprint->GetClearanceOverrides( aSource );
return std::optional<int>();
} }
@ -862,35 +856,32 @@ int PAD::GetSolderMaskExpansion() const
if( ( m_layerMask & LSET::AllCuMask() ).none() ) if( ( m_layerMask & LSET::AllCuMask() ).none() )
return 0; return 0;
int margin = m_localSolderMaskMargin; std::optional<int> margin = m_solderMaskMargin;
if( FOOTPRINT* parentFootprint = GetParentFootprint() ) if( !margin.has_value() )
{ {
if( margin == 0 ) if( FOOTPRINT* parentFootprint = GetParentFootprint() )
{ margin = parentFootprint->GetLocalSolderMaskMargin();
if( parentFootprint->GetLocalSolderMaskMargin() )
margin = parentFootprint->GetLocalSolderMaskMargin();
}
if( margin == 0 )
{
const BOARD* brd = GetBoard();
if( brd )
margin = brd->GetDesignSettings().m_SolderMaskExpansion;
}
} }
if( !margin.has_value() )
{
if( const BOARD* brd = GetBoard() )
margin = brd->GetDesignSettings().m_SolderMaskExpansion;
}
int marginValue = margin.value_or( 0 );
// ensure mask have a size always >= 0 // ensure mask have a size always >= 0
if( margin < 0 ) if( marginValue < 0 )
{ {
int minsize = -std::min( m_size.x, m_size.y ) / 2; int minsize = -std::min( m_size.x, m_size.y ) / 2;
if( margin < minsize ) if( marginValue < minsize )
margin = minsize; marginValue = minsize;
} }
return margin; return marginValue;
} }
@ -902,31 +893,36 @@ VECTOR2I PAD::GetSolderPasteMargin() const
if( ( m_layerMask & LSET::AllCuMask() ).none() ) if( ( m_layerMask & LSET::AllCuMask() ).none() )
return VECTOR2I( 0, 0 ); return VECTOR2I( 0, 0 );
int margin = m_localSolderPasteMargin; std::optional<int> margin = m_solderPasteMargin;
double mratio = m_localSolderPasteMarginRatio; std::optional<double> mratio = m_solderPasteMarginRatio;
if( FOOTPRINT* parentFootprint = GetParentFootprint() ) if( !margin.has_value() )
{ {
if( margin == 0 ) if( FOOTPRINT* parentFootprint = GetParentFootprint() )
margin = parentFootprint->GetLocalSolderPasteMargin(); margin = parentFootprint->GetLocalSolderPasteMargin();
}
auto brd = GetBoard(); if( !margin.has_value() )
{
if( const BOARD* board = GetBoard() )
margin = board->GetDesignSettings().m_SolderPasteMargin;
}
if( margin == 0 && brd ) if( !mratio.has_value() )
margin = brd->GetDesignSettings().m_SolderPasteMargin; {
if( FOOTPRINT* parentFootprint = GetParentFootprint() )
if( mratio == 0.0 )
mratio = parentFootprint->GetLocalSolderPasteMarginRatio(); mratio = parentFootprint->GetLocalSolderPasteMarginRatio();
}
if( mratio == 0.0 && brd ) if( !mratio.has_value() )
{ {
mratio = brd->GetDesignSettings().m_SolderPasteMarginRatio; if( const BOARD* board = GetBoard() )
} mratio = board->GetDesignSettings().m_SolderPasteMarginRatio;
} }
VECTOR2I pad_margin; VECTOR2I pad_margin;
pad_margin.x = margin + KiROUND( m_size.x * mratio ); pad_margin.x = margin.value_or( 0 ) + KiROUND( m_size.x * mratio.value_or( 0 ) );
pad_margin.y = margin + KiROUND( m_size.y * mratio ); pad_margin.y = margin.value_or( 0 ) + KiROUND( m_size.y * mratio.value_or( 0 ) );
// ensure mask have a size always >= 0 // ensure mask have a size always >= 0
if( m_padShape != PAD_SHAPE::CUSTOM ) if( m_padShape != PAD_SHAPE::CUSTOM )
@ -942,12 +938,23 @@ VECTOR2I PAD::GetSolderPasteMargin() const
} }
ZONE_CONNECTION PAD::GetLocalZoneConnectionOverride( wxString* aSource ) const ZONE_CONNECTION PAD::GetZoneConnectionOverrides( wxString* aSource ) const
{ {
if( m_zoneConnection != ZONE_CONNECTION::INHERITED && aSource ) ZONE_CONNECTION connection = m_zoneConnection;
*aSource = _( "pad" );
return m_zoneConnection; if( connection != ZONE_CONNECTION::INHERITED )
{
if( aSource )
*aSource = _( "pad" );
}
if( connection == ZONE_CONNECTION::INHERITED )
{
if( FOOTPRINT* parentFootprint = GetParentFootprint() )
connection = parentFootprint->GetZoneConnectionOverrides( aSource );
}
return connection;
} }
@ -1544,7 +1551,7 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad )
SetLocalSolderPasteMargin( aMasterPad.GetLocalSolderPasteMargin() ); SetLocalSolderPasteMargin( aMasterPad.GetLocalSolderPasteMargin() );
SetLocalSolderPasteMarginRatio( aMasterPad.GetLocalSolderPasteMarginRatio() ); SetLocalSolderPasteMarginRatio( aMasterPad.GetLocalSolderPasteMarginRatio() );
SetZoneConnection( aMasterPad.GetZoneConnection() ); SetLocalZoneConnection( aMasterPad.GetLocalZoneConnection() );
SetThermalSpokeWidth( aMasterPad.GetThermalSpokeWidth() ); SetThermalSpokeWidth( aMasterPad.GetThermalSpokeWidth() );
SetThermalSpokeAngle( aMasterPad.GetThermalSpokeAngle() ); SetThermalSpokeAngle( aMasterPad.GetThermalSpokeAngle() );
SetThermalGap( aMasterPad.GetThermalGap() ); SetThermalGap( aMasterPad.GetThermalGap() );
@ -1733,7 +1740,7 @@ bool PAD::operator==( const BOARD_ITEM& aOther ) const
if( GetOrientation() != other.GetOrientation() ) if( GetOrientation() != other.GetOrientation() )
return false; return false;
if( GetZoneConnection() != other.GetZoneConnection() ) if( GetLocalZoneConnection() != other.GetLocalZoneConnection() )
return false; return false;
if( GetThermalSpokeWidth() != other.GetThermalSpokeWidth() ) if( GetThermalSpokeWidth() != other.GetThermalSpokeWidth() )
@ -1827,7 +1834,7 @@ double PAD::Similarity( const BOARD_ITEM& aOther ) const
if( GetOrientation() != other.GetOrientation() ) if( GetOrientation() != other.GetOrientation() )
similarity *= 0.9; similarity *= 0.9;
if( GetZoneConnection() != other.GetZoneConnection() ) if( GetLocalZoneConnection() != other.GetLocalZoneConnection() )
similarity *= 0.9; similarity *= 0.9;
if( GetThermalSpokeWidth() != other.GetThermalSpokeWidth() ) if( GetThermalSpokeWidth() != other.GetThermalSpokeWidth() )
@ -2019,25 +2026,30 @@ static struct PAD_DESC
const wxString groupOverrides = _HKI( "Overrides" ); const wxString groupOverrides = _HKI( "Overrides" );
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Clearance Override" ), propMgr.AddProperty( new PROPERTY<PAD, std::optional<int>>(
_HKI( "Clearance Override" ),
&PAD::SetLocalClearance, &PAD::GetLocalClearance, &PAD::SetLocalClearance, &PAD::GetLocalClearance,
PROPERTY_DISPLAY::PT_SIZE ), groupOverrides ); PROPERTY_DISPLAY::PT_SIZE ), groupOverrides );
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Soldermask Margin Override" ), propMgr.AddProperty( new PROPERTY<PAD, std::optional<int>>(
_HKI( "Soldermask Margin Override" ),
&PAD::SetLocalSolderMaskMargin, &PAD::GetLocalSolderMaskMargin, &PAD::SetLocalSolderMaskMargin, &PAD::GetLocalSolderMaskMargin,
PROPERTY_DISPLAY::PT_SIZE ), groupOverrides ); PROPERTY_DISPLAY::PT_SIZE ), groupOverrides );
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Solderpaste Margin Override" ), propMgr.AddProperty( new PROPERTY<PAD, std::optional<int>>(
_HKI( "Solderpaste Margin Override" ),
&PAD::SetLocalSolderPasteMargin, &PAD::GetLocalSolderPasteMargin, &PAD::SetLocalSolderPasteMargin, &PAD::GetLocalSolderPasteMargin,
PROPERTY_DISPLAY::PT_SIZE ), groupOverrides ); PROPERTY_DISPLAY::PT_SIZE ), groupOverrides );
propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Solderpaste Margin Ratio Override" ), propMgr.AddProperty( new PROPERTY<PAD, std::optional<double>>(
&PAD::SetLocalSolderPasteMarginRatio, &PAD::GetLocalSolderPasteMarginRatio ), _HKI( "Solderpaste Margin Ratio Override" ),
&PAD::SetLocalSolderPasteMarginRatio, &PAD::GetLocalSolderPasteMarginRatio,
PROPERTY_DISPLAY::PT_RATIO ),
groupOverrides ); groupOverrides );
propMgr.AddProperty( new PROPERTY_ENUM<PAD, ZONE_CONNECTION>( propMgr.AddProperty( new PROPERTY_ENUM<PAD, ZONE_CONNECTION>(
_HKI( "Zone Connection Style" ), _HKI( "Zone Connection Style" ),
&PAD::SetZoneConnection, &PAD::GetZoneConnection ), groupOverrides ); &PAD::SetLocalZoneConnection, &PAD::GetLocalZoneConnection ), groupOverrides );
constexpr int minZoneWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM ); constexpr int minZoneWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );

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) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -374,7 +374,7 @@ public:
PAD_ATTRIB GetAttribute() const { return m_attribute; } PAD_ATTRIB GetAttribute() const { return m_attribute; }
void SetProperty( PAD_PROP aProperty ); void SetProperty( PAD_PROP aProperty );
PAD_PROP GetProperty() const { return m_property; } PAD_PROP GetProperty() const { return m_property; }
// We don't currently have an attribute for APERTURE, and adding one will change the file // We don't currently have an attribute for APERTURE, and adding one will change the file
// format, so for now just infer a copper-less pad to be an APERTURE pad. // format, so for now just infer a copper-less pad to be an APERTURE pad.
@ -386,19 +386,28 @@ public:
void SetPadToDieLength( int aLength ) { m_lengthPadToDie = aLength; } void SetPadToDieLength( int aLength ) { m_lengthPadToDie = aLength; }
int GetPadToDieLength() const { return m_lengthPadToDie; } int GetPadToDieLength() const { return m_lengthPadToDie; }
int GetLocalSolderMaskMargin() const { return m_localSolderMaskMargin; } std::optional<int> GetLocalClearance() const override { return m_clearance; }
void SetLocalSolderMaskMargin( int aMargin ) { m_localSolderMaskMargin = aMargin; } void SetLocalClearance( std::optional<int> aClearance ) { m_clearance = aClearance; }
int GetLocalClearance( wxString* aSource ) const override; std::optional<int> GetLocalSolderMaskMargin() const { return m_solderMaskMargin; }
int GetLocalClearance() const { return m_localClearance; } void SetLocalSolderMaskMargin( std::optional<int> aMargin ) { m_solderMaskMargin = aMargin; }
void SetLocalClearance( int aClearance ) { m_localClearance = aClearance; }
int GetLocalSolderPasteMargin() const { return m_localSolderPasteMargin; } std::optional<int> GetLocalSolderPasteMargin() const { return m_solderPasteMargin; }
void SetLocalSolderPasteMargin( int aMargin ) { m_localSolderPasteMargin = aMargin; } void SetLocalSolderPasteMargin( std::optional<int> aMargin ) { m_solderPasteMargin = aMargin; }
double GetLocalSolderPasteMarginRatio() const { return m_localSolderPasteMarginRatio; } std::optional<double> GetLocalSolderPasteMarginRatio() const { return m_solderPasteMarginRatio; }
void SetLocalSolderPasteMarginRatio( double aRatio ) { m_localSolderPasteMarginRatio = aRatio; } void SetLocalSolderPasteMarginRatio( std::optional<double> aRatio ) { m_solderPasteMarginRatio = aRatio; }
void SetLocalZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; }
ZONE_CONNECTION GetLocalZoneConnection() const { return m_zoneConnection; }
/**
* Return the pad's "own" clearance in internal units.
*
* @param aLayer the layer in question.
* @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance in internal units.
*/
int GetOwnClearance( PCB_LAYER_ID aLayer, wxString* aSource = nullptr ) const override; int GetOwnClearance( PCB_LAYER_ID aLayer, wxString* aSource = nullptr ) const override;
/** /**
@ -465,7 +474,15 @@ public:
* @param aSource [out] optionally reports the source as a user-readable string. * @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance in internal units. * @return the clearance in internal units.
*/ */
int GetLocalClearanceOverrides( wxString* aSource ) const override; std::optional<int> GetLocalClearance( wxString* aSource ) const override;
/**
* Return any clearance overrides set in the "classic" (ie: pre-rule) system.
*
* @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance in internal units.
*/
std::optional<int> GetClearanceOverrides( wxString* aSource ) const override;
/** /**
* @return the expansion for the solder mask layer * @return the expansion for the solder mask layer
@ -492,10 +509,7 @@ public:
*/ */
VECTOR2I GetSolderPasteMargin() const; VECTOR2I GetSolderPasteMargin() const;
void SetZoneConnection( ZONE_CONNECTION aType ) { m_zoneConnection = aType; } ZONE_CONNECTION GetZoneConnectionOverrides( wxString* aSource = nullptr ) const;
ZONE_CONNECTION GetZoneConnection() const { return m_zoneConnection; }
ZONE_CONNECTION GetLocalZoneConnectionOverride( wxString* aSource = nullptr ) const;
/** /**
* Set the width of the thermal spokes connecting the pad to a zone. If != 0 this will * Set the width of the thermal spokes connecting the pad to a zone. If != 0 this will
@ -821,13 +835,13 @@ private:
* LEVEL 2: Rules * LEVEL 2: Rules
* LEVEL 3: Accumulated local settings, netclass settings, & board design settings * LEVEL 3: Accumulated local settings, netclass settings, & board design settings
* *
* These are the LEVEL 1 settings for a pad. * These are the LEVEL 1 settings (overrides) for a pad.
*/ */
int m_localClearance; std::optional<int> m_clearance;
int m_localSolderMaskMargin; // Local solder mask margin std::optional<int> m_solderMaskMargin; // Solder mask margin
int m_localSolderPasteMargin; // Local solder paste margin absolute value std::optional<int> m_solderPasteMargin; // Solder paste margin absolute value
double m_localSolderPasteMarginRatio; // Local solder mask margin ratio of pad size std::optional<double> m_solderPasteMarginRatio; // Solder mask margin ratio of pad size
// The final margin is the sum of these 2 values // The final margin is the sum of these 2 values
/* /*
* How to build the custom shape in zone, to create the clearance area: * How to build the custom shape in zone, to create the clearance area:

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-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com> * Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-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
@ -1062,12 +1062,20 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
if( kiLayer == F_Mask || kiLayer == B_Mask ) if( kiLayer == F_Mask || kiLayer == B_Mask )
{ {
if( std::abs( pad->GetLocalSolderMaskMargin() ) < std::abs( newMargin ) ) std::optional<int> localMargin = pad->GetLocalSolderMaskMargin();
if( !localMargin.has_value() )
pad->SetLocalSolderMaskMargin( newMargin );
else if( std::abs( localMargin.value() ) < std::abs( newMargin ) )
pad->SetLocalSolderMaskMargin( newMargin ); pad->SetLocalSolderMaskMargin( newMargin );
} }
else if( kiLayer == F_Paste || kiLayer == B_Paste ) else if( kiLayer == F_Paste || kiLayer == B_Paste )
{ {
if( std::abs( pad->GetLocalSolderPasteMargin() ) < std::abs( newMargin ) ) std::optional<int> localMargin = pad->GetLocalSolderPasteMargin();
if( !localMargin.has_value() )
pad->SetLocalSolderPasteMargin( newMargin );
else if( std::abs( localMargin.value() ) < std::abs( newMargin ) )
pad->SetLocalSolderPasteMargin( newMargin ); pad->SetLocalSolderPasteMargin( newMargin );
} }
else else
@ -3748,7 +3756,8 @@ bool CADSTAR_PCB_ARCHIVE_LOADER::calculateZonePriorities( PCB_LAYER_ID& aLayer )
int extra = getKiCadLength( Assignments.Codedefs.SpacingCodes.at( wxT( "C_C" ) ).Spacing ) int extra = getKiCadLength( Assignments.Codedefs.SpacingCodes.at( wxT( "C_C" ) ).Spacing )
- m_board->GetDesignSettings().m_MinClearance; - m_board->GetDesignSettings().m_MinClearance;
int retval = std::max( aZoneA->GetLocalClearance(), aZoneB->GetLocalClearance() ); int retval = std::max( aZoneA->GetLocalClearance().value(),
aZoneB->GetLocalClearance().value() );
retval += extra; retval += extra;

View File

@ -2512,7 +2512,7 @@ void PCB_IO_EAGLE::transferPad( const EPAD_COMMON& aEaglePad, PAD* aPad ) const
// Solid connection to copper zones // Solid connection to copper zones
if( aEaglePad.thermals && !*aEaglePad.thermals ) if( aEaglePad.thermals && !*aEaglePad.thermals )
aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL );
FOOTPRINT* footprint = aPad->GetParentFootprint(); FOOTPRINT* footprint = aPad->GetParentFootprint();
wxCHECK( footprint, /* void */ ); wxCHECK( footprint, /* void */ );

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) 2023 Alex Shvartzkop <dudesuchamazing@gmail.com> * Copyright (C) 2023 Alex Shvartzkop <dudesuchamazing@gmail.com>
* 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
@ -532,11 +532,12 @@ void PCB_IO_EASYEDA_PARSER::ParseToBoardItemContainer(
zone->SetLayer( layer ); zone->SetLayer( layer );
wxString netname = arr[3]; wxString netname = arr[3];
if( IsCopperLayer( layer ) ) if( IsCopperLayer( layer ) )
zone->SetNet( getOrAddNetItem( netname ) ); zone->SetNet( getOrAddNetItem( netname ) );
zone->SetLocalClearance( ConvertSize( arr[5] ) ); zone->SetLocalClearance( ConvertSize( arr[5] ) );
zone->SetThermalReliefGap( zone->GetLocalClearance() ); zone->SetThermalReliefGap( zone->GetLocalClearance().value() );
wxString fillStyle = arr[5]; wxString fillStyle = arr[5];
if( fillStyle == wxS( "none" ) ) if( fillStyle == wxS( "none" ) )

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2007-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2007-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras@wanadoo.fr * Copyright (C) 2019 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -1341,7 +1341,7 @@ void PCB_IO_KICAD_LEGACY::loadFOOTPRINT( FOOTPRINT* aFootprint )
else if( TESTLINE( ".ZoneConnection" ) ) else if( TESTLINE( ".ZoneConnection" ) )
{ {
int tmp = intParse( line + SZ( ".ZoneConnection" ) ); int tmp = intParse( line + SZ( ".ZoneConnection" ) );
aFootprint->SetZoneConnection((ZONE_CONNECTION) tmp ); aFootprint->SetLocalZoneConnection((ZONE_CONNECTION) tmp );
} }
else if( TESTLINE( ".ThermalWidth" ) ) else if( TESTLINE( ".ThermalWidth" ) )
{ {
@ -1554,7 +1554,7 @@ void PCB_IO_KICAD_LEGACY::loadPAD( FOOTPRINT* aFootprint )
else if( TESTLINE( ".ZoneConnection" ) ) else if( TESTLINE( ".ZoneConnection" ) )
{ {
int tmp = intParse( line + SZ( ".ZoneConnection" ) ); int tmp = intParse( line + SZ( ".ZoneConnection" ) );
pad->SetZoneConnection( (ZONE_CONNECTION) tmp ); pad->SetLocalZoneConnection( (ZONE_CONNECTION) tmp );
} }
else if( TESTLINE( ".ThermalWidth" ) ) else if( TESTLINE( ".ThermalWidth" ) )
{ {

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) 2012 CERN * Copyright (C) 2012 CERN
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -1197,34 +1197,34 @@ void PCB_IO_KICAD_SEXPR::format( const FOOTPRINT* aFootprint, int aNestLevel ) c
m_out->Quotew( aFootprint->GetSheetfile() ).c_str() ); m_out->Quotew( aFootprint->GetSheetfile() ).c_str() );
} }
if( aFootprint->GetLocalSolderMaskMargin() != 0 ) if( aFootprint->GetLocalSolderMaskMargin().has_value() )
{ {
m_out->Print( aNestLevel+1, "(solder_mask_margin %s)\n", m_out->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
formatInternalUnits( aFootprint->GetLocalSolderMaskMargin() ).c_str() ); formatInternalUnits( aFootprint->GetLocalSolderMaskMargin().value() ).c_str() );
} }
if( aFootprint->GetLocalSolderPasteMargin() != 0 ) if( aFootprint->GetLocalSolderPasteMargin().has_value() )
{ {
m_out->Print( aNestLevel+1, "(solder_paste_margin %s)\n", m_out->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
formatInternalUnits( aFootprint->GetLocalSolderPasteMargin() ).c_str() ); formatInternalUnits( aFootprint->GetLocalSolderPasteMargin().value() ).c_str() );
} }
if( aFootprint->GetLocalSolderPasteMarginRatio() != 0 ) if( aFootprint->GetLocalSolderPasteMarginRatio().has_value() )
{ {
m_out->Print( aNestLevel+1, "(solder_paste_ratio %s)\n", m_out->Print( aNestLevel+1, "(solder_paste_ratio %s)\n",
FormatDouble2Str( aFootprint->GetLocalSolderPasteMarginRatio() ).c_str() ); FormatDouble2Str( aFootprint->GetLocalSolderPasteMarginRatio().value() ).c_str() );
} }
if( aFootprint->GetLocalClearance() != 0 ) if( aFootprint->GetLocalClearance().has_value() )
{ {
m_out->Print( aNestLevel+1, "(clearance %s)\n", m_out->Print( aNestLevel+1, "(clearance %s)\n",
formatInternalUnits( aFootprint->GetLocalClearance() ).c_str() ); formatInternalUnits( aFootprint->GetLocalClearance().value() ).c_str() );
} }
if( aFootprint->GetZoneConnection() != ZONE_CONNECTION::INHERITED ) if( aFootprint->GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED )
{ {
m_out->Print( aNestLevel+1, "(zone_connect %d)\n", m_out->Print( aNestLevel+1, "(zone_connect %d)\n",
static_cast<int>( aFootprint->GetZoneConnection() ) ); static_cast<int>( aFootprint->GetLocalZoneConnection() ) );
} }
// Attributes // Attributes
@ -1623,34 +1623,34 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad, int aNestLevel ) const
formatInternalUnits( aPad->GetPadToDieLength() ).c_str() ); formatInternalUnits( aPad->GetPadToDieLength() ).c_str() );
} }
if( aPad->GetLocalSolderMaskMargin() != 0 ) if( aPad->GetLocalSolderMaskMargin().has_value() )
{ {
StrPrintf( &output, " (solder_mask_margin %s)", StrPrintf( &output, " (solder_mask_margin %s)",
formatInternalUnits( aPad->GetLocalSolderMaskMargin() ).c_str() ); formatInternalUnits( aPad->GetLocalSolderMaskMargin().value() ).c_str() );
} }
if( aPad->GetLocalSolderPasteMargin() != 0 ) if( aPad->GetLocalSolderPasteMargin().has_value() )
{ {
StrPrintf( &output, " (solder_paste_margin %s)", StrPrintf( &output, " (solder_paste_margin %s)",
formatInternalUnits( aPad->GetLocalSolderPasteMargin() ).c_str() ); formatInternalUnits( aPad->GetLocalSolderPasteMargin().value() ).c_str() );
} }
if( aPad->GetLocalSolderPasteMarginRatio() != 0 ) if( aPad->GetLocalSolderPasteMarginRatio().has_value() )
{ {
StrPrintf( &output, " (solder_paste_margin_ratio %s)", StrPrintf( &output, " (solder_paste_margin_ratio %s)",
FormatDouble2Str( aPad->GetLocalSolderPasteMarginRatio() ).c_str() ); FormatDouble2Str( aPad->GetLocalSolderPasteMarginRatio().value() ).c_str() );
} }
if( aPad->GetLocalClearance() != 0 ) if( aPad->GetLocalClearance().has_value() )
{ {
StrPrintf( &output, " (clearance %s)", StrPrintf( &output, " (clearance %s)",
formatInternalUnits( aPad->GetLocalClearance() ).c_str() ); formatInternalUnits( aPad->GetLocalClearance().value() ).c_str() );
} }
if( aPad->GetZoneConnection() != ZONE_CONNECTION::INHERITED ) if( aPad->GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED )
{ {
StrPrintf( &output, " (zone_connect %d)", StrPrintf( &output, " (zone_connect %d)",
static_cast<int>( aPad->GetZoneConnection() ) ); static_cast<int>( aPad->GetLocalZoneConnection() ) );
} }
if( aPad->GetThermalSpokeWidth() != 0 ) if( aPad->GetThermalSpokeWidth() != 0 )
@ -2275,9 +2275,11 @@ void PCB_IO_KICAD_SEXPR::format( const ZONE* aZone, int aNestLevel ) const
break; break;
} }
m_out->Print( 0, " (clearance %s))\n", formatInternalUnits( aZone->GetLocalClearance() ).c_str() ); m_out->Print( 0, " (clearance %s))\n",
formatInternalUnits( aZone->GetLocalClearance().value() ).c_str() );
m_out->Print( aNestLevel+1, "(min_thickness %s)", formatInternalUnits( aZone->GetMinThickness() ).c_str() ); m_out->Print( aNestLevel+1, "(min_thickness %s)",
formatInternalUnits( aZone->GetMinThickness() ).c_str() );
// We continue to write this for 3rd-party parsers, but we no longer read it (as of V7). // We continue to write this for 3rd-party parsers, but we no longer read it (as of V7).
m_out->Print( 0, " (filled_areas_thickness no)" ); m_out->Print( 0, " (filled_areas_thickness no)" );

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) 2012 CERN. * Copyright (C) 2012 CERN.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -148,7 +148,9 @@ class PCB_IO_KICAD_SEXPR; // forward decl
//#define SEXPR_BOARD_FILE_VERSION 20231014 // V8 file format normalization //#define SEXPR_BOARD_FILE_VERSION 20231014 // V8 file format normalization
//#define SEXPR_BOARD_FILE_VERSION 20231212 // Reference image locking/UUIDs, footprint boolean format //#define SEXPR_BOARD_FILE_VERSION 20231212 // Reference image locking/UUIDs, footprint boolean format
//#define SEXPR_BOARD_FILE_VERSION 20231231 // Use 'uuid' rather than 'id' for generators and groups //#define SEXPR_BOARD_FILE_VERSION 20231231 // Use 'uuid' rather than 'id' for generators and groups
#define SEXPR_BOARD_FILE_VERSION 20240108 // Convert teardrop parameters to explicit bools //#define SEXPR_BOARD_FILE_VERSION 20240108 // Convert teardrop parameters to explicit bools
//----------------- Start of 9.0 development -----------------
#define SEXPR_BOARD_FILE_VERSION 20240201 // Use nullable properties for overrides
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag #define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting #define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting

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) 2012 CERN * Copyright (C) 2012 CERN
* Copyright (C) 2012-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2012-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
@ -4188,30 +4188,47 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
break; break;
case T_solder_mask_margin: case T_solder_mask_margin:
footprint->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin " footprint->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
"value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
footprint->SetLocalSolderMaskMargin( {} );
break; break;
case T_solder_paste_margin: case T_solder_paste_margin:
footprint->SetLocalSolderPasteMargin( parseBoardUnits( "local solder paste margin " footprint->SetLocalSolderPasteMargin( parseBoardUnits( "local solder paste margin value" ) );
"value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
footprint->SetLocalSolderPasteMargin( {} );
break; break;
case T_solder_paste_ratio: case T_solder_paste_margin_ratio:
footprint->SetLocalSolderPasteMarginRatio( parseDouble( "local solder paste margin " footprint->SetLocalSolderPasteMarginRatio( parseDouble( "local solder paste margin ratio value" ) );
"ratio value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
footprint->SetLocalSolderPasteMarginRatio( {} );
break; break;
case T_clearance: case T_clearance:
footprint->SetLocalClearance( parseBoardUnits( "local clearance value" ) ); footprint->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
footprint->SetLocalClearance( {} );
break; break;
case T_zone_connect: case T_zone_connect:
footprint->SetZoneConnection((ZONE_CONNECTION) parseInt( "zone connection value" ) ); footprint->SetLocalZoneConnection((ZONE_CONNECTION) parseInt( "zone connection value" ) );
NeedRIGHT(); NeedRIGHT();
break; break;
@ -4592,8 +4609,7 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent )
// than 0 used to fix a bunch of debug assertions even though it is defined as a // than 0 used to fix a bunch of debug assertions even though it is defined as a
// through hole pad. Wouldn't a though hole pad with no drill be a surface mount // through hole pad. Wouldn't a though hole pad with no drill be a surface mount
// pad (or a conn pad which is a smd pad with no solder paste)? // pad (or a conn pad which is a smd pad with no solder paste)?
if( ( pad->GetAttribute() != PAD_ATTRIB::SMD ) if( pad->GetAttribute() != PAD_ATTRIB::SMD && pad->GetAttribute() != PAD_ATTRIB::CONN )
&& ( pad->GetAttribute() != PAD_ATTRIB::CONN ) )
pad->SetDrillSize( drillSize ); pad->SetDrillSize( drillSize );
else else
pad->SetDrillSize( VECTOR2I( 0, 0 ) ); pad->SetDrillSize( VECTOR2I( 0, 0 ) );
@ -4658,24 +4674,43 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent )
break; break;
case T_solder_mask_margin: case T_solder_mask_margin:
pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) ); pad->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
pad->SetLocalSolderMaskMargin( {} );
break; break;
case T_solder_paste_margin: case T_solder_paste_margin:
pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) ); pad->SetLocalSolderPasteMargin( parseBoardUnits( "local solder paste margin value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
pad->SetLocalSolderPasteMargin( {} );
break; break;
case T_solder_paste_margin_ratio: case T_solder_paste_margin_ratio:
pad->SetLocalSolderPasteMarginRatio( pad->SetLocalSolderPasteMarginRatio( parseDouble( "local solder paste margin ratio value" ) );
parseDouble( "pad local solder paste margin ratio value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
pad->SetLocalSolderPasteMarginRatio( {} );
break; break;
case T_clearance: case T_clearance:
pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) ); pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
NeedRIGHT(); NeedRIGHT();
// In pre-9.0 files "0" meant inherit.
if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
pad->SetLocalClearance( {} );
break; break;
case T_teardrops: case T_teardrops:
@ -4683,7 +4718,7 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent )
break; break;
case T_zone_connect: case T_zone_connect:
pad->SetZoneConnection( (ZONE_CONNECTION) parseInt( "zone connection value" ) ); pad->SetLocalZoneConnection( (ZONE_CONNECTION) parseInt( "zone connection value" ) );
NeedRIGHT(); NeedRIGHT();
break; break;

View File

@ -4,7 +4,7 @@
* Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -295,13 +295,6 @@ bool PCB_TRACK::ApproxCollinear( const PCB_TRACK& aTrack )
} }
int PCB_TRACK::GetLocalClearance( wxString* aSource ) const
{
// Not currently implemented
return 0;
}
MINOPTMAX<int> PCB_TRACK::GetWidthConstraint( wxString* aSource ) const MINOPTMAX<int> PCB_TRACK::GetWidthConstraint( wxString* aSource ) const
{ {
DRC_CONSTRAINT constraint; DRC_CONSTRAINT constraint;

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) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -189,14 +189,6 @@ public:
return wxT( "PCB_TRACK" ); return wxT( "PCB_TRACK" );
} }
/**
* Return any local clearance overrides set in the "classic" (ie: pre-rule) system.
*
* @param aSource [out] optionally reports the source as a user-readable string
* @return int - the clearance in internal units.
*/
int GetLocalClearance( wxString* aSource ) const override;
virtual MINOPTMAX<int> GetWidthConstraint( wxString* aSource = nullptr ) const; virtual MINOPTMAX<int> GetWidthConstraint( wxString* aSource = nullptr ) const;
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override; wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override;

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013-2016 CERN * Copyright (C) 2013-2016 CERN
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* 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
@ -1555,7 +1555,10 @@ void PNS_KICAD_IFACE_BASE::SyncWorld( PNS::NODE *aWorld )
if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) ) if( std::unique_ptr<PNS::SOLID> solid = syncPad( pad ) )
aWorld->Add( std::move( solid ) ); aWorld->Add( std::move( solid ) );
worstClearance = std::max( worstClearance, pad->GetLocalClearance() ); std::optional<int> clearanceOverride = pad->GetClearanceOverrides( nullptr );
if( clearanceOverride.has_value() )
worstClearance = std::max( worstClearance, clearanceOverride.value() );
if( pad->GetProperty() == PAD_PROP::CASTELLATED ) if( pad->GetProperty() == PAD_PROP::CASTELLATED )
{ {

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 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2021 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2024 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
@ -133,7 +133,7 @@ bool TEARDROP_MANAGER::areItemsInSameZone( BOARD_ITEM* aPadOrVia, PCB_TRACK* aTr
PAD *pad = static_cast<PAD*>( aPadOrVia ); PAD *pad = static_cast<PAD*>( aPadOrVia );
if( zone->GetPadConnection() == ZONE_CONNECTION::NONE if( zone->GetPadConnection() == ZONE_CONNECTION::NONE
|| pad->GetZoneConnection() == ZONE_CONNECTION::NONE ) || pad->GetZoneConnectionOverrides( nullptr ) == ZONE_CONNECTION::NONE )
{ {
return false; return false;
} }

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) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-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
@ -782,7 +782,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
r->Report( "" ); r->Report( "" );
reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r ); reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
clearance = zone->GetLocalClearance(); clearance = zone->GetLocalClearance().value();
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Zone clearance: %s." ), r->Report( wxString::Format( _( "Zone clearance: %s." ),
m_frame->StringFromValue( clearance, true ) ) ); m_frame->StringFromValue( clearance, true ) ) );

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) 2014-2017 CERN * Copyright (C) 2014-2017 CERN
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2018-2024 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -2814,7 +2814,12 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
for( FOOTPRINT* footprint : aFrame->GetBoard()->Footprints() ) for( FOOTPRINT* footprint : aFrame->GetBoard()->Footprints() )
{ {
for( PAD* pad : footprint->Pads() ) for( PAD* pad : footprint->Pads() )
m_worstClearance = std::max( m_worstClearance, pad->GetLocalClearance() ); {
std::optional<int> padOverride = pad->GetClearanceOverrides( nullptr );
if( padOverride.has_value() )
m_worstClearance = std::max( m_worstClearance, padOverride.value() );
}
} }
} }
catch( PARSE_ERROR& ) catch( PARSE_ERROR& )

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -486,15 +486,9 @@ bool ZONE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
} }
int ZONE::GetLocalClearance( wxString* aSource ) const std::optional<int> ZONE::GetLocalClearance() const
{ {
if( m_isRuleArea ) return m_isRuleArea ? 0 : m_ZoneClearance;
return 0;
if( aSource )
*aSource = _( "zone" );
return m_ZoneClearance;
} }
@ -1715,7 +1709,7 @@ static struct ZONE_DESC
const wxString groupElectrical = _HKI( "Electrical" ); const wxString groupElectrical = _HKI( "Electrical" );
auto clearanceOverride = new PROPERTY<ZONE, int>( _HKI( "Clearance" ), auto clearanceOverride = new PROPERTY<ZONE, std::optional<int>>( _HKI( "Clearance" ),
&ZONE::SetLocalClearance, &ZONE::GetLocalClearance, &ZONE::SetLocalClearance, &ZONE::GetLocalClearance,
PROPERTY_DISPLAY::PT_SIZE ); PROPERTY_DISPLAY::PT_SIZE );
clearanceOverride->SetAvailableFunc( isCopperZone ); clearanceOverride->SetAvailableFunc( isCopperZone );

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) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -148,16 +148,27 @@ public:
void CacheBoundingBox(); void CacheBoundingBox();
/** /**
* Return any local clearances set in the "classic" (ie: pre-rule) system. These are * @return the zone's clearance in internal units.
* things like zone clearance which are NOT an override. */
std::optional<int> GetLocalClearance() const override;
void SetLocalClearance( std::optional<int> aClearance ) { m_ZoneClearance = aClearance.value(); }
/**
* Return any local clearances set in the "classic" (ie: pre-rule) system.
* *
* @param aSource [out] optionally reports the source as a user-readable string * @param aSource [out] optionally reports the source as a user-readable string.
* @return the clearance in internal units. * @return the clearance in internal units.
*/ */
int GetLocalClearance( wxString* aSource ) const override; std::optional<int> GetLocalClearance( wxString* aSource ) const override
{
if( m_isRuleArea )
return std::optional<int>();
int GetLocalClearance() const { return GetLocalClearance( nullptr ); } if( aSource )
void SetLocalClearance( int aClearance ) { m_ZoneClearance = aClearance; } *aSource = _( "zone" );
return GetLocalClearance();
}
/** /**
* @return true if this zone is on a copper layer, false if on a technical layer. * @return true if this zone is on a copper layer, false if on a technical layer.

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) 2014-2017 CERN * Copyright (C) 2014-2017 CERN
* Copyright (C) 2014-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2014-2024 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Włostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Włostowski <tomasz.wlostowski@cern.ch>
* *
* 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
@ -930,10 +930,10 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
constraint = bds.m_DRCEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, pad, constraint = bds.m_DRCEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, pad,
aZone, aLayer ); aZone, aLayer );
if( constraint.GetValue().Min() > aZone->GetLocalClearance() ) if( constraint.GetValue().Min() > aZone->GetLocalClearance().value() )
padClearance = constraint.GetValue().Min(); padClearance = constraint.GetValue().Min();
else else
padClearance = aZone->GetLocalClearance(); padClearance = aZone->GetLocalClearance().value();
if( pad->FlashLayer( aLayer ) ) if( pad->FlashLayer( aLayer ) )
{ {
@ -1746,7 +1746,7 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE* aZone, PCB_LAYER_ID aLayer,
BOX2I zoneBB = aZone->GetBoundingBox(); BOX2I zoneBB = aZone->GetBoundingBox();
DRC_CONSTRAINT constraint; DRC_CONSTRAINT constraint;
zoneBB.Inflate( std::max( bds.GetBiggestClearanceValue(), aZone->GetLocalClearance() ) ); zoneBB.Inflate( std::max( bds.GetBiggestClearanceValue(), aZone->GetLocalClearance().value() ) );
// Is a point on the boundary of the polygon inside or outside? The boundary may be off by // Is a point on the boundary of the polygon inside or outside? The boundary may be off by
// MaxError, and we add 1.5 mil for some wiggle room. // MaxError, and we add 1.5 mil for some wiggle room.

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-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
@ -132,7 +132,7 @@ ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE& aSource )
{ {
m_ZonePriority = aSource.GetAssignedPriority(); m_ZonePriority = aSource.GetAssignedPriority();
m_FillMode = aSource.GetFillMode(); m_FillMode = aSource.GetFillMode();
m_ZoneClearance = aSource.GetLocalClearance(); m_ZoneClearance = aSource.GetLocalClearance().value();
m_ZoneMinThickness = aSource.GetMinThickness(); m_ZoneMinThickness = aSource.GetMinThickness();
m_HatchThickness = aSource.GetHatchThickness(); m_HatchThickness = aSource.GetHatchThickness();
m_HatchGap = aSource.GetHatchGap(); m_HatchGap = aSource.GetHatchGap();

View File

@ -1,5 +1,5 @@
(footprint "Reverb_BTDR-1V" (footprint "Reverb_BTDR-1V"
(version 20231007) (version 20240201)
(generator pcbnew) (generator pcbnew)
(layer "F.Cu") (layer "F.Cu")
(descr "Digital Reverberation Unit, http://www.belton.co.kr/inc/downfile.php?seq=17&file=pdf (footprint from http://www.uk-electronic.de/PDF/BTDR-1.pdf)") (descr "Digital Reverberation Unit, http://www.belton.co.kr/inc/downfile.php?seq=17&file=pdf (footprint from http://www.uk-electronic.de/PDF/BTDR-1.pdf)")

View File

@ -1,5 +1,5 @@
(footprint "Samtec_HLE-133-02-xx-DV-PE-LC_2x33_P2.54mm_Horizontal" (footprint "Samtec_HLE-133-02-xx-DV-PE-LC_2x33_P2.54mm_Horizontal"
(version 20231007) (version 20240201)
(generator pcbnew) (generator pcbnew)
(layer "F.Cu") (layer "F.Cu")
(descr "Samtec HLE .100\" Tiger Beam Cost-effective Single Beam Socket Strip, HLE-133-02-xx-DV-PE-LC, 33 Pins per row (http://suddendocs.samtec.com/prints/hle-1xx-02-xx-dv-xe-xx-mkt.pdf, http://suddendocs.samtec.com/prints/hle-thru.pdf), generated with kicad-footprint-generator") (descr "Samtec HLE .100\" Tiger Beam Cost-effective Single Beam Socket Strip, HLE-133-02-xx-DV-PE-LC, 33 Pins per row (http://suddendocs.samtec.com/prints/hle-1xx-02-xx-dv-xe-xx-mkt.pdf, http://suddendocs.samtec.com/prints/hle-thru.pdf), generated with kicad-footprint-generator")

View File

@ -1,5 +1,5 @@
(kicad_pcb (kicad_pcb
(version 20231007) (version 20240201)
(generator pcbnew) (generator pcbnew)
(general (general
(thickness 1.6) (thickness 1.6)

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) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-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
@ -42,7 +42,7 @@
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#define CHECK_ENUM_CLASS_EQUAL( L, R ) \ #define CHECK_ENUM_CLASS_EQUAL( L, R ) \
BOOST_CHECK_EQUAL( static_cast<int>( L ), static_cast<int>( R ) ) BOOST_CHECK_EQUAL( static_cast<int>( L ), static_cast<int>( R ) )
@ -349,13 +349,15 @@ void CheckFpPad( const PAD* expected, const PAD* pad )
BOOST_CHECK_EQUAL( expected->GetPinFunction(), pad->GetPinFunction() ); BOOST_CHECK_EQUAL( expected->GetPinFunction(), pad->GetPinFunction() );
BOOST_CHECK_EQUAL( expected->GetPinType(), pad->GetPinType() ); BOOST_CHECK_EQUAL( expected->GetPinType(), pad->GetPinType() );
BOOST_CHECK_EQUAL( expected->GetPadToDieLength(), pad->GetPadToDieLength() ); BOOST_CHECK_EQUAL( expected->GetPadToDieLength(), pad->GetPadToDieLength() );
BOOST_CHECK_EQUAL( expected->GetLocalSolderMaskMargin(), pad->GetLocalSolderMaskMargin() ); BOOST_CHECK_EQUAL( expected->GetLocalSolderMaskMargin().value_or( 0 ),
BOOST_CHECK_EQUAL( expected->GetLocalSolderPasteMargin(), pad->GetLocalSolderMaskMargin().value_or( 0 ) );
pad->GetLocalSolderPasteMargin() ); BOOST_CHECK_EQUAL( expected->GetLocalSolderPasteMargin().value_or( 0 ),
BOOST_CHECK_EQUAL( expected->GetLocalSolderPasteMarginRatio(), pad->GetLocalSolderPasteMargin().value_or( 0 ) );
pad->GetLocalSolderPasteMarginRatio() ); BOOST_CHECK_EQUAL( expected->GetLocalSolderPasteMarginRatio().value_or( 0 ),
BOOST_CHECK_EQUAL( expected->GetLocalClearance(), pad->GetLocalClearance() ); pad->GetLocalSolderPasteMarginRatio().value_or( 0 ) );
CHECK_ENUM_CLASS_EQUAL( expected->GetZoneConnection(), pad->GetZoneConnection() ); BOOST_CHECK_EQUAL( expected->GetLocalClearance().value_or( 0 ),
pad->GetLocalClearance().value_or( 0 ) );
CHECK_ENUM_CLASS_EQUAL( expected->GetLocalZoneConnection(), pad->GetLocalZoneConnection() );
BOOST_CHECK_EQUAL( expected->GetThermalSpokeWidth(), pad->GetThermalSpokeWidth() ); BOOST_CHECK_EQUAL( expected->GetThermalSpokeWidth(), pad->GetThermalSpokeWidth() );
BOOST_CHECK_EQUAL( expected->GetThermalSpokeAngle(), pad->GetThermalSpokeAngle() ); BOOST_CHECK_EQUAL( expected->GetThermalSpokeAngle(), pad->GetThermalSpokeAngle() );
BOOST_CHECK_EQUAL( expected->GetThermalGap(), pad->GetThermalGap() ); BOOST_CHECK_EQUAL( expected->GetThermalGap(), pad->GetThermalGap() );
@ -467,7 +469,8 @@ void CheckFpZone( const ZONE* expected, const ZONE* zone )
BOOST_CHECK_EQUAL( expected->GetNetCode(), zone->GetNetCode() ); BOOST_CHECK_EQUAL( expected->GetNetCode(), zone->GetNetCode() );
BOOST_CHECK_EQUAL( expected->GetAssignedPriority(), zone->GetAssignedPriority() ); BOOST_CHECK_EQUAL( expected->GetAssignedPriority(), zone->GetAssignedPriority() );
CHECK_ENUM_CLASS_EQUAL( expected->GetPadConnection(), zone->GetPadConnection() ); CHECK_ENUM_CLASS_EQUAL( expected->GetPadConnection(), zone->GetPadConnection() );
BOOST_CHECK_EQUAL( expected->GetLocalClearance(), zone->GetLocalClearance() ); BOOST_CHECK_EQUAL( expected->GetLocalClearance().value_or( 0 ),
zone->GetLocalClearance().value_or( 0 ) );
BOOST_CHECK_EQUAL( expected->GetMinThickness(), zone->GetMinThickness() ); BOOST_CHECK_EQUAL( expected->GetMinThickness(), zone->GetMinThickness() );
BOOST_CHECK_EQUAL( expected->GetLayerSet(), zone->GetLayerSet() ); BOOST_CHECK_EQUAL( expected->GetLayerSet(), zone->GetLayerSet() );