Browse Source

Add new DRC expression function isMemberOfSheetOrChildren

This allows the multichannel tool to search for footprints that are in nested
hierarchical sheets.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20339
revert-0c36e162
JamesJCode 9 months ago
parent
commit
4a99a3060d
  1. 18
      pcbnew/dialogs/panel_setup_rules_help_8expression_functions.h
  2. 5
      pcbnew/dialogs/panel_setup_rules_help_8expression_functions.md
  3. 64
      pcbnew/pcbexpr_functions.cpp
  4. 4
      pcbnew/tools/multichannel_tool.cpp

18
pcbnew/dialogs/panel_setup_rules_help_8expression_functions.h

@ -7,7 +7,8 @@ _HKI( "### Expression functions\n"
" A.enclosedByArea('<zone_name>')\n"
"True if all of `A` lies within the given zone's outline.\n"
"\n"
"NB: this is potentially a more expensive call than `intersectsArea()`. Use `intersectsArea()`\n"
"NB: this is potentially a more expensive call than `intersectsArea()`. Use "
"`intersectsArea()`\n"
"where possible.\n"
"<br><br>\n"
"\n"
@ -38,7 +39,8 @@ _HKI( "### Expression functions\n"
"<br><br>\n"
"\n"
" A.hasNetclass('<netclass_name>')\n"
"True if `A` has had the given netclass assigned to it, either by an explicit netclass label\n"
"True if `A` has had the given netclass assigned to it, either by an explicit netclass "
"label\n"
"or through a pattern match assignment.\n"
"<br><br>\n"
"\n"
@ -98,11 +100,19 @@ _HKI( "### Expression functions\n"
"\n"
" A.memberOfFootprint('<footprint_identifier>')\n"
"True if `A` is a member of a given footprint (for example, a pad or graphic shape defined\n"
"inside that footprint). The various ways of specifying `footprint_identifier` are described above.\n"
"inside that footprint). The various ways of specifying `footprint_identifier` are "
"described above.\n"
"<br><br>\n"
"\n"
" A.memberOfSheet('<sheet_path>')\n"
"True if `A` is a member of the given schematic sheet. The sheet path can contain wildcards.\n"
"True if `A` is a member of the given schematic sheet. The sheet path can contain "
"wildcards.\n"
"<br><br>\n"
"\n"
" A.memberOfSheetOrChildren('<sheet_path>')\n"
"True if `A` is a member of the given schematic sheet, or any of its child hierarchical "
"sheets. The sheet path can \n"
"contain wildcards.\n"
"<br><br>\n"
"\n"
"" );

5
pcbnew/dialogs/panel_setup_rules_help_8expression_functions.md

@ -102,5 +102,10 @@ inside that footprint). The various ways of specifying `footprint_identifier` a
A.memberOfSheet('<sheet_path>')
True if `A` is a member of the given schematic sheet. The sheet path can contain wildcards.
<br><br>
A.memberOfSheetOrChildren('<sheet_path>')
True if `A` is a member of the given schematic sheet, or any of its child hierarchical sheets. The sheet path can
contain wildcards.
<br><br>

64
pcbnew/pcbexpr_functions.cpp

@ -995,6 +995,69 @@ static void memberOfSheetFunc( LIBEVAL::CONTEXT* aCtx, void* self )
}
static void memberOfSheetOrChildrenFunc( LIBEVAL::CONTEXT* aCtx, void* self )
{
LIBEVAL::VALUE* arg = aCtx->Pop();
LIBEVAL::VALUE* result = aCtx->AllocValue();
result->Set( 0.0 );
aCtx->Push( result );
if( !arg || arg->AsString().IsEmpty() )
{
if( aCtx->HasErrorCallback() )
aCtx->ReportError( MISSING_SHEET_ARG( wxT( "memberOfSheetOrChildren()" ) ) );
return;
}
PCBEXPR_VAR_REF* vref = static_cast<PCBEXPR_VAR_REF*>( self );
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
if( !item )
return;
result->SetDeferredEval(
[item, arg]() -> double
{
FOOTPRINT* fp = item->GetParentFootprint();
if( !fp && item->Type() == PCB_FOOTPRINT_T )
fp = static_cast<FOOTPRINT*>( item );
if( !fp )
return 0.0;
wxString sheetName = fp->GetSheetname();
wxString refName = arg->AsString();
if( sheetName.EndsWith( wxT( "/" ) ) )
sheetName.RemoveLast();
if( refName.EndsWith( wxT( "/" ) ) )
refName.RemoveLast();
wxArrayString sheetPath = wxSplit( sheetName, '/' );
wxArrayString refPath = wxSplit( refName, '/' );
if( refPath.size() > sheetPath.size() )
return 0.0;
if( ( refName.Matches( wxT( "/" ) ) || refName.IsEmpty() ) && sheetName.IsEmpty() )
{
return 1.0;
}
for( size_t i = 0; i < refPath.size(); i++ )
{
if( !sheetPath[i].Matches( refPath[i] ) )
return 0.0;
}
return 1.0;
} );
}
#define MISSING_REF_ARG( f ) \
wxString::Format( _( "Missing footprint argument (reference designator) to %s." ), f )
@ -1316,6 +1379,7 @@ void PCBEXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions()
RegisterFunc( wxT( "memberOfGroup('x')" ), memberOfGroupFunc );
RegisterFunc( wxT( "memberOfFootprint('x')" ), memberOfFootprintFunc );
RegisterFunc( wxT( "memberOfSheet('x')" ), memberOfSheetFunc );
RegisterFunc( wxT( "memberOfSheetOrChildren('x')" ), memberOfSheetOrChildrenFunc );
RegisterFunc( wxT( "fromTo('x','y')" ), fromToFunc );
RegisterFunc( wxT( "isCoupledDiffPair()" ), isCoupledDiffPairFunc );

4
pcbnew/tools/multichannel_tool.cpp

@ -99,8 +99,8 @@ bool MULTICHANNEL_TOOL::identifyComponentsInRuleArea( ZONE* aRul
{
case RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME:
{
ruleText =
wxT( "A.memberOfSheet('" ) + aRuleArea->GetRuleAreaPlacementSource() + wxT( "')" );
ruleText = wxT( "A.memberOfSheetOrChildren('" ) + aRuleArea->GetRuleAreaPlacementSource()
+ wxT( "')" );
break;
}
case RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS:

Loading…
Cancel
Save