Merge remote-tracking branch 'origin/master' into lh_avoid_crossing_perimeters

# Conflicts:
#	src/libslic3r/MotionPlanner.cpp
#	src/libslic3r/libslic3r.h
This commit is contained in:
Lukáš Hejl 2020-11-29 17:27:23 +01:00
commit 87879034f6
175 changed files with 34821 additions and 26174 deletions

View file

@ -162,6 +162,8 @@ set(SLIC3R_GUI_SOURCES
GUI/Jobs/ArrangeJob.cpp
GUI/Jobs/RotoptimizeJob.hpp
GUI/Jobs/RotoptimizeJob.cpp
GUI/Jobs/FillBedJob.hpp
GUI/Jobs/FillBedJob.cpp
GUI/Jobs/SLAImportJob.hpp
GUI/Jobs/SLAImportJob.cpp
GUI/Jobs/ProgressIndicator.hpp

View file

@ -87,7 +87,7 @@ void Bed_2D::repaint(const std::vector<Vec2d>& shape)
for (auto y = bb.min(1) - fmod(bb.min(1), step) + step; y < bb.max(1); y += step) {
polylines.push_back(Polyline::new_scale({ Vec2d(bb.min(0), y), Vec2d(bb.max(0), y) }));
}
polylines = intersection_pl(polylines, bed_polygon);
polylines = intersection_pl(polylines, (Polygons)bed_polygon);
dc.SetPen(wxPen(wxColour(230, 230, 230), 1, wxPENSTYLE_SOLID));
for (auto pl : polylines)

View file

@ -5,24 +5,18 @@
#include "libslic3r/Polygon.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/BoundingBox.hpp"
#if ENABLE_GCODE_VIEWER
#include "libslic3r/Geometry.hpp"
#endif // ENABLE_GCODE_VIEWER
#include "GUI_App.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "GLCanvas3D.hpp"
#if ENABLE_GCODE_VIEWER
#include "3DScene.hpp"
#endif // ENABLE_GCODE_VIEWER
#include <GL/glew.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
#if ENABLE_GCODE_VIEWER
#include <boost/log/trivial.hpp>
#endif // ENABLE_GCODE_VIEWER
static const float GROUND_Z = -0.02f;
@ -121,43 +115,19 @@ const float* GeometryBuffer::get_vertices_data() const
return (m_vertices.size() > 0) ? (const float*)m_vertices.data() : nullptr;
}
#if ENABLE_GCODE_VIEWER
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
const float Bed3D::Axes::DefaultStemLength = 25.0f;
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
const float Bed3D::Axes::DefaultTipLength = 5.0f;
#else
const double Bed3D::Axes::Radius = 0.5;
const double Bed3D::Axes::ArrowBaseRadius = 2.5 * Bed3D::Axes::Radius;
const double Bed3D::Axes::ArrowLength = 5.0;
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
void Bed3D::Axes::set_stem_length(float length)
{
m_stem_length = length;
m_arrow.reset();
}
#else
Bed3D::Axes::Axes()
: origin(Vec3d::Zero())
, length(25.0 * Vec3d::Ones())
{
m_quadric = ::gluNewQuadric();
if (m_quadric != nullptr)
::gluQuadricDrawStyle(m_quadric, GLU_FILL);
}
Bed3D::Axes::~Axes()
{
if (m_quadric != nullptr)
::gluDeleteQuadric(m_quadric);
}
#endif // ENABLE_GCODE_VIEWER
void Bed3D::Axes::render() const
{
#if ENABLE_GCODE_VIEWER
auto render_axis = [this](const Transform3f& transform) {
glsafe(::glPushMatrix());
glsafe(::glMultMatrixf(transform.data()));
@ -193,56 +163,8 @@ void Bed3D::Axes::render() const
shader->stop_using();
glsafe(::glDisable(GL_DEPTH_TEST));
#else
if (m_quadric == nullptr)
return;
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glEnable(GL_LIGHTING));
// x axis
glsafe(::glColor3fv(AXES_COLOR[0]));
glsafe(::glPushMatrix());
glsafe(::glTranslated(origin(0), origin(1), origin(2)));
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
render_axis(length(0));
glsafe(::glPopMatrix());
// y axis
glsafe(::glColor3fv(AXES_COLOR[1]));
glsafe(::glPushMatrix());
glsafe(::glTranslated(origin(0), origin(1), origin(2)));
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
render_axis(length(1));
glsafe(::glPopMatrix());
// z axis
glsafe(::glColor3fv(AXES_COLOR[2]));
glsafe(::glPushMatrix());
glsafe(::glTranslated(origin(0), origin(1), origin(2)));
render_axis(length(2));
glsafe(::glPopMatrix());
glsafe(::glDisable(GL_LIGHTING));
glsafe(::glDisable(GL_DEPTH_TEST));
#endif // !ENABLE_GCODE_VIEWER
}
#if !ENABLE_GCODE_VIEWER
void Bed3D::Axes::render_axis(double length) const
{
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, Radius, Radius, length, 32, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, Radius, 32, 1);
glsafe(::glTranslated(0.0, 0.0, length));
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, ArrowBaseRadius, 0.0, ArrowLength, 32, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, ArrowBaseRadius, 32, 1);
}
#endif // !ENABLE_GCODE_VIEWER
Bed3D::Bed3D()
: m_type(Custom)
, m_vbo_id(0)
@ -308,13 +230,8 @@ bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, c
m_model.reset();
// Set the origin and size for rendering the coordinate system axes.
#if ENABLE_GCODE_VIEWER
m_axes.set_origin({ 0.0, 0.0, static_cast<double>(GROUND_Z) });
m_axes.set_stem_length(0.1f * static_cast<float>(m_bounding_box.max_size()));
#else
m_axes.origin = Vec3d(0.0, 0.0, (double)GROUND_Z);
m_axes.length = 0.1 * m_bounding_box.max_size() * Vec3d::Ones();
#endif // ENABLE_GCODE_VIEWER
// Let the calee to update the UI.
return true;
@ -360,7 +277,6 @@ void Bed3D::calc_bounding_boxes() const
m_extended_bounding_box = m_bounding_box;
// extend to contain axes
#if ENABLE_GCODE_VIEWER
m_extended_bounding_box.merge(m_axes.get_origin() + m_axes.get_total_length() * Vec3d::Ones());
m_extended_bounding_box.merge(m_extended_bounding_box.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, m_extended_bounding_box.max(2)));
@ -370,12 +286,6 @@ void Bed3D::calc_bounding_boxes() const
model_bb.translate(m_model_offset);
m_extended_bounding_box.merge(model_bb);
}
#else
m_extended_bounding_box.merge(m_axes.length + Axes::ArrowLength * Vec3d::Ones());
// extend to contain model, if any
if (!m_model.get_filename().empty())
m_extended_bounding_box.merge(m_model.get_transformed_bounding_box());
#endif // ENABLE_GCODE_VIEWER
}
void Bed3D::calc_triangles(const ExPolygon& poly)
@ -414,25 +324,6 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
printf("Unable to create bed grid lines\n");
}
#if !ENABLE_GCODE_VIEWER
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)
{
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;
}
#endif // !ENABLE_GCODE_VIEWER
std::tuple<Bed3D::EType, std::string, std::string> Bed3D::detect_type(const Pointfs& shape) const
{
@ -442,13 +333,8 @@ std::tuple<Bed3D::EType, std::string, std::string> Bed3D::detect_type(const Poin
while (curr != nullptr) {
if (curr->config.has("bed_shape")) {
if (shape == dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values) {
#if ENABLE_GCODE_VIEWER
std::string model_filename = PresetUtils::system_printer_bed_model(*curr);
std::string texture_filename = PresetUtils::system_printer_bed_texture(*curr);
#else
std::string model_filename = system_print_bed_model(*curr);
std::string texture_filename = system_print_bed_texture(*curr);
#endif // ENABLE_GCODE_VIEWER
if (!model_filename.empty() && !texture_filename.empty())
return { System, model_filename, texture_filename };
}
@ -614,11 +500,7 @@ void Bed3D::render_model() const
// 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();
shift(2) = -0.03;
#if ENABLE_GCODE_VIEWER
m_model_offset = shift;
#else
m_model.set_offset(shift);
#endif // ENABLE_GCODE_VIEWER
// update extended bounding box
calc_bounding_boxes();
@ -628,15 +510,11 @@ void Bed3D::render_model() const
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GCODE_VIEWER
shader->set_uniform("uniform_color", m_model_color);
::glPushMatrix();
::glTranslated(m_model_offset(0), m_model_offset(1), m_model_offset(2));
#endif // ENABLE_GCODE_VIEWER
m_model.render();
#if ENABLE_GCODE_VIEWER
::glPopMatrix();
#endif // ENABLE_GCODE_VIEWER
shader->stop_using();
}
}
@ -673,11 +551,7 @@ void Bed3D::render_default(bool bottom) const
if (!has_model && !bottom) {
// draw background
glsafe(::glDepthMask(GL_FALSE));
#if ENABLE_GCODE_VIEWER
glsafe(::glColor4fv(m_model_color.data()));
#else
glsafe(::glColor4f(0.35f, 0.35f, 0.35f, 0.4f));
#endif // ENABLE_GCODE_VIEWER
glsafe(::glNormal3d(0.0f, 0.0f, 1.0f));
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_vertices_data()));
glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)triangles_vcount));

View file

@ -3,19 +3,10 @@
#include "GLTexture.hpp"
#include "3DScene.hpp"
#if ENABLE_GCODE_VIEWER
#include "GLModel.hpp"
#endif // ENABLE_GCODE_VIEWER
#include <tuple>
#if ENABLE_GCODE_VIEWER
#include <array>
#endif // ENABLE_GCODE_VIEWER
#if !ENABLE_GCODE_VIEWER
class GLUquadric;
typedef class GLUquadric GLUquadricObj;
#endif // !ENABLE_GCODE_VIEWER
namespace Slic3r {
namespace GUI {
@ -52,7 +43,6 @@ public:
class Bed3D
{
#if ENABLE_GCODE_VIEWER
class Axes
{
public:
@ -62,43 +52,16 @@ class Bed3D
static const float DefaultTipLength;
private:
#else
struct Axes
{
static const double Radius;
static const double ArrowBaseRadius;
static const double ArrowLength;
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
Vec3d m_origin{ Vec3d::Zero() };
float m_stem_length{ DefaultStemLength };
mutable GLModel m_arrow;
public:
#else
Vec3d origin;
Vec3d length;
GLUquadricObj* m_quadric;
#endif // ENABLE_GCODE_VIEWER
#if !ENABLE_GCODE_VIEWER
Axes();
~Axes();
#endif // !ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
const Vec3d& get_origin() const { return m_origin; }
void set_origin(const Vec3d& origin) { m_origin = origin; }
void set_stem_length(float length);
float get_total_length() const { return m_stem_length + DefaultTipLength; }
#endif // ENABLE_GCODE_VIEWER
void render() const;
#if !ENABLE_GCODE_VIEWER
private:
void render_axis(double length) const;
#endif // !ENABLE_GCODE_VIEWER
};
public:
@ -120,13 +83,9 @@ private:
GeometryBuffer m_triangles;
GeometryBuffer m_gridlines;
mutable GLTexture m_texture;
#if ENABLE_GCODE_VIEWER
mutable GLModel m_model;
mutable Vec3d m_model_offset{ Vec3d::Zero() };
std::array<float, 4> m_model_color{ 0.235f, 0.235f, 0.235f, 1.0f };
#else
mutable GLBed m_model;
#endif // ENABLE_GCODE_VIEWER
// temporary texture shown until the main texture has still no levels compressed
mutable GLTexture m_temp_texture;
mutable unsigned int m_vbo_id;

View file

@ -993,290 +993,6 @@ bool GLVolumeCollection::has_toolpaths_to_export() const
return false;
}
#if !ENABLE_GCODE_VIEWER
void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
{
if (filename == nullptr)
return;
if (!has_toolpaths_to_export())
return;
// collect color information to generate materials
typedef std::array<float, 4> Color;
std::set<Color> colors;
for (const GLVolume* volume : this->volumes)
{
if (!can_export_to_obj(*volume))
continue;
Color color;
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
colors.insert(color);
}
// save materials file
boost::filesystem::path mat_filename(filename);
mat_filename.replace_extension("mtl");
FILE* fp = boost::nowide::fopen(mat_filename.string().c_str(), "w");
if (fp == nullptr) {
BOOST_LOG_TRIVIAL(error) << "GLVolumeCollection::export_toolpaths_to_obj: Couldn't open " << mat_filename.string().c_str() << " for writing";
return;
}
fprintf(fp, "# G-Code Toolpaths Materials\n");
fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
unsigned int colors_count = 1;
for (const Color& color : colors)
{
fprintf(fp, "\nnewmtl material_%d\n", colors_count++);
fprintf(fp, "Ka 1 1 1\n");
fprintf(fp, "Kd %f %f %f\n", color[0], color[1], color[2]);
fprintf(fp, "Ks 0 0 0\n");
}
fclose(fp);
// save geometry file
fp = boost::nowide::fopen(filename, "w");
if (fp == nullptr) {
BOOST_LOG_TRIVIAL(error) << "GLVolumeCollection::export_toolpaths_to_obj: Couldn't open " << filename << " for writing";
return;
}
fprintf(fp, "# G-Code Toolpaths\n");
fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
fprintf(fp, "\nmtllib ./%s\n", mat_filename.filename().string().c_str());
unsigned int vertices_count = 0;
unsigned int normals_count = 0;
unsigned int volumes_count = 0;
for (const GLVolume* volume : this->volumes)
{
if (!can_export_to_obj(*volume))
continue;
std::vector<float> src_vertices_and_normals_interleaved;
std::vector<int> src_triangle_indices;
std::vector<int> src_quad_indices;
if (!volume->indexed_vertex_array.vertices_and_normals_interleaved.empty())
// data are in CPU memory
src_vertices_and_normals_interleaved = volume->indexed_vertex_array.vertices_and_normals_interleaved;
else if ((volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id != 0) && (volume->indexed_vertex_array.vertices_and_normals_interleaved_size != 0))
{
// data are in GPU memory
src_vertices_and_normals_interleaved = std::vector<float>(volume->indexed_vertex_array.vertices_and_normals_interleaved_size, 0.0f);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id));
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, src_vertices_and_normals_interleaved.size() * sizeof(float), src_vertices_and_normals_interleaved.data()));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
else
continue;
if (!volume->indexed_vertex_array.triangle_indices.empty())
{
// data are in CPU memory
size_t size = std::min(volume->indexed_vertex_array.triangle_indices.size(), volume->tverts_range.second - volume->tverts_range.first);
if (size != 0)
{
std::vector<int>::const_iterator it_begin = volume->indexed_vertex_array.triangle_indices.begin() + volume->tverts_range.first;
std::vector<int>::const_iterator it_end = volume->indexed_vertex_array.triangle_indices.begin() + volume->tverts_range.first + size;
std::copy(it_begin, it_end, std::back_inserter(src_triangle_indices));
}
}
else if ((volume->indexed_vertex_array.triangle_indices_VBO_id != 0) && (volume->indexed_vertex_array.triangle_indices_size != 0))
{
// data are in GPU memory
size_t size = std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first);
if (size != 0)
{
src_triangle_indices = std::vector<int>(size, 0);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.triangle_indices_VBO_id));
glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->tverts_range.first * sizeof(int), size * sizeof(int), src_triangle_indices.data()));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
}
if (!volume->indexed_vertex_array.quad_indices.empty())
{
// data are in CPU memory
size_t size = std::min(volume->indexed_vertex_array.quad_indices.size(), volume->qverts_range.second - volume->qverts_range.first);
if (size != 0)
{
std::vector<int>::const_iterator it_begin = volume->indexed_vertex_array.quad_indices.begin() + volume->qverts_range.first;
std::vector<int>::const_iterator it_end = volume->indexed_vertex_array.quad_indices.begin() + volume->qverts_range.first + size;
std::copy(it_begin, it_end, std::back_inserter(src_quad_indices));
}
}
else if ((volume->indexed_vertex_array.quad_indices_VBO_id != 0) && (volume->indexed_vertex_array.quad_indices_size != 0))
{
// data are in GPU memory
size_t size = std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first);
if (size != 0)
{
src_quad_indices = std::vector<int>(size, 0);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.quad_indices_VBO_id));
glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->qverts_range.first * sizeof(int), size * sizeof(int), src_quad_indices.data()));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
}
if (src_triangle_indices.empty() && src_quad_indices.empty())
continue;
++volumes_count;
// reduce output size by keeping only used vertices and normals
struct Vector
{
std::array<coord_t, 3> vector;
explicit Vector(float* ptr)
{
vector[0] = scale_(*(ptr + 0));
vector[1] = scale_(*(ptr + 1));
vector[2] = scale_(*(ptr + 2));
}
};
typedef std::vector<Vector> Vectors;
auto vector_less = [](const Vector& v1, const Vector& v2)->bool {
return v1.vector < v2.vector;
};
auto vector_equal = [](const Vector& v1, const Vector& v2)->bool {
return (v1.vector[0] == v2.vector[0]) && (v1.vector[1] == v2.vector[1]) && (v1.vector[2] == v2.vector[2]);
};
// copy used vertices and normals data
Vectors dst_normals;
Vectors dst_vertices;
unsigned int src_triangle_indices_size = (unsigned int)src_triangle_indices.size();
for (unsigned int i = 0; i < src_triangle_indices_size; ++i)
{
float* src_ptr = src_vertices_and_normals_interleaved.data() + src_triangle_indices[i] * 6;
dst_normals.emplace_back(src_ptr + 0);
dst_vertices.emplace_back(src_ptr + 3);
}
unsigned int src_quad_indices_size = (unsigned int)src_quad_indices.size();
for (unsigned int i = 0; i < src_quad_indices_size; ++i)
{
float* src_ptr = src_vertices_and_normals_interleaved.data() + src_quad_indices[i] * 6;
dst_normals.emplace_back(src_ptr + 0);
dst_vertices.emplace_back(src_ptr + 3);
}
// sort vertices and normals
std::sort(dst_normals.begin(), dst_normals.end(), vector_less);
std::sort(dst_vertices.begin(), dst_vertices.end(), vector_less);
// remove duplicated vertices and normals
dst_normals.erase(std::unique(dst_normals.begin(), dst_normals.end(), vector_equal), dst_normals.end());
dst_vertices.erase(std::unique(dst_vertices.begin(), dst_vertices.end(), vector_equal), dst_vertices.end());
// reindex triangles and quads
struct IndicesPair
{
int vertex;
int normal;
IndicesPair(int vertex, int normal) : vertex(vertex), normal(normal) {}
};
typedef std::vector<IndicesPair> Indices;
unsigned int src_vertices_count = (unsigned int)src_vertices_and_normals_interleaved.size() / 6;
std::vector<int> src_dst_vertex_indices_map(src_vertices_count, -1);
std::vector<int> src_dst_normal_indices_map(src_vertices_count, -1);
for (unsigned int i = 0; i < src_vertices_count; ++i)
{
float* src_ptr = src_vertices_and_normals_interleaved.data() + i * 6;
src_dst_normal_indices_map[i] = std::distance(dst_normals.begin(), std::lower_bound(dst_normals.begin(), dst_normals.end(), Vector(src_ptr + 0), vector_less));
src_dst_vertex_indices_map[i] = std::distance(dst_vertices.begin(), std::lower_bound(dst_vertices.begin(), dst_vertices.end(), Vector(src_ptr + 3), vector_less));
}
Indices dst_triangle_indices;
if (src_triangle_indices_size > 0)
dst_triangle_indices.reserve(src_triangle_indices_size);
for (unsigned int i = 0; i < src_triangle_indices_size; ++i)
{
int id = src_triangle_indices[i];
dst_triangle_indices.emplace_back(src_dst_vertex_indices_map[id], src_dst_normal_indices_map[id]);
}
Indices dst_quad_indices;
if (src_quad_indices_size > 0)
dst_quad_indices.reserve(src_quad_indices_size);
for (unsigned int i = 0; i < src_quad_indices_size; ++i)
{
int id = src_quad_indices[i];
dst_quad_indices.emplace_back(src_dst_vertex_indices_map[id], src_dst_normal_indices_map[id]);
}
// save to file
fprintf(fp, "\n# vertices volume %d\n", volumes_count);
for (const Vector& v : dst_vertices)
{
fprintf(fp, "v %g %g %g\n", unscale<float>(v.vector[0]), unscale<float>(v.vector[1]), unscale<float>(v.vector[2]));
}
fprintf(fp, "\n# normals volume %d\n", volumes_count);
for (const Vector& n : dst_normals)
{
fprintf(fp, "vn %g %g %g\n", unscale<float>(n.vector[0]), unscale<float>(n.vector[1]), unscale<float>(n.vector[2]));
}
Color color;
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
fprintf(fp, "\n# material volume %d\n", volumes_count);
fprintf(fp, "usemtl material_%lld\n", (long long)(1 + std::distance(colors.begin(), colors.find(color))));
int base_vertex_id = vertices_count + 1;
int base_normal_id = normals_count + 1;
if (!dst_triangle_indices.empty())
{
fprintf(fp, "\n# triangular facets volume %d\n", volumes_count);
for (unsigned int i = 0; i < (unsigned int)dst_triangle_indices.size(); i += 3)
{
fprintf(fp, "f %d//%d %d//%d %d//%d\n",
base_vertex_id + dst_triangle_indices[i + 0].vertex, base_normal_id + dst_triangle_indices[i + 0].normal,
base_vertex_id + dst_triangle_indices[i + 1].vertex, base_normal_id + dst_triangle_indices[i + 1].normal,
base_vertex_id + dst_triangle_indices[i + 2].vertex, base_normal_id + dst_triangle_indices[i + 2].normal);
}
}
if (!dst_quad_indices.empty())
{
fprintf(fp, "\n# quadrangular facets volume %d\n", volumes_count);
for (unsigned int i = 0; i < (unsigned int)src_quad_indices.size(); i += 4)
{
fprintf(fp, "f %d//%d %d//%d %d//%d %d//%d\n",
base_vertex_id + dst_quad_indices[i + 0].vertex, base_normal_id + dst_quad_indices[i + 0].normal,
base_vertex_id + dst_quad_indices[i + 1].vertex, base_normal_id + dst_quad_indices[i + 1].normal,
base_vertex_id + dst_quad_indices[i + 2].vertex, base_normal_id + dst_quad_indices[i + 2].normal,
base_vertex_id + dst_quad_indices[i + 3].vertex, base_normal_id + dst_quad_indices[i + 3].normal);
}
}
vertices_count += (unsigned int)dst_vertices.size();
normals_count += (unsigned int)dst_normals.size();
}
fclose(fp);
}
#endif // !ENABLE_GCODE_VIEWER
// caller is responsible for supplying NO lines with zero length
static void thick_lines_to_indexed_vertex_array(
const Lines &lines,
@ -1923,287 +1639,4 @@ void _3DScene::point3_to_verts(const Vec3crd& point, double width, double height
thick_point_to_verts(point, width, height, volume);
}
#if !ENABLE_GCODE_VIEWER
GLModel::GLModel()
: m_filename("")
{
m_volume.shader_outside_printer_detection_enabled = false;
}
GLModel::~GLModel()
{
reset();
}
void GLModel::set_color(const float* color, unsigned int size)
{
::memcpy((void*)m_volume.color, (const void*)color, (size_t)(std::min((unsigned int)4, size) * sizeof(float)));
m_volume.set_render_color(color, size);
}
const Vec3d& GLModel::get_offset() const
{
return m_volume.get_volume_offset();
}
void GLModel::set_offset(const Vec3d& offset)
{
m_volume.set_volume_offset(offset);
}
const Vec3d& GLModel::get_rotation() const
{
return m_volume.get_volume_rotation();
}
void GLModel::set_rotation(const Vec3d& rotation)
{
m_volume.set_volume_rotation(rotation);
}
const Vec3d& GLModel::get_scale() const
{
return m_volume.get_volume_scaling_factor();
}
void GLModel::set_scale(const Vec3d& scale)
{
m_volume.set_volume_scaling_factor(scale);
}
void GLModel::reset()
{
m_volume.indexed_vertex_array.release_geometry();
m_filename = "";
}
void GLModel::render() const
{
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr)
return;
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glsafe(::glCullFace(GL_BACK));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
shader->set_uniform("uniform_color", m_volume.render_color, 4);
m_volume.render();
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glDisable(GL_BLEND));
}
bool GLArrow::on_init()
{
Pointf3s vertices;
std::vector<Vec3i> triangles;
// bottom face
vertices.emplace_back(0.5, 0.0, -0.1);
vertices.emplace_back(0.5, 2.0, -0.1);
vertices.emplace_back(1.0, 2.0, -0.1);
vertices.emplace_back(0.0, 3.0, -0.1);
vertices.emplace_back(-1.0, 2.0, -0.1);
vertices.emplace_back(-0.5, 2.0, -0.1);
vertices.emplace_back(-0.5, 0.0, -0.1);
// top face
vertices.emplace_back(0.5, 0.0, 0.1);
vertices.emplace_back(0.5, 2.0, 0.1);
vertices.emplace_back(1.0, 2.0, 0.1);
vertices.emplace_back(0.0, 3.0, 0.1);
vertices.emplace_back(-1.0, 2.0, 0.1);
vertices.emplace_back(-0.5, 2.0, 0.1);
vertices.emplace_back(-0.5, 0.0, 0.1);
// bottom face
triangles.emplace_back(0, 6, 1);
triangles.emplace_back(6, 5, 1);
triangles.emplace_back(5, 4, 3);
triangles.emplace_back(5, 3, 1);
triangles.emplace_back(1, 3, 2);
// top face
triangles.emplace_back(7, 8, 13);
triangles.emplace_back(13, 8, 12);
triangles.emplace_back(12, 10, 11);
triangles.emplace_back(8, 10, 12);
triangles.emplace_back(8, 9, 10);
// side face
triangles.emplace_back(0, 1, 8);
triangles.emplace_back(8, 7, 0);
triangles.emplace_back(1, 2, 9);
triangles.emplace_back(9, 8, 1);
triangles.emplace_back(2, 3, 10);
triangles.emplace_back(10, 9, 2);
triangles.emplace_back(3, 4, 11);
triangles.emplace_back(11, 10, 3);
triangles.emplace_back(4, 5, 12);
triangles.emplace_back(12, 11, 4);
triangles.emplace_back(5, 6, 13);
triangles.emplace_back(13, 12, 5);
triangles.emplace_back(6, 0, 7);
triangles.emplace_back(7, 13, 6);
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
m_volume.indexed_vertex_array.finalize_geometry(true);
return true;
}
GLCurvedArrow::GLCurvedArrow(unsigned int resolution)
: GLModel()
, m_resolution(resolution)
{
if (m_resolution == 0)
m_resolution = 1;
}
bool GLCurvedArrow::on_init()
{
Pointf3s vertices;
std::vector<Vec3i> triangles;
double ext_radius = 2.5;
double int_radius = 1.5;
double step = 0.5 * (double)PI / (double)m_resolution;
unsigned int vertices_per_level = 4 + 2 * m_resolution;
// bottom face
vertices.emplace_back(0.0, 1.5, -0.1);
vertices.emplace_back(0.0, 1.0, -0.1);
vertices.emplace_back(-1.0, 2.0, -0.1);
vertices.emplace_back(0.0, 3.0, -0.1);
vertices.emplace_back(0.0, 2.5, -0.1);
for (unsigned int i = 1; i <= m_resolution; ++i)
{
double angle = (double)i * step;
double x = ext_radius * ::sin(angle);
double y = ext_radius * ::cos(angle);
vertices.emplace_back(x, y, -0.1);
}
for (unsigned int i = 0; i < m_resolution; ++i)
{
double angle = (double)i * step;
double x = int_radius * ::cos(angle);
double y = int_radius * ::sin(angle);
vertices.emplace_back(x, y, -0.1);
}
// top face
vertices.emplace_back(0.0, 1.5, 0.1);
vertices.emplace_back(0.0, 1.0, 0.1);
vertices.emplace_back(-1.0, 2.0, 0.1);
vertices.emplace_back(0.0, 3.0, 0.1);
vertices.emplace_back(0.0, 2.5, 0.1);
for (unsigned int i = 1; i <= m_resolution; ++i)
{
double angle = (double)i * step;
double x = ext_radius * ::sin(angle);
double y = ext_radius * ::cos(angle);
vertices.emplace_back(x, y, 0.1);
}
for (unsigned int i = 0; i < m_resolution; ++i)
{
double angle = (double)i * step;
double x = int_radius * ::cos(angle);
double y = int_radius * ::sin(angle);
vertices.emplace_back(x, y, 0.1);
}
// bottom face
triangles.emplace_back(0, 1, 2);
triangles.emplace_back(0, 2, 4);
triangles.emplace_back(4, 2, 3);
int first_id = 4;
int last_id = (int)vertices_per_level;
triangles.emplace_back(last_id, 0, first_id);
triangles.emplace_back(last_id, first_id, first_id + 1);
for (unsigned int i = 1; i < m_resolution; ++i)
{
triangles.emplace_back(last_id - i, last_id - i + 1, first_id + i);
triangles.emplace_back(last_id - i, first_id + i, first_id + i + 1);
}
// top face
last_id += 1;
triangles.emplace_back(last_id + 0, last_id + 2, last_id + 1);
triangles.emplace_back(last_id + 0, last_id + 4, last_id + 2);
triangles.emplace_back(last_id + 4, last_id + 3, last_id + 2);
first_id = last_id + 4;
last_id = last_id + 4 + 2 * (int)m_resolution;
triangles.emplace_back(last_id, first_id, (int)vertices_per_level + 1);
triangles.emplace_back(last_id, first_id + 1, first_id);
for (unsigned int i = 1; i < m_resolution; ++i)
{
triangles.emplace_back(last_id - i, first_id + i, last_id - i + 1);
triangles.emplace_back(last_id - i, first_id + i + 1, first_id + i);
}
// side face
for (unsigned int i = 0; i < 4 + 2 * (unsigned int)m_resolution; ++i)
{
triangles.emplace_back(i, vertices_per_level + 2 + i, i + 1);
triangles.emplace_back(i, vertices_per_level + 1 + i, vertices_per_level + 2 + i);
}
triangles.emplace_back(vertices_per_level, vertices_per_level + 1, 0);
triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1);
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles));
m_volume.indexed_vertex_array.finalize_geometry(true);
return true;
}
bool GLBed::on_init_from_file(const std::string& filename)
{
reset();
if (!boost::filesystem::exists(filename))
return false;
if (!boost::algorithm::iends_with(filename, ".stl"))
return false;
Model model;
try
{
model = Model::read_from_file(filename);
}
catch (std::exception & /* ex */)
{
return false;
}
m_filename = filename;
m_volume.indexed_vertex_array.load_mesh(model.mesh());
m_volume.indexed_vertex_array.finalize_geometry(true);
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
set_color(color, 4);
return true;
}
#endif // !ENABLE_GCODE_VIEWER
} // namespace Slic3r

View file

@ -588,10 +588,6 @@ public:
std::string log_memory_info() const;
bool has_toolpaths_to_export() const;
#if !ENABLE_GCODE_VIEWER
// Export the geometry of the GLVolumes toolpaths of this collection into the file with the given path, in obj format
void export_toolpaths_to_obj(const char* filename) const;
#endif // !ENABLE_GCODE_VIEWER
private:
GLVolumeCollection(const GLVolumeCollection &other);
@ -600,68 +596,6 @@ private:
GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = nullptr);
#if !ENABLE_GCODE_VIEWER
class GLModel
{
protected:
GLVolume m_volume;
std::string m_filename;
public:
GLModel();
virtual ~GLModel();
// init() / init_from_file() shall be called with the OpenGL context active!
bool init() { return on_init(); }
bool init_from_file(const std::string& filename) { return on_init_from_file(filename); }
void center_around(const Vec3d& center) { m_volume.set_volume_offset(center - m_volume.bounding_box().center()); }
void set_color(const float* color, unsigned int size);
const Vec3d& get_offset() const;
void set_offset(const Vec3d& offset);
const Vec3d& get_rotation() const;
void set_rotation(const Vec3d& rotation);
const Vec3d& get_scale() const;
void set_scale(const Vec3d& scale);
const std::string& get_filename() const { return m_filename; }
const BoundingBoxf3& get_bounding_box() const { return m_volume.bounding_box(); }
const BoundingBoxf3& get_transformed_bounding_box() const { return m_volume.transformed_bounding_box(); }
void reset();
void render() const;
protected:
virtual bool on_init() { return false; }
virtual bool on_init_from_file(const std::string& filename) { return false; }
};
class GLArrow : public GLModel
{
protected:
bool on_init() override;
};
class GLCurvedArrow : public GLModel
{
unsigned int m_resolution;
public:
explicit GLCurvedArrow(unsigned int resolution);
protected:
bool on_init() override;
};
class GLBed : public GLModel
{
protected:
bool on_init_from_file(const std::string& filename) override;
};
#endif // !ENABLE_GCODE_VIEWER
struct _3DScene
{
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);

View file

@ -4,7 +4,7 @@
#include "libslic3r/Utils.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
namespace Slic3r {
namespace GUI {
@ -37,17 +37,10 @@ void AboutDialogLogo::onRepaint(wxEvent &event)
// CopyrightsDialog
// -----------------------------------------
CopyrightsDialog::CopyrightsDialog()
#if ENABLE_GCODE_VIEWER
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format("%1% - %2%")
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, from_u8((boost::format("%1% - %2%")
% (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME)
% _utf8(L("Portions copyright"))).str()),
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
#else
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format("%1% - %2%")
% SLIC3R_APP_NAME
% _utf8(L("Portions copyright"))).str()),
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
#endif // ENABLE_GCODE_VIEWER
{
this->SetFont(wxGetApp().normal_font());
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
@ -208,13 +201,8 @@ void CopyrightsDialog::onCloseDialog(wxEvent &)
}
AboutDialog::AboutDialog()
#if ENABLE_GCODE_VIEWER
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME)).str()), wxDefaultPosition,
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME)).str()), wxDefaultPosition,
wxDefaultSize, /*wxCAPTION*/wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
#else
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % SLIC3R_APP_NAME).str()), wxDefaultPosition,
wxDefaultSize, /*wxCAPTION*/wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
#endif // ENABLE_GCODE_VIEWER
{
SetFont(wxGetApp().normal_font());
@ -226,11 +214,7 @@ AboutDialog::AboutDialog()
main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
// logo
#if ENABLE_GCODE_VIEWER
m_logo_bitmap = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_192px.png" : "PrusaSlicer-gcodeviewer_192px.png", 192);
#else
m_logo_bitmap = ScalableBitmap(this, "PrusaSlicer_192px.png", 192);
#endif // ENABLE_GCODE_VIEWER
m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp());
hsizer->Add(m_logo, 1, wxALIGN_CENTER_VERTICAL);
@ -239,11 +223,7 @@ AboutDialog::AboutDialog()
// title
{
#if ENABLE_GCODE_VIEWER
wxStaticText* title = new wxStaticText(this, wxID_ANY, wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME, wxDefaultPosition, wxDefaultSize);
#else
wxStaticText* title = new wxStaticText(this, wxID_ANY, SLIC3R_APP_NAME, wxDefaultPosition, wxDefaultSize);
#endif // ENABLE_GCODE_VIEWER
wxFont title_font = GUI::wxGetApp().bold_font();
title_font.SetFamily(wxFONTFAMILY_ROMAN);
title_font.SetPointSize(24);
@ -253,7 +233,7 @@ AboutDialog::AboutDialog()
// version
{
auto version_string = _L("Version")+ " " + std::string(SLIC3R_VERSION);
auto version_string = _L("Version") + " " + std::string(SLIC3R_VERSION);
wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize);
wxFont version_font = GetFont();
#ifdef __WXMSW__

View file

@ -141,11 +141,7 @@ void BackgroundSlicingProcess::process_fff()
// Passing the timestamp
evt.SetInt((int)(m_fff_print->step_state_with_timestamp(PrintStep::psSlicingFinished).timestamp));
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone());
#if ENABLE_GCODE_VIEWER
m_fff_print->export_gcode(m_temp_output_path, m_gcode_result, m_thumbnail_cb);
#else
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_cb);
#endif // ENABLE_GCODE_VIEWER
if (this->set_step_started(bspsGCodeFinalize)) {
if (! m_export_path.empty()) {
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id));
@ -433,25 +429,14 @@ Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const Dyn
assert(m_print != nullptr);
assert(config.opt_enum<PrinterTechnology>("printer_technology") == m_print->technology());
Print::ApplyStatus invalidated = m_print->apply(model, config);
#if ENABLE_GCODE_VIEWER
if ((invalidated & PrintBase::APPLY_STATUS_INVALIDATED) != 0 && m_print->technology() == ptFFF &&
!this->m_fff_print->is_step_done(psGCodeExport))
{
!this->m_fff_print->is_step_done(psGCodeExport)) {
// Some FFF status was invalidated, and the G-code was not exported yet.
// Let the G-code preview UI know that the final G-code preview is not valid.
// In addition, this early memory deallocation reduces memory footprint.
if (m_gcode_result != nullptr)
m_gcode_result->reset();
}
#else
if ((invalidated & PrintBase::APPLY_STATUS_INVALIDATED) != 0 && m_print->technology() == ptFFF &&
m_gcode_preview_data != nullptr && ! this->m_fff_print->is_step_done(psGCodeExport)) {
// Some FFF status was invalidated, and the G-code was not exported yet.
// Let the G-code preview UI know that the final G-code preview is not valid.
// In addition, this early memory deallocation reduces memory footprint.
m_gcode_preview_data->reset();
}
#endif // ENABLE_GCODE_VIEWER
return invalidated;
}

View file

@ -11,9 +11,7 @@
#include "libslic3r/GCode/ThumbnailData.hpp"
#include "libslic3r/Format/SL1.hpp"
#include "slic3r/Utils/PrintHost.hpp"
#if ENABLE_GCODE_VIEWER
#include "libslic3r/GCode/GCodeProcessor.hpp"
#endif // ENABLE_GCODE_VIEWER
namespace boost { namespace filesystem { class path; } }
@ -21,9 +19,6 @@ namespace boost { namespace filesystem { class path; } }
namespace Slic3r {
class DynamicPrintConfig;
#if !ENABLE_GCODE_VIEWER
class GCodePreviewData;
#endif // !ENABLE_GCODE_VIEWER
class Model;
class SLAPrint;
@ -88,11 +83,7 @@ public:
void set_fff_print(Print *print) { m_fff_print = print; }
void set_sla_print(SLAPrint *print) { m_sla_print = print; m_sla_print->set_printer(&m_sla_archive); }
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
#if ENABLE_GCODE_VIEWER
void set_gcode_result(GCodeProcessor::Result* result) { m_gcode_result = result; }
#else
void set_gcode_preview_data(GCodePreviewData* gpd) { m_gcode_preview_data = gpd; }
#endif // ENABLE_GCODE_VIEWER
// 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.
@ -198,13 +189,8 @@ private:
// Non-owned pointers to Print instances.
Print *m_fff_print = nullptr;
SLAPrint *m_sla_print = nullptr;
#if ENABLE_GCODE_VIEWER
// Data structure, to which the G-code export writes its annotations.
GCodeProcessor::Result *m_gcode_result = nullptr;
#else
// Data structure, to which the G-code export writes its annotations.
GCodePreviewData *m_gcode_preview_data = nullptr;
#endif // ENABLE_GCODE_VIEWER
// Callback function, used to write thumbnails into gcode.
ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr;
SL1Archive m_sla_archive;

View file

@ -3,9 +3,7 @@
#include "libslic3r/Utils.hpp"
#include "../Utils/MacDarkMode.hpp"
#include "GUI.hpp"
#if ENABLE_GCODE_VIEWER
#include "GUI_Utils.hpp"
#endif // ENABLE_GCODE_VIEWER
#include <boost/filesystem.hpp>
@ -357,17 +355,6 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi
return wxImage_to_wxBitmap_with_alpha(std::move(image), scale);
}
#if !ENABLE_GCODE_VIEWER
static inline int hex_digit_to_int(const char c)
{
return
(c >= '0' && c <= '9') ? int(c - '0') :
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
}
#endif // !ENABLE_GCODE_VIEWER
bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out)
{
rgb_out[0] = rgb_out[1] = rgb_out[2] = 0;

View file

@ -237,8 +237,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0;
// infill_extruder uses the same logic as in Print::extruders()
for (auto el : { "fill_pattern", "infill_every_layers", "infill_only_where_needed",
"solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" })
"solid_infill_every_layers", "solid_infill_below_area", "infill_extruder", "infill_anchor_max" })
toggle_field(el, have_infill);
// Only allow configuration of open anchors if the anchoring is enabled.
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("infill_anchor_max")->value > 0;
toggle_field("infill_anchor", has_infill_anchors);
bool has_spiral_vase = config->opt_bool("spiral_vase");
bool has_top_solid_infill = config->opt_int("top_solid_layers") > 0;

View file

@ -6,6 +6,7 @@
#include "libslic3r/Utils.hpp"
#include "libslic3r/Time.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
#include "wxExtensions.hpp"
namespace Slic3r {
@ -109,7 +110,7 @@ static wxString generate_html_page(const Config::SnapshotDB &snapshot_db, const
}
ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const wxString &on_snapshot)
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition,
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition,
wxSize(45 * wxGetApp().em_unit(), 40 * wxGetApp().em_unit()),
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
{

View file

@ -192,26 +192,23 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
wxBitmap bitmap;
int bitmap_width = 0;
int bitmap_height = 0;
const wxString bitmap_file = GUI::from_u8(Slic3r::resources_dir() + "/profiles/" + vendor.id + "/" + model.id + "_thumbnail.png");
if (wxFileExists(bitmap_file)) {
bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG);
bitmap_width = bitmap.GetWidth();
bitmap_height = bitmap.GetHeight();
} else {
BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead")
% bitmap_file
% vendor.id
% model.id;
const wxString placeholder_file = GUI::from_u8(Slic3r::var(PRINTER_PLACEHOLDER));
if (wxFileExists(placeholder_file)) {
bitmap.LoadFile(placeholder_file, wxBITMAP_TYPE_PNG);
auto load_bitmap = [](const wxString& bitmap_file, wxBitmap& bitmap, int& bitmap_width)->bool {
if (wxFileExists(bitmap_file)) {
bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG);
bitmap_width = bitmap.GetWidth();
bitmap_height = bitmap.GetHeight();
return true;
}
return false;
};
if (!load_bitmap(GUI::from_u8(Slic3r::data_dir() + "/vendor/" + vendor.id + "/" + model.id + "_thumbnail.png"), bitmap, bitmap_width)) {
if (!load_bitmap(GUI::from_u8(Slic3r::resources_dir() + "/profiles/" + vendor.id + "/" + model.id + "_thumbnail.png"), bitmap, bitmap_width)) {
BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead")
% (Slic3r::resources_dir() + "/profiles/" + vendor.id + "/" + model.id + "_thumbnail.png")
% vendor.id
% model.id;
load_bitmap(Slic3r::var(PRINTER_PLACEHOLDER), bitmap, bitmap_width);
}
}
auto *title = new wxStaticText(this, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
title->SetFont(font_name);
const int wrap_width = std::max((int)MODEL_MIN_WRAP, bitmap_width);
@ -241,7 +238,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
: from_u8(model.name);
if (i == 1) {
auto *alt_label = new wxStaticText(variants_panel, wxID_ANY, _(L("Alternate nozzles:")));
auto *alt_label = new wxStaticText(variants_panel, wxID_ANY, _L("Alternate nozzles:"));
alt_label->SetFont(font_alt_nozzle);
variants_sizer->Add(alt_label, 0, wxBOTTOM, 3);
is_variants = true;
@ -305,9 +302,9 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
if (/*titles.size() > 1*/is_variants) {
// It only makes sense to add the All / None buttons if there's multiple printers
auto *sel_all_std = new wxButton(this, wxID_ANY, titles.size() > 1 ? _(L("All standard")) : _(L("Standard")));
auto *sel_all = new wxButton(this, wxID_ANY, _(L("All")));
auto *sel_none = new wxButton(this, wxID_ANY, _(L("None")));
auto *sel_all_std = new wxButton(this, wxID_ANY, titles.size() > 1 ? _L("All standard") : _L("Standard"));
auto *sel_all = new wxButton(this, wxID_ANY, _L("All"));
auto *sel_none = new wxButton(this, wxID_ANY, _L("None"));
sel_all_std->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(true, false); });
sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(true, true); });
sel_none->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(false); });
@ -447,14 +444,14 @@ PageWelcome::PageWelcome(ConfigWizard *parent)
#else
_utf8(L("Welcome to the %s Configuration Wizard"))
#endif
) % SLIC3R_APP_NAME).str()), _(L("Welcome")))
) % SLIC3R_APP_NAME).str()), _L("Welcome"))
, welcome_text(append_text(from_u8((boost::format(
_utf8(L("Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")))
% SLIC3R_APP_NAME
% _utf8(ConfigWizard::name())).str())
))
, cbox_reset(append(
new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles (a snapshot will be taken beforehand)")))
new wxCheckBox(this, wxID_ANY, _L("Remove user profiles (a snapshot will be taken beforehand)"))
))
{
welcome_text->Hide();
@ -585,10 +582,10 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
grid->AddGrowableCol(3, 1);
grid->AddGrowableRow(1, 1);
grid->Add(new wxStaticText(this, wxID_ANY, _(L("Printer:"))));
grid->Add(new wxStaticText(this, wxID_ANY, _L("Printer:")));
grid->Add(new wxStaticText(this, wxID_ANY, list1name));
grid->Add(new wxStaticText(this, wxID_ANY, _(L("Vendor:"))));
grid->Add(new wxStaticText(this, wxID_ANY, _(L("Profile:"))));
grid->Add(new wxStaticText(this, wxID_ANY, _L("Vendor:")));
grid->Add(new wxStaticText(this, wxID_ANY, _L("Profile:")));
grid->Add(list_printer, 0, wxEXPAND);
grid->Add(list_type, 0, wxEXPAND);
@ -596,8 +593,8 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
grid->Add(list_profile, 1, wxEXPAND);
auto *btn_sizer = new wxBoxSizer(wxHORIZONTAL);
auto *sel_all = new wxButton(this, wxID_ANY, _(L("All")));
auto *sel_none = new wxButton(this, wxID_ANY, _(L("None")));
auto *sel_all = new wxButton(this, wxID_ANY, _L("All"));
auto *sel_none = new wxButton(this, wxID_ANY, _L("None"));
btn_sizer->Add(sel_all, 0, wxRIGHT, em / 2);
btn_sizer->Add(sel_none);
@ -660,7 +657,7 @@ void PageMaterials::reload_presets()
{
clear();
list_printer->append(_(L("(All)")), &EMPTY);
list_printer->append(_L("(All)"), &EMPTY);
//list_printer->SetLabelMarkup("<b>bald</b>");
for (const Preset* printer : materials->printers) {
list_printer->append(printer->name, &printer->name);
@ -689,10 +686,10 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
wxString first_line = _(L("Filaments marked with <b>*</b> are <b>not</b> compatible with some installed printers."));
wxString first_line = _L("Filaments marked with <b>*</b> are <b>not</b> compatible with some installed printers.");
wxString text;
if (all_printers) {
wxString second_line = _(L("All installed printers are compatible with the selected filament."));
wxString second_line = _L("All installed printers are compatible with the selected filament.");
text = wxString::Format(
"<html>"
"<style>"
@ -712,7 +709,7 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
, second_line
);
} else {
wxString second_line = _(L("Only the following installed printers are compatible with the selected filament:"));
wxString second_line = _L("Only the following installed printers are compatible with the selected filament:");
text = wxString::Format(
"<html>"
"<style>"
@ -810,7 +807,7 @@ void PageMaterials::update_lists(int sel_printer, int sel_type, int sel_vendor)
if (sel_printers_count != sel_printer_count_prev || (sel_printers_count == 1 && sel_printer_item_prev != sel_printer && sel_printer != -1)) {
// Refresh type list
list_type->Clear();
list_type->append(_(L("(All)")), &EMPTY);
list_type->append(_L("(All)"), &EMPTY);
if (sel_printers_count > 0) {
// If all is selected with other printers
// unselect "all" or all printers depending on last value
@ -871,7 +868,7 @@ void PageMaterials::update_lists(int sel_printer, int sel_type, int sel_vendor)
// but the number of vendors is going to be very small this shouldn't be a problem.
list_vendor->Clear();
list_vendor->append(_(L("(All)")), &EMPTY);
list_vendor->append(_L("(All)"), &EMPTY);
if (sel_printers_count != 0 && sel_type != wxNOT_FOUND) {
const std::string& type = list_type->get_data(sel_type);
// find printer preset
@ -1008,7 +1005,7 @@ void PageMaterials::sort_list_data(StringList* list, bool add_All_item, bool mat
list->Clear();
if (add_All_item)
list->append(_(L("(All)")), &EMPTY);
list->append(_L("(All)"), &EMPTY);
for (const auto& item : prusa_profiles)
list->append(item, &const_cast<std::string&>(item.get()));
for (const auto& item : other_profiles)
@ -1098,11 +1095,11 @@ void PageMaterials::on_activate()
const char *PageCustom::default_profile_name = "My Settings";
PageCustom::PageCustom(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Custom Printer Setup")), _(L("Custom Printer")))
: ConfigWizardPage(parent, _L("Custom Printer Setup"), _L("Custom Printer"))
{
cb_custom = new wxCheckBox(this, wxID_ANY, _(L("Define a custom printer profile")));
cb_custom = new wxCheckBox(this, wxID_ANY, _L("Define a custom printer profile"));
tc_profile_name = new wxTextCtrl(this, wxID_ANY, default_profile_name);
auto *label = new wxStaticText(this, wxID_ANY, _(L("Custom profile name:")));
auto *label = new wxStaticText(this, wxID_ANY, _L("Custom profile name:"));
tc_profile_name->Enable(false);
tc_profile_name->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &evt) {
@ -1127,7 +1124,7 @@ PageCustom::PageCustom(ConfigWizard *parent)
}
PageUpdate::PageUpdate(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Automatic updates")), _(L("Updates")))
: ConfigWizardPage(parent, _L("Automatic updates"), _L("Updates"))
, version_check(true)
, preset_update(true)
{
@ -1135,60 +1132,76 @@ PageUpdate::PageUpdate(ConfigWizard *parent)
auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
auto *box_slic3r = new wxCheckBox(this, wxID_ANY, _(L("Check for application updates")));
auto *box_slic3r = new wxCheckBox(this, wxID_ANY, _L("Check for application updates"));
box_slic3r->SetValue(app_config->get("version_check") == "1");
append(box_slic3r);
append_text(wxString::Format(_(L(
append_text(wxString::Format(_L(
"If enabled, %s checks for new application versions 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.")), SLIC3R_APP_NAME));
"This is only a notification mechanisms, no automatic installation is done."), SLIC3R_APP_NAME));
append_spacer(VERTICAL_SPACING);
auto *box_presets = new wxCheckBox(this, wxID_ANY, _(L("Update built-in Presets automatically")));
auto *box_presets = new wxCheckBox(this, wxID_ANY, _L("Update built-in Presets automatically"));
box_presets->SetValue(app_config->get("preset_update") == "1");
append(box_presets);
append_text(wxString::Format(_(L(
append_text(wxString::Format(_L(
"If enabled, %s 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.")), SLIC3R_APP_NAME));
const auto text_bold = _(L("Updates are never applied without user's consent and never overwrite user's customized settings."));
"When a new preset version becomes available it is offered at application startup."), SLIC3R_APP_NAME));
const auto text_bold = _L("Updates are never applied without user's consent and never overwrite user's customized settings.");
auto *label_bold = new wxStaticText(this, wxID_ANY, text_bold);
label_bold->SetFont(boldfont);
label_bold->Wrap(WRAP_WIDTH);
append(label_bold);
append_text(_(L("Additionally a backup snapshot of the whole configuration is created before an update is applied.")));
append_text(_L("Additionally a backup snapshot of the whole configuration is created before an update is applied."));
box_slic3r->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { this->version_check = event.IsChecked(); });
box_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { this->preset_update = event.IsChecked(); });
}
PageReloadFromDisk::PageReloadFromDisk(ConfigWizard* parent)
: ConfigWizardPage(parent, _(L("Reload from disk")), _(L("Reload from disk")))
: 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")));
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(
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(); });
}
PageMode::PageMode(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("View mode")), _(L("View mode")))
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
PageFilesAssociation::PageFilesAssociation(ConfigWizard* parent)
: ConfigWizardPage(parent, _L("Files association"), _L("Files association"))
{
append_text(_(L("PrusaSlicer's user interfaces comes in three variants:\nSimple, Advanced, and Expert.\n"
cb_3mf = new wxCheckBox(this, wxID_ANY, _L("Associate .3mf files to PrusaSlicer"));
cb_stl = new wxCheckBox(this, wxID_ANY, _L("Associate .stl files to PrusaSlicer"));
// cb_gcode = new wxCheckBox(this, wxID_ANY, _L("Associate .gcode files to PrusaSlicer G-code Viewer"));
append(cb_3mf);
append(cb_stl);
// append(cb_gcode);
}
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
PageMode::PageMode(ConfigWizard *parent)
: ConfigWizardPage(parent, _L("View mode"), _L("View mode"))
{
append_text(_L("PrusaSlicer's user interfaces comes in three variants:\nSimple, Advanced, and Expert.\n"
"The Simple mode shows only the most frequently used settings relevant for regular 3D printing. "
"The other two offer progressively more sophisticated fine-tuning, "
"they are suitable for advanced and expert users, respectively.")));
"they are suitable for advanced and expert users, respectively."));
radio_simple = new wxRadioButton(this, wxID_ANY, _(L("Simple mode")));
radio_advanced = new wxRadioButton(this, wxID_ANY, _(L("Advanced mode")));
radio_expert = new wxRadioButton(this, wxID_ANY, _(L("Expert mode")));
radio_simple = new wxRadioButton(this, wxID_ANY, _L("Simple mode"));
radio_advanced = new wxRadioButton(this, wxID_ANY, _L("Advanced mode"));
radio_expert = new wxRadioButton(this, wxID_ANY, _L("Expert mode"));
append(radio_simple);
append(radio_advanced);
@ -1229,11 +1242,11 @@ void PageMode::serialize_mode(AppConfig *app_config) const
}
PageVendors::PageVendors(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors")))
: ConfigWizardPage(parent, _L("Other Vendors"), _L("Other Vendors"))
{
const AppConfig &appconfig = this->wizard_p()->appconfig_new;
append_text(wxString::Format(_(L("Pick another vendor supported by %s")), SLIC3R_APP_NAME) + ":");
append_text(wxString::Format(_L("Pick another vendor supported by %s"), SLIC3R_APP_NAME) + ":");
auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
@ -1264,11 +1277,11 @@ PageVendors::PageVendors(ConfigWizard *parent)
}
PageFirmware::PageFirmware(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Firmware Type")), _(L("Firmware")), 1)
: ConfigWizardPage(parent, _L("Firmware Type"), _L("Firmware"), 1)
, gcode_opt(*print_config_def.get("gcode_flavor"))
, gcode_picker(nullptr)
{
append_text(_(L("Choose the type of firmware used by your printer.")));
append_text(_L("Choose the type of firmware used by your printer."));
append_text(_(gcode_opt.tooltip));
wxArrayString choices;
@ -1302,10 +1315,10 @@ void PageFirmware::apply_custom_config(DynamicPrintConfig &config)
}
PageBedShape::PageBedShape(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Bed Shape and Size")), _(L("Bed Shape")), 1)
: ConfigWizardPage(parent, _L("Bed Shape and Size"), _L("Bed Shape"), 1)
, shape_panel(new BedShapePanel(this))
{
append_text(_(L("Set the shape of your printer's bed.")));
append_text(_L("Set the shape of your printer's bed."));
shape_panel->build_panel(*wizard_p()->custom_config->option<ConfigOptionPoints>("bed_shape"),
*wizard_p()->custom_config->option<ConfigOptionString>("bed_custom_texture"),
@ -1325,7 +1338,7 @@ void PageBedShape::apply_custom_config(DynamicPrintConfig &config)
}
PageDiameters::PageDiameters(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Filament and Nozzle Diameters")), _(L("Print Diameters")), 1)
: ConfigWizardPage(parent, _L("Filament and Nozzle Diameters"), _L("Print Diameters"), 1)
, spin_nozzle(new wxSpinCtrlDouble(this, wxID_ANY))
, spin_filam(new wxSpinCtrlDouble(this, wxID_ANY))
{
@ -1339,11 +1352,11 @@ PageDiameters::PageDiameters(ConfigWizard *parent)
auto *default_filam = print_config_def.get("filament_diameter")->get_default_value<ConfigOptionFloats>();
spin_filam->SetValue(default_filam != nullptr && default_filam->size() > 0 ? default_filam->get_at(0) : 3.0);
append_text(_(L("Enter the diameter of your printer's hot end nozzle.")));
append_text(_L("Enter the diameter of your printer's hot end nozzle."));
auto *sizer_nozzle = new wxFlexGridSizer(3, 5, 5);
auto *text_nozzle = new wxStaticText(this, wxID_ANY, _(L("Nozzle Diameter:")));
auto *unit_nozzle = new wxStaticText(this, wxID_ANY, _(L("mm")));
auto *text_nozzle = new wxStaticText(this, wxID_ANY, _L("Nozzle Diameter:"));
auto *unit_nozzle = new wxStaticText(this, wxID_ANY, _L("mm"));
sizer_nozzle->AddGrowableCol(0, 1);
sizer_nozzle->Add(text_nozzle, 0, wxALIGN_CENTRE_VERTICAL);
sizer_nozzle->Add(spin_nozzle);
@ -1352,12 +1365,12 @@ PageDiameters::PageDiameters(ConfigWizard *parent)
append_spacer(VERTICAL_SPACING);
append_text(_(L("Enter the diameter of your filament.")));
append_text(_(L("Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.")));
append_text(_L("Enter the diameter of your filament."));
append_text(_L("Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average."));
auto *sizer_filam = new wxFlexGridSizer(3, 5, 5);
auto *text_filam = new wxStaticText(this, wxID_ANY, _(L("Filament Diameter:")));
auto *unit_filam = new wxStaticText(this, wxID_ANY, _(L("mm")));
auto *text_filam = new wxStaticText(this, wxID_ANY, _L("Filament Diameter:"));
auto *unit_filam = new wxStaticText(this, wxID_ANY, _L("mm"));
sizer_filam->AddGrowableCol(0, 1);
sizer_filam->Add(text_filam, 0, wxALIGN_CENTRE_VERTICAL);
sizer_filam->Add(spin_filam);
@ -1390,7 +1403,7 @@ void PageDiameters::apply_custom_config(DynamicPrintConfig &config)
}
PageTemperatures::PageTemperatures(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Nozzle and Bed Temperatures")), _(L("Temperatures")), 1)
: ConfigWizardPage(parent, _L("Nozzle and Bed Temperatures"), _L("Temperatures"), 1)
, spin_extr(new wxSpinCtrlDouble(this, wxID_ANY))
, spin_bed(new wxSpinCtrlDouble(this, wxID_ANY))
{
@ -1406,12 +1419,12 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent)
auto *default_bed = def_bed.get_default_value<ConfigOptionInts>();
spin_bed->SetValue(default_bed != nullptr && default_bed->size() > 0 ? default_bed->get_at(0) : 0);
append_text(_(L("Enter the temperature needed for extruding your filament.")));
append_text(_(L("A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS.")));
append_text(_L("Enter the temperature needed for extruding your filament."));
append_text(_L("A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS."));
auto *sizer_extr = new wxFlexGridSizer(3, 5, 5);
auto *text_extr = new wxStaticText(this, wxID_ANY, _(L("Extrusion Temperature:")));
auto *unit_extr = new wxStaticText(this, wxID_ANY, _(L("°C")));
auto *text_extr = new wxStaticText(this, wxID_ANY, _L("Extrusion Temperature:"));
auto *unit_extr = new wxStaticText(this, wxID_ANY, _L("°C"));
sizer_extr->AddGrowableCol(0, 1);
sizer_extr->Add(text_extr, 0, wxALIGN_CENTRE_VERTICAL);
sizer_extr->Add(spin_extr);
@ -1420,12 +1433,12 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent)
append_spacer(VERTICAL_SPACING);
append_text(_(L("Enter the bed temperature needed for getting your filament to stick to your heated bed.")));
append_text(_(L("A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed.")));
append_text(_L("Enter the bed temperature needed for getting your filament to stick to your heated bed."));
append_text(_L("A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed."));
auto *sizer_bed = new wxFlexGridSizer(3, 5, 5);
auto *text_bed = new wxStaticText(this, wxID_ANY, _(L("Bed Temperature:")));
auto *unit_bed = new wxStaticText(this, wxID_ANY, _(L("°C")));
auto *text_bed = new wxStaticText(this, wxID_ANY, _L("Bed Temperature:"));
auto *unit_bed = new wxStaticText(this, wxID_ANY, _L("°C"));
sizer_bed->AddGrowableCol(0, 1);
sizer_bed->Add(text_bed, 0, wxALIGN_CENTRE_VERTICAL);
sizer_bed->Add(spin_bed);
@ -1783,6 +1796,11 @@ void ConfigWizard::priv::load_pages()
index->add_page(page_update);
index->add_page(page_reload_from_disk);
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
index->add_page(page_files_association);
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
index->add_page(page_mode);
index->go_to(former_active); // Will restore the active item/page if possible
@ -1879,7 +1897,7 @@ void ConfigWizard::priv::load_vendors()
void ConfigWizard::priv::add_page(ConfigWizardPage *page)
{
const int proportion = (page->shortname == _(L("Filaments"))) || (page->shortname == _(L("SLA Materials"))) ? 1 : 0;
const int proportion = (page->shortname == _L("Filaments")) || (page->shortname == _L("SLA Materials")) ? 1 : 0;
hscroll_sizer->Add(page, proportion, wxEXPAND);
all_pages.push_back(page);
}
@ -1933,12 +1951,12 @@ void ConfigWizard::priv::create_3rdparty_pages()
PagePrinters* pageSLA = nullptr;
if (is_fff_technology) {
pageFFF = new PagePrinters(q, vendor->name + " " +_(L("FFF Technology Printers")), vendor->name+" FFF", *vendor, 1, T_FFF);
pageFFF = new PagePrinters(q, vendor->name + " " +_L("FFF Technology Printers"), vendor->name+" FFF", *vendor, 1, T_FFF);
add_page(pageFFF);
}
if (is_sla_technology) {
pageSLA = new PagePrinters(q, vendor->name + " " + _(L("SLA Technology Printers")), vendor->name+" MSLA", *vendor, 1, T_SLA);
pageSLA = new PagePrinters(q, vendor->name + " " + _L("SLA Technology Printers"), vendor->name+" MSLA", *vendor, 1, T_SLA);
add_page(pageSLA);
}
@ -2244,7 +2262,7 @@ bool ConfigWizard::priv::check_and_install_missing_materials(Technology technolo
const auto ask_and_select_default_materials = [this](const wxString &message, const std::set<const VendorProfile::PrinterModel*> &printer_models, Technology technology)
{
wxMessageDialog msg(q, message, _(L("Notice")), wxYES_NO);
wxMessageDialog msg(q, message, _L("Notice"), wxYES_NO);
if (msg.ShowModal() == wxID_YES)
select_default_materials_for_printer_models(technology, printer_models);
};
@ -2375,6 +2393,26 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
app_config->set("preset_update", page_update->preset_update ? "1" : "0");
app_config->set("export_sources_full_pathnames", page_reload_from_disk->full_pathnames ? "1" : "0");
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
app_config->set("associate_3mf", page_files_association->associate_3mf() ? "1" : "0");
app_config->set("associate_stl", page_files_association->associate_stl() ? "1" : "0");
// app_config->set("associate_gcode", page_files_association->associate_gcode() ? "1" : "0");
if (wxGetApp().is_editor()) {
if (page_files_association->associate_3mf())
wxGetApp().associate_3mf_files();
if (page_files_association->associate_stl())
wxGetApp().associate_stl_files();
}
// else {
// if (page_files_association->associate_gcode())
// wxGetApp().associate_gcode_files();
// }
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
page_mode->serialize_mode(app_config);
std::string preferred_model;
@ -2494,13 +2532,13 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
topsizer->AddSpacer(INDEX_MARGIN);
topsizer->Add(p->hscroll, 1, wxEXPAND);
p->btn_sel_all = new wxButton(this, wxID_ANY, _(L("Select all standard printers")));
p->btn_sel_all = new wxButton(this, wxID_ANY, _L("Select all standard printers"));
p->btnsizer->Add(p->btn_sel_all);
p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back")));
p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >")));
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
p->btn_cancel = new wxButton(this, wxID_CANCEL, _(L("Cancel"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
p->btn_prev = new wxButton(this, wxID_ANY, _L("< &Back"));
p->btn_next = new wxButton(this, wxID_ANY, _L("&Next >"));
p->btn_finish = new wxButton(this, wxID_APPLY, _L("&Finish"));
p->btn_cancel = new wxButton(this, wxID_CANCEL, _L("Cancel")); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
p->btnsizer->AddStretchSpacer();
p->btnsizer->Add(p->btn_prev, 0, wxLEFT, BTN_SPACING);
p->btnsizer->Add(p->btn_next, 0, wxLEFT, BTN_SPACING);
@ -2513,10 +2551,10 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
p->add_page(p->page_welcome = new PageWelcome(this));
p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", *vendor_prusa, 0, T_FFF);
p->page_fff = new PagePrinters(this, _L("Prusa FFF Technology Printers"), "Prusa FFF", *vendor_prusa, 0, T_FFF);
p->add_page(p->page_fff);
p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", *vendor_prusa, 0, T_SLA);
p->page_msla = new PagePrinters(this, _L("Prusa MSLA Technology Printers"), "Prusa MSLA", *vendor_prusa, 0, T_SLA);
p->add_page(p->page_msla);
// Pages for 3rd party vendors
@ -2531,13 +2569,18 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
p->update_materials(T_ANY);
p->add_page(p->page_filaments = new PageMaterials(this, &p->filaments,
_(L("Filament Profiles Selection")), _(L("Filaments")), _(L("Type:")) ));
_L("Filament Profiles Selection"), _L("Filaments"), _L("Type:") ));
p->add_page(p->page_sla_materials = new PageMaterials(this, &p->sla_materials,
_(L("SLA Material Profiles Selection")) + " ", _(L("SLA Materials")), _(L("Type:")) ));
_L("SLA Material Profiles Selection") + " ", _L("SLA Materials"), _L("Type:") ));
p->add_page(p->page_update = new PageUpdate(this));
p->add_page(p->page_reload_from_disk = new PageReloadFromDisk(this));
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
p->add_page(p->page_files_association = new PageFilesAssociation(this));
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
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));

View file

@ -392,6 +392,25 @@ struct PageReloadFromDisk : ConfigWizardPage
PageReloadFromDisk(ConfigWizard* parent);
};
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
struct PageFilesAssociation : ConfigWizardPage
{
private:
wxCheckBox* cb_3mf{ nullptr };
wxCheckBox* cb_stl{ nullptr };
// wxCheckBox* cb_gcode;
public:
PageFilesAssociation(ConfigWizard* parent);
bool associate_3mf() const { return cb_3mf->IsChecked(); }
bool associate_stl() const { return cb_stl->IsChecked(); }
// bool associate_gcode() const { return cb_gcode->IsChecked(); }
};
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
struct PageMode: ConfigWizardPage
{
wxRadioButton *radio_simple;
@ -550,6 +569,11 @@ struct ConfigWizard::priv
PageCustom *page_custom = nullptr;
PageUpdate *page_update = nullptr;
PageReloadFromDisk *page_reload_from_disk = nullptr;
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
PageFilesAssociation* page_files_association = nullptr;
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
PageMode *page_mode = nullptr;
PageVendors *page_vendors = nullptr;
Pages3rdparty pages_3rdparty;
@ -565,9 +589,7 @@ struct ConfigWizard::priv
priv(ConfigWizard *q)
: q(q)
#if ENABLE_GCODE_VIEWER
, appconfig_new(AppConfig::EAppMode::Editor)
#endif // ENABLE_GCODE_VIEWER
, filaments(T_FFF)
, sla_materials(T_SLA)
{}

View file

@ -1,10 +1,6 @@
#include "libslic3r/libslic3r.h"
#if ENABLE_GCODE_VIEWER
#include "DoubleSlider.hpp"
#include "libslic3r/GCode.hpp"
#else
#include "wxExtensions.hpp"
#endif // ENABLE_GCODE_VIEWER
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "Plater.hpp"
@ -12,6 +8,7 @@
#include "ExtruderSequenceDialog.hpp"
#include "libslic3r/Print.hpp"
#include "libslic3r/AppConfig.hpp"
#include "GUI_Utils.hpp"
#include <wx/button.h>
#include <wx/dialog.h>
@ -21,9 +18,6 @@
#include <wx/bmpcbox.h>
#include <wx/statline.h>
#include <wx/dcclient.h>
#if !ENABLE_GCODE_VIEWER
#include <wx/numformatter.h>
#endif // !ENABLE_GCODE_VIEWER
#include <wx/colordlg.h>
#include <cmath>
@ -68,7 +62,8 @@ Control::Control( wxWindow *parent,
m_higher_value (higherValue),
m_min_value(minValue),
m_max_value(maxValue),
m_style(style == wxSL_HORIZONTAL || style == wxSL_VERTICAL ? style: wxSL_HORIZONTAL)
m_style(style == wxSL_HORIZONTAL || style == wxSL_VERTICAL ? style: wxSL_HORIZONTAL),
m_extra_style(style == wxSL_VERTICAL ? wxSL_AUTOTICKS | wxSL_VALUE_LABEL : 0)
{
#ifdef __WXOSX__
is_osx = true;
@ -76,13 +71,8 @@ Control::Control( wxWindow *parent,
if (!is_osx)
SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
#if ENABLE_GCODE_VIEWER
m_bmp_thumb_higher = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "thumb_right") : ScalableBitmap(this, "thumb_up"));
m_bmp_thumb_lower = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "thumb_left") : ScalableBitmap(this, "thumb_down"));
#else
m_bmp_thumb_higher = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "right_half_circle.png") : ScalableBitmap(this, "thumb_up"));
m_bmp_thumb_lower = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "left_half_circle.png" ) : ScalableBitmap(this, "thumb_down"));
#endif // ENABLE_GCODE_VIEWER
m_thumb_size = m_bmp_thumb_lower.GetBmpSize();
m_bmp_add_tick_on = ScalableBitmap(this, "colorchange_add");
@ -134,14 +124,13 @@ Control::Control( wxWindow *parent,
m_line_pens = { &DARK_GREY_PEN, &GREY_PEN, &LIGHT_GREY_PEN };
m_segm_pens = { &DARK_ORANGE_PEN, &ORANGE_PEN, &LIGHT_ORANGE_PEN };
const wxFont& font = GetFont();
m_font = is_osx ? font.Smaller().Smaller() : font.Smaller();
m_font = GetFont();
this->SetMinSize(get_min_size());
}
void Control::msw_rescale()
{
const wxFont& font = GUI::wxGetApp().normal_font();
m_font = is_osx ? font.Smaller().Smaller() : font.Smaller();
m_font = GUI::wxGetApp().normal_font();
m_bmp_thumb_higher.msw_rescale();
m_bmp_thumb_lower .msw_rescale();
@ -179,8 +168,7 @@ int Control::GetActiveValue() const
wxSize Control::get_min_size() const
{
const int min_side = GUI::wxGetApp().em_unit() * ( is_horizontal() ? (is_osx ? 8 : 6) : 10 );
const int min_side = GUI::wxGetApp().em_unit() * ( is_horizontal() ? 5 : 11 );
return wxSize(min_side, min_side);
}
@ -240,6 +228,12 @@ void Control::SetMaxValue(const int max_value)
Update();
}
void Control::SetSliderValues(const std::vector<double>& values)
{
m_values = values;
m_ruler.count = std::count(m_values.begin(), m_values.end(), m_values.front());
}
void Control::draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos)
{
int width;
@ -312,22 +306,14 @@ double Control::get_double_value(const SelectedSlider& selection)
Info Control::GetTicksValues() const
{
Info custom_gcode_per_print_z;
#if ENABLE_GCODE_VIEWER
std::vector<CustomGCode::Item>& values = custom_gcode_per_print_z.gcodes;
#else
std::vector<Item>& values = custom_gcode_per_print_z.gcodes;
#endif // ENABLE_GCODE_VIEWER
const int val_size = m_values.size();
if (!m_values.empty())
for (const TickCode& tick : m_ticks.ticks) {
if (tick.tick > val_size)
break;
#if ENABLE_GCODE_VIEWER
values.emplace_back(CustomGCode::Item{ m_values[tick.tick], tick.type, tick.extruder, tick.color, tick.extra });
#else
values.emplace_back(Item{m_values[tick.tick], tick.type, tick.extruder, tick.color, tick.extra});
#endif // ENABLE_GCODE_VIEWER
}
if (m_force_mode_apply)
@ -346,11 +332,7 @@ void Control::SetTicksValues(const Info& custom_gcode_per_print_z)
const bool was_empty = m_ticks.empty();
m_ticks.ticks.clear();
#if ENABLE_GCODE_VIEWER
const std::vector<CustomGCode::Item>& heights = custom_gcode_per_print_z.gcodes;
#else
const std::vector<Item>& heights = custom_gcode_per_print_z.gcodes;
#endif // ENABLE_GCODE_VIEWER
for (auto h : heights) {
auto it = std::lower_bound(m_values.begin(), m_values.end(), h.print_z - epsilon());
@ -371,6 +353,24 @@ void Control::SetTicksValues(const Info& custom_gcode_per_print_z)
Update();
}
void Control::SetLayersTimes(const std::vector<float>& layers_times)
{
m_layers_times.clear();
if (layers_times.empty())
return;
m_layers_times.resize(layers_times.size(), 0.0);
m_layers_times[0] = layers_times[0];
for (size_t i = 1; i < layers_times.size(); i++)
m_layers_times[i] = m_layers_times[i - 1] + layers_times[i];
}
void Control::SetLayersTimes(const std::vector<double>& layers_times)
{
m_layers_times = layers_times;
for (size_t i = 1; i < m_layers_times.size(); i++)
m_layers_times[i] += m_layers_times[i - 1];
}
void Control::SetDrawMode(bool is_sla_print, bool is_sequential_print)
{
m_draw_mode = is_sla_print ? dmSlaPrint :
@ -422,15 +422,11 @@ void Control::draw_focus_rect()
void Control::render()
{
#if ENABLE_GCODE_VIEWER
#ifdef _WIN32
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#else
SetBackgroundColour(GetParent()->GetBackgroundColour());
#endif // _WIN32
#else
SetBackgroundColour(GetParent()->GetBackgroundColour());
#endif // ENABLE_GCODE_VIEWER
draw_focus_rect();
wxPaintDC dc(this);
@ -443,6 +439,9 @@ void Control::render()
// and only in a case of no-empty m_values
draw_colored_band(dc);
if (m_extra_style & wxSL_AUTOTICKS)
draw_ruler(dc);
if (!m_render_as_disabled) {
// draw line
draw_scroll_line(dc, lower_pos, higher_pos);
@ -471,10 +470,8 @@ void Control::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_
{
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
#if ENABLE_GCODE_VIEWER
if (!m_enable_action_icon)
return;
#endif // ENABLE_GCODE_VIEWER
// suppress add tick on first layer
if (tick == 0)
@ -560,7 +557,7 @@ void Control::draw_tick_on_mouse_position(wxDC& dc)
}
tick = get_value_from_position(m_moving_pos);
if (tick >= m_max_value || tick <= m_min_value || tick == m_higher_value || tick == m_lower_value)
if (tick > m_max_value || tick < m_min_value || tick == m_higher_value || tick == m_lower_value)
return;
wxCoord new_pos = get_position_from_value(tick);
@ -569,9 +566,57 @@ void Control::draw_tick_on_mouse_position(wxDC& dc)
//draw info line
dc.SetPen(LIGHT_GREY_PEN);
draw_ticks(dc, pos);
if (m_extra_style & wxSL_VALUE_LABEL) {
wxColour old_clr = dc.GetTextForeground();
dc.SetTextForeground(GREY_PEN.GetColour());
draw_tick_text(dc, pos, tick, ltEstimatedTime, false);
dc.SetTextForeground(old_clr);
}
}
wxString Control::get_label(int tick) const
static std::string short_and_splitted_time(const std::string& time)
{
// Parse the dhms time format.
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
if (time.find('d') != std::string::npos)
::sscanf(time.c_str(), "%dd %dh %dm %ds", &days, &hours, &minutes, &seconds);
else if (time.find('h') != std::string::npos)
::sscanf(time.c_str(), "%dh %dm %ds", &hours, &minutes, &seconds);
else if (time.find('m') != std::string::npos)
::sscanf(time.c_str(), "%dm %ds", &minutes, &seconds);
else if (time.find('s') != std::string::npos)
::sscanf(time.c_str(), "%ds", &seconds);
// Format the dhm time.
char buffer[64];
if (days > 0)
::sprintf(buffer, "%dd%dh\n%dm", days, hours, minutes);
else if (hours > 0) {
if (hours < 10 && minutes < 10 && seconds < 10)
::sprintf(buffer, "%dh%dm%ds", hours, minutes, seconds);
else if (hours > 10 && minutes > 10 && seconds > 10)
::sprintf(buffer, "%dh\n%dm\n%ds", hours, minutes, seconds);
else if (minutes < 10 && seconds > 10 || minutes > 10 && seconds < 10)
::sprintf(buffer, "%dh\n%dm%ds", hours, minutes, seconds);
else
::sprintf(buffer, "%dh%dm\n%ds", hours, minutes, seconds);
}
else if (minutes > 0) {
if (minutes > 10 && seconds > 10)
::sprintf(buffer, "%dm\n%ds", minutes, seconds);
else
::sprintf(buffer, "%dm%ds", minutes, seconds);
}
else
::sprintf(buffer, "%ds", seconds);
return buffer;
}
wxString Control::get_label(int tick, LabelType label_type/* = ltHeightWithLayer*/) const
{
const int value = tick;
@ -580,27 +625,28 @@ wxString Control::get_label(int tick) const
if (value >= m_values.size())
return "ErrVal";
#if ENABLE_GCODE_VIEWER
if (m_draw_mode == dmSequentialGCodeView)
return wxString::Format("%d", static_cast<unsigned int>(m_values[value]));
else {
const wxString str = m_values.empty() ?
if (label_type == ltEstimatedTime) {
return (value < m_layers_times.size()) ? short_and_splitted_time(get_time_dhms(m_layers_times[value])) : "";
}
wxString str = m_values.empty() ?
wxString::Format("%.*f", 2, m_label_koef * value) :
wxString::Format("%.*f", 2, m_values[value]);
return format_wxstr("%1%\n(%2%)", str, m_values.empty() ? value : value + 1);
if (label_type == ltHeight)
return str;
if (label_type == ltHeightWithLayer)
return format_wxstr("%1%\n(%2%)", str, m_values.empty() ? value : value + 1);
}
#else
const wxString str = m_values.empty() ?
wxNumberFormatter::ToString(m_label_koef * value, 2, wxNumberFormatter::Style_None) :
wxNumberFormatter::ToString(m_values[value], 2, wxNumberFormatter::Style_None);
return format_wxstr("%1%\n(%2%)", str, m_values.empty() ? value : value + 1);
#endif // ENABLE_GCODE_VIEWER
return wxEmptyString;
}
void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side/*=true*/) const
void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, LabelType label_type/* = ltHeight*/, bool right_side/*=true*/) const
{
wxCoord text_width, text_height;
const wxString label = get_label(tick);
const wxString label = get_label(tick, label_type);
dc.GetMultiLineTextExtent(label, &text_width, &text_height);
wxPoint text_pos;
if (right_side) {
@ -615,9 +661,6 @@ void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_
}
else
text_pos = wxPoint(pos.x + m_thumb_size.x + 1, pos.y - 0.5 * text_height - 1);
// update text rectangle
m_rect_lower_thumb_text = wxRect(text_pos, wxSize(text_width, text_height));
}
else {
if (is_horizontal()) {
@ -626,48 +669,24 @@ void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_
text_pos = wxPoint(xx, pos.y - m_thumb_size.x / 2 - text_height - 1);
}
else
text_pos = wxPoint(pos.x - text_width - 1 - m_thumb_size.x, pos.y - 0.5 * text_height + 1);
// update text rectangle
m_rect_higher_thumb_text = wxRect(text_pos, wxSize(text_width, text_height));
text_pos = wxPoint(std::max(2, pos.x - text_width - 1 - m_thumb_size.x), pos.y - 0.5 * text_height + 1);
}
dc.DrawText(label, text_pos);
if (label_type == ltEstimatedTime)
dc.DrawLabel(label, wxRect(text_pos, wxSize(text_width, text_height)), wxALIGN_RIGHT);
else
dc.DrawText(label, text_pos);
}
void Control::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const
{
draw_tick_text(dc, pos, selection == ssLower ? m_lower_value : m_higher_value, selection == ssLower);
draw_tick_text(dc, pos, selection == ssLower ? m_lower_value : m_higher_value, ltHeightWithLayer, selection == ssLower);
}
void Control::draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection)
{
#if ENABLE_GCODE_VIEWER
wxCoord x_draw = pos.x - int(0.5 * m_thumb_size.x);
wxCoord y_draw = pos.y - int(0.5 * m_thumb_size.y);
#else
wxCoord x_draw, y_draw;
if (selection == ssLower) {
if (is_horizontal()) {
x_draw = pos.x - m_thumb_size.x;
y_draw = pos.y - int(0.5*m_thumb_size.y);
}
else {
x_draw = pos.x - int(0.5*m_thumb_size.x);
y_draw = pos.y - int(0.5*m_thumb_size.y);
}
}
else {
if (is_horizontal()) {
x_draw = pos.x;
y_draw = pos.y - int(0.5*m_thumb_size.y);
}
else {
x_draw = pos.x - int(0.5*m_thumb_size.x);
y_draw = pos.y - int(0.5*m_thumb_size.y);
}
}
#endif // ENABLE_GCODE_VIEWER
dc.DrawBitmap(selection == ssLower ? m_bmp_thumb_lower.bmp() : m_bmp_thumb_higher.bmp(), x_draw, y_draw);
// Update thumb rect
@ -715,6 +734,15 @@ void Control::draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& hig
draw_thumb_text(dc, pos_l, ssLower);
}
void Control::draw_ticks_pair(wxDC& dc, wxCoord pos, wxCoord mid, int tick_len)
{
int mid_space = 9;
is_horizontal() ? dc.DrawLine(pos, mid - (mid_space + tick_len), pos, mid - mid_space) :
dc.DrawLine(mid - (mid_space + tick_len), pos, mid - mid_space, pos);
is_horizontal() ? dc.DrawLine(pos, mid + (mid_space + tick_len), pos, mid + mid_space) :
dc.DrawLine(mid + (mid_space + tick_len), pos, mid + mid_space, pos);
};
void Control::draw_ticks(wxDC& dc)
{
if (m_draw_mode == dmSlaPrint)
@ -726,11 +754,7 @@ void Control::draw_ticks(wxDC& dc)
const wxCoord mid = is_horizontal() ? 0.5*height : 0.5*width;
for (auto tick : m_ticks.ticks) {
const wxCoord pos = get_position_from_value(tick.tick);
is_horizontal() ? dc.DrawLine(pos, mid-14, pos, mid-9) :
dc.DrawLine(mid - 14, pos/* - 1*/, mid - 9, pos/* - 1*/);
is_horizontal() ? dc.DrawLine(pos, mid+14, pos, mid+9) :
dc.DrawLine(mid + 14, pos/* - 1*/, mid + 9, pos/* - 1*/);
draw_ticks_pair(dc, pos, mid, 7);
// if current tick if focused, we should to use a specific "focused" icon
bool focused_tick = m_moving_pos != wxDefaultPosition && tick.tick == get_tick_near_point(m_moving_pos);
@ -828,15 +852,11 @@ void Control::draw_colored_band(wxDC& dc)
// don't color a band for MultiExtruder mode
if (m_ticks.empty() || m_mode == MultiExtruder) {
#if ENABLE_GCODE_VIEWER
#ifdef _WIN32
draw_band(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW), main_band);
#else
draw_band(dc, GetParent()->GetBackgroundColour(), main_band);
#endif // _WIN32
#else
draw_band(dc, GetParent()->GetBackgroundColour(), main_band);
#endif // ENABLE_GCODE_VIEWER
return;
}
@ -866,12 +886,133 @@ void Control::draw_colored_band(wxDC& dc)
}
}
void Control::Ruler::update(wxWindow* win, const std::vector<double>& values, double scroll_step)
{
int DPI = GUI::get_dpi_for_window(win);
int pixels_per_sm = lround((double)(DPI) * 5.0/25.4);
if (lround(scroll_step) > pixels_per_sm) {
long_step = -1.0;
return;
}
int pow = -2;
int step = 0;
auto end_it = count == 1 ? values.end() : values.begin() + lround(values.size() / count);
while (pow < 3) {
int tick = 0;
for (int istep : {1, 2, 5}) {
double val = (double)istep * std::pow(10,pow);
auto val_it = std::lower_bound(values.begin(), end_it, val - epsilon());
if (val_it == values.end())
break;
int tick = val_it - values.begin();
// find next tick with istep
val *= 2;
val_it = std::lower_bound(values.begin(), end_it, val - epsilon());
// count of short ticks between ticks
int short_ticks_cnt = val_it == values.end() ? tick : val_it - values.begin() - tick;
if (lround(short_ticks_cnt * scroll_step) > pixels_per_sm) {
step = istep;
// there couldn't be more then 10 short ticks between ticks
short_step = 0.1 * short_ticks_cnt;
break;
}
}
if (step > 0)
break;
pow++;
}
long_step = step == 0 ? -1.0 : (double)step* std::pow(10, pow);
}
void Control::draw_ruler(wxDC& dc)
{
m_ruler.update(this->GetParent(), m_values, get_scroll_step());
int height, width;
get_size(&width, &height);
const wxCoord mid = is_horizontal() ? 0.5 * height : 0.5 * width;
dc.SetPen(GREY_PEN);
wxColour old_clr = dc.GetTextForeground();
dc.SetTextForeground(GREY_PEN.GetColour());
if (m_ruler.long_step < 0)
for (int tick = 1; tick < m_values.size(); tick++) {
wxCoord pos = get_position_from_value(tick);
draw_ticks_pair(dc, pos, mid, 5);
draw_tick_text(dc, wxPoint(mid, pos), tick);
}
else {
auto draw_short_ticks = [this, mid](wxDC& dc, double& current_tick, int max_tick) {
while (current_tick < max_tick) {
wxCoord pos = get_position_from_value(lround(current_tick));
draw_ticks_pair(dc, pos, mid, 2);
current_tick += m_ruler.short_step;
if (current_tick > m_max_value)
break;
}
};
double short_tick;
int tick = 0;
double value = 0.0;
int sequence = 0;
while (tick <= m_max_value) {
value += m_ruler.long_step;
if (value > m_values.back() && sequence < m_ruler.count) {
value = m_ruler.long_step;
for (tick; tick < m_values.size(); tick++)
if (m_values[tick] < value)
break;
// short ticks from the last tick to the end of current sequence
draw_short_ticks(dc, short_tick, tick);
sequence++;
}
short_tick = tick;
for (tick; tick < m_values.size(); tick++) {
if (m_values[tick] == value)
break;
if (m_values[tick] > value) {
if (tick > 0)
tick--;
break;
}
}
if (tick > m_max_value)
break;
wxCoord pos = get_position_from_value(tick);
draw_ticks_pair(dc, pos, mid, 5);
draw_tick_text(dc, wxPoint(mid, pos), tick);
draw_short_ticks(dc, short_tick, tick);
if (value == m_values.back() && sequence < m_ruler.count) {
value = 0.0;
sequence++;
tick++;
}
}
// short ticks from the last tick to the end
draw_short_ticks(dc, short_tick, m_max_value);
}
dc.SetTextForeground(old_clr);
}
void Control::draw_one_layer_icon(wxDC& dc)
{
#if ENABLE_GCODE_VIEWER
if (m_draw_mode == dmSequentialGCodeView)
return;
#endif // ENABLE_GCODE_VIEWER
const wxBitmap& icon = m_is_one_layer ?
m_focus == fiOneLayerIcon ? m_bmp_one_layer_lock_off.bmp() : m_bmp_one_layer_lock_on.bmp() :
@ -910,26 +1051,21 @@ void Control::draw_revert_icon(wxDC& dc)
void Control::draw_cog_icon(wxDC& dc)
{
#if ENABLE_GCODE_VIEWER
if (m_draw_mode == dmSequentialGCodeView)
return;
#endif // ENABLE_GCODE_VIEWER
int width, height;
get_size(&width, &height);
wxCoord x_draw, y_draw;
#if ENABLE_GCODE_VIEWER
if (m_draw_mode == dmSequentialGCodeView) {
is_horizontal() ? x_draw = width - 2 : x_draw = 0.5 * width - 0.5 * m_cog_icon_dim;
is_horizontal() ? y_draw = 0.5 * height - 0.5 * m_cog_icon_dim : y_draw = height - 2;
}
else {
#endif // ENABLE_GCODE_VIEWER
is_horizontal() ? x_draw = width - 2 : x_draw = width - m_cog_icon_dim - 2;
is_horizontal() ? y_draw = height - m_cog_icon_dim - 2 : y_draw = height - 2;
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
dc.DrawBitmap(m_bmp_cog.bmp(), x_draw, y_draw);
@ -1076,19 +1212,15 @@ wxString Control::get_tooltip(int tick/*=-1*/)
if (m_focus == fiRevertIcon)
return _L("Discard all custom changes");
if (m_focus == fiCogIcon)
#if ENABLE_GCODE_VIEWER
{
if (m_draw_mode == dmSequentialGCodeView)
return _L("Jump to move") + " (Shift + G)";
else
#endif // ENABLE_GCODE_VIEWER
return m_mode == MultiAsSingle ?
GUI::from_u8((boost::format(_u8L("Jump to height %s or "
"Set extruder sequence for the entire print")) % " (Shift + G)\n").str()) :
_L("Jump to height") + " (Shift + G)";
#if ENABLE_GCODE_VIEWER
GUI::from_u8((boost::format(_u8L("Jump to height %s Set ruler mode\n or "
"Set extruder sequence for the entire print")) % " (Shift + G)\n").str()) :
GUI::from_u8((boost::format(_u8L("Jump to height %s or Set ruler mode")) % " (Shift + G)\n").str());
}
#endif // ENABLE_GCODE_VIEWER
if (m_focus == fiColorBand)
return m_mode != SingleExtruder ? "" :
_L("Edit current color - Right click the colored slider segment");
@ -1339,14 +1471,7 @@ void Control::OnLeftUp(wxMouseEvent& event)
add_current_tick();
break;
case maCogIconClick :
if (m_mode == MultiAsSingle && m_draw_mode == dmRegular)
show_cog_icon_context_menu();
else
#if ENABLE_GCODE_VIEWER
jump_to_value();
#else
jump_to_print_z();
#endif // ENABLE_GCODE_VIEWER
show_cog_icon_context_menu();
break;
case maOneLayerIconClick:
switch_one_layer_mode();
@ -1429,17 +1554,12 @@ void Control::OnWheel(wxMouseEvent& event)
if (m_selection == ssLower && !is_lower_thumb_editable())
m_selection = ssUndef;
#if ENABLE_GCODE_VIEWER
move_current_thumb((m_draw_mode == dmSequentialGCodeView) ? event.GetWheelRotation() < 0 : event.GetWheelRotation() > 0);
#else
move_current_thumb(event.GetWheelRotation() > 0);
#endif // ENABLE_GCODE_VIEWER
}
void Control::OnKeyDown(wxKeyEvent &event)
{
const int key = event.GetKeyCode();
#if ENABLE_GCODE_VIEWER
if (m_draw_mode != dmSequentialGCodeView && 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.
@ -1454,26 +1574,8 @@ void Control::OnKeyDown(wxKeyEvent &event)
}
else if (m_draw_mode != dmSequentialGCodeView && event.GetKeyCode() == WXK_SHIFT)
UseDefaultColors(false);
#else
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 (event.GetKeyCode() == WXK_SHIFT)
UseDefaultColors(false);
#endif // ENABLE_GCODE_VIEWER
else if (is_horizontal()) {
#if ENABLE_GCODE_VIEWER
if (m_is_focused) {
#endif // ENABLE_GCODE_VIEWER
if (key == WXK_LEFT || key == WXK_RIGHT)
move_current_thumb(key == WXK_LEFT);
else if (key == WXK_UP || key == WXK_DOWN) {
@ -1483,14 +1585,10 @@ void Control::OnKeyDown(wxKeyEvent &event)
m_selection = ssLower;
Refresh();
}
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
}
else {
#if ENABLE_GCODE_VIEWER
if (m_is_focused) {
#endif // ENABLE_GCODE_VIEWER
if (key == WXK_LEFT || key == WXK_RIGHT) {
if (key == WXK_LEFT)
m_selection = ssHigher;
@ -1500,9 +1598,7 @@ void Control::OnKeyDown(wxKeyEvent &event)
}
else if (key == WXK_UP || key == WXK_DOWN)
move_current_thumb(key == WXK_UP);
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
}
event.Skip(); // !Needed to have EVT_CHAR generated as well
@ -1523,10 +1619,7 @@ void Control::OnKeyUp(wxKeyEvent &event)
void Control::OnChar(wxKeyEvent& event)
{
const int key = event.GetKeyCode();
#if ENABLE_GCODE_VIEWER
if (m_draw_mode != dmSequentialGCodeView)
{
#endif // ENABLE_GCODE_VIEWER
if (m_draw_mode != dmSequentialGCodeView) {
if (key == '+' && !m_ticks.suppressed_plus()) {
add_current_tick(true);
m_ticks.suppress_plus(false);
@ -1535,15 +1628,9 @@ void Control::OnChar(wxKeyEvent& event)
delete_current_tick();
m_ticks.suppress_minus(false);
}
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
if (key == 'G')
#if ENABLE_GCODE_VIEWER
jump_to_value();
#else
jump_to_print_z();
#endif // ENABLE_GCODE_VIEWER
}
void Control::OnRightDown(wxMouseEvent& event)
@ -1730,14 +1817,29 @@ void Control::show_cog_icon_context_menu()
wxMenu menu;
append_menu_item(&menu, wxID_ANY, _L("Jump to height") + " (Shift+G)", "",
#if ENABLE_GCODE_VIEWER
[this](wxCommandEvent&) { jump_to_value(); }, "", & menu);
#else
[this](wxCommandEvent&) { jump_to_print_z(); }, "", &menu);
#endif // ENABLE_GCODE_VIEWER
[this](wxCommandEvent&) { jump_to_value(); }, "", & menu);
append_menu_item(&menu, wxID_ANY, _L("Set extruder sequence for the entire print"), "",
[this](wxCommandEvent&) { edit_extruder_sequence(); }, "", &menu);
wxMenu* ruler_mode_menu = new wxMenu();
if (ruler_mode_menu) {
append_menu_check_item(ruler_mode_menu, wxID_ANY, _L("None"), _L("Supprese show the ruler"),
[this](wxCommandEvent&) { if (m_extra_style != 0) m_extra_style = 0; }, ruler_mode_menu,
[]() { return true; }, [this]() { return m_extra_style == 0; }, GUI::wxGetApp().plater());
append_menu_check_item(ruler_mode_menu, wxID_ANY, _L("Show object height"), _L("Show object height on the ruler"),
[this](wxCommandEvent&) { m_extra_style & wxSL_AUTOTICKS ? m_extra_style &= wxSL_AUTOTICKS : m_extra_style |= wxSL_AUTOTICKS; }, ruler_mode_menu,
[]() { return true; }, [this]() { return m_extra_style & wxSL_AUTOTICKS; }, GUI::wxGetApp().plater());
append_menu_check_item(ruler_mode_menu, wxID_ANY, _L("Show estimated print time"), _L("Show estimated print time on the ruler"),
[this](wxCommandEvent&) { m_extra_style & wxSL_VALUE_LABEL ? m_extra_style &= wxSL_VALUE_LABEL : m_extra_style |= wxSL_VALUE_LABEL; }, ruler_mode_menu,
[]() { return true; }, [this]() { return m_extra_style & wxSL_VALUE_LABEL; }, GUI::wxGetApp().plater());
append_submenu(&menu, ruler_mode_menu, wxID_ANY, _L("Ruler mode"), _L("Set ruler mode"), "",
[this]() { return true; }, this);
}
if (m_mode == MultiAsSingle && m_draw_mode == dmRegular)
append_menu_item(&menu, wxID_ANY, _L("Set extruder sequence for the entire print"), "",
[this](wxCommandEvent&) { edit_extruder_sequence(); }, "", &menu);
GUI::wxGetApp().plater()->PopupMenu(&menu);
}
@ -1852,21 +1954,11 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height)
return into_u8(dlg.GetValue());
}
#if ENABLE_GCODE_VIEWER
static double get_value_to_jump(double active_value, double min_z, double max_z, DrawMode mode)
#else
static double get_print_z_to_jump(double active_print_z, double min_z, double max_z)
#endif // ENABLE_GCODE_VIEWER
{
#if ENABLE_GCODE_VIEWER
wxString msg_text = (mode == dmSequentialGCodeView) ? _L("Enter the move you want to jump to") + ":" : _L("Enter the height you want to jump to") + ":";
wxString msg_header = (mode == dmSequentialGCodeView) ? _L("Jump to move") : _L("Jump to height");
wxString msg_in = GUI::double_to_string(active_value);
#else
wxString msg_text = _L("Enter the height you want to jump to") + ":";
wxString msg_header = _L("Jump to height");
wxString msg_in = GUI::double_to_string(active_print_z);
#endif // ENABLE_GCODE_VIEWER
// get custom gcode
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, msg_in, wxTextEntryDialogStyle);
@ -2068,7 +2160,6 @@ void Control::edit_extruder_sequence()
post_ticks_changed_event(ToolChange);
}
#if ENABLE_GCODE_VIEWER
void Control::jump_to_value()
{
double value = get_value_to_jump(m_values[m_selection == ssLower ? m_lower_value : m_higher_value],
@ -2084,23 +2175,6 @@ void Control::jump_to_value()
else
SetHigherValue(tick_value);
}
#else
void Control::jump_to_print_z()
{
double print_z = get_print_z_to_jump(m_values[m_selection == ssLower ? m_lower_value : m_higher_value],
m_values[m_min_value], m_values[m_max_value]);
if (print_z < 0)
return;
auto it = std::lower_bound(m_values.begin(), m_values.end(), print_z - epsilon());
int tick_value = it - m_values.begin();
if (m_selection == ssLower)
SetLowerValue(tick_value);
else
SetHigherValue(tick_value);
}
#endif // ENABLE_GCODE_VIEWER
void Control::post_ticks_changed_event(Type type /*= Custom*/)
{
@ -2169,11 +2243,7 @@ bool Control::check_ticks_changed_event(Type type)
std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder)
{
if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) {
#if ENABLE_GCODE_VIEWER
const std::vector<std::string>& colors = ColorPrintColors::get();
#else
const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
#endif // ENABLE_GCODE_VIEWER
if (ticks.empty())
return colors[0];
m_default_color_idx++;

View file

@ -4,9 +4,6 @@
#include "libslic3r/CustomGCode.hpp"
#include "wxExtensions.hpp"
#if !ENABLE_GCODE_VIEWER
#include <wx/wx.h>
#endif // !ENABLE_GCODE_VIEWER
#include <wx/window.h>
#include <wx/control.h>
#include <wx/dc.h>
@ -79,9 +76,14 @@ enum DrawMode
dmRegular,
dmSlaPrint,
dmSequentialFffPrint,
#if ENABLE_GCODE_VIEWER
dmSequentialGCodeView,
#endif // ENABLE_GCODE_VIEWER
};
enum LabelType
{
ltHeightWithLayer,
ltHeight,
ltEstimatedTime,
};
struct TickCode
@ -212,16 +214,16 @@ public:
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 SetSliderValues(const std::vector<double>& values);
void ChangeOneLayerLock();
Info GetTicksValues() const;
void SetTicksValues(const Info &custom_gcode_per_print_z);
Info GetTicksValues() const;
void SetTicksValues(const Info &custom_gcode_per_print_z);
void SetLayersTimes(const std::vector<float>& layers_times);
void SetLayersTimes(const std::vector<double>& layers_times);
void SetDrawMode(bool is_sla_print, bool is_sequential_print);
#if ENABLE_GCODE_VIEWER
void SetDrawMode(DrawMode mode) { m_draw_mode = mode; }
#endif // ENABLE_GCODE_VIEWER
void SetManipulationMode(Mode mode) { m_mode = mode; }
Mode GetManipulationMode() const { return m_mode; }
@ -261,12 +263,8 @@ public:
void discard_all_thicks();
void move_current_thumb_to_pos(wxPoint pos);
void edit_extruder_sequence();
#if ENABLE_GCODE_VIEWER
void jump_to_value();
void enable_action_icon(bool enable) { m_enable_action_icon = enable; }
#else
void jump_to_print_z();
#endif // ENABLE_GCODE_VIEWER
void show_add_context_menu();
void show_edit_context_menu();
void show_cog_icon_context_menu();
@ -281,15 +279,17 @@ protected:
void draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos);
void draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection);
void draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& higher_pos);
void draw_ticks_pair(wxDC& dc, wxCoord pos, wxCoord mid, int tick_len);
void draw_ticks(wxDC& dc);
void draw_colored_band(wxDC& dc);
void draw_ruler(wxDC& dc);
void draw_one_layer_icon(wxDC& dc);
void draw_revert_icon(wxDC& dc);
void draw_cog_icon(wxDC &dc);
void draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection);
void draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, SelectedSlider selection);
void draw_tick_on_mouse_position(wxDC &dc);
void draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side = true) const;
void draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, LabelType label_type = ltHeight, bool right_side = true) const;
void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const;
void update_thumb_rect(const wxCoord begin_x, const wxCoord begin_y, const SelectedSlider& selection);
@ -306,7 +306,7 @@ private:
int get_tick_near_point(const wxPoint& pt);
double get_scroll_step();
wxString get_label(int tick) const;
wxString get_label(int tick, LabelType label_type = ltHeightWithLayer) const;
void get_lower_and_higher_position(int& lower_pos, int& higher_pos);
int get_value_from_position(const wxCoord x, const wxCoord y);
int get_value_from_position(const wxPoint pos) { return get_value_from_position(pos.x, pos.y); }
@ -360,9 +360,7 @@ private:
bool m_is_one_layer = false;
bool m_is_focused = false;
bool m_force_mode_apply = true;
#if ENABLE_GCODE_VIEWER
bool m_enable_action_icon = true;
#endif // ENABLE_GCODE_VIEWER
DrawMode m_draw_mode = dmRegular;
@ -387,10 +385,12 @@ private:
int m_revert_icon_dim;
int m_cog_icon_dim;
long m_style;
long m_extra_style;
float m_label_koef = 1.0;
std::vector<double> m_values;
TickCodeInfo m_ticks;
std::vector<double> m_layers_times;
std::vector<std::string> m_extruder_colors;
@ -407,6 +407,15 @@ private:
std::vector<wxPen*> m_line_pens;
std::vector<wxPen*> m_segm_pens;
struct Ruler {
double long_step;
double short_step;
int count { 1 }; // > 1 for sequential print
void update(wxWindow* win, const std::vector<double>& values, double scroll_step);
bool is_ok() { return long_step > 0 && short_step > 0; }
} m_ruler;
};
} // DoubleSlider;

View file

@ -316,7 +316,7 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
bool BitmapChoiceRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value)
{
wxBitmapComboBox* c = (wxBitmapComboBox*)ctrl;
wxBitmapComboBox* c = static_cast<wxBitmapComboBox*>(ctrl);
int selection = c->GetSelection();
if (selection < 0)
return false;

View file

@ -14,13 +14,14 @@
#include "GUI_App.hpp"
#include "I18N.hpp"
#include "OptionsGroup.hpp"
#include "MainFrame.hpp"
namespace Slic3r {
namespace GUI {
ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequence& sequence)
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Set extruder sequence")),
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Set extruder sequence")),
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
m_sequence(sequence)
{

View file

@ -262,6 +262,11 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
double val = 0.;
// Replace the first occurence of comma in decimal number.
str.Replace(",", ".", false);
// remove space and "mm" substring, if any exists
str.Replace(" ", "", true);
str.Replace("m", "", true);
if (!str.ToCDouble(&val))
{
if (!check_value) {
@ -280,13 +285,15 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
break;
}
bool infill_anchors = m_opt.opt_key == "infill_anchor" || m_opt.opt_key == "infill_anchor_max";
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
const wxString stVal = double_to_string(val, 2);
const wxString msg_text = from_u8((boost::format(_utf8(L("Do you mean %s%% instead of %s %s?\n"
"Select YES if you want to change this value to %s%%, \n"
"or NO if you are sure that %s %s is a correct value."))) % stVal % stVal % sidetext % stVal % stVal % sidetext).str());
wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")) + ": " + m_opt_id , wxICON_WARNING | wxYES | wxNO);
if (dialog.ShowModal() == wxID_YES) {
if ((!infill_anchors || val > 100) && dialog.ShowModal() == wxID_YES) {
set_value(from_u8((boost::format("%s%%") % stVal).str()), false/*true*/);
str += "%%";
}
@ -861,8 +868,16 @@ void Choice::BUILD() {
temp->SetItemBitmap(0, empty_bmp);
#endif
// temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
temp->Bind(wxEVT_MOUSEWHEEL, [this](wxMouseEvent& e) {
if (m_suppress_scroll && !m_is_dropped)
e.StopPropagation();
else
e.Skip();
});
temp->Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_is_dropped = true; });
temp->Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_is_dropped = false; });
temp->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { on_change_field(); }, temp->GetId());
if (m_is_editable) {
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) {
@ -872,12 +887,18 @@ void Choice::BUILD() {
return;
}
double old_val = !m_value.empty() ? boost::any_cast<double>(m_value) : -99999;
if (is_defined_input_value<choice_ctrl>(window, m_opt.type)) {
if (fabs(old_val - boost::any_cast<double>(get_value())) <= 0.0001)
return;
else
on_change_field();
if (m_opt.type == coFloatOrPercent) {
std::string old_val = !m_value.empty() ? boost::any_cast<std::string>(m_value) : "";
if (old_val == boost::any_cast<std::string>(get_value()))
return;
}
else {
double old_val = !m_value.empty() ? boost::any_cast<double>(m_value) : -99999;
if (fabs(old_val - boost::any_cast<double>(get_value())) <= 0.0001)
return;
}
on_change_field();
}
else
on_kill_focus();
@ -887,6 +908,11 @@ void Choice::BUILD() {
temp->SetToolTip(get_tooltip_text(temp->GetValue()));
}
void Choice::suppress_scroll()
{
m_suppress_scroll = true;
}
void Choice::set_selection()
{
/* To prevent earlier control updating under OSX set m_disable_change_event to true
@ -898,59 +924,42 @@ void Choice::set_selection()
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
switch (m_opt.type) {
case coFloat:
case coPercent: {
double val = m_opt.default_value->getFloat();
text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 1);
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
if (el == text_value)
break;
++idx;
}
// if (m_opt.type == coPercent) text_value += "%";
idx == m_opt.enum_values.size() ?
field->SetValue(text_value) :
field->SetSelection(idx);
break;
}
case coEnum:{
int id_value = m_opt.get_default_value<ConfigOptionEnum<SeamPosition>>()->value; //!!
field->SetSelection(id_value);
break;
}
case coFloat:
case coPercent: {
double val = m_opt.default_value->getFloat();
text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 1);
break;
}
case coInt:{
int val = m_opt.default_value->getInt(); //!!
text_value = wxString::Format(_T("%i"), int(val));
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
if (el == text_value)
break;
++idx;
}
idx == m_opt.enum_values.size() ?
field->SetValue(text_value) :
field->SetSelection(idx);
text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getInt()));
break;
}
case coStrings:{
text_value = m_opt.get_default_value<ConfigOptionStrings>()->get_at(m_opt_idx);
break;
}
case coFloatOrPercent: {
text_value = double_to_string(m_opt.default_value->getFloat());
if (m_opt.get_default_value<ConfigOptionFloatOrPercent>()->percent)
text_value += "%";
break;
}
default: break;
}
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
if (!text_value.IsEmpty()) {
int idx = 0;
for (auto el : m_opt.enum_values) {
if (el == text_value)
break;
++idx;
}
idx == m_opt.enum_values.size() ?
field->SetValue(text_value) :
field->SetSelection(idx);
break;
}
default: break;
idx == m_opt.enum_values.size() ? field->SetValue(text_value) : field->SetSelection(idx);
}
}
@ -984,6 +993,7 @@ void Choice::set_value(const boost::any& value, bool change_event)
case coInt:
case coFloat:
case coPercent:
case coFloatOrPercent:
case coString:
case coStrings: {
wxString text_value;
@ -992,13 +1002,14 @@ void Choice::set_value(const boost::any& value, bool change_event)
else
text_value = boost::any_cast<wxString>(value);
size_t idx = 0;
for (auto el : m_opt.enum_values)
const std::vector<std::string>& enums = m_opt.enum_values.empty() ? m_opt.enum_labels : m_opt.enum_values;
for (auto el : enums)
{
if (el == text_value)
break;
++idx;
}
if (idx == m_opt.enum_values.size()) {
if (idx == enums.size()) {
// For editable Combobox under OSX is needed to set selection to -1 explicitly,
// otherwise selection doesn't be changed
field->SetSelection(-1);
@ -1137,7 +1148,9 @@ boost::any& Choice::get_value()
(ret_str != m_opt.enum_values[ret_enum] && ret_str != _(m_opt.enum_labels[ret_enum])))
// modifies ret_string!
get_value_by_opt_type(ret_str);
else
else if (m_opt.type == coFloatOrPercent)
m_value = m_opt.enum_values[ret_enum];
else
m_value = atof(m_opt.enum_values[ret_enum].c_str());
}
else

View file

@ -38,39 +38,6 @@ using t_back_to_init = std::function<void(const std::string&)>;
wxString double_to_string(double const value, const int max_precision = 4);
class RevertButton : public ScalableButton
{
bool hidden = false; // never show button if it's hidden ones
public:
// RevertButton() {}
// RevertButton(wxWindow* parent, wxWindowID id, const wxString& label = wxEmptyString,
// const wxPoint& pos = wxDefaultPosition,
// const wxSize& size = wxDefaultSize, long style = 0,
// const wxValidator& validator = wxDefaultValidator,
// const wxString& name = wxTextCtrlNameStr)
// {
// this->Create(parent, id, label, pos, size, style, validator, name);
// }
RevertButton(
wxWindow *parent,
const std::string& icon_name = ""
) :
ScalableButton(parent, wxID_ANY, icon_name) {}
// overridden from wxWindow base class
virtual bool
AcceptsFocusFromKeyboard() const { return false; }
void set_as_hidden() {
Hide();
hidden = true;
}
virtual bool Show(bool show = true) override {
return wxButton::Show(hidden ? false : show);
}
};
class Field {
protected:
// factory function to defer and enforce creation of derived type.
@ -283,14 +250,14 @@ public:
void propagate_value();
wxWindow* window {nullptr};
virtual void set_value(const std::string& value, bool change_event = false) {
void set_value(const std::string& value, bool change_event = false) {
m_disable_change_event = !change_event;
dynamic_cast<wxTextCtrl*>(window)->SetValue(wxString(value));
m_disable_change_event = false;
}
virtual void set_value(const boost::any& value, bool change_event = false) override;
virtual void set_last_meaningful_value() override;
virtual void set_na_value() override;
void set_value(const boost::any& value, bool change_event = false) override;
void set_last_meaningful_value() override;
void set_na_value() override;
boost::any& get_value() override;
@ -385,11 +352,14 @@ public:
/* Under OSX: wxBitmapComboBox->GetWindowStyle() returns some weard value,
* so let use a flag, which has TRUE value for a control without wxCB_READONLY style
*/
bool m_is_editable { false };
bool m_is_editable { false };
bool m_is_dropped { false };
bool m_suppress_scroll { false };
int m_last_selected { wxNOT_FOUND };
void set_selection();
void set_value(const std::string& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false) override;
void set_values(const std::vector<std::string> &values);
void set_values(const wxArrayString &values);
boost::any& get_value() override;
@ -399,6 +369,8 @@ public:
void enable() override ;//{ dynamic_cast<wxBitmapComboBox*>(window)->Enable(); };
void disable() override;//{ dynamic_cast<wxBitmapComboBox*>(window)->Disable(); };
wxWindow* getWindow() override { return window; }
void suppress_scroll();
};
class ColourPicker : public Field {
@ -443,7 +415,7 @@ public:
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value(wxTextCtrl* win);
void set_value(const Vec2d& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false) override;
boost::any& get_value() override;
void msw_rescale() override;
@ -473,7 +445,7 @@ public:
dynamic_cast<wxStaticText*>(window)->SetLabel(wxString::FromUTF8(value.data()));
m_disable_change_event = false;
}
void set_value(const boost::any& value, bool change_event = false) {
void set_value(const boost::any& value, bool change_event = false) override {
m_disable_change_event = !change_event;
dynamic_cast<wxStaticText*>(window)->SetLabel(boost::any_cast<wxString>(value));
m_disable_change_event = false;
@ -504,7 +476,7 @@ public:
void BUILD() override;
void set_value(const int value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false) override;
boost::any& get_value() override;
void enable() override {

View file

@ -1,7 +1,6 @@
#include "libslic3r/libslic3r.h"
#include "GCodeViewer.hpp"
#if ENABLE_GCODE_VIEWER
#include "libslic3r/Print.hpp"
#include "libslic3r/Geometry.hpp"
#include "libslic3r/Model.hpp"
@ -272,6 +271,10 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Travel_Colors {{
{ 0.505f, 0.064f, 0.028f } // Retract
}};
#if ENABLE_SHOW_WIPE_MOVES
const GCodeViewer::Color GCodeViewer::Wipe_Color = { 1.0f, 1.0f, 0.0f };
#endif // ENABLE_SHOW_WIPE_MOVES
const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors {{
{ 0.043f, 0.173f, 0.478f }, // bluish
{ 0.075f, 0.349f, 0.522f },
@ -370,6 +373,10 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std:
// update tool colors
m_tool_colors = decode_colors(str_tool_colors);
// ensure at least one (default) color is defined
if (m_tool_colors.empty())
m_tool_colors.push_back(decode_color("#FF8000"));
// update ranges for coloring / legend
m_extrusions.reset_ranges();
for (size_t i = 0; i < m_moves_count; ++i) {
@ -456,6 +463,9 @@ void GCodeViewer::render() const
buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110";
break;
}
#if ENABLE_SHOW_WIPE_MOVES
case EMoveType::Wipe:
#endif // ENABLE_SHOW_WIPE_MOVES
case EMoveType::Extrude: {
buffer.shader = "gouraud_light";
break;
@ -569,6 +579,9 @@ unsigned int GCodeViewer::get_options_visibility_flags() const
unsigned int flags = 0;
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Travel), is_toolpath_move_type_visible(EMoveType::Travel));
#if ENABLE_SHOW_WIPE_MOVES
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Wipe), is_toolpath_move_type_visible(EMoveType::Wipe));
#endif // ENABLE_SHOW_WIPE_MOVES
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Retractions), is_toolpath_move_type_visible(EMoveType::Retract));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Unretractions), is_toolpath_move_type_visible(EMoveType::Unretract));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ToolChanges), is_toolpath_move_type_visible(EMoveType::Tool_change));
@ -588,6 +601,9 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags)
};
set_toolpath_move_type_visible(EMoveType::Travel, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Travel)));
#if ENABLE_SHOW_WIPE_MOVES
set_toolpath_move_type_visible(EMoveType::Wipe, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Wipe)));
#endif // ENABLE_SHOW_WIPE_MOVES
set_toolpath_move_type_visible(EMoveType::Retract, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Retractions)));
set_toolpath_move_type_visible(EMoveType::Unretract, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Unretractions)));
set_toolpath_move_type_visible(EMoveType::Tool_change, is_flag_set(static_cast<unsigned int>(Preview::OptionType::ToolChanges)));
@ -925,6 +941,9 @@ void GCodeViewer::init()
buffer.vertices.format = VBuffer::EFormat::Position;
break;
}
#if ENABLE_SHOW_WIPE_MOVES
case EMoveType::Wipe:
#endif // ENABLE_SHOW_WIPE_MOVES
case EMoveType::Extrude:
{
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle;
@ -1197,6 +1216,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
prev_up = up;
prev_length = length;
};
auto add_indices_as_solid = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer,
size_t& buffer_vertices_size, unsigned int index_buffer_id, IndexBuffer& buffer_indices, size_t move_id) {
static Vec3f prev_dir;
@ -1339,6 +1359,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
// the data are deleted as soon as they are sent to the gpu.
std::vector<std::vector<float>> vertices(m_buffers.size());
std::vector<MultiIndexBuffer> indices(m_buffers.size());
#if ENABLE_SHOW_OPTION_POINT_LAYERS
std::vector<float> options_zs;
#endif // ENABLE_SHOW_OPTION_POINT_LAYERS
// toolpaths data -> extract vertices from result
for (size_t i = 0; i < m_moves_count; ++i) {
@ -1363,24 +1386,39 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point:
{
case TBuffer::ERenderPrimitiveType::Point: {
add_vertices_as_point(curr, buffer_vertices);
break;
}
case TBuffer::ERenderPrimitiveType::Line:
{
case TBuffer::ERenderPrimitiveType::Line: {
add_vertices_as_line(prev, curr, buffer, buffer_vertices);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle:
{
case TBuffer::ERenderPrimitiveType::Triangle: {
add_vertices_as_solid(prev, curr, buffer, buffer_vertices, i);
break;
}
}
#if ENABLE_SHOW_OPTION_POINT_LAYERS
EMoveType type = buffer_type(id);
if (type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) {
const float* const last_z = options_zs.empty() ? nullptr : &options_zs.back();
float z = static_cast<double>(curr.position[2]);
if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
options_zs.emplace_back(curr.position[2]);
}
#endif // ENABLE_SHOW_OPTION_POINT_LAYERS
}
#if ENABLE_SHOW_WIPE_MOVES
// move the wipe toolpaths half height up to render them on proper position
std::vector<float>& wipe_vertices = vertices[buffer_id(EMoveType::Wipe)];
for (size_t i = 2; i < wipe_vertices.size(); i += 3) {
wipe_vertices[i] += 0.5f * GCodeProcessor::Wipe_Height;
}
#endif // ENABLE_SHOW_WIPE_MOVES
log_memory_usage("Loaded G-code generated vertex buffers, ", vertices, indices);
// toolpaths data -> send vertices data to gpu
@ -1414,7 +1452,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
buffer.paths.clear();
}
// variable used to keep track of the current size (in vertices) of the vertex buffer
#if ENABLE_SHOW_WIPE_MOVES
std::vector<size_t> curr_buffer_vertices_size(m_buffers.size(), 0);
#else
size_t curr_buffer_vertices_size = 0;
#endif // ENABLE_SHOW_WIPE_MOVES
for (size_t i = 0; i < m_moves_count; ++i) {
// skip first vertex
if (i == 0)
@ -1442,7 +1484,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
// create another index buffer, and move the current path indices into it
if (buffer_indices.back().size() >= THRESHOLD - static_cast<size_t>(buffer.indices_per_segment())) {
buffer_indices.push_back(IndexBuffer());
#if ENABLE_SHOW_WIPE_MOVES
if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
#else
if (curr.type == EMoveType::Extrude || curr.type == EMoveType::Travel) {
#endif // ENABLE_SHOW_WIPE_MOVES
if (!(prev.type != curr.type || !buffer.paths.back().matches(curr))) {
Path& last_path = buffer.paths.back();
size_t delta_id = last_path.last.i_id - last_path.first.i_id;
@ -1464,19 +1510,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point:
{
case TBuffer::ERenderPrimitiveType::Point: {
add_indices_as_point(curr, buffer, static_cast<unsigned int>(buffer_indices.size()) - 1, buffer_indices.back(), i);
break;
}
case TBuffer::ERenderPrimitiveType::Line:
{
case TBuffer::ERenderPrimitiveType::Line: {
add_indices_as_line(prev, curr, buffer, static_cast<unsigned int>(buffer_indices.size()) - 1, buffer_indices.back(), i);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle:
{
case TBuffer::ERenderPrimitiveType::Triangle: {
#if ENABLE_SHOW_WIPE_MOVES
add_indices_as_solid(prev, curr, buffer, curr_buffer_vertices_size[id], static_cast<unsigned int>(buffer_indices.size()) - 1, buffer_indices.back(), i);
#else
add_indices_as_solid(prev, curr, buffer, curr_buffer_vertices_size, static_cast<unsigned int>(buffer_indices.size()) - 1, buffer_indices.back(), i);
#endif // ENABLE_SHOW_WIPE_MOVES
break;
}
}
@ -1521,6 +1568,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
for (size_t i = 0; i < travel_buffer_indices.size(); ++i) {
m_statistics.travel_segments_count = travel_buffer_indices[i].size() / m_buffers[travel_buffer_id].indices_per_segment();
}
#if ENABLE_SHOW_WIPE_MOVES
unsigned int wipe_buffer_id = buffer_id(EMoveType::Wipe);
const MultiIndexBuffer& wipe_buffer_indices = indices[wipe_buffer_id];
for (size_t i = 0; i < wipe_buffer_indices.size(); ++i) {
m_statistics.wipe_segments_count = wipe_buffer_indices[i].size() / m_buffers[wipe_buffer_id].indices_per_segment();
}
#endif // ENABLE_SHOW_WIPE_MOVES
unsigned int extrude_buffer_id = buffer_id(EMoveType::Extrude);
const MultiIndexBuffer& extrude_buffer_indices = indices[extrude_buffer_id];
for (size_t i = 0; i < extrude_buffer_indices.size(); ++i) {
@ -1558,9 +1612,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
}
// set layers z range
if (!m_layers.empty()) {
if (!m_layers.empty())
m_layers_z_range = { 0, static_cast<unsigned int>(m_layers.size() - 1) };
#if ENABLE_SHOW_OPTION_POINT_LAYERS
// change color of paths whose layer contains option points
if (!options_zs.empty()) {
TBuffer& extrude_buffer = m_buffers[buffer_id(EMoveType::Extrude)];
for (Path& path : extrude_buffer.paths) {
float z = path.first.position[2];
if (std::find_if(options_zs.begin(), options_zs.end(), [z](float f) { return f - EPSILON <= z && z <= f + EPSILON; }) != options_zs.end())
path.cp_color_id = 255 - path.cp_color_id;
}
}
#endif // ENABLE_SHOW_OPTION_POINT_LAYERS
// roles -> remove duplicates
std::sort(m_roles.begin(), m_roles.end());
@ -1657,9 +1722,25 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; }
case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; }
case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; }
#if ENABLE_SHOW_OPTION_POINT_LAYERS
case EViewType::ColorPrint: {
if (path.cp_color_id >= static_cast<unsigned char>(m_tool_colors.size())) {
color = { 0.5f, 0.5f, 0.5f };
// // complementary color
// color = m_tool_colors[255 - path.cp_color_id];
// color = { 1.0f - color[0], 1.0f - color[1], 1.0f - color[2] };
}
else
color = m_tool_colors[path.cp_color_id];
break;
}
#else
case EViewType::ColorPrint: { color = m_tool_colors[path.cp_color_id]; break; }
#endif // ENABLE_SHOW_OPTION_POINT_LAYERS
default: { color = { 1.0f, 1.0f, 1.0f }; break; }
}
return color;
};
@ -1830,6 +1911,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
break;
}
#if ENABLE_SHOW_WIPE_MOVES
case EMoveType::Wipe: { color = Wipe_Color; break; }
#endif // ENABLE_SHOW_WIPE_MOVES
default: { color = { 0.0f, 0.0f, 0.0f }; break; }
}
@ -2562,6 +2646,28 @@ void GCodeViewer::render_legend() const
}
}
#if ENABLE_SHOW_WIPE_MOVES
// wipe paths section
if (m_buffers[buffer_id(EMoveType::Wipe)].visible) {
switch (m_view_type)
{
case EViewType::Feedrate:
case EViewType::Tool:
case EViewType::ColorPrint: { break; }
default: {
// title
ImGui::Spacing();
imgui.title(_u8L("Wipe"));
// items
append_item(EItemType::Line, Wipe_Color, _u8L("Wipe"));
break;
}
}
}
#endif // ENABLE_SHOW_WIPE_MOVES
auto any_option_available = [this]() {
auto available = [this](EMoveType type) {
const TBuffer& buffer = m_buffers[buffer_id(type)];
@ -2640,7 +2746,9 @@ void GCodeViewer::render_legend() const
}
if (!m_settings_ids.filament.empty()) {
for (unsigned char i : m_extruder_ids) {
imgui.text(_u8L("Filament") + " " + std::to_string(i + 1) + ":");
std::string txt = _u8L("Filament");
txt += (m_extruder_ids.size() == 1) ? ":" : " " + std::to_string(i + 1);
imgui.text(txt);
ImGui::SameLine(offset);
imgui.text(m_settings_ids.filament[i]);
}
@ -2675,7 +2783,7 @@ void GCodeViewer::render_legend() const
ImGui::SameLine();
imgui.text(short_time(get_time_dhms(time_mode.time)));
auto show_mode_button = [this, &imgui](const std::string& label, PrintEstimatedTimeStatistics::ETimeMode mode) {
auto show_mode_button = [this, &imgui](const wxString& label, PrintEstimatedTimeStatistics::ETimeMode mode) {
bool show = false;
for (size_t i = 0; i < m_time_statistics.modes.size(); ++i) {
if (i != static_cast<size_t>(mode) &&
@ -2695,11 +2803,11 @@ void GCodeViewer::render_legend() const
switch (m_time_estimate_mode) {
case PrintEstimatedTimeStatistics::ETimeMode::Normal: {
show_mode_button(_u8L("Show stealth mode"), PrintEstimatedTimeStatistics::ETimeMode::Stealth);
show_mode_button(_L("Show stealth mode"), PrintEstimatedTimeStatistics::ETimeMode::Stealth);
break;
}
case PrintEstimatedTimeStatistics::ETimeMode::Stealth: {
show_mode_button(_u8L("Show normal mode"), PrintEstimatedTimeStatistics::ETimeMode::Normal);
show_mode_button(_L("Show normal mode"), PrintEstimatedTimeStatistics::ETimeMode::Normal);
break;
}
}
@ -2790,6 +2898,9 @@ void GCodeViewer::render_statistics() const
if (ImGui::CollapsingHeader("Other")) {
add_counter(std::string("Travel segments count:"), m_statistics.travel_segments_count);
#if ENABLE_SHOW_WIPE_MOVES
add_counter(std::string("Wipe segments count:"), m_statistics.wipe_segments_count);
#endif // ENABLE_SHOW_WIPE_MOVES
add_counter(std::string("Extrude segments count:"), m_statistics.extrude_segments_count);
add_counter(std::string("Max vertices in vertex buffer:"), m_statistics.max_vertices_in_vertex_buffer);
add_counter(std::string("Max indices in index buffer:"), m_statistics.max_indices_in_index_buffer);
@ -2826,4 +2937,3 @@ void GCodeViewer::log_memory_used(const std::string& label, long long additional
} // namespace GUI
} // namespace Slic3r
#endif // ENABLE_GCODE_VIEWER

View file

@ -1,7 +1,6 @@
#ifndef slic3r_GCodeViewer_hpp_
#define slic3r_GCodeViewer_hpp_
#if ENABLE_GCODE_VIEWER
#include "3DScene.hpp"
#include "libslic3r/GCode/GCodeProcessor.hpp"
#include "GLModel.hpp"
@ -24,6 +23,9 @@ class GCodeViewer
static const std::vector<Color> Extrusion_Role_Colors;
static const std::vector<Color> Options_Colors;
static const std::vector<Color> Travel_Colors;
#if ENABLE_SHOW_WIPE_MOVES
static const Color Wipe_Color;
#endif // ENABLE_SHOW_WIPE_MOVES
static const std::vector<Color> Range_Colors;
enum class EOptionsColors : unsigned char
@ -327,6 +329,9 @@ class GCodeViewer
long long render_paths_size{ 0 };
// other
long long travel_segments_count{ 0 };
#if ENABLE_SHOW_WIPE_MOVES
long long wipe_segments_count{ 0 };
#endif // ENABLE_SHOW_WIPE_MOVES
long long extrude_segments_count{ 0 };
long long max_vertices_in_vertex_buffer{ 0 };
long long max_indices_in_index_buffer{ 0 };
@ -361,6 +366,9 @@ class GCodeViewer
void reset_others() {
travel_segments_count = 0;
#if ENABLE_SHOW_WIPE_MOVES
wipe_segments_count = 0;
#endif // ENABLE_SHOW_WIPE_MOVES
extrude_segments_count = 0;
max_vertices_in_vertex_buffer = 0;
max_indices_in_index_buffer = 0;
@ -513,7 +521,5 @@ private:
} // namespace GUI
} // namespace Slic3r
#endif // ENABLE_GCODE_VIEWER
#endif // slic3r_GCodeViewer_hpp_

File diff suppressed because it is too large Load diff

View file

@ -12,10 +12,8 @@
#include "GUI_ObjectLayers.hpp"
#include "GLSelectionRectangle.hpp"
#include "MeshUtils.hpp"
#if ENABLE_GCODE_VIEWER
#include "libslic3r/GCode/GCodeProcessor.hpp"
#include "GCodeViewer.hpp"
#endif // ENABLE_GCODE_VIEWER
#include "libslic3r/Slicing.hpp"
@ -39,9 +37,6 @@ namespace Slic3r {
struct Camera;
class BackgroundSlicingProcess;
#if !ENABLE_GCODE_VIEWER
class GCodePreviewData;
#endif // !ENABLE_GCODE_VIEWER
struct ThumbnailData;
class ModelObject;
class ModelInstance;
@ -108,11 +103,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent);
#if ENABLE_GCODE_VIEWER
wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent);
#else
wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent);
#endif // ENABLE_GCODE_VIEWER
wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
@ -127,37 +118,6 @@ class GLCanvas3D
{
static const double DefaultCameraZoomToBoxMarginFactor;
public:
#if !ENABLE_GCODE_VIEWER
struct GCodePreviewVolumeIndex
{
enum EType
{
Extrusion,
Travel,
Retraction,
Unretraction,
Shell,
Num_Geometry_Types
};
struct FirstVolume
{
EType type;
unsigned int flag;
// Index of the first volume in a GLVolumeCollection.
unsigned int id;
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
};
std::vector<FirstVolume> first_volumes;
void reset() { first_volumes.clear(); }
};
#endif // !ENABLE_GCODE_VIEWER
private:
class LayersEditing
{
public:
@ -355,35 +315,6 @@ private:
bool generate(const std::string& msg, const GLCanvas3D& canvas, bool compress, bool red_colored = false);
};
#if !ENABLE_GCODE_VIEWER
class LegendTexture : public GUI::GLTexture
{
static const int Px_Title_Offset = 5;
static const int Px_Text_Offset = 5;
static const int Px_Square = 20;
static const int Px_Square_Contour = 1;
static const int Px_Border = Px_Square / 2;
static const unsigned char Squares_Border_Color[3];
static const unsigned char Default_Background_Color[3];
static const unsigned char Error_Background_Color[3];
static const unsigned char Opacity;
int m_original_width;
int m_original_height;
public:
LegendTexture();
void fill_color_print_legend_items(const GLCanvas3D& canvas,
const std::vector<float>& colors_in,
std::vector<float>& colors,
std::vector<std::string>& cp_legend_items);
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors, const GLCanvas3D& canvas, bool compress);
void render(const GLCanvas3D& canvas) const;
};
#endif // !ENABLE_GCODE_VIEWER
#if ENABLE_RENDER_STATISTICS
struct RenderStats
{
@ -450,6 +381,13 @@ public:
Cross
};
struct ArrangeSettings
{
float distance = 6.;
float accuracy = 0.65f;
bool enable_rotation = false;
};
private:
wxGLCanvas* m_canvas;
wxGLContext* m_context;
@ -457,9 +395,6 @@ private:
std::unique_ptr<RetinaHelper> m_retina_helper;
#endif
bool m_in_render;
#if !ENABLE_GCODE_VIEWER
LegendTexture m_legend_texture;
#endif // !ENABLE_GCODE_VIEWER
WarningTexture m_warning_texture;
wxTimer m_timer;
LayersEditing m_layers_editing;
@ -478,9 +413,7 @@ private:
bool m_event_handlers_bound{ false };
mutable GLVolumeCollection m_volumes;
#if ENABLE_GCODE_VIEWER
GCodeViewer m_gcode_viewer;
#endif // ENABLE_GCODE_VIEWER
Selection m_selection;
const DynamicPrintConfig* m_config;
@ -492,9 +425,6 @@ private:
bool m_initialized;
bool m_apply_zoom_to_volumes_filter;
mutable std::vector<int> m_hover_volume_idxs;
#if !ENABLE_GCODE_VIEWER
bool m_legend_texture_enabled;
#endif // !ENABLE_GCODE_VIEWER
bool m_picking_enabled;
bool m_moving_enabled;
bool m_dynamic_background_enabled;
@ -512,10 +442,6 @@ private:
bool m_reload_delayed;
#if !ENABLE_GCODE_VIEWER
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
#endif // !ENABLE_GCODE_VIEWER
#if ENABLE_RENDER_PICKING_PASS
bool m_show_picking_texture;
#endif // ENABLE_RENDER_PICKING_PASS
@ -533,6 +459,8 @@ private:
mutable bool m_tooltip_enabled{ true };
Slope m_slope;
ArrangeSettings m_arrange_settings;
public:
explicit GLCanvas3D(wxGLCanvas* canvas);
~GLCanvas3D();
@ -554,11 +482,9 @@ public:
void reset_volumes();
int check_volumes_outside_state() const;
#if ENABLE_GCODE_VIEWER
void reset_gcode_toolpaths() { m_gcode_viewer.reset(); }
const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); }
void update_gcode_sequential_view_current(unsigned int first, unsigned int last) { m_gcode_viewer.update_sequential_view_current(first, last); }
#endif // ENABLE_GCODE_VIEWER
void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
@ -622,9 +548,7 @@ public:
void zoom_to_bed();
void zoom_to_volumes();
void zoom_to_selection();
#if ENABLE_GCODE_VIEWER
void zoom_to_gcode();
#endif // ENABLE_GCODE_VIEWER
void select_view(const std::string& direction);
void update_volumes_colors_by_extruder();
@ -641,7 +565,6 @@ public:
void delete_selected();
void ensure_on_bed(unsigned int object_idx);
#if ENABLE_GCODE_VIEWER
bool is_gcode_legend_enabled() const { return m_gcode_viewer.is_legend_enabled(); }
GCodeViewer::EViewType get_gcode_view_type() const { return m_gcode_viewer.get_view_type(); }
const std::vector<double>& get_gcode_layers_zs() const;
@ -653,9 +576,6 @@ public:
void set_toolpath_view_type(GCodeViewer::EViewType type);
void set_volumes_z_range(const std::array<double, 2>& range);
void set_toolpaths_z_range(const std::array<unsigned int, 2>& range);
#else
std::vector<double> get_current_print_zs(bool active_only) const;
#endif // ENABLE_GCODE_VIEWER
void set_toolpaths_range(double low, double high);
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
@ -665,14 +585,10 @@ public:
void reload_scene(bool refresh_immediately, bool force_full_scene_refresh = false);
#if ENABLE_GCODE_VIEWER
void load_gcode_preview(const GCodeProcessor::Result& gcode_result);
void refresh_gcode_preview(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors);
void set_gcode_view_preview_type(GCodeViewer::EViewType type) { return m_gcode_viewer.set_view_type(type); }
GCodeViewer::EViewType get_gcode_view_preview_type() const { return m_gcode_viewer.get_view_type(); }
#else
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
#endif // ENABLE_GCODE_VIEWER
void load_sla_preview();
void load_preview(const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values);
void bind_event_handlers();
@ -691,10 +607,6 @@ public:
Size get_canvas_size() const;
Vec2d get_local_mouse_position() const;
#if !ENABLE_GCODE_VIEWER
void reset_legend_texture();
#endif // !ENABLE_GCODE_VIEWER
void set_tooltip(const std::string& tooltip) const;
// the following methods add a snapshot to the undo/redo stack, unless the given string is empty
@ -768,6 +680,8 @@ public:
void use_slope(bool use) { m_slope.use(use); }
void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); }
const ArrangeSettings& get_arrange_settings() const { return m_arrange_settings; }
private:
bool _is_shown_on_screen() const;
@ -792,9 +706,7 @@ private:
void _render_background() const;
void _render_bed(bool bottom, bool show_axes) const;
void _render_objects() const;
#if ENABLE_GCODE_VIEWER
void _render_gcode() const;
#endif // ENABLE_GCODE_VIEWER
void _render_selection() const;
#if ENABLE_RENDER_SELECTION_CENTER
void _render_selection_center() const;
@ -802,9 +714,6 @@ private:
void _check_and_update_toolbar_icon_scale() const;
void _render_overlays() const;
void _render_warning_texture() const;
#if !ENABLE_GCODE_VIEWER
void _render_legend_texture() const;
#endif // !ENABLE_GCODE_VIEWER
void _render_volumes_for_picking() const;
void _render_current_gizmo() const;
void _render_gizmos_overlay() const;
@ -819,6 +728,7 @@ private:
void _render_selection_sidebar_hints() const;
bool _render_undo_redo_stack(const bool is_undo, float pos_x) const;
bool _render_search_list(float pos_x) const;
bool _render_arrange_menu(float pos_x);
void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) const;
// render thumbnail using an off-screen framebuffer
void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) const;
@ -852,29 +762,12 @@ private:
// Create 3D thick extrusion lines for wipe tower extrusions
void _load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
#if !ENABLE_GCODE_VIEWER
// generates gcode extrusion paths geometry
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates gcode travel paths geometry
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates objects and wipe tower geometry
void _load_fff_shells();
#endif // !ENABLE_GCODE_VIEWER
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
void _load_sla_shells();
#if !ENABLE_GCODE_VIEWER
// sets gcode geometry visibility according to user selection
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
#endif // !ENABLE_GCODE_VIEWER
void _update_toolpath_volumes_outside_state();
void _update_sla_shells_outside_state();
void _show_warning_texture_if_needed(WarningTexture::Warning warning);
#if !ENABLE_GCODE_VIEWER
// generates the legend texture in dependence of the current shown view type
void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
#endif // !ENABLE_GCODE_VIEWER
// generates a warning texture containing the given message
void _set_warning_texture(WarningTexture::Warning warning, bool state);
@ -887,6 +780,7 @@ private:
bool _deactivate_search_toolbar_item();
bool _activate_search_toolbar_item();
bool _deactivate_collapse_toolbar_items();
bool _deactivate_arrange_menu();
float get_overlay_window_width() { return LayersEditing::get_overlay_window_width(); }

View file

@ -75,11 +75,9 @@ void GLTexture::Compressor::send_compressed_data_to_gpu()
glsafe(::glBindTexture(GL_TEXTURE_2D, m_texture.m_id));
// Querying the atomic m_num_levels_compressed value synchronizes processor caches, so that the dat of m_levels modified by the worker thread are accessible to the calling thread.
int num_compressed = (int)m_num_levels_compressed;
for (int i = 0; i < num_compressed; ++ i)
{
for (int i = 0; i < num_compressed; ++ i) {
Level& level = m_levels[i];
if (! level.sent_to_gpu && ! level.compressed_data.empty())
{
if (! level.sent_to_gpu && ! level.compressed_data.empty()) {
glsafe(::glCompressedTexSubImage2D(GL_TEXTURE_2D, (GLint)i, 0, 0, (GLsizei)level.w, (GLsizei)level.h, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)level.compressed_data.size(), (const GLvoid*)level.compressed_data.data()));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (i > 0) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
@ -102,14 +100,13 @@ void GLTexture::Compressor::compress()
assert(m_num_levels_compressed == 0);
assert(m_abort_compressing == false);
for (Level& level : m_levels)
{
for (Level& level : m_levels) {
if (m_abort_compressing)
break;
// stb_dxt library, despite claiming that the needed size of the destination buffer is equal to (source buffer size)/4,
// crashes if doing so, requiring a minimum of 16 bytes and up to a third of the source buffer size, so we set the destination buffer initial size to be half the source buffer size
level.compressed_data = std::vector<unsigned char>(std::max((unsigned int)16, level.w * level.h * 2), 0);
// crashes if doing so, requiring a minimum of 64 bytes and up to a third of the source buffer size, so we set the destination buffer initial size to be half the source buffer size
level.compressed_data = std::vector<unsigned char>(std::max((unsigned int)64, (unsigned int)level.src_data.size() / 2), 0);
int compressed_size = 0;
rygCompress(level.compressed_data.data(), level.src_data.data(), level.w, level.h, 1, compressed_size);
level.compressed_data.resize(compressed_size);
@ -166,7 +163,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
{
reset();
if (filenames.empty() || states.empty() || (sprite_size_px == 0))
if (filenames.empty() || states.empty() || sprite_size_px == 0)
return false;
// every tile needs to have a 1px border around it to avoid artifacts when linear sampling on its edges
@ -180,8 +177,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
int sprite_stride = sprite_size_px_ex * 4;
int sprite_bytes = sprite_n_pixels * 4;
if (n_pixels <= 0)
{
if (n_pixels <= 0) {
reset();
return false;
}
@ -193,15 +189,13 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
std::vector<unsigned char> output_data(sprite_bytes, 0);
NSVGrasterizer* rast = nsvgCreateRasterizer();
if (rast == nullptr)
{
if (rast == nullptr) {
reset();
return false;
}
int sprite_id = -1;
for (const std::string& filename : filenames)
{
for (const std::string& filename : filenames) {
++sprite_id;
if (!boost::filesystem::exists(filename))
@ -221,8 +215,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
// makes white only copy of the sprite
::memcpy((void*)sprite_white_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
for (int i = 0; i < sprite_n_pixels; ++i)
{
for (int i = 0; i < sprite_n_pixels; ++i) {
int offset = i * 4;
if (sprite_white_only_data.data()[offset] != 0)
::memset((void*)&sprite_white_only_data.data()[offset], 255, 3);
@ -230,8 +223,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
// makes gray only copy of the sprite
::memcpy((void*)sprite_gray_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
for (int i = 0; i < sprite_n_pixels; ++i)
{
for (int i = 0; i < sprite_n_pixels; ++i) {
int offset = i * 4;
if (sprite_gray_only_data.data()[offset] != 0)
::memset((void*)&sprite_gray_only_data.data()[offset], 128, 3);
@ -239,30 +231,26 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
int sprite_offset_px = sprite_id * (int)sprite_size_px_ex * m_width;
int state_id = -1;
for (const std::pair<int, bool>& state : states)
{
for (const std::pair<int, bool>& state : states) {
++state_id;
// select the sprite variant
std::vector<unsigned char>* src = nullptr;
switch (state.first)
{
case 1: { src = &sprite_white_only_data; break; }
case 2: { src = &sprite_gray_only_data; break; }
case 1: { src = &sprite_white_only_data; break; }
case 2: { src = &sprite_gray_only_data; break; }
default: { src = &sprite_data; break; }
}
::memcpy((void*)output_data.data(), (const void*)src->data(), sprite_bytes);
// applies background, if needed
if (state.second)
{
if (state.second) {
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)
{
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)
{
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);
@ -274,8 +262,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
}
int state_offset_px = sprite_offset_px + state_id * sprite_size_px_ex;
for (int j = 0; j < (int)sprite_size_px_ex; ++j)
{
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);
}
}
@ -309,11 +296,9 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
wxImage output(m_width, m_height);
output.InitAlpha();
for (int h = 0; h < m_height; ++h)
{
for (int h = 0; h < m_height; ++h) {
int px_h = h * m_width;
for (int w = 0; w < m_width; ++w)
{
for (int w = 0; w < m_width; ++w) {
int offset = (px_h + w) * 4;
output.SetRGB(w, h, data.data()[offset + 0], data.data()[offset + 1], data.data()[offset + 2]);
output.SetAlpha(w, h, data.data()[offset + 3]);
@ -373,8 +358,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
// Load a PNG with an alpha channel.
wxImage image;
if (!image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_PNG))
{
if (!image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_PNG)) {
reset();
return false;
}
@ -384,20 +368,17 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
bool requires_rescale = false;
if (compression_enabled && (compression_type == MultiThreaded))
{
if (compression_enabled && compression_type == MultiThreaded) {
// the stb_dxt compression library seems to like only texture sizes which are a multiple of 4
int width_rem = m_width % 4;
int height_rem = m_height % 4;
if (width_rem != 0)
{
if (width_rem != 0) {
m_width += (4 - width_rem);
requires_rescale = true;
}
if (height_rem != 0)
{
if (height_rem != 0) {
m_height += (4 - height_rem);
requires_rescale = true;
}
@ -407,16 +388,14 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
image = image.ResampleBicubic(m_width, m_height);
int n_pixels = m_width * m_height;
if (n_pixels <= 0)
{
if (n_pixels <= 0) {
reset();
return false;
}
// Get RGB & alpha raw data from wxImage, pack them into an array.
unsigned char* img_rgb = image.GetData();
if (img_rgb == nullptr)
{
if (img_rgb == nullptr) {
reset();
return false;
}
@ -424,8 +403,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
unsigned char* img_alpha = image.GetAlpha();
std::vector<unsigned char> data(n_pixels * 4, 0);
for (int i = 0; i < n_pixels; ++i)
{
for (int i = 0; i < n_pixels; ++i) {
int data_id = i * 4;
int img_id = i * 3;
data[data_id + 0] = img_rgb[img_id + 0];
@ -439,19 +417,16 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_id));
if (apply_anisotropy)
{
if (apply_anisotropy) {
GLfloat max_anisotropy = OpenGLManager::get_gl_info().get_max_anisotropy();
if (max_anisotropy > 1.0f)
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
}
if (compression_enabled)
{
if (compression_enabled) {
if (compression_type == SingleThreaded)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
else
{
else {
// initializes the texture on GPU
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
// and send the uncompressed data to the compressor
@ -461,14 +436,12 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
if (use_mipmaps)
{
if (use_mipmaps) {
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
int lod_w = m_width;
int lod_h = m_height;
GLint level = 0;
while ((lod_w > 1) || (lod_h > 1))
{
while (lod_w > 1 || lod_h > 1) {
++level;
lod_w = std::max(lod_w / 2, 1);
@ -482,8 +455,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
img_rgb = image.GetData();
img_alpha = image.GetAlpha();
for (int i = 0; i < n_pixels; ++i)
{
for (int i = 0; i < n_pixels; ++i) {
int data_id = i * 4;
int img_id = i * 3;
data[data_id + 0] = img_rgb[img_id + 0];
@ -492,12 +464,10 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
}
if (compression_enabled)
{
if (compression_enabled) {
if (compression_type == SingleThreaded)
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
else
{
else {
// initializes the texture on GPU
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
// and send the uncompressed data to the compressor
@ -508,14 +478,12 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
}
if (!compression_enabled)
{
if (!compression_enabled) {
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
}
}
else
{
else {
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
}
@ -526,7 +494,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECo
m_source = filename;
if (compression_enabled && (compression_type == MultiThreaded))
if (compression_enabled && compression_type == MultiThreaded)
// start asynchronous compression
m_compressor.start_compressing();
@ -538,8 +506,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
bool compression_enabled = compress && GLEW_EXT_texture_compression_s3tc;
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
if (image == nullptr)
{
if (image == nullptr) {
reset();
return false;
}
@ -549,8 +516,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
m_width = (int)(scale * image->width);
m_height = (int)(scale * image->height);
if (compression_enabled)
{
if (compression_enabled) {
// the stb_dxt compression library seems to like only texture sizes which are a multiple of 4
int width_rem = m_width % 4;
int height_rem = m_height % 4;
@ -564,16 +530,14 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
int n_pixels = m_width * m_height;
if (n_pixels <= 0)
{
if (n_pixels <= 0) {
reset();
nsvgDelete(image);
return false;
}
NSVGrasterizer* rast = nsvgCreateRasterizer();
if (rast == nullptr)
{
if (rast == nullptr) {
nsvgDelete(image);
reset();
return false;
@ -588,15 +552,13 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_id));
if (apply_anisotropy)
{
if (apply_anisotropy) {
GLfloat max_anisotropy = OpenGLManager::get_gl_info().get_max_anisotropy();
if (max_anisotropy > 1.0f)
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
}
if (compression_enabled)
{
if (compression_enabled) {
// initializes the texture on GPU
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
// and send the uncompressed data to the compressor
@ -605,14 +567,12 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
if (use_mipmaps)
{
if (use_mipmaps) {
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
int lod_w = m_width;
int lod_h = m_height;
GLint level = 0;
while ((lod_w > 1) || (lod_h > 1))
{
while (lod_w > 1 || lod_h > 1) {
++level;
lod_w = std::max(lod_w / 2, 1);
@ -622,8 +582,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
data.resize(lod_w * lod_h * 4);
nsvgRasterize(rast, image, 0, 0, scale, data.data(), lod_w, lod_h, lod_w * 4);
if (compression_enabled)
{
if (compression_enabled) {
// initializes the texture on GPU
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
// and send the uncompressed data to the compressor
@ -633,14 +592,12 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
}
if (!compression_enabled)
{
if (!compression_enabled) {
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
}
}
else
{
else {
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
}

View file

@ -86,7 +86,7 @@ class SplashScreen : public wxSplashScreen
{
public:
SplashScreen(const wxBitmap& bitmap, long splashStyle, int milliseconds, wxPoint pos = wxDefaultPosition)
: wxSplashScreen(bitmap, splashStyle, milliseconds, (wxWindow*)wxGetApp().mainframe, wxID_ANY, wxDefaultPosition, wxDefaultSize,
: wxSplashScreen(bitmap, splashStyle, milliseconds, static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, wxDefaultPosition, wxDefaultSize,
#ifdef __APPLE__
wxSIMPLE_BORDER | wxFRAME_NO_TASKBAR | wxSTAY_ON_TOP
#else
@ -177,11 +177,7 @@ public:
// load bitmap for logo
BitmapCache bmp_cache;
int logo_size = lround(width * 0.25);
#if ENABLE_GCODE_VIEWER
wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().is_editor() ? "prusa_slicer_logo" : "add_gcode", logo_size, logo_size);
#else
wxBitmap logo_bmp = *bmp_cache.load_svg("prusa_slicer_logo", logo_size, logo_size);
#endif // ENABLE_GCODE_VIEWER
wxCoord margin = int(m_scale * 20);
@ -229,11 +225,7 @@ private:
void init(wxFont init_font)
{
// title
#if ENABLE_GCODE_VIEWER
title = wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME;
#else
title = SLIC3R_APP_NAME;
#endif // ENABLE_GCODE_VIEWER
// dynamically get the version to display
version = _L("Version") + " " + std::string(SLIC3R_VERSION);
@ -550,7 +542,6 @@ static void register_win32_device_notification_event()
});
wxWindow::MSWRegisterMessageHandler(WM_COPYDATA, [](wxWindow* win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) {
COPYDATASTRUCT* copy_data_structure = { 0 };
copy_data_structure = (COPYDATASTRUCT*)lParam;
if (copy_data_structure->dwData == 1) {
@ -601,13 +592,11 @@ void GUI_App::post_init()
if (! this->initialized())
throw Slic3r::RuntimeError("Calling post_init() while not yet initialized");
#if ENABLE_GCODE_VIEWER
if (this->init_params->start_as_gcodeviewer) {
if (! this->init_params->input_files.empty())
this->plater()->load_gcode(wxString::FromUTF8(this->init_params->input_files[0].c_str()));
}
else {
#endif // ENABLE_GCODE_VIEWER_AS
#if 0
// Load the cummulative config over the currently active profiles.
//FIXME if multiple configs are loaded, only the last one will have an effect.
@ -626,22 +615,14 @@ void GUI_App::post_init()
this->plater()->load_files(this->init_params->input_files, true, true);
if (! this->init_params->extra_config.empty())
this->mainframe->load_config(this->init_params->extra_config);
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
}
IMPLEMENT_APP(GUI_App)
#if ENABLE_GCODE_VIEWER
GUI_App::GUI_App(EAppMode mode)
#else
GUI_App::GUI_App()
#endif // ENABLE_GCODE_VIEWER
: wxApp()
#if ENABLE_GCODE_VIEWER
, m_app_mode(mode)
#endif // ENABLE_GCODE_VIEWER
, m_em_unit(10)
, m_imgui(new ImGuiWrapper())
, m_wizard(nullptr)
@ -682,8 +663,8 @@ bool GUI_App::init_opengl()
void GUI_App::init_app_config()
{
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
SetAppName(SLIC3R_APP_KEY);
SetAppName(SLIC3R_APP_KEY "-alpha");
// SetAppName(SLIC3R_APP_KEY);
SetAppName(SLIC3R_APP_KEY "-beta");
// SetAppDisplayName(SLIC3R_APP_NAME);
// Set the Slic3r data directory at the Slic3r XS module.
@ -705,11 +686,7 @@ void GUI_App::init_app_config()
}
if (!app_config)
#if ENABLE_GCODE_VIEWER
app_config = new AppConfig(is_editor() ? AppConfig::EAppMode::Editor : AppConfig::EAppMode::GCodeViewer);
#else
app_config = new AppConfig();
#endif // ENABLE_GCODE_VIEWER
// load settings
m_app_conf_exists = app_config->exists();
@ -717,7 +694,6 @@ void GUI_App::init_app_config()
std::string error = app_config->load();
if (!error.empty()) {
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
#if ENABLE_GCODE_VIEWER
if (is_editor()) {
throw Slic3r::RuntimeError(
_u8L("Error parsing PrusaSlicer config file, it is probably corrupted. "
@ -725,14 +701,11 @@ void GUI_App::init_app_config()
"\n\n" + app_config->config_path() + "\n\n" + error);
}
else {
#endif // ENABLE_GCODE_VIEWER
throw Slic3r::RuntimeError(
_u8L("Error parsing PrusaGCodeViewer config file, it is probably corrupted. "
"Try to manually delete the file to recover from the error.") +
"\n\n" + app_config->config_path() + "\n\n" + error);
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
}
}
}
@ -775,9 +748,7 @@ bool GUI_App::on_init_inner()
// Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION;
#if ENABLE_GCODE_VIEWER
if (is_editor()) {
#endif // ENABLE_GCODE_VIEWER
std::string msg = Http::tls_global_init();
std::string ssl_cert_store = app_config->get("tls_accepted_cert_store_location");
bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes" && ssl_cert_store == Http::tls_system_cert_store();
@ -795,9 +766,7 @@ bool GUI_App::on_init_inner()
app_config->set("tls_accepted_cert_store_location",
dlg.IsCheckBoxChecked() ? Http::tls_system_cert_store() : "");
}
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
app_config->set("version", SLIC3R_VERSION);
app_config->save();
@ -807,11 +776,7 @@ bool GUI_App::on_init_inner()
SplashScreen* scrn = nullptr;
if (app_config->get("show_splash_screen") == "1") {
// make a bitmap with dark grey banner on the left side
#if ENABLE_GCODE_VIEWER
wxBitmap bmp = SplashScreen::MakeBitmap(wxBitmap(from_u8(var(is_editor() ? "splashscreen.jpg" : "splashscreen-gcodepreview.jpg")), wxBITMAP_TYPE_JPEG));
#else
wxBitmap bmp = SplashScreen::MakeBitmap(wxBitmap(from_u8(var("splashscreen.jpg")), wxBITMAP_TYPE_JPEG));
#endif // ENABLE_GCODE_VIEWER
// Detect position (display) to show the splash screen
// Now this position is equal to the mainframe position
@ -825,8 +790,10 @@ bool GUI_App::on_init_inner()
// create splash screen with updated bmp
scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("prusa_slicer_logo", nullptr, 400),
wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 4000, splashscreen_pos);
#ifndef __linux__
wxYield();
scrn->SetText(_L("Loading configuration..."));
#endif
scrn->SetText(_L("Loading configuration")+ dots);
}
preset_bundle = new PresetBundle();
@ -835,11 +802,16 @@ bool GUI_App::on_init_inner()
// supplied as argument to --datadir; in that case we should still run the wizard
preset_bundle->setup_directories();
#if ENABLE_GCODE_VIEWER
if (is_editor()) {
#endif // ENABLE_GCODE_VIEWER
#ifdef __WXMSW__
associate_3mf_files();
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (app_config->get("associate_3mf") == "1")
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
associate_3mf_files();
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (app_config->get("associate_stl") == "1")
associate_stl_files();
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#endif // __WXMSW__
preset_updater = new PresetUpdater();
@ -852,14 +824,15 @@ bool GUI_App::on_init_inner()
}
}
});
#if ENABLE_GCODE_VIEWER
}
else {
#ifdef __WXMSW__
associate_gcode_files();
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (app_config->get("associate_gcode") == "1")
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
associate_gcode_files();
#endif // __WXMSW__
}
#endif // ENABLE_GCODE_VIEWER
// initialize label colors and fonts
init_label_colours();
@ -887,18 +860,12 @@ bool GUI_App::on_init_inner()
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
// application frame
#if ENABLE_GCODE_VIEWER
if (scrn && is_editor())
#else
if (scrn)
#endif // ENABLE_GCODE_VIEWER
scrn->SetText(_L("Preparing settings tabs..."));
scrn->SetText(_L("Preparing settings tabs") + dots);
mainframe = new MainFrame();
// hide settings tabs after first Layout
#if ENABLE_GCODE_VIEWER
if (is_editor())
#endif // ENABLE_GCODE_VIEWER
mainframe->select_tab(size_t(0));
sidebar().obj_list()->init_objects(); // propagate model objects to object list
@ -939,9 +906,7 @@ bool GUI_App::on_init_inner()
if (once) {
once = false;
#if ENABLE_GCODE_VIEWER
if (preset_updater != nullptr) {
#endif // ENABLE_GCODE_VIEWER
check_updates(false);
CallAfter([this] {
@ -949,9 +914,7 @@ bool GUI_App::on_init_inner()
preset_updater->slic3r_update_notify();
preset_updater->sync(preset_bundle);
});
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
#ifdef _WIN32
//sets window property to mainframe so other instances can indentify it
@ -960,7 +923,6 @@ bool GUI_App::on_init_inner()
}
});
#if ENABLE_GCODE_VIEWER
if (is_gcode_viewer()) {
mainframe->update_layout();
if (plater_ != nullptr)
@ -968,7 +930,6 @@ bool GUI_App::on_init_inner()
plater_->set_printer_technology(ptFFF);
}
else
#endif // ENABLE_GCODE_VIEWER
load_current_presets();
mainframe->Show(true);
@ -1161,9 +1122,7 @@ void GUI_App::check_printer_presets()
void GUI_App::recreate_GUI(const wxString& msg_name)
{
#if ENABLE_GCODE_VIEWER
m_is_recreating_gui = true;
#endif // ENABLE_GCODE_VIEWER
mainframe->shutdown();
@ -1173,9 +1132,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
MainFrame *old_main_frame = mainframe;
mainframe = new MainFrame();
#if ENABLE_GCODE_VIEWER
if (is_editor())
#endif // ENABLE_GCODE_VIEWER
// hide settings tabs after first Layout
mainframe->select_tab(size_t(0));
// Propagate model objects to object list.
@ -1208,9 +1165,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
// config_wizard_startup(true);
// });
#if ENABLE_GCODE_VIEWER
m_is_recreating_gui = false;
#endif // ENABLE_GCODE_VIEWER
}
void GUI_App::system_info()
@ -1295,7 +1250,6 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
dialog.GetPaths(input_files);
}
#if ENABLE_GCODE_VIEWER
void GUI_App::load_gcode(wxWindow* parent, wxString& input_file) const
{
input_file.Clear();
@ -1307,7 +1261,6 @@ void GUI_App::load_gcode(wxWindow* parent, wxString& input_file) const
if (dialog.ShowModal() == wxID_OK)
input_file = dialog.GetPath();
}
#endif // ENABLE_GCODE_VIEWER
bool GUI_App::switch_language()
{
@ -1543,17 +1496,13 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
const auto config_wizard_name = _(ConfigWizard::name(true));
const auto config_wizard_tooltip = from_u8((boost::format(_utf8(L("Run %s"))) % config_wizard_name).str());
// Cmd+, is standard on OS X - what about other operating systems?
#if ENABLE_GCODE_VIEWER
if (is_editor()) {
#endif // ENABLE_GCODE_VIEWER
local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip);
local_menu->Append(config_id_base + ConfigMenuSnapshots, _L("&Configuration Snapshots") + dots, _L("Inspect / activate configuration snapshots"));
local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _L("Take Configuration &Snapshot"), _L("Capture a configuration snapshot"));
local_menu->Append(config_id_base + ConfigMenuUpdate, _L("Check for updates"), _L("Check for configuration updates"));
local_menu->AppendSeparator();
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
local_menu->Append(config_id_base + ConfigMenuPreferences, _L("&Preferences") + dots +
#ifdef __APPLE__
"\tCtrl+,",
@ -1561,16 +1510,10 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
"\tCtrl+P",
#endif
_L("Application preferences"));
#if ENABLE_GCODE_VIEWER
wxMenu* mode_menu = nullptr;
if (is_editor()) {
#endif // ENABLE_GCODE_VIEWER
local_menu->AppendSeparator();
#if ENABLE_GCODE_VIEWER
mode_menu = new wxMenu();
#else
auto mode_menu = new wxMenu();
#endif // ENABLE_GCODE_VIEWER
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _L("Simple"), _L("Simple View Mode"));
// mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeAdvanced, _L("Advanced"), _L("Advanced View Mode"));
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeAdvanced, _CTX(L_CONTEXT("Advanced", "Mode"), "Mode"), _L("Advanced View Mode"));
@ -1580,21 +1523,15 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { if (get_mode() == comExpert) evt.Check(true); }, config_id_base + ConfigMenuModeExpert);
local_menu->AppendSubMenu(mode_menu, _L("Mode"), wxString::Format(_L("%s View Mode"), SLIC3R_APP_NAME));
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuLanguage, _L("&Language"));
#if ENABLE_GCODE_VIEWER
if (is_editor()) {
#endif // ENABLE_GCODE_VIEWER
local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _L("Flash printer &firmware"), _L("Upload a firmware image into an Arduino based printer"));
// TODO: for when we're able to flash dictionaries
// local_menu->Append(config_id_base + FirmwareMenuDict, _L("Flash language file"), _L("Upload a language dictionary file into a Prusa printer"));
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
local_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent &event) {
switch (event.GetId() - config_id_base) {
@ -1648,10 +1585,22 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
PreferencesDialog dlg(mainframe);
dlg.ShowModal();
app_layout_changed = dlg.settings_layout_changed();
#if ENABLE_GCODE_VIEWER
if (dlg.seq_top_layer_only_changed())
this->plater_->refresh_print();
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
if (is_editor()) {
if (app_config->get("associate_3mf") == "1")
associate_3mf_files();
if (app_config->get("associate_stl") == "1")
associate_stl_files();
}
else {
if (app_config->get("associate_gcode") == "1")
associate_gcode_files();
}
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
}
if (app_layout_changed) {
// hide full main_sizer for mainFrame
@ -1670,19 +1619,13 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
// the dialog needs to be destroyed before the call to switch_language()
// or sometimes the application crashes into wxDialogBase() destructor
// so we put it into an inner scope
#if ENABLE_GCODE_VIEWER
wxString title = is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME);
title += " - " + _L("Language selection");
#endif // ENABLE_GCODE_VIEWER
wxMessageDialog dialog(nullptr,
_L("Switching the language will trigger application restart.\n"
"You will lose content of the plater.") + "\n\n" +
_L("Do you want to proceed?"),
#if ENABLE_GCODE_VIEWER
title,
#else
wxString(SLIC3R_APP_NAME) + " - " + _L("Language selection"),
#endif // ENABLE_GCODE_VIEWER
wxICON_QUESTION | wxOK | wxCANCEL);
if (dialog.ShowModal() == wxID_CANCEL)
return;
@ -1701,16 +1644,12 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
using std::placeholders::_1;
#if ENABLE_GCODE_VIEWER
if (mode_menu != nullptr) {
#endif // ENABLE_GCODE_VIEWER
auto modfn = [this](int mode, wxCommandEvent&) { if (get_mode() != mode) save_mode(mode); };
mode_menu->Bind(wxEVT_MENU, std::bind(modfn, comSimple, _1), config_id_base + ConfigMenuModeSimple);
mode_menu->Bind(wxEVT_MENU, std::bind(modfn, comAdvanced, _1), config_id_base + ConfigMenuModeAdvanced);
mode_menu->Bind(wxEVT_MENU, std::bind(modfn, comExpert, _1), config_id_base + ConfigMenuModeExpert);
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
menu->Append(local_menu, _L("&Configuration"));
}
@ -1832,8 +1771,17 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
if (!non_gcode_files.empty())
start_new_slicer(non_gcode_files, true);
} else {
if (! files.empty())
if (! files.empty()) {
#if ENABLE_DRAG_AND_DROP_FIX
wxArrayString input_files;
for (size_t i = 0; i < non_gcode_files.size(); ++i) {
input_files.push_back(non_gcode_files[i]);
}
this->plater()->load_files(input_files);
#else
this->plater()->load_files(files, true, true);
#endif
}
for (const wxString &filename : gcode_files)
start_new_gcodeviewer(&filename);
}
@ -2197,6 +2145,32 @@ void GUI_App::associate_3mf_files()
::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
}
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
void GUI_App::associate_stl_files()
{
wchar_t app_path[MAX_PATH];
::GetModuleFileNameW(nullptr, app_path, sizeof(app_path));
std::wstring prog_path = L"\"" + std::wstring(app_path) + L"\"";
std::wstring prog_id = L"Prusa.Slicer.1";
std::wstring prog_desc = L"PrusaSlicer";
std::wstring prog_command = prog_path + L" \"%1\"";
std::wstring reg_base = L"Software\\Classes";
std::wstring reg_extension = reg_base + L"\\.stl";
std::wstring reg_prog_id = reg_base + L"\\" + prog_id;
std::wstring reg_prog_id_command = reg_prog_id + L"\\Shell\\Open\\Command";
bool is_new = false;
is_new |= set_into_win_registry(HKEY_CURRENT_USER, reg_extension.c_str(), prog_id.c_str());
is_new |= set_into_win_registry(HKEY_CURRENT_USER, reg_prog_id.c_str(), prog_desc.c_str());
is_new |= set_into_win_registry(HKEY_CURRENT_USER, reg_prog_id_command.c_str(), prog_command.c_str());
if (is_new)
// notify Windows only when any of the values gets changed
::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
}
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
void GUI_App::associate_gcode_files()
{
wchar_t app_path[MAX_PATH];

View file

@ -97,7 +97,6 @@ static wxString dots("…", wxConvUTF8);
class GUI_App : public wxApp
{
#if ENABLE_GCODE_VIEWER
public:
enum class EAppMode : unsigned char
{
@ -106,14 +105,10 @@ public:
};
private:
#endif // ENABLE_GCODE_VIEWER
bool m_initialized { false };
bool m_app_conf_exists{ false };
#if ENABLE_GCODE_VIEWER
EAppMode m_app_mode{ EAppMode::Editor };
bool m_is_recreating_gui{ false };
#endif // ENABLE_GCODE_VIEWER
wxColour m_color_label_modified;
wxColour m_color_label_sys;
@ -149,19 +144,13 @@ public:
bool OnInit() override;
bool initialized() const { return m_initialized; }
#if ENABLE_GCODE_VIEWER
explicit GUI_App(EAppMode mode = EAppMode::Editor);
#else
GUI_App();
#endif // ENABLE_GCODE_VIEWER
~GUI_App() override;
#if ENABLE_GCODE_VIEWER
EAppMode get_app_mode() const { return m_app_mode; }
bool is_editor() const { return m_app_mode == EAppMode::Editor; }
bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
bool is_recreating_gui() const { return m_is_recreating_gui; }
#endif // ENABLE_GCODE_VIEWER
// To be called after the GUI is fully built up.
// Process command line parameters cached in this->init_params,
@ -199,9 +188,7 @@ public:
void keyboard_shortcuts();
void load_project(wxWindow *parent, wxString& input_file) const;
void import_model(wxWindow *parent, wxArrayString& input_files) const;
#if ENABLE_GCODE_VIEWER
void load_gcode(wxWindow* parent, wxString& input_file) const;
#endif // ENABLE_GCODE_VIEWER
static bool catch_error(std::function<void()> cb, const std::string& err);
@ -287,6 +274,14 @@ public:
bool is_gl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_version_greater_or_equal_to(major, minor); }
bool is_glsl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_glsl_version_greater_or_equal_to(major, minor); }
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef __WXMSW__
void associate_3mf_files();
void associate_stl_files();
void associate_gcode_files();
#endif // __WXMSW__
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
private:
bool on_init_inner();
void init_app_config();
@ -298,11 +293,14 @@ private:
bool config_wizard_startup();
void check_updates(const bool verbose);
#if !ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef __WXMSW__
void associate_3mf_files();
void associate_gcode_files();
#endif // __WXMSW__
#endif // !ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
};
DECLARE_APP(GUI_App)
} // GUI

View file

@ -22,7 +22,6 @@ namespace GUI {
int GUI_Run(GUI_InitParams &params)
{
try {
#if ENABLE_GCODE_VIEWER
GUI::GUI_App* gui = new GUI::GUI_App(params.start_as_gcodeviewer ? GUI::GUI_App::EAppMode::GCodeViewer : GUI::GUI_App::EAppMode::Editor);
if (gui->get_app_mode() != GUI::GUI_App::EAppMode::GCodeViewer) {
// G-code viewer is currently not performing instance check, a new G-code viewer is started every time.
@ -32,29 +31,20 @@ int GUI_Run(GUI_InitParams &params)
return -1;
}
}
#else
GUI::GUI_App *gui = new GUI::GUI_App();
#endif // ENABLE_GCODE_VIEWER
// gui->autosave = m_config.opt_string("autosave");
GUI::GUI_App::SetInstance(gui);
gui->init_params = &params;
/*
#if ENABLE_GCODE_VIEWER
gui->CallAfter([gui, this, &load_configs, params.start_as_gcodeviewer] {
#else
gui->CallAfter([gui, this, &load_configs] {
#endif // ENABLE_GCODE_VIEWER
if (!gui->initialized()) {
return;
}
#if ENABLE_GCODE_VIEWER
if (params.start_as_gcodeviewer) {
if (!m_input_files.empty())
gui->plater()->load_gcode(wxString::FromUTF8(m_input_files[0].c_str()));
} else {
#endif // ENABLE_GCODE_VIEWER_AS
#if 0
// Load the cummulative config over the currently active profiles.
//FIXME if multiple configs are loaded, only the last one will have an effect.
@ -73,9 +63,7 @@ int GUI_Run(GUI_InitParams &params)
gui->plater()->load_files(m_input_files, true, true);
if (!m_extra_config.empty())
gui->mainframe->load_config(m_extra_config);
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
});
*/
int result = wxEntry(params.argc, params.argv);

View file

@ -10,9 +10,7 @@
#include "libslic3r/PresetBundle.hpp"
#include "DoubleSlider.hpp"
#include "Plater.hpp"
#if ENABLE_GCODE_VIEWER
#include "MainFrame.hpp"
#endif // ENABLE_GCODE_VIEWER
#include <wx/notebook.h>
#include <wx/glcanvas.h>
@ -168,62 +166,33 @@ void View3D::render()
m_canvas->set_as_dirty();
}
#if ENABLE_GCODE_VIEWER
Preview::Preview(
wxWindow* parent, Model* model, DynamicPrintConfig* config,
BackgroundSlicingProcess* process, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process_func)
#else
Preview::Preview(
wxWindow* parent, Model* model, DynamicPrintConfig* config,
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
#endif // ENABLE_GCODE_VIEWER
: m_canvas_widget(nullptr)
, m_canvas(nullptr)
#if ENABLE_GCODE_VIEWER
, m_left_sizer(nullptr)
, m_layers_slider_sizer(nullptr)
, m_bottom_toolbar_panel(nullptr)
#else
, m_double_slider_sizer(nullptr)
#endif // ENABLE_GCODE_VIEWER
, m_label_view_type(nullptr)
, m_choice_view_type(nullptr)
, m_label_show(nullptr)
, m_combochecklist_features(nullptr)
#if ENABLE_GCODE_VIEWER
, m_combochecklist_features_pos(0)
, m_combochecklist_options(nullptr)
#else
, m_checkbox_travel(nullptr)
, m_checkbox_retractions(nullptr)
, m_checkbox_unretractions(nullptr)
, m_checkbox_shells(nullptr)
, m_checkbox_legend(nullptr)
#endif // ENABLE_GCODE_VIEWER
, m_config(config)
, m_process(process)
#if ENABLE_GCODE_VIEWER
, m_gcode_result(gcode_result)
#else
, m_gcode_preview_data(gcode_preview_data)
#endif // ENABLE_GCODE_VIEWER
, m_number_extruders(1)
, m_preferred_color_mode("feature")
, m_loaded(false)
#if !ENABLE_GCODE_VIEWER
, m_enabled(false)
#endif // !ENABLE_GCODE_VIEWER
, m_schedule_background_process(schedule_background_process_func)
#ifdef __linux__
, m_volumes_cleanup_required(false)
#endif // __linux__
{
if (init(parent, model)) {
#if !ENABLE_GCODE_VIEWER
show_hide_ui_elements("none");
#endif // !ENABLE_GCODE_VIEWER
if (init(parent, model))
load_print();
}
}
bool Preview::init(wxWindow* parent, Model* model)
@ -231,14 +200,12 @@ bool Preview::init(wxWindow* parent, Model* model)
if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */))
return false;
#if ENABLE_GCODE_VIEWER
// to match the background of the sliders
#ifdef _WIN32
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#else
SetBackgroundColour(GetParent()->GetBackgroundColour());
#endif // _WIN32
#endif // ENABLE_GCODE_VIEWER
m_canvas_widget = OpenGLManager::create_wxglcanvas(*this);
if (m_canvas_widget == nullptr)
@ -253,20 +220,11 @@ bool Preview::init(wxWindow* parent, Model* model)
m_canvas->enable_legend_texture(true);
m_canvas->enable_dynamic_background(true);
#if ENABLE_GCODE_VIEWER
m_layers_slider_sizer = create_layers_slider_sizer();
m_bottom_toolbar_panel = new wxPanel(this);
m_label_view_type = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("View"));
m_choice_view_type = new wxChoice(m_bottom_toolbar_panel, wxID_ANY);
#else
m_double_slider_sizer = new wxBoxSizer(wxHORIZONTAL);
create_double_slider();
m_label_view_type = new wxStaticText(this, wxID_ANY, _L("View"));
m_choice_view_type = new wxChoice(this, wxID_ANY);
#endif // ENABLE_GCODE_VIEWER
m_choice_view_type->Append(_L("Feature type"));
m_choice_view_type->Append(_L("Height"));
m_choice_view_type->Append(_L("Width"));
@ -277,22 +235,12 @@ bool Preview::init(wxWindow* parent, Model* model)
m_choice_view_type->Append(_L("Color Print"));
m_choice_view_type->SetSelection(0);
#if ENABLE_GCODE_VIEWER
m_label_show = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("Show"));
#else
m_label_show = new wxStaticText(this, wxID_ANY, _L("Show"));
#endif // ENABLE_GCODE_VIEWER
m_combochecklist_features = new wxComboCtrl();
#if ENABLE_GCODE_VIEWER
m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, wxCB_READONLY);
#else
m_combochecklist_features->Create(this, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, wxCB_READONLY);
#endif // ENABLE_GCODE_VIEWER
std::string feature_items = GUI::into_u8(
#if ENABLE_GCODE_VIEWER
_L("Unknown") + "|1|" +
#endif // ENABLE_GCODE_VIEWER
_L("Perimeter") + "|1|" +
_L("External perimeter") + "|1|" +
_L("Overhang perimeter") + "|1|" +
@ -310,11 +258,13 @@ bool Preview::init(wxWindow* parent, Model* model)
);
Slic3r::GUI::create_combochecklist(m_combochecklist_features, GUI::into_u8(_L("Feature types")), feature_items);
#if ENABLE_GCODE_VIEWER
m_combochecklist_options = new wxComboCtrl();
m_combochecklist_options->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Options"), wxDefaultPosition, wxDefaultSize, wxCB_READONLY);
std::string options_items = GUI::into_u8(
get_option_type_string(OptionType::Travel) + "|0|" +
#if ENABLE_SHOW_WIPE_MOVES
get_option_type_string(OptionType::Wipe) + "|0|" +
#endif // ENABLE_SHOW_WIPE_MOVES
get_option_type_string(OptionType::Retractions) + "|0|" +
get_option_type_string(OptionType::Unretractions) + "|0|" +
get_option_type_string(OptionType::ToolChanges) + "|0|" +
@ -324,25 +274,16 @@ bool Preview::init(wxWindow* parent, Model* model)
get_option_type_string(OptionType::Shells) + "|0|" +
get_option_type_string(OptionType::ToolMarker) + "|1|" +
get_option_type_string(OptionType::Legend) + "|1"
);
);
Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
#else
m_checkbox_travel = new wxCheckBox(this, wxID_ANY, _L("Travel"));
m_checkbox_retractions = new wxCheckBox(this, wxID_ANY, _L("Retractions"));
m_checkbox_unretractions = new wxCheckBox(this, wxID_ANY, _L("Deretractions"));
m_checkbox_shells = new wxCheckBox(this, wxID_ANY, _L("Shells"));
m_checkbox_legend = new wxCheckBox(this, wxID_ANY, _L("Legend"));
m_checkbox_legend->SetValue(true);
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
m_left_sizer = new wxBoxSizer(wxVERTICAL);
m_left_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
wxBoxSizer* right_sizer = new wxBoxSizer(wxVERTICAL);
right_sizer->Add(m_layers_slider_sizer, 1, wxEXPAND, 0);
m_moves_slider = new DoubleSlider::Control(m_bottom_toolbar_panel, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxSize(-1, 3 * GetTextExtent("m").y), wxSL_HORIZONTAL);
m_moves_slider = new DoubleSlider::Control(m_bottom_toolbar_panel, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView);
wxBoxSizer* bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL);
@ -366,32 +307,6 @@ bool Preview::init(wxWindow* parent, Model* model)
wxBoxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL);
main_sizer->Add(m_left_sizer, 1, wxALL | wxEXPAND, 0);
main_sizer->Add(right_sizer, 0, wxALL | wxEXPAND, 0);
#else
wxBoxSizer* top_sizer = new wxBoxSizer(wxHORIZONTAL);
top_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
top_sizer->Add(m_double_slider_sizer, 0, wxEXPAND, 0);
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
bottom_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5);
bottom_sizer->Add(m_choice_view_type, 0, wxEXPAND | wxALL, 5);
bottom_sizer->AddSpacer(10);
bottom_sizer->Add(m_label_show, 0, wxALIGN_CENTER_VERTICAL, 5);
bottom_sizer->Add(m_combochecklist_features, 0, wxEXPAND | wxALL, 5);
bottom_sizer->AddSpacer(20);
bottom_sizer->Add(m_checkbox_travel, 0, wxEXPAND | wxALL, 5);
bottom_sizer->AddSpacer(10);
bottom_sizer->Add(m_checkbox_retractions, 0, wxEXPAND | wxALL, 5);
bottom_sizer->AddSpacer(10);
bottom_sizer->Add(m_checkbox_unretractions, 0, wxEXPAND | wxALL, 5);
bottom_sizer->AddSpacer(10);
bottom_sizer->Add(m_checkbox_shells, 0, wxEXPAND | wxALL, 5);
bottom_sizer->AddSpacer(20);
bottom_sizer->Add(m_checkbox_legend, 0, wxEXPAND | wxALL, 5);
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(top_sizer, 1, wxALL | wxEXPAND, 0);
main_sizer->Add(bottom_sizer, 0, wxALL | wxEXPAND, 0);
#endif // ENABLE_GCODE_VIEWER
SetSizer(main_sizer);
SetMinSize(GetSize());
@ -399,26 +314,6 @@ bool Preview::init(wxWindow* parent, Model* model)
bind_event_handlers();
#if !ENABLE_GCODE_VIEWER
// sets colors for gcode preview extrusion roles
std::vector<std::string> extrusion_roles_colors = {
"Perimeter", "FFFF66",
"External perimeter", "FFA500",
"Overhang perimeter", "0000FF",
"Internal infill", "B1302A",
"Solid infill", "D732D7",
"Top solid infill", "FF1A1A",
"Bridge infill", "9999FF",
"Gap fill", "FFFFFF",
"Skirt", "845321",
"Support material", "00FF00",
"Support material interface", "008000",
"Wipe tower", "B3E3AB",
"Custom", "28CC94"
};
m_gcode_preview_data->set_extrusion_paths_colors(extrusion_roles_colors);
#endif // !ENABLE_GCODE_VIEWER
return true;
}
@ -441,31 +336,18 @@ void Preview::set_as_dirty()
void Preview::set_number_extruders(unsigned int number_extruders)
{
if (m_number_extruders != number_extruders)
{
if (m_number_extruders != number_extruders) {
m_number_extruders = number_extruders;
int tool_idx = m_choice_view_type->FindString(_(L("Tool")));
int type = (number_extruders > 1) ? tool_idx /* color by a tool number */ : 0; // color by a feature type
m_choice_view_type->SetSelection(type);
#if ENABLE_GCODE_VIEWER
if ((0 <= type) && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
if (0 <= type && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
#else
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
#endif // ENABLE_GCODE_VIEWER
m_preferred_color_mode = (type == tool_idx) ? "tool_or_feature" : "feature";
}
}
#if !ENABLE_GCODE_VIEWER
void Preview::set_enabled(bool enabled)
{
m_enabled = enabled;
}
#endif // !ENABLE_GCODE_VIEWER
void Preview::bed_shape_changed()
{
if (m_canvas != nullptr)
@ -491,9 +373,7 @@ void Preview::load_print(bool keep_z_range)
else if (tech == ptSLA)
load_print_as_sla();
#if ENABLE_GCODE_VIEWER
update_bottom_toolbar();
#endif // ENABLE_GCODE_VIEWER
Layout();
}
@ -515,9 +395,6 @@ void Preview::reload_print(bool keep_volumes)
!keep_volumes)
{
m_canvas->reset_volumes();
#if !ENABLE_GCODE_VIEWER
m_canvas->reset_legend_texture();
#endif // !ENABLE_GCODE_VIEWER
m_loaded = false;
#ifdef __linux__
m_volumes_cleanup_required = false;
@ -540,12 +417,8 @@ void Preview::refresh_print()
void Preview::msw_rescale()
{
// rescale slider
#if ENABLE_GCODE_VIEWER
if (m_layers_slider != nullptr) m_layers_slider->msw_rescale();
if (m_moves_slider != nullptr) m_moves_slider->msw_rescale();
#else
if (m_slider) m_slider->msw_rescale();
#endif // ENABLE_GCODE_VIEWER
// rescale warning legend on the canvas
get_canvas3d()->msw_rescale();
@ -556,55 +429,26 @@ void Preview::msw_rescale()
void Preview::jump_layers_slider(wxKeyEvent& evt)
{
#if ENABLE_GCODE_VIEWER
if (m_layers_slider) m_layers_slider->OnChar(evt);
#else
if (m_slider)
m_slider->OnKeyDown(evt);
#endif // ENABLE_GCODE_VIEWER
}
#if ENABLE_GCODE_VIEWER
void Preview::move_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider != nullptr) m_layers_slider->OnKeyDown(evt);
}
#else
void Preview::move_double_slider(wxKeyEvent& evt)
{
if (m_slider)
m_slider->OnKeyDown(evt);
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
void Preview::edit_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider != nullptr) m_layers_slider->OnChar(evt);
}
#else
void Preview::edit_double_slider(wxKeyEvent& evt)
{
if (m_slider)
m_slider->OnChar(evt);
}
#endif // ENABLE_GCODE_VIEWER
void Preview::bind_event_handlers()
{
this->Bind(wxEVT_SIZE, &Preview::on_size, this);
m_choice_view_type->Bind(wxEVT_CHOICE, &Preview::on_choice_view_type, this);
m_combochecklist_features->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
#if ENABLE_GCODE_VIEWER
m_combochecklist_options->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this);
m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
#else
m_checkbox_travel->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_travel, this);
m_checkbox_retractions->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_retractions, this);
m_checkbox_unretractions->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_unretractions, this);
m_checkbox_shells->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_shells, this);
m_checkbox_legend->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_legend, this);
#endif // ENABLE_GCODE_VIEWER
}
void Preview::unbind_event_handlers()
@ -612,76 +456,15 @@ void Preview::unbind_event_handlers()
this->Unbind(wxEVT_SIZE, &Preview::on_size, this);
m_choice_view_type->Unbind(wxEVT_CHOICE, &Preview::on_choice_view_type, this);
m_combochecklist_features->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
#if ENABLE_GCODE_VIEWER
m_combochecklist_options->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this);
m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
#else
m_checkbox_travel->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_travel, this);
m_checkbox_retractions->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_retractions, this);
m_checkbox_unretractions->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_unretractions, this);
m_checkbox_shells->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_shells, this);
m_checkbox_legend->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_legend, this);
#endif // ENABLE_GCODE_VIEWER
}
#if !ENABLE_GCODE_VIEWER
void Preview::show_hide_ui_elements(const std::string& what)
{
bool enable = (what == "full");
m_label_show->Enable(enable);
m_combochecklist_features->Enable(enable);
m_checkbox_travel->Enable(enable);
m_checkbox_retractions->Enable(enable);
m_checkbox_unretractions->Enable(enable);
m_checkbox_shells->Enable(enable);
m_checkbox_legend->Enable(enable);
enable = (what != "none");
m_label_view_type->Enable(enable);
m_choice_view_type->Enable(enable);
bool visible = (what != "none");
m_label_show->Show(visible);
m_combochecklist_features->Show(visible);
m_checkbox_travel->Show(visible);
m_checkbox_retractions->Show(visible);
m_checkbox_unretractions->Show(visible);
m_checkbox_shells->Show(visible);
m_checkbox_legend->Show(visible);
m_label_view_type->Show(visible);
m_choice_view_type->Show(visible);
}
#endif // !ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
void Preview::hide_layers_slider()
{
m_layers_slider_sizer->Hide((size_t)0);
Layout();
}
#else
void Preview::reset_sliders(bool reset_all)
{
m_enabled = false;
// reset_double_slider();
if (reset_all)
m_double_slider_sizer->Hide((size_t)0);
else
m_double_slider_sizer->GetItem(size_t(0))->GetSizer()->Hide(1);
}
#endif // ENABLE_GCODE_VIEWER
#if !ENABLE_GCODE_VIEWER
void Preview::update_sliders(const std::vector<double>& layers_z, bool keep_z_range)
{
m_enabled = true;
update_double_slider(layers_z, keep_z_range);
m_double_slider_sizer->Show((size_t)0);
Layout();
}
#endif // !ENABLE_GCODE_VIEWER
void Preview::on_size(wxSizeEvent& evt)
{
@ -693,31 +476,19 @@ void Preview::on_choice_view_type(wxCommandEvent& evt)
{
m_preferred_color_mode = (m_choice_view_type->GetStringSelection() == L("Tool")) ? "tool" : "feature";
int selection = m_choice_view_type->GetCurrentSelection();
#if ENABLE_GCODE_VIEWER
if (0 <= selection && selection < static_cast<int>(GCodeViewer::EViewType::Count))
m_canvas->set_toolpath_view_type(static_cast<GCodeViewer::EViewType>(selection));
refresh_print();
#else
if ((0 <= selection) && (selection < (int)GCodePreviewData::Extrusion::Num_View_Types))
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)selection;
reload_print();
#endif // ENABLE_GCODE_VIEWER
}
void Preview::on_combochecklist_features(wxCommandEvent& evt)
{
unsigned int flags = Slic3r::GUI::combochecklist_get_flags(m_combochecklist_features);
#if ENABLE_GCODE_VIEWER
m_canvas->set_toolpath_role_visibility_flags(flags);
#else
m_gcode_preview_data->extrusion.role_flags = flags;
#endif // ENABLE_GCODE_VIEWER
refresh_print();
}
#if ENABLE_GCODE_VIEWER
void Preview::on_combochecklist_options(wxCommandEvent& evt)
{
auto xored = [](unsigned int flags1, unsigned int flags2, unsigned int flag) {
@ -742,39 +513,6 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt)
else
m_canvas->set_as_dirty();
}
#else
void Preview::on_checkbox_travel(wxCommandEvent& evt)
{
m_gcode_preview_data->travel.is_visible = m_checkbox_travel->IsChecked();
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)
{
m_gcode_preview_data->retraction.is_visible = m_checkbox_retractions->IsChecked();
refresh_print();
}
void Preview::on_checkbox_unretractions(wxCommandEvent& evt)
{
m_gcode_preview_data->unretraction.is_visible = m_checkbox_unretractions->IsChecked();
refresh_print();
}
void Preview::on_checkbox_shells(wxCommandEvent& evt)
{
m_gcode_preview_data->shell.is_visible = m_checkbox_shells->IsChecked();
refresh_print();
}
void Preview::on_checkbox_legend(wxCommandEvent& evt)
{
m_canvas->enable_legend_texture(m_checkbox_legend->IsChecked());
m_canvas_widget->Refresh();
}
#endif // ENABLE_GCODE_VIEWER
void Preview::update_view_type(bool keep_volumes)
{
@ -790,49 +528,34 @@ void Preview::update_view_type(bool keep_volumes)
int type = m_choice_view_type->FindString(choice);
if (m_choice_view_type->GetSelection() != type) {
m_choice_view_type->SetSelection(type);
#if ENABLE_GCODE_VIEWER
if ((0 <= type) && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
if (0 <= type && type < static_cast<int>(GCodeViewer::EViewType::Count))
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
#else
if (0 <= type && type < (int)GCodePreviewData::Extrusion::Num_View_Types)
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
#endif // ENABLE_GCODE_VIEWER
m_preferred_color_mode = "feature";
}
#if ENABLE_GCODE_VIEWER
reload_print(keep_volumes);
#else
reload_print();
#endif // ENABLE_GCODE_VIEWER
}
#if ENABLE_GCODE_VIEWER
void Preview::update_bottom_toolbar()
{
combochecklist_set_flags(m_combochecklist_features, m_canvas->get_toolpath_role_visibility_flags());
combochecklist_set_flags(m_combochecklist_options, m_canvas->get_gcode_options_visibility_flags());
// updates visibility of features combobox
if (m_bottom_toolbar_panel->IsShown())
{
if (m_bottom_toolbar_panel->IsShown()) {
wxSizer* sizer = m_bottom_toolbar_panel->GetSizer();
bool show = !m_canvas->is_gcode_legend_enabled() || m_canvas->get_gcode_view_type() != GCodeViewer::EViewType::FeatureType;
if (show)
{
if (sizer->GetItem(m_combochecklist_features) == nullptr)
{
if (show) {
if (sizer->GetItem(m_combochecklist_features) == nullptr) {
sizer->Insert(m_combochecklist_features_pos, m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
sizer->Show(m_combochecklist_features);
sizer->Layout();
Refresh();
}
}
else
{
if (sizer->GetItem(m_combochecklist_features) != nullptr)
{
else {
if (sizer->GetItem(m_combochecklist_features) != nullptr) {
sizer->Hide(m_combochecklist_features);
sizer->Detach(m_combochecklist_features);
sizer->Layout();
@ -841,9 +564,7 @@ void Preview::update_bottom_toolbar()
}
}
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
wxBoxSizer* Preview::create_layers_slider_sizer()
{
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
@ -875,37 +596,6 @@ wxBoxSizer* Preview::create_layers_slider_sizer()
return sizer;
}
#else
void Preview::create_double_slider()
{
m_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100);
bool sla_print_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA;
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
m_slider->SetDrawMode(sla_print_technology, sequential_print);
m_double_slider_sizer->Add(m_slider, 0, wxEXPAND, 0);
// sizer, m_canvas_widget
m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_double_slider_from_canvas, this);
m_canvas_widget->Bind(wxEVT_KEY_UP, [this](wxKeyEvent& event) {
if (event.GetKeyCode() == WXK_SHIFT)
m_slider->UseDefaultColors(true);
event.Skip();
});
m_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_sliders_scroll_changed, this);
Bind(DoubleSlider::wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) {
Model& model = wxGetApp().plater()->model();
model.custom_gcode_per_print_z = m_slider->GetTicksValues();
m_schedule_background_process();
update_view_type(false);
});
}
#endif // ENABLE_GCODE_VIEWER
// Find an index of a value in a sorted vector, which is in <z-eps, z+eps>.
// Returns -1 if there is no such member.
@ -934,12 +624,7 @@ static int find_close_layer_idx(const std::vector<double>& zs, double &z, double
return -1;
}
#if ENABLE_GCODE_VIEWER
void Preview::check_layers_slider_values(std::vector<CustomGCode::Item>& ticks_from_model, const std::vector<double>& layers_z)
#else
void Preview::check_slider_values(std::vector<CustomGCode::Item>& ticks_from_model,
const std::vector<double>& layers_z)
#endif // ENABLE_GCODE_VIEWER
{
// All ticks that would end up outside the slider range should be erased.
// TODO: this should be placed into more appropriate part of code,
@ -956,7 +641,6 @@ void Preview::check_slider_values(std::vector<CustomGCode::Item>& ticks_from_mod
m_schedule_background_process();
}
#if ENABLE_GCODE_VIEWER
void Preview::update_layers_slider(const std::vector<double>& layers_z, bool keep_z_range)
{
// Save the initial slider span.
@ -976,7 +660,8 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
// Detect and set manipulation mode for double slider
update_layers_slider_mode();
CustomGCode::Info& ticks_info_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z;
Plater* plater = wxGetApp().plater();
CustomGCode::Info& ticks_info_from_model = plater->model().custom_gcode_per_print_z;
check_layers_slider_values(ticks_info_from_model.gcodes, layers_z);
m_layers_slider->SetSliderValues(layers_z);
@ -1000,72 +685,20 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
m_layers_slider->SetSelectionSpan(idx_low, idx_high);
m_layers_slider->SetTicksValues(ticks_info_from_model);
bool sla_print_technology = wxGetApp().plater()->printer_technology() == ptSLA;
bool sla_print_technology = plater->printer_technology() == ptSLA;
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
m_layers_slider->SetDrawMode(sla_print_technology, sequential_print);
m_layers_slider->SetExtruderColors(wxGetApp().plater()->get_extruder_colors_from_plater_config());
m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config());
if (sla_print_technology)
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times);
else
m_layers_slider->SetLayersTimes(m_gcode_result->time_statistics.modes.front().layers_times);
m_layers_slider_sizer->Show((size_t)0);
Layout();
}
#else
void Preview::update_double_slider(const std::vector<double> & layers_z, bool keep_z_range)
{
// Save the initial slider span.
double z_low = m_slider->GetLowerValueD();
double z_high = m_slider->GetHigherValueD();
bool was_empty = m_slider->GetMaxValue() == 0;
bool force_sliders_full_range = was_empty;
if (!keep_z_range)
{
bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_slider->GetMaxValueD()) > DoubleSlider::epsilon()/*1e-6*/;
force_sliders_full_range |= span_changed;
}
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();
// Detect and set manipulation mode for double slider
update_double_slider_mode();
CustomGCode::Info& 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);
m_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1);
int idx_low = 0;
int idx_high = m_slider->GetMaxValue();
if (!layers_z.empty()) {
if (!snap_to_min) {
int idx_new = find_close_layer_idx(layers_z, z_low, DoubleSlider::epsilon()/*1e-6*/);
if (idx_new != -1)
idx_low = idx_new;
}
if (!snap_to_max) {
int idx_new = find_close_layer_idx(layers_z, z_high, DoubleSlider::epsilon()/*1e-6*/);
if (idx_new != -1)
idx_high = idx_new;
}
}
m_slider->SetSelectionSpan(idx_low, idx_high);
m_slider->SetTicksValues(ticks_info_from_model);
bool sla_print_technology = wxGetApp().plater()->printer_technology() == ptSLA;
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
m_slider->SetDrawMode(sla_print_technology, sequential_print);
m_slider->SetExtruderColors(wxGetApp().plater()->get_extruder_colors_from_plater_config());
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
void Preview::update_layers_slider_mode()
#else
void Preview::update_double_slider_mode()
#endif // ENABLE_GCODE_VIEWER
{
// true -> single-extruder printer profile OR
// multi-extruder printer profile , but whole model is printed by only one extruder
@ -1114,28 +747,15 @@ void Preview::update_double_slider_mode()
}
}
#if ENABLE_GCODE_VIEWER
m_layers_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder);
#else
m_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder);
#endif // ENABLE_GCODE_VIEWER
}
#if ENABLE_GCODE_VIEWER
void Preview::reset_layers_slider()
{
m_layers_slider->SetHigherValue(0);
m_layers_slider->SetLowerValue(0);
}
#else
void Preview::reset_double_slider()
{
m_slider->SetHigherValue(0);
m_slider->SetLowerValue(0);
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
void Preview::update_layers_slider_from_canvas(wxKeyEvent& event)
{
if (event.HasModifiers()) {
@ -1184,42 +804,12 @@ void Preview::enable_moves_slider(bool enable)
m_moves_slider->Refresh();
}
}
#else
void Preview::update_double_slider_from_canvas(wxKeyEvent & event)
{
if (event.HasModifiers()) {
event.Skip();
return;
}
const auto key = event.GetKeyCode();
if (key == 'U' || key == 'D') {
const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1;
m_slider->SetHigherValue(new_pos);
if (event.ShiftDown() || m_slider->is_one_layer()) m_slider->SetLowerValue(m_slider->GetHigherValue());
}
else if (key == 'L') {
m_checkbox_legend->SetValue(!m_checkbox_legend->GetValue());
auto evt = wxCommandEvent();
on_checkbox_legend(evt);
}
else if (key == 'S')
m_slider->ChangeOneLayerLock();
else if (key == WXK_SHIFT)
m_slider->UseDefaultColors(false);
else
event.Skip();
}
#endif // ENABLE_GCODE_VIEWER
void Preview::load_print_as_fff(bool keep_z_range)
{
#if ENABLE_GCODE_VIEWER
if (wxGetApp().mainframe == nullptr || wxGetApp().is_recreating_gui())
// avoid processing while mainframe is being constructed
return;
#endif // ENABLE_GCODE_VIEWER
if (m_loaded || m_process->current_printer_technology() != ptFFF)
return;
@ -1244,17 +834,11 @@ void Preview::load_print_as_fff(bool keep_z_range)
}
}
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_editor() && !has_layers) {
hide_layers_slider();
m_left_sizer->Hide(m_bottom_toolbar_panel);
m_left_sizer->Layout();
Refresh();
#else
if (! has_layers) {
reset_sliders(true);
m_canvas->reset_legend_texture();
#endif // ENABLE_GCODE_VIEWER
m_canvas_widget->Refresh();
return;
}
@ -1266,100 +850,58 @@ void Preview::load_print_as_fff(bool keep_z_range)
int tool_idx = m_choice_view_type->FindString(_L("Tool"));
int type = (number_extruders > 1) ? tool_idx /* color by a tool number */ : 0; // color by a feature type
m_choice_view_type->SetSelection(type);
#if ENABLE_GCODE_VIEWER
if (0 <= type && type < static_cast<int>(GCodeViewer::EViewType::Count))
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
#else
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
#endif // ENABLE_GCODE_VIEWER
// If the->SetSelection changed the following line, revert it to "decide yourself".
m_preferred_color_mode = "tool_or_feature";
}
#if ENABLE_GCODE_VIEWER
GCodeViewer::EViewType gcode_view_type = m_canvas->get_gcode_view_preview_type();
bool gcode_preview_data_valid = !m_gcode_result->moves.empty();
#else
bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty();
#endif // ENABLE_GCODE_VIEWER
// Collect colors per extruder.
std::vector<std::string> colors;
std::vector<CustomGCode::Item> color_print_values = {};
// set color print values, if it si selected "ColorPrint" view type
#if ENABLE_GCODE_VIEWER
if (gcode_view_type == GCodeViewer::EViewType::ColorPrint) {
colors = wxGetApp().plater()->get_colors_for_color_print(m_gcode_result);
#else
if (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint) {
colors = wxGetApp().plater()->get_colors_for_color_print();
colors.push_back("#808080"); // gray color for pause print or custom G-code
#endif // ENABLE_GCODE_VIEWER
if (!gcode_preview_data_valid) {
color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
#if ENABLE_GCODE_VIEWER
colors.push_back("#808080"); // gray color for pause print or custom G-code
#endif // ENABLE_GCODE_VIEWER
}
}
#if ENABLE_GCODE_VIEWER
else if (gcode_preview_data_valid || gcode_view_type == GCodeViewer::EViewType::Tool) {
colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(m_gcode_result);
#else
else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) ) {
colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
#endif // ENABLE_GCODE_VIEWER
color_print_values.clear();
}
if (IsShown()) {
#if ENABLE_GCODE_VIEWER
std::vector<double> zs;
#endif // ENABLE_GCODE_VIEWER
m_canvas->set_selected_extruder(0);
if (gcode_preview_data_valid) {
// Load the real G-code preview.
#if ENABLE_GCODE_VIEWER
m_canvas->load_gcode_preview(*m_gcode_result);
m_canvas->refresh_gcode_preview(*m_gcode_result, colors);
m_left_sizer->Show(m_bottom_toolbar_panel);
m_left_sizer->Layout();
Refresh();
zs = m_canvas->get_gcode_layers_zs();
#else
m_canvas->load_gcode_preview(*m_gcode_preview_data, colors);
#endif // ENABLE_GCODE_VIEWER
m_loaded = true;
} else {
// Load the initial preview based on slices, not the final G-code.
m_canvas->load_preview(colors, color_print_values);
#if ENABLE_GCODE_VIEWER
m_left_sizer->Hide(m_bottom_toolbar_panel);
m_left_sizer->Layout();
Refresh();
zs = m_canvas->get_volumes_print_zs(true);
#endif // ENABLE_GCODE_VIEWER
}
#if !ENABLE_GCODE_VIEWER
show_hide_ui_elements(gcode_preview_data_valid ? "full" : "simple");
std::vector<double> zs = m_canvas->get_current_print_zs(true);
#endif // !ENABLE_GCODE_VIEWER
if (zs.empty()) {
// all layers filtered out
#if ENABLE_GCODE_VIEWER
hide_layers_slider();
#else
reset_sliders(true);
#endif // ENABLE_GCODE_VIEWER
m_canvas_widget->Refresh();
} else
#if ENABLE_GCODE_VIEWER
update_layers_slider(zs, keep_z_range);
#else
update_sliders(zs, keep_z_range);
#endif // ENABLE_GCODE_VIEWER
}
}
@ -1374,8 +916,7 @@ void Preview::load_print_as_sla()
std::vector<double> zs;
double initial_layer_height = print->material_config().initial_layer_height.value;
for (const SLAPrintObject* obj : print->objects())
if (obj->is_step_done(slaposSliceSupports) && !obj->get_slice_index().empty())
{
if (obj->is_step_done(slaposSliceSupports) && !obj->get_slice_index().empty()) {
auto low_coord = obj->get_slice_index().front().print_level();
for (auto& rec : obj->get_slice_index())
zs.emplace_back(initial_layer_height + (rec.print_level() - low_coord) * SCALING_FACTOR);
@ -1385,74 +926,43 @@ void Preview::load_print_as_sla()
m_canvas->reset_clipping_planes_cache();
n_layers = (unsigned int)zs.size();
if (n_layers == 0)
{
#if ENABLE_GCODE_VIEWER
if (n_layers == 0) {
hide_layers_slider();
#else
reset_sliders(true);
#endif // ENABLE_GCODE_VIEWER
m_canvas_widget->Refresh();
}
if (IsShown())
{
if (IsShown()) {
m_canvas->load_sla_preview();
#if ENABLE_GCODE_VIEWER
m_left_sizer->Hide(m_bottom_toolbar_panel);
m_left_sizer->Hide(m_bottom_toolbar_panel);
m_left_sizer->Layout();
Refresh();
#else
show_hide_ui_elements("none");
#endif // ENABLE_GCODE_VIEWER
if (n_layers > 0)
#if ENABLE_GCODE_VIEWER
update_layers_slider(zs);
#else
update_sliders(zs);
#endif // ENABLE_GCODE_VIEWER
m_loaded = true;
}
}
#if ENABLE_GCODE_VIEWER
void Preview::on_layers_slider_scroll_changed(wxCommandEvent& event)
#else
void Preview::on_sliders_scroll_changed(wxCommandEvent& event)
#endif // ENABLE_GCODE_VIEWER
{
if (IsShown()) {
PrinterTechnology tech = m_process->current_printer_technology();
if (tech == ptFFF) {
#if ENABLE_GCODE_VIEWER
m_canvas->set_volumes_z_range({ m_layers_slider->GetLowerValueD(), m_layers_slider->GetHigherValueD() });
m_canvas->set_toolpaths_z_range({ static_cast<unsigned int>(m_layers_slider->GetLowerValue()), static_cast<unsigned int>(m_layers_slider->GetHigherValue()) });
m_canvas->set_as_dirty();
#else
m_canvas->set_toolpaths_range(m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6);
m_canvas->render();
m_canvas->set_use_clipping_planes(false);
#endif // ENABLE_GCODE_VIEWER
}
else if (tech == ptSLA) {
#if ENABLE_GCODE_VIEWER
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValueD()));
m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValueD()));
m_canvas->set_use_clipping_planes(m_layers_slider->GetHigherValue() != 0);
#else
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_slider->GetLowerValueD()));
m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_slider->GetHigherValueD()));
m_canvas->set_use_clipping_planes(m_slider->GetHigherValue() != 0);
#endif // ENABLE_GCODE_VIEWER
m_canvas->render();
}
}
}
#if ENABLE_GCODE_VIEWER
void Preview::on_moves_slider_scroll_changed(wxCommandEvent& event)
{
m_canvas->update_gcode_sequential_view_current(static_cast<unsigned int>(m_moves_slider->GetLowerValueD() - 1.0), static_cast<unsigned int>(m_moves_slider->GetHigherValueD() - 1.0));
@ -1464,6 +974,9 @@ wxString Preview::get_option_type_string(OptionType type) const
switch (type)
{
case OptionType::Travel: { return _L("Travel"); }
#if ENABLE_SHOW_WIPE_MOVES
case OptionType::Wipe: { return _L("Wipe"); }
#endif // ENABLE_SHOW_WIPE_MOVES
case OptionType::Retractions: { return _L("Retractions"); }
case OptionType::Unretractions: { return _L("Deretractions"); }
case OptionType::ToolChanges: { return _L("Tool changes"); }
@ -1476,7 +989,6 @@ wxString Preview::get_option_type_string(OptionType type) const
default: { return ""; }
}
}
#endif // ENABLE_GCODE_VIEWER
} // namespace GUI
} // namespace Slic3r

View file

@ -7,9 +7,7 @@
#include "libslic3r/CustomGCode.hpp"
#include <string>
#if ENABLE_GCODE_VIEWER
#include "libslic3r/GCode/GCodeProcessor.hpp"
#endif // ENABLE_GCODE_VIEWER
class wxNotebook;
class wxGLCanvas;
@ -25,9 +23,6 @@ namespace Slic3r {
class DynamicPrintConfig;
class Print;
class BackgroundSlicingProcess;
#if !ENABLE_GCODE_VIEWER
class GCodePreviewData;
#endif // !ENABLE_GCODE_VIEWER
class Model;
namespace DoubleSlider {
@ -83,35 +78,19 @@ class Preview : public wxPanel
{
wxGLCanvas* m_canvas_widget;
GLCanvas3D* m_canvas;
#if ENABLE_GCODE_VIEWER
wxBoxSizer* m_left_sizer;
wxBoxSizer* m_layers_slider_sizer;
wxPanel* m_bottom_toolbar_panel;
#else
wxBoxSizer* m_double_slider_sizer;
#endif // ENABLE_GCODE_VIEWER
wxStaticText* m_label_view_type;
wxChoice* m_choice_view_type;
wxStaticText* m_label_show;
wxComboCtrl* m_combochecklist_features;
#if ENABLE_GCODE_VIEWER
size_t m_combochecklist_features_pos;
wxComboCtrl* m_combochecklist_options;
#else
wxCheckBox* m_checkbox_travel;
wxCheckBox* m_checkbox_retractions;
wxCheckBox* m_checkbox_unretractions;
wxCheckBox* m_checkbox_shells;
wxCheckBox* m_checkbox_legend;
#endif // ENABLE_GCODE_VIEWER
DynamicPrintConfig* m_config;
BackgroundSlicingProcess* m_process;
#if ENABLE_GCODE_VIEWER
GCodeProcessor::Result* m_gcode_result;
#else
GCodePreviewData* m_gcode_preview_data;
#endif // ENABLE_GCODE_VIEWER
#ifdef __linux__
// We are getting mysterious crashes on Linux in gtk due to OpenGL context activation GH #1874 #1955.
@ -126,22 +105,17 @@ class Preview : public wxPanel
std::string m_preferred_color_mode;
bool m_loaded;
#if !ENABLE_GCODE_VIEWER
bool m_enabled;
#endif // !ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
DoubleSlider::Control* m_layers_slider{ nullptr };
DoubleSlider::Control* m_moves_slider{ nullptr };
#else
DoubleSlider::Control* m_slider {nullptr};
#endif // ENABLE_GCODE_VIEWER
public:
#if ENABLE_GCODE_VIEWER
enum class OptionType : unsigned int
{
Travel,
#if ENABLE_SHOW_WIPE_MOVES
Wipe,
#endif // ENABLE_SHOW_WIPE_MOVES
Retractions,
Unretractions,
ToolChanges,
@ -153,12 +127,8 @@ public:
Legend
};
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
#else
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = []() {});
#endif // ENABLE_GCODE_VIEWER
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
virtual ~Preview();
wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; }
@ -167,9 +137,6 @@ Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
void set_as_dirty();
void set_number_extruders(unsigned int number_extruders);
#if !ENABLE_GCODE_VIEWER
void set_enabled(bool enabled);
#endif // !ENABLE_GCODE_VIEWER
void bed_shape_changed();
void select_view(const std::string& direction);
void set_drop_target(wxDropTarget* target);
@ -180,24 +147,17 @@ Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
void msw_rescale();
void jump_layers_slider(wxKeyEvent& evt);
#if ENABLE_GCODE_VIEWER
void move_layers_slider(wxKeyEvent& evt);
void edit_layers_slider(wxKeyEvent& evt);
#else
void move_double_slider(wxKeyEvent& evt);
void edit_double_slider(wxKeyEvent& evt);
#endif // ENABLE_GCODE_VIEWER
void update_view_type(bool keep_volumes);
bool is_loaded() const { return m_loaded; }
#if ENABLE_GCODE_VIEWER
void update_bottom_toolbar();
void update_moves_slider();
void enable_moves_slider(bool enable);
void hide_layers_slider();
#endif // ENABLE_GCODE_VIEWER
private:
bool init(wxWindow* parent, Model* model);
@ -205,27 +165,11 @@ private:
void bind_event_handlers();
void unbind_event_handlers();
#if !ENABLE_GCODE_VIEWER
void show_hide_ui_elements(const std::string& what);
void reset_sliders(bool reset_all);
void update_sliders(const std::vector<double>& layers_z, bool keep_z_range = false);
#endif // !ENABLE_GCODE_VIEWER
void on_size(wxSizeEvent& evt);
void on_choice_view_type(wxCommandEvent& evt);
void on_combochecklist_features(wxCommandEvent& evt);
#if ENABLE_GCODE_VIEWER
void on_combochecklist_options(wxCommandEvent& evt);
#else
void on_checkbox_travel(wxCommandEvent& evt);
void on_checkbox_retractions(wxCommandEvent& evt);
void on_checkbox_unretractions(wxCommandEvent& evt);
void on_checkbox_shells(wxCommandEvent& evt);
void on_checkbox_legend(wxCommandEvent& evt);
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
// Create/Update/Reset double slider on 3dPreview
wxBoxSizer* create_layers_slider_sizer();
void check_layers_slider_values(std::vector<CustomGCode::Item>& ticks_from_model,
@ -235,28 +179,13 @@ private:
void update_layers_slider_mode();
// update vertical DoubleSlider after keyDown in canvas
void update_layers_slider_from_canvas(wxKeyEvent& event);
#else
// Create/Update/Reset double slider on 3dPreview
void create_double_slider();
void check_slider_values(std::vector<CustomGCode::Item>& ticks_from_model,
const std::vector<double>& layers_z);
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);
#endif // ENABLE_GCODE_VIEWER
void load_print_as_fff(bool keep_z_range = false);
void load_print_as_sla();
#if ENABLE_GCODE_VIEWER
void on_layers_slider_scroll_changed(wxCommandEvent& event);
void on_moves_slider_scroll_changed(wxCommandEvent& event);
wxString get_option_type_string(OptionType type) const;
#else
void on_sliders_scroll_changed(wxCommandEvent& event);
#endif // ENABLE_GCODE_VIEWER
};
} // namespace GUI

View file

@ -385,7 +385,6 @@ public:
std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);
#if ENABLE_GCODE_VIEWER
inline int hex_digit_to_int(const char c)
{
return
@ -393,7 +392,6 @@ inline int hex_digit_to_int(const char c)
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
}
#endif // ENABLE_GCODE_VIEWER
class TaskTimer
{

View file

@ -45,7 +45,7 @@ bool GLGizmoFdmSupports::on_init()
m_desc["cursor_type"] = _L("Brush shape") + ": ";
m_desc["enforce_caption"] = _L("Left mouse button") + ": ";
m_desc["enforce"] = _L("Enforce supports");
m_desc["block_caption"] = _L("Right mouse button") + " ";
m_desc["block_caption"] = _L("Right mouse button") + ": ";
m_desc["block"] = _L("Block supports");
m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": ";
m_desc["remove"] = _L("Remove selection");

View file

@ -28,7 +28,7 @@ bool GLGizmoSeam::on_init()
m_desc["cursor_type"] = _L("Brush shape") + ": ";
m_desc["enforce_caption"] = _L("Left mouse button") + ": ";
m_desc["enforce"] = _L("Enforce seam");
m_desc["block_caption"] = _L("Right mouse button") + " ";
m_desc["block_caption"] = _L("Right mouse button") + ": ";
m_desc["block"] = _L("Block seam");
m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": ";
m_desc["remove"] = _L("Remove selection");

View file

@ -23,7 +23,7 @@
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
#include "3DScene.hpp"+
#include "3DScene.hpp"
#include "GUI.hpp"
#include "I18N.hpp"
#include "Search.hpp"

View file

@ -79,7 +79,7 @@ namespace instance_check_internal
return true;
std::wstring classNameString(className);
std::wstring wndTextString(wndText);
if (wndTextString.find(L"PrusaSlicer") == 0 && classNameString == L"wxWindowNR") {
if (wndTextString.find(L"PrusaSlicer") != std::wstring::npos && classNameString == L"wxWindowNR") {
//check if other instances has same instance hash
//if not it is not same version(binary) as this version
HANDLE handle = GetProp(hwnd, L"Instance_Hash_Minor");
@ -251,11 +251,23 @@ namespace instance_check_internal
bool instance_check(int argc, char** argv, bool app_config_single_instance)
{
#ifndef _WIN32
boost::system::error_code ec;
#endif
std::size_t hashed_path =
#ifdef _WIN32
std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
#else
std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0])).string());
std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]), ec).string());
if (ec.value() > 0) { // canonical was not able to find the executable (can happen with appimage on some systems. Does it fail on Fuse file systems?)
ec.clear();
// Compose path with boost canonical of folder and filename
hashed_path = std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]).parent_path(), ec).string() + "/" + boost::filesystem::system_complete(argv[0]).filename().string());
if (ec.value() > 0) {
// Still not valid, process without canonical
hashed_path = std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
}
}
#endif // win32
std::string lock_name = std::to_string(hashed_path);

View file

@ -41,12 +41,13 @@ public:
ret.poly.contour = std::move(ap);
ret.translation = scaled(m_pos);
ret.rotation = m_rotation;
ret.priority++;
++ret.priority;
return ret;
}
};
static WipeTower get_wipe_tower(Plater &plater)
static WipeTower get_wipe_tower(const Plater &plater)
{
return WipeTower{plater.canvas3D()->get_wipe_tower_info()};
}
@ -68,29 +69,24 @@ void ArrangeJob::clear_input()
m_unprintable.reserve(cunprint /* for optional wti */);
}
double ArrangeJob::bed_stride() const {
double bedwidth = m_plater->bed_shape_bb().size().x();
return scaled<double>((1. + LOGICAL_BED_GAP) * bedwidth);
}
void ArrangeJob::prepare_all() {
clear_input();
for (ModelObject *obj: m_plater->model().objects)
for (ModelInstance *mi : obj->instances) {
ArrangePolygons & cont = mi->printable ? m_selected : m_unprintable;
cont.emplace_back(get_arrange_poly(mi));
cont.emplace_back(get_arrange_poly(PtrWrapper{mi}, m_plater));
}
if (auto wti = get_wipe_tower(*m_plater))
m_selected.emplace_back(wti.get_arrange_polygon());
if (auto wti = get_wipe_tower_arrangepoly(*m_plater))
m_selected.emplace_back(std::move(*wti));
}
void ArrangeJob::prepare_selected() {
clear_input();
Model &model = m_plater->model();
double stride = bed_stride();
double stride = bed_stride(m_plater);
std::vector<const Selection::InstanceIdxsList *>
obj_sel(model.objects.size(), nullptr);
@ -111,8 +107,9 @@ void ArrangeJob::prepare_selected() {
inst_sel[size_t(inst_id)] = true;
for (size_t i = 0; i < inst_sel.size(); ++i) {
ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]);
ArrangePolygon &&ap =
get_arrange_poly(PtrWrapper{mo->instances[i]}, m_plater);
ArrangePolygons &cont = mo->instances[i]->printable ?
(inst_sel[i] ? m_selected :
m_unselected) :
@ -123,11 +120,11 @@ void ArrangeJob::prepare_selected() {
}
if (auto wti = get_wipe_tower(*m_plater)) {
ArrangePolygon &&ap = get_arrange_poly(&wti);
m_plater->get_selection().is_wipe_tower() ?
m_selected.emplace_back(std::move(ap)) :
m_unselected.emplace_back(std::move(ap));
ArrangePolygon &&ap = get_arrange_poly(wti, m_plater);
auto &cont = m_plater->get_selection().is_wipe_tower() ? m_selected :
m_unselected;
cont.emplace_back(std::move(ap));
}
// If the selection was empty arrange everything
@ -147,11 +144,13 @@ void ArrangeJob::prepare()
void ArrangeJob::process()
{
static const auto arrangestr = _(L("Arranging"));
double dist = min_object_distance(*m_plater->config());
GLCanvas3D::ArrangeSettings settings =
m_plater->canvas3D()->get_arrange_settings();
arrangement::ArrangeParams params;
params.min_obj_distance = scaled(dist);
params.min_obj_distance = scaled(settings.distance);
params.allow_rotations = settings.enable_rotation;
auto count = unsigned(m_selected.size() + m_unprintable.size());
Points bedpts = get_bed_shape(*m_plater->config());
@ -211,14 +210,18 @@ void ArrangeJob::finalize() {
Job::finalize();
}
arrangement::ArrangePolygon get_wipe_tower_arrangepoly(Plater &plater)
std::optional<arrangement::ArrangePolygon>
get_wipe_tower_arrangepoly(const Plater &plater)
{
return WipeTower{plater.canvas3D()->get_wipe_tower_info()}.get_arrange_polygon();
if (auto wti = get_wipe_tower(plater))
return get_arrange_poly(wti, &plater);
return {};
}
void apply_wipe_tower_arrangepoly(Plater &plater, const arrangement::ArrangePolygon &ap)
{
WipeTower{plater.canvas3D()->get_wipe_tower_info()}.apply_arrange_result(ap.translation.cast<double>(), ap.rotation);
double bed_stride(const Plater *plater) {
double bedwidth = plater->bed_shape_bb().size().x();
return scaled<double>((1. + LOGICAL_BED_GAP) * bedwidth);
}
}} // namespace Slic3r::GUI

View file

@ -14,35 +14,12 @@ class ArrangeJob : public Job
using ArrangePolygon = arrangement::ArrangePolygon;
using ArrangePolygons = arrangement::ArrangePolygons;
// The gap between logical beds in the x axis expressed in ratio of
// the current bed width.
static const constexpr double LOGICAL_BED_GAP = 1. / 5.;
ArrangePolygons m_selected, m_unselected, m_unprintable;
// clear m_selected and m_unselected, reserve space for next usage
void clear_input();
// Stride between logical beds
double bed_stride() const;
// Set up arrange polygon for a ModelInstance and Wipe tower
template<class T> ArrangePolygon get_arrange_poly(T *obj) const
{
ArrangePolygon ap = obj->get_arrange_polygon();
ap.priority = 0;
ap.bed_idx = ap.translation.x() / bed_stride();
ap.setter = [obj, this](const ArrangePolygon &p) {
if (p.is_arranged()) {
Vec2d t = p.translation.cast<double>();
t.x() += p.bed_idx * bed_stride();
obj->apply_arrange_result(t, p.rotation);
}
};
return ap;
}
// Prepare all objects on the bed regardless of the selection
void prepare_all();
@ -69,8 +46,51 @@ public:
void finalize() override;
};
arrangement::ArrangePolygon get_wipe_tower_arrangepoly(Plater &);
void apply_wipe_tower_arrangepoly(Plater &plater, const arrangement::ArrangePolygon &ap);
std::optional<arrangement::ArrangePolygon> get_wipe_tower_arrangepoly(const Plater &);
// The gap between logical beds in the x axis expressed in ratio of
// the current bed width.
static const constexpr double LOGICAL_BED_GAP = 1. / 5.;
// Stride between logical beds
double bed_stride(const Plater *plater);
template<class T> struct PtrWrapper
{
T *ptr;
explicit PtrWrapper(T *p) : ptr{p} {}
arrangement::ArrangePolygon get_arrange_polygon() const
{
return ptr->get_arrange_polygon();
}
void apply_arrange_result(const Vec2d &t, double rot)
{
ptr->apply_arrange_result(t, rot);
}
};
// Set up arrange polygon for a ModelInstance and Wipe tower
template<class T>
arrangement::ArrangePolygon get_arrange_poly(T obj, const Plater *plater)
{
using ArrangePolygon = arrangement::ArrangePolygon;
ArrangePolygon ap = obj.get_arrange_polygon();
ap.bed_idx = ap.translation.x() / bed_stride(plater);
ap.setter = [obj, plater](const ArrangePolygon &p) {
if (p.is_arranged()) {
Vec2d t = p.translation.cast<double>();
t.x() += p.bed_idx * bed_stride(plater);
T{obj}.apply_arrange_result(t, p.rotation);
}
};
return ap;
}
}} // namespace Slic3r::GUI

View file

@ -0,0 +1,146 @@
#include "FillBedJob.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include <numeric>
namespace Slic3r {
namespace GUI {
void FillBedJob::prepare()
{
m_selected.clear();
m_unselected.clear();
m_bedpts.clear();
m_object_idx = m_plater->get_selected_object_idx();
if (m_object_idx == -1)
return;
ModelObject *model_object = m_plater->model().objects[m_object_idx];
if (model_object->instances.empty()) return;
m_selected.reserve(model_object->instances.size());
for (ModelInstance *inst : model_object->instances)
if (inst->printable) {
ArrangePolygon ap = get_arrange_poly(PtrWrapper{inst}, m_plater);
++ap.priority; // need to be included in the result
m_selected.emplace_back(ap);
}
if (m_selected.empty()) return;
m_bedpts = get_bed_shape(*m_plater->config());
auto &objects = m_plater->model().objects;
for (size_t idx = 0; idx < objects.size(); ++idx)
if (int(idx) != m_object_idx)
for (ModelInstance *mi : objects[idx]->instances) {
m_unselected.emplace_back(get_arrange_poly(PtrWrapper{mi}, m_plater));
m_unselected.back().bed_idx = 0;
}
if (auto wt = get_wipe_tower_arrangepoly(*m_plater))
m_unselected.emplace_back(std::move(*wt));
double sc = scaled<double>(1.) * scaled(1.);
ExPolygon poly = m_selected.front().poly;
double poly_area = poly.area() / sc;
double unsel_area = std::accumulate(m_unselected.begin(),
m_unselected.end(), 0.,
[](double s, const auto &ap) {
return s + ap.poly.area();
}) / sc;
double fixed_area = unsel_area + m_selected.size() * poly_area;
// This is the maximum range, the real number will always be close but less.
double bed_area = Polygon{m_bedpts}.area() / sc;
m_status_range = (bed_area - fixed_area) / poly_area;
ModelInstance *mi = model_object->instances[0];
for (int i = 0; i < m_status_range; ++i) {
ArrangePolygon ap;
ap.poly = m_selected.front().poly;
ap.bed_idx = arrangement::UNARRANGED;
ap.setter = [this, mi](const ArrangePolygon &p) {
ModelObject *mo = m_plater->model().objects[m_object_idx];
ModelInstance *inst = mo->add_instance(*mi);
inst->apply_arrange_result(p.translation.cast<double>(), p.rotation);
};
m_selected.emplace_back(ap);
}
}
void FillBedJob::process()
{
if (m_object_idx == -1 || m_selected.empty()) return;
GLCanvas3D::ArrangeSettings settings =
m_plater->canvas3D()->get_arrange_settings();
arrangement::ArrangeParams params;
params.min_obj_distance = scaled(settings.distance);
params.allow_rotations = settings.enable_rotation;
bool do_stop = false;
params.stopcondition = [this, &do_stop]() {
return was_canceled() || do_stop;
};
params.progressind = [this](unsigned st) {
if (st > 0)
update_status(int(m_status_range - st), _(L("Filling bed")));
};
params.on_packed = [&do_stop] (const ArrangePolygon &ap) {
do_stop = ap.bed_idx > 0 && ap.priority == 0;
};
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);
// finalize just here.
update_status(m_status_range, was_canceled() ?
_(L("Bed filling canceled.")) :
_(L("Bed filling done.")));
}
void FillBedJob::finalize()
{
if (m_object_idx == -1) return;
ModelObject *model_object = m_plater->model().objects[m_object_idx];
if (model_object->instances.empty()) return;
size_t inst_cnt = model_object->instances.size();
for (ArrangePolygon &ap : m_selected) {
if (ap.bed_idx != arrangement::UNARRANGED && (ap.priority != 0 || ap.bed_idx == 0))
ap.apply();
}
model_object->ensure_on_bed();
m_plater->update();
int added_cnt = std::accumulate(m_selected.begin(), m_selected.end(), 0,
[](int s, auto &ap) {
return s + int(ap.priority == 0 && ap.bed_idx == 0);
});
// FIXME: somebody explain why this is needed for increase_object_instances
if (inst_cnt == 1) added_cnt++;
if (added_cnt > 0)
m_plater->sidebar()
.obj_list()->increase_object_instances(m_object_idx, size_t(added_cnt));
}
}} // namespace Slic3r::GUI

View file

@ -0,0 +1,46 @@
#ifndef FILLBEDJOB_HPP
#define FILLBEDJOB_HPP
#include "ArrangeJob.hpp"
namespace Slic3r { namespace GUI {
class Plater;
class FillBedJob : public Job
{
Plater *m_plater;
int m_object_idx = -1;
using ArrangePolygon = arrangement::ArrangePolygon;
using ArrangePolygons = arrangement::ArrangePolygons;
ArrangePolygons m_selected;
ArrangePolygons m_unselected;
Points m_bedpts;
int m_status_range = 0;
protected:
void prepare() override;
public:
FillBedJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
: Job{std::move(pri)}, m_plater{plater}
{}
int status_range() const override
{
return m_status_range;
}
void process() override;
void finalize() override;
};
}} // namespace Slic3r::GUI
#endif // FILLBEDJOB_HPP

View file

@ -36,7 +36,7 @@ public:
"SL1 archive files (*.sl1, *.zip)|*.sl1;*.SL1;*.zip;*.ZIP",
wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE | wxFD_OPEN | wxFD_FILE_MUST_EXIST);
szfilepck->Add(new wxStaticText(this, wxID_ANY, _(L("Import file: "))), 0, wxALIGN_CENTER);
szfilepck->Add(new wxStaticText(this, wxID_ANY, _L("Import file") + ": "), 0, wxALIGN_CENTER);
szfilepck->Add(m_filepicker, 1);
szvert->Add(szfilepck, 0, wxALL | wxEXPAND, 5);
@ -53,7 +53,7 @@ public:
inp_choices.size(), inp_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
szchoices->Add(m_import_dropdown);
szchoices->Add(new wxStaticText(this, wxID_ANY, _(L("Quality: "))), 0, wxALIGN_CENTER | wxALL, 5);
szchoices->Add(new wxStaticText(this, wxID_ANY, _L("Quality") + ": "), 0, wxALIGN_CENTER | wxALL, 5);
static const std::vector<wxString> qual_choices = {
_(L("Accurate")),

View file

@ -7,9 +7,7 @@
#include <wx/display.h>
#include "GUI_App.hpp"
#include "wxExtensions.hpp"
#if ENABLE_GCODE_VIEWER
#include "MainFrame.hpp"
#endif // ENABLE_GCODE_VIEWER
#define NOTEBOOK_TOP 1
#define NOTEBOOK_LEFT 2
@ -33,11 +31,7 @@ namespace Slic3r {
namespace GUI {
KBShortcutsDialog::KBShortcutsDialog()
#if ENABLE_GCODE_VIEWER
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
#else
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
#endif // ENABLE_GCODE_VIEWER
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, wxString(wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
@ -97,9 +91,7 @@ void KBShortcutsDialog::fill_shortcuts()
const std::string& ctrl = GUI::shortkey_ctrl_prefix();
const std::string& alt = GUI::shortkey_alt_prefix();
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_editor()) {
#endif // ENABLE_GCODE_VIEWER
Shortcuts commands_shortcuts = {
// File
{ ctrl + "N", L("New project, clear plater") },
@ -179,7 +171,11 @@ void KBShortcutsDialog::fill_shortcuts()
{ "Tab", L("Switch between Editor/Preview") },
{ "Shift+Tab", L("Collapse/Expand the sidebar") },
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog, if enabled") },
#else
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
#endif // _WIN32
#else
#if defined(__linux__) || defined(__APPLE__)
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
@ -204,9 +200,7 @@ void KBShortcutsDialog::fill_shortcuts()
};
m_full_shortcuts.push_back(std::make_pair(_L("Gizmos"), gizmos_shortcuts));
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
Shortcuts preview_shortcuts = {
{ L("Arrow Up"), L("Upper Layer") },
@ -231,7 +225,6 @@ void KBShortcutsDialog::fill_shortcuts()
m_full_shortcuts.push_back(std::make_pair(_L("Layers Slider"), layers_slider_shortcuts));
#if ENABLE_GCODE_VIEWER
Shortcuts sequential_slider_shortcuts = {
{ L("Arrow Left"), L("Move current slider thumb Left") },
{ L("Arrow Right"), L("Move current slider thumb Right") },
@ -240,7 +233,6 @@ void KBShortcutsDialog::fill_shortcuts()
};
m_full_shortcuts.push_back(std::make_pair(_L("Sequential Slider"), sequential_slider_shortcuts));
#endif // ENABLE_GCODE_VIEWER
}
wxPanel* KBShortcutsDialog::create_header(wxWindow* parent, const wxFont& bold_font)
@ -258,11 +250,7 @@ wxPanel* KBShortcutsDialog::create_header(wxWindow* parent, const wxFont& bold_f
sizer->AddStretchSpacer();
// logo
#if ENABLE_GCODE_VIEWER
m_logo_bmp = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_32px.png" : "PrusaSlicer-gcodeviewer_32px.png", 32);
#else
m_logo_bmp = ScalableBitmap(this, "PrusaSlicer_32px.png", 32);
#endif // ENABLE_GCODE_VIEWER
m_header_bitmap = new wxStaticBitmap(panel, wxID_ANY, m_logo_bmp.bmp());
sizer->Add(m_header_bitmap, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);

View file

@ -31,6 +31,7 @@
#include "GLCanvas3D.hpp"
#include "Plater.hpp"
#include "../Utils/Process.hpp"
#include "format.hpp"
#include <fstream>
#include "GUI_App.hpp"
@ -116,7 +117,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
// Load the icon either from the exe, or from the ico file.
#if _WIN32
{
#if ENABLE_GCODE_VIEWER
wxString src_path;
wxFileName::SplitPath(wxStandardPaths::Get().GetExecutablePath(), &src_path, nullptr, nullptr, wxPATH_NATIVE);
switch (wxGetApp().get_app_mode()) {
@ -127,22 +127,14 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
wxIconLocation icon_location;
icon_location.SetFileName(src_path);
SetIcon(icon_location);
#else
TCHAR szExeFileName[MAX_PATH];
GetModuleFileName(nullptr, szExeFileName, MAX_PATH);
SetIcon(wxIcon(szExeFileName, wxBITMAP_TYPE_ICO));
#endif // ENABLE_GCODE_VIEWER
}
#else
#if ENABLE_GCODE_VIEWER
switch (wxGetApp().get_app_mode())
{
default:
case GUI_App::EAppMode::Editor:
{
#endif // ENABLE_GCODE_VIEWER
SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
#if ENABLE_GCODE_VIEWER
break;
}
case GUI_App::EAppMode::GCodeViewer:
@ -151,23 +143,19 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
break;
}
}
#endif // ENABLE_GCODE_VIEWER
#endif // _WIN32
// initialize status bar
m_statusbar = std::make_shared<ProgressStatusBar>(this);
m_statusbar->set_font(GUI::wxGetApp().normal_font());
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_editor())
#endif // ENABLE_GCODE_VIEWER
m_statusbar->embed(this);
m_statusbar->set_status_text(_L("Version") + " " +
SLIC3R_VERSION +
_L(" - Remember to check for updates at https://github.com/prusa3d/PrusaSlicer/releases"));
SLIC3R_VERSION + " - " +
_L("Remember to check for updates at https://github.com/prusa3d/PrusaSlicer/releases"));
// initialize tabpanel and menubar
init_tabpanel();
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_gcode_viewer())
init_menubar_as_gcodeviewer();
else
@ -185,9 +173,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
wxAcceleratorTable accel(6, entries);
SetAcceleratorTable(accel);
#endif // _WIN32
#else
init_menubar();
#endif // ENABLE_GCODE_VIEWER
// set default tooltip timer in msec
// SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values
@ -255,9 +240,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
update_ui_from_settings(); // FIXME (?)
if (m_plater != nullptr) {
#if ENABLE_GCODE_VIEWER
m_plater->get_collapse_toolbar().set_enabled(wxGetApp().app_config->get("show_collapse_button") == "1");
#endif // ENABLE_GCODE_VIEWER
m_plater->show_action_buttons(true);
}
}
@ -300,16 +283,10 @@ void MainFrame::update_layout()
Layout();
};
#if ENABLE_GCODE_VIEWER
ESettingsLayout layout = wxGetApp().is_gcode_viewer() ? ESettingsLayout::GCodeViewer :
(wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? ESettingsLayout::Old :
wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ESettingsLayout::New :
wxGetApp().app_config->get("dlg_settings_layout_mode") == "1" ? ESettingsLayout::Dlg : ESettingsLayout::Old);
#else
ESettingsLayout layout = wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? ESettingsLayout::Old :
wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ESettingsLayout::New :
wxGetApp().app_config->get("dlg_settings_layout_mode") == "1" ? ESettingsLayout::Dlg : ESettingsLayout::Old;
#endif // ENABLE_GCODE_VIEWER
if (m_layout == layout)
return;
@ -373,7 +350,6 @@ void MainFrame::update_layout()
m_plater->Show();
break;
}
#if ENABLE_GCODE_VIEWER
case ESettingsLayout::GCodeViewer:
{
m_main_sizer->Add(m_plater, 1, wxEXPAND);
@ -383,7 +359,6 @@ void MainFrame::update_layout()
m_plater->Show();
break;
}
#endif // ENABLE_GCODE_VIEWER
}
#ifdef __WXMSW__
@ -452,7 +427,6 @@ void MainFrame::shutdown()
}
#endif // _WIN32
#if ENABLE_GCODE_VIEWER
if (m_plater != nullptr) {
m_plater->stop_jobs();
@ -465,19 +439,6 @@ void MainFrame::shutdown()
// see: https://github.com/prusa3d/PrusaSlicer/issues/3964
m_plater->reset_canvas_volumes();
}
#else
if (m_plater)
m_plater->stop_jobs();
// Unbinding of wxWidgets event handling in canvases needs to be done here because on MAC,
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
// causing a crash
if (m_plater) m_plater->unbind_canvas_event_handlers();
// Cleanup of canvases' volumes needs to be done here or a crash may happen on some Linux Debian flavours
// see: https://github.com/prusa3d/PrusaSlicer/issues/3964
if (m_plater) m_plater->reset_canvas_volumes();
#endif // ENABLE_GCODE_VIEWER
// Weird things happen as the Paint messages are floating around the windows being destructed.
// Avoid the Paint messages by hiding the main window.
@ -525,11 +486,7 @@ void MainFrame::update_title()
title += (project + " - ");
}
#if ENABLE_GCODE_VIEWER
std::string build_id = wxGetApp().is_editor() ? SLIC3R_BUILD_ID : GCODEVIEWER_BUILD_ID;
#else
std::string build_id = SLIC3R_BUILD_ID;
#endif // ENABLE_GCODE_VIEWER
size_t idx_plus = build_id.find('+');
if (idx_plus != build_id.npos) {
// Parse what is behind the '+'. If there is a number, then it is a build number after the label, and full build ID is shown.
@ -544,13 +501,10 @@ void MainFrame::update_title()
#endif
}
}
#if ENABLE_GCODE_VIEWER
title += wxString(build_id);
if (wxGetApp().is_editor())
title += (" " + _L("based on Slic3r"));
#else
title += (wxString(build_id) + " " + _L("based on Slic3r"));
#endif // ENABLE_GCODE_VIEWER
SetTitle(title);
}
@ -599,9 +553,7 @@ void MainFrame::init_tabpanel()
// or when the preset's "modified" status changes.
Bind(EVT_TAB_PRESETS_CHANGED, &MainFrame::on_presets_changed, this); // #ys_FIXME_to_delete
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_editor())
#endif // ENABLE_GCODE_VIEWER
create_preset_tabs();
if (m_plater) {
@ -810,9 +762,7 @@ bool MainFrame::can_change_view() const
int page_id = m_tabpanel->GetSelection();
return page_id != wxNOT_FOUND && dynamic_cast<const Slic3r::GUI::Plater*>(m_tabpanel->GetPage((size_t)page_id)) != nullptr;
}
#if ENABLE_GCODE_VIEWER
case ESettingsLayout::GCodeViewer: { return true; }
#endif // ENABLE_GCODE_VIEWER
}
}
@ -904,7 +854,6 @@ void MainFrame::on_sys_color_changed()
msw_rescale_menu(menu_bar->GetMenu(id));
}
#if ENABLE_GCODE_VIEWER
#ifdef _MSC_VER
// \xA0 is a non-breaking space. It is entered here to spoil the automatic accelerators,
// as the simple numeric accelerators spoil all numeric data entry.
@ -939,17 +888,13 @@ static wxMenu* generate_help_menu()
[](wxCommandEvent&) { Slic3r::GUI::desktop_open_datadir_folder(); });
append_menu_item(helpMenu, wxID_ANY, _L("Report an I&ssue"), wxString::Format(_L("Report an issue on %s"), SLIC3R_APP_NAME),
[](wxCommandEvent&) { wxLaunchDefaultBrowser("https://github.com/prusa3d/slic3r/issues/new"); });
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_editor())
#endif // ENABLE_GCODE_VIEWER
append_menu_item(helpMenu, wxID_ANY, wxString::Format(_L("&About %s"), SLIC3R_APP_NAME), _L("Show about dialog"),
[](wxCommandEvent&) { Slic3r::GUI::about(); });
#if ENABLE_GCODE_VIEWER
else
append_menu_item(helpMenu, wxID_ANY, wxString::Format(_L("&About %s"), GCODEVIEWER_APP_NAME), _L("Show about dialog"),
[](wxCommandEvent&) { Slic3r::GUI::about(); });
#endif // ENABLE_GCODE_VIEWER
helpMenu->AppendSeparator();
helpMenu->AppendSeparator();
append_menu_item(helpMenu, wxID_ANY, _L("Keyboard Shortcuts") + sep + "&?", _L("Show the list of the keyboard shortcuts"),
[](wxCommandEvent&) { wxGetApp().keyboard_shortcuts(); });
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG
@ -984,9 +929,6 @@ static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame,
}
void MainFrame::init_menubar_as_editor()
#else
void MainFrame::init_menubar()
#endif // ENABLE_GCODE_VIEWER
{
#ifdef __APPLE__
wxMenuBar::SetAutoWindowMenu(false);
@ -1157,18 +1099,6 @@ void MainFrame::init_menubar()
[this](wxCommandEvent&) { Close(false); }, "exit");
}
#if !ENABLE_GCODE_VIEWER
#ifdef _MSC_VER
// \xA0 is a non-breaking space. It is entered here to spoil the automatic accelerators,
// as the simple numeric accelerators spoil all numeric data entry.
wxString sep = "\t\xA0";
wxString sep_space = "\xA0";
#else
wxString sep = " - ";
wxString sep_space = "";
#endif
#endif // !ENABLE_GCODE_VIEWER
// Edit menu
wxMenu* editMenu = nullptr;
if (m_plater != nullptr)
@ -1251,21 +1181,6 @@ void MainFrame::init_menubar()
[this](){return can_change_view(); }, this);
}
#if !ENABLE_GCODE_VIEWER
#if _WIN32
// This is needed on Windows to fake the CTRL+# of the window menu when using the numpad
wxAcceleratorEntry entries[6];
entries[0].Set(wxACCEL_CTRL, WXK_NUMPAD1, wxID_HIGHEST + 1);
entries[1].Set(wxACCEL_CTRL, WXK_NUMPAD2, wxID_HIGHEST + 2);
entries[2].Set(wxACCEL_CTRL, WXK_NUMPAD3, wxID_HIGHEST + 3);
entries[3].Set(wxACCEL_CTRL, WXK_NUMPAD4, wxID_HIGHEST + 4);
entries[4].Set(wxACCEL_CTRL, WXK_NUMPAD5, wxID_HIGHEST + 5);
entries[5].Set(wxACCEL_CTRL, WXK_NUMPAD6, wxID_HIGHEST + 6);
wxAcceleratorTable accel(6, entries);
SetAcceleratorTable(accel);
#endif // _WIN32
#endif // !ENABLE_GCODE_VIEWER
windowMenu->AppendSeparator();
append_menu_item(windowMenu, wxID_ANY, _L("Print &Host Upload Queue") + "\tCtrl+J", _L("Display the Print Host Upload Queue window"),
[this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "upload_queue", nullptr, []() {return true; }, this);
@ -1280,28 +1195,7 @@ void MainFrame::init_menubar()
wxMenu* viewMenu = nullptr;
if (m_plater) {
viewMenu = new wxMenu();
#if ENABLE_GCODE_VIEWER
add_common_view_menu_items(viewMenu, this, std::bind(&MainFrame::can_change_view, this));
#else
// The camera control accelerators are captured by GLCanvas3D::on_char().
append_menu_item(viewMenu, wxID_ANY, _L("Iso") + sep + "&0", _L("Iso View"), [this](wxCommandEvent&) { select_view("iso"); },
"", nullptr, [this](){return can_change_view(); }, this);
viewMenu->AppendSeparator();
//TRN To be shown in the main menu View->Top
append_menu_item(viewMenu, wxID_ANY, _L("Top") + sep + "&1", _L("Top View"), [this](wxCommandEvent&) { select_view("top"); },
"", nullptr, [this](){return can_change_view(); }, this);
//TRN To be shown in the main menu View->Bottom
append_menu_item(viewMenu, wxID_ANY, _L("Bottom") + sep + "&2", _L("Bottom View"), [this](wxCommandEvent&) { select_view("bottom"); },
"", nullptr, [this](){return can_change_view(); }, this);
append_menu_item(viewMenu, wxID_ANY, _L("Front") + sep + "&3", _L("Front View"), [this](wxCommandEvent&) { select_view("front"); },
"", nullptr, [this](){return can_change_view(); }, this);
append_menu_item(viewMenu, wxID_ANY, _L("Rear") + sep + "&4", _L("Rear View"), [this](wxCommandEvent&) { select_view("rear"); },
"", nullptr, [this](){return can_change_view(); }, this);
append_menu_item(viewMenu, wxID_ANY, _L("Left") + sep + "&5", _L("Left View"), [this](wxCommandEvent&) { select_view("left"); },
"", nullptr, [this](){return can_change_view(); }, this);
append_menu_item(viewMenu, wxID_ANY, _L("Right") + sep + "&6", _L("Right View"), [this](wxCommandEvent&) { select_view("right"); },
"", nullptr, [this](){return can_change_view(); }, this);
#endif // ENABLE_GCODE_VIEWER
viewMenu->AppendSeparator();
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &labels") + sep + "E", _L("Show object/instance labels in 3D scene"),
[this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this,
@ -1312,49 +1206,11 @@ void MainFrame::init_menubar()
}
// Help menu
#if ENABLE_GCODE_VIEWER
auto helpMenu = generate_help_menu();
#else
auto helpMenu = new wxMenu();
{
append_menu_item(helpMenu, wxID_ANY, _L("Prusa 3D &Drivers"), _L("Open the Prusa3D drivers download page in your browser"),
[this](wxCommandEvent&) { wxGetApp().open_web_page_localized("https://www.prusa3d.com/downloads"); });
append_menu_item(helpMenu, wxID_ANY, _L("Software &Releases"), _L("Open the software releases page in your browser"),
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases"); });
//# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", "Check for new Slic3r versions", sub{
//# wxTheApp->check_version(1);
//# });
//# $versioncheck->Enable(wxTheApp->have_version_check);
append_menu_item(helpMenu, wxID_ANY, wxString::Format(_L("%s &Website"), SLIC3R_APP_NAME),
wxString::Format(_L("Open the %s website in your browser"), SLIC3R_APP_NAME),
[this](wxCommandEvent&) { wxGetApp().open_web_page_localized("https://www.prusa3d.com/slicerweb"); });
// append_menu_item(helpMenu, wxID_ANY, wxString::Format(_L("%s &Manual"), SLIC3R_APP_NAME),
// wxString::Format(_L("Open the %s manual in your browser"), SLIC3R_APP_NAME),
// [this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://manual.slic3r.org/"); });
helpMenu->AppendSeparator();
append_menu_item(helpMenu, wxID_ANY, _L("System &Info"), _L("Show system information"),
[this](wxCommandEvent&) { wxGetApp().system_info(); });
append_menu_item(helpMenu, wxID_ANY, _L("Show &Configuration Folder"), _L("Show user configuration folder (datadir)"),
[this](wxCommandEvent&) { Slic3r::GUI::desktop_open_datadir_folder(); });
append_menu_item(helpMenu, wxID_ANY, _L("Report an I&ssue"), wxString::Format(_L("Report an issue on %s"), SLIC3R_APP_NAME),
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("https://github.com/prusa3d/slic3r/issues/new"); });
append_menu_item(helpMenu, wxID_ANY, wxString::Format(_L("&About %s"), SLIC3R_APP_NAME), _L("Show about dialog"),
[this](wxCommandEvent&) { Slic3r::GUI::about(); });
helpMenu->AppendSeparator();
append_menu_item(helpMenu, wxID_ANY, _L("Keyboard Shortcuts") + sep + "&?", _L("Show the list of the keyboard shortcuts"),
[this](wxCommandEvent&) { wxGetApp().keyboard_shortcuts(); });
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG
helpMenu->AppendSeparator();
append_menu_item(helpMenu, wxID_ANY, "DEBUG gcode thumbnails", "DEBUG ONLY - read the selected gcode file and generates png for the contained thumbnails",
[this](wxCommandEvent&) { wxGetApp().gcode_thumbnails_debug(); });
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG
}
#endif // ENABLE_GCODE_VIEWER
// menubar
// assign menubar to frame after appending items, otherwise special items
// will not be handled correctly
#if ENABLE_GCODE_VIEWER
m_menubar = new wxMenuBar();
m_menubar->Append(fileMenu, _L("&File"));
if (editMenu) m_menubar->Append(editMenu, _L("&Edit"));
@ -1364,26 +1220,11 @@ void MainFrame::init_menubar()
wxGetApp().add_config_menu(m_menubar);
m_menubar->Append(helpMenu, _L("&Help"));
SetMenuBar(m_menubar);
#else
auto menubar = new wxMenuBar();
menubar->Append(fileMenu, _L("&File"));
if (editMenu) menubar->Append(editMenu, _L("&Edit"));
menubar->Append(windowMenu, _L("&Window"));
if (viewMenu) menubar->Append(viewMenu, _L("&View"));
// Add additional menus from C++
wxGetApp().add_config_menu(menubar);
menubar->Append(helpMenu, _L("&Help"));
SetMenuBar(menubar);
#endif // ENABLE_GCODE_VIEWER
#ifdef __APPLE__
// This fixes a bug on Mac OS where the quit command doesn't emit window close events
// wx bug: https://trac.wxwidgets.org/ticket/18328
#if ENABLE_GCODE_VIEWER
wxMenu* apple_menu = m_menubar->OSXGetAppleMenu();
#else
wxMenu *apple_menu = menubar->OSXGetAppleMenu();
#endif // ENABLE_GCODE_VIEWER
if (apple_menu != nullptr) {
apple_menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) {
Close();
@ -1395,7 +1236,6 @@ void MainFrame::init_menubar()
update_menubar();
}
#if ENABLE_GCODE_VIEWER
void MainFrame::init_menubar_as_gcodeviewer()
{
wxMenu* fileMenu = new wxMenu;
@ -1428,10 +1268,8 @@ void MainFrame::init_menubar_as_gcodeviewer()
m_menubar = new wxMenuBar();
m_menubar->Append(fileMenu, _L("&File"));
if (viewMenu != nullptr) m_menubar->Append(viewMenu, _L("&View"));
#if ENABLE_GCODE_VIEWER
// Add additional menus from C++
wxGetApp().add_config_menu(m_menubar);
#endif // ENABLE_GCODE_VIEWER
m_menubar->Append(helpMenu, _L("&Help"));
SetMenuBar(m_menubar);
@ -1446,14 +1284,11 @@ void MainFrame::init_menubar_as_gcodeviewer()
}
#endif // __APPLE__
}
#endif // ENABLE_GCODE_VIEWER
void MainFrame::update_menubar()
{
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_gcode_viewer())
return;
#endif // ENABLE_GCODE_VIEWER
const bool is_fff = plater()->printer_technology() == ptFFF;
@ -1582,7 +1417,7 @@ void MainFrame::quick_slice(const int qs)
m_progress_dialog->Destroy();
m_progress_dialog = nullptr;
auto message = input_file_basename + _L(" was successfully sliced.");
auto message = format(_L("%1% was successfully sliced."), input_file_basename);
// wxTheApp->notify(message);
wxMessageDialog(this, message, _L("Slicing Done!"), wxOK | wxICON_INFORMATION).ShowModal();
// };
@ -1982,10 +1817,8 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"),
m_main_frame(mainframe)
{
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_gcode_viewer())
return;
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling
@ -2058,10 +1891,8 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
{
#if ENABLE_GCODE_VIEWER
if (wxGetApp().is_gcode_viewer())
return;
#endif // ENABLE_GCODE_VIEWER
const int& em = em_unit();
const wxSize& size = wxSize(85 * em, 50 * em);

View file

@ -71,9 +71,7 @@ class MainFrame : public DPIFrame
wxString m_qs_last_input_file = wxEmptyString;
wxString m_qs_last_output_file = wxEmptyString;
wxString m_last_config = wxEmptyString;
#if ENABLE_GCODE_VIEWER
wxMenuBar* m_menubar{ nullptr };
#endif // ENABLE_GCODE_VIEWER
#if 0
wxMenuItem* m_menu_item_repeat { nullptr }; // doesn't used now
@ -128,9 +126,7 @@ class MainFrame : public DPIFrame
Old,
New,
Dlg,
#if ENABLE_GCODE_VIEWER
GCodeViewer
#endif // ENABLE_GCODE_VIEWER
};
ESettingsLayout m_layout{ ESettingsLayout::Unknown };
@ -159,12 +155,8 @@ public:
// Register Win32 RawInput callbacks (3DConnexion) and removable media insert / remove callbacks.
// Called from wxEVT_ACTIVATE, as wxEVT_CREATE was not reliable (bug in wxWidgets?).
void register_win32_callbacks();
#if ENABLE_GCODE_VIEWER
void init_menubar_as_editor();
void init_menubar_as_gcodeviewer();
#else
void init_menubar();
#endif // ENABLE_GCODE_VIEWER
void update_menubar();
void update_ui_from_settings(bool apply_free_camera_correction = true);

View file

@ -99,7 +99,7 @@ void Mouse3DController::State::append_button(unsigned int id, size_t /* input_qu
#endif // ENABLE_3DCONNEXION_DEVICES_DEBUG_OUTPUT
}
#ifdef WIN32
#ifdef _WIN32
#if ENABLE_CTRL_M_ON_WINDOWS
static std::string format_device_string(int vid, int pid)
{
@ -319,7 +319,7 @@ bool Mouse3DController::State::process_mouse_wheel()
m_mouse_wheel_counter = 0;
return true;
}
#endif // WIN32
#endif // _WIN32
bool Mouse3DController::State::apply(const Mouse3DController::Params &params, Camera& camera)
{
@ -700,10 +700,10 @@ void Mouse3DController::shutdown()
}
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef WIN32
#ifdef _WIN32
if (!m_device_str.empty())
m_params_by_device[m_device_str] = m_params_ui;
#endif // WIN32
#endif // _WIN32
#endif // ENABLE_CTRL_M_ON_WINDOWS
}

View file

@ -189,7 +189,7 @@ public:
bool handle_input(const DataPacketAxis& packet);
#endif // __APPLE__
#ifdef WIN32
#ifdef _WIN32
bool handle_raw_input_win32(const unsigned char *data, const int packet_lenght);
// Called by Win32 HID enumeration callback.
@ -202,7 +202,7 @@ public:
// if the application does not register at the driver. This is a workaround to ignore these superfluous
// mouse wheel events.
bool process_mouse_wheel() { return m_state.process_mouse_wheel(); }
#endif // WIN32
#endif // _WIN32
// Apply the received 3DConnexion mouse events to the camera. Called from the UI rendering thread.
bool apply(Camera& camera);

View file

@ -150,7 +150,9 @@ private:
const int duration;
const std::string text1;
const std::string hypertext;
// Callback for hypertext - returns if notif shall close.
// Callback for hypertext - returns true if notification should close after triggering
// Usually sends event to UI thread thru wxEvtHandler.
// Examples in basic_notifications.
std::function<bool(wxEvtHandler*)> callback { nullptr };
const std::string text2;
};
@ -227,7 +229,8 @@ private:
void render_left_sign(ImGuiWrapper& imgui);
virtual void render_minimize_button(ImGuiWrapper& imgui,
const float win_pos_x, const float win_pos_y);
// Hypertext action, returns if close notification
// Hypertext action, returns true if notification should close.
// Action is stored in NotificationData::callback as std::function<bool(wxEvtHandler*)>
virtual bool on_text_click();
const NotificationData m_data;

View file

@ -8,6 +8,7 @@
#include <boost/algorithm/string/split.hpp>
#include "libslic3r/Utils.hpp"
#include "I18N.hpp"
#include "format.hpp"
namespace Slic3r { namespace GUI {
@ -90,7 +91,7 @@ void OG_CustomCtrl::init_ctrl_lines()
height = m_bmp_blinking_sz.GetHeight() + m_v_gap;
ctrl_lines.emplace_back(CtrlLine(height, this, line, true));
}
else if (opt_group->label_width != 0 && !line.label.IsEmpty())
else if (opt_group->label_width != 0 && (!line.label.IsEmpty() || option_set.front().opt.gui_type == "legend") )
{
wxSize label_sz = GetTextExtent(line.label);
height = label_sz.y * (label_sz.GetWidth() > int(opt_group->label_width * m_em_unit) ? 2 : 1) + m_v_gap;
@ -135,7 +136,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
}
wxString label = line.label;
if (opt_group->label_width != 0 && !label.IsEmpty())
if (opt_group->label_width != 0)
h_pos += opt_group->label_width * m_em_unit + m_h_gap;
int blinking_button_width = m_bmp_blinking_sz.GetWidth() + m_h_gap;
@ -174,13 +175,24 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
label += ":";
wxCoord label_w, label_h;
#ifdef __WXMSW__
// when we use 2 monitors with different DPIs, GetTextExtent() return value for the primary display
// so, use dc.GetMultiLineTextExtent on Windows
wxPaintDC dc(this);
dc.SetFont(m_font);
dc.GetMultiLineTextExtent(label, &label_w, &label_h);
#else
GetTextExtent(label, &label_w, &label_h, 0, 0, &m_font);
#endif //__WXMSW__
h_pos += label_w + 1 + m_h_gap;
}
h_pos += 3 * blinking_button_width;
h_pos += (opt.opt.gui_type == "legend" ? 1 : 3) * blinking_button_width;
if (field == field_in)
break;
break;
if (opt.opt.gui_type == "legend")
h_pos += 2 * blinking_button_width;
h_pos += field->getWindow()->GetSize().x;
if (option_set.size() == 1 && option_set.front().opt.full_width)
@ -228,10 +240,14 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
wxString language = wxGetApp().app_config->get("translation_language");
bool suppress_hyperlinks = get_app_config()->get("suppress_hyperlinks") == "1";
for (CtrlLine& line : ctrl_lines) {
line.is_focused = is_point_in_rect(pos, line.rect_label);
if (line.is_focused) {
tooltip = get_url(line.og_line.label_path);
if (!suppress_hyperlinks && !line.og_line.label_path.empty())
tooltip = get_url(line.og_line.label_path) +"\n\n";
tooltip += line.og_line.label_tooltip;
break;
}
@ -461,6 +477,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
{
Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id);
bool suppress_hyperlinks = get_app_config()->get("suppress_hyperlinks") == "1";
if (draw_just_act_buttons) {
if (field)
draw_act_bmps(dc, wxPoint(0, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink());
@ -478,7 +495,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
bool is_url_string = false;
if (ctrl->opt_group->label_width != 0 && !label.IsEmpty()) {
const wxColour* text_clr = (option_set.size() == 1 && field ? field->label_color() : og_line.full_Label_color);
is_url_string = !og_line.label_path.IsEmpty();
is_url_string = !suppress_hyperlinks && !og_line.label_path.IsEmpty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label + ":", text_clr, ctrl->opt_group->label_width * ctrl->m_em_unit, is_url_string);
}
@ -518,7 +535,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
if (is_url_string)
is_url_string = false;
else if(opt == option_set.front())
is_url_string = !og_line.label_path.IsEmpty();
is_url_string = !suppress_hyperlinks && !og_line.label_path.IsEmpty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit, is_url_string);
}
@ -556,7 +573,8 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos)
wxBitmap bmp = create_scaled_bitmap(bmp_name, ctrl, wxOSX ? 10 : 12);
wxCoord y_draw = v_pos + lround((height - get_bitmap_size(bmp).GetHeight()) / 2);
dc.DrawBitmap(bmp, 0, y_draw);
if (og_line.get_options().front().opt.gui_type != "legend")
dc.DrawBitmap(bmp, 0, y_draw);
return get_bitmap_size(bmp).GetWidth() + ctrl->m_h_gap;
}
@ -594,7 +612,7 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr
dc.GetMultiLineTextExtent(out_text, &text_width, &text_height);
pos.y = pos.y + lround((height - text_height) / 2);
if (width > 0 && is_url)
if (width > 0)
rect_label = wxRect(pos, wxSize(text_width, text_height));
wxColour old_clr = dc.GetTextForeground();
@ -656,9 +674,67 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBi
bool OG_CustomCtrl::CtrlLine::launch_browser() const
{
return is_focused && !og_line.label_path.IsEmpty() && wxLaunchDefaultBrowser(get_url(og_line.label_path));
if (!is_focused || og_line.label_path.IsEmpty())
return false;
bool launch = true;
if (get_app_config()->get("suppress_hyperlinks").empty()) {
RememberChoiceDialog dialog(nullptr, _L("Should we open this hyperlink in your default browser?"), _L("PrusaSlicer: Open hyperlink"));
int answer = dialog.ShowModal();
launch = answer == wxID_YES;
get_app_config()->set("suppress_hyperlinks", dialog.remember_choice() ? (answer == wxID_NO ? "1" : "0") : "");
}
if (launch)
launch = get_app_config()->get("suppress_hyperlinks") != "1";
return launch && wxLaunchDefaultBrowser(get_url(og_line.label_path));
}
RememberChoiceDialog::RememberChoiceDialog(wxWindow* parent, const wxString& msg_text, const wxString& caption)
: wxDialog(parent, wxID_ANY, caption, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxICON_INFORMATION)
{
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
this->SetEscapeId(wxID_CLOSE);
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
m_remember_choice = new wxCheckBox(this, wxID_ANY, _L("Remember my choice"));
m_remember_choice->SetValue(false);
m_remember_choice->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& evt)
{
if (!evt.IsChecked())
return;
wxString preferences_item = _L("Suppress to open hyperlink in browser");
wxString msg =
_L("PrusaSlicer will remember your choice.") + "\n\n" +
_L("You will not be asked about it again on label hovering.") + "\n\n" +
format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto changes your choice."), preferences_item);
wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION);
if (dialog.ShowModal() == wxID_CANCEL)
m_remember_choice->SetValue(false);
});
// Add dialog's buttons
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxYES | wxNO);
wxButton* btnYES = static_cast<wxButton*>(this->FindWindowById(wxID_YES, this));
wxButton* btnNO = static_cast<wxButton*>(this->FindWindowById(wxID_NO, this));
btnYES->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { this->EndModal(wxID_YES); });
btnNO->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { this->EndModal(wxID_NO); });
topSizer->Add(new wxStaticText(this, wxID_ANY, msg_text), 0, wxEXPAND | wxALL, 10);
topSizer->Add(m_remember_choice, 0, wxEXPAND | wxALL, 10);
topSizer->Add(btns, 0, wxEXPAND | wxALL, 10);
this->SetSizer(topSizer);
topSizer->SetSizeHints(this);
this->CenterOnScreen();
}
} // GUI
} // Slic3r

View file

@ -95,6 +95,20 @@ public:
};
//-----------------------------------------------
// RememberChoiceDialog
//-----------------------------------------------
class RememberChoiceDialog : public wxDialog
{
wxCheckBox* m_remember_choice;
public:
RememberChoiceDialog(wxWindow* parent, const wxString& msg_text, const wxString& caption);
~RememberChoiceDialog() {}
bool remember_choice() const { return m_remember_choice->GetValue(); }
};
}}
#endif /* slic3r_OG_CustomCtrl_hpp_ */

View file

@ -285,7 +285,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent
const int extruder/* = 0*/,
const bool create_frst_child/* = true*/)
{
ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode *root = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
if (!root) return wxDataViewItem(0);
wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder);
@ -331,7 +331,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent
wxDataViewItem ObjectDataViewModel::AddSettingsChild(const wxDataViewItem &parent_item)
{
ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode *root = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
if (!root) return wxDataViewItem(0);
const auto node = new ObjectDataViewModelNode(root, itSettings);
@ -370,7 +370,7 @@ static bool append_root_node(ObjectDataViewModelNode *parent_node,
wxDataViewItem ObjectDataViewModel::AddRoot(const wxDataViewItem &parent_item, ItemType root_type)
{
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode *parent_node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
if (!parent_node) return wxDataViewItem(0);
// get InstanceRoot node
@ -408,7 +408,7 @@ wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem& paren
const wxDataViewItem inst_root_item = AddInstanceRoot(parent_item);
if (!inst_root_item) return wxDataViewItem(0);
ObjectDataViewModelNode* inst_root_node = (ObjectDataViewModelNode*)inst_root_item.GetID();
ObjectDataViewModelNode* inst_root_node = static_cast<ObjectDataViewModelNode*>(inst_root_item.GetID());
// Add instance nodes
ObjectDataViewModelNode *instance_node = nullptr;
@ -437,7 +437,7 @@ void ObjectDataViewModel::UpdateObjectPrintable(wxDataViewItem parent_item)
if (!inst_root_item)
return;
ObjectDataViewModelNode* inst_root_node = (ObjectDataViewModelNode*)inst_root_item.GetID();
ObjectDataViewModelNode* inst_root_node = static_cast<ObjectDataViewModelNode*>(inst_root_item.GetID());
const size_t child_cnt = inst_root_node->GetChildren().Count();
PrintIndicator obj_pi = piUnprintable;
@ -447,7 +447,7 @@ void ObjectDataViewModel::UpdateObjectPrintable(wxDataViewItem parent_item)
break;
}
// and set printable state for object_node to piUndef
ObjectDataViewModelNode* obj_node = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode* obj_node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
obj_node->set_printable_icon(obj_pi);
ItemChanged(parent_item);
}
@ -459,10 +459,10 @@ void ObjectDataViewModel::UpdateInstancesPrintable(wxDataViewItem parent_item)
if (!inst_root_item)
return;
ObjectDataViewModelNode* obj_node = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode* obj_node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
const PrintIndicator obj_pi = obj_node->IsPrintable();
ObjectDataViewModelNode* inst_root_node = (ObjectDataViewModelNode*)inst_root_item.GetID();
ObjectDataViewModelNode* inst_root_node = static_cast<ObjectDataViewModelNode*>(inst_root_item.GetID());
const size_t child_cnt = inst_root_node->GetChildren().Count();
for (size_t i=0; i < child_cnt; i++)
@ -476,7 +476,7 @@ void ObjectDataViewModel::UpdateInstancesPrintable(wxDataViewItem parent_item)
bool ObjectDataViewModel::IsPrintable(const wxDataViewItem& item) const
{
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node)
return false;
@ -493,7 +493,7 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_
const int extruder/* = 0*/,
const int index /* = -1*/)
{
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode *parent_node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
if (!parent_node) return wxDataViewItem(0);
wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder);
@ -530,7 +530,7 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_
wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
{
auto ret_item = wxDataViewItem(0);
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node) // happens if item.IsOk()==false
return ret_item;
@ -701,7 +701,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
wxDataViewItem ObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &parent_item, size_t num)
{
auto ret_item = wxDataViewItem(0);
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode *parent_node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
if (!parent_node) return ret_item;
const int inst_root_id = get_root_idx(parent_node, itInstanceRoot);
@ -755,7 +755,7 @@ void ObjectDataViewModel::DeleteAll()
void ObjectDataViewModel::DeleteChildren(wxDataViewItem& parent)
{
ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode *root = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!root) // happens if item.IsOk()==false
return;
@ -787,7 +787,7 @@ void ObjectDataViewModel::DeleteChildren(wxDataViewItem& parent)
void ObjectDataViewModel::DeleteVolumeChildren(wxDataViewItem& parent)
{
ObjectDataViewModelNode *root = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode *root = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!root) // happens if item.IsOk()==false
return;
@ -821,7 +821,7 @@ void ObjectDataViewModel::DeleteVolumeChildren(wxDataViewItem& parent)
void ObjectDataViewModel::DeleteSettings(const wxDataViewItem& parent)
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!node) return;
// if volume has a "settings"item, than delete it before volume deleting
@ -880,7 +880,7 @@ wxDataViewItem ObjectDataViewModel::GetItemById(const int obj_idx, const int sub
if (!item)
return wxDataViewItem(0);
auto parent = (ObjectDataViewModelNode*)item.GetID();
auto parent = static_cast<ObjectDataViewModelNode*>(item.GetID());
for (size_t i = 0; i < parent->GetChildCount(); i++)
if (parent->GetNthChild(i)->m_idx == sub_obj_idx)
return wxDataViewItem(parent->GetNthChild(i));
@ -909,7 +909,7 @@ wxDataViewItem ObjectDataViewModel::GetItemByLayerRange(const int obj_idx, const
if (!item)
return wxDataViewItem(0);
auto parent = (ObjectDataViewModelNode*)item.GetID();
auto parent = static_cast<ObjectDataViewModelNode*>(item.GetID());
for (size_t i = 0; i < parent->GetChildCount(); i++)
if (parent->GetNthChild(i)->m_layer_range == layer_range)
return wxDataViewItem(parent->GetNthChild(i));
@ -931,7 +931,7 @@ int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const
if(!item.IsOk())
return -1;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
auto it = find(m_objects.begin(), m_objects.end(), node);
if (it == m_objects.end())
return -1;
@ -943,7 +943,7 @@ int ObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const It
{
wxASSERT(item.IsOk());
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node || node->m_type != type)
return -1;
return node->GetIdx();
@ -973,7 +973,7 @@ t_layer_height_range ObjectDataViewModel::GetLayerRangeByItem(const wxDataViewIt
{
wxASSERT(item.IsOk());
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node || node->m_type != itLayer)
return { 0.0f, 0.0f };
return node->GetLayerRange();
@ -1029,7 +1029,7 @@ void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type
wxASSERT(item.IsOk());
type = itUndef;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node ||
node->GetIdx() <-1 ||
( node->GetIdx() == -1 &&
@ -1098,7 +1098,7 @@ bool ObjectDataViewModel::InvalidItem(const wxDataViewItem& item)
if (!item)
return true;
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node || node->invalid())
return true;
@ -1107,7 +1107,7 @@ bool ObjectDataViewModel::InvalidItem(const wxDataViewItem& item)
wxString ObjectDataViewModel::GetName(const wxDataViewItem &item) const
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node) // happens if item.IsOk()==false
return wxEmptyString;
@ -1116,13 +1116,13 @@ wxString ObjectDataViewModel::GetName(const wxDataViewItem &item) const
wxBitmap& ObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
return node->m_bmp;
}
wxString ObjectDataViewModel::GetExtruder(const wxDataViewItem& item) const
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node) // happens if item.IsOk()==false
return wxEmptyString;
@ -1131,7 +1131,7 @@ wxString ObjectDataViewModel::GetExtruder(const wxDataViewItem& item) const
int ObjectDataViewModel::GetExtruderNumber(const wxDataViewItem& item) const
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node) // happens if item.IsOk()==false
return 0;
@ -1142,7 +1142,7 @@ void ObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &ite
{
wxASSERT(item.IsOk());
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
switch (col)
{
case colPrint:
@ -1166,7 +1166,7 @@ bool ObjectDataViewModel::SetValue(const wxVariant &variant, const wxDataViewIte
{
wxASSERT(item.IsOk());
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
return node->SetValue(variant, col);
}
@ -1196,7 +1196,7 @@ void ObjectDataViewModel::SetExtruder(const wxString& extruder, wxDataViewItem i
void ObjectDataViewModel::AddAllChildren(const wxDataViewItem& parent)
{
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!node || node->GetChildCount() == 0)
return;
@ -1222,7 +1222,7 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume
if (current_volume_id == new_volume_id)
return ret_item;
wxASSERT(parent.IsOk());
ObjectDataViewModelNode *node_parent = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode *node_parent = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!node_parent) // happens if item.IsOk()==false
return ret_item;
@ -1270,7 +1270,7 @@ wxDataViewItem ObjectDataViewModel::ReorganizeObjects( const int current_id, co
bool ObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const
{
wxASSERT(item.IsOk());
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
// disable extruder selection for the non "itObject|itVolume" item
return !(col == colExtruder && node->m_extruder.IsEmpty());
@ -1282,7 +1282,7 @@ wxDataViewItem ObjectDataViewModel::GetParent(const wxDataViewItem &item) const
if (!item.IsOk())
return wxDataViewItem(0);
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
assert(node != nullptr && node->valid());
// objects nodes has no parent too
@ -1298,7 +1298,7 @@ wxDataViewItem ObjectDataViewModel::GetTopParent(const wxDataViewItem &item) con
if (!item.IsOk())
return wxDataViewItem(0);
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (node->m_type == itObject)
return item;
@ -1315,13 +1315,13 @@ bool ObjectDataViewModel::IsContainer(const wxDataViewItem &item) const
if (!item.IsOk())
return true;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
return node->IsContainer();
}
unsigned int ObjectDataViewModel::GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!node)
{
for (auto object : m_objects)
@ -1346,7 +1346,7 @@ unsigned int ObjectDataViewModel::GetChildren(const wxDataViewItem &parent, wxDa
void ObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const
{
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(parent.GetID());
if (!node) {
for (auto object : m_objects)
array.Add(wxDataViewItem((void*)object));
@ -1374,7 +1374,7 @@ ItemType ObjectDataViewModel::GetItemType(const wxDataViewItem &item) const
{
if (!item.IsOk())
return itUndef;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
return node->m_type < 0 ? itUndef : node->m_type;
}
@ -1383,7 +1383,7 @@ wxDataViewItem ObjectDataViewModel::GetItemByType(const wxDataViewItem &parent_i
if (!parent_item.IsOk())
return wxDataViewItem(0);
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)parent_item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
if (node->GetChildCount() == 0)
return wxDataViewItem(0);
@ -1414,7 +1414,7 @@ bool ObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const
{
if (!item.IsOk())
return false;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
return node->m_type == itSettings;
}
@ -1422,7 +1422,7 @@ void ObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item,
const std::vector<std::string>& categories)
{
if (!item.IsOk()) return;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node->update_settings_digest(categories))
return;
ItemChanged(item);
@ -1433,7 +1433,7 @@ void ObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r
if (!item.IsOk() || GetItemType(item) != itVolume)
return;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
node->SetBitmap(*m_volume_bmps[int(type)]);
ItemChanged(item);
}
@ -1451,7 +1451,7 @@ wxDataViewItem ObjectDataViewModel::SetPrintableState(
item = subobj_type&itInstance ? GetItemByInstanceId(obj_idx, subobj_idx) :
GetItemByVolumeId(obj_idx, subobj_idx);
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node)
return wxDataViewItem(0);
node->set_printable_icon(printable);
@ -1467,7 +1467,7 @@ wxDataViewItem ObjectDataViewModel::SetObjectPrintableState(
PrintIndicator printable,
wxDataViewItem obj_item)
{
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)obj_item.GetID();
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(obj_item.GetID());
if (!node)
return wxDataViewItem(0);
node->set_printable_icon(printable);
@ -1488,7 +1488,7 @@ void ObjectDataViewModel::Rescale()
if (!item.IsOk())
continue;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
node->msw_rescale();
switch (node->m_type)
@ -1537,7 +1537,7 @@ void ObjectDataViewModel::DeleteWarningIcon(const wxDataViewItem& item, const bo
if (!item.IsOk())
return;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (!node->GetBitmap().IsOk() || !(node->GetType() & (itVolume | itObject)))
return;

View file

@ -300,15 +300,15 @@ public:
// helper methods to change the model
virtual unsigned int GetColumnCount() const override { return 3;}
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
unsigned int GetColumnCount() const override { return 3;}
wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
virtual void GetValue( wxVariant &variant,
const wxDataViewItem &item,
unsigned int col) const override;
virtual bool SetValue( const wxVariant &variant,
const wxDataViewItem &item,
unsigned int col) override;
void GetValue( wxVariant &variant,
const wxDataViewItem &item,
unsigned int col) const override;
bool SetValue( const wxVariant &variant,
const wxDataViewItem &item,
unsigned int col) override;
bool SetValue( const wxVariant &variant,
const int item_idx,
unsigned int col);
@ -322,18 +322,17 @@ public:
const wxDataViewItem &parent);
wxDataViewItem ReorganizeObjects( int current_id, int new_id);
virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
wxDataViewItem GetParent(const wxDataViewItem &item) const override;
// get object item
wxDataViewItem GetTopParent(const wxDataViewItem &item) const;
virtual bool IsContainer(const wxDataViewItem &item) const override;
virtual unsigned int GetChildren(const wxDataViewItem &parent,
wxDataViewItemArray &array) const override;
bool IsContainer(const wxDataViewItem &item) const override;
unsigned int GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const override;
void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
// Is the container just a header or an item with all columns
// In our case it is an item with all columns
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
ItemType GetItemType(const wxDataViewItem &item) const ;
wxDataViewItem GetItemByType( const wxDataViewItem &parent_item,

View file

@ -106,11 +106,25 @@ OptionsGroup::OptionsGroup( wxWindow* _parent, const wxString& title,
bool is_tab_opt /* = false */,
column_t extra_clmn /* = nullptr */) :
m_parent(_parent), title(title),
m_show_modified_btns(is_tab_opt),
m_use_custom_ctrl(is_tab_opt),
staticbox(title!=""), extra_column(extra_clmn)
{
}
wxWindow* OptionsGroup::ctrl_parent() const
{
return this->custom_ctrl && m_use_custom_ctrl_as_parent ? static_cast<wxWindow*>(this->custom_ctrl) : (this->stb ? static_cast<wxWindow*>(this->stb) : this->parent());
}
bool OptionsGroup::is_legend_line()
{
if (m_lines.size() == 1) {
const std::vector<Option>& option_set = m_lines.front().get_options();
return !option_set.empty() && option_set.front().opt.gui_type == "legend";
}
return false;
}
void OptionsGroup::show_field(const t_config_option_key& opt_key, bool show/* = true*/)
{
Field* field = get_field(opt_key);
@ -196,16 +210,20 @@ void OptionsGroup::activate_line(Line& line)
}
}
if (!custom_ctrl && m_show_modified_btns) {
custom_ctrl = new OG_CustomCtrl((wxWindow*)this->stb, this);
sizer->Add(custom_ctrl, 0, wxEXPAND | wxALL, wxOSX || !staticbox ? 0 : 5);
}
auto option_set = line.get_options();
bool is_legend_line = option_set.front().opt.gui_type == "legend";
if (!custom_ctrl && m_use_custom_ctrl) {
custom_ctrl = new OG_CustomCtrl(is_legend_line ? this->parent() : static_cast<wxWindow*>(this->stb), this);
if (is_legend_line)
sizer->Add(custom_ctrl, 0, wxEXPAND | wxLEFT, wxOSX ? 0 : 10);
else
sizer->Add(custom_ctrl, 0, wxEXPAND | wxALL, wxOSX || !staticbox ? 0 : 5);
}
// Set sidetext width for a better alignment of options in line
// "m_show_modified_btns==true" means that options groups are in tabs
if (option_set.size() > 1 && m_show_modified_btns) {
if (option_set.size() > 1 && m_use_custom_ctrl) {
sidetext_width = Field::def_width_thinner();
}
@ -231,7 +249,7 @@ void OptionsGroup::activate_line(Line& line)
m_use_custom_ctrl_as_parent = true;
// if we have an extra column, build it
if (extra_column && !m_show_modified_btns)
if (extra_column)
{
m_extra_column_item_ptrs.push_back(extra_column(this->ctrl_parent(), line));
grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3);
@ -511,7 +529,7 @@ Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index
std::pair<std::string, int> pair(opt_key, opt_index);
m_opt_map.emplace(opt_id, pair);
if (m_show_modified_btns) // fill group and category values just fro options from Settings Tab
if (m_use_custom_ctrl) // fill group and category values just for options from Settings Tab
wxGetApp().sidebar().get_searcher().add_key(opt_id, title, this->config_category());
return Option(*m_config->def()->get(opt_key), opt_id);

View file

@ -115,22 +115,9 @@ public:
/// Returns a copy of the pointer of the parent wxWindow.
/// Accessor function is because users are not allowed to change the parent
/// but defining it as const means a lot of const_casts to deal with wx functions.
inline wxWindow* parent() const {
#if 0//#ifdef __WXGTK__
return m_panel;
#else
return m_parent;
#endif /* __WXGTK__ */
}
#if 0//#ifdef __WXGTK__
wxWindow* get_parent() const {
return m_parent;
}
#endif /* __WXGTK__ */
inline wxWindow* parent() const { return m_parent; }
wxWindow* ctrl_parent() const {
return this->stb ? (this->custom_ctrl && m_use_custom_ctrl_as_parent ? (wxWindow*)this->custom_ctrl : (wxWindow*)this->stb) : this->parent();
}
wxWindow* ctrl_parent() const;
void append_line(const Line& line);
// create controls for the option group
@ -173,10 +160,6 @@ public:
inline void disable() { for (auto& field : m_fields) field.second->disable(); }
void set_grid_vgap(int gap) { m_grid_sizer->SetVGap(gap); }
void set_show_modified_btns_val(bool show) {
m_show_modified_btns = show;
}
void clear_fields_except_of(const std::vector<std::string> left_fields);
void hide_labels() { label_width = 0; }
@ -187,6 +170,7 @@ public:
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
const std::vector<Line>& get_lines() { return m_lines; }
bool is_legend_line();
protected:
std::map<t_config_option_key, Option> m_options;
@ -203,7 +187,7 @@ protected:
bool m_disabled {false};
wxGridSizer* m_grid_sizer {nullptr};
// "true" if option is created in preset tabs
bool m_show_modified_btns{ false };
bool m_use_custom_ctrl{ false };
// "true" if control should be created on custom_ctrl
bool m_use_custom_ctrl_as_parent { false };

View file

@ -189,10 +189,10 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_
}
else
{
m_printer = *printer;
const std::set<std::string>& preset_names = printer->get_preset_names();
for (const std::string& preset_name : preset_names)
m_presets.emplace_back(new PresetForPrinter(this, preset_name));
m_printer = *printer;
}
if (m_presets.size() == 1)

File diff suppressed because it is too large Load diff

View file

@ -11,9 +11,7 @@
#include "libslic3r/Preset.hpp"
#include "libslic3r/BoundingBox.hpp"
#if ENABLE_GCODE_VIEWER
#include "libslic3r/GCode/GCodeProcessor.hpp"
#endif // ENABLE_GCODE_VIEWER
#include "Jobs/Job.hpp"
#include "Search.hpp"
@ -144,15 +142,17 @@ public:
void add_model(bool imperial_units = false);
void import_sl1_archive();
void extract_config_from_project();
#if ENABLE_GCODE_VIEWER
void load_gcode();
void load_gcode(const wxString& filename);
void refresh_print();
#endif // ENABLE_GCODE_VIEWER
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
// To be called when providing a list of files to the GUI slic3r on command line.
std::vector<size_t> load_files(const std::vector<std::string>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
#if ENABLE_DRAG_AND_DROP_FIX
// to be called on drag and drop
bool load_files(const wxArrayString& filenames);
#endif // ENABLE_DRAG_AND_DROP_FIX
void update();
void stop_jobs();
@ -185,6 +185,7 @@ public:
void increase_instances(size_t num = 1);
void decrease_instances(size_t num = 1);
void set_number_of_copies(/*size_t num*/);
void fill_bed_with_instances();
bool is_selection_empty() const;
void scale_selection_to_fit_print_volume();
void convert_unit(bool from_imperial_unit);
@ -223,9 +224,7 @@ public:
bool search_string_getter(int idx, const char** label, const char** tooltip);
// For the memory statistics.
const Slic3r::UndoRedo::Stack& undo_redo_stack_main() const;
#if ENABLE_GCODE_VIEWER
void clear_undo_redo_stack_main();
#endif // ENABLE_GCODE_VIEWER
// Enter / leave the Gizmos specific Undo / Redo stack. To be used by the SLA support point editing gizmo.
void enter_gizmos_stack();
void leave_gizmos_stack();
@ -236,13 +235,8 @@ public:
void force_print_bed_update();
// On activating the parent window.
void on_activate();
#if ENABLE_GCODE_VIEWER
std::vector<std::string> get_extruder_colors_from_plater_config(const GCodeProcessor::Result* const result = nullptr) const;
std::vector<std::string> get_colors_for_color_print(const GCodeProcessor::Result* const result = nullptr) const;
#else
std::vector<std::string> get_extruder_colors_from_plater_config() const;
std::vector<std::string> get_colors_for_color_print() const;
#endif // ENABLE_GCODE_VIEWER
void update_object_menu();
void show_action_buttons(const bool is_ready_to_slice) const;
@ -256,6 +250,7 @@ public:
int get_selected_object_idx();
bool is_single_full_object_selection() const;
GLCanvas3D* canvas3D();
const GLCanvas3D * canvas3D() const;
GLCanvas3D* get_current_canvas3D();
BoundingBoxf bed_shape_bb() const;
@ -268,11 +263,7 @@ public:
PrinterTechnology printer_technology() const;
const DynamicPrintConfig * config() const;
#if ENABLE_GCODE_VIEWER
bool set_printer_technology(PrinterTechnology printer_technology);
#else
void set_printer_technology(PrinterTechnology printer_technology);
#endif // ENABLE_GCODE_VIEWER
void copy_selection_to_clipboard();
void paste_from_clipboard();
@ -298,13 +289,9 @@ public:
void sys_color_changed();
bool init_view_toolbar();
#if ENABLE_GCODE_VIEWER
void enable_view_toolbar(bool enable);
#endif // ENABLE_GCODE_VIEWER
bool init_collapse_toolbar();
#if ENABLE_GCODE_VIEWER
void enable_collapse_toolbar(bool enable);
#endif // ENABLE_GCODE_VIEWER
const Camera& get_camera() const;
Camera& get_camera();
@ -323,23 +310,19 @@ public:
const GLToolbar& get_collapse_toolbar() const;
GLToolbar& get_collapse_toolbar();
#if ENABLE_GCODE_VIEWER
void update_preview_bottom_toolbar();
void update_preview_moves_slider();
void enable_preview_moves_slider(bool enable);
void reset_gcode_toolpaths();
void reset_last_loaded_gcode() { m_last_loaded_gcode = ""; }
#endif // ENABLE_GCODE_VIEWER
const Mouse3DController& get_mouse3d_controller() const;
Mouse3DController& get_mouse3d_controller();
void set_bed_shape() const;
#if ENABLE_GCODE_VIEWER
void set_bed_shape(const Pointfs& shape, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false) const;
#endif // ENABLE_GCODE_VIEWER
const NotificationManager* get_notification_manager() const;
NotificationManager* get_notification_manager();
@ -394,9 +377,7 @@ private:
bool m_tracking_popup_menu = false;
wxString m_tracking_popup_menu_error_message;
#if ENABLE_GCODE_VIEWER
wxString m_last_loaded_gcode;
#endif // ENABLE_GCODE_VIEWER
void suppress_snapshots();
void allow_snapshots();

View file

@ -40,25 +40,17 @@ void PreferencesDialog::build()
// readonly = > !wxTheApp->have_version_check,
// ));
#if ENABLE_GCODE_VIEWER
bool is_editor = wxGetApp().is_editor();
#endif // ENABLE_GCODE_VIEWER
ConfigOptionDef def;
#if ENABLE_GCODE_VIEWER
Option option(def, "");
if (is_editor) {
#endif // ENABLE_GCODE_VIEWER
def.label = L("Remember output directory");
def.type = coBool;
def.tooltip = L("If this is enabled, Slic3r will prompt the last output directory "
"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 });
#if ENABLE_GCODE_VIEWER
option = Option(def, "remember_output_path");
#else
Option option(def, "remember_output_path");
#endif // ENABLE_GCODE_VIEWER
m_optgroup_general->append_single_option_line(option);
def.label = L("Auto-center parts");
@ -93,6 +85,25 @@ void PreferencesDialog::build()
option = Option(def, "export_sources_full_pathnames");
m_optgroup_general->append_single_option_line(option);
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
// Please keep in sync with ConfigWizard
def.label = L("Associate .3mf files to PrusaSlicer");
def.type = coBool;
def.tooltip = L("If enabled, sets PrusaSlicer as default application to open .3mf files.");
def.set_default_value(new ConfigOptionBool(app_config->get("associate_3mf") == "1"));
option = Option(def, "associate_3mf");
m_optgroup_general->append_single_option_line(option);
def.label = L("Associate .stl files to PrusaSlicer");
def.type = coBool;
def.tooltip = L("If enabled, sets PrusaSlicer as default application to open .stl files.");
def.set_default_value(new ConfigOptionBool(app_config->get("associate_stl") == "1"));
option = Option(def, "associate_stl");
m_optgroup_general->append_single_option_line(option);
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
// Please keep in sync with ConfigWizard
def.label = L("Update built-in Presets automatically");
def.type = coBool;
@ -134,9 +145,44 @@ void PreferencesDialog::build()
def.set_default_value(new ConfigOptionBool{ app_config->has("single_instance") ? app_config->get("single_instance") == "1" : false });
option = Option(def, "single_instance");
m_optgroup_general->append_single_option_line(option);
#if ENABLE_GCODE_VIEWER
/* // ysFIXME THis part is temporary commented
// The using of inches is implemented just for object's size and position
def.label = L("Use inches instead of millimeters");
def.type = coBool;
def.tooltip = L("Use inches instead of millimeters for the object's size");
def.set_default_value(new ConfigOptionBool{ app_config->get("use_inches") == "1" });
option = Option(def, "use_inches");
m_optgroup_general->append_single_option_line(option);
*/
def.label = L("Ask for unsaved changes when closing application");
def.type = coBool;
def.tooltip = L("When closing the application, always ask for unsaved changes");
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_close_application") == "none" });
option = Option(def, "default_action_on_close_application");
m_optgroup_general->append_single_option_line(option);
def.label = L("Ask for unsaved changes when selecting new preset");
def.type = coBool;
def.tooltip = L("Always ask for unsaved changes when selecting new preset");
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_select_preset") == "none" });
option = Option(def, "default_action_on_select_preset");
m_optgroup_general->append_single_option_line(option);
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
else {
def.label = L("Associate .gcode files to PrusaSlicer G-code Viewer");
def.type = coBool;
def.tooltip = L("If enabled, sets PrusaSlicer G-code Viewer as default application to open .gcode files.");
def.set_default_value(new ConfigOptionBool(app_config->get("associate_gcode") == "1"));
option = Option(def, "associate_gcode");
m_optgroup_general->append_single_option_line(option);
}
#endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#if __APPLE__
def.label = L("Use Retina resolution for the 3D scene");
@ -147,30 +193,6 @@ void PreferencesDialog::build()
option = Option (def, "use_retina_opengl");
m_optgroup_general->append_single_option_line(option);
#endif
/* // ysFIXME THis part is temporary commented
// The using of inches is implemented just for object's size and position
def.label = L("Use inches instead of millimeters");
def.type = coBool;
def.tooltip = L("Use inches instead of millimeters for the object's size");
def.set_default_value(new ConfigOptionBool{ app_config->get("use_inches") == "1" });
option = Option(def, "use_inches");
m_optgroup_general->append_single_option_line(option);
*/
def.label = L("Ask for unsaved changes when closing application");
def.type = coBool;
def.tooltip = L("When closing the application, always ask for unsaved changes");
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_close_application") == "none" });
option = Option(def, "default_action_on_close_application");
m_optgroup_general->append_single_option_line(option);
def.label = L("Ask for unsaved changes when selecting new preset");
def.type = coBool;
def.tooltip = L("Always ask for unsaved changes when selecting new preset");
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_select_preset") == "none" });
option = Option(def, "default_action_on_select_preset");
m_optgroup_general->append_single_option_line(option);
// Show/Hide splash screen
def.label = L("Show splash screen");
@ -180,6 +202,17 @@ void PreferencesDialog::build()
option = Option(def, "show_splash_screen");
m_optgroup_general->append_single_option_line(option);
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32
def.label = L("Enable support for legacy 3DConnexion devices");
def.type = coBool;
def.tooltip = L("If enabled, the legacy 3DConnexion devices settings dialog is available by pressing CTRL+M");
def.set_default_value(new ConfigOptionBool{ app_config->get("use_legacy_3DConnexion") == "1" });
option = Option(def, "use_legacy_3DConnexion");
m_optgroup_general->append_single_option_line(option);
#endif // _WIN32
#endif // ENABLE_CTRL_M_ON_WINDOWS
m_optgroup_general->activate();
m_optgroup_camera = std::make_shared<ConfigOptionsGroup>(this, _L("Camera"));
@ -214,16 +247,18 @@ void PreferencesDialog::build()
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 == "suppress_hyperlinks")
m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "";
else
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();
}
};
#if ENABLE_GCODE_VIEWER
if (is_editor) {
#endif // ENABLE_GCODE_VIEWER
def.label = L("Show sidebar collapse/expand button");
def.type = coBool;
def.tooltip = L("If enabled, the button for the collapse sidebar will be appeared in top right corner of the 3D Scene");
@ -237,7 +272,14 @@ void PreferencesDialog::build()
def.set_default_value(new ConfigOptionBool{ app_config->get("use_custom_toolbar_size") == "1" });
option = Option(def, "use_custom_toolbar_size");
m_optgroup_gui->append_single_option_line(option);
#if ENABLE_GCODE_VIEWER
def.label = L("Suppress to open hyperlink in browser");
def.type = coBool;
def.tooltip = L("If enabled, the descriptions of configuration parameters in settings tabs woldn't work as hyperlinks. "
"If disabled, the descriptions of configuration parameters in settings tabs will work as hyperlinks.");
def.set_default_value(new ConfigOptionBool{ app_config->get("suppress_hyperlinks") == "1" });
option = Option(def, "suppress_hyperlinks");
m_optgroup_gui->append_single_option_line(option);
}
def.label = L("Sequential slider applied only to top layer");
@ -247,25 +289,18 @@ void PreferencesDialog::build()
def.set_default_value(new ConfigOptionBool{ app_config->get("seq_top_layer_only") == "1" });
option = Option(def, "seq_top_layer_only");
m_optgroup_gui->append_single_option_line(option);
#endif // ENABLE_GCODE_VIEWER
m_optgroup_gui->activate();
#if ENABLE_GCODE_VIEWER
if (is_editor) {
#endif // ENABLE_GCODE_VIEWER
create_icon_size_slider();
m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1");
create_settings_mode_widget();
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
if (is_editor) {
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_ENVIRONMENT_MAP
if (is_editor) {
m_optgroup_render = std::make_shared<ConfigOptionsGroup>(this, _L("Render"));
m_optgroup_render->label_width = 40;
m_optgroup_render->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
@ -280,19 +315,15 @@ void PreferencesDialog::build()
m_optgroup_render->append_single_option_line(option);
m_optgroup_render->activate();
#endif // ENABLE_ENVIRONMENT_MAP
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
#endif // ENABLE_ENVIRONMENT_MAP
auto sizer = new wxBoxSizer(wxVERTICAL);
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);
#if ENABLE_ENVIRONMENT_MAP
#if ENABLE_GCODE_VIEWER
if (m_optgroup_render != nullptr)
#endif // ENABLE_GCODE_VIEWER
sizer->Add(m_optgroup_render->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
#endif // ENABLE_ENVIRONMENT_MAP
@ -305,13 +336,13 @@ void PreferencesDialog::build()
SetSizer(sizer);
sizer->SetSizeHints(this);
this->CenterOnParent();
}
void PreferencesDialog::accept()
{
if (m_values.find("no_defaults") != m_values.end()) {
if (m_values.find("no_defaults") != m_values.end())
warning_catcher(this, wxString::Format(_L("You need to restart %s to make the changes effective."), SLIC3R_APP_NAME));
}
auto app_config = get_app_config();
@ -320,9 +351,9 @@ void PreferencesDialog::accept()
m_seq_top_layer_only_changed = app_config->get("seq_top_layer_only") != it->second;
m_settings_layout_changed = false;
for (const std::string& key : {"old_settings_layout_mode",
"new_settings_layout_mode",
"dlg_settings_layout_mode" })
for (const std::string& key : { "old_settings_layout_mode",
"new_settings_layout_mode",
"dlg_settings_layout_mode" })
{
auto it = m_values.find(key);
if (it != m_values.end() && app_config->get(key) != it->second) {
@ -331,8 +362,7 @@ void PreferencesDialog::accept()
}
}
for (const std::string& key : {"default_action_on_close_application", "default_action_on_select_preset"})
{
for (const std::string& key : {"default_action_on_close_application", "default_action_on_select_preset"}) {
auto it = m_values.find(key);
if (it != m_values.end() && it->second != "none" && app_config->get(key) != "none")
m_values.erase(it); // we shouldn't change value, if some of those parameters was selected, and then deselected
@ -433,9 +463,9 @@ void PreferencesDialog::create_icon_size_slider()
void PreferencesDialog::create_settings_mode_widget()
{
wxString choices[] = { _L("Old regular layout with the tab bar"),
_L("New layout, access via settings button in the top menu"),
_L("Settings in non-modal window") };
wxString choices[] = { _L("Old regular layout with the tab bar"),
_L("New layout, access via settings button in the top menu"),
_L("Settings in non-modal window") };
auto app_config = get_app_config();
int selection = app_config->get("old_settings_layout_mode") == "1" ? 0 :
@ -444,14 +474,13 @@ void PreferencesDialog::create_settings_mode_widget()
wxWindow* parent = m_optgroup_gui->ctrl_parent();
m_layout_mode_box = new wxRadioBox(parent, wxID_ANY, _L("Layout Options"), wxDefaultPosition, wxDefaultSize, WXSIZEOF(choices), choices,
3, wxRA_SPECIFY_ROWS);
m_layout_mode_box = new wxRadioBox(parent, wxID_ANY, _L("Layout Options"), wxDefaultPosition, wxDefaultSize,
WXSIZEOF(choices), choices, 3, wxRA_SPECIFY_ROWS);
m_layout_mode_box->SetFont(wxGetApp().normal_font());
m_layout_mode_box->SetSelection(selection);
m_layout_mode_box->Bind(wxEVT_RADIOBOX, [this](wxCommandEvent& e) {
int selection = e.GetSelection();
m_values["old_settings_layout_mode"] = boost::any_cast<bool>(selection == 0) ? "1" : "0";
m_values["new_settings_layout_mode"] = boost::any_cast<bool>(selection == 1) ? "1" : "0";
m_values["dlg_settings_layout_mode"] = boost::any_cast<bool>(selection == 2) ? "1" : "0";
@ -459,7 +488,6 @@ void PreferencesDialog::create_settings_mode_widget()
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_layout_mode_box, 1, wxALIGN_CENTER_VERTICAL);
m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND);
}

View file

@ -104,6 +104,15 @@ PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const
// parameters for an icon's drawing
fill_width_height();
Bind(wxEVT_MOUSEWHEEL, [this](wxMouseEvent& e) {
if (m_suppress_change)
e.StopPropagation();
else
e.Skip();
});
Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_suppress_change = false; });
Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_suppress_change = true; });
Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
@ -501,7 +510,7 @@ void PresetComboBox::OnDrawItem(wxDC& dc,
int item,
int flags) const
{
const wxBitmap& bmp = *(wxBitmap*)m_bitmaps[item];
const wxBitmap& bmp = *(static_cast<wxBitmap*>(m_bitmaps[item]));
if (bmp.IsOk())
{
// we should use scaled! size values of bitmap

View file

@ -86,6 +86,7 @@ protected:
int m_last_selected;
int m_em_unit;
bool m_suppress_change { true };
// parameters for an icon's drawing
int icon_height;
@ -129,8 +130,8 @@ protected:
* For this purpose control drawing methods and
* control size calculation methods (virtual) are overridden.
**/
virtual bool OnAddBitmap(const wxBitmap& bitmap) override;
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
bool OnAddBitmap(const wxBitmap& bitmap) override;
void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
#endif
private:

View file

@ -81,7 +81,7 @@ void RemovableDriveManager::eject_drive()
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
this->update();
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
BOOST_LOG_TRIVIAL(info) << "Ejecting started";
tbb::mutex::scoped_lock lock(m_drives_mutex);
auto it_drive_data = this->find_last_save_path_drive_data();
if (it_drive_data != m_current_drives.end()) {
@ -90,7 +90,7 @@ void RemovableDriveManager::eject_drive()
mpath = mpath.substr(0, mpath.size() - 1);
HANDLE handle = CreateFileW(boost::nowide::widen(mpath).c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) {
std::cerr << "Ejecting " << mpath << " failed " << GetLastError() << " \n";
BOOST_LOG_TRIVIAL(error) << "Ejecting " << mpath << " failed (handle == INVALID_HANDLE_VALUE): " << GetLastError();
assert(m_callback_evt_handler);
if (m_callback_evt_handler)
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
@ -99,19 +99,22 @@ void RemovableDriveManager::eject_drive()
DWORD deviceControlRetVal(0);
//these 3 commands should eject device safely but they dont, the device does disappear from file explorer but the "device was safely remove" notification doesnt trigger.
//sd cards does trigger WM_DEVICECHANGE messege, usb drives dont
DeviceIoControl(handle, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
BOOL e1 = DeviceIoControl(handle, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
BOOST_LOG_TRIVIAL(debug) << "FSCTL_LOCK_VOLUME " << e1 << " ; " << deviceControlRetVal << " ; " << GetLastError();
BOOL e2 = DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
BOOST_LOG_TRIVIAL(debug) << "FSCTL_DISMOUNT_VOLUME " << e2 << " ; " << deviceControlRetVal << " ; " << GetLastError();
// some implemenatations also calls IOCTL_STORAGE_MEDIA_REMOVAL here but it returns error to me
BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
if (error == 0) {
CloseHandle(handle);
BOOST_LOG_TRIVIAL(error) << "Ejecting " << mpath << " failed " << deviceControlRetVal << " " << GetLastError() << " \n";
BOOST_LOG_TRIVIAL(error) << "Ejecting " << mpath << " failed (IOCTL_STORAGE_EJECT_MEDIA)" << deviceControlRetVal << " " << GetLastError();
assert(m_callback_evt_handler);
if (m_callback_evt_handler)
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
return;
}
CloseHandle(handle);
BOOST_LOG_TRIVIAL(info) << "Ejecting finished";
assert(m_callback_evt_handler);
if (m_callback_evt_handler)
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair< DriveData, bool >(std::move(*it_drive_data), true)));
@ -256,6 +259,7 @@ void RemovableDriveManager::eject_drive()
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
this->update();
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
BOOST_LOG_TRIVIAL(info) << "Ejecting started";
tbb::mutex::scoped_lock lock(m_drives_mutex);
auto it_drive_data = this->find_last_save_path_drive_data();
@ -290,7 +294,7 @@ void RemovableDriveManager::eject_drive()
child.wait();
int err = child.exit_code();
if (err) {
BOOST_LOG_TRIVIAL(error) << "Ejecting failed";
BOOST_LOG_TRIVIAL(error) << "Ejecting failed. Exit code: " << err;
assert(m_callback_evt_handler);
if (m_callback_evt_handler)
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));

View file

@ -335,81 +335,6 @@ void OptionsSearcher::add_key(const std::string& opt_key, const wxString& group,
}
//------------------------------------------
// SearchComboPopup
//------------------------------------------
void SearchComboPopup::Init()
{
this->Bind(wxEVT_MOTION, &SearchComboPopup::OnMouseMove, this);
this->Bind(wxEVT_LEFT_UP, &SearchComboPopup::OnMouseClick, this);
this->Bind(wxEVT_KEY_DOWN, &SearchComboPopup::OnKeyDown, this);
}
bool SearchComboPopup::Create(wxWindow* parent)
{
return wxListBox::Create(parent, 1, wxPoint(0, 0), wxDefaultSize);
}
void SearchComboPopup::SetStringValue(const wxString& s)
{
int n = wxListBox::FindString(s);
if (n >= 0 && n < int(wxListBox::GetCount()))
wxListBox::Select(n);
// save a combo control's string
m_input_string = s;
}
void SearchComboPopup::ProcessSelection(int selection)
{
wxCommandEvent event(wxEVT_LISTBOX, GetId());
event.SetInt(selection);
event.SetEventObject(this);
ProcessEvent(event);
Dismiss();
}
void SearchComboPopup::OnMouseMove(wxMouseEvent& event)
{
wxPoint pt = wxGetMousePosition() - this->GetScreenPosition();
int selection = this->HitTest(pt);
wxListBox::Select(selection);
}
void SearchComboPopup::OnMouseClick(wxMouseEvent&)
{
int selection = wxListBox::GetSelection();
SetSelection(wxNOT_FOUND);
ProcessSelection(selection);
}
void SearchComboPopup::OnKeyDown(wxKeyEvent& event)
{
int key = event.GetKeyCode();
// change selected item in the list
if (key == WXK_UP || key == WXK_DOWN)
{
int selection = wxListBox::GetSelection();
if (key == WXK_UP && selection > 0)
selection--;
if (key == WXK_DOWN && selection < int(wxListBox::GetCount() - 1))
selection++;
wxListBox::Select(selection);
}
// send wxEVT_LISTBOX event if "Enter" was pushed
else if (key == WXK_NUMPAD_ENTER || key == WXK_RETURN)
ProcessSelection(wxListBox::GetSelection());
else
event.Skip(); // !Needed to have EVT_CHAR generated as well
}
//------------------------------------------
// SearchDialog
//------------------------------------------

View file

@ -131,38 +131,6 @@ public:
};
class SearchComboPopup : public wxListBox, public wxComboPopup
{
public:
// Initialize member variables
void Init();
// Create popup control
virtual bool Create(wxWindow* parent);
// Return pointer to the created control
virtual wxWindow* GetControl() { return this; }
// Translate string into a list selection
virtual void SetStringValue(const wxString& s);
// Get list selection as a string
virtual wxString GetStringValue() const {
// we shouldn't change a combo control's string
return m_input_string;
}
void ProcessSelection(int selection);
// Do mouse hot-tracking (which is typical in list popups)
void OnMouseMove(wxMouseEvent& event);
// On mouse left up, set the value and close the popup
void OnMouseClick(wxMouseEvent& WXUNUSED(event));
// process Up/Down arrows and Enter press
void OnKeyDown(wxKeyEvent& event);
protected:
wxString m_input_string;
};
//------------------------------------------
// SearchDialog
//------------------------------------------
@ -204,7 +172,7 @@ public:
protected:
void on_dpi_changed(const wxRect& suggested_rect) override;
virtual void on_sys_color_changed() override;
void on_sys_color_changed() override;
};
@ -234,11 +202,11 @@ public:
// implementation of base class virtuals to define model
virtual unsigned int GetColumnCount() const override { return colMax; }
virtual wxString GetColumnType(unsigned int col) const override;
virtual void GetValueByRow(wxVariant& variant, unsigned int row, unsigned int col) const override;
virtual bool GetAttrByRow(unsigned int row, unsigned int col, wxDataViewItemAttr& attr) const override { return true; }
virtual bool SetValueByRow(const wxVariant& variant, unsigned int row, unsigned int col) override { return false; }
unsigned int GetColumnCount() const override { return colMax; }
wxString GetColumnType(unsigned int col) const override;
void GetValueByRow(wxVariant& variant, unsigned int row, unsigned int col) const override;
bool GetAttrByRow(unsigned int row, unsigned int col, wxDataViewItemAttr& attr) const override { return true; }
bool SetValueByRow(const wxVariant& variant, unsigned int row, unsigned int col) override { return false; }
};

View file

@ -16,9 +16,7 @@
#include <GL/glew.h>
#include <boost/algorithm/string/predicate.hpp>
#if ENABLE_GCODE_VIEWER
#include <boost/log/trivial.hpp>
#endif // ENABLE_GCODE_VIEWER
static const float UNIFORM_SCALE_COLOR[4] = { 0.923f, 0.504f, 0.264f, 1.0f };
@ -113,11 +111,6 @@ Selection::Selection()
, m_valid(false)
, m_scale_factor(1.0f)
{
#if !ENABLE_GCODE_VIEWER
m_arrow.reset(new GLArrow);
m_curved_arrow.reset(new GLCurvedArrow(16));
#endif // !ENABLE_GCODE_VIEWER
this->set_bounding_boxes_dirty();
#if ENABLE_RENDER_SELECTION_CENTER
m_quadric = ::gluNewQuadric();
@ -143,20 +136,8 @@ void Selection::set_volumes(GLVolumePtrs* volumes)
// Init shall be called from the OpenGL render function, so that the OpenGL context is initialized!
bool Selection::init()
{
#if ENABLE_GCODE_VIEWER
m_arrow.init_from(straight_arrow(10.0f, 5.0f, 5.0f, 10.0f, 1.0f));
m_curved_arrow.init_from(circular_arrow(16, 10.0f, 5.0f, 10.0f, 5.0f, 1.0f));
#else
if (!m_arrow->init())
return false;
m_arrow->set_scale(5.0 * Vec3d::Ones());
if (!m_curved_arrow->init())
return false;
m_curved_arrow->set_scale(5.0 * Vec3d::Ones());
#endif //ENABLE_GCODE_VIEWER
return true;
}
@ -1962,7 +1943,6 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons
glsafe(::glEnd());
}
#if ENABLE_GCODE_VIEWER
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const
{
auto set_color = [](Axis axis) {
@ -1984,25 +1964,7 @@ void Selection::render_sidebar_position_hints(const std::string& sidebar_field)
m_arrow.render();
}
}
#else
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const
{
if (boost::ends_with(sidebar_field, "x"))
{
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
render_sidebar_position_hint(X);
}
else if (boost::ends_with(sidebar_field, "y"))
render_sidebar_position_hint(Y);
else if (boost::ends_with(sidebar_field, "z"))
{
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
render_sidebar_position_hint(Z);
}
}
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const
{
auto set_color = [](Axis axis) {
@ -2030,23 +1992,6 @@ void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field)
render_sidebar_rotation_hint();
}
}
#else
void Selection::render_sidebar_rotation_hints(const std::string & sidebar_field) const
{
if (boost::ends_with(sidebar_field, "x"))
{
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
render_sidebar_rotation_hint(X);
}
else if (boost::ends_with(sidebar_field, "y"))
{
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
render_sidebar_rotation_hint(Y);
}
else if (boost::ends_with(sidebar_field, "z"))
render_sidebar_rotation_hint(Z);
}
#endif // ENABLE_GCODE_VIEWER
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) const
{
@ -2058,38 +2003,27 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con
shader->set_uniform("uniform_color", uniform_scale ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis], 4);
glsafe(::glTranslated(0.0, 5.0, 0.0));
#if ENABLE_GCODE_VIEWER
m_arrow.render();
#else
m_arrow->render();
#endif // ENABLE_GCODE_VIEWER
glsafe(::glTranslated(0.0, -10.0, 0.0));
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
#if ENABLE_GCODE_VIEWER
m_arrow.render();
#else
m_arrow->render();
#endif // ENABLE_GCODE_VIEWER
};
if (boost::ends_with(sidebar_field, "x") || uniform_scale)
{
if (boost::ends_with(sidebar_field, "x") || uniform_scale) {
glsafe(::glPushMatrix());
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
render_sidebar_scale_hint(X);
glsafe(::glPopMatrix());
}
if (boost::ends_with(sidebar_field, "y") || uniform_scale)
{
if (boost::ends_with(sidebar_field, "y") || uniform_scale) {
glsafe(::glPushMatrix());
render_sidebar_scale_hint(Y);
glsafe(::glPopMatrix());
}
if (boost::ends_with(sidebar_field, "z") || uniform_scale)
{
if (boost::ends_with(sidebar_field, "z") || uniform_scale) {
glsafe(::glPushMatrix());
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
render_sidebar_scale_hint(Z);
@ -2169,35 +2103,6 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
glsafe(::glDisable(GL_BLEND));
}
#if !ENABLE_GCODE_VIEWER
void Selection::render_sidebar_position_hint(Axis axis) const
{
m_arrow->set_color(AXES_COLOR[axis], 3);
m_arrow->render();
}
void Selection::render_sidebar_rotation_hint(Axis axis) const
{
m_curved_arrow->set_color(AXES_COLOR[axis], 3);
m_curved_arrow->render();
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
m_curved_arrow->render();
}
void Selection::render_sidebar_scale_hint(Axis axis) const
{
m_arrow->set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
glsafe(::glTranslated(0.0, 5.0, 0.0));
m_arrow->render();
glsafe(::glTranslated(0.0, -10.0, 0.0));
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
m_arrow->render();
}
#endif // !ENABLE_GCODE_VIEWER
#ifndef NDEBUG
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{

View file

@ -3,9 +3,7 @@
#include <set>
#include "libslic3r/Geometry.hpp"
#if ENABLE_GCODE_VIEWER
#include "GLModel.hpp"
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_RENDER_SELECTION_CENTER
class GLUquadric;
@ -221,15 +219,8 @@ private:
GLUquadricObj* m_quadric;
#endif // ENABLE_RENDER_SELECTION_CENTER
#if ENABLE_GCODE_VIEWER
GLModel m_arrow;
GLModel m_curved_arrow;
#else
// Arrows are saved through pointers to avoid including 3DScene.hpp.
// It also allows mutability.
std::unique_ptr<GLArrow> m_arrow;
std::unique_ptr<GLCurvedArrow> m_curved_arrow;
#endif // ENABLE_GCODE_VIEWER
mutable float m_scale_factor;
@ -386,11 +377,6 @@ private:
void render_sidebar_rotation_hints(const std::string& sidebar_field) const;
void render_sidebar_scale_hints(const std::string& sidebar_field) const;
void render_sidebar_layers_hints(const std::string& sidebar_field) const;
#if !ENABLE_GCODE_VIEWER
void render_sidebar_position_hint(Axis axis) const;
void render_sidebar_rotation_hint(Axis axis) const;
void render_sidebar_scale_hint(Axis axis) const;
#endif // !ENABLE_GCODE_VIEWER
public:
enum SyncRotationType {

View file

@ -12,6 +12,7 @@
#include <wx/clipbrd.h>
#include <wx/platinfo.h>
#include "GUI_App.hpp"
#include "MainFrame.hpp"
#include "wxExtensions.hpp"
#ifdef _WIN32
@ -34,17 +35,9 @@ std::string get_main_info(bool format_as_html)
std::string line_end = format_as_html ? "<br>" : "\n";
if (!format_as_html)
#if ENABLE_GCODE_VIEWER
out << b_start << (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME) << b_end << line_end;
#else
out << b_start << SLIC3R_APP_NAME << b_end << line_end;
#endif // ENABLE_GCODE_VIEWER
out << b_start << "Version: " << b_end << SLIC3R_VERSION << line_end;
#if ENABLE_GCODE_VIEWER
out << b_start << "Build: " << b_end << (wxGetApp().is_editor() ? SLIC3R_BUILD_ID : GCODEVIEWER_BUILD_ID) << line_end;
#else
out << b_start << "Build: " << b_end << SLIC3R_BUILD_ID << line_end;
#endif // ENABLE_GCODE_VIEWER
out << line_end;
out << b_start << "Operating System: " << b_end << wxPlatformInfo::Get().GetOperatingSystemFamilyName() << line_end;
out << b_start << "System Architecture: " << b_end << wxPlatformInfo::Get().GetArchName() << line_end;
@ -86,11 +79,7 @@ std::string get_mem_info(bool format_as_html)
}
SysInfoDialog::SysInfoDialog()
#if ENABLE_GCODE_VIEWER
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, (wxGetApp().is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME)) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
#else
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
#endif // ENABLE_GCODE_VIEWER
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, (wxGetApp().is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME)) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
SetBackgroundColour(bgr_clr);
@ -103,11 +92,7 @@ SysInfoDialog::SysInfoDialog()
main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10);
// logo
#if ENABLE_GCODE_VIEWER
m_logo_bmp = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_192px.png" : "PrusaSlicer-gcodeviewer_192px.png", 192);
#else
m_logo_bmp = ScalableBitmap(this, "PrusaSlicer_192px.png", 192);
#endif // ENABLE_GCODE_VIEWER
m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bmp.bmp());
hsizer->Add(m_logo, 0, wxALIGN_CENTER_VERTICAL);
@ -116,11 +101,7 @@ SysInfoDialog::SysInfoDialog()
// title
{
#if ENABLE_GCODE_VIEWER
wxStaticText* title = new wxStaticText(this, wxID_ANY, wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME, wxDefaultPosition, wxDefaultSize);
#else
wxStaticText* title = new wxStaticText(this, wxID_ANY, SLIC3R_APP_NAME, wxDefaultPosition, wxDefaultSize);
#endif // ENABLE_GCODE_VIEWER
wxFont title_font = wxGetApp().bold_font();
title_font.SetFamily(wxFONTFAMILY_ROMAN);
title_font.SetPointSize(22);

View file

@ -27,6 +27,7 @@
#include <wx/filedlg.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include "wxExtensions.hpp"
#include "PresetComboBoxes.hpp"
#include <wx/wupdlock.h>
@ -1279,7 +1280,9 @@ void Tab::update_preset_description_line()
} else if (parent == nullptr) {
description_line = _(L("Current preset is inherited from the default preset."));
} else {
description_line = _(L("Current preset is inherited from")) + ":\n\t" + parent->name;
std::string name = parent->name;
boost::replace_all(name, "&", "&&");
description_line = _(L("Current preset is inherited from")) + ":\n\t" + from_u8(name);
}
if (preset.is_default || preset.is_system)
@ -1423,6 +1426,8 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Infill"));
optgroup->append_single_option_line("fill_density", category_path + "fill-density");
optgroup->append_single_option_line("fill_pattern", category_path + "fill-pattern");
optgroup->append_single_option_line("infill_anchor", category_path + "fill-pattern");
optgroup->append_single_option_line("infill_anchor_max", category_path + "fill-pattern");
optgroup->append_single_option_line("top_fill_pattern", category_path + "top-fill-pattern");
optgroup->append_single_option_line("bottom_fill_pattern", category_path + "bottom-fill-pattern");
@ -1785,6 +1790,19 @@ void TabFilament::build()
optgroup->append_single_option_line("extrusion_multiplier");
optgroup->append_single_option_line("filament_density");
optgroup->append_single_option_line("filament_cost");
optgroup->append_single_option_line("filament_spool_weight");
optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value)
{
update_dirty();
if (opt_key == "filament_spool_weight") {
// Change of this option influences for an update of "Sliced Info"
wxGetApp().sidebar().update_sliced_info_sizer();
wxGetApp().sidebar().Layout();
}
else
on_value_change(opt_key, value);
};
// optgroup = page->new_optgroup(_(L("Temperature")) + wxString(" °C", wxConvUTF8));
optgroup = page->new_optgroup(L("Temperature"));
@ -2373,13 +2391,11 @@ PageShp TabPrinter::build_kinematics_page()
if (m_use_silent_mode) {
// Legend for OptionsGroups
auto optgroup = page->new_optgroup("");
optgroup->set_show_modified_btns_val(false);
optgroup->label_width = 23;// 230;
auto line = Line{ "", "" };
ConfigOptionDef def;
def.type = coString;
def.width = 15;
def.width = Field::def_width();
def.gui_type = "legend";
def.mode = comAdvanced;
def.tooltip = L("Values in this column are for Normal mode");
@ -3784,7 +3800,7 @@ void Page::activate(ConfigOptionMode mode, std::function<void()> throw_if_cancel
for (auto group : m_optgroups) {
if (!group->activate(throw_if_canceled))
continue;
m_vsizer->Add(group->sizer, 0, wxEXPAND | wxALL, 10);
m_vsizer->Add(group->sizer, 0, wxEXPAND | (group->is_legend_line() ? (wxLEFT|wxTOP) : wxALL), 10);
group->update_visibility(mode);
group->reload_config();
throw_if_canceled();

View file

@ -327,7 +327,7 @@ static void update_parents(ModelNode* node)
void UnsavedChangesModel::UpdateItemEnabling(wxDataViewItem item)
{
assert(item.IsOk());
ModelNode* node = (ModelNode*)item.GetID();
ModelNode* node = static_cast<ModelNode*>(item.GetID());
node->UpdateEnabling();
update_children(node);
@ -337,7 +337,7 @@ void UnsavedChangesModel::UpdateItemEnabling(wxDataViewItem item)
bool UnsavedChangesModel::IsEnabledItem(const wxDataViewItem& item)
{
assert(item.IsOk());
ModelNode* node = (ModelNode*)item.GetID();
ModelNode* node = static_cast<ModelNode*>(item.GetID());
return node->IsToggled();
}
@ -345,7 +345,7 @@ void UnsavedChangesModel::GetValue(wxVariant& variant, const wxDataViewItem& ite
{
assert(item.IsOk());
ModelNode* node = (ModelNode*)item.GetID();
ModelNode* node = static_cast<ModelNode*>(item.GetID());
switch (col)
{
case colToggle:
@ -382,7 +382,7 @@ bool UnsavedChangesModel::SetValue(const wxVariant& variant, const wxDataViewIte
{
assert(item.IsOk());
ModelNode* node = (ModelNode*)item.GetID();
ModelNode* node = static_cast<ModelNode*>(item.GetID());
switch (col)
{
case colToggle:
@ -440,7 +440,7 @@ bool UnsavedChangesModel::IsEnabled(const wxDataViewItem& item, unsigned int col
return true;
// disable unchecked nodes
return ((ModelNode*)item.GetID())->IsToggled();
return (static_cast<ModelNode*>(item.GetID()))->IsToggled();
}
wxDataViewItem UnsavedChangesModel::GetParent(const wxDataViewItem& item) const
@ -449,7 +449,7 @@ wxDataViewItem UnsavedChangesModel::GetParent(const wxDataViewItem& item) const
if (!item.IsOk())
return wxDataViewItem(nullptr);
ModelNode* node = (ModelNode*)item.GetID();
ModelNode* node = static_cast<ModelNode*>(item.GetID());
// "MyMusic" also has no parent
if (node->IsRoot())
@ -464,7 +464,7 @@ bool UnsavedChangesModel::IsContainer(const wxDataViewItem& item) const
if (!item.IsOk())
return true;
ModelNode* node = (ModelNode*)item.GetID();
ModelNode* node = static_cast<ModelNode*>(item.GetID());
return node->IsContainer();
}
@ -522,7 +522,7 @@ void UnsavedChangesModel::Rescale()
//------------------------------------------
UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header)
: DPIDialog((wxWindow*)wxGetApp().mainframe , wxID_ANY, _L("PrusaSlicer is closing: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, _L("PrusaSlicer is closing: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
m_app_config_key = "default_action_on_close_application";
@ -539,7 +539,7 @@ UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header)
}
UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset)
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, _L("Switching Presets: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, _L("Switching Presets: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
m_app_config_key = "default_action_on_select_preset";

View file

@ -448,6 +448,15 @@ Http& Http::auth_digest(const std::string &user, const std::string &password)
return *this;
}
Http& Http::auth_basic(const std::string &user, const std::string &password)
{
curl_easy_setopt(p->curl, CURLOPT_USERNAME, user.c_str());
curl_easy_setopt(p->curl, CURLOPT_PASSWORD, password.c_str());
curl_easy_setopt(p->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
return *this;
}
Http& Http::ca_file(const std::string &name)
{
if (p && priv::ca_file_supported(p->curl)) {

View file

@ -67,6 +67,8 @@ public:
Http& remove_header(std::string name);
// Authorization by HTTP digest, based on RFC2617.
Http& auth_digest(const std::string &user, const std::string &password);
// Basic HTTP authorization
Http& auth_basic(const std::string &user, const std::string &password);
// Sets a CA certificate file for usage with HTTPS. This is only supported on some backends,
// specifically, this is supported with OpenSSL and NOT supported with Windows and OS X native certificate store.
// See also ca_file_supported().