Merge remote-tracking branch 'origin/master' into ys_search
This commit is contained in:
commit
5f31d9ed41
@ -8,7 +8,7 @@ const float EPSILON = 0.0001;
|
|||||||
|
|
||||||
struct SlopeDetection
|
struct SlopeDetection
|
||||||
{
|
{
|
||||||
bool active;
|
bool actived;
|
||||||
// x = yellow, y = red
|
// x = yellow, y = red
|
||||||
vec2 z_range;
|
vec2 z_range;
|
||||||
mat3 volume_world_normal_matrix;
|
mat3 volume_world_normal_matrix;
|
||||||
@ -37,7 +37,7 @@ void main()
|
|||||||
{
|
{
|
||||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||||
discard;
|
discard;
|
||||||
vec3 color = slope.active ? slope_color() : uniform_color.rgb;
|
vec3 color = slope.actived ? slope_color() : uniform_color.rgb;
|
||||||
// if the fragment is outside the print volume -> use darker color
|
// if the fragment is outside the print volume -> use darker color
|
||||||
color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
|
color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
|
||||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a);
|
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a);
|
||||||
|
@ -20,7 +20,7 @@ const vec3 ZERO = vec3(0.0, 0.0, 0.0);
|
|||||||
|
|
||||||
struct PrintBoxDetection
|
struct PrintBoxDetection
|
||||||
{
|
{
|
||||||
bool active;
|
bool actived;
|
||||||
vec3 min;
|
vec3 min;
|
||||||
vec3 max;
|
vec3 max;
|
||||||
mat4 volume_world_matrix;
|
mat4 volume_world_matrix;
|
||||||
@ -28,7 +28,7 @@ struct PrintBoxDetection
|
|||||||
|
|
||||||
struct SlopeDetection
|
struct SlopeDetection
|
||||||
{
|
{
|
||||||
bool active;
|
bool actived;
|
||||||
// x = yellow, y = red
|
// x = yellow, y = red
|
||||||
vec2 z_range;
|
vec2 z_range;
|
||||||
mat3 volume_world_normal_matrix;
|
mat3 volume_world_normal_matrix;
|
||||||
@ -72,7 +72,7 @@ void main()
|
|||||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||||
|
|
||||||
// compute deltas for out of print volume detection (world coordinates)
|
// compute deltas for out of print volume detection (world coordinates)
|
||||||
if (print_box.active)
|
if (print_box.actived)
|
||||||
{
|
{
|
||||||
vec3 v = (print_box.volume_world_matrix * gl_Vertex).xyz;
|
vec3 v = (print_box.volume_world_matrix * gl_Vertex).xyz;
|
||||||
delta_box_min = v - print_box.min;
|
delta_box_min = v - print_box.min;
|
||||||
@ -85,7 +85,7 @@ void main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// z component of normal vector in world coordinate used for slope shading
|
// z component of normal vector in world coordinate used for slope shading
|
||||||
world_normal_z = slope.active ? (normalize(slope.volume_world_normal_matrix * gl_Normal)).z : 0.0;
|
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * gl_Normal)).z : 0.0;
|
||||||
|
|
||||||
gl_Position = ftransform();
|
gl_Position = ftransform();
|
||||||
// Point in homogenous coordinates.
|
// Point in homogenous coordinates.
|
||||||
|
@ -64,6 +64,7 @@ add_library(libslic3r STATIC
|
|||||||
Fill/FillRectilinear3.hpp
|
Fill/FillRectilinear3.hpp
|
||||||
Flow.cpp
|
Flow.cpp
|
||||||
Flow.hpp
|
Flow.hpp
|
||||||
|
format.hpp
|
||||||
Format/3mf.cpp
|
Format/3mf.cpp
|
||||||
Format/3mf.hpp
|
Format/3mf.hpp
|
||||||
Format/AMF.cpp
|
Format/AMF.cpp
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Config.hpp"
|
#include "Config.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -464,7 +465,7 @@ bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src,
|
|||||||
void ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
|
void ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
|
||||||
{
|
{
|
||||||
if (! this->set_deserialize_nothrow(opt_key_src, value_src, append))
|
if (! this->set_deserialize_nothrow(opt_key_src, value_src, append))
|
||||||
throw BadOptionTypeException((boost::format("ConfigBase::set_deserialize() failed for parameter \"%1%\", value \"%2%\"") % opt_key_src % value_src).str());
|
throw BadOptionTypeException(format("ConfigBase::set_deserialize() failed for parameter \"%1%\", value \"%2%\"", opt_key_src, value_src));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigBase::set_deserialize(std::initializer_list<SetDeserializeItem> items)
|
void ConfigBase::set_deserialize(std::initializer_list<SetDeserializeItem> items)
|
||||||
@ -620,7 +621,7 @@ void ConfigBase::load_from_gcode_file(const std::string &file)
|
|||||||
|
|
||||||
size_t key_value_pairs = load_from_gcode_string(data.data());
|
size_t key_value_pairs = load_from_gcode_string(data.data());
|
||||||
if (key_value_pairs < 80)
|
if (key_value_pairs < 80)
|
||||||
throw std::runtime_error((boost::format("Suspiciously low number of configuration values extracted from %1%: %2%") % file % key_value_pairs).str());
|
throw std::runtime_error(format("Suspiciously low number of configuration values extracted from %1%: %2%", file, key_value_pairs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the config keys from the given string.
|
// Load the config keys from the given string.
|
||||||
|
@ -18,7 +18,7 @@ static const float INCHES_TO_MM = 25.4f;
|
|||||||
static const float DEFAULT_FEEDRATE = 0.0f;
|
static const float DEFAULT_FEEDRATE = 0.0f;
|
||||||
static const unsigned int DEFAULT_EXTRUDER_ID = 0;
|
static const unsigned int DEFAULT_EXTRUDER_ID = 0;
|
||||||
static const unsigned int DEFAULT_COLOR_PRINT_ID = 0;
|
static const unsigned int DEFAULT_COLOR_PRINT_ID = 0;
|
||||||
static const Slic3r::Vec3d DEFAULT_START_POSITION = Slic3r::Vec3d(0.0f, 0.0f, 0.0f);
|
static const Slic3r::Vec3f DEFAULT_START_POSITION = Slic3r::Vec3f::Zero();
|
||||||
static const float DEFAULT_START_EXTRUSION = 0.0f;
|
static const float DEFAULT_START_EXTRUSION = 0.0f;
|
||||||
static const float DEFAULT_FAN_SPEED = 0.0f;
|
static const float DEFAULT_FAN_SPEED = 0.0f;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ const std::string GCodeAnalyzer::Pause_Print_Tag = "_ANALYZER_PAUSE_PRINT";
|
|||||||
const std::string GCodeAnalyzer::Custom_Code_Tag = "_ANALYZER_CUSTOM_CODE";
|
const std::string GCodeAnalyzer::Custom_Code_Tag = "_ANALYZER_CUSTOM_CODE";
|
||||||
const std::string GCodeAnalyzer::End_Pause_Print_Or_Custom_Code_Tag = "_ANALYZER_END_PAUSE_PRINT_OR_CUSTOM_CODE";
|
const std::string GCodeAnalyzer::End_Pause_Print_Or_Custom_Code_Tag = "_ANALYZER_END_PAUSE_PRINT_OR_CUSTOM_CODE";
|
||||||
|
|
||||||
const double GCodeAnalyzer::Default_mm3_per_mm = 0.0;
|
const float GCodeAnalyzer::Default_mm3_per_mm = 0.0f;
|
||||||
const float GCodeAnalyzer::Default_Width = 0.0f;
|
const float GCodeAnalyzer::Default_Width = 0.0f;
|
||||||
const float GCodeAnalyzer::Default_Height = 0.0f;
|
const float GCodeAnalyzer::Default_Height = 0.0f;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ GCodeAnalyzer::Metadata::Metadata()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GCodeAnalyzer::Metadata::Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id/* = 0*/)
|
GCodeAnalyzer::Metadata::Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, float mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id/* = 0*/)
|
||||||
: extrusion_role(extrusion_role)
|
: extrusion_role(extrusion_role)
|
||||||
, extruder_id(extruder_id)
|
, extruder_id(extruder_id)
|
||||||
, mm3_per_mm(mm3_per_mm)
|
, mm3_per_mm(mm3_per_mm)
|
||||||
@ -90,7 +90,7 @@ bool GCodeAnalyzer::Metadata::operator != (const GCodeAnalyzer::Metadata& other)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id/* = 0*/)
|
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, float mm3_per_mm, float width, float height, float feedrate, const Vec3f& start_position, const Vec3f& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id/* = 0*/)
|
||||||
: type(type)
|
: type(type)
|
||||||
, data(extrusion_role, extruder_id, mm3_per_mm, width, height, feedrate, fan_speed, cp_color_id)
|
, data(extrusion_role, extruder_id, mm3_per_mm, width, height, feedrate, fan_speed, cp_color_id)
|
||||||
, start_position(start_position)
|
, start_position(start_position)
|
||||||
@ -99,7 +99,7 @@ GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusi
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, const GCodeAnalyzer::Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder)
|
GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, const GCodeAnalyzer::Metadata& data, const Vec3f& start_position, const Vec3f& end_position, float delta_extruder)
|
||||||
: type(type)
|
: type(type)
|
||||||
, data(data)
|
, data(data)
|
||||||
, start_position(start_position)
|
, start_position(start_position)
|
||||||
@ -691,7 +691,7 @@ void GCodeAnalyzer::_process_extrusion_role_tag(const std::string& comment, size
|
|||||||
|
|
||||||
void GCodeAnalyzer::_process_mm3_per_mm_tag(const std::string& comment, size_t pos)
|
void GCodeAnalyzer::_process_mm3_per_mm_tag(const std::string& comment, size_t pos)
|
||||||
{
|
{
|
||||||
_set_mm3_per_mm(::strtod(comment.substr(pos + Mm3_Per_Mm_Tag.length()).c_str(), nullptr));
|
_set_mm3_per_mm((float)::strtod(comment.substr(pos + Mm3_Per_Mm_Tag.length()).c_str(), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeAnalyzer::_process_width_tag(const std::string& comment, size_t pos)
|
void GCodeAnalyzer::_process_width_tag(const std::string& comment, size_t pos)
|
||||||
@ -784,12 +784,12 @@ unsigned int GCodeAnalyzer::_get_cp_color_id() const
|
|||||||
return m_state.data.cp_color_id;
|
return m_state.data.cp_color_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeAnalyzer::_set_mm3_per_mm(double value)
|
void GCodeAnalyzer::_set_mm3_per_mm(float value)
|
||||||
{
|
{
|
||||||
m_state.data.mm3_per_mm = value;
|
m_state.data.mm3_per_mm = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GCodeAnalyzer::_get_mm3_per_mm() const
|
float GCodeAnalyzer::_get_mm3_per_mm() const
|
||||||
{
|
{
|
||||||
return m_state.data.mm3_per_mm;
|
return m_state.data.mm3_per_mm;
|
||||||
}
|
}
|
||||||
@ -864,12 +864,12 @@ void GCodeAnalyzer::_reset_axes_origin()
|
|||||||
::memset((void*)m_state.origin, 0, Num_Axis * sizeof(float));
|
::memset((void*)m_state.origin, 0, Num_Axis * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeAnalyzer::_set_start_position(const Vec3d& position)
|
void GCodeAnalyzer::_set_start_position(const Vec3f& position)
|
||||||
{
|
{
|
||||||
m_state.start_position = position;
|
m_state.start_position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vec3d& GCodeAnalyzer::_get_start_position() const
|
const Vec3f& GCodeAnalyzer::_get_start_position() const
|
||||||
{
|
{
|
||||||
return m_state.start_position;
|
return m_state.start_position;
|
||||||
}
|
}
|
||||||
@ -900,9 +900,9 @@ float GCodeAnalyzer::_get_delta_extrusion() const
|
|||||||
return _get_axis_position(E) - m_state.start_extrusion;
|
return _get_axis_position(E) - m_state.start_extrusion;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d GCodeAnalyzer::_get_end_position() const
|
Vec3f GCodeAnalyzer::_get_end_position() const
|
||||||
{
|
{
|
||||||
return Vec3d(m_state.position[X], m_state.position[Y], m_state.position[Z]);
|
return Vec3f(m_state.position[X], m_state.position[Y], m_state.position[Z]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
|
void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
|
||||||
@ -913,14 +913,14 @@ void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
|
|||||||
it = m_moves_map.insert(TypeToMovesMap::value_type(type, GCodeMovesList())).first;
|
it = m_moves_map.insert(TypeToMovesMap::value_type(type, GCodeMovesList())).first;
|
||||||
|
|
||||||
// store move
|
// store move
|
||||||
Vec3d extruder_offset = Vec3d::Zero();
|
Vec3f extruder_offset = Vec3f::Zero();
|
||||||
unsigned int extruder_id = _get_extruder_id();
|
unsigned int extruder_id = _get_extruder_id();
|
||||||
ExtruderOffsetsMap::iterator extr_it = m_extruder_offsets.find(extruder_id);
|
ExtruderOffsetsMap::iterator extr_it = m_extruder_offsets.find(extruder_id);
|
||||||
if (extr_it != m_extruder_offsets.end())
|
if (extr_it != m_extruder_offsets.end())
|
||||||
extruder_offset = Vec3d(extr_it->second(0), extr_it->second(1), 0.0);
|
extruder_offset = Vec3f((float)extr_it->second(0), (float)extr_it->second(1), 0.0f);
|
||||||
|
|
||||||
Vec3d start_position = _get_start_position() + extruder_offset;
|
Vec3f start_position = _get_start_position() + extruder_offset;
|
||||||
Vec3d end_position = _get_end_position() + extruder_offset;
|
Vec3f end_position = _get_end_position() + extruder_offset;
|
||||||
it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_fan_speed(), _get_cp_color_id());
|
it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_fan_speed(), _get_cp_color_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -958,8 +958,8 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||||||
GCodePreviewData::Extrusion::Path &path = paths.back();
|
GCodePreviewData::Extrusion::Path &path = paths.back();
|
||||||
path.polyline = polyline;
|
path.polyline = polyline;
|
||||||
path.extrusion_role = data.extrusion_role;
|
path.extrusion_role = data.extrusion_role;
|
||||||
path.mm3_per_mm = float(data.mm3_per_mm);
|
path.mm3_per_mm = data.mm3_per_mm;
|
||||||
path.width = data.width;
|
path.width = data.width;
|
||||||
path.height = data.height;
|
path.height = data.height;
|
||||||
path.feedrate = data.feedrate;
|
path.feedrate = data.feedrate;
|
||||||
path.extruder_id = data.extruder_id;
|
path.extruder_id = data.extruder_id;
|
||||||
@ -976,7 +976,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||||||
Metadata data;
|
Metadata data;
|
||||||
float z = FLT_MAX;
|
float z = FLT_MAX;
|
||||||
Polyline polyline;
|
Polyline polyline;
|
||||||
Vec3d position(FLT_MAX, FLT_MAX, FLT_MAX);
|
Vec3f position(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||||
float volumetric_rate = FLT_MAX;
|
float volumetric_rate = FLT_MAX;
|
||||||
GCodePreviewData::Range height_range;
|
GCodePreviewData::Range height_range;
|
||||||
GCodePreviewData::Range width_range;
|
GCodePreviewData::Range width_range;
|
||||||
@ -996,7 +996,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||||||
if (cancel_callback_curr == 0)
|
if (cancel_callback_curr == 0)
|
||||||
cancel_callback();
|
cancel_callback();
|
||||||
|
|
||||||
if ((data != move.data) || (z != move.start_position.z()) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm))
|
if ((data != move.data) || (z != move.start_position.z()) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * move.data.mm3_per_mm))
|
||||||
{
|
{
|
||||||
// store current polyline
|
// store current polyline
|
||||||
polyline.remove_duplicate_points();
|
polyline.remove_duplicate_points();
|
||||||
@ -1012,7 +1012,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||||||
// update current values
|
// update current values
|
||||||
data = move.data;
|
data = move.data;
|
||||||
z = (float)move.start_position.z();
|
z = (float)move.start_position.z();
|
||||||
volumetric_rate = move.data.feedrate * (float)move.data.mm3_per_mm;
|
volumetric_rate = move.data.feedrate * move.data.mm3_per_mm;
|
||||||
height_range.update_from(move.data.height);
|
height_range.update_from(move.data.height);
|
||||||
width_range.update_from(move.data.width);
|
width_range.update_from(move.data.width);
|
||||||
feedrate_range.update_from(move.data.feedrate, GCodePreviewData::FeedrateKind::EXTRUSION);
|
feedrate_range.update_from(move.data.feedrate, GCodePreviewData::FeedrateKind::EXTRUSION);
|
||||||
@ -1060,7 +1060,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Polyline3 polyline;
|
Polyline3 polyline;
|
||||||
Vec3d position(FLT_MAX, FLT_MAX, FLT_MAX);
|
Vec3f position(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||||
GCodePreviewData::Travel::EType type = GCodePreviewData::Travel::Num_Types;
|
GCodePreviewData::Travel::EType type = GCodePreviewData::Travel::Num_Types;
|
||||||
GCodePreviewData::Travel::Polyline::EDirection direction = GCodePreviewData::Travel::Polyline::Num_Directions;
|
GCodePreviewData::Travel::Polyline::EDirection direction = GCodePreviewData::Travel::Polyline::Num_Directions;
|
||||||
float feedrate = FLT_MAX;
|
float feedrate = FLT_MAX;
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
static const std::string Custom_Code_Tag;
|
static const std::string Custom_Code_Tag;
|
||||||
static const std::string End_Pause_Print_Or_Custom_Code_Tag;
|
static const std::string End_Pause_Print_Or_Custom_Code_Tag;
|
||||||
|
|
||||||
static const double Default_mm3_per_mm;
|
static const float Default_mm3_per_mm;
|
||||||
static const float Default_Width;
|
static const float Default_Width;
|
||||||
static const float Default_Height;
|
static const float Default_Height;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
{
|
{
|
||||||
ExtrusionRole extrusion_role;
|
ExtrusionRole extrusion_role;
|
||||||
unsigned int extruder_id;
|
unsigned int extruder_id;
|
||||||
double mm3_per_mm;
|
float mm3_per_mm;
|
||||||
float width; // mm
|
float width; // mm
|
||||||
float height; // mm
|
float height; // mm
|
||||||
float feedrate; // mm/s
|
float feedrate; // mm/s
|
||||||
@ -61,7 +61,7 @@ public:
|
|||||||
unsigned int cp_color_id;
|
unsigned int cp_color_id;
|
||||||
|
|
||||||
Metadata();
|
Metadata();
|
||||||
Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id = 0);
|
Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, float mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id = 0);
|
||||||
|
|
||||||
bool operator != (const Metadata& other) const;
|
bool operator != (const Metadata& other) const;
|
||||||
};
|
};
|
||||||
@ -81,12 +81,12 @@ public:
|
|||||||
|
|
||||||
EType type;
|
EType type;
|
||||||
Metadata data;
|
Metadata data;
|
||||||
Vec3d start_position;
|
Vec3f start_position;
|
||||||
Vec3d end_position;
|
Vec3f end_position;
|
||||||
float delta_extruder;
|
float delta_extruder;
|
||||||
|
|
||||||
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id = 0);
|
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, float mm3_per_mm, float width, float height, float feedrate, const Vec3f& start_position, const Vec3f& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id = 0);
|
||||||
GCodeMove(EType type, const Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder);
|
GCodeMove(EType type, const Metadata& data, const Vec3f& start_position, const Vec3f& end_position, float delta_extruder);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<GCodeMove> GCodeMovesList;
|
typedef std::vector<GCodeMove> GCodeMovesList;
|
||||||
@ -101,7 +101,7 @@ private:
|
|||||||
EPositioningType global_positioning_type;
|
EPositioningType global_positioning_type;
|
||||||
EPositioningType e_local_positioning_type;
|
EPositioningType e_local_positioning_type;
|
||||||
Metadata data;
|
Metadata data;
|
||||||
Vec3d start_position = Vec3d::Zero();
|
Vec3f start_position = Vec3f::Zero();
|
||||||
float cached_position[5];
|
float cached_position[5];
|
||||||
float start_extrusion;
|
float start_extrusion;
|
||||||
float position[Num_Axis];
|
float position[Num_Axis];
|
||||||
@ -246,8 +246,8 @@ private:
|
|||||||
void _set_cp_color_id(unsigned int id);
|
void _set_cp_color_id(unsigned int id);
|
||||||
unsigned int _get_cp_color_id() const;
|
unsigned int _get_cp_color_id() const;
|
||||||
|
|
||||||
void _set_mm3_per_mm(double value);
|
void _set_mm3_per_mm(float value);
|
||||||
double _get_mm3_per_mm() const;
|
float _get_mm3_per_mm() const;
|
||||||
|
|
||||||
void _set_width(float width);
|
void _set_width(float width);
|
||||||
float _get_width() const;
|
float _get_width() const;
|
||||||
@ -272,8 +272,8 @@ private:
|
|||||||
// Sets origin position to zero
|
// Sets origin position to zero
|
||||||
void _reset_axes_origin();
|
void _reset_axes_origin();
|
||||||
|
|
||||||
void _set_start_position(const Vec3d& position);
|
void _set_start_position(const Vec3f& position);
|
||||||
const Vec3d& _get_start_position() const;
|
const Vec3f& _get_start_position() const;
|
||||||
|
|
||||||
void _set_cached_position(unsigned char axis, float position);
|
void _set_cached_position(unsigned char axis, float position);
|
||||||
float _get_cached_position(unsigned char axis) const;
|
float _get_cached_position(unsigned char axis) const;
|
||||||
@ -285,7 +285,7 @@ private:
|
|||||||
float _get_delta_extrusion() const;
|
float _get_delta_extrusion() const;
|
||||||
|
|
||||||
// Returns current xyz position (from m_state.position[])
|
// Returns current xyz position (from m_state.position[])
|
||||||
Vec3d _get_end_position() const;
|
Vec3f _get_end_position() const;
|
||||||
|
|
||||||
// Adds a new move with the given data
|
// Adds a new move with the given data
|
||||||
void _store_move(GCodeMove::EType type);
|
void _store_move(GCodeMove::EType type);
|
||||||
|
@ -46,19 +46,19 @@ namespace Slic3r {
|
|||||||
::memset(abs_axis_feedrate, 0, Num_Axis * sizeof(float));
|
::memset(abs_axis_feedrate, 0, Num_Axis * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::Trapezoid::acceleration_time(float acceleration) const
|
float GCodeTimeEstimator::Block::Trapezoid::acceleration_time(float entry_feedrate, float acceleration) const
|
||||||
{
|
{
|
||||||
return acceleration_time_from_distance(feedrate.entry, accelerate_until, acceleration);
|
return acceleration_time_from_distance(entry_feedrate, accelerate_until, acceleration);
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::Trapezoid::cruise_time() const
|
float GCodeTimeEstimator::Block::Trapezoid::cruise_time() const
|
||||||
{
|
{
|
||||||
return (feedrate.cruise != 0.0f) ? cruise_distance() / feedrate.cruise : 0.0f;
|
return (cruise_feedrate != 0.0f) ? cruise_distance() / cruise_feedrate : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::Trapezoid::deceleration_time(float acceleration) const
|
float GCodeTimeEstimator::Block::Trapezoid::deceleration_time(float distance, float acceleration) const
|
||||||
{
|
{
|
||||||
return acceleration_time_from_distance(feedrate.cruise, (distance - decelerate_after), -acceleration);
|
return acceleration_time_from_distance(cruise_feedrate, (distance - decelerate_after), -acceleration);
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::Trapezoid::cruise_distance() const
|
float GCodeTimeEstimator::Block::Trapezoid::cruise_distance() const
|
||||||
@ -78,29 +78,9 @@ namespace Slic3r {
|
|||||||
return ::sqrt(value);
|
return ::sqrt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GCodeTimeEstimator::Block::Block()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::move_length() const
|
|
||||||
{
|
|
||||||
float length = ::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
|
|
||||||
return (length > 0.0f) ? length : std::abs(delta_pos[E]);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::is_extruder_only_move() const
|
|
||||||
{
|
|
||||||
return (delta_pos[X] == 0.0f) && (delta_pos[Y] == 0.0f) && (delta_pos[Z] == 0.0f) && (delta_pos[E] != 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::is_travel_move() const
|
|
||||||
{
|
|
||||||
return delta_pos[E] == 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::acceleration_time() const
|
float GCodeTimeEstimator::Block::acceleration_time() const
|
||||||
{
|
{
|
||||||
return trapezoid.acceleration_time(acceleration);
|
return trapezoid.acceleration_time(feedrate.entry, acceleration);
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::cruise_time() const
|
float GCodeTimeEstimator::Block::cruise_time() const
|
||||||
@ -110,7 +90,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
float GCodeTimeEstimator::Block::deceleration_time() const
|
float GCodeTimeEstimator::Block::deceleration_time() const
|
||||||
{
|
{
|
||||||
return trapezoid.deceleration_time(acceleration);
|
return trapezoid.deceleration_time(distance, acceleration);
|
||||||
}
|
}
|
||||||
|
|
||||||
float GCodeTimeEstimator::Block::cruise_distance() const
|
float GCodeTimeEstimator::Block::cruise_distance() const
|
||||||
@ -120,10 +100,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
void GCodeTimeEstimator::Block::calculate_trapezoid()
|
void GCodeTimeEstimator::Block::calculate_trapezoid()
|
||||||
{
|
{
|
||||||
float distance = move_length();
|
trapezoid.cruise_feedrate = feedrate.cruise;
|
||||||
|
|
||||||
trapezoid.distance = distance;
|
|
||||||
trapezoid.feedrate = feedrate;
|
|
||||||
|
|
||||||
float accelerate_distance = std::max(0.0f, estimate_acceleration_distance(feedrate.entry, feedrate.cruise, acceleration));
|
float accelerate_distance = std::max(0.0f, estimate_acceleration_distance(feedrate.entry, feedrate.cruise, acceleration));
|
||||||
float decelerate_distance = std::max(0.0f, estimate_acceleration_distance(feedrate.cruise, feedrate.exit, -acceleration));
|
float decelerate_distance = std::max(0.0f, estimate_acceleration_distance(feedrate.cruise, feedrate.exit, -acceleration));
|
||||||
@ -134,9 +111,9 @@ namespace Slic3r {
|
|||||||
// and start braking in order to reach the exit_feedrate exactly at the end of this block.
|
// and start braking in order to reach the exit_feedrate exactly at the end of this block.
|
||||||
if (cruise_distance < 0.0f)
|
if (cruise_distance < 0.0f)
|
||||||
{
|
{
|
||||||
accelerate_distance = clamp(0.0f, distance, intersection_distance(feedrate.entry, feedrate.exit, acceleration, distance));
|
accelerate_distance = std::clamp(intersection_distance(feedrate.entry, feedrate.exit, acceleration, distance), 0.0f, distance);
|
||||||
cruise_distance = 0.0f;
|
cruise_distance = 0.0f;
|
||||||
trapezoid.feedrate.cruise = Trapezoid::speed_from_distance(feedrate.entry, accelerate_distance, acceleration);
|
trapezoid.cruise_feedrate = Trapezoid::speed_from_distance(feedrate.entry, accelerate_distance, acceleration);
|
||||||
}
|
}
|
||||||
|
|
||||||
trapezoid.accelerate_until = accelerate_distance;
|
trapezoid.accelerate_until = accelerate_distance;
|
||||||
@ -207,11 +184,8 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
if (start_from_beginning)
|
if (start_from_beginning)
|
||||||
{
|
|
||||||
_reset_time();
|
_reset_time();
|
||||||
m_last_st_synchronized_block_id = -1;
|
_calculate_time(0);
|
||||||
}
|
|
||||||
_calculate_time();
|
|
||||||
|
|
||||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
||||||
@ -221,6 +195,7 @@ namespace Slic3r {
|
|||||||
#endif // ENABLE_MOVE_STATS
|
#endif // ENABLE_MOVE_STATS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void GCodeTimeEstimator::calculate_time_from_text(const std::string& gcode)
|
void GCodeTimeEstimator::calculate_time_from_text(const std::string& gcode)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
@ -229,7 +204,7 @@ namespace Slic3r {
|
|||||||
[this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
|
[this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
|
||||||
{ this->_process_gcode_line(reader, line); });
|
{ this->_process_gcode_line(reader, line); });
|
||||||
|
|
||||||
_calculate_time();
|
_calculate_time(0);
|
||||||
|
|
||||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
||||||
@ -244,7 +219,7 @@ namespace Slic3r {
|
|||||||
reset();
|
reset();
|
||||||
|
|
||||||
m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
|
m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
|
||||||
_calculate_time();
|
_calculate_time(0);
|
||||||
|
|
||||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
||||||
@ -262,7 +237,7 @@ namespace Slic3r {
|
|||||||
{ this->_process_gcode_line(reader, line); };
|
{ this->_process_gcode_line(reader, line); };
|
||||||
for (const std::string& line : gcode_lines)
|
for (const std::string& line : gcode_lines)
|
||||||
m_parser.parse_line(line, action);
|
m_parser.parse_line(line, action);
|
||||||
_calculate_time();
|
_calculate_time(0);
|
||||||
|
|
||||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache});
|
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache});
|
||||||
@ -271,6 +246,7 @@ namespace Slic3r {
|
|||||||
_log_moves_stats();
|
_log_moves_stats();
|
||||||
#endif // ENABLE_MOVE_STATS
|
#endif // ENABLE_MOVE_STATS
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool GCodeTimeEstimator::post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode)
|
bool GCodeTimeEstimator::post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode)
|
||||||
{
|
{
|
||||||
@ -317,25 +293,25 @@ namespace Slic3r {
|
|||||||
if (data == nullptr)
|
if (data == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert((g1_line_id >= (int)data->g1_line_ids.size()) || (data->g1_line_ids[g1_line_id].first >= g1_lines_count));
|
assert((g1_line_id >= (int)data->g1_times.size()) || (data->g1_times[g1_line_id].first >= (int)g1_lines_count));
|
||||||
const Block* block = nullptr;
|
float elapsed_time = -1.0f;
|
||||||
if (g1_line_id < (int)data->g1_line_ids.size())
|
if (g1_line_id < (int)data->g1_times.size())
|
||||||
{
|
{
|
||||||
const G1LineIdToBlockId& map_item = data->g1_line_ids[g1_line_id];
|
const G1LineIdTime& map_item = data->g1_times[g1_line_id];
|
||||||
if (map_item.first == g1_lines_count)
|
if (map_item.first == g1_lines_count)
|
||||||
{
|
{
|
||||||
if (line.has_e() && (map_item.second < (unsigned int)data->blocks.size()))
|
if (line.has_e())
|
||||||
block = &data->blocks[map_item.second];
|
elapsed_time = map_item.second;
|
||||||
++g1_line_id;
|
++g1_line_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((block != nullptr) && (block->elapsed_time != -1.0f))
|
if (elapsed_time != -1.0f)
|
||||||
{
|
{
|
||||||
float block_remaining_time = data->time - block->elapsed_time;
|
float block_remaining_time = data->time - elapsed_time;
|
||||||
if (std::abs(last_recorded_time - block_remaining_time) > interval_sec)
|
if (std::abs(last_recorded_time - block_remaining_time) > interval_sec)
|
||||||
{
|
{
|
||||||
sprintf(line_M73, time_mask.c_str(), std::to_string((int)(100.0f * block->elapsed_time / data->time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
|
sprintf(line_M73, time_mask.c_str(), std::to_string((int)(100.0f * elapsed_time / data->time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
|
||||||
gcode_line += line_M73;
|
gcode_line += line_M73;
|
||||||
|
|
||||||
last_recorded_time = block_remaining_time;
|
last_recorded_time = block_remaining_time;
|
||||||
@ -643,22 +619,6 @@ namespace Slic3r {
|
|||||||
m_state.extruder_id = m_state.extruder_id_unloaded;
|
m_state.extruder_id = m_state.extruder_id_unloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::add_additional_time(float timeSec)
|
|
||||||
{
|
|
||||||
PROFILE_FUNC();
|
|
||||||
m_state.additional_time += timeSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCodeTimeEstimator::set_additional_time(float timeSec)
|
|
||||||
{
|
|
||||||
m_state.additional_time = timeSec;
|
|
||||||
}
|
|
||||||
|
|
||||||
float GCodeTimeEstimator::get_additional_time() const
|
|
||||||
{
|
|
||||||
return m_state.additional_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCodeTimeEstimator::set_default()
|
void GCodeTimeEstimator::set_default()
|
||||||
{
|
{
|
||||||
set_units(Millimeters);
|
set_units(Millimeters);
|
||||||
@ -788,7 +748,7 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
size_t out = sizeof(*this);
|
size_t out = sizeof(*this);
|
||||||
out += SLIC3R_STDVEC_MEMSIZE(this->m_blocks, Block);
|
out += SLIC3R_STDVEC_MEMSIZE(this->m_blocks, Block);
|
||||||
out += SLIC3R_STDVEC_MEMSIZE(this->m_g1_line_ids, G1LineIdToBlockId);
|
out += SLIC3R_STDVEC_MEMSIZE(this->m_g1_times, G1LineIdTime);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,13 +767,9 @@ namespace Slic3r {
|
|||||||
if (get_e_local_positioning_type() == Absolute)
|
if (get_e_local_positioning_type() == Absolute)
|
||||||
set_axis_position(E, 0.0f);
|
set_axis_position(E, 0.0f);
|
||||||
|
|
||||||
set_additional_time(0.0f);
|
|
||||||
|
|
||||||
reset_extruder_id();
|
reset_extruder_id();
|
||||||
reset_g1_line_id();
|
reset_g1_line_id();
|
||||||
m_g1_line_ids.clear();
|
m_g1_times.clear();
|
||||||
|
|
||||||
m_last_st_synchronized_block_id = -1;
|
|
||||||
|
|
||||||
m_needs_custom_gcode_times = false;
|
m_needs_custom_gcode_times = false;
|
||||||
m_custom_gcode_times.clear();
|
m_custom_gcode_times.clear();
|
||||||
@ -830,17 +786,19 @@ namespace Slic3r {
|
|||||||
m_blocks.clear();
|
m_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_calculate_time()
|
void GCodeTimeEstimator::_calculate_time(size_t keep_last_n_blocks)
|
||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
|
|
||||||
|
assert(keep_last_n_blocks <= m_blocks.size());
|
||||||
|
|
||||||
_forward_pass();
|
_forward_pass();
|
||||||
_reverse_pass();
|
_reverse_pass();
|
||||||
_recalculate_trapezoids();
|
_recalculate_trapezoids();
|
||||||
|
|
||||||
m_time += get_additional_time();
|
size_t n_blocks_process = m_blocks.size() - keep_last_n_blocks;
|
||||||
m_custom_gcode_time_cache += get_additional_time();
|
m_g1_times.reserve(m_g1_times.size() + n_blocks_process);
|
||||||
|
for (size_t i = 0; i < n_blocks_process; ++ i)
|
||||||
for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i)
|
|
||||||
{
|
{
|
||||||
Block& block = m_blocks[i];
|
Block& block = m_blocks[i];
|
||||||
float block_time = 0.0f;
|
float block_time = 0.0f;
|
||||||
@ -848,7 +806,8 @@ namespace Slic3r {
|
|||||||
block_time += block.cruise_time();
|
block_time += block.cruise_time();
|
||||||
block_time += block.deceleration_time();
|
block_time += block.deceleration_time();
|
||||||
m_time += block_time;
|
m_time += block_time;
|
||||||
block.elapsed_time = m_time;
|
if (block.g1_line_id >= 0)
|
||||||
|
m_g1_times.emplace_back(block.g1_line_id, m_time);
|
||||||
|
|
||||||
#if ENABLE_MOVE_STATS
|
#if ENABLE_MOVE_STATS
|
||||||
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
|
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
|
||||||
@ -862,9 +821,10 @@ namespace Slic3r {
|
|||||||
m_custom_gcode_time_cache += block_time;
|
m_custom_gcode_time_cache += block_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_st_synchronized_block_id = (int)m_blocks.size() - 1;
|
if (keep_last_n_blocks)
|
||||||
// The additional time has been consumed (added to the total time), reset it to zero.
|
m_blocks.erase(m_blocks.begin(), m_blocks.begin() + n_blocks_process);
|
||||||
set_additional_time(0.);
|
else
|
||||||
|
m_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
|
void GCodeTimeEstimator::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
|
||||||
@ -1021,11 +981,22 @@ namespace Slic3r {
|
|||||||
return current_absolute_position;
|
return current_absolute_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// delta_pos must have size >= 4
|
||||||
|
auto move_length = [](const float* delta_pos) {
|
||||||
|
float xyz_length = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
|
||||||
|
return (xyz_length > 0.0f) ? xyz_length : std::abs(delta_pos[E]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// delta_pos must have size >= 4
|
||||||
|
auto is_extruder_only_move = [](const float* delta_pos) {
|
||||||
|
return (delta_pos[X] == 0.0f) && (delta_pos[Y] == 0.0f) && (delta_pos[Z] == 0.0f) && (delta_pos[E] != 0.0f);
|
||||||
|
};
|
||||||
|
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
increment_g1_line_id();
|
increment_g1_line_id();
|
||||||
|
|
||||||
// updates axes positions from line
|
// updates axes positions from line
|
||||||
float new_pos[Num_Axis];
|
std::array<float, Num_Axis> new_pos;
|
||||||
for (unsigned char a = X; a < Num_Axis; ++a)
|
for (unsigned char a = X; a < Num_Axis; ++a)
|
||||||
{
|
{
|
||||||
new_pos[a] = axis_absolute_position((EAxis)a, line);
|
new_pos[a] = axis_absolute_position((EAxis)a, line);
|
||||||
@ -1040,10 +1011,11 @@ namespace Slic3r {
|
|||||||
|
|
||||||
// calculates block movement deltas
|
// calculates block movement deltas
|
||||||
float max_abs_delta = 0.0f;
|
float max_abs_delta = 0.0f;
|
||||||
|
std::array<float, Num_Axis> delta_pos;
|
||||||
for (unsigned char a = X; a < Num_Axis; ++a)
|
for (unsigned char a = X; a < Num_Axis; ++a)
|
||||||
{
|
{
|
||||||
block.delta_pos[a] = new_pos[a] - get_axis_position((EAxis)a);
|
delta_pos[a] = new_pos[a] - get_axis_position((EAxis)a);
|
||||||
max_abs_delta = std::max(max_abs_delta, std::abs(block.delta_pos[a]));
|
max_abs_delta = std::max(max_abs_delta, std::abs(delta_pos[a]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// is it a move ?
|
// is it a move ?
|
||||||
@ -1051,15 +1023,15 @@ namespace Slic3r {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// calculates block feedrate
|
// calculates block feedrate
|
||||||
m_curr.feedrate = std::max(get_feedrate(), block.is_travel_move() ? get_minimum_travel_feedrate() : get_minimum_feedrate());
|
m_curr.feedrate = std::max(get_feedrate(), (delta_pos[E] == 0.0f) ? get_minimum_travel_feedrate() : get_minimum_feedrate());
|
||||||
|
|
||||||
float distance = block.move_length();
|
block.distance = move_length(delta_pos.data());
|
||||||
float invDistance = 1.0f / distance;
|
float invDistance = 1.0f / block.distance;
|
||||||
|
|
||||||
float min_feedrate_factor = 1.0f;
|
float min_feedrate_factor = 1.0f;
|
||||||
for (unsigned char a = X; a < Num_Axis; ++a)
|
for (unsigned char a = X; a < Num_Axis; ++a)
|
||||||
{
|
{
|
||||||
m_curr.axis_feedrate[a] = m_curr.feedrate * block.delta_pos[a] * invDistance;
|
m_curr.axis_feedrate[a] = m_curr.feedrate * delta_pos[a] * invDistance;
|
||||||
if (a == E)
|
if (a == E)
|
||||||
m_curr.axis_feedrate[a] *= get_extrude_factor_override_percentage();
|
m_curr.axis_feedrate[a] *= get_extrude_factor_override_percentage();
|
||||||
|
|
||||||
@ -1080,12 +1052,12 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculates block acceleration
|
// calculates block acceleration
|
||||||
float acceleration = block.is_extruder_only_move() ? get_retract_acceleration() : get_acceleration();
|
float acceleration = is_extruder_only_move(delta_pos.data()) ? get_retract_acceleration() : get_acceleration();
|
||||||
|
|
||||||
for (unsigned char a = X; a < Num_Axis; ++a)
|
for (unsigned char a = X; a < Num_Axis; ++a)
|
||||||
{
|
{
|
||||||
float axis_max_acceleration = get_axis_max_acceleration((EAxis)a);
|
float axis_max_acceleration = get_axis_max_acceleration((EAxis)a);
|
||||||
if (acceleration * std::abs(block.delta_pos[a]) * invDistance > axis_max_acceleration)
|
if (acceleration * std::abs(delta_pos[a]) * invDistance > axis_max_acceleration)
|
||||||
acceleration = axis_max_acceleration;
|
acceleration = axis_max_acceleration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,7 +1137,7 @@ namespace Slic3r {
|
|||||||
vmax_junction = m_curr.safe_feedrate;
|
vmax_junction = m_curr.safe_feedrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
float v_allowable = Block::max_allowable_speed(-acceleration, m_curr.safe_feedrate, distance);
|
float v_allowable = Block::max_allowable_speed(-acceleration, m_curr.safe_feedrate, block.distance);
|
||||||
block.feedrate.entry = std::min(vmax_junction, v_allowable);
|
block.feedrate.entry = std::min(vmax_junction, v_allowable);
|
||||||
|
|
||||||
block.max_entry_speed = vmax_junction;
|
block.max_entry_speed = vmax_junction;
|
||||||
@ -1189,27 +1161,30 @@ namespace Slic3r {
|
|||||||
// detects block move type
|
// detects block move type
|
||||||
block.move_type = Block::Noop;
|
block.move_type = Block::Noop;
|
||||||
|
|
||||||
if (block.delta_pos[E] < 0.0f)
|
if (delta_pos[E] < 0.0f)
|
||||||
{
|
{
|
||||||
if ((block.delta_pos[X] != 0.0f) || (block.delta_pos[Y] != 0.0f) || (block.delta_pos[Z] != 0.0f))
|
if ((delta_pos[X] != 0.0f) || (delta_pos[Y] != 0.0f) || (delta_pos[Z] != 0.0f))
|
||||||
block.move_type = Block::Move;
|
block.move_type = Block::Move;
|
||||||
else
|
else
|
||||||
block.move_type = Block::Retract;
|
block.move_type = Block::Retract;
|
||||||
}
|
}
|
||||||
else if (block.delta_pos[E] > 0.0f)
|
else if (delta_pos[E] > 0.0f)
|
||||||
{
|
{
|
||||||
if ((block.delta_pos[X] == 0.0f) && (block.delta_pos[Y] == 0.0f) && (block.delta_pos[Z] == 0.0f))
|
if ((delta_pos[X] == 0.0f) && (delta_pos[Y] == 0.0f) && (delta_pos[Z] == 0.0f))
|
||||||
block.move_type = Block::Unretract;
|
block.move_type = Block::Unretract;
|
||||||
else if ((block.delta_pos[X] != 0.0f) || (block.delta_pos[Y] != 0.0f))
|
else if ((delta_pos[X] != 0.0f) || (delta_pos[Y] != 0.0f))
|
||||||
block.move_type = Block::Extrude;
|
block.move_type = Block::Extrude;
|
||||||
}
|
}
|
||||||
else if ((block.delta_pos[X] != 0.0f) || (block.delta_pos[Y] != 0.0f) || (block.delta_pos[Z] != 0.0f))
|
else if ((delta_pos[X] != 0.0f) || (delta_pos[Y] != 0.0f) || (delta_pos[Z] != 0.0f))
|
||||||
block.move_type = Block::Move;
|
block.move_type = Block::Move;
|
||||||
#endif // ENABLE_MOVE_STATS
|
#endif // ENABLE_MOVE_STATS
|
||||||
|
|
||||||
// adds block to blocks list
|
// adds block to blocks list
|
||||||
|
block.g1_line_id = this->get_g1_line_id();
|
||||||
m_blocks.emplace_back(block);
|
m_blocks.emplace_back(block);
|
||||||
m_g1_line_ids.emplace_back(G1LineIdToBlockIdMap::value_type(get_g1_line_id(), (unsigned int)m_blocks.size() - 1));
|
|
||||||
|
if (m_blocks.size() > planner_refresh_if_larger)
|
||||||
|
_calculate_time(planner_queue_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_processG4(const GCodeReader::GCodeLine& line)
|
void GCodeTimeEstimator::_processG4(const GCodeReader::GCodeLine& line)
|
||||||
@ -1218,8 +1193,9 @@ namespace Slic3r {
|
|||||||
GCodeFlavor dialect = get_dialect();
|
GCodeFlavor dialect = get_dialect();
|
||||||
|
|
||||||
float value;
|
float value;
|
||||||
|
float extra_time = 0.f;
|
||||||
if (line.has_value('P', value))
|
if (line.has_value('P', value))
|
||||||
add_additional_time(value * MILLISEC_TO_SEC);
|
extra_time += value * MILLISEC_TO_SEC;
|
||||||
|
|
||||||
// see: http://reprap.org/wiki/G-code#G4:_Dwell
|
// see: http://reprap.org/wiki/G-code#G4:_Dwell
|
||||||
if ((dialect == gcfRepetier) ||
|
if ((dialect == gcfRepetier) ||
|
||||||
@ -1228,10 +1204,10 @@ namespace Slic3r {
|
|||||||
(dialect == gcfRepRap))
|
(dialect == gcfRepRap))
|
||||||
{
|
{
|
||||||
if (line.has_value('S', value))
|
if (line.has_value('S', value))
|
||||||
add_additional_time(value);
|
extra_time += value;
|
||||||
}
|
}
|
||||||
|
|
||||||
_simulate_st_synchronize();
|
_simulate_st_synchronize(extra_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_processG20(const GCodeReader::GCodeLine& line)
|
void GCodeTimeEstimator::_processG20(const GCodeReader::GCodeLine& line)
|
||||||
@ -1296,7 +1272,7 @@ namespace Slic3r {
|
|||||||
anyFound = true;
|
anyFound = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_simulate_st_synchronize();
|
_simulate_st_synchronize(0.f);
|
||||||
|
|
||||||
if (!anyFound)
|
if (!anyFound)
|
||||||
{
|
{
|
||||||
@ -1310,7 +1286,7 @@ namespace Slic3r {
|
|||||||
void GCodeTimeEstimator::_processM1(const GCodeReader::GCodeLine& line)
|
void GCodeTimeEstimator::_processM1(const GCodeReader::GCodeLine& line)
|
||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
_simulate_st_synchronize();
|
_simulate_st_synchronize(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_processM82(const GCodeReader::GCodeLine& line)
|
void GCodeTimeEstimator::_processM82(const GCodeReader::GCodeLine& line)
|
||||||
@ -1462,9 +1438,9 @@ namespace Slic3r {
|
|||||||
// MK3 MMU2 specific M code:
|
// MK3 MMU2 specific M code:
|
||||||
// M702 C is expected to be sent by the custom end G-code when finalizing a print.
|
// M702 C is expected to be sent by the custom end G-code when finalizing a print.
|
||||||
// The MK3 unit shall unload and park the active filament into the MMU2 unit.
|
// The MK3 unit shall unload and park the active filament into the MMU2 unit.
|
||||||
add_additional_time(get_filament_unload_time(get_extruder_id()));
|
float extra_time = get_filament_unload_time(get_extruder_id());
|
||||||
reset_extruder_id();
|
reset_extruder_id();
|
||||||
_simulate_st_synchronize();
|
_simulate_st_synchronize(extra_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1478,10 +1454,10 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
// Specific to the MK3 MMU2: The initial extruder ID is set to -1 indicating
|
// Specific to the MK3 MMU2: The initial extruder ID is set to -1 indicating
|
||||||
// that the filament is parked in the MMU2 unit and there is nothing to be unloaded yet.
|
// that the filament is parked in the MMU2 unit and there is nothing to be unloaded yet.
|
||||||
add_additional_time(get_filament_unload_time(get_extruder_id()));
|
float extra_time = get_filament_unload_time(get_extruder_id());
|
||||||
set_extruder_id(id);
|
set_extruder_id(id);
|
||||||
add_additional_time(get_filament_load_time(get_extruder_id()));
|
extra_time += get_filament_load_time(get_extruder_id());
|
||||||
_simulate_st_synchronize();
|
_simulate_st_synchronize(extra_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1513,7 +1489,9 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
m_needs_custom_gcode_times = true;
|
m_needs_custom_gcode_times = true;
|
||||||
_calculate_time();
|
//FIXME this simulates st_synchronize! is it correct?
|
||||||
|
// The estimated time may be longer than the real print time.
|
||||||
|
_simulate_st_synchronize(0.f);
|
||||||
if (m_custom_gcode_time_cache != 0.0f)
|
if (m_custom_gcode_time_cache != 0.0f)
|
||||||
{
|
{
|
||||||
m_custom_gcode_times.push_back({code, m_custom_gcode_time_cache});
|
m_custom_gcode_times.push_back({code, m_custom_gcode_time_cache});
|
||||||
@ -1521,34 +1499,26 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_simulate_st_synchronize()
|
void GCodeTimeEstimator::_simulate_st_synchronize(float extra_time)
|
||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
_calculate_time();
|
m_time += extra_time;
|
||||||
|
m_custom_gcode_time_cache += extra_time;
|
||||||
|
_calculate_time(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_forward_pass()
|
void GCodeTimeEstimator::_forward_pass()
|
||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
if (m_blocks.size() > 1)
|
for (int i = 0; i + 1 < (int)m_blocks.size(); ++i)
|
||||||
{
|
_planner_forward_pass_kernel(m_blocks[i], m_blocks[i + 1]);
|
||||||
for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size() - 1; ++i)
|
|
||||||
{
|
|
||||||
_planner_forward_pass_kernel(m_blocks[i], m_blocks[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_reverse_pass()
|
void GCodeTimeEstimator::_reverse_pass()
|
||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
if (m_blocks.size() > 1)
|
for (int i = (int)m_blocks.size() - 1; i > 0; -- i)
|
||||||
{
|
_planner_reverse_pass_kernel(m_blocks[i - 1], m_blocks[i]);
|
||||||
for (int i = (int)m_blocks.size() - 1; i >= m_last_st_synchronized_block_id + 2; --i)
|
|
||||||
{
|
|
||||||
_planner_reverse_pass_kernel(m_blocks[i - 1], m_blocks[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeTimeEstimator::_planner_forward_pass_kernel(Block& prev, Block& curr)
|
void GCodeTimeEstimator::_planner_forward_pass_kernel(Block& prev, Block& curr)
|
||||||
@ -1562,7 +1532,7 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
if (prev.feedrate.entry < curr.feedrate.entry)
|
if (prev.feedrate.entry < curr.feedrate.entry)
|
||||||
{
|
{
|
||||||
float entry_speed = std::min(curr.feedrate.entry, Block::max_allowable_speed(-prev.acceleration, prev.feedrate.entry, prev.move_length()));
|
float entry_speed = std::min(curr.feedrate.entry, Block::max_allowable_speed(-prev.acceleration, prev.feedrate.entry, prev.distance));
|
||||||
|
|
||||||
// Check for junction speed change
|
// Check for junction speed change
|
||||||
if (curr.feedrate.entry != entry_speed)
|
if (curr.feedrate.entry != entry_speed)
|
||||||
@ -1584,7 +1554,7 @@ namespace Slic3r {
|
|||||||
// If nominal length true, max junction speed is guaranteed to be reached. Only compute
|
// If nominal length true, max junction speed is guaranteed to be reached. Only compute
|
||||||
// for max allowable speed if block is decelerating and nominal length is false.
|
// for max allowable speed if block is decelerating and nominal length is false.
|
||||||
if (!curr.flags.nominal_length && (curr.max_entry_speed > next.feedrate.entry))
|
if (!curr.flags.nominal_length && (curr.max_entry_speed > next.feedrate.entry))
|
||||||
curr.feedrate.entry = std::min(curr.max_entry_speed, Block::max_allowable_speed(-curr.acceleration, next.feedrate.entry, curr.move_length()));
|
curr.feedrate.entry = std::min(curr.max_entry_speed, Block::max_allowable_speed(-curr.acceleration, next.feedrate.entry, curr.distance));
|
||||||
else
|
else
|
||||||
curr.feedrate.entry = curr.max_entry_speed;
|
curr.feedrate.entry = curr.max_entry_speed;
|
||||||
|
|
||||||
@ -1598,7 +1568,7 @@ namespace Slic3r {
|
|||||||
Block* curr = nullptr;
|
Block* curr = nullptr;
|
||||||
Block* next = nullptr;
|
Block* next = nullptr;
|
||||||
|
|
||||||
for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i)
|
for (size_t i = 0; i < m_blocks.size(); ++ i)
|
||||||
{
|
{
|
||||||
Block& b = m_blocks[i];
|
Block& b = m_blocks[i];
|
||||||
|
|
||||||
@ -1657,7 +1627,7 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
|
|
||||||
int minutes = std::round(time_in_secs / 60.);
|
int minutes = int(std::round(time_in_secs / 60.));
|
||||||
if (minutes <= 0) {
|
if (minutes <= 0) {
|
||||||
::sprintf(buffer, "%ds", (int)time_in_secs);
|
::sprintf(buffer, "%ds", (int)time_in_secs);
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,7 +85,6 @@ namespace Slic3r {
|
|||||||
// hard limit for the acceleration, to which the firmware will clamp.
|
// hard limit for the acceleration, to which the firmware will clamp.
|
||||||
float max_acceleration; // mm/s^2
|
float max_acceleration; // mm/s^2
|
||||||
float retract_acceleration; // mm/s^2
|
float retract_acceleration; // mm/s^2
|
||||||
float additional_time; // s
|
|
||||||
float minimum_feedrate; // mm/s
|
float minimum_feedrate; // mm/s
|
||||||
float minimum_travel_feedrate; // mm/s
|
float minimum_travel_feedrate; // mm/s
|
||||||
float extrude_factor_override_percentage;
|
float extrude_factor_override_percentage;
|
||||||
@ -125,14 +124,13 @@ namespace Slic3r {
|
|||||||
|
|
||||||
struct Trapezoid
|
struct Trapezoid
|
||||||
{
|
{
|
||||||
float distance; // mm
|
|
||||||
float accelerate_until; // mm
|
float accelerate_until; // mm
|
||||||
float decelerate_after; // mm
|
float decelerate_after; // mm
|
||||||
FeedrateProfile feedrate;
|
float cruise_feedrate; // mm/sec
|
||||||
|
|
||||||
float acceleration_time(float acceleration) const;
|
float acceleration_time(float entry_feedrate, float acceleration) const;
|
||||||
float cruise_time() const;
|
float cruise_time() const;
|
||||||
float deceleration_time(float acceleration) const;
|
float deceleration_time(float distance, float acceleration) const;
|
||||||
float cruise_distance() const;
|
float cruise_distance() const;
|
||||||
|
|
||||||
// This function gives the time needed to accelerate from an initial speed to reach a final distance.
|
// This function gives the time needed to accelerate from an initial speed to reach a final distance.
|
||||||
@ -153,25 +151,16 @@ namespace Slic3r {
|
|||||||
#endif // ENABLE_MOVE_STATS
|
#endif // ENABLE_MOVE_STATS
|
||||||
Flags flags;
|
Flags flags;
|
||||||
|
|
||||||
float delta_pos[Num_Axis]; // mm
|
float distance; // mm
|
||||||
float acceleration; // mm/s^2
|
float acceleration; // mm/s^2
|
||||||
float max_entry_speed; // mm/s
|
float max_entry_speed; // mm/s
|
||||||
float safe_feedrate; // mm/s
|
float safe_feedrate; // mm/s
|
||||||
|
|
||||||
FeedrateProfile feedrate;
|
FeedrateProfile feedrate;
|
||||||
Trapezoid trapezoid;
|
Trapezoid trapezoid;
|
||||||
float elapsed_time;
|
|
||||||
|
|
||||||
Block();
|
// Ordnary index of this G1 line in the file.
|
||||||
|
int g1_line_id { -1 };
|
||||||
// Returns the length of the move covered by this block, in mm
|
|
||||||
float move_length() const;
|
|
||||||
|
|
||||||
// Returns true if this block is a retract/unretract move only
|
|
||||||
float is_extruder_only_move() const;
|
|
||||||
|
|
||||||
// Returns true if this block is a move with no extrusion
|
|
||||||
float is_travel_move() const;
|
|
||||||
|
|
||||||
// Returns the time spent accelerating toward cruise speed, in seconds
|
// Returns the time spent accelerating toward cruise speed, in seconds
|
||||||
float acceleration_time() const;
|
float acceleration_time() const;
|
||||||
@ -217,16 +206,13 @@ namespace Slic3r {
|
|||||||
#endif // ENABLE_MOVE_STATS
|
#endif // ENABLE_MOVE_STATS
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<unsigned int, unsigned int> G1LineIdToBlockId;
|
typedef std::pair<int, float> G1LineIdTime;
|
||||||
typedef std::vector<G1LineIdToBlockId> G1LineIdToBlockIdMap;
|
typedef std::vector<G1LineIdTime> G1LineIdsTimes;
|
||||||
|
|
||||||
struct PostProcessData
|
struct PostProcessData
|
||||||
{
|
{
|
||||||
const G1LineIdToBlockIdMap& g1_line_ids;
|
const G1LineIdsTimes& g1_times;
|
||||||
const BlocksList& blocks;
|
|
||||||
float time;
|
float time;
|
||||||
|
|
||||||
PostProcessData(const G1LineIdToBlockIdMap& g1_line_ids, const BlocksList& blocks, float time) : g1_line_ids(g1_line_ids), blocks(blocks), time(time) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -236,10 +222,14 @@ namespace Slic3r {
|
|||||||
Feedrates m_curr;
|
Feedrates m_curr;
|
||||||
Feedrates m_prev;
|
Feedrates m_prev;
|
||||||
BlocksList m_blocks;
|
BlocksList m_blocks;
|
||||||
// Map between g1 line id and blocks id, used to speed up export of remaining times
|
// Size of the firmware planner queue. The old 8-bit Marlins usually just managed 16 trapezoidal blocks.
|
||||||
G1LineIdToBlockIdMap m_g1_line_ids;
|
// Let's be conservative and plan for newer boards with more memory.
|
||||||
// Index of the last block already st_synchronized
|
static constexpr size_t planner_queue_size = 64;
|
||||||
int m_last_st_synchronized_block_id;
|
// The firmware recalculates last planner_queue_size trapezoidal blocks each time a new block is added.
|
||||||
|
// We are not simulating the firmware exactly, we calculate a sequence of blocks once a reasonable number of blocks accumulate.
|
||||||
|
static constexpr size_t planner_refresh_if_larger = planner_queue_size * 4;
|
||||||
|
// Map from g1 line id to its elapsed time from the start of the print.
|
||||||
|
G1LineIdsTimes m_g1_times;
|
||||||
float m_time; // s
|
float m_time; // s
|
||||||
|
|
||||||
// data to calculate custom code times
|
// data to calculate custom code times
|
||||||
@ -267,13 +257,13 @@ namespace Slic3r {
|
|||||||
void calculate_time(bool start_from_beginning);
|
void calculate_time(bool start_from_beginning);
|
||||||
|
|
||||||
// Calculates the time estimate from the given gcode in string format
|
// Calculates the time estimate from the given gcode in string format
|
||||||
void calculate_time_from_text(const std::string& gcode);
|
//void calculate_time_from_text(const std::string& gcode);
|
||||||
|
|
||||||
// Calculates the time estimate from the gcode contained in the file with the given filename
|
// Calculates the time estimate from the gcode contained in the file with the given filename
|
||||||
void calculate_time_from_file(const std::string& file);
|
//void calculate_time_from_file(const std::string& file);
|
||||||
|
|
||||||
// Calculates the time estimate from the gcode contained in given list of gcode lines
|
// Calculates the time estimate from the gcode contained in given list of gcode lines
|
||||||
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
|
//void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
|
||||||
|
|
||||||
// Process the gcode contained in the file with the given filename,
|
// Process the gcode contained in the file with the given filename,
|
||||||
// replacing placeholders with correspondent new lines M73
|
// replacing placeholders with correspondent new lines M73
|
||||||
@ -350,10 +340,6 @@ namespace Slic3r {
|
|||||||
unsigned int get_extruder_id() const;
|
unsigned int get_extruder_id() const;
|
||||||
void reset_extruder_id();
|
void reset_extruder_id();
|
||||||
|
|
||||||
void add_additional_time(float timeSec);
|
|
||||||
void set_additional_time(float timeSec);
|
|
||||||
float get_additional_time() const;
|
|
||||||
|
|
||||||
void set_default();
|
void set_default();
|
||||||
|
|
||||||
// Call this method before to start adding lines using add_gcode_line() when reusing an instance of GCodeTimeEstimator
|
// Call this method before to start adding lines using add_gcode_line() when reusing an instance of GCodeTimeEstimator
|
||||||
@ -389,7 +375,7 @@ namespace Slic3r {
|
|||||||
// Return an estimate of the memory consumed by the time estimator.
|
// Return an estimate of the memory consumed by the time estimator.
|
||||||
size_t memory_used() const;
|
size_t memory_used() const;
|
||||||
|
|
||||||
PostProcessData get_post_process_data() const { return PostProcessData(m_g1_line_ids, m_blocks, m_time); }
|
PostProcessData get_post_process_data() const { return PostProcessData{ m_g1_times, m_time }; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _reset();
|
void _reset();
|
||||||
@ -397,7 +383,7 @@ namespace Slic3r {
|
|||||||
void _reset_blocks();
|
void _reset_blocks();
|
||||||
|
|
||||||
// Calculates the time estimate
|
// Calculates the time estimate
|
||||||
void _calculate_time();
|
void _calculate_time(size_t keep_last_n_blocks);
|
||||||
|
|
||||||
// Processes the given gcode line
|
// Processes the given gcode line
|
||||||
void _process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line);
|
void _process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line);
|
||||||
@ -470,7 +456,7 @@ namespace Slic3r {
|
|||||||
void _process_custom_gcode_tag(CustomGcodeType code);
|
void _process_custom_gcode_tag(CustomGcodeType code);
|
||||||
|
|
||||||
// Simulates firmware st_synchronize() call
|
// Simulates firmware st_synchronize() call
|
||||||
void _simulate_st_synchronize();
|
void _simulate_st_synchronize(float additional_time);
|
||||||
|
|
||||||
void _forward_pass();
|
void _forward_pass();
|
||||||
void _reverse_pass();
|
void _reverse_pass();
|
||||||
|
@ -419,7 +419,7 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb)
|
|||||||
if (input[i].bed_idx != 0) ret = false;
|
if (input[i].bed_idx != 0) ret = false;
|
||||||
if (input[i].bed_idx >= 0) {
|
if (input[i].bed_idx >= 0) {
|
||||||
input[i].translation += Vec2crd{input[i].bed_idx * stride, 0};
|
input[i].translation += Vec2crd{input[i].bed_idx * stride, 0};
|
||||||
instances[i]->apply_arrange_result(input[i].translation,
|
instances[i]->apply_arrange_result(input[i].translation.cast<double>(),
|
||||||
input[i].rotation);
|
input[i].rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,7 +668,7 @@ public:
|
|||||||
arrangement::ArrangePolygon get_arrange_polygon() const;
|
arrangement::ArrangePolygon get_arrange_polygon() const;
|
||||||
|
|
||||||
// Apply the arrange result on the ModelInstance
|
// Apply the arrange result on the ModelInstance
|
||||||
void apply_arrange_result(const Vec2crd& offs, double rotation)
|
void apply_arrange_result(const Vec2d& offs, double rotation)
|
||||||
{
|
{
|
||||||
// write the transformation data into the model instance
|
// write the transformation data into the model instance
|
||||||
set_rotation(Z, rotation);
|
set_rotation(Z, rotation);
|
||||||
|
@ -44,19 +44,15 @@
|
|||||||
// Enable fix for dragging mouse event handling for gizmobar
|
// Enable fix for dragging mouse event handling for gizmobar
|
||||||
#define ENABLE_GIZMO_TOOLBAR_DRAGGING_FIX (1 && ENABLE_2_2_0_FINAL)
|
#define ENABLE_GIZMO_TOOLBAR_DRAGGING_FIX (1 && ENABLE_2_2_0_FINAL)
|
||||||
|
|
||||||
//============
|
|
||||||
// 2.3.0 techs
|
|
||||||
//============
|
|
||||||
#define ENABLE_2_3_0 1
|
|
||||||
|
|
||||||
// Enable rendering of objects colored by facets' slope
|
|
||||||
#define ENABLE_SLOPE_RENDERING (1 && ENABLE_2_3_0)
|
|
||||||
|
|
||||||
//===================
|
//===================
|
||||||
// 2.3.0.alpha1 techs
|
// 2.3.0.alpha1 techs
|
||||||
//===================
|
//===================
|
||||||
#define ENABLE_2_3_0_ALPHA1 1
|
#define ENABLE_2_3_0_ALPHA1 1
|
||||||
|
|
||||||
|
// Enable rendering of objects colored by facets' slope
|
||||||
|
#define ENABLE_SLOPE_RENDERING (1 && ENABLE_2_3_0_ALPHA1)
|
||||||
|
|
||||||
// Moves GLCanvas3DManager from being a static member of _3DScene to be a normal member of GUI_App
|
// Moves GLCanvas3DManager from being a static member of _3DScene to be a normal member of GUI_App
|
||||||
#define ENABLE_NON_STATIC_CANVAS_MANAGER (1 && ENABLE_2_3_0_ALPHA1)
|
#define ENABLE_NON_STATIC_CANVAS_MANAGER (1 && ENABLE_2_3_0_ALPHA1)
|
||||||
|
|
||||||
|
57
src/libslic3r/format.hpp
Normal file
57
src/libslic3r/format.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef slic3r_format_hpp_
|
||||||
|
#define slic3r_format_hpp_
|
||||||
|
|
||||||
|
// Functional wrapper around boost::format.
|
||||||
|
// One day we may replace this wrapper with C++20 format
|
||||||
|
// https://en.cppreference.com/w/cpp/utility/format/format
|
||||||
|
// though C++20 format uses a different template pattern for position independent parameters.
|
||||||
|
//
|
||||||
|
// Boost::format works around the missing variadic templates by an ugly % chaining operator. The usage of boost::format looks like this:
|
||||||
|
// (boost::format("template") % arg1 %arg2).str()
|
||||||
|
// This wrapper allows for a nicer syntax:
|
||||||
|
// Slic3r::format("template", arg1, arg2)
|
||||||
|
// One can also override Slic3r::internal::format::cook() function to convert a Slic3r::format() argument to something that
|
||||||
|
// boost::format may convert to string, see slic3r/GUI/I18N.hpp for a "cook" function to convert wxString to UTF8.
|
||||||
|
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// https://gist.github.com/gchudnov/6a90d51af004d97337ec
|
||||||
|
namespace internal {
|
||||||
|
namespace format {
|
||||||
|
// Default "cook" function - just forward.
|
||||||
|
template<typename T>
|
||||||
|
inline T&& cook(T&& arg) {
|
||||||
|
return std::forward<T>(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of the recursive chain.
|
||||||
|
inline std::string format_recursive(boost::format& message) {
|
||||||
|
return message.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TValue, typename... TArgs>
|
||||||
|
std::string format_recursive(boost::format& message, TValue&& arg, TArgs&&... args) {
|
||||||
|
// Format, possibly convert the argument by the "cook" function.
|
||||||
|
message % cook(std::forward<TValue>(arg));
|
||||||
|
return format_recursive(message, std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... TArgs>
|
||||||
|
inline std::string format(const char* fmt, TArgs&&... args) {
|
||||||
|
boost::format message(fmt);
|
||||||
|
return internal::format::format_recursive(message, std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... TArgs>
|
||||||
|
inline std::string format(const std::string& fmt, TArgs&&... args) {
|
||||||
|
boost::format message(fmt);
|
||||||
|
return internal::format::format_recursive(message, std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // slic3r_format_hpp_
|
@ -111,6 +111,7 @@
|
|||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "Config.hpp"
|
#include "Config.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "MultiPoint.hpp"
|
#include "MultiPoint.hpp"
|
||||||
#include "Point.hpp"
|
#include "Point.hpp"
|
||||||
|
@ -22,6 +22,7 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/ConfigSnapshotDialog.hpp
|
GUI/ConfigSnapshotDialog.hpp
|
||||||
GUI/3DScene.cpp
|
GUI/3DScene.cpp
|
||||||
GUI/3DScene.hpp
|
GUI/3DScene.hpp
|
||||||
|
GUI/format.hpp
|
||||||
GUI/GLShader.cpp
|
GUI/GLShader.cpp
|
||||||
GUI/GLShader.hpp
|
GUI/GLShader.hpp
|
||||||
GUI/GLCanvas3D.hpp
|
GUI/GLCanvas3D.hpp
|
||||||
|
@ -655,11 +655,11 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
|||||||
|
|
||||||
GLint print_box_min_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.min") : -1;
|
GLint print_box_min_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.min") : -1;
|
||||||
GLint print_box_max_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.max") : -1;
|
GLint print_box_max_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.max") : -1;
|
||||||
GLint print_box_active_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.active") : -1;
|
GLint print_box_active_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.actived") : -1;
|
||||||
GLint print_box_worldmatrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1;
|
GLint print_box_worldmatrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1;
|
||||||
|
|
||||||
#if ENABLE_SLOPE_RENDERING
|
#if ENABLE_SLOPE_RENDERING
|
||||||
GLint slope_active_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.active") : -1;
|
GLint slope_active_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.actived") : -1;
|
||||||
GLint slope_normal_matrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.volume_world_normal_matrix") : -1;
|
GLint slope_normal_matrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.volume_world_normal_matrix") : -1;
|
||||||
GLint slope_z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.z_range") : -1;
|
GLint slope_z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.z_range") : -1;
|
||||||
#endif // ENABLE_SLOPE_RENDERING
|
#endif // ENABLE_SLOPE_RENDERING
|
||||||
|
@ -74,6 +74,8 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf
|
|||||||
ConfigOptionDef def;
|
ConfigOptionDef def;
|
||||||
def.type = coPoints;
|
def.type = coPoints;
|
||||||
def.set_default_value(new ConfigOptionPoints{ Vec2d(200, 200) });
|
def.set_default_value(new ConfigOptionPoints{ Vec2d(200, 200) });
|
||||||
|
def.min = 0;
|
||||||
|
def.max = 1200;
|
||||||
def.label = L("Size");
|
def.label = L("Size");
|
||||||
def.tooltip = L("Size in X and Y of the rectangular plate.");
|
def.tooltip = L("Size in X and Y of the rectangular plate.");
|
||||||
Option option(def, "rect_size");
|
Option option(def, "rect_size");
|
||||||
@ -81,6 +83,8 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf
|
|||||||
|
|
||||||
def.type = coPoints;
|
def.type = coPoints;
|
||||||
def.set_default_value(new ConfigOptionPoints{ Vec2d(0, 0) });
|
def.set_default_value(new ConfigOptionPoints{ Vec2d(0, 0) });
|
||||||
|
def.min = -600;
|
||||||
|
def.max = 600;
|
||||||
def.label = L("Origin");
|
def.label = L("Origin");
|
||||||
def.tooltip = L("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle.");
|
def.tooltip = L("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle.");
|
||||||
option = Option(def, "rect_origin");
|
option = Option(def, "rect_origin");
|
||||||
|
@ -20,11 +20,13 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include "Field.hpp"
|
#include "Field.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
using GUI::from_u8;
|
using GUI::from_u8;
|
||||||
using GUI::into_u8;
|
using GUI::into_u8;
|
||||||
|
using GUI::format_wxstr;
|
||||||
|
|
||||||
namespace DoubleSlider {
|
namespace DoubleSlider {
|
||||||
|
|
||||||
@ -530,7 +532,7 @@ wxString Control::get_label(int tick) const
|
|||||||
const wxString str = m_values.empty() ?
|
const wxString str = m_values.empty() ?
|
||||||
wxNumberFormatter::ToString(m_label_koef*value, 2, wxNumberFormatter::Style_None) :
|
wxNumberFormatter::ToString(m_label_koef*value, 2, wxNumberFormatter::Style_None) :
|
||||||
wxNumberFormatter::ToString(m_values[value], 2, wxNumberFormatter::Style_None);
|
wxNumberFormatter::ToString(m_values[value], 2, wxNumberFormatter::Style_None);
|
||||||
return from_u8((boost::format("%1%\n(%2%)") % str % (m_values.empty() ? value : value+1)).str());
|
return format_wxstr("%1%\n(%2%)", str, m_values.empty() ? value : value+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side/*=true*/) const
|
void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side/*=true*/) const
|
||||||
@ -1001,16 +1003,16 @@ wxString Control::get_tooltip(int tick/*=-1*/)
|
|||||||
|
|
||||||
// Show custom Gcode as a first string of tooltop
|
// Show custom Gcode as a first string of tooltop
|
||||||
tooltip = " ";
|
tooltip = " ";
|
||||||
tooltip += tick_code_it->gcode == ColorChangeCode ? ( m_mode == t_mode::SingleExtruder ?
|
tooltip +=
|
||||||
from_u8((boost::format(_utf8(L("Color change (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
tick_code_it->gcode == ColorChangeCode ?
|
||||||
from_u8((boost::format(_utf8(L("Color change (\"%1%\") for Extruder %2%"))) %
|
(m_mode == t_mode::SingleExtruder ?
|
||||||
tick_code_it->gcode % tick_code_it->extruder).str()) ) :
|
format_wxstr(_L("Color change (\"%1%\")"), tick_code_it->gcode) :
|
||||||
tick_code_it->gcode == PausePrintCode ?
|
format_wxstr(_L("Color change (\"%1%\") for Extruder %2%"), tick_code_it->gcode, tick_code_it->extruder)) :
|
||||||
from_u8((boost::format(_utf8(L("Pause print (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
tick_code_it->gcode == PausePrintCode ?
|
||||||
tick_code_it->gcode == ToolChangeCode ?
|
format_wxstr(_L("Pause print (\"%1%\")"), tick_code_it->gcode) :
|
||||||
from_u8((boost::format(_utf8(L("Extruder (tool) is changed to Extruder \"%1%\""))) %
|
tick_code_it->gcode == ToolChangeCode ?
|
||||||
tick_code_it->extruder ).str()) :
|
format_wxstr(_L("Extruder (tool) is changed to Extruder \"%1%\""), tick_code_it->extruder) :
|
||||||
from_u8(tick_code_it->gcode);
|
from_u8(tick_code_it->gcode);
|
||||||
|
|
||||||
// If tick is marked as a conflict (exclamation icon),
|
// If tick is marked as a conflict (exclamation icon),
|
||||||
// we should to explain why
|
// we should to explain why
|
||||||
@ -1176,8 +1178,8 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wxString menu_name = switch_current_code ?
|
const wxString menu_name = switch_current_code ?
|
||||||
from_u8((boost::format(_utf8(L("Switch code to Color change (%1%) for:"))) % ColorChangeCode).str()) :
|
format_wxstr(_L("Switch code to Color change (%1%) for:"), ColorChangeCode) :
|
||||||
from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % ColorChangeCode).str());
|
format_wxstr(_L("Add color change (%1%) for:"), ColorChangeCode);
|
||||||
wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, "");
|
wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, "");
|
||||||
add_color_change_menu_item->SetBitmap(create_scaled_bitmap("colorchange_add_m"));
|
add_color_change_menu_item->SetBitmap(create_scaled_bitmap("colorchange_add_m"));
|
||||||
}
|
}
|
||||||
@ -1615,8 +1617,8 @@ static void upgrade_text_entry_dialog(wxTextEntryDialog* dlg, double min = -1.0,
|
|||||||
|
|
||||||
static std::string get_custom_code(const std::string& code_in, double height)
|
static std::string get_custom_code(const std::string& code_in, double height)
|
||||||
{
|
{
|
||||||
wxString msg_text = from_u8(_utf8(L("Enter custom G-code used on current layer"))) + ":";
|
wxString msg_text = _L("Enter custom G-code used on current layer") + ":";
|
||||||
wxString msg_header = from_u8((boost::format(_utf8(L("Custom G-code on current layer (%1% mm)."))) % height).str());
|
wxString msg_header = format_wxstr(_L("Custom G-code on current layer (%1% mm)."), height);
|
||||||
|
|
||||||
// get custom gcode
|
// get custom gcode
|
||||||
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, code_in,
|
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, code_in,
|
||||||
@ -1631,8 +1633,8 @@ static std::string get_custom_code(const std::string& code_in, double height)
|
|||||||
|
|
||||||
static std::string get_pause_print_msg(const std::string& msg_in, double height)
|
static std::string get_pause_print_msg(const std::string& msg_in, double height)
|
||||||
{
|
{
|
||||||
wxString msg_text = from_u8(_utf8(L("Enter short message shown on Printer display when a print is paused"))) + ":";
|
wxString msg_text = _L("Enter short message shown on Printer display when a print is paused") + ":";
|
||||||
wxString msg_header = from_u8((boost::format(_utf8(L("Message for pause print on current layer (%1% mm)."))) % height).str());
|
wxString msg_header = format_wxstr(_L("Message for pause print on current layer (%1% mm)."), height);
|
||||||
|
|
||||||
// get custom gcode
|
// get custom gcode
|
||||||
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, from_u8(msg_in),
|
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, from_u8(msg_in),
|
||||||
|
@ -1242,12 +1242,24 @@ void PointCtrl::msw_rescale(bool rescale_sidetext/* = false*/)
|
|||||||
y_textctrl->SetMinSize(field_size);
|
y_textctrl->SetMinSize(field_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PointCtrl::value_was_changed(wxTextCtrl* win)
|
||||||
|
{
|
||||||
|
if (m_value.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
boost::any val = m_value;
|
||||||
|
// update m_value!
|
||||||
|
get_value();
|
||||||
|
|
||||||
|
return boost::any_cast<Vec2d>(m_value) != boost::any_cast<Vec2d>(val);
|
||||||
|
}
|
||||||
|
|
||||||
void PointCtrl::propagate_value(wxTextCtrl* win)
|
void PointCtrl::propagate_value(wxTextCtrl* win)
|
||||||
{
|
{
|
||||||
if (!win->GetValue().empty())
|
if (win->GetValue().empty())
|
||||||
on_change_field();
|
|
||||||
else
|
|
||||||
on_kill_focus();
|
on_kill_focus();
|
||||||
|
else if (value_was_changed(win))
|
||||||
|
on_change_field();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointCtrl::set_value(const Vec2d& value, bool change_event)
|
void PointCtrl::set_value(const Vec2d& value, bool change_event)
|
||||||
@ -1281,6 +1293,19 @@ boost::any& PointCtrl::get_value()
|
|||||||
double x, y;
|
double x, y;
|
||||||
x_textctrl->GetValue().ToDouble(&x);
|
x_textctrl->GetValue().ToDouble(&x);
|
||||||
y_textctrl->GetValue().ToDouble(&y);
|
y_textctrl->GetValue().ToDouble(&y);
|
||||||
|
|
||||||
|
if (m_opt.min > x || x > m_opt.max ||
|
||||||
|
m_opt.min > y || y > m_opt.max)
|
||||||
|
{
|
||||||
|
if (m_opt.min > x) x = m_opt.min;
|
||||||
|
if (x > m_opt.max) x = m_opt.max;
|
||||||
|
if (m_opt.min > y) y = m_opt.min;
|
||||||
|
if (y > m_opt.max) y = m_opt.max;
|
||||||
|
set_value(Vec2d(x, y), true);
|
||||||
|
|
||||||
|
show_error(m_parent, _(L("Input value is out of range")));
|
||||||
|
}
|
||||||
|
|
||||||
return m_value = Vec2d(x, y);
|
return m_value = Vec2d(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +445,7 @@ public:
|
|||||||
wxTextCtrl* y_textctrl{ nullptr };
|
wxTextCtrl* y_textctrl{ nullptr };
|
||||||
|
|
||||||
void BUILD() override;
|
void BUILD() override;
|
||||||
|
bool value_was_changed(wxTextCtrl* win);
|
||||||
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
||||||
void propagate_value(wxTextCtrl* win);
|
void propagate_value(wxTextCtrl* win);
|
||||||
void set_value(const Vec2d& value, bool change_event = false);
|
void set_value(const Vec2d& value, bool change_event = false);
|
||||||
|
@ -1825,14 +1825,12 @@ void GLCanvas3D::set_color_by(const std::string& value)
|
|||||||
m_color_by = value;
|
m_color_by = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
void GLCanvas3D::refresh_camera_scene_box()
|
void GLCanvas3D::refresh_camera_scene_box()
|
||||||
{
|
{
|
||||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
||||||
wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box());
|
wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box());
|
||||||
#else
|
|
||||||
m_camera.set_scene_box(scene_bounding_box());
|
|
||||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const
|
BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const
|
||||||
{
|
{
|
||||||
@ -3014,18 +3012,15 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||||||
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
|
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __linux__
|
||||||
case 'm':
|
|
||||||
case 'M':
|
|
||||||
#else /* __APPLE__ */
|
|
||||||
case WXK_CONTROL_M:
|
case WXK_CONTROL_M:
|
||||||
#endif /* __APPLE__ */
|
{
|
||||||
{
|
Mouse3DController& controller = wxGetApp().plater()->get_mouse3d_controller();
|
||||||
Mouse3DController& controller = wxGetApp().plater()->get_mouse3d_controller();
|
controller.show_settings_dialog(!controller.is_settings_dialog_shown());
|
||||||
controller.show_settings_dialog(!controller.is_settings_dialog_shown());
|
m_dirty = true;
|
||||||
m_dirty = true;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -6608,7 +6603,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
|||||||
case GCodePreviewData::Extrusion::FanSpeed:
|
case GCodePreviewData::Extrusion::FanSpeed:
|
||||||
return path.fan_speed;
|
return path.fan_speed;
|
||||||
case GCodePreviewData::Extrusion::VolumetricRate:
|
case GCodePreviewData::Extrusion::VolumetricRate:
|
||||||
return path.feedrate * (float)path.mm3_per_mm;
|
return path.feedrate * path.mm3_per_mm;
|
||||||
case GCodePreviewData::Extrusion::Tool:
|
case GCodePreviewData::Extrusion::Tool:
|
||||||
return (float)path.extruder_id;
|
return (float)path.extruder_id;
|
||||||
case GCodePreviewData::Extrusion::ColorPrint:
|
case GCodePreviewData::Extrusion::ColorPrint:
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#include "GUI_ObjectLayers.hpp"
|
#include "GUI_ObjectLayers.hpp"
|
||||||
#include "GLSelectionRectangle.hpp"
|
#include "GLSelectionRectangle.hpp"
|
||||||
#include "MeshUtils.hpp"
|
#include "MeshUtils.hpp"
|
||||||
|
#if !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
#include "Camera.hpp"
|
||||||
|
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include "SysInfoDialog.hpp"
|
#include "SysInfoDialog.hpp"
|
||||||
#include "KBShortcutsDialog.hpp"
|
#include "KBShortcutsDialog.hpp"
|
||||||
#include "UpdateDialogs.hpp"
|
#include "UpdateDialogs.hpp"
|
||||||
|
#include "Mouse3DController.hpp"
|
||||||
#include "RemovableDriveManager.hpp"
|
#include "RemovableDriveManager.hpp"
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
@ -193,6 +194,20 @@ static void register_win32_device_notification_event()
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
wxWindow::MSWRegisterMessageHandler(WM_INPUT, [](wxWindow *win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) {
|
||||||
|
auto main_frame = dynamic_cast<MainFrame*>(Slic3r::GUI::find_toplevel_parent(win));
|
||||||
|
auto plater = (main_frame == nullptr) ? nullptr : main_frame->plater();
|
||||||
|
// if (wParam == RIM_INPUTSINK && plater != nullptr && main_frame->IsActive()) {
|
||||||
|
if (wParam == RIM_INPUT && plater != nullptr && main_frame->IsActive()) {
|
||||||
|
RAWINPUT raw;
|
||||||
|
UINT rawSize = sizeof(RAWINPUT);
|
||||||
|
::GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &raw, &rawSize, sizeof(RAWINPUTHEADER));
|
||||||
|
if (raw.header.dwType == RIM_TYPEHID && plater->get_mouse3d_controller().handle_raw_input_win32(raw.data.hid.bRawData, raw.data.hid.dwSizeHid))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
|
@ -185,10 +185,12 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
{ "Z", L("Zoom to selected object\nor all objects in scene, if none selected") },
|
{ "Z", L("Zoom to selected object\nor all objects in scene, if none selected") },
|
||||||
{ "I", L("Zoom in") },
|
{ "I", L("Zoom in") },
|
||||||
{ "O", L("Zoom out") },
|
{ "O", L("Zoom out") },
|
||||||
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") }
|
#ifdef __linux__
|
||||||
|
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
|
||||||
|
#endif // __linux__
|
||||||
#if ENABLE_RENDER_PICKING_PASS
|
#if ENABLE_RENDER_PICKING_PASS
|
||||||
// Don't localize debugging texts.
|
// Don't localize debugging texts.
|
||||||
, { "T", "Toggle picking pass texture rendering on/off" }
|
{ "T", "Toggle picking pass texture rendering on/off" },
|
||||||
#endif // ENABLE_RENDER_PICKING_PASS
|
#endif // ENABLE_RENDER_PICKING_PASS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,6 +152,16 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||||||
// Failed to get desktop location
|
// Failed to get desktop location
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
static constexpr int device_count = 1;
|
||||||
|
RAWINPUTDEVICE devices[device_count] = { 0 };
|
||||||
|
// multi-axis mouse (SpaceNavigator, etc.)
|
||||||
|
devices[0].usUsagePage = 0x01;
|
||||||
|
devices[0].usUsage = 0x08;
|
||||||
|
if (! RegisterRawInputDevices(devices, device_count, sizeof(RAWINPUTDEVICE)))
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "RegisterRawInputDevices failed";
|
||||||
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
// propagate event
|
// propagate event
|
||||||
@ -204,6 +214,10 @@ void MainFrame::shutdown()
|
|||||||
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
|
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
|
||||||
// causing a crash
|
// causing a crash
|
||||||
if (m_plater) m_plater->unbind_canvas_event_handlers();
|
if (m_plater) m_plater->unbind_canvas_event_handlers();
|
||||||
|
|
||||||
|
// Cleanup of canvases' volumes needs to be done here or a crash may happen on some Linux Debian flavours
|
||||||
|
// see: https://github.com/prusa3d/PrusaSlicer/issues/3964
|
||||||
|
if (m_plater) m_plater->reset_canvas_volumes();
|
||||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
// Weird things happen as the Paint messages are floating around the windows being destructed.
|
// Weird things happen as the Paint messages are floating around the windows being destructed.
|
||||||
|
@ -484,7 +484,10 @@ void Mouse3DController::init()
|
|||||||
assert(! m_thread.joinable());
|
assert(! m_thread.joinable());
|
||||||
if (! m_thread.joinable()) {
|
if (! m_thread.joinable()) {
|
||||||
m_stop = false;
|
m_stop = false;
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Don't start the background thread on Windows, as the HID messages are sent as Windows messages.
|
||||||
m_thread = std::thread(&Mouse3DController::run, this);
|
m_thread = std::thread(&Mouse3DController::run, this);
|
||||||
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,7 +603,10 @@ bool Mouse3DController::connect_device()
|
|||||||
: path(path), usage_page(usage_page), usage(usage)
|
: path(path), usage_page(usage_page), usage(usage)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool has_valid_usage() const { return (usage_page == 1) && (usage == 8); }
|
// https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
|
||||||
|
// Usage page 1 - Generic Desktop Controls
|
||||||
|
// Usage page 1, usage 8 - Multi-axis Controller
|
||||||
|
bool has_valid_usage() const { return usage_page == 1 && usage == 8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
||||||
@ -688,7 +694,7 @@ bool Mouse3DController::connect_device()
|
|||||||
if (detected_devices.empty())
|
if (detected_devices.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string path = "";
|
std::string path;
|
||||||
unsigned short vendor_id = 0;
|
unsigned short vendor_id = 0;
|
||||||
unsigned short product_id = 0;
|
unsigned short product_id = 0;
|
||||||
|
|
||||||
@ -865,45 +871,60 @@ void Mouse3DController::collect_input()
|
|||||||
this->handle_input(packet, res, m_params, m_state);
|
this->handle_input(packet, res, m_params, m_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by the worker thread.
|
#ifdef _WIN32
|
||||||
bool Mouse3DController::handle_input(const DataPacketRaw& packet, const int packet_lenght, const Params ¶ms, State &state_in_out)
|
bool Mouse3DController::handle_raw_input_win32(const unsigned char *data, const int packet_length)
|
||||||
{
|
{
|
||||||
if (! wxGetApp().IsActive())
|
if (! wxGetApp().IsActive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int res = packet_lenght;
|
if (packet_length == 7 || packet_length == 13) {
|
||||||
|
DataPacketRaw packet;
|
||||||
|
memcpy(packet.data(), data, packet_length);
|
||||||
|
handle_packet(packet, packet_length, m_params, m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by the worker thread.
|
||||||
|
bool Mouse3DController::handle_input(const DataPacketRaw& packet, const int packet_length, const Params ¶ms, State &state_in_out)
|
||||||
|
{
|
||||||
|
if (! wxGetApp().IsActive())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int res = packet_length;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
|
|
||||||
if (res == 7)
|
if (res == 7 || res == 13 ||
|
||||||
updated = handle_packet(packet, params, state_in_out);
|
|
||||||
else if (res == 13)
|
|
||||||
updated = handle_wireless_packet(packet, params, state_in_out);
|
|
||||||
else if ((res == 3) && (packet[0] == 3))
|
|
||||||
// On Mac button packets can be 3 bytes long
|
// On Mac button packets can be 3 bytes long
|
||||||
updated = handle_packet(packet, params, state_in_out);
|
((res == 3) && (packet[0] == 3)))
|
||||||
|
updated = handle_packet(packet, res, params, state_in_out);
|
||||||
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
||||||
else if (res > 0)
|
else if (res > 0)
|
||||||
std::cout << "Got unknown data packet of length: " << res << ", code:" << (int)packet[0] << std::endl;
|
std::cout << "Got unknown data packet of length: " << res << ", code:" << (int)packet[0] << std::endl;
|
||||||
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (updated) {
|
if (updated) {
|
||||||
wxGetApp().plater()->set_current_canvas_as_dirty();
|
wxGetApp().plater()->set_current_canvas_as_dirty();
|
||||||
// ask for an idle event to update 3D scene
|
// ask for an idle event to update 3D scene
|
||||||
wxWakeUpIdle();
|
wxWakeUpIdle();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by handle_input() from the worker thread.
|
// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by handle_input() from the worker thread.
|
||||||
bool Mouse3DController::handle_packet(const DataPacketRaw& packet, const Params ¶ms, State &state_in_out)
|
bool Mouse3DController::handle_packet(const DataPacketRaw& packet, const int packet_length, const Params ¶ms, State &state_in_out)
|
||||||
{
|
{
|
||||||
switch (packet[0])
|
switch (packet[0])
|
||||||
{
|
{
|
||||||
case 1: // Translation
|
case 1: // Translation + Rotation
|
||||||
{
|
{
|
||||||
if (handle_packet_translation(packet, params, state_in_out))
|
bool updated = handle_packet_translation(packet, params, state_in_out);
|
||||||
|
if (packet_length == 13)
|
||||||
|
updated |= handle_packet_rotation(packet, 7, params, state_in_out);
|
||||||
|
|
||||||
|
if (updated)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -941,47 +962,6 @@ bool Mouse3DController::handle_packet(const DataPacketRaw& packet, const Params
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack raw 3DConnexion HID packet of a wireless 3D mouse into m_state. Called by handle_input() from the worker thread.
|
|
||||||
bool Mouse3DController::handle_wireless_packet(const DataPacketRaw& packet, const Params ¶ms, State &state_in_out)
|
|
||||||
{
|
|
||||||
switch (packet[0])
|
|
||||||
{
|
|
||||||
case 1: // Translation + Rotation
|
|
||||||
{
|
|
||||||
bool updated = handle_packet_translation(packet, params, state_in_out);
|
|
||||||
updated |= handle_packet_rotation(packet, 7, params, state_in_out);
|
|
||||||
|
|
||||||
if (updated)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // Button
|
|
||||||
{
|
|
||||||
if (params.buttons_enabled && handle_packet_button(packet, 12, params, state_in_out))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 23: // Battery charge
|
|
||||||
{
|
|
||||||
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
|
||||||
std::cout << "3DConnexion - battery level: " << (int)packet[1] << " percent" << std::endl;
|
|
||||||
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
|
||||||
std::cout << "3DConnexion - Got unknown data packet of code: " << (int)packet[0] << std::endl;
|
|
||||||
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a signed 16bit word from a 3DConnexion mouse HID packet into a double coordinate, apply a dead zone.
|
// Convert a signed 16bit word from a 3DConnexion mouse HID packet into a double coordinate, apply a dead zone.
|
||||||
static double convert_input(int coord_byte_low, int coord_byte_high, double deadzone)
|
static double convert_input(int coord_byte_low, int coord_byte_high, double deadzone)
|
||||||
{
|
{
|
||||||
|
@ -190,6 +190,8 @@ public:
|
|||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
bool handle_raw_input_win32(const unsigned char *data, const int packet_lenght);
|
||||||
|
|
||||||
// Called by Win32 HID enumeration callback.
|
// Called by Win32 HID enumeration callback.
|
||||||
void device_attached(const std::string &device);
|
void device_attached(const std::string &device);
|
||||||
|
|
||||||
@ -218,10 +220,9 @@ private:
|
|||||||
typedef std::array<unsigned char, 13> DataPacketRaw;
|
typedef std::array<unsigned char, 13> DataPacketRaw;
|
||||||
|
|
||||||
// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by the worker thread.
|
// Unpack raw 3DConnexion HID packet of a wired 3D mouse into m_state. Called by the worker thread.
|
||||||
static bool handle_input(const DataPacketRaw& packet, const int packet_lenght, const Params ¶ms, State &state_in_out);
|
static bool handle_input(const DataPacketRaw& packet, const int packet_length, const Params ¶ms, State &state_in_out);
|
||||||
// The following is called by handle_input() from the worker thread.
|
// The following is called by handle_input() from the worker thread.
|
||||||
static bool handle_packet(const DataPacketRaw& packet, const Params ¶ms, State &state_in_out);
|
static bool handle_packet(const DataPacketRaw& packet, const int packet_length, const Params ¶ms, State &state_in_out);
|
||||||
static bool handle_wireless_packet(const DataPacketRaw& packet, const Params ¶ms, State &state_in_out);
|
|
||||||
static bool handle_packet_translation(const DataPacketRaw& packet, const Params ¶ms, State &state_in_out);
|
static bool handle_packet_translation(const DataPacketRaw& packet, const Params ¶ms, State &state_in_out);
|
||||||
static bool handle_packet_rotation(const DataPacketRaw& packet, unsigned int first_byte, const Params ¶ms, State &state_in_out);
|
static bool handle_packet_rotation(const DataPacketRaw& packet, unsigned int first_byte, const Params ¶ms, State &state_in_out);
|
||||||
static bool handle_packet_button(const DataPacketRaw& packet, unsigned int packet_size, const Params ¶ms, State &state_in_out);
|
static bool handle_packet_button(const DataPacketRaw& packet, unsigned int packet_size, const Params ¶ms, State &state_in_out);
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
#include "wxExtensions.hpp"
|
#include "wxExtensions.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "GLCanvas3D.hpp"
|
#include "GLCanvas3D.hpp"
|
||||||
#include "Selection.hpp"
|
#include "Selection.hpp"
|
||||||
@ -96,6 +97,7 @@ namespace fs = boost::filesystem;
|
|||||||
using Slic3r::_3DScene;
|
using Slic3r::_3DScene;
|
||||||
using Slic3r::Preset;
|
using Slic3r::Preset;
|
||||||
using Slic3r::PrintHostJob;
|
using Slic3r::PrintHostJob;
|
||||||
|
using Slic3r::GUI::format_wxstr;
|
||||||
|
|
||||||
static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 256, 256 };
|
static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 256, 256 };
|
||||||
|
|
||||||
@ -140,7 +142,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ObjectInfo::ObjectInfo(wxWindow *parent) :
|
ObjectInfo::ObjectInfo(wxWindow *parent) :
|
||||||
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Info"))), wxVERTICAL)
|
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _L("Info")), wxVERTICAL)
|
||||||
{
|
{
|
||||||
GetStaticBox()->SetFont(wxGetApp().bold_font());
|
GetStaticBox()->SetFont(wxGetApp().bold_font());
|
||||||
|
|
||||||
@ -159,13 +161,13 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
|
|||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
init_info_label(&info_size, _(L("Size")));
|
init_info_label(&info_size, _L("Size"));
|
||||||
label_volume = init_info_label(&info_volume, _(L("Volume")));
|
label_volume = init_info_label(&info_volume, _L("Volume"));
|
||||||
init_info_label(&info_facets, _(L("Facets")));
|
init_info_label(&info_facets, _L("Facets"));
|
||||||
label_materials = init_info_label(&info_materials, _(L("Materials")));
|
label_materials = init_info_label(&info_materials, _L("Materials"));
|
||||||
Add(grid_sizer, 0, wxEXPAND);
|
Add(grid_sizer, 0, wxEXPAND);
|
||||||
|
|
||||||
auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold")) + ":");
|
auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _L("Manifold") + ":");
|
||||||
info_manifold_text->SetFont(wxGetApp().small_font());
|
info_manifold_text->SetFont(wxGetApp().small_font());
|
||||||
info_manifold = new wxStaticText(parent, wxID_ANY, "");
|
info_manifold = new wxStaticText(parent, wxID_ANY, "");
|
||||||
info_manifold->SetFont(wxGetApp().small_font());
|
info_manifold->SetFont(wxGetApp().small_font());
|
||||||
@ -215,7 +217,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SlicedInfo::SlicedInfo(wxWindow *parent) :
|
SlicedInfo::SlicedInfo(wxWindow *parent) :
|
||||||
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Sliced Info"))), wxVERTICAL)
|
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _L("Sliced Info")), wxVERTICAL)
|
||||||
{
|
{
|
||||||
GetStaticBox()->SetFont(wxGetApp().bold_font());
|
GetStaticBox()->SetFont(wxGetApp().bold_font());
|
||||||
|
|
||||||
@ -234,13 +236,13 @@ SlicedInfo::SlicedInfo(wxWindow *parent) :
|
|||||||
info_vec.push_back(std::pair<wxStaticText*, wxStaticText*>(text, info_label));
|
info_vec.push_back(std::pair<wxStaticText*, wxStaticText*>(text, info_label));
|
||||||
};
|
};
|
||||||
|
|
||||||
init_info_label(_(L("Used Filament (m)")));
|
init_info_label(_L("Used Filament (m)"));
|
||||||
init_info_label(_(L("Used Filament (mm³)")));
|
init_info_label(_L("Used Filament (mm³)"));
|
||||||
init_info_label(_(L("Used Filament (g)")));
|
init_info_label(_L("Used Filament (g)"));
|
||||||
init_info_label(_(L("Used Material (unit)")));
|
init_info_label(_L("Used Material (unit)"));
|
||||||
init_info_label(_(L("Cost (money)")));
|
init_info_label(_L("Cost (money)"));
|
||||||
init_info_label(_(L("Estimated printing time")));
|
init_info_label(_L("Estimated printing time"));
|
||||||
init_info_label(_(L("Number of tool changes")));
|
init_info_label(_L("Number of tool changes"));
|
||||||
|
|
||||||
Add(grid_sizer, 0, wxEXPAND);
|
Add(grid_sizer, 0, wxEXPAND);
|
||||||
this->Show(false);
|
this->Show(false);
|
||||||
@ -347,7 +349,7 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
|
|||||||
}
|
}
|
||||||
|
|
||||||
edit_btn = new ScalableButton(parent, wxID_ANY, "cog");
|
edit_btn = new ScalableButton(parent, wxID_ANY, "cog");
|
||||||
edit_btn->SetToolTip(_(L("Click to edit preset")));
|
edit_btn->SetToolTip(_L("Click to edit preset"));
|
||||||
|
|
||||||
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
|
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
|
||||||
{
|
{
|
||||||
@ -548,7 +550,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
|
|||||||
line.append_option(option);
|
line.append_option(option);
|
||||||
|
|
||||||
auto wiping_dialog_btn = [this](wxWindow* parent) {
|
auto wiping_dialog_btn = [this](wxWindow* parent) {
|
||||||
m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _L("Purging volumes") + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||||
m_wiping_dialog_button->SetFont(wxGetApp().normal_font());
|
m_wiping_dialog_button->SetFont(wxGetApp().normal_font());
|
||||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
sizer->Add(m_wiping_dialog_button, 0, wxALIGN_CENTER_VERTICAL);
|
sizer->Add(m_wiping_dialog_button, 0, wxALIGN_CENTER_VERTICAL);
|
||||||
@ -823,11 +825,11 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
};
|
};
|
||||||
|
|
||||||
p->combos_filament.push_back(nullptr);
|
p->combos_filament.push_back(nullptr);
|
||||||
init_combo(&p->combo_print, _(L("Print settings")), Preset::TYPE_PRINT, false);
|
init_combo(&p->combo_print, _L("Print settings"), Preset::TYPE_PRINT, false);
|
||||||
init_combo(&p->combos_filament[0], _(L("Filament")), Preset::TYPE_FILAMENT, true);
|
init_combo(&p->combos_filament[0], _L("Filament"), Preset::TYPE_FILAMENT, true);
|
||||||
init_combo(&p->combo_sla_print, _(L("SLA print settings")), Preset::TYPE_SLA_PRINT, false);
|
init_combo(&p->combo_sla_print, _L("SLA print settings"), Preset::TYPE_SLA_PRINT, false);
|
||||||
init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false);
|
init_combo(&p->combo_sla_material, _L("SLA material"), Preset::TYPE_SLA_MATERIAL, false);
|
||||||
init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false);
|
init_combo(&p->combo_printer, _L("Printer"), Preset::TYPE_PRINTER, false);
|
||||||
|
|
||||||
const int margin_5 = int(0.5*wxGetApp().em_unit());// 5;
|
const int margin_5 = int(0.5*wxGetApp().em_unit());// 5;
|
||||||
|
|
||||||
@ -886,9 +888,9 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
(*btn)->Hide();
|
(*btn)->Hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _(L("Send to printer")) + "\tCtrl+Shift+G");
|
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _L("Send to printer") + "\tCtrl+Shift+G");
|
||||||
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _(L("Remove device")) + "\tCtrl+T");
|
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _L("Remove device") + "\tCtrl+T");
|
||||||
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _(L("Export to SD card / Flash drive")) + "\tCtrl+U");
|
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _L("Export to SD card / Flash drive") + "\tCtrl+U");
|
||||||
|
|
||||||
// regular buttons "Slice now" and "Export G-code"
|
// regular buttons "Slice now" and "Export G-code"
|
||||||
|
|
||||||
@ -899,8 +901,8 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
(*btn)->SetFont(wxGetApp().bold_font());
|
(*btn)->SetFont(wxGetApp().bold_font());
|
||||||
};
|
};
|
||||||
|
|
||||||
init_btn(&p->btn_export_gcode, _(L("Export G-code")) + dots , scaled_height);
|
init_btn(&p->btn_export_gcode, _L("Export G-code") + dots , scaled_height);
|
||||||
init_btn(&p->btn_reslice , _(L("Slice now")) , scaled_height);
|
init_btn(&p->btn_reslice , _L("Slice now") , scaled_height);
|
||||||
|
|
||||||
enable_buttons(false);
|
enable_buttons(false);
|
||||||
|
|
||||||
@ -1050,7 +1052,7 @@ void Sidebar::update_reslice_btn_tooltip() const
|
|||||||
{
|
{
|
||||||
wxString tooltip = wxString("Slice") + " [" + GUI::shortkey_ctrl_prefix() + "R]";
|
wxString tooltip = wxString("Slice") + " [" + GUI::shortkey_ctrl_prefix() + "R]";
|
||||||
if (m_mode != comSimple)
|
if (m_mode != comSimple)
|
||||||
tooltip += wxString("\n") + _(L("Hold Shift to Slice & Export G-code"));
|
tooltip += wxString("\n") + _L("Hold Shift to Slice & Export G-code");
|
||||||
p->btn_reslice->SetToolTip(tooltip);
|
p->btn_reslice->SetToolTip(tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1171,16 +1173,16 @@ void Sidebar::show_info_sizer()
|
|||||||
|
|
||||||
const auto& stats = model_object->get_object_stl_stats();//model_object->volumes.front()->mesh.stl.stats;
|
const auto& stats = model_object->get_object_stl_stats();//model_object->volumes.front()->mesh.stl.stats;
|
||||||
p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume));
|
p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume));
|
||||||
p->object_info->info_facets->SetLabel(wxString::Format(_(L("%d (%d shells)")), static_cast<int>(model_object->facets_count()), stats.number_of_parts));
|
p->object_info->info_facets->SetLabel(wxString::Format(_L("%d (%d shells)"), static_cast<int>(model_object->facets_count()), stats.number_of_parts));
|
||||||
|
|
||||||
int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
|
int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
|
||||||
stats.facets_added + stats.facets_reversed + stats.backwards_edges;
|
stats.facets_added + stats.facets_reversed + stats.backwards_edges;
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors)")), errors);
|
wxString tooltip = wxString::Format(_L("Auto-repaired (%d errors)"), errors);
|
||||||
p->object_info->info_manifold->SetLabel(tooltip);
|
p->object_info->info_manifold->SetLabel(tooltip);
|
||||||
|
|
||||||
tooltip += ":\n" + wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, "
|
tooltip += ":\n" + wxString::Format(_L("%d degenerate facets, %d edges fixed, %d facets removed, "
|
||||||
"%d facets added, %d facets reversed, %d backwards edges")),
|
"%d facets added, %d facets reversed, %d backwards edges"),
|
||||||
stats.degenerate_facets, stats.edges_fixed, stats.facets_removed,
|
stats.degenerate_facets, stats.edges_fixed, stats.facets_removed,
|
||||||
stats.facets_added, stats.facets_reversed, stats.backwards_edges);
|
stats.facets_added, stats.facets_reversed, stats.backwards_edges);
|
||||||
|
|
||||||
@ -1189,7 +1191,7 @@ void Sidebar::show_info_sizer()
|
|||||||
p->object_info->manifold_warning_icon->SetToolTip(tooltip);
|
p->object_info->manifold_warning_icon->SetToolTip(tooltip);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p->object_info->info_manifold->SetLabel(_(L("Yes")));
|
p->object_info->info_manifold->SetLabel(_L("Yes"));
|
||||||
p->object_info->showing_manifold_warning_icon = false;
|
p->object_info->showing_manifold_warning_icon = false;
|
||||||
p->object_info->info_manifold->SetToolTip("");
|
p->object_info->info_manifold->SetToolTip("");
|
||||||
p->object_info->manifold_warning_icon->SetToolTip("");
|
p->object_info->manifold_warning_icon->SetToolTip("");
|
||||||
@ -1210,10 +1212,10 @@ void Sidebar::update_sliced_info_sizer()
|
|||||||
if (p->plater->printer_technology() == ptSLA)
|
if (p->plater->printer_technology() == ptSLA)
|
||||||
{
|
{
|
||||||
const SLAPrintStatistics& ps = p->plater->sla_print().print_statistics();
|
const SLAPrintStatistics& ps = p->plater->sla_print().print_statistics();
|
||||||
wxString new_label = _(L("Used Material (ml)")) + ":";
|
wxString new_label = _L("Used Material (ml)") + ":";
|
||||||
const bool is_supports = ps.support_used_material > 0.0;
|
const bool is_supports = ps.support_used_material > 0.0;
|
||||||
if (is_supports)
|
if (is_supports)
|
||||||
new_label += from_u8((boost::format("\n - %s\n - %s") % _utf8(L("object(s)")) % _utf8(L("supports and pad"))).str());
|
new_label += format_wxstr("\n - %s\n - %s", _L("object(s)"), _L("supports and pad"));
|
||||||
|
|
||||||
wxString info_text = is_supports ?
|
wxString info_text = is_supports ?
|
||||||
wxString::Format("%.2f \n%.2f \n%.2f", (ps.objects_used_material + ps.support_used_material) / 1000,
|
wxString::Format("%.2f \n%.2f \n%.2f", (ps.objects_used_material + ps.support_used_material) / 1000,
|
||||||
@ -1235,7 +1237,7 @@ void Sidebar::update_sliced_info_sizer()
|
|||||||
p->sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost");
|
p->sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost");
|
||||||
|
|
||||||
wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : get_time_dhms(float(ps.estimated_print_time));
|
wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : get_time_dhms(float(ps.estimated_print_time));
|
||||||
p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _(L("Estimated printing time")) + ":");
|
p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _L("Estimated printing time") + ":");
|
||||||
|
|
||||||
// Hide non-SLA sliced info parameters
|
// Hide non-SLA sliced info parameters
|
||||||
p->sliced_info->SetTextAndShow(siFilament_m, "N/A");
|
p->sliced_info->SetTextAndShow(siFilament_m, "N/A");
|
||||||
@ -1248,9 +1250,9 @@ void Sidebar::update_sliced_info_sizer()
|
|||||||
const PrintStatistics& ps = p->plater->fff_print().print_statistics();
|
const PrintStatistics& ps = p->plater->fff_print().print_statistics();
|
||||||
const bool is_wipe_tower = ps.total_wipe_tower_filament > 0;
|
const bool is_wipe_tower = ps.total_wipe_tower_filament > 0;
|
||||||
|
|
||||||
wxString new_label = _(L("Used Filament (m)"));
|
wxString new_label = _L("Used Filament (m)");
|
||||||
if (is_wipe_tower)
|
if (is_wipe_tower)
|
||||||
new_label += from_u8((boost::format(":\n - %1%\n - %2%") % _utf8(L("objects")) % _utf8(L("wipe tower"))).str());
|
new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower"));
|
||||||
|
|
||||||
wxString info_text = is_wipe_tower ?
|
wxString info_text = is_wipe_tower ?
|
||||||
wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / 1000,
|
wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / 1000,
|
||||||
@ -1262,9 +1264,9 @@ void Sidebar::update_sliced_info_sizer()
|
|||||||
p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume));
|
p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume));
|
||||||
p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight));
|
p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight));
|
||||||
|
|
||||||
new_label = _(L("Cost"));
|
new_label = _L("Cost");
|
||||||
if (is_wipe_tower)
|
if (is_wipe_tower)
|
||||||
new_label += from_u8((boost::format(":\n - %1%\n - %2%") % _utf8(L("objects")) % _utf8(L("wipe tower"))).str());
|
new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower"));
|
||||||
|
|
||||||
info_text = ps.total_cost == 0.0 ? "N/A" :
|
info_text = ps.total_cost == 0.0 ? "N/A" :
|
||||||
is_wipe_tower ?
|
is_wipe_tower ?
|
||||||
@ -1277,10 +1279,10 @@ void Sidebar::update_sliced_info_sizer()
|
|||||||
if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
|
if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
|
||||||
p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A");
|
p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A");
|
||||||
else {
|
else {
|
||||||
new_label = _(L("Estimated printing time")) +":";
|
new_label = _L("Estimated printing time") +":";
|
||||||
info_text = "";
|
info_text = "";
|
||||||
wxString str_color = _(L("Color"));
|
wxString str_color = _L("Color");
|
||||||
wxString str_pause = _(L("Pause"));
|
wxString str_pause = _L("Pause");
|
||||||
|
|
||||||
auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGcodeType, std::string>>& times,
|
auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGcodeType, std::string>>& times,
|
||||||
wxString& new_label, wxString& info_text)
|
wxString& new_label, wxString& info_text)
|
||||||
@ -1293,25 +1295,25 @@ void Sidebar::update_sliced_info_sizer()
|
|||||||
for (int i = (int)times.size() - 1; i >= 0; --i)
|
for (int i = (int)times.size() - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
if (i == 0 || times[i - 1].first == cgtPausePrint)
|
if (i == 0 || times[i - 1].first == cgtPausePrint)
|
||||||
new_label += from_u8((boost::format("\n - %1%%2%") % (std::string(str_color.ToUTF8()) + " ") % color_change_count).str());
|
new_label += format_wxstr("\n - %1%%2%", str_color + " ", color_change_count);
|
||||||
else if (times[i - 1].first == cgtColorChange)
|
else if (times[i - 1].first == cgtColorChange)
|
||||||
new_label += from_u8((boost::format("\n - %1%%2%") % (std::string(str_color.ToUTF8()) + " ") % color_change_count--).str());
|
new_label += format_wxstr("\n - %1%%2%", str_color + " ", color_change_count--);
|
||||||
|
|
||||||
if (i != (int)times.size() - 1 && times[i].first == cgtPausePrint)
|
if (i != (int)times.size() - 1 && times[i].first == cgtPausePrint)
|
||||||
new_label += from_u8((boost::format(" -> %1%") % std::string(str_pause.ToUTF8())).str());
|
new_label += format_wxstr(" -> %1%", str_pause);
|
||||||
|
|
||||||
info_text += from_u8((boost::format("\n%1%") % times[i].second).str());
|
info_text += format_wxstr("\n%1%", times[i].second);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ps.estimated_normal_print_time != "N/A") {
|
if (ps.estimated_normal_print_time != "N/A") {
|
||||||
new_label += from_u8((boost::format("\n - %1%") % _utf8(L("normal mode"))).str());
|
new_label += format_wxstr("\n - %1%", _L("normal mode"));
|
||||||
info_text += from_u8((boost::format("\n%1%") % ps.estimated_normal_print_time).str());
|
info_text += format_wxstr("\n%1%", ps.estimated_normal_print_time);
|
||||||
fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text);
|
fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text);
|
||||||
}
|
}
|
||||||
if (ps.estimated_silent_print_time != "N/A") {
|
if (ps.estimated_silent_print_time != "N/A") {
|
||||||
new_label += from_u8((boost::format("\n - %1%") % _utf8(L("stealth mode"))).str());
|
new_label += format_wxstr("\n - %1%", _L("stealth mode"));
|
||||||
info_text += from_u8((boost::format("\n%1%") % ps.estimated_silent_print_time).str());
|
info_text += format_wxstr("\n%1%", ps.estimated_silent_print_time);
|
||||||
fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text);
|
fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text);
|
||||||
}
|
}
|
||||||
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
|
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
|
||||||
@ -1463,11 +1465,11 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
|
|||||||
wxString snapshot_label;
|
wxString snapshot_label;
|
||||||
assert(! paths.empty());
|
assert(! paths.empty());
|
||||||
if (paths.size() == 1) {
|
if (paths.size() == 1) {
|
||||||
snapshot_label = _(L("Load File"));
|
snapshot_label = _L("Load File");
|
||||||
snapshot_label += ": ";
|
snapshot_label += ": ";
|
||||||
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
||||||
} else {
|
} else {
|
||||||
snapshot_label = _(L("Load Files"));
|
snapshot_label = _L("Load Files");
|
||||||
snapshot_label += ": ";
|
snapshot_label += ": ";
|
||||||
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
||||||
for (size_t i = 1; i < paths.size(); ++ i) {
|
for (size_t i = 1; i < paths.size(); ++ i) {
|
||||||
@ -1555,7 +1557,7 @@ struct Plater::priv
|
|||||||
friend priv;
|
friend priv;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void apply_arrange_result(const Vec2crd& tr, double rotation)
|
void apply_arrange_result(const Vec2d& tr, double rotation)
|
||||||
{
|
{
|
||||||
m_pos = unscaled(tr); m_rotation = rotation;
|
m_pos = unscaled(tr); m_rotation = rotation;
|
||||||
apply_wipe_tower();
|
apply_wipe_tower();
|
||||||
@ -1658,9 +1660,9 @@ struct Plater::priv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stride between logical beds
|
// Stride between logical beds
|
||||||
coord_t bed_stride() const {
|
double bed_stride() const {
|
||||||
double bedwidth = plater().bed_shape_bb().size().x();
|
double bedwidth = plater().bed_shape_bb().size().x();
|
||||||
return scaled((1. + LOGICAL_BED_GAP) * bedwidth);
|
return scaled<double>((1. + LOGICAL_BED_GAP) * bedwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up arrange polygon for a ModelInstance and Wipe tower
|
// Set up arrange polygon for a ModelInstance and Wipe tower
|
||||||
@ -1670,7 +1672,7 @@ struct Plater::priv
|
|||||||
ap.bed_idx = ap.translation.x() / bed_stride();
|
ap.bed_idx = ap.translation.x() / bed_stride();
|
||||||
ap.setter = [obj, this](const ArrangePolygon &p) {
|
ap.setter = [obj, this](const ArrangePolygon &p) {
|
||||||
if (p.is_arranged()) {
|
if (p.is_arranged()) {
|
||||||
auto t = p.translation;
|
Vec2d t = p.translation.cast<double>();
|
||||||
t.x() += p.bed_idx * bed_stride();
|
t.x() += p.bed_idx * bed_stride();
|
||||||
obj->apply_arrange_result(t, p.rotation);
|
obj->apply_arrange_result(t, p.rotation);
|
||||||
}
|
}
|
||||||
@ -1903,6 +1905,7 @@ struct Plater::priv
|
|||||||
GLCanvas3D* get_current_canvas3D();
|
GLCanvas3D* get_current_canvas3D();
|
||||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
void unbind_canvas_event_handlers();
|
void unbind_canvas_event_handlers();
|
||||||
|
void reset_canvas_volumes();
|
||||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
bool init_view_toolbar();
|
bool init_view_toolbar();
|
||||||
@ -2271,11 +2274,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
|
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
|
||||||
if (evt.data.second) {
|
if (evt.data.second) {
|
||||||
this->show_action_buttons(this->ready_to_slice);
|
this->show_action_buttons(this->ready_to_slice);
|
||||||
Slic3r::GUI::show_info(this->q, (boost::format(_utf8(L("Unmounting successful. The device %s(%s) can now be safely removed from the computer.")))
|
Slic3r::GUI::show_info(this->q, format_wxstr(_L("Unmounting successful. The device %s(%s) can now be safely removed from the computer."),
|
||||||
% evt.data.first.name % evt.data.first.path).str());
|
evt.data.first.name, evt.data.first.path));
|
||||||
} else
|
} else
|
||||||
Slic3r::GUI::show_info(this->q, (boost::format(_utf8(L("Ejecting of device %s(%s) has failed.")))
|
Slic3r::GUI::show_info(this->q, format_wxstr(_L("Ejecting of device %s(%s) has failed."),
|
||||||
% evt.data.first.name % evt.data.first.path).str());
|
evt.data.first.name, evt.data.first.path));
|
||||||
});
|
});
|
||||||
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this](RemovableDrivesChangedEvent &) { this->show_action_buttons(this->ready_to_slice); });
|
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this](RemovableDrivesChangedEvent &) { this->show_action_buttons(this->ready_to_slice); });
|
||||||
// Start the background thread and register this window as a target for update events.
|
// Start the background thread and register this window as a target for update events.
|
||||||
@ -2287,7 +2290,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
// Initialize the Undo / Redo stack with a first snapshot.
|
// Initialize the Undo / Redo stack with a first snapshot.
|
||||||
this->take_snapshot(_(L("New Project")));
|
this->take_snapshot(_L("New Project"));
|
||||||
|
|
||||||
// collapse sidebar according to saved value
|
// collapse sidebar according to saved value
|
||||||
sidebar->collapse(wxGetApp().app_config->get("collapsed_sidebar") == "1");
|
sidebar->collapse(wxGetApp().app_config->get("collapsed_sidebar") == "1");
|
||||||
@ -2404,7 +2407,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto loading = _(L("Loading")) + dots;
|
const auto loading = _L("Loading") + dots;
|
||||||
wxProgressDialog dlg(loading, loading);
|
wxProgressDialog dlg(loading, loading);
|
||||||
dlg.Pulse();
|
dlg.Pulse();
|
||||||
|
|
||||||
@ -2414,7 +2417,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
for (size_t i = 0; i < input_files.size(); i++) {
|
for (size_t i = 0; i < input_files.size(); i++) {
|
||||||
const auto &path = input_files[i];
|
const auto &path = input_files[i];
|
||||||
const auto filename = path.filename();
|
const auto filename = path.filename();
|
||||||
const auto dlg_info = from_u8((boost::format(_utf8(L("Processing input file %s"))) % from_path(filename)).str()) + "\n";
|
const auto dlg_info = format_wxstr(_L("Processing input file %s"), from_path(filename)) + "\n";
|
||||||
dlg.Update(100 * i / input_files.size(), dlg_info);
|
dlg.Update(100 * i / input_files.size(), dlg_info);
|
||||||
|
|
||||||
const bool type_3mf = std::regex_match(path.string(), pattern_3mf);
|
const bool type_3mf = std::regex_match(path.string(), pattern_3mf);
|
||||||
@ -2442,9 +2445,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
if (object->volumes.size() > 1)
|
if (object->volumes.size() > 1)
|
||||||
{
|
{
|
||||||
Slic3r::GUI::show_info(nullptr,
|
Slic3r::GUI::show_info(nullptr,
|
||||||
_(L("You cannot load SLA project with a multi-part object on the bed")) + "\n\n" +
|
_L("You cannot load SLA project with a multi-part object on the bed") + "\n\n" +
|
||||||
_(L("Please check your object list before preset changing.")),
|
_L("Please check your object list before preset changing."),
|
||||||
_(L("Attention!")));
|
_L("Attention!"));
|
||||||
return obj_idxs;
|
return obj_idxs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2487,19 +2490,19 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
|
|
||||||
if (! is_project_file) {
|
if (! is_project_file) {
|
||||||
if (model.looks_like_multipart_object()) {
|
if (model.looks_like_multipart_object()) {
|
||||||
wxMessageDialog msg_dlg(q, _(L(
|
wxMessageDialog msg_dlg(q, _L(
|
||||||
"This file contains several objects positioned at multiple heights.\n"
|
"This file contains several objects positioned at multiple heights.\n"
|
||||||
"Instead of considering them as multiple objects, should I consider\n"
|
"Instead of considering them as multiple objects, should I consider\n"
|
||||||
"this file as a single object having multiple parts?")) + "\n",
|
"this file as a single object having multiple parts?") + "\n",
|
||||||
_(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
|
_L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO);
|
||||||
if (msg_dlg.ShowModal() == wxID_YES) {
|
if (msg_dlg.ShowModal() == wxID_YES) {
|
||||||
model.convert_multipart_object(nozzle_dmrs->values.size());
|
model.convert_multipart_object(nozzle_dmrs->values.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) {
|
else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) {
|
||||||
wxMessageDialog msg_dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?"))+"\n",
|
wxMessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n",
|
||||||
_(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO);
|
_L("Detected advanced data"), wxICON_WARNING | wxYES | wxNO);
|
||||||
if (msg_dlg.ShowModal() == wxID_YES)
|
if (msg_dlg.ShowModal() == wxID_YES)
|
||||||
{
|
{
|
||||||
Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
|
Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
|
||||||
@ -2521,8 +2524,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
for (auto obj : model.objects)
|
for (auto obj : model.objects)
|
||||||
if ( obj->volumes.size()>1 ) {
|
if ( obj->volumes.size()>1 ) {
|
||||||
Slic3r::GUI::show_error(nullptr,
|
Slic3r::GUI::show_error(nullptr,
|
||||||
from_u8((boost::format(_utf8(L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part")))
|
format_wxstr(_L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part"),
|
||||||
% from_path(filename)).str()));
|
from_path(filename)));
|
||||||
return obj_idxs;
|
return obj_idxs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2540,11 +2543,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (new_model != nullptr && new_model->objects.size() > 1) {
|
if (new_model != nullptr && new_model->objects.size() > 1) {
|
||||||
wxMessageDialog msg_dlg(q, _(L(
|
wxMessageDialog msg_dlg(q, _L(
|
||||||
"Multiple objects were loaded for a multi-material printer.\n"
|
"Multiple objects were loaded for a multi-material printer.\n"
|
||||||
"Instead of considering them as multiple objects, should I consider\n"
|
"Instead of considering them as multiple objects, should I consider\n"
|
||||||
"these files to represent a single object having multiple parts?")) + "\n",
|
"these files to represent a single object having multiple parts?") + "\n",
|
||||||
_(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
|
_L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO);
|
||||||
if (msg_dlg.ShowModal() == wxID_YES) {
|
if (msg_dlg.ShowModal() == wxID_YES) {
|
||||||
new_model->convert_multipart_object(nozzle_dmrs->values.size());
|
new_model->convert_multipart_object(nozzle_dmrs->values.size());
|
||||||
}
|
}
|
||||||
@ -2557,7 +2560,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
{
|
{
|
||||||
wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string());
|
wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string());
|
||||||
// XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames...
|
// XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames...
|
||||||
statusbar()->set_status_text(_(L("Loaded")));
|
statusbar()->set_status_text(_L("Loaded"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// automatic selection of added objects
|
// automatic selection of added objects
|
||||||
@ -2659,8 +2662,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
|
|||||||
|
|
||||||
if (scaled_down) {
|
if (scaled_down) {
|
||||||
GUI::show_info(q,
|
GUI::show_info(q,
|
||||||
_(L("Your object appears to be too large, so it was automatically scaled down to fit your print bed.")),
|
_L("Your object appears to be too large, so it was automatically scaled down to fit your print bed."),
|
||||||
_(L("Object too large?")));
|
_L("Object too large?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const size_t idx : obj_idxs) {
|
for (const size_t idx : obj_idxs) {
|
||||||
@ -2722,26 +2725,26 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
|
|||||||
case FT_STL:
|
case FT_STL:
|
||||||
{
|
{
|
||||||
output_file.replace_extension("stl");
|
output_file.replace_extension("stl");
|
||||||
dlg_title = _(L("Export STL file:"));
|
dlg_title = _L("Export STL file:");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FT_AMF:
|
case FT_AMF:
|
||||||
{
|
{
|
||||||
// XXX: Problem on OS X with double extension?
|
// XXX: Problem on OS X with double extension?
|
||||||
output_file.replace_extension("zip.amf");
|
output_file.replace_extension("zip.amf");
|
||||||
dlg_title = _(L("Export AMF file:"));
|
dlg_title = _L("Export AMF file:");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FT_3MF:
|
case FT_3MF:
|
||||||
{
|
{
|
||||||
output_file.replace_extension("3mf");
|
output_file.replace_extension("3mf");
|
||||||
dlg_title = _(L("Save file as:"));
|
dlg_title = _L("Save file as:");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FT_OBJ:
|
case FT_OBJ:
|
||||||
{
|
{
|
||||||
output_file.replace_extension("obj");
|
output_file.replace_extension("obj");
|
||||||
dlg_title = _(L("Export OBJ file:"));
|
dlg_title = _L("Export OBJ file:");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
@ -2813,15 +2816,12 @@ void Plater::priv::object_list_changed()
|
|||||||
|
|
||||||
void Plater::priv::select_all()
|
void Plater::priv::select_all()
|
||||||
{
|
{
|
||||||
// this->take_snapshot(_(L("Select All")));
|
|
||||||
|
|
||||||
view3D->select_all();
|
view3D->select_all();
|
||||||
this->sidebar->obj_list()->update_selections();
|
this->sidebar->obj_list()->update_selections();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::deselect_all()
|
void Plater::priv::deselect_all()
|
||||||
{
|
{
|
||||||
// this->take_snapshot(_(L("Deselect All")));
|
|
||||||
view3D->deselect_all();
|
view3D->deselect_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2843,7 +2843,7 @@ void Plater::priv::remove(size_t obj_idx)
|
|||||||
|
|
||||||
void Plater::priv::delete_object_from_model(size_t obj_idx)
|
void Plater::priv::delete_object_from_model(size_t obj_idx)
|
||||||
{
|
{
|
||||||
wxString snapshot_label = _(L("Delete Object"));
|
wxString snapshot_label = _L("Delete Object");
|
||||||
if (! model.objects[obj_idx]->name.empty())
|
if (! model.objects[obj_idx]->name.empty())
|
||||||
snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str());
|
snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str());
|
||||||
Plater::TakeSnapshot snapshot(q, snapshot_label);
|
Plater::TakeSnapshot snapshot(q, snapshot_label);
|
||||||
@ -2854,7 +2854,7 @@ void Plater::priv::delete_object_from_model(size_t obj_idx)
|
|||||||
|
|
||||||
void Plater::priv::reset()
|
void Plater::priv::reset()
|
||||||
{
|
{
|
||||||
Plater::TakeSnapshot snapshot(q, _(L("Reset Project")));
|
Plater::TakeSnapshot snapshot(q, _L("Reset Project"));
|
||||||
|
|
||||||
set_project_filename(wxEmptyString);
|
set_project_filename(wxEmptyString);
|
||||||
|
|
||||||
@ -2885,7 +2885,7 @@ void Plater::priv::mirror(Axis axis)
|
|||||||
|
|
||||||
void Plater::priv::arrange()
|
void Plater::priv::arrange()
|
||||||
{
|
{
|
||||||
this->take_snapshot(_(L("Arrange")));
|
this->take_snapshot(_L("Arrange"));
|
||||||
m_ui_jobs.start(Jobs::Arrange);
|
m_ui_jobs.start(Jobs::Arrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2893,7 +2893,7 @@ void Plater::priv::arrange()
|
|||||||
// This method will find an optimal orientation for the currently selected item
|
// This method will find an optimal orientation for the currently selected item
|
||||||
// Very similar in nature to the arrange method above...
|
// Very similar in nature to the arrange method above...
|
||||||
void Plater::priv::sla_optimize_rotation() {
|
void Plater::priv::sla_optimize_rotation() {
|
||||||
this->take_snapshot(_(L("Optimize Rotation")));
|
this->take_snapshot(_L("Optimize Rotation"));
|
||||||
m_ui_jobs.start(Jobs::Rotoptimize);
|
m_ui_jobs.start(Jobs::Rotoptimize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2934,12 +2934,12 @@ void Plater::priv::find_new_position(const ModelInstancePtrs &instances,
|
|||||||
|
|
||||||
for (size_t i = 0; i < instances.size(); ++i)
|
for (size_t i = 0; i < instances.size(); ++i)
|
||||||
if (movable[i].bed_idx == 0)
|
if (movable[i].bed_idx == 0)
|
||||||
instances[i]->apply_arrange_result(movable[i].translation,
|
instances[i]->apply_arrange_result(movable[i].translation.cast<double>(),
|
||||||
movable[i].rotation);
|
movable[i].rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::ArrangeJob::process() {
|
void Plater::priv::ArrangeJob::process() {
|
||||||
static const auto arrangestr = _(L("Arranging"));
|
static const auto arrangestr = _L("Arranging");
|
||||||
|
|
||||||
// FIXME: I don't know how to obtain the minimum distance, it depends
|
// FIXME: I don't know how to obtain the minimum distance, it depends
|
||||||
// on printer technology. I guess the following should work but it crashes.
|
// on printer technology. I guess the following should work but it crashes.
|
||||||
@ -2966,14 +2966,14 @@ void Plater::priv::ArrangeJob::process() {
|
|||||||
}, stopfn);
|
}, stopfn);
|
||||||
} catch (std::exception & /*e*/) {
|
} catch (std::exception & /*e*/) {
|
||||||
GUI::show_error(plater().q,
|
GUI::show_error(plater().q,
|
||||||
_(L("Could not arrange model objects! "
|
_L("Could not arrange model objects! "
|
||||||
"Some geometries may be invalid.")));
|
"Some geometries may be invalid."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalize just here.
|
// finalize just here.
|
||||||
update_status(int(count),
|
update_status(int(count),
|
||||||
was_canceled() ? _(L("Arranging canceled."))
|
was_canceled() ? _L("Arranging canceled.")
|
||||||
: _(L("Arranging done.")));
|
: _L("Arranging done."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::RotoptimizeJob::process()
|
void Plater::priv::RotoptimizeJob::process()
|
||||||
@ -2989,7 +2989,7 @@ void Plater::priv::RotoptimizeJob::process()
|
|||||||
[this](unsigned s) {
|
[this](unsigned s) {
|
||||||
if (s < 100)
|
if (s < 100)
|
||||||
update_status(int(s),
|
update_status(int(s),
|
||||||
_(L("Searching for optimal orientation")));
|
_L("Searching for optimal orientation"));
|
||||||
},
|
},
|
||||||
[this]() { return was_canceled(); });
|
[this]() { return was_canceled(); });
|
||||||
|
|
||||||
@ -3022,8 +3022,8 @@ void Plater::priv::RotoptimizeJob::process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_status(100,
|
update_status(100,
|
||||||
was_canceled() ? _(L("Orientation search canceled."))
|
was_canceled() ? _L("Orientation search canceled.")
|
||||||
: _(L("Orientation found.")));
|
: _L("Orientation found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3040,7 +3040,7 @@ void Plater::priv::split_object()
|
|||||||
|
|
||||||
if (current_model_object->volumes.size() > 1)
|
if (current_model_object->volumes.size() > 1)
|
||||||
{
|
{
|
||||||
Slic3r::GUI::warning_catcher(q, _(L("The selected object can't be split because it contains more than one volume/material.")));
|
Slic3r::GUI::warning_catcher(q, _L("The selected object can't be split because it contains more than one volume/material."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3048,10 +3048,10 @@ void Plater::priv::split_object()
|
|||||||
ModelObjectPtrs new_objects;
|
ModelObjectPtrs new_objects;
|
||||||
current_model_object->split(&new_objects);
|
current_model_object->split(&new_objects);
|
||||||
if (new_objects.size() == 1)
|
if (new_objects.size() == 1)
|
||||||
Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part.")));
|
Slic3r::GUI::warning_catcher(q, _L("The selected object couldn't be split because it contains only one part."));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Plater::TakeSnapshot snapshot(q, _(L("Split to Objects")));
|
Plater::TakeSnapshot snapshot(q, _L("Split to Objects"));
|
||||||
|
|
||||||
unsigned int counter = 1;
|
unsigned int counter = 1;
|
||||||
for (ModelObject* m : new_objects)
|
for (ModelObject* m : new_objects)
|
||||||
@ -3176,7 +3176,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||||||
if ((return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
|
if ((return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
|
||||||
{
|
{
|
||||||
// Validation of the background data failed.
|
// Validation of the background data failed.
|
||||||
const wxString invalid_str = _(L("Invalid data"));
|
const wxString invalid_str = _L("Invalid data");
|
||||||
for (auto btn : {ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport})
|
for (auto btn : {ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport})
|
||||||
sidebar->set_btn_label(btn, invalid_str);
|
sidebar->set_btn_label(btn, invalid_str);
|
||||||
}
|
}
|
||||||
@ -3185,13 +3185,13 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||||||
// Background data is valid.
|
// Background data is valid.
|
||||||
if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
|
if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
|
||||||
(return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
|
(return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
|
||||||
this->statusbar()->set_status_text(_(L("Ready to slice")));
|
this->statusbar()->set_status_text(_L("Ready to slice"));
|
||||||
|
|
||||||
sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export));
|
sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export));
|
||||||
sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send));
|
sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send));
|
||||||
|
|
||||||
const wxString slice_string = background_process.running() && wxGetApp().get_mode() == comSimple ?
|
const wxString slice_string = background_process.running() && wxGetApp().get_mode() == comSimple ?
|
||||||
_(L("Slicing")) + dots : _(L("Slice now"));
|
_L("Slicing") + dots : _L("Slice now");
|
||||||
sidebar->set_btn_label(ActionButtonType::abReslice, slice_string);
|
sidebar->set_btn_label(ActionButtonType::abReslice, slice_string);
|
||||||
|
|
||||||
if (background_process.finished())
|
if (background_process.finished())
|
||||||
@ -3223,7 +3223,7 @@ bool Plater::priv::restart_background_process(unsigned int state)
|
|||||||
// The print is valid and it can be started.
|
// The print is valid and it can be started.
|
||||||
if (this->background_process.start()) {
|
if (this->background_process.start()) {
|
||||||
this->statusbar()->set_cancel_callback([this]() {
|
this->statusbar()->set_cancel_callback([this]() {
|
||||||
this->statusbar()->set_status_text(_(L("Cancelling")));
|
this->statusbar()->set_status_text(_L("Cancelling"));
|
||||||
this->background_process.stop();
|
this->background_process.stop();
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@ -3240,7 +3240,7 @@ void Plater::priv::export_gcode(fs::path output_path, bool output_path_on_remova
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (background_process.is_export_scheduled()) {
|
if (background_process.is_export_scheduled()) {
|
||||||
GUI::show_error(q, _(L("Another export job is currently running.")));
|
GUI::show_error(q, _L("Another export job is currently running."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3295,7 +3295,7 @@ void Plater::priv::update_sla_scene()
|
|||||||
|
|
||||||
void Plater::priv::reload_from_disk()
|
void Plater::priv::reload_from_disk()
|
||||||
{
|
{
|
||||||
Plater::TakeSnapshot snapshot(q, _(L("Reload from disk")));
|
Plater::TakeSnapshot snapshot(q, _L("Reload from disk"));
|
||||||
|
|
||||||
const Selection& selection = get_selection();
|
const Selection& selection = get_selection();
|
||||||
|
|
||||||
@ -3356,7 +3356,7 @@ void Plater::priv::reload_from_disk()
|
|||||||
{
|
{
|
||||||
// ask user to select the missing file
|
// ask user to select the missing file
|
||||||
fs::path search = missing_input_paths.back();
|
fs::path search = missing_input_paths.back();
|
||||||
wxString title = _(L("Please select the file to reload"));
|
wxString title = _L("Please select the file to reload");
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
title += " (" + from_u8(search.filename().string()) + ")";
|
title += " (" + from_u8(search.filename().string()) + ")";
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
@ -3391,7 +3391,7 @@ void Plater::priv::reload_from_disk()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxString message = _(L("It is not allowed to change the file to reload")) + " (" + from_u8(search.filename().string()) + ").\n" + _(L("Do you want to retry")) + " ?";
|
wxString message = _L("It is not allowed to change the file to reload") + " (" + from_u8(search.filename().string()) + ").\n" + _L("Do you want to retry") + " ?";
|
||||||
wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
|
wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
|
||||||
if (dlg.ShowModal() != wxID_YES)
|
if (dlg.ShowModal() != wxID_YES)
|
||||||
return;
|
return;
|
||||||
@ -3409,7 +3409,7 @@ void Plater::priv::reload_from_disk()
|
|||||||
const auto& path = input_paths[i].string();
|
const auto& path = input_paths[i].string();
|
||||||
|
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
wxBusyInfo info(_(L("Reload from:")) + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
|
wxBusyInfo info(_L("Reload from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
|
||||||
|
|
||||||
Model new_model;
|
Model new_model;
|
||||||
try
|
try
|
||||||
@ -3498,12 +3498,12 @@ void Plater::priv::reload_from_disk()
|
|||||||
|
|
||||||
if (!fail_list.empty())
|
if (!fail_list.empty())
|
||||||
{
|
{
|
||||||
wxString message = _(L("Unable to reload:")) + "\n";
|
wxString message = _L("Unable to reload:") + "\n";
|
||||||
for (const wxString& s : fail_list)
|
for (const wxString& s : fail_list)
|
||||||
{
|
{
|
||||||
message += s + "\n";
|
message += s + "\n";
|
||||||
}
|
}
|
||||||
wxMessageDialog dlg(q, message, _(L("Error during reload")), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
wxMessageDialog dlg(q, message, _L("Error during reload"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
|
||||||
dlg.ShowModal();
|
dlg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3522,7 +3522,7 @@ void Plater::priv::reload_all_from_disk()
|
|||||||
if (model.objects.empty())
|
if (model.objects.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(q, _(L("Reload all from disk")));
|
Plater::TakeSnapshot snapshot(q, _L("Reload all from disk"));
|
||||||
Plater::SuppressSnapshots suppress(q);
|
Plater::SuppressSnapshots suppress(q);
|
||||||
|
|
||||||
Selection& selection = get_selection();
|
Selection& selection = get_selection();
|
||||||
@ -3543,7 +3543,7 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* =
|
|||||||
if (obj_idx < 0)
|
if (obj_idx < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(q, _(L("Fix Throught NetFabb")));
|
Plater::TakeSnapshot snapshot(q, _L("Fix Throught NetFabb"));
|
||||||
|
|
||||||
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
|
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
|
||||||
this->update();
|
this->update();
|
||||||
@ -3746,7 +3746,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
|
|||||||
if (error) {
|
if (error) {
|
||||||
wxString message = evt.GetString();
|
wxString message = evt.GetString();
|
||||||
if (message.IsEmpty())
|
if (message.IsEmpty())
|
||||||
message = _(L("Export failed"));
|
message = _L("Export failed");
|
||||||
if (q->m_tracking_popup_menu)
|
if (q->m_tracking_popup_menu)
|
||||||
// We don't want to pop-up a message box when tracking a pop-up menu.
|
// We don't want to pop-up a message box when tracking a pop-up menu.
|
||||||
// We postpone the error message instead.
|
// We postpone the error message instead.
|
||||||
@ -3756,7 +3756,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
|
|||||||
this->statusbar()->set_status_text(message);
|
this->statusbar()->set_status_text(message);
|
||||||
}
|
}
|
||||||
if (canceled)
|
if (canceled)
|
||||||
this->statusbar()->set_status_text(_(L("Cancelled")));
|
this->statusbar()->set_status_text(_L("Cancelled"));
|
||||||
|
|
||||||
this->sidebar->show_sliced_info_sizer(success);
|
this->sidebar->show_sliced_info_sizer(success);
|
||||||
|
|
||||||
@ -3819,8 +3819,6 @@ void Plater::priv::on_action_layersediting(SimpleEvent&)
|
|||||||
|
|
||||||
void Plater::priv::on_object_select(SimpleEvent& evt)
|
void Plater::priv::on_object_select(SimpleEvent& evt)
|
||||||
{
|
{
|
||||||
// this->take_snapshot(_(L("Object Selection")));
|
|
||||||
|
|
||||||
wxGetApp().obj_list()->update_selections();
|
wxGetApp().obj_list()->update_selections();
|
||||||
selection_changed();
|
selection_changed();
|
||||||
}
|
}
|
||||||
@ -3870,7 +3868,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
|||||||
*/
|
*/
|
||||||
const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
|
const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
|
||||||
if (wxGetApp().get_mode() == comSimple) {
|
if (wxGetApp().get_mode() == comSimple) {
|
||||||
if (menu->FindItem(_(L("Add instance"))) != wxNOT_FOUND)
|
if (menu->FindItem(_L("Add instance")) != wxNOT_FOUND)
|
||||||
{
|
{
|
||||||
/* Detach an items from the menu, but don't delete them
|
/* Detach an items from the menu, but don't delete them
|
||||||
* so that they can be added back later
|
* so that they can be added back later
|
||||||
@ -3882,7 +3880,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (menu->FindItem(_(L("Add instance"))) == wxNOT_FOUND)
|
if (menu->FindItem(_L("Add instance")) == wxNOT_FOUND)
|
||||||
{
|
{
|
||||||
// Prepend items to the menu, if those aren't not there
|
// Prepend items to the menu, if those aren't not there
|
||||||
menu->Prepend(items_set_number_of_copies[id]);
|
menu->Prepend(items_set_number_of_copies[id]);
|
||||||
@ -4011,20 +4009,20 @@ void Plater::priv::set_project_filename(const wxString& filename)
|
|||||||
bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/)
|
bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/)
|
||||||
{
|
{
|
||||||
if (is_part) {
|
if (is_part) {
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
|
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),
|
||||||
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
|
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
|
||||||
|
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Reload from disk")), _(L("Reload the selected volumes from disk")),
|
append_menu_item(menu, wxID_ANY, _L("Reload from disk"), _L("Reload the selected volumes from disk"),
|
||||||
[this](wxCommandEvent&) { q->reload_from_disk(); }, "", menu, [this]() { return can_reload_from_disk(); }, q);
|
[this](wxCommandEvent&) { q->reload_from_disk(); }, "", menu, [this]() { return can_reload_from_disk(); }, q);
|
||||||
|
|
||||||
sidebar->obj_list()->append_menu_item_export_stl(menu);
|
sidebar->obj_list()->append_menu_item_export_stl(menu);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Add instance")) + "\t+", _(L("Add one more instance of the selected object")),
|
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _L("Add instance") + "\t+", _L("Add one more instance of the selected object"),
|
||||||
[this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q);
|
[this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q);
|
||||||
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Remove instance")) + "\t-", _(L("Remove one instance of the selected object")),
|
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _L("Remove instance") + "\t-", _L("Remove one instance of the selected object"),
|
||||||
[this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q);
|
[this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q);
|
||||||
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of instances")) + dots, _(L("Change the number of instances of the selected object")),
|
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _L("Set number of instances") + dots, _L("Change the number of instances of the selected object"),
|
||||||
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q);
|
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q);
|
||||||
|
|
||||||
|
|
||||||
@ -4033,7 +4031,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
|||||||
items_set_number_of_copies.push_back(item_set_number_of_copies);
|
items_set_number_of_copies.push_back(item_set_number_of_copies);
|
||||||
|
|
||||||
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
|
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
|
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),
|
||||||
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
|
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
|
||||||
|
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
@ -4043,10 +4041,10 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
|||||||
wxMenuItem* menu_item_printable = sidebar->obj_list()->append_menu_item_printable(menu, q);
|
wxMenuItem* menu_item_printable = sidebar->obj_list()->append_menu_item_printable(menu, q);
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
|
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Reload from disk")), _(L("Reload the selected object from disk")),
|
append_menu_item(menu, wxID_ANY, _L("Reload from disk"), _L("Reload the selected object from disk"),
|
||||||
[this](wxCommandEvent&) { reload_from_disk(); }, "", nullptr, [this]() { return can_reload_from_disk(); }, q);
|
[this](wxCommandEvent&) { reload_from_disk(); }, "", nullptr, [this]() { return can_reload_from_disk(); }, q);
|
||||||
|
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")),
|
append_menu_item(menu, wxID_ANY, _L("Export as STL") + dots, _L("Export the selected object as STL file"),
|
||||||
[this](wxCommandEvent&) { q->export_stl(false, true); }, "", nullptr,
|
[this](wxCommandEvent&) { q->export_stl(false, true); }, "", nullptr,
|
||||||
[this]() {
|
[this]() {
|
||||||
const Selection& selection = get_selection();
|
const Selection& selection = get_selection();
|
||||||
@ -4075,14 +4073,14 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
|||||||
if (mirror_menu == nullptr)
|
if (mirror_menu == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
append_menu_item(mirror_menu, wxID_ANY, _(L("Along X axis")), _(L("Mirror the selected object along the X axis")),
|
append_menu_item(mirror_menu, wxID_ANY, _L("Along X axis"), _L("Mirror the selected object along the X axis"),
|
||||||
[this](wxCommandEvent&) { mirror(X); }, "mark_X", menu);
|
[this](wxCommandEvent&) { mirror(X); }, "mark_X", menu);
|
||||||
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Y axis")), _(L("Mirror the selected object along the Y axis")),
|
append_menu_item(mirror_menu, wxID_ANY, _L("Along Y axis"), _L("Mirror the selected object along the Y axis"),
|
||||||
[this](wxCommandEvent&) { mirror(Y); }, "mark_Y", menu);
|
[this](wxCommandEvent&) { mirror(Y); }, "mark_Y", menu);
|
||||||
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")),
|
append_menu_item(mirror_menu, wxID_ANY, _L("Along Z axis"), _L("Mirror the selected object along the Z axis"),
|
||||||
[this](wxCommandEvent&) { mirror(Z); }, "mark_Z", menu);
|
[this](wxCommandEvent&) { mirror(Z); }, "mark_Z", menu);
|
||||||
|
|
||||||
append_submenu(menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object")), "",
|
append_submenu(menu, mirror_menu, wxID_ANY, _L("Mirror"), _L("Mirror the selected object"), "",
|
||||||
[this]() { return can_mirror(); }, q);
|
[this]() { return can_mirror(); }, q);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -4094,12 +4092,12 @@ bool Plater::priv::complit_init_object_menu()
|
|||||||
if (split_menu == nullptr)
|
if (split_menu == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")),
|
append_menu_item(split_menu, wxID_ANY, _L("To objects"), _L("Split the selected object into individual objects"),
|
||||||
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu, [this]() { return can_split(); }, q);
|
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu, [this]() { return can_split(); }, q);
|
||||||
append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")),
|
append_menu_item(split_menu, wxID_ANY, _L("To parts"), _L("Split the selected object into individual sub-parts"),
|
||||||
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu, [this]() { return can_split(); }, q);
|
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu, [this]() { return can_split(); }, q);
|
||||||
|
|
||||||
append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "",
|
append_submenu(&object_menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "",
|
||||||
[this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q);
|
[this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q);
|
||||||
object_menu.AppendSeparator();
|
object_menu.AppendSeparator();
|
||||||
|
|
||||||
@ -4114,13 +4112,13 @@ bool Plater::priv::complit_init_object_menu()
|
|||||||
|
|
||||||
bool Plater::priv::complit_init_sla_object_menu()
|
bool Plater::priv::complit_init_sla_object_menu()
|
||||||
{
|
{
|
||||||
append_menu_item(&sla_object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual objects")),
|
append_menu_item(&sla_object_menu, wxID_ANY, _L("Split"), _L("Split the selected object into individual objects"),
|
||||||
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", nullptr, [this]() { return can_split(); }, q);
|
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", nullptr, [this]() { return can_split(); }, q);
|
||||||
|
|
||||||
sla_object_menu.AppendSeparator();
|
sla_object_menu.AppendSeparator();
|
||||||
|
|
||||||
// Add the automatic rotation sub-menu
|
// Add the automatic rotation sub-menu
|
||||||
append_menu_item(&sla_object_menu, wxID_ANY, _(L("Optimize orientation")), _(L("Optimize the rotation of the object for better print results.")),
|
append_menu_item(&sla_object_menu, wxID_ANY, _L("Optimize orientation"), _L("Optimize the rotation of the object for better print results."),
|
||||||
[this](wxCommandEvent&) { sla_optimize_rotation(); });
|
[this](wxCommandEvent&) { sla_optimize_rotation(); });
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -4128,7 +4126,7 @@ bool Plater::priv::complit_init_sla_object_menu()
|
|||||||
|
|
||||||
bool Plater::priv::complit_init_part_menu()
|
bool Plater::priv::complit_init_part_menu()
|
||||||
{
|
{
|
||||||
append_menu_item(&part_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual sub-parts")),
|
append_menu_item(&part_menu, wxID_ANY, _L("Split"), _L("Split the selected object into individual sub-parts"),
|
||||||
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", nullptr, [this]() { return can_split(); }, q);
|
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", nullptr, [this]() { return can_split(); }, q);
|
||||||
|
|
||||||
part_menu.AppendSeparator();
|
part_menu.AppendSeparator();
|
||||||
@ -4161,6 +4159,15 @@ void Plater::priv::unbind_canvas_event_handlers()
|
|||||||
if (preview != nullptr)
|
if (preview != nullptr)
|
||||||
preview->get_canvas3d()->unbind_event_handlers();
|
preview->get_canvas3d()->unbind_event_handlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::priv::reset_canvas_volumes()
|
||||||
|
{
|
||||||
|
if (view3D != nullptr)
|
||||||
|
view3D->get_canvas3d()->reset_volumes();
|
||||||
|
|
||||||
|
if (preview != nullptr)
|
||||||
|
preview->get_canvas3d()->reset_volumes();
|
||||||
|
}
|
||||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
bool Plater::priv::init_view_toolbar()
|
bool Plater::priv::init_view_toolbar()
|
||||||
@ -4494,8 +4501,8 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
|||||||
if (printer_technology_changed) {
|
if (printer_technology_changed) {
|
||||||
// Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type.
|
// Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type.
|
||||||
std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA";
|
std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA";
|
||||||
if (! wxGetApp().check_unsaved_changes(from_u8((boost::format(_utf8(
|
if (! wxGetApp().check_unsaved_changes(format_wxstr(_L(
|
||||||
L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."))) % s_pt).str())))
|
"%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."), s_pt)))
|
||||||
// Don't switch the profiles.
|
// Don't switch the profiles.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4671,7 +4678,7 @@ void Plater::load_project(const wxString& filename)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Take the Undo / Redo snapshot.
|
// Take the Undo / Redo snapshot.
|
||||||
Plater::TakeSnapshot snapshot(this, _(L("Load Project")) + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()));
|
Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()));
|
||||||
|
|
||||||
p->reset();
|
p->reset();
|
||||||
|
|
||||||
@ -4699,11 +4706,11 @@ void Plater::add_model()
|
|||||||
wxString snapshot_label;
|
wxString snapshot_label;
|
||||||
assert(! paths.empty());
|
assert(! paths.empty());
|
||||||
if (paths.size() == 1) {
|
if (paths.size() == 1) {
|
||||||
snapshot_label = _(L("Import Object"));
|
snapshot_label = _L("Import Object");
|
||||||
snapshot_label += ": ";
|
snapshot_label += ": ";
|
||||||
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
||||||
} else {
|
} else {
|
||||||
snapshot_label = _(L("Import Objects"));
|
snapshot_label = _L("Import Objects");
|
||||||
snapshot_label += ": ";
|
snapshot_label += ": ";
|
||||||
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
|
||||||
for (size_t i = 1; i < paths.size(); ++ i) {
|
for (size_t i = 1; i < paths.size(); ++ i) {
|
||||||
@ -4775,7 +4782,7 @@ void Plater::remove(size_t obj_idx) { p->remove(obj_idx); }
|
|||||||
void Plater::reset() { p->reset(); }
|
void Plater::reset() { p->reset(); }
|
||||||
void Plater::reset_with_confirm()
|
void Plater::reset_with_confirm()
|
||||||
{
|
{
|
||||||
if (wxMessageDialog((wxWindow*)this, _(L("All objects will be removed, continue?")), wxString(SLIC3R_APP_NAME) + " - " + _(L("Delete all")), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES)
|
if (wxMessageDialog((wxWindow*)this, _L("All objects will be removed, continue?"), wxString(SLIC3R_APP_NAME) + " - " + _L("Delete all"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES)
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4783,7 +4790,7 @@ void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_mo
|
|||||||
|
|
||||||
void Plater::remove_selected()
|
void Plater::remove_selected()
|
||||||
{
|
{
|
||||||
Plater::TakeSnapshot snapshot(this, _(L("Delete Selected Objects")));
|
Plater::TakeSnapshot snapshot(this, _L("Delete Selected Objects"));
|
||||||
this->p->view3D->delete_selected();
|
this->p->view3D->delete_selected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4791,7 +4798,7 @@ void Plater::increase_instances(size_t num)
|
|||||||
{
|
{
|
||||||
if (! can_increase_instances()) { return; }
|
if (! can_increase_instances()) { return; }
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(this, _(L("Increase Instances")));
|
Plater::TakeSnapshot snapshot(this, _L("Increase Instances"));
|
||||||
|
|
||||||
int obj_idx = p->get_selected_object_idx();
|
int obj_idx = p->get_selected_object_idx();
|
||||||
|
|
||||||
@ -4826,7 +4833,7 @@ void Plater::decrease_instances(size_t num)
|
|||||||
{
|
{
|
||||||
if (! can_decrease_instances()) { return; }
|
if (! can_decrease_instances()) { return; }
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(this, _(L("Decrease Instances")));
|
Plater::TakeSnapshot snapshot(this, _L("Decrease Instances"));
|
||||||
|
|
||||||
int obj_idx = p->get_selected_object_idx();
|
int obj_idx = p->get_selected_object_idx();
|
||||||
|
|
||||||
@ -4857,12 +4864,12 @@ void Plater::set_number_of_copies(/*size_t num*/)
|
|||||||
|
|
||||||
ModelObject* model_object = p->model.objects[obj_idx];
|
ModelObject* model_object = p->model.objects[obj_idx];
|
||||||
|
|
||||||
const int num = wxGetNumberFromUser( " ", _(L("Enter the number of copies:")),
|
const int num = wxGetNumberFromUser( " ", _L("Enter the number of copies:"),
|
||||||
_(L("Copies of the selected object")), model_object->instances.size(), 0, 1000, this );
|
_L("Copies of the selected object"), model_object->instances.size(), 0, 1000, this );
|
||||||
if (num < 0)
|
if (num < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(this, wxString::Format(_(L("Set numbers of copies to %d")), num));
|
Plater::TakeSnapshot snapshot(this, wxString::Format(_L("Set numbers of copies to %d"), num));
|
||||||
|
|
||||||
int diff = num - (int)model_object->instances.size();
|
int diff = num - (int)model_object->instances.size();
|
||||||
if (diff > 0)
|
if (diff > 0)
|
||||||
@ -4892,7 +4899,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(this, _(L("Cut by Plane")));
|
Plater::TakeSnapshot snapshot(this, _L("Cut by Plane"));
|
||||||
|
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
|
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
|
||||||
@ -4943,7 +4950,7 @@ void Plater::export_gcode(bool prefer_removable)
|
|||||||
|
|
||||||
fs::path output_path;
|
fs::path output_path;
|
||||||
{
|
{
|
||||||
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
|
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _L("Save G-code file as:") : _L("Save SL1 file as:"),
|
||||||
start_dir,
|
start_dir,
|
||||||
from_path(default_output_file.filename()),
|
from_path(default_output_file.filename()),
|
||||||
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
|
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
|
||||||
@ -5078,7 +5085,7 @@ void Plater::export_stl(bool extended, bool selection_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
|
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
|
||||||
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("STL file exported to %s"))) % path).str()));
|
p->statusbar()->set_status_text(format_wxstr(_L("STL file exported to %s"), path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::export_amf()
|
void Plater::export_amf()
|
||||||
@ -5095,10 +5102,10 @@ void Plater::export_amf()
|
|||||||
bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
|
bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
|
||||||
if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames)) {
|
if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames)) {
|
||||||
// Success
|
// Success
|
||||||
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("AMF file exported to %s"))) % path).str()));
|
p->statusbar()->set_status_text(format_wxstr(_L("AMF file exported to %s"), path));
|
||||||
} else {
|
} else {
|
||||||
// Failure
|
// Failure
|
||||||
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("Error exporting AMF file %s"))) % path).str()));
|
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting AMF file %s"), path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5127,12 +5134,12 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
|
|||||||
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
|
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
|
||||||
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data)) {
|
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data)) {
|
||||||
// Success
|
// Success
|
||||||
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("3MF file exported to %s"))) % path).str()));
|
p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path));
|
||||||
p->set_project_filename(path);
|
p->set_project_filename(path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Failure
|
// Failure
|
||||||
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("Error exporting 3MF file %s"))) % path).str()));
|
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5192,10 +5199,10 @@ void Plater::reslice()
|
|||||||
if (p->background_process.running())
|
if (p->background_process.running())
|
||||||
{
|
{
|
||||||
if (wxGetApp().get_mode() == comSimple)
|
if (wxGetApp().get_mode() == comSimple)
|
||||||
p->sidebar->set_btn_label(ActionButtonType::abReslice, _(L("Slicing")) + dots);
|
p->sidebar->set_btn_label(ActionButtonType::abReslice, _L("Slicing") + dots);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p->sidebar->set_btn_label(ActionButtonType::abReslice, _(L("Slice now")));
|
p->sidebar->set_btn_label(ActionButtonType::abReslice, _L("Slice now"));
|
||||||
p->show_action_buttons(false);
|
p->show_action_buttons(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5592,6 +5599,11 @@ void Plater::unbind_canvas_event_handlers()
|
|||||||
{
|
{
|
||||||
p->unbind_canvas_event_handlers();
|
p->unbind_canvas_event_handlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::reset_canvas_volumes()
|
||||||
|
{
|
||||||
|
p->reset_canvas_volumes();
|
||||||
|
}
|
||||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
PrinterTechnology Plater::printer_technology() const
|
PrinterTechnology Plater::printer_technology() const
|
||||||
@ -5694,7 +5706,7 @@ void Plater::paste_from_clipboard()
|
|||||||
if (!can_paste_from_clipboard())
|
if (!can_paste_from_clipboard())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(this, _(L("Paste From Clipboard")));
|
Plater::TakeSnapshot snapshot(this, _L("Paste From Clipboard"));
|
||||||
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
|
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +275,7 @@ public:
|
|||||||
void set_current_canvas_as_dirty();
|
void set_current_canvas_as_dirty();
|
||||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
void unbind_canvas_event_handlers();
|
void unbind_canvas_event_handlers();
|
||||||
|
void reset_canvas_volumes();
|
||||||
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||||
|
|
||||||
PrinterTechnology printer_technology() const;
|
PrinterTechnology printer_technology() const;
|
||||||
|
65
src/slic3r/GUI/format.hpp
Normal file
65
src/slic3r/GUI/format.hpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef slic3r_GUI_format_hpp_
|
||||||
|
#define slic3r_GUI_format_hpp_
|
||||||
|
|
||||||
|
// Functional wrapper around boost::format.
|
||||||
|
// One day we may replace this wrapper with C++20 format
|
||||||
|
// https://en.cppreference.com/w/cpp/utility/format/format
|
||||||
|
// though C++20 format uses a different template pattern for position independent parameters.
|
||||||
|
// This wrapper also manages implicit conversion from wxString to UTF8 and format_wxstr() variants are provided to format into wxString.
|
||||||
|
|
||||||
|
#include <libslic3r/format.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
// Format input mixing UTF8 encoded strings (const char*, std::string) and wxStrings, return a wxString.
|
||||||
|
template<typename... TArgs>
|
||||||
|
inline wxString format_wxstr(const char* fmt, TArgs&&... args) {
|
||||||
|
boost::format message(fmt);
|
||||||
|
return wxString::FromUTF8(Slic3r::internal::format::format_recursive(message, std::forward<TArgs>(args)...).c_str());
|
||||||
|
}
|
||||||
|
template<typename... TArgs>
|
||||||
|
inline wxString format_wxstr(const std::string& fmt, TArgs&&... args) {
|
||||||
|
boost::format message(fmt);
|
||||||
|
return wxString::FromUTF8(Slic3r::internal::format::format_recursive(message, std::forward<TArgs>(args)...).c_str());
|
||||||
|
}
|
||||||
|
template<typename... TArgs>
|
||||||
|
inline wxString format_wxstr(const wxString& fmt, TArgs&&... args) {
|
||||||
|
return format_wxstr(fmt.ToUTF8().data(), std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
template<typename... TArgs>
|
||||||
|
inline std::string format(const wxString& fmt, TArgs&&... args) {
|
||||||
|
return format(fmt.ToUTF8().data(), std::forward<TArgs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GUI
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
namespace format {
|
||||||
|
// Wrapper around wxScopedCharBuffer to indicate that the content is UTF8 formatted.
|
||||||
|
struct utf8_buffer {
|
||||||
|
// wxScopedCharBuffer is reference counted, therefore copying by value is cheap.
|
||||||
|
wxScopedCharBuffer data;
|
||||||
|
};
|
||||||
|
// Accept wxString and convert it to UTF8 to be processed by Slic3r::format().
|
||||||
|
inline const utf8_buffer cook(const wxString &arg) {
|
||||||
|
return utf8_buffer { arg.ToUTF8() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace io {
|
||||||
|
namespace detail {
|
||||||
|
// Adaptor for boost::format to accept wxString converted to UTF8.
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const Slic3r::internal::format::utf8_buffer& str) {
|
||||||
|
os << str.data.data();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* slic3r_GUI_format_hpp_ */
|
@ -17,6 +17,7 @@
|
|||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
#include "libslic3r/format.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
#include "slic3r/GUI/I18N.hpp"
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
@ -24,6 +25,7 @@
|
|||||||
#include "slic3r/GUI/UpdateDialogs.hpp"
|
#include "slic3r/GUI/UpdateDialogs.hpp"
|
||||||
#include "slic3r/GUI/ConfigWizard.hpp"
|
#include "slic3r/GUI/ConfigWizard.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#include "slic3r/GUI/format.hpp"
|
||||||
#include "slic3r/Utils/Http.hpp"
|
#include "slic3r/Utils/Http.hpp"
|
||||||
#include "slic3r/Config/Version.hpp"
|
#include "slic3r/Config/Version.hpp"
|
||||||
#include "slic3r/Config/Snapshot.hpp"
|
#include "slic3r/Config/Snapshot.hpp"
|
||||||
@ -54,7 +56,7 @@ void copy_file_fix(const fs::path &source, const fs::path &target)
|
|||||||
{
|
{
|
||||||
static const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; // aka 644
|
static const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; // aka 644
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << boost::format("PresetUpdater: Copying %1% -> %2%") % source % target;
|
BOOST_LOG_TRIVIAL(debug) << format("PresetUpdater: Copying %1% -> %2%", source, target);
|
||||||
|
|
||||||
// Make sure the file has correct permission both before and after we copy over it
|
// Make sure the file has correct permission both before and after we copy over it
|
||||||
if (fs::exists(target)) {
|
if (fs::exists(target)) {
|
||||||
@ -190,12 +192,12 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
|
|||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
fs::path tmp_path = target_path;
|
fs::path tmp_path = target_path;
|
||||||
tmp_path += (boost::format(".%1%%2%") % get_current_pid() % TMP_EXTENSION).str();
|
tmp_path += format(".%1%%2%", get_current_pid(), TMP_EXTENSION);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Get: `%1%`\n\t-> `%2%`\n\tvia tmp path `%3%`")
|
BOOST_LOG_TRIVIAL(info) << format("Get: `%1%`\n\t-> `%2%`\n\tvia tmp path `%3%`",
|
||||||
% url
|
url,
|
||||||
% target_path.string()
|
target_path.string(),
|
||||||
% tmp_path.string();
|
tmp_path.string());
|
||||||
|
|
||||||
Http::get(url)
|
Http::get(url)
|
||||||
.on_progress([this](Http::Progress, bool &cancel) {
|
.on_progress([this](Http::Progress, bool &cancel) {
|
||||||
@ -203,10 +205,10 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
|
|||||||
})
|
})
|
||||||
.on_error([&](std::string body, std::string error, unsigned http_status) {
|
.on_error([&](std::string body, std::string error, unsigned http_status) {
|
||||||
(void)body;
|
(void)body;
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%")
|
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
|
||||||
% url
|
url,
|
||||||
% http_status
|
http_status,
|
||||||
% error;
|
error);
|
||||||
})
|
})
|
||||||
.on_complete([&](std::string body, unsigned /* http_status */) {
|
.on_complete([&](std::string body, unsigned /* http_status */) {
|
||||||
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
|
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||||
@ -235,7 +237,7 @@ void PresetUpdater::priv::sync_version() const
|
|||||||
{
|
{
|
||||||
if (! enabled_version_check) { return; }
|
if (! enabled_version_check) { return; }
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Downloading %1% online version from: `%2%`") % SLIC3R_APP_NAME % version_check_url;
|
BOOST_LOG_TRIVIAL(info) << format("Downloading %1% online version from: `%2%`", SLIC3R_APP_NAME, version_check_url);
|
||||||
|
|
||||||
Http::get(version_check_url)
|
Http::get(version_check_url)
|
||||||
.size_limit(SLIC3R_VERSION_BODY_MAX)
|
.size_limit(SLIC3R_VERSION_BODY_MAX)
|
||||||
@ -244,10 +246,10 @@ void PresetUpdater::priv::sync_version() const
|
|||||||
})
|
})
|
||||||
.on_error([&](std::string body, std::string error, unsigned http_status) {
|
.on_error([&](std::string body, std::string error, unsigned http_status) {
|
||||||
(void)body;
|
(void)body;
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%")
|
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
|
||||||
% version_check_url
|
version_check_url,
|
||||||
% http_status
|
http_status,
|
||||||
% error;
|
error);
|
||||||
})
|
})
|
||||||
.on_complete([&](std::string body, unsigned /* http_status */) {
|
.on_complete([&](std::string body, unsigned /* http_status */) {
|
||||||
boost::trim(body);
|
boost::trim(body);
|
||||||
@ -257,11 +259,11 @@ void PresetUpdater::priv::sync_version() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! Semver::parse(body)) {
|
if (! Semver::parse(body)) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Received invalid contents from `%1%`: Not a correct semver: `%2%`") % SLIC3R_APP_NAME % body;
|
BOOST_LOG_TRIVIAL(warning) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, body);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Got %1% online version: `%2%`. Sending to GUI thread...") % SLIC3R_APP_NAME % body;
|
BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, body);
|
||||||
|
|
||||||
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
|
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
|
||||||
evt->SetString(GUI::from_u8(body));
|
evt->SetString(GUI::from_u8(body));
|
||||||
@ -315,11 +317,11 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors)
|
|||||||
try {
|
try {
|
||||||
new_index.load(idx_path_temp);
|
new_index.load(idx_path_temp);
|
||||||
} catch (const std::exception & /* err */) {
|
} catch (const std::exception & /* err */) {
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("Could not load downloaded index %1% for vendor %2%: invalid index?") % idx_path_temp % vendor.name;
|
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_temp, vendor.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (new_index.version() < index.version()) {
|
if (new_index.version() < index.version()) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << boost::format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.") % idx_path_temp % vendor.name;
|
BOOST_LOG_TRIVIAL(warning) << format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.", idx_path_temp, vendor.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Slic3r::rename_file(idx_path_temp, idx_path);
|
Slic3r::rename_file(idx_path_temp, idx_path);
|
||||||
@ -331,22 +333,22 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors)
|
|||||||
// See if a there's a new version to download
|
// See if a there's a new version to download
|
||||||
const auto recommended_it = index.recommended();
|
const auto recommended_it = index.recommended();
|
||||||
if (recommended_it == index.end()) {
|
if (recommended_it == index.end()) {
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % vendor.name;
|
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index?", vendor.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto recommended = recommended_it->config_version;
|
const auto recommended = recommended_it->config_version;
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Got index for vendor: %1%: current version: %2%, recommended version: %3%")
|
BOOST_LOG_TRIVIAL(debug) << format("Got index for vendor: %1%: current version: %2%, recommended version: %3%",
|
||||||
% vendor.name
|
vendor.name,
|
||||||
% vendor.config_version.to_string()
|
vendor.config_version.to_string(),
|
||||||
% recommended.to_string();
|
recommended.to_string());
|
||||||
|
|
||||||
if (vendor.config_version >= recommended) { continue; }
|
if (vendor.config_version >= recommended) { continue; }
|
||||||
|
|
||||||
// Download a fresh bundle
|
// Download a fresh bundle
|
||||||
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
|
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
|
||||||
const auto bundle_url = (boost::format("%1%/%2%.ini") % vendor.config_update_url % recommended.to_string()).str();
|
const auto bundle_url = format("%1%/%2%.ini", vendor.config_update_url, recommended.to_string());
|
||||||
const auto bundle_path = cache_path / (vendor.id + ".ini");
|
const auto bundle_path = cache_path / (vendor.id + ".ini");
|
||||||
if (! get_file(bundle_url, bundle_path)) { continue; }
|
if (! get_file(bundle_url, bundle_path)) { continue; }
|
||||||
if (cancel) { return; }
|
if (cancel) { return; }
|
||||||
@ -394,7 +396,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
auto bundle_path_idx = vendor_path / idx.path().filename();
|
auto bundle_path_idx = vendor_path / idx.path().filename();
|
||||||
|
|
||||||
if (! fs::exists(bundle_path)) {
|
if (! fs::exists(bundle_path)) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Confing bundle not installed for vendor %1%, skipping: ") % idx.vendor();
|
BOOST_LOG_TRIVIAL(info) << format("Confing bundle not installed for vendor %1%, skipping: ", idx.vendor());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +407,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
// from the internet, or installed / updated from the installation resources.
|
// from the internet, or installed / updated from the installation resources.
|
||||||
auto recommended = idx.recommended();
|
auto recommended = idx.recommended();
|
||||||
if (recommended == idx.end()) {
|
if (recommended == idx.end()) {
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index? Giving up.") % idx.vendor();
|
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index? Giving up.", idx.vendor());
|
||||||
// XXX: what should be done here?
|
// XXX: what should be done here?
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -413,15 +415,15 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
const auto ver_current = idx.find(vp.config_version);
|
const auto ver_current = idx.find(vp.config_version);
|
||||||
const bool ver_current_found = ver_current != idx.end();
|
const bool ver_current_found = ver_current != idx.end();
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Vendor: %1%, version installed: %2%%3%, version cached: %4%")
|
BOOST_LOG_TRIVIAL(debug) << format("Vendor: %1%, version installed: %2%%3%, version cached: %4%",
|
||||||
% vp.name
|
vp.name,
|
||||||
% vp.config_version.to_string()
|
vp.config_version.to_string(),
|
||||||
% (ver_current_found ? "" : " (not found in index!)")
|
(ver_current_found ? "" : " (not found in index!)"),
|
||||||
% recommended->config_version.to_string();
|
recommended->config_version.to_string());
|
||||||
|
|
||||||
if (! ver_current_found) {
|
if (! ver_current_found) {
|
||||||
// Any published config shall be always found in the latest config index.
|
// Any published config shall be always found in the latest config index.
|
||||||
auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str();
|
auto message = format("Preset bundle `%1%` version not found in index: %2%", idx.vendor(), vp.config_version.to_string());
|
||||||
BOOST_LOG_TRIVIAL(error) << message;
|
BOOST_LOG_TRIVIAL(error) << message;
|
||||||
GUI::show_error(nullptr, message);
|
GUI::show_error(nullptr, message);
|
||||||
continue;
|
continue;
|
||||||
@ -440,7 +442,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recommended->config_version < vp.config_version) {
|
if (recommended->config_version < vp.config_version) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << (boost::format("Recommended config version for the currently running PrusaSlicer is older than the currently installed config for vendor %1%. This should not happen.") % idx.vendor()).str();
|
BOOST_LOG_TRIVIAL(warning) << format("Recommended config version for the currently running PrusaSlicer is older than the currently installed config for vendor %1%. This should not happen.", idx.vendor());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +484,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Failed to load the config bundle `%1%`: %2%") % path_in_cache.string() % ex.what();
|
BOOST_LOG_TRIVIAL(info) << format("Failed to load the config bundle `%1%`: %2%", path_in_cache.string(), ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,13 +498,13 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
try {
|
try {
|
||||||
rsrc_vp = VendorProfile::from_ini(path_in_rsrc, false);
|
rsrc_vp = VendorProfile::from_ini(path_in_rsrc, false);
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Cannot load the config bundle at `%1%`: %2%") % path_in_rsrc.string() % ex.what();
|
BOOST_LOG_TRIVIAL(info) << format("Cannot load the config bundle at `%1%`: %2%", path_in_rsrc.string(), ex.what());
|
||||||
}
|
}
|
||||||
if (rsrc_vp.valid()) {
|
if (rsrc_vp.valid()) {
|
||||||
try {
|
try {
|
||||||
rsrc_idx.load(path_idx_in_rsrc);
|
rsrc_idx.load(path_idx_in_rsrc);
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Cannot load the config index at `%1%`: %2%") % path_idx_in_rsrc.string() % ex.what();
|
BOOST_LOG_TRIVIAL(info) << format("Cannot load the config index at `%1%`: %2%", path_idx_in_rsrc.string(), ex.what());
|
||||||
}
|
}
|
||||||
recommended = rsrc_idx.recommended();
|
recommended = rsrc_idx.recommended();
|
||||||
if (recommended != rsrc_idx.end() && recommended->config_version == rsrc_vp.config_version && recommended->config_version > vp.config_version) {
|
if (recommended != rsrc_idx.end() && recommended->config_version == rsrc_vp.config_version && recommended->config_version > vp.config_version) {
|
||||||
@ -510,8 +512,8 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
bundle_path_idx_to_install = path_idx_in_rsrc;
|
bundle_path_idx_to_install = path_idx_in_rsrc;
|
||||||
found = true;
|
found = true;
|
||||||
} else {
|
} else {
|
||||||
BOOST_LOG_TRIVIAL(warning) << (boost::format("The recommended config version for vendor `%1%` in resources does not match the recommended\n"
|
BOOST_LOG_TRIVIAL(warning) << format("The recommended config version for vendor `%1%` in resources does not match the recommended\n"
|
||||||
" config version for this version of PrusaSlicer. Corrupted installation?") % idx.vendor()).str();
|
" config version for this version of PrusaSlicer. Corrupted installation?", idx.vendor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -529,11 +531,11 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
/*const auto existing_recommended = existing_idx.recommended(old_slic3r_version);
|
/*const auto existing_recommended = existing_idx.recommended(old_slic3r_version);
|
||||||
if (existing_recommended != existing_idx.end() && recommended->config_version == existing_recommended->config_version) {
|
if (existing_recommended != existing_idx.end() && recommended->config_version == existing_recommended->config_version) {
|
||||||
// The user has already seen (and presumably rejected) this update
|
// The user has already seen (and presumably rejected) this update
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Downloaded index for `%1%` is the same as installed one, not offering an update.") % idx.vendor();
|
BOOST_LOG_TRIVIAL(info) << format("Downloaded index for `%1%` is the same as installed one, not offering an update.",idx.vendor());
|
||||||
continue;
|
continue;
|
||||||
}*/
|
}*/
|
||||||
} catch (const std::exception &err) {
|
} catch (const std::exception &err) {
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("Cannot load the installed index at `%1%`: %2%") % bundle_path_idx % err.what();
|
BOOST_LOG_TRIVIAL(error) << format("Cannot load the installed index at `%1%`: %2%", bundle_path_idx, err.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,10 +544,10 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
{
|
{
|
||||||
const auto recommended_snap = SnapshotDB::singleton().snapshot_with_vendor_preset(vp.name, recommended->config_version);
|
const auto recommended_snap = SnapshotDB::singleton().snapshot_with_vendor_preset(vp.name, recommended->config_version);
|
||||||
if (recommended_snap != SnapshotDB::singleton().end()) {
|
if (recommended_snap != SnapshotDB::singleton().end()) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Bundle update %1% %2% already found in snapshot %3%, skipping...")
|
BOOST_LOG_TRIVIAL(info) << format("Bundle update %1% %2% already found in snapshot %3%, skipping...",
|
||||||
% vp.name
|
vp.name,
|
||||||
% recommended->config_version.to_string()
|
recommended->config_version.to_string(),
|
||||||
% recommended_snap->id;
|
recommended_snap->id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,9 +557,9 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
// offered updates and to not offer the same update again if it was cancelled by the user.
|
// offered updates and to not offer the same update again if it was cancelled by the user.
|
||||||
copy_file_fix(bundle_path_idx_to_install, bundle_path_idx);
|
copy_file_fix(bundle_path_idx_to_install, bundle_path_idx);
|
||||||
} else {
|
} else {
|
||||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources")
|
BOOST_LOG_TRIVIAL(warning) << format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources",
|
||||||
% idx.vendor()
|
idx.vendor(),
|
||||||
% recommended->config_version.to_string();
|
recommended->config_version.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,7 +574,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_DOWNGRADE);
|
SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_DOWNGRADE);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% incompatible bundles") % updates.incompats.size();
|
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% incompatible bundles", updates.incompats.size());
|
||||||
|
|
||||||
for (auto &incompat : updates.incompats) {
|
for (auto &incompat : updates.incompats) {
|
||||||
BOOST_LOG_TRIVIAL(info) << '\t' << incompat;
|
BOOST_LOG_TRIVIAL(info) << '\t' << incompat;
|
||||||
@ -587,7 +589,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_UPGRADE);
|
SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_UPGRADE);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.updates.size();
|
BOOST_LOG_TRIVIAL(info) << format("Performing %1% updates", updates.updates.size());
|
||||||
|
|
||||||
for (const auto &update : updates.updates) {
|
for (const auto &update : updates.updates) {
|
||||||
BOOST_LOG_TRIVIAL(info) << '\t' << update;
|
BOOST_LOG_TRIVIAL(info) << '\t' << update;
|
||||||
@ -597,8 +599,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
PresetBundle bundle;
|
PresetBundle bundle;
|
||||||
bundle.load_configbundle(update.source.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
bundle.load_configbundle(update.source.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% conflicting presets")
|
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% conflicting presets", bundle.prints.size() + bundle.filaments.size() + bundle.printers.size());
|
||||||
% (bundle.prints.size() + bundle.filaments.size() + bundle.printers.size());
|
|
||||||
|
|
||||||
auto preset_remover = [](const Preset &preset) {
|
auto preset_remover = [](const Preset &preset) {
|
||||||
BOOST_LOG_TRIVIAL(info) << '\t' << preset.file;
|
BOOST_LOG_TRIVIAL(info) << '\t' << preset.file;
|
||||||
@ -611,8 +612,8 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
|
|
||||||
// Also apply the `obsolete_presets` property, removing obsolete ini files
|
// Also apply the `obsolete_presets` property, removing obsolete ini files
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% obsolete presets")
|
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% obsolete presets",
|
||||||
% (bundle.obsolete_presets.prints.size() + bundle.obsolete_presets.filaments.size() + bundle.obsolete_presets.printers.size());
|
bundle.obsolete_presets.prints.size() + bundle.obsolete_presets.filaments.size() + bundle.obsolete_presets.printers.size());
|
||||||
|
|
||||||
auto obsolete_remover = [](const char *subdir, const std::string &preset) {
|
auto obsolete_remover = [](const char *subdir, const std::string &preset) {
|
||||||
auto path = fs::path(Slic3r::data_dir()) / subdir / preset;
|
auto path = fs::path(Slic3r::data_dir()) / subdir / preset;
|
||||||
@ -694,7 +695,7 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
|
|||||||
|
|
||||||
auto updates = p->get_config_updates(old_slic3r_version);
|
auto updates = p->get_config_updates(old_slic3r_version);
|
||||||
if (updates.incompats.size() > 0) {
|
if (updates.incompats.size() > 0) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1% bundles incompatible. Asking for action...") % updates.incompats.size();
|
BOOST_LOG_TRIVIAL(info) << format("%1% bundles incompatible. Asking for action...", updates.incompats.size());
|
||||||
|
|
||||||
std::unordered_map<std::string, wxString> incompats_map;
|
std::unordered_map<std::string, wxString> incompats_map;
|
||||||
for (const auto &incompat : updates.incompats) {
|
for (const auto &incompat : updates.incompats) {
|
||||||
@ -702,15 +703,14 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
|
|||||||
const auto max_slic3r = incompat.version.max_slic3r_version;
|
const auto max_slic3r = incompat.version.max_slic3r_version;
|
||||||
wxString restrictions;
|
wxString restrictions;
|
||||||
if (min_slic3r != Semver::zero() && max_slic3r != Semver::inf()) {
|
if (min_slic3r != Semver::zero() && max_slic3r != Semver::inf()) {
|
||||||
restrictions = GUI::from_u8((boost::format(_utf8(L("requires min. %s and max. %s")))
|
restrictions = GUI::format_wxstr(_L("requires min. %s and max. %s"),
|
||||||
% min_slic3r.to_string()
|
min_slic3r.to_string(),
|
||||||
% max_slic3r.to_string()).str()
|
max_slic3r.to_string());
|
||||||
);
|
|
||||||
} else if (min_slic3r != Semver::zero()) {
|
} else if (min_slic3r != Semver::zero()) {
|
||||||
restrictions = GUI::from_u8((boost::format(_utf8(L("requires min. %s"))) % min_slic3r.to_string()).str());
|
restrictions = GUI::format_wxstr(_L("requires min. %s"), min_slic3r.to_string());
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Bundle is not downgrade, user will now have to do whole wizard. This should not happen.";
|
BOOST_LOG_TRIVIAL(debug) << "Bundle is not downgrade, user will now have to do whole wizard. This should not happen.";
|
||||||
} else {
|
} else {
|
||||||
restrictions = GUI::from_u8((boost::format(_utf8(L("requires max. %s"))) % max_slic3r.to_string()).str());
|
restrictions = GUI::format_wxstr(_L("requires max. %s"), max_slic3r.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
incompats_map.emplace(std::make_pair(incompat.vendor, std::move(restrictions)));
|
incompats_map.emplace(std::make_pair(incompat.vendor, std::move(restrictions)));
|
||||||
@ -742,13 +742,13 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
|
|||||||
for (const auto& update : updates.updates) {
|
for (const auto& update : updates.updates) {
|
||||||
incompatible_version = (update.forced_update ? true : incompatible_version);
|
incompatible_version = (update.forced_update ? true : incompatible_version);
|
||||||
//td::cout << update.forced_update << std::endl;
|
//td::cout << update.forced_update << std::endl;
|
||||||
//BOOST_LOG_TRIVIAL(info) << boost::format("Update requires higher version.");
|
//BOOST_LOG_TRIVIAL(info) << format("Update requires higher version.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//forced update
|
//forced update
|
||||||
if(incompatible_version)
|
if(incompatible_version)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. At least one requires higher version of Slicer.") % updates.updates.size();
|
BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. At least one requires higher version of Slicer.", updates.updates.size());
|
||||||
|
|
||||||
std::vector<GUI::MsgUpdateForced::Update> updates_msg;
|
std::vector<GUI::MsgUpdateForced::Update> updates_msg;
|
||||||
for (const auto& update : updates.updates) {
|
for (const auto& update : updates.updates) {
|
||||||
@ -778,7 +778,7 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
|
|||||||
}
|
}
|
||||||
|
|
||||||
// regular update
|
// regular update
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. Asking for confirmation ...") % updates.updates.size();
|
BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. Asking for confirmation ...", updates.updates.size());
|
||||||
|
|
||||||
std::vector<GUI::MsgUpdateConfig::Update> updates_msg;
|
std::vector<GUI::MsgUpdateConfig::Update> updates_msg;
|
||||||
for (const auto &update : updates.updates) {
|
for (const auto &update : updates.updates) {
|
||||||
@ -813,7 +813,7 @@ void PresetUpdater::install_bundles_rsrc(std::vector<std::string> bundles, bool
|
|||||||
{
|
{
|
||||||
Updates updates;
|
Updates updates;
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("Installing %1% bundles from resources ...") % bundles.size();
|
BOOST_LOG_TRIVIAL(info) << format("Installing %1% bundles from resources ...", bundles.size());
|
||||||
|
|
||||||
for (const auto &bundle : bundles) {
|
for (const auto &bundle : bundles) {
|
||||||
auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");
|
auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");
|
||||||
|
@ -183,3 +183,7 @@
|
|||||||
#include "libslic3r/BoundingBox.hpp"
|
#include "libslic3r/BoundingBox.hpp"
|
||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "GUI/format.hpp"
|
||||||
|
#endif // _WIN32
|
||||||
|
Loading…
Reference in New Issue
Block a user