2017-11-02 15:21:34 +00:00
# include <cassert>
2017-10-30 17:41:50 +00:00
# include "PresetBundle.hpp"
2018-03-12 15:04:32 +00:00
# include "BitmapCache.hpp"
2018-10-10 11:53:45 +00:00
# include "Plater.hpp"
2018-11-26 13:41:58 +00:00
# include "I18N.hpp"
2019-04-08 07:37:23 +00:00
# include "wxExtensions.hpp"
2017-10-30 17:41:50 +00:00
2018-03-13 11:39:57 +00:00
# include <algorithm>
2017-10-30 17:41:50 +00:00
# include <fstream>
# include <boost/filesystem.hpp>
2017-11-01 18:30:05 +00:00
# include <boost/algorithm/clamp.hpp>
2017-10-30 17:41:50 +00:00
# include <boost/algorithm/string/predicate.hpp>
# include <boost/nowide/cenv.hpp>
# include <boost/nowide/cstdio.hpp>
# include <boost/nowide/fstream.hpp>
# include <boost/property_tree/ini_parser.hpp>
# include <boost/property_tree/ptree.hpp>
# include <boost/locale.hpp>
2018-03-07 15:48:28 +00:00
# include <boost/log/trivial.hpp>
2017-10-30 17:41:50 +00:00
2017-11-10 16:27:05 +00:00
# include <wx/dcmemory.h>
2017-10-30 17:41:50 +00:00
# include <wx/image.h>
# include <wx/choice.h>
# include <wx/bmpcbox.h>
# include <wx/wupdlock.h>
2018-11-26 13:41:58 +00:00
# include "libslic3r/libslic3r.h"
# include "libslic3r/Utils.hpp"
2017-10-30 17:41:50 +00:00
2017-12-14 08:40:45 +00:00
// Store the print/filament/printer presets into a "presets" subdirectory of the Slic3rPE config dir.
// This breaks compatibility with the upstream Slic3r if the --datadir is used to switch between the two versions.
// #define SLIC3R_PROFILE_USE_PRESETS_SUBDIR
2017-10-30 17:41:50 +00:00
namespace Slic3r {
2018-04-04 08:18:26 +00:00
static std : : vector < std : : string > s_project_options {
2018-11-07 13:44:47 +00:00
" colorprint_heights " ,
2018-04-04 08:18:26 +00:00
" wiping_volumes_extruders " ,
" wiping_volumes_matrix "
2018-03-14 10:54:11 +00:00
} ;
2017-10-30 17:41:50 +00:00
PresetBundle : : PresetBundle ( ) :
2018-08-03 12:14:25 +00:00
prints ( Preset : : TYPE_PRINT , Preset : : print_options ( ) , static_cast < const HostConfig & > ( FullPrintConfig : : defaults ( ) ) ) ,
filaments ( Preset : : TYPE_FILAMENT , Preset : : filament_options ( ) , static_cast < const HostConfig & > ( FullPrintConfig : : defaults ( ) ) ) ,
sla_materials ( Preset : : TYPE_SLA_MATERIAL , Preset : : sla_material_options ( ) , static_cast < const SLAMaterialConfig & > ( SLAFullPrintConfig : : defaults ( ) ) ) ,
2018-11-16 16:36:23 +00:00
sla_prints ( Preset : : TYPE_SLA_PRINT , Preset : : sla_print_options ( ) , static_cast < const SLAPrintObjectConfig & > ( SLAFullPrintConfig : : defaults ( ) ) ) ,
2018-08-03 12:14:25 +00:00
printers ( Preset : : TYPE_PRINTER , Preset : : printer_options ( ) , static_cast < const HostConfig & > ( FullPrintConfig : : defaults ( ) ) , " - default FFF - " ) ,
2017-10-30 17:41:50 +00:00
m_bitmapCompatible ( new wxBitmap ) ,
2018-03-12 15:04:32 +00:00
m_bitmapIncompatible ( new wxBitmap ) ,
m_bitmapLock ( new wxBitmap ) ,
m_bitmapLockOpen ( new wxBitmap ) ,
m_bitmapCache ( new GUI : : BitmapCache )
2017-10-30 17:41:50 +00:00
{
2017-11-30 19:25:59 +00:00
if ( wxImage : : FindHandler ( wxBITMAP_TYPE_PNG ) = = nullptr )
wxImage : : AddHandler ( new wxPNGHandler ) ;
2017-10-30 17:41:50 +00:00
2018-06-26 08:50:50 +00:00
// The following keys are handled by the UI, they do not have a counterpart in any StaticPrintConfig derived classes,
// therefore they need to be handled differently. As they have no counterpart in StaticPrintConfig, they are not being
// initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings).
//
// "compatible_printers", "compatible_printers_condition", "inherits",
// "print_settings_id", "filament_settings_id", "printer_settings_id",
// "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile"
// Create the ID config keys, as they are not part of the Static print config classes.
this - > prints . default_preset ( ) . config . optptr ( " print_settings_id " , true ) ;
2018-06-27 14:57:42 +00:00
this - > prints . default_preset ( ) . compatible_printers_condition ( ) ;
this - > prints . default_preset ( ) . inherits ( ) ;
2018-06-26 08:50:50 +00:00
this - > filaments . default_preset ( ) . config . option < ConfigOptionStrings > ( " filament_settings_id " , true ) - > values = { " " } ;
2018-06-27 14:57:42 +00:00
this - > filaments . default_preset ( ) . compatible_printers_condition ( ) ;
this - > filaments . default_preset ( ) . inherits ( ) ;
WIP: Nullable configuration value concept, implemented for
ConfigOptionFloatsNullable, ConfigOptionIntsNullable,
ConfigOptionPercentsNullable, ConfigOptionBoolsNullable.
retract override values were added to the Filament profile:
vector of floats: "retract_length", "retract_lift", "retract_lift_above",
"retract_lift_below", "retract_speed", "deretract_speed",
"retract_restart_extra", "retract_before_travel",
vector of bools: "retract_layer_change", "wipe"
vector of percents: "retract_before_wipe"
2019-07-23 12:15:42 +00:00
// Set all the nullable values to nils.
this - > filaments . default_preset ( ) . config . null_nullables ( ) ;
2018-06-26 08:50:50 +00:00
2018-07-31 13:09:57 +00:00
this - > sla_materials . default_preset ( ) . config . optptr ( " sla_material_settings_id " , true ) ;
this - > sla_materials . default_preset ( ) . compatible_printers_condition ( ) ;
this - > sla_materials . default_preset ( ) . inherits ( ) ;
2018-11-16 16:36:23 +00:00
this - > sla_prints . default_preset ( ) . config . optptr ( " sla_print_settings_id " , true ) ;
2019-05-16 13:55:26 +00:00
this - > sla_prints . default_preset ( ) . config . opt_string ( " output_filename_format " , true ) = " [input_filename_base].sl1 " ;
2018-11-16 16:36:23 +00:00
this - > sla_prints . default_preset ( ) . compatible_printers_condition ( ) ;
this - > sla_prints . default_preset ( ) . inherits ( ) ;
2018-08-03 12:14:25 +00:00
this - > printers . add_default_preset ( Preset : : sla_printer_options ( ) , static_cast < const SLAMaterialConfig & > ( SLAFullPrintConfig : : defaults ( ) ) , " - default SLA - " ) ;
2019-01-10 17:08:38 +00:00
this - > printers . preset ( 1 ) . printer_technology_ref ( ) = ptSLA ;
2018-08-01 09:09:51 +00:00
for ( size_t i = 0 ; i < 2 ; + + i ) {
2018-10-24 12:45:22 +00:00
// The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one.
2018-10-31 15:22:36 +00:00
Preset & preset = this - > printers . default_preset ( i ) ;
2018-08-01 09:09:51 +00:00
preset . config . optptr ( " printer_settings_id " , true ) ;
preset . config . optptr ( " printer_vendor " , true ) ;
preset . config . optptr ( " printer_model " , true ) ;
preset . config . optptr ( " printer_variant " , true ) ;
2018-10-31 15:22:36 +00:00
if ( i = = 0 ) {
preset . config . optptr ( " default_print_profile " , true ) ;
preset . config . option < ConfigOptionStrings > ( " default_filament_profile " , true ) - > values = { " " } ;
2018-11-16 16:36:23 +00:00
}
else {
preset . config . optptr ( " default_sla_print_profile " , true ) ;
2018-12-03 12:14:28 +00:00
preset . config . optptr ( " default_sla_material_profile " , true ) ;
2018-11-16 16:36:23 +00:00
}
2018-10-31 15:22:36 +00:00
// default_sla_material_profile
2018-08-01 09:09:51 +00:00
preset . inherits ( ) ;
}
2018-06-26 08:50:50 +00:00
// Load the default preset bitmaps.
2019-04-08 07:37:23 +00:00
// #ys_FIXME_to_delete we'll load them later, using em_unit()
// this->prints .load_bitmap_default("cog");
// this->sla_prints .load_bitmap_default("package_green.png");
// this->filaments .load_bitmap_default("spool.png");
// this->sla_materials.load_bitmap_default("package_green.png");
// this->printers .load_bitmap_default("printer_empty.png");
// this->printers .load_bitmap_add("add.png");
// this->load_compatible_bitmaps();
2018-06-26 08:50:50 +00:00
2018-05-22 12:17:27 +00:00
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
2018-07-31 13:09:57 +00:00
this - > prints . select_preset ( 0 ) ;
2018-11-16 16:36:23 +00:00
this - > sla_prints . select_preset ( 0 ) ;
2018-07-31 13:09:57 +00:00
this - > filaments . select_preset ( 0 ) ;
this - > sla_materials . select_preset ( 0 ) ;
this - > printers . select_preset ( 0 ) ;
2018-03-14 10:54:11 +00:00
this - > project_config . apply_only ( FullPrintConfig : : defaults ( ) , s_project_options ) ;
2017-10-30 17:41:50 +00:00
}
PresetBundle : : ~ PresetBundle ( )
{
assert ( m_bitmapCompatible ! = nullptr ) ;
assert ( m_bitmapIncompatible ! = nullptr ) ;
2018-03-12 15:04:32 +00:00
assert ( m_bitmapLock ! = nullptr ) ;
assert ( m_bitmapLockOpen ! = nullptr ) ;
2017-10-30 17:41:50 +00:00
delete m_bitmapCompatible ;
m_bitmapCompatible = nullptr ;
delete m_bitmapIncompatible ;
m_bitmapIncompatible = nullptr ;
2018-03-12 15:04:32 +00:00
delete m_bitmapLock ;
m_bitmapLock = nullptr ;
delete m_bitmapLockOpen ;
m_bitmapLockOpen = nullptr ;
delete m_bitmapCache ;
m_bitmapCache = nullptr ;
2017-10-30 17:41:50 +00:00
}
2017-12-19 18:51:22 +00:00
void PresetBundle : : reset ( bool delete_files )
{
// Clear the existing presets, delete their respective files.
2018-06-06 08:52:19 +00:00
this - > vendors . clear ( ) ;
2018-07-31 13:09:57 +00:00
this - > prints . reset ( delete_files ) ;
2018-11-16 16:36:23 +00:00
this - > sla_prints . reset ( delete_files ) ;
2018-07-31 13:09:57 +00:00
this - > filaments . reset ( delete_files ) ;
this - > sla_materials . reset ( delete_files ) ;
this - > printers . reset ( delete_files ) ;
2017-12-19 18:51:22 +00:00
this - > filament_presets . clear ( ) ;
2018-07-31 13:09:57 +00:00
this - > filament_presets . emplace_back ( this - > filaments . get_selected_preset_name ( ) ) ;
2018-05-16 14:34:07 +00:00
this - > obsolete_presets . prints . clear ( ) ;
2018-11-16 16:36:23 +00:00
this - > obsolete_presets . sla_prints . clear ( ) ;
2018-05-16 14:34:07 +00:00
this - > obsolete_presets . filaments . clear ( ) ;
2018-07-31 13:09:57 +00:00
this - > obsolete_presets . sla_materials . clear ( ) ;
2018-05-16 14:34:07 +00:00
this - > obsolete_presets . printers . clear ( ) ;
2017-12-19 18:51:22 +00:00
}
2017-10-30 17:41:50 +00:00
void PresetBundle : : setup_directories ( )
{
2017-11-30 14:51:51 +00:00
boost : : filesystem : : path data_dir = boost : : filesystem : : path ( Slic3r : : data_dir ( ) ) ;
2017-12-10 21:11:00 +00:00
std : : initializer_list < boost : : filesystem : : path > paths = {
2018-03-09 15:37:33 +00:00
data_dir ,
data_dir / " vendor " ,
2018-04-11 11:12:08 +00:00
data_dir / " cache " ,
2017-12-14 08:40:45 +00:00
# ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
2017-12-10 21:11:00 +00:00
data_dir / " presets " ,
data_dir / " presets " / " print " ,
data_dir / " presets " / " filament " ,
2018-11-19 10:10:22 +00:00
data_dir / " presets " / " sla_print " ,
2018-07-31 13:09:57 +00:00
data_dir / " presets " / " sla_material " ,
2017-12-14 08:40:45 +00:00
data_dir / " presets " / " printer "
# else
// Store the print/filament/printer presets at the same location as the upstream Slic3r.
data_dir / " print " ,
data_dir / " filament " ,
2018-11-19 10:10:22 +00:00
data_dir / " sla_print " ,
2018-07-31 13:09:57 +00:00
data_dir / " sla_material " ,
2017-12-14 08:40:45 +00:00
data_dir / " printer "
# endif
} ;
2017-11-30 14:51:51 +00:00
for ( const boost : : filesystem : : path & path : paths ) {
boost : : filesystem : : path subdir = path ;
subdir . make_preferred ( ) ;
2017-10-30 17:41:50 +00:00
if ( ! boost : : filesystem : : is_directory ( subdir ) & &
! boost : : filesystem : : create_directory ( subdir ) )
throw std : : runtime_error ( std : : string ( " Slic3r was unable to create its data directory at " ) + subdir . string ( ) ) ;
}
}
2019-04-26 14:53:04 +00:00
void PresetBundle : : load_presets ( const AppConfig & config , const std : : string & preferred_model_id )
2017-10-30 17:41:50 +00:00
{
2018-03-09 15:37:33 +00:00
// First load the vendor specific system presets.
std : : string errors_cummulative = this - > load_system_presets ( ) ;
const std : : string dir_user_presets = data_dir ( )
2017-12-14 08:40:45 +00:00
# ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
+ " /presets "
# else
// Store the print/filament/printer presets at the same location as the upstream Slic3r.
# endif
;
2017-11-28 09:08:01 +00:00
try {
2018-03-09 15:37:33 +00:00
this - > prints . load_presets ( dir_user_presets , " print " ) ;
2017-11-28 09:08:01 +00:00
} catch ( const std : : runtime_error & err ) {
errors_cummulative + = err . what ( ) ;
}
2018-11-16 16:36:23 +00:00
try {
this - > sla_prints . load_presets ( dir_user_presets , " sla_print " ) ;
} catch ( const std : : runtime_error & err ) {
errors_cummulative + = err . what ( ) ;
}
2017-11-28 09:08:01 +00:00
try {
2018-03-09 15:37:33 +00:00
this - > filaments . load_presets ( dir_user_presets , " filament " ) ;
2017-11-28 09:08:01 +00:00
} catch ( const std : : runtime_error & err ) {
errors_cummulative + = err . what ( ) ;
}
2018-07-31 13:09:57 +00:00
try {
this - > sla_materials . load_presets ( dir_user_presets , " sla_material " ) ;
} catch ( const std : : runtime_error & err ) {
errors_cummulative + = err . what ( ) ;
}
2017-11-28 09:08:01 +00:00
try {
2018-03-09 15:37:33 +00:00
this - > printers . load_presets ( dir_user_presets , " printer " ) ;
2017-11-28 09:08:01 +00:00
} catch ( const std : : runtime_error & err ) {
errors_cummulative + = err . what ( ) ;
}
2017-10-30 17:41:50 +00:00
this - > update_multi_material_filament_presets ( ) ;
2018-12-04 16:56:49 +00:00
this - > update_compatible ( false ) ;
2017-11-28 09:08:01 +00:00
if ( ! errors_cummulative . empty ( ) )
throw std : : runtime_error ( errors_cummulative ) ;
2018-03-09 15:37:33 +00:00
2019-04-26 14:53:04 +00:00
this - > load_selections ( config , preferred_model_id ) ;
2018-03-09 15:37:33 +00:00
}
// Load system presets into this PresetBundle.
// For each vendor, there will be a single PresetBundle loaded.
std : : string PresetBundle : : load_system_presets ( )
{
// Here the vendor specific read only Config Bundles are stored.
boost : : filesystem : : path dir = ( boost : : filesystem : : path ( data_dir ( ) ) / " vendor " ) . make_preferred ( ) ;
std : : string errors_cummulative ;
2018-04-18 11:35:51 +00:00
bool first = true ;
2018-03-09 15:37:33 +00:00
for ( auto & dir_entry : boost : : filesystem : : directory_iterator ( dir ) )
2019-02-03 14:30:37 +00:00
if ( Slic3r : : is_ini_file ( dir_entry ) ) {
2018-03-09 15:37:33 +00:00
std : : string name = dir_entry . path ( ) . filename ( ) . string ( ) ;
// Remove the .ini suffix.
name . erase ( name . size ( ) - 4 ) ;
try {
// Load the config bundle, flatten it.
2018-04-18 11:35:51 +00:00
if ( first ) {
// Reset this PresetBundle and load the first vendor config.
this - > load_configbundle ( dir_entry . path ( ) . string ( ) , LOAD_CFGBNDLE_SYSTEM ) ;
first = false ;
} else {
// Load the other vendor configs, merge them with this PresetBundle.
// Report duplicate profiles.
PresetBundle other ;
other . load_configbundle ( dir_entry . path ( ) . string ( ) , LOAD_CFGBNDLE_SYSTEM ) ;
std : : vector < std : : string > duplicates = this - > merge_presets ( std : : move ( other ) ) ;
if ( ! duplicates . empty ( ) ) {
errors_cummulative + = " Vendor configuration file " + name + " contains the following presets with names used by other vendors: " ;
for ( size_t i = 0 ; i < duplicates . size ( ) ; + + i ) {
if ( i > 0 )
errors_cummulative + = " , " ;
errors_cummulative + = duplicates [ i ] ;
}
}
}
2018-03-09 15:37:33 +00:00
} catch ( const std : : runtime_error & err ) {
errors_cummulative + = err . what ( ) ;
errors_cummulative + = " \n " ;
}
}
2018-05-16 08:11:00 +00:00
if ( first ) {
// No config bundle loaded, reset.
this - > reset ( false ) ;
}
2018-03-09 15:37:33 +00:00
return errors_cummulative ;
2017-10-30 17:41:50 +00:00
}
2018-04-18 11:35:51 +00:00
// Merge one vendor's presets with the other vendor's presets, report duplicates.
std : : vector < std : : string > PresetBundle : : merge_presets ( PresetBundle & & other )
{
this - > vendors . insert ( other . vendors . begin ( ) , other . vendors . end ( ) ) ;
2018-07-31 13:09:57 +00:00
std : : vector < std : : string > duplicate_prints = this - > prints . merge_presets ( std : : move ( other . prints ) , this - > vendors ) ;
2018-11-16 16:36:23 +00:00
std : : vector < std : : string > duplicate_sla_prints = this - > sla_prints . merge_presets ( std : : move ( other . sla_prints ) , this - > vendors ) ;
2018-07-31 13:09:57 +00:00
std : : vector < std : : string > duplicate_filaments = this - > filaments . merge_presets ( std : : move ( other . filaments ) , this - > vendors ) ;
std : : vector < std : : string > duplicate_sla_materials = this - > sla_materials . merge_presets ( std : : move ( other . sla_materials ) , this - > vendors ) ;
std : : vector < std : : string > duplicate_printers = this - > printers . merge_presets ( std : : move ( other . printers ) , this - > vendors ) ;
append ( this - > obsolete_presets . prints , std : : move ( other . obsolete_presets . prints ) ) ;
2018-11-16 16:36:23 +00:00
append ( this - > obsolete_presets . sla_prints , std : : move ( other . obsolete_presets . sla_prints ) ) ;
2018-07-31 13:09:57 +00:00
append ( this - > obsolete_presets . filaments , std : : move ( other . obsolete_presets . filaments ) ) ;
append ( this - > obsolete_presets . sla_materials , std : : move ( other . obsolete_presets . sla_materials ) ) ;
append ( this - > obsolete_presets . printers , std : : move ( other . obsolete_presets . printers ) ) ;
2018-11-16 16:36:23 +00:00
append ( duplicate_prints , std : : move ( duplicate_sla_prints ) ) ;
2018-05-16 14:34:07 +00:00
append ( duplicate_prints , std : : move ( duplicate_filaments ) ) ;
2018-07-31 13:09:57 +00:00
append ( duplicate_prints , std : : move ( duplicate_sla_materials ) ) ;
2018-04-18 11:35:51 +00:00
append ( duplicate_prints , std : : move ( duplicate_printers ) ) ;
return duplicate_prints ;
}
2017-11-02 16:31:24 +00:00
static inline std : : string remove_ini_suffix ( const std : : string & name )
{
std : : string out = name ;
if ( boost : : iends_with ( out , " .ini " ) )
out . erase ( out . end ( ) - 4 , out . end ( ) ) ;
return out ;
}
2018-03-09 15:37:33 +00:00
// Set the "enabled" flag for printer vendors, printer models and printer variants
// based on the user configuration.
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
void PresetBundle : : load_installed_printers ( const AppConfig & config )
{
2018-03-29 15:54:43 +00:00
for ( auto & preset : printers ) {
preset . set_visible_from_appconfig ( config ) ;
}
2018-03-09 15:37:33 +00:00
}
2017-10-30 17:41:50 +00:00
// Load selections (current print, current filaments, current printer) from config.ini
2018-07-23 12:19:40 +00:00
// This is done on application start up or after updates are applied.
2019-04-26 14:53:04 +00:00
void PresetBundle : : load_selections ( const AppConfig & config , const std : : string & preferred_model_id )
2017-10-30 17:41:50 +00:00
{
2018-04-13 12:49:33 +00:00
// Update visibility of presets based on application vendor / model / variant configuration.
this - > load_installed_printers ( config ) ;
// Parse the initial print / filament / printer profile names.
2018-07-31 13:09:57 +00:00
std : : string initial_print_profile_name = remove_ini_suffix ( config . get ( " presets " , " print " ) ) ;
2018-11-16 16:36:23 +00:00
std : : string initial_sla_print_profile_name = remove_ini_suffix ( config . get ( " presets " , " sla_print " ) ) ;
2018-07-31 13:09:57 +00:00
std : : string initial_filament_profile_name = remove_ini_suffix ( config . get ( " presets " , " filament " ) ) ;
std : : string initial_sla_material_profile_name = remove_ini_suffix ( config . get ( " presets " , " sla_material " ) ) ;
std : : string initial_printer_profile_name = remove_ini_suffix ( config . get ( " presets " , " printer " ) ) ;
2018-04-13 12:49:33 +00:00
2019-04-26 14:53:04 +00:00
// Activate print / filament / printer profiles from either the config,
// or from the preferred_model_id suggestion passed in by ConfigWizard.
// If the printer profile enumerated by the config are not visible, select an alternate preset.
2018-07-02 18:25:37 +00:00
// Do not select alternate profiles for the print / filament profiles as those presets
2018-12-04 16:56:49 +00:00
// will be selected by the following call of this->update_compatible(true).
2019-04-26 14:53:04 +00:00
const Preset * initial_printer = printers . find_preset ( initial_printer_profile_name ) ;
const Preset * preferred_printer = printers . find_by_model_id ( preferred_model_id ) ;
2019-05-15 15:15:52 +00:00
printers . select_preset_by_name (
( preferred_printer ! = nullptr & & ( initial_printer = = nullptr | | ! initial_printer - > is_visible ) ) ?
preferred_printer - > name :
initial_printer_profile_name ,
true ) ;
// Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found.
prints . select_preset_by_name_strict ( initial_print_profile_name ) ;
filaments . select_preset_by_name_strict ( initial_filament_profile_name ) ;
sla_prints . select_preset_by_name_strict ( initial_sla_print_profile_name ) ;
sla_materials . select_preset_by_name_strict ( initial_sla_material_profile_name ) ;
// Load the names of the other filament profiles selected for a multi-material printer.
// Load it even if the current printer technology is SLA.
// The possibly excessive filament names will be later removed with this->update_multi_material_filament_presets()
// once the FFF technology gets selected.
this - > filament_presets = { filaments . get_selected_preset_name ( ) } ;
for ( unsigned int i = 1 ; i < 1000 ; + + i ) {
char name [ 64 ] ;
sprintf ( name , " filament_%d " , i ) ;
if ( ! config . has ( " presets " , name ) )
break ;
this - > filament_presets . emplace_back ( remove_ini_suffix ( config . get ( " presets " , name ) ) ) ;
2017-10-30 17:41:50 +00:00
}
2018-03-29 15:54:43 +00:00
2017-11-10 16:27:05 +00:00
// Update visibility of presets based on their compatibility with the active printer.
2017-12-20 10:28:16 +00:00
// Always try to select a compatible print and filament preset to the current printer preset,
// as the application may have been closed with an active "external" preset, which does not
// exist.
2018-12-04 16:56:49 +00:00
this - > update_compatible ( true ) ;
2018-07-02 18:25:37 +00:00
this - > update_multi_material_filament_presets ( ) ;
2017-10-30 17:41:50 +00:00
}
// Export selections (current print, current filaments, current printer) into config.ini
void PresetBundle : : export_selections ( AppConfig & config )
{
2018-10-31 15:22:36 +00:00
assert ( this - > printers . get_edited_preset ( ) . printer_technology ( ) ! = ptFFF | | filament_presets . size ( ) > = 1 ) ;
assert ( this - > printers . get_edited_preset ( ) . printer_technology ( ) ! = ptFFF | | filament_presets . size ( ) > 1 | | filaments . get_selected_preset_name ( ) = = filament_presets . front ( ) ) ;
2017-11-01 18:30:05 +00:00
config . clear_section ( " presets " ) ;
2018-07-31 13:09:57 +00:00
config . set ( " presets " , " print " , prints . get_selected_preset_name ( ) ) ;
config . set ( " presets " , " filament " , filament_presets . front ( ) ) ;
2017-11-01 18:30:05 +00:00
for ( int i = 1 ; i < filament_presets . size ( ) ; + + i ) {
2017-10-30 17:41:50 +00:00
char name [ 64 ] ;
sprintf ( name , " filament_%d " , i ) ;
config . set ( " presets " , name , filament_presets [ i ] ) ;
}
2018-11-19 10:10:22 +00:00
config . set ( " presets " , " sla_print " , sla_prints . get_selected_preset_name ( ) ) ;
2018-07-31 13:09:57 +00:00
config . set ( " presets " , " sla_material " , sla_materials . get_selected_preset_name ( ) ) ;
2018-12-03 12:14:28 +00:00
config . set ( " presets " , " printer " , printers . get_selected_preset_name ( ) ) ;
2017-11-02 15:21:34 +00:00
}
2019-04-09 15:40:14 +00:00
void PresetBundle : : load_compatible_bitmaps ( wxWindow * window )
2017-10-30 17:41:50 +00:00
{
2019-04-12 08:57:30 +00:00
// We don't actually pass the window pointer here and instead generate
2019-04-12 09:28:07 +00:00
// a low DPI bitmap, because the wxBitmapComboBox and wxDataViewCtrl don't support
2019-04-12 08:57:30 +00:00
// high DPI bitmaps very well, they compute their dimensions wrong.
// TODO: Update this when fixed in wxWidgets
// See also PresetCollection::load_bitmap_default() and PresetCollection::load_bitmap_add()
( void ) window ;
* m_bitmapCompatible = create_scaled_bitmap ( nullptr , " flag_green " ) ;
* m_bitmapIncompatible = create_scaled_bitmap ( nullptr , " flag_red " ) ;
* m_bitmapLock = create_scaled_bitmap ( nullptr , " lock_closed " ) ;
2019-05-13 10:13:28 +00:00
* m_bitmapLockOpen = create_scaled_bitmap ( nullptr , " lock_open " ) ;
2019-04-09 12:18:03 +00:00
prints . set_bitmap_compatible ( m_bitmapCompatible ) ;
filaments . set_bitmap_compatible ( m_bitmapCompatible ) ;
sla_prints . set_bitmap_compatible ( m_bitmapCompatible ) ;
sla_materials . set_bitmap_compatible ( m_bitmapCompatible ) ;
prints . set_bitmap_incompatible ( m_bitmapIncompatible ) ;
filaments . set_bitmap_incompatible ( m_bitmapIncompatible ) ;
sla_prints . set_bitmap_incompatible ( m_bitmapIncompatible ) ;
sla_materials . set_bitmap_incompatible ( m_bitmapIncompatible ) ;
prints . set_bitmap_lock ( m_bitmapLock ) ;
filaments . set_bitmap_lock ( m_bitmapLock ) ;
sla_prints . set_bitmap_lock ( m_bitmapLock ) ;
sla_materials . set_bitmap_lock ( m_bitmapLock ) ;
printers . set_bitmap_lock ( m_bitmapLock ) ;
prints . set_bitmap_lock_open ( m_bitmapLock ) ;
filaments . set_bitmap_lock_open ( m_bitmapLock ) ;
sla_prints . set_bitmap_lock_open ( m_bitmapLock ) ;
sla_materials . set_bitmap_lock_open ( m_bitmapLock ) ;
printers . set_bitmap_lock_open ( m_bitmapLock ) ;
2017-10-30 17:41:50 +00:00
}
DynamicPrintConfig PresetBundle : : full_config ( ) const
2018-07-31 13:09:57 +00:00
{
return ( this - > printers . get_edited_preset ( ) . printer_technology ( ) = = ptFFF ) ?
this - > full_fff_config ( ) :
this - > full_sla_config ( ) ;
}
2018-12-06 13:42:15 +00:00
DynamicPrintConfig PresetBundle : : full_config_secure ( ) const
{
DynamicPrintConfig config = this - > full_config ( ) ;
2019-08-26 14:39:08 +00:00
config . erase ( " print_host " ) ;
2018-12-06 13:42:15 +00:00
config . erase ( " printhost_apikey " ) ;
config . erase ( " printhost_cafile " ) ;
return config ;
}
2018-07-31 13:09:57 +00:00
DynamicPrintConfig PresetBundle : : full_fff_config ( ) const
2017-10-30 17:41:50 +00:00
{
DynamicPrintConfig out ;
2018-08-03 12:14:25 +00:00
out . apply ( FullPrintConfig : : defaults ( ) ) ;
2017-10-30 17:41:50 +00:00
out . apply ( this - > prints . get_edited_preset ( ) . config ) ;
2018-05-23 11:19:25 +00:00
// Add the default filament preset to have the "filament_preset_id" defined.
out . apply ( this - > filaments . default_preset ( ) . config ) ;
out . apply ( this - > printers . get_edited_preset ( ) . config ) ;
2018-03-14 10:54:11 +00:00
out . apply ( this - > project_config ) ;
2017-10-30 17:41:50 +00:00
auto * nozzle_diameter = dynamic_cast < const ConfigOptionFloats * > ( out . option ( " nozzle_diameter " ) ) ;
size_t num_extruders = nozzle_diameter - > values . size ( ) ;
2018-06-26 08:50:50 +00:00
// Collect the "compatible_printers_condition" and "inherits" values over all presets (print, filaments, printers) into a single vector.
std : : vector < std : : string > compatible_printers_condition ;
2018-12-04 16:56:49 +00:00
std : : vector < std : : string > compatible_prints_condition ;
2018-06-26 08:50:50 +00:00
std : : vector < std : : string > inherits ;
2018-06-27 14:57:42 +00:00
compatible_printers_condition . emplace_back ( this - > prints . get_edited_preset ( ) . compatible_printers_condition ( ) ) ;
inherits . emplace_back ( this - > prints . get_edited_preset ( ) . inherits ( ) ) ;
2017-10-30 17:41:50 +00:00
if ( num_extruders < = 1 ) {
out . apply ( this - > filaments . get_edited_preset ( ) . config ) ;
2018-06-27 14:57:42 +00:00
compatible_printers_condition . emplace_back ( this - > filaments . get_edited_preset ( ) . compatible_printers_condition ( ) ) ;
2018-12-04 16:56:49 +00:00
compatible_prints_condition . emplace_back ( this - > filaments . get_edited_preset ( ) . compatible_prints_condition ( ) ) ;
2018-06-27 14:57:42 +00:00
inherits . emplace_back ( this - > filaments . get_edited_preset ( ) . inherits ( ) ) ;
2017-10-30 17:41:50 +00:00
} else {
// Retrieve filament presets and build a single config object for them.
// First collect the filament configurations based on the user selection of this->filament_presets.
2018-05-16 14:34:07 +00:00
// Here this->filaments.find_preset() and this->filaments.first_visible() return the edited copy of the preset if active.
2017-10-30 17:41:50 +00:00
std : : vector < const DynamicPrintConfig * > filament_configs ;
for ( const std : : string & filament_preset_name : this - > filament_presets )
filament_configs . emplace_back ( & this - > filaments . find_preset ( filament_preset_name , true ) - > config ) ;
while ( filament_configs . size ( ) < num_extruders )
filament_configs . emplace_back ( & this - > filaments . first_visible ( ) . config ) ;
2018-06-26 08:50:50 +00:00
for ( const DynamicPrintConfig * cfg : filament_configs ) {
2018-06-27 14:57:42 +00:00
compatible_printers_condition . emplace_back ( Preset : : compatible_printers_condition ( * const_cast < DynamicPrintConfig * > ( cfg ) ) ) ;
2018-12-04 16:56:49 +00:00
compatible_prints_condition . emplace_back ( Preset : : compatible_prints_condition ( * const_cast < DynamicPrintConfig * > ( cfg ) ) ) ;
2018-06-27 14:57:42 +00:00
inherits . emplace_back ( Preset : : inherits ( * const_cast < DynamicPrintConfig * > ( cfg ) ) ) ;
2018-06-26 08:50:50 +00:00
}
2017-10-30 17:41:50 +00:00
// Option values to set a ConfigOptionVector from.
std : : vector < const ConfigOption * > filament_opts ( num_extruders , nullptr ) ;
// loop through options and apply them to the resulting config.
for ( const t_config_option_key & key : this - > filaments . default_preset ( ) . config . keys ( ) ) {
2018-12-04 16:56:49 +00:00
if ( key = = " compatible_prints " | | key = = " compatible_printers " )
2017-11-10 16:27:05 +00:00
continue ;
2017-10-30 17:41:50 +00:00
// Get a destination option.
ConfigOption * opt_dst = out . option ( key , false ) ;
if ( opt_dst - > is_scalar ( ) ) {
// Get an option, do not create if it does not exist.
const ConfigOption * opt_src = filament_configs . front ( ) - > option ( key ) ;
if ( opt_src ! = nullptr )
opt_dst - > set ( opt_src ) ;
} else {
// Setting a vector value from all filament_configs.
for ( size_t i = 0 ; i < filament_opts . size ( ) ; + + i )
filament_opts [ i ] = filament_configs [ i ] - > option ( key ) ;
static_cast < ConfigOptionVectorBase * > ( opt_dst ) - > set ( filament_opts ) ;
}
}
}
2017-12-01 17:55:57 +00:00
2018-06-26 08:50:50 +00:00
// Don't store the "compatible_printers_condition" for the printer profile, there is none.
2018-06-27 14:57:42 +00:00
inherits . emplace_back ( this - > printers . get_edited_preset ( ) . inherits ( ) ) ;
2018-06-26 08:50:50 +00:00
2018-12-04 16:56:49 +00:00
// These value types clash between the print and filament profiles. They should be renamed.
out . erase ( " compatible_prints " ) ;
out . erase ( " compatible_prints_condition " ) ;
2017-12-01 17:55:57 +00:00
out . erase ( " compatible_printers " ) ;
2018-05-23 11:19:25 +00:00
out . erase ( " compatible_printers_condition " ) ;
2018-06-26 08:50:50 +00:00
out . erase ( " inherits " ) ;
2017-10-30 17:41:50 +00:00
static const char * keys [ ] = { " perimeter " , " infill " , " solid_infill " , " support_material " , " support_material_interface " } ;
for ( size_t i = 0 ; i < sizeof ( keys ) / sizeof ( keys [ 0 ] ) ; + + i ) {
std : : string key = std : : string ( keys [ i ] ) + " _extruder " ;
auto * opt = dynamic_cast < ConfigOptionInt * > ( out . option ( key , false ) ) ;
assert ( opt ! = nullptr ) ;
2017-11-01 18:30:05 +00:00
opt - > value = boost : : algorithm : : clamp < int > ( opt - > value , 0 , int ( num_extruders ) ) ;
2017-10-30 17:41:50 +00:00
}
2019-05-22 09:31:36 +00:00
out . option < ConfigOptionString > ( " print_settings_id " , true ) - > value = this - > prints . get_selected_preset_name ( ) ;
2018-06-22 12:17:03 +00:00
out . option < ConfigOptionStrings > ( " filament_settings_id " , true ) - > values = this - > filament_presets ;
2019-05-22 09:31:36 +00:00
out . option < ConfigOptionString > ( " printer_settings_id " , true ) - > value = this - > printers . get_selected_preset_name ( ) ;
2018-06-26 08:50:50 +00:00
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
// The vector will not be stored if all fields are empty strings.
auto add_if_some_non_empty = [ & out ] ( std : : vector < std : : string > & & values , const std : : string & key ) {
bool nonempty = false ;
for ( const std : : string & v : values )
if ( ! v . empty ( ) ) {
nonempty = true ;
break ;
}
if ( nonempty )
out . set_key_value ( key , new ConfigOptionStrings ( std : : move ( values ) ) ) ;
} ;
2018-06-28 18:13:01 +00:00
add_if_some_non_empty ( std : : move ( compatible_printers_condition ) , " compatible_printers_condition_cummulative " ) ;
2018-12-04 16:56:49 +00:00
add_if_some_non_empty ( std : : move ( compatible_prints_condition ) , " compatible_prints_condition_cummulative " ) ;
2018-06-28 18:13:01 +00:00
add_if_some_non_empty ( std : : move ( inherits ) , " inherits_cummulative " ) ;
2018-11-08 19:18:40 +00:00
out . option < ConfigOptionEnumGeneric > ( " printer_technology " , true ) - > value = ptFFF ;
2017-10-30 17:41:50 +00:00
return out ;
}
2018-07-31 13:09:57 +00:00
DynamicPrintConfig PresetBundle : : full_sla_config ( ) const
{
DynamicPrintConfig out ;
2018-08-03 12:14:25 +00:00
out . apply ( SLAFullPrintConfig : : defaults ( ) ) ;
2018-11-16 16:36:23 +00:00
out . apply ( this - > sla_prints . get_edited_preset ( ) . config ) ;
2018-07-31 13:09:57 +00:00
out . apply ( this - > sla_materials . get_edited_preset ( ) . config ) ;
out . apply ( this - > printers . get_edited_preset ( ) . config ) ;
// There are no project configuration values as of now, the project_config is reserved for FFF printers.
// out.apply(this->project_config);
2018-11-16 16:36:23 +00:00
// Collect the "compatible_printers_condition" and "inherits" values over all presets (sla_prints, sla_materials, printers) into a single vector.
2018-07-31 13:09:57 +00:00
std : : vector < std : : string > compatible_printers_condition ;
2018-12-04 16:56:49 +00:00
std : : vector < std : : string > compatible_prints_condition ;
2018-07-31 13:09:57 +00:00
std : : vector < std : : string > inherits ;
2018-12-04 16:56:49 +00:00
compatible_printers_condition . emplace_back ( this - > sla_prints . get_edited_preset ( ) . compatible_printers_condition ( ) ) ;
inherits . emplace_back ( this - > sla_prints . get_edited_preset ( ) . inherits ( ) ) ;
compatible_printers_condition . emplace_back ( this - > sla_materials . get_edited_preset ( ) . compatible_printers_condition ( ) ) ;
compatible_prints_condition . emplace_back ( this - > sla_materials . get_edited_preset ( ) . compatible_prints_condition ( ) ) ;
inherits . emplace_back ( this - > sla_materials . get_edited_preset ( ) . inherits ( ) ) ;
2018-07-31 13:09:57 +00:00
inherits . emplace_back ( this - > printers . get_edited_preset ( ) . inherits ( ) ) ;
// These two value types clash between the print and filament profiles. They should be renamed.
out . erase ( " compatible_printers " ) ;
out . erase ( " compatible_printers_condition " ) ;
out . erase ( " inherits " ) ;
2019-05-22 09:31:36 +00:00
out . option < ConfigOptionString > ( " sla_print_settings_id " , true ) - > value = this - > sla_prints . get_selected_preset_name ( ) ;
out . option < ConfigOptionString > ( " sla_material_settings_id " , true ) - > value = this - > sla_materials . get_selected_preset_name ( ) ;
out . option < ConfigOptionString > ( " printer_settings_id " , true ) - > value = this - > printers . get_selected_preset_name ( ) ;
2018-07-31 13:09:57 +00:00
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
// The vector will not be stored if all fields are empty strings.
auto add_if_some_non_empty = [ & out ] ( std : : vector < std : : string > & & values , const std : : string & key ) {
bool nonempty = false ;
for ( const std : : string & v : values )
if ( ! v . empty ( ) ) {
nonempty = true ;
break ;
}
if ( nonempty )
out . set_key_value ( key , new ConfigOptionStrings ( std : : move ( values ) ) ) ;
} ;
add_if_some_non_empty ( std : : move ( compatible_printers_condition ) , " compatible_printers_condition_cummulative " ) ;
2018-12-04 16:56:49 +00:00
add_if_some_non_empty ( std : : move ( compatible_prints_condition ) , " compatible_prints_condition_cummulative " ) ;
2018-07-31 13:09:57 +00:00
add_if_some_non_empty ( std : : move ( inherits ) , " inherits_cummulative " ) ;
2018-11-08 19:18:40 +00:00
out . option < ConfigOptionEnumGeneric > ( " printer_technology " , true ) - > value = ptSLA ;
return out ;
2018-07-31 13:09:57 +00:00
}
2017-10-30 17:41:50 +00:00
// Load an external config file containing the print, filament and printer presets.
// Instead of a config file, a G-code may be loaded containing the full set of parameters.
// In the future the configuration will likely be read from an AMF file as well.
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
void PresetBundle : : load_config_file ( const std : : string & path )
2017-11-01 18:30:05 +00:00
{
2017-11-02 15:21:34 +00:00
if ( boost : : iends_with ( path , " .gcode " ) | | boost : : iends_with ( path , " .g " ) ) {
DynamicPrintConfig config ;
config . apply ( FullPrintConfig : : defaults ( ) ) ;
2018-02-13 14:19:55 +00:00
config . load_from_gcode_file ( path ) ;
Preset : : normalize ( config ) ;
2017-12-20 10:28:16 +00:00
load_config_file_config ( path , true , std : : move ( config ) ) ;
2017-11-02 15:21:34 +00:00
return ;
}
2017-11-01 18:30:05 +00:00
// 1) Try to load the config file into a boost property tree.
boost : : property_tree : : ptree tree ;
try {
boost : : nowide : : ifstream ifs ( path ) ;
boost : : property_tree : : read_ini ( ifs , tree ) ;
2017-11-28 09:08:01 +00:00
} catch ( const std : : ifstream : : failure & err ) {
throw std : : runtime_error ( std : : string ( " The config file cannot be loaded: " ) + path + " \n \t Reason: " + err . what ( ) ) ;
} catch ( const std : : runtime_error & err ) {
throw std : : runtime_error ( std : : string ( " Failed loading the preset file: " ) + path + " \n \t Reason: " + err . what ( ) ) ;
2017-11-01 18:30:05 +00:00
}
// 2) Continue based on the type of the configuration file.
ConfigFileType config_file_type = guess_config_file_type ( tree ) ;
switch ( config_file_type ) {
case CONFIG_FILE_TYPE_UNKNOWN :
throw std : : runtime_error ( std : : string ( " Unknown configuration file type: " ) + path ) ;
case CONFIG_FILE_TYPE_APP_CONFIG :
throw std : : runtime_error ( std : : string ( " Invalid configuration file: " ) + path + " . This is an application config file. " ) ;
2017-11-02 15:21:34 +00:00
case CONFIG_FILE_TYPE_CONFIG :
{
// Initialize a config from full defaults.
DynamicPrintConfig config ;
config . apply ( FullPrintConfig : : defaults ( ) ) ;
config . load ( tree ) ;
Preset : : normalize ( config ) ;
2017-12-20 10:28:16 +00:00
load_config_file_config ( path , true , std : : move ( config ) ) ;
2017-11-02 15:21:34 +00:00
break ;
}
2017-11-01 18:30:05 +00:00
case CONFIG_FILE_TYPE_CONFIG_BUNDLE :
2017-11-02 15:21:34 +00:00
load_config_file_config_bundle ( path , tree ) ;
2017-11-01 18:30:05 +00:00
break ;
}
}
// Load a config file from a boost property_tree. This is a private method called from load_config_file.
2017-12-20 10:28:16 +00:00
void PresetBundle : : load_config_file_config ( const std : : string & name_or_path , bool is_external , DynamicPrintConfig & & config )
2017-10-30 17:41:50 +00:00
{
2018-07-31 13:09:57 +00:00
PrinterTechnology printer_technology = Preset : : printer_technology ( config ) ;
2017-12-01 17:55:57 +00:00
// The "compatible_printers" field should not have been exported into a config.ini or a G-code anyway,
// but some of the alpha versions of Slic3r did.
{
ConfigOption * opt_compatible = config . optptr ( " compatible_printers " ) ;
if ( opt_compatible ! = nullptr ) {
assert ( opt_compatible - > type ( ) = = coStrings ) ;
if ( opt_compatible - > type ( ) = = coStrings )
static_cast < ConfigOptionStrings * > ( opt_compatible ) - > values . clear ( ) ;
}
}
2018-07-31 13:09:57 +00:00
size_t num_extruders = ( printer_technology = = ptFFF ) ?
std : : min ( config . option < ConfigOptionFloats > ( " nozzle_diameter " ) - > values . size ( ) ,
config . option < ConfigOptionFloats > ( " filament_diameter " ) - > values . size ( ) ) :
2018-12-03 12:14:28 +00:00
// 1 SLA material
1 ;
2018-06-28 18:13:01 +00:00
// Make a copy of the "compatible_printers_condition_cummulative" and "inherits_cummulative" vectors, which
2018-06-26 08:50:50 +00:00
// accumulate values over all presets (print, filaments, printers).
// These values will be distributed into their particular presets when loading.
2018-06-28 18:13:01 +00:00
std : : vector < std : : string > compatible_printers_condition_values = std : : move ( config . option < ConfigOptionStrings > ( " compatible_printers_condition_cummulative " , true ) - > values ) ;
2018-12-04 16:56:49 +00:00
std : : vector < std : : string > compatible_prints_condition_values = std : : move ( config . option < ConfigOptionStrings > ( " compatible_prints_condition_cummulative " , true ) - > values ) ;
2018-06-28 18:13:01 +00:00
std : : vector < std : : string > inherits_values = std : : move ( config . option < ConfigOptionStrings > ( " inherits_cummulative " , true ) - > values ) ;
std : : string & compatible_printers_condition = Preset : : compatible_printers_condition ( config ) ;
2018-12-04 16:56:49 +00:00
std : : string & compatible_prints_condition = Preset : : compatible_prints_condition ( config ) ;
2018-06-28 18:13:01 +00:00
std : : string & inherits = Preset : : inherits ( config ) ;
compatible_printers_condition_values . resize ( num_extruders + 2 , std : : string ( ) ) ;
2018-12-04 16:56:49 +00:00
compatible_prints_condition_values . resize ( num_extruders , std : : string ( ) ) ;
2018-06-28 18:13:01 +00:00
inherits_values . resize ( num_extruders + 2 , std : : string ( ) ) ;
2018-07-27 07:53:12 +00:00
// The "default_filament_profile" will be later extracted into the printer profile.
2018-12-03 12:14:28 +00:00
switch ( printer_technology ) {
case ptFFF :
config . option < ConfigOptionString > ( " default_print_profile " , true ) ;
config . option < ConfigOptionStrings > ( " default_filament_profile " , true ) - > values . resize ( num_extruders , std : : string ( ) ) ;
break ;
case ptSLA :
config . option < ConfigOptionString > ( " default_sla_print_profile " , true ) ;
config . option < ConfigOptionString > ( " default_sla_material_profile " , true ) ;
break ;
}
2018-06-26 08:50:50 +00:00
2017-11-02 15:21:34 +00:00
// 1) Create a name from the file name.
2017-10-30 17:41:50 +00:00
// Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles.
2017-12-20 10:28:16 +00:00
std : : string name = is_external ? boost : : filesystem : : path ( name_or_path ) . filename ( ) . string ( ) : name_or_path ;
2017-10-30 17:41:50 +00:00
2017-11-02 15:21:34 +00:00
// 2) If the loading succeeded, split and load the config into print / filament / printer settings.
2017-10-30 17:41:50 +00:00
// First load the print and printer presets.
2018-11-16 16:36:23 +00:00
2018-12-03 12:14:28 +00:00
auto load_preset =
2018-12-04 16:56:49 +00:00
[ & config , & inherits , & inherits_values ,
& compatible_printers_condition , & compatible_printers_condition_values ,
& compatible_prints_condition , & compatible_prints_condition_values ,
is_external , & name , & name_or_path ]
2018-12-03 12:14:28 +00:00
( PresetCollection & presets , size_t idx , const std : : string & key ) {
// Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles.
inherits = inherits_values [ idx ] ;
compatible_printers_condition = compatible_printers_condition_values [ idx ] ;
2018-12-04 16:56:49 +00:00
if ( idx > 0 & & idx - 1 < compatible_prints_condition_values . size ( ) )
compatible_prints_condition = compatible_prints_condition_values [ idx - 1 ] ;
2018-07-17 08:41:17 +00:00
if ( is_external )
2018-12-03 12:14:28 +00:00
presets . load_external_preset ( name_or_path , name , config . opt_string ( key , true ) , config ) ;
else
presets . load_preset ( presets . path_from_name ( name ) , name , config ) . save ( ) ;
} ;
switch ( Preset : : printer_technology ( config ) ) {
case ptFFF :
{
load_preset ( this - > prints , 0 , " print_settings_id " ) ;
load_preset ( this - > printers , num_extruders + 1 , " printer_settings_id " ) ;
2017-10-30 17:41:50 +00:00
2018-07-31 13:09:57 +00:00
// 3) Now load the filaments. If there are multiple filament presets, split them and load them.
auto old_filament_profile_names = config . option < ConfigOptionStrings > ( " filament_settings_id " , true ) ;
old_filament_profile_names - > values . resize ( num_extruders , std : : string ( ) ) ;
2018-06-28 18:13:01 +00:00
2018-07-31 13:09:57 +00:00
if ( num_extruders < = 1 ) {
2018-06-28 18:13:01 +00:00
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
2018-07-31 13:09:57 +00:00
inherits = inherits_values [ 1 ] ;
compatible_printers_condition = compatible_printers_condition_values [ 1 ] ;
2018-12-04 16:56:49 +00:00
compatible_prints_condition = compatible_prints_condition_values . front ( ) ;
2018-12-03 12:14:28 +00:00
Preset * loaded = nullptr ;
if ( is_external ) {
loaded = & this - > filaments . load_external_preset ( name_or_path , name , old_filament_profile_names - > values . front ( ) , config ) ;
} else {
loaded = & this - > filaments . load_preset ( this - > filaments . path_from_name ( name ) , name , config ) ;
loaded - > save ( ) ;
}
2018-07-31 13:09:57 +00:00
this - > filament_presets . clear ( ) ;
2018-12-03 12:14:28 +00:00
this - > filament_presets . emplace_back ( loaded - > name ) ;
2018-07-31 13:09:57 +00:00
} else {
// Split the filament presets, load each of them separately.
std : : vector < DynamicPrintConfig > configs ( num_extruders , this - > filaments . default_preset ( ) . config ) ;
// loop through options and scatter them into configs.
for ( const t_config_option_key & key : this - > filaments . default_preset ( ) . config . keys ( ) ) {
const ConfigOption * other_opt = config . option ( key ) ;
if ( other_opt = = nullptr )
continue ;
if ( other_opt - > is_scalar ( ) ) {
for ( size_t i = 0 ; i < configs . size ( ) ; + + i )
configs [ i ] . option ( key , false ) - > set ( other_opt ) ;
2018-12-04 16:56:49 +00:00
} else if ( key ! = " compatible_printers " & & key ! = " compatible_prints " ) {
2018-07-31 13:09:57 +00:00
for ( size_t i = 0 ; i < configs . size ( ) ; + + i )
static_cast < ConfigOptionVectorBase * > ( configs [ i ] . option ( key , false ) ) - > set_at ( other_opt , 0 , i ) ;
}
}
// Load the configs into this->filaments and make them active.
2019-08-20 16:45:12 +00:00
this - > filament_presets = std : : vector < std : : string > ( configs . size ( ) ) ;
// To avoid incorrect selection of the first filament preset (means a value of Preset->m_idx_selected)
// in a case when next added preset take a place of previosly selected preset,
// we should add presets from last to first
for ( int i = ( int ) configs . size ( ) - 1 ; i > = 0 ; i - - ) {
2018-07-31 13:09:57 +00:00
DynamicPrintConfig & cfg = configs [ i ] ;
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
cfg . opt_string ( " compatible_printers_condition " , true ) = compatible_printers_condition_values [ i + 1 ] ;
2018-12-04 16:56:49 +00:00
cfg . opt_string ( " compatible_prints_condition " , true ) = compatible_prints_condition_values [ i ] ;
2018-07-31 13:09:57 +00:00
cfg . opt_string ( " inherits " , true ) = inherits_values [ i + 1 ] ;
// Load all filament presets, but only select the first one in the preset dialog.
Preset * loaded = nullptr ;
if ( is_external )
loaded = & this - > filaments . load_external_preset ( name_or_path , name ,
( i < old_filament_profile_names - > values . size ( ) ) ? old_filament_profile_names - > values [ i ] : " " ,
std : : move ( cfg ) , i = = 0 ) ;
else {
// Used by the config wizard when creating a custom setup.
// Therefore this block should only be called for a single extruder.
char suffix [ 64 ] ;
if ( i = = 0 )
suffix [ 0 ] = 0 ;
else
2019-06-10 16:30:54 +00:00
sprintf ( suffix , " %d " , ( int ) i ) ;
2018-07-31 13:09:57 +00:00
std : : string new_name = name + suffix ;
loaded = & this - > filaments . load_preset ( this - > filaments . path_from_name ( new_name ) ,
new_name , std : : move ( cfg ) , i = = 0 ) ;
loaded - > save ( ) ;
}
2019-08-20 16:45:12 +00:00
this - > filament_presets [ i ] = loaded - > name ;
2018-06-26 09:31:01 +00:00
}
2017-10-30 17:41:50 +00:00
}
2018-07-31 13:09:57 +00:00
// 4) Load the project config values (the per extruder wipe matrix etc).
this - > project_config . apply_only ( config , s_project_options ) ;
2018-12-03 12:14:28 +00:00
break ;
}
case ptSLA :
load_preset ( this - > sla_prints , 0 , " sla_print_settings_id " ) ;
load_preset ( this - > sla_materials , 1 , " sla_material_settings_id " ) ;
load_preset ( this - > printers , 2 , " printer_settings_id " ) ;
break ;
2018-07-31 13:09:57 +00:00
}
2018-03-14 10:54:11 +00:00
2018-12-04 16:56:49 +00:00
this - > update_compatible ( false ) ;
2017-10-30 17:41:50 +00:00
}
2017-11-01 18:30:05 +00:00
// Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file.
void PresetBundle : : load_config_file_config_bundle ( const std : : string & path , const boost : : property_tree : : ptree & tree )
{
// 1) Load the config bundle into a temp data.
PresetBundle tmp_bundle ;
2017-12-19 18:51:22 +00:00
// Load the config bundle, don't save the loaded presets to user profile directory.
tmp_bundle . load_configbundle ( path , 0 ) ;
2017-11-28 10:57:33 +00:00
std : : string bundle_name = std : : string ( " - " ) + boost : : filesystem : : path ( path ) . filename ( ) . string ( ) ;
2017-11-01 18:30:05 +00:00
// 2) Extract active configs from the config bundle, copy them and activate them in this bundle.
2017-11-28 10:57:33 +00:00
auto load_one = [ this , & path , & bundle_name ] ( PresetCollection & collection_dst , PresetCollection & collection_src , const std : : string & preset_name_src , bool activate ) - > std : : string {
Preset * preset_src = collection_src . find_preset ( preset_name_src , false ) ;
Preset * preset_dst = collection_dst . find_preset ( preset_name_src , false ) ;
assert ( preset_src ! = nullptr ) ;
std : : string preset_name_dst ;
if ( preset_dst ! = nullptr & & preset_dst - > is_default ) {
// No need to copy a default preset, it always exists in collection_dst.
if ( activate )
collection_dst . select_preset ( 0 ) ;
return preset_name_src ;
} else if ( preset_dst ! = nullptr & & preset_src - > config = = preset_dst - > config ) {
2017-11-01 18:30:05 +00:00
// Don't save as the config exists in the current bundle and its content is the same.
2017-11-28 10:57:33 +00:00
return preset_name_src ;
2017-11-01 18:30:05 +00:00
} else {
// Generate a new unique name.
2017-11-28 10:57:33 +00:00
preset_name_dst = preset_name_src + bundle_name ;
Preset * preset_dup = nullptr ;
for ( size_t i = 1 ; ( preset_dup = collection_dst . find_preset ( preset_name_dst , false ) ) ! = nullptr ; + + i ) {
if ( preset_src - > config = = preset_dup - > config )
// The preset has been already copied into collection_dst.
return preset_name_dst ;
// Try to generate another name.
char buf [ 64 ] ;
2019-06-10 17:45:38 +00:00
sprintf ( buf , " (%d) " , ( int ) i ) ;
2017-11-28 10:57:33 +00:00
preset_name_dst = preset_name_src + buf + bundle_name ;
}
2017-11-01 18:30:05 +00:00
}
2017-11-28 10:57:33 +00:00
assert ( ! preset_name_dst . empty ( ) ) ;
// Save preset_src->config into collection_dst under preset_name_dst.
2017-12-01 17:55:57 +00:00
// The "compatible_printers" field should not have been exported into a config.ini or a G-code anyway,
// but some of the alpha versions of Slic3r did.
ConfigOption * opt_compatible = preset_src - > config . optptr ( " compatible_printers " ) ;
if ( opt_compatible ! = nullptr ) {
assert ( opt_compatible - > type ( ) = = coStrings ) ;
if ( opt_compatible - > type ( ) = = coStrings )
static_cast < ConfigOptionStrings * > ( opt_compatible ) - > values . clear ( ) ;
}
2017-11-28 10:57:33 +00:00
collection_dst . load_preset ( path , preset_name_dst , std : : move ( preset_src - > config ) , activate ) . is_external = true ;
return preset_name_dst ;
} ;
2019-05-22 09:31:36 +00:00
load_one ( this - > prints , tmp_bundle . prints , tmp_bundle . prints . get_selected_preset_name ( ) , true ) ;
load_one ( this - > sla_prints , tmp_bundle . sla_prints , tmp_bundle . sla_prints . get_selected_preset_name ( ) , true ) ;
load_one ( this - > filaments , tmp_bundle . filaments , tmp_bundle . filaments . get_selected_preset_name ( ) , true ) ;
load_one ( this - > sla_materials , tmp_bundle . sla_materials , tmp_bundle . sla_materials . get_selected_preset_name ( ) , true ) ;
load_one ( this - > printers , tmp_bundle . printers , tmp_bundle . printers . get_selected_preset_name ( ) , true ) ;
2017-11-28 10:57:33 +00:00
this - > update_multi_material_filament_presets ( ) ;
for ( size_t i = 1 ; i < std : : min ( tmp_bundle . filament_presets . size ( ) , this - > filament_presets . size ( ) ) ; + + i )
this - > filament_presets [ i ] = load_one ( this - > filaments , tmp_bundle . filaments , tmp_bundle . filament_presets [ i ] , false ) ;
2017-12-20 10:28:16 +00:00
2018-12-04 16:56:49 +00:00
this - > update_compatible ( false ) ;
2017-11-01 18:30:05 +00:00
}
2018-03-07 15:48:28 +00:00
// Process the Config Bundle loaded as a Boost property tree.
// For each print, filament and printer preset (group defined by group_name), apply the inherited presets.
// The presets starting with '*' are considered non-terminal and they are
// removed through the flattening process by this function.
// This function will never fail, but it will produce error messages through boost::log.
2019-01-08 09:52:11 +00:00
// system_profiles will not be flattened, and they will be kept inside the "inherits" field
static void flatten_configbundle_hierarchy ( boost : : property_tree : : ptree & tree , const std : : string & group_name , const std : : vector < std : : string > & system_profiles )
2018-03-07 15:48:28 +00:00
{
namespace pt = boost : : property_tree ;
typedef std : : pair < pt : : ptree : : key_type , pt : : ptree > ptree_child_type ;
// 1) For the group given by group_name, initialize the presets.
struct Prst {
Prst ( const std : : string & name , pt : : ptree * node ) : name ( name ) , node ( node ) { }
// Name of this preset. If the name starts with '*', it is an intermediate preset,
// which will not make it into the result.
const std : : string name ;
// Link to the source boost property tree node, owned by tree.
pt : : ptree * node ;
// Link to the presets, from which this preset inherits.
std : : vector < Prst * > inherits ;
// Link to the presets, for which this preset is a direct parent.
std : : vector < Prst * > parent_of ;
// When running the Kahn's Topological sorting algorithm, this counter is decreased from inherits.size() to zero.
// A cycle is indicated, if the number does not drop to zero after the Kahn's algorithm finishes.
size_t num_incoming_edges_left = 0 ;
// Sorting by the name, to be used when inserted into std::set.
bool operator = = ( const Prst & rhs ) const { return this - > name = = rhs . name ; }
bool operator < ( const Prst & rhs ) const { return this - > name < rhs . name ; }
} ;
// Find the presets, store them into a std::map, addressed by their names.
std : : set < Prst > presets ;
std : : string group_name_preset = group_name + " : " ;
for ( auto & section : tree )
if ( boost : : starts_with ( section . first , group_name_preset ) & & section . first . size ( ) > group_name_preset . size ( ) )
presets . emplace ( section . first . substr ( group_name_preset . size ( ) ) , & section . second ) ;
// Fill in the "inherits" and "parent_of" members, report invalid inheritance fields.
for ( const Prst & prst : presets ) {
// Parse the list of comma separated values, possibly enclosed in quotes.
std : : vector < std : : string > inherits_names ;
2019-01-08 09:52:11 +00:00
std : : vector < std : : string > inherits_system ;
2018-03-07 15:48:28 +00:00
if ( Slic3r : : unescape_strings_cstyle ( prst . node - > get < std : : string > ( " inherits " , " " ) , inherits_names ) ) {
// Resolve the inheritance by name.
std : : vector < Prst * > & inherits_nodes = const_cast < Prst & > ( prst ) . inherits ;
for ( const std : : string & node_name : inherits_names ) {
2019-01-08 09:52:11 +00:00
auto it_system = std : : lower_bound ( system_profiles . begin ( ) , system_profiles . end ( ) , node_name ) ;
if ( it_system ! = system_profiles . end ( ) & & * it_system = = node_name ) {
// Loading a user config budnle, this preset is derived from a system profile.
inherits_system . emplace_back ( node_name ) ;
} else {
auto it = presets . find ( Prst ( node_name , nullptr ) ) ;
if ( it = = presets . end ( ) )
BOOST_LOG_TRIVIAL ( error ) < < " flatten_configbundle_hierarchy: The preset " < < prst . name < < " inherits an unknown preset \" " < < node_name < < " \" " ;
else {
inherits_nodes . emplace_back ( const_cast < Prst * > ( & ( * it ) ) ) ;
inherits_nodes . back ( ) - > parent_of . emplace_back ( const_cast < Prst * > ( & prst ) ) ;
}
2018-03-07 15:48:28 +00:00
}
}
} else {
BOOST_LOG_TRIVIAL ( error ) < < " flatten_configbundle_hierarchy: The preset " < < prst . name < < " has an invalid \" inherits \" field " ;
}
2019-01-08 09:52:11 +00:00
// Remove the "inherits" key, it has no meaning outside of the config bundle.
2018-03-07 15:48:28 +00:00
const_cast < pt : : ptree * > ( prst . node ) - > erase ( " inherits " ) ;
2019-01-08 09:52:11 +00:00
if ( ! inherits_system . empty ( ) ) {
// Loaded a user config bundle, where a profile inherits a system profile.
// User profile should be derived from a single system profile only.
assert ( inherits_system . size ( ) = = 1 ) ;
if ( inherits_system . size ( ) > 1 )
BOOST_LOG_TRIVIAL ( error ) < < " flatten_configbundle_hierarchy: The preset " < < prst . name < < " inherits from more than single system preset " ;
prst . node - > put ( " inherits " , Slic3r : : escape_string_cstyle ( inherits_system . front ( ) ) ) ;
}
2018-03-07 15:48:28 +00:00
}
// 2) Create a linear ordering for the directed acyclic graph of preset inheritance.
// https://en.wikipedia.org/wiki/Topological_sorting
// Kahn's algorithm.
std : : vector < Prst * > sorted ;
{
// Initialize S with the set of all nodes with no incoming edge.
std : : deque < Prst * > S ;
for ( const Prst & prst : presets )
if ( prst . inherits . empty ( ) )
S . emplace_back ( const_cast < Prst * > ( & prst ) ) ;
else
const_cast < Prst * > ( & prst ) - > num_incoming_edges_left = prst . inherits . size ( ) ;
while ( ! S . empty ( ) ) {
Prst * n = S . front ( ) ;
S . pop_front ( ) ;
sorted . emplace_back ( n ) ;
for ( Prst * m : n - > parent_of ) {
assert ( m - > num_incoming_edges_left > 0 ) ;
if ( - - m - > num_incoming_edges_left = = 0 ) {
// We have visited all parents of m.
S . emplace_back ( m ) ;
}
}
}
if ( sorted . size ( ) < presets . size ( ) ) {
for ( const Prst & prst : presets )
if ( prst . num_incoming_edges_left )
BOOST_LOG_TRIVIAL ( error ) < < " flatten_configbundle_hierarchy: The preset " < < prst . name < < " has cyclic dependencies " ;
}
}
// Apply the dependencies in their topological ordering.
for ( Prst * prst : sorted ) {
// Merge the preset nodes in their order of application.
// Iterate in a reverse order, so the last change will be placed first in merged.
for ( auto it_inherits = prst - > inherits . rbegin ( ) ; it_inherits ! = prst - > inherits . rend ( ) ; + + it_inherits )
for ( auto it = ( * it_inherits ) - > node - > begin ( ) ; it ! = ( * it_inherits ) - > node - > end ( ) ; + + it )
if ( prst - > node - > find ( it - > first ) = = prst - > node - > not_found ( ) )
prst - > node - > add_child ( it - > first , it - > second ) ;
}
// Remove the "internal" presets from the ptree. These presets are marked with '*'.
group_name_preset + = ' * ' ;
for ( auto it_section = tree . begin ( ) ; it_section ! = tree . end ( ) ; ) {
if ( boost : : starts_with ( it_section - > first , group_name_preset ) & & it_section - > first . size ( ) > group_name_preset . size ( ) )
// Remove the "internal" preset from the ptree.
it_section = tree . erase ( it_section ) ;
else
// Keep the preset.
+ + it_section ;
}
}
2019-01-08 09:52:11 +00:00
// preset_bundle is set when loading user config bundles, which must not overwrite the system profiles.
static void flatten_configbundle_hierarchy ( boost : : property_tree : : ptree & tree , const PresetBundle * preset_bundle )
2018-03-07 15:48:28 +00:00
{
2019-01-08 09:52:11 +00:00
flatten_configbundle_hierarchy ( tree , " print " , preset_bundle ? preset_bundle - > prints . system_preset_names ( ) : std : : vector < std : : string > ( ) ) ;
flatten_configbundle_hierarchy ( tree , " filament " , preset_bundle ? preset_bundle - > filaments . system_preset_names ( ) : std : : vector < std : : string > ( ) ) ;
flatten_configbundle_hierarchy ( tree , " sla_print " , preset_bundle ? preset_bundle - > sla_prints . system_preset_names ( ) : std : : vector < std : : string > ( ) ) ;
flatten_configbundle_hierarchy ( tree , " sla_material " , preset_bundle ? preset_bundle - > sla_materials . system_preset_names ( ) : std : : vector < std : : string > ( ) ) ;
flatten_configbundle_hierarchy ( tree , " printer " , preset_bundle ? preset_bundle - > printers . system_preset_names ( ) : std : : vector < std : : string > ( ) ) ;
2018-03-07 15:48:28 +00:00
}
2017-10-30 17:41:50 +00:00
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
2017-12-19 18:51:22 +00:00
size_t PresetBundle : : load_configbundle ( const std : : string & path , unsigned int flags )
2017-10-30 17:41:50 +00:00
{
2018-03-09 15:37:33 +00:00
if ( flags & ( LOAD_CFGBNDLE_RESET_USER_PROFILE | LOAD_CFGBNDLE_SYSTEM ) )
// Reset this bundle, delete user profile files if LOAD_CFGBNDLE_SAVE.
2017-12-19 18:51:22 +00:00
this - > reset ( flags & LOAD_CFGBNDLE_SAVE ) ;
2017-10-30 17:41:50 +00:00
// 1) Read the complete config file into a boost::property_tree.
namespace pt = boost : : property_tree ;
pt : : ptree tree ;
boost : : nowide : : ifstream ifs ( path ) ;
pt : : read_ini ( ifs , tree ) ;
2018-03-09 15:37:33 +00:00
const VendorProfile * vendor_profile = nullptr ;
2018-03-13 11:39:57 +00:00
if ( flags & ( LOAD_CFGBNDLE_SYSTEM | LOAD_CFGBUNDLE_VENDOR_ONLY ) ) {
2018-04-12 18:04:48 +00:00
auto vp = VendorProfile : : from_ini ( tree , path ) ;
2018-03-09 15:37:33 +00:00
if ( vp . num_variants ( ) = = 0 )
return 0 ;
vendor_profile = & ( * this - > vendors . insert ( vp ) . first ) ;
}
2018-03-13 11:39:57 +00:00
if ( flags & LOAD_CFGBUNDLE_VENDOR_ONLY ) {
return 0 ;
}
// 1.5) Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
2019-01-08 09:52:11 +00:00
// If loading a user config bundle, do not flatten with the system profiles, but keep the "inherits" flag intact.
flatten_configbundle_hierarchy ( tree , ( ( flags & LOAD_CFGBNDLE_SYSTEM ) = = 0 ) ? this : nullptr ) ;
2018-03-09 15:37:33 +00:00
2017-10-30 17:41:50 +00:00
// 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
2018-05-16 14:34:07 +00:00
// Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure.
2017-10-30 17:41:50 +00:00
std : : vector < std : : string > loaded_prints ;
std : : vector < std : : string > loaded_filaments ;
2018-11-16 16:36:23 +00:00
std : : vector < std : : string > loaded_sla_prints ;
2018-07-31 13:09:57 +00:00
std : : vector < std : : string > loaded_sla_materials ;
2017-10-30 17:41:50 +00:00
std : : vector < std : : string > loaded_printers ;
std : : string active_print ;
std : : vector < std : : string > active_filaments ;
2018-11-16 16:36:23 +00:00
std : : string active_sla_print ;
2018-07-31 13:09:57 +00:00
std : : string active_sla_material ;
2017-10-30 17:41:50 +00:00
std : : string active_printer ;
size_t presets_loaded = 0 ;
for ( const auto & section : tree ) {
PresetCollection * presets = nullptr ;
std : : vector < std : : string > * loaded = nullptr ;
std : : string preset_name ;
if ( boost : : starts_with ( section . first , " print: " ) ) {
2018-03-09 15:37:33 +00:00
presets = & this - > prints ;
2017-10-30 17:41:50 +00:00
loaded = & loaded_prints ;
preset_name = section . first . substr ( 6 ) ;
} else if ( boost : : starts_with ( section . first , " filament: " ) ) {
2018-03-09 15:37:33 +00:00
presets = & this - > filaments ;
2017-10-30 17:41:50 +00:00
loaded = & loaded_filaments ;
preset_name = section . first . substr ( 9 ) ;
2018-11-16 16:36:23 +00:00
} else if ( boost : : starts_with ( section . first , " sla_print: " ) ) {
presets = & this - > sla_prints ;
loaded = & loaded_sla_prints ;
2018-11-19 10:10:22 +00:00
preset_name = section . first . substr ( 10 ) ;
2018-07-31 13:09:57 +00:00
} else if ( boost : : starts_with ( section . first , " sla_material: " ) ) {
presets = & this - > sla_materials ;
loaded = & loaded_sla_materials ;
2018-10-31 15:22:36 +00:00
preset_name = section . first . substr ( 13 ) ;
2017-10-30 17:41:50 +00:00
} else if ( boost : : starts_with ( section . first , " printer: " ) ) {
2018-03-09 15:37:33 +00:00
presets = & this - > printers ;
2017-10-30 17:41:50 +00:00
loaded = & loaded_printers ;
preset_name = section . first . substr ( 8 ) ;
} else if ( section . first = = " presets " ) {
// Load the names of the active presets.
for ( auto & kvp : section . second ) {
if ( kvp . first = = " print " ) {
active_print = kvp . second . data ( ) ;
} else if ( boost : : starts_with ( kvp . first , " filament " ) ) {
int idx = 0 ;
if ( kvp . first = = " filament " | | sscanf ( kvp . first . c_str ( ) , " filament_%d " , & idx ) = = 1 ) {
if ( int ( active_filaments . size ( ) ) < = idx )
active_filaments . resize ( idx + 1 , std : : string ( ) ) ;
active_filaments [ idx ] = kvp . second . data ( ) ;
}
2018-11-16 16:36:23 +00:00
} else if ( kvp . first = = " sla_print " ) {
active_sla_print = kvp . second . data ( ) ;
2018-07-31 13:09:57 +00:00
} else if ( kvp . first = = " sla_material " ) {
active_sla_material = kvp . second . data ( ) ;
2017-10-30 17:41:50 +00:00
} else if ( kvp . first = = " printer " ) {
active_printer = kvp . second . data ( ) ;
}
}
2018-05-16 14:34:07 +00:00
} else if ( section . first = = " obsolete_presets " ) {
// Parse the names of obsolete presets. These presets will be deleted from user's
// profile directory on installation of this vendor preset.
for ( auto & kvp : section . second ) {
std : : vector < std : : string > * dst = nullptr ;
if ( kvp . first = = " print " )
dst = & this - > obsolete_presets . prints ;
else if ( kvp . first = = " filament " )
dst = & this - > obsolete_presets . filaments ;
2018-11-16 16:36:23 +00:00
else if ( kvp . first = = " sla_print " )
dst = & this - > obsolete_presets . sla_prints ;
2018-07-31 13:09:57 +00:00
else if ( kvp . first = = " sla_material " )
dst = & this - > obsolete_presets . sla_materials ;
2018-05-16 14:34:07 +00:00
else if ( kvp . first = = " printer " )
dst = & this - > obsolete_presets . printers ;
if ( dst )
unescape_strings_cstyle ( kvp . second . data ( ) , * dst ) ;
}
2017-10-30 17:41:50 +00:00
} else if ( section . first = = " settings " ) {
// Load the settings.
for ( auto & kvp : section . second ) {
if ( kvp . first = = " autocenter " ) {
}
}
} else
// Ignore an unknown section.
continue ;
if ( presets ! = nullptr ) {
// Load the print, filament or printer preset.
2018-10-31 15:22:36 +00:00
const DynamicPrintConfig * default_config = nullptr ;
DynamicPrintConfig config ;
if ( presets = = & this - > printers ) {
// Select the default config based on the printer_technology field extracted from kvp.
DynamicPrintConfig config_src ;
for ( auto & kvp : section . second )
config_src . set_deserialize ( kvp . first , kvp . second . data ( ) ) ;
default_config = & presets - > default_preset_for ( config_src ) . config ;
config = * default_config ;
config . apply ( config_src ) ;
} else {
default_config = & presets - > default_preset ( ) . config ;
config = * default_config ;
for ( auto & kvp : section . second )
config . set_deserialize ( kvp . first , kvp . second . data ( ) ) ;
}
2017-11-02 15:21:34 +00:00
Preset : : normalize ( config ) ;
2018-05-22 12:17:27 +00:00
// Report configuration fields, which are misplaced into a wrong group.
2018-10-31 15:22:36 +00:00
std : : string incorrect_keys = Preset : : remove_invalid_keys ( config , * default_config ) ;
2018-05-22 12:17:27 +00:00
if ( ! incorrect_keys . empty ( ) )
BOOST_LOG_TRIVIAL ( error ) < < " Error in a Vendor Config Bundle \" " < < path < < " \" : The printer preset \" " < <
section . first < < " \" contains the following incorrect keys: " < < incorrect_keys < < " , which were removed " ;
2018-03-09 15:37:33 +00:00
if ( ( flags & LOAD_CFGBNDLE_SYSTEM ) & & presets = = & printers ) {
// Filter out printer presets, which are not mentioned in the vendor profile.
// These presets are considered not installed.
auto printer_model = config . opt_string ( " printer_model " ) ;
if ( printer_model . empty ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < " Error in a Vendor Config Bundle \" " < < path < < " \" : The printer preset \" " < <
section . first < < " \" defines no printer model, it will be ignored. " ;
continue ;
}
auto printer_variant = config . opt_string ( " printer_variant " ) ;
if ( printer_variant . empty ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < " Error in a Vendor Config Bundle \" " < < path < < " \" : The printer preset \" " < <
section . first < < " \" defines no printer variant, it will be ignored. " ;
continue ;
}
2018-03-13 11:39:57 +00:00
auto it_model = std : : find_if ( vendor_profile - > models . cbegin ( ) , vendor_profile - > models . cend ( ) ,
[ & ] ( const VendorProfile : : PrinterModel & m ) { return m . id = = printer_model ; }
) ;
2018-03-09 15:37:33 +00:00
if ( it_model = = vendor_profile - > models . end ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < " Error in a Vendor Config Bundle \" " < < path < < " \" : The printer preset \" " < <
section . first < < " \" defines invalid printer model \" " < < printer_model < < " \" , it will be ignored. " ;
continue ;
}
auto it_variant = it_model - > variant ( printer_variant ) ;
if ( it_variant = = nullptr ) {
BOOST_LOG_TRIVIAL ( error ) < < " Error in a Vendor Config Bundle \" " < < path < < " \" : The printer preset \" " < <
section . first < < " \" defines invalid printer variant \" " < < printer_variant < < " \" , it will be ignored. " ;
continue ;
}
const Preset * preset_existing = presets - > find_preset ( section . first , false ) ;
if ( preset_existing ! = nullptr ) {
BOOST_LOG_TRIVIAL ( error ) < < " Error in a Vendor Config Bundle \" " < < path < < " \" : The printer preset \" " < <
section . first < < " \" has already been loaded from another Confing Bundle. " ;
continue ;
}
2019-01-03 15:36:45 +00:00
} else if ( ( flags & LOAD_CFGBNDLE_SYSTEM ) = = 0 ) {
// This is a user config bundle.
const Preset * existing = presets - > find_preset ( preset_name , false ) ;
if ( existing ! = nullptr ) {
if ( existing - > is_system ) {
assert ( existing - > vendor ! = nullptr ) ;
BOOST_LOG_TRIVIAL ( error ) < < " Error in a user provided Config Bundle \" " < < path < < " \" : The " < < presets - > name ( ) < < " preset \" " < <
existing - > name < < " \" is a system preset of vendor " < < existing - > vendor - > name < < " and it will be ignored. " ;
continue ;
} else {
assert ( existing - > vendor = = nullptr ) ;
BOOST_LOG_TRIVIAL ( trace ) < < " A " < < presets - > name ( ) < < " preset \" " < < existing - > name < < " \" was overwritten with a preset from user Config Bundle \" " < < path < < " \" " ;
}
} else {
BOOST_LOG_TRIVIAL ( trace ) < < " A new " < < presets - > name ( ) < < " preset \" " < < preset_name < < " \" was imported from user Config Bundle \" " < < path < < " \" " ;
}
2018-03-09 15:37:33 +00:00
}
2017-12-10 21:11:00 +00:00
// Decide a full path to this .ini file.
auto file_name = boost : : algorithm : : iends_with ( preset_name , " .ini " ) ? preset_name : preset_name + " .ini " ;
2017-12-14 08:40:45 +00:00
auto file_path = ( boost : : filesystem : : path ( data_dir ( ) )
# ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
/ " presets "
# else
// Store the print/filament/printer presets at the same location as the upstream Slic3r.
# endif
2019-02-03 19:17:55 +00:00
/ presets - > section_name ( ) / file_name ) . make_preferred ( ) ;
2017-10-30 17:41:50 +00:00
// Load the preset into the list of presets, save it to disk.
2017-12-19 18:51:22 +00:00
Preset & loaded = presets - > load_preset ( file_path . string ( ) , preset_name , std : : move ( config ) , false ) ;
if ( flags & LOAD_CFGBNDLE_SAVE )
loaded . save ( ) ;
2018-03-09 15:37:33 +00:00
if ( flags & LOAD_CFGBNDLE_SYSTEM ) {
loaded . is_system = true ;
loaded . vendor = vendor_profile ;
}
2017-10-30 17:41:50 +00:00
+ + presets_loaded ;
}
}
// 3) Activate the presets.
2018-03-09 15:37:33 +00:00
if ( ( flags & LOAD_CFGBNDLE_SYSTEM ) = = 0 ) {
if ( ! active_print . empty ( ) )
prints . select_preset_by_name ( active_print , true ) ;
2018-11-16 16:36:23 +00:00
if ( ! active_sla_print . empty ( ) )
sla_materials . select_preset_by_name ( active_sla_print , true ) ;
2018-07-31 13:09:57 +00:00
if ( ! active_sla_material . empty ( ) )
sla_materials . select_preset_by_name ( active_sla_material , true ) ;
2018-03-09 15:37:33 +00:00
if ( ! active_printer . empty ( ) )
printers . select_preset_by_name ( active_printer , true ) ;
// Activate the first filament preset.
if ( ! active_filaments . empty ( ) & & ! active_filaments . front ( ) . empty ( ) )
filaments . select_preset_by_name ( active_filaments . front ( ) , true ) ;
this - > update_multi_material_filament_presets ( ) ;
for ( size_t i = 0 ; i < std : : min ( this - > filament_presets . size ( ) , active_filaments . size ( ) ) ; + + i )
this - > filament_presets [ i ] = filaments . find_preset ( active_filaments [ i ] , true ) - > name ;
2018-12-04 16:56:49 +00:00
this - > update_compatible ( false ) ;
2018-03-09 15:37:33 +00:00
}
2017-12-20 10:28:16 +00:00
2017-10-30 17:41:50 +00:00
return presets_loaded ;
}
void PresetBundle : : update_multi_material_filament_presets ( )
{
2018-08-01 09:09:51 +00:00
if ( printers . get_edited_preset ( ) . printer_technology ( ) ! = ptFFF )
return ;
2017-10-30 17:41:50 +00:00
// Verify and select the filament presets.
2017-11-01 18:30:05 +00:00
auto * nozzle_diameter = static_cast < const ConfigOptionFloats * > ( printers . get_edited_preset ( ) . config . option ( " nozzle_diameter " ) ) ;
2017-10-30 17:41:50 +00:00
size_t num_extruders = nozzle_diameter - > values . size ( ) ;
// Verify validity of the current filament presets.
for ( size_t i = 0 ; i < std : : min ( this - > filament_presets . size ( ) , num_extruders ) ; + + i )
this - > filament_presets [ i ] = this - > filaments . find_preset ( this - > filament_presets [ i ] , true ) - > name ;
// Append the rest of filament presets.
2018-07-02 18:25:37 +00:00
this - > filament_presets . resize ( num_extruders , this - > filament_presets . empty ( ) ? this - > filaments . first_visible ( ) . name : this - > filament_presets . back ( ) ) ;
2018-03-21 08:36:27 +00:00
// Now verify if wiping_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator):
2018-04-04 08:18:26 +00:00
std : : vector < double > old_matrix = this - > project_config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) - > values ;
2018-03-21 08:36:27 +00:00
size_t old_number_of_extruders = int ( sqrt ( old_matrix . size ( ) ) + EPSILON ) ;
2018-03-21 09:20:36 +00:00
if ( num_extruders ! = old_number_of_extruders ) {
// First verify if purging volumes presets for each extruder matches number of extruders
2018-04-04 08:18:26 +00:00
std : : vector < double > & extruders = this - > project_config . option < ConfigOptionFloats > ( " wiping_volumes_extruders " ) - > values ;
2018-03-21 08:36:27 +00:00
while ( extruders . size ( ) < 2 * num_extruders ) {
2018-03-21 09:20:36 +00:00
extruders . push_back ( extruders . size ( ) > 1 ? extruders [ 0 ] : 50. ) ; // copy the values from the first extruder
extruders . push_back ( extruders . size ( ) > 1 ? extruders [ 1 ] : 50. ) ;
2018-03-21 08:36:27 +00:00
}
while ( extruders . size ( ) > 2 * num_extruders ) {
extruders . pop_back ( ) ;
extruders . pop_back ( ) ;
}
2018-03-21 09:20:36 +00:00
2018-03-21 08:36:27 +00:00
std : : vector < double > new_matrix ;
for ( unsigned int i = 0 ; i < num_extruders ; + + i )
for ( unsigned int j = 0 ; j < num_extruders ; + + j ) {
// append the value for this pair from the old matrix (if it's there):
if ( i < old_number_of_extruders & & j < old_number_of_extruders )
new_matrix . push_back ( old_matrix [ i * old_number_of_extruders + j ] ) ;
else
new_matrix . push_back ( i = = j ? 0. : extruders [ 2 * i ] + extruders [ 2 * j + 1 ] ) ; // so it matches new extruder volumes
}
2018-04-04 08:18:26 +00:00
this - > project_config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) - > values = new_matrix ;
2018-03-21 08:36:27 +00:00
}
2017-10-30 17:41:50 +00:00
}
2018-12-04 16:56:49 +00:00
void PresetBundle : : update_compatible ( bool select_other_if_incompatible )
2017-11-10 16:27:05 +00:00
{
2018-12-04 16:56:49 +00:00
const Preset & printer_preset = this - > printers . get_edited_preset ( ) ;
2018-08-01 09:09:51 +00:00
2019-03-13 14:44:50 +00:00
switch ( printer_preset . printer_technology ( ) ) {
2018-08-01 09:09:51 +00:00
case ptFFF :
{
2018-12-03 12:14:28 +00:00
assert ( printer_preset . config . has ( " default_print_profile " ) ) ;
assert ( printer_preset . config . has ( " default_filament_profile " ) ) ;
2018-12-04 16:56:49 +00:00
const Preset & print_preset = this - > prints . get_edited_preset ( ) ;
2018-12-03 12:14:28 +00:00
const std : : string & prefered_print_profile = printer_preset . config . opt_string ( " default_print_profile " ) ;
2018-08-01 09:09:51 +00:00
const std : : vector < std : : string > & prefered_filament_profiles = printer_preset . config . option < ConfigOptionStrings > ( " default_filament_profile " ) - > values ;
prefered_print_profile . empty ( ) ?
2018-12-04 16:56:49 +00:00
this - > prints . update_compatible ( printer_preset , nullptr , select_other_if_incompatible ) :
this - > prints . update_compatible ( printer_preset , nullptr , select_other_if_incompatible ,
2018-10-31 11:56:08 +00:00
[ & prefered_print_profile ] ( const std : : string & profile_name ) { return profile_name = = prefered_print_profile ; } ) ;
2018-08-01 09:09:51 +00:00
prefered_filament_profiles . empty ( ) ?
2018-12-04 16:56:49 +00:00
this - > filaments . update_compatible ( printer_preset , & print_preset , select_other_if_incompatible ) :
this - > filaments . update_compatible ( printer_preset , & print_preset , select_other_if_incompatible ,
2018-08-01 09:09:51 +00:00
[ & prefered_filament_profiles ] ( const std : : string & profile_name )
{ return std : : find ( prefered_filament_profiles . begin ( ) , prefered_filament_profiles . end ( ) , profile_name ) ! = prefered_filament_profiles . end ( ) ; } ) ;
if ( select_other_if_incompatible ) {
// Verify validity of the current filament presets.
2019-03-18 14:10:40 +00:00
if ( this - > filament_presets . size ( ) = = 1 )
this - > filament_presets . front ( ) = this - > filaments . get_edited_preset ( ) . name ;
else
{
for ( size_t idx = 0 ; idx < this - > filament_presets . size ( ) ; + + idx ) {
std : : string & filament_name = this - > filament_presets [ idx ] ;
Preset * preset = this - > filaments . find_preset ( filament_name , false ) ;
if ( preset = = nullptr | | ! preset - > is_compatible ) {
// Pick a compatible profile. If there are prefered_filament_profiles, use them.
if ( prefered_filament_profiles . empty ( ) )
filament_name = this - > filaments . first_compatible ( ) . name ;
else {
const std : : string & preferred = ( idx < prefered_filament_profiles . size ( ) ) ?
prefered_filament_profiles [ idx ] : prefered_filament_profiles . front ( ) ;
filament_name = this - > filaments . first_compatible (
[ & preferred ] ( const std : : string & profile_name ) { return profile_name = = preferred ; } ) . name ;
}
2018-08-01 09:09:51 +00:00
}
2018-04-13 12:49:33 +00:00
}
}
2017-11-10 16:27:05 +00:00
}
2018-10-31 17:05:25 +00:00
break ;
2017-11-10 16:27:05 +00:00
}
2018-08-01 09:09:51 +00:00
case ptSLA :
{
2018-12-03 12:14:28 +00:00
assert ( printer_preset . config . has ( " default_sla_print_profile " ) ) ;
assert ( printer_preset . config . has ( " default_sla_material_profile " ) ) ;
2018-12-04 16:56:49 +00:00
const Preset & sla_print_preset = this - > sla_prints . get_edited_preset ( ) ;
2018-12-03 12:14:28 +00:00
const std : : string & prefered_sla_print_profile = printer_preset . config . opt_string ( " default_sla_print_profile " ) ;
( prefered_sla_print_profile . empty ( ) ) ?
2018-12-04 16:56:49 +00:00
this - > sla_prints . update_compatible ( printer_preset , nullptr , select_other_if_incompatible ) :
this - > sla_prints . update_compatible ( printer_preset , nullptr , select_other_if_incompatible ,
2018-12-03 12:14:28 +00:00
[ & prefered_sla_print_profile ] ( const std : : string & profile_name ) { return profile_name = = prefered_sla_print_profile ; } ) ;
const std : : string & prefered_sla_material_profile = printer_preset . config . opt_string ( " default_sla_material_profile " ) ;
2018-10-31 15:22:36 +00:00
prefered_sla_material_profile . empty ( ) ?
2018-12-04 16:56:49 +00:00
this - > sla_materials . update_compatible ( printer_preset , & sla_print_preset , select_other_if_incompatible ) :
this - > sla_materials . update_compatible ( printer_preset , & sla_print_preset , select_other_if_incompatible ,
2018-10-31 15:25:55 +00:00
[ & prefered_sla_material_profile ] ( const std : : string & profile_name ) { return profile_name = = prefered_sla_material_profile ; } ) ;
2018-10-31 17:05:25 +00:00
break ;
}
2018-08-01 09:09:51 +00:00
}
2017-11-10 16:27:05 +00:00
}
2018-12-12 17:37:10 +00:00
void PresetBundle : : export_configbundle ( const std : : string & path , bool export_system_settings )
2017-10-30 17:41:50 +00:00
{
boost : : nowide : : ofstream c ;
c . open ( path , std : : ios : : out | std : : ios : : trunc ) ;
// Put a comment at the first line including the time stamp and Slic3r version.
c < < " # " < < Slic3r : : header_slic3r_generated ( ) < < std : : endl ;
// Export the print, filament and printer profiles.
2018-11-16 16:36:23 +00:00
2018-12-12 17:37:10 +00:00
for ( const PresetCollection * presets : {
( const PresetCollection * ) & this - > prints , ( const PresetCollection * ) & this - > filaments ,
( const PresetCollection * ) & this - > sla_prints , ( const PresetCollection * ) & this - > sla_materials ,
( const PresetCollection * ) & this - > printers } ) {
for ( const Preset & preset : ( * presets ) ( ) ) {
if ( preset . is_default | | preset . is_external | | ( preset . is_system & & ! export_system_settings ) )
2017-10-30 17:41:50 +00:00
// Only export the common presets, not external files or the default preset.
continue ;
2019-02-03 19:17:55 +00:00
c < < std : : endl < < " [ " < < presets - > section_name ( ) < < " : " < < preset . name < < " ] " < < std : : endl ;
2017-10-30 17:41:50 +00:00
for ( const std : : string & opt_key : preset . config . keys ( ) )
2019-06-26 11:26:49 +00:00
c < < opt_key < < " = " < < preset . config . opt_serialize ( opt_key ) < < std : : endl ;
2017-10-30 17:41:50 +00:00
}
}
// Export the names of the active presets.
2017-11-01 18:30:05 +00:00
c < < std : : endl < < " [presets] " < < std : : endl ;
2019-05-22 09:31:36 +00:00
c < < " print = " < < this - > prints . get_selected_preset_name ( ) < < std : : endl ;
c < < " sla_print = " < < this - > sla_prints . get_selected_preset_name ( ) < < std : : endl ;
c < < " sla_material = " < < this - > sla_materials . get_selected_preset_name ( ) < < std : : endl ;
c < < " printer = " < < this - > printers . get_selected_preset_name ( ) < < std : : endl ;
2017-10-30 17:41:50 +00:00
for ( size_t i = 0 ; i < this - > filament_presets . size ( ) ; + + i ) {
char suffix [ 64 ] ;
if ( i > 0 )
2019-06-10 16:30:54 +00:00
sprintf ( suffix , " _%d " , ( int ) i ) ;
2017-10-30 17:41:50 +00:00
else
suffix [ 0 ] = 0 ;
c < < " filament " < < suffix < < " = " < < this - > filament_presets [ i ] < < std : : endl ;
}
2017-11-01 18:30:05 +00:00
#if 0
2017-10-30 17:41:50 +00:00
// Export the following setting values from the provided setting repository.
static const char * settings_keys [ ] = { " autocenter " } ;
2017-11-01 18:30:05 +00:00
c < < " [settings] " < < std : : endl ;
2017-10-30 17:41:50 +00:00
for ( size_t i = 0 ; i < sizeof ( settings_keys ) / sizeof ( settings_keys [ 0 ] ) ; + + i )
c < < settings_keys [ i ] < < " = " < < settings . serialize ( settings_keys [ i ] ) < < std : : endl ;
2017-11-01 18:30:05 +00:00
# endif
2017-10-30 17:41:50 +00:00
c . close ( ) ;
}
// Set the filament preset name. As the name could come from the UI selection box,
// an optional "(modified)" suffix will be removed from the filament name.
void PresetBundle : : set_filament_preset ( size_t idx , const std : : string & name )
{
2019-03-22 16:07:12 +00:00
if ( name . find_first_of ( PresetCollection : : separator_head ( ) ) = = 0 )
2018-04-20 15:32:08 +00:00
return ;
2017-10-30 17:41:50 +00:00
if ( idx > = filament_presets . size ( ) )
filament_presets . resize ( idx + 1 , filaments . default_preset ( ) . name ) ;
filament_presets [ idx ] = Preset : : remove_suffix_modified ( name ) ;
}
static inline int hex_digit_to_int ( const char c )
{
return
( c > = ' 0 ' & & c < = ' 9 ' ) ? int ( c - ' 0 ' ) :
( c > = ' A ' & & c < = ' F ' ) ? int ( c - ' A ' ) + 10 :
( c > = ' a ' & & c < = ' f ' ) ? int ( c - ' a ' ) + 10 : - 1 ;
}
2018-04-05 10:52:29 +00:00
bool PresetBundle : : parse_color ( const std : : string & scolor , unsigned char * rgb_out )
2017-10-30 17:41:50 +00:00
{
rgb_out [ 0 ] = rgb_out [ 1 ] = rgb_out [ 2 ] = 0 ;
if ( scolor . size ( ) ! = 7 | | scolor . front ( ) ! = ' # ' )
return false ;
2017-11-30 16:55:39 +00:00
const char * c = scolor . data ( ) + 1 ;
2017-10-30 17:41:50 +00:00
for ( size_t i = 0 ; i < 3 ; + + i ) {
int digit1 = hex_digit_to_int ( * c + + ) ;
int digit2 = hex_digit_to_int ( * c + + ) ;
if ( digit1 = = - 1 | | digit2 = = - 1 )
return false ;
rgb_out [ i ] = ( unsigned char ) ( digit1 * 16 + digit2 ) ;
}
return true ;
}
2019-04-09 15:40:14 +00:00
void PresetBundle : : load_default_preset_bitmaps ( wxWindow * window )
2019-04-08 07:37:23 +00:00
{
2019-04-10 07:56:32 +00:00
// Clear bitmap cache, before load new scaled default preset bitmaps
m_bitmapCache - > clear ( ) ;
this - > prints . clear_bitmap_cache ( ) ;
this - > sla_prints . clear_bitmap_cache ( ) ;
this - > filaments . clear_bitmap_cache ( ) ;
this - > sla_materials . clear_bitmap_cache ( ) ;
this - > printers . clear_bitmap_cache ( ) ;
2019-04-09 15:40:14 +00:00
this - > prints . load_bitmap_default ( window , " cog " ) ;
this - > sla_prints . load_bitmap_default ( window , " cog " ) ;
this - > filaments . load_bitmap_default ( window , " spool.png " ) ;
2019-04-10 07:41:04 +00:00
this - > sla_materials . load_bitmap_default ( window , " resin " ) ;
2019-04-09 15:40:14 +00:00
this - > printers . load_bitmap_default ( window , " printer " ) ;
this - > printers . load_bitmap_add ( window , " add.png " ) ;
this - > load_compatible_bitmaps ( window ) ;
2019-04-08 07:37:23 +00:00
}
2019-04-23 14:33:06 +00:00
void PresetBundle : : update_platter_filament_ui ( unsigned int idx_extruder , GUI : : PresetComboBox * ui )
2017-10-30 17:41:50 +00:00
{
2019-02-22 08:38:56 +00:00
if ( ui = = nullptr | | this - > printers . get_edited_preset ( ) . printer_technology ( ) = = ptSLA | |
2019-03-16 21:23:51 +00:00
this - > filament_presets . size ( ) < = idx_extruder )
2017-10-30 17:41:50 +00:00
return ;
unsigned char rgb [ 3 ] ;
std : : string extruder_color = this - > printers . get_edited_preset ( ) . config . opt_string ( " extruder_colour " , idx_extruder ) ;
if ( ! parse_color ( extruder_color , rgb ) )
// Extruder color is not defined.
extruder_color . clear ( ) ;
// Fill in the list from scratch.
ui - > Freeze ( ) ;
ui - > Clear ( ) ;
2018-06-29 09:29:23 +00:00
size_t selected_preset_item = 0 ;
2017-11-10 16:27:05 +00:00
const Preset * selected_preset = this - > filaments . find_preset ( this - > filament_presets [ idx_extruder ] ) ;
// Show wide icons if the currently selected preset is not compatible with the current printer,
// and draw a red flag in front of the selected preset.
bool wide_icons = selected_preset ! = nullptr & & ! selected_preset - > is_compatible & & m_bitmapIncompatible ! = nullptr ;
assert ( selected_preset ! = nullptr ) ;
2018-04-19 10:08:59 +00:00
std : : map < wxString , wxBitmap * > nonsys_presets ;
2018-04-11 11:56:37 +00:00
wxString selected_str = " " ;
2018-04-19 10:08:59 +00:00
if ( ! this - > filaments ( ) . front ( ) . is_visible )
2019-03-22 16:07:12 +00:00
ui - > set_label_marker ( ui - > Append ( PresetCollection : : separator ( L ( " System presets " ) ) , wxNullBitmap ) ) ;
2019-04-14 08:57:03 +00:00
/* It's supposed that standard size of an icon is 16px*16px for 100% scaled display.
* So set sizes for solid_colored icons used for filament preset
2019-04-23 14:33:06 +00:00
* and scale them in respect to em_unit value
2019-04-14 08:57:03 +00:00
*/
2019-04-23 14:33:06 +00:00
const float scale_f = ui - > em_unit ( ) * 0.1f ;
2019-08-25 08:31:18 +00:00
// To avoid the errors of number rounding for different combination of monitor configuration,
// let use scaled 8px, as a smallest icon unit
const int icon_unit = 8 * scale_f + 0.5f ;
const int icon_height = 2 * icon_unit ; //16 * scale_f + 0.5f;
const int normal_icon_width = 2 * icon_unit ; //16 * scale_f + 0.5f;
const int thin_icon_width = icon_unit ; //8 * scale_f + 0.5f;
const int wide_icon_width = 3 * icon_unit ; //24 * scale_f + 0.5f;
2019-04-14 08:57:03 +00:00
const int space_icon_width = 2 * scale_f + 0.5f ;
2018-04-19 10:08:59 +00:00
for ( int i = this - > filaments ( ) . front ( ) . is_visible ? 0 : 1 ; i < int ( this - > filaments ( ) . size ( ) ) ; + + i ) {
2017-11-10 16:27:05 +00:00
const Preset & preset = this - > filaments . preset ( i ) ;
bool selected = this - > filament_presets [ idx_extruder ] = = preset . name ;
if ( ! preset . is_visible | | ( ! preset . is_compatible & & ! selected ) )
2017-10-30 17:41:50 +00:00
continue ;
// Assign an extruder color to the selected item if the extruder color is defined.
std : : string filament_rgb = preset . config . opt_string ( " filament_colour " , 0 ) ;
std : : string extruder_rgb = ( selected & & ! extruder_color . empty ( ) ) ? extruder_color : filament_rgb ;
2017-11-10 16:27:05 +00:00
bool single_bar = filament_rgb = = extruder_rgb ;
std : : string bitmap_key = single_bar ? filament_rgb : filament_rgb + extruder_rgb ;
// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
// to the filament color image.
if ( wide_icons )
2018-03-12 15:04:32 +00:00
bitmap_key + = preset . is_compatible ? " ,cmpt " : " ,ncmpt " ;
bitmap_key + = ( preset . is_system | | preset . is_default ) ? " ,syst " : " ,nsyst " ;
2018-03-13 08:45:04 +00:00
if ( preset . is_dirty )
bitmap_key + = " ,drty " ;
2018-03-12 15:04:32 +00:00
wxBitmap * bitmap = m_bitmapCache - > find ( bitmap_key ) ;
2017-11-10 16:27:05 +00:00
if ( bitmap = = nullptr ) {
// Create the bitmap with color bars.
2018-03-12 15:04:32 +00:00
std : : vector < wxBitmap > bmps ;
if ( wide_icons )
// Paint a red flag for incompatible presets.
2019-04-14 08:57:03 +00:00
bmps . emplace_back ( preset . is_compatible ? m_bitmapCache - > mkclear ( normal_icon_width , icon_height ) : * m_bitmapIncompatible ) ;
2017-11-10 16:27:05 +00:00
// Paint the color bars.
parse_color ( filament_rgb , rgb ) ;
2019-04-14 08:57:03 +00:00
bmps . emplace_back ( m_bitmapCache - > mksolid ( single_bar ? wide_icon_width : normal_icon_width , icon_height , rgb ) ) ;
2017-11-10 16:27:05 +00:00
if ( ! single_bar ) {
parse_color ( extruder_rgb , rgb ) ;
2019-04-14 08:57:03 +00:00
bmps . emplace_back ( m_bitmapCache - > mksolid ( thin_icon_width , icon_height , rgb ) ) ;
2017-11-10 16:27:05 +00:00
}
2018-03-12 15:04:32 +00:00
// Paint a lock at the system presets.
2019-04-14 08:57:03 +00:00
bmps . emplace_back ( m_bitmapCache - > mkclear ( space_icon_width , icon_height ) ) ;
bmps . emplace_back ( ( preset . is_system | | preset . is_default ) ? * m_bitmapLock : m_bitmapCache - > mkclear ( normal_icon_width , icon_height ) ) ;
2018-04-19 10:08:59 +00:00
// (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16));
2018-03-12 15:04:32 +00:00
bitmap = m_bitmapCache - > insert ( bitmap_key , bmps ) ;
2017-10-30 17:41:50 +00:00
}
2018-04-11 11:56:37 +00:00
2018-10-31 11:56:08 +00:00
if ( preset . is_default | | preset . is_system ) {
2018-04-11 11:56:37 +00:00
ui - > Append ( wxString : : FromUTF8 ( ( preset . name + ( preset . is_dirty ? Preset : : suffix_modified ( ) : " " ) ) . c_str ( ) ) ,
( bitmap = = 0 ) ? wxNullBitmap : * bitmap ) ;
if ( selected )
2018-06-29 09:29:23 +00:00
selected_preset_item = ui - > GetCount ( ) - 1 ;
2018-04-11 11:56:37 +00:00
}
else
{
nonsys_presets . emplace ( wxString : : FromUTF8 ( ( preset . name + ( preset . is_dirty ? Preset : : suffix_modified ( ) : " " ) ) . c_str ( ) ) ,
2018-04-19 10:08:59 +00:00
( bitmap = = 0 ) ? & wxNullBitmap : bitmap ) ;
2018-04-11 11:56:37 +00:00
if ( selected )
selected_str = wxString : : FromUTF8 ( ( preset . name + ( preset . is_dirty ? Preset : : suffix_modified ( ) : " " ) ) . c_str ( ) ) ;
}
if ( preset . is_default )
2019-03-22 16:07:12 +00:00
ui - > set_label_marker ( ui - > Append ( PresetCollection : : separator ( L ( " System presets " ) ) , wxNullBitmap ) ) ;
2017-10-30 17:41:50 +00:00
}
2018-04-11 11:56:37 +00:00
if ( ! nonsys_presets . empty ( ) )
{
2019-03-22 16:07:12 +00:00
ui - > set_label_marker ( ui - > Append ( PresetCollection : : separator ( L ( " User presets " ) ) , wxNullBitmap ) ) ;
2018-04-19 10:08:59 +00:00
for ( std : : map < wxString , wxBitmap * > : : iterator it = nonsys_presets . begin ( ) ; it ! = nonsys_presets . end ( ) ; + + it ) {
ui - > Append ( it - > first , * it - > second ) ;
2018-04-11 11:56:37 +00:00
if ( it - > first = = selected_str )
2018-06-29 09:29:23 +00:00
selected_preset_item = ui - > GetCount ( ) - 1 ;
2018-04-11 11:56:37 +00:00
}
}
2018-06-29 09:29:23 +00:00
ui - > SetSelection ( selected_preset_item ) ;
ui - > SetToolTip ( ui - > GetString ( selected_preset_item ) ) ;
2019-03-23 09:04:44 +00:00
ui - > check_selection ( ) ;
2017-10-30 17:41:50 +00:00
ui - > Thaw ( ) ;
2019-04-23 14:33:06 +00:00
// Update control min size after rescale (changed Display DPI under MSW)
if ( ui - > GetMinWidth ( ) ! = 20 * ui - > em_unit ( ) )
ui - > SetMinSize ( wxSize ( 20 * ui - > em_unit ( ) , ui - > GetSize ( ) . GetHeight ( ) ) ) ;
2017-10-30 17:41:50 +00:00
}
void PresetBundle : : set_default_suppressed ( bool default_suppressed )
{
prints . set_default_suppressed ( default_suppressed ) ;
filaments . set_default_suppressed ( default_suppressed ) ;
2018-11-16 16:36:23 +00:00
sla_prints . set_default_suppressed ( default_suppressed ) ;
2018-08-09 07:25:23 +00:00
sla_materials . set_default_suppressed ( default_suppressed ) ;
2017-10-30 17:41:50 +00:00
printers . set_default_suppressed ( default_suppressed ) ;
}
} // namespace Slic3r