Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Matena <lukasmatena@seznam.cz>2020-01-21 15:00:07 +0300
committerLukas Matena <lukasmatena@seznam.cz>2020-01-21 15:00:07 +0300
commit63b0eec5a94c55ab5040cbd4ee235a95a6858e14 (patch)
treea6e27921c783441eea3d30a05cf2312da82233a6 /src/slic3r/GUI
parent87f2578ee71c9baa13dcfc09c1afb4d751cb2ed3 (diff)
parent05ea01bdcccb3d8bc5d46b71c20a30e25352cea8 (diff)
Merge branch 'master' into lm_tm_hollowing
Diffstat (limited to 'src/slic3r/GUI')
-rw-r--r--src/slic3r/GUI/3DBed.cpp155
-rw-r--r--src/slic3r/GUI/3DBed.hpp27
-rw-r--r--src/slic3r/GUI/3DScene.cpp9
-rw-r--r--src/slic3r/GUI/AppConfig.cpp10
-rw-r--r--src/slic3r/GUI/BackgroundSlicingProcess.cpp8
-rw-r--r--src/slic3r/GUI/BackgroundSlicingProcess.hpp13
-rw-r--r--src/slic3r/GUI/BitmapCache.cpp44
-rw-r--r--src/slic3r/GUI/BitmapCache.hpp2
-rw-r--r--src/slic3r/GUI/Camera.cpp167
-rw-r--r--src/slic3r/GUI/Camera.hpp44
-rw-r--r--src/slic3r/GUI/ConfigWizard.cpp134
-rw-r--r--src/slic3r/GUI/ConfigWizard_private.hpp29
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp244
-rw-r--r--src/slic3r/GUI/GLCanvas3D.hpp36
-rw-r--r--src/slic3r/GUI/GLSelectionRectangle.cpp3
-rw-r--r--src/slic3r/GUI/GLTexture.cpp51
-rw-r--r--src/slic3r/GUI/GLToolbar.cpp51
-rw-r--r--src/slic3r/GUI/GLToolbar.hpp4
-rw-r--r--src/slic3r/GUI/GUI_Preview.cpp72
-rw-r--r--src/slic3r/GUI/GUI_Preview.hpp3
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoMove.cpp2
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoMove.hpp2
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp2
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp2
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoScale.cpp4
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmosManager.cpp44
-rw-r--r--src/slic3r/GUI/MainFrame.cpp4
-rw-r--r--src/slic3r/GUI/MainFrame.hpp2
-rw-r--r--src/slic3r/GUI/Mouse3DController.cpp69
-rw-r--r--src/slic3r/GUI/Mouse3DController.hpp12
-rw-r--r--src/slic3r/GUI/Plater.cpp113
-rw-r--r--src/slic3r/GUI/Plater.hpp2
-rw-r--r--src/slic3r/GUI/Preferences.cpp97
-rw-r--r--src/slic3r/GUI/Preferences.hpp6
-rw-r--r--src/slic3r/GUI/Preset.cpp28
-rw-r--r--src/slic3r/GUI/Preset.hpp16
-rw-r--r--src/slic3r/GUI/PresetBundle.cpp4
-rw-r--r--src/slic3r/GUI/PresetBundle.hpp4
-rw-r--r--src/slic3r/GUI/Selection.cpp4
-rw-r--r--src/slic3r/GUI/Tab.cpp20
-rw-r--r--src/slic3r/GUI/Tab.hpp2
-rw-r--r--src/slic3r/GUI/wxExtensions.cpp862
-rw-r--r--src/slic3r/GUI/wxExtensions.hpp154
43 files changed, 1593 insertions, 968 deletions
diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index f6f80d822..00b7f2382 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -189,8 +189,6 @@ void Bed3D::Axes::render_axis(double length) const
Bed3D::Bed3D()
: m_type(Custom)
- , m_custom_texture("")
- , m_custom_model("")
, m_vbo_id(0)
, m_scale_factor(1.0f)
{
@@ -198,31 +196,31 @@ Bed3D::Bed3D()
bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, const std::string& custom_model)
{
- EType new_type = detect_type(shape);
+ auto check_texture = [](const std::string& texture) {
+ return !texture.empty() && (boost::algorithm::iends_with(texture, ".png") || boost::algorithm::iends_with(texture, ".svg")) && boost::filesystem::exists(texture);
+ };
- // check that the passed custom texture filename is valid
- std::string cst_texture(custom_texture);
- if (!cst_texture.empty())
- {
- if ((!boost::algorithm::iends_with(custom_texture, ".png") && !boost::algorithm::iends_with(custom_texture, ".svg")) || !boost::filesystem::exists(custom_texture))
- cst_texture = "";
- }
+ auto check_model = [](const std::string& model) {
+ return !model.empty() && boost::algorithm::iends_with(model, ".stl") && boost::filesystem::exists(model);
+ };
- // check that the passed custom texture filename is valid
- std::string cst_model(custom_model);
- if (!cst_model.empty())
- {
- if (!boost::algorithm::iends_with(custom_model, ".stl") || !boost::filesystem::exists(custom_model))
- cst_model = "";
- }
+ auto [new_type, system_model, system_texture] = detect_type(shape);
+
+ std::string texture_filename = custom_texture.empty() ? system_texture : custom_texture;
+ if (!check_texture(texture_filename))
+ texture_filename.clear();
+
+ std::string model_filename = custom_model.empty() ? system_model : custom_model;
+ if (!check_model(model_filename))
+ model_filename.clear();
- if ((m_shape == shape) && (m_type == new_type) && (m_custom_texture == cst_texture) && (m_custom_model == cst_model))
+ if ((m_shape == shape) && (m_type == new_type) && (m_texture_filename == texture_filename) && (m_model_filename == model_filename))
// No change, no need to update the UI.
return false;
m_shape = shape;
- m_custom_texture = cst_texture;
- m_custom_model = cst_model;
+ m_texture_filename = texture_filename;
+ m_model_filename = model_filename;
m_type = new_type;
calc_bounding_boxes();
@@ -244,7 +242,7 @@ bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, c
m_texture.reset();
m_model.reset();
- // Set the origin and size for painting of the coordinate system axes.
+ // Set the origin and size for rendering the coordinate system axes.
m_axes.origin = Vec3d(0.0, 0.0, (double)GROUND_Z);
m_axes.length = 0.1 * m_bounding_box.max_size() * Vec3d::Ones();
@@ -262,7 +260,11 @@ Point Bed3D::point_projection(const Point& point) const
return m_polygon.point_projection(point);
}
+#if ENABLE_6DOF_CAMERA
+void Bed3D::render(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes) const
+#else
void Bed3D::render(GLCanvas3D& canvas, float theta, float scale_factor, bool show_axes) const
+#endif // ENABLE_6DOF_CAMERA
{
m_scale_factor = scale_factor;
@@ -273,13 +275,15 @@ void Bed3D::render(GLCanvas3D& canvas, float theta, float scale_factor, bool sho
switch (m_type)
{
- case MK2: { render_prusa(canvas, "mk2", theta > 90.0f); break; }
- case MK3: { render_prusa(canvas, "mk3", theta > 90.0f); break; }
- case SL1: { render_prusa(canvas, "sl1", theta > 90.0f); break; }
- case MINI: { render_prusa(canvas, "mini", theta > 90.0f); break; }
- case ENDER3: { render_prusa(canvas, "ender3", theta > 90.0f); break; }
+#if ENABLE_6DOF_CAMERA
+ case System: { render_system(canvas, bottom); break; }
+ default:
+ case Custom: { render_custom(canvas, bottom); break; }
+#else
+ case System: { render_system(canvas, theta > 90.0f); break; }
default:
case Custom: { render_custom(canvas, theta > 90.0f); break; }
+#endif // ENABLE_6DOF_CAMERA
}
glsafe(::glDisable(GL_DEPTH_TEST));
@@ -341,10 +345,26 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
printf("Unable to create bed grid lines\n");
}
-Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const
+static std::string system_print_bed_model(const Preset &preset)
+{
+ std::string out;
+ const VendorProfile::PrinterModel *pm = PresetUtils::system_printer_model(preset);
+ if (pm != nullptr && ! pm->bed_model.empty())
+ out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->bed_model;
+ return out;
+}
+
+static std::string system_print_bed_texture(const Preset &preset)
{
- EType type = Custom;
+ std::string out;
+ const VendorProfile::PrinterModel *pm = PresetUtils::system_printer_model(preset);
+ if (pm != nullptr && ! pm->bed_texture.empty())
+ out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->bed_texture;
+ return out;
+}
+std::tuple<Bed3D::EType, std::string, std::string> Bed3D::detect_type(const Pointfs& shape) const
+{
auto bundle = wxGetApp().preset_bundle;
if (bundle != nullptr)
{
@@ -353,39 +373,12 @@ Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const
{
if (curr->config.has("bed_shape"))
{
- if (curr->vendor != nullptr)
+ if (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values)
{
- if ((curr->vendor->name == "Prusa Research") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
- {
- if (boost::contains(curr->name, "SL1"))
- {
- type = SL1;
- break;
- }
- else if (boost::contains(curr->name, "MK3") || boost::contains(curr->name, "MK2.5"))
- {
- type = MK3;
- break;
- }
- else if (boost::contains(curr->name, "MK2"))
- {
- type = MK2;
- break;
- }
- else if (boost::contains(curr->name, "MINI"))
- {
- type = MINI;
- break;
- }
- }
- else if ((curr->vendor->name == "Creality") && (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
- {
- if (boost::contains(curr->name, "ENDER-3"))
- {
- type = ENDER3;
- break;
- }
- }
+ std::string model_filename = system_print_bed_model(*curr);
+ std::string texture_filename = system_print_bed_texture(*curr);
+ if (!model_filename.empty() && !texture_filename.empty())
+ return std::make_tuple(System, model_filename, texture_filename);
}
}
@@ -393,7 +386,7 @@ Bed3D::EType Bed3D::detect_type(const Pointfs& shape) const
}
}
- return type;
+ return std::make_tuple(Custom, "", "");
}
void Bed3D::render_axes() const
@@ -402,35 +395,35 @@ void Bed3D::render_axes() const
m_axes.render();
}
-void Bed3D::render_prusa(GLCanvas3D& canvas, const std::string& key, bool bottom) const
+void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const
{
if (!bottom)
- render_model(m_custom_model.empty() ? resources_dir() + "/models/" + key + "_bed.stl" : m_custom_model);
+ render_model();
- render_texture(m_custom_texture.empty() ? resources_dir() + "/icons/bed/" + key + ".svg" : m_custom_texture, bottom, canvas);
+ render_texture(bottom, canvas);
}
-void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D& canvas) const
+void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) const
{
- if (filename.empty())
+ if (m_texture_filename.empty())
{
m_texture.reset();
render_default(bottom);
return;
}
- if ((m_texture.get_id() == 0) || (m_texture.get_source() != filename))
+ if ((m_texture.get_id() == 0) || (m_texture.get_source() != m_texture_filename))
{
m_texture.reset();
- if (boost::algorithm::iends_with(filename, ".svg"))
+ if (boost::algorithm::iends_with(m_texture_filename, ".svg"))
{
// use higher resolution images if graphic card and opengl version allow
GLint max_tex_size = GLCanvas3DManager::get_gl_info().get_max_tex_size();
- if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != filename))
+ if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != m_texture_filename))
{
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
- if (!m_temp_texture.load_from_svg_file(filename, false, false, false, max_tex_size / 8))
+ if (!m_temp_texture.load_from_svg_file(m_texture_filename, false, false, false, max_tex_size / 8))
{
render_default(bottom);
return;
@@ -439,18 +432,18 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D&
}
// starts generating the main texture, compression will run asynchronously
- if (!m_texture.load_from_svg_file(filename, true, true, true, max_tex_size))
+ if (!m_texture.load_from_svg_file(m_texture_filename, true, true, true, max_tex_size))
{
render_default(bottom);
return;
}
}
- else if (boost::algorithm::iends_with(filename, ".png"))
+ else if (boost::algorithm::iends_with(m_texture_filename, ".png"))
{
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
- if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != filename))
+ if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != m_texture_filename))
{
- if (!m_temp_texture.load_from_file(filename, false, GLTexture::None, false))
+ if (!m_temp_texture.load_from_file(m_texture_filename, false, GLTexture::None, false))
{
render_default(bottom);
return;
@@ -459,7 +452,7 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D&
}
// starts generating the main texture, compression will run asynchronously
- if (!m_texture.load_from_file(filename, true, GLTexture::MultiThreaded, true))
+ if (!m_texture.load_from_file(m_texture_filename, true, GLTexture::MultiThreaded, true))
{
render_default(bottom);
return;
@@ -558,12 +551,12 @@ void Bed3D::render_texture(const std::string& filename, bool bottom, GLCanvas3D&
}
}
-void Bed3D::render_model(const std::string& filename) const
+void Bed3D::render_model() const
{
- if (filename.empty())
+ if (m_model_filename.empty())
return;
- if ((m_model.get_filename() != filename) && m_model.init_from_file(filename))
+ if ((m_model.get_filename() != m_model_filename) && m_model.init_from_file(m_model_filename))
{
// move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad
Vec3d shift = m_bounding_box.center();
@@ -584,16 +577,16 @@ void Bed3D::render_model(const std::string& filename) const
void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) const
{
- if (m_custom_texture.empty() && m_custom_model.empty())
+ if (m_texture_filename.empty() && m_model_filename.empty())
{
render_default(bottom);
return;
}
if (!bottom)
- render_model(m_custom_model);
+ render_model();
- render_texture(m_custom_texture, bottom, canvas);
+ render_texture(bottom, canvas);
}
void Bed3D::render_default(bool bottom) const
diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp
index cd2de862e..b1835a919 100644
--- a/src/slic3r/GUI/3DBed.hpp
+++ b/src/slic3r/GUI/3DBed.hpp
@@ -5,6 +5,8 @@
#include "3DScene.hpp"
#include "GLShader.hpp"
+#include <tuple>
+
class GLUquadric;
typedef class GLUquadric GLUquadricObj;
@@ -64,11 +66,7 @@ class Bed3D
public:
enum EType : unsigned char
{
- MK2,
- MK3,
- SL1,
- MINI,
- ENDER3,
+ System,
Custom,
Num_Types
};
@@ -76,19 +74,19 @@ public:
private:
EType m_type;
Pointfs m_shape;
- std::string m_custom_texture;
- std::string m_custom_model;
+ std::string m_texture_filename;
+ std::string m_model_filename;
mutable BoundingBoxf3 m_bounding_box;
mutable BoundingBoxf3 m_extended_bounding_box;
Polygon m_polygon;
GeometryBuffer m_triangles;
GeometryBuffer m_gridlines;
mutable GLTexture m_texture;
+ mutable GLBed m_model;
// temporary texture shown until the main texture has still no levels compressed
mutable GLTexture m_temp_texture;
mutable Shader m_shader;
mutable unsigned int m_vbo_id;
- mutable GLBed m_model;
Axes m_axes;
mutable float m_scale_factor;
@@ -99,7 +97,6 @@ public:
EType get_type() const { return m_type; }
- bool is_prusa() const { return (m_type == MK2) || (m_type == MK3) || (m_type == SL1); }
bool is_custom() const { return m_type == Custom; }
const Pointfs& get_shape() const { return m_shape; }
@@ -110,17 +107,21 @@ public:
bool contains(const Point& point) const;
Point point_projection(const Point& point) const;
+#if ENABLE_6DOF_CAMERA
+ void render(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes) const;
+#else
void render(GLCanvas3D& canvas, float theta, float scale_factor, bool show_axes) const;
+#endif // ENABLE_6DOF_CAMERA
private:
void calc_bounding_boxes() const;
void calc_triangles(const ExPolygon& poly);
void calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox);
- EType detect_type(const Pointfs& shape) const;
+ std::tuple<EType, std::string, std::string> detect_type(const Pointfs& shape) const;
void render_axes() const;
- void render_prusa(GLCanvas3D& canvas, const std::string& key, bool bottom) const;
- void render_texture(const std::string& filename, bool bottom, GLCanvas3D& canvas) const;
- void render_model(const std::string& filename) const;
+ void render_system(GLCanvas3D& canvas, bool bottom) const;
+ void render_texture(bool bottom, GLCanvas3D& canvas) const;
+ void render_model() const;
void render_custom(GLCanvas3D& canvas, bool bottom) const;
void render_default(bool bottom) const;
void reset();
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index bbfcabd36..f6b1719db 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -877,13 +877,10 @@ bool can_export_to_obj(const GLVolume& volume)
if (!volume.is_active || !volume.is_extrusion_path)
return false;
- if (volume.indexed_vertex_array.triangle_indices.empty() && (std::min(volume.indexed_vertex_array.triangle_indices_size, volume.tverts_range.second - volume.tverts_range.first) == 0))
- return false;
-
- if (volume.indexed_vertex_array.quad_indices.empty() && (std::min(volume.indexed_vertex_array.quad_indices_size, volume.qverts_range.second - volume.qverts_range.first) == 0))
- return false;
+ bool has_triangles = !volume.indexed_vertex_array.triangle_indices.empty() || (std::min(volume.indexed_vertex_array.triangle_indices_size, volume.tverts_range.second - volume.tverts_range.first) > 0);
+ bool has_quads = !volume.indexed_vertex_array.quad_indices.empty() || (std::min(volume.indexed_vertex_array.quad_indices_size, volume.qverts_range.second - volume.qverts_range.first) > 0);
- return true;
+ return has_triangles || has_quads;
}
bool GLVolumeCollection::has_toolpaths_to_export() const
diff --git a/src/slic3r/GUI/AppConfig.cpp b/src/slic3r/GUI/AppConfig.cpp
index eb0a7fca6..12302a5dc 100644
--- a/src/slic3r/GUI/AppConfig.cpp
+++ b/src/slic3r/GUI/AppConfig.cpp
@@ -61,6 +61,11 @@ void AppConfig::set_defaults()
if (get("preset_update").empty())
set("preset_update", "1");
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ if (get("export_sources_full_pathnames").empty())
+ set("export_sources_full_pathnames", "0");
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+
// remove old 'use_legacy_opengl' parameter from this config, if present
if (!get("use_legacy_opengl").empty())
erase("", "use_legacy_opengl");
@@ -82,6 +87,11 @@ void AppConfig::set_defaults()
if (get("use_perspective_camera").empty())
set("use_perspective_camera", "1");
+#if ENABLE_6DOF_CAMERA
+ if (get("use_free_camera").empty())
+ set("use_free_camera", "0");
+#endif // ENABLE_6DOF_CAMERA
+
// Remove legacy window positions/sizes
erase("", "main_frame_maximized");
erase("", "main_frame_pos");
diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp
index 9d6a2a5ec..8af721f9d 100644
--- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp
+++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp
@@ -95,14 +95,6 @@ void BackgroundSlicingProcess::process_fff()
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data);
#endif // ENABLE_THUMBNAIL_GENERATOR
- /* #ys_FIXME_no_exported_codes
- if (m_fff_print->model().custom_gcode_per_print_z != GUI::wxGetApp().model().custom_gcode_per_print_z) {
- GUI::wxGetApp().model().custom_gcode_per_print_z = m_fff_print->model().custom_gcode_per_print_z;
- GUI::show_info(nullptr, _(L("To except of redundant tool manipulation, \n"
- "Color change(s) for unused extruder(s) was(were) deleted")), _(L("Info")));
- }
- */
-
if (this->set_step_started(bspsGCodeFinalize)) {
if (! m_export_path.empty()) {
//FIXME localize the messages
diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp
index a66dcf39c..c8ece38f0 100644
--- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp
+++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp
@@ -53,11 +53,11 @@ public:
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
#endif // ENABLE_THUMBNAIL_GENERATOR
- // The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished
+ // The following wxCommandEvent will be sent to the UI thread / Plater window, when the slicing is finished
// and the background processing will transition into G-code export.
// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
void set_slicing_completed_event(int event_id) { m_event_slicing_completed_id = event_id; }
- // The following wxCommandEvent will be sent to the UI thread / Platter window, when the G-code export is finished.
+ // The following wxCommandEvent will be sent to the UI thread / Plater window, when the G-code export is finished.
// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
void set_finished_event(int event_id) { m_event_finished_id = event_id; }
@@ -132,11 +132,6 @@ public:
// This "finished" flag does not account for the final export of the output file (.gcode or zipped PNGs),
// and it does not account for the OctoPrint scheduling.
bool finished() const { return m_print->finished(); }
-
- void set_force_update_print_regions(bool force_update_print_regions) {
- if (m_fff_print)
- m_fff_print->set_force_update_print_regions(force_update_print_regions);
- }
private:
void thread_proc();
@@ -191,9 +186,9 @@ private:
void throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); }
void prepare_upload();
- // wxWidgets command ID to be sent to the platter to inform that the slicing is finished, and the G-code export will continue.
+ // wxWidgets command ID to be sent to the plater to inform that the slicing is finished, and the G-code export will continue.
int m_event_slicing_completed_id = 0;
- // wxWidgets command ID to be sent to the platter to inform that the task finished.
+ // wxWidgets command ID to be sent to the plater to inform that the task finished.
int m_event_finished_id = 0;
};
diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp
index f7cefe72b..7322a88d1 100644
--- a/src/slic3r/GUI/BitmapCache.cpp
+++ b/src/slic3r/GUI/BitmapCache.cpp
@@ -1,6 +1,7 @@
#include "BitmapCache.hpp"
#include "libslic3r/Utils.hpp"
+#include <boost/filesystem.hpp>
#if ! defined(WIN32) && ! defined(__APPLE__)
#define BROKEN_ALPHA
@@ -15,7 +16,7 @@
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
-#include "GUI_App.hpp"
+//#include "GUI_App.hpp"
namespace Slic3r { namespace GUI {
@@ -226,7 +227,7 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned width,
}
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_width, unsigned target_height,
- float scale /* = 1.0f */, const bool grayscale/* = false*/)
+ float scale /* = 1.0f */, const bool grayscale/* = false*/, const bool dark_mode/* = false*/)
{
std::string bitmap_key = bitmap_name + ( target_height !=0 ?
"-h" + std::to_string(target_height) :
@@ -234,16 +235,45 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
+ (scale != 1.0f ? "-s" + std::to_string(scale) : "")
+ (grayscale ? "-gs" : "");
- target_height != 0 ? target_height *= scale : target_width *= scale;
+ /* For the Dark mode of any platform, we should draw icons in respect to OS background
+ * Note: All standard(regular) icons are collected in "icons" folder,
+ * SVG-icons, which have "Dark mode" variant, are collected in "icons/white" folder
+ */
+ std::string folder;
+ if (dark_mode)
+ {
+#ifdef __WXMSW__
+ folder = "white\\";
+#else
+ folder = "white/";
+#endif
+ auto it = m_map.find(folder + bitmap_key);
+ if (it != m_map.end())
+ return it->second;
+ else {
+ it = m_map.find(bitmap_key);
+ if (it != m_map.end())
+ return it->second;
+ }
- auto it = m_map.find(bitmap_key);
- if (it != m_map.end())
- return it->second;
+ if (!boost::filesystem::exists(Slic3r::var(folder + bitmap_name + ".svg")))
+ folder.clear();
+ else
+ bitmap_key = folder + bitmap_key;
+ }
+ else
+ {
+ auto it = m_map.find(bitmap_key);
+ if (it != m_map.end())
+ return it->second;
+ }
- NSVGimage *image = ::nsvgParseFromFile(Slic3r::var(bitmap_name + ".svg").c_str(), "px", 96.0f);
+ NSVGimage *image = ::nsvgParseFromFile(Slic3r::var(folder + bitmap_name + ".svg").c_str(), "px", 96.0f);
if (image == nullptr)
return nullptr;
+ target_height != 0 ? target_height *= scale : target_width *= scale;
+
float svg_scale = target_height != 0 ?
(float)target_height / image->height : target_width != 0 ?
(float)target_width / image->width : 1;
diff --git a/src/slic3r/GUI/BitmapCache.hpp b/src/slic3r/GUI/BitmapCache.hpp
index ce77057c8..041e7d892 100644
--- a/src/slic3r/GUI/BitmapCache.hpp
+++ b/src/slic3r/GUI/BitmapCache.hpp
@@ -34,7 +34,7 @@ public:
// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
wxBitmap* load_png(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false);
// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
- wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, float scale = 1.0f, const bool grayscale = false);
+ wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, float scale = 1.0f, const bool grayscale = false, const bool dark_mode = false);
static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency);
static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }
diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp
index fa7a3be21..c21947d58 100644
--- a/src/slic3r/GUI/Camera.cpp
+++ b/src/slic3r/GUI/Camera.cpp
@@ -6,6 +6,11 @@
#endif // !ENABLE_THUMBNAIL_GENERATOR
#include "GUI_App.hpp"
#include "AppConfig.hpp"
+#if ENABLE_CAMERA_STATISTICS
+#if ENABLE_6DOF_CAMERA
+#include "Mouse3DController.hpp"
+#endif // ENABLE_6DOF_CAMERA
+#endif // ENABLE_CAMERA_STATISTICS
#include <GL/glew.h>
@@ -34,18 +39,27 @@ double Camera::FrustrumZMargin = 10.0;
double Camera::MaxFovDeg = 60.0;
Camera::Camera()
+#if ENABLE_6DOF_CAMERA
+ : requires_zoom_to_bed(false)
+#else
: phi(45.0f)
, requires_zoom_to_bed(false)
, inverted_phi(false)
+#endif // ENABLE_6DOF_CAMERA
, m_type(Perspective)
, m_target(Vec3d::Zero())
+#if !ENABLE_6DOF_CAMERA
, m_theta(45.0f)
+#endif // !ENABLE_6DOF_CAMERA
, m_zoom(1.0)
, m_distance(DefaultDistance)
, m_gui_scale(1.0)
, m_view_matrix(Transform3d::Identity())
, m_projection_matrix(Transform3d::Identity())
{
+#if ENABLE_6DOF_CAMERA
+ set_default_orientation();
+#endif // ENABLE_6DOF_CAMERA
}
std::string Camera::get_type_as_string() const
@@ -91,6 +105,9 @@ void Camera::select_next_type()
void Camera::set_target(const Vec3d& target)
{
+#if ENABLE_6DOF_CAMERA
+ translate_world(target - m_target);
+#else
BoundingBoxf3 test_box = m_scene_box;
test_box.translate(-m_scene_box.center());
// We may let this factor be customizable
@@ -101,8 +118,10 @@ void Camera::set_target(const Vec3d& target)
m_target(0) = clamp(test_box.min(0), test_box.max(0), target(0));
m_target(1) = clamp(test_box.min(1), test_box.max(1), target(1));
m_target(2) = clamp(test_box.min(2), test_box.max(2), target(2));
+#endif // ENABLE_6DOF_CAMERA
}
+#if !ENABLE_6DOF_CAMERA
void Camera::set_theta(float theta, bool apply_limit)
{
if (apply_limit)
@@ -114,6 +133,7 @@ void Camera::set_theta(float theta, bool apply_limit)
m_theta += 360.0f;
}
}
+#endif // !ENABLE_6DOF_CAMERA
void Camera::update_zoom(double delta_zoom)
{
@@ -123,14 +143,33 @@ void Camera::update_zoom(double delta_zoom)
void Camera::set_zoom(double zoom)
{
// Don't allow to zoom too far outside the scene.
- double zoom_min = calc_zoom_to_bounding_box_factor(m_scene_box, (int)m_viewport[2], (int)m_viewport[3]);
+ double zoom_min = min_zoom();
if (zoom_min > 0.0)
- zoom = std::max(zoom, zoom_min * 0.7);
+ zoom = std::max(zoom, zoom_min);
// Don't allow to zoom too close to the scene.
- m_zoom = std::min(zoom, 100.0);
+ m_zoom = std::min(zoom, max_zoom());
}
+#if ENABLE_6DOF_CAMERA
+void Camera::select_view(const std::string& direction)
+{
+ if (direction == "iso")
+ set_default_orientation();
+ else if (direction == "left")
+ m_view_matrix = look_at(m_target - m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
+ else if (direction == "right")
+ m_view_matrix = look_at(m_target + m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
+ else if (direction == "top")
+ m_view_matrix = look_at(m_target + m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY());
+ else if (direction == "bottom")
+ m_view_matrix = look_at(m_target - m_distance * Vec3d::UnitZ(), m_target, -Vec3d::UnitY());
+ else if (direction == "front")
+ m_view_matrix = look_at(m_target - m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
+ else if (direction == "rear")
+ m_view_matrix = look_at(m_target + m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
+}
+#else
bool Camera::select_view(const std::string& direction)
{
const float* dir_vec = nullptr;
@@ -159,6 +198,7 @@ bool Camera::select_view(const std::string& direction)
else
return false;
}
+#endif // ENABLE_6DOF_CAMERA
double Camera::get_fov() const
{
@@ -180,20 +220,26 @@ void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) const
void Camera::apply_view_matrix() const
{
+#if !ENABLE_6DOF_CAMERA
double theta_rad = Geometry::deg2rad(-(double)m_theta);
double phi_rad = Geometry::deg2rad((double)phi);
double sin_theta = ::sin(theta_rad);
Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
+#endif // !ENABLE_6DOF_CAMERA
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glLoadIdentity());
+#if ENABLE_6DOF_CAMERA
+ glsafe(::glMultMatrixd(m_view_matrix.data()));
+#else
glsafe(::glRotatef(-m_theta, 1.0f, 0.0f, 0.0f)); // pitch
glsafe(::glRotatef(phi, 0.0f, 0.0f, 1.0f)); // yaw
glsafe(::glTranslated(-camera_pos(0), -camera_pos(1), -camera_pos(2)));
glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, m_view_matrix.data()));
+#endif // ENABLE_6DOF_CAMERA
}
void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z) const
@@ -300,7 +346,11 @@ void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h)
{
m_zoom = zoom;
// center view around box center
+#if ENABLE_6DOF_CAMERA
+ set_target(box.center());
+#else
m_target = box.center();
+#endif // ENABLE_6DOF_CAMERA
}
}
@@ -313,7 +363,11 @@ void Camera::zoom_to_volumes(const GLVolumePtrs& volumes, int canvas_w, int canv
{
m_zoom = zoom;
// center view around the calculated center
+#if ENABLE_6DOF_CAMERA
+ set_target(center);
+#else
m_target = center;
+#endif // ENABLE_6DOF_CAMERA
}
}
#endif // ENABLE_THUMBNAIL_GENERATOR
@@ -325,6 +379,12 @@ void Camera::debug_render() const
imgui.begin(std::string("Camera statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
std::string type = get_type_as_string();
+#if ENABLE_6DOF_CAMERA
+ if (wxGetApp().plater()->get_mouse3d_controller().is_running() || (wxGetApp().app_config->get("use_free_camera") == "1"))
+ type += "/free";
+ else
+ type += "/constrained";
+#endif // ENABLE_6DOF_CAMERA
Vec3f position = get_position().cast<float>();
Vec3f target = m_target.cast<float>();
float distance = (float)get_distance();
@@ -360,6 +420,50 @@ void Camera::debug_render() const
}
#endif // ENABLE_CAMERA_STATISTICS
+#if ENABLE_6DOF_CAMERA
+void Camera::translate_world(const Vec3d& displacement)
+{
+ Vec3d new_target = validate_target(m_target + displacement);
+ Vec3d new_displacement = new_target - m_target;
+ if (!new_displacement.isApprox(Vec3d::Zero()))
+ {
+ m_target += new_displacement;
+ m_view_matrix.translate(-new_displacement);
+ }
+}
+
+void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad)
+{
+ Vec3d target = m_target;
+ translate_world(-target);
+ m_view_matrix.rotate(Eigen::AngleAxisd(delta_zenit_rad, get_dir_right()));
+ m_view_matrix.rotate(Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ()));
+ translate_world(target);
+}
+
+void Camera::rotate_local_around_target(const Vec3d& rotation_rad)
+{
+ rotate_local_around_pivot(rotation_rad, m_target);
+}
+
+void Camera::rotate_local_around_pivot(const Vec3d& rotation_rad, const Vec3d& pivot)
+{
+ // we use a copy of the pivot because a reference to the current m_target may be passed in (see i.e. rotate_local_around_target())
+ // and m_target is modified by the translate_world() calls
+ Vec3d center = pivot;
+ translate_world(-center);
+ m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(0), get_dir_right()));
+ m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(1), get_dir_up()));
+ m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(2), get_dir_forward()));
+ translate_world(center);
+}
+
+double Camera::min_zoom() const
+{
+ return 0.7 * calc_zoom_to_bounding_box_factor(m_scene_box, (int)m_viewport[2], (int)m_viewport[3]);
+}
+#endif // ENABLE_6DOF_CAMERA
+
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
{
std::pair<double, double> ret;
@@ -540,6 +644,63 @@ void Camera::set_distance(double distance) const
apply_view_matrix();
}
+#if ENABLE_6DOF_CAMERA
+Transform3d Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up) const
+{
+ Vec3d unit_z = (position - target).normalized();
+ Vec3d unit_x = up.cross(unit_z).normalized();
+ Vec3d unit_y = unit_z.cross(unit_x).normalized();
+
+ Transform3d matrix;
+
+ matrix(0, 0) = unit_x(0);
+ matrix(0, 1) = unit_x(1);
+ matrix(0, 2) = unit_x(2);
+ matrix(0, 3) = -unit_x.dot(position);
+
+ matrix(1, 0) = unit_y(0);
+ matrix(1, 1) = unit_y(1);
+ matrix(1, 2) = unit_y(2);
+ matrix(1, 3) = -unit_y.dot(position);
+
+ matrix(2, 0) = unit_z(0);
+ matrix(2, 1) = unit_z(1);
+ matrix(2, 2) = unit_z(2);
+ matrix(2, 3) = -unit_z.dot(position);
+
+ matrix(3, 0) = 0.0;
+ matrix(3, 1) = 0.0;
+ matrix(3, 2) = 0.0;
+ matrix(3, 3) = 1.0;
+
+ return matrix;
+}
+
+void Camera::set_default_orientation()
+{
+ double theta_rad = Geometry::deg2rad(-45.0);
+ double phi_rad = Geometry::deg2rad(45.0);
+ double sin_theta = ::sin(theta_rad);
+ Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
+ m_view_matrix = Transform3d::Identity();
+ m_view_matrix.rotate(Eigen::AngleAxisd(theta_rad, Vec3d::UnitX())).rotate(Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ())).translate(-camera_pos);
+}
+
+Vec3d Camera::validate_target(const Vec3d& target) const
+{
+ BoundingBoxf3 test_box = m_scene_box;
+ test_box.translate(-m_scene_box.center());
+ // We may let this factor be customizable
+ static const double ScaleFactor = 1.5;
+ test_box.scale(ScaleFactor);
+ test_box.translate(m_scene_box.center());
+
+ return Vec3d(std::clamp(target(0), test_box.min(0), test_box.max(0)),
+ std::clamp(target(1), test_box.min(1), test_box.max(1)),
+ std::clamp(target(2), test_box.min(2), test_box.max(2)));
+}
+#endif // ENABLE_6DOF_CAMERA
+
} // GUI
} // Slic3r
diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp
index 6cd1b75a5..2a4336108 100644
--- a/src/slic3r/GUI/Camera.hpp
+++ b/src/slic3r/GUI/Camera.hpp
@@ -30,21 +30,29 @@ struct Camera
Num_types
};
+#if !ENABLE_6DOF_CAMERA
float phi;
- bool requires_zoom_to_bed;
bool inverted_phi;
+#endif // !ENABLE_6DOF_CAMERA
+ bool requires_zoom_to_bed;
private:
EType m_type;
Vec3d m_target;
+#if !ENABLE_6DOF_CAMERA
float m_theta;
+#endif // !ENABLE_6DOF_CAMERA
double m_zoom;
// Distance between camera position and camera target measured along the camera Z axis
mutable double m_distance;
mutable double m_gui_scale;
mutable std::array<int, 4> m_viewport;
+#if ENABLE_6DOF_CAMERA
+ Transform3d m_view_matrix;
+#else
mutable Transform3d m_view_matrix;
+#endif // ENABLE_6DOF_CAMERA
mutable Transform3d m_projection_matrix;
mutable std::pair<double, double> m_frustrum_zs;
@@ -66,17 +74,24 @@ public:
double get_distance() const { return m_distance; }
double get_gui_scale() const { return m_gui_scale; }
+#if !ENABLE_6DOF_CAMERA
float get_theta() const { return m_theta; }
void set_theta(float theta, bool apply_limit);
+#endif // !ENABLE_6DOF_CAMERA
double get_zoom() const { return m_zoom; }
+ double get_inv_zoom() const { assert(m_zoom != 0.0); return 1.0 / m_zoom; }
void update_zoom(double delta_zoom);
void set_zoom(double zoom);
const BoundingBoxf3& get_scene_box() const { return m_scene_box; }
void set_scene_box(const BoundingBoxf3& box) { m_scene_box = box; }
+#if ENABLE_6DOF_CAMERA
+ void select_view(const std::string& direction);
+#else
bool select_view(const std::string& direction);
+#endif // ENABLE_6DOF_CAMERA
const std::array<int, 4>& get_viewport() const { return m_viewport; }
const Transform3d& get_view_matrix() const { return m_view_matrix; }
@@ -110,6 +125,27 @@ public:
void debug_render() const;
#endif // ENABLE_CAMERA_STATISTICS
+#if ENABLE_6DOF_CAMERA
+ // translate the camera in world space
+ void translate_world(const Vec3d& displacement);
+
+ // rotate the camera on a sphere having center == m_target and radius == m_distance
+ // using the given variations of spherical coordinates
+ void rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad);
+
+ // rotate the camera around three axes parallel to the camera local axes and passing through m_target
+ void rotate_local_around_target(const Vec3d& rotation_rad);
+
+ // rotate the camera around three axes parallel to the camera local axes and passing through the given pivot point
+ void rotate_local_around_pivot(const Vec3d& rotation_rad, const Vec3d& pivot);
+
+ // returns true if the camera z axis (forward) is pointing in the negative direction of the world z axis
+ bool is_looking_downward() const { return get_dir_forward().dot(Vec3d::UnitZ()) < 0.0; }
+
+ double max_zoom() const { return 100.0; }
+ double min_zoom() const;
+#endif // ENABLE_6DOF_CAMERA
+
private:
// returns tight values for nearZ and farZ plane around the given bounding box
// the camera MUST be outside of the bounding box in eye coordinate of the given box
@@ -121,6 +157,12 @@ private:
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
#endif // ENABLE_THUMBNAIL_GENERATOR
void set_distance(double distance) const;
+
+#if ENABLE_6DOF_CAMERA
+ Transform3d look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up) const;
+ void set_default_orientation();
+ Vec3d validate_target(const Vec3d& target) const;
+#endif // ENABLE_6DOF_CAMERA
};
} // GUI
diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp
index 265e7f203..add680a40 100644
--- a/src/slic3r/GUI/ConfigWizard.cpp
+++ b/src/slic3r/GUI/ConfigWizard.cpp
@@ -350,6 +350,21 @@ bool PrinterPicker::any_selected() const
return false;
}
+std::set<std::string> PrinterPicker::get_selected_models() const
+{
+ std::set<std::string> ret_set;
+
+ for (const auto& cb : cboxes)
+ if (cb->GetValue())
+ ret_set.emplace(cb->model);
+
+ for (const auto& cb : cboxes_alt)
+ if (cb->GetValue())
+ ret_set.emplace(cb->model);
+
+ return ret_set;
+}
+
void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked)
{
PrinterPickerEvent evt(EVT_PRINTER_PICK, GetId(), vendor_id, cbox->model, cbox->variant, checked);
@@ -500,6 +515,19 @@ bool PagePrinters::any_selected() const
return false;
}
+std::set<std::string> PagePrinters::get_selected_models()
+{
+ std::set<std::string> ret_set;
+
+ for (const auto *picker : printer_pickers)
+ {
+ std::set<std::string> tmp_models = picker->get_selected_models();
+ ret_set.insert(tmp_models.begin(), tmp_models.end());
+ }
+
+ return ret_set;
+}
+
void PagePrinters::set_run_reason(ConfigWizard::RunReason run_reason)
{
if (technology == T_FFF
@@ -765,6 +793,23 @@ PageUpdate::PageUpdate(ConfigWizard *parent)
box_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { this->preset_update = event.IsChecked(); });
}
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+PageReloadFromDisk::PageReloadFromDisk(ConfigWizard* parent)
+ : ConfigWizardPage(parent, _(L("Reload from disk")), _(L("Reload from disk")))
+ , full_pathnames(false)
+{
+ auto* box_pathnames = new wxCheckBox(this, wxID_ANY, _(L("Export full pathnames of models and parts sources into 3mf and amf files")));
+ box_pathnames->SetValue(wxGetApp().app_config->get("export_sources_full_pathnames") == "1");
+ append(box_pathnames);
+ append_text(_(L(
+ "If enabled, allows the Reload from disk command to automatically find and load the files when invoked.\n"
+ "If not enabled, the Reload from disk command will ask to select each file using an open file dialog."
+ )));
+
+ box_pathnames->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) { this->full_pathnames = event.IsChecked(); });
+}
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+
PageMode::PageMode(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("View mode")), _(L("View mode")))
{
@@ -1356,6 +1401,9 @@ void ConfigWizard::priv::load_pages()
btn_finish->Enable(any_fff_selected || any_sla_selected);
index->add_page(page_update);
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ index->add_page(page_reload_from_disk);
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
index->add_page(page_mode);
index->go_to(former_active); // Will restore the active item/page if possible
@@ -1580,6 +1628,10 @@ void ConfigWizard::priv::on_printer_pick(PagePrinters *page, const PrinterPicker
preset.is_visible = evt.enable;
}
}
+
+ // if at list one printer is selected but there in no one selected material,
+ // select materials which is default for selected printer(s)
+ select_default_materials_if_needed(pair.second.vendor_profile, page->technology, evt.model_id);
}
if (page->technology & T_FFF) {
@@ -1589,6 +1641,57 @@ void ConfigWizard::priv::on_printer_pick(PagePrinters *page, const PrinterPicker
}
}
+void ConfigWizard::priv::select_default_materials_for_printer_model(const std::vector<VendorProfile::PrinterModel>& models, Technology technology, const std::string& model_id)
+{
+ PageMaterials* page_materials = technology & T_FFF ? page_filaments : page_sla_materials;
+
+ auto it = std::find_if(models.begin(), models.end(), [model_id](VendorProfile::PrinterModel model) {return model_id == model.id; });
+ if (it != models.end())
+ for (const std::string& material : it->default_materials)
+ appconfig_new.set(page_materials->materials->appconfig_section(), material, "1");
+}
+
+void ConfigWizard::priv::select_default_materials_if_needed(VendorProfile* vendor_profile, Technology technology, const std::string& model_id)
+{
+ if ((technology & T_FFF && !any_fff_selected) ||
+ (technology & T_SLA && !any_sla_selected) ||
+ check_materials_in_config(technology, false))
+ return;
+
+ select_default_materials_for_printer_model(vendor_profile->models, technology, model_id);
+}
+
+void ConfigWizard::priv::selected_default_materials(Technology technology)
+{
+ auto select_default_materials_for_printer_page = [this](PagePrinters * page_printers, Technology technology)
+ {
+ std::set<std::string> selected_models = page_printers->get_selected_models();
+ const std::string vendor_id = page_printers->get_vendor_id();
+
+ for (auto& pair : bundles)
+ {
+ if (pair.first != vendor_id)
+ continue;
+
+ for (const std::string& model_id : selected_models)
+ select_default_materials_for_printer_model(pair.second.vendor_profile->models, technology, model_id);
+ }
+ };
+
+ PagePrinters* page_printers = technology & T_FFF ? page_fff : page_msla;
+ select_default_materials_for_printer_page(page_printers, technology);
+
+ for (const auto& printer : pages_3rdparty)
+ {
+ page_printers = technology & T_FFF ? printer.second.first : printer.second.second;
+ if (page_printers)
+ select_default_materials_for_printer_page(page_printers, technology);
+ }
+
+ update_materials(technology);
+ (technology& T_FFF ? page_filaments : page_sla_materials)->reload_presets();
+}
+
void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool install)
{
auto it = pages_3rdparty.find(vendor->id);
@@ -1625,7 +1728,7 @@ bool ConfigWizard::priv::on_bnt_finish()
return check_materials_in_config(T_ANY);
}
-bool ConfigWizard::priv::check_materials_in_config(Technology technology)
+bool ConfigWizard::priv::check_materials_in_config(Technology technology, bool show_info_msg)
{
const auto exist_preset = [this](const std::string& section, const Materials& materials)
{
@@ -1640,15 +1743,32 @@ bool ConfigWizard::priv::check_materials_in_config(Technology technology)
return false;
};
+ const auto ask_and_selected_default_materials = [this](wxString message, Technology technology)
+ {
+ wxMessageDialog msg(q, message, _(L("Notice")), wxYES_NO);
+ if (msg.ShowModal() == wxID_YES)
+ selected_default_materials(technology);
+ };
+
if (any_fff_selected && technology & T_FFF && !exist_preset(AppConfig::SECTION_FILAMENTS, filaments))
{
- show_info(q, _(L("You have to select at least one filament for selected printers")), "");
+ if (show_info_msg)
+ {
+ wxString message = _(L("You have to select at least one filament for selected printers")) + "\n\n\t" +
+ _(L("Do you want to automatic select default filaments?"));
+ ask_and_selected_default_materials(message, T_FFF);
+ }
return false;
}
if (any_sla_selected && technology & T_SLA && !exist_preset(AppConfig::SECTION_MATERIALS, sla_materials))
{
- show_info(q, _(L("You have to select at least one material for selected printers")), "");
+ if (show_info_msg)
+ {
+ wxString message = _(L("You have to select at least one material for selected printers")) + "\n\n\t" +
+ _(L("Do you want to automatic select default materials?"));
+ ask_and_selected_default_materials(message, T_SLA);
+ }
return false;
}
@@ -1730,6 +1850,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
}
app_config->set("version_check", page_update->version_check ? "1" : "0");
app_config->set("preset_update", page_update->preset_update ? "1" : "0");
+
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ app_config->set("export_sources_full_pathnames", page_reload_from_disk->full_pathnames ? "1" : "0");
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+
page_mode->serialize_mode(app_config);
std::string preferred_model;
@@ -1885,6 +2010,9 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
p->add_page(p->page_custom = new PageCustom(this));
p->add_page(p->page_update = new PageUpdate(this));
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ p->add_page(p->page_reload_from_disk = new PageReloadFromDisk(this));
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
p->add_page(p->page_mode = new PageMode(this));
p->add_page(p->page_firmware = new PageFirmware(this));
p->add_page(p->page_bed = new PageBedShape(this));
diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp
index a90832a3f..9c14633c9 100644
--- a/src/slic3r/GUI/ConfigWizard_private.hpp
+++ b/src/slic3r/GUI/ConfigWizard_private.hpp
@@ -149,6 +149,7 @@ struct PrinterPicker: wxPanel
void select_all(bool select, bool alternates = false);
void select_one(size_t i, bool select);
bool any_selected() const;
+ std::set<std::string> get_selected_models() const ;
int get_width() const { return width; }
const std::vector<int>& get_button_indexes() { return m_button_indexes; }
@@ -215,6 +216,9 @@ struct PagePrinters: ConfigWizardPage
void select_all(bool select, bool alternates = false);
int get_width() const;
bool any_selected() const;
+ std::set<std::string> get_selected_models();
+
+ std::string get_vendor_id() const { return printer_pickers.empty() ? "" : printer_pickers[0]->vendor_id; }
virtual void set_run_reason(ConfigWizard::RunReason run_reason) override;
};
@@ -301,6 +305,17 @@ struct PageUpdate: ConfigWizardPage
PageUpdate(ConfigWizard *parent);
};
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+struct PageReloadFromDisk : ConfigWizardPage
+{
+ bool full_pathnames;
+
+ PageReloadFromDisk(ConfigWizard* parent);
+};
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
struct PageMode: ConfigWizardPage
{
wxRadioButton *radio_simple;
@@ -455,6 +470,11 @@ struct ConfigWizard::priv
PageMaterials *page_sla_materials = nullptr;
PageCustom *page_custom = nullptr;
PageUpdate *page_update = nullptr;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ PageReloadFromDisk *page_reload_from_disk = nullptr;
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
PageMode *page_mode = nullptr;
PageVendors *page_vendors = nullptr;
Pages3rdparty pages_3rdparty;
@@ -487,10 +507,17 @@ struct ConfigWizard::priv
void on_custom_setup();
void on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt);
+ void select_default_materials_for_printer_model(const std::vector<VendorProfile::PrinterModel> &models,
+ Technology technology,
+ const std::string & model_id);
+ void select_default_materials_if_needed(VendorProfile* vendor_profile,
+ Technology technology,
+ const std::string &model_id);
+ void selected_default_materials(Technology technology);
void on_3rdparty_install(const VendorProfile *vendor, bool install);
bool on_bnt_finish();
- bool check_materials_in_config(Technology technology);
+ bool check_materials_in_config(Technology technology, bool show_info_msg = true);
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
// #ys_FIXME_alise
void update_presets_in_config(const std::string& section, const std::string& alias_key, bool add);
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 6392b97c0..85f7197fc 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -132,9 +132,7 @@ GLCanvas3D::LayersEditing::LayersEditing()
, m_object_max_z(0.f)
, m_slicing_parameters(nullptr)
, m_layer_height_profile_modified(false)
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
, m_adaptive_quality(0.5f)
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
, state(Unknown)
, band_width(2.0f)
, strength(0.005f)
@@ -155,9 +153,6 @@ GLCanvas3D::LayersEditing::~LayersEditing()
}
const float GLCanvas3D::LayersEditing::THICKNESS_BAR_WIDTH = 70.0f;
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-const float GLCanvas3D::LayersEditing::THICKNESS_RESET_BUTTON_HEIGHT = 22.0f;
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename)
{
@@ -224,7 +219,6 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
if (!m_enabled)
return;
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
const Size& cnv_size = canvas.get_canvas_size();
@@ -319,13 +313,6 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
imgui.end();
const Rect& bar_rect = get_bar_rect_viewport(canvas);
-#else
- const Rect& bar_rect = get_bar_rect_viewport(canvas);
- const Rect& reset_rect = get_reset_rect_viewport(canvas);
-
- _render_tooltip_texture(canvas, bar_rect, reset_rect);
- _render_reset_texture(reset_rect);
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
render_active_object_annotations(canvas, bar_rect);
render_profile(bar_rect);
}
@@ -352,67 +339,25 @@ bool GLCanvas3D::LayersEditing::bar_rect_contains(const GLCanvas3D& canvas, floa
return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom());
}
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-bool GLCanvas3D::LayersEditing::reset_rect_contains(const GLCanvas3D& canvas, float x, float y)
-{
- const Rect& rect = get_reset_rect_screen(canvas);
- return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom());
-}
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-
Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas)
{
const Size& cnv_size = canvas.get_canvas_size();
float w = (float)cnv_size.get_width();
float h = (float)cnv_size.get_height();
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
return Rect(w - thickness_bar_width(canvas), 0.0f, w, h);
-#else
- return Rect(w - thickness_bar_width(canvas), 0.0f, w, h - reset_button_height(canvas));
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
}
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-Rect GLCanvas3D::LayersEditing::get_reset_rect_screen(const GLCanvas3D& canvas)
-{
- const Size& cnv_size = canvas.get_canvas_size();
- float w = (float)cnv_size.get_width();
- float h = (float)cnv_size.get_height();
-
- return Rect(w - thickness_bar_width(canvas), h - reset_button_height(canvas), w, h);
-}
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-
Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas)
{
const Size& cnv_size = canvas.get_canvas_size();
float half_w = 0.5f * (float)cnv_size.get_width();
float half_h = 0.5f * (float)cnv_size.get_height();
- float zoom = (float)canvas.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)canvas.get_camera().get_inv_zoom();
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom);
-#else
- return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom);
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-}
-
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-Rect GLCanvas3D::LayersEditing::get_reset_rect_viewport(const GLCanvas3D& canvas)
-{
- const Size& cnv_size = canvas.get_canvas_size();
- float half_w = 0.5f * (float)cnv_size.get_width();
- float half_h = 0.5f * (float)cnv_size.get_height();
-
- float zoom = (float)canvas.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
-
- return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, (-half_h + reset_button_height(canvas)) * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom);
}
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
bool GLCanvas3D::LayersEditing::is_initialized() const
{
@@ -448,54 +393,6 @@ std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) con
return ret;
}
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const
-{
- // TODO: do this with ImGui
-
- if (m_tooltip_texture.get_id() == 0)
- {
- std::string filename = resources_dir() + "/icons/variable_layer_height_tooltip.png";
- if (!m_tooltip_texture.load_from_file(filename, false, GLTexture::SingleThreaded, false))
- return;
- }
-
-#if ENABLE_RETINA_GL
- const float scale = canvas.get_canvas_size().get_scale_factor();
-#else
- const float scale = canvas.get_wxglcanvas()->GetContentScaleFactor();
-#endif
- const float width = (float)m_tooltip_texture.get_width() * scale;
- const float height = (float)m_tooltip_texture.get_height() * scale;
-
- float zoom = (float)canvas.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
- float gap = 10.0f * inv_zoom;
-
- float bar_left = bar_rect.get_left();
- float reset_bottom = reset_rect.get_bottom();
-
- float l = bar_left - width * inv_zoom - gap;
- float r = bar_left - gap;
- float t = reset_bottom + height * inv_zoom + gap;
- float b = reset_bottom + gap;
-
- GLTexture::render_texture(m_tooltip_texture.get_id(), l, r, b, t);
-}
-
-void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) const
-{
- if (m_reset_texture.get_id() == 0)
- {
- std::string filename = resources_dir() + "/icons/variable_layer_height_reset.png";
- if (!m_reset_texture.load_from_file(filename, false, GLTexture::SingleThreaded, false))
- return;
- }
-
- GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top());
-}
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-
void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const
{
m_shader.start_using();
@@ -644,7 +541,6 @@ void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D& canvas, float quality_factor)
{
this->update_slicing_parameters();
@@ -662,7 +558,6 @@ void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D& canvas,
m_layers_texture.valid = false;
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void GLCanvas3D::LayersEditing::generate_layer_height_texture()
{
@@ -725,19 +620,6 @@ float GLCanvas3D::LayersEditing::thickness_bar_width(const GLCanvas3D &canvas)
* THICKNESS_BAR_WIDTH;
}
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas)
-{
- return
-#if ENABLE_RETINA_GL
- canvas.get_canvas_size().get_scale_factor()
-#else
- canvas.get_wxglcanvas()->GetContentScaleFactor()
-#endif
- * THICKNESS_RESET_BUTTON_HEIGHT;
-}
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
-
const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX);
const Vec3d GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX);
@@ -964,8 +846,7 @@ void GLCanvas3D::WarningTexture::render(const GLCanvas3D& canvas) const
if ((m_id > 0) && (m_original_width > 0) && (m_original_height > 0) && (m_width > 0) && (m_height > 0))
{
const Size& cnv_size = canvas.get_canvas_size();
- float zoom = (float)canvas.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)canvas.get_camera().get_inv_zoom();
float left = (-0.5f * (float)m_original_width) * inv_zoom;
float top = (-0.5f * (float)cnv_size.get_height() + (float)m_original_height + 2.0f) * inv_zoom;
float right = left + (float)m_original_width * inv_zoom;
@@ -1011,7 +892,7 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
std::vector<float>& colors,
std::vector<std::string>& cp_legend_items)
{
- std::vector<Model::CustomGCode> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z;
+ std::vector<Model::CustomGCode> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
const int extruders_cnt = wxGetApp().extruders_edited_cnt();
if (extruders_cnt == 1)
@@ -1137,6 +1018,12 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
// calculate scaling
const float scale_gl = canvas.get_canvas_size().get_scale_factor();
+#if ENABLE_RETINA_GL
+ // For non-visible or non-created window getBackingScaleFactor function return 0.0 value.
+ // And using of the zero scale causes a crash, when we trying to draw text to the (0,0) rectangle
+ if (scale_gl <= 0.0f)
+ return false;
+#endif
const float scale = scale_gl * wxGetApp().em_unit()*0.1; // get scale from em_unit() value, because of get_scale_factor() return 1
const int scaled_square = std::floor((float)Px_Square * scale);
const int scaled_title_offset = Px_Title_Offset * scale;
@@ -1321,8 +1208,7 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const
if ((m_id > 0) && (m_original_width > 0) && (m_original_height > 0) && (m_width > 0) && (m_height > 0))
{
const Size& cnv_size = canvas.get_canvas_size();
- float zoom = (float)canvas.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)canvas.get_camera().get_inv_zoom();
float left = (-0.5f * (float)cnv_size.get_width()) * inv_zoom;
float top = (0.5f * (float)cnv_size.get_height()) * inv_zoom;
float right = left + (float)m_original_width * inv_zoom;
@@ -1343,9 +1229,6 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const
}
}
-#if !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
-wxDEFINE_EVENT(EVT_GLCANVAS_INIT, SimpleEvent);
-#endif // !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
@@ -1369,11 +1252,9 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
wxDEFINE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>);
wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent);
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
#if ENABLE_THUMBNAIL_GENERATOR
const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25;
@@ -1515,10 +1396,6 @@ bool GLCanvas3D::init()
if (m_selection.is_enabled() && !m_selection.init())
return false;
-#if !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
- post_event(SimpleEvent(EVT_GLCANVAS_INIT));
-#endif // !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
-
m_initialized = true;
return true;
@@ -1675,7 +1552,6 @@ bool GLCanvas3D::is_layers_editing_allowed() const
return m_layers_editing.is_allowed();
}
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void GLCanvas3D::reset_layer_height_profile()
{
wxGetApp().plater()->take_snapshot(_(L("Variable layer height - Reset")));
@@ -1699,7 +1575,6 @@ void GLCanvas3D::smooth_layer_height_profile(const HeightProfileSmoothingParams&
m_layers_editing.state = LayersEditing::Completed;
m_dirty = true;
}
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
bool GLCanvas3D::is_reload_delayed() const
{
@@ -1786,8 +1661,14 @@ void GLCanvas3D::zoom_to_selection()
void GLCanvas3D::select_view(const std::string& direction)
{
+#if ENABLE_6DOF_CAMERA
+ m_camera.select_view(direction);
+ if (m_canvas != nullptr)
+ m_canvas->Refresh();
+#else
if (m_camera.select_view(direction) && (m_canvas != nullptr))
m_canvas->Refresh();
+#endif // ENABLE_6DOF_CAMERA
}
void GLCanvas3D::update_volumes_colors_by_extruder()
@@ -1844,10 +1725,12 @@ void GLCanvas3D::render()
GLfloat position_top[4] = { -0.5f, -0.5f, 1.0f, 0.0f };
glsafe(::glLightfv(GL_LIGHT0, GL_POSITION, position_top));
+#if !ENABLE_6DOF_CAMERA
float theta = m_camera.get_theta();
if (theta > 180.f)
// absolute value of the rotation
theta = 360.f - theta;
+#endif // !ENABLE_6DOF_CAMERA
wxGetApp().imgui()->new_frame();
@@ -1872,7 +1755,11 @@ void GLCanvas3D::render()
_render_objects();
_render_sla_slices();
_render_selection();
+#if ENABLE_6DOF_CAMERA
+ _render_bed(!m_camera.is_looking_downward(), true);
+#else
_render_bed(theta, true);
+#endif // ENABLE_6DOF_CAMERA
#if ENABLE_RENDER_SELECTION_CENTER
_render_selection_center();
@@ -1921,11 +1808,7 @@ void GLCanvas3D::render()
m_camera.debug_render();
#endif // ENABLE_CAMERA_STATISTICS
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
-#else
- wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
wxGetApp().imgui()->render();
@@ -2421,7 +2304,7 @@ static void load_gcode_retractions(const GCodePreviewData::Retraction& retractio
volume_index.first_volumes.emplace_back(extrusion_type, 0, (unsigned int)volumes.volumes.size());
- GLVolume *volume = volumes.new_nontoolpath_volume(retractions.color.rgba, VERTEX_BUFFER_RESERVE_SIZE);
+ GLVolume *volume = volumes.new_nontoolpath_volume(retractions.color.rgba.data(), VERTEX_BUFFER_RESERVE_SIZE);
GCodePreviewData::Retraction::PositionsList copy(retractions.positions);
std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2) { return p1.position(2) < p2.position(2); });
@@ -3111,20 +2994,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_layers_editing.state = LayersEditing::Editing;
_perform_layer_editing_action(&evt);
}
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- else if ((layer_editing_object_idx != -1) && m_layers_editing.reset_rect_contains(*this, pos(0), pos(1)))
- {
- if (evt.LeftDown())
- {
- // A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
- m_layers_editing.reset_layer_height_profile(*this);
- // Index 2 means no editing, just wait for mouse up event.
- m_layers_editing.state = LayersEditing::Completed;
-
- m_dirty = true;
- }
- }
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled)
{
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)
@@ -3207,7 +3076,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag
if (m_selection.contains_volume(get_first_hover_volume_idx()))
{
+#if ENABLE_6DOF_CAMERA
+ if (std::abs(m_camera.get_dir_forward()(2)) < EPSILON)
+#else
if (m_camera.get_theta() == 90.0f)
+#endif // ENABLE_6DOF_CAMERA
{
// side view -> move selected volumes orthogonally to camera view direction
Linef3 ray = mouse_ray(pos);
@@ -3267,9 +3140,18 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (m_hover_volume_idxs.empty() && m_mouse.is_start_position_3D_defined())
{
const Vec3d& orig = m_mouse.drag.start_position_3D;
+#if ENABLE_6DOF_CAMERA
+ double x = Geometry::deg2rad(pos(0) - orig(0)) * (double)TRACKBALLSIZE;
+ double y = Geometry::deg2rad(pos(1) - orig(1)) * (double)TRACKBALLSIZE;
+ if (wxGetApp().plater()->get_mouse3d_controller().is_running() || (wxGetApp().app_config->get("use_free_camera") == "1"))
+ m_camera.rotate_local_around_target(Vec3d(y, x, 0.0));
+ else
+ m_camera.rotate_on_sphere(x, y);
+#else
float sign = m_camera.inverted_phi ? -1.0f : 1.0f;
m_camera.phi += sign * ((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE;
m_camera.set_theta(m_camera.get_theta() - ((float)pos(1) - (float)orig(1)) * TRACKBALLSIZE, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA);
+#endif // ENABLE_6DOF_CAMERA
m_dirty = true;
}
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
@@ -3319,9 +3201,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (!evt.ShiftDown() && m_picking_enabled)
deselect_all();
}
+#if !ENABLE_6DOF_CAMERA
else if (evt.LeftUp() && m_mouse.dragging)
// Flips X mouse deltas if bed is upside down
m_camera.inverted_phi = (m_camera.get_dir_up()(2) < 0.0);
+#endif // !ENABLE_6DOF_CAMERA
else if (evt.RightUp())
{
m_mouse.position = pos.cast<double>();
@@ -3926,6 +3810,9 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
Camera camera;
camera.set_type(Camera::Ortho);
+#if ENABLE_6DOF_CAMERA
+ camera.set_scene_box(scene_bounding_box());
+#endif // ENABLE_6DOF_CAMERA
camera.zoom_to_volumes(visible_volumes, thumbnail_data.width, thumbnail_data.height);
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
camera.apply_view_matrix();
@@ -3976,7 +3863,11 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
glsafe(::glDisable(GL_DEPTH_TEST));
if (show_bed)
+#if ENABLE_6DOF_CAMERA
+ _render_bed(!camera.is_looking_downward(), false);
+#else
_render_bed(camera.get_theta(), false);
+#endif // ENABLE_6DOF_CAMERA
if (transparent_background)
glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f));
@@ -4227,10 +4118,8 @@ bool GLCanvas3D::_init_toolbars()
if (!_init_undoredo_toolbar())
return false;
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
if (!_init_view_toolbar())
return false;
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
return true;
}
@@ -4489,12 +4378,10 @@ bool GLCanvas3D::_init_undoredo_toolbar()
return true;
}
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool GLCanvas3D::_init_view_toolbar()
{
return wxGetApp().plater()->init_view_toolbar();
}
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool GLCanvas3D::_set_current()
{
@@ -4933,8 +4820,7 @@ void GLCanvas3D::_render_main_toolbar() const
#endif // ENABLE_RETINA_GL
Size cnv_size = get_canvas_size();
- float zoom = (float)m_camera.get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)m_camera.get_inv_zoom();
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom;
float left = -0.5f * (m_main_toolbar.get_width() + m_undoredo_toolbar.get_width()) * inv_zoom;
@@ -4960,8 +4846,7 @@ void GLCanvas3D::_render_undoredo_toolbar() const
#endif // ENABLE_RETINA_GL
Size cnv_size = get_canvas_size();
- float zoom = (float)m_camera.get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)m_camera.get_inv_zoom();
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom;
float left = (m_main_toolbar.get_width() - 0.5f * (m_main_toolbar.get_width() + m_undoredo_toolbar.get_width())) * inv_zoom;
@@ -4983,8 +4868,7 @@ void GLCanvas3D::_render_view_toolbar() const
#endif // ENABLE_RETINA_GL
Size cnv_size = get_canvas_size();
- float zoom = (float)m_camera.get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)m_camera.get_inv_zoom();
// places the toolbar on the bottom-left corner of the 3d scene
float top = (-0.5f * (float)cnv_size.get_height() + m_view_toolbar.get_height()) * inv_zoom;
@@ -5407,11 +5291,11 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
const std::string& code = it->gcode;
// pause print or custom Gcode
if (code == PausePrintCode ||
- (code != ColorChangeCode && code != ExtruderChangeCode))
+ (code != ColorChangeCode && code != ToolChangeCode))
return number_tools()-1; // last color item is a gray color for pause print or custom G-code
// change tool (extruder)
- if (code == ExtruderChangeCode)
+ if (code == ToolChangeCode)
return get_color_idx_for_tool_change(it, extruder);
// change color for current extruder
if (code == ColorChangeCode) {
@@ -5433,7 +5317,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
return color_idx;
}
// change tool (extruder)
- if (it->gcode == ExtruderChangeCode)
+ if (it->gcode == ToolChangeCode)
return get_color_idx_for_tool_change(it, extruder);
}
@@ -5477,7 +5361,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
bool is_tool_change = false;
while (it_n != color_print_values->begin()) {
--it_n;
- if (it_n->gcode == ExtruderChangeCode) {
+ if (it_n->gcode == ToolChangeCode) {
is_tool_change = true;
if (it_n->extruder == it->extruder || (it_n->extruder == 0 && it->extruder == extruder))
return get_m600_color_idx(it);
@@ -5857,7 +5741,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
return 0.0f;
}
- static GCodePreviewData::Color path_color(const GCodePreviewData& data, const std::vector<float>& tool_colors, float value)
+ static Color path_color(const GCodePreviewData& data, const std::vector<float>& tool_colors, float value)
{
switch (data.extrusion.view_type)
{
@@ -5875,8 +5759,8 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
return data.get_volumetric_rate_color(value);
case GCodePreviewData::Extrusion::Tool:
{
- GCodePreviewData::Color color;
- ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (unsigned int)value * 4), 4 * sizeof(float));
+ Color color;
+ ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data() + (unsigned int)value * 4), 4 * sizeof(float));
return color;
}
case GCodePreviewData::Extrusion::ColorPrint:
@@ -5884,16 +5768,16 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
int color_cnt = (int)tool_colors.size() / 4;
int val = value > color_cnt ? color_cnt - 1 : value;
- GCodePreviewData::Color color;
- ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float));
+ Color color;
+ ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float));
return color;
}
default:
- return GCodePreviewData::Color::Dummy;
+ return Color{};
}
- return GCodePreviewData::Color::Dummy;
+ return Color{};
}
};
@@ -5936,7 +5820,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
if (! values.empty()) {
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, role, (unsigned int)m_volumes.volumes.size());
for (const float value : values)
- roles_filters.back().emplace_back(value, m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value).rgba, vertex_buffer_prealloc_size));
+ roles_filters.back().emplace_back(value, m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value).rgba.data(), vertex_buffer_prealloc_size));
}
}
}
@@ -6019,7 +5903,7 @@ inline void travel_paths_internal(
by_type.reserve(values.size());
// creates a new volume for each feedrate
for (TYPE type : values)
- by_type.emplace_back(type, volumes.new_nontoolpath_volume(func_color(type).rgba, VERTEX_BUFFER_RESERVE_SIZE));
+ by_type.emplace_back(type, volumes.new_nontoolpath_volume(func_color(type).rgba.data(), VERTEX_BUFFER_RESERVE_SIZE));
}
// populates volumes
@@ -6066,19 +5950,19 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data,
case GCodePreviewData::Extrusion::Feedrate:
travel_paths_internal<float>(preview_data,
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.feedrate; },
- [&preview_data](const float feedrate) -> const GCodePreviewData::Color { return preview_data.get_feedrate_color(feedrate); },
+ [&preview_data](const float feedrate) -> const Color { return preview_data.get_feedrate_color(feedrate); },
m_volumes, m_initialized);
break;
case GCodePreviewData::Extrusion::Tool:
travel_paths_internal<unsigned int>(preview_data,
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.extruder_id; },
- [&tool_colors](const unsigned int extruder_id) -> const GCodePreviewData::Color { assert((extruder_id + 1) * 4 <= tool_colors.size()); return GCodePreviewData::Color(tool_colors.data() + extruder_id * 4); },
+ [&tool_colors](const unsigned int extruder_id) -> const Color { assert((extruder_id + 1) * 4 <= tool_colors.size()); return Color(tool_colors.data() + extruder_id * 4); },
m_volumes, m_initialized);
break;
default:
travel_paths_internal<unsigned int>(preview_data,
[](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.type; },
- [&preview_data](const unsigned int type) -> const GCodePreviewData::Color& { return preview_data.travel.type_colors[type]; },
+ [&preview_data](const unsigned int type) -> const Color& { return preview_data.travel.type_colors[type]; },
m_volumes, m_initialized);
break;
}
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 3e8b56bd0..c842c7b42 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -83,9 +83,6 @@ template <size_t N> using Vec3dsEvent = ArrayEvent<Vec3d, N>;
using HeightProfileSmoothEvent = Event<HeightProfileSmoothingParams>;
-#if !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
-wxDECLARE_EVENT(EVT_GLCANVAS_INIT, SimpleEvent);
-#endif // !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
wxDECLARE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
@@ -108,11 +105,9 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
wxDECLARE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>);
wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent);
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
class GLCanvas3D
{
@@ -162,17 +157,10 @@ private:
private:
static const float THICKNESS_BAR_WIDTH;
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- static const float THICKNESS_RESET_BUTTON_HEIGHT;
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
bool m_enabled;
Shader m_shader;
unsigned int m_z_texture_id;
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- mutable GLTexture m_tooltip_texture;
- mutable GLTexture m_reset_texture;
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// Not owned by LayersEditing.
const DynamicPrintConfig *m_config;
// ModelObject for the currently selected object (Model::objects[last_object_id]).
@@ -184,10 +172,8 @@ private:
std::vector<double> m_layer_height_profile;
bool m_layer_height_profile_modified;
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
mutable float m_adaptive_quality;
mutable HeightProfileSmoothingParams m_smooth_params;
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
class LayersTexture
{
@@ -235,24 +221,13 @@ private:
void adjust_layer_height_profile();
void accept_changes(GLCanvas3D& canvas);
void reset_layer_height_profile(GLCanvas3D& canvas);
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void adaptive_layer_height_profile(GLCanvas3D& canvas, float quality_factor);
void smooth_layer_height_profile(GLCanvas3D& canvas, const HeightProfileSmoothingParams& smoothing_params);
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
static float get_cursor_z_relative(const GLCanvas3D& canvas);
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- static bool reset_rect_contains(const GLCanvas3D& canvas, float x, float y);
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
static Rect get_bar_rect_screen(const GLCanvas3D& canvas);
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- static Rect get_reset_rect_screen(const GLCanvas3D& canvas);
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- static Rect get_reset_rect_viewport(const GLCanvas3D& canvas);
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
float object_max_z() const { return m_object_max_z; }
@@ -261,18 +236,11 @@ private:
private:
bool is_initialized() const;
void generate_layer_height_texture();
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const;
- void _render_reset_texture(const Rect& reset_rect) const;
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const;
void render_profile(const Rect& bar_rect) const;
void update_slicing_parameters();
static float thickness_bar_width(const GLCanvas3D &canvas);
-#if !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
- static float reset_button_height(const GLCanvas3D &canvas);
-#endif // !ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
};
struct Mouse
@@ -540,11 +508,9 @@ public:
bool is_layers_editing_enabled() const;
bool is_layers_editing_allowed() const;
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
void reset_layer_height_profile();
void adaptive_layer_height_profile(float quality_factor);
void smooth_layer_height_profile(const HeightProfileSmoothingParams& smoothing_params);
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
bool is_reload_delayed() const;
@@ -684,9 +650,7 @@ private:
bool _init_toolbars();
bool _init_main_toolbar();
bool _init_undoredo_toolbar();
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool _init_view_toolbar();
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool _set_current();
void _resize(unsigned int w, unsigned int h);
diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp
index 684563bff..a8b69d75a 100644
--- a/src/slic3r/GUI/GLSelectionRectangle.cpp
+++ b/src/slic3r/GUI/GLSelectionRectangle.cpp
@@ -69,8 +69,7 @@ namespace GUI {
return;
const Camera& camera = canvas.get_camera();
- float zoom = (float)camera.get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)camera.get_inv_zoom();
Size cnv_size = canvas.get_canvas_size();
float cnv_half_width = 0.5f * (float)cnv_size.get_width();
diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp
index 62129cfc0..4ac69d71f 100644
--- a/src/slic3r/GUI/GLTexture.cpp
+++ b/src/slic3r/GUI/GLTexture.cpp
@@ -168,12 +168,26 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
if (filenames.empty() || states.empty() || (sprite_size_px == 0))
return false;
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ // every tile needs to have a 1px border around it to avoid artifacts when linear sampling on its edges
+ unsigned int sprite_size_px_ex = sprite_size_px + 1;
+
+ m_width = 1 + (int)(sprite_size_px_ex * states.size());
+ m_height = 1 + (int)(sprite_size_px_ex * filenames.size());
+#else
m_width = (int)(sprite_size_px * states.size());
m_height = (int)(sprite_size_px * filenames.size());
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
+
int n_pixels = m_width * m_height;
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ int sprite_n_pixels = sprite_size_px_ex * sprite_size_px_ex;
+ int sprite_stride = sprite_size_px_ex * 4;
+#else
int sprite_n_pixels = sprite_size_px * sprite_size_px;
- int sprite_bytes = sprite_n_pixels * 4;
int sprite_stride = sprite_size_px * 4;
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ int sprite_bytes = sprite_n_pixels * 4;
if (n_pixels <= 0)
{
@@ -211,7 +225,12 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
float scale = (float)sprite_size_px / std::max(image->width, image->height);
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ // offset by 1 to leave the first pixel empty (both in x and y)
+ nsvgRasterize(rast, image, 1, 1, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_stride);
+#else
nsvgRasterize(rast, image, 0, 0, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_stride);
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
// makes white only copy of the sprite
::memcpy((void*)sprite_white_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
@@ -231,7 +250,11 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
::memset((void*)&sprite_gray_only_data.data()[offset], 128, 3);
}
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ int sprite_offset_px = sprite_id * (int)sprite_size_px_ex * m_width;
+#else
int sprite_offset_px = sprite_id * sprite_size_px * m_width;
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
int state_id = -1;
for (const std::pair<int, bool>& state : states)
{
@@ -250,6 +273,23 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
// applies background, if needed
if (state.second)
{
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ float inv_255 = 1.0f / 255.0f;
+ // offset by 1 to leave the first pixel empty (both in x and y)
+ for (unsigned int r = 1; r <= sprite_size_px; ++r)
+ {
+ unsigned int offset_r = r * sprite_size_px_ex;
+ for (unsigned int c = 1; c <= sprite_size_px; ++c)
+ {
+ unsigned int offset = (offset_r + c) * 4;
+ float alpha = (float)output_data.data()[offset + 3] * inv_255;
+ output_data.data()[offset + 0] = (unsigned char)(output_data.data()[offset + 0] * alpha);
+ output_data.data()[offset + 1] = (unsigned char)(output_data.data()[offset + 1] * alpha);
+ output_data.data()[offset + 2] = (unsigned char)(output_data.data()[offset + 2] * alpha);
+ output_data.data()[offset + 3] = (unsigned char)(128 * (1.0f - alpha) + output_data.data()[offset + 3] * alpha);
+ }
+ }
+#else
for (int i = 0; i < sprite_n_pixels; ++i)
{
int offset = i * 4;
@@ -259,13 +299,22 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
output_data.data()[offset + 2] = (unsigned char)(output_data.data()[offset + 2] * alpha);
output_data.data()[offset + 3] = (unsigned char)(128 * (1.0f - alpha) + output_data.data()[offset + 3] * alpha);
}
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
}
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ int state_offset_px = sprite_offset_px + state_id * sprite_size_px_ex;
+ for (int j = 0; j < (int)sprite_size_px_ex; ++j)
+ {
+ ::memcpy((void*)&data.data()[(state_offset_px + j * m_width) * 4], (const void*)&output_data.data()[j * sprite_stride], sprite_stride);
+ }
+#else
int state_offset_px = sprite_offset_px + state_id * sprite_size_px;
for (int j = 0; j < (int)sprite_size_px; ++j)
{
::memcpy((void*)&data.data()[(state_offset_px + j * m_width) * 4], (const void*)&output_data.data()[j * sprite_stride], sprite_stride);
}
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
}
nsvgDelete(image);
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index 2fc0590d5..d1edff10f 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -86,7 +86,35 @@ bool GLToolbarItem::update_enabled_state()
void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
{
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ auto uvs = [this](unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) ->GLTexture::Quad_UVs
+ {
+ assert((tex_width != 0) && (tex_height != 0));
+ GLTexture::Quad_UVs ret;
+ // tiles in the texture are spaced by 1 pixel
+ float icon_size_px = (float)(tex_width - 1) / (float)Num_States;
+ float inv_tex_width = 1.0f / (float)tex_width;
+ float inv_tex_height = 1.0f / (float)tex_height;
+ // tiles in the texture are spaced by 1 pixel
+ float u_offset = 1.0f * inv_tex_width;
+ float v_offset = 1.0f * inv_tex_height;
+ float du = icon_size_px * inv_tex_width;
+ float dv = icon_size_px * inv_tex_height;
+ float left = u_offset + (float)m_state * du;
+ float right = left + du - u_offset;
+ float top = v_offset + (float)m_data.sprite_id * dv;
+ float bottom = top + dv - v_offset;
+ ret.left_top = { left, top };
+ ret.left_bottom = { left, bottom };
+ ret.right_bottom = { right, bottom };
+ ret.right_top = { right, top };
+ return ret;
+ };
+
+ GLTexture::render_sub_texture(tex_id, left, right, bottom, top, uvs(tex_width, tex_height, icon_size));
+#else
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(tex_width, tex_height, icon_size));
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
if (is_pressed())
{
@@ -97,6 +125,7 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b
}
}
+#if !ENABLE_MODIFIED_TOOLBAR_TEXTURES
GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
{
GLTexture::Quad_UVs uvs;
@@ -110,14 +139,14 @@ GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int
float right = left + scaled_icon_width;
float top = (float)m_data.sprite_id * scaled_icon_height;
float bottom = top + scaled_icon_height;
-
uvs.left_top = { left, top };
uvs.left_bottom = { left, bottom };
uvs.right_bottom = { right, bottom };
uvs.right_top = { right, top };
-
+
return uvs;
}
+#endif // !ENABLE_MODIFIED_TOOLBAR_TEXTURES
BackgroundTexture::Metadata::Metadata()
: filename("")
@@ -624,8 +653,7 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
{
// NB: mouse_pos is already scaled appropriately
- float zoom = (float)parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)parent.get_camera().get_inv_zoom();
float factor = m_layout.scale * inv_zoom;
Size cnv_size = parent.get_canvas_size();
@@ -729,8 +757,7 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
{
// NB: mouse_pos is already scaled appropriately
- float zoom = (float)parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)parent.get_camera().get_inv_zoom();
float factor = m_layout.scale * inv_zoom;
Size cnv_size = parent.get_canvas_size();
@@ -846,8 +873,7 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
{
// NB: mouse_pos is already scaled appropriately
- float zoom = (float)parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)parent.get_camera().get_inv_zoom();
float factor = m_layout.scale * inv_zoom;
Size cnv_size = parent.get_canvas_size();
@@ -920,8 +946,7 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
{
// NB: mouse_pos is already scaled appropriately
- float zoom = (float)parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)parent.get_camera().get_inv_zoom();
float factor = m_layout.scale * inv_zoom;
Size cnv_size = parent.get_canvas_size();
@@ -1073,8 +1098,7 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height();
- float zoom = (float)parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)parent.get_camera().get_inv_zoom();
float factor = inv_zoom * m_layout.scale;
float scaled_icons_size = m_layout.icons_size * factor;
@@ -1122,8 +1146,7 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const
int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height();
- float zoom = (float)parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)parent.get_camera().get_inv_zoom();
float factor = inv_zoom * m_layout.scale;
float scaled_icons_size = m_layout.icons_size * factor;
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index eb73dcdfd..f53b8efb9 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -143,7 +143,9 @@ public:
void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
private:
+#if !ENABLE_MODIFIED_TOOLBAR_TEXTURES
GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
+#endif // !ENABLE_MODIFIED_TOOLBAR_TEXTURES
void set_visible(bool visible) { m_data.visible = visible; }
friend class GLToolbar;
@@ -293,9 +295,7 @@ public:
bool is_any_item_pressed() const;
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
unsigned int get_items_count() const { return (unsigned int)m_items.size(); }
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
int get_item_id(const std::string& name) const;
void force_left_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Left, item_id, parent, false); }
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 1a4d12d31..f7010a503 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -533,7 +533,9 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt)
void Preview::on_checkbox_travel(wxCommandEvent& evt)
{
m_gcode_preview_data->travel.is_visible = m_checkbox_travel->IsChecked();
- refresh_print();
+ m_gcode_preview_data->ranges.feedrate.set_mode(GCodePreviewData::FeedrateKind::TRAVEL, m_gcode_preview_data->travel.is_visible);
+ // Rather than refresh, reload print so that speed color ranges get recomputed (affected by travel visibility)
+ reload_print();
}
void Preview::on_checkbox_retractions(wxCommandEvent& evt)
@@ -564,7 +566,7 @@ void Preview::update_view_type(bool slice_completed)
{
const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config;
- const wxString& choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.empty() /*&&
+ const wxString& choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes.empty() /*&&
(wxGetApp().extruders_edited_cnt()==1 || !slice_completed) */?
_(L("Color Print")) :
config.option<ConfigOptionFloats>("wiping_volumes_matrix")->values.size() > 1 ?
@@ -664,8 +666,11 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
bool snap_to_min = force_sliders_full_range || m_slider->is_lower_at_min();
bool snap_to_max = force_sliders_full_range || m_slider->is_higher_at_max();
- std::vector<Model::CustomGCode> &ticks_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z;
- check_slider_values(ticks_from_model, layers_z);
+ // Detect and set manipulation mode for double slider
+ update_double_slider_mode();
+
+ Model::CustomGCodeInfo &ticks_info_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z;
+ check_slider_values(ticks_info_from_model.gcodes, layers_z);
m_slider->SetSliderValues(layers_z);
assert(m_slider->GetMinValue() == 0);
@@ -687,12 +692,61 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
}
m_slider->SetSelectionSpan(idx_low, idx_high);
- m_slider->SetTicksValues(ticks_from_model);
+ m_slider->SetTicksValues(ticks_info_from_model);
+
+ m_slider->EnableTickManipulation(wxGetApp().plater()->printer_technology() == ptFFF);
+}
+
+void Preview::update_double_slider_mode()
+{
+ // true -> single-extruder printer profile OR
+ // multi-extruder printer profile , but whole model is printed by only one extruder
+ // false -> multi-extruder printer profile , and model is printed by several extruders
+ bool one_extruder_printed_model = true;
- bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF);
+ // extruder used for whole model for multi-extruder printer profile
+ int only_extruder = -1;
+
+ if (wxGetApp().extruders_edited_cnt() > 1)
+ {
+ const ModelObjectPtrs& objects = wxGetApp().plater()->model().objects;
+
+ // check if whole model uses just only one extruder
+ if (!objects.empty())
+ {
+ const int extruder = objects[0]->config.has("extruder") ?
+ objects[0]->config.option("extruder")->getInt() : 0;
+
+ auto is_one_extruder_printed_model = [objects, extruder]()
+ {
+ for (ModelObject* object : objects)
+ {
+ if (object->config.has("extruder") &&
+ object->config.option("extruder")->getInt() != extruder)
+ return false;
+
+ if (object->volumes.size() > 1)
+ for (ModelVolume* volume : object->volumes)
+ if (volume->config.has("extruder") &&
+ volume->config.option("extruder")->getInt() != extruder)
+ return false;
+
+ for (const auto& range : object->layer_config_ranges)
+ if (range.second.has("extruder") &&
+ range.second.option("extruder")->getInt() != extruder)
+ return false;
+ }
+ return true;
+ };
+
+ if (is_one_extruder_printed_model())
+ only_extruder = extruder;
+ else
+ one_extruder_printed_model = false;
+ }
+ }
- m_slider->EnableTickManipulation(color_print_enable);
- m_slider->SetManipulationState(wxGetApp().extruders_edited_cnt());
+ m_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder);
}
void Preview::reset_double_slider()
@@ -784,7 +838,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
colors.push_back("#808080"); // gray color for pause print or custom G-code
if (!gcode_preview_data_valid)
- color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z;
+ color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
}
else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) )
{
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index 92ec15b22..ae93e2ff0 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -157,8 +157,9 @@ private:
void create_double_slider();
void check_slider_values(std::vector<Model::CustomGCode> &ticks_from_model,
const std::vector<double> &layers_z);
- void update_double_slider(const std::vector<double>& layers_z, bool keep_z_range = false);
void reset_double_slider();
+ void update_double_slider(const std::vector<double>& layers_z, bool keep_z_range = false);
+ void update_double_slider_mode();
// update DoubleSlider after keyDown in canvas
void update_double_slider_from_canvas(wxKeyEvent& event);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
index 925727e76..6be108c85 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
@@ -48,12 +48,10 @@ std::string GLGizmoMove3D::on_get_name() const
return (_(L("Move")) + " [M]").ToUTF8().data();
}
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
bool GLGizmoMove3D::on_is_activable() const
{
return !m_parent.get_selection().is_empty();
}
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
void GLGizmoMove3D::on_start_dragging()
{
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
index 19958615e..b2367ac68 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
@@ -33,9 +33,7 @@ public:
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
virtual bool on_is_activable() const;
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
virtual void on_start_dragging();
virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
index 5d3b6f365..9a0d75033 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
@@ -449,12 +449,10 @@ std::string GLGizmoRotate3D::on_get_name() const
return (_(L("Rotate")) + " [R]").ToUTF8().data();
}
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
bool GLGizmoRotate3D::on_is_activable() const
{
return !m_parent.get_selection().is_empty();
}
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
void GLGizmoRotate3D::on_start_dragging()
{
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index 930a76e2e..6e7bf1a09 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -104,9 +104,7 @@ protected:
if (id < 3)
m_gizmos[id].disable_grabber(0);
}
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
virtual bool on_is_activable() const;
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
virtual void on_start_dragging();
virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
index fa49b06ce..b4972e6fa 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
@@ -49,12 +49,8 @@ std::string GLGizmoScale3D::on_get_name() const
bool GLGizmoScale3D::on_is_activable() const
{
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
const Selection& selection = m_parent.get_selection();
return !selection.is_empty() && !selection.is_wipe_tower();
-#else
- return !m_parent.get_selection().is_wipe_tower();
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
}
void GLGizmoScale3D::on_start_dragging()
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 8300d7479..ccc6369e4 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -567,7 +567,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
update_data();
wxGetApp().obj_manipul()->set_dirty();
- // Let the platter know that the dragging finished, so a delayed refresh
+ // Let the plater know that the dragging finished, so a delayed refresh
// of the scene with the background processing data should be performed.
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints
@@ -861,13 +861,19 @@ void GLGizmosManager::render_background(float left, float top, float right, floa
void GLGizmosManager::do_render_overlay() const
{
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ std::vector<size_t> selectable_idxs = get_selectable_idxs();
+ if (selectable_idxs.empty())
+ return;
+#else
if (m_gizmos.empty())
return;
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
float cnv_w = (float)m_parent.get_canvas_size().get_width();
float cnv_h = (float)m_parent.get_canvas_size().get_height();
float zoom = (float)m_parent.get_camera().get_zoom();
- float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
+ float inv_zoom = (float)m_parent.get_camera().get_inv_zoom();
float height = get_scaled_total_height();
float width = get_scaled_total_width();
@@ -893,23 +899,42 @@ void GLGizmosManager::do_render_overlay() const
unsigned int icons_texture_id = m_icons_texture.get_id();
int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height();
- float inv_tex_width = (tex_width != 0) ? 1.0f / tex_width : 0.0f;
- float inv_tex_height = (tex_height != 0) ? 1.0f / tex_height : 0.0f;
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1))
+ return;
+
+ float du = (float)(tex_width - 1) / (4.0f * (float)tex_width); // 4 is the number of possible states if the icons
+ float dv = (float)(tex_height - 1) / (float)(m_gizmos.size() * tex_height);
+
+ // tiles in the texture are spaced by 1 pixel
+ float u_offset = 1.0f / (float)tex_width;
+ float v_offset = 1.0f / (float)tex_height;
+#else
if ((icons_texture_id == 0) || (tex_width <= 0) || (tex_height <= 0))
return;
+ float inv_tex_width = (tex_width != 0) ? 1.0f / tex_width : 0.0f;
+ float inv_tex_height = (tex_height != 0) ? 1.0f / tex_height : 0.0f;
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
+
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ for (size_t idx : selectable_idxs)
+#else
for (size_t idx : get_selectable_idxs())
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
{
GLGizmoBase* gizmo = m_gizmos[idx].get();
unsigned int sprite_id = gizmo->get_sprite_id();
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
int icon_idx = (m_current == idx) ? 2 : ((m_hover == idx) ? 1 : (gizmo->is_activable()? 0 : 3));
-#else
- int icon_idx = m_current == idx ? 2 : (m_hover == idx ? 1 : 0);
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
+#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
+ float v_top = v_offset + sprite_id * dv;
+ float u_left = u_offset + icon_idx * du;
+ float v_bottom = v_top + dv - v_offset;
+ float u_right = u_left + du - u_offset;
+#else
float u_icon_size = icons_size * inv_tex_width;
float v_icon_size = icons_size * inv_tex_height;
@@ -917,6 +942,7 @@ void GLGizmosManager::do_render_overlay() const
float u_left = icon_idx * u_icon_size;
float v_bottom = v_top + v_icon_size;
float u_right = u_left + u_icon_size;
+#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
GLTexture::render_sub_texture(icons_texture_id, zoomed_top_x, zoomed_top_x + zoomed_icons_size, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
if (idx == m_current) {
@@ -960,9 +986,7 @@ bool GLGizmosManager::generate_icons_texture() const
states.push_back(std::make_pair(1, false)); // Activable
states.push_back(std::make_pair(0, false)); // Hovered
states.push_back(std::make_pair(0, true)); // Selected
-#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
states.push_back(std::make_pair(2, false)); // Disabled
-#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
unsigned int sprite_size_px = (unsigned int)m_layout.scaled_icons_size();
// // force even size
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 4ae03792b..d1466ef0b 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -125,7 +125,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
_3DScene::remove_all_canvases();
// Slic3r::GUI::deregister_on_request_update_callback();
- // set to null tabs and a platter
+ // set to null tabs and a plater
// to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing
wxGetApp().tabs_list.clear();
wxGetApp().plater_ = nullptr;
@@ -1007,7 +1007,7 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re
}
// Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset.
-// Also update the platter with the new presets.
+// Also update the plater with the new presets.
void MainFrame::load_config(const DynamicPrintConfig& config)
{
PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology();
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index 1a7568092..3d4818eaf 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -125,7 +125,7 @@ public:
void load_config(const DynamicPrintConfig& config);
void select_tab(size_t tab) const;
void select_view(const std::string& direction);
- // Propagate changed configuration from the Tab to the Platter and save changes to the AppConfig
+ // Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
void on_config_changed(DynamicPrintConfig* cfg) const ;
void add_to_recent_projects(const wxString& filename);
diff --git a/src/slic3r/GUI/Mouse3DController.cpp b/src/slic3r/GUI/Mouse3DController.cpp
index 707a1d143..e28336913 100644
--- a/src/slic3r/GUI/Mouse3DController.cpp
+++ b/src/slic3r/GUI/Mouse3DController.cpp
@@ -5,9 +5,7 @@
#include "GUI_App.hpp"
#include "PresetBundle.hpp"
#include "AppConfig.hpp"
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
#include "GLCanvas3D.hpp"
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
#include <wx/glcanvas.h>
@@ -156,7 +154,8 @@ bool Mouse3DController::State::apply(Camera& camera)
{
const Vec3d& translation = m_translation.queue.front();
#if ENABLE_3DCONNEXION_Y_AS_ZOOM
- camera.set_target(camera.get_target() + m_translation_params.scale * (translation(0) * camera.get_dir_right() + translation(2) * camera.get_dir_up()));
+ double zoom_factor = camera.min_zoom() / camera.get_zoom();
+ camera.set_target(camera.get_target() + zoom_factor * m_translation_params.scale * (translation(0) * camera.get_dir_right() + translation(2) * camera.get_dir_up()));
if (translation(1) != 0.0)
camera.update_zoom(m_zoom_params.scale * translation(1) / std::abs(translation(1)));
#else
@@ -168,12 +167,17 @@ bool Mouse3DController::State::apply(Camera& camera)
if (has_rotation())
{
+#if ENABLE_6DOF_CAMERA
+ Vec3d rotation = (m_rotation_params.scale * m_rotation.queue.front()).cast<double>();
+ camera.rotate_local_around_target(Vec3d(Geometry::deg2rad(rotation(0)), Geometry::deg2rad(-rotation(2)), Geometry::deg2rad(-rotation(1))));
+#else
const Vec3f& rotation = m_rotation.queue.front();
float theta = m_rotation_params.scale * rotation(0);
float phi = m_rotation_params.scale * rotation(2);
float sign = camera.inverted_phi ? -1.0f : 1.0f;
camera.phi += sign * phi;
camera.set_theta(camera.get_theta() + theta, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA);
+#endif // ENABLE_6DOF_CAMERA
m_rotation.queue.pop();
ret = true;
}
@@ -200,9 +204,7 @@ Mouse3DController::Mouse3DController()
, m_device_str("")
, m_running(false)
, m_show_settings_dialog(false)
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
, m_settings_dialog_closed_by_user(false)
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
{
m_last_time = std::chrono::high_resolution_clock::now();
}
@@ -247,9 +249,7 @@ bool Mouse3DController::apply(Camera& camera)
disconnect_device();
// hides the settings dialog if the user un-plug the device
m_show_settings_dialog = false;
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
m_settings_dialog_closed_by_user = false;
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
}
// check if the user plugged the device
@@ -259,16 +259,11 @@ bool Mouse3DController::apply(Camera& camera)
return is_device_connected() ? m_state.apply(camera) : false;
}
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
void Mouse3DController::render_settings_dialog(GLCanvas3D& canvas) const
-#else
-void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
{
if (!m_running || !m_show_settings_dialog)
return;
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
// when the user clicks on [X] or [Close] button we need to trigger
// an extra frame to let the dialog disappear
if (m_settings_dialog_closed_by_user)
@@ -280,16 +275,10 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
}
Size cnv_size = canvas.get_canvas_size();
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
ImGuiWrapper& imgui = *wxGetApp().imgui();
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
imgui.set_next_window_pos(0.5f * (float)cnv_size.get_width(), 0.5f * (float)cnv_size.get_height(), ImGuiCond_Always, 0.5f, 0.5f);
-#else
- imgui.set_next_window_pos(0.5f * (float)canvas_width, 0.5f * (float)canvas_height, ImGuiCond_Always, 0.5f, 0.5f);
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
static ImVec2 last_win_size(0.0f, 0.0f);
bool shown = true;
if (imgui.begin(_(L("3Dconnexion settings")), &shown, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse))
@@ -304,9 +293,6 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
last_win_size = win_size;
canvas.request_extra_frame();
}
-#else
- imgui.begin(_(L("3Dconnexion settings")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
const ImVec4& color = ImGui::GetStyleColorVec4(ImGuiCol_Separator);
ImGui::PushStyleColor(ImGuiCol_Text, color);
@@ -321,16 +307,16 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
ImGui::PopStyleColor();
float translation_scale = (float)m_state.get_translation_scale() / State::DefaultTranslationScale;
- if (imgui.slider_float(_(L("Translation")) + "##1", &translation_scale, 0.2f, 5.0f, "%.1f"))
+ if (imgui.slider_float(_(L("Translation")) + "##1", &translation_scale, 0.1f, 10.0f, "%.1f"))
m_state.set_translation_scale(State::DefaultTranslationScale * (double)translation_scale);
float rotation_scale = m_state.get_rotation_scale() / State::DefaultRotationScale;
- if (imgui.slider_float(_(L("Rotation")) + "##1", &rotation_scale, 0.2f, 5.0f, "%.1f"))
+ if (imgui.slider_float(_(L("Rotation")) + "##1", &rotation_scale, 0.1f, 10.0f, "%.1f"))
m_state.set_rotation_scale(State::DefaultRotationScale * rotation_scale);
#if ENABLE_3DCONNEXION_Y_AS_ZOOM
float zoom_scale = m_state.get_zoom_scale() / State::DefaultZoomScale;
- if (imgui.slider_float(_(L("Zoom")), &zoom_scale, 0.2f, 5.0f, "%.1f"))
+ if (imgui.slider_float(_(L("Zoom")), &zoom_scale, 0.1f, 10.0f, "%.1f"))
m_state.set_zoom_scale(State::DefaultZoomScale * zoom_scale);
#endif // ENABLE_3DCONNEXION_Y_AS_ZOOM
@@ -389,7 +375,6 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
Vec3f target = wxGetApp().plater()->get_camera().get_target().cast<float>();
ImGui::InputFloat3("Target", target.data(), "%.3f", ImGuiInputTextFlags_ReadOnly);
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
ImGui::Separator();
if (imgui.button(_(L("Close"))))
@@ -406,7 +391,6 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
canvas.set_as_dirty();
}
}
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
imgui.end();
}
@@ -631,13 +615,16 @@ bool Mouse3DController::connect_device()
if (m_device != nullptr)
{
- std::vector<wchar_t> manufacturer(1024, 0);
- hid_get_manufacturer_string(m_device, manufacturer.data(), 1024);
- m_device_str = boost::nowide::narrow(manufacturer.data());
+ wchar_t buffer[1024];
+ hid_get_manufacturer_string(m_device, buffer, 1024);
+ m_device_str = boost::nowide::narrow(buffer);
+ // #3479 seems to show that sometimes an extra whitespace is added, so we remove it
+ boost::algorithm::trim(m_device_str);
- std::vector<wchar_t> product(1024, 0);
- hid_get_product_string(m_device, product.data(), 1024);
- m_device_str += "/" + boost::nowide::narrow(product.data());
+ hid_get_product_string(m_device, buffer, 1024);
+ m_device_str += "/" + boost::nowide::narrow(buffer);
+ // #3479 seems to show that sometimes an extra whitespace is added, so we remove it
+ boost::algorithm::trim(m_device_str);
BOOST_LOG_TRIVIAL(info) << "Connected 3DConnexion device:";
BOOST_LOG_TRIVIAL(info) << "Manufacturer/product: " << m_device_str;
@@ -647,12 +634,12 @@ bool Mouse3DController::connect_device()
BOOST_LOG_TRIVIAL(info) << "Path................: '" << path << "'";
// get device parameters from the config, if present
- double translation_speed = 1.0;
- float rotation_speed = 1.0;
+ double translation_speed = 4.0;
+ float rotation_speed = 4.0;
double translation_deadzone = State::DefaultTranslationDeadzone;
float rotation_deadzone = State::DefaultRotationDeadzone;
#if ENABLE_3DCONNEXION_Y_AS_ZOOM
- double zoom_speed = 1.0;
+ double zoom_speed = 2.0;
#endif // ENABLE_3DCONNEXION_Y_AS_ZOOM
wxGetApp().app_config->get_mouse_device_translation_speed(m_device_str, translation_speed);
wxGetApp().app_config->get_mouse_device_translation_deadzone(m_device_str, translation_deadzone);
@@ -662,12 +649,12 @@ bool Mouse3DController::connect_device()
wxGetApp().app_config->get_mouse_device_zoom_speed(m_device_str, zoom_speed);
#endif // ENABLE_3DCONNEXION_Y_AS_ZOOM
// clamp to valid values
- m_state.set_translation_scale(State::DefaultTranslationScale * std::clamp(translation_speed, 0.2, 5.0));
+ m_state.set_translation_scale(State::DefaultTranslationScale * std::clamp(translation_speed, 0.1, 10.0));
m_state.set_translation_deadzone(std::clamp(translation_deadzone, 0.0, State::MaxTranslationDeadzone));
- m_state.set_rotation_scale(State::DefaultRotationScale * std::clamp(rotation_speed, 0.2f, 5.0f));
+ m_state.set_rotation_scale(State::DefaultRotationScale * std::clamp(rotation_speed, 0.1f, 10.0f));
m_state.set_rotation_deadzone(std::clamp(rotation_deadzone, 0.0f, State::MaxRotationDeadzone));
#if ENABLE_3DCONNEXION_Y_AS_ZOOM
- m_state.set_zoom_scale(State::DefaultZoomScale * std::clamp(zoom_speed, 0.2, 5.0));
+ m_state.set_zoom_scale(State::DefaultZoomScale * std::clamp(zoom_speed, 0.1, 10.0));
#endif // ENABLE_3DCONNEXION_Y_AS_ZOOM
}
#if ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
@@ -874,9 +861,15 @@ bool Mouse3DController::handle_packet_translation(const DataPacket& packet)
bool Mouse3DController::handle_packet_rotation(const DataPacket& packet, unsigned int first_byte)
{
double deadzone = (double)m_state.get_rotation_deadzone();
+#if ENABLE_6DOF_CAMERA
+ Vec3f rotation((float)convert_input(packet[first_byte + 0], packet[first_byte + 1], deadzone),
+ (float)convert_input(packet[first_byte + 2], packet[first_byte + 3], deadzone),
+ (float)convert_input(packet[first_byte + 4], packet[first_byte + 5], deadzone));
+#else
Vec3f rotation(-(float)convert_input(packet[first_byte + 0], packet[first_byte + 1], deadzone),
(float)convert_input(packet[first_byte + 2], packet[first_byte + 3], deadzone),
-(float)convert_input(packet[first_byte + 4], packet[first_byte + 5], deadzone));
+#endif // ENABLE_6DOF_CAMERA
if (!rotation.isApprox(Vec3f::Zero()))
{
diff --git a/src/slic3r/GUI/Mouse3DController.hpp b/src/slic3r/GUI/Mouse3DController.hpp
index 3598d7df7..f3826f8e2 100644
--- a/src/slic3r/GUI/Mouse3DController.hpp
+++ b/src/slic3r/GUI/Mouse3DController.hpp
@@ -18,9 +18,7 @@ namespace Slic3r {
namespace GUI {
struct Camera;
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
class GLCanvas3D;
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
class Mouse3DController
{
@@ -68,7 +66,7 @@ class Mouse3DController
CustomParameters<double> m_translation_params;
CustomParameters<float> m_rotation_params;
#if ENABLE_3DCONNEXION_Y_AS_ZOOM
- CustomParameters<float> m_zoom_params;
+ CustomParameters<double> m_zoom_params;
#endif // ENABLE_3DCONNEXION_Y_AS_ZOOM
// When the 3Dconnexion driver is running the system gets, by default, mouse wheel events when rotations around the X axis are detected.
@@ -143,13 +141,9 @@ class Mouse3DController
hid_device* m_device;
std::string m_device_str;
bool m_running;
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
mutable bool m_show_settings_dialog;
// set to true when ther user closes the dialog by clicking on [X] or [Close] buttons
mutable bool m_settings_dialog_closed_by_user;
-#else
- bool m_show_settings_dialog;
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
std::chrono::time_point<std::chrono::high_resolution_clock> m_last_time;
public:
@@ -167,11 +161,7 @@ public:
bool is_settings_dialog_shown() const { return m_show_settings_dialog; }
void show_settings_dialog(bool show) { m_show_settings_dialog = show && is_running(); }
-#if ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
void render_settings_dialog(GLCanvas3D& canvas) const;
-#else
- void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const;
-#endif // ENABLE_3DCONNEXION_DEVICES_CLOSE_SETTING_DIALOG
private:
bool connect_device();
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index f1a9a10f2..fb28f2a5f 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -326,7 +326,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 *
cfg_new.set_key_value("extruder_colour", colors);
wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
- wxGetApp().preset_bundle->update_platter_filament_ui(extruder_idx, this);
+ wxGetApp().preset_bundle->update_plater_filament_ui(extruder_idx, this);
wxGetApp().plater()->on_config_change(cfg_new);
}
});
@@ -952,18 +952,18 @@ void Sidebar::update_all_preset_comboboxes()
// Update the print choosers to only contain the compatible presets, update the dirty flags.
if (print_tech == ptFFF)
- preset_bundle.prints.update_platter_ui(p->combo_print);
+ preset_bundle.prints.update_plater_ui(p->combo_print);
else {
- preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print);
- preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material);
+ preset_bundle.sla_prints.update_plater_ui(p->combo_sla_print);
+ preset_bundle.sla_materials.update_plater_ui(p->combo_sla_material);
}
// Update the printer choosers, update the dirty flags.
- preset_bundle.printers.update_platter_ui(p->combo_printer);
+ preset_bundle.printers.update_plater_ui(p->combo_printer);
// Update the filament choosers to only contain the compatible presets, update the color preview,
// update the dirty flags.
if (print_tech == ptFFF) {
for (size_t i = 0; i < p->combos_filament.size(); ++i)
- preset_bundle.update_platter_filament_ui(i, p->combos_filament[i]);
+ preset_bundle.update_plater_filament_ui(i, p->combos_filament[i]);
}
}
@@ -986,22 +986,22 @@ void Sidebar::update_presets(Preset::Type preset_type)
}
for (size_t i = 0; i < filament_cnt; i++) {
- preset_bundle.update_platter_filament_ui(i, p->combos_filament[i]);
+ preset_bundle.update_plater_filament_ui(i, p->combos_filament[i]);
}
break;
}
case Preset::TYPE_PRINT:
- preset_bundle.prints.update_platter_ui(p->combo_print);
+ preset_bundle.prints.update_plater_ui(p->combo_print);
break;
case Preset::TYPE_SLA_PRINT:
- preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print);
+ preset_bundle.sla_prints.update_plater_ui(p->combo_sla_print);
break;
case Preset::TYPE_SLA_MATERIAL:
- preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material);
+ preset_bundle.sla_materials.update_plater_ui(p->combo_sla_material);
break;
case Preset::TYPE_PRINTER:
@@ -1195,9 +1195,9 @@ void Sidebar::update_sliced_info_sizer()
{
double material_cost = cfg->option("bottle_cost")->getFloat() /
cfg->option("bottle_volume")->getFloat();
- str_total_cost = wxString::Format("%.2f", material_cost*(ps.objects_used_material + ps.support_used_material) / 1000);
+ str_total_cost = wxString::Format("%.3f", material_cost*(ps.objects_used_material + ps.support_used_material) / 1000);
}
- p->sliced_info->SetTextAndShow(siCost, str_total_cost);
+ p->sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost");
wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : get_time_dhms(float(ps.estimated_print_time));
p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _(L("Estimated printing time")) + " :");
@@ -1774,9 +1774,7 @@ struct Plater::priv
void set_current_canvas_as_dirty();
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool init_view_toolbar();
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
void reset_all_gizmos();
void update_ui_from_settings();
@@ -1924,9 +1922,6 @@ private:
bool complit_init_object_menu();
bool complit_init_sla_object_menu();
bool complit_init_part_menu();
-#if !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
- void init_view_toolbar();
-#endif // !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool can_split() const;
bool layers_height_allowed() const;
@@ -1995,7 +1990,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
background_process.set_finished_event(EVT_PROCESS_COMPLETED);
// Default printer technology for default config.
background_process.select_technology(this->printer_technology);
- // Register progress callback from the Print class to the Platter.
+ // Register progress callback from the Print class to the Plater.
auto statuscb = [this](const Slic3r::PrintBase::SlicingStatus &status) {
wxQueueEvent(this->q, new Slic3r::SlicingStatusEvent(EVT_SLICING_UPDATE, 0, status));
@@ -2060,11 +2055,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); });
view3D_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); });
view3D_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); });
-#if ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); });
view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event<float>& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); });
view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); });
-#endif // ENABLE_ADAPTIVE_LAYER_HEIGHT_PROFILE
// 3DScene/Toolbar:
view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
@@ -2078,9 +2071,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this);
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this);
view3D_canvas->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this);
-#if !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
- view3D_canvas->Bind(EVT_GLCANVAS_INIT, [this](SimpleEvent&) { init_view_toolbar(); });
-#endif // !ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [this](SimpleEvent&)
{
set_bed_shape(config->option<ConfigOptionPoints>("bed_shape")->values,
@@ -2276,7 +2266,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (object->volumes.size() > 1)
{
Slic3r::GUI::show_info(nullptr,
- _(L("You can't load SLA project if there is at least one multi-part object on the bed")) + "\n\n" +
+ _(L("You cannot load SLA project with a multi-part object on the bed")) + "\n\n" +
_(L("Please check your object list before preset changing.")),
_(L("Attention!")));
return obj_idxs;
@@ -2709,7 +2699,7 @@ void Plater::priv::reset()
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
this->sidebar->show_sliced_info_sizer(false);
- model.custom_gcode_per_print_z.clear();
+ model.custom_gcode_per_print_z.gcodes.clear();
}
void Plater::priv::mirror(Axis axis)
@@ -3008,7 +2998,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
this->update_print_volume_state();
// Apply new config to the possibly running background task.
bool was_running = this->background_process.running();
- this->background_process.set_force_update_print_regions(force_validation);
Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config());
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
@@ -3228,12 +3217,9 @@ void Plater::priv::reload_from_disk()
// collects paths of files to load
std::vector<fs::path> input_paths;
-#if ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
std::vector<fs::path> missing_input_paths;
-#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
for (const SelectedVolume& v : selected_volumes)
{
-#if ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
const ModelObject* object = model.objects[v.object_idx];
const ModelVolume* volume = object->volumes[v.volume_idx];
@@ -3244,14 +3230,8 @@ void Plater::priv::reload_from_disk()
else
missing_input_paths.push_back(volume->source.input_file);
}
-#else
- const ModelVolume* volume = model.objects[v.object_idx]->volumes[v.volume_idx];
- if (!volume->source.input_file.empty() && boost::filesystem::exists(volume->source.input_file))
- input_paths.push_back(volume->source.input_file);
-#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
}
-#if ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
std::sort(missing_input_paths.begin(), missing_input_paths.end());
missing_input_paths.erase(std::unique(missing_input_paths.begin(), missing_input_paths.end()), missing_input_paths.end());
@@ -3301,7 +3281,6 @@ void Plater::priv::reload_from_disk()
return;
}
}
-#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
std::sort(input_paths.begin(), input_paths.end());
input_paths.erase(std::unique(input_paths.begin(), input_paths.end()), input_paths.end());
@@ -3347,27 +3326,17 @@ void Plater::priv::reload_from_disk()
new_volume->config.apply(old_volume->config);
new_volume->set_type(old_volume->type());
new_volume->set_material_id(old_volume->material_id());
-#if ENABLE_KEEP_LOADED_VOLUME_TRANSFORM_AS_STAND_ALONE
new_volume->set_transformation(old_volume->get_transformation() * old_volume->source.transform);
-#else
- new_volume->set_transformation(old_volume->get_transformation());
-#endif // ENABLE_KEEP_LOADED_VOLUME_TRANSFORM_AS_STAND_ALONE
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
new_volume->source.input_file = path;
std::swap(old_model_object->volumes[old_v.volume_idx], old_model_object->volumes.back());
old_model_object->delete_volume(old_model_object->volumes.size() - 1);
-#if ENABLE_KEEP_LOADED_VOLUME_TRANSFORM_AS_STAND_ALONE
old_model_object->ensure_on_bed();
-#endif // ENABLE_KEEP_LOADED_VOLUME_TRANSFORM_AS_STAND_ALONE
}
}
}
}
-#if !ENABLE_KEEP_LOADED_VOLUME_TRANSFORM_AS_STAND_ALONE
- model.adjust_min_z();
-#endif // !ENABLE_KEEP_LOADED_VOLUME_TRANSFORM_AS_STAND_ALONE
-
// update 3D scene
update();
@@ -3490,8 +3459,8 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
// TODO: ?
if (preset_type == Preset::TYPE_FILAMENT && sidebar->is_multifilament()) {
- // Only update the platter UI for the 2nd and other filaments.
- wxGetApp().preset_bundle->update_platter_filament_ui(idx, combo);
+ // Only update the plater UI for the 2nd and other filaments.
+ wxGetApp().preset_bundle->update_plater_filament_ui(idx, combo);
}
else {
wxWindowUpdateLocker noUpdates(sidebar->presets_panel());
@@ -3981,17 +3950,11 @@ void Plater::priv::set_current_canvas_as_dirty()
preview->set_as_dirty();
}
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool Plater::priv::init_view_toolbar()
-#else
-void Plater::priv::init_view_toolbar()
-#endif //!ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
{
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
if (view_toolbar.get_items_count() > 0)
// already initialized
return true;
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
BackgroundTexture::Metadata background_data;
background_data.filename = "toolbar_background.png";
@@ -4001,11 +3964,7 @@ void Plater::priv::init_view_toolbar()
background_data.bottom = 16;
if (!view_toolbar.init(background_data))
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
return false;
-#else
- return;
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
view_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left);
view_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Bottom);
@@ -4020,11 +3979,7 @@ void Plater::priv::init_view_toolbar()
item.sprite_id = 0;
item.left.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); };
if (!view_toolbar.add_item(item))
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
return false;
-#else
- return;
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
item.name = "Preview";
item.icon_filename = "preview.svg";
@@ -4032,18 +3987,12 @@ void Plater::priv::init_view_toolbar()
item.sprite_id = 1;
item.left.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW)); };
if (!view_toolbar.add_item(item))
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
return false;
-#else
- return;
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
view_toolbar.select_item("3D");
view_toolbar.set_enabled(true);
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
return true;
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
}
bool Plater::priv::can_set_instance_to_object() const
@@ -4108,11 +4057,7 @@ bool Plater::priv::can_reload_from_disk() const
for (const SelectedVolume& v : selected_volumes)
{
const ModelVolume* volume = model.objects[v.object_idx]->volumes[v.volume_idx];
-#if ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
if (!volume->source.input_file.empty())
-#else
- if (!volume->source.input_file.empty() && boost::filesystem::exists(volume->source.input_file))
-#endif // ENABLE_RELOAD_FROM_DISK_MISSING_SELECTION
paths.push_back(volume->source.input_file);
}
std::sort(paths.begin(), paths.end());
@@ -4895,7 +4840,12 @@ void Plater::export_amf()
wxBusyCursor wait;
bool export_config = true;
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
+ if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames)) {
+#else
if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) {
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
// Success
p->statusbar()->set_status_text(wxString::Format(_(L("AMF file exported to %s")), path));
} else {
@@ -4924,6 +4874,16 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
const std::string path_u8 = into_u8(path);
wxBusyCursor wait;
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
+#if ENABLE_THUMBNAIL_GENERATOR
+ ThumbnailData thumbnail_data;
+ p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
+ if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data)) {
+#else
+ if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames)) {
+#endif // ENABLE_THUMBNAIL_GENERATOR
+#else
#if ENABLE_THUMBNAIL_GENERATOR
ThumbnailData thumbnail_data;
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
@@ -4931,6 +4891,7 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
#else
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) {
#endif // ENABLE_THUMBNAIL_GENERATOR
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
// Success
p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path));
p->set_project_filename(path);
@@ -5158,7 +5119,7 @@ void Plater::on_extruders_change(size_t num_extruders)
choices.push_back(choice);
// initialize selection
- wxGetApp().preset_bundle->update_platter_filament_ui(i, choice);
+ wxGetApp().preset_bundle->update_plater_filament_ui(i, choice);
++i;
}
@@ -5325,9 +5286,9 @@ std::vector<std::string> Plater::get_extruder_colors_from_plater_config() const
std::vector<std::string> Plater::get_colors_for_color_print() const
{
std::vector<std::string> colors = get_extruder_colors_from_plater_config();
- colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.size());
+ colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.gcodes.size());
- for (const Model::CustomGCode& code : p->model.custom_gcode_per_print_z)
+ for (const Model::CustomGCode& code : p->model.custom_gcode_per_print_z.gcodes)
if (code.gcode == ColorChangeCode)
colors.emplace_back(code.color);
@@ -5491,12 +5452,10 @@ void Plater::msw_rescale()
GetParent()->Layout();
}
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool Plater::init_view_toolbar()
{
return p->init_view_toolbar();
}
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
const Camera& Plater::get_camera() const
{
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 774875cd7..591f49378 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -267,9 +267,7 @@ public:
void msw_rescale();
-#if ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
bool init_view_toolbar();
-#endif // ENABLE_VIEW_TOOLBAR_BACKGROUND_FIX
const Camera& get_camera() const;
const Mouse3DController& get_mouse3d_controller() const;
diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp
index 827d1f4e0..4fd63fe0e 100644
--- a/src/slic3r/GUI/Preferences.cpp
+++ b/src/slic3r/GUI/Preferences.cpp
@@ -19,16 +19,11 @@ PreferencesDialog::PreferencesDialog(wxWindow* parent) :
void PreferencesDialog::build()
{
auto app_config = get_app_config();
- m_optgroup = std::make_shared<ConfigOptionsGroup>(this, _(L("General")));
- m_optgroup->label_width = 40;
- m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
+ m_optgroup_general = std::make_shared<ConfigOptionsGroup>(this, _(L("General")));
+ m_optgroup_general->label_width = 40;
+ m_optgroup_general->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0";
-
- if (opt_key == "use_custom_toolbar_size") {
- m_icon_size_sizer->ShowItems(boost::any_cast<bool>(value));
- this->layout();
- }
- };
+ };
// TODO
// $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
@@ -47,7 +42,7 @@ void PreferencesDialog::build()
"instead of the one containing the input files.");
def.set_default_value(new ConfigOptionBool{ app_config->has("remember_output_path") ? app_config->get("remember_output_path") == "1" : true });
Option option(def, "remember_output_path");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
def.label = L("Auto-center parts");
def.type = coBool;
@@ -55,7 +50,7 @@ void PreferencesDialog::build()
"around the print bed center.");
def.set_default_value(new ConfigOptionBool{ app_config->get("autocenter") == "1" });
option = Option (def,"autocenter");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
def.label = L("Background processing");
def.type = coBool;
@@ -63,7 +58,7 @@ void PreferencesDialog::build()
"as they\'re loaded in order to save time when exporting G-code.");
def.set_default_value(new ConfigOptionBool{ app_config->get("background_processing") == "1" });
option = Option (def,"background_processing");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
// Please keep in sync with ConfigWizard
def.label = L("Check for application updates");
@@ -71,7 +66,17 @@ void PreferencesDialog::build()
def.tooltip = L("If enabled, PrusaSlicer will check for the new versions of itself online. When a new version becomes available a notification is displayed at the next application startup (never during program usage). This is only a notification mechanisms, no automatic installation is done.");
def.set_default_value(new ConfigOptionBool(app_config->get("version_check") == "1"));
option = Option (def, "version_check");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
+
+#if ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
+ // Please keep in sync with ConfigWizard
+ def.label = L("Export sources full pathnames to 3mf and amf");
+ def.type = coBool;
+ def.tooltip = L("If enabled, allows the Reload from disk command to automatically find and load the files when invoked.");
+ def.set_default_value(new ConfigOptionBool(app_config->get("export_sources_full_pathnames") == "1"));
+ option = Option(def, "export_sources_full_pathnames");
+ m_optgroup_general->append_single_option_line(option);
+#endif // ENABLE_CONFIGURABLE_PATHS_EXPORT_TO_3MF_AND_AMF
// Please keep in sync with ConfigWizard
def.label = L("Update built-in Presets automatically");
@@ -79,7 +84,7 @@ void PreferencesDialog::build()
def.tooltip = L("If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded into a separate temporary location. When a new preset version becomes available it is offered at application startup.");
def.set_default_value(new ConfigOptionBool(app_config->get("preset_update") == "1"));
option = Option (def, "preset_update");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
def.label = L("Suppress \" - default - \" presets");
def.type = coBool;
@@ -87,7 +92,7 @@ void PreferencesDialog::build()
"selections once there are any other valid presets available.");
def.set_default_value(new ConfigOptionBool{ app_config->get("no_defaults") == "1" });
option = Option (def,"no_defaults");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
def.label = L("Show incompatible print and filament presets");
def.type = coBool;
@@ -95,7 +100,7 @@ void PreferencesDialog::build()
"even if they are marked as incompatible with the active printer");
def.set_default_value(new ConfigOptionBool{ app_config->get("show_incompatible_presets") == "1" });
option = Option (def,"show_incompatible_presets");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
#if __APPLE__
def.label = L("Use Retina resolution for the 3D scene");
@@ -104,28 +109,55 @@ void PreferencesDialog::build()
"If you are experiencing 3D performance problems, disabling this option may help.");
def.set_default_value(new ConfigOptionBool{ app_config->get("use_retina_opengl") == "1" });
option = Option (def, "use_retina_opengl");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_general->append_single_option_line(option);
#endif
- def.label = L("Use perspective camera");
- def.type = coBool;
- def.tooltip = L("If enabled, use perspective camera. If not enabled, use orthographic camera.");
- def.set_default_value(new ConfigOptionBool{ app_config->get("use_perspective_camera") == "1" });
- option = Option(def, "use_perspective_camera");
- m_optgroup->append_single_option_line(option);
+ m_optgroup_camera = std::make_shared<ConfigOptionsGroup>(this, _(L("Camera")));
+ m_optgroup_camera->label_width = 40;
+ m_optgroup_camera->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
+ m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0";
+ };
+
+ def.label = L("Use perspective camera");
+ def.type = coBool;
+ def.tooltip = L("If enabled, use perspective camera. If not enabled, use orthographic camera.");
+ def.set_default_value(new ConfigOptionBool{ app_config->get("use_perspective_camera") == "1" });
+ option = Option(def, "use_perspective_camera");
+ m_optgroup_camera->append_single_option_line(option);
+
+#if ENABLE_6DOF_CAMERA
+ def.label = L("Use free camera");
+ def.type = coBool;
+ def.tooltip = L("If enabled, use free camera. If not enabled, use constrained camera.");
+ def.set_default_value(new ConfigOptionBool(app_config->get("use_free_camera") == "1"));
+ option = Option(def, "use_free_camera");
+ m_optgroup_camera->append_single_option_line(option);
+#endif // ENABLE_6DOF_CAMERA
+
+ m_optgroup_gui = std::make_shared<ConfigOptionsGroup>(this, _(L("GUI")));
+ m_optgroup_gui->label_width = 40;
+ m_optgroup_gui->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
+ m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0";
+ if (opt_key == "use_custom_toolbar_size") {
+ m_icon_size_sizer->ShowItems(boost::any_cast<bool>(value));
+ this->layout();
+ }
+ };
def.label = L("Use custom size for toolbar icons");
def.type = coBool;
def.tooltip = L("If enabled, you can change size of toolbar icons manually.");
def.set_default_value(new ConfigOptionBool{ app_config->get("use_custom_toolbar_size") == "1" });
- option = Option (def,"use_custom_toolbar_size");
- m_optgroup->append_single_option_line(option);
+ option = Option(def, "use_custom_toolbar_size");
+ m_optgroup_gui->append_single_option_line(option);
- create_icon_size_slider();
- m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1");
+ create_icon_size_slider();
+ m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1");
auto sizer = new wxBoxSizer(wxVERTICAL);
- sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
+ sizer->Add(m_optgroup_general->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
+ sizer->Add(m_optgroup_camera->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
+ sizer->Add(m_optgroup_gui->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
SetFont(wxGetApp().normal_font());
@@ -157,7 +189,9 @@ void PreferencesDialog::accept()
void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect)
{
- m_optgroup->msw_rescale();
+ m_optgroup_general->msw_rescale();
+ m_optgroup_camera->msw_rescale();
+ m_optgroup_gui->msw_rescale();
msw_buttons_rescale(this, em_unit(), { wxID_OK, wxID_CANCEL });
@@ -182,7 +216,7 @@ void PreferencesDialog::create_icon_size_slider()
m_icon_size_sizer = new wxBoxSizer(wxHORIZONTAL);
- wxWindow* parent = m_optgroup->ctrl_parent();
+ wxWindow* parent = m_optgroup_gui->ctrl_parent();
if (isOSX)
// For correct rendering of the slider and value label under OSX
@@ -230,8 +264,9 @@ void PreferencesDialog::create_icon_size_slider()
win->SetBackgroundStyle(wxBG_STYLE_PAINT);
}
- m_optgroup->sizer->Add(m_icon_size_sizer, 0, wxEXPAND | wxALL, em);
+ m_optgroup_gui->sizer->Add(m_icon_size_sizer, 0, wxEXPAND | wxALL, em);
}
+
} // GUI
} // Slic3r \ No newline at end of file
diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp
index 9fffe6a7f..35bf2b8c5 100644
--- a/src/slic3r/GUI/Preferences.hpp
+++ b/src/slic3r/GUI/Preferences.hpp
@@ -15,8 +15,10 @@ class ConfigOptionsGroup;
class PreferencesDialog : public DPIDialog
{
std::map<std::string, std::string> m_values;
- std::shared_ptr<ConfigOptionsGroup> m_optgroup;
- wxSizer* m_icon_size_sizer;
+ std::shared_ptr<ConfigOptionsGroup> m_optgroup_general;
+ std::shared_ptr<ConfigOptionsGroup> m_optgroup_camera;
+ std::shared_ptr<ConfigOptionsGroup> m_optgroup_gui;
+ wxSizer* m_icon_size_sizer;
bool isOSX {false};
public:
PreferencesDialog(wxWindow* parent);
diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp
index 9f64c67ac..b0e1f066b 100644
--- a/src/slic3r/GUI/Preset.cpp
+++ b/src/slic3r/GUI/Preset.cpp
@@ -184,6 +184,16 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
} else {
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Malformed variants field: `%2%`") % id % variants_field;
}
+ auto default_materials_field = section.second.get<std::string>("default_materials", "");
+ if (default_materials_field.empty())
+ default_materials_field = section.second.get<std::string>("default_filaments", "");
+ if (Slic3r::unescape_strings_cstyle(default_materials_field, model.default_materials)) {
+ Slic3r::sort_remove_duplicates(model.default_materials);
+ } else {
+ BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Malformed default_materials field: `%2%`") % id % default_materials_field;
+ }
+ model.bed_model = section.second.get<std::string>("bed_model", "");
+ model.bed_texture = section.second.get<std::string>("bed_texture", "");
if (! model.id.empty() && ! model.variants.empty())
res.models.push_back(std::move(model));
}
@@ -1020,7 +1030,7 @@ size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfil
// Update the wxChoice UI component from this list of presets.
// Hide the
-void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui)
+void PresetCollection::update_plater_ui(GUI::PresetComboBox *ui)
{
if (ui == nullptr)
return;
@@ -1504,4 +1514,20 @@ const Preset* PrinterPresetCollection::find_by_model_id(const std::string &model
return it != cend() ? &*it : nullptr;
}
+namespace PresetUtils {
+ const VendorProfile::PrinterModel* system_printer_model(const Preset &preset)
+ {
+ const VendorProfile::PrinterModel *out = nullptr;
+ if (preset.vendor != nullptr) {
+ auto *printer_model = preset.config.opt<ConfigOptionString>("printer_model");
+ if (printer_model != nullptr && ! printer_model->value.empty()) {
+ auto it = std::find_if(preset.vendor->models.begin(), preset.vendor->models.end(), [printer_model](const VendorProfile::PrinterModel &pm) { return pm.id == printer_model->value; });
+ if (it != preset.vendor->models.end())
+ out = &(*it);
+ }
+ }
+ return out;
+ }
+} // namespace PresetUtils
+
} // namespace Slic3r
diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp
index 547814559..742d3e01d 100644
--- a/src/slic3r/GUI/Preset.hpp
+++ b/src/slic3r/GUI/Preset.hpp
@@ -61,6 +61,10 @@ public:
PrinterTechnology technology;
std::string family;
std::vector<PrinterVariant> variants;
+ std::vector<std::string> default_materials;
+ // Vendor & Printer Model specific print bed model & texture.
+ std::string bed_model;
+ std::string bed_texture;
PrinterVariant* variant(const std::string &name) {
for (auto &v : this->variants)
@@ -380,7 +384,8 @@ public:
size_t n = this->m_presets.size();
size_t i_compatible = n;
for (; i < n; ++ i)
- if (m_presets[i].is_compatible) {
+ // Since we use the filament selection from Wizard, it's needed to control the preset visibility too
+ if (m_presets[i].is_compatible && m_presets[i].is_visible) {
if (prefered_condition(m_presets[i].name))
return i;
if (i_compatible == n)
@@ -437,7 +442,7 @@ public:
// Update the choice UI from the list of presets.
// Only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well.
- void update_platter_ui(GUI::PresetComboBox *ui);
+ void update_plater_ui(GUI::PresetComboBox *ui);
// Update a dirty floag of the current preset, update the labels of the UI component accordingly.
// Return true if the dirty flag changed.
@@ -526,7 +531,7 @@ private:
// Is the "- default -" preset suppressed?
bool m_default_suppressed = true;
size_t m_num_default_presets = 0;
- // Compatible & incompatible marks, to be placed at the wxBitmapComboBox items of a Platter.
+ // Compatible & incompatible marks, to be placed at the wxBitmapComboBox items of a Plater.
// These bitmaps are not owned by PresetCollection, but by a PresetBundle.
const wxBitmap *m_bitmap_compatible = nullptr;
const wxBitmap *m_bitmap_incompatible = nullptr;
@@ -559,6 +564,11 @@ public:
const Preset* find_by_model_id(const std::string &model_id) const;
};
+namespace PresetUtils {
+ // PrinterModel of a system profile, from which this preset is derived, or null if it is not derived from a system profile.
+ const VendorProfile::PrinterModel* system_printer_model(const Preset &preset);
+} // namespace PresetUtils
+
} // namespace Slic3r
#endif /* slic3r_Preset_hpp_ */
diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp
index 219d7b89d..bb08ce2d0 100644
--- a/src/slic3r/GUI/PresetBundle.cpp
+++ b/src/slic3r/GUI/PresetBundle.cpp
@@ -877,7 +877,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// 4) Load the project config values (the per extruder wipe matrix etc).
this->project_config.apply_only(config, s_project_options);
- update_custom_gcode_per_print_z_from_config(GUI::wxGetApp().plater()->model().custom_gcode_per_print_z, &this->project_config);
+ update_custom_gcode_per_print_z_from_config(GUI::wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes, &this->project_config);
break;
}
@@ -1572,7 +1572,7 @@ void PresetBundle::load_default_preset_bitmaps(wxWindow *window)
this->load_compatible_bitmaps(window);
}
-void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
+void PresetBundle::update_plater_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
{
if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA ||
this->filament_presets.size() <= idx_extruder )
diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp
index 5205042c5..ff27d0023 100644
--- a/src/slic3r/GUI/PresetBundle.hpp
+++ b/src/slic3r/GUI/PresetBundle.hpp
@@ -109,8 +109,8 @@ public:
// Export a config bundle file containing all the presets and the names of the active presets.
void export_configbundle(const std::string &path, bool export_system_settings = false);
- // Update a filament selection combo box on the platter for an idx_extruder.
- void update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui);
+ // Update a filament selection combo box on the plater for an idx_extruder.
+ void update_plater_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui);
// Enable / disable the "- default -" preset.
void set_default_suppressed(bool default_suppressed);
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index 13be48289..224f5007d 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -2004,7 +2004,11 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
const float max_y = box.max(1) + Margin;
// view dependend order of rendering to keep correct transparency
+#if ENABLE_6DOF_CAMERA
+ bool camera_on_top = wxGetApp().plater()->get_camera().is_looking_downward();
+#else
bool camera_on_top = wxGetApp().plater()->get_camera().get_theta() <= 90.0f;
+#endif // ENABLE_6DOF_CAMERA
float z1 = camera_on_top ? min_z : max_z;
float z2 = camera_on_top ? max_z : min_z;
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index c8239e0b7..eef304e58 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -905,7 +905,7 @@ void Tab::update_wiping_button_visibility() {
}
-// Call a callback to update the selection of presets on the platter:
+// Call a callback to update the selection of presets on the plater:
// To update the content of the selection boxes,
// to update the filament colors of the selection boxes,
// to update the "dirty" flags of the selection boxes,
@@ -2825,7 +2825,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current)
if (canceled) {
update_tab_ui();
// Trigger the on_presets_changed event so that we also restore the previous value in the plater selector,
- // if this action was initiated from the platter.
+ // if this action was initiated from the plater.
on_presets_changed();
} else {
if (current_dirty)
@@ -3053,7 +3053,7 @@ void Tab::save_preset(std::string name /*= ""*/)
m_preset_bundle->update_compatible(false);
// Add the new item into the UI component, remove dirty flags and activate the saved item.
update_tab_ui();
- // Update the selection boxes at the platter.
+ // Update the selection boxes at the plater.
on_presets_changed();
// If current profile is saved, "delete preset" button have to be enabled
m_btn_delete_preset->Enable(true);
@@ -3444,27 +3444,25 @@ void TabSLAMaterial::build()
DynamicPrintConfig new_conf = *m_config;
if (opt_key == "bottle_volume") {
- double new_bottle_weight = boost::any_cast<double>(value)/(new_conf.option("material_density")->getFloat() * 1000);
+ double new_bottle_weight = boost::any_cast<double>(value)*(new_conf.option("material_density")->getFloat() / 1000);
new_conf.set_key_value("bottle_weight", new ConfigOptionFloat(new_bottle_weight));
}
if (opt_key == "bottle_weight") {
- double new_bottle_volume = boost::any_cast<double>(value)*(new_conf.option("material_density")->getFloat() * 1000);
+ double new_bottle_volume = boost::any_cast<double>(value)/new_conf.option("material_density")->getFloat() * 1000;
new_conf.set_key_value("bottle_volume", new ConfigOptionFloat(new_bottle_volume));
}
if (opt_key == "material_density") {
- double new_bottle_volume = new_conf.option("bottle_weight")->getFloat() * boost::any_cast<double>(value) * 1000;
+ double new_bottle_volume = new_conf.option("bottle_weight")->getFloat() / boost::any_cast<double>(value) * 1000;
new_conf.set_key_value("bottle_volume", new ConfigOptionFloat(new_bottle_volume));
}
load_config(new_conf);
update_dirty();
- on_value_change(opt_key, value);
- if (opt_key == "bottle_volume" || opt_key == "bottle_cost") {
- wxGetApp().sidebar().update_sliced_info_sizer();
- wxGetApp().sidebar().Layout();
- }
+ // Change of any from those options influences for an update of "Sliced Info"
+ wxGetApp().sidebar().update_sliced_info_sizer();
+ wxGetApp().sidebar().Layout();
};
optgroup = page->new_optgroup(_(L("Layers")));
diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp
index ee6937652..4345f196c 100644
--- a/src/slic3r/GUI/Tab.hpp
+++ b/src/slic3r/GUI/Tab.hpp
@@ -231,7 +231,7 @@ public:
// Counter for the updating (because of an update() function can have a recursive behavior):
// 1. increase value from the very beginning of an update() function
// 2. decrease value at the end of an update() function
- // 3. propagate changed configuration to the Platter when (m_update_cnt == 0) only
+ // 3. propagate changed configuration to the Plater when (m_update_cnt == 0) only
int m_update_cnt = 0;
public:
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index 7b36207f5..8f43f6c30 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -5,6 +5,7 @@
#include "libslic3r/Utils.hpp"
#include "libslic3r/Model.hpp"
+#include "libslic3r/Print.hpp"
#include <wx/sizer.h>
#include <wx/bmpcbox.h>
@@ -13,9 +14,7 @@
#include <wx/numformatter.h>
#include <wx/colordlg.h>
-#include <boost/filesystem.hpp>
#include <boost/algorithm/string/replace.hpp>
-#include <boost/nowide/cstdio.hpp>
#include "BitmapCache.hpp"
#include "GUI.hpp"
@@ -426,28 +425,6 @@ static float get_svg_scale_factor(wxWindow *win)
#endif
}
-// in the Dark mode of any platform, we should draw icons in respect to OS background
-static std::string icon_name_respected_to_mode(const std::string& bmp_name_in)
-{
-#ifdef __WXMSW__
- const std::string folder = "white\\";
-#else
- const std::string folder = "white/";
-#endif
- std::string bmp_name;
- if (Slic3r::GUI::wxGetApp().dark_mode()) {
- bmp_name = folder + bmp_name_in;
- boost::replace_last(bmp_name, ".png", "");
- if (! boost::filesystem::exists(Slic3r::var(bmp_name + ".svg")))
- bmp_name.clear();
- }
- if (bmp_name.empty()) {
- bmp_name = bmp_name_in;
- boost::replace_last(bmp_name, ".png", "");
- }
- return bmp_name;
-}
-
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in,
const int px_cnt/* = 16*/, const bool is_horizontal /* = false*/, const bool grayscale/* = false*/)
@@ -474,13 +451,13 @@ wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in,
scale_base = (unsigned int)(em_unit(win) * px_cnt * 0.1f + 0.5f);
-// std::string bmp_name = bmp_name_in;
-// boost::replace_last(bmp_name, ".png", "");
+ std::string bmp_name = bmp_name_in;
+ boost::replace_last(bmp_name, ".png", "");
- std::string bmp_name = icon_name_respected_to_mode(bmp_name_in);
+// std::string bmp_name = icon_name_respected_to_mode(bmp_name_in);
// Try loading an SVG first, then PNG if SVG is not found:
- wxBitmap *bmp = cache.load_svg(bmp_name, width, height, scale_factor, grayscale);
+ wxBitmap *bmp = cache.load_svg(bmp_name, width, height, scale_factor, grayscale, Slic3r::GUI::wxGetApp().dark_mode());
if (bmp == nullptr) {
bmp = cache.load_png(bmp_name, width, height, grayscale);
}
@@ -2348,7 +2325,7 @@ DoubleSlider::DoubleSlider( wxWindow *parent,
m_cog_icon_dim = int((float)m_bmp_cog.bmp().GetSize().x / scale_factor);
m_selection = ssUndef;
- m_pause_print_msg = _utf8(L("Place bearings in slots and resume"));
+ m_ticks.set_pause_print_msg(_utf8(L("Place bearings in slots and resume")));
// slider events
Bind(wxEVT_PAINT, &DoubleSlider::OnPaint, this);
@@ -2555,41 +2532,50 @@ double DoubleSlider::get_double_value(const SelectedSlider& selection)
}
using t_custom_code = Slic3r::Model::CustomGCode;
-std::vector<t_custom_code> DoubleSlider::GetTicksValues() const
+Slic3r::Model::CustomGCodeInfo DoubleSlider::GetTicksValues() const
{
- std::vector<t_custom_code> values;
+ Slic3r::Model::CustomGCodeInfo custom_gcode_per_print_z;
+ std::vector<t_custom_code>& values = custom_gcode_per_print_z.gcodes;
const int val_size = m_values.size();
if (!m_values.empty())
- for (const TICK_CODE& tick : m_ticks_) {
+ for (const TICK_CODE& tick : m_ticks.ticks) {
if (tick.tick > val_size)
break;
values.emplace_back(t_custom_code{m_values[tick.tick], tick.gcode, tick.extruder, tick.color});
}
- return values;
+ custom_gcode_per_print_z.mode = m_force_mode_apply ? m_mode : m_ticks.mode;
+
+ return custom_gcode_per_print_z;
}
-void DoubleSlider::SetTicksValues(const std::vector<t_custom_code>& heights)
+void DoubleSlider::SetTicksValues(const Slic3r::Model::CustomGCodeInfo& custom_gcode_per_print_z)
{
if (m_values.empty())
+ {
+ m_ticks.mode = m_mode;
return;
+ }
- const bool was_empty = m_ticks_.empty();
+ const bool was_empty = m_ticks.empty();
- m_ticks_.clear();
+ m_ticks.ticks.clear();
+ const std::vector<t_custom_code>& heights = custom_gcode_per_print_z.gcodes;
for (auto h : heights) {
auto it = std::lower_bound(m_values.begin(), m_values.end(), h.print_z - epsilon());
if (it == m_values.end())
continue;
- m_ticks_.emplace(TICK_CODE{int(it-m_values.begin()), h.gcode, h.extruder, h.color});
+ m_ticks.ticks.emplace(TICK_CODE{int(it-m_values.begin()), h.gcode, h.extruder, h.color});
}
- if (!was_empty && m_ticks_.empty())
+ if (!was_empty && m_ticks.empty())
// Switch to the "Feature type"/"Tool" from the very beginning of a new object slicing after deleting of the old one
- wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
+ post_ticks_changed_event();
+
+ m_ticks.mode = custom_gcode_per_print_z.mode;
Refresh();
Update();
@@ -2638,11 +2624,6 @@ void DoubleSlider::render()
// draw line
draw_scroll_line(dc, lower_pos, higher_pos);
-// //lower slider:
-// draw_thumb(dc, lower_pos, ssLower);
-// //higher slider:
-// draw_thumb(dc, higher_pos, ssHigher);
-
//draw color print ticks
draw_ticks(dc);
@@ -2668,7 +2649,7 @@ void DoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoin
return;
wxBitmap* icon = m_is_action_icon_focesed ? &m_bmp_add_tick_off.bmp() : &m_bmp_add_tick_on.bmp();
- if (m_ticks_.find(TICK_CODE{tick}) != m_ticks_.end())
+ if (m_ticks.ticks.find(TICK_CODE{tick}) != m_ticks.ticks.end())
icon = m_is_action_icon_focesed ? &m_bmp_del_tick_off.bmp() : &m_bmp_del_tick_on.bmp();
wxCoord x_draw, y_draw;
@@ -2811,7 +2792,7 @@ void DoubleSlider::draw_ticks(wxDC& dc)
int height, width;
get_size(&width, &height);
const wxCoord mid = is_horizontal() ? 0.5*height : 0.5*width;
- for (auto tick : m_ticks_)
+ for (auto tick : m_ticks.ticks)
{
const wxCoord pos = get_position_from_value(tick.tick);
@@ -2820,11 +2801,23 @@ void DoubleSlider::draw_ticks(wxDC& dc)
is_horizontal() ? dc.DrawLine(pos, mid+14, pos, mid+9) :
dc.DrawLine(mid + 14, pos/* - 1*/, mid + 9, pos/* - 1*/);
+ wxBitmap icon = wxNullBitmap;
+
// Draw icon for "Pause print" or "Custom Gcode"
- if (tick.gcode != Slic3r::ColorChangeCode && tick.gcode != Slic3r::ExtruderChangeCode)
+ if (tick.gcode != Slic3r::ColorChangeCode && tick.gcode != Slic3r::ToolChangeCode)
+ icon = create_scaled_bitmap(this, tick.gcode == Slic3r::PausePrintCode ? "pause_print" : "edit_gcode");
+ else
{
- wxBitmap icon = create_scaled_bitmap(this, tick.gcode == Slic3r::PausePrintCode ? "pause_print" : "edit_gcode");
+ if ((tick.gcode == Slic3r::ColorChangeCode && (
+ (m_ticks.mode == t_mode::SingleExtruder && m_mode == t_mode::MultiExtruder ) ||
+ (m_ticks.mode == t_mode::MultiExtruder && m_mode == t_mode::SingleExtruder) )) ||
+ (tick.gcode == Slic3r::ToolChangeCode &&
+ (m_ticks.mode == t_mode::MultiAsSingle && m_mode != t_mode::MultiAsSingle ) ))
+ icon = create_scaled_bitmap(this, "error_tick");
+ }
+ if (!icon.IsNull())
+ {
wxCoord x_draw, y_draw;
is_horizontal() ? x_draw = pos - 0.5 * m_tick_icon_dim : y_draw = pos - 0.5 * m_tick_icon_dim;
is_horizontal() ? y_draw = mid + 22 : x_draw = mid + m_thumb_size.x + 3;
@@ -2834,6 +2827,40 @@ void DoubleSlider::draw_ticks(wxDC& dc)
}
}
+std::string DoubleSlider::get_color_for_tool_change_tick(std::set<TICK_CODE>::const_iterator it) const
+{
+ const int current_extruder = it->extruder == 0 ? std::max<int>(m_only_extruder, 1) : it->extruder;
+
+ auto it_n = it;
+ while (it_n != m_ticks.ticks.begin()) {
+ --it_n;
+ if (it_n->gcode == Slic3r::ColorChangeCode && it_n->extruder == current_extruder)
+ return it_n->color;
+ }
+
+ return it->color;
+}
+
+std::string DoubleSlider::get_color_for_color_change_tick(std::set<TICK_CODE>::const_iterator it) const
+{
+ const int def_extruder = std::max<int>(1, m_only_extruder);
+ auto it_n = it;
+ bool is_tool_change = false;
+ while (it_n != m_ticks.ticks.begin()) {
+ --it_n;
+ if (it_n->gcode == Slic3r::ToolChangeCode) {
+ is_tool_change = true;
+ if (it_n->extruder == it->extruder)
+ return it->color;
+ break;
+ }
+ }
+ if (!is_tool_change && it->extruder == def_extruder)
+ return it->color;
+
+ return "";
+}
+
void DoubleSlider::draw_colored_band(wxDC& dc)
{
if (!m_is_enabled_tick_manipulation)
@@ -2856,29 +2883,36 @@ void DoubleSlider::draw_colored_band(wxDC& dc)
dc.DrawRectangle(band_rc);
};
- const std::vector<std::string>& colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
- int colors_cnt = colors.size();
+ // don't color a band for MultiExtruder mode
+ if (m_ticks.empty() || m_mode == t_mode::MultiExtruder)
+ {
+ draw_band(dc, GetParent()->GetBackgroundColour(), main_band);
+ return;
+ }
- const wxColour bg_clr = GetParent()->GetBackgroundColour();
+ const int default_color_idx = m_mode==t_mode::MultiAsSingle ? std::max<int>(m_only_extruder - 1, 0) : 0;
+ draw_band(dc, wxColour(Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config()[default_color_idx]), main_band);
- wxColour clr = m_state == msSingleExtruder ? wxColour(colors[0]) : bg_clr;
- draw_band(dc, clr, main_band);
+ std::set<TICK_CODE>::const_iterator tick_it = m_ticks.ticks.begin();
- size_t i = 1;
- for (auto tick : m_ticks_)
+ while (tick_it != m_ticks.ticks.end())
{
- if ( (m_state == msSingleExtruder && tick.gcode != Slic3r::ColorChangeCode) ||
- (m_state == msMultiExtruder && tick.gcode != Slic3r::ExtruderChangeCode) )
- continue;
-
- const wxCoord pos = get_position_from_value(tick.tick);
- is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) :
- main_band.SetBottom(pos - 1);
-
- clr = (m_state == msMultiExtruder && tick.color.empty()) ? bg_clr :
- m_state == msMultiExtruder ? wxColour(colors[std::min<int>(colors_cnt - 1, tick.extruder-1)]) : wxColour(tick.color);
- draw_band(dc, clr, main_band);
- i++;
+ if ( (m_mode == t_mode::SingleExtruder && tick_it->gcode == Slic3r::ColorChangeCode ) ||
+ (m_mode == t_mode::MultiAsSingle && (tick_it->gcode == Slic3r::ToolChangeCode || tick_it->gcode == Slic3r::ColorChangeCode)) )
+ {
+ const wxCoord pos = get_position_from_value(tick_it->tick);
+ is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) :
+ main_band.SetBottom(pos - 1);
+
+ const std::string clr_str = m_mode == t_mode::SingleExtruder ? tick_it->color :
+ tick_it->gcode == Slic3r::ToolChangeCode ?
+ get_color_for_tool_change_tick(tick_it) :
+ get_color_for_color_change_tick(tick_it);
+
+ if (!clr_str.empty())
+ draw_band(dc, wxColour(clr_str), main_band);
+ }
+ ++tick_it;
}
}
@@ -2903,7 +2937,7 @@ void DoubleSlider::draw_one_layer_icon(wxDC& dc)
void DoubleSlider::draw_revert_icon(wxDC& dc)
{
- if (m_ticks_.empty() || !m_is_enabled_tick_manipulation)
+ if (m_ticks.empty() || !m_is_enabled_tick_manipulation)
return;
int width, height;
@@ -2921,7 +2955,7 @@ void DoubleSlider::draw_revert_icon(wxDC& dc)
void DoubleSlider::draw_cog_icon(wxDC& dc)
{
- if (m_state != msMultiExtruder)
+ if (m_mode != t_mode::MultiExtruder)
return;
int width, height;
@@ -2965,15 +2999,13 @@ void DoubleSlider::detect_selected_slider(const wxPoint& pt)
bool DoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect)
{
- if (rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() &&
- rect.GetTop() <= pt.y && pt.y <= rect.GetBottom())
- return true;
- return false;
+ return rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() &&
+ rect.GetTop() <= pt.y && pt.y <= rect.GetBottom();
}
int DoubleSlider::is_point_near_tick(const wxPoint& pt)
{
- for (auto tick : m_ticks_) {
+ for (auto tick : m_ticks.ticks) {
const wxCoord pos = get_position_from_value(tick.tick);
if (is_horizontal()) {
@@ -3010,8 +3042,13 @@ void DoubleSlider::OnLeftDown(wxMouseEvent& event)
wxClientDC dc(this);
wxPoint pos = event.GetLogicalPosition(dc);
- if (is_point_in_rect(pos, m_rect_tick_action) && m_is_enabled_tick_manipulation) {
- action_tick(taOnIcon);
+ if (is_point_in_rect(pos, m_rect_tick_action) && m_is_enabled_tick_manipulation)
+ {
+ const auto it = m_ticks.ticks.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value });
+ if (it == m_ticks.ticks.end())
+ m_force_add_tick = true;
+ else
+ m_force_delete_tick = true;
return;
}
@@ -3034,12 +3071,13 @@ void DoubleSlider::OnLeftDown(wxMouseEvent& event)
m_selection == ssLower ? correct_lower_value() : correct_higher_value();
if (!m_selection) m_selection = ssHigher;
- m_ticks_.clear();
- wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
+ m_ticks.ticks.clear();
+ post_ticks_changed_event();
}
- else if (is_point_in_rect(pos, m_rect_cog_icon) && m_state == msMultiExtruder) {
+ else if (is_point_in_rect(pos, m_rect_cog_icon) && m_mode == t_mode::MultiExtruder) {
// show dialog for set extruder sequence
- m_edit_extruder_sequence = true;
+ m_force_edit_extruder_sequence = true;
+ return;
}
else
detect_selected_slider(pos);
@@ -3107,17 +3145,18 @@ wxString DoubleSlider::get_tooltip(IconFocus icon_focus)
else if (m_is_action_icon_focesed)
{
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
- const auto tick_code_it = m_ticks_.find(TICK_CODE{tick});
- tooltip = tick_code_it == m_ticks_.end() ? (m_state == msSingleExtruder ?
- _(L("For add color change use left mouse button click")) :
- _(L("For add change extruder use left mouse button click"))) + "\n" +
- _(L("For add another code use right mouse button click")) :
- tick_code_it->gcode == Slic3r::ColorChangeCode ? ( m_state == msSingleExtruder ?
+ const auto tick_code_it = m_ticks.ticks.find(TICK_CODE{tick});
+ tooltip = tick_code_it == m_ticks.ticks.end() ? (m_mode == t_mode::MultiAsSingle ?
+ _(L("For add change extruder use left mouse button click")) :
+ _(L("For add color change use left mouse button click")) ) + "\n" +
+ _(L("For add another code use right mouse button click")) :
+ tick_code_it->gcode == Slic3r::ColorChangeCode ? ( m_mode == t_mode::SingleExtruder ?
_(L("For Delete color change use left mouse button click\n"
"For Edit color use right mouse button click")) :
from_u8((boost::format(_utf8(L("Delete color change for Extruder %1%"))) % tick_code_it->extruder).str()) ):
-// tick_code_it->gcode == Slic3r::PausePrintCode ? _(L("Delete pause")) :
- tick_code_it->gcode == Slic3r::ExtruderChangeCode ?
+ tick_code_it->gcode == Slic3r::PausePrintCode ?
+ _(L("Delete pause")) :
+ tick_code_it->gcode == Slic3r::ToolChangeCode ?
from_u8((boost::format(_utf8(L("Delete extruder change to \"%1%\""))) % tick_code_it->extruder).str()) :
from_u8((boost::format(_utf8(L("For Delete \"%1%\" code use left mouse button click\n"
"For Edit \"%1%\" code use right mouse button click"))) % tick_code_it->gcode ).str());
@@ -3138,7 +3177,7 @@ void DoubleSlider::OnMotion(wxMouseEvent& event)
if (!m_is_left_down && !m_is_one_layer) {
m_is_action_icon_focesed = is_point_in_rect(pos, m_rect_tick_action);
- if (!m_ticks_.empty() && is_point_in_rect(pos, m_rect_revert_icon))
+ if (!m_ticks.empty() && is_point_in_rect(pos, m_rect_revert_icon))
icon_focus = ifRevert;
else if (is_point_in_rect(pos, m_rect_cog_icon))
icon_focus = ifCog;
@@ -3173,47 +3212,87 @@ void DoubleSlider::OnMotion(wxMouseEvent& event)
}
}
-void DoubleSlider::OnLeftUp(wxMouseEvent& event)
+void DoubleSlider::append_change_extruder_menu_item(wxMenu* menu)
{
- if (!HasCapture())
- return;
- this->ReleaseMouse();
- m_is_left_down = false;
-
- if (m_show_context_menu)
+ const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt();
+ if (extruders_cnt > 1)
{
- if (m_state == msMultiExtruder)
+ const int initial_extruder = std::max<int>(1 , get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value));
+
+ wxMenu* change_extruder_menu = new wxMenu();
+
+ for (int i = 1; i <= extruders_cnt; i++)
{
- wxMenu menu;
- const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt();
- if (extruders_cnt > 1)
- {
- const int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
+ const bool is_active_extruder = i == initial_extruder;
+ const wxString item_name = wxString::Format(_(L("Extruder %d")), i) +
+ (is_active_extruder ? " (" + _(L("active")) + ")" : "");
+
+ if (m_mode == t_mode::MultiAsSingle)
+ append_menu_item(change_extruder_menu, wxID_ANY, item_name, "",
+ [this, i](wxCommandEvent&) { add_code_as_tick(Slic3r::ToolChangeCode, i); }, "", menu,
+ [is_active_extruder]() { return !is_active_extruder; }, Slic3r::GUI::wxGetApp().plater());
+ }
- wxMenu* change_extruder_menu = new wxMenu();
+ const wxString change_extruder_menu_name = m_mode == t_mode::MultiAsSingle ? _(L("Change extruder")) : _(L("Change extruder (N/A)"));
- for (int i = 0; i <= extruders_cnt; i++) {
- const wxString item_name = i == 0 ? _(L("Default")) : wxString::Format(_(L("Extruder %d")), i);
+ wxMenuItem* change_extruder_menu_item = menu->AppendSubMenu(change_extruder_menu, change_extruder_menu_name, _(L("Use another extruder")));
+ change_extruder_menu_item->SetBitmap(create_scaled_bitmap(this, "change_extruder"));
- append_menu_radio_item(change_extruder_menu, wxID_ANY, item_name, "",
- [this, i](wxCommandEvent&) { change_extruder(i); }, &menu)->Check(i == initial_extruder);
- }
+ Slic3r::GUI::wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this, change_extruder_menu_item](wxUpdateUIEvent& evt) {
+ enable_menu_item(evt, [this]() {return m_mode == t_mode::MultiAsSingle; }, change_extruder_menu_item, this); },
+ change_extruder_menu_item->GetId());
+ }
+}
- wxMenuItem* change_extruder_menu_item = menu.AppendSubMenu(change_extruder_menu, _(L("Change extruder")), _(L("Use another extruder")));
- change_extruder_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "change_extruder"));
- }
+void DoubleSlider::append_add_color_change_menu_item(wxMenu* menu)
+{
+ const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt();
+ if (extruders_cnt > 1)
+ {
+ std::set<int> used_extruders_for_tick = get_used_extruders_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
- Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu);
+ wxMenu* add_color_change_menu = new wxMenu();
+
+ for (int i = 1; i <= extruders_cnt; i++)
+ {
+ const bool is_used_extruder = used_extruders_for_tick.empty() ? true : // #ys_FIXME till used_extruders_for_tick doesn't filled correct for mmMultiExtruder
+ used_extruders_for_tick.find(i) != used_extruders_for_tick.end();
+ const wxString item_name = wxString::Format(_(L("Extruder %d")), i) +
+ (is_used_extruder ? " (" + _(L("used")) + ")" : "");
+
+ append_menu_item(add_color_change_menu, wxID_ANY, item_name, "",
+ [this, i](wxCommandEvent&) { add_code_as_tick(Slic3r::ColorChangeCode, i); }, "", menu,
+ [is_used_extruder]() { return is_used_extruder; }, Slic3r::GUI::wxGetApp().plater());
}
- else
- add_code(Slic3r::ColorChangeCode);
-
- m_show_context_menu = false;
+
+ const wxString menu_name = from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % Slic3r::ColorChangeCode).str());
+ wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, "");
+ add_color_change_menu_item->SetBitmap(create_scaled_bitmap(this, "colorchange_add_m"));
}
+}
- if (m_edit_extruder_sequence) {
+void DoubleSlider::OnLeftUp(wxMouseEvent& event)
+{
+ if (!HasCapture())
+ return;
+ this->ReleaseMouse();
+ m_is_left_down = false;
+
+ if (m_force_delete_tick)
+ {
+ delete_current_tick();
+ m_force_delete_tick = false;
+ }
+ else
+ if (m_force_add_tick)
+ {
+ add_current_tick();
+ m_force_add_tick = false;
+ }
+ else
+ if (m_force_edit_extruder_sequence) {
edit_extruder_sequence();
- m_edit_extruder_sequence = false;
+ m_force_edit_extruder_sequence = false;
}
Refresh();
@@ -3259,45 +3338,6 @@ void DoubleSlider::move_current_thumb(const bool condition)
ProcessWindowEvent(e);
}
-void DoubleSlider::action_tick(const TicksAction action)
-{
- if (m_selection == ssUndef)
- return;
-
- const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
-
- const auto it = m_ticks_.find(TICK_CODE{tick});
-
- if (it != m_ticks_.end()) // erase this tick
- {
- if (action == taAdd)
- return;
- m_ticks_.erase(TICK_CODE{tick});
-
- wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
- Refresh();
- Update();
- return;
- }
-
- if (action == taDel)
- return;
- if (action == taAdd)
- {
- // OnChar() is called immediately after OnKeyDown(), which can cause call of add_code() twice.
- // To avoid this case we should suppress second add_code() call.
- if (m_suppress_add_code)
- return;
- m_suppress_add_code = true;
- if (m_state != msMultiExtruder)
- add_code(Slic3r::ColorChangeCode);
- m_suppress_add_code = false;
- return;
- }
-
- m_show_context_menu = true;
-}
-
void DoubleSlider::OnWheel(wxMouseEvent& event)
{
// Set nearest to the mouse thumb as a selected, if there is not selected thumb
@@ -3321,10 +3361,18 @@ void DoubleSlider::OnWheel(wxMouseEvent& event)
void DoubleSlider::OnKeyDown(wxKeyEvent &event)
{
const int key = event.GetKeyCode();
- if (key == WXK_NUMPAD_ADD)
- action_tick(taAdd);
- else if (key == 390 || key == WXK_DELETE || key == WXK_BACK)
- action_tick(taDel);
+ if (key == WXK_NUMPAD_ADD) {
+ // OnChar() is called immediately after OnKeyDown(), which can cause call of add_tick() twice.
+ // To avoid this case we should suppress second add_tick() call.
+ m_ticks.suppress_plus(true);
+ add_current_tick(true);
+ }
+ else if (key == 390 || key == WXK_DELETE || key == WXK_BACK) {
+ // OnChar() is called immediately after OnKeyDown(), which can cause call of delete_tick() twice.
+ // To avoid this case we should suppress second delete_tick() call.
+ m_ticks.suppress_minus(true);
+ delete_current_tick();
+ }
else if (is_horizontal())
{
if (key == WXK_LEFT || key == WXK_RIGHT)
@@ -3358,10 +3406,14 @@ void DoubleSlider::OnKeyUp(wxKeyEvent &event)
void DoubleSlider::OnChar(wxKeyEvent& event)
{
const int key = event.GetKeyCode();
- if (key == '+')
- action_tick(taAdd);
- else if (key == '-')
- action_tick(taDel);
+ if (key == '+' && !m_ticks.suppressed_plus()) {
+ add_current_tick(true);
+ m_ticks.suppress_plus(false);
+ }
+ else if (key == '-' && !m_ticks.suppressed_minus()) {
+ delete_current_tick();
+ m_ticks.suppress_minus(false);
+ }
}
void DoubleSlider::OnRightDown(wxMouseEvent& event)
@@ -3376,14 +3428,14 @@ void DoubleSlider::OnRightDown(wxMouseEvent& event)
{
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
// if on this Z doesn't exist tick
- auto it = m_ticks_.find(TICK_CODE{ tick });
- if (it == m_ticks_.end())
+ auto it = m_ticks.ticks.find(TICK_CODE{ tick });
+ if (it == m_ticks.ticks.end())
{
// show context menu on OnRightUp()
m_show_context_menu = true;
return;
}
- if (it->gcode != Slic3r::ExtruderChangeCode)
+ if (it->gcode != Slic3r::ToolChangeCode)
{
// show "Edit" and "Delete" menu on OnRightUp()
m_show_edit_menu = true;
@@ -3410,17 +3462,78 @@ void DoubleSlider::OnRightDown(wxMouseEvent& event)
int DoubleSlider::get_extruder_for_tick(int tick)
{
- if (m_ticks_.empty())
- return 0;
+ int default_initial_extruder = m_mode == t_mode::MultiAsSingle ? m_only_extruder : 0;
+ if (m_ticks.empty())
+ return default_initial_extruder;
- auto it = m_ticks_.lower_bound(TICK_CODE{tick});
- while (it != m_ticks_.begin()) {
+ auto it = m_ticks.ticks.lower_bound(TICK_CODE{tick});
+ while (it != m_ticks.ticks.begin()) {
--it;
- if(it->gcode == Slic3r::ExtruderChangeCode)
+ if(it->gcode == Slic3r::ToolChangeCode)
return it->extruder;
}
- return 0;
+ return default_initial_extruder;
+}
+
+std::set<int> DoubleSlider::get_used_extruders_for_tick(int tick)
+{
+ if (m_mode == t_mode::MultiExtruder)
+ {
+ // #ys_FIXME: get tool ordering from _correct_ place
+ const Slic3r::ToolOrdering& tool_ordering = Slic3r::GUI::wxGetApp().plater()->fff_print().get_tool_ordering();
+
+ if (tool_ordering.empty())
+ return {};
+
+ std::set<int> used_extruders;
+
+ auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), Slic3r::LayerTools(m_values[tick]));
+ for (; it_layer_tools != tool_ordering.end(); it_layer_tools++)
+ {
+ const std::vector<unsigned>& extruders = it_layer_tools->extruders;
+ for (const auto& extruder : extruders)
+ used_extruders.emplace(extruder+1);
+ }
+
+ return used_extruders;
+ }
+
+ const int default_initial_extruder = m_mode == t_mode::MultiAsSingle ? std::max(m_only_extruder, 1) : 1;
+ if (m_ticks.empty())
+ return {default_initial_extruder};
+
+ std::set<int> used_extruders;
+ const std::set<TICK_CODE>& ticks = m_ticks.ticks;
+
+ auto it_start = ticks.lower_bound(TICK_CODE{tick});
+ auto it = it_start;
+ if (it == ticks.begin() && it->gcode == Slic3r::ToolChangeCode) {
+ used_extruders.emplace(it->extruder);
+ if (tick < it->tick)
+ used_extruders.emplace(default_initial_extruder);
+ }
+
+ while (it != ticks.begin()) {
+ --it;
+ if(it->gcode == Slic3r::ToolChangeCode)
+ {
+ used_extruders.emplace(it->extruder);
+ break;
+ }
+ }
+
+ if (it == ticks.begin() && used_extruders.empty())
+ used_extruders.emplace(default_initial_extruder);
+
+ it = it_start;
+ while (it != ticks.end()) {
+ if(it->gcode == Slic3r::ToolChangeCode)
+ used_extruders.emplace(it->extruder);
+ ++it;
+ }
+
+ return used_extruders;
}
void DoubleSlider::OnRightUp(wxMouseEvent& event)
@@ -3433,45 +3546,23 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event)
if (m_show_context_menu) {
wxMenu menu;
- if (m_state == msMultiExtruder)
+ if (m_mode == t_mode::SingleExtruder)
+ append_menu_item(&menu, wxID_ANY, _(L("Add color change")) + " (M600)", "",
+ [this](wxCommandEvent&) { add_code_as_tick(Slic3r::ColorChangeCode); }, "colorchange_add_m", &menu,
+ [](){return true;}, this);
+ else
{
- const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt();
- if (extruders_cnt > 1)
- {
- const int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
-
- wxMenu* change_extruder_menu = new wxMenu();
- wxMenu* add_color_change_menu = new wxMenu();
-
- for (int i = 0; i <= extruders_cnt; i++) {
- const wxString item_name = i == 0 ? _(L("Default")) : wxString::Format(_(L("Extruder %d")), i);
-
- append_menu_radio_item(change_extruder_menu, wxID_ANY, item_name, "",
- [this, i](wxCommandEvent&) { change_extruder(i); }, &menu)->Check(i == initial_extruder);
-
- if (i==0) // don't use M600 for default extruder, if multimaterial print is selected
- continue;
- append_menu_item(add_color_change_menu, wxID_ANY, item_name, "",
- [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", &menu);
- }
-
- wxMenuItem* change_extruder_menu_item = menu.AppendSubMenu(change_extruder_menu, _(L("Change extruder")), _(L("Use another extruder")));
- change_extruder_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "change_extruder"));
-
- const wxString menu_name = from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % Slic3r::ColorChangeCode).str());
- wxMenuItem* add_color_change_menu_item = menu.AppendSubMenu(add_color_change_menu, menu_name, "");
- add_color_change_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "colorchange_add_m"));
- }
+ append_change_extruder_menu_item(&menu);
+ append_add_color_change_menu_item(&menu);
}
- else
- append_menu_item(&menu, wxID_ANY, _(L("Add color change")) + " (M600)", "",
- [this](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode); }, "colorchange_add_m", &menu);
append_menu_item(&menu, wxID_ANY, _(L("Add pause print")) + " (M601)", "",
- [this](wxCommandEvent&) { add_code(Slic3r::PausePrintCode); }, "pause_print", &menu);
+ [this](wxCommandEvent&) { add_code_as_tick(Slic3r::PausePrintCode); }, "pause_print", &menu,
+ []() {return true; }, this);
append_menu_item(&menu, wxID_ANY, _(L("Add custom G-code")), "",
- [this](wxCommandEvent&) { add_code(""); }, "edit_gcode", &menu);
+ [this](wxCommandEvent&) { add_code_as_tick(""); }, "edit_gcode", &menu,
+ []() {return true; }, this);
Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu);
@@ -3480,7 +3571,7 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event)
else if (m_show_edit_menu) {
wxMenu menu;
- std::set<TICK_CODE>::iterator it = m_ticks_.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value });
+ std::set<TICK_CODE>::iterator it = m_ticks.ticks.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value });
const bool is_color_change = it->gcode == Slic3r::ColorChangeCode;
append_menu_item(&menu, wxID_ANY, it->gcode == Slic3r::ColorChangeCode ? _(L("Edit color")) :
@@ -3491,7 +3582,7 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event)
append_menu_item(&menu, wxID_ANY, it->gcode == Slic3r::ColorChangeCode ? _(L("Delete color change")) :
it->gcode == Slic3r::PausePrintCode ? _(L("Delete pause print")) :
_(L("Delete custom G-code")), "",
- [this](wxCommandEvent&) { action_tick(taDel); }, "colorchange_del_f", &menu);
+ [this](wxCommandEvent&) { delete_current_tick();}, "colorchange_del_f", &menu);
Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu);
@@ -3548,128 +3639,100 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height)
return into_u8(dlg.GetValue());
}
-void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/)
+void DoubleSlider::add_code_as_tick(std::string code, int selected_extruder/* = -1*/)
{
+ if (m_selection == ssUndef)
+ return;
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
- // if on this Z doesn't exist tick
- auto it = m_ticks_.find(TICK_CODE{ tick });
- if (it == m_ticks_.end())
- {
- std::string color = "";
- if (code == Slic3r::ColorChangeCode)
- {
- std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
-
- if (m_state == msSingleExtruder && !m_ticks_.empty()) {
- auto before_tick_it = std::lower_bound(m_ticks_.begin(), m_ticks_.end(), TICK_CODE{ tick });
- while (before_tick_it != m_ticks_.begin()) {
- --before_tick_it;
- if (before_tick_it->gcode == Slic3r::ColorChangeCode) {
- color = before_tick_it->color;
- break;
- }
- }
-
- if (color.empty())
- color = colors[0];
- }
- else
- color = colors[selected_extruder > 0 ? selected_extruder-1 : 0];
- color = get_new_color(color);
- if (color.empty())
- return;
- }
- else if (code == Slic3r::PausePrintCode)
- {
- /* PausePrintCode doesn't need a color, so
- * this field is used for save a short message shown on Printer display
- * */
- color = get_pause_print_msg(m_pause_print_msg, m_values[tick]);
- if (color.empty())
- return;
- m_pause_print_msg = color;
- }
- else if (code.empty())
- {
- code = get_custom_code(m_custom_gcode, m_values[tick]);
- if (code.empty())
- return;
- m_custom_gcode = code;
- }
+ if (m_ticks.ticks.find(TICK_CODE{ tick }) != m_ticks.ticks.end() || // if on this Z doesn't exist tick
+ !check_ticks_changed_event(code))
+ return;
- int extruder = 1;
- if (m_state == msMultiExtruder) {
- if (code == Slic3r::ColorChangeCode && selected_extruder >= 0)
- extruder = selected_extruder;
- else
- extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
- }
+ const int extruder = selected_extruder > 0 ? selected_extruder : std::max<int>(1, m_only_extruder);
- m_ticks_.emplace(TICK_CODE{tick, code, extruder, color});
+ if (!m_ticks.add_tick(tick, code, extruder, m_values[tick]))
+ return;
- wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
- Refresh();
- Update();
- }
+ post_ticks_changed_event(code);
}
-void DoubleSlider::edit_tick()
+void DoubleSlider::add_current_tick(bool call_from_keyboard /*= false*/)
{
+ if (m_selection == ssUndef)
+ return;
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
- // if on this Z exists tick
- std::set<TICK_CODE>::iterator it = m_ticks_.find(TICK_CODE{ tick });
- if (it != m_ticks_.end())
+ auto it = m_ticks.ticks.find(TICK_CODE{ tick });
+
+ if (it != m_ticks.ticks.end() || // this tick is already exist
+ !check_ticks_changed_event(m_mode == t_mode::MultiAsSingle ? Slic3r::ToolChangeCode : Slic3r::ColorChangeCode))
+ return;
+
+ if (m_mode == t_mode::SingleExtruder)
+ add_code_as_tick(Slic3r::ColorChangeCode);
+ else
{
- std::string edited_value;
- if (it->gcode == Slic3r::ColorChangeCode)
- edited_value = get_new_color(it->color);
- else if (it->gcode == Slic3r::PausePrintCode)
- edited_value = get_pause_print_msg(it->color, m_values[it->tick]);
+ wxMenu menu;
+
+ if (m_mode == t_mode::MultiAsSingle)
+ append_change_extruder_menu_item(&menu);
else
- edited_value = get_custom_code(it->gcode, m_values[it->tick]);
+ append_add_color_change_menu_item(&menu);
- if (edited_value.empty())
- return;
+ wxPoint pos = wxDefaultPosition;
+ if (call_from_keyboard)
+ {
+ int width, height;
+ get_size(&width, &height);
- TICK_CODE changed_tick = *it;
- if (it->gcode == Slic3r::ColorChangeCode || it->gcode == Slic3r::PausePrintCode) {
- if (it->color == edited_value)
- return;
- changed_tick.color = edited_value;
- }
- else {
- if (it->gcode == edited_value)
- return;
- changed_tick.gcode = edited_value;
+ const wxCoord coord = 0.75 * (is_horizontal() ? height : width);
+ this->GetPosition(&width, &height);
+
+ pos = is_horizontal() ?
+ wxPoint(get_position_from_value(tick), height + coord) :
+ wxPoint(width + coord, get_position_from_value(tick));
}
-
- m_ticks_.erase(it);
- m_ticks_.emplace(changed_tick);
- wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
+ Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu, pos);
}
}
-void DoubleSlider::change_extruder(int extruder)
+void DoubleSlider::delete_current_tick()
{
- const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
-
- std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
+ if (m_selection == ssUndef)
+ return;
+ auto it = m_ticks.ticks.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value });
- // if on this Y doesn't exist tick
- if (m_ticks_.find(TICK_CODE{tick}) == m_ticks_.end())
- {
- m_ticks_.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, extruder, extruder == 0 ? "" : colors[extruder-1]});
+ if (it != m_ticks.ticks.end())
+ {
+ if (!check_ticks_changed_event(it->gcode))
+ return;
- wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
- Refresh();
- Update();
+ const std::string code = it->gcode;
+ m_ticks.ticks.erase(it);
+ post_ticks_changed_event(code);
}
}
+void DoubleSlider::edit_tick()
+{
+ const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
+ const std::set<TICK_CODE>::iterator it = m_ticks.ticks.find(TICK_CODE{ tick });
+
+ if (it == m_ticks.ticks.end() || // if on this Z exists tick
+ !check_ticks_changed_event(it->gcode))
+ return;
+
+ const std::string code = it->gcode;
+ if (m_ticks.edit_tick(it, m_values[it->tick]))
+ post_ticks_changed_event(code);
+}
+
void DoubleSlider::edit_extruder_sequence()
{
+ if (!check_ticks_changed_event(Slic3r::ToolChangeCode))
+ return;
+
Slic3r::GUI::ExtruderSequenceDialog dlg(m_extruders_sequence);
if (dlg.ShowModal() != wxID_OK)
return;
@@ -3680,13 +3743,7 @@ void DoubleSlider::edit_extruder_sequence()
m_extruders_sequence = from_dlg_val;
- auto it = m_ticks_.begin();
- while (it != m_ticks_.end()) {
- if (it->gcode == Slic3r::ExtruderChangeCode)
- it = m_ticks_.erase(it);
- else
- ++it;
- }
+ m_ticks.erase_all_ticks_with_code(Slic3r::ToolChangeCode);
int tick = 0;
double value = 0.0;
@@ -3697,8 +3754,8 @@ void DoubleSlider::edit_extruder_sequence()
while (tick <= m_max_value)
{
- int cur_extruder = m_extruders_sequence.extruders[extruder];
- m_ticks_.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, cur_extruder + 1, colors[cur_extruder]});
+ const int cur_extruder = m_extruders_sequence.extruders[extruder];
+ m_ticks.ticks.emplace(TICK_CODE{tick, Slic3r::ToolChangeCode, cur_extruder + 1, colors[cur_extruder]});
extruder++;
if (extruder == extr_cnt)
@@ -3717,9 +3774,188 @@ void DoubleSlider::edit_extruder_sequence()
tick += m_extruders_sequence.interval_by_layers;
}
+ post_ticks_changed_event(Slic3r::ToolChangeCode);
+}
+
+void DoubleSlider::post_ticks_changed_event(const std::string& gcode /*= ""*/)
+{
+ m_force_mode_apply = (gcode.empty() || gcode == Slic3r::ColorChangeCode || gcode == Slic3r::ToolChangeCode);
+
wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED));
}
+bool DoubleSlider::check_ticks_changed_event(const std::string& gcode)
+{
+ if ( m_ticks.mode == m_mode ||
+ (gcode != Slic3r::ColorChangeCode && gcode != Slic3r::ToolChangeCode) ||
+ (m_ticks.mode == t_mode::SingleExtruder && m_mode == t_mode::MultiAsSingle) || // All ColorChanges will be applied for 1st extruder
+ (m_ticks.mode == t_mode::MultiExtruder && m_mode == t_mode::MultiAsSingle) ) // Just mark ColorChanges for all unused extruders
+ return true;
+
+ if ((m_ticks.mode == t_mode::SingleExtruder && m_mode == t_mode::MultiExtruder ) ||
+ (m_ticks.mode == t_mode::MultiExtruder && m_mode == t_mode::SingleExtruder) )
+ {
+ if (!m_ticks.has_tick_with_code(Slic3r::ColorChangeCode))
+ return true;
+
+ wxString message = (m_ticks.mode == t_mode::SingleExtruder ?
+ _(L("The last color change data was saved for a single extruder printer profile.")) :
+ _(L("The last color change data was saved for a multiple extruder printer profile."))
+ ) + "\n" +
+ _(L("Your current changes will cause a deletion of all saved color changes.")) + "\n\n\t" +
+ _(L("Are you sure you want to continue?"));
+
+ wxMessageDialog msg(this, message, _(L("Notice")), wxYES_NO);
+ if (msg.ShowModal() == wxID_YES) {
+ m_ticks.erase_all_ticks_with_code(Slic3r::ColorChangeCode);
+ post_ticks_changed_event(Slic3r::ColorChangeCode);
+ }
+ return false;
+ }
+ // m_ticks_mode == t_mode::MultiAsSingle
+ if( m_ticks.has_tick_with_code(Slic3r::ToolChangeCode) )
+ {
+ wxString message = m_mode == t_mode::SingleExtruder ? (
+ _(L("The last color change data was saved for a multi extruder printing.")) + "\n\n" +
+ _(L("Select YES if you want to delete all saved tool changes, \n\t"
+ "NO if you want all tool changes switch to color changes, \n\t"
+ "or CANCEL for do nothing")) + "\n\n\t" +
+ _(L("Do you want to delete all saved tool changes?"))
+ ) : ( // t_mode::MultiExtruder
+ _(L("The last color change data was saved for a multi extruder printing with tool changes for whole print.")) + "\n\n" +
+ _(L("Your current changes will cause a deletion of all saved tool changes.")) + "\n\n\t" +
+ _(L("Are you sure you want to continue?")) ) ;
+
+ wxMessageDialog msg(this, message, _(L("Notice")), wxYES_NO | (m_mode == t_mode::SingleExtruder ? wxCANCEL : 0));
+ const int answer = msg.ShowModal();
+ if (answer == wxID_YES) {
+ m_ticks.erase_all_ticks_with_code(Slic3r::ToolChangeCode);
+ post_ticks_changed_event(Slic3r::ToolChangeCode);
+ }
+ else if (m_mode == t_mode::SingleExtruder && answer == wxID_NO) {
+ m_ticks.switch_code(Slic3r::ToolChangeCode, Slic3r::ColorChangeCode);
+ post_ticks_changed_event(Slic3r::ColorChangeCode);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool DoubleSlider::TICK_CODE_INFO::add_tick(const int tick, std::string& code, const int extruder, double print_z)
+{
+ std::string color;
+ if (code.empty()) // custom Gcode
+ {
+ code = get_custom_code(custom_gcode, print_z);
+ if (code.empty())
+ return false;
+ custom_gcode = code;
+ }
+ else if (code == Slic3r::PausePrintCode)
+ {
+ /* PausePrintCode doesn't need a color, so
+ * this field is used for save a short message shown on Printer display
+ * */
+ color = get_pause_print_msg(pause_print_msg, print_z);
+ if (color.empty())
+ return false;
+ pause_print_msg = color;
+ }
+ else
+ {
+ std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
+ color = colors[extruder - 1];
+
+ if (code == Slic3r::ColorChangeCode)
+ {
+ if (!ticks.empty())
+ {
+ auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), TICK_CODE{ tick });
+ while (before_tick_it != ticks.begin()) {
+ --before_tick_it;
+ if (before_tick_it->gcode == Slic3r::ColorChangeCode && before_tick_it->extruder == extruder) {
+ color = before_tick_it->color;
+ break;
+ }
+ }
+ }
+
+ color = get_new_color(color);
+ if (color.empty())
+ return false;
+ }
+ }
+
+ ticks.emplace(TICK_CODE{ tick, code, extruder, color });
+ return true;
+}
+
+bool DoubleSlider::TICK_CODE_INFO::edit_tick(std::set<TICK_CODE>::iterator it, double print_z)
+{
+ std::string edited_value;
+ if (it->gcode == Slic3r::ColorChangeCode)
+ edited_value = get_new_color(it->color);
+ else if (it->gcode == Slic3r::PausePrintCode)
+ edited_value = get_pause_print_msg(it->color, print_z);
+ else
+ edited_value = get_custom_code(it->gcode, print_z);
+
+ if (edited_value.empty())
+ return false;
+
+ TICK_CODE changed_tick = *it;
+ if (it->gcode == Slic3r::ColorChangeCode || it->gcode == Slic3r::PausePrintCode) {
+ if (it->color == edited_value)
+ return false;
+ changed_tick.color = edited_value;
+ }
+ else {
+ if (it->gcode == edited_value)
+ return false;
+ changed_tick.gcode = edited_value;
+ }
+
+ ticks.erase(it);
+ ticks.emplace(changed_tick);
+
+ return true;
+}
+
+void DoubleSlider::TICK_CODE_INFO::switch_code(const std::string& code_from, const std::string& code_to)
+{
+ for (auto it{ ticks.begin() }, end{ ticks.end() }; it != end; )
+ if (it->gcode == code_from)
+ {
+ TICK_CODE tick = *it;
+ tick.gcode = code_to;
+ tick.extruder = 1;
+ ticks.erase(it);
+ it = ticks.emplace(tick).first;
+ }
+ else
+ ++it;
+}
+
+void DoubleSlider::TICK_CODE_INFO::erase_all_ticks_with_code(const std::string& gcode)
+{
+ for (auto it{ ticks.begin() }, end{ ticks.end() }; it != end; ) {
+ if (it->gcode == gcode)
+ it = ticks.erase(it);
+ else
+ ++it;
+ }
+}
+
+bool DoubleSlider::TICK_CODE_INFO::has_tick_with_code(const std::string& gcode)
+{
+ for (const TICK_CODE& tick : ticks)
+ if (tick.gcode == gcode)
+ return true;
+
+ return false;
+}
+
// ----------------------------------------------------------------------------
// LockButton
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index 390dafab9..8cae495ef 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -782,6 +782,8 @@ public:
const wxString& name = wxEmptyString);
~DoubleSlider() {}
+ using t_mode = Slic3r::Model::CustomGCodeInfo::MODE;
+
/* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values.
* So, let use same value as a permissible error for layer height.
*/
@@ -805,33 +807,24 @@ public:
// Set low and high slider position. If the span is non-empty, disable the "one layer" mode.
void SetSelectionSpan(const int lower_val, const int higher_val);
void SetMaxValue(const int max_value);
- void SetKoefForLabels(const double koef) {
- m_label_koef = koef;
- }
- void SetSliderValues(const std::vector<double>& values) {
- m_values = values;
- }
+ void SetKoefForLabels(const double koef) { m_label_koef = koef; }
+ void SetSliderValues(const std::vector<double>& values) { m_values = values; }
void ChangeOneLayerLock();
- std::vector<Slic3r::Model::CustomGCode> GetTicksValues() const;
- void SetTicksValues(const std::vector<Slic3r::Model::CustomGCode> &heights);
- void EnableTickManipulation(bool enable = true) {
- m_is_enabled_tick_manipulation = enable;
- }
- void DisableTickManipulation() {
- EnableTickManipulation(false);
- }
+ Slic3r::Model::CustomGCodeInfo GetTicksValues() const;
+ void SetTicksValues(const Slic3r::Model::CustomGCodeInfo &custom_gcode_per_print_z);
+ void EnableTickManipulation(bool enable = true) { m_is_enabled_tick_manipulation = enable; }
+ void DisableTickManipulation() { EnableTickManipulation(false); }
- enum ManipulationState {
- msSingleExtruder, // single extruder printer preset is selected
- msMultiExtruder // multiple extruder printer preset is selected, and "Whole print" is selected
- };
- void SetManipulationState(ManipulationState state) {
- m_state = state;
- }
- void SetManipulationState(int extruders_cnt) {
- m_state = extruders_cnt ==1 ? msSingleExtruder : msMultiExtruder;
+ void SetManipulationMode(t_mode mode) { m_mode = mode; }
+ t_mode GetManipulationMode() const { return m_mode; }
+
+ void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder)
+ {
+ m_mode = !is_one_extruder_printed_model ? t_mode::MultiExtruder :
+ only_extruder < 0 ? t_mode::SingleExtruder :
+ t_mode::MultiAsSingle;
+ m_only_extruder = only_extruder;
}
- ManipulationState GetManipulationState() const { return m_state; }
bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; }
bool is_one_layer() const { return m_is_one_layer; }
@@ -850,13 +843,27 @@ public:
void OnKeyUp(wxKeyEvent &event);
void OnChar(wxKeyEvent &event);
void OnRightDown(wxMouseEvent& event);
- int get_extruder_for_tick(int tick);
void OnRightUp(wxMouseEvent& event);
- void add_code(std::string code, int selected_extruder = -1);
+
+ void add_code_as_tick(std::string code, int selected_extruder = -1);
+ // add default action for tick, when press "+"
+ void add_current_tick(bool call_from_keyboard = false);
+ // delete current tick, when press "-"
+ void delete_current_tick();
void edit_tick();
- void change_extruder(int extruder);
void edit_extruder_sequence();
+ struct TICK_CODE
+ {
+ bool operator<(const TICK_CODE& other) const { return other.tick > this->tick; }
+ bool operator>(const TICK_CODE& other) const { return other.tick < this->tick; }
+
+ int tick = 0;
+ std::string gcode = Slic3r::ColorChangeCode;
+ int extruder = 0;
+ std::string color;
+ };
+
protected:
void render();
@@ -878,11 +885,11 @@ protected:
void detect_selected_slider(const wxPoint& pt);
void correct_lower_value();
void correct_higher_value();
- wxString get_tooltip(IconFocus icon_focus);
void move_current_thumb(const bool condition);
- void action_tick(const TicksAction action);
void enter_window(wxMouseEvent& event, const bool enter);
+private:
+
bool is_point_in_rect(const wxPoint& pt, const wxRect& rect);
int is_point_near_tick(const wxPoint& pt);
@@ -894,8 +901,18 @@ protected:
wxSize get_size();
void get_size(int *w, int *h);
double get_double_value(const SelectedSlider& selection);
+ wxString get_tooltip(IconFocus icon_focus);
+
+ std::string get_color_for_tool_change_tick(std::set<TICK_CODE>::const_iterator it) const;
+ std::string get_color_for_color_change_tick(std::set<TICK_CODE>::const_iterator it) const;
+ int get_extruder_for_tick(int tick);
+ std::set<int> get_used_extruders_for_tick(int tick);
+
+ void post_ticks_changed_event(const std::string& gcode = "");
+ bool check_ticks_changed_event(const std::string& gcode);
+ void append_change_extruder_menu_item(wxMenu*);
+ void append_add_color_change_menu_item(wxMenu*);
-private:
bool is_osx { false };
wxFont m_font;
int m_min_value;
@@ -914,7 +931,7 @@ private:
ScalableBitmap m_bmp_one_layer_unlock_off;
ScalableBitmap m_bmp_revert;
ScalableBitmap m_bmp_cog;
- SelectedSlider m_selection;
+ SelectedSlider m_selection;
bool m_is_left_down = false;
bool m_is_right_down = false;
bool m_is_one_layer = false;
@@ -924,11 +941,12 @@ private:
bool m_is_enabled_tick_manipulation = true;
bool m_show_context_menu = false;
bool m_show_edit_menu = false;
- bool m_edit_extruder_sequence = false;
- bool m_suppress_add_code = false;
- ManipulationState m_state = msSingleExtruder;
- std::string m_custom_gcode = "";
- std::string m_pause_print_msg;
+ bool m_force_edit_extruder_sequence = false;
+ bool m_force_mode_apply = true;
+ bool m_force_add_tick = false;
+ bool m_force_delete_tick = false;
+ t_mode m_mode = t_mode::SingleExtruder;
+ int m_only_extruder = -1;
wxRect m_rect_lower_thumb;
wxRect m_rect_higher_thumb;
@@ -957,50 +975,44 @@ private:
std::vector<wxPen*> m_line_pens;
std::vector<wxPen*> m_segm_pens;
- std::set<int> m_ticks;
std::vector<double> m_values;
- struct TICK_CODE
+ struct TICK_CODE_INFO
{
- bool operator<(const TICK_CODE& other) const { return other.tick > this->tick; }
- bool operator>(const TICK_CODE& other) const { return other.tick < this->tick; }
+ std::set<TICK_CODE> ticks;
+ t_mode mode = t_mode::SingleExtruder;
- int tick = 0;
- std::string gcode = Slic3r::ColorChangeCode;
- int extruder = 0;
- std::string color;
- };
+ bool empty() const { return ticks.empty(); }
+ void set_pause_print_msg(const std::string& message) { pause_print_msg = message; }
+
+ bool add_tick (const int tick, std::string &code, int extruder, double print_z);
+ bool edit_tick (std::set<TICK_CODE>::iterator it, double print_z);
+ void switch_code(const std::string& code_from, const std::string& code_to);
+ void erase_all_ticks_with_code (const std::string& gcode);
+ bool has_tick_with_code (const std::string& gcode);
- std::set<TICK_CODE> m_ticks_;
+ void suppress_plus (bool suppress) { m_suppress_plus = suppress;}
+ void suppress_minus(bool suppress) { m_suppress_minus = suppress;}
+ bool suppressed_plus () { return m_suppress_plus ; }
+ bool suppressed_minus() { return m_suppress_minus; }
+
+ private:
+
+ std::string custom_gcode = "";
+ std::string pause_print_msg = "";
+ bool m_suppress_plus = false;
+ bool m_suppress_minus = false;
+ }
+ m_ticks;
public:
struct ExtrudersSequence
{
- bool is_mm_intervals;
- double interval_by_mm;
- int interval_by_layers;
- std::vector<size_t> extruders;
-
- ExtrudersSequence() :
- is_mm_intervals(true),
- interval_by_mm(3.0),
- interval_by_layers(10),
- extruders({ 0 }) {}
-
- ExtrudersSequence(const ExtrudersSequence& other) :
- is_mm_intervals(other.is_mm_intervals),
- interval_by_mm(other.interval_by_mm),
- interval_by_layers(other.interval_by_layers),
- extruders(other.extruders) {}
-
- ExtrudersSequence& operator=(const ExtrudersSequence& other) {
- this->is_mm_intervals = other.is_mm_intervals;
- this->interval_by_mm = other.interval_by_mm;
- this->interval_by_layers= other.interval_by_layers;
- this->extruders = other.extruders;
-
- return *this;
- }
+ bool is_mm_intervals = true;
+ double interval_by_mm = 3.0;
+ int interval_by_layers = 10;
+ std::vector<size_t> extruders = { 0 };
+
bool operator==(const ExtrudersSequence& other) const
{
return (other.is_mm_intervals == this->is_mm_intervals ) &&