diff --git a/3d-viewer/3d_cache/3d_plugin_manager.cpp b/3d-viewer/3d_cache/3d_plugin_manager.cpp index 0e47dbdec9..995667067e 100644 --- a/3d-viewer/3d_cache/3d_plugin_manager.cpp +++ b/3d-viewer/3d_cache/3d_plugin_manager.cpp @@ -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 ) { wxFileName raw( aFileName ); - wxString ext = raw.GetExt(); + wxString ext_to_find = raw.GetExt(); #ifdef _WIN32 // note: plugins only have a lowercase filter within Windows; including an uppercase // filter will result in duplicate file entries and should be avoided. - ext.LowerCase(); + ext_to_find.MakeLower(); #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::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; while( sL != items.second ) diff --git a/plugins/3d/oce/loadmodel.cpp b/plugins/3d/oce/loadmodel.cpp index 0aae47134f..68507ddaac 100644 --- a/plugins/3d/oce/loadmodel.cpp +++ b/plugins/3d/oce/loadmodel.cpp @@ -76,6 +76,7 @@ #include "plugins/3dapi/ifsg_all.h" + // log mask for wxLogTrace #define MASK_OCE "PLUGIN_OCE" diff --git a/utils/kicad2step/pcb/oce_utils.cpp b/utils/kicad2step/pcb/oce_utils.cpp index 70e1a9bd46..b62e72cb60 100644 --- a/utils/kicad2step/pcb/oce_utils.cpp +++ b/utils/kicad2step/pcb/oce_utils.cpp @@ -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, TRIPLET aOffset, TRIPLET aOrientation, TRIPLET aScale, bool aSubstituteModels ) { - if( aFileName.empty() ) + if( aFileNameUTF8.empty() ) { ReportMessage( wxString::Format( "No model defined for component %s.\n", aRefDes ) ); return false; } + wxString fileName( wxString::FromUTF8( aFileNameUTF8 ) ); ReportMessage( wxString::Format( "Add component %s.\n", aRefDes ) ); // first retrieve a label TDF_Label lmodel; wxString errorMessage; - if( !getModelLabel( aFileName, aScale, lmodel, aSubstituteModels, &errorMessage ) ) + if( !getModelLabel( aFileNameUTF8, aScale, lmodel, aSubstituteModels, &errorMessage ) ) { if( errorMessage.IsEmpty() ) - ReportMessage( wxString::Format( "No model for filename '%s'.\n", aFileName ) ); + ReportMessage( wxString::Format( "No model for filename '%s'.\n", fileName ) ); else 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 ) ) { - ReportMessage( wxString::Format( "No location data for filename '%s'.\n", aFileName ) ); + ReportMessage( wxString::Format( "No location data for filename '%s'.\n", fileName ) ); return false; } @@ -642,7 +643,7 @@ bool PCBMODEL::AddComponent( const std::string& aFileName, const std::string& aR if( llabel.IsNull() ) { ReportMessage( wxString::Format( "Could not add component with filename '%s'.\n", - aFileName ) ); + fileName ) ); 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 ) { - 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 ); 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; 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 ) { 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; } break; 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; } break; case FMT_STEPZ: { - wxFFileInputStream ifile( aFileName ); - wxFileName outFile( aFileName ); + // To export a compressed step file (.stpz or .stp.gz file), the best way is to + // decaompress it in a temporaty file and load this temporary file + wxFFileInputStream ifile( fileName ); + wxFileName outFile( fileName ); outFile.SetPath( wxStandardPaths::Get().GetTempDir() ); - outFile.SetExt( "STEP" ); - + outFile.SetExt( "step" ); wxFileOffset size = ifile.GetLength(); 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; } @@ -1052,6 +1056,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_ } catch( ... ) { + ReportMessage( wxString::Format( "failed to decompress '%s'.\n", fileName ) ); } if( expanded.empty() ) @@ -1075,6 +1080,12 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_ delete[] buffer; 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; } @@ -1093,7 +1104,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_ */ if( aSubstituteModels ) { - wxFileName wrlName( aFileName ); + wxFileName wrlName( fileName ); wxString basePath = wrlName.GetPath(); 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( "step.gz" ); + alts.Add( "stp.gz" ); // IGES files alts.Add( "iges" ); @@ -1129,7 +1141,7 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_ 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 // 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. // TODO: Fix model handling in v7. Default models should only be STP. // 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; } @@ -1168,13 +1180,13 @@ bool PCBMODEL::getModelLabel( const std::string& aFileName, TRIPLET aScale, TDF_ if( aLabel.IsNull() ) { ReportMessage( wxString::Format( "Could not transfer model data from file '%s'.\n", - aFileName ) ); + fileName ) ); return false; } // attach the PART NAME ( base filename: note that in principle // different models may have the same base filename ) - wxFileName afile( aFileName.c_str() ); + wxFileName afile( fileName ); std::string pname( afile.GetName().ToUTF8() ); TCollection_ExtendedString partname( pname.c_str() ); TDataStd_Name::Set( aLabel, partname ); diff --git a/utils/kicad2step/pcb/oce_utils.h b/utils/kicad2step/pcb/oce_utils.h index 82e054b305..d85c86871a 100644 --- a/utils/kicad2step/pcb/oce_utils.h +++ b/utils/kicad2step/pcb/oce_utils.h @@ -125,15 +125,16 @@ private: /** * Load a 3D model data. * - * @param aFileName is the filename (different formats allowed) but for WRML files a model - * data can be loaded instead of the vrml data, not suitable in a step file. + * @param aFileNameUTF8 is the filename encoded UTF8 (different formats allowed) + * 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 aLabel is the TDF_Label to store the data. * @param aSubstituteModels = true to allows data substitution, false to disallow. * @param aErrorMessage (can be nullptr) is an error message to be displayed 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 getModelLocation( bool aBottom, DOUBLET aPosition, double aRotation, TRIPLET aOffset,