2024-09-03 09:34:33 +08:00
# ifdef WIN32
// Why?
# define _WIN32_WINNT 0x0502
// The standard Windows includes.
# define WIN32_LEAN_AND_MEAN
# define NOMINMAX
# include <Windows.h>
# include <wchar.h>
# ifdef SLIC3R_GUI
extern " C "
{
// Let the NVIDIA and AMD know we want to use their graphics card
// on a dual graphics card system.
__declspec ( dllexport ) DWORD NvOptimusEnablement = 0x00000001 ;
__declspec ( dllexport ) int AmdPowerXpressRequestHighPerformance = 1 ;
}
# endif /* SLIC3R_GUI */
# endif /* WIN32 */
# include <cstdio>
# include <string>
# include <cstring>
# include <iostream>
# include <math.h>
# if defined(__linux__) || defined(__LINUX__)
# include <condition_variable>
# include <mutex>
# include <boost/thread.hpp>
//add json logic
# include "nlohmann/json.hpp"
using namespace nlohmann ;
# endif
# include <boost/algorithm/string/predicate.hpp>
# include <boost/filesystem.hpp>
# include <boost/nowide/args.hpp>
# include <boost/nowide/cenv.hpp>
# include <boost/nowide/iostream.hpp>
# include <boost/nowide/fstream.hpp>
# include <boost/nowide/integration/filesystem.hpp>
# include <boost/dll/runtime_symbol_info.hpp>
# include <boost/log/trivial.hpp>
# include "unix/fhs.hpp" // Generated by CMake from ../platform/unix/fhs.hpp.in
# include "libslic3r/libslic3r.h"
# include "libslic3r/Config.hpp"
# include "libslic3r/Geometry.hpp"
# include "libslic3r/GCode/PostProcessor.hpp"
# include "libslic3r/Model.hpp"
# include "libslic3r/ModelArrange.hpp"
# include "libslic3r/Platform.hpp"
# include "libslic3r/Print.hpp"
# include "libslic3r/SLAPrint.hpp"
# include "libslic3r/TriangleMesh.hpp"
# include "libslic3r/Format/AMF.hpp"
# include "libslic3r/Format/3mf.hpp"
# include "libslic3r/Format/STL.hpp"
# include "libslic3r/Format/OBJ.hpp"
# include "libslic3r/Format/SL1.hpp"
# include "libslic3r/Utils.hpp"
# include "libslic3r/Time.hpp"
# include "libslic3r/Thread.hpp"
# include "libslic3r/BlacklistedLibraryCheck.hpp"
# include "libslic3r/FlushVolCalc.hpp"
# include "libslic3r/Orient.hpp"
# include "libslic3r/PNGReadWrite.hpp"
2024-09-16 16:07:29 +08:00
# include "libslic3r/ObjColorUtils.hpp"
2024-09-03 09:34:33 +08:00
# include "QIDIStudio.hpp"
//QDS: add exception handler for win32
# include <wx/stdpaths.h>
# ifdef WIN32
# include "BaseException.h"
# endif
# include "slic3r/GUI/PartPlate.hpp"
# include "slic3r/GUI/BitmapCache.hpp"
# include "slic3r/GUI/OpenGLManager.hpp"
# include "slic3r/GUI/GLCanvas3D.hpp"
# include "slic3r/GUI/Camera.hpp"
# include "slic3r/GUI/Plater.hpp"
2024-09-16 16:07:29 +08:00
# include "slic3r/GUI/GuiColor.hpp"
2024-09-03 09:34:33 +08:00
# include <GLFW/glfw3.h>
# ifdef __WXGTK__
# include <X11/Xlib.h>
# endif
# ifdef SLIC3R_GUI
# include "slic3r/GUI/GUI_Init.hpp"
# endif /* SLIC3R_GUI */
using namespace Slic3r ;
/*typedef struct _error_message{
int code ;
std : : string message ;
} error_message ; */
# define MAX_CLONEABLE_SIZE 512
std : : map < int , std : : string > cli_errors = {
{ CLI_SUCCESS , " Success. " } ,
{ CLI_ENVIRONMENT_ERROR , " Failed setting up server environment. " } ,
{ CLI_INVALID_PARAMS , " Invalid parameters to the slicer. " } ,
{ CLI_FILE_NOTFOUND , " The input files to the slicer are not found. " } ,
{ CLI_FILELIST_INVALID_ORDER , " File list order to the slicer is invalid. Please make sure the 3mf in the first place. " } ,
{ CLI_CONFIG_FILE_ERROR , " The input preset file is invalid and can not be parsed. " } ,
{ CLI_DATA_FILE_ERROR , " The input model file to the slicer can not be parsed. " } ,
{ CLI_INVALID_PRINTER_TECH , " Unsupported printer technology (not FDM). " } ,
{ CLI_UNSUPPORTED_OPERATION , " Unsupported CLI instruction. " } ,
{ CLI_COPY_OBJECTS_ERROR , " Failed copying objects. " } ,
{ CLI_SCALE_TO_FIT_ERROR , " Failed scaling an object to fit the plate. " } ,
{ CLI_EXPORT_STL_ERROR , " Failed exporting STL files. " } ,
{ CLI_EXPORT_OBJ_ERROR , " Failed exporting OBJ files. " } ,
{ CLI_EXPORT_3MF_ERROR , " Failed exporting 3mf files. " } ,
{ CLI_OUT_OF_MEMORY , " Out of memory during slicing. Please upload a model with lower geometry resolution and try again. " } ,
{ CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE , " The selected printer is not supported. " } ,
{ CLI_3MF_NEW_MACHINE_NOT_SUPPORTED , " The selected printer is not compatible with the 3mf. " } ,
{ CLI_PROCESS_NOT_COMPATIBLE , " The selected printer is not compatible with the process preset in the 3mf. " } ,
{ CLI_INVALID_VALUES_IN_3MF , " Invalid parameter value(s) included in the 3mf file. " } ,
{ CLI_POSTPROCESS_NOT_SUPPORTED , " post_process is not supported under CLI. " } ,
{ CLI_PRINTABLE_SIZE_REDUCED , " The selected printer's bed size is smaller than the bed size used in the print profile. " } ,
{ CLI_OBJECT_ARRANGE_FAILED , " An error occurred when auto-arranging object(s). " } ,
{ CLI_OBJECT_ORIENT_FAILED , " An error occurred when auto-orienting object(s). " } ,
{ CLI_MODIFIED_PARAMS_TO_PRINTER , " You cannot change the Printable Area, Printable Height, and Exclude Area in Printer Settings. " } ,
{ CLI_FILE_VERSION_NOT_SUPPORTED , " Unsupported 3MF version. Please make sure the 3MF file was created with the official version of QIDI Studio, not a beta version. " } ,
{ CLI_NO_SUITABLE_OBJECTS , " One of the plate is empty or has no object fully inside it. Please check that the 3mf contains no empty plate in QIDI Studio before uploading. " } ,
{ CLI_VALIDATE_ERROR , " There are some incorrect slicing parameters in the 3mf. Please verify the slicing of all plates in QIDI Studio before uploading. " } ,
{ CLI_OBJECTS_PARTLY_INSIDE , " Some objects are located over the boundary of the heated bed. " } ,
{ CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED , " Failed creating directory when exporting cache data. " } ,
{ CLI_EXPORT_CACHE_WRITE_FAILED , " Failed exporting cache data. " } ,
{ CLI_IMPORT_CACHE_NOT_FOUND , " Cache data not found. " } ,
{ CLI_IMPORT_CACHE_DATA_CAN_NOT_USE , " Cache data can not be parsed. " } ,
{ CLI_IMPORT_CACHE_LOAD_FAILED , " Failed importing cache data. " } ,
{ CLI_SLICING_TIME_EXCEEDS_LIMIT , " Slicing time of a certain plate exceeds the limit. Please simplify the model or use a larger slicing layer height. " } ,
{ CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT , " Triangle count of single plate exceeds the limit. Please simplify the model and try to upload again. " } ,
{ CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP , " No printable objects to slice after skipping. " } ,
{ CLI_FILAMENT_NOT_MATCH_BED_TYPE , " Filaments are not compatible with the plate type. Please verify the slicing of all plates in QIDI Studio before uploading. " } ,
{ CLI_FILAMENTS_DIFFERENT_TEMP , " The temperature difference of the filaments used is too large. Please verify the slicing of all plates in QIDI Studio before uploading. " } ,
{ CLI_OBJECT_COLLISION_IN_SEQ_PRINT , " Object conflicts were detected when using print-by-object mode. Please verify the slicing of all plates in QIDI Studio before uploading. " } ,
{ CLI_OBJECT_COLLISION_IN_LAYER_PRINT , " Object conflicts were detected. Please verify the slicing of all plates in QIDI Studio before uploading. " } ,
{ CLI_SPIRAL_MODE_INVALID_PARAMS , " Some slicing parameters cannot work with Spiral Vase mode. Please solve the issue in QIDI Studio before uploading. " } ,
{ CLI_SLICING_ERROR , " Failed slicing the model. Please verify the slicing of all plates on QIDI Studio before uploading. " } ,
{ CLI_GCODE_PATH_CONFLICTS , " G-code conflicts detected after slicing. Please make sure the 3mf file can be successfully sliced in the latest QIDI Studio. " }
} ;
typedef struct _sliced_plate_info {
int plate_id { 0 } ;
size_t sliced_time { 0 } ;
size_t sliced_time_with_cache { 0 } ;
2024-09-16 16:07:29 +08:00
//1.9.5
size_t make_perimeters_time { 0 } ;
size_t infill_time { 0 } ;
size_t generate_support_material_time { 0 } ;
2024-09-03 09:34:33 +08:00
size_t triangle_count { 0 } ;
std : : string warning_message ;
} sliced_plate_info_t ;
typedef struct _sliced_info {
int plate_count { 0 } ;
int plate_to_slice { 0 } ;
std : : vector < sliced_plate_info_t > sliced_plates ;
size_t prepare_time ;
size_t export_time ;
std : : vector < std : : string > upward_machines ;
std : : vector < std : : string > downward_machines ;
} sliced_info_t ;
std : : vector < PrintBase : : SlicingStatus > g_slicing_warnings ;
# if defined(__linux__) || defined(__LINUX__)
# define PIPE_BUFFER_SIZE 512
typedef struct _cli_callback_mgr {
int m_plate_count { 0 } ;
int m_plate_index { 0 } ;
int m_progress { 0 } ;
int m_total_progress { 0 } ;
std : : string m_message ;
int m_warning_step ;
bool m_exit { false } ;
bool m_data_ready { false } ;
bool m_started { false } ;
boost : : thread m_thread ;
// Mutex and condition variable to synchronize m_thread with the UI thread.
std : : mutex m_mutex ;
std : : condition_variable m_condition ;
int m_pipe_fd { - 1 } ;
bool is_started ( )
{
bool result ;
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
result = m_started ;
lck . unlock ( ) ;
return result ;
}
void set_plate_info ( int index , int count )
{
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : index= " < < index < < " , count = " < < count ;
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
m_plate_count = count ;
m_plate_index = index ;
m_progress = 0 ;
lck . unlock ( ) ;
return ;
}
void notify ( )
{
if ( m_pipe_fd < 0 )
return ;
json j ;
//record the headers
j [ " plate_index " ] = m_plate_index ;
j [ " plate_count " ] = m_plate_count ;
j [ " plate_percent " ] = m_progress ;
j [ " total_percent " ] = m_total_progress ;
if ( m_warning_step > = 0 )
j [ " warning " ] = m_message ;
else
j [ " message " ] = m_message ;
std : : string notify_message = j . dump ( ) ;
//notify_message = "Plate "+ std::to_string(m_plate_index) + "/" +std::to_string(m_plate_count)+ ": Percent " + std::to_string(m_progress) + ": "+m_message;
char pipe_message [ PIPE_BUFFER_SIZE ] = { 0 } ;
snprintf ( pipe_message , PIPE_BUFFER_SIZE , " %s \n " , notify_message . c_str ( ) ) ;
int ret = write ( m_pipe_fd , pipe_message , strlen ( pipe_message ) ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < " : write returns " < < ret ;
return ;
}
void thread_proc ( )
{
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
m_started = true ;
m_data_ready = false ;
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
boost : : this_thread : : sleep ( boost : : posix_time : : milliseconds ( 20 ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::thread_proc started. " ;
while ( 1 ) {
lck . lock ( ) ;
m_condition . wait ( lck , [ this ] ( ) { return m_data_ready | | m_exit ; } ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < " : wakup. " ;
if ( m_data_ready ) {
notify ( ) ;
m_data_ready = false ;
}
if ( m_exit ) {
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::thread_proc will exit. " ;
break ;
}
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
}
lck . unlock ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::thread_proc exit. " ;
}
void update ( int percent , std : : string message , int warning_step )
{
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
if ( ! m_started ) {
lck . unlock ( ) ;
return ;
}
if ( ( m_progress > = percent ) & & ( warning_step = = - 1 ) ) {
//already update before
lck . unlock ( ) ;
return ;
}
int old_total_progress = m_total_progress ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : percent= " < < percent < < " , warning_step= " < < warning_step < < " , plate_index = " < < m_plate_index < < " , plate_count= " < < m_plate_count < < " , message= " < < message ;
if ( warning_step = = - 1 ) {
m_progress = percent ;
if ( ( m_plate_count < = 1 ) & & ( m_plate_index > = 1 ) )
m_total_progress = 3 + 0.9 * m_progress ;
else if ( ( m_plate_count > 1 ) & & ( m_plate_index > = 1 ) ) {
m_total_progress = 3 + ( ( float ) ( m_plate_index - 1 ) * 90 ) / m_plate_count + ( ( float ) m_progress * 0.9 ) / m_plate_count ;
}
else
m_total_progress = m_progress ;
}
if ( m_total_progress < old_total_progress )
m_total_progress = old_total_progress ;
m_message = message ;
m_warning_step = warning_step ;
m_data_ready = true ;
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : m_total_progress= " < < m_total_progress ;
return ;
}
bool start ( std : : string pipe_name )
{
int retry_count = 0 ;
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::start enter. " ;
m_pipe_fd = open ( pipe_name . c_str ( ) , O_WRONLY | O_NONBLOCK ) ;
while ( m_pipe_fd < 0 ) {
if ( ( retry_count % 10 ) = = 0 )
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " could not open pipe for %1%, errno %2%, reason: %3%, retry_count = %4% " ) % pipe_name % errno % strerror ( errno ) % retry_count ;
retry_count + + ;
if ( retry_count > = 50 ) {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " reach max retry_count, failed to open pipe " ) ;
return false ;
}
boost : : this_thread : : sleep ( boost : : posix_time : : milliseconds ( 20 ) ) ;
m_pipe_fd = open ( pipe_name . c_str ( ) , O_WRONLY | O_NONBLOCK ) ;
}
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
m_thread = create_thread ( [ this ] {
this - > thread_proc ( ) ;
} ) ;
m_condition . wait ( lck , [ this ] ( ) { return m_started ; } ) ;
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::start successfully. " ;
return true ;
}
void stop ( )
{
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::stop enter. " ;
std : : unique_lock < std : : mutex > lck ( m_mutex ) ;
if ( ! m_started ) {
lck . unlock ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::stop not started before, return directly. " ;
return ;
}
m_exit = true ;
lck . unlock ( ) ;
m_condition . notify_one ( ) ;
// Wait until the worker thread exits.
m_thread . join ( ) ;
if ( m_pipe_fd > 0 ) {
close ( m_pipe_fd ) ;
m_pipe_fd = - 1 ;
}
BOOST_LOG_TRIVIAL ( info ) < < " cli_callback_mgr_t::stop successfully. " ;
}
} cli_callback_mgr_t ;
cli_callback_mgr_t g_cli_callback_mgr ;
void cli_status_callback ( const PrintBase : : SlicingStatus & slicing_status )
{
if ( slicing_status . warning_step ! = - 1 ) {
g_slicing_warnings . push_back ( slicing_status ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : percent=%1%, warning_step=%2%, message=%3%, message_type=%4%, flag=%5% " )
% slicing_status . percent % slicing_status . warning_step % slicing_status . text % ( int ) ( slicing_status . message_type ) % slicing_status . flags ;
}
g_cli_callback_mgr . update ( slicing_status . percent , slicing_status . text , slicing_status . warning_step ) ;
return ;
}
# endif
void default_status_callback ( const PrintBase : : SlicingStatus & slicing_status )
{
if ( slicing_status . warning_step ! = - 1 ) {
g_slicing_warnings . push_back ( slicing_status ) ;
}
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " : percent=%1%, warning_step=%2%, message=%3%, message_type=%4% " ) % slicing_status . percent % slicing_status . warning_step % slicing_status . text % ( int ) ( slicing_status . message_type ) ;
return ;
}
static PrinterTechnology get_printer_technology ( const DynamicConfig & config )
{
const ConfigOptionEnum < PrinterTechnology > * opt = config . option < ConfigOptionEnum < PrinterTechnology > > ( " printer_technology " ) ;
return ( opt = = nullptr ) ? ptUnknown : opt - > value ;
}
//QDS: add flush and exit
# if defined(__linux__) || defined(__LINUX__)
# define flush_and_exit(ret) { boost::nowide::cout << __FUNCTION__ << " found error, return "<<ret<<", exit..." << std::endl;\
g_cli_callback_mgr . stop ( ) ; \
boost : : nowide : : cout . flush ( ) ; \
boost : : nowide : : cerr . flush ( ) ; \
for ( Model & model : m_models ) { \
model . remove_backup_path_if_exist ( ) ; \
} \
return ( ret ) ; }
# else
# define flush_and_exit(ret) { boost::nowide::cout << __FUNCTION__ << " found error, exit" << std::endl;\
boost : : nowide : : cout . flush ( ) ; \
boost : : nowide : : cerr . flush ( ) ; \
for ( Model & model : m_models ) { \
model . remove_backup_path_if_exist ( ) ; \
} \
return ( ret ) ; }
# endif
void record_exit_reson ( std : : string outputdir , int code , int plate_id , std : : string error_message , sliced_info_t & sliced_info , std : : map < std : : string , std : : string > key_values = std : : map < std : : string , std : : string > ( ) )
{
# if defined(__linux__) || defined(__LINUX__)
std : : string result_file ;
if ( ! outputdir . empty ( ) )
result_file = outputdir + " /result.json " ;
else
result_file = " result.json " ;
try {
json j ;
//record the headers
if ( sliced_info . downward_machines . size ( ) > 0 )
j [ " downward_compatible_machine " ] = sliced_info . downward_machines ;
if ( sliced_info . upward_machines . size ( ) > 0 )
j [ " upward_compatible_machine " ] = sliced_info . upward_machines ;
j [ " plate_index " ] = plate_id ;
j [ " return_code " ] = code ;
j [ " error_string " ] = error_message ;
j [ " prepare_time " ] = sliced_info . prepare_time ;
j [ " export_time " ] = sliced_info . export_time ;
for ( size_t index = 0 ; index < sliced_info . sliced_plates . size ( ) ; index + + )
{
json plate_json ;
plate_json [ " id " ] = sliced_info . sliced_plates [ index ] . plate_id ;
plate_json [ " sliced_time " ] = sliced_info . sliced_plates [ index ] . sliced_time ;
plate_json [ " sliced_time_with_cache " ] = sliced_info . sliced_plates [ index ] . sliced_time_with_cache ;
2024-09-16 16:07:29 +08:00
//1.9.5
plate_json [ " make_perimeters_time " ] = sliced_info . sliced_plates [ index ] . make_perimeters_time ;
plate_json [ " infill_time " ] = sliced_info . sliced_plates [ index ] . infill_time ;
plate_json [ " generate_support_material_time " ] = sliced_info . sliced_plates [ index ] . generate_support_material_time ;
2024-09-03 09:34:33 +08:00
plate_json [ " triangle_count " ] = sliced_info . sliced_plates [ index ] . triangle_count ;
plate_json [ " warning_message " ] = sliced_info . sliced_plates [ index ] . warning_message ;
j [ " sliced_plates " ] . push_back ( plate_json ) ;
}
for ( auto & iter : key_values )
j [ iter . first ] = iter . second ;
boost : : nowide : : ofstream c ;
c . open ( result_file , std : : ios : : out | std : : ios : : trunc ) ;
c < < std : : setw ( 4 ) < < j < < std : : endl ;
c . close ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " : " < < __LINE__ < < boost : : format ( " , saved config to %1% \n " ) % result_file ;
}
catch ( . . . ) { }
# endif
}
static int decode_png_to_thumbnail ( std : : string png_file , ThumbnailData & thumbnail_data )
{
if ( ! boost : : filesystem : : exists ( png_file ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " can not find file %1% " ) % png_file ;
return - 1 ;
}
const std : : size_t & size = boost : : filesystem : : file_size ( png_file ) ;
std : : string png_buffer ( size , ' \0 ' ) ;
png_buffer . reserve ( size ) ;
boost : : filesystem : : ifstream ifs ( png_file , std : : ios : : binary ) ;
ifs . read ( png_buffer . data ( ) , png_buffer . size ( ) ) ;
ifs . close ( ) ;
Slic3r : : png : : ImageColorscale img ;
Slic3r : : png : : ReadBuf rb { png_buffer . data ( ) , png_buffer . size ( ) } ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " read png file %1%, size %2% " ) % png_file % size ;
if ( ! Slic3r : : png : : decode_colored_png ( rb , img ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " decode png file %1% failed " ) % png_file ;
return - 2 ;
}
thumbnail_data . width = img . cols ;
thumbnail_data . height = img . rows ;
thumbnail_data . pixels = std : : move ( img . buf ) ;
return 0 ;
}
static void glfw_callback ( int error_code , const char * description )
{
BOOST_LOG_TRIVIAL ( error ) < < " error_code " < < error_code < < " , description: " < < description < < std : : endl ;
}
const float bed3d_ax3s_default_stem_radius = 0.5f ;
const float bed3d_ax3s_default_stem_length = 25.0f ;
const float bed3d_ax3s_default_tip_radius = 2.5f * bed3d_ax3s_default_stem_radius ;
const float bed3d_ax3s_default_tip_length = 5.0f ;
static int load_key_values_from_json ( const std : : string & file , std : : map < std : : string , std : : string > & key_values )
{
json j ;
CNumericLocalesSetter locales_setter ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < " : begin to parse " < < file ;
try {
boost : : nowide : : ifstream ifs ( file ) ;
ifs > > j ;
ifs . close ( ) ;
//parse the json elements
for ( auto it = j . begin ( ) ; it ! = j . end ( ) ; it + + ) {
if ( boost : : iequals ( it . key ( ) , QDT_JSON_KEY_MODEL_ID ) ) {
key_values . emplace ( QDT_JSON_KEY_MODEL_ID , it . value ( ) ) ;
}
else if ( boost : : iequals ( it . key ( ) , QDT_JSON_KEY_NAME ) ) {
key_values . emplace ( QDT_JSON_KEY_NAME , it . value ( ) ) ;
}
}
}
catch ( const std : : ifstream : : failure & err ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " : parse " < < file < < " got a ifstream error, reason = " < < err . what ( ) ;
return - 1 ;
}
catch ( nlohmann : : detail : : parse_error & err ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " : parse " < < file < < " got a nlohmann::detail::parse_error, reason = " < < err . what ( ) ;
return - 2 ;
}
catch ( std : : exception & err ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " : parse " < < file < < " got a generic exception, reason = " < < err . what ( ) ;
return - 3 ;
}
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < " : finished parse, key_values size " < < key_values . size ( ) ;
return 0 ;
}
static std : : set < std : : string > gcodes_key_set = { " filament_end_gcode " , " filament_start_gcode " , " change_filament_gcode " , " layer_change_gcode " , " machine_end_gcode " , " machine_pause_gcode " , " machine_start_gcode " ,
" template_custom_gcode " , " printing_by_object_gcode " , " before_layer_change_gcode " , " time_lapse_gcode " } ;
static void load_default_gcodes_to_config ( DynamicPrintConfig & config , Preset : : Type type )
{
if ( config . size ( ) = = 0 ) {
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " , empty config, return directly " ;
return ;
}
//add those empty gcodes by default
if ( type = = Preset : : TYPE_PRINTER )
{
std : : string change_filament_gcode = config . option < ConfigOptionString > ( " change_filament_gcode " , true ) - > value ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , change_filament_gcode: " < < change_filament_gcode ;
ConfigOptionString * layer_change_gcode_opt = config . option < ConfigOptionString > ( " layer_change_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , layer_change_gcode: " < < layer_change_gcode_opt - > value ;
ConfigOptionString * machine_end_gcode_opt = config . option < ConfigOptionString > ( " machine_end_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , machine_end_gcode: " < < machine_end_gcode_opt - > value ;
ConfigOptionString * machine_pause_gcode_opt = config . option < ConfigOptionString > ( " machine_pause_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , machine_pause_gcode: " < < machine_pause_gcode_opt - > value ;
ConfigOptionString * machine_start_gcode_opt = config . option < ConfigOptionString > ( " machine_start_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , machine_start_gcode: " < < machine_start_gcode_opt - > value ;
ConfigOptionString * template_custom_gcode_opt = config . option < ConfigOptionString > ( " template_custom_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , template_custom_gcode: " < < template_custom_gcode_opt - > value ;
ConfigOptionString * printing_by_object_gcode_opt = config . option < ConfigOptionString > ( " printing_by_object_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , printing_by_object_gcode: " < < printing_by_object_gcode_opt - > value ;
ConfigOptionString * before_layer_change_gcode_opt = config . option < ConfigOptionString > ( " before_layer_change_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , before_layer_change_gcode: " < < before_layer_change_gcode_opt - > value ;
ConfigOptionString * timeplase_gcode_opt = config . option < ConfigOptionString > ( " time_lapse_gcode " , true ) ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , time_lapse_gcode: " < < timeplase_gcode_opt - > value ;
}
else if ( type = = Preset : : TYPE_FILAMENT )
{
std : : vector < std : : string > & filament_start_gcodes = config . option < ConfigOptionStrings > ( " filament_start_gcode " , true ) - > values ;
if ( filament_start_gcodes . empty ( ) ) {
filament_start_gcodes . resize ( 1 , std : : string ( ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " , set filament_start_gcodes to empty " ;
}
else {
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , filament_start_gcodes: " < < filament_start_gcodes [ 0 ] ;
}
std : : vector < std : : string > & filament_end_gcodes = config . option < ConfigOptionStrings > ( " filament_end_gcode " , true ) - > values ;
if ( filament_end_gcodes . empty ( ) ) {
filament_end_gcodes . resize ( 1 , std : : string ( ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " , set filament_end_gcode to empty " ;
}
else {
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " , filament_end_gcode: " < < filament_end_gcodes [ 0 ] ;
}
}
}
static int load_assemble_plate_list ( std : : string config_file , std : : vector < assemble_plate_info_t > & assemble_plate_info_list )
{
int ret = 0 ;
boost : : filesystem : : path directory_path ( config_file ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1% enter, file %2% " ) % __FUNCTION__ % config_file ;
if ( ! fs : : exists ( directory_path ) ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " directory %1% not exist. " ) % config_file ;
return CLI_FILE_NOTFOUND ;
}
try {
json root_json ;
boost : : nowide : : ifstream ifs ( config_file ) ;
ifs > > root_json ;
ifs . close ( ) ;
int plate_count = root_json [ JSON_ASSEMPLE_PLATES ] . size ( ) ;
if ( ( plate_count < = 0 ) | | ( plate_count > MAX_PLATE_COUNT ) ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : invalid plate count %1% " ) % plate_count ;
return CLI_CONFIG_FILE_ERROR ;
}
assemble_plate_info_list . resize ( plate_count ) ;
for ( int plate_index = 0 ; plate_index < plate_count ; plate_index + + )
{
assemble_plate_info_t & assemble_plate = assemble_plate_info_list [ plate_index ] ;
const json & plate_json = root_json [ JSON_ASSEMPLE_PLATES ] [ plate_index ] ;
assemble_plate . plate_name = plate_json [ JSON_ASSEMPLE_PLATE_NAME ] ;
assemble_plate . need_arrange = plate_json [ JSON_ASSEMPLE_PLATE_NEED_ARRANGE ] ;
if ( plate_json . contains ( JSON_ASSEMPLE_PLATE_PARAMS ) ) {
assemble_plate . plate_params = plate_json [ JSON_ASSEMPLE_PLATE_PARAMS ] . get < std : : map < std : : string , std : : string > > ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, has %2% plate params " ) % ( plate_index + 1 ) % assemble_plate . plate_params . size ( ) ;
}
int object_count = plate_json [ JSON_ASSEMPLE_OBJECTS ] . size ( ) ;
if ( object_count < = 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : invalid object count %1% in plate %2% " ) % object_count % ( plate_index + 1 ) ;
return CLI_CONFIG_FILE_ERROR ;
}
assemble_plate . assemble_obj_list . resize ( object_count ) ;
for ( int object_index = 0 ; object_index < object_count ; object_index + + )
{
assemble_object_info_t & assemble_object = assemble_plate . assemble_obj_list [ object_index ] ;
const json & object_json = plate_json [ JSON_ASSEMPLE_OBJECTS ] [ object_index ] ;
assemble_object . path = object_json [ JSON_ASSEMPLE_OBJECT_PATH ] ;
assemble_object . count = object_json [ JSON_ASSEMPLE_OBJECT_COUNT ] ;
if ( assemble_object . count < = 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : invalid object clone count %1% in plate %2% Object %3% " ) % assemble_object . count % ( plate_index + 1 ) % assemble_object . path ;
return CLI_CONFIG_FILE_ERROR ;
}
assemble_object . filaments = object_json . at ( JSON_ASSEMPLE_OBJECT_FILAMENTS ) . get < std : : vector < int > > ( ) ;
if ( ( assemble_object . filaments . size ( ) > 0 ) & & ( assemble_object . filaments . size ( ) ! = assemble_object . count ) & & ( assemble_object . filaments . size ( ) ! = 1 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : object %1%'s filaments count %2% not equal to clone count %3%, also not equal to 1 " ) % assemble_object . path % assemble_object . filaments . size ( ) % assemble_object . count ;
return CLI_CONFIG_FILE_ERROR ;
}
if ( object_json . contains ( JSON_ASSEMPLE_OBJECT_ASSEMBLE_INDEX ) ) {
assemble_object . assemble_index = object_json [ JSON_ASSEMPLE_OBJECT_ASSEMBLE_INDEX ] . get < std : : vector < int > > ( ) ;
if ( ( assemble_object . assemble_index . size ( ) > 0 ) & & ( assemble_object . assemble_index . size ( ) ! = assemble_object . count ) & & ( assemble_object . assemble_index . size ( ) ! = 1 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : object %1%'s assemble_index count %2% not equal to clone count %3%, also not equal to 1 " ) % assemble_object . path % assemble_object . assemble_index . size ( ) % assemble_object . count ;
return CLI_CONFIG_FILE_ERROR ;
}
}
if ( object_json . contains ( JSON_ASSEMPLE_OBJECT_POS_X ) ) {
assemble_object . pos_x = object_json [ JSON_ASSEMPLE_OBJECT_POS_X ] . get < std : : vector < float > > ( ) ;
if ( ( assemble_object . pos_x . size ( ) > 0 ) & & ( assemble_object . pos_x . size ( ) ! = assemble_object . count ) & & ( assemble_object . pos_x . size ( ) ! = 1 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : object %1%'s pos_x count %2% not equal to clone count %3%, also not equal to 1 " ) % assemble_object . path % assemble_object . pos_x . size ( ) % assemble_object . count ;
return CLI_CONFIG_FILE_ERROR ;
}
}
if ( object_json . contains ( JSON_ASSEMPLE_OBJECT_POS_Y ) ) {
assemble_object . pos_y = object_json [ JSON_ASSEMPLE_OBJECT_POS_Y ] . get < std : : vector < float > > ( ) ;
if ( ( assemble_object . pos_y . size ( ) > 0 ) & & ( assemble_object . pos_y . size ( ) ! = assemble_object . count ) & & ( assemble_object . pos_y . size ( ) ! = 1 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : object %1%'s pos_y count %2% not equal to clone count %3%, also not equal to 1 " ) % assemble_object . path % assemble_object . pos_y . size ( ) % assemble_object . count ;
return CLI_CONFIG_FILE_ERROR ;
}
}
if ( object_json . contains ( JSON_ASSEMPLE_OBJECT_POS_Z ) ) {
assemble_object . pos_z = object_json [ JSON_ASSEMPLE_OBJECT_POS_Z ] . get < std : : vector < float > > ( ) ;
if ( ( assemble_object . pos_z . size ( ) > 0 ) & & ( assemble_object . pos_z . size ( ) ! = assemble_object . count ) & & ( assemble_object . pos_z . size ( ) ! = 1 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : object %1%'s pos_z count %2% not equal to clone count %3%, also not equal to 1 " ) % assemble_object . path % assemble_object . pos_z . size ( ) % assemble_object . count ;
return CLI_CONFIG_FILE_ERROR ;
}
}
if ( object_json . contains ( JSON_ASSEMPLE_OBJECT_PRINT_PARAMS ) ) {
assemble_object . print_params = object_json [ JSON_ASSEMPLE_OBJECT_PRINT_PARAMS ] . get < std : : map < std : : string , std : : string > > ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, object %2% has %3% print params " ) % ( plate_index + 1 ) % assemble_object . path % assemble_object . print_params . size ( ) ;
}
if ( object_json . contains ( JSON_ASSEMPLE_OBJECT_HEIGHT_RANGES ) ) {
json height_range_json = object_json [ JSON_ASSEMPLE_OBJECT_HEIGHT_RANGES ] ;
int range_count = height_range_json . size ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, object %2% has %3% height ranges " ) % ( plate_index + 1 ) % assemble_object . path % range_count ;
assemble_object . height_ranges . resize ( range_count ) ;
for ( int range_index = 0 ; range_index < range_count ; range_index + + )
{
height_range_info_t & height_range = assemble_object . height_ranges [ range_index ] ;
height_range . min_z = height_range_json [ range_index ] [ JSON_ASSEMPLE_OBJECT_MIN_Z ] ;
height_range . max_z = height_range_json [ range_index ] [ JSON_ASSEMPLE_OBJECT_MAX_Z ] ;
height_range . range_params = height_range_json [ range_index ] [ JSON_ASSEMPLE_OBJECT_RANGE_PARAMS ] . get < std : : map < std : : string , std : : string > > ( ) ;
}
}
}
if ( plate_json . contains ( JSON_ASSEMPLE_ASSEMBLE_PARAMS ) ) {
json assemble_params_json = plate_json [ JSON_ASSEMPLE_ASSEMBLE_PARAMS ] ;
int assemble_count = assemble_params_json . size ( ) ;
for ( int i = 0 ; i < assemble_count ; i + + )
{
assembled_param_info_t assembled_param ;
int assemble_index = assemble_params_json [ i ] [ JSON_ASSEMPLE_OBJECT_ASSEMBLE_INDEX ] ;
if ( assemble_params_json [ i ] . contains ( JSON_ASSEMPLE_OBJECT_PRINT_PARAMS ) ) {
assembled_param . print_params = assemble_params_json [ i ] [ JSON_ASSEMPLE_OBJECT_PRINT_PARAMS ] . get < std : : map < std : : string , std : : string > > ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, assemble object %2% has %3% print params " ) % ( plate_index + 1 ) % i % assembled_param . print_params . size ( ) ;
}
if ( assemble_params_json [ i ] . contains ( JSON_ASSEMPLE_OBJECT_HEIGHT_RANGES ) ) {
json height_range_json = assemble_params_json [ i ] [ JSON_ASSEMPLE_OBJECT_HEIGHT_RANGES ] ;
int range_count = height_range_json . size ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, assemble object %2% has %3% height ranges " ) % ( plate_index + 1 ) % i % range_count ;
assembled_param . height_ranges . resize ( range_count ) ;
for ( int range_index = 0 ; range_index < range_count ; range_index + + )
{
height_range_info_t & height_range = assembled_param . height_ranges [ range_index ] ;
height_range . min_z = height_range_json [ range_index ] [ JSON_ASSEMPLE_OBJECT_MIN_Z ] ;
height_range . max_z = height_range_json [ range_index ] [ JSON_ASSEMPLE_OBJECT_MAX_Z ] ;
height_range . range_params = height_range_json [ range_index ] [ JSON_ASSEMPLE_OBJECT_RANGE_PARAMS ] . get < std : : map < std : : string , std : : string > > ( ) ;
}
}
assemble_plate . assembled_param_list . emplace ( assemble_index , std : : move ( assembled_param ) ) ;
}
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, has %2% plate params " ) % ( plate_index + 1 ) % assemble_plate . plate_params . size ( ) ;
}
}
}
catch ( std : : exception & err ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " : parse file " < < config_file < < " got a generic exception, reason = " < < err . what ( ) ;
ret = CLI_CONFIG_FILE_ERROR ;
}
return ret ;
}
void merge_or_add_object ( assemble_plate_info_t & assemble_plate_info , Model & model , int assemble_index , std : : map < int , ModelObject * > & merged_objects , ModelObject * ori_object )
{
if ( assemble_index > 0 ) {
auto iter = merged_objects . find ( assemble_index ) ;
ModelObject * new_object = nullptr ;
if ( iter = = merged_objects . end ( ) ) {
//create the object to merge
new_object = model . add_object ( ) ;
new_object - > name = " assemble_ " + std : : to_string ( assemble_index ) ;
merged_objects [ assemble_index ] = new_object ;
assemble_plate_info . loaded_obj_list . emplace_back ( new_object ) ;
new_object - > config . assign_config ( ori_object - > config . get ( ) ) ;
}
else
new_object = iter - > second ;
for ( auto volume : ori_object - > volumes ) {
ModelVolume * new_volume = new_object - > add_volume ( * volume ) ;
// set extruder id
new_volume - > config . set_key_value ( " extruder " , new ConfigOptionInt ( ori_object - > config . extruder ( ) ) ) ;
}
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " assemble_index %1%, name %2%, merged to new model %3% " ) % assemble_index % ori_object - > name % new_object - > name ;
}
else {
ModelObject * new_object = model . add_object ( * ori_object ) ;
assemble_plate_info . loaded_obj_list . emplace_back ( new_object ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " assemble_index %1%, name %2%, no need to merge, copy to new model " ) % assemble_index % ori_object - > name ;
}
}
2024-09-16 16:07:29 +08:00
//1.9.5
bool convert_obj_cluster_colors ( std : : vector < Slic3r : : RGBA > & input_colors , std : : vector < RGBA > & all_colours , int max_filament_count , std : : vector < unsigned char > & output_filament_ids , int & first_filament_id )
{
using namespace Slic3r : : GUI ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, got original input obj colors %3% " ) % __FUNCTION__ % __LINE__ % input_colors . size ( ) ;
if ( input_colors . size ( ) > 0 ) {
std : : vector < Slic3r : : RGBA > cluster_colors ;
std : : vector < int > cluster_labels ;
char cluster_number = - 1 ;
obj_color_deal_algo ( input_colors , cluster_colors , cluster_labels , cluster_number ) ;
std : : vector < int > cluster_color_maps ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, after obj_color_deal_algo, cluster_colors size %3%, all_colours size %4%, max_filament_count=%5% " ) % __FUNCTION__ % __LINE__ % cluster_colors . size ( ) % all_colours . size ( ) % max_filament_count ;
cluster_color_maps . resize ( cluster_colors . size ( ) , 1 ) ;
int init_size = all_colours . size ( ) ;
first_filament_id = max_filament_count ;
for ( size_t i = 0 ; i < cluster_colors . size ( ) ; i + + ) {
auto previous_color = std : : find ( all_colours . begin ( ) , all_colours . end ( ) , cluster_colors [ i ] ) ;
if ( previous_color ! = all_colours . end ( ) ) {
cluster_color_maps [ i ] = previous_color - all_colours . begin ( ) + 1 ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, cluster color index %3% RGBA {%4%,%5%,%6%,%7%} found same color before, id %8% " )
% __FUNCTION__ % __LINE__ % ( i + 1 ) % cluster_colors [ i ] [ 0 ] % cluster_colors [ i ] [ 1 ] % cluster_colors [ i ] [ 2 ] % cluster_colors [ i ] [ 3 ] % cluster_color_maps [ i ] ;
}
else {
if ( ( init_size + i + 1 ) < = max_filament_count ) {
all_colours . push_back ( cluster_colors [ i ] ) ;
cluster_color_maps [ i ] = all_colours . size ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, cluster color index %3% RGBA {%4%,%5%,%6%,%7%} directly inserted, id %8% " )
% __FUNCTION__ % __LINE__ % ( i + 1 ) % cluster_colors [ i ] [ 0 ] % cluster_colors [ i ] [ 1 ] % cluster_colors [ i ] [ 2 ] % cluster_colors [ i ] [ 3 ] % cluster_color_maps [ i ] ;
}
else {
std : : vector < ColorDistValue > color_dists ;
color_dists . resize ( max_filament_count ) ;
for ( size_t j = 0 ; j < max_filament_count ; j + + ) {
color_dists [ j ] . distance = calc_color_distance ( cluster_colors [ i ] , all_colours [ j ] ) ;
color_dists [ j ] . id = j + 1 ;
}
std : : sort ( color_dists . begin ( ) , color_dists . end ( ) , [ ] ( ColorDistValue & a , ColorDistValue & b ) { return a . distance < b . distance ; } ) ;
cluster_color_maps [ i ] = color_dists [ 0 ] . id ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, color size reaches to max, cluster color index %3% RGBA {%4%,%5%,%6%,%7%} mapped to id %8% " )
% __FUNCTION__ % __LINE__ % ( i + 1 ) % cluster_colors [ i ] [ 0 ] % cluster_colors [ i ] [ 1 ] % cluster_colors [ i ] [ 2 ] % cluster_colors [ i ] [ 3 ] % cluster_color_maps [ i ] ;
}
}
if ( cluster_color_maps [ i ] < first_filament_id )
first_filament_id = cluster_color_maps [ i ] ;
}
//3.generate filament_ids
auto input_colors_size = input_colors . size ( ) ;
output_filament_ids . resize ( input_colors_size ) ;
for ( size_t i = 0 ; i < input_colors_size ; i + + ) {
int label = cluster_labels [ i ] ;
output_filament_ids [ i ] = cluster_color_maps [ label ] ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, all_colours size changes to %3%, first_filament_id = %4% " ) % __FUNCTION__ % __LINE__ % all_colours . size ( ) % first_filament_id ;
return true ;
}
return false ;
}
2024-09-03 09:34:33 +08:00
# ifdef _WIN32
# define DIR_SEPARATOR '\\'
# else
# define DIR_SEPARATOR ' / '
# endif
2024-09-16 16:07:29 +08:00
//1.9.5
static int construct_assemble_list ( std : : vector < assemble_plate_info_t > & assemble_plate_info_list , Model & model , PlateDataPtrs & plate_list , std : : vector < RGBA > & all_colours )
2024-09-03 09:34:33 +08:00
{
int ret = 0 ;
int plate_count = assemble_plate_info_list . size ( ) ;
ConfigSubstitutionContext config_substitutions ( ForwardCompatibilitySubstitutionRule : : Enable ) ;
Model temp_model ;
2024-09-16 16:07:29 +08:00
//1.9.5
const int max_filament_count = size_t ( EnforcerBlockerType : : ExtruderMax ) ;
2024-09-03 09:34:33 +08:00
plate_list . resize ( plate_count ) ;
for ( int index = 0 ; index < plate_count ; index + + )
{
//each plate has its dependent assemble list
std : : map < int , ModelObject * > merged_objects ;
std : : set < int > used_filaments ;
//std::map<ModelObject*, int> to_merge_objects;
assemble_plate_info_t & assemble_plate_info = assemble_plate_info_list [ index ] ;
int object_count = assemble_plate_info . assemble_obj_list . size ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : Plate %1%, name %2%, obj count %3%, plate params count %4% " ) % ( index + 1 ) % assemble_plate_info . plate_name % object_count % assemble_plate_info . plate_params . size ( ) ;
PlateData * plate_data = new PlateData ( ) ;
plate_list [ index ] = plate_data ;
plate_data - > plate_name = assemble_plate_info . plate_name ;
plate_data - > plate_index = index ;
if ( ! assemble_plate_info . plate_params . empty ( ) )
{
for ( auto plate_iter = assemble_plate_info . plate_params . begin ( ) ; plate_iter ! = assemble_plate_info . plate_params . end ( ) ; plate_iter + + )
{
plate_data - > config . set_deserialize ( plate_iter - > first , plate_iter - > second , config_substitutions ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " : Plate %1%, key %2%, value %3% " ) % ( index + 1 ) % plate_iter - > first % plate_iter - > second ;
}
}
//construct the object list
for ( size_t obj_index = 0 ; obj_index < object_count ; obj_index + + )
{
assemble_object_info_t & assemble_object = assemble_plate_info . assemble_obj_list [ obj_index ] ;
std : : string object_name ;
2024-09-16 16:07:29 +08:00
//1.9.5
std : : string object_1_name ;
ModelObject * object = nullptr ;
2024-09-03 09:34:33 +08:00
TriangleMesh mesh ;
2024-09-16 16:07:29 +08:00
bool skip_filament = false ;
2024-09-03 09:34:33 +08:00
boost : : filesystem : : path object_path ( assemble_object . path ) ;
if ( ! fs : : exists ( object_path ) ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : directory %1% not exist in plate %2% " ) % assemble_object . path % ( index + 1 ) ;
return CLI_FILE_NOTFOUND ;
}
const char * path_str = assemble_object . path . c_str ( ) ;
const char * last_slash = strrchr ( path_str , DIR_SEPARATOR ) ;
object_name . assign ( ( last_slash = = nullptr ) ? path_str : last_slash + 1 ) ;
if ( boost : : algorithm : : iends_with ( assemble_object . path , " .stl " ) )
{
if ( ! mesh . ReadSTLFile ( path_str , true , nullptr ) ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : failed to read stl file from %1%, plate index %2%, object index %3% " ) % assemble_object . path % ( index + 1 ) % ( obj_index + 1 ) ;
return CLI_DATA_FILE_ERROR ;
}
if ( mesh . empty ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : found no mesh data from stl file %1%, plate index %2%, object index %3% " ) % assemble_object . path % ( index + 1 ) % ( obj_index + 1 ) ;
return CLI_DATA_FILE_ERROR ;
}
2024-09-16 16:07:29 +08:00
//1.9.5
object_name . erase ( object_name . end ( ) - 4 , object_name . end ( ) ) ;
object_1_name = object_name + " _1 " ;
object = temp_model . add_object ( object_1_name . c_str ( ) , path_str , std : : move ( mesh ) ) ;
if ( ! object ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : add_object %1% for stl failed, plate index %2%, object index %3% " ) % object_1_name % ( index + 1 ) % ( obj_index + 1 ) ;
return CLI_DATA_FILE_ERROR ;
}
2024-09-03 09:34:33 +08:00
}
else if ( boost : : algorithm : : iends_with ( assemble_object . path , " .obj " ) )
{
std : : string message ;
ObjInfo obj_info ;
bool result = load_obj ( path_str , & mesh , obj_info , message ) ;
if ( ! result ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : failed to read a valid mesh from obj file %1%, plate index %2%, object index %3%, error %4% " ) % assemble_object . path % ( index + 1 ) % ( obj_index + 1 ) % message ;
return CLI_DATA_FILE_ERROR ;
}
2024-09-16 16:07:29 +08:00
//1.9.5
object_name . erase ( object_name . end ( ) - 4 , object_name . end ( ) ) ;
object_1_name = object_name + " _1 " ;
//process colors
Model obj_temp_model ;
ModelObject * temp_object = obj_temp_model . add_object ( object_1_name . c_str ( ) , path_str , std : : move ( mesh ) ) ;
if ( ! temp_object ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : add_object %1% for obj failed, plate index %2%, object index %3% " ) % object_1_name % ( index + 1 ) % ( obj_index + 1 ) ;
return CLI_DATA_FILE_ERROR ;
}
std : : vector < unsigned char > output_filament_ids ;
int first_filament_id ;
if ( obj_info . vertex_colors . size ( ) > 0 ) {
convert_obj_cluster_colors ( obj_info . vertex_colors , all_colours , max_filament_count , output_filament_ids , first_filament_id ) ;
if ( output_filament_ids . size ( ) > 0 ) {
unsigned char first_eid = ( unsigned char ) first_filament_id ;
result = Model : : obj_import_vertex_color_deal ( output_filament_ids , first_eid , & obj_temp_model ) ;
}
skip_filament = true ;
} else if ( obj_info . face_colors . size ( ) > 0 & & obj_info . has_uv_png = = false ) { // mtl file
convert_obj_cluster_colors ( obj_info . face_colors , all_colours , max_filament_count , output_filament_ids , first_filament_id ) ;
if ( output_filament_ids . size ( ) > 0 ) {
unsigned char first_eid = ( unsigned char ) first_filament_id ;
result = Model : : obj_import_face_color_deal ( output_filament_ids , first_eid , & obj_temp_model ) ;
}
skip_filament = true ;
}
if ( ! result ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : failed to convert colors for %1%, plate index %2%, object index %3%, error %4% " ) % assemble_object . path % ( index + 1 ) % ( obj_index + 1 ) % message ;
return CLI_DATA_FILE_ERROR ;
}
object = temp_model . add_object ( * temp_object ) ;
if ( ! object ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : add_object %1% for stl failed, plate index %2%, object index %3% " ) % object_1_name % ( index + 1 ) % ( obj_index + 1 ) ;
return CLI_DATA_FILE_ERROR ;
}
obj_temp_model . clear_objects ( ) ;
obj_temp_model . clear_materials ( ) ;
2024-09-03 09:34:33 +08:00
}
else {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : unsupported file %1%, plate index %2%, object index %3% " ) % assemble_object . path % ( index + 1 ) % ( obj_index + 1 ) ;
return CLI_INVALID_PARAMS ;
}
2024-09-16 16:07:29 +08:00
//1.9.5
if ( ! skip_filament ) {
object - > config . set_key_value ( " extruder " , new ConfigOptionInt ( assemble_object . filaments [ 0 ] ) ) ;
used_filaments . emplace ( assemble_object . filaments [ 0 ] ) ;
}
else {
assemble_object . filaments [ 0 ] = 0 ;
for ( const ModelVolume * mv : object - > volumes ) {
std : : vector < int > volume_extruders = mv - > get_extruders ( ) ;
used_filaments . insert ( volume_extruders . begin ( ) , volume_extruders . end ( ) ) ;
}
2024-09-03 09:34:33 +08:00
}
if ( ! assemble_object . print_params . empty ( ) )
{
for ( auto param_iter = assemble_object . print_params . begin ( ) ; param_iter ! = assemble_object . print_params . end ( ) ; param_iter + + )
{
object - > config . set_deserialize ( param_iter - > first , param_iter - > second , config_substitutions ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, object %2% key %3%, value %4% " ) % ( index + 1 ) % object_1_name % param_iter - > first % param_iter - > second ;
}
}
if ( ! assemble_object . height_ranges . empty ( ) )
{
for ( int range_index = 0 ; range_index < assemble_object . height_ranges . size ( ) ; range_index + + )
{
height_range_info_t & range = assemble_object . height_ranges [ range_index ] ;
DynamicPrintConfig range_config ;
for ( auto range_config_iter = range . range_params . begin ( ) ; range_config_iter ! = range . range_params . end ( ) ; range_config_iter + + )
{
range_config . set_deserialize ( range_config_iter - > first , range_config_iter - > second , config_substitutions ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " object %1%, height range %2% key %3%, value %4% " ) % object_1_name % range_index % range_config_iter - > first % range_config_iter - > second ;
}
object - > layer_config_ranges [ { range . min_z , range . max_z } ] . assign_config ( std : : move ( range_config ) ) ;
}
}
if ( assemble_object . pos_x . empty ( ) )
assemble_object . pos_x . resize ( 1 , 0.f ) ;
if ( assemble_object . pos_y . empty ( ) )
assemble_object . pos_y . resize ( 1 , 0.f ) ;
if ( assemble_object . pos_z . empty ( ) )
assemble_object . pos_z . resize ( 1 , 0.f ) ;
if ( assemble_object . assemble_index . empty ( ) )
assemble_object . assemble_index . resize ( 1 , 0 ) ;
object - > translate ( assemble_object . pos_x [ 0 ] , assemble_object . pos_y [ 0 ] , assemble_object . pos_z [ 0 ] ) ;
merge_or_add_object ( assemble_plate_info , model , assemble_object . assemble_index [ 0 ] , merged_objects , object ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " : object %1%, name %2%, pos_x %3% pos_y %4%, pos_z %5%, filament %6%, assemble_index %7% " )
% obj_index % object - > name % assemble_object . pos_x [ 0 ] % assemble_object . pos_y [ 0 ] % assemble_object . pos_z [ 0 ] % assemble_object . filaments [ 0 ] % assemble_object . assemble_index [ 0 ] ;
for ( size_t copy_index = 1 ; copy_index < assemble_object . count ; copy_index + + )
{
int array_index = copy_index ;
ModelObject * copy_obj = temp_model . add_object ( * object ) ;
copy_obj - > name = object_name + " _ " + std : : to_string ( copy_index + 1 ) ;
if ( copy_index > = assemble_object . pos_x . size ( ) )
array_index = 0 ;
copy_obj - > translate ( assemble_object . pos_x [ array_index ] , assemble_object . pos_y [ array_index ] , assemble_object . pos_z [ array_index ] ) ;
if ( copy_index < assemble_object . filaments . size ( ) )
array_index = copy_index ;
else
array_index = 0 ;
2024-09-16 16:07:29 +08:00
//1.9.5
if ( ! skip_filament ) {
copy_obj - > config . set_key_value ( " extruder " , new ConfigOptionInt ( assemble_object . filaments [ array_index ] ) ) ;
used_filaments . emplace ( assemble_object . filaments [ array_index ] ) ;
}
else {
assemble_object . filaments [ array_index ] = 0 ;
}
2024-09-03 09:34:33 +08:00
if ( copy_index < assemble_object . assemble_index . size ( ) )
array_index = copy_index ;
else
array_index = 0 ;
merge_or_add_object ( assemble_plate_info , model , assemble_object . assemble_index [ array_index ] , merged_objects , copy_obj ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " : cloned object %1%, name %2%, pos_x %3% pos_y %4%, pos_z %5% " )
% copy_index % object - > name % assemble_object . pos_x [ array_index ] % assemble_object . pos_y [ array_index ] % assemble_object . pos_z [ array_index ] ;
}
}
size_t assemble_count = merged_objects . size ( ) ;
if ( ( assemble_count > 0 ) & & ( assemble_plate_info . assembled_param_list . size ( ) > 0 ) )
{
for ( auto & iter : merged_objects )
{
ModelObject * assemble_obj = iter . second ;
int assemble_index = iter . first ;
auto assemble_iter = assemble_plate_info . assembled_param_list . find ( assemble_index ) ;
if ( assemble_iter ! = assemble_plate_info . assembled_param_list . end ( ) )
{
assembled_param_info_t & assembled_param = assemble_iter - > second ;
if ( ! assembled_param . print_params . empty ( ) )
{
for ( auto param_iter = assembled_param . print_params . begin ( ) ; param_iter ! = assembled_param . print_params . end ( ) ; param_iter + + )
{
assemble_obj - > config . set_deserialize ( param_iter - > first , param_iter - > second , config_substitutions ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " Plate %1%, assemble object %2% key %3%, value %4% " ) % ( index + 1 ) % assemble_obj - > name % param_iter - > first % param_iter - > second ;
}
}
if ( ! assembled_param . height_ranges . empty ( ) )
{
for ( int range_index = 0 ; range_index < assembled_param . height_ranges . size ( ) ; range_index + + )
{
height_range_info_t & range = assembled_param . height_ranges [ range_index ] ;
DynamicPrintConfig range_config ;
for ( auto range_config_iter = range . range_params . begin ( ) ; range_config_iter ! = range . range_params . end ( ) ; range_config_iter + + )
{
range_config . set_deserialize ( range_config_iter - > first , range_config_iter - > second , config_substitutions ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " assenble object %1%, height range %2% key %3%, value %4% " ) % assemble_obj - > name % range_index % range_config_iter - > first % range_config_iter - > second ;
}
assemble_obj - > layer_config_ranges [ { range . min_z , range . max_z } ] . assign_config ( std : : move ( range_config ) ) ;
}
}
}
}
}
assemble_plate_info . filaments_count = used_filaments . size ( ) ;
assemble_plate_info . assemble_obj_list . clear ( ) ;
assemble_plate_info . assemble_obj_list . shrink_to_fit ( ) ;
assemble_plate_info . plate_params . clear ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : Plate %1%, used filaments %2% " ) % ( index + 1 ) % assemble_plate_info . filaments_count ;
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : has objects need to be merged, total plates %1%, total objects %2% " ) % plate_count % model . objects . size ( ) ;
temp_model . clear_objects ( ) ;
temp_model . clear_materials ( ) ;
return ret ;
}
static void load_downward_settings_list_from_config ( std : : string config_file , std : : string printer_name , std : : string printer_model , std : : vector < std : : string > & downward_settings )
{
std : : map < std : : string , std : : string > printer_params ;
boost : : filesystem : : path directory_path ( config_file ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, will parse file %2% for printer mode %3%, printer name %4% " ) % __FUNCTION__ % config_file % printer_model % printer_name ;
if ( ! fs : : exists ( directory_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " file %1% not exist. " ) % config_file ;
}
else {
try {
json root_json ;
boost : : nowide : : ifstream ifs ( config_file ) ;
ifs > > root_json ;
ifs . close ( ) ;
if ( root_json . contains ( " printer " ) ) {
json printer_json = root_json [ " printer " ] ;
if ( ! printer_model . empty ( ) & & printer_json . contains ( printer_model ) ) {
json printer_model_json = printer_json [ printer_model ] ;
if ( printer_model_json . contains ( " downward_check " ) ) {
json downward_check_json = printer_model_json [ " downward_check " ] ;
if ( downward_check_json . contains ( printer_name ) ) {
downward_settings = downward_check_json [ printer_name ] . get < std : : vector < std : : string > > ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " got %1% downward settings of %2% in cli_config.json " ) % downward_settings . size ( ) % printer_name ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " can not find %1% in downward_check of %2% in cli_config.json " ) % printer_name % printer_model ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " can not find downward_check for %1% in cli_config.json " ) % printer_model ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " can not find printer_model %1% in the file " ) % printer_model ;
}
}
else {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " can not find key printer in the file " ) ;
}
}
catch ( std : : exception & err ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " : parse file " < < config_file < < " got a generic exception, reason = " < < err . what ( ) ;
}
}
}
int CLI : : run ( int argc , char * * argv )
{
// Mark the main thread for the debugger and for runtime checks.
set_current_thread_name ( " qidistu_main " ) ;
// Save the thread ID of the main thread.
save_main_thread_id ( ) ;
# ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on
// startup if gtk3 is used. This env var has to be set explicitly to
// instruct the window manager to fall back to X server mode.
: : setenv ( " GDK_BACKEND " , " x11 " , /* replace */ true ) ;
: : setenv ( " WEBKIT_DISABLE_COMPOSITING_MODE " , " 1 " , /* replace */ false ) ;
// Also on Linux, we need to tell Xlib that we will be using threads,
// lest we crash when we fire up GStreamer.
XInitThreads ( ) ;
# endif
// Switch boost::filesystem to utf8.
try {
boost : : nowide : : nowide_filesystem ( ) ;
} catch ( const std : : runtime_error & ex ) {
std : : string caption = std : : string ( SLIC3R_APP_FULL_NAME ) + " Error " ;
std : : string text = std : : string ( " boost::nowide::nowide_filesystem Failed! \n " ) + (
SLIC3R_APP_FULL_NAME " will now terminate. \n \n " ) + ex . what ( ) ;
# if defined(_WIN32) && defined(SLIC3R_GUI)
if ( m_actions . empty ( ) )
// Empty actions means Slicer is executed in the GUI mode. Show a GUI message.
MessageBoxA ( NULL , text . c_str ( ) , caption . c_str ( ) , MB_OK | MB_ICONERROR ) ;
# endif
boost : : nowide : : cerr < < text . c_str ( ) < < std : : endl ;
return CLI_ENVIRONMENT_ERROR ;
}
/*BOOST_LOG_TRIVIAL(info) << "begin to setup params, argc=" << argc << std::endl;
for ( int index = 0 ; index < argc ; index + + )
BOOST_LOG_TRIVIAL ( info ) < < " index= " < < index < < " , arg is " < < argv [ index ] < < std : : endl ;
int debug_argc = 11 ;
char * debug_argv [ ] = {
" F: \ work \ projects \ qidi_debug \ qidi_slicer \b uild_debug \ src \ Debug \ qidi-studio.exe " ,
" --debug=2 " ,
" --load-settings " ,
" machine.json;process.json " ,
" --load-filaments " ,
" filament.json;filament.json;filament.json;filament.json;filament.json;filament.json " ,
" --export-3mf=output.3mf " ,
" --filament-colour " ,
" #FFFFFFFF;#0000FFFF;#00FF00FF;#FF0000FF;#00000000;#FFFF00FF " ,
" --slice=0 " ,
" 1.3mf "
} ;
if ( ! this - > setup ( debug_argc , debug_argv ) ) */
if ( ! this - > setup ( argc , argv ) )
{
boost : : nowide : : cerr < < " setup params error " < < std : : endl ;
return CLI_INVALID_PARAMS ;
}
BOOST_LOG_TRIVIAL ( info ) < < " finished setup params, argc= " < < argc < < std : : endl ;
std : : string temp_path = wxFileName : : GetTempDir ( ) . utf8_str ( ) . data ( ) ;
set_temporary_dir ( temp_path ) ;
m_extra_config . apply ( m_config , true ) ;
m_extra_config . normalize_fdm ( ) ;
PrinterTechnology printer_technology = get_printer_technology ( m_config ) ;
//QDS: remove GCodeViewer as seperate APP logic
/*bool start_as_gcodeviewer =
# ifdef _WIN32
false ;
# else
// On Unix systems, the prusa-slicer binary may be symlinked to give the application a different meaning.
boost : : algorithm : : iends_with ( boost : : filesystem : : path ( argv [ 0 ] ) . filename ( ) . string ( ) , " gcodeviewer " ) ;
# endif // _WIN32*/
bool translate_old = false , regenerate_thumbnails = false , filament_color_changed = false , downward_check = false ;
int current_printable_width , current_printable_depth , current_printable_height , shrink_to_new_bed = 0 ;
int old_printable_height = 0 , old_printable_width = 0 , old_printable_depth = 0 ;
Pointfs old_printable_area , old_exclude_area ;
float old_max_radius = 0.f , old_height_to_rod = 0.f , old_height_to_lid = 0.f ;
std : : vector < double > old_max_layer_height , old_min_layer_height ;
std : : string outfile_dir = m_config . opt_string ( " outputdir " , true ) ;
const std : : vector < std : : string > & load_configs = m_config . option < ConfigOptionStrings > ( " load_settings " , true ) - > values ;
const std : : vector < std : : string > & uptodate_configs = m_config . option < ConfigOptionStrings > ( " uptodate_settings " , true ) - > values ;
const std : : vector < std : : string > & uptodate_filaments = m_config . option < ConfigOptionStrings > ( " uptodate_filaments " , true ) - > values ;
std : : vector < std : : string > downward_settings = m_config . option < ConfigOptionStrings > ( " downward_settings " , true ) - > values ;
std : : vector < std : : string > downward_compatible_machines ;
//QDS: always use ForwardCompatibilitySubstitutionRule::Enable
//const ForwardCompatibilitySubstitutionRule config_substitution_rule = m_config.option<ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>>("config_compatibility", true)->value;
const ForwardCompatibilitySubstitutionRule config_substitution_rule = ForwardCompatibilitySubstitutionRule : : Enable ;
const std : : vector < std : : string > & load_filaments = m_config . option < ConfigOptionStrings > ( " load_filaments " , true ) - > values ;
//skip model object logic
const std : : vector < int > & skip_objects = m_config . option < ConfigOptionInts > ( " skip_objects " , true ) - > values ;
std : : map < int , bool > skip_maps ;
bool need_skip = ( skip_objects . size ( ) > 0 ) ? true : false ;
long long global_begin_time = 0 , global_current_time ;
sliced_info_t sliced_info ;
std : : map < std : : string , std : : string > record_key_values ;
ConfigOptionBool * downward_check_option = m_config . option < ConfigOptionBool > ( " downward_check " ) ;
if ( downward_check_option )
downward_check = downward_check_option - > value ;
bool start_gui = m_actions . empty ( ) & & ! downward_check ;
if ( start_gui ) {
BOOST_LOG_TRIVIAL ( info ) < < " no action, start gui directly " < < std : : endl ;
: : Label : : initSysFont ( ) ;
# ifdef SLIC3R_GUI
/*#if !defined(_WIN32) && !defined(__APPLE__)
// likely some linux / unix system
const char * display = boost : : nowide : : getenv ( " DISPLAY " ) ;
// const char *wayland_display = boost::nowide::getenv("WAYLAND_DISPLAY");
//if (! ((display && *display) || (wayland_display && *wayland_display))) {
if ( ! ( display & & * display ) ) {
// DISPLAY not set.
boost : : nowide : : cerr < < " DISPLAY not set, GUI mode not available. " < < std : : endl < < std : : endl ;
this - > print_help ( false ) ;
// Indicate an error.
return 1 ;
}
# endif // some linux / unix system*/
Slic3r : : GUI : : GUI_InitParams params ;
params . argc = argc ;
params . argv = argv ;
params . load_configs = load_configs ;
params . extra_config = std : : move ( m_extra_config ) ;
std : : vector < std : : string > gcode_files ;
std : : vector < std : : string > non_gcode_files ;
for ( const auto & filename : m_input_files ) {
if ( is_gcode_file ( filename ) )
gcode_files . emplace_back ( filename ) ;
else {
non_gcode_files . emplace_back ( filename ) ;
}
}
if ( non_gcode_files . empty ( ) & & ! gcode_files . empty ( ) ) {
params . input_gcode = true ;
params . input_files = std : : move ( gcode_files ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " , gcode only, gcode_files size = " < < params . input_files . size ( ) ;
}
else {
params . input_files = std : : move ( m_input_files ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " , normal mode, input_files size = " < < params . input_files . size ( ) ;
}
//QDS: remove GCodeViewer as seperate APP logic
//params.start_as_gcodeviewer = start_as_gcodeviewer;
BOOST_LOG_TRIVIAL ( info ) < < " begin to launch QIDIStudio GUI soon " ;
return Slic3r : : GUI : : GUI_Run ( params ) ;
# else // SLIC3R_GUI
// No GUI support. Just print out a help.
this - > print_help ( false ) ;
// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
return ( argc = = 0 ) ? 0 : 1 ;
# endif // SLIC3R_GUI
}
else {
const ConfigOptionInt * opt_loglevel = m_config . opt < ConfigOptionInt > ( " debug " ) ;
if ( opt_loglevel ) {
set_logging_level ( opt_loglevel - > value ) ;
}
else {
set_logging_level ( 2 ) ;
}
}
2024-09-16 16:07:29 +08:00
//1.9.5
global_begin_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
2024-09-03 09:34:33 +08:00
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " cli mode, Current QIDIStudio Version %1% " ) % SLIC3R_VERSION ;
//QDS: add plate data related logic
PlateDataPtrs plate_data_src ;
std : : vector < plate_obj_size_info_t > plate_obj_size_infos ;
int arrange_option ;
int plate_to_slice = 0 , filament_count = 0 , duplicate_count = 0 , real_duplicate_count = 0 ;
bool first_file = true , is_qdt_3mf = false , need_arrange = true , has_thumbnails = false , up_config_to_date = false , normative_check = true , duplicate_single_object = false , use_first_fila_as_default = false , minimum_save = false , enable_timelapse = false ;
bool allow_rotations = true , skip_modified_gcodes = false , avoid_extrusion_cali_region = false , skip_useless_pick = false , allow_newer_file = false ;
Semver file_version ;
std : : map < size_t , bool > orients_requirement ;
std : : vector < Preset * > project_presets ;
std : : string new_printer_name , current_printer_name , new_process_name , current_process_name , current_printer_system_name , current_process_system_name , new_process_system_name , new_printer_system_name , printer_model_id , current_printer_model , printer_model ; //, printer_inherits, print_inherits;
std : : vector < std : : string > upward_compatible_printers , new_print_compatible_printers , current_print_compatible_printers , current_different_settings ;
std : : vector < std : : string > current_filaments_name , current_filaments_system_name , current_inherits_group ;
DynamicPrintConfig load_process_config , load_machine_config ;
bool new_process_config_is_system = true , new_printer_config_is_system = true ;
std : : string pipe_name , makerlab_name , makerlab_version , different_process_setting ;
const std : : vector < std : : string > & metadata_name = m_config . option < ConfigOptionStrings > ( " metadata_name " , true ) - > values ;
const std : : vector < std : : string > & metadata_value = m_config . option < ConfigOptionStrings > ( " metadata_value " , true ) - > values ;
if ( metadata_name . size ( ) ! = metadata_value . size ( ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " metadata_name should be the same size with metadata_value " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
// Read input file(s) if any.
BOOST_LOG_TRIVIAL ( info ) < < " Will start to read model file now, file count : " < < m_input_files . size ( ) < < " \n " ;
ConfigOptionInt * slice_option = m_config . option < ConfigOptionInt > ( " slice " ) ;
if ( slice_option )
plate_to_slice = slice_option - > value ;
ConfigOptionBool * normative_check_option = m_config . option < ConfigOptionBool > ( " normative_check " ) ;
if ( normative_check_option )
normative_check = normative_check_option - > value ;
ConfigOptionBool * uptodate_option = m_config . option < ConfigOptionBool > ( " uptodate " ) ;
if ( uptodate_option )
up_config_to_date = uptodate_option - > value ;
ConfigOptionBool * load_defaultfila_option = m_config . option < ConfigOptionBool > ( " load_defaultfila " ) ;
if ( load_defaultfila_option )
use_first_fila_as_default = load_defaultfila_option - > value ;
ConfigOptionBool * min_save_option = m_config . option < ConfigOptionBool > ( " min_save " ) ;
if ( min_save_option )
minimum_save = min_save_option - > value ;
ConfigOptionBool * enable_timelapse_option = m_config . option < ConfigOptionBool > ( " enable_timelapse " ) ;
if ( enable_timelapse_option )
enable_timelapse = enable_timelapse_option - > value ;
ConfigOptionBool * allow_rotations_option = m_config . option < ConfigOptionBool > ( " allow_rotations " ) ;
if ( allow_rotations_option )
allow_rotations = allow_rotations_option - > value ;
ConfigOptionBool * skip_modified_gcodes_option = m_config . option < ConfigOptionBool > ( " skip_modified_gcodes " ) ;
if ( skip_modified_gcodes_option )
skip_modified_gcodes = skip_modified_gcodes_option - > value ;
ConfigOptionBool * skip_useless_picks_option = m_config . option < ConfigOptionBool > ( " skip_useless_pick " ) ;
if ( skip_useless_picks_option )
skip_useless_pick = skip_useless_picks_option - > value ;
ConfigOptionBool * allow_newer_file_option = m_config . option < ConfigOptionBool > ( " allow_newer_file " ) ;
if ( allow_newer_file_option )
allow_newer_file = allow_newer_file_option - > value ;
ConfigOptionBool * avoid_extrusion_cali_region_option = m_config . option < ConfigOptionBool > ( " avoid_extrusion_cali_region " ) ;
if ( avoid_extrusion_cali_region_option )
avoid_extrusion_cali_region = avoid_extrusion_cali_region_option - > value ;
ConfigOptionString * pipe_option = m_config . option < ConfigOptionString > ( " pipe " ) ;
if ( pipe_option ) {
pipe_name = pipe_option - > value ;
if ( ! pipe_name . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Will use pipe %1% " ) % pipe_name ;
# if defined(__linux__) || defined(__LINUX__)
g_cli_callback_mgr . start ( pipe_name ) ;
PrintBase : : SlicingStatus slicing_status { 1 , " Start to load files " } ;
cli_status_callback ( slicing_status ) ;
# endif
}
}
ConfigOptionString * makerlab_name_option = m_config . option < ConfigOptionString > ( " makerlab_name " ) ;
if ( makerlab_name_option )
makerlab_name = makerlab_name_option - > value ;
ConfigOptionString * makerlab_version_option = m_config . option < ConfigOptionString > ( " makerlab_version " ) ;
if ( makerlab_version_option )
makerlab_version = makerlab_version_option - > value ;
//skip model object map construct
if ( need_skip ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " need to skip objects, size %1%: " ) % skip_objects . size ( ) ;
for ( int index = 0 ; index < skip_objects . size ( ) ; index + + )
{
skip_maps [ skip_objects [ index ] ] = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " object %1%, id %2% " ) % index % skip_objects [ index ] ;
}
}
std : : string custom_gcode_file ;
ConfigOptionString * custom_gcode_option = m_config . option < ConfigOptionString > ( " load_custom_gcodes " ) ;
if ( custom_gcode_option )
custom_gcode_file = custom_gcode_option - > value ;
std : : string load_assemble_list ;
std : : vector < assemble_plate_info_t > assemble_plate_info_list ;
ConfigOptionString * load_assemble_list_option = m_config . option < ConfigOptionString > ( " load_assemble_list " ) ;
if ( load_assemble_list_option )
load_assemble_list = load_assemble_list_option - > value ;
bool allow_multicolor_oneplate = m_config . option < ConfigOptionBool > ( " allow_multicolor_oneplate " , true ) - > value ;
const std : : vector < int > loaded_filament_ids = m_config . option < ConfigOptionInts > ( " load_filament_ids " , true ) - > values ;
const std : : vector < int > clone_objects = m_config . option < ConfigOptionInts > ( " clone_objects " , true ) - > values ;
//when load objects from stl/obj, the total used filaments set
std : : set < int > used_filament_set ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " allow_multicolor_oneplate %1%, allow_rotations %2% skip_modified_gcodes %3% avoid_extrusion_cali_region %4% loaded_filament_ids size %5%, clone_objects size %6%, skip_useless_pick %7%, allow_newer_file %8% " )
% allow_multicolor_oneplate % allow_rotations % skip_modified_gcodes % avoid_extrusion_cali_region % loaded_filament_ids . size ( ) % clone_objects . size ( ) % skip_useless_pick % allow_newer_file ;
if ( clone_objects . size ( ) > 0 )
{
if ( clone_objects . size ( ) ! = m_input_files . size ( ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " clone_objects size %1% should be the same with input files size %2% " ) % clone_objects . size ( ) % m_input_files . size ( ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
else if ( load_filaments . size ( ) = = 0 )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " clone_objects should be used with load_filaments together " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
}
if ( loaded_filament_ids . size ( ) > 0 )
{
if ( loaded_filament_ids . size ( ) ! = m_input_files . size ( ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " loaded_filament_ids size %1% should be the same with input files size %2% " ) % loaded_filament_ids . size ( ) % m_input_files . size ( ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
else if ( load_filaments . size ( ) = = 0 )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " loaded_filament_ids should be used with load_filaments together " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
}
/*for (const std::string& file : m_input_files)
if ( is_gcode_file ( file ) & & boost : : filesystem : : exists ( file ) ) {
start_as_gcodeviewer = true ;
BOOST_LOG_TRIVIAL ( info ) < < " found a gcode file: " < < file < < " , will start as gcode viewer \n " ;
break ;
} */
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate_to_slice=%1%, normative_check=%2%, use_first_fila_as_default=%3% " ) % plate_to_slice % normative_check % use_first_fila_as_default ;
unsigned int input_index = 0 ;
2024-09-16 16:07:29 +08:00
//1.9.5
std : : vector < RGBA > input_obj_colours ;
if ( ! load_assemble_list . empty ( ) & & ( m_input_files . size ( ) > 0 ) )
2024-09-03 09:34:33 +08:00
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " load_assemble_list should not be used with input model files to load and should not be sued with transforms " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
if ( load_assemble_list . empty ( ) ) {
for ( const std : : string & file : m_input_files ) {
if ( ! boost : : filesystem : : exists ( file ) ) {
boost : : nowide : : cerr < < " No such file: " < < file < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_FILE_NOTFOUND , 0 , cli_errors [ CLI_FILE_NOTFOUND ] , sliced_info ) ;
flush_and_exit ( CLI_FILE_NOTFOUND ) ;
}
Model model ;
//QDS: add plate related logic
//bool load_aux = false;
BOOST_LOG_TRIVIAL ( info ) < < " read model file: " < < file < < " \n " ;
try {
// When loading an AMF or 3MF, config is imported as well, including the printer technology.
DynamicPrintConfig config ;
ConfigSubstitutionContext config_substitutions ( config_substitution_rule ) ;
//FIXME should we check the version here? // | LoadStrategy::CheckVersion ?
is_qdt_3mf = false ;
LoadStrategy strategy ;
if ( boost : : algorithm : : iends_with ( file , " .3mf " ) & & first_file ) {
if ( ( clone_objects . size ( ) > 0 ) | | ( loaded_filament_ids . size ( ) > 0 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " can not load 3mf when set loaded_filament_ids or clone_objects " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
strategy = LoadStrategy : : LoadModel | LoadStrategy : : LoadConfig | LoadStrategy : : AddDefaultInstances | LoadStrategy : : LoadAuxiliary ;
//load_aux = true;
}
else {
strategy = LoadStrategy : : LoadModel | LoadStrategy : : AddDefaultInstances ;
}
// QDS: adjust whebackup
//LoadStrategy strategy = LoadStrategy::LoadModel | LoadStrategy::LoadConfig|LoadStrategy::AddDefaultInstances;
//if (load_aux) strategy = strategy | LoadStrategy::LoadAuxiliary;
model = Model : : read_from_file ( file , & config , & config_substitutions , strategy , & plate_data_src , & project_presets , & is_qdt_3mf , & file_version , nullptr , nullptr , nullptr , nullptr , nullptr , plate_to_slice ) ;
if ( is_qdt_3mf )
{
if ( ! first_file )
{
BOOST_LOG_TRIVIAL ( info ) < < " The QDT 3mf file should be placed at the first position, filename= " < < file < < " \n " ;
record_exit_reson ( outfile_dir , CLI_FILELIST_INVALID_ORDER , 0 , cli_errors [ CLI_FILELIST_INVALID_ORDER ] , sliced_info ) ;
flush_and_exit ( CLI_FILELIST_INVALID_ORDER ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " the first file is a 3mf, version %1%, got plate count %2% " ) % file_version . to_string ( ) % plate_data_src . size ( ) ;
need_arrange = false ;
/*for (ModelObject* o : model.objects)
{
orients_requirement . insert ( std : : pair < size_t , bool > ( o - > id ( ) . id , false ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < " object " < < o - > name < < " , id : " < < o - > id ( ) . id < < " , from qdt 3mf \n " ;
} */
Semver cli_ver = * Semver : : parse ( SLIC3R_VERSION ) ;
if ( ! allow_newer_file & & ( ( cli_ver . maj ( ) ! = file_version . maj ( ) ) | | ( cli_ver . min ( ) < file_version . min ( ) ) ) ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " Version Check: File Version %1% not supported by current cli version %2% " ) % file_version . to_string ( ) % SLIC3R_VERSION ;
record_exit_reson ( outfile_dir , CLI_FILE_VERSION_NOT_SUPPORTED , 0 , cli_errors [ CLI_FILE_VERSION_NOT_SUPPORTED ] , sliced_info ) ;
flush_and_exit ( CLI_FILE_VERSION_NOT_SUPPORTED ) ;
}
Semver old_version ( 1 , 5 , 9 ) , old_version2 ( 1 , 5 , 9 ) ;
if ( ( file_version < old_version ) & & ! config . empty ( ) ) {
translate_old = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old 3mf version %1%, need to translate " ) % file_version . to_string ( ) ;
}
if ( ( file_version < old_version2 ) & & ! config . empty ( ) ) {
regenerate_thumbnails = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old 3mf version %1%, need to regenerate_thumbnails for all " ) % file_version . to_string ( ) ;
}
if ( normative_check ) {
ConfigOptionStrings * postprocess_scripts = config . option < ConfigOptionStrings > ( " post_process " ) ;
if ( postprocess_scripts ) {
std : : vector < std : : string > postprocess_values = postprocess_scripts - > values ;
if ( postprocess_values . size ( ) > 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " normative_check: postprocess not supported, array size %1% " ) % postprocess_values . size ( ) ;
record_exit_reson ( outfile_dir , CLI_POSTPROCESS_NOT_SUPPORTED , 0 , cli_errors [ CLI_POSTPROCESS_NOT_SUPPORTED ] , sliced_info ) ;
flush_and_exit ( CLI_POSTPROCESS_NOT_SUPPORTED ) ;
}
}
}
/*for (ModelObject *model_object : model.objects)
for ( ModelInstance * model_instance : model_object - > instances )
{
const Vec3d & instance_offset = model_instance - > get_offset ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " instance %1% transform {%2%,%3%,%4%} at %5%:%6% " ) % model_object - > name % instance_offset . x ( ) % instance_offset . y ( ) % instance_offset . z ( ) % __FUNCTION__ % __LINE__ < < std : : endl ;
} */
current_printer_name = config . option < ConfigOptionString > ( " printer_settings_id " ) - > value ;
current_process_name = config . option < ConfigOptionString > ( " print_settings_id " ) - > value ;
current_printer_model = config . option < ConfigOptionString > ( " printer_model " , true ) - > value ;
current_filaments_name = config . option < ConfigOptionStrings > ( " filament_settings_id " ) - > values ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " current_printer_name %1%, current_process_name %2% " ) % current_printer_name % current_process_name ;
ConfigOptionStrings * option_strings = config . option < ConfigOptionStrings > ( " inherits_group " ) ;
if ( option_strings ) {
current_inherits_group = option_strings - > values ;
size_t size = current_inherits_group . size ( ) ;
if ( current_inherits_group [ size - 1 ] . empty ( ) ) {
current_printer_system_name = current_printer_name ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " inherits of printer is null, should be system preset " ) ;
}
else {
current_printer_system_name = current_inherits_group [ size - 1 ] ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " inherits of printer valid, current_printer_system_name is %1% " ) % current_printer_system_name ;
}
if ( current_inherits_group [ 0 ] . empty ( ) ) {
current_process_system_name = current_process_name ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " inherits of process is null, should be system preset " ) ;
}
else {
current_process_system_name = current_inherits_group [ 0 ] ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " inherits of process valid, current_process_system_name is %1% " ) % current_process_system_name ;
}
current_filaments_system_name . resize ( size - 2 ) ;
for ( int index = 1 ; index < ( size - 1 ) ; index + + ) {
if ( current_inherits_group [ index ] . empty ( ) ) {
current_filaments_system_name [ index - 1 ] = current_filaments_name [ index - 1 ] ;
}
else {
current_filaments_system_name [ index - 1 ] = current_inherits_group [ index ] ;
}
}
}
else {
current_printer_system_name = current_printer_name ;
current_process_system_name = current_process_name ;
current_filaments_system_name = current_filaments_name ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " no inherits_group: use system name the same as current name " ) ;
}
filament_count = current_filaments_name . size ( ) ;
upward_compatible_printers = config . option < ConfigOptionStrings > ( " upward_compatible_machine " , true ) - > values ;
current_print_compatible_printers = config . option < ConfigOptionStrings > ( " print_compatible_printers " , true ) - > values ;
current_different_settings = config . option < ConfigOptionStrings > ( " different_settings_to_system " , true ) - > values ;
//use Pointfs insteadof Points
old_printable_area = config . option < ConfigOptionPoints > ( " printable_area " , true ) - > values ;
old_exclude_area = config . option < ConfigOptionPoints > ( " bed_exclude_area " , true ) - > values ;
if ( old_printable_area . size ( ) > = 4 ) {
old_printable_width = ( int ) ( old_printable_area [ 2 ] . x ( ) - old_printable_area [ 0 ] . x ( ) ) ;
old_printable_depth = ( int ) ( old_printable_area [ 2 ] . y ( ) - old_printable_area [ 0 ] . y ( ) ) ;
}
old_printable_height = ( int ) ( config . opt_float ( " printable_height " ) ) ;
if ( config . option < ConfigOptionFloat > ( " extruder_clearance_height_to_rod " ) )
old_height_to_rod = config . opt_float ( " extruder_clearance_height_to_rod " ) ;
if ( config . option < ConfigOptionFloat > ( " extruder_clearance_height_to_lid " ) )
old_height_to_lid = config . opt_float ( " extruder_clearance_height_to_lid " ) ;
if ( config . option < ConfigOptionFloat > ( " extruder_clearance_max_radius " ) )
old_max_radius = config . opt_float ( " extruder_clearance_max_radius " ) ;
if ( config . option < ConfigOptionFloats > ( " max_layer_height " ) )
old_max_layer_height = config . option < ConfigOptionFloats > ( " max_layer_height " ) - > values ;
if ( config . option < ConfigOptionFloats > ( " min_layer_height " ) )
old_min_layer_height = config . option < ConfigOptionFloats > ( " min_layer_height " ) - > values ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old printable size from 3mf: {%1%, %2%, %3%} " ) % old_printable_width % old_printable_depth % old_printable_height ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old extruder_clearance_height_to_rod %1%, extruder_clearance_height_to_lid %2%, extruder_clearance_max_radius %3%} " ) % old_height_to_rod % old_height_to_lid % old_max_radius ;
}
else
{
need_arrange = true ;
int object_extruder_id = 0 , clone_count = 1 ;
if ( loaded_filament_ids . size ( ) > input_index ) {
if ( loaded_filament_ids [ input_index ] > 0 ) {
if ( loaded_filament_ids [ input_index ] > load_filaments . size ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " invalid filament_id %1% at index %2%, max %3% " ) % loaded_filament_ids [ input_index ] % ( input_index + 1 ) % load_filaments . size ( ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
object_extruder_id = loaded_filament_ids [ input_index ] ;
used_filament_set . emplace ( object_extruder_id ) ;
}
}
if ( clone_objects . size ( ) > input_index ) {
if ( clone_objects [ input_index ] > 0 ) {
if ( clone_objects [ input_index ] > MAX_CLONEABLE_SIZE ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " invalid clone count %1% at index %2%, max %3% " ) % clone_objects [ input_index ] % ( input_index + 1 ) % MAX_CLONEABLE_SIZE ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
clone_count = clone_objects [ input_index ] ;
}
}
//clone objects process
if ( clone_count > 1 )
{
unsigned int object_count = model . objects . size ( ) ;
for ( unsigned int obj_index = 0 ; obj_index < object_count ; obj_index + + )
{
ModelObject * object = model . objects [ obj_index ] ;
for ( unsigned int clone_index = 1 ; clone_index < clone_count ; clone_index + + )
{
ModelObject * newObj = model . add_object ( * object ) ;
newObj - > name = object - > name + " _ " + std : : to_string ( clone_index + 1 ) ;
}
object - > name = object - > name + " _ " + std : : to_string ( 1 ) ;
}
}
for ( ModelObject * o : model . objects )
{
if ( object_extruder_id ! = 0 ) {
o - > config . set_key_value ( " extruder " , new ConfigOptionInt ( object_extruder_id ) ) ;
}
//default not orient for all, if need to orient use the action
//orients_requirement.insert(std::pair<size_t, bool>(o->id().id, false));
BOOST_LOG_TRIVIAL ( info ) < < " object " < < o - > name < < " , id : " < < o - > id ( ) . id < < " , from stl or other 3mf \n " ;
o - > ensure_on_bed ( ) ;
}
}
first_file = false ;
PrinterTechnology other_printer_technology = get_printer_technology ( config ) ;
if ( printer_technology = = ptUnknown ) {
printer_technology = other_printer_technology ;
}
if ( ( printer_technology ! = other_printer_technology ) & & ( other_printer_technology ! = ptUnknown ) ) {
boost : : nowide : : cerr < < " invalid printer_technology " < < printer_technology < < " , from source file " < < file < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PRINTER_TECH , 0 , cli_errors [ CLI_INVALID_PRINTER_TECH ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PRINTER_TECH ) ;
}
if ( ! config_substitutions . substitutions . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " Found legacy configuration values, substituted when loading " < < file < < " : \n " ;
for ( const ConfigSubstitution & subst : config_substitutions . substitutions )
BOOST_LOG_TRIVIAL ( info ) < < " \t key = \" " < < subst . opt_def - > opt_key < < " \" \t old_value = \" " < < subst . old_value < < " \t new_value = \" " < < subst . new_value - > serialize ( ) < < " \" \n " ;
}
// config is applied to m_print_config before the current m_config values.
config + = std : : move ( m_print_config ) ;
m_print_config = std : : move ( config ) ;
input_index + + ;
}
catch ( std : : exception & e ) {
boost : : nowide : : cerr < < file < < " : " < < e . what ( ) < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_DATA_FILE_ERROR , 0 , cli_errors [ CLI_DATA_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_DATA_FILE_ERROR ) ;
}
if ( model . objects . empty ( ) ) {
boost : : nowide : : cerr < < " Error: file is empty: " < < file < < std : : endl ;
continue ;
}
m_models . push_back ( std : : move ( model ) ) ;
}
}
else {
//parse the json and assemble object here
Model model ;
int ret = load_assemble_plate_list ( load_assemble_list , assemble_plate_info_list ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
try {
2024-09-16 16:07:29 +08:00
//1.9.5
ret = construct_assemble_list ( assemble_plate_info_list , model , plate_data_src , input_obj_colours ) ;
2024-09-03 09:34:33 +08:00
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
}
catch ( std : : exception & e ) {
boost : : nowide : : cerr < < construct_assemble_list < < " : " < < e . what ( ) < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_DATA_FILE_ERROR , 0 , cli_errors [ CLI_DATA_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_DATA_FILE_ERROR ) ;
}
model . add_default_instances ( ) ;
m_models . push_back ( std : : move ( model ) ) ;
}
if ( ! is_qdt_3mf & & plate_to_slice > 0 )
{
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " %1%: not support to slice plate %2%, reset to 0 " ) % __LINE__ % plate_to_slice ;
plate_to_slice = 0 ;
}
//load custom gcode file
std : : map < int , CustomGCode : : Info > custom_gcodes_map ;
if ( ! custom_gcode_file . empty ( ) ) {
// parse the custom gcode json file
std : : string file = custom_gcode_file ;
if ( ! boost : : filesystem : : exists ( file ) ) {
boost : : nowide : : cerr < < __FUNCTION__ < < " : can not find custom_gcode file: " < < file < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_FILE_NOTFOUND , 0 , cli_errors [ CLI_FILE_NOTFOUND ] , sliced_info ) ;
flush_and_exit ( CLI_FILE_NOTFOUND ) ;
}
try {
nlohmann : : json jj ;
boost : : nowide : : ifstream ifs ( file ) ;
ifs > > jj ;
ifs . close ( ) ;
int plate_id = 0 ;
if ( plate_to_slice = = 0 )
plate_id = 0 ;
else
plate_id = plate_to_slice - 1 ;
CustomGCode : : Info info ;
info . from_json ( jj ) ;
custom_gcodes_map . emplace ( plate_id , info ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " load custom_gcode from file %1% success, store custom gcodes to plate %2% " ) % file % ( plate_id + 1 ) ;
}
catch ( std : : exception & ex ) {
boost : : nowide : : cerr < < __FUNCTION__ < < " :Loading custom-gcode file \" " < < file < < " \" failed: " < < ex . what ( ) < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
}
auto load_config_file = [ config_substitution_rule ] ( const std : : string & file , DynamicPrintConfig & config , std : : string & config_type ,
std : : string & config_name , std : : string & filament_id , std : : string & config_from ) {
if ( ! boost : : filesystem : : exists ( file ) ) {
boost : : nowide : : cerr < < __FUNCTION__ < < " : can not find setting file: " < < file < < std : : endl ;
return CLI_FILE_NOTFOUND ;
}
ConfigSubstitutions config_substitutions ;
try {
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " :load setting file " < < file < < " , with rule " < < config_substitution_rule < < std : : endl ;
std : : map < std : : string , std : : string > key_values ;
std : : string reason ;
config_substitutions = config . load_from_json ( file , config_substitution_rule , key_values , reason ) ;
if ( ! reason . empty ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " :Can not load config from file " < < file < < " \n " ;
return CLI_CONFIG_FILE_ERROR ;
}
config_name = key_values [ QDT_JSON_KEY_NAME ] ;
auto from_iter = key_values . find ( QDT_JSON_KEY_FROM ) ;
if ( from_iter ! = key_values . end ( ) ) {
config_from = from_iter - > second ;
}
if ( ( config_from ! = " system " ) & & ( config_from ! = " User " ) & & ( config_from ! = " user " ) ) {
boost : : nowide : : cerr < < __FUNCTION__ < < boost : : format ( " :file %1%'s from %2% unsupported " ) % file % config_from ;
return CLI_CONFIG_FILE_ERROR ;
}
auto type_iter = key_values . find ( QDT_JSON_KEY_TYPE ) ;
if ( type_iter ! = key_values . end ( ) ) {
config_type = type_iter - > second ;
}
if ( config_type = = " machine " ) {
//config.set("printer_settings_id", config_name, true);
//printer_inherits = config.option<ConfigOptionString>("inherits", true)->value;
}
else if ( config_type = = " process " ) {
//config.set("print_settings_id", config_name, true);
//print_inherits = config.option<ConfigOptionString>("inherits", true)->value;
}
else if ( config_type = = " filament " ) {
auto filament_id_iter = key_values . find ( QDT_JSON_KEY_FILAMENT_ID ) ;
if ( filament_id_iter ! = key_values . end ( ) )
filament_id = filament_id_iter - > second ;
}
else {
boost : : nowide : : cerr < < __FUNCTION__ < < boost : : format ( " : unknown config type %1% of file %2% in load-settings " ) % config_type % file ;
return CLI_CONFIG_FILE_ERROR ;
}
config . normalize_fdm ( ) ;
if ( ! config_substitutions . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " Found legacy configuration values, substituted when loading " < < file < < " : \n " ;
for ( const ConfigSubstitution & subst : config_substitutions )
BOOST_LOG_TRIVIAL ( info ) < < " \t key = \" " < < subst . opt_def - > opt_key < < " \" \t old_value = \" " < < subst . old_value < < " \t new_value = \" " < < subst . new_value - > serialize ( ) < < " \" \n " ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " no substitutions performed from file " < < file < < " \n " ;
}
//config.erase("inherits");
//config.erase("compatible_printers");
//BOOST_LOG_TRIVIAL(info) << "got printable_area "<< config.option("printable_area")->serialize() << std::endl;
} catch ( std : : exception & ex ) {
boost : : nowide : : cerr < < __FUNCTION__ < < " :Loading setting file \" " < < file < < " \" failed: " < < ex . what ( ) < < std : : endl ;
return CLI_CONFIG_FILE_ERROR ;
}
return 0 ;
} ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " :before load settings, file count= " < < load_configs . size ( ) < < std : : endl ;
//std::vector<std::string> filament_compatible_printers;
// load config files supplied via --load
for ( auto const & file : load_configs ) {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( file , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( config_type = = " machine " ) {
if ( ! new_printer_name . empty ( ) ) {
boost : : nowide : : cerr < < " duplicate machine config file: " < < file < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
new_printer_name = config_name ;
if ( config_from = = " system " ) {
new_printer_system_name = new_printer_name ;
new_printer_config_is_system = true ;
}
else {
new_printer_system_name = config . option < ConfigOptionString > ( " inherits " , true ) - > value ;
new_printer_config_is_system = false ;
}
config . set ( " printer_settings_id " , new_printer_name , true ) ;
//get printer_model_id
printer_model = config . option < ConfigOptionString > ( " printer_model " , true ) - > value ;
if ( ! printer_model . empty ( ) ) {
std : : string printer_model_path = resources_dir ( ) + " /profiles/QDT/machine_full/ " + printer_model + " .json " ;
if ( boost : : filesystem : : exists ( printer_model_path ) )
{
std : : map < std : : string , std : : string > key_values ;
load_key_values_from_json ( printer_model_path , key_values ) ;
if ( key_values . find ( " model_id " ) ! = key_values . end ( ) ) {
printer_model_id = key_values [ " model_id " ] ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " :%1%, load printer_model_id %2% from current printer model %3% " ) % __LINE__ % printer_model_id % printer_model ;
}
}
}
//printer_inherits = config.option<ConfigOptionString>("inherits", true)->value;
load_machine_config = std : : move ( config ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " loaded machine config %1%, type %2%, name %3%, inherits %4%, printer_model_id %5% " ) % file % config_name % config_from % new_printer_system_name % printer_model_id ;
}
else if ( config_type = = " process " ) {
if ( ! new_process_name . empty ( ) ) {
boost : : nowide : : cerr < < " duplicate process config file: " < < file < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
new_process_name = config_name ;
if ( config_from = = " system " ) {
new_process_system_name = new_process_name ;
new_process_config_is_system = true ;
}
else {
new_process_system_name = config . option < ConfigOptionString > ( " inherits " , true ) - > value ;
new_process_config_is_system = false ;
}
config . set ( " print_settings_id " , new_process_name , true ) ;
//print_inherits = config.option<ConfigOptionString>("inherits", true)->value;
new_print_compatible_printers = config . option < ConfigOptionStrings > ( " compatible_printers " , true ) - > values ;
if ( ! is_qdt_3mf & & config . option < ConfigOptionStrings > ( " different_settings_to_system " ) ) {
std : : vector < std : : string > diff_settings = config . option < ConfigOptionStrings > ( " different_settings_to_system " ) - > values ;
different_process_setting = diff_settings [ 0 ] ;
}
load_process_config = std : : move ( config ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " loaded process config %1%, type %2%, name %3%, inherits %4% " ) % file % config_name % config_from % new_process_system_name ;
}
PrinterTechnology other_printer_technology = get_printer_technology ( config ) ;
if ( printer_technology = = ptUnknown ) {
printer_technology = other_printer_technology ;
}
if ( ( printer_technology ! = other_printer_technology ) & & ( other_printer_technology ! = ptUnknown ) ) {
boost : : nowide : : cerr < < " invalid printer_technology " < < printer_technology < < " , from config " < < file < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PRINTER_TECH , 0 , cli_errors [ CLI_INVALID_PRINTER_TECH ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PRINTER_TECH ) ;
}
}
//load filaments files
int load_filament_count = load_filaments . size ( ) ;
std : : vector < int > load_filaments_index ;
std : : set < std : : string > load_filaments_set ;
bool disable_wipe_tower_after_mapping = false ;
std : : vector < DynamicPrintConfig > load_filaments_config ;
std : : vector < std : : string > load_filaments_id ;
std : : vector < std : : string > load_filaments_name , load_filaments_inherit ;
int current_index = 0 ;
std : : string default_load_fila_name , default_load_fila_id , default_filament_file , default_filament_inherit ;
DynamicPrintConfig default_load_fila_config ;
if ( use_first_fila_as_default ) {
//construct default filament
for ( int index = 0 ; index < load_filament_count ; index + + ) {
const std : : string & file = load_filaments [ index ] ;
if ( default_filament_file . empty ( ) & & ! file . empty ( ) ) {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( file , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( config_type ! = " filament " ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : unknown config type %1% of file %2% in load-filaments " ) % config_type % file ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
if ( ( config_from = = " User " ) | | ( config_from = = " user " ) ) {
default_filament_inherit = config . option < ConfigOptionString > ( " inherits " , true ) - > value ;
}
default_filament_file = file ;
default_load_fila_name = config_name ;
default_load_fila_id = filament_id ;
default_load_fila_config = std : : move ( config ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " loaded default filament config %1%, type %2%, name %3%, inherits %4% " ) % file % config_from % config_name % default_filament_inherit ;
break ;
}
}
if ( ( load_filament_count > 0 ) & & default_filament_file . empty ( ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : load_filament_count is %1%, but can not load a default filament " ) % load_filament_count ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
}
for ( int index = 0 ; index < load_filament_count ; index + + ) {
const std : : string & file = load_filaments [ index ] ;
current_index + + ;
if ( ! file . empty ( ) ) {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( file , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( config_type ! = " filament " ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : unknown config type %1% of file %2% in load-filaments " ) % config_type % file ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
PrinterTechnology other_printer_technology = get_printer_technology ( config ) ;
if ( printer_technology = = ptUnknown ) {
printer_technology = other_printer_technology ;
}
if ( ( printer_technology ! = other_printer_technology ) & & ( other_printer_technology ! = ptUnknown ) ) {
BOOST_LOG_TRIVIAL ( error ) < < " invalid printer_technology " < < printer_technology < < " , from filament file " < < file ;
record_exit_reson ( outfile_dir , CLI_INVALID_PRINTER_TECH , 0 , cli_errors [ CLI_INVALID_PRINTER_TECH ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PRINTER_TECH ) ;
}
std : : string inherits ;
if ( ( config_from = = " User " ) | | ( config_from = = " user " ) ) {
inherits = config . option < ConfigOptionString > ( " inherits " , true ) - > value ;
}
load_filaments_inherit . push_back ( inherits ) ;
load_filaments_id . push_back ( filament_id ) ;
load_filaments_name . push_back ( config_name ) ;
load_filaments_config . push_back ( std : : move ( config ) ) ;
load_filaments_index . push_back ( current_index ) ;
load_filaments_set . emplace ( config_name ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " loaded filament %1% from file %2%, type %3%, name %4%, inherits %5% " ) % ( index + 1 ) % file % config_from % config_name % inherits ;
}
else {
if ( use_first_fila_as_default ) {
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : load filament %1% from default, config name %2%, filament_id %3%, current_index %4% " ) % ( index + 1 ) % default_load_fila_name % default_load_fila_id % current_index ;
load_filaments_id . push_back ( default_load_fila_id ) ;
load_filaments_name . push_back ( default_load_fila_name ) ;
load_filaments_config . push_back ( default_load_fila_config ) ;
load_filaments_index . push_back ( current_index ) ;
load_filaments_inherit . push_back ( default_filament_inherit ) ;
load_filaments_set . emplace ( default_load_fila_name ) ;
}
continue ;
}
}
2024-09-16 16:07:29 +08:00
//1.9.5
//add logic for obj auto colors
if ( input_obj_colours . size ( ) > 0 ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, got input obj colors %3% " ) % __FUNCTION__ % __LINE__ % input_obj_colours . size ( ) ;
int input_color_count = input_obj_colours . size ( ) ;
if ( load_filament_count = = 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " filament config not loaded when loading colored obj " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
//check filament_color from extra config
ConfigOptionStrings * selected_filament_colors_option = m_extra_config . option < ConfigOptionStrings > ( " filament_colour " ) ;
if ( selected_filament_colors_option ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " filament_colour should not be set when loading colored obj " ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
if ( load_filament_count < input_color_count ) {
int delta = input_color_count - load_filament_count ;
for ( int index = 0 ; index < delta ; index + + ) {
load_filaments_id . push_back ( load_filaments_id [ 0 ] ) ;
load_filaments_name . push_back ( load_filaments_name [ 0 ] ) ;
load_filaments_config . push_back ( load_filaments_config [ 0 ] ) ;
load_filaments_index . push_back ( index + 1 + load_filament_count ) ;
load_filaments_inherit . push_back ( load_filaments_inherit [ 0 ] ) ;
}
load_filament_count = input_color_count ;
}
selected_filament_colors_option = m_extra_config . option < ConfigOptionStrings > ( " filament_colour " , true ) ;
std : : vector < std : : string > & filament_colors = selected_filament_colors_option - > values ;
filament_colors . resize ( input_color_count ) ;
for ( int index = 0 ; index < input_color_count ; index + + )
{
std : : string color_string ;
int color [ 4 ] ;
color [ 0 ] = std : : clamp ( ( int ) ( input_obj_colours [ index ] [ 0 ] * 255.f ) , 0 , 255 ) ;
color [ 1 ] = std : : clamp ( ( int ) ( input_obj_colours [ index ] [ 1 ] * 255.f ) , 0 , 255 ) ;
color [ 2 ] = std : : clamp ( ( int ) ( input_obj_colours [ index ] [ 2 ] * 255.f ) , 0 , 255 ) ;
color [ 3 ] = std : : clamp ( ( int ) ( input_obj_colours [ index ] [ 3 ] * 255.f ) , 0 , 255 ) ;
std : : stringstream stream ;
stream < < std : : hex < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < color [ 0 ] ;
stream < < std : : hex < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < color [ 1 ] ;
stream < < std : : hex < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < color [ 2 ] ;
stream < < std : : hex < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < color [ 3 ] ;
std : : string result ( stream . str ( ) ) ;
filament_colors [ index ] = " # " + result ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%:%2%, index %3%, argb {%4%,%5%,%6%,%7%} to string %8% " ) % __FUNCTION__ % __LINE__ % ( index + 1 ) % color [ 0 ] % color [ 1 ] % color [ 2 ] % color [ 3 ] % filament_colors [ index ] ;
}
}
2024-09-03 09:34:33 +08:00
if ( filament_count = = 0 )
filament_count = load_filament_count ;
if ( is_qdt_3mf & & ( load_filament_count > 0 ) & & ( load_filaments_set . size ( ) = = 1 ) )
{
disable_wipe_tower_after_mapping = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " map all the filaments to the same one, load_filament_count %1% " ) % load_filament_count ;
}
//load system config if needed
bool fetch_compatible_values = false , fetch_upward_values = false ;
if ( is_qdt_3mf & & up_config_to_date ) {
if ( uptodate_configs . size ( ) > 0 )
{
for ( auto const & file : uptodate_configs ) {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( file , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( config_type = = " machine " ) {
if ( config_name ! = current_printer_system_name ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " wrong machine config file %1% loaded, current machine config name %2% " ) % config_name % current_printer_system_name ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
upward_compatible_printers = config . option < ConfigOptionStrings > ( " upward_compatible_machine " , true ) - > values ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " load a machine config %1% from file %2%, upward_compatible_printers size is %3% " ) % config_name % file % upward_compatible_printers . size ( ) ;
if ( new_printer_name . empty ( ) & & ! current_printer_system_name . empty ( ) )
{
config . set ( " printer_settings_id " , config_name , true ) ;
//get printer_model_id
printer_model = config . option < ConfigOptionString > ( " printer_model " , true ) - > value ;
if ( ! printer_model . empty ( ) ) {
std : : string printer_model_path = resources_dir ( ) + " /profiles/QDT/machine_full/ " + printer_model + " .json " ;
if ( boost : : filesystem : : exists ( printer_model_path ) )
{
std : : map < std : : string , std : : string > key_values ;
load_key_values_from_json ( printer_model_path , key_values ) ;
if ( key_values . find ( " model_id " ) ! = key_values . end ( ) ) {
printer_model_id = key_values [ " model_id " ] ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " :%1%, load printer_model_id %2% from current printer model %3% " ) % __LINE__ % printer_model_id % printer_model ;
}
}
}
int orig_printable_width = 0 , orig_printable_depth = 0 , orig_printable_height = 0 ;
Pointfs orig_printable_area ;
orig_printable_area = config . option < ConfigOptionPoints > ( " printable_area " , true ) - > values ;
if ( orig_printable_area . size ( ) > = 4 ) {
orig_printable_width = ( int ) ( orig_printable_area [ 2 ] . x ( ) - orig_printable_area [ 0 ] . x ( ) ) ;
orig_printable_depth = ( int ) ( orig_printable_area [ 2 ] . y ( ) - orig_printable_area [ 0 ] . y ( ) ) ;
}
orig_printable_height = ( int ) ( config . opt_float ( " printable_height " ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " :%1%, check printable size: old_printable_width=%2%, orig_printable_width=%3%, old_printable_depth=%4%, orig_printable_depth=%5%, old_printable_height=%6%, orig_printable_height=%7% " )
% __LINE__ % old_printable_width % orig_printable_width % old_printable_depth % orig_printable_depth % old_printable_height % orig_printable_height ;
if ( ( orig_printable_width > 0 ) & & ( orig_printable_depth > 0 ) & & ( orig_printable_height > 0 ) )
{
if ( ( old_printable_width > orig_printable_width ) | | ( old_printable_depth > orig_printable_depth ) | | ( old_printable_height > orig_printable_height ) )
{
std : : string error_str = ( boost : : format ( " Printer Settings: the printable size {%1%, %2%, %3%} exceeds the default size. " ) % old_printable_width % old_printable_depth % old_printable_height ) . str ( ) ;
BOOST_LOG_TRIVIAL ( error ) < < error_str ;
record_exit_reson ( outfile_dir , CLI_MODIFIED_PARAMS_TO_PRINTER , 0 , error_str , sliced_info ) ;
flush_and_exit ( CLI_MODIFIED_PARAMS_TO_PRINTER ) ;
}
}
load_machine_config = std : : move ( config ) ;
}
}
else if ( config_type = = " process " ) {
if ( config_name ! = current_process_system_name ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " wrong process config file %1% loaded, current process config name %2% " ) % config_name % current_process_system_name ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
current_print_compatible_printers = config . option < ConfigOptionStrings > ( " compatible_printers " , true ) - > values ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " load a process config %1% from file %2%, current_print_compatible_printers size is %3% " ) % config_name % file % current_print_compatible_printers . size ( ) ;
if ( new_process_name . empty ( ) & & ! current_process_system_name . empty ( ) )
{
config . set ( " print_settings_id " , config_name , true ) ;
load_process_config = std : : move ( config ) ;
}
}
else {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " found invalid config type %1% from config %2% " ) % config_type % file ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
}
}
else {
if ( new_printer_name . empty ( ) & & ! current_printer_system_name . empty ( ) ) {
//use the original printer name in 3mf
std : : string system_printer_path = resources_dir ( ) + " /profiles/QDT/machine_full/ " + current_printer_system_name + " .json " ;
if ( ! boost : : filesystem : : exists ( system_printer_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " :%1%, can not find system preset file: %2% " ) % __LINE__ % system_printer_path ;
//use original one
}
else {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( system_printer_path , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
upward_compatible_printers = config . option < ConfigOptionStrings > ( " upward_compatible_machine " , true ) - > values ;
config . set ( " printer_settings_id " , config_name , true ) ;
//get printer_model_id
printer_model = config . option < ConfigOptionString > ( " printer_model " , true ) - > value ;
if ( ! printer_model . empty ( ) ) {
std : : string printer_model_path = resources_dir ( ) + " /profiles/QDT/machine_full/ " + printer_model + " .json " ;
if ( boost : : filesystem : : exists ( printer_model_path ) )
{
std : : map < std : : string , std : : string > key_values ;
load_key_values_from_json ( printer_model_path , key_values ) ;
if ( key_values . find ( " model_id " ) ! = key_values . end ( ) ) {
printer_model_id = key_values [ " model_id " ] ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " :%1%, load printer_model_id %2% from current printer model %3% " ) % __LINE__ % printer_model_id % printer_model ;
}
}
}
load_machine_config = std : : move ( config ) ;
}
}
else
fetch_upward_values = true ;
if ( new_process_name . empty ( ) & & ! current_process_system_name . empty ( ) ) {
//use the original printer name in 3mf
std : : string system_process_path = resources_dir ( ) + " /profiles/QDT/process_full/ " + current_process_system_name + " .json " ;
if ( ! boost : : filesystem : : exists ( system_process_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " :%1%, can not find system preset file: %2% " ) % __LINE__ % system_process_path ;
//use original one
}
else {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( system_process_path , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
current_print_compatible_printers = config . option < ConfigOptionStrings > ( " compatible_printers " , true ) - > values ;
config . set ( " print_settings_id " , config_name , true ) ;
load_process_config = std : : move ( config ) ;
}
}
else
fetch_compatible_values = true ;
}
//filament processes
if ( load_filament_count = = 0 )
{
if ( uptodate_filaments . size ( ) > 0 )
{
2024-09-16 16:07:29 +08:00
//1.9.5
if ( uptodate_filaments . size ( ) ! = ( size_t ) filament_count )
2024-09-03 09:34:33 +08:00
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " uptodate_filaments size %1% not equal to filament_count %2% " ) % uptodate_filaments . size ( ) % filament_count ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
2024-09-16 16:07:29 +08:00
//1.9.5
for ( int index = 0 ; index < filament_count ; index + + )
2024-09-03 09:34:33 +08:00
{
std : : string file = uptodate_filaments [ index ] ;
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( file , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " load uptodate_filaments %1% fail, index %2%! " ) % file % index ;
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( config_type ! = " filament " ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : unknown config type %1% of file %2% in load-filaments " ) % config_type % file ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
if ( config_name ! = current_filaments_system_name [ index ] ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " wrong filament config file %1% loaded, current filament config name %2%, index %3% " ) % config_name % current_filaments_system_name [ index ] % index ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
load_filaments_id . push_back ( filament_id ) ;
load_filaments_name . push_back ( config_name ) ;
load_filaments_config . push_back ( std : : move ( config ) ) ;
load_filaments_index . push_back ( index + 1 ) ;
load_filaments_inherit . push_back ( config_name ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " load a filament config %1% from file %2%, using uptodate_filaments index %3% " ) % config_name % file % index ;
}
}
else
{
current_index = 0 ;
for ( int index = 0 ; index < current_filaments_system_name . size ( ) ; index + + )
{
std : : string system_filament_path = resources_dir ( ) + " /profiles/QDT/filament_full/ " + current_filaments_system_name [ index ] + " .json " ;
current_index + + ;
if ( ! boost : : filesystem : : exists ( system_filament_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " :%1%, can not find system preset file: %2% " ) % __LINE__ % system_filament_path ;
continue ;
}
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( system_filament_path , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( config_type ! = " filament " ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " : unknown config type %1% of file %2% in load-filaments " ) % config_type % system_filament_path ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
load_filaments_id . push_back ( filament_id ) ;
load_filaments_name . push_back ( config_name ) ;
load_filaments_config . push_back ( std : : move ( config ) ) ;
load_filaments_index . push_back ( current_index ) ;
load_filaments_inherit . push_back ( config_name ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " LINE %4%: load a filament config %1% from file %2%, index %3% " ) % config_name % system_filament_path % index % __LINE__ ;
}
}
}
}
else if ( is_qdt_3mf ) {
fetch_upward_values = true ;
fetch_compatible_values = true ;
}
//fetch upward_compatible_machine
if ( fetch_upward_values ) {
if ( ! current_printer_system_name . empty ( ) ) {
//use the original printer name in 3mf
std : : string system_printer_path = resources_dir ( ) + " /profiles/QDT/machine_full/ " + current_printer_system_name + " .json " ;
if ( ! boost : : filesystem : : exists ( system_printer_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " :%1%, can not find system preset file: %2% " ) % __LINE__ % system_printer_path ;
//skip
}
else {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( system_printer_path , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
upward_compatible_printers = config . option < ConfigOptionStrings > ( " upward_compatible_machine " , true ) - > values ;
}
}
}
//fetch print_compatible_printers
if ( fetch_compatible_values ) {
if ( ! current_process_system_name . empty ( ) ) {
//use the original printer name in 3mf
std : : string system_process_path = resources_dir ( ) + " /profiles/QDT/process_full/ " + current_process_system_name + " .json " ;
if ( ! boost : : filesystem : : exists ( system_process_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " :%1%, can not find system preset file: %2% " ) % __LINE__ % system_process_path ;
//use original one
}
else {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from ;
int ret = load_config_file ( system_process_path , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
current_print_compatible_printers = config . option < ConfigOptionStrings > ( " compatible_printers " , true ) - > values ;
}
}
}
//upwards check
bool process_compatible = false , machine_upwards = false , machine_switch = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " current printer %1%, new printer %2%, current process %3%, new process %4% " ) % current_printer_name % new_printer_name % current_process_name % new_process_name ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " current printer inherits %1%, new printer inherits %2%, current process inherits %3%, new process inherits %4% " )
% current_printer_system_name % new_printer_system_name % current_process_system_name % new_process_system_name ;
for ( int index = 0 ; index < current_print_compatible_printers . size ( ) ; index + + ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " index %1%, current print compatible printer %2% " ) % index % current_print_compatible_printers [ index ] ;
}
for ( int index = 0 ; index < new_print_compatible_printers . size ( ) ; index + + ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " index %1%, new print compatible printer %2% " ) % index % new_print_compatible_printers [ index ] ;
}
for ( int index = 0 ; index < upward_compatible_printers . size ( ) ; index + + ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " index %1%, upward_compatible_printers %2% " ) % index % upward_compatible_printers [ index ] ;
}
if ( ! new_printer_name . empty ( ) ) {
if ( ! new_process_name . empty ( ) ) {
for ( int index = 0 ; index < new_print_compatible_printers . size ( ) ; index + + ) {
if ( new_print_compatible_printers [ index ] = = new_printer_system_name ) {
process_compatible = true ;
break ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " new printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5% " )
% new_printer_name % new_printer_system_name % new_process_name % new_process_system_name % process_compatible ;
}
else {
for ( int index = 0 ; index < current_print_compatible_printers . size ( ) ; index + + ) {
if ( current_print_compatible_printers [ index ] = = new_printer_system_name ) {
process_compatible = true ;
break ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " new printer %1%, inherited from %2%, old process %3%, inherited from %4% ,compatible %5% " )
% new_printer_name % new_printer_system_name % current_process_name % current_process_system_name % process_compatible ;
}
}
else if ( ! new_process_name . empty ( ) ) {
for ( int index = 0 ; index < new_print_compatible_printers . size ( ) ; index + + ) {
if ( new_print_compatible_printers [ index ] = = current_printer_system_name ) {
process_compatible = true ;
break ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5% " )
% current_printer_name % current_printer_system_name % new_process_name % new_process_system_name % process_compatible ;
}
else {
//check the compatible of old printer&&process
for ( int index = 0 ; index < current_print_compatible_printers . size ( ) ; index + + ) {
if ( current_print_compatible_printers [ index ] = = current_printer_system_name ) {
process_compatible = true ;
break ;
}
}
if ( ! process_compatible & & current_print_compatible_printers . empty ( ) )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old 3mf, no compatible printers, set to compatible " ) ;
process_compatible = true ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old printer %1%, inherited from %2%, old process %3%, inherited from %4% ,compatible %5% " )
% current_printer_name % current_printer_system_name % current_process_name % current_process_system_name % process_compatible ;
}
if ( ! process_compatible & & ! new_printer_name . empty ( ) & & ! current_printer_name . empty ( ) & & ( new_printer_name ! = current_printer_name ) ) {
//set all printer to compatible
process_compatible = true ;
machine_switch = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " switch to new printers, set to compatible " ) ;
if ( upward_compatible_printers . size ( ) > 0 ) {
for ( int index = 0 ; index < upward_compatible_printers . size ( ) ; index + + ) {
if ( upward_compatible_printers [ index ] = = new_printer_system_name ) {
process_compatible = true ;
machine_upwards = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " new printer is upward_compatible " ) ;
break ;
}
}
if ( ! process_compatible ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " %1% : current 3mf file not support the new printer %2%, new_printer_system_name %3% " ) % __LINE__ % new_printer_name % new_printer_system_name ;
record_exit_reson ( outfile_dir , CLI_3MF_NEW_MACHINE_NOT_SUPPORTED , 0 , cli_errors [ CLI_3MF_NEW_MACHINE_NOT_SUPPORTED ] , sliced_info ) ;
flush_and_exit ( CLI_3MF_NEW_MACHINE_NOT_SUPPORTED ) ;
}
}
/*else {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " %1%: current 3mf file not support upward_compatible_printers, can not change machine preset. " ) % __LINE__ ;
record_exit_reson ( outfile_dir , CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE , 0 , cli_errors [ CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE ] , sliced_info ) ;
flush_and_exit ( CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE ) ;
} */
}
if ( ! process_compatible ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " %1%: process not compatible with printer. " ) % __LINE__ ;
record_exit_reson ( outfile_dir , CLI_PROCESS_NOT_COMPATIBLE , 0 , cli_errors [ CLI_PROCESS_NOT_COMPATIBLE ] , sliced_info ) ;
flush_and_exit ( CLI_PROCESS_NOT_COMPATIBLE ) ;
}
sliced_info . upward_machines = upward_compatible_printers ;
//create project embedded preset if needed
Preset * new_preset = NULL ;
if ( is_qdt_3mf & & machine_switch ) {
//we need to update the compatible printer and create a new process here, or if we load the 3mf in studio, the process preset can not be loaded as not compatible
Preset * current_preset = NULL ;
size_t project_presets_count = project_presets . size ( ) ;
for ( int index = 0 ; index < project_presets_count ; index + + )
{
if ( project_presets [ index ] - > name = = current_process_name ) {
current_preset = project_presets [ index ] ;
break ;
}
}
new_preset = new Preset ( Preset : : TYPE_PRINT , current_process_name ) ;
if ( current_preset ) {
* new_preset = * current_preset ;
std : : vector < std : : string > & compatible_printers = new_preset - > config . option < ConfigOptionStrings > ( " compatible_printers " , true ) - > values ;
bool need_insert = true ;
for ( int index = 0 ; index < compatible_printers . size ( ) ; index + + ) {
if ( compatible_printers [ index ] = = new_printer_system_name ) {
need_insert = false ;
break ;
}
}
if ( need_insert )
compatible_printers . push_back ( new_printer_system_name ) ;
}
else {
//store a project-embedded preset
const std : : vector < std : : string > & process_keys = Preset : : print_options ( ) ;
new_preset - > config . apply_only ( m_print_config , process_keys ) ;
std : : vector < std : : string > & compatible_printers = new_preset - > config . option < ConfigOptionStrings > ( " compatible_printers " , true ) - > values ;
compatible_printers = current_print_compatible_printers ;
compatible_printers . push_back ( new_printer_system_name ) ;
if ( current_process_system_name ! = current_process_name ) {
std : : string & inherits = new_preset - > config . option < ConfigOptionString > ( " inherits " , true ) - > value ;
inherits = current_process_system_name ;
}
new_preset - > is_project_embedded = true ;
new_preset - > type = Preset : : TYPE_PRINT ;
//new_preset->name = current_process_name;
}
new_preset - > name + = " (auto) " ;
new_preset - > config . set ( " print_settings_id " , new_preset - > name , true ) ;
m_print_config . set ( " print_settings_id " , new_preset - > name , true ) ;
project_presets . push_back ( new_preset ) ;
}
//update seperate configs into full config
auto update_full_config = [ ] ( DynamicPrintConfig & full_config , const DynamicPrintConfig & config , std : : set < std : : string > & diff_key_sets , bool update_all = false , bool skip_gcodes = false ) {
const t_config_option_keys & config_keys = config . keys ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " update_full_config: config keys count %1% " ) % config_keys . size ( ) ;
for ( const t_config_option_key & opt_key : config_keys ) {
if ( ! update_all & & ! diff_key_sets . empty ( ) ) {
std : : set < std : : string > : : iterator iter = diff_key_sets . find ( opt_key ) ;
if ( iter ! = diff_key_sets . end ( ) ) {
if ( skip_gcodes & & ( gcodes_key_set . find ( opt_key ) ! = gcodes_key_set . end ( ) ) )
{
diff_key_sets . erase ( iter ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, gcodes %2% modified, reset to default. " ) % __LINE__ % opt_key ;
}
else {
//uptodate, diff keys, continue
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, keep key %2% " ) % __LINE__ % opt_key ;
continue ;
}
}
}
const ConfigOption * source_opt = config . option ( opt_key ) ;
if ( source_opt = = nullptr ) {
// The key was not found in the source config, therefore it will not be initialized!
boost : : nowide : : cerr < < __FUNCTION__ < < " : can not found option " < < opt_key < < " from config. " < < std : : endl ;
return CLI_CONFIG_FILE_ERROR ;
}
if ( opt_key = = " compatible_prints " | | opt_key = = " compatible_printers " | | opt_key = = " model_id " | | opt_key = = " inherits " | | opt_key = = " dev_model_name "
| | opt_key = = " name " | | opt_key = = " from " | | opt_key = = " type " | | opt_key = = " version " | | opt_key = = " setting_id " | | opt_key = = " instantiation " )
continue ;
else {
ConfigOption * dest_opt = full_config . option ( opt_key , true ) ;
if ( dest_opt = = nullptr ) {
boost : : nowide : : cerr < < __FUNCTION__ < < " :can not create option " < < opt_key < < " to full_config " < < std : : endl ;
return CLI_CONFIG_FILE_ERROR ;
}
dest_opt - > set ( source_opt ) ;
//*dest_opt = *source_opt;
}
}
return 0 ;
} ;
std : : vector < std : : string > & different_settings = m_print_config . option < ConfigOptionStrings > ( " different_settings_to_system " , true ) - > values ;
std : : vector < std : : string > & inherits_group = m_print_config . option < ConfigOptionStrings > ( " inherits_group " , true ) - > values ;
inherits_group . resize ( filament_count + 2 , std : : string ( ) ) ;
different_settings . resize ( filament_count + 2 , std : : string ( ) ) ;
if ( ! is_qdt_3mf & & ! different_process_setting . empty ( ) ) {
different_settings [ 0 ] = different_process_setting ;
}
//set the machine settings into print config
if ( ! new_printer_name . empty ( ) | | up_config_to_date ) {
std : : vector < std : : string > different_keys ;
if ( new_printer_name . empty ( ) ) {
std : : string diff_settings ;
if ( ! different_settings . empty ( ) ) {
diff_settings = different_settings [ filament_count + 1 ] ;
Slic3r : : unescape_strings_cstyle ( diff_settings , different_keys ) ;
}
}
else {
//todo: support user machine preset's different settings
different_settings [ filament_count + 1 ] = " " ;
if ( new_printer_config_is_system )
inherits_group [ filament_count + 1 ] = " " ;
else
inherits_group [ filament_count + 1 ] = new_printer_system_name ;
}
std : : set < std : : string > different_keys_set ( different_keys . begin ( ) , different_keys . end ( ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " update printer config to newest, different size %1%, different_settings: %2% " ) % different_keys_set . size ( ) % different_settings [ filament_count + 1 ] ;
int ret ;
load_default_gcodes_to_config ( load_machine_config , Preset : : TYPE_PRINTER ) ;
if ( new_printer_name . empty ( ) ) {
int diff_keys_size = different_keys_set . size ( ) ;
ret = update_full_config ( m_print_config , load_machine_config , different_keys_set , false , skip_modified_gcodes ) ;
if ( diff_keys_size ! = different_keys_set . size ( ) ) {
//changed
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " new different key size %1% " ) % different_keys_set . size ( ) ;
different_keys . clear ( ) ;
for ( std : : set < std : : string > : : iterator iter = different_keys_set . begin ( ) ; iter ! = different_keys_set . end ( ) ; + + iter )
different_keys . emplace_back ( * iter ) ;
different_settings [ filament_count + 1 ] = Slic3r : : escape_strings_cstyle ( different_keys ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " no new printer, only update the different key, new different_settings: %1% " ) % different_settings [ filament_count + 1 ] ;
}
else {
ret = update_full_config ( m_print_config , load_machine_config , different_keys_set , true ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " load a new printer, update all the keys, different_settings: %1% " ) % different_settings [ filament_count + 1 ] ;
if ( new_printer_name ! = current_printer_name )
{
//printer safe check
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " check printer cli safe params, current_printer_name %1%, new_printer_name %2%, printer_model %3% " ) % current_printer_name % new_printer_name % printer_model ;
std : : map < std : : string , std : : string > printer_params ;
std : : string cli_config_file = resources_dir ( ) + " /profiles/QDT/cli_config.json " ;
boost : : filesystem : : path directory_path ( cli_config_file ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " line %1% , will parse file %2% " ) % __LINE__ % cli_config_file ;
if ( ! fs : : exists ( directory_path ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " file %1% not exist. " ) % cli_config_file ;
}
else {
try {
json root_json ;
boost : : nowide : : ifstream ifs ( cli_config_file ) ;
ifs > > root_json ;
ifs . close ( ) ;
if ( root_json . contains ( " printer " ) ) {
json printer_json = root_json [ " printer " ] ;
if ( ! printer_model . empty ( ) & & printer_json . contains ( printer_model ) ) {
json printer_model_json = printer_json [ printer_model ] ;
if ( printer_model_json . contains ( " machine_limits " ) ) {
json machine_limits_json = printer_model_json [ " machine_limits " ] ;
printer_params = machine_limits_json . get < std : : map < std : : string , std : : string > > ( ) ;
for ( auto param_iter = printer_params . begin ( ) ; param_iter ! = printer_params . end ( ) ; param_iter + + )
{
std : : string key = param_iter - > first ;
//replace "cli_safe" with "machine_max"
key . replace ( 0 , 8 , " machine_max " ) ;
ConfigOptionFloats * option = m_print_config . option < ConfigOptionFloats > ( key ) ;
if ( option ) {
//de-serialize the values from param_iter->second, and do the compare here
unsigned int array_count = option - > size ( ) ;
ConfigOptionFloats new_option ;
new_option . deserialize ( param_iter - > second ) ;
unsigned int new_array_count = new_option . size ( ) ;
for ( unsigned int index = 0 ; index < array_count ; index + + )
{
if ( ( index < new_array_count ) & & new_option . values [ index ] ! = 0.f & & ( new_option . values [ index ] < option - > values [ index ] ) )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " set key %1% index %2%, from %3% to %4% " ) % key % index % option - > values [ index ] % new_option . values [ index ] ;
option - > values [ index ] = new_option . values [ index ] ;
}
}
}
else
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " can not find key %1% in config " ) % key ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " can not find machine_limits for printer %1% in cli_config.json " ) % printer_model ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " can not find key %1% in the file " ) % printer_model ;
}
}
else {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " can not find key printer in the file " ) ;
}
}
catch ( std : : exception & err ) {
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < " : parse file " < < cli_config_file < < " got a generic exception, reason = " < < err . what ( ) ;
}
}
}
}
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
}
//set the process settings into print config
std : : vector < std : : string > & print_compatible_printers = m_print_config . option < ConfigOptionStrings > ( " print_compatible_printers " , true ) - > values ;
if ( ! new_process_name . empty ( ) | | up_config_to_date ) {
std : : vector < std : : string > different_keys ;
if ( new_process_name . empty ( ) ) {
std : : string diff_settings ;
if ( ! different_settings . empty ( ) ) {
diff_settings = different_settings [ 0 ] ;
Slic3r : : unescape_strings_cstyle ( diff_settings , different_keys ) ;
int remove_index = - 1 ;
for ( int index = 0 ; index < different_keys . size ( ) ; index + + ) {
if ( different_keys [ index ] = = " compatible_printers " ) {
remove_index = index ;
break ;
}
}
if ( remove_index ! = - 1 ) {
different_keys [ remove_index ] = different_keys [ different_keys . size ( ) - 1 ] ;
different_keys . erase ( different_keys . begin ( ) + different_keys . size ( ) - 1 ) ;
different_settings [ 0 ] = Slic3r : : escape_strings_cstyle ( different_keys ) ;
}
}
print_compatible_printers = std : : move ( current_print_compatible_printers ) ;
}
else {
//todo: support system process preset
different_settings [ 0 ] = " " ;
if ( new_process_config_is_system )
inherits_group [ 0 ] = " " ;
else
inherits_group [ 0 ] = new_process_system_name ;
print_compatible_printers = std : : move ( new_print_compatible_printers ) ;
}
std : : set < std : : string > different_keys_set ( different_keys . begin ( ) , different_keys . end ( ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " update process config to newest, different size %1%, different_settings: %2% " ) % different_keys_set . size ( ) % different_settings [ 0 ] ;
int ret ;
load_default_gcodes_to_config ( load_machine_config , Preset : : TYPE_PRINT ) ;
if ( new_process_name . empty ( ) ) {
int diff_keys_size = different_keys_set . size ( ) ;
ret = update_full_config ( m_print_config , load_process_config , different_keys_set , false , skip_modified_gcodes ) ;
if ( diff_keys_size ! = different_keys_set . size ( ) ) {
//changed
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " new different key size %1% " ) % different_keys_set . size ( ) ;
different_keys . clear ( ) ;
for ( std : : set < std : : string > : : iterator iter = different_keys_set . begin ( ) ; iter ! = different_keys_set . end ( ) ; + + iter )
different_keys . emplace_back ( * iter ) ;
different_settings [ 0 ] = Slic3r : : escape_strings_cstyle ( different_keys ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " no new process, only update the different key, new different_settings: %1% " ) % different_settings [ 0 ] ;
}
else {
ret = update_full_config ( m_print_config , load_process_config , different_keys_set , true ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " load a new process, update all the keys, different_settings: %1% " ) % different_settings [ 0 ] ;
}
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
}
if ( machine_switch ) {
print_compatible_printers . push_back ( new_printer_system_name ) ;
std : : string old_setting = different_settings [ 0 ] ;
if ( old_setting . empty ( ) )
different_settings [ 0 ] = " compatible_printers " ;
else {
std : : vector < std : : string > different_keys ;
Slic3r : : unescape_strings_cstyle ( old_setting , different_keys ) ;
bool need_insert = true ;
for ( int index = 0 ; index < different_keys . size ( ) ; index + + ) {
if ( different_keys [ index ] = = " compatible_printers " ) {
need_insert = false ;
break ;
}
}
if ( need_insert )
different_settings [ 0 ] = old_setting + " ;compatible_printers " ;
}
}
//set the filament settings into print config
if ( ( load_filament_count > 0 ) | | ( up_config_to_date ) )
{
for ( int index = 0 ; index < load_filaments_config . size ( ) ; index + + ) {
DynamicPrintConfig & config = load_filaments_config [ index ] ;
int filament_index = load_filaments_index [ index ] ;
std : : vector < std : : string > different_keys ;
load_default_gcodes_to_config ( config , Preset : : TYPE_FILAMENT ) ;
if ( load_filament_count > 0 ) {
ConfigOptionStrings * opt_filament_settings = static_cast < ConfigOptionStrings * > ( m_print_config . option ( " filament_settings_id " , true ) ) ;
std : : string & filament_name = load_filaments_name [ index ] ;
ConfigOptionString * filament_name_setting = new ConfigOptionString ( filament_name ) ;
if ( opt_filament_settings - > size ( ) < filament_count )
opt_filament_settings - > resize ( filament_count , filament_name_setting ) ;
opt_filament_settings - > set_at ( filament_name_setting , filament_index - 1 , 0 ) ;
config . erase ( " filament_settings_id " ) ;
std : : string & filament_id = load_filaments_id [ index ] ;
ConfigOptionStrings * opt_filament_ids = static_cast < ConfigOptionStrings * > ( m_print_config . option ( " filament_ids " , true ) ) ;
ConfigOptionString * filament_id_setting = new ConfigOptionString ( filament_id ) ;
if ( opt_filament_ids - > size ( ) < filament_count )
opt_filament_ids - > resize ( filament_count , filament_id_setting ) ;
opt_filament_ids - > set_at ( filament_id_setting , filament_index - 1 , 0 ) ;
//todo: update different settings of filaments
different_settings [ filament_index ] = " " ;
inherits_group [ filament_index ] = load_filaments_inherit [ index ] ;
}
else {
std : : string diff_settings ;
if ( ! different_settings . empty ( ) ) {
diff_settings = different_settings [ filament_index ] ;
Slic3r : : unescape_strings_cstyle ( diff_settings , different_keys ) ;
}
}
//parse the filament value to index th
//loop through options and apply them
std : : set < std : : string > different_keys_set ( different_keys . begin ( ) , different_keys . end ( ) ) ;
int diff_keys_size = different_keys_set . size ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " update filament %1%'s config to newest, different size %2%, name %3%, different_settings %4% " )
% filament_index % different_keys_set . size ( ) % load_filaments_name [ index ] % different_settings [ filament_index ] ;
for ( const t_config_option_key & opt_key : config . keys ( ) ) {
if ( ( load_filament_count = = 0 ) & & ! different_keys_set . empty ( ) )
{
std : : set < std : : string > : : iterator iter = different_keys_set . find ( opt_key ) ;
if ( iter ! = different_keys_set . end ( ) ) {
if ( skip_modified_gcodes & & ( gcodes_key_set . find ( opt_key ) ! = gcodes_key_set . end ( ) ) )
{
different_keys_set . erase ( iter ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, filament %2%'s gcodes %3% modified, reset to default. " ) % __LINE__ % filament_index % opt_key ;
}
else {
//uptodate, diff keys, continue
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, keep key %2% " ) % __LINE__ % opt_key ;
continue ;
}
}
}
// Create a new option with default value for the key.
// If the key is not in the parameter definition, or this ConfigBase is a static type and it does not support the parameter,
// an exception is thrown if not ignore_nonexistent.
const ConfigOption * source_opt = config . option ( opt_key ) ;
if ( source_opt = = nullptr ) {
// The key was not found in the source config, therefore it will not be initialized!
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " can not find %1% from filament %2%: %3% " ) % opt_key % filament_index % load_filaments_name [ index ] ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
if ( source_opt - > is_scalar ( ) ) {
if ( opt_key = = " compatible_printers_condition " ) {
ConfigOption * opt = m_print_config . option ( " compatible_machine_expression_group " , true ) ;
ConfigOptionStrings * opt_vec_dst = static_cast < ConfigOptionStrings * > ( opt ) ;
if ( opt_vec_dst - > size ( ) = = 0 )
opt_vec_dst - > resize ( filament_count + 2 , new ConfigOptionString ( ) ) ;
opt_vec_dst - > set_at ( source_opt , filament_index , 0 ) ;
}
else if ( opt_key = = " compatible_prints_condition " ) {
ConfigOption * opt = m_print_config . option ( " compatible_process_expression_group " , true ) ;
ConfigOptionStrings * opt_vec_dst = static_cast < ConfigOptionStrings * > ( opt ) ;
if ( opt_vec_dst - > size ( ) = = 0 )
opt_vec_dst - > resize ( filament_count , new ConfigOptionString ( ) ) ;
opt_vec_dst - > set_at ( source_opt , filament_index - 1 , 0 ) ;
}
else {
//skip the scalar values
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " skip scalar option %1% from filament %2%: %3% " ) % opt_key % filament_index % load_filaments_name [ index ] ; ;
continue ;
}
}
else
{
if ( opt_key = = " compatible_prints " | | opt_key = = " compatible_printers " | | opt_key = = " model_id " | | opt_key = = " dev_model_name " | | opt_key = = " filament_settings_id " )
continue ;
ConfigOption * opt = m_print_config . option ( opt_key , true ) ;
if ( opt = = nullptr ) {
// opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def().
// This is only possible if other is of DynamicConfig type.
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " can not create option %1% to config, from filament %2%: %3% " ) % opt_key % filament_index % load_filaments_name [ index ] ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
ConfigOptionVectorBase * opt_vec_dst = static_cast < ConfigOptionVectorBase * > ( opt ) ;
const ConfigOptionVectorBase * opt_vec_src = static_cast < const ConfigOptionVectorBase * > ( source_opt ) ;
opt_vec_dst - > set_at ( opt_vec_src , filament_index - 1 , 0 ) ;
}
}
if ( diff_keys_size ! = different_keys_set . size ( ) ) {
//changed
different_keys . clear ( ) ;
for ( std : : set < std : : string > : : iterator iter = different_keys_set . begin ( ) ; iter ! = different_keys_set . end ( ) ; + + iter )
different_keys . emplace_back ( * iter ) ;
different_settings [ filament_index ] = Slic3r : : escape_strings_cstyle ( different_keys ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " filament %1% new different key size %2%, different_settings %3% " ) % filament_index % different_keys_set . size ( ) % different_settings [ filament_index ] ;
}
}
}
//compute the flush volume
ConfigOptionStrings * selected_filament_colors_option = m_extra_config . option < ConfigOptionStrings > ( " filament_colour " ) ;
ConfigOptionStrings * project_filament_colors_option = m_print_config . option < ConfigOptionStrings > ( " filament_colour " ) ;
if ( ( ! project_filament_colors_option | | ( project_filament_colors_option - > values . size ( ) = = 0 ) ) & & selected_filament_colors_option )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " initial project_filament_colors is null, create it due to filament_colour set in cli " ) ;
project_filament_colors_option = m_print_config . option < ConfigOptionStrings > ( " filament_colour " , true ) ;
std : : vector < std : : string > & project_filament_colors = project_filament_colors_option - > values ;
project_filament_colors . resize ( filament_count , " #FFFFFF " ) ;
}
if ( project_filament_colors_option & & ( selected_filament_colors_option | | ! m_print_config . option < ConfigOptionFloats > ( " flush_volumes_matrix " ) ) )
{
std : : vector < std : : string > selected_filament_colors ;
if ( selected_filament_colors_option ) {
selected_filament_colors = selected_filament_colors_option - > values ;
//erase here
m_extra_config . erase ( " filament_colour " ) ;
if ( disable_wipe_tower_after_mapping ) {
std : : set < std : : string > filament_color_set ;
for ( unsigned int color_index = 0 ; color_index < selected_filament_colors . size ( ) ; color_index + + )
{
if ( ! selected_filament_colors [ color_index ] . empty ( ) ) {
filament_color_set . emplace ( selected_filament_colors [ color_index ] ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " add color, index %1%, value %2% to set " ) % color_index % selected_filament_colors [ color_index ] ;
}
else
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " skip empty color %1% " ) % color_index ;
}
if ( filament_color_set . size ( ) > 1 ) {
disable_wipe_tower_after_mapping = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " different filament colours, switch disable_wipe_tower_after_mapping back to false " ) ;
}
else {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " only %1% filament colour, finally set disable_wipe_tower_after_mapping to true " ) % filament_color_set . size ( ) ;
}
}
}
std : : vector < std : : string > & project_filament_colors = project_filament_colors_option - > values ;
size_t project_filament_count = project_filament_colors . size ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " select filament color from cli, size %1% " ) % selected_filament_colors . size ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " project filament colors size %1% " ) % project_filament_colors . size ( ) ;
if ( project_filament_count > 0 )
{
for ( size_t index = 0 ; index < project_filament_count ; index + + )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " project filament %1% original color %2% " ) % index % project_filament_colors [ index ] ;
if ( selected_filament_colors . size ( ) > index )
{
if ( ! selected_filament_colors [ index ] . empty ( ) )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " changed to new color %1% " ) % selected_filament_colors [ index ] ;
unsigned char ori_rgb_color [ 4 ] = { } , new_rgb_color [ 4 ] = { } ;
Slic3r : : GUI : : BitmapCache : : parse_color4 ( project_filament_colors [ index ] , ori_rgb_color ) ;
Slic3r : : GUI : : BitmapCache : : parse_color4 ( selected_filament_colors [ index ] , new_rgb_color ) ;
if ( ( ori_rgb_color [ 0 ] ! = new_rgb_color [ 0 ] ) | | ( ori_rgb_color [ 1 ] ! = new_rgb_color [ 1 ] ) | | ( ori_rgb_color [ 2 ] ! = new_rgb_color [ 2 ] ) | | ( ori_rgb_color [ 3 ] ! = new_rgb_color [ 3 ] ) )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " found color changes, need to regenerate thumbnail " ) ;
filament_color_changed = true ;
}
project_filament_colors [ index ] = selected_filament_colors [ index ] ;
}
}
}
//computing
ConfigOptionBools * filament_is_support = m_print_config . option < ConfigOptionBools > ( " filament_is_support " , true ) ;
std : : vector < double > & flush_vol_matrix = m_print_config . option < ConfigOptionFloats > ( " flush_volumes_matrix " , true ) - > values ;
//std::vector<float>& flush_vol_vector = m_print_config.option<ConfigOptionFloats>("flush_volumes_vector", true)->values;
flush_vol_matrix . resize ( project_filament_count * project_filament_count , 0.f ) ;
//flush_vol_vector.resize(project_filament_count);
//set multiplier to 1?
m_print_config . option < ConfigOptionFloat > ( " flush_multiplier " , true ) - > set ( new ConfigOptionFloat ( 1.f ) ) ;
const std : : vector < int > & min_flush_volumes = Slic3r : : GUI : : get_min_flush_volumes ( m_print_config ) ;
if ( filament_is_support - > size ( ) ! = project_filament_count )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " filament_is_support's count %1% not equal to filament_colour's size %2% " ) % filament_is_support - > size ( ) % project_filament_count ;
record_exit_reson ( outfile_dir , CLI_CONFIG_FILE_ERROR , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_CONFIG_FILE_ERROR ) ;
}
{
std : : ostringstream volumes_str ;
std : : copy ( min_flush_volumes . begin ( ) , min_flush_volumes . end ( ) , std : : ostream_iterator < int > ( volumes_str , " , " ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " extra_flush_volume: %1% " ) % volumes_str . str ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " filament_is_support: %1% " ) % filament_is_support - > serialize ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " flush_volumes_matrix before computing: %1% " ) % m_print_config . option < ConfigOptionFloats > ( " flush_volumes_matrix " ) - > serialize ( ) ;
}
for ( int from_idx = 0 ; from_idx < project_filament_count ; from_idx + + ) {
const std : : string & from_color = project_filament_colors [ from_idx ] ;
unsigned char from_rgb [ 4 ] = { } ;
Slic3r : : GUI : : BitmapCache : : parse_color4 ( from_color , from_rgb ) ;
bool is_from_support = filament_is_support - > get_at ( from_idx ) ;
for ( int to_idx = 0 ; to_idx < project_filament_count ; to_idx + + ) {
bool is_to_support = filament_is_support - > get_at ( to_idx ) ;
if ( from_idx = = to_idx ) {
flush_vol_matrix [ project_filament_count * from_idx + to_idx ] = 0.f ;
}
else {
int flushing_volume = 0 ;
if ( is_to_support ) {
flushing_volume = Slic3r : : g_flush_volume_to_support ;
}
else {
const std : : string & to_color = project_filament_colors [ to_idx ] ;
unsigned char to_rgb [ 4 ] = { } ;
Slic3r : : GUI : : BitmapCache : : parse_color4 ( to_color , to_rgb ) ;
//BOOST_LOG_TRIVIAL(info) << boost::format("src_idx %1%, src color %2%, dst idex %3%, dst color %4%")%from_idx %from_color %to_idx %to_color;
//BOOST_LOG_TRIVIAL(info) << boost::format("src_rgba {%1%,%2%,%3%,%4%} dst_rgba {%5%,%6%,%7%,%8%}")%(unsigned int)(from_rgb[0]) %(unsigned int)(from_rgb[1]) %(unsigned int)(from_rgb[2]) %(unsigned int)(from_rgb[3])
// %(unsigned int)(to_rgb[0]) %(unsigned int)(to_rgb[1]) %(unsigned int)(to_rgb[2]) %(unsigned int)(to_rgb[3]);
Slic3r : : FlushVolCalculator calculator ( min_flush_volumes [ from_idx ] , Slic3r : : g_max_flush_volume ) ;
flushing_volume = calculator . calc_flush_vol ( from_rgb [ 3 ] , from_rgb [ 0 ] , from_rgb [ 1 ] , from_rgb [ 2 ] , to_rgb [ 3 ] , to_rgb [ 0 ] , to_rgb [ 1 ] , to_rgb [ 2 ] ) ;
if ( is_from_support ) {
flushing_volume = std : : max ( Slic3r : : g_min_flush_volume_from_support , flushing_volume ) ;
}
}
flush_vol_matrix [ project_filament_count * from_idx + to_idx ] = flushing_volume ;
//flushing_volume = int(flushing_volume * get_flush_multiplier());
}
}
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " flush_volumes_matrix after computed: %1% " ) % m_print_config . option < ConfigOptionFloats > ( " flush_volumes_matrix " ) - > serialize ( ) ;
}
else
{
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " filament colors count is 0 in projects " ) ;
}
}
else
{
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " no filament colors found in projects " ) ;
}
//QDS: set default to ptFFF
if ( printer_technology = = ptUnknown )
printer_technology = ptFFF ;
//QDS: merge these models into one
BOOST_LOG_TRIVIAL ( info ) < < " total " < < m_models . size ( ) < < " models, " < < orients_requirement . size ( ) < < " objects " < < std : : endl ;
if ( m_models . size ( ) > 1 )
{
BOOST_LOG_TRIVIAL ( info ) < < " merge all the models into one \n " ;
Model m ;
m . set_backup_path ( m_models [ 0 ] . get_backup_path ( ) ) ;
for ( auto & model : m_models )
for ( ModelObject * o : model . objects )
{
ModelObject * new_object = m . add_object ( * o ) ;
//BOOST_LOG_TRIVIAL(info) << "object "<<o->name <<", id :" << o->id().id << "\n";
//orients_requirement.emplace(new_object->id().id, orients_requirement[o->id().id]);
//orients_requirement.erase(o->id().id);
}
m . add_default_instances ( ) ;
m_models . clear ( ) ;
m_models . emplace_back ( std : : move ( m ) ) ;
}
//load custom gcodes into model if needed
if ( ( custom_gcodes_map . size ( ) > 0 ) & & ( m_models . size ( ) > 0 ) )
{
m_models [ 0 ] . plates_custom_gcodes = custom_gcodes_map ;
/*m_models[0].plates_custom_gcodes.clear();
for ( auto & custom_gcode : custom_gcodes_map )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " insert custom_gocde %1% into plate %2% " ) % plate_id ;
m_models [ 0 ] . plates_custom_gcodes . emplace ( custom_gcode . first , custom_gcode . second ) ;
} */
}
if ( skip_modified_gcodes )
{
std : : map < int , CustomGCode : : Info > : : iterator gcodes_iter ;
for ( gcodes_iter = m_models [ 0 ] . plates_custom_gcodes . begin ( ) ; gcodes_iter ! = m_models [ 0 ] . plates_custom_gcodes . end ( ) ; gcodes_iter + + )
{
CustomGCode : : Info & gcode_info = gcodes_iter - > second ;
std : : vector < CustomGCode : : Item > : : iterator item_iter = gcode_info . gcodes . begin ( ) ;
while ( item_iter ! = gcode_info . gcodes . end ( ) )
{
if ( item_iter - > type = = CustomGCode : : Custom ) {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " skip_modified_gcodes: remove custom gcodes %1% in plate %2% " ) % item_iter - > extra % gcodes_iter - > first ;
item_iter = gcode_info . gcodes . erase ( item_iter ) ;
}
else
item_iter + + ;
}
}
}
// Apply command line options to a more specific DynamicPrintConfig which provides normalize()
// (command line options override --load files)
m_print_config . apply ( m_extra_config , true ) ;
// Normalizing after importing the 3MFs / AMFs
m_print_config . normalize_fdm ( ) ;
m_print_config . option < ConfigOptionEnum < PrinterTechnology > > ( " printer_technology " , true ) - > value = printer_technology ;
// Initialize full print configs for both the FFF and SLA technologies.
FullPrintConfig fff_print_config ;
//SLAFullPrintConfig sla_print_config;
// Synchronize the default parameters and the ones received on the command line.
if ( printer_technology = = ptFFF ) {
fff_print_config . apply ( m_print_config , true ) ;
m_print_config . apply ( fff_print_config , true ) ;
} else {
boost : : nowide : : cerr < < " invalid printer_technology " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PRINTER_TECH , 0 , cli_errors [ CLI_INVALID_PRINTER_TECH ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PRINTER_TECH ) ;
/*assert(printer_technology == ptSLA);
sla_print_config . filename_format . value = " [input_filename_base].sl1 " ;
// The default bed shape should reflect the default display parameters
// and not the fff defaults.
double w = sla_print_config . display_width . getFloat ( ) ;
double h = sla_print_config . display_height . getFloat ( ) ;
sla_print_config . printable_area . values = { Vec2d ( 0 , 0 ) , Vec2d ( w , 0 ) , Vec2d ( w , h ) , Vec2d ( 0 , h ) } ;
sla_print_config . apply ( m_print_config , true ) ;
m_print_config . apply ( sla_print_config , true ) ; */
}
std : : map < std : : string , std : : string > validity = m_print_config . validate ( true ) ;
if ( ! validity . empty ( ) ) {
boost : : nowide : : cerr < < " Param values in 3mf/config error: " < < std : : endl ;
for ( std : : map < std : : string , std : : string > : : iterator it = validity . begin ( ) ; it ! = validity . end ( ) ; + + it )
boost : : nowide : : cerr < < it - > first < < " : " < < it - > second < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_VALUES_IN_3MF , 0 , cli_errors [ CLI_INVALID_VALUES_IN_3MF ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_VALUES_IN_3MF ) ;
}
auto timelapse_type_opt = m_print_config . option ( " timelapse_type " ) ;
bool is_smooth_timelapse = false ;
if ( enable_timelapse & & timelapse_type_opt & & ( timelapse_type_opt - > getInt ( ) = = TimelapseType : : tlSmooth ) )
is_smooth_timelapse = true ;
if ( disable_wipe_tower_after_mapping ) {
if ( is_smooth_timelapse )
{
disable_wipe_tower_after_mapping = false ;
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " %1%: disable_wipe_tower_after_mapping: set back to false due to smooth timelapse! " ) % __LINE__ ;
}
else {
ConfigOptionBool * enable_wipe_op = m_print_config . option < ConfigOptionBool > ( " enable_prime_tower " , true ) ;
enable_wipe_op - > value = false ;
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " %1%: disable_wipe_tower_after_mapping: disable prime tower for only one filament! " ) % __LINE__ ;
std : : string diff_settings = different_settings [ 0 ] ;
if ( diff_settings . empty ( ) )
different_settings [ 0 ] = " enable_prime_tower " ;
else {
std : : vector < std : : string > different_keys ;
Slic3r : : unescape_strings_cstyle ( diff_settings , different_keys ) ;
bool need_insert = true ;
for ( int index = 0 ; index < different_keys . size ( ) ; index + + ) {
if ( different_keys [ index ] = = " enable_prime_tower " ) {
need_insert = false ;
break ;
}
}
if ( need_insert )
different_settings [ 0 ] = diff_settings + " ;enable_prime_tower " ;
}
}
}
//QDS: partplate list
Slic3r : : GUI : : PartPlateList partplate_list ( NULL , m_models . data ( ) , printer_technology ) ;
//use Pointfs insteadof Points
Pointfs current_printable_area = m_print_config . opt < ConfigOptionPoints > ( " printable_area " ) - > values ;
Pointfs current_exclude_area = m_print_config . opt < ConfigOptionPoints > ( " bed_exclude_area " ) - > values ;
//update part plate's size
double print_height = m_print_config . opt_float ( " printable_height " ) ;
double height_to_lid = m_print_config . opt_float ( " extruder_clearance_height_to_lid " ) ;
double height_to_rod = m_print_config . opt_float ( " extruder_clearance_height_to_rod " ) ;
double cleareance_radius = m_print_config . opt_float ( " extruder_clearance_max_radius " ) ;
//double plate_stride;
std : : string bed_texture ;
current_printable_width = current_printable_area [ 2 ] . x ( ) - current_printable_area [ 0 ] . x ( ) ;
current_printable_depth = current_printable_area [ 2 ] . y ( ) - current_printable_area [ 0 ] . y ( ) ;
current_printable_height = print_height ;
if ( old_printable_width = = 0 )
old_printable_width = current_printable_width ;
if ( old_printable_depth = = 0 )
old_printable_depth = current_printable_depth ;
if ( old_printable_height = = 0 )
old_printable_height = current_printable_height ;
if ( is_qdt_3mf & & ( old_printable_width > 0 ) & & ( old_printable_depth > 0 ) & & ( old_printable_height > 0 ) )
{
//check the printable size logic
//if ((old_printable_width > current_printable_width) || (old_printable_depth > current_printable_depth) || (old_printable_height > current_printable_height))
if ( ( old_printable_width > current_printable_width ) | | ( old_printable_depth > current_printable_depth ) | | ( old_printable_height > current_printable_height ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " old printable size {%1%, %2%, %3%} is larger than new printable size {%4%, %5%, %6%}, the object size should be limited " )
% old_printable_width % old_printable_depth % old_printable_height % current_printable_width % current_printable_depth % current_printable_height ;
/*record_exit_reson(outfile_dir, CLI_PRINTABLE_SIZE_REDUCED, 0, cli_errors[CLI_PRINTABLE_SIZE_REDUCED], sliced_info);
flush_and_exit ( CLI_PRINTABLE_SIZE_REDUCED ) ; */
shrink_to_new_bed = 2 ;
}
else if ( ( old_printable_width < current_printable_width ) | | ( old_printable_depth < current_printable_depth ) )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old printable size {%1%, %2%, %3%} is smaller than new printable size {%4%, %5%, %6%}, need to center the model " )
% old_printable_width % old_printable_depth % old_printable_height % current_printable_width % current_printable_depth % current_printable_height ;
shrink_to_new_bed = 1 ;
}
else {
if ( ( current_exclude_area . size ( ) > 0 ) & & ( current_exclude_area ! = old_exclude_area ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old printable size {%1%, %2%, %3%}, new printable size {%4%, %5%, %6%}, exclude_area different, need to shrink " )
% old_printable_width % old_printable_depth % old_printable_height % current_printable_width % current_printable_depth % current_printable_height ;
shrink_to_new_bed = 2 ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old printable size {%1%, %2%, %3%}, new printable size {%4%, %5%, %6%}, extract the same, no need shrink " )
% old_printable_width % old_printable_depth % old_printable_height % current_printable_width % current_printable_depth % current_printable_height ;
}
}
}
if ( m_models . size ( ) > 0 )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " translate_old %1%, shrink_to_new_bed %2%, old bed size {%3%, %4%, %5%} " ) % translate_old % shrink_to_new_bed % old_printable_width % old_printable_depth % old_printable_height ;
if ( translate_old ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " translate old 3mf, switch to older bed size,{%1%, %2%, %3%} " ) % ( old_printable_width + bed3d_ax3s_default_tip_radius ) % ( old_printable_depth + bed3d_ax3s_default_tip_radius ) % old_printable_height ;
partplate_list . reset_size ( old_printable_width + bed3d_ax3s_default_tip_radius , old_printable_depth + bed3d_ax3s_default_tip_radius , old_printable_height , false ) ;
}
else {
partplate_list . reset_size ( old_printable_width , old_printable_depth , old_printable_height , false ) ;
}
partplate_list . set_shapes ( current_printable_area , current_exclude_area , bed_texture , height_to_lid , height_to_rod ) ;
//plate_stride = partplate_list.plate_stride_x();
}
auto get_print_sequence = [ ] ( Slic3r : : GUI : : PartPlate * plate , DynamicPrintConfig & print_config , bool & is_seq_print ) {
PrintSequence curr_plate_seq = plate - > get_print_seq ( ) ;
if ( curr_plate_seq = = PrintSequence : : ByDefault ) {
auto seq_print = print_config . option < ConfigOptionEnum < PrintSequence > > ( " print_sequence " ) ;
if ( seq_print & & ( seq_print - > value = = PrintSequence : : ByObject ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate print by object, set from global " ) ;
is_seq_print = true ;
}
}
else if ( curr_plate_seq = = PrintSequence : : ByObject ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate print by object, set from plate self " ) ;
is_seq_print = true ;
}
} ;
auto check_plate_wipe_tower = [ get_print_sequence , is_smooth_timelapse ] ( Slic3r : : GUI : : PartPlate * plate , int plate_index , DynamicPrintConfig & print_config , plate_obj_size_info_t & plate_obj_size_info ) {
plate_obj_size_info . obj_bbox = plate - > get_objects_bounding_box ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%, object bbox: min {%2%, %3%, %4%} - max {%5%, %6%, %7%} " )
% ( plate_index + 1 ) % plate_obj_size_info . obj_bbox . min . x ( ) % plate_obj_size_info . obj_bbox . min . y ( ) % plate_obj_size_info . obj_bbox . min . z ( ) % plate_obj_size_info . obj_bbox . max . x ( ) % plate_obj_size_info . obj_bbox . max . y ( ) % plate_obj_size_info . obj_bbox . max . z ( ) ;
if ( ! print_config . has ( " wipe_tower_x " ) ) {
plate_obj_size_info . has_wipe_tower = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " can not found wipe_tower_x in config, set to no wipe tower " ) ;
return ;
}
2024-09-16 16:07:29 +08:00
//1.9.5
bool wipe_tower_enabled = false ;
if ( print_config . has ( " enable_prime_tower " ) ) {
wipe_tower_enabled = print_config . option < ConfigOptionBool > ( " enable_prime_tower " ) - > value ;
}
if ( ! wipe_tower_enabled ) {
plate_obj_size_info . has_wipe_tower = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " enable_prime_tower set to false " ) ;
return ;
}
2024-09-03 09:34:33 +08:00
int valid_count = plate - > printable_instance_size ( ) ;
if ( valid_count < = 0 ) {
plate_obj_size_info . has_wipe_tower = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " no printable object found, set to no wipe tower " ) ;
return ;
}
bool is_sequence = false ;
get_print_sequence ( plate , print_config , is_sequence ) ;
if ( is_sequence & & valid_count > 1 ) {
plate_obj_size_info . has_wipe_tower = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " sequence print, valid_count=%1%, set to no wipe tower " ) % valid_count ;
return ;
}
std : : vector < int > extruders = plate - > get_extruders_under_cli ( true , print_config ) ;
unsigned int filaments_cnt = extruders . size ( ) ;
if ( ( filaments_cnt < = 1 ) & & ! is_smooth_timelapse ) {
plate_obj_size_info . has_wipe_tower = false ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " filaments_cnt=%1%, set to no wipe tower " ) % filaments_cnt ;
return ;
}
ConfigOptionFloats * wipe_x_option = dynamic_cast < ConfigOptionFloats * > ( print_config . option ( " wipe_tower_x " ) ) ;
ConfigOptionFloats * wipe_y_option = dynamic_cast < ConfigOptionFloats * > ( print_config . option ( " wipe_tower_y " ) ) ;
plate_obj_size_info . wipe_x = wipe_x_option - > get_at ( plate_index ) ;
plate_obj_size_info . wipe_y = wipe_y_option - > get_at ( plate_index ) ;
ConfigOptionFloat * width_option = print_config . option < ConfigOptionFloat > ( " prime_tower_width " , true ) ;
plate_obj_size_info . wipe_width = width_option - > value ;
ConfigOptionFloat * brim_width_option = print_config . option < ConfigOptionFloat > ( " prime_tower_brim_width " , true ) ;
float brim_width = brim_width_option - > value ;
ConfigOptionFloat * volume_option = print_config . option < ConfigOptionFloat > ( " prime_volume " , true ) ;
float wipe_volume = volume_option - > value ;
Vec3d wipe_tower_size = plate - > estimate_wipe_tower_size ( print_config , plate_obj_size_info . wipe_width , wipe_volume , filaments_cnt ) ;
plate_obj_size_info . wipe_depth = wipe_tower_size ( 1 ) ;
Vec3d origin = plate - > get_origin ( ) ;
Vec3d start ( origin ( 0 ) + plate_obj_size_info . wipe_x - brim_width , origin ( 1 ) + plate_obj_size_info . wipe_y , 0.f ) ;
plate_obj_size_info . obj_bbox . merge ( start ) ;
Vec3d end ( origin ( 0 ) + plate_obj_size_info . wipe_x + plate_obj_size_info . wipe_width + brim_width , origin ( 1 ) + plate_obj_size_info . wipe_y + plate_obj_size_info . wipe_depth , 0.f ) ;
plate_obj_size_info . obj_bbox . merge ( end ) ;
plate_obj_size_info . has_wipe_tower = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%, has wipe tower, wipe bbox: min {%2%, %3%, %4%} - max {%5%, %6%, %7%} " )
% ( plate_index + 1 ) % start . x ( ) % start . y ( ) % start . z ( ) % end . x ( ) % end . y ( ) % end . z ( ) ;
} ;
auto translate_models = [ translate_old , shrink_to_new_bed , old_printable_width , old_printable_depth , old_printable_height , current_printable_width , current_printable_depth , current_printable_height , current_exclude_area , & plate_obj_size_infos ] ( Slic3r : : GUI : : PartPlateList & plate_list , DynamicPrintConfig & print_config ) {
//QDS: translate old 3mf to correct positions
if ( translate_old ) {
//translate the objects
int plate_count = plate_list . get_plate_count ( ) ;
for ( int index = 1 ; index < plate_count ; index + + ) {
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) plate_list . get_plate ( index ) ;
Vec3d cur_origin = cur_plate - > get_origin ( ) ;
Vec3d new_origin = plate_list . compute_origin_using_new_size ( index , old_printable_width , old_printable_depth ) ;
cur_plate - > translate_all_instance ( new_origin - cur_origin ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " translate old 3mf, switch back to current bed size,{%1%, %2%, %3%} " ) % old_printable_width % old_printable_depth % old_printable_height ;
plate_list . reset_size ( old_printable_width , old_printable_depth , old_printable_height , true , true ) ;
}
if ( shrink_to_new_bed > 0 )
{
int plate_count = plate_list . get_plate_count ( ) ;
ConfigOptionFloats * wipe_x_option = nullptr , * wipe_y_option = nullptr ;
Vec3d wipe_offset ;
if ( print_config . has ( " wipe_tower_x " ) ) {
wipe_x_option = dynamic_cast < ConfigOptionFloats * > ( print_config . option ( " wipe_tower_x " ) ) ;
wipe_y_option = dynamic_cast < ConfigOptionFloats * > ( print_config . option ( " wipe_tower_y " ) ) ;
}
double exclude_width = 0.f , exclude_depth = 0.f ;
if ( current_exclude_area . size ( ) > = 4 ) {
exclude_width = current_exclude_area [ 2 ] . x ( ) - current_exclude_area [ 0 ] . x ( ) ;
exclude_depth = current_exclude_area [ 2 ] . y ( ) - current_exclude_area [ 0 ] . y ( ) ;
}
for ( int index = 0 ; index < plate_count ; index + + ) {
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) plate_list . get_plate ( index ) ;
Vec3d cur_origin = cur_plate - > get_origin ( ) ;
Vec3d new_origin = plate_list . compute_origin_using_new_size ( index , current_printable_width , current_printable_depth ) ;
Vec3d offset ;
if ( shrink_to_new_bed = = 1 ) {
Vec3d cur_center_offset { ( ( double ) old_printable_width ) / 2 , ( ( double ) old_printable_depth ) / 2 , 0 } , new_center_offset { ( ( double ) current_printable_width ) / 2 , ( ( double ) current_printable_depth ) / 2 , 0 } ;
Vec3d cur_center = cur_origin + cur_center_offset ;
Vec3d new_center = new_origin + new_center_offset ;
offset = new_center - cur_center ;
if ( index = = 0 )
wipe_offset = offset ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " shrink_to_new_bed 1, plate %1%, cur_origin: {%2%, %3%}, new_origin: {%4%, %5%}, cur_center {%6%, %7%} new_center {%8%, %9%} " )
% ( index + 1 ) % cur_origin ( 0 ) % cur_origin ( 1 ) % new_origin ( 0 ) % new_origin ( 1 ) % cur_center ( 0 ) % cur_center ( 1 ) % new_center ( 0 ) % new_center ( 1 ) ;
}
else {
//center the object
Vec3d new_center_offset { ( ( double ) current_printable_width + exclude_width ) / 2 , ( ( double ) current_printable_depth + exclude_depth ) / 2 , 0 } ;
BoundingBoxf3 & bbox = plate_obj_size_infos [ index ] . obj_bbox ;
Vec3d size = bbox . size ( ) ;
if ( size . x ( ) > ( current_printable_width - exclude_width ) )
new_center_offset ( 0 ) = ( ( double ) current_printable_width ) / 2 ;
if ( size . y ( ) > ( current_printable_depth - exclude_depth ) )
new_center_offset ( 1 ) = ( ( double ) current_printable_depth ) / 2 ;
Vec3d new_center = new_origin + new_center_offset ;
offset = new_center - bbox . center ( ) ;
wipe_offset = offset + cur_origin - new_origin ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " shrink_to_new_bed 2, plate %1%, new_origin: {%2%, %3%}, new_center: {%4%, %5%}, obj bbox(including wipe tower) min {%6%, %7%} max {%8%, %9%} " )
% ( index + 1 ) % new_origin ( 0 ) % new_origin ( 1 ) % new_center ( 0 ) % new_center ( 1 ) % bbox . min ( 0 ) % bbox . min ( 1 ) % bbox . max ( 0 ) % bbox . max ( 1 ) ;
}
offset ( 2 ) = 0.f ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " shrink_to_new_bed %1%, plate %2% translate offset: {%3%, %4%} wipe_offset {%5%, %6%} " ) % shrink_to_new_bed % ( index + 1 ) % offset [ 0 ] % offset [ 1 ] % wipe_offset [ 0 ] % wipe_offset [ 1 ] ;
cur_plate - > translate_all_instance ( offset ) ;
if ( wipe_x_option ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " shrink_to_new_bed %4%, plate %1%: wipe tower src: {%2%, %3%} " ) % ( index + 1 ) % wipe_x_option - > get_at ( index ) % wipe_y_option - > get_at ( index ) % shrink_to_new_bed ;
ConfigOptionFloat wipe_tower_x ( wipe_x_option - > get_at ( index ) + wipe_offset ( 0 ) ) ;
ConfigOptionFloat wipe_tower_y ( wipe_y_option - > get_at ( index ) + wipe_offset ( 1 ) ) ;
wipe_x_option - > set_at ( & wipe_tower_x , index , 0 ) ;
wipe_y_option - > set_at ( & wipe_tower_y , index , 0 ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " shrink_to_new_bed %4%, plate %1% wipe tower changes to: {%2%, %3%} " ) % ( index + 1 ) % wipe_x_option - > get_at ( index ) % wipe_y_option - > get_at ( index ) % shrink_to_new_bed ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " shrink_to_new_bed, shrink all the models to current bed size,{%1%, %2%, %3%} " ) % current_printable_width % current_printable_depth % current_printable_height ;
plate_list . reset_size ( current_printable_width , current_printable_depth , current_printable_height , true , true ) ;
}
} ;
if ( plate_data_src . size ( ) > 0 )
{
partplate_list . load_from_3mf_structure ( plate_data_src ) ;
int plate_count = partplate_list . get_plate_count ( ) ;
plate_obj_size_infos . resize ( plate_count , plate_obj_size_info_t ( ) ) ;
for ( int index = 0 ; index < plate_count ; index + + ) {
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( index ) ;
check_plate_wipe_tower ( cur_plate , index , m_print_config , plate_obj_size_infos [ index ] ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%, has_wipe_tower %2%, wipe_x %3%, wipe_y %4%, width %5%, depth %6% " )
% ( index + 1 ) % plate_obj_size_infos [ index ] . has_wipe_tower % plate_obj_size_infos [ index ] . wipe_x % plate_obj_size_infos [ index ] . wipe_y % plate_obj_size_infos [ index ] . wipe_width % plate_obj_size_infos [ index ] . wipe_depth ;
}
translate_models ( partplate_list , m_print_config ) ;
}
/*for (ModelObject *model_object : m_models[0].objects)
for ( ModelInstance * model_instance : model_object - > instances )
{
const Vec3d & instance_offset = model_instance - > get_offset ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " instance %1% transform {%2%,%3%,%4%} at %5%:%6% " ) % model_object - > name % instance_offset . x ( ) % instance_offset . y ( ) % instance_offset . z ( ) % __FUNCTION__ % __LINE__ < < std : : endl ;
} */
//doing downward_check
std : : vector < printer_plate_info_t > downward_check_printers ;
std : : vector < bool > downward_check_status ;
if ( downward_check ) {
bool use_default = false ;
std : : string default_path ;
if ( downward_settings . size ( ) = = 0 ) {
//parse from internal
std : : string cli_config_file = resources_dir ( ) + " /profiles/QIDI/cli_config.json " ;
load_downward_settings_list_from_config ( cli_config_file , current_printer_name , current_printer_model , downward_settings ) ;
use_default = true ;
default_path = resources_dir ( ) + " /profiles/QIDI/machine_full/ " ;
}
for ( auto const & file : downward_settings ) {
DynamicPrintConfig config ;
std : : string config_type , config_name , filament_id , config_from , downward_printer ;
std : : string file_path = use_default ? ( default_path + file + " .json " ) : file ;
int ret = load_config_file ( file_path , config , config_type , config_name , filament_id , config_from ) ;
if ( ret ) {
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
if ( ( config_type ! = " machine " ) | | ( config_from ! = " system " ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " found invalid config type %1% or from %2% in file %3% when downward_check " ) % config_type % config_from % file_path ;
record_exit_reson ( outfile_dir , ret , 0 , cli_errors [ CLI_CONFIG_FILE_ERROR ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " downward_check: loaded machine config %1%, from %2% " ) % config_name % file_path ;
printer_plate_info_t printer_plate ;
Pointfs temp_printable_area , temp_exclude_area ;
printer_plate . printer_name = config_name ;
temp_printable_area = config . option < ConfigOptionPoints > ( " printable_area " , true ) - > values ;
temp_exclude_area = config . option < ConfigOptionPoints > ( " bed_exclude_area " , true ) - > values ;
if ( temp_printable_area . size ( ) > = 4 ) {
printer_plate . printable_width = ( int ) ( temp_printable_area [ 2 ] . x ( ) - temp_printable_area [ 0 ] . x ( ) ) ;
printer_plate . printable_depth = ( int ) ( temp_printable_area [ 2 ] . y ( ) - temp_printable_area [ 0 ] . y ( ) ) ;
printer_plate . printable_height = ( int ) ( config . opt_float ( " printable_height " ) ) ;
}
if ( temp_exclude_area . size ( ) > = 4 ) {
printer_plate . exclude_width = ( int ) ( temp_exclude_area [ 2 ] . x ( ) - temp_exclude_area [ 0 ] . x ( ) ) ;
printer_plate . exclude_depth = ( int ) ( temp_exclude_area [ 2 ] . y ( ) - temp_exclude_area [ 0 ] . y ( ) ) ;
printer_plate . exclude_x = ( int ) temp_exclude_area [ 0 ] . x ( ) ;
printer_plate . exclude_y = ( int ) temp_exclude_area [ 0 ] . y ( ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " downward_check: printable size{%1%,%2%, %3%}, exclude area{%4%, %5%: %6% x %7%} " )
% printer_plate . printable_width % printer_plate . printable_depth % printer_plate . printable_height
% printer_plate . exclude_x % printer_plate . exclude_y % printer_plate . exclude_width % printer_plate . exclude_depth ;
downward_check_printers . push_back ( std : : move ( printer_plate ) ) ;
}
}
int downward_check_size = downward_check_printers . size ( ) ;
if ( downward_check_size > 0 )
{
downward_check_status . resize ( downward_check_size , false ) ;
int plate_count = partplate_list . get_plate_count ( ) ;
int failed_count = 0 ;
for ( int index = 0 ; index < plate_count ; index + + )
{
if ( failed_count = = downward_check_size ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " downward_check: all failed, size %1% " ) % downward_check_size ;
break ;
}
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( index ) ;
Vec3d size = plate_obj_size_infos [ index ] . obj_bbox . size ( ) ;
for ( int index2 = 0 ; index2 < downward_check_size ; index2 + + )
{
if ( failed_count = = downward_check_size ) {
break ;
}
if ( downward_check_status [ index2 ] )
continue ;
printer_plate_info_t & plate_info = downward_check_printers [ index2 ] ;
if ( ( size . z ( ) > plate_info . printable_height ) | | ( size . y ( ) > plate_info . printable_depth ) | | ( size . x ( ) > plate_info . printable_width ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%, %6%} exceeds printer size {%7%, %8%, %9%} " )
% ( index + 1 ) % ( index2 + 1 ) % plate_info . printer_name
% size . x ( ) % size . y ( ) % size . z ( ) % plate_info . printable_width % plate_info . printable_depth % plate_info . printable_height ;
downward_check_status [ index2 ] = true ;
failed_count + + ;
continue ;
}
if ( plate_info . exclude_width > 0 ) {
int real_width = plate_info . printable_width - plate_info . exclude_width ;
int real_depth = plate_info . printable_depth - plate_info . exclude_depth ;
if ( ( size . x ( ) > real_width ) & & ( size . y ( ) > real_depth ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%} exceeds real size without exclude_area {%6%, %7%} " )
% ( index + 1 ) % ( index2 + 1 ) % plate_info . printer_name
% size . x ( ) % size . y ( ) % real_width % real_depth ;
downward_check_status [ index2 ] = true ;
failed_count + + ;
continue ;
}
}
}
}
if ( failed_count < downward_check_size )
{
//has success ones
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " downward_check: downward_check_size %1%, failed_count %2% " ) % downward_check_size % failed_count ;
for ( int index2 = 0 ; index2 < downward_check_size ; index2 + + )
{
if ( downward_check_status [ index2 ] )
continue ;
printer_plate_info_t & plate_info = downward_check_printers [ index2 ] ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " downward_check: found compatible printer %1% " ) % plate_info . printer_name ;
downward_compatible_machines . push_back ( plate_info . printer_name ) ;
}
sliced_info . downward_machines = downward_compatible_machines ;
}
}
// Loop through transform options.
bool user_center_specified = false ;
Points beds = get_bed_shape ( m_print_config ) ;
ArrangeParams arrange_cfg ;
BOOST_LOG_TRIVIAL ( info ) < < " will start transforms, commands count " < < m_transforms . size ( ) < < " \n " ;
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 2 , " Loading files finished " } ;
cli_status_callback ( slicing_status ) ;
}
# endif
for ( auto const & opt_key : m_transforms ) {
BOOST_LOG_TRIVIAL ( info ) < < " process transform " < < opt_key < < " \n " ;
if ( opt_key = = " assemble " ) {
if ( clone_objects . size ( ) > 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < " Invalid params: can not set assemble and clone_objects together. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
Model m ;
ModelObject * new_object = m . add_object ( ) ;
new_object - > name = _u8L ( " Assembly " ) ;
new_object - > add_instance ( ) ;
int idx = 0 ;
for ( auto & model : m_models )
for ( ModelObject * o : model . objects ) {
for ( auto volume : o - > volumes ) {
ModelVolume * new_volume = new_object - > add_volume ( * volume ) ;
// set extruder id
new_volume - > config . set_key_value ( " extruder " , new ConfigOptionInt ( o - > config . extruder ( ) ) ) ;
}
}
m_models . clear ( ) ;
m_models . emplace_back ( std : : move ( m ) ) ;
}
else if ( opt_key = = " repetitions " ) {
int repetitions_count = m_config . option < ConfigOptionInt > ( " repetitions " ) - > value ;
if ( repetitions_count < = 1 )
{
BOOST_LOG_TRIVIAL ( info ) < < " invalid repetitions value " < < repetitions_count < < " , just skip \n " ;
}
else {
if ( plate_to_slice = = 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < " Invalid params: can not set repetitions when slice all. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
else if ( plate_to_slice > partplate_list . get_plate_count ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " Invalid params:invalid plate %1% to slice, total %2% " ) % plate_to_slice % partplate_list . get_plate_count ( ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < " repetitions value " < < repetitions_count < < std : : endl ;
duplicate_count = repetitions_count - 1 ;
}
}
else if ( opt_key = = " convert_unit " ) {
for ( auto & model : m_models ) {
if ( model . looks_like_saved_in_meters ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " convert from meter to millimeter \n " ;
model . convert_from_meters ( true ) ;
}
else if ( model . looks_like_imperial_units ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " convert from inch to millimeter \n " ;
model . convert_from_imperial_units ( true ) ;
}
}
}
else if ( opt_key = = " orient " ) {
//QDS: orient 0 means disable, 1 means force orient, others means auto
int orient_option = m_config . option < ConfigOptionInt > ( " orient " ) - > value ;
if ( orient_option = = 0 )
{
//orients_requirement.clear();
for ( auto & model : m_models )
for ( ModelObject * o : model . objects )
{
orients_requirement . insert ( std : : pair < size_t , bool > ( o - > id ( ) . id , false ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < " object " < < o - > name < < " , id : " < < o - > id ( ) . id < < " , no need to orient when setting orient to 0 \n " ;
}
}
else if ( orient_option = = 1 )
{
//force orient
//orients_requirement.clear();
for ( auto & model : m_models )
for ( ModelObject * o : model . objects )
{
orients_requirement . insert ( std : : pair < size_t , bool > ( o - > id ( ) . id , true ) ) ;
BOOST_LOG_TRIVIAL ( info ) < < " object " < < o - > name < < " , id : " < < o - > id ( ) . id < < " , need to orient when setting orient to 1 \n " ;
}
}
else
{
//auto arrange, keep the original logic
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " orient_option %1% " ) % orient_option ;
}
else if ( opt_key = = " copy " ) {
for ( auto & model : m_models ) {
const bool all_objects_have_instances = std : : none_of (
model . objects . begin ( ) , model . objects . end ( ) ,
[ ] ( ModelObject * o ) { return o - > instances . empty ( ) ; }
) ;
int dups = m_config . opt_int ( " copy " ) ;
if ( ! all_objects_have_instances ) model . add_default_instances ( ) ;
try {
if ( dups > 1 ) {
// if all input objects have defined position(s) apply duplication to the whole model
duplicate ( model , size_t ( dups ) , beds , arrange_cfg ) ;
} else {
arrange_objects ( model , beds , arrange_cfg ) ;
}
} catch ( std : : exception & ex ) {
boost : : nowide : : cerr < < " error: " < < ex . what ( ) < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_COPY_OBJECTS_ERROR , 0 , cli_errors [ CLI_COPY_OBJECTS_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_COPY_OBJECTS_ERROR ) ;
}
}
} else if ( opt_key = = " center " ) {
user_center_specified = true ;
for ( auto & model : m_models ) {
model . add_default_instances ( ) ;
// this affects instances:
model . center_instances_around_point ( m_config . option < ConfigOptionPoint > ( " center " ) - > value ) ;
// this affects volumes:
//FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body?
//model.align_to_ground();
BoundingBoxf3 bbox ;
for ( ModelObject * model_object : model . objects )
// We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only.
bbox . merge ( model_object - > instance_bounding_box ( 0 , false ) ) ;
for ( ModelObject * model_object : model . objects )
for ( ModelInstance * model_instance : model_object - > instances )
model_instance - > set_offset ( Z , model_instance - > get_offset ( Z ) - bbox . min . z ( ) ) ;
}
} else if ( opt_key = = " align_xy " ) {
const Vec2d & p = m_config . option < ConfigOptionPoint > ( " align_xy " ) - > value ;
for ( auto & model : m_models ) {
BoundingBoxf3 bb = model . bounding_box ( ) ;
// this affects volumes:
model . translate ( - ( bb . min . x ( ) - p . x ( ) ) , - ( bb . min . y ( ) - p . y ( ) ) , - bb . min . z ( ) ) ;
}
} else if ( opt_key = = " arrange " ) {
//QDS: arrange 0 means disable, 1 means force arrange, others means auto
int arrange_option = m_config . option < ConfigOptionInt > ( " arrange " ) - > value ;
if ( arrange_option = = 0 )
{
need_arrange = false ;
}
else if ( arrange_option = = 1 )
{
need_arrange = true ;
}
else
{
//auto arrange, keep the original logic
}
} else if ( opt_key = = " ensure_on_bed " ) {
// do nothing, the value is used later
} else if ( opt_key = = " rotate " ) {
for ( auto & model : m_models )
for ( auto & o : model . objects )
// this affects volumes:
o - > rotate ( Geometry : : deg2rad ( m_config . opt_float ( opt_key ) ) , Z ) ;
} else if ( opt_key = = " rotate_x " ) {
for ( auto & model : m_models )
for ( auto & o : model . objects )
// this affects volumes:
o - > rotate ( Geometry : : deg2rad ( m_config . opt_float ( opt_key ) ) , X ) ;
} else if ( opt_key = = " rotate_y " ) {
for ( auto & model : m_models )
for ( auto & o : model . objects )
// this affects volumes:
o - > rotate ( Geometry : : deg2rad ( m_config . opt_float ( opt_key ) ) , Y ) ;
} else if ( opt_key = = " scale " ) {
2024-09-16 16:07:29 +08:00
//1.9.5
float ratio = m_config . opt_float ( opt_key ) ;
if ( ratio < = 0.f ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " Invalid params:invalid scale ratio %1% " ) % ratio ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
2024-09-03 09:34:33 +08:00
for ( auto & model : m_models )
for ( auto & o : model . objects )
// this affects volumes:
2024-09-16 16:07:29 +08:00
o - > scale ( ratio ) ;
2024-09-03 09:34:33 +08:00
} else if ( opt_key = = " scale_to_fit " ) {
const Vec3d & opt = m_config . opt < ConfigOptionPoint3 > ( opt_key ) - > value ;
if ( opt . x ( ) < = 0 | | opt . y ( ) < = 0 | | opt . z ( ) < = 0 ) {
boost : : nowide : : cerr < < " --scale-to-fit requires a positive volume " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_SCALE_TO_FIT_ERROR , 0 , cli_errors [ CLI_SCALE_TO_FIT_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_SCALE_TO_FIT_ERROR ) ;
}
for ( auto & model : m_models )
for ( auto & o : model . objects )
// this affects volumes:
o - > scale_to_fit ( opt ) ;
} else if ( opt_key = = " cut " | | opt_key = = " cut_x " | | opt_key = = " cut_y " ) {
std : : vector < Model > new_models ;
for ( auto & model : m_models ) {
model . translate ( 0 , 0 , - model . bounding_box ( ) . min . z ( ) ) ; // align to z = 0
size_t num_objects = model . objects . size ( ) ;
for ( size_t i = 0 ; i < num_objects ; + + i ) {
#if 0
if ( opt_key = = " cut_x " ) {
o - > cut ( X , m_config . opt_float ( " cut_x " ) , & out ) ;
} else if ( opt_key = = " cut_y " ) {
o - > cut ( Y , m_config . opt_float ( " cut_y " ) , & out ) ;
} else if ( opt_key = = " cut " ) {
o - > cut ( Z , m_config . opt_float ( " cut " ) , & out ) ;
}
# else
ModelObject * object = model . objects . front ( ) ;
const BoundingBoxf3 & box = object - > bounding_box ( ) ;
const float Margin = 20.0 ;
const float max_x = box . size ( ) ( 0 ) / 2.0 + Margin ;
const float min_x = - max_x ;
const float max_y = box . size ( ) ( 1 ) / 2.0 + Margin ;
const float min_y = - max_y ;
std : : array < Vec3d , 4 > plane_points ;
plane_points [ 0 ] = { min_x , min_y , 0 } ;
plane_points [ 1 ] = { max_x , min_y , 0 } ;
plane_points [ 2 ] = { max_x , max_y , 0 } ;
plane_points [ 3 ] = { min_x , max_y , 0 } ;
for ( Vec3d & point : plane_points ) {
point + = box . center ( ) ;
}
model . objects . front ( ) - > cut ( 0 , plane_points , ModelObjectCutAttribute : : KeepUpper | ModelObjectCutAttribute : : KeepLower ) ;
# endif
model . delete_object ( size_t ( 0 ) ) ;
}
}
// TODO: copy less stuff around using pointers
m_models = new_models ;
if ( m_actions . empty ( ) )
m_actions . push_back ( " export_stl " ) ;
}
#if 0
else if ( opt_key = = " cut_grid " ) {
std : : vector < Model > new_models ;
for ( auto & model : m_models ) {
TriangleMesh mesh = model . mesh ( ) ;
mesh . repair ( ) ;
std : : vector < TriangleMesh > meshes = mesh . cut_by_grid ( m_config . option < ConfigOptionPoint > ( " cut_grid " ) - > value ) ;
size_t i = 0 ;
for ( TriangleMesh * m : meshes ) {
Model out ;
auto o = out . add_object ( ) ;
o - > add_volume ( * m ) ;
o - > input_file + = " _ " + std : : to_string ( i + + ) ;
delete m ;
}
}
// TODO: copy less stuff around using pointers
m_models = new_models ;
if ( m_actions . empty ( ) )
m_actions . push_back ( " export_stl " ) ;
}
# endif
else if ( opt_key = = " split " ) {
for ( Model & model : m_models ) {
size_t num_objects = model . objects . size ( ) ;
for ( size_t i = 0 ; i < num_objects ; + + i ) {
ModelObjectPtrs new_objects ;
model . objects . front ( ) - > split ( & new_objects ) ;
model . delete_object ( size_t ( 0 ) ) ;
}
}
} else if ( opt_key = = " repair " ) {
// Models are repaired by default.
//for (auto &model : m_models)
// model.repair();
} else {
boost : : nowide : : cerr < < " error: option not implemented yet: " < < opt_key < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_UNSUPPORTED_OPERATION , 0 , cli_errors [ CLI_UNSUPPORTED_OPERATION ] , sliced_info ) ;
flush_and_exit ( CLI_UNSUPPORTED_OPERATION ) ;
}
}
BOOST_LOG_TRIVIAL ( info ) < < " finished model pre-process commands \n " ;
bool oriented_or_arranged = false ;
//QDS: add orient and arrange logic here
for ( auto & model : m_models )
{
for ( ModelObject * o : model . objects )
{
if ( orients_requirement [ o - > id ( ) . id ] )
{
BOOST_LOG_TRIVIAL ( info ) < < " Before process command, Orient object, name= " < < o - > name < < " ,id= " < < o - > id ( ) . id < < std : : endl ;
orientation : : orient ( o ) ;
oriented_or_arranged = true ;
}
else
{
BOOST_LOG_TRIVIAL ( debug ) < < " Before process command, no need to orient, object id : " < < o - > id ( ) . id < < std : : endl ;
}
}
}
//QDS: clear the orient objects lists
orients_requirement . clear ( ) ;
bool is_seq_print_for_curr_plate = false ;
if ( ( plate_to_slice < 0 ) | | ( plate_to_slice > partplate_list . get_plate_count ( ) ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " invalid plate id %1%, total %2% " ) % plate_to_slice % partplate_list . get_plate_count ( ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
else if ( plate_to_slice > 0 ) {
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( plate_to_slice - 1 ) ;
PrintSequence curr_plate_seq = cur_plate - > get_print_seq ( ) ;
if ( curr_plate_seq = = PrintSequence : : ByDefault ) {
auto seq_print = m_print_config . option < ConfigOptionEnum < PrintSequence > > ( " print_sequence " ) ;
if ( seq_print & & ( seq_print - > value = = PrintSequence : : ByObject ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Check whether need to arrange by print_sequence: plate %1% print by object, set from global " ) % plate_to_slice ;
is_seq_print_for_curr_plate = true ;
}
}
else if ( curr_plate_seq = = PrintSequence : : ByObject ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Check whether need to arrange by print_sequence: plate %1% print by object, set from plate self " ) % plate_to_slice ;
is_seq_print_for_curr_plate = true ;
}
if ( duplicate_count > 0 ) {
const ConfigOptionBool * spiral_vase = m_print_config . option < ConfigOptionBool > ( " spiral_mode " ) ;
if ( ( spiral_vase ! = nullptr ) & & spiral_vase - > value )
{
//spiral mode can only be duplicated with by-object
if ( ! is_seq_print_for_curr_plate ) {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " Spiral mode can not be duplicated under by-object print, skip duplicate " ) ;
duplicate_count = 0 ;
}
}
}
if ( duplicate_count > 0 )
need_arrange = true ;
}
if ( ( ! need_arrange ) & & is_qdt_3mf & & ! shrink_to_new_bed & & ( plate_to_slice > 0 ) )
{
if ( ( ( old_height_to_rod ! = 0.f ) & & ( old_height_to_rod ! = height_to_rod ) )
| | ( ( old_height_to_lid ! = 0.f ) & & ( old_height_to_lid ! = height_to_lid ) )
| | ( ( old_max_radius ! = 0.f ) & & ( old_max_radius ! = cleareance_radius ) ) )
{
if ( is_seq_print_for_curr_plate ) {
need_arrange = true ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " old_height_to_rod %1%, old_height_to_lid %2%, old_max_radius %3%, current height_to_rod %4%, height_to_lid %5%, cleareance_radius %6%, need arrange! " )
% old_height_to_rod % old_height_to_lid % old_max_radius % height_to_rod % height_to_lid % cleareance_radius ;
}
}
}
oriented_or_arranged | = need_arrange ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " before arrange, need_arrange=%1%, duplicate_count %2%, filament_color_changed %3% " ) % need_arrange % duplicate_count % filament_color_changed ;
if ( need_arrange | | filament_color_changed )
{
for ( int index = 0 ; index < partplate_list . get_plate_count ( ) ; index + + )
{
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( index + 1 ) ) ) {
continue ;
}
if ( plate_data_src . size ( ) > index ) {
if ( ! plate_data_src [ index ] - > thumbnail_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > thumbnail_file ;
plate_data_src [ index ] - > thumbnail_file . clear ( ) ;
}
if ( ! plate_data_src [ index ] - > no_light_thumbnail_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded no_light_thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > no_light_thumbnail_file ;
plate_data_src [ index ] - > no_light_thumbnail_file . clear ( ) ;
}
if ( ! plate_data_src [ index ] - > top_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded top_thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > top_file ;
plate_data_src [ index ] - > top_file . clear ( ) ;
}
if ( ! plate_data_src [ index ] - > pick_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded pick_thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > pick_file ;
plate_data_src [ index ] - > pick_file . clear ( ) ;
}
}
}
}
if ( ! assemble_plate_info_list . empty ( ) )
{
//need to arrange for assemble cases
int plate_count = assemble_plate_info_list . size ( ) ;
if ( plate_count ! = partplate_list . get_plate_count ( ) )
{
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " mismatch plate count, to_assemble %1%, generated %2% " ) % plate_count % partplate_list . get_plate_count ( ) ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
for ( size_t i = 0 ; i < plate_count ; i + + )
{
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( i ) ;
//lock those plates no need to arrange
if ( ! assemble_plate_info_list [ i ] . need_arrange )
cur_plate - > lock ( true ) ;
}
for ( size_t i = 0 ; i < plate_count ; i + + )
{
assemble_plate_info_t & assemble_plate = assemble_plate_info_list [ i ] ;
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( i ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%, need arrange %2%, filaments_count %3% " ) % ( i + 1 ) % assemble_plate . need_arrange % assemble_plate . filaments_count ;
if ( assemble_plate . need_arrange )
{
//do arrange for plate
ArrangePolygons selected , unselected ;
Model & model = m_models [ 0 ] ;
arrange_cfg = ArrangeParams ( ) ; // reset all params
get_print_sequence ( cur_plate , m_print_config , arrange_cfg . is_seq_print ) ;
//Step-1: prepare the arranged data
partplate_list . lock_plate ( i , false ) ;
partplate_list . select_plate ( i ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% set to selected " ) % i ;
size_t plate_obj_count = assemble_plate . loaded_obj_list . size ( ) ;
for ( size_t oidx = 0 ; oidx < plate_obj_count ; + + oidx )
{
ModelObject * mo = assemble_plate . loaded_obj_list [ oidx ] ;
for ( size_t inst_idx = 0 ; inst_idx < mo - > instances . size ( ) ; + + inst_idx )
{
ModelInstance * minst = mo - > instances [ inst_idx ] ;
ArrangePolygon ap = get_instance_arrange_poly ( minst , m_print_config ) ;
ap . itemid = selected . size ( ) ;
selected . emplace_back ( std : : move ( ap ) ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " plate %1%: add object %2% object index %3%, into selected " ) % ( i + 1 ) % ap . name % ( oidx + 1 ) ;
}
}
if ( ! arrange_cfg . is_seq_print & & assemble_plate . filaments_count > 1 )
{
//prepare the wipe tower
int plate_count = partplate_list . get_plate_count ( ) ;
auto printer_structure_opt = m_print_config . option < ConfigOptionEnum < PrinterStructure > > ( " printer_structure " ) ;
// set the default position, the same with print config(left top)
float x = WIPE_TOWER_DEFAULT_X_POS ;
float y = WIPE_TOWER_DEFAULT_Y_POS ;
if ( printer_structure_opt & & printer_structure_opt - > value = = PrinterStructure : : psI3 ) {
x = I3_WIPE_TOWER_DEFAULT_X_POS ;
y = I3_WIPE_TOWER_DEFAULT_Y_POS ;
}
if ( x < WIPE_TOWER_MARGIN ) {
x = WIPE_TOWER_MARGIN ;
}
if ( y < WIPE_TOWER_MARGIN ) {
y = WIPE_TOWER_MARGIN ;
}
ConfigOptionFloat wt_x_opt ( x ) ;
ConfigOptionFloat wt_y_opt ( y ) ;
//create the options using default if neccessary
ConfigOptionFloats * wipe_x_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_x " , true ) ;
ConfigOptionFloats * wipe_y_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_y " , true ) ;
ConfigOptionFloat * width_option = m_print_config . option < ConfigOptionFloat > ( " prime_tower_width " , true ) ;
ConfigOptionFloat * rotation_angle_option = m_print_config . option < ConfigOptionFloat > ( " wipe_tower_rotation_angle " , true ) ;
ConfigOptionFloat * volume_option = m_print_config . option < ConfigOptionFloat > ( " prime_volume " , true ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " prime_tower_width %1% wipe_tower_rotation_angle %2% prime_volume %3% " ) % width_option - > value % rotation_angle_option - > value % volume_option - > value ;
wipe_x_option - > set_at ( & wt_x_opt , i , 0 ) ;
wipe_y_option - > set_at ( & wt_y_opt , i , 0 ) ;
ArrangePolygon wipe_tower_ap = cur_plate - > estimate_wipe_tower_polygon ( m_print_config , i , assemble_plate . filaments_count , true ) ;
wipe_tower_ap . bed_idx = i ;
unselected . emplace_back ( wipe_tower_ap ) ;
}
// add the virtual object into unselect list if has
partplate_list . preprocess_exclude_areas ( unselected , i + 1 ) ;
if ( avoid_extrusion_cali_region )
partplate_list . preprocess_nonprefered_areas ( unselected , i + 1 ) ;
//Step-2:prepare the arrange params
arrange_cfg . allow_rotations = allow_rotations ;
arrange_cfg . allow_multi_materials_on_same_plate = allow_multicolor_oneplate ;
arrange_cfg . avoid_extrusion_cali_region = avoid_extrusion_cali_region ;
arrange_cfg . clearance_height_to_rod = height_to_rod ;
arrange_cfg . clearance_height_to_lid = height_to_lid ;
arrange_cfg . cleareance_radius = cleareance_radius ;
arrange_cfg . printable_height = print_height ;
arrange_cfg . min_obj_distance = 0 ;
if ( arrange_cfg . is_seq_print ) {
arrange_cfg . bed_shrink_x = BED_SHRINK_SEQ_PRINT ;
arrange_cfg . bed_shrink_y = BED_SHRINK_SEQ_PRINT ;
}
if ( auto printer_structure_opt = m_print_config . option < ConfigOptionEnum < PrinterStructure > > ( " printer_structure " ) ) {
arrange_cfg . align_to_y_axis = ( printer_structure_opt - > value = = PrinterStructure : : psI3 ) ;
}
arrangement : : update_arrange_params ( arrange_cfg , & m_print_config , selected ) ;
arrangement : : update_selected_items_inflation ( selected , & m_print_config , arrange_cfg ) ;
arrangement : : update_unselected_items_inflation ( unselected , & m_print_config , arrange_cfg ) ;
arrangement : : update_selected_items_axis_align ( selected , & m_print_config , arrange_cfg ) ;
beds = get_shrink_bedpts ( & m_print_config , arrange_cfg ) ;
partplate_list . preprocess_exclude_areas ( arrange_cfg . excluded_regions , 1 , scale_ ( 1 ) ) ;
{
BOOST_LOG_TRIVIAL ( debug ) < < " arrange bedpts: " < < beds [ 0 ] . transpose ( ) < < " , " < < beds [ 1 ] . transpose ( ) < < " , " < < beds [ 2 ] . transpose ( ) < < " , " < < beds [ 3 ] . transpose ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < " Arrange full params: " < < arrange_cfg . to_json ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " arrange: items selected before arranging: %1% " ) % selected . size ( ) ;
for ( auto item : selected )
BOOST_LOG_TRIVIAL ( trace ) < < item . name < < " , extruder: " < < item . extrude_ids . back ( ) < < " , bed: " < < item . bed_idx
< < " , trans: " < < item . translation . transpose ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " arrange: items unselected before arranging: %1% " ) % unselected . size ( ) ;
for ( auto item : unselected )
BOOST_LOG_TRIVIAL ( trace ) < < item . name < < " , bed: " < < item . bed_idx < < " , trans: " < < item . translation . transpose ( ) ;
}
arrange_cfg . progressind = [ ] ( unsigned st , std : : string str = " " ) {
//boost::nowide::cout << "st=" << st << ", " << str << std::endl;
} ;
//Step-3:do the arrange
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " start plate %1%'s arranging... " ) % ( i + 1 ) ;
arrangement : : arrange ( selected , unselected , beds , arrange_cfg ) ;
//arrangement::arrange(unprintable, {}, beds, arrange_cfg);
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " finished plate %1%'s arranging " ) % ( i + 1 ) ;
//step-4: postprocess the bed index and result
partplate_list . clear ( false , false , true , i ) ;
for ( ArrangePolygon & ap : selected ) {
partplate_list . postprocess_bed_index_for_current_plate ( ap ) ;
if ( ap . bed_idx ! = i )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " :arrange failed: ap.name %1% ap.bed_idx %2%, plate index %3% " ) % ap . name % ap . bed_idx % i ;
record_exit_reson ( outfile_dir , CLI_OBJECT_ARRANGE_FAILED , 0 , cli_errors [ CLI_OBJECT_ARRANGE_FAILED ] , sliced_info ) ;
flush_and_exit ( CLI_OBJECT_ARRANGE_FAILED ) ;
}
}
// Apply the arrange result to all selected objects
for ( ArrangePolygon & ap : selected ) {
//QDS: partplate postprocess
partplate_list . postprocess_arrange_polygon ( ap , true ) ;
ap . apply ( ) ;
}
//lock here
cur_plate - > lock ( true ) ;
}
else {
size_t plate_obj_count = assemble_plate . loaded_obj_list . size ( ) ;
Vec3d plate_origin = cur_plate - > get_origin ( ) ;
for ( size_t oidx = 0 ; oidx < plate_obj_count ; + + oidx )
{
ModelObject * mo = assemble_plate . loaded_obj_list [ oidx ] ;
mo - > translate_instances ( plate_origin ) ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " plate %1%: no arrange, directly translate object %2% by {%3%, %4%} " ) % ( i + 1 ) % mo - > name % plate_origin ( 0 ) % plate_origin ( 1 ) ;
}
}
}
for ( size_t i = 0 ; i < plate_count ; i + + )
{
//unlock all the plates
Slic3r : : GUI : : PartPlate * cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( i ) ;
cur_plate - > lock ( false ) ;
}
partplate_list . reload_all_objects ( false , - 1 ) ;
}
else if ( need_arrange )
{
ArrangePolygons selected , unselected , unprintable , locked_aps ;
//for (Model &model : m_models)
if ( m_models . size ( ) > 0 )
{
Model & model = m_models [ 0 ] ;
Model original_model ;
std : : set < std : : pair < int , int > > backup_set ;
bool finished_arrange = false , first_run = true ;
Slic3r : : GUI : : PartPlate * cur_plate = nullptr ;
int low_duplicate_count = 0 , up_duplicate_count = duplicate_count , arrange_count = 0 ;
float orig_wipe_x = 0.f , orig_wipe_y = 0.f ;
if ( duplicate_count > 0 ) {
original_model = model ;
}
while ( ! finished_arrange )
{
arrange_cfg = ArrangeParams ( ) ; // reset all params
arrange_count + + ;
//step-0: duplicate model
if ( duplicate_count > 0 )
{
//copy model objects and instances on plate
if ( ! first_run ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " restore model object and plate, new duplicate_count %1%, arrange_count=%2% " ) % duplicate_count % arrange_count ;
beds = get_bed_shape ( m_print_config ) ;
model . clear_objects ( ) ;
model . clear_materials ( ) ;
model = original_model ;
partplate_list . load_from_3mf_structure ( plate_data_src ) ;
selected . clear ( ) ;
unselected . clear ( ) ;
unprintable . clear ( ) ;
locked_aps . clear ( ) ;
}
else {
first_run = false ;
if ( plate_to_slice > 0 ) {
ConfigOptionFloats * wipe_x_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_x " ) ;
ConfigOptionFloats * wipe_y_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_y " ) ;
if ( wipe_x_option & & ( wipe_x_option - > size ( ) > ( plate_to_slice - 1 ) ) ) {
orig_wipe_x = wipe_x_option - > get_at ( plate_to_slice - 1 ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, plate_to_slice %2%, orig_wipe_x=%3% " ) % __LINE__ % plate_to_slice % orig_wipe_x ;
}
if ( wipe_y_option & & ( wipe_y_option - > size ( ) > ( plate_to_slice - 1 ) ) ) {
orig_wipe_y = wipe_y_option - > get_at ( plate_to_slice - 1 ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " %1%, plate_to_slice %2%, orig_wipe_y=%3% " ) % __LINE__ % plate_to_slice % orig_wipe_y ;
}
}
}
cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( plate_to_slice - 1 ) ;
cur_plate - > duplicate_all_instance ( duplicate_count , need_skip , skip_maps ) ;
}
else if ( plate_to_slice > 0 )
{
cur_plate = ( Slic3r : : GUI : : PartPlate * ) partplate_list . get_plate ( plate_to_slice - 1 ) ;
}
if ( cur_plate ) {
get_print_sequence ( cur_plate , m_print_config , arrange_cfg . is_seq_print ) ;
}
//Step-1: prepare arrange polygons
if ( ( duplicate_count = = 0 ) & & ( plate_to_slice = = 0 ) )
{
//global arrange
for ( size_t oidx = 0 ; oidx < model . objects . size ( ) ; + + oidx )
{
ModelObject * mo = model . objects [ oidx ] ;
for ( size_t inst_idx = 0 ; inst_idx < mo - > instances . size ( ) ; + + inst_idx )
{
ModelInstance * minst = mo - > instances [ inst_idx ] ;
ArrangePolygon ap = get_instance_arrange_poly ( minst , m_print_config ) ;
//preprocess by partplate list
//remove the locked plate's instances, neither in selected, nor in un-selected
bool locked = partplate_list . preprocess_arrange_polygon ( oidx , inst_idx , ap , true ) ;
if ( ! locked )
{
ap . itemid = selected . size ( ) ;
if ( minst - > printable )
selected . emplace_back ( ap ) ;
else
unprintable . emplace_back ( ap ) ;
}
else
{
//skip this object due to be locked in plate
ap . itemid = locked_aps . size ( ) ;
locked_aps . emplace_back ( ap ) ;
boost : : nowide : : cout < < __FUNCTION__ < < boost : : format ( " : skip locked instance, obj_id %1%, instance_id %2% " ) % oidx % inst_idx ;
}
}
}
if ( m_print_config . has ( " print_sequence " ) ) {
PrintSequence seq = m_print_config . option < ConfigOptionEnum < PrintSequence > > ( " print_sequence " ) - > value ;
arrange_cfg . is_seq_print = ( seq = = PrintSequence : : ByObject ) ;
}
//add the virtual object into unselect list if has
partplate_list . preprocess_exclude_areas ( unselected ) ;
if ( used_filament_set . size ( ) > 0 )
{
//prepare the wipe tower
int plate_count = partplate_list . get_plate_count ( ) ;
int extruder_size = used_filament_set . size ( ) ;
auto printer_structure_opt = m_print_config . option < ConfigOptionEnum < PrinterStructure > > ( " printer_structure " ) ;
// set the default position, the same with print config(left top)
float x = WIPE_TOWER_DEFAULT_X_POS ;
float y = WIPE_TOWER_DEFAULT_Y_POS ;
if ( printer_structure_opt & & printer_structure_opt - > value = = PrinterStructure : : psI3 ) {
x = I3_WIPE_TOWER_DEFAULT_X_POS ;
y = I3_WIPE_TOWER_DEFAULT_Y_POS ;
}
if ( x < WIPE_TOWER_MARGIN ) {
x = WIPE_TOWER_MARGIN ;
}
if ( y < WIPE_TOWER_MARGIN ) {
y = WIPE_TOWER_MARGIN ;
}
ConfigOptionFloat wt_x_opt ( x ) ;
ConfigOptionFloat wt_y_opt ( y ) ;
//create the options using default if neccessary
ConfigOptionFloats * wipe_x_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_x " , true ) ;
ConfigOptionFloats * wipe_y_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_y " , true ) ;
ConfigOptionFloat * width_option = m_print_config . option < ConfigOptionFloat > ( " prime_tower_width " , true ) ;
ConfigOptionFloat * rotation_angle_option = m_print_config . option < ConfigOptionFloat > ( " wipe_tower_rotation_angle " , true ) ;
ConfigOptionFloat * volume_option = m_print_config . option < ConfigOptionFloat > ( " prime_volume " , true ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " prime_tower_width %1% wipe_tower_rotation_angle %2% prime_volume %3% " ) % width_option - > value % rotation_angle_option - > value % volume_option - > value ;
for ( int bedid = 0 ; bedid < MAX_PLATE_COUNT ; bedid + + ) {
int plate_index_valid = std : : min ( bedid , plate_count - 1 ) ;
if ( bedid < plate_count ) {
wipe_x_option - > set_at ( & wt_x_opt , plate_index_valid , 0 ) ;
wipe_y_option - > set_at ( & wt_y_opt , plate_index_valid , 0 ) ;
}
ArrangePolygon wipe_tower_ap = partplate_list . get_plate ( plate_index_valid ) - > estimate_wipe_tower_polygon ( m_print_config , plate_index_valid , extruder_size , true ) ;
wipe_tower_ap . bed_idx = bedid ;
unselected . emplace_back ( wipe_tower_ap ) ;
}
}
}
else {
//only arrange current plate
partplate_list . lock_plate ( plate_to_slice - 1 , false ) ;
partplate_list . select_plate ( plate_to_slice - 1 ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% set to selected " ) % plate_to_slice ;
for ( size_t oidx = 0 ; oidx < model . objects . size ( ) ; + + oidx )
{
ModelObject * mo = model . objects [ oidx ] ;
for ( size_t inst_idx = 0 ; inst_idx < mo - > instances . size ( ) ; + + inst_idx )
{
ModelInstance * minst = mo - > instances [ inst_idx ] ;
bool in_plate = cur_plate - > contain_instance ( oidx , inst_idx ) | | cur_plate - > intersect_instance ( oidx , inst_idx ) ;
ArrangePolygon ap = get_instance_arrange_poly ( minst , m_print_config ) ;
ArrangePolygons & cont = mo - > instances [ inst_idx ] - > printable ?
( in_plate ? selected : unselected ) :
unprintable ;
bool locked = partplate_list . preprocess_arrange_polygon_other_locked ( oidx , inst_idx , ap , in_plate ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " name %4% in_plate %1% printable %2%, locked %3% " ) % in_plate % mo - > instances [ inst_idx ] - > printable % locked % ap . name ;
if ( ! locked )
{
ap . itemid = cont . size ( ) ;
cont . emplace_back ( std : : move ( ap ) ) ;
}
else
{
//skip this object due to be not in current plate, treated as locked
ap . itemid = locked_aps . size ( ) ;
locked_aps . emplace_back ( std : : move ( ap ) ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " arrange: skip locked instance, obj_id %1%, name %2% " ) % oidx % mo - > name ;
}
}
}
if ( ( duplicate_count > 0 ) & & ( selected . size ( ) = = ( duplicate_count + 1 ) ) )
{
duplicate_single_object = true ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : found single object mode " ) ;
}
if ( m_print_config . has ( " wipe_tower_x " ) & & ( is_smooth_timelapse | | ! arrange_cfg . is_seq_print | | ( selected . size ( ) < = 1 ) ) ) {
float x ;
float y ;
if ( duplicate_count > 0 ) {
auto printer_structure_opt = m_print_config . option < ConfigOptionEnum < PrinterStructure > > ( " printer_structure " ) ;
x = WIPE_TOWER_DEFAULT_X_POS ;
y = WIPE_TOWER_DEFAULT_Y_POS ;
if ( printer_structure_opt & & printer_structure_opt - > value = = PrinterStructure : : psI3 ) {
x = I3_WIPE_TOWER_DEFAULT_X_POS ;
y = I3_WIPE_TOWER_DEFAULT_Y_POS ;
}
}
else {
//keep the original
x = dynamic_cast < const ConfigOptionFloats * > ( m_print_config . option ( " wipe_tower_x " ) ) - > get_at ( plate_to_slice - 1 ) ;
y = dynamic_cast < const ConfigOptionFloats * > ( m_print_config . option ( " wipe_tower_y " ) ) - > get_at ( plate_to_slice - 1 ) ;
}
float w = dynamic_cast < const ConfigOptionFloat * > ( m_print_config . option ( " prime_tower_width " ) ) - > value ;
float a = dynamic_cast < const ConfigOptionFloat * > ( m_print_config . option ( " wipe_tower_rotation_angle " ) ) - > value ;
float v = dynamic_cast < const ConfigOptionFloat * > ( m_print_config . option ( " prime_volume " ) ) - > value ;
unsigned int filaments_cnt = plate_data_src [ plate_to_slice - 1 ] - > slice_filaments_info . size ( ) ;
if ( ( filaments_cnt = = 0 ) | | need_skip )
{
// slice filaments info invalid
std : : vector < int > extruders = cur_plate - > get_extruders_under_cli ( true , m_print_config ) ;
filaments_cnt = extruders . size ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " arrange: slice filaments info invalid or need_skip, get from partplate: filament_count %1% " ) % filaments_cnt ;
}
if ( ( filaments_cnt < = 1 ) & & ! is_smooth_timelapse )
{
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " arrange: not a multi-color object anymore, drop the wipe tower before arrange. " ) ;
}
else
{
float layer_height = 0.2 ;
ConfigOption * layer_height_opt = m_print_config . option ( " layer_height " ) ;
if ( layer_height_opt )
layer_height = layer_height_opt - > getFloat ( ) ;
//float depth = v * (filaments_cnt - 1) / (layer_height * w);
Vec3d wipe_tower_size = cur_plate - > estimate_wipe_tower_size ( m_print_config , w , v , filaments_cnt ) ;
Vec3d plate_origin = cur_plate - > get_origin ( ) ;
int plate_width , plate_depth , plate_height ;
partplate_list . get_plate_size ( plate_width , plate_depth , plate_height ) ;
float depth = wipe_tower_size ( 1 ) ;
float margin = 15.f , wp_brim_width = 0.f ;
ConfigOption * wipe_tower_brim_width_opt = m_print_config . option ( " prime_tower_brim_width " ) ;
if ( wipe_tower_brim_width_opt ) {
wp_brim_width = wipe_tower_brim_width_opt - > getFloat ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " arrange wipe_tower: wp_brim_width %1% " ) % wp_brim_width ;
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " arrange wipe_tower: x=%1%, y=%2%, width=%3%, depth=%4%, angle=%5%, prime_volume=%6%, filaments_cnt=%7%, layer_height=%8%, plate_width=%9%, plate_depth=%10% " )
% x % y % w % depth % a % v % filaments_cnt % layer_height % plate_width % plate_depth ;
if ( ( y + depth + margin + wp_brim_width ) > ( float ) plate_depth ) {
y = ( float ) plate_depth - depth - margin - wp_brim_width ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " arrange wipe_tower: exceeds the border, change y to %1%, plate_depth=%2% " ) % y % plate_depth ;
}
if ( ( x + w + margin + wp_brim_width ) > ( float ) plate_width ) {
x = ( float ) plate_width - w - margin - wp_brim_width ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " arrange wipe_tower: exceeds the border, change x to %1%, plate_width=%2% " ) % y % plate_width ;
}
if ( x < margin ) {
x = margin ;
}
if ( y < margin ) {
y = margin ;
}
//update wipe_tower_x and wipe_tower_y
ConfigOptionFloat wt_x_opt ( x ) ;
ConfigOptionFloat wt_y_opt ( y ) ;
ConfigOptionFloats * wipe_x_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_x " , true ) ;
ConfigOptionFloats * wipe_y_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_y " , true ) ;
wipe_x_option - > set_at ( & wt_x_opt , plate_to_slice - 1 , 0 ) ;
wipe_y_option - > set_at ( & wt_y_opt , plate_to_slice - 1 , 0 ) ;
ArrangePolygon wipe_tower_ap ;
Polygon ap ( {
{ scaled ( x - wp_brim_width ) , scaled ( y - wp_brim_width ) } ,
{ scaled ( x + w + wp_brim_width ) , scaled ( y - wp_brim_width ) } ,
{ scaled ( x + w + wp_brim_width ) , scaled ( y + depth + wp_brim_width ) } ,
{ scaled ( x - wp_brim_width ) , scaled ( y + depth + wp_brim_width ) }
} ) ;
wipe_tower_ap . bed_idx = 0 ;
wipe_tower_ap . setter = NULL ; // do not move wipe tower
wipe_tower_ap . poly . contour = std : : move ( ap ) ;
wipe_tower_ap . translation = { scaled ( 0.f ) , scaled ( 0.f ) } ;
wipe_tower_ap . rotation = a ;
wipe_tower_ap . name = " WipeTower " ;
wipe_tower_ap . is_virt_object = true ;
wipe_tower_ap . is_wipe_tower = true ;
+ + wipe_tower_ap . priority ;
unselected . emplace_back ( std : : move ( wipe_tower_ap ) ) ;
}
}
// add the virtual object into unselect list if has
partplate_list . preprocess_exclude_areas ( unselected , plate_to_slice ) ;
}
//Step-2:prepare the arrange params
arrange_cfg . allow_rotations = allow_rotations ;
arrange_cfg . allow_multi_materials_on_same_plate = allow_multicolor_oneplate ;
arrange_cfg . avoid_extrusion_cali_region = avoid_extrusion_cali_region ;
arrange_cfg . clearance_height_to_rod = height_to_rod ;
arrange_cfg . clearance_height_to_lid = height_to_lid ;
arrange_cfg . cleareance_radius = cleareance_radius ;
arrange_cfg . printable_height = print_height ;
arrange_cfg . min_obj_distance = 0 ;
if ( arrange_cfg . is_seq_print ) {
arrange_cfg . bed_shrink_x = BED_SHRINK_SEQ_PRINT ;
arrange_cfg . bed_shrink_y = BED_SHRINK_SEQ_PRINT ;
}
if ( auto printer_structure_opt = m_print_config . option < ConfigOptionEnum < PrinterStructure > > ( " printer_structure " ) ) {
arrange_cfg . align_to_y_axis = ( printer_structure_opt - > value = = PrinterStructure : : psI3 ) ;
}
arrangement : : update_arrange_params ( arrange_cfg , & m_print_config , selected ) ;
arrangement : : update_selected_items_inflation ( selected , & m_print_config , arrange_cfg ) ;
arrangement : : update_unselected_items_inflation ( unselected , & m_print_config , arrange_cfg ) ;
arrangement : : update_selected_items_axis_align ( selected , & m_print_config , arrange_cfg ) ;
beds = get_shrink_bedpts ( & m_print_config , arrange_cfg ) ;
partplate_list . preprocess_exclude_areas ( arrange_cfg . excluded_regions , 1 , scale_ ( 1 ) ) ;
{
BOOST_LOG_TRIVIAL ( debug ) < < " arrange bedpts: " < < beds [ 0 ] . transpose ( ) < < " , " < < beds [ 1 ] . transpose ( ) < < " , " < < beds [ 2 ] . transpose ( ) < < " , " < < beds [ 3 ] . transpose ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < " Arrange full params: " < < arrange_cfg . to_json ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " arrange: items selected before arranging: %1% " ) % selected . size ( ) ;
for ( auto item : selected )
BOOST_LOG_TRIVIAL ( trace ) < < item . name < < " , extruder: " < < item . extrude_ids . back ( ) < < " , bed: " < < item . bed_idx
< < " , trans: " < < item . translation . transpose ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " arrange: items unselected before arranging: %1% " ) % unselected . size ( ) ;
for ( auto item : unselected )
BOOST_LOG_TRIVIAL ( trace ) < < item . name < < " , bed: " < < item . bed_idx < < " , trans: " < < item . translation . transpose ( ) ;
}
arrange_cfg . progressind = [ ] ( unsigned st , std : : string str = " " ) {
//boost::nowide::cout << "st=" << st << ", " << str << std::endl;
} ;
//Step-3:do the arrange
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " start %1% th arranging... " ) % arrange_count ;
arrangement : : arrange ( selected , unselected , beds , arrange_cfg ) ;
arrangement : : arrange ( unprintable , { } , beds , arrange_cfg ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " finished %1% th arranging... " ) % arrange_count ;
//Step-4:postprocess by partplate list&&apply the result
int bed_idx_max = 0 ;
if ( duplicate_count = = 0 )
{
if ( plate_to_slice > 0 )
{
//only for partplate case
partplate_list . clear ( false , false , true , plate_to_slice - 1 ) ;
for ( ArrangePolygon & ap : selected ) {
partplate_list . postprocess_bed_index_for_current_plate ( ap ) ;
if ( ap . bed_idx ! = ( plate_to_slice - 1 ) )
{
BOOST_LOG_TRIVIAL ( error ) < < __FUNCTION__ < < boost : : format ( " :arrange failed: ap.name %1% ap.bed_idx %2%, plate index %3% " ) % ap . name % ap . bed_idx % ( plate_to_slice - 1 ) ;
record_exit_reson ( outfile_dir , CLI_OBJECT_ARRANGE_FAILED , 0 , cli_errors [ CLI_OBJECT_ARRANGE_FAILED ] , sliced_info ) ;
flush_and_exit ( CLI_OBJECT_ARRANGE_FAILED ) ;
}
bed_idx_max = std : : max ( ap . bed_idx , bed_idx_max ) ;
}
}
else
{
//clear all the relations before apply the arrangement results
partplate_list . clear ( ) ;
// Apply the arrange result to all selected objects
for ( ArrangePolygon & ap : selected ) {
//QDS: partplate postprocess
partplate_list . postprocess_bed_index_for_selected ( ap ) ;
bed_idx_max = std : : max ( ap . bed_idx , bed_idx_max ) ;
BOOST_LOG_TRIVIAL ( trace ) < < " after arrange: name= " < < ap . name < < boost : : format ( " ,bed_id %1%, trans {%2%,%3%} " ) % ap . bed_idx % unscale < double > ( ap . translation ( X ) ) % unscale < double > ( ap . translation ( Y ) ) < < " \n " ;
}
}
for ( ArrangePolygon & ap : locked_aps ) {
bed_idx_max = std : : max ( ap . bed_idx , bed_idx_max ) ;
partplate_list . postprocess_arrange_polygon ( ap , false ) ;
ap . apply ( ) ;
}
// Apply the arrange result to all selected objects
for ( ArrangePolygon & ap : selected ) {
//QDS: partplate postprocess
partplate_list . postprocess_arrange_polygon ( ap , true ) ;
ap . apply ( ) ;
}
// Apply the arrange result to unselected objects(due to the sukodu-style column changes, the position of unselected may also be modified)
for ( ArrangePolygon & ap : unselected )
{
if ( ap . is_virt_object )
continue ;
//QDS: partplate postprocess
partplate_list . postprocess_arrange_polygon ( ap , false ) ;
ap . apply ( ) ;
}
// Move the unprintable items to the last virtual bed.
// Note ap.apply() moves relatively according to bed_idx, so we need to subtract the orignal bed_idx
for ( ArrangePolygon & ap : unprintable )
{
ap . bed_idx = bed_idx_max + 1 ;
partplate_list . postprocess_arrange_polygon ( ap , true ) ;
ap . apply ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " :arrange m_unprintable: name: %4%, bed_id %1%, trans {%2%,%3%} " ) % ap . bed_idx % unscale < double > ( ap . translation ( X ) ) % unscale < double > ( ap . translation ( Y ) ) % ap . name ;
}
//QDS: reload all objects due to arrange
if ( plate_to_slice > 0 )
partplate_list . rebuild_plates_after_arrangement ( false , true , plate_to_slice - 1 ) ;
else
partplate_list . rebuild_plates_after_arrangement ( ) ;
}
else {
//only for partplate case
partplate_list . clear ( false , false , true , plate_to_slice - 1 ) ;
//QDS: adjust the bed_index, create new plates, get the max bed_index
bool failed_this_time = false ;
for ( ArrangePolygon & ap : selected ) {
partplate_list . postprocess_bed_index_for_current_plate ( ap ) ;
if ( ap . bed_idx ! = ( plate_to_slice - 1 ) )
{
//
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " :arrange failed: ap.name %1% ap.bed_idx %2%, plate index %3% " ) % ap . name % ap . bed_idx % ( plate_to_slice - 1 ) ;
if ( ! duplicate_single_object )
{
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " arrange failed when duplicate multiple objects at count %1%, low_duplicate_count %2%, up_duplicate_count %3% " ) % duplicate_count % low_duplicate_count % up_duplicate_count ;
if ( duplicate_count = = 1 )
{
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " : failed even on duplicate 1 copy, just print one original model " ) ;
duplicate_count = 0 ;
}
else
{
if ( duplicate_count = = low_duplicate_count )
{
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " : previous success, but currently failed count %1%!!! " ) % duplicate_count ;
up_duplicate_count = duplicate_count ;
low_duplicate_count - - ;
duplicate_count - - ;
}
else {
up_duplicate_count = duplicate_count ;
duplicate_count = ( up_duplicate_count + low_duplicate_count ) / 2 ;
}
BOOST_LOG_TRIVIAL ( warning ) < < __FUNCTION__ < < boost : : format ( " : try new count %1%, low_duplicate_count %2%, up_duplicate_count %3% " ) % duplicate_count % low_duplicate_count % up_duplicate_count ;
}
//record_exit_reson(outfile_dir, CLI_OBJECT_ARRANGE_FAILED, 0, cli_errors[CLI_OBJECT_ARRANGE_FAILED], sliced_info);
//flush_and_exit(CLI_OBJECT_ARRANGE_FAILED);
failed_this_time = true ;
break ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " :arrange success: ap.name %1% ap.bed_idx %2%, plate index %3% " ) % ap . name % ap . bed_idx % ( plate_to_slice - 1 ) ;
real_duplicate_count + + ;
}
bed_idx_max = std : : max ( ap . bed_idx , bed_idx_max ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " : arrange selected %4%: bed_id %1%, trans {%2%,%3%} " ) % ap . bed_idx % unscale < double > ( ap . translation ( X ) ) % unscale < double > ( ap . translation ( Y ) ) % ap . name ;
}
if ( failed_this_time ) {
if ( duplicate_count = = 0 )
{
//restore to the original
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : restore to the original model and plates, orig_wipe_x %1%, orig_wipe_y %2% " ) % orig_wipe_x % orig_wipe_y ;
finished_arrange = true ;
model = original_model ;
partplate_list . load_from_3mf_structure ( plate_data_src ) ;
partplate_list . reset_size ( current_printable_width , current_printable_depth , current_printable_height , true , true ) ;
if ( ( orig_wipe_x > 0.f ) & & ( orig_wipe_y > 0.f ) )
{
ConfigOptionFloat wt_x_opt ( orig_wipe_x ) ;
ConfigOptionFloat wt_y_opt ( orig_wipe_y ) ;
ConfigOptionFloats * wipe_x_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_x " , true ) ;
ConfigOptionFloats * wipe_y_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_y " , true ) ;
wipe_x_option - > set_at ( & wt_x_opt , plate_to_slice - 1 , 0 ) ;
wipe_y_option - > set_at ( & wt_y_opt , plate_to_slice - 1 , 0 ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : restore wipe_tower position to {%1%, %2%} " ) % orig_wipe_x % orig_wipe_y ;
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : exit arrange process " ) ;
}
continue ;
}
if ( duplicate_single_object )
{
if ( real_duplicate_count < = 1 ) {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " no object can be placed under single object mode, restore to the original model and plates also, orig_wipe_x %1%, orig_wipe_y %2% " ) % orig_wipe_x % orig_wipe_y ;
//record_exit_reson(outfile_dir, CLI_OBJECT_ARRANGE_FAILED, 0, cli_errors[CLI_OBJECT_ARRANGE_FAILED], sliced_info);
//flush_and_exit(CLI_OBJECT_ARRANGE_FAILED);
finished_arrange = true ;
model = original_model ;
partplate_list . load_from_3mf_structure ( plate_data_src ) ;
partplate_list . reset_size ( current_printable_width , current_printable_depth , current_printable_height , true , true ) ;
duplicate_count = 0 ;
if ( ( orig_wipe_x > 0.f ) & & ( orig_wipe_y > 0.f ) )
{
ConfigOptionFloat wt_x_opt ( orig_wipe_x ) ;
ConfigOptionFloat wt_y_opt ( orig_wipe_y ) ;
ConfigOptionFloats * wipe_x_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_x " , true ) ;
ConfigOptionFloats * wipe_y_option = m_print_config . option < ConfigOptionFloats > ( " wipe_tower_y " , true ) ;
wipe_x_option - > set_at ( & wt_x_opt , plate_to_slice - 1 , 0 ) ;
wipe_y_option - > set_at ( & wt_y_opt , plate_to_slice - 1 , 0 ) ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : restore wipe_tower position to {%1%, %2%} " ) % orig_wipe_x % orig_wipe_y ;
}
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : exit arrange process " ) ;
continue ;
}
duplicate_count = real_duplicate_count - 1 ;
}
else {
//multiple objects case
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : multiple objects mode, arrange success on count %1%, low_duplicate_count %2%, up_duplicate_count %3% " ) % duplicate_count % low_duplicate_count % up_duplicate_count ;
if ( ( duplicate_count = = up_duplicate_count ) | | ( duplicate_count = = ( up_duplicate_count - 1 ) ) )
{
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : found the max arrangeable count %1% " ) % duplicate_count ;
}
else {
low_duplicate_count = duplicate_count ;
duplicate_count = ( up_duplicate_count + low_duplicate_count ) / 2 ;
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < boost : : format ( " : try new count %1%, low_duplicate_count %2%, up_duplicate_count %3% " ) % duplicate_count % low_duplicate_count % up_duplicate_count ;
continue ;
}
}
//QDS: adjust the bed_index, create new plates, get the max bed_index
for ( ArrangePolygon & ap : unselected )
{
if ( ap . is_virt_object )
continue ;
bed_idx_max = std : : max ( ap . bed_idx , bed_idx_max ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " :arrange unselected %4%: bed_id %1%, trans {%2%,%3%} " ) % ap . bed_idx % unscale < double > ( ap . translation ( X ) ) % unscale < double > ( ap . translation ( Y ) ) % ap . name ;
}
for ( ArrangePolygon & ap : locked_aps )
{
bed_idx_max = std : : max ( ap . bed_idx , bed_idx_max ) ;
partplate_list . postprocess_arrange_polygon ( ap , false ) ;
ap . apply ( ) ;
}
// Apply the arrange result to all selected objects
for ( ArrangePolygon & ap : selected ) {
//QDS: partplate postprocess
partplate_list . postprocess_arrange_polygon ( ap , true ) ;
ap . apply ( ) ;
}
// Apply the arrange result to unselected objects(due to the sukodu-style column changes, the position of unselected may also be modified)
for ( ArrangePolygon & ap : unselected )
{
if ( ap . is_virt_object )
continue ;
//QDS: partplate postprocess
partplate_list . postprocess_arrange_polygon ( ap , false ) ;
ap . apply ( ) ;
}
// Move the unprintable items to the last virtual bed.
// Note ap.apply() moves relatively according to bed_idx, so we need to subtract the orignal bed_idx
for ( ArrangePolygon & ap : unprintable )
{
ap . bed_idx = bed_idx_max + 1 ;
partplate_list . postprocess_arrange_polygon ( ap , true ) ;
ap . apply ( ) ;
BOOST_LOG_TRIVIAL ( debug ) < < __FUNCTION__ < < boost : : format ( " :arrange m_unprintable: name: %4%, bed_id %1%, trans {%2%,%3%} " ) % ap . bed_idx % unscale < double > ( ap . translation ( X ) ) % unscale < double > ( ap . translation ( Y ) ) % ap . name ;
}
partplate_list . rebuild_plates_after_arrangement ( false , true , plate_to_slice - 1 ) ;
}
finished_arrange = true ;
}
original_model . clear_objects ( ) ;
original_model . clear_materials ( ) ;
}
}
// All transforms have been dealt with. Now ensure that the objects are on bed.
// (Unless the user said otherwise.)
//QDS: current only support models on bed, 0407 sinking supported
if ( m_config . opt_bool ( " ensure_on_bed " ) )
{
BOOST_LOG_TRIVIAL ( info ) < < " ensure_on_bed: need to ensure each object on beds " ;
for ( auto & model : m_models )
for ( auto & o : model . objects )
o - > ensure_on_bed ( ) ;
}
// loop through action options
bool export_to_3mf = false , load_slicedata = false , export_slicedata = false , export_slicedata_error = false ;
bool no_check = false ;
std : : string export_3mf_file , load_slice_data_dir , export_slice_data_dir , export_stls_dir ;
std : : vector < ThumbnailData * > calibration_thumbnails ;
std : : vector < int > plate_object_count ( partplate_list . get_plate_count ( ) , 0 ) ;
int max_slicing_time_per_plate = 0 , max_triangle_count_per_plate = 0 , sliced_plate = - 1 ;
std : : vector < bool > plate_has_skips ( partplate_list . get_plate_count ( ) , false ) ;
std : : vector < std : : vector < size_t > > plate_skipped_objects ( partplate_list . get_plate_count ( ) ) ;
2024-09-16 16:07:29 +08:00
//1.9.5
global_current_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
2024-09-03 09:34:33 +08:00
sliced_info . prepare_time = ( size_t ) ( global_current_time - global_begin_time ) ;
global_begin_time = global_current_time ;
2024-09-16 16:07:29 +08:00
//1.9.5
//opengl related
Slic3r : : GUI : : OpenGLManager opengl_mgr ;
GLShaderProgram * shader = nullptr ;
GLVolumeCollection glvolume_collection ;
bool opengl_valid = false ;
const ConfigOptionStrings * filament_color = dynamic_cast < const ConfigOptionStrings * > ( m_print_config . option ( " filament_colour " ) ) ;
std : : vector < std : : string > colors ;
if ( filament_color ) {
colors = filament_color - > vserialize ( ) ;
}
else
colors . push_back ( " #FFFFFFFF " ) ;
std : : vector < std : : array < float , 4 > > colors_out ( colors . size ( ) ) ;
auto init_opengl_and_colors = [ & opengl_mgr , & colors_out , & glvolume_collection , & shader , & filament_color ] ( Model & model , std : : vector < std : : string > & f_colors ) - > bool {
unsigned char rgb_color [ 4 ] = { } ;
for ( const std : : string & color : f_colors ) {
Slic3r : : GUI : : BitmapCache : : parse_color4 ( color , rgb_color ) ;
size_t color_idx = & color - & f_colors . front ( ) ;
colors_out [ color_idx ] = { float ( rgb_color [ 0 ] ) / 255.f , float ( rgb_color [ 1 ] ) / 255.f , float ( rgb_color [ 2 ] ) / 255.f , float ( rgb_color [ 3 ] ) / 255.f } ;
}
int gl_major , gl_minor , gl_verbos ;
glfwGetVersion ( & gl_major , & gl_minor , & gl_verbos ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " opengl version %1%.%2%.%3% " ) % gl_major % gl_minor % gl_verbos ;
glfwSetErrorCallback ( glfw_callback ) ;
int ret = glfwInit ( ) ;
if ( ret = = GLFW_FALSE ) {
int code = glfwGetError ( NULL ) ;
BOOST_LOG_TRIVIAL ( error ) < < " glfwInit return error, code " < < code < < std : : endl ;
return false ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " glfwInit Success. " < < std : : endl ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , gl_major ) ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , gl_minor ) ;
glfwWindowHint ( GLFW_RED_BITS , 8 ) ;
glfwWindowHint ( GLFW_GREEN_BITS , 8 ) ;
glfwWindowHint ( GLFW_BLUE_BITS , 8 ) ;
glfwWindowHint ( GLFW_ALPHA_BITS , 8 ) ;
glfwWindowHint ( GLFW_VISIBLE , false ) ;
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwDisable(GLFW_AUTO_POLL_EVENTS);
# ifdef __WXMAC__
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE ) ;
glfwWindowHint ( GLFW_OPENGL_FORWARD_COMPAT , GL_TRUE ) ;
# else
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_COMPAT_PROFILE ) ;
# endif
# ifdef __linux__
glfwWindowHint ( GLFW_CONTEXT_CREATION_API , GLFW_OSMESA_CONTEXT_API ) ;
# endif
GLFWwindow * window = glfwCreateWindow ( 640 , 480 , " base_window " , NULL , NULL ) ;
if ( window = = NULL )
{
BOOST_LOG_TRIVIAL ( error ) < < " Failed to create GLFW window " < < std : : endl ;
return false ;
}
else
glfwMakeContextCurrent ( window ) ;
}
bool gl_valid = opengl_mgr . init_gl ( false ) ;
if ( ! gl_valid ) {
BOOST_LOG_TRIVIAL ( error ) < < " init opengl failed! skip thumbnail generating " < < std : : endl ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " glewInit Sucess. " < < std : : endl ;
shader = opengl_mgr . get_shader ( " thumbnail " ) ;
if ( ! shader ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " can not get shader for rendering thumbnail " ) ;
gl_valid = false ;
}
else {
int obj_extruder_id = 1 , volume_extruder_id = 1 ;
for ( unsigned int obj_idx = 0 ; obj_idx < ( unsigned int ) model . objects . size ( ) ; + + obj_idx ) {
const ModelObject & model_object = * model . objects [ obj_idx ] ;
const ConfigOption * option = model_object . config . option ( " extruder " ) ;
if ( option )
obj_extruder_id = ( dynamic_cast < const ConfigOptionInt * > ( option ) ) - > getInt ( ) ;
else
obj_extruder_id = 1 ;
for ( int volume_idx = 0 ; volume_idx < ( int ) model_object . volumes . size ( ) ; + + volume_idx ) {
const ModelVolume & model_volume = * model_object . volumes [ volume_idx ] ;
option = model_volume . config . option ( " extruder " ) ;
if ( option )
volume_extruder_id = ( dynamic_cast < const ConfigOptionInt * > ( option ) ) - > getInt ( ) ;
else
volume_extruder_id = obj_extruder_id ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " volume %1%'s extruder_id %2% " ) % volume_idx % volume_extruder_id ;
//if (!model_volume.is_model_part())
// continue;
for ( int instance_idx = 0 ; instance_idx < ( int ) model_object . instances . size ( ) ; + + instance_idx ) {
const ModelInstance & model_instance = * model_object . instances [ instance_idx ] ;
glvolume_collection . load_object_volume ( & model_object , obj_idx , volume_idx , instance_idx , " volume " , true , false , true ) ;
//glvolume_collection.volumes.back()->geometry_id = key.geometry_id;
std : : string color = filament_color ? filament_color - > get_at ( volume_extruder_id - 1 ) : " #00FF00FF " ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " volume %1%'s color %2% " ) % volume_idx % color ;
unsigned char rgb_color [ 4 ] = { } ;
Slic3r : : GUI : : BitmapCache : : parse_color4 ( color , rgb_color ) ;
std : : array < float , 4 > new_color ;
new_color [ 0 ] = float ( rgb_color [ 0 ] ) / 255.f ;
new_color [ 1 ] = float ( rgb_color [ 1 ] ) / 255.f ;
new_color [ 2 ] = float ( rgb_color [ 2 ] ) / 255.f ;
new_color [ 3 ] = float ( rgb_color [ 3 ] ) / 255.f ;
glvolume_collection . volumes . back ( ) - > set_render_color ( new_color [ 0 ] , new_color [ 1 ] , new_color [ 2 ] , new_color [ 3 ] ) ;
glvolume_collection . volumes . back ( ) - > set_color ( new_color ) ;
glvolume_collection . volumes . back ( ) - > printable = model_instance . printable ;
}
}
}
}
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " init_opengl_and_colors finished, gl_valid=%1% " ) % gl_valid ;
return gl_valid ;
} ;
2024-09-03 09:34:33 +08:00
for ( auto const & opt_key : m_actions ) {
if ( opt_key = = " help " ) {
this - > print_help ( ) ;
} else if ( opt_key = = " help_fff " ) {
this - > print_help ( true , ptFFF ) ;
} else if ( opt_key = = " help_sla " ) {
this - > print_help ( true , ptSLA ) ;
} else if ( opt_key = = " pipe " ) {
//already processed before
} else if ( opt_key = = " load_slicedata " ) {
load_slicedata = true ;
load_slice_data_dir = m_config . opt_string ( opt_key ) ;
if ( export_slicedata ) {
BOOST_LOG_TRIVIAL ( error ) < < " should not set load_slicedata and export_slicedata together. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
else if ( duplicate_count > 0 )
{
BOOST_LOG_TRIVIAL ( error ) < < " should not set load_slicedata when set repetitions. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
else if ( shrink_to_new_bed > 0 )
{
BOOST_LOG_TRIVIAL ( warning ) < < " use load_slicedata when shrink_to_new_bed. " < < std : : endl ;
//record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info);
//flush_and_exit(CLI_INVALID_PARAMS);
}
} else if ( opt_key = = " export_settings " ) {
//FIXME check for mixing the FFF / SLA parameters.
// or better save fff_print_config vs. sla_print_config
//m_print_config.save(m_config.opt_string("save"));
m_print_config . save_to_json ( m_config . opt_string ( opt_key ) , std : : string ( " project_settings " ) , std : : string ( " project " ) , std : : string ( SLIC3R_VERSION ) ) ;
} else if ( opt_key = = " info " ) {
// --info works on unrepaired model
for ( Model & model : m_models ) {
model . add_default_instances ( ) ;
model . print_info ( ) ;
}
} else if ( opt_key = = " uptodate " ) {
//already processed before
} else if ( opt_key = = " min_save " ) {
//already processed before
} else if ( opt_key = = " load_defaultfila " ) {
//already processed before
} else if ( opt_key = = " mtcpp " ) {
max_triangle_count_per_plate = m_config . option < ConfigOptionInt > ( " mtcpp " ) - > value ;
} else if ( opt_key = = " mstpp " ) {
max_slicing_time_per_plate = m_config . option < ConfigOptionInt > ( " mstpp " ) - > value ;
} else if ( opt_key = = " export_stl " ) {
for ( auto & model : m_models )
model . add_default_instances ( ) ;
if ( ! this - > export_models ( IO : : STL ) ) {
record_exit_reson ( outfile_dir , CLI_EXPORT_STL_ERROR , 0 , cli_errors [ CLI_EXPORT_STL_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_EXPORT_STL_ERROR ) ;
}
} else if ( opt_key = = " export_stls " ) {
export_stls_dir = m_config . opt_string ( opt_key ) ;
for ( auto & model : m_models )
model . add_default_instances ( ) ;
if ( ! this - > export_models ( IO : : STL , export_stls_dir ) ) {
record_exit_reson ( outfile_dir , CLI_EXPORT_STL_ERROR , 0 , cli_errors [ CLI_EXPORT_STL_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_EXPORT_STL_ERROR ) ;
}
} else if ( opt_key = = " export_obj " ) {
for ( auto & model : m_models )
model . add_default_instances ( ) ;
if ( ! this - > export_models ( IO : : OBJ ) ) {
record_exit_reson ( outfile_dir , CLI_EXPORT_OBJ_ERROR , 0 , cli_errors [ CLI_EXPORT_OBJ_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_EXPORT_OBJ_ERROR ) ;
}
} /* else if (opt_key == "export_amf") {
if ( ! this - > export_models ( IO : : AMF ) )
return 1 ;
} */ else if ( opt_key = = " export_3mf " ) {
export_to_3mf = true ;
export_3mf_file = m_config . opt_string ( opt_key ) ;
} else if ( opt_key = = " no_check " ) {
no_check = m_config . opt_bool ( opt_key ) ;
//} else if (opt_key == "export_gcode" || opt_key == "export_sla" || opt_key == "slice") {
} else if ( opt_key = = " normative_check " ) {
//already processed before
} else if ( opt_key = = " export_slicedata " ) {
export_slicedata = true ;
export_slice_data_dir = m_config . opt_string ( opt_key ) ;
if ( load_slicedata ) {
BOOST_LOG_TRIVIAL ( error ) < < " should not set load_slicedata and export_slicedata together. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_INVALID_PARAMS , 0 , cli_errors [ CLI_INVALID_PARAMS ] , sliced_info ) ;
flush_and_exit ( CLI_INVALID_PARAMS ) ;
}
} else if ( opt_key = = " slice " ) {
//QDS: slice 0 means all plates, i means plate i;
plate_to_slice = m_config . option < ConfigOptionInt > ( " slice " ) - > value ;
sliced_plate = plate_to_slice ;
bool pre_check = ( plate_to_slice = = 0 ) ? true : false ;
bool finished = false ;
/*if (opt_key == "export_gcode" && printer_technology == ptSLA) {
boost : : nowide : : cerr < < " error: cannot export G-code for an FFF configuration " < < std : : endl ;
record_exit_reson ( outfile_dir , 1 , 0 , cli_errors [ 1 ] , sliced_info ) ;
flush_and_exit ( 1 ) ;
} else if ( opt_key = = " export_sla " & & printer_technology = = ptFFF ) {
boost : : nowide : : cerr < < " error: cannot export SLA slices for a SLA configuration " < < std : : endl ;
record_exit_reson ( outfile_dir , 1 , 0 , cli_errors [ 1 ] , sliced_info ) ;
flush_and_exit ( 1 ) ;
} */
BOOST_LOG_TRIVIAL ( info ) < < " Need to slice for plate " < < plate_to_slice < < " , total plate count " < < partplate_list . get_plate_count ( ) < < " partplates! " < < std : : endl ;
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 3 , " Prepare slicing " } ;
cli_status_callback ( slicing_status ) ;
}
# endif
// Make a copy of the model if the current action is not the last action, as the model may be
// modified by the centering and such.
Model model_copy ;
bool make_copy = & opt_key ! = & m_actions . back ( ) ;
for ( Model & model_in : m_models ) {
if ( make_copy )
model_copy = model_in ;
Model & model = make_copy ? model_copy : model_in ;
// If all objects have defined instances, their relative positions will be
// honored when printing (they will be only centered, unless --dont-arrange
// is supplied); if any object has no instances, it will get a default one
// and all instances will be rearranged (unless --dont-arrange is supplied).
std : : string outfile ;
//Print fff_print;
std : : vector < size_t > plate_triangle_counts ( partplate_list . get_plate_count ( ) , 0 ) ;
while ( ! finished )
{
//QDS: slice every partplate one by one
PrintBase * print = NULL ;
Print * print_fff = NULL ;
Slic3r : : GUI : : GCodeResult * gcode_result = NULL ;
int print_index ;
for ( int index = 0 ; index < partplate_list . get_plate_count ( ) ; index + + )
{
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( index + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " Skip plate " < < index + 1 < < std : : endl ;
continue ;
}
sliced_plate_info_t sliced_plate_info ;
sliced_plate_info . plate_id = index + 1 ;
model . curr_plate_index = index ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: pre_check %2%, start " ) % ( index + 1 ) % pre_check ;
2024-09-16 16:07:29 +08:00
//1.9.5
long long start_time = 0 , end_time = 0 , temp_time = 0 ;
std : : unordered_map < std : : string , long long > slice_time ;
slice_time [ TIME_USING_CACHE ] = 0 ;
slice_time [ TIME_MAKE_PERIMETERS ] = 0 ;
slice_time [ TIME_INFILL ] = 0 ;
slice_time [ TIME_GENERATE_SUPPORT ] = 0 ;
start_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
2024-09-03 09:34:33 +08:00
//get the current partplate
Slic3r : : GUI : : PartPlate * part_plate = partplate_list . get_plate ( index ) ;
part_plate - > get_print ( & print , & gcode_result , & print_index ) ;
print_fff = dynamic_cast < Print * > ( print ) ;
/*if (outfile_config.empty())
{
outfile = " plate_ " + std : : to_string ( index + 1 ) + " .gcode " ;
}
else
{
outfile = " plate_ " + std : : to_string ( index + 1 ) + " _ " + outfile_config + " .gcode " ;
} */
//update plate's bounding box to model
#if 0
BoundingBoxf3 print_volume = part_plate - > get_bounding_box ( false ) ;
print_volume . max ( 2 ) = z ;
print_volume . min ( 2 ) = - 1e10 ;
model . update_print_volume_state ( print_volume ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " print_volume {%1%,%2%,%3%}->{%4%, %5%, %6%} " ) % print_volume . min ( 0 ) % print_volume . min ( 1 )
% print_volume . min ( 2 ) % print_volume . max ( 0 ) % print_volume . max ( 1 ) % print_volume . max ( 2 ) < < std : : endl ;
# else
BuildVolume build_volume ( part_plate - > get_shape ( ) , print_height ) ;
//model.update_print_volume_state(build_volume);
unsigned int count = model . update_print_volume_state ( build_volume ) ;
if ( count = = 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : Nothing to be sliced, Either the print is empty or no object is fully inside the print volume before apply. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_NO_SUITABLE_OBJECTS , index + 1 , cli_errors [ CLI_NO_SUITABLE_OBJECTS ] , sliced_info ) ;
flush_and_exit ( CLI_NO_SUITABLE_OBJECTS ) ;
}
else if ( ( plate_to_slice ! = 0 ) | | pre_check ) {
long long triangle_count = 0 ;
int printable_instances = 0 ;
int skipped_count = 0 ;
for ( ModelObject * model_object : model . objects )
for ( ModelInstance * i : model_object - > instances )
{
i - > use_loaded_id_for_label = true ;
if ( skip_maps . find ( i - > loaded_id ) ! = skip_maps . end ( ) ) {
skip_maps [ i - > loaded_id ] = true ;
i - > printable = false ;
if ( i - > print_volume_state = = ModelInstancePVS_Inside ) {
skipped_count + + ;
plate_has_skips [ index ] = true ;
plate_skipped_objects [ index ] . emplace_back ( i - > loaded_id ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: skip object %2%. " ) % ( index + 1 ) % i - > loaded_id ;
//need to regenerate the thumbnail
if ( plate_data_src . size ( ) > index ) {
if ( ! plate_data_src [ index ] - > thumbnail_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > thumbnail_file ;
plate_data_src [ index ] - > thumbnail_file . clear ( ) ;
}
if ( ! plate_data_src [ index ] - > no_light_thumbnail_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded no_light_thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > no_light_thumbnail_file ;
plate_data_src [ index ] - > no_light_thumbnail_file . clear ( ) ;
}
if ( ! plate_data_src [ index ] - > top_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded top_thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > top_file ;
plate_data_src [ index ] - > top_file . clear ( ) ;
}
if ( ! plate_data_src [ index ] - > pick_file . empty ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Plate %1%: clear loaded pick_thumbnail %2%. " ) % ( index + 1 ) % plate_data_src [ index ] - > pick_file ;
plate_data_src [ index ] - > pick_file . clear ( ) ;
}
}
}
continue ;
}
if ( i - > print_volume_state = = ModelInstancePVS_Partly_Outside )
{
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : Found Object " < < model_object - > name < < " partly inside, can not be sliced. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_OBJECTS_PARTLY_INSIDE , index + 1 , cli_errors [ CLI_OBJECTS_PARTLY_INSIDE ] , sliced_info ) ;
flush_and_exit ( CLI_OBJECTS_PARTLY_INSIDE ) ;
}
else if ( i - > print_volume_state = = ModelInstancePVS_Inside )
{
for ( const ModelVolume * vol : model_object - > volumes )
{
if ( vol - > is_model_part ( ) ) {
size_t volume_triangle_count = vol - > mesh ( ) . facets_count ( ) ;
triangle_count + = volume_triangle_count ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " volume triangle count %1%, total %2% " ) % volume_triangle_count % triangle_count ;
if ( ( max_triangle_count_per_plate ! = 0 ) & & ( triangle_count > max_triangle_count_per_plate ) )
{
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : triangle count " < < triangle_count < < " exceeds the limit: " < < max_triangle_count_per_plate ;
record_exit_reson ( outfile_dir , CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT , index + 1 , cli_errors [ CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT ] , sliced_info ) ;
flush_and_exit ( CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT ) ;
}
}
}
}
if ( i - > print_volume_state = = ModelInstancePVS_Inside )
printable_instances + + ;
}
if ( printable_instances = = 0 ) {
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : Nothing to be sliced, after skipping " < < skipped_count < < " objects. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP , index + 1 , cli_errors [ CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP ] , sliced_info ) ;
flush_and_exit ( CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP ) ;
}
plate_triangle_counts [ index ] = triangle_count ;
plate_object_count [ index ] = printable_instances ;
BOOST_LOG_TRIVIAL ( info ) < < " plate " < < index + 1 < < " : load cached data success, go on. " ;
}
// QDS: TODO
//BOOST_LOG_TRIVIAL(info) << boost::format("print_volume {%1%,%2%,%3%}->{%4%, %5%, %6%}, has %7% printables") % print_volume.min(0) % print_volume.min(1)
// % print_volume.min(2) % print_volume.max(0) % print_volume.max(1) % print_volume.max(2) % count << std::endl;
# endif
DynamicPrintConfig new_print_config = m_print_config ;
new_print_config . apply ( * part_plate - > config ( ) ) ;
new_print_config . apply ( m_extra_config , true ) ;
print - > apply ( model , new_print_config ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " set no_check to %1%: " ) % no_check ;
print - > set_no_check_flag ( no_check ) ; //QDS
StringObjectException warning ;
auto err = print - > validate ( & warning ) ;
if ( ! err . string . empty ( ) ) {
if ( ( STRING_EXCEPT_LAYER_HEIGHT_EXCEEDS_LIMIT = = err . type ) & & no_check ) {
BOOST_LOG_TRIVIAL ( warning ) < < " got warnings: " < < err . string < < std : : endl ;
}
else {
BOOST_LOG_TRIVIAL ( error ) < < " got error when validate: " < < err . string < < std : : endl ;
boost : : nowide : : cerr < < err . string < < std : : endl ;
int validate_error ;
switch ( err . type )
{
case STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE :
validate_error = CLI_FILAMENT_NOT_MATCH_BED_TYPE ;
break ;
case STRING_EXCEPT_FILAMENTS_DIFFERENT_TEMP :
validate_error = CLI_FILAMENTS_DIFFERENT_TEMP ;
break ;
case STRING_EXCEPT_OBJECT_COLLISION_IN_SEQ_PRINT :
validate_error = CLI_OBJECT_COLLISION_IN_SEQ_PRINT ;
break ;
case STRING_EXCEPT_OBJECT_COLLISION_IN_LAYER_PRINT :
validate_error = CLI_OBJECT_COLLISION_IN_LAYER_PRINT ;
break ;
default :
validate_error = CLI_VALIDATE_ERROR ;
break ;
}
if ( no_check )
record_exit_reson ( outfile_dir , validate_error , index + 1 , err . string , sliced_info ) ;
else
record_exit_reson ( outfile_dir , validate_error , index + 1 , cli_errors [ validate_error ] , sliced_info ) ;
flush_and_exit ( validate_error ) ;
}
}
else if ( ! warning . string . empty ( ) ) {
BOOST_LOG_TRIVIAL ( warning ) < < " got warnings: " < < warning . string < < std : : endl ;
}
if ( print - > empty ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : Nothing to be sliced, Either the print is empty or no object is fully inside the print volume after apply. " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_NO_SUITABLE_OBJECTS , index + 1 , cli_errors [ CLI_NO_SUITABLE_OBJECTS ] , sliced_info ) ;
flush_and_exit ( CLI_NO_SUITABLE_OBJECTS ) ;
}
else {
if ( pre_check & & ( partplate_list . get_plate_count ( ) > 1 ) ) //continue to next plate directly
continue ;
try {
std : : string outfile_final ;
BOOST_LOG_TRIVIAL ( info ) < < " start Print::process for partplate " < < index + 1 < < std : : endl ;
# if defined(__linux__) || defined(__LINUX__)
BOOST_LOG_TRIVIAL ( info ) < < " cli callback mgr started: " < < g_cli_callback_mgr . m_started < < std : : endl ;
if ( g_cli_callback_mgr . is_started ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " set print's callback to cli_status_callback. " ;
print - > set_status_callback ( cli_status_callback ) ;
g_cli_callback_mgr . set_plate_info ( index + 1 , ( plate_to_slice = = 0 ) ? partplate_list . get_plate_count ( ) : 1 ) ;
if ( ! warning . string . empty ( ) ) {
PrintBase : : SlicingStatus slicing_status { 4 , warning . string , 0 , 0 } ;
cli_status_callback ( slicing_status ) ;
}
else {
PrintBase : : SlicingStatus slicing_status { 4 , " Slicing begins " } ;
cli_status_callback ( slicing_status ) ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " set print's callback to default_status_callback. " ;
print - > set_status_callback ( default_status_callback ) ;
}
# else
BOOST_LOG_TRIVIAL ( info ) < < " set print's callback to default_status_callback. " ;
print - > set_status_callback ( default_status_callback ) ;
# endif
//check whether it is qdt printer
std : : string & printer_model_string = new_print_config . opt_string ( " printer_model " , true ) ;
bool is_qdt_vendor_preset = false ;
if ( ! printer_model_string . empty ( ) ) {
is_qdt_vendor_preset = ( printer_model_string . compare ( 0 , 9 , " QIDI Lab " ) = = 0 ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " printer_model_string: %1%, is_qdt_vendor_preset %2% " ) % printer_model_string % is_qdt_vendor_preset ;
}
else {
if ( ! new_printer_name . empty ( ) )
is_qdt_vendor_preset = ( new_printer_name . compare ( 0 , 9 , " QIDI Lab " ) = = 0 ) ;
else if ( ! current_printer_system_name . empty ( ) )
is_qdt_vendor_preset = ( current_printer_system_name . compare ( 0 , 9 , " QIDI Lab " ) = = 0 ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " new_printer_name: %1%, current_printer_system_name %2%, is_qdt_vendor_preset %3% " ) % new_printer_name % current_printer_system_name % is_qdt_vendor_preset ;
}
( dynamic_cast < Print * > ( print ) ) - > set_QDT_Printer ( is_qdt_vendor_preset ) ;
//update information for brim
const PrintConfig & print_config = print_fff - > config ( ) ;
Model : : setExtruderParams ( m_print_config , filament_count ) ;
Model : : setPrintSpeedTable ( m_print_config , print_config ) ;
if ( load_slicedata ) {
std : : string plate_dir = load_slice_data_dir + " / " + std : : to_string ( index + 1 ) ;
int ret = print - > load_cached_data ( plate_dir ) ;
if ( ret ) {
BOOST_LOG_TRIVIAL ( warning ) < < " plate " < < index + 1 < < " : load Slicing data error, ret= " < < ret ;
BOOST_LOG_TRIVIAL ( warning ) < < " plate " < < index + 1 < < " : switch normal slicing " ;
print - > process ( ) ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " plate " < < index + 1 < < " : load cached data success, go on. " ;
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 69 , " Cache data loaded " } ;
cli_status_callback ( slicing_status ) ;
}
# endif
print - > process ( nullptr , true ) ;
BOOST_LOG_TRIVIAL ( info ) < < " plate " < < index + 1 < < " : finished print::process. " ;
}
}
else {
2024-09-16 16:07:29 +08:00
//1.9.5
print - > process ( & slice_time ) ;
BOOST_LOG_TRIVIAL ( info ) < < " print::process: first time_using_cache is " < < slice_time [ TIME_USING_CACHE ] < < " secs. " ;
2024-09-03 09:34:33 +08:00
}
if ( printer_technology = = ptFFF ) {
std : : string conflict_result = print_fff - > get_conflict_string ( ) ;
if ( ! conflict_result . empty ( ) ) {
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : found slicing result conflict! " < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_GCODE_PATH_CONFLICTS , index + 1 , cli_errors [ CLI_GCODE_PATH_CONFLICTS ] , sliced_info ) ;
flush_and_exit ( CLI_GCODE_PATH_CONFLICTS ) ;
}
//check the warnings
if ( ! g_slicing_warnings . empty ( ) )
{
for ( unsigned int i = 0 ; i < g_slicing_warnings . size ( ) ; i + + )
{
PrintBase : : SlicingStatus & status = g_slicing_warnings [ i ] ;
if ( ( status . warning_step ! = - 1 ) & & ( status . message_type ! = PrintStateBase : : SlicingDefaultNotification ) )
{
sliced_plate_info . warning_message = status . text ;
if ( status . warning_level = = PrintStateBase : : WarningLevel : : NON_CRITICAL ) {
BOOST_LOG_TRIVIAL ( warning ) < < " plate " < < index + 1 < < " : found NON_CRITICAL slicing warnings: " < < status . text < < std : : endl ;
}
else {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " plate %1%: found slicing warnings: %2%, no_check=%3% " ) % ( index + 1 ) % status . text % no_check ;
if ( ! no_check ) {
//only following message will be reported under import mode
if ( status . message_type = = PrintStateBase : : SlicingEmptyGcodeLayers
| | status . message_type = = PrintStateBase : : SlicingGcodeOverlap )
{
sliced_info . sliced_plates . push_back ( sliced_plate_info ) ;
record_exit_reson ( outfile_dir , CLI_SLICING_ERROR , index + 1 , cli_errors [ CLI_SLICING_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_SLICING_ERROR ) ;
}
}
}
}
}
g_slicing_warnings . clear ( ) ;
}
sliced_plate_info . triangle_count = plate_triangle_counts [ index ] ;
2024-09-16 16:07:29 +08:00
//1.9.5
auto cli_generate_thumbnails = [ & partplate_list , & model , & glvolume_collection , & colors_out , & shader ] ( const ThumbnailsParams & params ) - > ThumbnailsList {
ThumbnailsList thumbnails ;
for ( const Vec2d & size : params . sizes ) {
thumbnails . push_back ( ThumbnailData ( ) ) ;
Point isize ( size ) ; // round to ints
ThumbnailData & thumbnail_data = thumbnails . back ( ) ;
switch ( Slic3r : : GUI : : OpenGLManager : : get_framebuffers_type ( ) )
{
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Arb :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: ARB " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer ( thumbnail_data ,
isize . x ( ) , isize . y ( ) , params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho ) ;
break ;
}
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Ext :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: EXT " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer_ext ( thumbnail_data ,
isize . x ( ) , isize . y ( ) , params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho ) ;
break ;
}
default :
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: unknown " ) ;
break ;
}
if ( ! thumbnails . back ( ) . is_valid ( ) )
thumbnails . pop_back ( ) ;
}
return thumbnails ;
} ;
2024-09-03 09:34:33 +08:00
// The outfile is processed by a PlaceholderParser.
//outfile = part_plate->get_tmp_gcode_path();
if ( outfile_dir . empty ( ) ) {
outfile = part_plate - > get_tmp_gcode_path ( ) ;
}
else {
outfile = outfile_dir + " /plate_ " + std : : to_string ( index + 1 ) + " .gcode " ;
part_plate - > set_tmp_gcode_path ( outfile ) ;
}
BOOST_LOG_TRIVIAL ( info ) < < " process finished, will export gcode temporily to " < < outfile < < std : : endl ;
2024-09-16 16:07:29 +08:00
//1.9.5
temp_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
if ( is_qdt_vendor_preset ) {
outfile = print_fff - > export_gcode ( outfile , gcode_result , nullptr ) ;
}
else {
if ( ! opengl_valid )
opengl_valid = init_opengl_and_colors ( model , colors ) ;
outfile = print_fff - > export_gcode ( outfile , gcode_result , cli_generate_thumbnails ) ;
}
slice_time [ TIME_USING_CACHE ] = slice_time [ TIME_USING_CACHE ] + ( ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) - temp_time ) ;
BOOST_LOG_TRIVIAL ( info ) < < " export_gcode finished: time_using_cache update to " < < slice_time [ TIME_USING_CACHE ] < < " secs. " ;
2024-09-03 09:34:33 +08:00
//outfile_final = (dynamic_cast<Print*>(print))->print_statistics().finalize_output_path(outfile);
//m_fff_print->export_gcode(m_temp_output_path, m_gcode_result, [this](const ThumbnailsParams& params) { return this->render_thumbnails(params); });
} /* else {
outfile = sla_print . output_filepath ( outfile ) ;
// We need to finalize the filename beforehand because the export function sets the filename inside the zip metadata
outfile_final = sla_print . print_statistics ( ) . finalize_output_path ( outfile ) ;
sla_archive . export_print ( outfile_final , sla_print ) ;
} */
/*if (outfile != outfile_final) {
if ( Slic3r : : rename_file ( outfile , outfile_final ) ) {
boost : : nowide : : cerr < < " Renaming file " < < outfile < < " to " < < outfile_final < < " failed " < < std : : endl ;
record_exit_reson ( outfile_dir , 1 , index + 1 , cli_errors [ 1 ] , sliced_info ) ;
flush_and_exit ( 1 ) ;
}
outfile = outfile_final ;
} */
// Run the post-processing scripts if defined.
//run_post_process_scripts(outfile, print->full_print_config());
BOOST_LOG_TRIVIAL ( info ) < < " Slicing result exported to " < < outfile < < std : : endl ;
part_plate - > update_slice_result_valid_state ( true ) ;
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 100 , " Slicing finished " } ;
cli_status_callback ( slicing_status ) ;
}
# endif
if ( export_slicedata ) {
BOOST_LOG_TRIVIAL ( info ) < < " plate " < < index + 1 < < " :will export Slicing data to " < < export_slice_data_dir ;
std : : string plate_dir = export_slice_data_dir + " / " + std : : to_string ( index + 1 ) ;
bool with_space = ( get_logging_level ( ) > = 4 ) ? true : false ;
int ret = print - > export_cached_data ( plate_dir , with_space ) ;
if ( ret ) {
BOOST_LOG_TRIVIAL ( error ) < < " plate " < < index + 1 < < " : export Slicing data error, ret= " < < ret ;
export_slicedata_error = true ;
if ( fs : : exists ( plate_dir ) )
fs : : remove_all ( plate_dir ) ;
record_exit_reson ( outfile_dir , ret , index + 1 , cli_errors [ ret ] , sliced_info ) ;
flush_and_exit ( ret ) ;
}
}
2024-09-16 16:07:29 +08:00
//1.9.5
end_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
2024-09-03 09:34:33 +08:00
sliced_plate_info . sliced_time = end_time - start_time ;
2024-09-16 16:07:29 +08:00
//1.9.5
sliced_plate_info . sliced_time_with_cache = slice_time [ TIME_USING_CACHE ] ;
sliced_plate_info . make_perimeters_time = slice_time [ TIME_MAKE_PERIMETERS ] ;
sliced_plate_info . infill_time = slice_time [ TIME_INFILL ] ;
sliced_plate_info . generate_support_material_time = slice_time [ TIME_GENERATE_SUPPORT ] ;
2024-09-03 09:34:33 +08:00
if ( max_slicing_time_per_plate ! = 0 ) {
long long time_cost = end_time - start_time ;
2024-09-16 16:07:29 +08:00
//1.9.5
if ( time_cost > max_slicing_time_per_plate * 1000 ) {
sliced_plate_info . warning_message = ( boost : : format ( " plate %1%'s slice time %2% exceeds the limit %3%, return error. " ) % ( index + 1 ) % time_cost % ( max_slicing_time_per_plate * 1000 ) ) . str ( ) ;
2024-09-03 09:34:33 +08:00
BOOST_LOG_TRIVIAL ( error ) < < sliced_plate_info . warning_message ;
sliced_info . sliced_plates . push_back ( sliced_plate_info ) ;
record_exit_reson ( outfile_dir , CLI_SLICING_TIME_EXCEEDS_LIMIT , index + 1 , cli_errors [ CLI_SLICING_TIME_EXCEEDS_LIMIT ] , sliced_info ) ;
flush_and_exit ( CLI_SLICING_TIME_EXCEEDS_LIMIT ) ;
}
}
sliced_info . sliced_plates . push_back ( sliced_plate_info ) ;
} catch ( const std : : exception & ex ) {
BOOST_LOG_TRIVIAL ( error ) < < " found slicing or export error for partplate " < < index + 1 < < std : : endl ;
boost : : nowide : : cerr < < ex . what ( ) < < std : : endl ;
//continue;
record_exit_reson ( outfile_dir , CLI_SLICING_ERROR , index + 1 , cli_errors [ CLI_SLICING_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_SLICING_ERROR ) ;
}
}
}
if ( pre_check & & ( partplate_list . get_plate_count ( ) > 1 ) )
pre_check = false ;
else
finished = true ;
} //end for partplate
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
int plate_count = ( plate_to_slice = = 0 ) ? partplate_list . get_plate_count ( ) : 1 ;
g_cli_callback_mgr . set_plate_info ( 0 , plate_count ) ;
}
# endif
/*
print . center = ! m_config . has ( " center " )
& & ! m_config . has ( " align_xy " )
& & ! m_config . opt_bool ( " dont_arrange " ) ;
print . set_model ( model ) ;
// start chronometer
typedef std : : chrono : : high_resolution_clock clock_ ;
typedef std : : chrono : : duration < double , std : : ratio < 1 > > second_ ;
std : : chrono : : time_point < clock_ > t0 { clock_ : : now ( ) } ;
const std : : string outfile = this - > output_filepath ( model , IO : : Gcode ) ;
try {
print . export_gcode ( outfile ) ;
} catch ( std : : runtime_error & e ) {
boost : : nowide : : cerr < < e . what ( ) < < std : : endl ;
return 1 ;
}
BOOST_LOG_TRIVIAL ( info ) < < " G-code exported to " < < outfile < < std : : endl ;
// output some statistics
double duration { std : : chrono : : duration_cast < second_ > ( clock_ : : now ( ) - t0 ) . count ( ) } ;
BOOST_LOG_TRIVIAL ( info ) < < std : : fixed < < std : : setprecision ( 0 )
< < " Done. Process took " < < ( duration / 60 ) < < " minutes and "
< < std : : setprecision ( 3 )
< < std : : fmod ( duration , 60.0 ) < < " seconds. " < < std : : endl
< < std : : setprecision ( 2 )
< < " Filament required: " < < print . total_used_filament ( ) < < " mm "
< < " ( " < < print . total_extruded_volume ( ) / 1000 < < " cm3) " < < std : : endl ;
*/
}
} else {
boost : : nowide : : cerr < < " error: option not supported yet: " < < opt_key < < std : : endl ;
record_exit_reson ( outfile_dir , CLI_UNSUPPORTED_OPERATION , 0 , cli_errors [ CLI_UNSUPPORTED_OPERATION ] , sliced_info ) ;
flush_and_exit ( CLI_UNSUPPORTED_OPERATION ) ;
}
}
2024-09-16 16:07:29 +08:00
//1.9.5
global_begin_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
2024-09-03 09:34:33 +08:00
if ( export_to_3mf ) {
//QDS: export as qdt 3mf
std : : vector < ThumbnailData * > thumbnails , no_light_thumbnails , top_thumbnails , pick_thumbnails ;
std : : vector < PlateBBoxData * > plate_bboxes ;
PlateDataPtrs plate_data_list ;
partplate_list . store_to_3mf_structure ( plate_data_list ) ;
if ( sliced_plate = = - 1 ) {
for ( int i = 0 ; i < plate_data_list . size ( ) ; i + + ) {
Slic3r : : GUI : : PartPlate * part_plate = partplate_list . get_plate ( i ) ;
plate_object_count [ i ] = part_plate - > printable_instance_size ( ) ;
}
}
else if ( sliced_plate = = 0 ) {
//slicing all
for ( int i = 0 ; i < plate_data_list . size ( ) ; i + + ) {
if ( skip_useless_pick & & ( plate_object_count [ i ] = = 1 ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " only has 1 object, set plate %1%'s is_label_object_enabled from %2% to false " ) % ( i + 1 ) % ( plate_data_list [ i ] - > is_label_object_enabled ) ;
plate_data_list [ i ] - > is_label_object_enabled = false ;
}
}
}
else {
if ( skip_useless_pick & & ( plate_object_count [ sliced_plate - 1 ] = = 1 ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " only has 1 object, set plate %1%'s is_label_object_enabled from %2% to false " ) % sliced_plate % ( plate_data_list [ sliced_plate - 1 ] - > is_label_object_enabled ) ;
plate_data_list [ sliced_plate - 1 ] - > is_label_object_enabled = false ;
}
}
if ( ! outfile_dir . empty ( ) ) {
export_3mf_file = outfile_dir + " / " + export_3mf_file ;
}
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 94 , " Generate thumbnails " } ;
cli_status_callback ( slicing_status ) ;
}
# endif
bool need_regenerate_thumbnail = oriented_or_arranged | | regenerate_thumbnails ;
bool need_regenerate_no_light_thumbnail = oriented_or_arranged | | regenerate_thumbnails ;
bool need_regenerate_top_thumbnail = oriented_or_arranged | | regenerate_thumbnails ;
bool need_create_thumbnail_group = false , need_create_no_light_group = false , need_create_top_group = false ;
// get type and color for platedata
2024-09-16 16:07:29 +08:00
//1.9.5
//auto* filament_types = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_type"));
//const ConfigOptionStrings* filament_color = dynamic_cast<const ConfigOptionStrings *>(m_print_config.option("filament_colour"));
2024-09-03 09:34:33 +08:00
auto * filament_id = dynamic_cast < const ConfigOptionStrings * > ( m_print_config . option ( " filament_ids " ) ) ;
const ConfigOptionFloats * nozzle_diameter_option = dynamic_cast < const ConfigOptionFloats * > ( m_print_config . option ( " nozzle_diameter " ) ) ;
std : : string nozzle_diameter_str ;
if ( nozzle_diameter_option )
nozzle_diameter_str = nozzle_diameter_option - > serialize ( ) ;
for ( int i = 0 ; i < plate_data_list . size ( ) ; i + + ) {
PlateData * plate_data = plate_data_list [ i ] ;
bool skip_this_plate = ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) ? true : false ;
plate_data - > skipped_objects = plate_skipped_objects [ i ] ;
if ( ! printer_model_id . empty ( ) )
plate_data - > printer_model_id = printer_model_id ;
if ( ! nozzle_diameter_str . empty ( ) )
plate_data - > nozzle_diameters = nozzle_diameter_str ;
for ( auto it = plate_data - > slice_filaments_info . begin ( ) ; it ! = plate_data - > slice_filaments_info . end ( ) ; it + + ) {
std : : string display_filament_type ;
it - > type = m_print_config . get_filament_type ( display_filament_type , it - > id ) ;
it - > color = filament_color ? filament_color - > get_at ( it - > id ) : " #FFFFFF " ;
it - > filament_id = filament_id ? filament_id - > get_at ( it - > id ) : " " ;
}
if ( ! plate_data - > plate_thumbnail . is_valid ( ) ) {
if ( ! oriented_or_arranged & & ! regenerate_thumbnails & & plate_data_src . size ( ) > i )
plate_data - > thumbnail_file = plate_data_src [ i ] - > thumbnail_file ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s thumbnail data is invalid, check the file %2% exist or not " ) % ( i + 1 ) % plate_data - > thumbnail_file ;
if ( plate_data - > thumbnail_file . empty ( ) | | ( ! boost : : filesystem : : exists ( plate_data - > thumbnail_file ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s thumbnail file also not there, need to regenerate " ) % ( i + 1 ) ;
if ( ! skip_this_plate ) {
need_regenerate_thumbnail = true ;
need_create_thumbnail_group = true ;
}
}
else {
if ( regenerate_thumbnails ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s thumbnail file %2% cleared, need to regenerate " ) % ( i + 1 ) % plate_data - > thumbnail_file ;
plate_data - > thumbnail_file . clear ( ) ;
}
else
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s thumbnail file exists, no need to regenerate " ) % ( i + 1 ) ;
}
}
else {
if ( regenerate_thumbnails )
plate_data - > plate_thumbnail . reset ( ) ;
if ( ! skip_this_plate ) {
need_create_thumbnail_group = true ;
}
}
if ( plate_data - > no_light_thumbnail_file . empty ( ) ) {
if ( ! regenerate_thumbnails & & ( plate_data_src . size ( ) > i ) ) {
plate_data - > no_light_thumbnail_file = plate_data_src [ i ] - > no_light_thumbnail_file ;
}
if ( plate_data - > no_light_thumbnail_file . empty ( ) | | ( ! boost : : filesystem : : exists ( plate_data - > no_light_thumbnail_file ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s no_light_thumbnail_file %2% also not there, need to regenerate " ) % ( i + 1 ) % plate_data - > no_light_thumbnail_file ;
if ( ! skip_this_plate ) {
need_regenerate_no_light_thumbnail = true ;
need_create_no_light_group = true ;
}
}
else {
if ( regenerate_thumbnails ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s no_light_thumbnail file %2% cleared, need to regenerate " ) % ( i + 1 ) % plate_data - > no_light_thumbnail_file ;
plate_data - > no_light_thumbnail_file . clear ( ) ;
}
else
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s no_light_thumbnail file exists, no need to regenerate " ) % ( i + 1 ) ;
}
}
if ( plate_data - > top_file . empty ( ) | | plate_data - > pick_file . empty ( ) ) {
if ( ! regenerate_thumbnails & & ( plate_data_src . size ( ) > i ) ) {
plate_data - > top_file = plate_data_src [ i ] - > top_file ;
plate_data - > pick_file = plate_data_src [ i ] - > pick_file ;
}
if ( plate_data - > top_file . empty ( ) | | plate_data - > pick_file . empty ( )
| | ( ! boost : : filesystem : : exists ( plate_data - > top_file ) ) | | ( ! boost : : filesystem : : exists ( plate_data - > pick_file ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s top_file %2% also not there, need to regenerate " ) % ( i + 1 ) % plate_data - > top_file ;
if ( ! skip_this_plate ) {
need_regenerate_top_thumbnail = true ;
need_create_top_group = true ;
}
}
else {
if ( regenerate_thumbnails ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s top_thumbnail file %2% cleared, need to regenerate " ) % ( i + 1 ) % plate_data - > top_file ;
plate_data - > top_file . clear ( ) ;
plate_data - > pick_file . clear ( ) ;
}
else
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " thumbnails stage: plate %1%'s top_thumbnail file exists, no need to regenerate " ) % ( i + 1 ) ;
}
}
}
if ( need_regenerate_thumbnail | | need_regenerate_no_light_thumbnail | | need_regenerate_top_thumbnail ) {
2024-09-16 16:07:29 +08:00
//1.9.5
if ( ! opengl_valid )
opengl_valid = init_opengl_and_colors ( m_models [ 0 ] , colors ) ;
/*std::vector<std::string> colors;
2024-09-03 09:34:33 +08:00
if ( filament_color ) {
colors = filament_color - > vserialize ( ) ;
}
else
colors . push_back ( " #FFFFFFFF " ) ;
std : : vector < std : : array < float , 4 > > colors_out ( colors . size ( ) ) ;
unsigned char rgb_color [ 4 ] = { } ;
for ( const std : : string & color : colors ) {
Slic3r : : GUI : : BitmapCache : : parse_color4 ( color , rgb_color ) ;
size_t color_idx = & color - & colors . front ( ) ;
colors_out [ color_idx ] = { float ( rgb_color [ 0 ] ) / 255.f , float ( rgb_color [ 1 ] ) / 255.f , float ( rgb_color [ 2 ] ) / 255.f , float ( rgb_color [ 3 ] ) / 255.f } ;
}
int gl_major , gl_minor , gl_verbos ;
glfwGetVersion ( & gl_major , & gl_minor , & gl_verbos ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " opengl version %1%.%2%.%3% " ) % gl_major % gl_minor % gl_verbos ;
glfwSetErrorCallback ( glfw_callback ) ;
int ret = glfwInit ( ) ;
if ( ret = = GLFW_FALSE ) {
int code = glfwGetError ( NULL ) ;
BOOST_LOG_TRIVIAL ( error ) < < " glfwInit return error, code " < < code < < std : : endl ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " glfwInit Success. " < < std : : endl ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , gl_major ) ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , gl_minor ) ;
glfwWindowHint ( GLFW_RED_BITS , 8 ) ;
glfwWindowHint ( GLFW_GREEN_BITS , 8 ) ;
glfwWindowHint ( GLFW_BLUE_BITS , 8 ) ;
glfwWindowHint ( GLFW_ALPHA_BITS , 8 ) ;
glfwWindowHint ( GLFW_VISIBLE , false ) ;
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwDisable(GLFW_AUTO_POLL_EVENTS);
# ifdef __WXMAC__
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE ) ;
glfwWindowHint ( GLFW_OPENGL_FORWARD_COMPAT , GL_TRUE ) ;
# else
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_COMPAT_PROFILE ) ;
# endif
# ifdef __linux__
glfwWindowHint ( GLFW_CONTEXT_CREATION_API , GLFW_OSMESA_CONTEXT_API ) ;
# endif
GLFWwindow * window = glfwCreateWindow ( 640 , 480 , " base_window " , NULL , NULL ) ;
if ( window = = NULL )
{
BOOST_LOG_TRIVIAL ( error ) < < " Failed to create GLFW window " < < std : : endl ;
}
else
glfwMakeContextCurrent ( window ) ;
2024-09-16 16:07:29 +08:00
} */
2024-09-03 09:34:33 +08:00
//opengl manager related logic
{
2024-09-16 16:07:29 +08:00
/*Slic3r::GUI::OpenGLManager opengl_mgr;
2024-09-03 09:34:33 +08:00
bool opengl_valid = opengl_mgr . init_gl ( false ) ;
if ( ! opengl_valid ) {
BOOST_LOG_TRIVIAL ( error ) < < " init opengl failed! skip thumbnail generating " < < std : : endl ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < " glewInit Sucess. " < < std : : endl ;
GLVolumeCollection glvolume_collection ;
Model & model = m_models [ 0 ] ;
int obj_extruder_id = 1 , volume_extruder_id = 1 ;
for ( unsigned int obj_idx = 0 ; obj_idx < ( unsigned int ) model . objects . size ( ) ; + + obj_idx ) {
const ModelObject & model_object = * model . objects [ obj_idx ] ;
const ConfigOption * option = model_object . config . option ( " extruder " ) ;
if ( option )
obj_extruder_id = ( dynamic_cast < const ConfigOptionInt * > ( option ) ) - > getInt ( ) ;
else
obj_extruder_id = 1 ;
for ( int volume_idx = 0 ; volume_idx < ( int ) model_object . volumes . size ( ) ; + + volume_idx ) {
const ModelVolume & model_volume = * model_object . volumes [ volume_idx ] ;
option = model_volume . config . option ( " extruder " ) ;
if ( option )
volume_extruder_id = ( dynamic_cast < const ConfigOptionInt * > ( option ) ) - > getInt ( ) ;
else
volume_extruder_id = obj_extruder_id ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " volume %1%'s extruder_id %2% " ) % volume_idx % volume_extruder_id ;
//if (!model_volume.is_model_part())
// continue;
for ( int instance_idx = 0 ; instance_idx < ( int ) model_object . instances . size ( ) ; + + instance_idx ) {
const ModelInstance & model_instance = * model_object . instances [ instance_idx ] ;
glvolume_collection . load_object_volume ( & model_object , obj_idx , volume_idx , instance_idx , " volume " , true , false , true ) ;
//glvolume_collection.volumes.back()->geometry_id = key.geometry_id;
std : : string color = filament_color ? filament_color - > get_at ( volume_extruder_id - 1 ) : " #00FF00FF " ;
BOOST_LOG_TRIVIAL ( debug ) < < boost : : format ( " volume %1%'s color %2% " ) % volume_idx % color ;
unsigned char rgb_color [ 4 ] = { } ;
Slic3r : : GUI : : BitmapCache : : parse_color4 ( color , rgb_color ) ;
std : : array < float , 4 > new_color ;
new_color [ 0 ] = float ( rgb_color [ 0 ] ) / 255.f ;
new_color [ 1 ] = float ( rgb_color [ 1 ] ) / 255.f ;
new_color [ 2 ] = float ( rgb_color [ 2 ] ) / 255.f ;
new_color [ 3 ] = float ( rgb_color [ 3 ] ) / 255.f ;
glvolume_collection . volumes . back ( ) - > set_render_color ( new_color [ 0 ] , new_color [ 1 ] , new_color [ 2 ] , new_color [ 3 ] ) ;
glvolume_collection . volumes . back ( ) - > set_color ( new_color ) ;
glvolume_collection . volumes . back ( ) - > printable = model_instance . printable ;
}
}
}
ThumbnailsParams thumbnail_params ;
GLShaderProgram * shader = opengl_mgr . get_shader ( " thumbnail " ) ;
if ( ! shader ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " can not get shader for rendering thumbnail " ) ;
}
2024-09-16 16:07:29 +08:00
else { */
//1.9.5
if ( opengl_valid ) {
Model & model = m_models [ 0 ] ;
2024-09-03 09:34:33 +08:00
for ( int i = 0 ; i < partplate_list . get_plate_count ( ) ; i + + ) {
Slic3r : : GUI : : PartPlate * part_plate = partplate_list . get_plate ( i ) ;
PlateData * plate_data = plate_data_list [ i ] ;
if ( plate_data - > plate_thumbnail . is_valid ( ) ) {
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, reset plate %2%'s thumbnail. " ) % __LINE__ % ( i + 1 ) ;
plate_data - > plate_thumbnail . reset ( ) ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% has a valid thumbnail, width %2%, height %3%, directly using it " ) % ( i + 1 ) % plate_data - > plate_thumbnail . width % plate_data - > plate_thumbnail . height ;
}
}
else if ( ! plate_data - > thumbnail_file . empty ( ) & & ( boost : : filesystem : : exists ( plate_data - > thumbnail_file ) ) )
{
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, clear plate %2%'s thumbnail file path to empty. " ) % __LINE__ % ( i + 1 ) ;
plate_data - > thumbnail_file . clear ( ) ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% has a valid thumbnail %2% extracted from 3mf, directly using it " ) % ( i + 1 ) % plate_data - > thumbnail_file ;
int dec_ret = decode_png_to_thumbnail ( plate_data - > thumbnail_file , plate_data - > plate_thumbnail ) ;
if ( ! dec_ret )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " decode png to mem sucess. " ) ;
}
else {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " decode png to mem failed. " ) ;
}
}
}
else {
ThumbnailData * thumbnail_data = & plate_data - > plate_thumbnail ;
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, Skip plate %2%. " ) % __LINE__ % ( i + 1 ) ;
}
else {
unsigned int thumbnail_width = 512 , thumbnail_height = 512 ;
const ThumbnailsParams thumbnail_params = { { } , false , true , true , true , i } ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s thumbnail, need to regenerate " ) % ( i + 1 ) ;
switch ( Slic3r : : GUI : : OpenGLManager : : get_framebuffers_type ( ) )
{
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Arb :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: ARB " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer ( * thumbnail_data ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho ) ;
break ;
}
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Ext :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: EXT " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer_ext ( * thumbnail_data ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho ) ;
break ;
}
default :
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: unknown " ) ;
break ;
}
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s thumbnail,finished rendering " ) % ( i + 1 ) ;
}
}
if ( need_create_thumbnail_group ) {
thumbnails . push_back ( & plate_data - > plate_thumbnail ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%: add thumbnail data into group " ) % ( i + 1 ) ;
}
//no light thumbnail
if ( ! plate_data - > no_light_thumbnail_file . empty ( ) & & ( boost : : filesystem : : exists ( plate_data - > no_light_thumbnail_file ) ) )
{
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, clear plate %2%'s no_light_thumbnail_file path to empty. " ) % __LINE__ % ( i + 1 ) ;
plate_data - > no_light_thumbnail_file . clear ( ) ;
}
else
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% has valid no_light_thumbnail_file extracted from 3mf, directly using it " ) % ( i + 1 ) ;
}
else {
ThumbnailData * no_light_thumbnail = & part_plate - > no_light_thumbnail_data ;
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, Skip plate %2%. " ) % __LINE__ % ( i + 1 ) ;
part_plate - > no_light_thumbnail_data . reset ( ) ;
plate_data - > no_light_thumbnail_file . clear ( ) ;
}
else {
unsigned int thumbnail_width = 512 , thumbnail_height = 512 ;
const ThumbnailsParams thumbnail_params = { { } , false , true , false , true , i } ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s no_light_thumbnail_file missed, need to regenerate " ) % ( i + 1 ) ;
switch ( Slic3r : : GUI : : OpenGLManager : : get_framebuffers_type ( ) )
{
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Arb :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: ARB " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer ( * no_light_thumbnail ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho , false , false , true ) ;
break ;
}
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Ext :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: EXT " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer_ext ( * no_light_thumbnail ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho , false , false , true ) ;
break ;
}
default :
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: unknown " ) ;
break ;
}
plate_data - > no_light_thumbnail_file = " valid_no_light " ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s no_light thumbnail,finished rendering " ) % ( i + 1 ) ;
}
}
if ( need_create_no_light_group ) {
no_light_thumbnails . push_back ( & part_plate - > no_light_thumbnail_data ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%: add thumbnail data for no_light into group " ) % ( i + 1 ) ;
}
//top thumbnails
/*if (part_plate->top_thumbnail_data.is_valid() && part_plate->pick_thumbnail_data.is_valid()) {
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, reset plate %2%'s top/pick thumbnail. " ) % __LINE__ % ( i + 1 ) ;
part_plate - > top_thumbnail_data . reset ( ) ;
part_plate - > pick_thumbnail_data . reset ( ) ;
plate_data - > top_file . clear ( ) ;
plate_data - > pick_file . clear ( ) ;
}
else {
plate_data - > top_file = " valid_top " ;
plate_data - > pick_file = " valid_pick " ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% has a valid top/pick thumbnail data, directly using it " ) % ( i + 1 ) ;
}
}
else */
if ( ( ! plate_data - > top_file . empty ( ) & & ( boost : : filesystem : : exists ( plate_data - > top_file ) ) )
& & ( ! plate_data - > pick_file . empty ( ) & & ( boost : : filesystem : : exists ( plate_data - > pick_file ) ) ) )
{
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, clear plate %2%'s top/pick thumbnail file path to empty. " ) % __LINE__ % ( i + 1 ) ;
plate_data - > top_file . clear ( ) ;
plate_data - > pick_file . clear ( ) ;
}
else
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% has valid top/pick thumbnail extracted from 3mf, directly using it " ) % ( i + 1 ) ;
}
else {
ThumbnailData * top_thumbnail = & part_plate - > top_thumbnail_data ;
ThumbnailData * picking_thumbnail = & part_plate - > pick_thumbnail_data ;
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: regenerate thumbnail, Skip plate %2%. " ) % __LINE__ % ( i + 1 ) ;
part_plate - > top_thumbnail_data . reset ( ) ;
part_plate - > pick_thumbnail_data . reset ( ) ;
plate_data - > top_file . clear ( ) ;
plate_data - > pick_file . clear ( ) ;
}
else {
unsigned int thumbnail_width = 512 , thumbnail_height = 512 ;
const ThumbnailsParams thumbnail_params = { { } , false , true , false , true , i } ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s top/pick thumbnail missed, need to regenerate, objects count %2%, skip_useless_pick %3% " ) % ( i + 1 ) % plate_object_count [ i ] % skip_useless_pick ;
if ( skip_useless_pick & & ( ( plate_object_count [ i ] < = 1 ) | | ( plate_object_count [ i ] > 64 ) ) )
{
//don't render pick and top
part_plate - > top_thumbnail_data . reset ( ) ;
part_plate - > pick_thumbnail_data . reset ( ) ;
plate_data - > top_file . clear ( ) ;
plate_data - > pick_file . clear ( ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " skip rendering for top&&pick " ) ;
}
else {
switch ( Slic3r : : GUI : : OpenGLManager : : get_framebuffers_type ( ) )
{
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Arb :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: ARB " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer ( * top_thumbnail ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho , true , false ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer ( * picking_thumbnail ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho , true , true ) ;
break ;
}
case Slic3r : : GUI : : OpenGLManager : : EFramebufferType : : Ext :
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: EXT " ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer_ext ( * top_thumbnail ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho , true , false ) ;
Slic3r : : GUI : : GLCanvas3D : : render_thumbnail_framebuffer_ext ( * picking_thumbnail ,
thumbnail_width , thumbnail_height , thumbnail_params ,
partplate_list , model . objects , glvolume_collection , colors_out , shader , Slic3r : : GUI : : Camera : : EType : : Ortho , true , true ) ;
break ;
}
default :
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " framebuffer_type: unknown " ) ;
break ;
}
plate_data - > top_file = " valid_top " ;
plate_data - > pick_file = " valid_pick " ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s top_thumbnail,finished rendering " ) % ( i + 1 ) ;
}
}
}
if ( need_create_top_group ) {
top_thumbnails . push_back ( & part_plate - > top_thumbnail_data ) ;
pick_thumbnails . push_back ( & part_plate - > pick_thumbnail_data ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%: add thumbnail data for top and pick into group " ) % ( i + 1 ) ;
}
}
}
}
//QDS: release glfw
glfwTerminate ( ) ;
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: use previous thumbnails, no need to regenerate " ) % __LINE__ ;
for ( int i = 0 ; i < partplate_list . get_plate_count ( ) ; i + + ) {
PlateData * plate_data = plate_data_list [ i ] ;
bool skip_this_plate = ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) ? true : false ;
Slic3r : : GUI : : PartPlate * part_plate = partplate_list . get_plate ( i ) ;
if ( skip_this_plate ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%'s all the thumbnails skipped, reset here " ) % ( i + 1 ) ;
plate_data - > plate_thumbnail . reset ( ) ;
plate_data - > thumbnail_file . clear ( ) ;
part_plate - > no_light_thumbnail_data . reset ( ) ;
plate_data - > no_light_thumbnail_file . clear ( ) ;
part_plate - > top_thumbnail_data . reset ( ) ;
part_plate - > pick_thumbnail_data . reset ( ) ;
plate_data - > top_file . clear ( ) ;
plate_data - > pick_file . clear ( ) ;
}
else if ( ! plate_data - > plate_thumbnail . is_valid ( ) & & ! plate_data - > thumbnail_file . empty ( ) & & ( boost : : filesystem : : exists ( plate_data - > thumbnail_file ) ) )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " no need to generate: plate %1% has a valid thumbnail %2% extracted from 3mf, convert to data " ) % ( i + 1 ) % plate_data - > thumbnail_file ;
int dec_ret = decode_png_to_thumbnail ( plate_data - > thumbnail_file , plate_data - > plate_thumbnail ) ;
if ( ! dec_ret )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " decode png to mem sucess. " ) ;
need_create_thumbnail_group = true ;
}
else {
BOOST_LOG_TRIVIAL ( warning ) < < boost : : format ( " decode png to mem failed. " ) ;
}
}
}
for ( int i = 0 ; i < partplate_list . get_plate_count ( ) ; i + + ) {
PlateData * plate_data = plate_data_list [ i ] ;
Slic3r : : GUI : : PartPlate * part_plate = partplate_list . get_plate ( i ) ;
if ( need_create_thumbnail_group ) {
thumbnails . push_back ( & plate_data - > plate_thumbnail ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%: add thumbnail data into group " ) % ( i + 1 ) ;
}
if ( need_create_no_light_group ) {
no_light_thumbnails . push_back ( & part_plate - > no_light_thumbnail_data ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%: add thumbnail data into group " ) % ( i + 1 ) ;
}
if ( need_create_top_group ) {
top_thumbnails . push_back ( & part_plate - > top_thumbnail_data ) ;
pick_thumbnails . push_back ( & part_plate - > pick_thumbnail_data ) ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1%: add thumbnail data for top and pick into group " ) % ( i + 1 ) ;
}
}
}
//generate first layer bboxes
for ( int i = 0 ; i < partplate_list . get_plate_count ( ) ; i + + ) {
if ( ( plate_to_slice ! = 0 ) & & ( plate_to_slice ! = ( i + 1 ) ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " Line %1%: generate bbox, Skip plate %2%. " ) % __LINE__ % ( i + 1 ) ;
plate_bboxes . push_back ( new PlateBBoxData ( ) ) ;
continue ;
}
Slic3r : : GUI : : PartPlate * part_plate = partplate_list . get_plate ( i ) ;
//render calibration thumbnail
if ( ! part_plate - > get_slice_result ( ) | | ! part_plate - > is_slice_result_valid ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% doesn't have a valid sliced result, skip it " ) % ( i + 1 ) ;
//calibration_thumbnails.push_back(new ThumbnailData());
plate_bboxes . push_back ( new PlateBBoxData ( ) ) ;
continue ;
}
PrintBase * print_base = NULL ;
Slic3r : : GUI : : GCodeResult * gcode_result = NULL ;
int print_index ;
part_plate - > get_print ( & print_base , & gcode_result , & print_index ) ;
Print * print = dynamic_cast < Print * > ( print_base ) ;
//don't render calibration picture
/*BuildVolume build_volume(part_plate->get_shape(), print_height);
const std : : vector < BoundingBoxf3 > & exclude_bounding_box = part_plate - > get_exclude_areas ( ) ;
Slic3r : : GUI : : GCodeViewer gcode_viewer ;
gcode_viewer . init ( ConfigOptionMode : : comAdvanced , nullptr ) ;
gcode_viewer . load ( * gcode_result , * print , build_volume , exclude_bounding_box , false , ConfigOptionMode : : comAdvanced , false ) ;
std : : vector < std : : string > colors ;
if ( filament_color )
colors = filament_color - > values ;
gcode_viewer . refresh ( * gcode_result , colors ) ;
ThumbnailData * calibration_data = new ThumbnailData ( ) ;
const ThumbnailsParams calibration_params = { { } , false , true , true , true , i } ;
//QDS fixed size
const int cali_thumbnail_width = 2560 ;
const int cali_thumbnail_height = 2560 ;
gcode_viewer . render_calibration_thumbnail ( * calibration_data , cali_thumbnail_width , cali_thumbnail_height ,
calibration_params , partplate_list , opengl_mgr ) ;
//generate_calibration_thumbnail(*calibration_data, thumbnail_width, thumbnail_height, calibration_params);
//*plate_bboxes[index] = p->generate_first_layer_bbox();
calibration_thumbnails . push_back ( calibration_data ) ; */
PlateBBoxData * plate_bbox = new PlateBBoxData ( ) ;
std : : vector < BBoxData > & id_bboxes = plate_bbox - > bbox_objs ;
BoundingBoxf bbox_all ;
PrintSequence curr_plate_seq = part_plate - > get_print_seq ( ) ;
if ( curr_plate_seq = = PrintSequence : : ByDefault ) {
auto seq_print = m_print_config . option < ConfigOptionEnum < PrintSequence > > ( " print_sequence " ) ;
if ( seq_print & & ( seq_print - > value = = PrintSequence : : ByObject ) ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% print by object, set from global " ) % ( i + 1 ) ;
plate_bbox - > is_seq_print = true ;
}
}
else if ( curr_plate_seq = = PrintSequence : : ByObject ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% print by object, set from plate self " ) % ( i + 1 ) ;
plate_bbox - > is_seq_print = true ;
}
plate_bbox - > first_extruder = print - > get_tool_ordering ( ) . first_extruder ( ) ;
//bed type;
BedType plate_bed_type = part_plate - > get_bed_type ( ) ;
if ( plate_bed_type = = btDefault ) {
auto cur_bed_type = m_print_config . option < ConfigOptionEnum < BedType > > ( " curr_bed_type " ) ;
if ( cur_bed_type ) {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% bed type: %2%, set from global " ) % ( i + 1 ) % cur_bed_type - > serialize ( ) ;
plate_bbox - > bed_type = bed_type_to_gcode_string ( cur_bed_type - > value ) ;
}
}
else {
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " plate %1% bed type: %2%, set from plate self " ) % ( i + 1 ) % plate_bed_type ;
plate_bbox - > bed_type = bed_type_to_gcode_string ( plate_bed_type ) ;
}
// get nozzle diameter
auto opt_nozzle_diameters = m_print_config . option < ConfigOptionFloats > ( " nozzle_diameter " ) ;
if ( opt_nozzle_diameters ! = nullptr )
plate_bbox - > nozzle_diameter = float ( opt_nozzle_diameters - > get_at ( plate_bbox - > first_extruder ) ) ;
auto objects = print - > objects ( ) ;
auto orig = part_plate - > get_origin ( ) ;
Vec2d orig2d = { orig [ 0 ] , orig [ 1 ] } ;
for ( auto obj : objects )
{
BBoxData data ;
auto bb_scaled = obj - > get_first_layer_bbox ( data . area , data . layer_height , data . name ) ;
auto bb = unscaled ( bb_scaled ) ;
bbox_all . merge ( bb ) ;
data . area * = ( SCALING_FACTOR * SCALING_FACTOR ) ; // unscale area
data . id = obj - > id ( ) . id ;
data . bbox = { bb . min . x ( ) , bb . min . y ( ) , bb . max . x ( ) , bb . max . y ( ) } ;
id_bboxes . emplace_back ( std : : move ( data ) ) ;
}
// add wipe tower bounding box
if ( print - > has_wipe_tower ( ) ) {
BBoxData data ;
auto wt_corners = print - > first_layer_wipe_tower_corners ( ) ;
// when loading gcode.3mf, wipe tower info may not be correct
if ( ! wt_corners . empty ( ) ) {
BoundingBox bb_scaled = { wt_corners [ 0 ] , wt_corners [ 2 ] } ;
auto bb = unscaled ( bb_scaled ) ;
bb . min - = orig2d ;
bb . max - = orig2d ;
bbox_all . merge ( bb ) ;
data . name = " wipe_tower " ;
data . id = partplate_list . get_curr_plate ( ) - > get_index ( ) + 1000 ;
data . bbox = { bb . min . x ( ) , bb . min . y ( ) , bb . max . x ( ) , bb . max . y ( ) } ;
id_bboxes . emplace_back ( std : : move ( data ) ) ;
}
}
plate_bbox - > bbox_all = { bbox_all . min . x ( ) , bbox_all . min . y ( ) , bbox_all . max . x ( ) , bbox_all . max . y ( ) } ;
PlateData * plate_data = plate_data_list [ i ] ;
for ( auto it = plate_data - > slice_filaments_info . begin ( ) ; it ! = plate_data - > slice_filaments_info . end ( ) ; it + + ) {
plate_bbox - > filament_ids . push_back ( it - > id ) ;
plate_bbox - > filament_colors . push_back ( it - > color ) ;
}
plate_bboxes . push_back ( plate_bbox ) ;
}
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 97 , " Exporting 3mf " } ;
cli_status_callback ( slicing_status ) ;
}
# endif
BOOST_LOG_TRIVIAL ( info ) < < " will export 3mf to " < < export_3mf_file < < std : : endl ;
if ( ! makerlab_name . empty ( ) ) {
Model & model = m_models [ 0 ] ;
model . mk_name = makerlab_name ;
model . mk_version = makerlab_version ;
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " mk_name %1%, mk_version %2% " ) % makerlab_name % makerlab_version ;
}
if ( ! metadata_name . empty ( ) ) {
Model & model = m_models [ 0 ] ;
model . md_value = metadata_value ;
model . md_name = metadata_name ;
for ( unsigned int i = 0 ; i < metadata_name . size ( ) ; i + + )
{
BOOST_LOG_TRIVIAL ( info ) < < boost : : format ( " index %1% metadata_name %2%, metadata_value %3% " ) % i % metadata_name [ i ] % metadata_value [ i ] ;
}
}
if ( ! this - > export_project ( & m_models [ 0 ] , export_3mf_file , plate_data_list , project_presets , thumbnails , no_light_thumbnails , top_thumbnails , pick_thumbnails ,
calibration_thumbnails , plate_bboxes , & m_print_config , minimum_save , plate_to_slice - 1 ) )
{
release_PlateData_list ( plate_data_list ) ;
record_exit_reson ( outfile_dir , CLI_EXPORT_3MF_ERROR , 0 , cli_errors [ CLI_EXPORT_3MF_ERROR ] , sliced_info ) ;
flush_and_exit ( CLI_EXPORT_3MF_ERROR ) ;
}
for ( unsigned int i = 0 ; i < thumbnails . size ( ) ; i + + )
thumbnails [ i ] - > reset ( ) ;
for ( unsigned int i = 0 ; i < no_light_thumbnails . size ( ) ; i + + )
no_light_thumbnails [ i ] - > reset ( ) ;
for ( unsigned int i = 0 ; i < top_thumbnails . size ( ) ; i + + )
top_thumbnails [ i ] - > reset ( ) ;
for ( unsigned int i = 0 ; i < pick_thumbnails . size ( ) ; i + + )
pick_thumbnails [ i ] - > reset ( ) ;
release_PlateData_list ( plate_data_list ) ;
for ( unsigned int i = 0 ; i < calibration_thumbnails . size ( ) ; i + + )
delete calibration_thumbnails [ i ] ;
for ( int i = 0 ; i < plate_bboxes . size ( ) ; i + + )
delete plate_bboxes [ i ] ;
}
if ( plate_data_src . size ( ) > 0 )
{
release_PlateData_list ( plate_data_src ) ;
}
# if defined(__linux__) || defined(__LINUX__)
if ( g_cli_callback_mgr . is_started ( ) ) {
PrintBase : : SlicingStatus slicing_status { 100 , " All done, Success " } ;
cli_status_callback ( slicing_status ) ;
}
g_cli_callback_mgr . stop ( ) ;
# endif
for ( Model & model : m_models ) {
model . remove_backup_path_if_exist ( ) ;
}
//QDS: flush logs
BOOST_LOG_TRIVIAL ( info ) < < __FUNCTION__ < < " , Finished " < < std : : endl ;
2024-09-16 16:07:29 +08:00
//1.9.5
global_current_time = ( long long ) Slic3r : : Utils : : get_current_milliseconds_time_utc ( ) ;
2024-09-03 09:34:33 +08:00
sliced_info . export_time = ( size_t ) ( global_current_time - global_begin_time ) ;
//record the duplicate here
if ( duplicate_count > 0 )
{
record_key_values [ " sliced_count " ] = std : : to_string ( duplicate_count + 1 ) ;
record_exit_reson ( outfile_dir , 0 , plate_to_slice , cli_errors [ 0 ] , sliced_info , record_key_values ) ;
}
else {
record_exit_reson ( outfile_dir , 0 , plate_to_slice , cli_errors [ 0 ] , sliced_info ) ;
}
boost : : nowide : : cout . flush ( ) ;
boost : : nowide : : cerr . flush ( ) ;
return 0 ;
}
bool CLI : : setup ( int argc , char * * argv )
{
// Detect the operating system flavor after SLIC3R_LOGLEVEL is set.
detect_platform ( ) ;
# ifdef WIN32
// Notify user that a blacklisted DLL was injected into QIDIStudio process (for example Nahimic, see GH #5573).
// We hope that if a DLL is being injected into a QIDIStudio process, it happens at the very start of the application,
// thus we shall detect them now.
if ( BlacklistedLibraryCheck : : get_instance ( ) . perform_check ( ) ) {
std : : wstring text = L " Following DLLs have been injected into the QIDIStudio process: \n \n " ;
text + = BlacklistedLibraryCheck : : get_instance ( ) . get_blacklisted_string ( ) ;
text + = L " \n \n "
L " QIDIStudio is known to not run correctly with these DLLs injected. "
L " We suggest stopping or uninstalling these services if you experience "
L " crashes or unexpected behaviour while using QIDIStudio. \n "
L " For example, ASUS Sonic Studio injects a Nahimic driver, which makes QIDIStudio "
L " to crash on a secondary monitor " ;
MessageBoxW ( NULL , text . c_str ( ) , L " Warning " /*L"Incopatible library found"*/ , MB_OK ) ;
}
# endif
// See Invoking prusa-slicer from $PATH environment variable crashes #5542
// boost::filesystem::path path_to_binary = boost::filesystem::system_complete(argv[0]);
boost : : filesystem : : path path_to_binary = boost : : dll : : program_location ( ) ;
// Path from the Slic3r binary to its resources.
# ifdef __APPLE__
// The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r'
// The resources are packed to 'Slic3r.app/Contents/Resources'
boost : : filesystem : : path path_resources = boost : : filesystem : : canonical ( path_to_binary ) . parent_path ( ) . parent_path ( ) / " Resources " ;
# elif defined _WIN32
// The application is packed in the .zip archive in the root,
// The resources are packed to 'resources'
// Path from Slic3r binary to resources:
boost : : filesystem : : path path_resources = path_to_binary . parent_path ( ) / " resources " ;
# elif defined SLIC3R_FHS
// The application is packaged according to the Linux Filesystem Hierarchy Standard
// Resources are set to the 'Architecture-independent (shared) data', typically /usr/share or /usr/local/share
boost : : filesystem : : path path_resources = SLIC3R_FHS_RESOURCES ;
# else
// The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r',
// The resources are packed to 'resources'
// Path from Slic3r binary to resources:
boost : : filesystem : : path path_resources = boost : : filesystem : : canonical ( path_to_binary ) . parent_path ( ) . parent_path ( ) / " resources " ;
# endif
set_resources_dir ( path_resources . string ( ) ) ;
set_var_dir ( ( path_resources / " images " ) . string ( ) ) ;
set_local_dir ( ( path_resources / " i18n " ) . string ( ) ) ;
set_sys_shapes_dir ( ( path_resources / " shapes " ) . string ( ) ) ;
// Parse all command line options into a DynamicConfig.
// If any option is unsupported, print usage and abort immediately.
t_config_option_keys opt_order ;
if ( ! m_config . read_cli ( argc , argv , & m_input_files , & opt_order ) ) {
// Separate error message reported by the CLI parser from the help.
boost : : nowide : : cerr < < std : : endl ;
this - > print_help ( ) ;
return false ;
}
// Parse actions and transform options.
for ( auto const & opt_key : opt_order ) {
if ( cli_actions_config_def . has ( opt_key ) )
m_actions . emplace_back ( opt_key ) ;
else if ( cli_transform_config_def . has ( opt_key ) )
m_transforms . emplace_back ( opt_key ) ;
}
//FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet.
std : : map < std : : string , std : : string > validity = m_config . validate ( true ) ;
// Initialize with defaults.
for ( const t_optiondef_map * options : { & cli_actions_config_def . options , & cli_transform_config_def . options , & cli_misc_config_def . options } )
for ( const t_optiondef_map : : value_type & optdef : * options )
m_config . option ( optdef . first , true ) ;
//set_data_dir(m_config.opt_string("datadir"));
//FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet.
if ( ! validity . empty ( ) ) {
boost : : nowide : : cerr < < " Params in command line error: " < < std : : endl ;
for ( std : : map < std : : string , std : : string > : : iterator it = validity . begin ( ) ; it ! = validity . end ( ) ; + + it )
boost : : nowide : : cerr < < it - > first < < " : " < < it - > second < < std : : endl ;
return false ;
}
return true ;
}
void CLI : : print_help ( bool include_print_options , PrinterTechnology printer_technology ) const
{
boost : : nowide : : cout
< < SLIC3R_APP_KEY < < " - " < < SLIC3R_VERSION < < " : "
< < std : : endl
< < " Usage: qidi-studio [ OPTIONS ] [ file.3mf/file.stl ... ] " < < std : : endl
< < std : : endl
< < " OPTIONS: " < < std : : endl ;
cli_misc_config_def . print_cli_help ( boost : : nowide : : cout , false ) ;
cli_transform_config_def . print_cli_help ( boost : : nowide : : cout , false ) ;
cli_actions_config_def . print_cli_help ( boost : : nowide : : cout , false ) ;
boost : : nowide : : cout
< < std : : endl
< < " Print settings priorites: " < < std : : endl
< < " \t 1) setting values from the command line (highest priority) " < < std : : endl
< < " \t 2) setting values loaded with --load_settings and --load_filaments " < < std : : endl
< < " \t 3) setting values loaded from 3mf(lowest priority) " < < std : : endl ;
/*if (include_print_options) {
boost : : nowide : : cout < < std : : endl ;
print_config_def . print_cli_help ( boost : : nowide : : cout , true , [ printer_technology ] ( const ConfigOptionDef & def )
{ return printer_technology = = ptAny | | def . printer_technology = = ptAny | | printer_technology = = def . printer_technology ; } ) ;
} else {
boost : : nowide : : cout
< < std : : endl
< < " Run --help-fff / --help-sla to see the full listing of print options. " < < std : : endl ;
} */
}
bool CLI : : export_models ( IO : : ExportFormat format , std : : string path_dir )
{
for ( Model & model : m_models ) {
const std : : string path = this - > output_filepath ( model , format ) ;
bool success = true ;
switch ( format ) {
//case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr, false); break;
case IO : : OBJ :
success = Slic3r : : store_obj ( path . c_str ( ) , & model ) ;
if ( success )
BOOST_LOG_TRIVIAL ( info ) < < " Model successfully exported to " < < path < < std : : endl ;
else {
boost : : nowide : : cerr < < " Model export to " < < path < < " failed " < < std : : endl ;
return false ;
}
break ;
case IO : : STL :
{
unsigned int index = 1 ;
for ( ModelObject * model_object : model . objects )
{
const std : : string path = this - > output_filepath ( * model_object , index + + , format , path_dir ) ;
success = Slic3r : : store_stl ( path . c_str ( ) , model_object , true ) ;
if ( success )
BOOST_LOG_TRIVIAL ( info ) < < " Model successfully exported to " < < path < < std : : endl ;
else {
boost : : nowide : : cerr < < " Model export to " < < path < < " failed " < < std : : endl ;
return false ;
}
}
break ;
}
//QDS: use qds 3mf instead of original
//case IO::TMF: success = Slic3r::store_qds_3mf(path.c_str(), &model, nullptr, false); break;
default : assert ( false ) ; break ;
}
}
return true ;
}
//QDS: add export_project function
bool CLI : : export_project ( Model * model , std : : string & path , PlateDataPtrs & partplate_data ,
std : : vector < Preset * > & project_presets ,
std : : vector < ThumbnailData * > & thumbnails ,
std : : vector < ThumbnailData * > & no_light_thumbnails ,
std : : vector < ThumbnailData * > & top_thumbnails ,
std : : vector < ThumbnailData * > & pick_thumbnails ,
std : : vector < ThumbnailData * > & calibration_thumbnails , std : : vector < PlateBBoxData * > & plate_bboxes , const DynamicPrintConfig * config , bool minimum_save , int plate_to_export )
{
//const std::string path = this->output_filepath(*model, IO::TMF);
bool success = false ;
StoreParams store_params ;
store_params . path = path . c_str ( ) ;
store_params . model = model ;
store_params . plate_data_list = partplate_data ;
store_params . project_presets = project_presets ;
store_params . config = ( DynamicPrintConfig * ) config ;
store_params . thumbnail_data = thumbnails ;
store_params . no_light_thumbnail_data = no_light_thumbnails ;
store_params . top_thumbnail_data = top_thumbnails ;
store_params . pick_thumbnail_data = pick_thumbnails ;
store_params . calibration_thumbnail_data = calibration_thumbnails ;
store_params . id_bboxes = plate_bboxes ;
store_params . strategy = SaveStrategy : : Silence | SaveStrategy : : WithGcode | SaveStrategy : : SplitModel | SaveStrategy : : UseLoadedId | SaveStrategy : : ShareMesh ;
store_params . export_plate_idx = plate_to_export ;
if ( minimum_save )
store_params . strategy = store_params . strategy | SaveStrategy : : SkipModel ;
success = Slic3r : : store_qds_3mf ( store_params ) ;
if ( success )
BOOST_LOG_TRIVIAL ( info ) < < " Project exported to " < < path < < std : : endl ;
else {
boost : : nowide : : cerr < < " Project export to " < < path < < " failed " < < std : : endl ;
return false ;
}
return true ;
}
std : : string CLI : : output_filepath ( const Model & model , IO : : ExportFormat format ) const
{
std : : string ext ;
switch ( format ) {
case IO : : AMF : ext = " .zip.amf " ; break ;
case IO : : OBJ : ext = " .obj " ; break ;
case IO : : STL : ext = " .stl " ; break ;
case IO : : TMF : ext = " .3mf " ; break ;
default : assert ( false ) ; break ;
} ;
auto proposed_path = boost : : filesystem : : path ( model . propose_export_file_name_and_path ( ext ) ) ;
// use --output when available
std : : string cmdline_param = m_config . opt_string ( " outputdir " ) ;
if ( ! cmdline_param . empty ( ) ) {
// if we were supplied a directory, use it and append our automatically generated filename
boost : : filesystem : : path cmdline_path ( cmdline_param ) ;
if ( boost : : filesystem : : is_directory ( cmdline_path ) )
proposed_path = cmdline_path / proposed_path . filename ( ) ;
else
proposed_path = cmdline_param + ext ;
}
return proposed_path . string ( ) ;
}
std : : string CLI : : output_filepath ( const ModelObject & object , unsigned int index , IO : : ExportFormat format , std : : string path_dir ) const
{
std : : string ext , subdir , file_name , output_path ;
switch ( format ) {
case IO : : AMF :
ext = " .zip.amf " ;
subdir = " amf " ;
break ;
case IO : : OBJ :
ext = " .obj " ;
subdir = " obj " ;
break ;
case IO : : STL :
ext = " .stl " ;
subdir = " stl " ;
break ;
case IO : : TMF :
ext = " .3mf " ;
subdir = " 3mf " ;
break ;
default : assert ( false ) ; break ;
} ;
// use --outputdir when available
file_name = object . name . empty ( ) ? object . input_file : object . name ;
file_name = " obj_ " + std : : to_string ( index ) + " _ " + file_name ;
size_t pos = file_name . find_last_of ( ext ) , ext_pos = file_name . size ( ) - 1 ;
if ( pos ! = ext_pos )
file_name + = ext ;
BOOST_LOG_TRIVIAL ( trace ) < < __FUNCTION__ < < " : dir = " < < path_dir < < " , file_name= " < < file_name < < " , pos = " < < pos < < " , ext_pos= " < < ext_pos ;
if ( path_dir . empty ( ) ) {
std : : string cmdline_param = m_config . opt_string ( " outputdir " ) ;
if ( ! cmdline_param . empty ( ) ) {
subdir = cmdline_param + " / " + subdir ;
}
}
else {
subdir = path_dir ;
}
output_path = subdir + " / " + file_name ;
boost : : filesystem : : path subdir_path ( subdir ) ;
if ( ! boost : : filesystem : : exists ( subdir_path ) )
boost : : filesystem : : create_directory ( subdir_path ) ;
return output_path ;
}
//QDS: dump stack debug codes, don't delete currently
//#include <dbghelp.h>
//#pragma comment(lib, "version.lib")
//#pragma comment( lib, "dbghelp.lib" )
/*DWORD main_thread_id;
std : : string TraceStack ( )
{
static const int MAX_STACK_FRAMES = 16 ;
void * pStack [ MAX_STACK_FRAMES ] ;
HANDLE process = GetCurrentProcess ( ) ;
SymInitialize ( process , NULL , TRUE ) ;
WORD frames = CaptureStackBackTrace ( 0 , MAX_STACK_FRAMES , pStack , NULL ) ;
std : : ostringstream oss ;
oss < < " stack traceback: frames= " < < frames < < std : : endl ;
for ( WORD i = 0 ; i < frames ; + + i ) {
DWORD64 address = ( DWORD64 ) ( pStack [ i ] ) ;
DWORD64 displacementSym = 0 ;
char buffer [ sizeof ( SYMBOL_INFO ) + MAX_SYM_NAME * sizeof ( TCHAR ) ] ;
PSYMBOL_INFO pSymbol = ( PSYMBOL_INFO ) buffer ;
pSymbol - > SizeOfStruct = sizeof ( SYMBOL_INFO ) ;
pSymbol - > MaxNameLen = MAX_SYM_NAME ;
DWORD displacementLine = 0 ;
IMAGEHLP_LINE64 line ;
//SymSetOptions(SYMOPT_LOAD_LINES);
line . SizeOfStruct = sizeof ( IMAGEHLP_LINE64 ) ;
if ( SymFromAddr ( process , address , & displacementSym , pSymbol )
& & SymGetLineFromAddr64 ( process , address , & displacementLine , & line ) ) {
oss < < " \t " < < pSymbol - > Name < < " at " < < line . FileName < < " : " < < line . LineNumber < < " (0x " < < std : : hex < < pSymbol - > Address < < std : : dec < < " ) " < < std : : endl ;
}
else {
oss < < " \t error: " < < GetLastError ( ) < < std : : endl ;
}
}
return oss . str ( ) ;
}
LONG WINAPI VectoredExceptionHandler ( PEXCEPTION_POINTERS pExceptionInfo )
{
std : : ofstream f ;
DWORD cur_thread_id = GetCurrentThreadId ( ) ;
f . open ( " VectoredExceptionHandler.txt " , std : : ios : : out | std : : ios : : app ) ;
f < < " main thread id= " < < main_thread_id < < " , current thread_id= " < < cur_thread_id < < std : : endl ;
f < < std : : hex < < pExceptionInfo - > ExceptionRecord - > ExceptionCode < < std : : endl ;
f < < TraceStack ( ) ;
f . flush ( ) ;
f . close ( ) ;
return EXCEPTION_CONTINUE_SEARCH ;
} */
# if defined(_MSC_VER) || defined(__MINGW32__)
extern " C " {
__declspec ( dllexport ) int __stdcall qidistu_main ( int argc , wchar_t * * argv )
{
// Convert wchar_t arguments to UTF8.
std : : vector < std : : string > argv_narrow ;
std : : vector < char * > argv_ptrs ( argc + 1 , nullptr ) ;
for ( size_t i = 0 ; i < argc ; + + i )
argv_narrow . emplace_back ( boost : : nowide : : narrow ( argv [ i ] ) ) ;
for ( size_t i = 0 ; i < argc ; + + i )
argv_ptrs [ i ] = argv_narrow [ i ] . data ( ) ;
//QDS: register default exception handler
# if QDT_RELEASE_TO_PUBLIC
SET_DEFULTER_HANDLER ( ) ;
# else
//AddVectoredExceptionHandler(1, CBaseException::UnhandledExceptionFilter);
SET_DEFULTER_HANDLER ( ) ;
# endif
std : : set_new_handler ( [ ] ( ) {
int * a = nullptr ;
* a = 0 ;
} ) ;
// Call the UTF8 main.
return CLI ( ) . run ( argc , argv_ptrs . data ( ) ) ;
}
}
# else /* _MSC_VER */
int main ( int argc , char * * argv )
{
return CLI ( ) . run ( argc , argv ) ;
}
# endif /* _MSC_VER */