Merge branch 'master' into fs_simplify_multipart_object

This commit is contained in:
Filip Sykala 2021-11-19 15:42:11 +01:00
commit 5e48ee7c83
40 changed files with 562 additions and 217 deletions

View File

@ -1,4 +1,5 @@
min_slic3r_version = 2.3.1-beta min_slic3r_version = 2.3.1-beta
0.0.4 Fixed first layer height in 0.28mm profile.
0.0.3 Fixed Genius bed size. 0.0.3 Fixed Genius bed size.
0.0.2 Updated start g-code. 0.0.2 Updated start g-code.
0.0.1 Initial Artillery bundle 0.0.1 Initial Artillery bundle

View File

@ -11,7 +11,7 @@
name = Artillery name = Artillery
# Configuration version of this file. Config file will only be installed, if the config_version differs. # Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded. # This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.3 config_version = 0.0.4
# Where to get the updates from? # Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Artillery/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Artillery/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% # changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -300,6 +300,7 @@ top_solid_layers = 4
[print:*0.28mm*] [print:*0.28mm*]
inherits = *common* inherits = *common*
layer_height = 0.28 layer_height = 0.28
first_layer_height = 0.36
top_infill_extrusion_width = 0.45 top_infill_extrusion_width = 0.45
first_layer_extrusion_width = 0.75 first_layer_extrusion_width = 0.75
bottom_solid_layers = 3 bottom_solid_layers = 3

View File

@ -1,3 +1,4 @@
min_slic3r_version = 2.3.1-beta min_slic3r_version = 2.3.1-beta
0.0.1 Initial version 0.0.3 Set default filament profile.
0.0.2 Improved start gcode, changed filename format 0.0.2 Improved start gcode, changed filename format
0.0.1 Initial version

View File

@ -3,7 +3,7 @@
[vendor] [vendor]
# Vendor name will be shown by the Config Wizard. # Vendor name will be shown by the Config Wizard.
name = INAT name = INAT
config_version = 0.0.2 config_version = 0.0.3
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/
### ###
@ -15,12 +15,14 @@ name = INAT Proton X Rail
variants = 0.4 variants = 0.4
technology = FFF technology = FFF
family = Proton family = Proton
default_materials = PLA @PROTON_X
[printer_model:PROTON_X_ROD] [printer_model:PROTON_X_ROD]
name = INAT Proton X Rod name = INAT Proton X Rod
variants = 0.4 variants = 0.4
technology = FFF technology = FFF
family = Proton family = Proton
default_materials = PLA @PROTON_X
### ###

View File

@ -216,6 +216,11 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
} }
} }
if (num_above == 0)
// Special case, the object is completely below the print bed, thus it is outside,
// however we want to allow an object to be still printable if some of its parts are completely below the print bed.
return BuildVolume::ObjectState::Below;
// 2) Calculate intersections of triangle edges with the build surface. // 2) Calculate intersections of triangle edges with the build surface.
inside = num_inside > 0; inside = num_inside > 0;
outside = num_inside < num_above; outside = num_inside < num_above;
@ -303,7 +308,9 @@ BuildVolume::ObjectState BuildVolume::volume_state_bbox(const BoundingBoxf3 &vol
BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon); BoundingBox3Base<Vec3d> build_volume = this->bounding_volume().inflated(SceneEpsilon);
if (m_max_print_height == 0) if (m_max_print_height == 0)
build_volume.max.z() = std::numeric_limits<double>::max(); build_volume.max.z() = std::numeric_limits<double>::max();
return build_volume.contains(volume_bbox) ? ObjectState::Inside : build_volume.intersects(volume_bbox) ? ObjectState::Colliding : ObjectState::Outside; return build_volume.max.z() <= - SceneEpsilon ? ObjectState::Below :
build_volume.contains(volume_bbox) ? ObjectState::Inside :
build_volume.intersects(volume_bbox) ? ObjectState::Colliding : ObjectState::Outside;
} }
bool BuildVolume::all_paths_inside(const GCodeProcessorResult &paths, const BoundingBoxf3 &paths_bbox) const bool BuildVolume::all_paths_inside(const GCodeProcessorResult &paths, const BoundingBoxf3 &paths_bbox) const

View File

@ -68,7 +68,10 @@ public:
// Colliding with the build volume boundary, thus not printable and error is shown. // Colliding with the build volume boundary, thus not printable and error is shown.
Colliding, Colliding,
// Outside of the build volume means the object is ignored: Not printed and no error is shown. // Outside of the build volume means the object is ignored: Not printed and no error is shown.
Outside Outside,
// Completely below the print bed. The same as Outside, but an object with one printable part below the print bed
// and at least one part above the print bed is still printable.
Below,
}; };
// 1) Tests called on the plater. // 1) Tests called on the plater.

View File

@ -19,6 +19,7 @@
#include "libslic3r/SLA/RasterBase.hpp" #include "libslic3r/SLA/RasterBase.hpp"
#include "libslic3r/miniz_extension.hpp" #include "libslic3r/miniz_extension.hpp"
#include "libslic3r/PNGReadWrite.hpp" #include "libslic3r/PNGReadWrite.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
@ -321,11 +322,13 @@ ConfigSubstitutions import_sla_archive(
lh_opt != arch.config.not_found()) lh_opt != arch.config.not_found())
{ {
auto lh_str = lh_opt->second.data(); auto lh_str = lh_opt->second.data();
try {
double lh = std::stod(lh_str); // TODO replace with std::from_chars size_t pos;
double lh = string_to_double_decimal_point(lh_str, &pos);
if (pos) { // TODO: verify that pos is 0 when parsing fails
profile_out.set("layer_height", lh); profile_out.set("layer_height", lh);
profile_out.set("initial_layer_height", lh); profile_out.set("initial_layer_height", lh);
} catch(...) {} }
} }
} }

View File

@ -533,9 +533,8 @@ std::string GCodeWriter::set_fan(unsigned int speed) const
return GCodeWriter::set_fan(this->config.gcode_flavor, this->config.gcode_comments, speed); return GCodeWriter::set_fan(this->config.gcode_flavor, this->config.gcode_comments, speed);
} }
void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) { void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) {
assert(digits <= 6); assert(digits <= 9);
static constexpr const std::array<int, 10> pow_10{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; static constexpr const std::array<int, 10> pow_10{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
*ptr_err.ptr++ = ' '; *ptr_err.ptr++ = axis; *ptr_err.ptr++ = ' '; *ptr_err.ptr++ = axis;
@ -576,6 +575,21 @@ void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) {
if ((this->ptr_err.ptr + 1) == base_ptr || *this->ptr_err.ptr == '-') if ((this->ptr_err.ptr + 1) == base_ptr || *this->ptr_err.ptr == '-')
*(++this->ptr_err.ptr) = '0'; *(++this->ptr_err.ptr) = '0';
this->ptr_err.ptr++; this->ptr_err.ptr++;
#if 0 // #ifndef NDEBUG
{
// Verify that the optimized formatter produces the same result as the standard sprintf().
double v1 = atof(std::string(base_ptr, this->ptr_err.ptr).c_str());
char buf[2048];
sprintf(buf, "%.*lf", int(digits), v);
double v2 = atof(buf);
// Numbers may differ when rounding at exactly or very close to 0.5 due to numerical issues when scaling the double to an integer.
// Thus the complex assert.
// assert(v1 == v2);
assert(std::abs(v1 - v) * pow_10[digits] < 0.50001);
assert(std::abs(v2 - v) * pow_10[digits] < 0.50001);
}
#endif // NDEBUG
} }
} // namespace Slic3r } // namespace Slic3r

View File

@ -12,11 +12,6 @@
#include <CGAL/Polygon_mesh_processing/corefinement.h> #include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/Exact_integer.h> #include <CGAL/Exact_integer.h>
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/Cartesian_converter.h> #include <CGAL/Cartesian_converter.h>
namespace Slic3r { namespace Slic3r {

View File

@ -182,6 +182,8 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config); CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
CustomGCode::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z); CustomGCode::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z);
handle_legacy_sla(*config);
return model; return model;
} }
@ -1544,15 +1546,21 @@ unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume
const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix(); const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix();
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */); BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
if (state == BuildVolume::ObjectState::Inside) if (state == BuildVolume::ObjectState::Inside)
// Volume is completely inside.
inside_outside |= INSIDE; inside_outside |= INSIDE;
else if (state == BuildVolume::ObjectState::Outside) else if (state == BuildVolume::ObjectState::Outside)
// Volume is completely outside.
inside_outside |= OUTSIDE; inside_outside |= OUTSIDE;
else else if (state == BuildVolume::ObjectState::Below) {
// Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable
// if some of its volumes are still inside the build volume.
} else
// Volume colliding with the build volume.
inside_outside |= INSIDE | OUTSIDE; inside_outside |= INSIDE | OUTSIDE;
} }
model_instance->print_volume_state = model_instance->print_volume_state =
(inside_outside == (INSIDE | OUTSIDE)) ? ModelInstancePVS_Partly_Outside : inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside :
(inside_outside == INSIDE) ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside; inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
if (inside_outside == INSIDE) if (inside_outside == INSIDE)
++num_printable; ++num_printable;
} }

View File

@ -1723,10 +1723,21 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
}); // end of parallel_for }); // end of parallel_for
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end";
std::vector<BoundingBox> layer_bboxes(num_layers);
for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) { for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
throw_on_cancel_callback(); throw_on_cancel_callback();
BoundingBox bbox(get_extents(layers[layer_idx]->regions())); layer_bboxes[layer_idx] = get_extents(layers[layer_idx]->regions());
bbox.merge(get_extents(input_expolygons[layer_idx])); layer_bboxes[layer_idx].merge(get_extents(input_expolygons[layer_idx]));
}
for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
throw_on_cancel_callback();
BoundingBox bbox = layer_bboxes[layer_idx];
// Projected triangles could, in rare cases (as in GH issue #7299), belongs to polygons printed in the previous or the next layer.
// Let's merge the bounding box of the current layer with bounding boxes of the previous and the next layer to ensure that
// every projected triangle will be inside the resulting bounding box.
if (layer_idx > 1) bbox.merge(layer_bboxes[layer_idx - 1]);
if (layer_idx < num_layers - 1) bbox.merge(layer_bboxes[layer_idx + 1]);
// Projected triangles may slightly exceed the input polygons. // Projected triangles may slightly exceed the input polygons.
bbox.offset(20 * SCALED_EPSILON); bbox.offset(20 * SCALED_EPSILON);
edge_grids[layer_idx].set_bbox(bbox); edge_grids[layer_idx].set_bbox(bbox);

View File

@ -303,6 +303,8 @@ void Preset::normalize(DynamicPrintConfig &config)
first_layer_height->value = first_layer_height->get_abs_value(layer_height->value); first_layer_height->value = first_layer_height->get_abs_value(layer_height->value);
first_layer_height->percent = false; first_layer_height->percent = false;
} }
handle_legacy_sla(config);
} }
std::string Preset::remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config) std::string Preset::remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config)
@ -544,6 +546,9 @@ static std::vector<std::string> s_Preset_sla_material_options {
"exposure_time", "exposure_time",
"initial_exposure_time", "initial_exposure_time",
"material_correction", "material_correction",
"material_correction_x",
"material_correction_y",
"material_correction_z",
"material_notes", "material_notes",
"material_vendor", "material_vendor",
"default_sla_material_profile", "default_sla_material_profile",
@ -559,6 +564,9 @@ static std::vector<std::string> s_Preset_sla_printer_options {
"display_orientation", "display_orientation",
"fast_tilt_time", "slow_tilt_time", "area_fill", "fast_tilt_time", "slow_tilt_time", "area_fill",
"relative_correction", "relative_correction",
"relative_correction_x",
"relative_correction_y",
"relative_correction_z",
"absolute_correction", "absolute_correction",
"elefant_foot_compensation", "elefant_foot_compensation",
"elefant_foot_min_width", "elefant_foot_min_width",

View File

@ -3148,6 +3148,30 @@ void PrintConfigDef::init_sla_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats( { 1., 1.} )); def->set_default_value(new ConfigOptionFloats( { 1., 1.} ));
def = this->add("relative_correction_x", coFloat);
def->label = L("Printer scaling correction in X axis");
def->full_label = L("Printer scaling X axis correction");
def->tooltip = L("Printer scaling correction in X axis");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(1.));
def = this->add("relative_correction_y", coFloat);
def->label = L("Printer scaling correction in Y axis");
def->full_label = L("Printer scaling X axis correction");
def->tooltip = L("Printer scaling correction in Y axis");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(1.));
def = this->add("relative_correction_z", coFloat);
def->label = L("Printer scaling correction in Z axis");
def->full_label = L("Printer scaling X axis correction");
def->tooltip = L("Printer scaling correction in Z axis");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(1.));
def = this->add("absolute_correction", coFloat); def = this->add("absolute_correction", coFloat);
def->label = L("Printer absolute correction"); def->label = L("Printer absolute correction");
def->full_label = L("Printer absolute correction"); def->full_label = L("Printer absolute correction");
@ -3292,7 +3316,28 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L("Correction for expansion"); def->tooltip = L("Correction for expansion");
def->min = 0; def->min = 0;
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats( { 1. , 1. } )); def->set_default_value(new ConfigOptionFloats( { 1., 1., 1. } ));
def = this->add("material_correction_x", coFloat);
def->full_label = L("Correction for expansion in X axis");
def->tooltip = L("Correction for expansion in X axis");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(1.));
def = this->add("material_correction_y", coFloat);
def->full_label = L("Correction for expansion in Y axis");
def->tooltip = L("Correction for expansion in Y axis");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(1.));
def = this->add("material_correction_z", coFloat);
def->full_label = L("Correction for expansion in Z axis");
def->tooltip = L("Correction for expansion in Z axis");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(1.));
def = this->add("material_notes", coString); def = this->add("material_notes", coString);
def->label = L("SLA print material notes"); def->label = L("SLA print material notes");
@ -3749,7 +3794,16 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
opt_key = "printhost_apikey"; opt_key = "printhost_apikey";
} else if (opt_key == "preset_name") { } else if (opt_key == "preset_name") {
opt_key = "preset_names"; opt_key = "preset_names";
} /*else if (opt_key == "material_correction" || opt_key == "relative_correction") {
ConfigOptionFloats p;
p.deserialize(value);
if (p.values.size() < 3) {
double firstval = p.values.front();
p.values.emplace(p.values.begin(), firstval);
value = p.serialize();
} }
}*/
// Ignore the following obsolete configuration keys: // Ignore the following obsolete configuration keys:
static std::set<std::string> ignore = { static std::set<std::string> ignore = {
@ -3866,6 +3920,28 @@ void DynamicPrintConfig::normalize_fdm()
} }
} }
void handle_legacy_sla(DynamicPrintConfig &config)
{
for (std::string corr : {"relative_correction", "material_correction"}) {
if (config.has(corr)) {
if (std::string corr_x = corr + "_x"; !config.has(corr_x)) {
auto* opt = config.opt<ConfigOptionFloat>(corr_x, true);
opt->value = config.opt<ConfigOptionFloats>(corr)->values[0];
}
if (std::string corr_y = corr + "_y"; !config.has(corr_y)) {
auto* opt = config.opt<ConfigOptionFloat>(corr_y, true);
opt->value = config.opt<ConfigOptionFloats>(corr)->values[0];
}
if (std::string corr_z = corr + "_z"; !config.has(corr_z)) {
auto* opt = config.opt<ConfigOptionFloat>(corr_z, true);
opt->value = config.opt<ConfigOptionFloats>(corr)->values[1];
}
}
}
}
void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders) void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders)
{ {
const auto &defaults = FullPrintConfig::defaults(); const auto &defaults = FullPrintConfig::defaults();

View File

@ -224,6 +224,8 @@ public:
{ PrintConfigDef::handle_legacy(opt_key, value); } { PrintConfigDef::handle_legacy(opt_key, value); }
}; };
void handle_legacy_sla(DynamicPrintConfig &config);
class StaticPrintConfig : public StaticConfig class StaticPrintConfig : public StaticConfig
{ {
public: public:
@ -924,6 +926,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, exposure_time)) ((ConfigOptionFloat, exposure_time))
((ConfigOptionFloat, initial_exposure_time)) ((ConfigOptionFloat, initial_exposure_time))
((ConfigOptionFloats, material_correction)) ((ConfigOptionFloats, material_correction))
((ConfigOptionFloat, material_correction_x))
((ConfigOptionFloat, material_correction_y))
((ConfigOptionFloat, material_correction_z))
) )
PRINT_CONFIG_CLASS_DEFINE( PRINT_CONFIG_CLASS_DEFINE(
@ -940,6 +945,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, display_mirror_x)) ((ConfigOptionBool, display_mirror_x))
((ConfigOptionBool, display_mirror_y)) ((ConfigOptionBool, display_mirror_y))
((ConfigOptionFloats, relative_correction)) ((ConfigOptionFloats, relative_correction))
((ConfigOptionFloat, relative_correction_x))
((ConfigOptionFloat, relative_correction_y))
((ConfigOptionFloat, relative_correction_z))
((ConfigOptionFloat, absolute_correction)) ((ConfigOptionFloat, absolute_correction))
((ConfigOptionFloat, elefant_foot_compensation)) ((ConfigOptionFloat, elefant_foot_compensation))
((ConfigOptionFloat, elefant_foot_min_width)) ((ConfigOptionFloat, elefant_foot_min_width))

View File

@ -807,7 +807,13 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
static std::unordered_set<std::string> steps_full = { static std::unordered_set<std::string> steps_full = {
"initial_layer_height", "initial_layer_height",
"material_correction", "material_correction",
"material_correction_x",
"material_correction_y",
"material_correction_z",
"relative_correction", "relative_correction",
"relative_correction_x",
"relative_correction_y",
"relative_correction_z",
"absolute_correction", "absolute_correction",
"elefant_foot_compensation", "elefant_foot_compensation",
"elefant_foot_min_width", "elefant_foot_min_width",
@ -1047,15 +1053,15 @@ Vec3d SLAPrint::relative_correction() const
Vec3d corr(1., 1., 1.); Vec3d corr(1., 1., 1.);
if(printer_config().relative_correction.values.size() >= 2) { if(printer_config().relative_correction.values.size() >= 2) {
corr.x() = printer_config().relative_correction.values[0]; corr.x() = printer_config().relative_correction_x.value;
corr.y() = corr.x(); corr.y() = printer_config().relative_correction_y.value;
corr.z() = printer_config().relative_correction.values[1]; corr.z() = printer_config().relative_correction_z.value;
} }
if(material_config().material_correction.values.size() >= 2) { if(material_config().material_correction.values.size() >= 2) {
corr.x() *= material_config().material_correction.values[0]; corr.x() *= material_config().material_correction_x.value;
corr.y() = corr.x(); corr.y() *= material_config().material_correction_y.value;
corr.z() *= material_config().material_correction.values[1]; corr.z() *= material_config().material_correction_z.value;
} }
return corr; return corr;

View File

@ -189,6 +189,7 @@ set(SLIC3R_GUI_SOURCES
GUI/Mouse3DController.hpp GUI/Mouse3DController.hpp
GUI/DoubleSlider.cpp GUI/DoubleSlider.cpp
GUI/DoubleSlider.hpp GUI/DoubleSlider.hpp
GUI/DoubleSlider_Utils.hpp
GUI/Notebook.cpp GUI/Notebook.cpp
GUI/Notebook.hpp GUI/Notebook.hpp
GUI/ObjectDataViewModel.cpp GUI/ObjectDataViewModel.cpp

View File

@ -932,9 +932,11 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state) const bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state) const
{ {
const Model& model = GUI::wxGetApp().plater()->model(); const Model& model = GUI::wxGetApp().plater()->model();
auto volume_below = [](GLVolume& volume) -> bool
{ return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_below_printbed(); };
// Volume is partially below the print bed, thus a pre-calculated convex hull cannot be used. // Volume is partially below the print bed, thus a pre-calculated convex hull cannot be used.
auto volume_sinking = [](GLVolume& volume) -> bool auto volume_sinking = [](GLVolume& volume) -> bool
{ return volume.is_sinking() && volume.object_idx() != -1 && volume.volume_idx() != -1; }; { return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_sinking(); };
// Cached bounding box of a volume above the print bed. // Cached bounding box of a volume above the print bed.
auto volume_bbox = [volume_sinking](GLVolume& volume) -> BoundingBoxf3 auto volume_bbox = [volume_sinking](GLVolume& volume) -> BoundingBoxf3
{ return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box() : volume.transformed_convex_hull_bounding_box(); }; { return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box() : volume.transformed_convex_hull_bounding_box(); };
@ -948,6 +950,9 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
for (GLVolume* volume : this->volumes) for (GLVolume* volume : this->volumes)
if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) { if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) {
BuildVolume::ObjectState state; BuildVolume::ObjectState state;
if (volume_below(*volume))
state = BuildVolume::ObjectState::Below;
else {
switch (build_volume.type()) { switch (build_volume.type()) {
case BuildVolume::Type::Rectangle: case BuildVolume::Type::Rectangle:
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects. //FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
@ -964,6 +969,8 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
state = BuildVolume::ObjectState::Inside; state = BuildVolume::ObjectState::Inside;
break; break;
} }
assert(state != BuildVolume::ObjectState::Below);
}
volume->is_outside = state != BuildVolume::ObjectState::Inside; volume->is_outside = state != BuildVolume::ObjectState::Inside;
if (volume->printable) { if (volume->printable) {
if (overall_state == ModelInstancePVS_Inside && volume->is_outside) if (overall_state == ModelInstancePVS_Inside && volume->is_outside)

View File

@ -1,5 +1,6 @@
#include "libslic3r/libslic3r.h" #include "libslic3r/libslic3r.h"
#include "DoubleSlider.hpp" #include "DoubleSlider.hpp"
#include "DoubleSlider_Utils.hpp"
#include "libslic3r/GCode.hpp" #include "libslic3r/GCode.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
@ -2546,12 +2547,70 @@ bool Control::check_ticks_changed_event(Type type)
std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder) std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder)
{ {
if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) { if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) {
#if 1
if (ticks.empty())
return get_opposite_color((*m_colors)[0]);
auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick);
if (before_tick_it == ticks.end())
{
while (before_tick_it != ticks.begin())
if (--before_tick_it; before_tick_it->type == ColorChange)
break;
if (before_tick_it->type == ColorChange)
return get_opposite_color(before_tick_it->color);
return get_opposite_color((*m_colors)[0]);
}
if (before_tick_it == ticks.begin())
{
const std::string& frst_color = (*m_colors)[0];
if (before_tick_it->type == ColorChange)
return get_opposite_color(frst_color, before_tick_it->color);
auto next_tick_it = before_tick_it;
while (next_tick_it != ticks.end())
if (++next_tick_it; next_tick_it->type == ColorChange)
break;
if (next_tick_it->type == ColorChange)
return get_opposite_color(frst_color, next_tick_it->color);
return get_opposite_color(frst_color);
}
std::string frst_color = "";
if (before_tick_it->type == ColorChange)
frst_color = before_tick_it->color;
else {
auto next_tick_it = before_tick_it;
while (next_tick_it != ticks.end())
if (++next_tick_it; next_tick_it->type == ColorChange) {
frst_color = next_tick_it->color;
break;
}
}
while (before_tick_it != ticks.begin())
if (--before_tick_it; before_tick_it->type == ColorChange)
break;
if (before_tick_it->type == ColorChange) {
if (frst_color.empty())
return get_opposite_color(before_tick_it->color);
return get_opposite_color(before_tick_it->color, frst_color);
}
if (frst_color.empty())
return get_opposite_color((*m_colors)[0]);
return get_opposite_color((*m_colors)[0], frst_color);
#else
const std::vector<std::string>& colors = ColorPrintColors::get(); const std::vector<std::string>& colors = ColorPrintColors::get();
if (ticks.empty()) if (ticks.empty())
return colors[0]; return colors[0];
m_default_color_idx++; m_default_color_idx++;
return colors[m_default_color_idx % colors.size()]; return colors[m_default_color_idx % colors.size()];
#endif
} }
std::string color = (*m_colors)[extruder - 1]; std::string color = (*m_colors)[extruder - 1];

View File

@ -0,0 +1,173 @@
#include <stdio.h>
#include "wx/colour.h"
// next code is borrowed from https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both
typedef struct {
double r; // a fraction between 0 and 1
double g; // a fraction between 0 and 1
double b; // a fraction between 0 and 1
} rgb;
typedef struct {
double h; // angle in degrees
double s; // a fraction between 0 and 1
double v; // a fraction between 0 and 1
} hsv;
static hsv rgb2hsv(rgb in);
static rgb hsv2rgb(hsv in);
hsv rgb2hsv(rgb in)
{
hsv out;
double min, max, delta;
min = in.r < in.g ? in.r : in.g;
min = min < in.b ? min : in.b;
max = in.r > in.g ? in.r : in.g;
max = max > in.b ? max : in.b;
out.v = max; // v
delta = max - min;
if (delta < 0.00001)
{
out.s = 0;
out.h = 0; // undefined, maybe nan?
return out;
}
if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
out.s = (delta / max); // s
} else {
// if max is 0, then r = g = b = 0
// s = 0, h is undefined
out.s = 0.0;
out.h = NAN; // its now undefined
return out;
}
if( in.r >= max ) // > is bogus, just keeps compilor happy
out.h = ( in.g - in.b ) / delta; // between yellow & magenta
else
if( in.g >= max )
out.h = 2.0 + ( in.b - in.r ) / delta; // between cyan & yellow
else
out.h = 4.0 + ( in.r - in.g ) / delta; // between magenta & cyan
out.h *= 60.0; // degrees
if( out.h < 0.0 )
out.h += 360.0;
return out;
}
hsv rgb2hsv(const std::string& str_clr_in)
{
wxColour clr(str_clr_in);
rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 };
return rgb2hsv(in);
}
rgb hsv2rgb(hsv in)
{
double hh, p, q, t, ff;
long i;
rgb out;
if(in.s <= 0.0) { // < is bogus, just shuts up warnings
out.r = in.v;
out.g = in.v;
out.b = in.v;
return out;
}
hh = in.h;
if (hh >= 360.0) hh -= 360.0;//hh = 0.0;
hh /= 60.0;
i = (long)hh;
ff = hh - i;
p = in.v * (1.0 - in.s);
q = in.v * (1.0 - (in.s * ff));
t = in.v * (1.0 - (in.s * (1.0 - ff)));
switch(i) {
case 0:
out.r = in.v;
out.g = t;
out.b = p;
break;
case 1:
out.r = q;
out.g = in.v;
out.b = p;
break;
case 2:
out.r = p;
out.g = in.v;
out.b = t;
break;
case 3:
out.r = p;
out.g = q;
out.b = in.v;
break;
case 4:
out.r = t;
out.g = p;
out.b = in.v;
break;
case 5:
default:
out.r = in.v;
out.g = p;
out.b = q;
break;
}
return out;
}
double rand_val()
{
return 0.1 * (10 - rand() % 8);
}
std::string get_opposite_color(const std::string& color)
{
std::string opp_color = "";
hsv hsv_clr = rgb2hsv(color);
hsv_clr.h += 65; // 65 instead 60 to avoid circle values
hsv_clr.s = rand_val();
hsv_clr.v = rand_val();
rgb rgb_opp_color = hsv2rgb(hsv_clr);
wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255));
opp_color = clr_str.ToStdString();
return opp_color;
}
std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd)
{
std::string opp_color = "";
hsv hsv_frst = rgb2hsv(color_frst);
hsv hsv_scnd = rgb2hsv(color_scnd);
double delta_h = fabs(hsv_frst.h - hsv_scnd.h);
double start_h = delta_h > 180 ? std::min<double>(hsv_scnd.h, hsv_frst.h) : std::max<double>(hsv_scnd.h, hsv_frst.h);
start_h += 5; // to avoid circle change of colors for 120 deg
if (delta_h < 180)
delta_h = 360 - delta_h;
hsv hsv_opp = hsv{ start_h + 0.5 * delta_h, rand_val(), rand_val() };
rgb rgb_opp_color = hsv2rgb(hsv_opp);
wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255));
opp_color = clr_str.ToStdString();
return opp_color;
}

View File

@ -4721,7 +4721,7 @@ bool GLCanvas3D::_init_undoredo_toolbar()
std::string curr_additional_tooltip; std::string curr_additional_tooltip;
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip); m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
std::string new_additional_tooltip = ""; std::string new_additional_tooltip;
if (can_undo) { if (can_undo) {
std::string action; std::string action;
wxGetApp().plater()->undo_redo_topmost_string_getter(true, action); wxGetApp().plater()->undo_redo_topmost_string_getter(true, action);
@ -4759,7 +4759,7 @@ bool GLCanvas3D::_init_undoredo_toolbar()
std::string curr_additional_tooltip; std::string curr_additional_tooltip;
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip); m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
std::string new_additional_tooltip = ""; std::string new_additional_tooltip;
if (can_redo) { if (can_redo) {
std::string action; std::string action;
wxGetApp().plater()->undo_redo_topmost_string_getter(false, action); wxGetApp().plater()->undo_redo_topmost_string_getter(false, action);

View File

@ -992,22 +992,13 @@ bool GUI_App::OnInit()
bool GUI_App::on_init_inner() bool GUI_App::on_init_inner()
{ {
// win32 build on win64 and viceversa #if defined(_WIN32) && ! defined(_WIN64)
#ifdef _WIN64 // Win32 32bit build.
if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "") {
RichMessageDialog dlg(nullptr,
_L("You have started PrusaSlicer for 64-bit architecture on 32-bit system."
"\nPlease download and install correct version at https://www.prusa3d.cz/prusaslicer/."
"\nDo you wish to continue?"),
"PrusaSlicer", wxICON_QUESTION | wxYES_NO);
if (dlg.ShowModal() != wxID_YES)
return false;
}
#elif _WIN32
if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "64") { if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "64") {
RichMessageDialog dlg(nullptr, RichMessageDialog dlg(nullptr,
_L("You have started PrusaSlicer for 32-bit architecture on 64-bit system." _L("You are running a 32 bit build of PrusaSlicer on 64-bit Windows."
"\nPlease download and install correct version at https://www.prusa3d.cz/prusaslicer/." "\n32 bit build of PrusaSlicer will likely not be able to utilize all the RAM available in the system."
"\nPlease download and install a 64 bit build of PrusaSlice from https://www.prusa3d.cz/prusaslicer/."
"\nDo you wish to continue?"), "\nDo you wish to continue?"),
"PrusaSlicer", wxICON_QUESTION | wxYES_NO); "PrusaSlicer", wxICON_QUESTION | wxYES_NO);
if (dlg.ShowModal() != wxID_YES) if (dlg.ShowModal() != wxID_YES)

View File

@ -913,18 +913,11 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
show_context_menu(evt_context_menu); show_context_menu(evt_context_menu);
else if (title == _("Name")) else if (title == _("Name"))
{ {
if (wxOSX) if (is_windows10() && m_objects_model->HasWarningIcon(item) &&
show_context_menu(evt_context_menu); // return context menu under OSX (related to #2909)
if (is_windows10())
{
int obj_idx, vol_idx;
get_selected_item_indexes(obj_idx, vol_idx, item);
if (m_objects_model->HasWarningIcon(item) &&
mouse_pos.x > 2 * wxGetApp().em_unit() && mouse_pos.x < 4 * wxGetApp().em_unit()) mouse_pos.x > 2 * wxGetApp().em_unit() && mouse_pos.x < 4 * wxGetApp().em_unit())
fix_through_netfabb(); fix_through_netfabb();
} else
show_context_menu(evt_context_menu); // show context menu for "Name" column too
} }
// workaround for extruder editing under OSX // workaround for extruder editing under OSX
else if (wxOSX && evt_context_menu && title == _("Extruder")) else if (wxOSX && evt_context_menu && title == _("Extruder"))

View File

@ -181,17 +181,16 @@ bool ObjectSettings::update_settings_list()
bool ObjectSettings::add_missed_options(ModelConfig* config_to, const DynamicPrintConfig& config_from) bool ObjectSettings::add_missed_options(ModelConfig* config_to, const DynamicPrintConfig& config_from)
{ {
const DynamicPrintConfig& print_config = wxGetApp().plater()->printer_technology() == ptFFF ?
wxGetApp().preset_bundle->prints.get_edited_preset().config :
wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
bool is_added = false; bool is_added = false;
if (wxGetApp().plater()->printer_technology() == ptFFF)
{ for (auto opt_key : config_from.diff(print_config))
if (config_to->has("fill_density") && !config_to->has("fill_pattern")) if (!config_to->has(opt_key)) {
{ config_to->set_key_value(opt_key, config_from.option(opt_key)->clone());
if (config_from.option<ConfigOptionPercent>("fill_density")->value == 100) {
config_to->set_key_value("fill_pattern", config_from.option("fill_pattern")->clone());
is_added = true; is_added = true;
} }
}
}
return is_added; return is_added;
} }

View File

@ -136,6 +136,8 @@ public:
bool is_selectable() const { return on_is_selectable(); } bool is_selectable() const { return on_is_selectable(); }
CommonGizmosDataID get_requirements() const { return on_get_requirements(); } CommonGizmosDataID get_requirements() const { return on_get_requirements(); }
virtual bool wants_enter_leave_snapshots() const { return false; } virtual bool wants_enter_leave_snapshots() const { return false; }
virtual std::string get_gizmo_entering_text() const { assert(false); return ""; }
virtual std::string get_gizmo_leaving_text() const { assert(false); return ""; }
virtual std::string get_action_snapshot_name() { return _u8L("Gizmo action"); } virtual std::string get_action_snapshot_name() { return _u8L("Gizmo action"); }
void set_common_data_pool(CommonGizmosDataPool* ptr) { m_c = ptr; } void set_common_data_pool(CommonGizmosDataPool* ptr) { m_c = ptr; }

View File

@ -133,8 +133,13 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
total_text_max += caption_max + m_imgui->scaled(1.f); total_text_max += caption_max + m_imgui->scaled(1.f);
caption_max += m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f);
float sliders_left_width = std::max(std::max(autoset_slider_left, smart_fill_slider_left), std::max(cursor_slider_left, clipping_slider_left)); const float sliders_left_width = std::max(std::max(autoset_slider_left, smart_fill_slider_left), std::max(cursor_slider_left, clipping_slider_left));
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
#else
float window_width = minimal_slider_width + sliders_left_width; float window_width = minimal_slider_width + sliders_left_width;
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_width); window_width = std::max(window_width, button_width);
window_width = std::max(window_width, split_triangles_checkbox_width); window_width = std::max(window_width, split_triangles_checkbox_width);
@ -163,18 +168,19 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
"Degree sign to use in the respective slider in FDM supports gizmo," "Degree sign to use in the respective slider in FDM supports gizmo,"
"placed after the number with no whitespace in between."); "placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_left_width); ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
float slider_height = m_imgui->get_slider_float_height(); float slider_height = m_imgui->get_slider_float_height();
// Makes slider to be aligned to bottom of the multi-line text. // Makes slider to be aligned to bottom of the multi-line text.
float slider_start_position = std::max(position_before_text_y, position_after_text_y - slider_height); float slider_start_position_y = std::max(position_before_text_y, position_after_text_y - slider_height);
ImGui::SetCursorPosY(slider_start_position); ImGui::SetCursorPosY(slider_start_position_y);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
wxString tooltip = format_wxstr(_L("Preselects faces by overhang angle. It is possible to restrict paintable facets to only preselected faces when " wxString tooltip = format_wxstr(_L("Preselects faces by overhang angle. It is possible to restrict paintable facets to only preselected faces when "
"the option \"%1%\" is enabled."), m_desc["on_overhangs_only"]); "the option \"%1%\" is enabled."), m_desc["on_overhangs_only"]);
if (m_imgui->slider_float("##angle_threshold_deg", &m_highlight_by_angle_threshold_deg, 0.f, 90.f, format_str.data(), 1.0f, true, tooltip)) { if (m_imgui->slider_float("##angle_threshold_deg", &m_highlight_by_angle_threshold_deg, 0.f, 90.f, format_str.data(), 1.0f, true, tooltip)) {
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##angle_threshold_deg", &m_highlight_by_angle_threshold_deg, 0.f, 90.f, format_str.data())) { if (m_imgui->slider_float("##angle_threshold_deg", &m_highlight_by_angle_threshold_deg, 0.f, 90.f, format_str.data())) {
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
m_parent.set_slope_normal_angle(90.f - m_highlight_by_angle_threshold_deg); m_parent.set_slope_normal_angle(90.f - m_highlight_by_angle_threshold_deg);
@ -274,10 +280,11 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_size")); m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_left_width); ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel")); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel"));
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width); m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width);
@ -295,10 +302,11 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
m_imgui->text(m_desc["smart_fill_angle"] + ":"); m_imgui->text(m_desc["smart_fill_angle"] + ":");
ImGui::SameLine(sliders_left_width); ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true, _L("Alt + Mouse wheel"))) if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true, _L("Alt + Mouse wheel")))
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data())) if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data()))
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
for (auto &triangle_selector : m_triangle_selectors) { for (auto &triangle_selector : m_triangle_selectors) {
@ -325,13 +333,14 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
} }
} }
ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
auto clp_dist = float(m_c->object_clipper()->get_position()); auto clp_dist = float(m_c->object_clipper()->get_position());
ImGui::SameLine(sliders_left_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel"))) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel")))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);

View File

@ -18,6 +18,9 @@ protected:
std::string on_get_name() const override; std::string on_get_name() const override;
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;
std::string get_gizmo_entering_text() const override { return _u8L("Entering Paint-on supports"); }
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Paint-on supports"); }
std::string get_action_snapshot_name() override { return _u8L("Paint-on supports editing"); } std::string get_action_snapshot_name() override { return _u8L("Paint-on supports editing"); }

View File

@ -311,8 +311,13 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
total_text_max += caption_max + m_imgui->scaled(1.f); total_text_max += caption_max + m_imgui->scaled(1.f);
caption_max += m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f);
float sliders_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left)); const float sliders_left_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left));
float window_width = minimal_slider_width + sliders_width; #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
#else
float window_width = minimal_slider_width + sliders_left_width;
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_width); window_width = std::max(window_width, button_width);
window_width = std::max(window_width, split_triangles_checkbox_width); window_width = std::max(window_width, split_triangles_checkbox_width);
@ -439,11 +444,12 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_size")); m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_width); ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel")); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel"));
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width); m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width);
@ -462,11 +468,12 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
m_imgui->text(m_desc["smart_fill_angle"] + ":"); m_imgui->text(m_desc["smart_fill_angle"] + ":");
std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in MMU gizmo," std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in MMU gizmo,"
"placed after the number with no whitespace in between."); "placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_width); ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true, _L("Alt + Mouse wheel"))) if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true, _L("Alt + Mouse wheel")))
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
if(m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data())) if(m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data()))
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
for (auto &triangle_selector : m_triangle_selectors) { for (auto &triangle_selector : m_triangle_selectors) {
@ -491,13 +498,14 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
} }
} }
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
auto clp_dist = float(m_c->object_clipper()->get_position()); auto clp_dist = float(m_c->object_clipper()->get_position());
ImGui::SameLine(sliders_left_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel"))) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel")))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);

View File

@ -113,6 +113,9 @@ protected:
bool on_is_activable() const override; bool on_is_activable() const override;
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;
std::string get_gizmo_entering_text() const override { return _u8L("Entering Multimaterial painting"); }
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Multimaterial painting"); }
std::string get_action_snapshot_name() override { return _u8L("Multimaterial painting editing"); } std::string get_action_snapshot_name() override { return _u8L("Multimaterial painting editing"); }
size_t m_first_selected_extruder_idx = 0; size_t m_first_selected_extruder_idx = 0;

View File

@ -104,8 +104,13 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
total_text_max += caption_max + m_imgui->scaled(1.f); total_text_max += caption_max + m_imgui->scaled(1.f);
caption_max += m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f);
float sliders_width = std::max(cursor_size_slider_left, clipping_slider_left); const float sliders_left_width = std::max(cursor_size_slider_left, clipping_slider_left);
float window_width = minimal_slider_width + sliders_width; #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
#else
float window_width = minimal_slider_width + sliders_left_width;
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_width); window_width = std::max(window_width, button_width);
window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_sphere + cursor_type_radio_circle); window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_sphere + cursor_type_radio_circle);
@ -126,11 +131,12 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_size")); m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_width); ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel")); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel"));
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width); m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width);
@ -169,13 +175,14 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
} }
} }
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
auto clp_dist = float(m_c->object_clipper()->get_position()); auto clp_dist = float(m_c->object_clipper()->get_position());
ImGui::SameLine(sliders_left_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel"))) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel")))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);
#else #else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f")) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);

View File

@ -20,6 +20,8 @@ protected:
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;
std::string get_gizmo_entering_text() const override { return _u8L("Entering Seam painting"); }
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Seam painting"); }
std::string get_action_snapshot_name() override { return _u8L("Paint-on seam editing"); } std::string get_action_snapshot_name() override { return _u8L("Paint-on seam editing"); }
private: private:

View File

@ -68,6 +68,8 @@ public:
void reslice_SLA_supports(bool postpone_error_messages = false) const; void reslice_SLA_supports(bool postpone_error_messages = false) const;
bool wants_enter_leave_snapshots() const override { return true; } bool wants_enter_leave_snapshots() const override { return true; }
std::string get_gizmo_entering_text() const override { return _u8L("Entering SLA support points"); }
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving SLA support points"); }
private: private:
bool on_init() override; bool on_init() override;

View File

@ -653,7 +653,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) { if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) {
// mouse is outside the toolbar // mouse is outside the toolbar
m_tooltip = ""; m_tooltip.clear();
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) { if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) {
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
@ -1230,16 +1230,14 @@ bool GLGizmosManager::activate_gizmo(EType type)
if (! m_parent.get_gizmos_manager().is_serializing() if (! m_parent.get_gizmos_manager().is_serializing()
&& old_gizmo->wants_enter_leave_snapshots()) && old_gizmo->wants_enter_leave_snapshots())
Plater::TakeSnapshot snapshot(wxGetApp().plater(), Plater::TakeSnapshot snapshot(wxGetApp().plater(),
Slic3r::format(_CTX_utf8("Leaving %1%", "undo/redo action name, placeholder " old_gizmo->get_gizmo_leaving_text(),
"expands to a name of a gizmo being closed"), old_gizmo->get_name(false)),
UndoRedo::SnapshotType::LeavingGizmoWithAction); UndoRedo::SnapshotType::LeavingGizmoWithAction);
} }
if (new_gizmo && ! m_parent.get_gizmos_manager().is_serializing() if (new_gizmo && ! m_parent.get_gizmos_manager().is_serializing()
&& new_gizmo->wants_enter_leave_snapshots()) && new_gizmo->wants_enter_leave_snapshots())
Plater::TakeSnapshot snapshot(wxGetApp().plater(), Plater::TakeSnapshot snapshot(wxGetApp().plater(),
Slic3r::format(_CTX_utf8("Entering %1%", "undo/redo action name, placeholder " new_gizmo->get_gizmo_entering_text(),
"expands to a name of a gizmo being opened"), new_gizmo->get_name(false)),
UndoRedo::SnapshotType::EnteringGizmo); UndoRedo::SnapshotType::EnteringGizmo);
m_current = type; m_current = type;

View File

@ -483,6 +483,11 @@ void ImGuiWrapper::tooltip(const wxString &label, float wrap_width)
} }
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImVec2 ImGuiWrapper::get_slider_icon_size() const
{
return this->calc_button_size(std::wstring(&ImGui::SliderFloatEditBtnIcon, 1));
}
bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float v_max, const char* format/* = "%.3f"*/, float power/* = 1.0f*/, bool clamp /*= true*/, const wxString& tooltip /*= ""*/, bool show_edit_btn /*= true*/) bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float v_max, const char* format/* = "%.3f"*/, float power/* = 1.0f*/, bool clamp /*= true*/, const wxString& tooltip /*= ""*/, bool show_edit_btn /*= true*/)
{ {
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;

View File

@ -96,9 +96,10 @@ public:
// Float sliders: Manually inserted values aren't clamped by ImGui.Using this wrapper function does (when clamp==true). // Float sliders: Manually inserted values aren't clamped by ImGui.Using this wrapper function does (when clamp==true).
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
bool slider_float(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = "", bool show_edit_btn = true); ImVec2 get_slider_icon_size() const;
bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = "", bool show_edit_btn = true); bool slider_float(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = "", bool show_edit_btn = true); bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
#else #else
bool slider_float(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true); bool slider_float(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true);
bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true); bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true);

View File

@ -80,10 +80,9 @@ void MeshClipper::render_cut()
void MeshClipper::recalculate_triangles() void MeshClipper::recalculate_triangles()
{ {
const Transform3f& instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>(); const Transform3f& instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>();
const Vec3f& scaling = m_trafo.get_scaling_factor().cast<float>();
// Calculate clipping plane normal in mesh coordinates. // Calculate clipping plane normal in mesh coordinates.
const Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast<float>(); const Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast<float>();
const Vec3d up (up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2)); const Vec3d up = up_noscale.cast<double>().cwiseProduct(m_trafo.get_scaling_factor());
// Calculate distance from mesh origin to the clipping plane (in mesh coordinates). // Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
const float height_mesh = m_plane.distance(m_trafo.get_offset()) * (up_noscale.norm()/up.norm()); const float height_mesh = m_plane.distance(m_trafo.get_offset()) * (up_noscale.norm()/up.norm());

View File

@ -393,6 +393,8 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
std::string line; std::string line;
for (size_t i = 0; i < (m_multiline ? m_endlines.size() : std::min(m_endlines.size(), (size_t)2)); i++) { for (size_t i = 0; i < (m_multiline ? m_endlines.size() : std::min(m_endlines.size(), (size_t)2)); i++) {
if (m_endlines[i] > m_text1.size())
break;
line.clear(); line.clear();
ImGui::SetCursorPosX(x_offset); ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y); ImGui::SetCursorPosY(starting_y + i * shift_y);
@ -788,73 +790,20 @@ void NotificationManager::ProgressBarNotification::init()
} else { } else {
m_lines_count = 2; m_lines_count = 2;
m_endlines.push_back(m_endlines.back()); m_endlines.push_back(m_endlines.back());
m_multiline = false;
} }
if(m_state == EState::Shown) if(m_state == EState::Shown)
m_state = EState::NotFading; m_state = EState::NotFading;
} }
void NotificationManager::ProgressBarNotification::count_lines()
{
std::string text = m_text1 + " " + m_hypertext;
size_t last_end = 0;
m_lines_count = 0;
m_endlines.clear();
while (last_end < text.length() - 1)
{
size_t next_hard_end = text.find_first_of('\n', last_end);
if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) {
//next line is ended by '/n'
m_endlines.push_back(next_hard_end);
last_end = next_hard_end + 1;
}
else {
// find next suitable endline
if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) {
// more than one line till end
size_t next_space = text.find_first_of(' ', last_end);
if (next_space > 0) {
size_t next_space_candidate = text.find_first_of(' ', next_space + 1);
while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset) {
next_space = next_space_candidate;
next_space_candidate = text.find_first_of(' ', next_space + 1);
}
// when one word longer than line. Or the last space is too early.
if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset ||
ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x < (m_window_width - m_window_width_offset) / 4 * 3
) {
float width_of_a = ImGui::CalcTextSize("a").x;
int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a);
while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) {
letter_count++;
}
m_endlines.push_back(last_end + letter_count);
last_end += letter_count;
}
else {
m_endlines.push_back(next_space);
last_end = next_space + 1;
}
}
}
else {
m_endlines.push_back(text.length());
last_end = text.length();
}
}
m_lines_count++;
}
}
void NotificationManager::ProgressBarNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::ProgressBarNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
// line1 - we do not print any more text than what fits on line 1. Line 2 is bar. // hypertext is not rendered at all. If it is needed, it needs to be added here.
// m_endlines should have endline for each line and then for hypertext thus m_endlines[1] should always be in m_text1
if (m_multiline) { if (m_multiline) {
// two lines text, one line bar if(m_endlines[0] > m_text1.size() || m_endlines[1] > m_text1.size())
return;
// two lines text (what doesnt fit, wont show), one line bar
ImGui::SetCursorPosX(m_left_indentation); ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height / 4); ImGui::SetCursorPosY(m_line_height / 4);
imgui.text(m_text1.substr(0, m_endlines[0]).c_str()); imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
@ -866,6 +815,8 @@ void NotificationManager::ProgressBarNotification::render_text(ImGuiWrapper& img
render_cancel_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); render_cancel_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
} else { } else {
if (m_endlines[0] > m_text1.size())
return;
//one line text, one line bar //one line text, one line bar
ImGui::SetCursorPosX(m_left_indentation); ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(/*win_size_y / 2 - win_size_y / 6 -*/ m_line_height / 4); ImGui::SetCursorPosY(/*win_size_y / 2 - win_size_y / 6 -*/ m_line_height / 4);
@ -1173,7 +1124,7 @@ void NotificationManager::SlicingProgressNotification::set_status_text(const std
break; break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS: case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
{ {
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text + ".", m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") }; NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text + "." };
update(data); update(data);
m_state = EState::NotFading; m_state = EState::NotFading;
} }

View File

@ -439,8 +439,6 @@ private:
virtual void set_percentage(float percent) { m_percentage = percent; } virtual void set_percentage(float percent) { m_percentage = percent; }
protected: protected:
virtual void init() override; virtual void init() override;
virtual void count_lines() override;
virtual void render_text(ImGuiWrapper& imgui, virtual void render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
@ -548,13 +546,6 @@ private:
void set_export_possible(bool b) { m_export_possible = b; } void set_export_possible(bool b) { m_export_possible = b; }
protected: protected:
void init() override; void init() override;
void count_lines() override
{
if (m_sp_state == SlicingProgressState::SP_PROGRESS)
ProgressBarNotification::count_lines();
else
PopNotification::count_lines();
}
void render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) override; void render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) override;
void render_bar(ImGuiWrapper& imgui, void render_bar(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,

View File

@ -528,16 +528,21 @@ void PhysicalPrinterDialog::update_host_type(bool printer_change)
std::string preset_name = prstft->get_preset_name(); std::string preset_name = prstft->get_preset_name();
if (Preset* preset = wxGetApp().preset_bundle->printers.find_preset(preset_name)) { if (Preset* preset = wxGetApp().preset_bundle->printers.find_preset(preset_name)) {
std::string model_id = preset->config.opt_string("printer_model"); std::string model_id = preset->config.opt_string("printer_model");
if (preset->vendor && preset->vendor->name == "Prusa Research") { auto model_supports_prusalink = [](const std::string &model) {
return model.size() >= 3 &&
((boost::starts_with(model, "MK") && model[2] > '2' && model[2] <= '9') ||
boost::starts_with(model, "MINI"));
};
if (preset->vendor) {
if (preset->vendor->name == "Prusa Research") {
const std::vector<VendorProfile::PrinterModel>& models = preset->vendor->models; const std::vector<VendorProfile::PrinterModel>& models = preset->vendor->models;
auto it = std::find_if(models.begin(), models.end(), auto it = std::find_if(models.begin(), models.end(),
[model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; }); [model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; });
if (it != models.end() && (it->family == "MK3" || it->family == "MINI")) if (it != models.end() && model_supports_prusalink(it->family))
continue;
} else if (!preset->vendor && (boost::starts_with(model_id, "MK3") || boost::starts_with(model_id, "MINI"))) {
continue; continue;
} }
} else if (model_supports_prusalink(model_id))
continue;
} }
all_presets_are_from_mk3_family = false; all_presets_are_from_mk3_family = false;
break; break;

View File

@ -786,8 +786,8 @@ void PlaterPresetComboBox::update()
std::map<wxString, wxBitmap*> nonsys_presets; std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected_user_preset = ""; wxString selected_user_preset;
wxString tooltip = ""; wxString tooltip;
const std::deque<Preset>& presets = m_collection->get_presets(); const std::deque<Preset>& presets = m_collection->get_presets();
if (!presets.front().is_visible) if (!presets.front().is_visible)

View File

@ -2479,14 +2479,11 @@ void TabPrinter::build_sla()
optgroup = page->new_optgroup(L("Corrections")); optgroup = page->new_optgroup(L("Corrections"));
line = Line{ m_config->def()->get("relative_correction")->full_label, "" }; line = Line{ m_config->def()->get("relative_correction")->full_label, "" };
// std::vector<std::string> axes{ "X", "Y", "Z" }; std::vector<std::string> axes{ "X", "Y", "Z" };
std::vector<std::string> axes{ "XY", "Z" };
int id = 0;
for (auto& axis : axes) { for (auto& axis : axes) {
auto opt = optgroup->get_option("relative_correction", id); auto opt = optgroup->get_option(std::string("relative_correction_") + char(std::tolower(axis[0])));
opt.opt.label = axis; opt.opt.label = axis;
line.append_option(opt); line.append_option(opt);
++id;
} }
optgroup->append_line(line); optgroup->append_line(line);
optgroup->append_single_option_line("absolute_correction"); optgroup->append_single_option_line("absolute_correction");
@ -4204,20 +4201,15 @@ void TabSLAMaterial::build()
optgroup->append_single_option_line("initial_exposure_time"); optgroup->append_single_option_line("initial_exposure_time");
optgroup = page->new_optgroup(L("Corrections")); optgroup = page->new_optgroup(L("Corrections"));
std::vector<std::string> corrections = {"material_correction"}; auto line = Line{ m_config->def()->get("material_correction")->full_label, "" };
// std::vector<std::string> axes{ "X", "Y", "Z" }; std::vector<std::string> axes{ "X", "Y", "Z" };
std::vector<std::string> axes{ "XY", "Z" };
for (auto& opt_key : corrections) {
auto line = Line{ m_config->def()->get(opt_key)->full_label, "" };
int id = 0;
for (auto& axis : axes) { for (auto& axis : axes) {
auto opt = optgroup->get_option(opt_key, id); auto opt = optgroup->get_option(std::string("material_correction_") + char(std::tolower(axis[0])));
opt.opt.label = axis; opt.opt.label = axis;
line.append_option(opt); line.append_option(opt);
++id;
} }
optgroup->append_line(line); optgroup->append_line(line);
}
page = add_options_page(L("Notes"), "note.png"); page = add_options_page(L("Notes"), "note.png");
optgroup = page->new_optgroup(L("Notes"), 0); optgroup = page->new_optgroup(L("Notes"), 0);