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
0.0.4 Fixed first layer height in 0.28mm profile.
0.0.3 Fixed Genius bed size.
0.0.2 Updated start g-code.
0.0.1 Initial Artillery bundle

View File

@ -11,7 +11,7 @@
name = Artillery
# 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.
config_version = 0.0.3
config_version = 0.0.4
# Where to get the updates from?
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%
@ -300,6 +300,7 @@ top_solid_layers = 4
[print:*0.28mm*]
inherits = *common*
layer_height = 0.28
first_layer_height = 0.36
top_infill_extrusion_width = 0.45
first_layer_extrusion_width = 0.75
bottom_solid_layers = 3

View File

@ -1,3 +1,4 @@
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.1 Initial version

View File

@ -3,7 +3,7 @@
[vendor]
# Vendor name will be shown by the Config Wizard.
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/
###
@ -15,12 +15,14 @@ name = INAT Proton X Rail
variants = 0.4
technology = FFF
family = Proton
default_materials = PLA @PROTON_X
[printer_model:PROTON_X_ROD]
name = INAT Proton X Rod
variants = 0.4
technology = FFF
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.
inside = num_inside > 0;
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);
if (m_max_print_height == 0)
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

View File

@ -68,7 +68,10 @@ public:
// Colliding with the build volume boundary, thus not printable and error is shown.
Colliding,
// 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.

View File

@ -19,6 +19,7 @@
#include "libslic3r/SLA/RasterBase.hpp"
#include "libslic3r/miniz_extension.hpp"
#include "libslic3r/PNGReadWrite.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp>
@ -321,11 +322,13 @@ ConfigSubstitutions import_sla_archive(
lh_opt != arch.config.not_found())
{
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("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);
}
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};
*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 == '-')
*(++this->ptr_err.ptr) = '0';
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

View File

@ -12,11 +12,6 @@
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/Exact_integer.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>
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::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z);
handle_legacy_sla(*config);
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();
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */);
if (state == BuildVolume::ObjectState::Inside)
// Volume is completely inside.
inside_outside |= INSIDE;
else if (state == BuildVolume::ObjectState::Outside)
// Volume is completely 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;
}
model_instance->print_volume_state =
(inside_outside == (INSIDE | OUTSIDE)) ? ModelInstancePVS_Partly_Outside :
(inside_outside == INSIDE) ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside :
inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
if (inside_outside == INSIDE)
++num_printable;
}

View File

@ -1723,10 +1723,21 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
}); // end of parallel_for
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) {
throw_on_cancel_callback();
BoundingBox bbox(get_extents(layers[layer_idx]->regions()));
bbox.merge(get_extents(input_expolygons[layer_idx]));
layer_bboxes[layer_idx] = get_extents(layers[layer_idx]->regions());
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.
bbox.offset(20 * SCALED_EPSILON);
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->percent = false;
}
handle_legacy_sla(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",
"initial_exposure_time",
"material_correction",
"material_correction_x",
"material_correction_y",
"material_correction_z",
"material_notes",
"material_vendor",
"default_sla_material_profile",
@ -559,6 +564,9 @@ static std::vector<std::string> s_Preset_sla_printer_options {
"display_orientation",
"fast_tilt_time", "slow_tilt_time", "area_fill",
"relative_correction",
"relative_correction_x",
"relative_correction_y",
"relative_correction_z",
"absolute_correction",
"elefant_foot_compensation",
"elefant_foot_min_width",

View File

@ -3146,7 +3146,31 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L("Printer scaling correction");
def->min = 0;
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->label = L("Printer absolute correction");
@ -3292,7 +3316,28 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L("Correction for expansion");
def->min = 0;
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->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";
} else if (opt_key == "preset_name") {
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:
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)
{
const auto &defaults = FullPrintConfig::defaults();

View File

@ -224,6 +224,8 @@ public:
{ PrintConfigDef::handle_legacy(opt_key, value); }
};
void handle_legacy_sla(DynamicPrintConfig &config);
class StaticPrintConfig : public StaticConfig
{
public:
@ -924,6 +926,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, exposure_time))
((ConfigOptionFloat, initial_exposure_time))
((ConfigOptionFloats, material_correction))
((ConfigOptionFloat, material_correction_x))
((ConfigOptionFloat, material_correction_y))
((ConfigOptionFloat, material_correction_z))
)
PRINT_CONFIG_CLASS_DEFINE(
@ -940,6 +945,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, display_mirror_x))
((ConfigOptionBool, display_mirror_y))
((ConfigOptionFloats, relative_correction))
((ConfigOptionFloat, relative_correction_x))
((ConfigOptionFloat, relative_correction_y))
((ConfigOptionFloat, relative_correction_z))
((ConfigOptionFloat, absolute_correction))
((ConfigOptionFloat, elefant_foot_compensation))
((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 = {
"initial_layer_height",
"material_correction",
"material_correction_x",
"material_correction_y",
"material_correction_z",
"relative_correction",
"relative_correction_x",
"relative_correction_y",
"relative_correction_z",
"absolute_correction",
"elefant_foot_compensation",
"elefant_foot_min_width",
@ -1047,15 +1053,15 @@ Vec3d SLAPrint::relative_correction() const
Vec3d corr(1., 1., 1.);
if(printer_config().relative_correction.values.size() >= 2) {
corr.x() = printer_config().relative_correction.values[0];
corr.y() = corr.x();
corr.z() = printer_config().relative_correction.values[1];
corr.x() = printer_config().relative_correction_x.value;
corr.y() = printer_config().relative_correction_y.value;
corr.z() = printer_config().relative_correction_z.value;
}
if(material_config().material_correction.values.size() >= 2) {
corr.x() *= material_config().material_correction.values[0];
corr.y() = corr.x();
corr.z() *= material_config().material_correction.values[1];
corr.x() *= material_config().material_correction_x.value;
corr.y() *= material_config().material_correction_y.value;
corr.z() *= material_config().material_correction_z.value;
}
return corr;

View File

@ -189,6 +189,7 @@ set(SLIC3R_GUI_SOURCES
GUI/Mouse3DController.hpp
GUI/DoubleSlider.cpp
GUI/DoubleSlider.hpp
GUI/DoubleSlider_Utils.hpp
GUI/Notebook.cpp
GUI/Notebook.hpp
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
{
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.
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.
auto volume_bbox = [volume_sinking](GLVolume& volume) -> BoundingBoxf3
{ return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box() : volume.transformed_convex_hull_bounding_box(); };
@ -948,21 +950,26 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
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))) {
BuildVolume::ObjectState state;
switch (build_volume.type()) {
case BuildVolume::Type::Rectangle:
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
state = build_volume.volume_state_bbox(volume_bbox(*volume));
break;
case BuildVolume::Type::Circle:
case BuildVolume::Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case BuildVolume::Type::Custom:
state = build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
break;
default:
// Ignore, don't produce any collision.
state = BuildVolume::ObjectState::Inside;
break;
if (volume_below(*volume))
state = BuildVolume::ObjectState::Below;
else {
switch (build_volume.type()) {
case BuildVolume::Type::Rectangle:
//FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects.
state = build_volume.volume_state_bbox(volume_bbox(*volume));
break;
case BuildVolume::Type::Circle:
case BuildVolume::Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case BuildVolume::Type::Custom:
state = build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast<float>(), volume_sinking(*volume));
break;
default:
// Ignore, don't produce any collision.
state = BuildVolume::ObjectState::Inside;
break;
}
assert(state != BuildVolume::ObjectState::Below);
}
volume->is_outside = state != BuildVolume::ObjectState::Inside;
if (volume->printable) {

View File

@ -1,5 +1,6 @@
#include "libslic3r/libslic3r.h"
#include "DoubleSlider.hpp"
#include "DoubleSlider_Utils.hpp"
#include "libslic3r/GCode.hpp"
#include "GUI.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)
{
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();
if (ticks.empty())
return colors[0];
m_default_color_idx++;
return colors[m_default_color_idx % colors.size()];
#endif
}
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;
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
std::string new_additional_tooltip = "";
std::string new_additional_tooltip;
if (can_undo) {
std::string action;
wxGetApp().plater()->undo_redo_topmost_string_getter(true, action);
@ -4759,7 +4759,7 @@ bool GLCanvas3D::_init_undoredo_toolbar()
std::string 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) {
std::string 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()
{
// win32 build on win64 and viceversa
#ifdef _WIN64
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 defined(_WIN32) && ! defined(_WIN64)
// Win32 32bit build.
if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "64") {
RichMessageDialog dlg(nullptr,
_L("You have started PrusaSlicer for 32-bit architecture on 64-bit system."
"\nPlease download and install correct version at https://www.prusa3d.cz/prusaslicer/."
_L("You are running a 32 bit build of PrusaSlicer on 64-bit Windows."
"\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?"),
"PrusaSlicer", wxICON_QUESTION | wxYES_NO);
if (dlg.ShowModal() != wxID_YES)

View File

@ -911,21 +911,14 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
toggle_printable_state();
else if (title == _("Editing"))
show_context_menu(evt_context_menu);
else if (title == _("Name"))
{
if (wxOSX)
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())
fix_through_netfabb();
}
}
else if (title == _("Name"))
{
if (is_windows10() && m_objects_model->HasWarningIcon(item) &&
mouse_pos.x > 2 * wxGetApp().em_unit() && mouse_pos.x < 4 * wxGetApp().em_unit())
fix_through_netfabb();
else
show_context_menu(evt_context_menu); // show context menu for "Name" column too
}
// workaround for extruder editing under OSX
else if (wxOSX && evt_context_menu && title == _("Extruder"))
extruder_editing();

View File

@ -181,17 +181,16 @@ bool ObjectSettings::update_settings_list()
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;
if (wxGetApp().plater()->printer_technology() == ptFFF)
{
if (config_to->has("fill_density") && !config_to->has("fill_pattern"))
{
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;
}
for (auto opt_key : config_from.diff(print_config))
if (!config_to->has(opt_key)) {
config_to->set_key_value(opt_key, config_from.option(opt_key)->clone());
is_added = true;
}
}
return is_added;
}

View File

@ -136,6 +136,8 @@ public:
bool is_selectable() const { return on_is_selectable(); }
CommonGizmosDataID get_requirements() const { return on_get_requirements(); }
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"); }
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);
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));
float window_width = minimal_slider_width + sliders_left_width;
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;
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_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,"
"placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
float slider_height = m_imgui->get_slider_float_height();
// 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);
ImGui::SetCursorPosY(slider_start_position);
float slider_start_position_y = std::max(position_before_text_y, position_after_text_y - slider_height);
ImGui::SetCursorPosY(slider_start_position_y);
#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 "
"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)) {
#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())) {
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
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();
m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
#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"));
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered())
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"] + ":");
ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width);
#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")))
#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()))
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
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());
ImGui::SameLine(sliders_left_width);
#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")))
m_c->object_clipper()->set_position(clp_dist, true);
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true);

View File

@ -18,6 +18,9 @@ protected:
std::string on_get_name() 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"); }

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);
caption_max += m_imgui->scaled(1.f);
float sliders_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left));
float window_width = minimal_slider_width + sliders_width;
const float sliders_left_width = std::max(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;
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_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();
m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
ImGui::SameLine(sliders_left_width);
#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"));
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered())
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"] + ":");
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.");
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
ImGui::SameLine(sliders_left_width);
#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")))
#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()))
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
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());
ImGui::SameLine(sliders_left_width);
#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")))
m_c->object_clipper()->set_position(clp_dist, true);
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true);

View File

@ -113,6 +113,9 @@ protected:
bool on_is_activable() 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"); }
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);
caption_max += m_imgui->scaled(1.f);
float sliders_width = std::max(cursor_size_slider_left, clipping_slider_left);
float window_width = minimal_slider_width + sliders_width;
const float sliders_left_width = std::max(cursor_size_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;
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
window_width = std::max(window_width, total_text_max);
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);
@ -126,11 +131,12 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
ImGui::SameLine(sliders_left_width);
#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"));
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered())
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());
ImGui::SameLine(sliders_left_width);
#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")))
m_c->object_clipper()->set_position(clp_dist, true);
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
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;
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"); }
private:

View File

@ -68,6 +68,8 @@ public:
void reslice_SLA_supports(bool postpone_error_messages = false) const;
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:
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) {
// mouse is outside the toolbar
m_tooltip = "";
m_tooltip.clear();
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) {
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()
&& old_gizmo->wants_enter_leave_snapshots())
Plater::TakeSnapshot snapshot(wxGetApp().plater(),
Slic3r::format(_CTX_utf8("Leaving %1%", "undo/redo action name, placeholder "
"expands to a name of a gizmo being closed"), old_gizmo->get_name(false)),
old_gizmo->get_gizmo_leaving_text(),
UndoRedo::SnapshotType::LeavingGizmoWithAction);
}
if (new_gizmo && ! m_parent.get_gizmos_manager().is_serializing()
&& new_gizmo->wants_enter_leave_snapshots())
Plater::TakeSnapshot snapshot(wxGetApp().plater(),
Slic3r::format(_CTX_utf8("Entering %1%", "undo/redo action name, placeholder "
"expands to a name of a gizmo being opened"), new_gizmo->get_name(false)),
new_gizmo->get_gizmo_entering_text(),
UndoRedo::SnapshotType::EnteringGizmo);
m_current = type;

View File

@ -483,6 +483,11 @@ void ImGuiWrapper::tooltip(const wxString &label, float wrap_width)
}
#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*/)
{
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).
#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);
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);
ImVec2 get_slider_icon_size() const;
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 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
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);

View File

@ -80,10 +80,9 @@ void MeshClipper::render_cut()
void MeshClipper::recalculate_triangles()
{
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.
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).
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;
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();
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y);
@ -788,73 +790,20 @@ void NotificationManager::ProgressBarNotification::init()
} else {
m_lines_count = 2;
m_endlines.push_back(m_endlines.back());
m_multiline = false;
}
if(m_state == EState::Shown)
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)
{
// 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) {
// 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::SetCursorPosY(m_line_height / 4);
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_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
} else {
if (m_endlines[0] > m_text1.size())
return;
//one line text, one line bar
ImGui::SetCursorPosX(m_left_indentation);
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;
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);
m_state = EState::NotFading;
}

View File

@ -438,9 +438,7 @@ private:
ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) { }
virtual void set_percentage(float percent) { m_percentage = percent; }
protected:
virtual void init() override;
virtual void count_lines() override;
virtual void init() override;
virtual 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;
@ -548,13 +546,6 @@ private:
void set_export_possible(bool b) { m_export_possible = b; }
protected:
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_bar(ImGuiWrapper& imgui,
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();
if (Preset* preset = wxGetApp().preset_bundle->printers.find_preset(preset_name)) {
std::string model_id = preset->config.opt_string("printer_model");
if (preset->vendor && preset->vendor->name == "Prusa Research") {
const std::vector<VendorProfile::PrinterModel>& models = preset->vendor->models;
auto it = std::find_if(models.begin(), models.end(),
[model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; });
if (it != models.end() && (it->family == "MK3" || it->family == "MINI"))
continue;
} else if (!preset->vendor && (boost::starts_with(model_id, "MK3") || boost::starts_with(model_id, "MINI"))) {
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;
auto it = std::find_if(models.begin(), models.end(),
[model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; });
if (it != models.end() && model_supports_prusalink(it->family))
continue;
}
} else if (model_supports_prusalink(model_id))
continue;
}
}
all_presets_are_from_mk3_family = false;
break;

View File

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

View File

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