kicad2step: fix broken handing of UTF8 filenames.
the conversion between UTF8 std::strings and wxString were missing in some places. 3D model: fix management of file having double ext .stp.gz Fixes #9038 https://gitlab.com/kicad/code/kicad/issues/9038
This commit is contained in:
parent
f6287053e5
commit
4670309ec1
|
@ -406,18 +406,23 @@ std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const no
|
||||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
||||||
{
|
{
|
||||||
wxFileName raw( aFileName );
|
wxFileName raw( aFileName );
|
||||||
wxString ext = raw.GetExt();
|
wxString ext_to_find = raw.GetExt();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// note: plugins only have a lowercase filter within Windows; including an uppercase
|
// note: plugins only have a lowercase filter within Windows; including an uppercase
|
||||||
// filter will result in duplicate file entries and should be avoided.
|
// filter will result in duplicate file entries and should be avoided.
|
||||||
ext.LowerCase();
|
ext_to_find.MakeLower();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// When the extension is .gz, the actual extension should be .stp.gz;
|
||||||
|
// So ensure is ext is the expected extension
|
||||||
|
if( ext_to_find == "gz" && aFileName.Lower().EndsWith( ".stp.gz" ) )
|
||||||
|
ext_to_find = "stp.gz";
|
||||||
|
|
||||||
std::pair < std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator,
|
std::pair < std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator,
|
||||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator > items;
|
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator > items;
|
||||||
|
|
||||||
items = m_ExtMap.equal_range( ext );
|
items = m_ExtMap.equal_range( ext_to_find );
|
||||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
||||||
|
|
||||||
while( sL != items.second )
|
while( sL != items.second )
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
|
|
||||||
#include "plugins/3dapi/ifsg_all.h"
|
#include "plugins/3dapi/ifsg_all.h"
|
||||||
|
|
||||||
|
|
||||||
// log mask for wxLogTrace
|
// log mask for wxLogTrace
|
||||||
#define MASK_OCE "PLUGIN_OCE"
|
#define MASK_OCE "PLUGIN_OCE"
|
||||||
|
|
||||||
|
|
|
@ -600,27 +600,28 @@ bool PCBMODEL::AddPadHole( const KICADPAD* aPad )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PCBMODEL::AddComponent( const std::string& aFileName, const std::string& aRefDes,
|
bool PCBMODEL::AddComponent( const std::string& aFileNameUTF8, const std::string& aRefDes,
|
||||||
bool aBottom, DOUBLET aPosition, double aRotation,
|
bool aBottom, DOUBLET aPosition, double aRotation,
|
||||||
TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale,
|
TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale,
|
||||||
bool aSubstituteModels )
|
bool aSubstituteModels )
|
||||||
{
|
{
|
||||||
if( aFileName.empty() )
|
if( aFileNameUTF8.empty() )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "No model defined for component %s.\n", aRefDes ) );
|
ReportMessage( wxString::Format( "No model defined for component %s.\n", aRefDes ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString fileName( wxString::FromUTF8( aFileNameUTF8 ) );
|
||||||
ReportMessage( wxString::Format( "Add component %s.\n", aRefDes ) );
|
ReportMessage( wxString::Format( "Add component %s.\n", aRefDes ) );
|
||||||
|
|
||||||
// first retrieve a label
|
// first retrieve a label
|
||||||
TDF_Label lmodel;
|
TDF_Label lmodel;
|
||||||
wxString errorMessage;
|
wxString errorMessage;
|
||||||
|
|
||||||
if( !getModelLabel( aFileName, aScale, lmodel, aSubstituteModels, &errorMessage ) )
|
if( !getModelLabel( aFileNameUTF8, aScale, lmodel, aSubstituteModels, &errorMessage ) )
|
||||||
{
|
{
|
||||||
if( errorMessage.IsEmpty() )
|
if( errorMessage.IsEmpty() )
|
||||||
ReportMessage( wxString::Format( "No model for filename '%s'.\n", aFileName ) );
|
ReportMessage( wxString::Format( "No model for filename '%s'.\n", fileName ) );
|
||||||
else
|
else
|
||||||
ReportMessage( errorMessage );
|
ReportMessage( errorMessage );
|
||||||
|
|
||||||
|
@ -632,7 +633,7 @@ bool PCBMODEL::AddComponent( const std::string& aFileName, const std::string& aR
|
||||||
|
|
||||||
if( !getModelLocation( aBottom, aPosition, aRotation, aOffset, aOrientation, toploc ) )
|
if( !getModelLocation( aBottom, aPosition, aRotation, aOffset, aOrientation, toploc ) )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "No location data for filename '%s'.\n", aFileName ) );
|
ReportMessage( wxString::Format( "No location data for filename '%s'.\n", fileName ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +643,7 @@ bool PCBMODEL::AddComponent( const std::string& aFileName, const std::string& aR
|
||||||
if( llabel.IsNull() )
|
if( llabel.IsNull() )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "Could not add component with filename '%s'.\n",
|
ReportMessage( wxString::Format( "Could not add component with filename '%s'.\n",
|
||||||
aFileName ) );
|
fileName ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,10 +979,10 @@ bool PCBMODEL::WriteSTEP( const wxString& aFileName )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel,
|
bool PCBMODEL::getModelLabel( const std::string& aFileNameUTF8, TRIPLET aScale, TDF_Label& aLabel,
|
||||||
bool aSubstituteModels, wxString* aErrorMessage )
|
bool aSubstituteModels, wxString* aErrorMessage )
|
||||||
{
|
{
|
||||||
std::string model_key = aFileName + "_" + std::to_string( aScale.x )
|
std::string model_key = aFileNameUTF8 + "_" + std::to_string( aScale.x )
|
||||||
+ "_" + std::to_string( aScale.y ) + "_" + std::to_string( aScale.z );
|
+ "_" + std::to_string( aScale.y ) + "_" + std::to_string( aScale.z );
|
||||||
|
|
||||||
MODEL_MAP::const_iterator mm = m_models.find( model_key );
|
MODEL_MAP::const_iterator mm = m_models.find( model_key );
|
||||||
|
@ -997,39 +998,42 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
Handle( TDocStd_Document ) doc;
|
Handle( TDocStd_Document ) doc;
|
||||||
m_app->NewDocument( "MDTV-XCAF", doc );
|
m_app->NewDocument( "MDTV-XCAF", doc );
|
||||||
|
|
||||||
FormatType modelFmt = fileType( aFileName.c_str() );
|
wxString fileName( wxString::FromUTF8( aFileNameUTF8 ) );
|
||||||
|
FormatType modelFmt = fileType( aFileNameUTF8.c_str() );
|
||||||
|
|
||||||
switch( modelFmt )
|
switch( modelFmt )
|
||||||
{
|
{
|
||||||
case FMT_IGES:
|
case FMT_IGES:
|
||||||
if( !readIGES( doc, aFileName.c_str() ) )
|
if( !readIGES( doc, aFileNameUTF8.c_str() ) )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "readIGES() failed on filename '%s'.\n", aFileName ) );
|
ReportMessage( wxString::Format( "readIGES() failed on filename '%s'.\n", fileName ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FMT_STEP:
|
case FMT_STEP:
|
||||||
if( !readSTEP( doc, aFileName.c_str() ) )
|
if( !readSTEP( doc, aFileNameUTF8.c_str() ) )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n", aFileName ) );
|
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n", fileName ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FMT_STEPZ:
|
case FMT_STEPZ:
|
||||||
{
|
{
|
||||||
wxFFileInputStream ifile( aFileName );
|
// To export a compressed step file (.stpz or .stp.gz file), the best way is to
|
||||||
wxFileName outFile( aFileName );
|
// decaompress it in a temporaty file and load this temporary file
|
||||||
|
wxFFileInputStream ifile( fileName );
|
||||||
|
wxFileName outFile( fileName );
|
||||||
|
|
||||||
outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
|
outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
|
||||||
outFile.SetExt( "STEP" );
|
outFile.SetExt( "step" );
|
||||||
|
|
||||||
wxFileOffset size = ifile.GetLength();
|
wxFileOffset size = ifile.GetLength();
|
||||||
|
|
||||||
if( size == wxInvalidOffset )
|
if( size == wxInvalidOffset )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "readSTEP() failed on filename '%s'.\n", aFileName ) );
|
ReportMessage( wxString::Format( "getModelLabel() failed on filename '%s'.\n",
|
||||||
|
fileName ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1052,6 +1056,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
{
|
{
|
||||||
|
ReportMessage( wxString::Format( "failed to decompress '%s'.\n", fileName ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( expanded.empty() )
|
if( expanded.empty() )
|
||||||
|
@ -1075,6 +1080,12 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
ofile.Close();
|
ofile.Close();
|
||||||
|
|
||||||
|
if( success )
|
||||||
|
{
|
||||||
|
std::string altFileNameUTF8 = outFile.GetFullPath().utf8_string();
|
||||||
|
success = getModelLabel( altFileNameUTF8, TRIPLET( 1.0, 1.0, 1.0 ), aLabel, false );
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1093,7 +1104,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
*/
|
*/
|
||||||
if( aSubstituteModels )
|
if( aSubstituteModels )
|
||||||
{
|
{
|
||||||
wxFileName wrlName( aFileName );
|
wxFileName wrlName( fileName );
|
||||||
|
|
||||||
wxString basePath = wrlName.GetPath();
|
wxString basePath = wrlName.GetPath();
|
||||||
wxString baseName = wrlName.GetName();
|
wxString baseName = wrlName.GetName();
|
||||||
|
@ -1114,6 +1125,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
alts.Add( "stpZ" );
|
alts.Add( "stpZ" );
|
||||||
alts.Add( "STPZ" );
|
alts.Add( "STPZ" );
|
||||||
alts.Add( "step.gz" );
|
alts.Add( "step.gz" );
|
||||||
|
alts.Add( "stp.gz" );
|
||||||
|
|
||||||
// IGES files
|
// IGES files
|
||||||
alts.Add( "iges" );
|
alts.Add( "iges" );
|
||||||
|
@ -1129,7 +1141,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
|
|
||||||
if( altFile.IsOk() && altFile.FileExists() )
|
if( altFile.IsOk() && altFile.FileExists() )
|
||||||
{
|
{
|
||||||
std::string altFileName = altFile.GetFullPath().ToStdString();
|
std::string altFileNameUTF8 = altFile.GetFullPath().utf8_string();
|
||||||
|
|
||||||
// When substituting a STEP/IGS file for VRML, do not apply the VRML scaling
|
// When substituting a STEP/IGS file for VRML, do not apply the VRML scaling
|
||||||
// to the new STEP model. This process of auto-substitution is janky as all
|
// to the new STEP model. This process of auto-substitution is janky as all
|
||||||
|
@ -1138,7 +1150,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
// named "model.wrl" and "model.stp" referring to different parts.
|
// named "model.wrl" and "model.stp" referring to different parts.
|
||||||
// TODO: Fix model handling in v7. Default models should only be STP.
|
// TODO: Fix model handling in v7. Default models should only be STP.
|
||||||
// Have option to override this in DISPLAY.
|
// Have option to override this in DISPLAY.
|
||||||
if( getModelLabel( altFileName, TRIPLET( 1.0, 1.0, 1.0 ), aLabel, false ) )
|
if( getModelLabel( altFileNameUTF8, TRIPLET( 1.0, 1.0, 1.0 ), aLabel, false ) )
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1168,13 +1180,13 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_
|
||||||
if( aLabel.IsNull() )
|
if( aLabel.IsNull() )
|
||||||
{
|
{
|
||||||
ReportMessage( wxString::Format( "Could not transfer model data from file '%s'.\n",
|
ReportMessage( wxString::Format( "Could not transfer model data from file '%s'.\n",
|
||||||
aFileName ) );
|
fileName ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach the PART NAME ( base filename: note that in principle
|
// attach the PART NAME ( base filename: note that in principle
|
||||||
// different models may have the same base filename )
|
// different models may have the same base filename )
|
||||||
wxFileName afile( aFileName.c_str() );
|
wxFileName afile( fileName );
|
||||||
std::string pname( afile.GetName().ToUTF8() );
|
std::string pname( afile.GetName().ToUTF8() );
|
||||||
TCollection_ExtendedString partname( pname.c_str() );
|
TCollection_ExtendedString partname( pname.c_str() );
|
||||||
TDataStd_Name::Set( aLabel, partname );
|
TDataStd_Name::Set( aLabel, partname );
|
||||||
|
|
|
@ -125,15 +125,16 @@ private:
|
||||||
/**
|
/**
|
||||||
* Load a 3D model data.
|
* Load a 3D model data.
|
||||||
*
|
*
|
||||||
* @param aFileName is the filename (different formats allowed) but for WRML files a model
|
* @param aFileNameUTF8 is the filename encoded UTF8 (different formats allowed)
|
||||||
* data can be loaded instead of the vrml data, not suitable in a step file.
|
* but for WRML files a model data can be loaded instead of the vrml data,
|
||||||
|
* not suitable in a step file.
|
||||||
* @param aScale is the X,Y,Z scaling factors.
|
* @param aScale is the X,Y,Z scaling factors.
|
||||||
* @param aLabel is the TDF_Label to store the data.
|
* @param aLabel is the TDF_Label to store the data.
|
||||||
* @param aSubstituteModels = true to allows data substitution, false to disallow.
|
* @param aSubstituteModels = true to allows data substitution, false to disallow.
|
||||||
* @param aErrorMessage (can be nullptr) is an error message to be displayed on error.
|
* @param aErrorMessage (can be nullptr) is an error message to be displayed on error.
|
||||||
* @return true if successfully loaded, false on error.
|
* @return true if successfully loaded, false on error.
|
||||||
*/
|
*/
|
||||||
bool getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_Label& aLabel,
|
bool getModelLabel( const std::string& aFileNameUTF8, TRIPLET aScale, TDF_Label& aLabel,
|
||||||
bool aSubstituteModels, wxString* aErrorMessage = nullptr );
|
bool aSubstituteModels, wxString* aErrorMessage = nullptr );
|
||||||
|
|
||||||
bool getModelLocation( bool aBottom, DOUBLET aPosition, double aRotation, TRIPLET aOffset,
|
bool getModelLocation( bool aBottom, DOUBLET aPosition, double aRotation, TRIPLET aOffset,
|
||||||
|
|
Loading…
Reference in New Issue