diff --git a/bitmap2component/bitmap2component.cpp b/bitmap2component/bitmap2component.cpp index 703f8763b5..723edfc4de 100644 --- a/bitmap2component/bitmap2component.cpp +++ b/bitmap2component/bitmap2component.cpp @@ -226,14 +226,14 @@ void BITMAPCONV_INFO::outputDataHeader( const char * aBrdLayerName ) strbuf = fmt::format( " (fp_text reference \"G***\" (at 0 0) (layer \"{}\")\n" " (effects (font (size 1.5 1.5) (thickness 0.3)))\n" - " (tstamp {})\n )\n", + " (uuid {})\n )\n", aBrdLayerName, KIID().AsString().ToStdString().c_str() ); m_Data += strbuf; strbuf = fmt::format( " (fp_text value \"{}\" (at 0.75 0) (layer \"{}\") hide\n" " (effects (font (size 1.5 1.5) (thickness 0.3)))\n" - " (tstamp {})\n )\n", + " (uuid {})\n )\n", m_CmpName.c_str(), aBrdLayerName, KIID().AsString().ToStdString().c_str() ); m_Data += strbuf; @@ -370,7 +370,7 @@ void BITMAPCONV_INFO::outputOnePolygon( SHAPE_LINE_CHAIN& aPolygon, const char* m_Data += " )\n\n"; strbuf = fmt::format( - " (stroke (width {:f}) (type solid)) (fill solid) (layer \"{}\") (tstamp {}))\n", + " (stroke (width {:f}) (type solid)) (fill solid) (layer \"{}\") (uuid {}))\n", width, aBrdLayerName, KIID().AsString().ToStdString().c_str() ); m_Data += strbuf; diff --git a/common/pcb.keywords b/common/pcb.keywords index 9dda19a02d..7697157f33 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -330,6 +330,7 @@ user user_diff_pair user_trace_width user_via +uuid uvia_dia uvia_drill uvia_min_drill diff --git a/common/plugins/kicad/kicad_plugin_utils.cpp b/common/plugins/kicad/kicad_plugin_utils.cpp index e9611720c0..cf847a6295 100644 --- a/common/plugins/kicad/kicad_plugin_utils.cpp +++ b/common/plugins/kicad/kicad_plugin_utils.cpp @@ -17,8 +17,10 @@ * with this program. If not, see . */ -#include +#include #include +#include +#include namespace KICAD_FORMAT { @@ -28,4 +30,13 @@ void FormatBool( OUTPUTFORMATTER* aOut, int aNestLevel, const wxString& aKey, bo aOut->Print( aNestLevel, "(%ls %s)%c", aKey.wc_str(), aValue ? "yes" : "no", aSuffix ); } + +void FormatUuid( OUTPUTFORMATTER* aOut, const KIID& aUuid, char aSuffix ) +{ + if( aSuffix ) + aOut->Print( 0, "(uuid \"%s\")%c", TO_UTF8( aUuid.AsString() ), aSuffix ); + else + aOut->Print( 0, "(uuid \"%s\")", TO_UTF8( aUuid.AsString() ) ); +} + } // namespace KICAD_FORMAT diff --git a/include/plugins/kicad/kicad_plugin_utils.h b/include/plugins/kicad/kicad_plugin_utils.h index 957391f914..ec2e1f78f0 100644 --- a/include/plugins/kicad/kicad_plugin_utils.h +++ b/include/plugins/kicad/kicad_plugin_utils.h @@ -23,6 +23,7 @@ #include class OUTPUTFORMATTER; +class KIID; namespace KICAD_FORMAT { @@ -38,6 +39,8 @@ namespace KICAD_FORMAT { void FormatBool( OUTPUTFORMATTER* aOut, int aNestLevel, const wxString& aKey, bool aValue, char aSuffix = '\n' ); +void FormatUuid( OUTPUTFORMATTER* aOut, const KIID& aUuid, char aSuffix = '\n' ); + } // namespace KICAD_FORMAT #endif //KICAD_PLUGIN_UTILS_H diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index 31cf430729..7055176a8a 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -2900,6 +2900,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE( BOARD_ITEM* aParent ) } case T_tstamp: + case T_uuid: NextTok(); const_cast( shape->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -2957,7 +2958,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE( BOARD_ITEM* aParent ) break; default: - Expecting( "layer, width, fill, tstamp, locked, net or status" ); + Expecting( "layer, width, fill, tstamp, uuid, locked, net or status" ); } } @@ -3191,6 +3192,7 @@ void PCB_PARSER::parsePCB_TEXT_effects( PCB_TEXT* aText ) break; case T_tstamp: + case T_uuid: NextTok(); const_cast( aText->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -3205,7 +3207,7 @@ void PCB_PARSER::parsePCB_TEXT_effects( PCB_TEXT* aText ) if( parentFP ) aText->SetVisible( !hide ); else - Expecting( "layer, effects, locked, render_cache or tstamp" ); + Expecting( "layer, effects, locked, render_cache, uuid or tstamp" ); break; } @@ -3352,6 +3354,7 @@ PCB_TEXTBOX* PCB_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) break; case T_tstamp: + case T_uuid: NextTok(); const_cast( textbox->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -3366,7 +3369,7 @@ PCB_TEXTBOX* PCB_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) break; default: - Expecting( "angle, width, layer, effects, render_cache or tstamp" ); + Expecting( "angle, width, layer, effects, render_cache, uuid or tstamp" ); } } @@ -3454,6 +3457,7 @@ PCB_DIMENSION_BASE* PCB_PARSER::parseDIMENSION( BOARD_ITEM* aParent ) break; case T_tstamp: + case T_uuid: NextTok(); const_cast( dim->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -3803,7 +3807,7 @@ PCB_DIMENSION_BASE* PCB_PARSER::parseDIMENSION( BOARD_ITEM* aParent ) } default: - Expecting( "layer, tstamp, gr_text, feature1, feature2, crossbar, arrow1a, " + Expecting( "layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, " "arrow1b, arrow2a, or arrow2b" ); } } @@ -3914,6 +3918,7 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments break; case T_tstamp: + case T_uuid: NextTok(); const_cast( footprint->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -4254,7 +4259,7 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments break; default: - Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, " + Expecting( "locked, placed, tedit, tstamp, uuid, at, descr, tags, path, " "autoplace_cost90, autoplace_cost180, solder_mask_margin, " "solder_paste_margin, solder_paste_ratio, clearance, " "zone_connect, thermal_gap, attr, fp_text, " @@ -4769,6 +4774,7 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent ) break; case T_tstamp: + case T_uuid: NextTok(); const_cast( pad->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -4776,7 +4782,7 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent ) default: Expecting( "at, locked, drill, layers, net, die_length, roundrect_rratio, " - "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, " + "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, " "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, " "pinfunction, pintype, zone_connect, thermal_width, thermal_gap or " "teardrops" ); @@ -5181,6 +5187,7 @@ PCB_ARC* PCB_PARSER::parseARC() break; case T_tstamp: + case T_uuid: NextTok(); const_cast( arc->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -5197,7 +5204,7 @@ PCB_ARC* PCB_PARSER::parseARC() break; default: - Expecting( "start, mid, end, width, layer, net, tstamp, or status" ); + Expecting( "start, mid, end, width, layer, net, tstamp, uuid, or status" ); } } @@ -5265,6 +5272,7 @@ PCB_TRACK* PCB_PARSER::parsePCB_TRACK() break; case T_tstamp: + case T_uuid: NextTok(); const_cast( track->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -5281,7 +5289,7 @@ PCB_TRACK* PCB_PARSER::parsePCB_TRACK() break; default: - Expecting( "start, end, width, layer, net, tstamp, or locked" ); + Expecting( "start, end, width, layer, net, tstamp, uuid, or locked" ); } } @@ -5406,6 +5414,7 @@ PCB_VIA* PCB_PARSER::parsePCB_VIA() break; case T_tstamp: + case T_uuid: NextTok(); const_cast( via->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -5426,7 +5435,7 @@ PCB_VIA* PCB_PARSER::parsePCB_VIA() break; default: - Expecting( "blind, micro, at, size, drill, layers, net, free, tstamp, status or " + Expecting( "blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or " "teardrops" ); } } @@ -5510,6 +5519,7 @@ ZONE* PCB_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent ) break; case T_tstamp: + case T_uuid: NextTok(); const_cast( zone->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); @@ -5967,7 +5977,7 @@ ZONE* PCB_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent ) default: Expecting( "net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, " - "fill, polygon, filled_polygon, fill_segments, attr, locked, or name" ); + "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" ); } } @@ -6143,13 +6153,14 @@ PCB_TARGET* PCB_PARSER::parsePCB_TARGET() break; case T_tstamp: + case T_uuid: NextTok(); const_cast( target->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); break; default: - Expecting( "x, plus, at, size, width, layer or tstamp" ); + Expecting( "x, plus, at, size, width, layer, uuid, or tstamp" ); } } @@ -6160,15 +6171,20 @@ PCB_TARGET* PCB_PARSER::parsePCB_TARGET() KIID PCB_PARSER::CurStrToKIID() { KIID aId; + std::string idStr( CurStr() ); + + // Older files did not quote UUIDs + if( *idStr.begin() == '"' && *idStr.rbegin() == '"' ) + idStr = idStr.substr( 1, idStr.length() - 1 ); if( m_appendToExisting ) { aId = KIID(); - m_resetKIIDMap.insert( std::make_pair( CurStr(), aId ) ); + m_resetKIIDMap.insert( std::make_pair( idStr, aId ) ); } else { - aId = KIID( CurStr() ); + aId = KIID( idStr ); } return aId; diff --git a/pcbnew/plugins/kicad/pcb_plugin.cpp b/pcbnew/plugins/kicad/pcb_plugin.cpp index 0ea59be2f7..8406791417 100644 --- a/pcbnew/plugins/kicad/pcb_plugin.cpp +++ b/pcbnew/plugins/kicad/pcb_plugin.cpp @@ -857,9 +857,7 @@ void PCB_PLUGIN::format( const PCB_DIMENSION_BASE* aDimension, int aNestLevel ) formatLayer( aDimension->GetLayer() ); - m_out->Print( 0, " (tstamp %s)", TO_UTF8( aDimension->m_Uuid.AsString() ) ); - - m_out->Print( 0, "\n" ); + KICAD_FORMAT::FormatUuid( m_out, aDimension->m_Uuid ); m_out->Print( aNestLevel+1, "(pts (xy %s %s) (xy %s %s))\n", formatInternalUnits( aDimension->GetStart().x ).c_str(), @@ -1019,7 +1017,7 @@ void PCB_PLUGIN::format( const PCB_SHAPE* aShape, int aNestLevel ) const if( aShape->GetNetCode() > 0 ) m_out->Print( 0, " (net %d)", m_mapping->Translate( aShape->GetNetCode() ) ); - m_out->Print( 0, " (tstamp %s)", TO_UTF8( aShape->m_Uuid.AsString() ) ); + KICAD_FORMAT::FormatUuid( m_out, aShape->m_Uuid, 0 ); m_out->Print( 0, ")\n" ); } @@ -1079,7 +1077,7 @@ void PCB_PLUGIN::format( const PCB_TARGET* aTarget, int aNestLevel ) const formatLayer( aTarget->GetLayer() ); - m_out->Print( 0, " (tstamp %s)", TO_UTF8( aTarget->m_Uuid.AsString() ) ); + KICAD_FORMAT::FormatUuid( m_out, aTarget->m_Uuid, 0 ); m_out->Print( 0, ")\n" ); } @@ -1124,8 +1122,8 @@ void PCB_PLUGIN::format( const FOOTPRINT* aFootprint, int aNestLevel ) const m_out->Print( 0, "\n" ); - if( !( m_ctl & CTL_OMIT_TSTAMPS ) ) - m_out->Print( aNestLevel+1, "(tstamp %s)\n", TO_UTF8( aFootprint->m_Uuid.AsString() ) ); + if( !( m_ctl & CTL_OMIT_UUIDS ) ) + KICAD_FORMAT::FormatUuid( m_out, aFootprint->m_Uuid ); if( !( m_ctl & CTL_OMIT_AT ) ) { @@ -1802,8 +1800,7 @@ void PCB_PLUGIN::format( const PAD* aPad, int aNestLevel ) const } m_out->Print( 0, "\n" ); - m_out->Print( aNestLevel + 1, "(tstamp %s)", TO_UTF8( aPad->m_Uuid.AsString() ) ); - m_out->Print( 0, "\n" ); + KICAD_FORMAT::FormatUuid( m_out, aPad->m_Uuid ); m_out->Print( aNestLevel, ")\n" ); } @@ -1858,9 +1855,7 @@ void PCB_PLUGIN::format( const PCB_TEXT* aText, int aNestLevel ) const if( parentFP && !aText->IsVisible() ) KICAD_FORMAT::FormatBool( m_out, 0, "hide", !aText->IsVisible() ); - m_out->Print( 0, " (tstamp %s)", TO_UTF8( aText->m_Uuid.AsString() ) ); - - m_out->Print( 0, "\n" ); + KICAD_FORMAT::FormatUuid( m_out, aText->m_Uuid ); aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl | CTL_OMIT_HIDE ); @@ -1915,9 +1910,7 @@ void PCB_PLUGIN::format( const PCB_TEXTBOX* aTextBox, int aNestLevel ) const formatLayer( aTextBox->GetLayer() ); m_out->Print( 0, "\n" ); - m_out->Print( aNestLevel + 1, "(tstamp %s)", TO_UTF8( aTextBox->m_Uuid.AsString() ) ); - - m_out->Print( 0, "\n" ); + KICAD_FORMAT::FormatUuid( m_out, aTextBox->m_Uuid ); // PCB_TEXTBOXes are never hidden, so always omit "hide" attribute aTextBox->EDA_TEXT::Format( m_out, aNestLevel, m_ctl | CTL_OMIT_HIDE ); @@ -1939,7 +1932,7 @@ void PCB_PLUGIN::format( const PCB_GROUP* aGroup, int aNestLevel ) const if( aGroup->GetItems().empty() ) return; - m_out->Print( aNestLevel, "(group %s (id %s)\n", + m_out->Print( aNestLevel, "(group %s (id \"%s\")\n", m_out->Quotew( aGroup->GetName() ).c_str(), TO_UTF8( aGroup->m_Uuid.AsString() ) ); @@ -1956,7 +1949,7 @@ void PCB_PLUGIN::format( const PCB_GROUP* aGroup, int aNestLevel ) const memberIds.Sort(); for( const wxString& memberId : memberIds ) - m_out->Print( aNestLevel + 2, "%s\n", TO_UTF8( memberId ) ); + m_out->Print( aNestLevel + 2, "\"%s\"\n", TO_UTF8( memberId ) ); m_out->Print( aNestLevel + 1, ")\n" ); // Close `members` token. m_out->Print( aNestLevel, ")\n" ); // Close `group` token. @@ -2172,7 +2165,7 @@ void PCB_PLUGIN::format( const PCB_TRACK* aTrack, int aNestLevel ) const m_out->Print( 0, " (net %d)", m_mapping->Translate( aTrack->GetNetCode() ) ); - m_out->Print( 0, " (tstamp %s)", TO_UTF8( aTrack->m_Uuid.AsString() ) ); + KICAD_FORMAT::FormatUuid( m_out, aTrack->m_Uuid ); m_out->Print( 0, ")\n" ); } @@ -2203,7 +2196,7 @@ void PCB_PLUGIN::format( const ZONE* aZone, int aNestLevel ) const formatLayer( aZone->GetFirstLayer() ); } - m_out->Print( 0, " (tstamp %s)", TO_UTF8( aZone->m_Uuid.AsString() ) ); + KICAD_FORMAT::FormatUuid( m_out, aZone->m_Uuid ); if( !aZone->GetZoneName().empty() ) m_out->Print( 0, " (name %s)", m_out->Quotew( aZone->GetZoneName() ).c_str() ); diff --git a/pcbnew/plugins/kicad/pcb_plugin.h b/pcbnew/plugins/kicad/pcb_plugin.h index 9d3dcfa4c4..90e63e6a61 100644 --- a/pcbnew/plugins/kicad/pcb_plugin.h +++ b/pcbnew/plugins/kicad/pcb_plugin.h @@ -152,7 +152,7 @@ class PCB_PLUGIN; // forward decl #define FIRST_NORMALIZED_VERISON 20230924 ///< Earlier files did not have normalized bools #define CTL_OMIT_PAD_NETS (1 << 1) ///< Omit pads net names (useless in library) -#define CTL_OMIT_TSTAMPS (1 << 2) ///< Omit component time stamp (useless in library) +#define CTL_OMIT_UUIDS (1 << 2) ///< Omit component unique ids (useless in library) #define CTL_OMIT_INITIAL_COMMENTS (1 << 3) ///< omit FOOTPRINT initial comments #define CTL_OMIT_PATH (1 << 4) ///< Omit component sheet time stamp (useless in library) #define CTL_OMIT_AT (1 << 5) ///< Omit position and rotation. (always saved @@ -170,7 +170,7 @@ class PCB_PLUGIN; // forward decl /// Format output for a footprint library instead of clipboard or BOARD #define CTL_FOR_LIBRARY \ - ( CTL_OMIT_PAD_NETS | CTL_OMIT_TSTAMPS | CTL_OMIT_PATH | CTL_OMIT_AT | CTL_OMIT_LIBNAME ) + ( CTL_OMIT_PAD_NETS | CTL_OMIT_UUIDS | CTL_OMIT_PATH | CTL_OMIT_AT | CTL_OMIT_LIBNAME ) /// The zero arg constructor when PCB_PLUGIN is used for PLUGIN::Load() and PLUGIN::Save()ing /// a BOARD file underneath IO_MGR.