Merge remote-tracking branch 'remotes/origin/master' into tm_relative_correction

This commit is contained in:
bubnikv 2019-04-08 14:00:27 +02:00
commit 0de084df8d
89 changed files with 3808 additions and 2930 deletions

View file

@ -30,6 +30,9 @@ set(SLIC3R_GUI_SOURCES
GUI/GLCanvas3DManager.cpp
GUI/Selection.hpp
GUI/Selection.cpp
GUI/Gizmos/GLGizmos.hpp
GUI/Gizmos/GLGizmosManager.cpp
GUI/Gizmos/GLGizmosManager.hpp
GUI/Gizmos/GLGizmoBase.cpp
GUI/Gizmos/GLGizmoBase.hpp
GUI/Gizmos/GLGizmoMove.cpp

View file

@ -495,11 +495,11 @@ void Bed3D::render_prusa(const std::string &key, bool bottom) const
// use anisotropic filter if graphic card allows
GLfloat max_anisotropy = 0.0f;
if (glewIsSupported("GL_EXT_texture_filter_anisotropic"))
::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy));
// use higher resolution images if graphic card allows
GLint max_tex_size;
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size));
// clamp or the texture generation becomes too slow
max_tex_size = std::min(max_tex_size, 8192);
@ -621,7 +621,6 @@ void Bed3D::render_prusa_shader(bool transparent) const
m_shader.stop_using();
}
}
#else
void Bed3D::render_prusa(const std::string &key, float theta, bool useVBOs) const
{
@ -629,7 +628,7 @@ void Bed3D::render_prusa(const std::string &key, float theta, bool useVBOs) cons
// use higher resolution images if graphic card allows
GLint max_tex_size;
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size));
// temporary set to lowest resolution
max_tex_size = 2048;
@ -644,7 +643,7 @@ void Bed3D::render_prusa(const std::string &key, float theta, bool useVBOs) cons
// use anisotropic filter if graphic card allows
GLfloat max_anisotropy = 0.0f;
if (glewIsSupported("GL_EXT_texture_filter_anisotropic"))
::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy));
std::string filename = tex_path + "_top.png";
if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))

View file

@ -41,6 +41,7 @@ void glAssertRecentCallImpl(const char *file_name, unsigned int line, const char
switch (err) {
case GL_INVALID_ENUM: sErr = "Invalid Enum"; break;
case GL_INVALID_VALUE: sErr = "Invalid Value"; break;
// be aware that GL_INVALID_OPERATION is generated if glGetError is executed between the execution of glBegin and the corresponding execution of glEnd
case GL_INVALID_OPERATION: sErr = "Invalid Operation"; break;
case GL_STACK_OVERFLOW: sErr = "Stack Overflow"; break;
case GL_STACK_UNDERFLOW: sErr = "Stack Underflow"; break;
@ -98,25 +99,25 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs)
if (use_VBOs) {
if (! empty()) {
glsafe(glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
this->vertices_and_normals_interleaved.clear();
}
if (! this->triangle_indices.empty()) {
glsafe(glGenBuffers(1, &this->triangle_indices_VBO_id));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW));
glsafe(::glGenBuffers(1, &this->triangle_indices_VBO_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW));
this->triangle_indices.clear();
}
if (! this->quad_indices.empty()) {
glsafe(glGenBuffers(1, &this->quad_indices_VBO_id));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW));
glsafe(::glGenBuffers(1, &this->quad_indices_VBO_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW));
this->quad_indices.clear();
}
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
this->shrink_to_fit();
}
@ -124,15 +125,15 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs)
void GLIndexedVertexArray::release_geometry()
{
if (this->vertices_and_normals_interleaved_VBO_id) {
glsafe(glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
this->vertices_and_normals_interleaved_VBO_id = 0;
}
if (this->triangle_indices_VBO_id) {
glsafe(glDeleteBuffers(1, &this->triangle_indices_VBO_id));
glsafe(::glDeleteBuffers(1, &this->triangle_indices_VBO_id));
this->triangle_indices_VBO_id = 0;
}
if (this->quad_indices_VBO_id) {
glsafe(glDeleteBuffers(1, &this->quad_indices_VBO_id));
glsafe(::glDeleteBuffers(1, &this->quad_indices_VBO_id));
this->quad_indices_VBO_id = 0;
}
this->clear();
@ -142,42 +143,42 @@ void GLIndexedVertexArray::release_geometry()
void GLIndexedVertexArray::render() const
{
if (this->vertices_and_normals_interleaved_VBO_id) {
glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
} else {
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
}
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (this->indexed()) {
if (this->vertices_and_normals_interleaved_VBO_id) {
// Render using the Vertex Buffer Objects.
if (this->triangle_indices_size > 0) {
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr));
}
if (this->quad_indices_size > 0) {
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(::glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr));
}
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
// Render in an immediate mode.
if (! this->triangle_indices.empty())
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data()));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data()));
if (! this->quad_indices.empty())
glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data()));
glsafe(::glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data()));
}
} else
glsafe(glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6)));
glsafe(::glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6)));
if (this->vertices_and_normals_interleaved_VBO_id)
glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(glDisableClientState(GL_VERTEX_ARRAY));
glsafe(glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
}
void GLIndexedVertexArray::render(
@ -190,35 +191,35 @@ void GLIndexedVertexArray::render(
if (this->vertices_and_normals_interleaved_VBO_id) {
// Render using the Vertex Buffer Objects.
glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (this->triangle_indices_size > 0) {
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
}
if (this->quad_indices_size > 0) {
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(::glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
}
glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
// Render in an immediate mode.
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (! this->triangle_indices.empty())
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first)));
glsafe(::glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first)));
if (! this->quad_indices.empty())
glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first)));
glsafe(::glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first)));
}
glsafe(glDisableClientState(GL_VERTEX_ARRAY));
glsafe(glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
}
const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
@ -736,7 +737,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
typedef std::pair<GLVolume*, double> GLVolumeWithZ;
typedef std::vector<GLVolumeWithZ> GLVolumesWithZList;
static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, std::function<bool(const GLVolume&)> filter_func)
static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func)
{
GLVolumesWithZList list;
list.reserve(volumes.size());
@ -753,12 +754,9 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum
if ((type == GLVolumeCollection::Transparent) && (list.size() > 1))
{
Transform3d modelview_matrix;
glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()));
for (GLVolumeWithZ& volume : list)
{
volume.second = volume.first->bounding_box.transformed(modelview_matrix * volume.first->world_matrix()).max(2);
volume.second = volume.first->bounding_box.transformed(view_matrix * volume.first->world_matrix()).max(2);
}
std::sort(list.begin(), list.end(),
@ -769,7 +767,7 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum
return list;
}
void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface, std::function<bool(const GLVolume&)> filter_func) const
void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func) const
{
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
@ -783,12 +781,13 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
GLint current_program_id;
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id));
GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1;
GLint z_range_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "z_range") : -1;
GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1;
GLint print_box_max_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.max") : -1;
GLint print_box_detection_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1;
GLint print_box_worldmatrix_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1;
GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
GLint z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "z_range") : -1;
GLint print_box_min_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.min") : -1;
GLint print_box_max_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.max") : -1;
GLint print_box_detection_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1;
GLint print_box_worldmatrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1;
glcheck();
if (print_box_min_id != -1)
glsafe(::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min));
@ -799,7 +798,7 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
if (z_range_id != -1)
glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range));
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, filter_func);
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func);
for (GLVolumeWithZ& volume : to_render) {
volume.first->set_render_color();
volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
@ -817,32 +816,32 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
glsafe(::glDisable(GL_BLEND));
}
void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface, std::function<bool(const GLVolume&)> filter_func) const
void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func) const
{
glsafe(glEnable(GL_BLEND));
glsafe(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glsafe(glCullFace(GL_BACK));
glsafe(::glCullFace(GL_BACK));
if (disable_cullface)
glsafe(::glDisable(GL_CULL_FACE));
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, filter_func);
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func);
for (GLVolumeWithZ& volume : to_render)
{
volume.first->set_render_color();
volume.first->render_legacy();
}
glsafe(glDisableClientState(GL_VERTEX_ARRAY));
glsafe(glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (disable_cullface)
glsafe(::glEnable(GL_CULL_FACE));
glsafe(glDisable(GL_BLEND));
glsafe(::glDisable(GL_BLEND));
}
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state)
@ -1771,7 +1770,8 @@ void GLModel::render_VBOs() const
GLint current_program_id;
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id));
GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1;
GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
glcheck();
m_volume.render_VBOs(color_id, -1, -1);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));

View file

@ -19,9 +19,11 @@
extern void glAssertRecentCallImpl(const char *file_name, unsigned int line, const char *function_name);
inline void glAssertRecentCall() { glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); }
#define glsafe(cmd) do { cmd; glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); } while (false)
#define glcheck() do { glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); } while (false)
#else
inline void glAssertRecentCall() { }
#define glsafe(cmd) cmd
#define glcheck()
#endif
namespace Slic3r {
@ -463,8 +465,8 @@ public:
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width);
// Render the volumes by OpenGL.
void render_VBOs(ERenderType type, bool disable_cullface, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
void render_legacy(ERenderType type, bool disable_cullface, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
void render_VBOs(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
void render_legacy(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
// Finalize the initialization of the geometry & indices,
// upload the geometry and indices to OpenGL VBO objects

View file

@ -42,9 +42,7 @@ AboutDialog::AboutDialog()
main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
// logo
// wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG);
// auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png"));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png", 192));
hsizer->Add(logo, 1, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);

View file

@ -98,8 +98,9 @@ void BackgroundSlicingProcess::process_sla()
m_print->process();
if (this->set_step_started(bspsGCodeFinalize)) {
if (! m_export_path.empty()) {
m_sla_print->export_raster(m_export_path);
m_print->set_status(100, "Masked SLA file exported to " + m_export_path);
const std::string export_path = m_sla_print->print_statistics().finalize_output_path(m_export_path);
m_sla_print->export_raster(export_path);
m_print->set_status(100, "Masked SLA file exported to " + export_path);
} else if (! m_upload_job.empty()) {
prepare_upload();
} else {
@ -389,7 +390,7 @@ void BackgroundSlicingProcess::prepare_upload()
// Generate a unique temp path to which the gcode/zip file is copied/exported
boost::filesystem::path source_path = boost::filesystem::temp_directory_path()
/ boost::filesystem::unique_path(".printhost.%%%%-%%%%-%%%%-%%%%.gcode");
/ boost::filesystem::unique_path(".Slic3rPE.upload.%%%%-%%%%-%%%%-%%%%");
if (m_print == m_fff_print) {
m_print->set_status(95, "Running post-processing scripts");
@ -399,8 +400,8 @@ void BackgroundSlicingProcess::prepare_upload()
run_post_process_scripts(source_path.string(), m_fff_print->config());
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
} else {
m_sla_print->export_raster(source_path.string());
// TODO: Also finalize upload path like with FFF when there are statistics for SLA print
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
m_sla_print->export_raster(source_path.string(), m_upload_job.upload_data.upload_path.string());
}
m_print->set_status(100, (boost::format("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue") % m_upload_job.printhost->get_host()).str());

View file

@ -1,5 +1,7 @@
#include "BitmapCache.hpp"
#include "libslic3r/Utils.hpp"
#if ! defined(WIN32) && ! defined(__APPLE__)
#define BROKEN_ALPHA
#endif
@ -9,6 +11,12 @@
#include <wx/rawbmp.h>
#endif /* BROKEN_ALPHA */
#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
#include "GUI_App.hpp"
namespace Slic3r { namespace GUI {
void BitmapCache::clear()
@ -155,8 +163,91 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
#endif
}
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data)
{
wxImage image(width, height);
image.InitAlpha();
unsigned char *rgb = image.GetData();
unsigned char *alpha = image.GetAlpha();
unsigned int pixels = width * height;
for (unsigned int i = 0; i < pixels; ++ i) {
*rgb ++ = *raw_data ++;
*rgb ++ = *raw_data ++;
*rgb ++ = *raw_data ++;
*alpha ++ = *raw_data ++;
}
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
}
wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int width, unsigned int height)
{
std::string bitmap_key = bitmap_name + ( height !=0 ?
"-h" + std::to_string(height) :
"-w" + std::to_string(width));
auto it = m_map.find(bitmap_key);
if (it != m_map.end())
return it->second;
wxImage image;
if (! image.LoadFile(Slic3r::GUI::from_u8(Slic3r::var(bitmap_name + ".png")), wxBITMAP_TYPE_PNG) ||
image.GetWidth() == 0 || image.GetHeight() == 0)
return nullptr;
if (height != 0 && image.GetHeight() != height)
width = int(0.5f + float(image.GetWidth()) * height / image.GetHeight());
else if (width != 0 && image.GetWidth() != width)
height = int(0.5f + float(image.GetHeight()) * width / image.GetWidth());
if (height != 0 && width != 0)
image.Rescale(width, height, wxIMAGE_QUALITY_BILINEAR);
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
}
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int target_width, unsigned int target_height)
{
std::string bitmap_key = bitmap_name + (target_height != 0 ?
"-h" + std::to_string(target_height) :
"-w" + std::to_string(target_width));
auto it = m_map.find(bitmap_key);
if (it != m_map.end())
return it->second;
NSVGimage *image = ::nsvgParseFromFile(Slic3r::var(bitmap_name + ".svg").c_str(), "px", 96.0f);
if (image == nullptr)
return nullptr;
float scale = target_height != 0 ?
(float)target_height / image->height : target_width != 0 ?
(float)target_width / image->width : 1;
int width = (int)(scale * image->width + 0.5f);
int height = (int)(scale * image->height + 0.5f);
int n_pixels = width * height;
if (n_pixels <= 0) {
::nsvgDelete(image);
return nullptr;
}
NSVGrasterizer *rast = ::nsvgCreateRasterizer();
if (rast == nullptr) {
::nsvgDelete(image);
return nullptr;
}
std::vector<unsigned char> data(n_pixels * 4, 0);
::nsvgRasterize(rast, image, 0, 0, scale, data.data(), width, height, width * 4);
::nsvgDeleteRasterizer(rast);
::nsvgDelete(image);
return this->insert_raw_rgba(bitmap_key, width, height, data.data());
}
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency)
{
width = width * 0.1f * Slic3r::GUI::wxGetApp().em_unit() + 0.5f;
height = height * 0.1f * Slic3r::GUI::wxGetApp().em_unit() + 0.5f;
wxImage image(width, height);
image.InitAlpha();
unsigned char* imgdata = image.GetData();

View file

@ -29,6 +29,12 @@ public:
wxBitmap* insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3);
wxBitmap* insert(const std::string &name, const std::vector<wxBitmap> &bmps) { return this->insert(name, &bmps.front(), &bmps.front() + bmps.size()); }
wxBitmap* insert(const std::string &name, const wxBitmap *begin, const wxBitmap *end);
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data);
// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
wxBitmap* load_png(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0);
// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
wxBitmap* load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0);
static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency);
static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }

View file

@ -1,9 +1,21 @@
#include "libslic3r/libslic3r.h"
#include "Camera.hpp"
#include "3DScene.hpp"
#include <GL/glew.h>
static const float GIMBALL_LOCK_THETA_MAX = 180.0f;
// phi / theta angles to orient the camera.
static const float VIEW_DEFAULT[2] = { 45.0f, 45.0f };
static const float VIEW_LEFT[2] = { 90.0f, 90.0f };
static const float VIEW_RIGHT[2] = { -90.0f, 90.0f };
static const float VIEW_TOP[2] = { 0.0f, 0.0f };
static const float VIEW_BOTTOM[2] = { 0.0f, 180.0f };
static const float VIEW_FRONT[2] = { 0.0f, 90.0f };
static const float VIEW_REAR[2] = { 180.0f, 90.0f };
namespace Slic3r {
namespace GUI {
@ -57,6 +69,64 @@ void Camera::set_scene_box(const BoundingBoxf3& box)
m_scene_box = box;
}
bool Camera::select_view(const std::string& direction)
{
const float* dir_vec = nullptr;
if (direction == "iso")
dir_vec = VIEW_DEFAULT;
else if (direction == "left")
dir_vec = VIEW_LEFT;
else if (direction == "right")
dir_vec = VIEW_RIGHT;
else if (direction == "top")
dir_vec = VIEW_TOP;
else if (direction == "bottom")
dir_vec = VIEW_BOTTOM;
else if (direction == "front")
dir_vec = VIEW_FRONT;
else if (direction == "rear")
dir_vec = VIEW_REAR;
if (dir_vec != nullptr)
{
phi = dir_vec[0];
set_theta(dir_vec[1], false);
return true;
}
else
return false;
}
void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) const
{
glsafe(::glViewport(0, 0, w, h));
glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data()));
}
void Camera::apply_view_matrix() const
{
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glLoadIdentity());
glsafe(::glRotatef(-m_theta, 1.0f, 0.0f, 0.0f)); // pitch
glsafe(::glRotatef(phi, 0.0f, 0.0f, 1.0f)); // yaw
glsafe(::glTranslated(-m_target(0), -m_target(1), -m_target(2)));
glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, m_view_matrix.data()));
}
void Camera::apply_ortho_projection(float x_min, float x_max, float y_min, float y_max, float z_min, float z_max) const
{
glsafe(::glMatrixMode(GL_PROJECTION));
glsafe(::glLoadIdentity());
glsafe(::glOrtho(x_min, x_max, y_min, y_max, z_min, z_max));
glsafe(::glGetDoublev(GL_PROJECTION_MATRIX, m_projection_matrix.data()));
glsafe(::glMatrixMode(GL_MODELVIEW));
}
} // GUI
} // Slic3r

View file

@ -2,6 +2,7 @@
#define slic3r_Camera_hpp_
#include "libslic3r/BoundingBox.hpp"
#include <array>
namespace Slic3r {
namespace GUI {
@ -26,6 +27,10 @@ private:
Vec3d m_target;
float m_theta;
mutable std::array<int, 4> m_viewport;
mutable Transform3d m_view_matrix;
mutable Transform3d m_projection_matrix;
BoundingBoxf3 m_scene_box;
public:
@ -41,6 +46,22 @@ public:
const BoundingBoxf3& get_scene_box() const { return m_scene_box; }
void set_scene_box(const BoundingBoxf3& box);
bool select_view(const std::string& direction);
const std::array<int, 4>& get_viewport() const { return m_viewport; }
const Transform3d& get_view_matrix() const { return m_view_matrix; }
const Transform3d& get_projection_matrix() const { return m_projection_matrix; }
Vec3d get_dir_right() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(0); }
Vec3d get_dir_up() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(1); }
Vec3d get_dir_forward() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(2); }
Vec3d get_position() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(3); }
void apply_viewport(int x, int y, unsigned int w, unsigned int h) const;
void apply_view_matrix() const;
void apply_ortho_projection(float x_min, float x_max, float y_min, float y_max, float z_min, float z_max) const;
};
} // GUI

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@
#include "3DBed.hpp"
#include "Camera.hpp"
#include "Selection.hpp"
#include "Gizmos/GLGizmosManager.hpp"
#include <float.h>
@ -64,33 +65,6 @@ public:
void set_scale_factor(int height);
};
class Rect
{
float m_left;
float m_top;
float m_right;
float m_bottom;
public:
Rect();
Rect(float left, float top, float right, float bottom);
float get_left() const;
void set_left(float left);
float get_top() const;
void set_top(float top);
float get_right() const;
void set_right(float right);
float get_bottom() const;
void set_bottom(float bottom);
float get_width() const { return m_right - m_left; }
float get_height() const { return m_top - m_bottom; }
};
wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
using Vec2dEvent = Event<Vec2d>;
@ -118,22 +92,6 @@ wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent);
// this describes events being passed from GLCanvas3D to SlaSupport gizmo
enum class SLAGizmoEventType {
LeftDown = 1,
LeftUp,
RightDown,
Dragging,
Delete,
SelectAll,
ShiftUp,
ApplyChanges,
DiscardChanges,
AutomaticGeneration,
ManualEditing
};
class GLCanvas3D
{
struct GCodePreviewVolumeIndex
@ -314,7 +272,6 @@ class GLCanvas3D
Vec2d position;
Vec3d scene_position;
Drag drag;
bool ignore_up_event;
Mouse();
@ -358,118 +315,6 @@ public:
};
private:
class Gizmos
{
public:
#if ENABLE_SVG_ICONS
static const float Default_Icons_Size;
#endif // ENABLE_SVG_ICONS
enum EType : unsigned char
{
Undefined,
Move,
Scale,
Rotate,
Flatten,
Cut,
SlaSupports,
Num_Types
};
private:
bool m_enabled;
typedef std::map<EType, GLGizmoBase*> GizmosMap;
GizmosMap m_gizmos;
#if ENABLE_SVG_ICONS
mutable GLTexture m_icons_texture;
mutable bool m_icons_texture_dirty;
#else
ItemsIconsTexture m_icons_texture;
#endif // ENABLE_SVG_ICONS
BackgroundTexture m_background_texture;
EType m_current;
#if ENABLE_SVG_ICONS
float m_overlay_icons_size;
float m_overlay_scale;
#else
float m_overlay_icons_scale;
#endif // ENABLE_SVG_ICONS
float m_overlay_border;
float m_overlay_gap_y;
public:
Gizmos();
~Gizmos();
bool init(GLCanvas3D& parent);
bool is_enabled() const;
void set_enabled(bool enable);
#if ENABLE_SVG_ICONS
void set_overlay_icon_size(float size);
#endif // ENABLE_SVG_ICONS
void set_overlay_scale(float scale);
std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
void update_on_off_state(const Selection& selection);
void reset_all_states();
void set_hover_id(int id);
void enable_grabber(EType type, unsigned int id, bool enable);
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
bool grabber_contains_mouse() const;
void update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos = nullptr);
Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
EType get_current_type() const;
bool is_running() const;
bool handle_shortcut(int key, const Selection& selection);
bool is_dragging() const;
void start_dragging(const Selection& selection);
void stop_dragging();
Vec3d get_displacement() const;
Vec3d get_scale() const;
void set_scale(const Vec3d& scale);
Vec3d get_rotation() const;
void set_rotation(const Vec3d& rotation);
Vec3d get_flattening_normal() const;
void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
void render_current_gizmo(const Selection& selection) const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const;
void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
private:
void reset();
void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
void do_render_current_gizmo(const Selection& selection) const;
float get_total_overlay_height() const;
float get_total_overlay_width() const;
GLGizmoBase* get_current() const;
#if ENABLE_SVG_ICONS
bool generate_icons_texture() const;
#endif // ENABLE_SVG_ICONS
};
struct SlaCap
{
struct Triangles
@ -557,7 +402,7 @@ private:
LayersEditing m_layers_editing;
Shader m_shader;
Mouse m_mouse;
mutable Gizmos m_gizmos;
mutable GLGizmosManager m_gizmos;
mutable GLToolbar m_toolbar;
ClippingPlane m_clipping_planes[2];
bool m_use_clipping_planes;
@ -639,7 +484,7 @@ public:
void set_color_by(const std::string& value);
float get_camera_zoom() const;
const Camera& get_camera() const { return m_camera; }
BoundingBoxf3 volumes_bounding_box() const;
BoundingBoxf3 scene_bounding_box() const;
@ -721,6 +566,19 @@ public:
void update_ui_from_settings();
float get_view_toolbar_height() const { return m_view_toolbar.get_height(); }
int get_move_volume_id() const { return m_mouse.drag.move_volume_idx; }
int get_hover_volume_id() const { return m_hover_volume_id; }
// Returns the view ray line, in world coordinate, at the given mouse position.
Linef3 mouse_ray(const Point& mouse_pos);
void set_mouse_as_dragging() { m_mouse.dragging = true; }
void disable_regenerate_volumes() { m_regenerate_volumes = false; }
void refresh_camera_scene_box() { m_camera.set_scene_box(scene_bounding_box()); }
bool is_mouse_dragging() const { return m_mouse.dragging; }
private:
bool _is_shown_on_screen() const;
@ -736,7 +594,6 @@ private:
void _refresh_if_shown_on_screen();
void _camera_tranform() const;
void _picking_pass() const;
void _render_background() const;
void _render_bed(float theta) const;
@ -760,7 +617,6 @@ private:
void _render_selection_sidebar_hints() const;
void _update_volumes_hover_state() const;
void _update_gizmos_data();
void _perform_layer_editing_action(wxMouseEvent* evt = nullptr);
@ -771,9 +627,6 @@ private:
// Convert the screen space coordinate to world coordinate on the bed.
Vec3d _mouse_to_bed_3d(const Point& mouse_pos);
// Returns the view ray line, in world coordinate, at the given mouse position.
Linef3 mouse_ray(const Point& mouse_pos);
void _start_timer();
void _stop_timer();

View file

@ -3,6 +3,7 @@
#include "GLShader.hpp"
#include "libslic3r/Utils.hpp"
#include "3DScene.hpp"
#include <boost/nowide/fstream.hpp>
#include <string>
@ -52,21 +53,22 @@ bool GLShader::load_from_text(const char *fragment_shader, const char *vertex_sh
}
if (fragment_shader != nullptr) {
this->fragment_program_id = glCreateShader(GL_FRAGMENT_SHADER);
this->fragment_program_id = ::glCreateShader(GL_FRAGMENT_SHADER);
glcheck();
if (this->fragment_program_id == 0) {
last_error = "glCreateShader(GL_FRAGMENT_SHADER) failed.";
return false;
}
GLint len = (GLint)strlen(fragment_shader);
glShaderSource(this->fragment_program_id, 1, &fragment_shader, &len);
glCompileShader(this->fragment_program_id);
glsafe(::glShaderSource(this->fragment_program_id, 1, &fragment_shader, &len));
glsafe(::glCompileShader(this->fragment_program_id));
GLint params;
glGetShaderiv(this->fragment_program_id, GL_COMPILE_STATUS, &params);
glsafe(::glGetShaderiv(this->fragment_program_id, GL_COMPILE_STATUS, &params));
if (params == GL_FALSE) {
// Compilation failed. Get the log.
glGetShaderiv(this->fragment_program_id, GL_INFO_LOG_LENGTH, &params);
glsafe(::glGetShaderiv(this->fragment_program_id, GL_INFO_LOG_LENGTH, &params));
std::vector<char> msg(params);
glGetShaderInfoLog(this->fragment_program_id, params, &params, msg.data());
glsafe(::glGetShaderInfoLog(this->fragment_program_id, params, &params, msg.data()));
this->last_error = std::string("Fragment shader compilation failed:\n") + msg.data();
this->release();
return false;
@ -74,22 +76,23 @@ bool GLShader::load_from_text(const char *fragment_shader, const char *vertex_sh
}
if (vertex_shader != nullptr) {
this->vertex_program_id = glCreateShader(GL_VERTEX_SHADER);
this->vertex_program_id = ::glCreateShader(GL_VERTEX_SHADER);
glcheck();
if (this->vertex_program_id == 0) {
last_error = "glCreateShader(GL_VERTEX_SHADER) failed.";
this->release();
return false;
}
GLint len = (GLint)strlen(vertex_shader);
glShaderSource(this->vertex_program_id, 1, &vertex_shader, &len);
glCompileShader(this->vertex_program_id);
glsafe(::glShaderSource(this->vertex_program_id, 1, &vertex_shader, &len));
glsafe(::glCompileShader(this->vertex_program_id));
GLint params;
glGetShaderiv(this->vertex_program_id, GL_COMPILE_STATUS, &params);
glsafe(::glGetShaderiv(this->vertex_program_id, GL_COMPILE_STATUS, &params));
if (params == GL_FALSE) {
// Compilation failed. Get the log.
glGetShaderiv(this->vertex_program_id, GL_INFO_LOG_LENGTH, &params);
glsafe(::glGetShaderiv(this->vertex_program_id, GL_INFO_LOG_LENGTH, &params));
std::vector<char> msg(params);
glGetShaderInfoLog(this->vertex_program_id, params, &params, msg.data());
glsafe(::glGetShaderInfoLog(this->vertex_program_id, params, &params, msg.data()));
this->last_error = std::string("Vertex shader compilation failed:\n") + msg.data();
this->release();
return false;
@ -97,7 +100,8 @@ bool GLShader::load_from_text(const char *fragment_shader, const char *vertex_sh
}
// Link shaders
this->shader_program_id = glCreateProgram();
this->shader_program_id = ::glCreateProgram();
glcheck();
if (this->shader_program_id == 0) {
last_error = "glCreateProgram() failed.";
this->release();
@ -105,18 +109,18 @@ bool GLShader::load_from_text(const char *fragment_shader, const char *vertex_sh
}
if (this->fragment_program_id)
glAttachShader(this->shader_program_id, this->fragment_program_id);
glsafe(::glAttachShader(this->shader_program_id, this->fragment_program_id));
if (this->vertex_program_id)
glAttachShader(this->shader_program_id, this->vertex_program_id);
glLinkProgram(this->shader_program_id);
glsafe(::glAttachShader(this->shader_program_id, this->vertex_program_id));
glsafe(::glLinkProgram(this->shader_program_id));
GLint params;
glGetProgramiv(this->shader_program_id, GL_LINK_STATUS, &params);
glsafe(::glGetProgramiv(this->shader_program_id, GL_LINK_STATUS, &params));
if (params == GL_FALSE) {
// Linking failed. Get the log.
glGetProgramiv(this->vertex_program_id, GL_INFO_LOG_LENGTH, &params);
glsafe(::glGetProgramiv(this->vertex_program_id, GL_INFO_LOG_LENGTH, &params));
std::vector<char> msg(params);
glGetProgramInfoLog(this->vertex_program_id, params, &params, msg.data());
glsafe(::glGetProgramInfoLog(this->vertex_program_id, params, &params, msg.data()));
this->last_error = std::string("Shader linking failed:\n") + msg.data();
this->release();
return false;
@ -165,31 +169,31 @@ void GLShader::release()
{
if (this->shader_program_id) {
if (this->vertex_program_id)
glDetachShader(this->shader_program_id, this->vertex_program_id);
glsafe(::glDetachShader(this->shader_program_id, this->vertex_program_id));
if (this->fragment_program_id)
glDetachShader(this->shader_program_id, this->fragment_program_id);
glDeleteProgram(this->shader_program_id);
glsafe(::glDetachShader(this->shader_program_id, this->fragment_program_id));
glsafe(::glDeleteProgram(this->shader_program_id));
this->shader_program_id = 0;
}
if (this->vertex_program_id) {
glDeleteShader(this->vertex_program_id);
glsafe(::glDeleteShader(this->vertex_program_id));
this->vertex_program_id = 0;
}
if (this->fragment_program_id) {
glDeleteShader(this->fragment_program_id);
glsafe(::glDeleteShader(this->fragment_program_id));
this->fragment_program_id = 0;
}
}
void GLShader::enable() const
{
glUseProgram(this->shader_program_id);
glsafe(::glUseProgram(this->shader_program_id));
}
void GLShader::disable() const
{
glUseProgram(0);
glsafe(::glUseProgram(0));
}
// Return shader vertex attribute ID
@ -208,7 +212,7 @@ bool GLShader::set_uniform(const char *name, float value) const
{
int id = this->get_uniform_location(name);
if (id >= 0) {
glUniform1fARB(id, value);
glsafe(::glUniform1fARB(id, value));
return true;
}
return false;
@ -219,7 +223,7 @@ bool GLShader::set_uniform(const char* name, const float* matrix) const
int id = get_uniform_location(name);
if (id >= 0)
{
::glUniformMatrix4fv(id, 1, GL_FALSE, (const GLfloat*)matrix);
glsafe(::glUniformMatrix4fv(id, 1, GL_FALSE, (const GLfloat*)matrix));
return true;
}
return false;
@ -230,7 +234,7 @@ bool GLShader::set_uniform(const char* name, int value) const
int id = get_uniform_location(name);
if (id >= 0)
{
::glUniform1i(id, value);
glsafe(::glUniform1i(id, value));
return true;
}
return false;

View file

@ -1,6 +1,8 @@
#include "libslic3r/libslic3r.h"
#include "GLTexture.hpp"
#include "3DScene.hpp"
#include <GL/glew.h>
#include <wx/image.h>
@ -11,15 +13,11 @@
#include <vector>
#include <algorithm>
#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
#include "libslic3r/Utils.hpp"
#include "libslic3r/Utils.hpp"
namespace Slic3r {
namespace GUI {
@ -177,15 +175,15 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
nsvgDeleteRasterizer(rast);
// sends data to gpu
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glGenTextures(1, &m_id);
::glBindTexture(GL_TEXTURE_2D, m_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_id));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
::glBindTexture(GL_TEXTURE_2D, 0);
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
m_source = filenames.front();
@ -218,7 +216,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
void GLTexture::reset()
{
if (m_id != 0)
::glDeleteTextures(1, &m_id);
glsafe(::glDeleteTextures(1, &m_id));
m_id = 0;
m_width = 0;
@ -233,25 +231,25 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo
void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const GLTexture::Quad_UVs& uvs)
{
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
::glEnable(GL_TEXTURE_2D);
::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glsafe(::glEnable(GL_TEXTURE_2D));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id);
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id));
::glBegin(GL_QUADS);
::glTexCoord2f(uvs.left_bottom.u, uvs.left_bottom.v); ::glVertex2f(left, bottom);
::glTexCoord2f(uvs.right_bottom.u, uvs.right_bottom.v); ::glVertex2f(right, bottom);
::glTexCoord2f(uvs.right_top.u, uvs.right_top.v); ::glVertex2f(right, top);
::glTexCoord2f(uvs.left_top.u, uvs.left_top.v); ::glVertex2f(left, top);
::glEnd();
glsafe(::glEnd());
::glBindTexture(GL_TEXTURE_2D, 0);
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
::glDisable(GL_TEXTURE_2D);
::glDisable(GL_BLEND);
glsafe(::glDisable(GL_TEXTURE_2D));
glsafe(::glDisable(GL_BLEND));
}
unsigned int GLTexture::generate_mipmaps(wxImage& image)
@ -286,7 +284,7 @@ unsigned int GLTexture::generate_mipmaps(wxImage& image)
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
}
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
}
return (unsigned int)level;
@ -334,25 +332,25 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps)
}
// sends data to gpu
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glGenTextures(1, &m_id);
::glBindTexture(GL_TEXTURE_2D, m_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_id));
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)
{
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
unsigned int levels_count = generate_mipmaps(image);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels_count);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels_count));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
}
else
{
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
}
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
::glBindTexture(GL_TEXTURE_2D, 0);
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
m_source = filename;
@ -378,6 +376,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
if (n_pixels <= 0)
{
reset();
nsvgDelete(image);
return false;
}
@ -395,10 +394,10 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
nsvgRasterize(rast, image, 0, 0, scale, data.data(), m_width, m_height, m_width * 4);
// sends data to gpu
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glGenTextures(1, &m_id);
::glBindTexture(GL_TEXTURE_2D, m_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_id));
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)
{
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
@ -414,20 +413,20 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
scale /= 2.0f;
nsvgRasterize(rast, image, 0, 0, scale, data.data(), lod_w, lod_h, lod_w * 4);
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
}
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
}
else
{
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
}
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
::glBindTexture(GL_TEXTURE_2D, 0);
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
m_source = filename;

View file

@ -388,10 +388,10 @@ void GLToolbar::render(const GLCanvas3D& parent) const
generate_icons_texture();
#endif // ENABLE_SVG_ICONS
::glDisable(GL_DEPTH_TEST);
glsafe(::glDisable(GL_DEPTH_TEST));
::glPushMatrix();
::glLoadIdentity();
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
switch (m_layout.type)
{
@ -400,7 +400,7 @@ void GLToolbar::render(const GLCanvas3D& parent) const
case Layout::Vertical: { render_vertical(parent); break; }
}
::glPopMatrix();
glsafe(::glPopMatrix());
}
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
@ -444,11 +444,11 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
{
m_mouse_capture.left = true;
m_mouse_capture.parent = &parent;
processed = true;
if ((item_id != -2) && !m_items[item_id]->is_separator())
{
// mouse is inside an icon
do_action((unsigned int)item_id, parent);
processed = true;
}
}
else if (evt.MiddleDown())
@ -612,7 +612,7 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
{
// NB: mouse_pos is already scaled appropriately
float zoom = parent.get_camera_zoom();
float zoom = parent.get_camera().zoom;
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
#if ENABLE_SVG_ICONS
float factor = m_layout.scale * inv_zoom;
@ -717,7 +717,7 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
{
// NB: mouse_pos is already scaled appropriately
float zoom = parent.get_camera_zoom();
float zoom = parent.get_camera().zoom;
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
#if ENABLE_SVG_ICONS
float factor = m_layout.scale * inv_zoom;
@ -834,7 +834,7 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
{
// NB: mouse_pos is already scaled appropriately
float zoom = parent.get_camera_zoom();
float zoom = parent.get_camera().zoom;
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
#if ENABLE_SVG_ICONS
float factor = m_layout.scale * inv_zoom;
@ -917,7 +917,7 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
{
// NB: mouse_pos is already scaled appropriately
float zoom = parent.get_camera_zoom();
float zoom = parent.get_camera().zoom;
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
#if ENABLE_SVG_ICONS
float factor = m_layout.scale * inv_zoom;
@ -1013,7 +1013,7 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
return;
#endif // !ENABLE_SVG_ICONS
float zoom = parent.get_camera_zoom();
float zoom = parent.get_camera().zoom;
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
#if ENABLE_SVG_ICONS
float factor = inv_zoom * m_layout.scale;
@ -1168,7 +1168,7 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const
return;
#endif // !ENABLE_SVG_ICONS
float zoom = parent.get_camera_zoom();
float zoom = parent.get_camera().zoom;
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
#if ENABLE_SVG_ICONS
float factor = inv_zoom * m_layout.scale;

View file

@ -7,6 +7,7 @@
#include "GLTexture.hpp"
#include "Event.hpp"
#include "libslic3r/Point.hpp"
class wxEvtHandler;

View file

@ -76,6 +76,24 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
static void register_dpi_event()
{
#ifdef WIN32
enum { WM_DPICHANGED_ = 0x02e0 };
wxWindow::MSWRegisterMessageHandler(WM_DPICHANGED_, [](wxWindow *win, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) {
const int dpi = wParam & 0xffff;
const auto rect = reinterpret_cast<PRECT>(lParam);
const wxRect wxrect(wxPoint(rect->top, rect->left), wxPoint(rect->bottom, rect->right));
DpiChangedEvent evt(EVT_DPI_CHANGED, dpi, wxrect);
win->GetEventHandler()->AddPendingEvent(evt);
return true;
});
#endif
}
IMPLEMENT_APP(GUI_App)
GUI_App::GUI_App()
@ -149,6 +167,8 @@ bool GUI_App::OnInit()
show_error(nullptr, ex.what());
}
register_dpi_event();
// Let the libslic3r know the callback, which will translate messages on demand.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);

View file

@ -62,18 +62,18 @@ ObjectList::ObjectList(wxWindow* parent) :
// Fill CATEGORY_ICON
{
// ptFFF
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers.png"); // wxBitmap(from_u8(var("layers.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill.png"); // wxBitmap(from_u8(var("infill.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("building.png"); // wxBitmap(from_u8(var("building.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time.png"); // wxBitmap(from_u8(var("time.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel.png"); // wxBitmap(from_u8(var("funnel.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap("funnel.png"); // wxBitmap(from_u8(var("funnel.png")), wxBITMAP_TYPE_PNG);
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap("box.png"); // wxBitmap(from_u8(var("box.png")), wxBITMAP_TYPE_PNG);
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap("time.png"); // wxBitmap(from_u8(var("time.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap("wand.png"); // wxBitmap(from_u8(var("wand.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers");
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill");
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("support");
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time");
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel");
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap("funnel");
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap("skirt+brim");
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap("time");
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap("wrench");
// ptSLA
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap("building.png"); // wxBitmap(from_u8(var("building.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap("brick.png"); // wxBitmap(from_u8(var("brick.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap("sla_supports");
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap("brick.png");
}
// create control
@ -82,13 +82,35 @@ ObjectList::ObjectList(wxWindow* parent) :
init_icons();
// describe control behavior
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) {
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent& event) {
#ifndef __APPLE__
// On Windows and Linux, forces a kill focus emulation on the object manipulator fields because this event handler is called
// before the kill focus event handler on the object manipulator when changing selection in the list, invalidating the object
// manipulator cache with the following call to selection_changed()
wxGetApp().obj_manipul()->emulate_kill_focus();
// To avoid selection update from SetSelection() and UnselectAll() under osx
if (m_prevent_list_events)
return;
#endif // __APPLE__
/* For multiple selection with pressed SHIFT,
* event.GetItem() returns value of a first item in selection list
* instead of real last clicked item.
* So, let check last selected item in such strange way
*/
if (wxGetKeyState(WXK_SHIFT))
{
wxDataViewItemArray sels;
GetSelections(sels);
if (sels.front() == m_last_selected_item)
m_last_selected_item = sels.back();
else
m_last_selected_item = event.GetItem();
}
else
m_last_selected_item = event.GetItem();
selection_changed();
#ifndef __WXMSW__
set_tooltip_for_item(get_mouse_position_in_control());
@ -368,13 +390,6 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const
void ObjectList::init_icons()
{
// m_bmp_modifiermesh = wxBitmap(from_u8(var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
// m_bmp_solidmesh = wxBitmap(from_u8(var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
// m_bmp_support_enforcer = wxBitmap(from_u8(var("support_enforcer_.png")), wxBITMAP_TYPE_PNG);
// m_bmp_support_blocker = wxBitmap(from_u8(var("support_blocker_.png")), wxBITMAP_TYPE_PNG);
m_bmp_modifiermesh = create_scaled_bitmap("lambda.png");
m_bmp_solidmesh = create_scaled_bitmap("object.png");
m_bmp_support_enforcer = create_scaled_bitmap("support_enforcer_.png");
@ -389,16 +404,13 @@ void ObjectList::init_icons()
m_objects_model->SetVolumeBitmaps(m_bmp_vector);
// init icon for manifold warning
// m_bmp_manifold_warning = wxBitmap(from_u8(var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
m_bmp_manifold_warning = create_scaled_bitmap("exclamation_mark_.png");
// init bitmap for "Split to sub-objects" context menu
// m_bmp_split = wxBitmap(from_u8(var("split.png")), wxBITMAP_TYPE_PNG);
m_bmp_split = create_scaled_bitmap("split.png");
m_bmp_split = create_scaled_bitmap("split_parts");
// init bitmap for "Add Settings" context menu
// m_bmp_cog = wxBitmap(from_u8(var("cog.png")), wxBITMAP_TYPE_PNG);
m_bmp_cog = create_scaled_bitmap("cog.png");
m_bmp_cog = create_scaled_bitmap("cog");
}
@ -509,7 +521,7 @@ void ObjectList::key_event(wxKeyEvent& event)
) {
remove();
}
else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_SHIFT))
else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/))
select_item_all_children();
else
event.Skip();
@ -1005,8 +1017,7 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu)
void ObjectList::append_menu_items_osx(wxMenu* menu)
{
append_menu_item(menu, wxID_ANY, _(L("Delete item")), "",
[this](wxCommandEvent&) { remove(); }, "", menu);
append_menu_item_delete(menu);
append_menu_item(menu, wxID_ANY, _(L("Rename")), "",
[this](wxCommandEvent&) { rename_item(); }, "", menu);
@ -1025,7 +1036,7 @@ void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu)
void ObjectList::append_menu_item_export_stl(wxMenu* menu) const
{
append_menu_item(menu, wxID_ANY, _(L("Export object as STL")) + dots, "",
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, "",
[](wxCommandEvent&) { wxGetApp().plater()->export_stl(true); }, "", menu);
menu->AppendSeparator();
}
@ -1061,6 +1072,12 @@ void ObjectList::append_menu_item_change_extruder(wxMenu* menu) const
}
}
void ObjectList::append_menu_item_delete(wxMenu* menu)
{
append_menu_item(menu, wxID_ANY, _(L("Delete")), "",
[this](wxCommandEvent&) { remove(); }, "", menu);
}
void ObjectList::create_object_popupmenu(wxMenu *menu)
{
#ifdef __WXOSX__
@ -1101,6 +1118,7 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
#endif // __WXOSX__
append_menu_item_fix_through_netfabb(menu);
append_menu_item_export_stl(menu);
m_menu_item_split_part = append_menu_item_split(menu);
@ -1117,10 +1135,21 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
void ObjectList::create_instance_popupmenu(wxMenu*menu)
{
#ifdef __WXOSX__
append_menu_item_delete(menu);
#endif // __WXOSX__
m_menu_item_split_instances = append_menu_item_instance_to_object(menu);
/* New behavior logic:
* 1. Split Object to several separated object, if ALL instances are selected
* 2. Separate selected instances from the initial object to the separated object,
* if some (not all) instances are selected
*/
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
// evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
evt.SetText(wxGetApp().plater()->canvas3D()->get_selection().is_single_full_object() ?
_(L("Set as a Separated Objects")) : _(L("Set as a Separated Object")));
}, m_menu_item_split_instances->GetId());
}
wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
@ -1551,7 +1580,7 @@ void ObjectList::split()
auto opt_keys = model_object->volumes[id]->config.keys();
if ( !(opt_keys.size() == 1 && opt_keys[0] == "extruder") ) {
select_item(m_objects_model->AddSettingsChild(vol_item));
Collapse(vol_item);
/*Collapse*/Expand(vol_item);
}
}
@ -1638,16 +1667,20 @@ void ObjectList::part_selection_changed()
bool update_and_show_manipulations = false;
bool update_and_show_settings = false;
if (multiple_selection()) {
const auto item = GetSelection();
if ( multiple_selection() || item && m_objects_model->GetItemType(item) == itInstanceRoot )
{
og_name = _(L("Group manipulation"));
update_and_show_manipulations = true;
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
// don't show manipulation panel for case of all Object's parts selection
update_and_show_manipulations = !selection.is_single_full_instance();
}
else
{
const auto item = GetSelection();
if (item)
{
bool is_part = false;
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
obj_idx = m_objects_model->GetIdByItem(item);
og_name = _(L("Object manipulation"));
@ -1665,7 +1698,6 @@ void ObjectList::part_selection_changed()
}
else {
og_name = _(L("Part Settings to modify"));
is_part = true;
auto main_parent = m_objects_model->GetParent(parent);
obj_idx = m_objects_model->GetIdByItem(main_parent);
const auto volume_id = m_objects_model->GetVolumeIdByItem(parent);
@ -1675,7 +1707,6 @@ void ObjectList::part_selection_changed()
}
else if (m_objects_model->GetItemType(item) == itVolume) {
og_name = _(L("Part manipulation"));
is_part = true;
const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
update_and_show_manipulations = true;
@ -1743,7 +1774,7 @@ void ObjectList::add_object_to_list(size_t obj_idx)
auto opt_keys = model_object->volumes[id]->config.keys();
if (!opt_keys.empty() && !(opt_keys.size() == 1 && opt_keys[0] == "extruder")) {
select_item(m_objects_model->AddSettingsChild(vol_item));
Collapse(vol_item);
/*Collapse*/Expand(vol_item);
}
}
Expand(item);
@ -1757,7 +1788,7 @@ void ObjectList::add_object_to_list(size_t obj_idx)
auto opt_keys = model_object->config.keys();
if (!opt_keys.empty() && !(opt_keys.size() == 1 && opt_keys[0] == "extruder")) {
select_item(m_objects_model->AddSettingsChild(item));
Collapse(item);
/*Collapse*/Expand(item);
}
#ifndef __WXOSX__
@ -1923,11 +1954,22 @@ bool ObjectList::multiple_selection() const
return GetSelectedItemsCount() > 1;
}
bool ObjectList::is_selected(const ItemType type) const
{
const wxDataViewItem& item = GetSelection();
if (item)
return m_objects_model->GetItemType(item) == type;
return false;
}
void ObjectList::update_selections()
{
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
wxDataViewItemArray sels;
m_selection_mode = smInstance;
// We doesn't update selection if SettingsItem for the current object/part is selected
if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) == itSettings )
{
@ -1941,32 +1983,56 @@ void ObjectList::update_selections()
return;
}
}
if (selection.is_single_full_object())
else if (selection.is_single_full_object() || selection.is_multiple_full_object())
{
sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
const Selection::ObjectIdxsToInstanceIdxsMap& objects_content = selection.get_content();
for (const auto& object : objects_content) {
if (object.second.size() == 1) // object with 1 instance
sels.Add(m_objects_model->GetItemById(object.first));
else if (object.second.size() > 1) // object with several instances
{
wxDataViewItemArray current_sels;
GetSelections(current_sels);
const wxDataViewItem frst_inst_item = m_objects_model->GetItemByInstanceId(object.first, 0);
bool root_is_selected = false;
for (const auto& item:current_sels)
if (item == m_objects_model->GetParent(frst_inst_item) ||
item == m_objects_model->GetTopParent(frst_inst_item)) {
root_is_selected = true;
sels.Add(item);
break;
}
if (root_is_selected)
continue;
const Selection::InstanceIdxsList& instances = object.second;
for (const auto& inst : instances)
sels.Add(m_objects_model->GetItemByInstanceId(object.first, inst));
}
}
}
else if (selection.is_single_volume() || selection.is_modifier() ||
selection.is_multiple_volume() || selection.is_multiple_full_object()) {
else if (selection.is_single_volume() || selection.is_modifier() || selection.is_multiple_volume())
{
for (auto idx : selection.get_volume_idxs()) {
const auto gl_vol = selection.get_volume(idx);
if (selection.is_multiple_full_object())
sels.Add(m_objects_model->GetItemById(gl_vol->object_idx()));
else if (gl_vol->volume_idx() >= 0)
if (gl_vol->volume_idx() >= 0)
// Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
// are not associated with ModelVolumes, but they are temporarily generated by the backend
// (for example, SLA supports or SLA pad).
sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx()));
}
m_selection_mode = smVolume;
}
else if (selection.is_single_full_instance() || selection.is_multiple_full_instance()) {
else if (selection.is_single_full_instance() || selection.is_multiple_full_instance())
{
for (auto idx : selection.get_instance_idxs()) {
sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx));
}
}
else if (selection.is_mixed())
{
auto& objects_content_list = selection.get_content();
const Selection::ObjectIdxsToInstanceIdxsMap& objects_content_list = selection.get_content();
for (auto idx : selection.get_volume_idxs()) {
const auto gl_vol = selection.get_volume(idx);
@ -1999,6 +2065,9 @@ void ObjectList::update_selections()
sels.Add(m_objects_model->GetItemByVolumeId(glv_obj_idx, glv_vol_idx));
}
}
if (sels.size() == 0)
m_selection_mode = smUndef;
select_items(sels);
@ -2034,29 +2103,34 @@ void ObjectList::update_selections_on_canvas()
auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, int instance_idx, bool as_single_selection)
{
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection);
const ItemType& type = m_objects_model->GetItemType(item);
if ( type == itInstanceRoot || m_objects_model->GetParent(item) == wxDataViewItem(0) ) {
wxDataViewItem obj_item = type == itInstanceRoot ? m_objects_model->GetParent(item) : item;
selection.add_object(m_objects_model->GetIdByItem(obj_item), as_single_selection);
return;
}
if (m_objects_model->GetItemType(item) == itVolume) {
if (type == itVolume) {
const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item));
const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
selection.add_volume(obj_idx, vol_idx, std::max(instance_idx, 0), as_single_selection);
}
else if (m_objects_model->GetItemType(item) == itInstance) {
else if (type == itInstance) {
const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
const int inst_idx = m_objects_model->GetInstanceIdByItem(item);
selection.add_instance(obj_idx, inst_idx, as_single_selection);
}
};
// stores current instance idx before to clear the selection
int instance_idx = selection.get_instance_idx();
if (sel_cnt == 1) {
wxDataViewItem item = GetSelection();
if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot))
add_to_selection(m_objects_model->GetParent(item), selection, -1, true);
add_to_selection(m_objects_model->GetParent(item), selection, instance_idx, true);
else
add_to_selection(item, selection, -1, true);
add_to_selection(item, selection, instance_idx, true);
wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state();
return;
@ -2065,8 +2139,6 @@ void ObjectList::update_selections_on_canvas()
wxDataViewItemArray sels;
GetSelections(sels);
// stores current instance idx before to clear the selection
int instance_idx = selection.get_instance_idx();
selection.clear();
for (auto item: sels)
add_to_selection(item, selection, instance_idx, false);
@ -2112,22 +2184,101 @@ void ObjectList::select_item_all_children()
if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) {
for (int i = 0; i < m_objects->size(); i++)
sels.Add(m_objects_model->GetItemById(i));
m_selection_mode = smInstance;
}
else {
const auto item = GetSelection();
// Some volume(instance) is selected => select all volumes(instances) inside the current object
if (m_objects_model->GetItemType(item) & (itVolume | itInstance)) {
if (m_objects_model->GetItemType(item) & (itVolume | itInstance))
m_objects_model->GetChildren(m_objects_model->GetParent(item), sels);
}
m_selection_mode = m_objects_model->GetItemType(item)&itVolume ? smVolume : smInstance;
}
SetSelections(sels);
selection_changed();
}
// update selection mode for non-multiple selection
void ObjectList::update_selection_mode()
{
// All items are unselected
if (!GetSelection())
{
m_last_selected_item = wxDataViewItem(0);
m_selection_mode = smUndef;
return;
}
const ItemType type = m_objects_model->GetItemType(GetSelection());
m_selection_mode = type&itSettings ? smUndef :
type&itVolume ? smVolume : smInstance;
}
// check last selected item. If is it possible to select it
bool ObjectList::check_last_selection(wxString& msg_str)
{
if (!m_last_selected_item)
return true;
const bool is_shift_pressed = wxGetKeyState(WXK_SHIFT);
/* We can't mix Parts and Objects/Instances.
* So, show information about it
*/
const ItemType type = m_objects_model->GetItemType(m_last_selected_item);
// check a case of a selection of the Parts from different Objects
bool impossible_multipart_selection = false;
if (type & itVolume && m_selection_mode == smVolume)
{
wxDataViewItemArray sels;
GetSelections(sels);
for (const auto& sel: sels)
if (sel != m_last_selected_item &&
m_objects_model->GetParent(sel) != m_objects_model->GetParent(m_last_selected_item))
{
impossible_multipart_selection = true;
break;
}
}
if (impossible_multipart_selection ||
type & itSettings ||
type & itVolume && m_selection_mode == smInstance ||
!(type & itVolume) && m_selection_mode == smVolume)
{
// Inform user why selection isn't complited
const wxString item_type = m_selection_mode == smInstance ? _(L("Object or Instance")) : _(L("Part"));
msg_str = wxString::Format( _(L("Unsupported selection")) + "\n\n" +
_(L("You started your selection with %s Item.")) + "\n" +
_(L("In this mode you can select only other %s Items%s")),
item_type, item_type,
m_selection_mode == smInstance ? "." :
" " + _(L("of a current Object")));
// Unselect last selected item, if selection is without SHIFT
if (!is_shift_pressed) {
Unselect(m_last_selected_item);
show_info(this, msg_str, _(L("Info")));
}
return is_shift_pressed;
}
return true;
}
void ObjectList::fix_multiselection_conflicts()
{
if (GetSelectedItemsCount() <= 1)
if (GetSelectedItemsCount() <= 1) {
update_selection_mode();
return;
}
wxString msg_string;
if (!check_last_selection(msg_string))
return;
m_prevent_list_events = true;
@ -2135,12 +2286,58 @@ void ObjectList::fix_multiselection_conflicts()
wxDataViewItemArray sels;
GetSelections(sels);
for (auto item : sels) {
if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot))
Unselect(item);
else if (m_objects_model->GetParent(item) != wxDataViewItem(0))
Unselect(m_objects_model->GetParent(item));
if (m_selection_mode == smVolume)
{
// identify correct parent of the initial selected item
const wxDataViewItem& parent = m_objects_model->GetParent(m_last_selected_item == sels.front() ? sels.back() : sels.front());
sels.clear();
wxDataViewItemArray children; // selected volumes from current parent
m_objects_model->GetChildren(parent, children);
for (const auto child : children)
if (IsSelected(child) && m_objects_model->GetItemType(child)&itVolume)
sels.Add(child);
// If some part is selected, unselect all items except of selected parts of the current object
UnselectAll();
SetSelections(sels);
}
else
{
for (const auto item : sels)
{
if (!IsSelected(item)) // if this item is unselected now (from previous actions)
continue;
if (m_objects_model->GetItemType(item) & itSettings) {
Unselect(item);
continue;
}
const wxDataViewItem& parent = m_objects_model->GetParent(item);
if (parent != wxDataViewItem(0) && IsSelected(parent))
Unselect(parent);
else
{
wxDataViewItemArray unsels;
m_objects_model->GetAllChildren(item, unsels);
for (const auto unsel_item : unsels)
Unselect(unsel_item);
}
if (m_objects_model->GetItemType(item) & itVolume)
Unselect(item);
m_selection_mode = smInstance;
}
}
if (!msg_string.IsEmpty())
show_info(this, msg_string, _(L("Info")));
if (!IsSelected(m_last_selected_item))
m_last_selected_item = wxDataViewItem(0);
m_prevent_list_events = false;
}
@ -2272,6 +2469,12 @@ void ObjectList::update_object_menu()
void ObjectList::instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idxs)
{
if ((*m_objects)[obj_idx]->instances.size() == inst_idxs.size())
{
instances_to_separated_objects(obj_idx);
return;
}
// create new object from selected instance
ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
for (int inst_idx = model_object->instances.size() - 1; inst_idx >= 0; inst_idx--)
@ -2292,6 +2495,31 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set
}
}
void ObjectList::instances_to_separated_objects(const int obj_idx)
{
const int inst_cnt = (*m_objects)[obj_idx]->instances.size();
for (int i = inst_cnt-1; i > 0 ; i--)
{
// create new object from initial
ModelObject* object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
for (int inst_idx = object->instances.size() - 1; inst_idx >= 0; inst_idx--)
{
if (inst_idx == i)
continue;
// delete unnecessary instances
object->delete_instance(inst_idx);
}
// Add new object to the object_list
add_object_to_list(m_objects->size() - 1);
// delete current instance from the initial object
del_subobject_from_object(obj_idx, i, itInstance);
delete_instance_from_list(obj_idx, i);
}
}
void ObjectList::split_instances()
{
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
@ -2299,6 +2527,12 @@ void ObjectList::split_instances()
if (obj_idx == -1)
return;
if (selection.is_single_full_object())
{
instances_to_separated_objects(obj_idx);
return;
}
const int inst_idx = selection.get_instance_idx();
const std::set<int> inst_idxs = inst_idx < 0 ?
selection.get_instance_idxs() :
@ -2424,8 +2658,7 @@ void ObjectList::show_multi_selection_menu()
wxMenu* menu = new wxMenu();
#ifdef __WXOSX__
append_menu_item(menu, wxID_ANY, _(L("Delete items")), "",
[this](wxCommandEvent&) { remove(); }, "", menu);
append_menu_item_delete(menu);
#endif //__WXOSX__
if (extruders_count() > 1)

View file

@ -60,6 +60,12 @@ struct ItemForDelete
class ObjectList : public wxDataViewCtrl
{
enum SELECTION_MODE
{
smUndef,
smVolume,
smInstance
} m_selection_mode {smUndef};
struct dragged_item_data
{
@ -135,6 +141,7 @@ class ObjectList : public wxDataViewCtrl
bool m_part_settings_changed = false;
int m_selected_row = 0;
wxDataViewItem m_last_selected_item {nullptr};
#if 0
FreqSettingsBundle m_freq_settings_fff;
@ -188,6 +195,7 @@ public:
void append_menu_item_fix_through_netfabb(wxMenu* menu);
void append_menu_item_export_stl(wxMenu* menu) const ;
void append_menu_item_change_extruder(wxMenu* menu) const;
void append_menu_item_delete(wxMenu* menu);
void create_object_popupmenu(wxMenu *menu);
void create_sla_object_popupmenu(wxMenu*menu);
void create_part_popupmenu(wxMenu*menu);
@ -251,12 +259,15 @@ public:
void init_objects();
bool multiple_selection() const ;
bool is_selected(const ItemType type) const;
void update_selections();
void update_selections_on_canvas();
void select_item(const wxDataViewItem& item);
void select_items(const wxDataViewItemArray& sels);
void select_all();
void select_item_all_children();
void update_selection_mode();
bool check_last_selection(wxString& msg_str);
// correct current selections to avoid of the possible conflicts
void fix_multiselection_conflicts();
@ -269,6 +280,7 @@ public:
void update_object_menu();
void instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idx);
void instances_to_separated_objects(const int obj_idx);
void split_instances();
void rename_item();
void fix_through_netfabb() const;

View file

@ -92,7 +92,6 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
else if (option_name == "Size") {
line.near_label_widget = [this](wxWindow* parent) {
return new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition,
// wxBitmap(from_u8(var("one_layer_lock_on.png")), wxBITMAP_TYPE_PNG).GetSize());
create_scaled_bitmap("one_layer_lock_on.png").GetSize());
};
}
@ -161,6 +160,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_move_label_string = L("Position");
m_new_rotate_label_string = L("Rotation");
m_new_scale_label_string = L("Scale factors");
ObjectList* obj_list = wxGetApp().obj_list();
if (selection.is_single_full_instance())
{
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
@ -187,7 +188,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_enabled = true;
}
else if (selection.is_single_full_object())
else if (selection.is_single_full_object() && obj_list->is_selected(itObject))
{
m_cache.instance.reset();
@ -212,7 +213,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_size = (volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size()).cwiseAbs();
m_new_enabled = true;
}
else if (wxGetApp().obj_list()->multiple_selection())
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot))
{
reset_settings_value();
m_new_move_label_string = L("Translate");

View file

@ -77,7 +77,6 @@ void ObjectSettings::update_settings_list()
{
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
// auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG),
auto btn = new wxBitmapButton(parent, wxID_ANY, create_scaled_bitmap("colorchange_delete_on.png"),
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
#ifdef __WXMSW__

View file

@ -4,9 +4,14 @@
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#ifdef _WIN32
#include <Windows.h>
#endif
#include <wx/toplevel.h>
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/dcclient.h>
#include "libslic3r/Config.hpp"
@ -48,6 +53,64 @@ void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback)
#endif
}
wxDEFINE_EVENT(EVT_DPI_CHANGED, DpiChangedEvent);
#ifdef _WIN32
template<class F> typename F::FN winapi_get_function(const wchar_t *dll, const char *fn_name) {
static HINSTANCE dll_handle = LoadLibraryExW(dll, nullptr, 0);
if (dll_handle == nullptr) { return nullptr; }
return (F::FN)GetProcAddress(dll_handle, fn_name);
}
#endif
int get_dpi_for_window(wxWindow *window)
{
#ifdef _WIN32
enum MONITOR_DPI_TYPE_ {
// This enum is inlined here to avoid build-time dependency
MDT_EFFECTIVE_DPI_ = 0,
MDT_ANGULAR_DPI_ = 1,
MDT_RAW_DPI_ = 2,
MDT_DEFAULT_ = MDT_EFFECTIVE_DPI_,
};
// Need strong types for winapi_get_function() to work
struct GetDpiForWindow_t { typedef HRESULT (WINAPI *FN)(HWND hwnd); };
struct GetDpiForMonitor_t { typedef HRESULT (WINAPI *FN)(HMONITOR hmonitor, MONITOR_DPI_TYPE_ dpiType, UINT *dpiX, UINT *dpiY); };
static auto GetDpiForWindow_fn = winapi_get_function<GetDpiForWindow_t>(L"User32.dll", "GetDpiForWindow");
static auto GetDpiForMonitor_fn = winapi_get_function<GetDpiForMonitor_t>(L"Shcore.dll", "GetDpiForMonitor");
const HWND hwnd = window->GetHandle();
if (GetDpiForWindow_fn != nullptr) {
// We're on Windows 10, we have per-screen DPI settings
return GetDpiForWindow_fn(hwnd);
} else if (GetDpiForMonitor_fn != nullptr) {
// We're on Windows 8.1, we have per-system DPI
// Note: MonitorFromWindow() is available on all Windows.
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
UINT dpiX;
UINT dpiY;
return GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI_, &dpiX, &dpiY) == S_OK ? dpiX : DPI_DEFAULT;
} else {
// We're on Windows earlier than 8.1, use DC
const HDC hdc = GetDC(hwnd);
if (hdc == NULL) { return DPI_DEFAULT; }
return GetDeviceCaps(hdc, LOGPIXELSX);
}
#elif defined __linux__
// TODO
return DPI_DEFAULT;
#elif defined __APPLE__
// TODO
return DPI_DEFAULT;
#endif
}
CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent)
: wxPanel(parent, wxID_ANY)

View file

@ -8,10 +8,13 @@
#include <boost/optional.hpp>
#include <wx/frame.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/filedlg.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/dcclient.h>
#include <wx/debug.h>
class wxCheckBox;
@ -27,6 +30,68 @@ wxTopLevelWindow* find_toplevel_parent(wxWindow *window);
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);
enum { DPI_DEFAULT = 96 };
int get_dpi_for_window(wxWindow *window);
struct DpiChangedEvent : public wxEvent {
int dpi;
wxRect rect;
DpiChangedEvent(wxEventType eventType, int dpi, wxRect rect)
: wxEvent(0, eventType), dpi(dpi), rect(rect)
{}
virtual wxEvent *Clone() const
{
return new DpiChangedEvent(*this);
}
};
wxDECLARE_EVENT(EVT_DPI_CHANGED, DpiChangedEvent);
template<class P> class DPIAware : public P
{
public:
DPIAware(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition,
const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name=wxFrameNameStr)
: P(parent, id, title, pos, size, style, name)
{
m_scale_factor = (float)get_dpi_for_window(this) / (float)DPI_DEFAULT;
recalc_font();
this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) {
m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;
on_dpi_changed(evt.rect);
});
}
virtual ~DPIAware() {}
float scale_factor() const { return m_scale_factor; }
int em_unit() const { return m_em_unit; }
int font_size() const { return m_font_size; }
protected:
virtual void on_dpi_changed(const wxRect &suggested_rect) = 0;
private:
int m_scale_factor;
int m_em_unit;
int m_font_size;
void recalc_font()
{
wxClientDC dc(this);
const auto metrics = dc.GetFontMetrics();
m_font_size = metrics.height;
m_em_unit = metrics.averageWidth;
}
};
typedef DPIAware<wxFrame> DPIFrame;
typedef DPIAware<wxDialog> DPIDialog;
class EventGuard
{

View file

@ -1,4 +1,5 @@
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
@ -60,62 +61,62 @@ void GLGizmoBase::Grabber::render(float size, const float* render_color, bool us
float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size);
if (use_lighting)
::glEnable(GL_LIGHTING);
glsafe(::glEnable(GL_LIGHTING));
::glColor3fv(render_color);
glsafe(::glColor3fv(render_color));
::glPushMatrix();
::glTranslated(center(0), center(1), center(2));
glsafe(::glPushMatrix());
glsafe(::glTranslated(center(0), center(1), center(2)));
::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0);
::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0);
::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0);
glsafe(::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0));
glsafe(::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0));
glsafe(::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0));
// face min x
::glPushMatrix();
::glTranslatef(-(GLfloat)half_size, 0.0f, 0.0f);
::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
glsafe(::glPushMatrix());
glsafe(::glTranslatef(-(GLfloat)half_size, 0.0f, 0.0f));
glsafe(::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f));
render_face(half_size);
::glPopMatrix();
glsafe(::glPopMatrix());
// face max x
::glPushMatrix();
::glTranslatef((GLfloat)half_size, 0.0f, 0.0f);
::glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
glsafe(::glPushMatrix());
glsafe(::glTranslatef((GLfloat)half_size, 0.0f, 0.0f));
glsafe(::glRotatef(90.0f, 0.0f, 1.0f, 0.0f));
render_face(half_size);
::glPopMatrix();
glsafe(::glPopMatrix());
// face min y
::glPushMatrix();
::glTranslatef(0.0f, -(GLfloat)half_size, 0.0f);
::glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.0f, -(GLfloat)half_size, 0.0f));
glsafe(::glRotatef(90.0f, 1.0f, 0.0f, 0.0f));
render_face(half_size);
::glPopMatrix();
glsafe(::glPopMatrix());
// face max y
::glPushMatrix();
::glTranslatef(0.0f, (GLfloat)half_size, 0.0f);
::glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.0f, (GLfloat)half_size, 0.0f));
glsafe(::glRotatef(-90.0f, 1.0f, 0.0f, 0.0f));
render_face(half_size);
::glPopMatrix();
glsafe(::glPopMatrix());
// face min z
::glPushMatrix();
::glTranslatef(0.0f, 0.0f, -(GLfloat)half_size);
::glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.0f, 0.0f, -(GLfloat)half_size));
glsafe(::glRotatef(180.0f, 1.0f, 0.0f, 0.0f));
render_face(half_size);
::glPopMatrix();
glsafe(::glPopMatrix());
// face max z
::glPushMatrix();
::glTranslatef(0.0f, 0.0f, (GLfloat)half_size);
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.0f, 0.0f, (GLfloat)half_size));
render_face(half_size);
::glPopMatrix();
glsafe(::glPopMatrix());
::glPopMatrix();
glsafe(::glPopMatrix());
if (use_lighting)
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_LIGHTING));
}
void GLGizmoBase::Grabber::render_face(float half_size) const
@ -128,7 +129,7 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f);
::glVertex3f(-(GLfloat)half_size, (GLfloat)half_size, 0.0f);
::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f);
::glEnd();
glsafe(::glEnd());
}
#if ENABLE_SVG_ICONS

View file

@ -3,7 +3,6 @@
#include "libslic3r/Point.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/Selection.hpp"

View file

@ -1,5 +1,6 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoCut.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
@ -15,12 +16,6 @@ namespace Slic3r {
namespace GUI {
// GLGizmoCut
class GLGizmoCutPanel : public wxPanel
{
public:
@ -141,10 +136,10 @@ void GLGizmoCut::on_render(const Selection& selection) const
const float max_x = box.max(0) + Margin;
const float min_y = box.min(1) - Margin;
const float max_y = box.max(1) + Margin;
::glEnable(GL_DEPTH_TEST);
::glDisable(GL_CULL_FACE);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glDisable(GL_CULL_FACE));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
// Draw the cutting plane
::glBegin(GL_QUADS);
@ -153,10 +148,10 @@ void GLGizmoCut::on_render(const Selection& selection) const
::glVertex3f(max_x, min_y, plane_center(2));
::glVertex3f(max_x, max_y, plane_center(2));
::glVertex3f(min_x, max_y, plane_center(2));
::glEnd();
glsafe(::glEnd());
::glEnable(GL_CULL_FACE);
::glDisable(GL_BLEND);
glsafe(::glEnable(GL_CULL_FACE));
glsafe(::glDisable(GL_BLEND));
// TODO: draw cut part contour?
@ -164,13 +159,13 @@ void GLGizmoCut::on_render(const Selection& selection) const
m_grabbers[0].center = plane_center;
m_grabbers[0].center(2) = plane_center(2) + Offset;
::glDisable(GL_DEPTH_TEST);
::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f);
::glColor3f(1.0, 1.0, 0.0);
glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f));
glsafe(::glColor3f(1.0, 1.0, 0.0));
::glBegin(GL_LINES);
::glVertex3dv(plane_center.data());
::glVertex3dv(m_grabbers[0].center.data());
::glEnd();
glsafe(::glEnd());
std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_grabbers[0].color);
m_grabbers[0].render(m_hover_id == 0, (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0));
@ -178,7 +173,7 @@ void GLGizmoCut::on_render(const Selection& selection) const
void GLGizmoCut::on_render_for_picking(const Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
glsafe(::glDisable(GL_DEPTH_TEST));
render_grabbers_for_picking(selection.get_bounding_box());
}
@ -192,7 +187,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, co
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
ImGui::PushItemWidth(100.0f);
ImGui::PushItemWidth(m_imgui->scaled(5.0f));
bool _value_changed = ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f");
m_imgui->checkbox(_(L("Keep upper part")), m_keep_upper);

View file

@ -49,67 +49,67 @@ void GLGizmoFlatten::on_start_dragging(const Selection& selection)
void GLGizmoFlatten::on_render(const Selection& selection) const
{
::glClear(GL_DEPTH_BUFFER_BIT);
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
::glEnable(GL_DEPTH_TEST);
::glEnable(GL_BLEND);
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glEnable(GL_BLEND));
if (selection.is_single_full_instance())
{
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
::glPushMatrix();
::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z());
::glMultMatrixd(m.data());
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()));
glsafe(::glMultMatrixd(m.data()));
if (this->is_plane_update_necessary())
const_cast<GLGizmoFlatten*>(this)->update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i)
{
if (i == m_hover_id)
::glColor4f(0.9f, 0.9f, 0.9f, 0.75f);
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.75f));
else
::glColor4f(0.9f, 0.9f, 0.9f, 0.5f);
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.5f));
::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices)
{
::glVertex3dv(vertex.data());
}
::glEnd();
glsafe(::glEnd());
}
::glPopMatrix();
glsafe(::glPopMatrix());
}
::glEnable(GL_CULL_FACE);
::glDisable(GL_BLEND);
glsafe(::glEnable(GL_CULL_FACE));
glsafe(::glDisable(GL_BLEND));
}
void GLGizmoFlatten::on_render_for_picking(const Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
::glDisable(GL_BLEND);
glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glDisable(GL_BLEND));
if (selection.is_single_full_instance())
{
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
::glPushMatrix();
::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z());
::glMultMatrixd(m.data());
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()));
glsafe(::glMultMatrixd(m.data()));
if (this->is_plane_update_necessary())
const_cast<GLGizmoFlatten*>(this)->update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i)
{
::glColor3fv(picking_color_component(i).data());
glsafe(::glColor3fv(picking_color_component(i).data()));
::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices)
{
::glVertex3dv(vertex.data());
}
::glEnd();
glsafe(::glEnd());
}
::glPopMatrix();
glsafe(::glPopMatrix());
}
::glEnable(GL_CULL_FACE);
glsafe(::glEnable(GL_CULL_FACE));
}
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)

View file

@ -97,8 +97,8 @@ void GLGizmoMove3D::on_render(const Selection& selection) const
else if (!m_grabbers[2].dragging && (m_hover_id == 2))
set_tooltip("Z");
::glClear(GL_DEPTH_BUFFER_BIT);
::glEnable(GL_DEPTH_TEST);
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
const BoundingBoxf3& box = selection.get_bounding_box();
const Vec3d& center = box.center();
@ -115,7 +115,7 @@ void GLGizmoMove3D::on_render(const Selection& selection) const
m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset);
::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float));
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
if (m_hover_id == -1)
{
@ -124,11 +124,11 @@ void GLGizmoMove3D::on_render(const Selection& selection) const
{
if (m_grabbers[i].enabled)
{
::glColor3fv(AXES_COLOR[i]);
glsafe(::glColor3fv(AXES_COLOR[i]));
::glBegin(GL_LINES);
::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[i].center.data());
::glEnd();
glsafe(::glEnd());
}
}
@ -143,11 +143,11 @@ void GLGizmoMove3D::on_render(const Selection& selection) const
else
{
// draw axis
::glColor3fv(AXES_COLOR[m_hover_id]);
glsafe(::glColor3fv(AXES_COLOR[m_hover_id]));
::glBegin(GL_LINES);
::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[m_hover_id].center.data());
::glEnd();
glsafe(::glEnd());
// draw grabber
m_grabbers[m_hover_id].render(true, box.max_size());
@ -157,7 +157,7 @@ void GLGizmoMove3D::on_render(const Selection& selection) const
void GLGizmoMove3D::on_render_for_picking(const Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
glsafe(::glDisable(GL_DEPTH_TEST));
const BoundingBoxf3& box = selection.get_bounding_box();
render_grabbers_for_picking(box);
@ -229,25 +229,25 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
}
if (!picking)
::glEnable(GL_LIGHTING);
glsafe(::glEnable(GL_LIGHTING));
::glColor3fv(color);
::glPushMatrix();
::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2));
glsafe(::glColor3fv(color));
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2)));
if (axis == X)
::glRotated(90.0, 0.0, 1.0, 0.0);
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
else if (axis == Y)
::glRotated(-90.0, 1.0, 0.0, 0.0);
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
::glTranslated(0.0, 0.0, 2.0 * size);
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
::glPopMatrix();
glsafe(::glPopMatrix());
if (!picking)
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_LIGHTING));
}

View file

@ -155,13 +155,13 @@ void GLGizmoRotate::on_render(const Selection& selection) const
m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
}
::glEnable(GL_DEPTH_TEST);
glsafe(::glEnable(GL_DEPTH_TEST));
::glPushMatrix();
glsafe(::glPushMatrix());
transform_to_local(selection);
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color);
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
glsafe(::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color));
render_circle();
@ -172,7 +172,7 @@ void GLGizmoRotate::on_render(const Selection& selection) const
render_reference_radius();
}
::glColor3fv(m_highlight_color);
glsafe(::glColor3fv(m_highlight_color));
if (m_hover_id != -1)
render_angle();
@ -180,14 +180,14 @@ void GLGizmoRotate::on_render(const Selection& selection) const
render_grabber(box);
render_grabber_extension(box, false);
::glPopMatrix();
glsafe(::glPopMatrix());
}
void GLGizmoRotate::on_render_for_picking(const Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
glsafe(::glDisable(GL_DEPTH_TEST));
::glPushMatrix();
glsafe(::glPushMatrix());
transform_to_local(selection);
@ -195,7 +195,7 @@ void GLGizmoRotate::on_render_for_picking(const Selection& selection) const
render_grabbers_for_picking(box);
render_grabber_extension(box, true);
::glPopMatrix();
glsafe(::glPopMatrix());
}
void GLGizmoRotate::render_circle() const
@ -209,7 +209,7 @@ void GLGizmoRotate::render_circle() const
float z = 0.0f;
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
}
::glEnd();
glsafe(::glEnd());
}
void GLGizmoRotate::render_scale() const
@ -232,7 +232,7 @@ void GLGizmoRotate::render_scale() const
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z);
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z);
}
::glEnd();
glsafe(::glEnd());
}
void GLGizmoRotate::render_snap_radii() const
@ -257,7 +257,7 @@ void GLGizmoRotate::render_snap_radii() const
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z);
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z);
}
::glEnd();
glsafe(::glEnd());
}
void GLGizmoRotate::render_reference_radius() const
@ -265,7 +265,7 @@ void GLGizmoRotate::render_reference_radius() const
::glBegin(GL_LINES);
::glVertex3f(0.0f, 0.0f, 0.0f);
::glVertex3f((GLfloat)(m_radius * (1.0f + GrabberOffset)), 0.0f, 0.0f);
::glEnd();
glsafe(::glEnd());
}
void GLGizmoRotate::render_angle() const
@ -282,7 +282,7 @@ void GLGizmoRotate::render_angle() const
float z = 0.0f;
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
}
::glEnd();
glsafe(::glEnd());
}
void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
@ -291,12 +291,12 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
m_grabbers[0].angles(2) = m_angle;
::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color);
glsafe(::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color));
::glBegin(GL_LINES);
::glVertex3f(0.0f, 0.0f, 0.0f);
::glVertex3dv(m_grabbers[0].center.data());
::glEnd();
glsafe(::glEnd());
::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float));
render_grabbers(box);
@ -320,56 +320,56 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
}
if (!picking)
::glEnable(GL_LIGHTING);
glsafe(::glEnable(GL_LIGHTING));
::glColor3fv(color);
::glPushMatrix();
::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2));
::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0);
::glRotated(90.0, 1.0, 0.0, 0.0);
::glTranslated(0.0, 0.0, 2.0 * size);
glsafe(::glColor3fv(color));
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)));
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
::glPopMatrix();
::glPushMatrix();
::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2));
::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0);
::glRotated(-90.0, 1.0, 0.0, 0.0);
::glTranslated(0.0, 0.0, 2.0 * size);
glsafe(::glPopMatrix());
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)));
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
::glPopMatrix();
glsafe(::glPopMatrix());
if (!picking)
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_LIGHTING));
}
void GLGizmoRotate::transform_to_local(const Selection& selection) const
{
::glTranslated(m_center(0), m_center(1), m_center(2));
glsafe(::glTranslated(m_center(0), m_center(1), m_center(2)));
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
{
Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
glsafe(::glMultMatrixd(orient_matrix.data()));
}
switch (m_axis)
{
case X:
{
::glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
glsafe(::glRotatef(90.0f, 0.0f, 1.0f, 0.0f));
glsafe(::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f));
break;
}
case Y:
{
::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
glsafe(::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f));
glsafe(::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f));
break;
}
default:
@ -472,7 +472,7 @@ void GLGizmoRotate3D::on_stop_dragging()
void GLGizmoRotate3D::on_render(const Selection& selection) const
{
::glClear(GL_DEPTH_BUFFER_BIT);
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
if ((m_hover_id == -1) || (m_hover_id == 0))
m_gizmos[X].render(selection);

View file

@ -108,8 +108,8 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9)))
set_tooltip("X/Y/Z");
::glClear(GL_DEPTH_BUFFER_BIT);
::glEnable(GL_DEPTH_TEST);
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
BoundingBoxf3 box;
Transform3d transform = Transform3d::Identity();
@ -187,7 +187,7 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
m_grabbers[i].angles = angles;
}
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
const BoundingBoxf3& selection_box = selection.get_bounding_box();
@ -198,20 +198,20 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
// draw connections
if (m_grabbers[0].enabled && m_grabbers[1].enabled)
{
::glColor3fv(m_grabbers[0].color);
glsafe(::glColor3fv(m_grabbers[0].color));
render_grabbers_connection(0, 1);
}
if (m_grabbers[2].enabled && m_grabbers[3].enabled)
{
::glColor3fv(m_grabbers[2].color);
glsafe(::glColor3fv(m_grabbers[2].color));
render_grabbers_connection(2, 3);
}
if (m_grabbers[4].enabled && m_grabbers[5].enabled)
{
::glColor3fv(m_grabbers[4].color);
glsafe(::glColor3fv(m_grabbers[4].color));
render_grabbers_connection(4, 5);
}
::glColor3fv(m_base_color);
glsafe(::glColor3fv(m_base_color));
render_grabbers_connection(6, 7);
render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9);
@ -222,7 +222,7 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
else if ((m_hover_id == 0) || (m_hover_id == 1))
{
// draw connection
::glColor3fv(m_grabbers[0].color);
glsafe(::glColor3fv(m_grabbers[0].color));
render_grabbers_connection(0, 1);
// draw grabbers
m_grabbers[0].render(true, grabber_mean_size);
@ -231,7 +231,7 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
else if ((m_hover_id == 2) || (m_hover_id == 3))
{
// draw connection
::glColor3fv(m_grabbers[2].color);
glsafe(::glColor3fv(m_grabbers[2].color));
render_grabbers_connection(2, 3);
// draw grabbers
m_grabbers[2].render(true, grabber_mean_size);
@ -240,7 +240,7 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
else if ((m_hover_id == 4) || (m_hover_id == 5))
{
// draw connection
::glColor3fv(m_grabbers[4].color);
glsafe(::glColor3fv(m_grabbers[4].color));
render_grabbers_connection(4, 5);
// draw grabbers
m_grabbers[4].render(true, grabber_mean_size);
@ -249,7 +249,7 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
else if (m_hover_id >= 6)
{
// draw connection
::glColor3fv(m_drag_color);
glsafe(::glColor3fv(m_drag_color));
render_grabbers_connection(6, 7);
render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9);
@ -264,7 +264,7 @@ void GLGizmoScale3D::on_render(const Selection& selection) const
void GLGizmoScale3D::on_render_for_picking(const Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
glsafe(::glDisable(GL_DEPTH_TEST));
render_grabbers_for_picking(selection.get_bounding_box());
}
@ -291,7 +291,7 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
::glBegin(GL_LINES);
::glVertex3dv(m_grabbers[id_1].center.data());
::glVertex3dv(m_grabbers[id_2].center.data());
::glEnd();
glsafe(::glEnd());
}
}

View file

@ -1,5 +1,6 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoSlaSupports.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h>
@ -84,13 +85,13 @@ void GLGizmoSlaSupports::on_render(const Selection& selection) const
return;
}
::glEnable(GL_BLEND);
::glEnable(GL_DEPTH_TEST);
glsafe(::glEnable(GL_BLEND));
glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, false);
render_selection_rectangle();
::glDisable(GL_BLEND);
glsafe(::glDisable(GL_BLEND));
}
void GLGizmoSlaSupports::render_selection_rectangle() const
@ -98,44 +99,44 @@ void GLGizmoSlaSupports::render_selection_rectangle() const
if (!m_selection_rectangle_active)
return;
::glLineWidth(1.5f);
glsafe(::glLineWidth(1.5f));
float render_color[3] = {1.f, 0.f, 0.f};
::glColor3fv(render_color);
glsafe(::glColor3fv(render_color));
::glPushAttrib(GL_TRANSFORM_BIT); // remember current MatrixMode
glsafe(::glPushAttrib(GL_TRANSFORM_BIT)); // remember current MatrixMode
::glMatrixMode(GL_MODELVIEW); // cache modelview matrix and set to identity
::glPushMatrix();
::glLoadIdentity();
glsafe(::glMatrixMode(GL_MODELVIEW)); // cache modelview matrix and set to identity
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
::glMatrixMode(GL_PROJECTION); // cache projection matrix and set to identity
::glPushMatrix();
::glLoadIdentity();
glsafe(::glMatrixMode(GL_PROJECTION)); // cache projection matrix and set to identity
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
::glOrtho(0.f, m_canvas_width, m_canvas_height, 0.f, -1.f, 1.f); // set projection matrix so that world coords = window coords
glsafe(::glOrtho(0.f, m_canvas_width, m_canvas_height, 0.f, -1.f, 1.f)); // set projection matrix so that world coords = window coords
// render the selection rectangle (window coordinates):
::glPushAttrib(GL_ENABLE_BIT);
::glLineStipple(4, 0xAAAA);
::glEnable(GL_LINE_STIPPLE);
glsafe(::glPushAttrib(GL_ENABLE_BIT));
glsafe(::glLineStipple(4, 0xAAAA));
glsafe(::glEnable(GL_LINE_STIPPLE));
::glBegin(GL_LINE_LOOP);
::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f);
::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f);
::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f);
::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f);
::glEnd();
::glPopAttrib();
glsafe(::glEnd());
glsafe(::glPopAttrib());
::glPopMatrix(); // restore former projection matrix
::glMatrixMode(GL_MODELVIEW);
::glPopMatrix(); // restore former modelview matrix
::glPopAttrib(); // restore former MatrixMode
glsafe(::glPopMatrix()); // restore former projection matrix
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glPopMatrix()); // restore former modelview matrix
glsafe(::glPopAttrib()); // restore former MatrixMode
}
void GLGizmoSlaSupports::on_render_for_picking(const Selection& selection) const
{
::glEnable(GL_DEPTH_TEST);
glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, true);
}
@ -146,16 +147,16 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
return;
if (!picking)
::glEnable(GL_LIGHTING);
glsafe(::glEnable(GL_LIGHTING));
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
double z_shift = vol->get_sla_shift_z();
const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix();
::glPushMatrix();
::glTranslated(0.0, 0.0, z_shift);
::glMultMatrixd(instance_matrix.data());
glsafe(::glPushMatrix());
glsafe(::glTranslated(0.0, 0.0, z_shift));
glsafe(::glMultMatrixd(instance_matrix.data()));
float render_color[3];
for (int i = 0; i < (int)m_editing_mode_cache.size(); ++i)
@ -187,14 +188,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f;
}
}
::glColor3fv(render_color);
glsafe(::glColor3fv(render_color));
float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f};
::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive);
glsafe(::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive));
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
::glPushMatrix();
::glTranslated(support_point.pos(0), support_point.pos(1), support_point.pos(2));
::glMultMatrixd(instance_scaling_matrix_inverse.data());
glsafe(::glPushMatrix());
glsafe(::glTranslated(support_point.pos(0), support_point.pos(1), support_point.pos(2)));
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
// Matrices set, we can render the point mark now.
// If in editing mode, we'll also render a cone pointing to the sphere.
@ -205,31 +206,31 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_mode_cache[i].normal.cast<double>());
Eigen::AngleAxisd aa(q);
::glRotated(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2));
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
const float cone_radius = 0.25f; // mm
const float cone_height = 0.75f;
::glPushMatrix();
::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale);
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale));
::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 24, 1);
::glTranslatef(0.f, 0.f, cone_height);
glsafe(::glTranslatef(0.f, 0.f, cone_height));
::gluDisk(m_quadric, 0.0, cone_radius, 24, 1);
::glPopMatrix();
glsafe(::glPopMatrix());
}
::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 24, 12);
::glPopMatrix();
glsafe(::glPopMatrix());
}
{
// Reset emissive component to zero (the default value)
float render_color_emissive[4] = { 0.f, 0.f, 0.f, 1.f };
::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive);
glsafe(::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive));
}
if (!picking)
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_LIGHTING));
::glPopMatrix();
glsafe(::glPopMatrix());
}
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
@ -272,17 +273,15 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
if (m_V.size() == 0)
update_mesh();
Eigen::Matrix<GLint, 4, 1, Eigen::DontAlign> viewport;
::glGetIntegerv(GL_VIEWPORT, viewport.data());
Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> projection_matrix;
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data());
const Camera& camera = m_parent.get_camera();
const std::array<int, 4>& viewport = camera.get_viewport();
const Transform3d& modelview_matrix = camera.get_view_matrix();
const Transform3d& projection_matrix = camera.get_projection_matrix();
Vec3d point1;
Vec3d point2;
::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2));
::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2));
::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2));
::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2));
igl::Hit hit;
@ -368,12 +367,10 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
// left up with selection rectangle - select points inside the rectangle:
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) && m_selection_rectangle_active) {
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
GLint viewport[4];
::glGetIntegerv(GL_VIEWPORT, viewport);
GLdouble modelview_matrix[16];
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
GLdouble projection_matrix[16];
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
const Camera& camera = m_parent.get_camera();
const std::array<int, 4>& viewport = camera.get_viewport();
const Transform3d& modelview_matrix = camera.get_view_matrix();
const Transform3d& projection_matrix = camera.get_projection_matrix();
const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
@ -384,7 +381,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
const Transform3d& instance_matrix_no_translation = volume->get_instance_transformation().get_matrix(true);
// we'll recover current look direction from the modelview matrix (in world coords)...
Vec3f direction_to_camera(modelview_matrix[2], modelview_matrix[6], modelview_matrix[10]);
Vec3f direction_to_camera = camera.get_dir_forward().cast<float>();
// ...and transform it to model coords.
direction_to_camera = (instance_matrix_no_translation.inverse().cast<float>() * direction_to_camera).normalized().eval();
@ -394,8 +391,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
Vec3f pos = instance_matrix.cast<float>() * support_point.pos;
pos(2) += z_offset;
GLdouble out_x, out_y, out_z;
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z);
out_y = m_canvas_height - out_y;
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), (GLdouble*)modelview_matrix.data(), (GLdouble*)projection_matrix.data(), (GLint*)viewport.data(), &out_x, &out_y, &out_z);
out_y = m_canvas_height - out_y;
if (rectangle.contains(Point(out_x, out_y))) {
bool is_obscured = false;
@ -729,40 +726,45 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::on_set_state()
{
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
if (is_mesh_update_necessary())
update_mesh();
wxGetApp().CallAfter([this]() {
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
// we'll now reload support points:
if (m_model_object)
editing_mode_reload_cache();
if (is_mesh_update_necessary())
update_mesh();
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
// we'll now reload support points:
if (m_model_object)
editing_mode_reload_cache();
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
}
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
}
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
}
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
}
}
m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear();
}
m_old_state = m_state;
m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear();
}
m_old_state = m_state;
});
}

View file

@ -2,6 +2,7 @@
#define slic3r_GLGizmoSlaSupports_hpp_
#include "GLGizmoBase.hpp"
#include "GLGizmos.hpp"
// There is an L function in igl that would be overridden by our localization macro - let's undefine it...
#undef L

View file

@ -1,6 +1,21 @@
#ifndef slic3r_GLGizmos_hpp_
#define slic3r_GLGizmos_hpp_
// this describes events being passed from GLCanvas3D to SlaSupport gizmo
enum class SLAGizmoEventType {
LeftDown = 1,
LeftUp,
RightDown,
Dragging,
Delete,
SelectAll,
ShiftUp,
ApplyChanges,
DiscardChanges,
AutomaticGeneration,
ManualEditing
};
#include "slic3r/GUI/Gizmos/GLGizmoMove.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoScale.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoRotate.hpp"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,184 @@
#ifndef slic3r_GUI_GLGizmosManager_hpp_
#define slic3r_GUI_GLGizmosManager_hpp_
#include "slic3r/GUI/GLTexture.hpp"
#include "slic3r/GUI/GLToolbar.hpp"
#include "slic3r/GUI/Gizmos/GLGizmos.hpp"
#include <map>
namespace Slic3r {
namespace GUI {
class Selection;
class GLGizmoBase;
class GLCanvas3D;
class Rect
{
float m_left;
float m_top;
float m_right;
float m_bottom;
public:
Rect() : m_left(0.0f) , m_top(0.0f) , m_right(0.0f) , m_bottom(0.0f) {}
Rect(float left, float top, float right, float bottom) : m_left(left) , m_top(top) , m_right(right) , m_bottom(bottom) {}
float get_left() const { return m_left; }
void set_left(float left) { m_left = left; }
float get_top() const { return m_top; }
void set_top(float top) { m_top = top; }
float get_right() const { return m_right; }
void set_right(float right) { m_right = right; }
float get_bottom() const { return m_bottom; }
void set_bottom(float bottom) { m_bottom = bottom; }
float get_width() const { return m_right - m_left; }
float get_height() const { return m_top - m_bottom; }
};
class GLGizmosManager
{
public:
#if ENABLE_SVG_ICONS
static const float Default_Icons_Size;
#endif // ENABLE_SVG_ICONS
enum EType : unsigned char
{
Undefined,
Move,
Scale,
Rotate,
Flatten,
Cut,
SlaSupports,
Num_Types
};
private:
bool m_enabled;
typedef std::map<EType, GLGizmoBase*> GizmosMap;
GizmosMap m_gizmos;
#if ENABLE_SVG_ICONS
mutable GLTexture m_icons_texture;
mutable bool m_icons_texture_dirty;
#else
ItemsIconsTexture m_icons_texture;
#endif // ENABLE_SVG_ICONS
BackgroundTexture m_background_texture;
EType m_current;
#if ENABLE_SVG_ICONS
float m_overlay_icons_size;
float m_overlay_scale;
#else
float m_overlay_icons_scale;
#endif // ENABLE_SVG_ICONS
float m_overlay_border;
float m_overlay_gap_y;
struct MouseCapture
{
bool left;
bool middle;
bool right;
GLCanvas3D* parent;
MouseCapture() { reset(); }
bool any() const { return left || middle || right; }
void reset() { left = middle = right = false; parent = nullptr; }
};
MouseCapture m_mouse_capture;
std::string m_tooltip;
public:
GLGizmosManager();
~GLGizmosManager();
bool init(GLCanvas3D& parent);
bool is_enabled() const { return m_enabled; }
void set_enabled(bool enable) { m_enabled = enable; }
#if ENABLE_SVG_ICONS
void set_overlay_icon_size(float size);
#endif // ENABLE_SVG_ICONS
void set_overlay_scale(float scale);
void refresh_on_off_state(const Selection& selection);
void reset_all_states();
void set_hover_id(int id);
void enable_grabber(EType type, unsigned int id, bool enable);
void update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos = nullptr);
void update_data(GLCanvas3D& canvas);
Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
EType get_current_type() const { return m_current; }
bool is_running() const;
bool handle_shortcut(int key, const Selection& selection);
bool is_dragging() const;
void start_dragging(const Selection& selection);
void stop_dragging();
Vec3d get_displacement() const;
Vec3d get_scale() const;
void set_scale(const Vec3d& scale);
Vec3d get_rotation() const;
void set_rotation(const Vec3d& rotation);
Vec3d get_flattening_normal() const;
void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
void render_current_gizmo(const Selection& selection) const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const;
void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
const std::string& get_tooltip() const { return m_tooltip; }
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas);
bool on_char(wxKeyEvent& evt, GLCanvas3D& canvas);
bool on_key(wxKeyEvent& evt, GLCanvas3D& canvas);
private:
void reset();
void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
float get_total_overlay_height() const;
float get_total_overlay_width() const;
GLGizmoBase* get_current() const;
#if ENABLE_SVG_ICONS
bool generate_icons_texture() const;
#endif // ENABLE_SVG_ICONS
void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos);
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
bool grabber_contains_mouse() const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GUI_GLGizmosManager_hpp_

View file

@ -19,6 +19,7 @@
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
#include "3DScene.hpp"
#include "GUI.hpp"
namespace Slic3r {
@ -359,19 +360,19 @@ void ImGuiWrapper::init_font()
// Upload texture to graphics system
GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGenTextures(1, &m_font_texture);
glBindTexture(GL_TEXTURE_2D, m_font_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
glsafe(::glGenTextures(1, &m_font_texture));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_font_texture));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)m_font_texture;
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture));
}
void ImGuiWrapper::init_input()
@ -466,39 +467,39 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_SCISSOR_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode));
GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport));
GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box));
glsafe(::glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glsafe(::glDisable(GL_CULL_FACE));
glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glDisable(GL_LIGHTING));
glsafe(::glDisable(GL_COLOR_MATERIAL));
glsafe(::glEnable(GL_SCISSOR_TEST));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY));
glsafe(::glEnableClientState(GL_COLOR_ARRAY));
glsafe(::glEnable(GL_TEXTURE_2D));
glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
GLint texture_env_mode = GL_MODULATE;
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &texture_env_mode);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glsafe(::glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &texture_env_mode));
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glsafe(::glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
glsafe(::glMatrixMode(GL_PROJECTION));
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
glsafe(::glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f));
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
// Render command lists
ImVec2 pos = draw_data->DisplayPos;
@ -507,9 +508,9 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
glsafe(::glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos))));
glsafe(::glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))));
glsafe(::glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))));
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
@ -525,11 +526,11 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
{
// Apply scissor/clipping rectangle
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)));
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId));
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer));
}
}
idx_buffer += pcmd->ElemCount;
@ -537,19 +538,19 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
}
// Restore modified state
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texture_env_mode);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texture_env_mode));
glsafe(::glDisableClientState(GL_COLOR_ARRAY));
glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture));
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glPopMatrix());
glsafe(::glMatrixMode(GL_PROJECTION));
glsafe(::glPopMatrix());
glsafe(::glPopAttrib());
glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]));
glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]));
glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]));
}
bool ImGuiWrapper::display_initialized() const
@ -563,7 +564,7 @@ void ImGuiWrapper::destroy_font()
if (m_font_texture != 0) {
ImGuiIO& io = ImGui::GetIO();
io.Fonts->TexID = 0;
glDeleteTextures(1, &m_font_texture);
glsafe(::glDeleteTextures(1, &m_font_texture));
m_font_texture = 0;
}
}

View file

@ -17,8 +17,7 @@ KBShortcutsDialog::KBShortcutsDialog()
auto main_sizer = new wxBoxSizer(wxVERTICAL);
// logo
// wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_32px.png")), wxBITMAP_TYPE_PNG);
const wxBitmap logo_bmp = create_scaled_bitmap("Slic3r_32px.png");
const wxBitmap logo_bmp = create_scaled_bitmap("Slic3r_32px.png", 32);
// fonts
wxFont head_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();

View file

@ -32,7 +32,7 @@ namespace Slic3r {
namespace GUI {
MainFrame::MainFrame() :
wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
{
// Load the icon either from the exe, or from the ico file.
@ -56,9 +56,13 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
// initialize default width_unit according to the width of the one symbol ("x") of the current system font
const wxSize size = GetTextExtent("m");
// wxGetApp().set_em_unit(size.x-1);
wxGetApp().set_em_unit(std::max<size_t>(10, size.x - 1));
/* Load default preset bitmaps before a tabpanel initialization,
* but after filling of an em_unit value
*/
wxGetApp().preset_bundle->load_default_preset_bitmaps();
// initialize tabpanel and menubar
init_tabpanel();
init_menubar();
@ -252,6 +256,11 @@ bool MainFrame::can_delete_all() const
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
}
void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
{
// TODO
}
void MainFrame::init_menubar()
{
#ifdef __APPLE__
@ -388,11 +397,11 @@ void MainFrame::init_menubar()
windowMenu->AppendSeparator();
}
append_menu_item(windowMenu, wxID_HIGHEST + 2, _(L("P&rint Settings Tab")) + "\tCtrl+2", _(L("Show the print settings")),
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog.png");
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog");
append_menu_item(windowMenu, wxID_HIGHEST + 3, _(L("&Filament Settings Tab")) + "\tCtrl+3", _(L("Show the filament settings")),
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 1); }, "spool.png");
append_menu_item(windowMenu, wxID_HIGHEST + 4, _(L("Print&er Settings Tab")) + "\tCtrl+4", _(L("Show the printer settings")),
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer_empty.png");
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer");
if (m_plater) {
windowMenu->AppendSeparator();
wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")),

View file

@ -9,6 +9,7 @@
#include <string>
#include <map>
#include "GUI_Utils.hpp"
#include "Plater.hpp"
#include "Event.hpp"
@ -40,7 +41,7 @@ struct PresetTab {
PrinterTechnology technology;
};
class MainFrame : public wxFrame
class MainFrame : public DPIFrame
{
bool m_loaded {false};
@ -68,6 +69,9 @@ class MainFrame : public wxFrame
bool can_delete() const;
bool can_delete_all() const;
protected:
virtual void on_dpi_changed(const wxRect &suggested_rect);
public:
MainFrame();
~MainFrame() {}

View file

@ -24,7 +24,7 @@ namespace GUI {
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id) :
MsgDialog(parent, title, headline, create_scaled_bitmap("Slic3r_192px.png"), button_id)
MsgDialog(parent, title, headline, create_scaled_bitmap("Slic3r_192px.png", 192), button_id)
{}
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id) :

View file

@ -38,6 +38,8 @@
#include "libslic3r/SLA/SLARotfinder.hpp"
#include "libslic3r/Utils.hpp"
#include "libnest2d/optimizers/nlopt/genetic.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "GUI_ObjectList.hpp"
@ -284,7 +286,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 *
#ifdef __WINDOWS__
edit_btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif
edit_btn->SetBitmap(create_scaled_bitmap("cog.png"));
edit_btn->SetBitmap(create_scaled_bitmap("cog"));
edit_btn->SetToolTip(_(L("Click to edit preset")));
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
@ -1199,7 +1201,7 @@ struct Plater::priv
BoundingBox scaled_bed_shape_bb() const;
std::vector<size_t> load_files(const std::vector<fs::path>& input_files, bool load_model, bool load_config);
std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects);
std::unique_ptr<CheckboxFileDialog> get_export_file(GUI::FileType file_type);
wxString get_export_file(GUI::FileType file_type);
const Selection& get_selection() const;
Selection& get_selection();
@ -1617,6 +1619,45 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
#if ENABLE_VOLUMES_CENTERING_FIXES
}
else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf))
{
bool advanced = false;
for (const ModelObject* model_object : model.objects)
{
// is there more than one instance ?
if (model_object->instances.size() > 1)
{
advanced = true;
break;
}
// is there any modifier ?
for (const ModelVolume* model_volume : model_object->volumes)
{
if (!model_volume->is_model_part())
{
advanced = true;
break;
}
}
if (advanced)
break;
}
if (advanced)
{
wxMessageDialog dlg(q, _(L("This file cannot be loaded in simple mode. Do you want to switch to expert mode?\n")),
_(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
{
Slic3r::GUI::wxGetApp().save_mode(comExpert);
view3D->set_as_dirty();
}
else
return obj_idxs;
}
}
#endif // ENABLE_VOLUMES_CENTERING_FIXES
#if !ENABLE_VOLUMES_CENTERING_FIXES
@ -1642,7 +1683,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
Slic3r::GUI::show_error(nullptr,
wxString::Format(_(L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part")),
from_path(filename)));
return std::vector<size_t>();
return obj_idxs;
}
}
@ -1784,7 +1825,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
return obj_idxs;
}
std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType file_type)
wxString Plater::priv::get_export_file(GUI::FileType file_type)
{
wxString wildcard;
switch (file_type) {
@ -1801,34 +1842,56 @@ std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType
// Update printbility state of each of the ModelInstances.
this->update_print_volume_state();
// Find the file name of the first printable object.
fs::path output_file = this->model.propose_export_file_name_and_path();
const Selection& selection = get_selection();
int obj_idx = selection.get_object_idx();
fs::path output_file;
// first try to get the file name from the current selection
if ((0 <= obj_idx) && (obj_idx < (int)this->model.objects.size()))
output_file = this->model.objects[obj_idx]->get_export_filename();
if (output_file.empty())
// Find the file name of the first printable object.
output_file = this->model.propose_export_file_name_and_path();
wxString dlg_title;
switch (file_type) {
case FT_STL: output_file.replace_extension("stl"); break;
case FT_AMF: output_file.replace_extension("zip.amf"); break; // XXX: Problem on OS X with double extension?
case FT_3MF: output_file.replace_extension("3mf"); break;
case FT_STL:
{
output_file.replace_extension("stl");
dlg_title = _(L("Export STL file:"));
break;
}
case FT_AMF:
{
// XXX: Problem on OS X with double extension?
output_file.replace_extension("zip.amf");
dlg_title = _(L("Export AMF file:"));
break;
}
case FT_3MF:
{
output_file.replace_extension("3mf");
dlg_title = _(L("Save file as:"));
break;
}
default: break;
}
auto dlg = Slic3r::make_unique<CheckboxFileDialog>(q,
((file_type == FT_AMF) || (file_type == FT_3MF)) ? _(L("Export print config")) : "",
true,
_(L("Save file as:")),
from_path(output_file.parent_path()),
from_path(output_file.filename()),
wildcard,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
);
wxFileDialog* dlg = new wxFileDialog(q, dlg_title,
from_path(output_file.parent_path()), from_path(output_file.filename()),
wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (dlg->ShowModal() != wxID_OK) {
return nullptr;
return wxEmptyString;
}
fs::path path(into_path(dlg->GetPath()));
wxString out_path = dlg->GetPath();
fs::path path(into_path(out_path));
wxGetApp().app_config->update_last_output_dir(path.parent_path().string());
return dlg;
return out_path;
}
const Selection& Plater::priv::get_selection() const
@ -2039,7 +2102,9 @@ void Plater::priv::sla_optimize_rotation() {
rotoptimizing.store(true);
int obj_idx = get_selected_object_idx();
ModelObject * o = model.objects[obj_idx];
if(obj_idx < 0) { rotoptimizing.store(false); return; }
ModelObject * o = model.objects[size_t(obj_idx)];
background_process.stop();
@ -2047,7 +2112,7 @@ void Plater::priv::sla_optimize_rotation() {
statusbar()->set_range(100);
auto stfn = [this] (unsigned st, const std::string& msg) {
statusbar()->set_progress(st);
statusbar()->set_progress(int(st));
statusbar()->set_status_text(msg);
// could be problematic, but we need the cancel button.
@ -2065,8 +2130,59 @@ void Plater::priv::sla_optimize_rotation() {
[this](){ return !rotoptimizing.load(); }
);
const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape");
assert(bed_shape_opt);
auto& bedpoints = bed_shape_opt->values;
Polyline bed; bed.points.reserve(bedpoints.size());
for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
double mindist = 6.0; // FIXME
double offs = mindist / 2.0 - EPSILON;
if(rotoptimizing.load()) // wasn't canceled
for(ModelInstance * oi : o->instances) oi->set_rotation({r[X], r[Y], r[Z]});
for(ModelInstance * oi : o->instances) {
oi->set_rotation({r[X], r[Y], r[Z]});
auto trchull = o->convex_hull_2d(oi->get_transformation().get_matrix());
namespace opt = libnest2d::opt;
opt::StopCriteria stopcr;
stopcr.relative_score_difference = 0.01;
stopcr.max_iterations = 10000;
stopcr.stop_score = 0.0;
opt::GeneticOptimizer solver(stopcr);
Polygon pbed(bed);
auto bin = pbed.bounding_box();
double binw = bin.size()(X) * SCALING_FACTOR - offs;
double binh = bin.size()(Y) * SCALING_FACTOR - offs;
auto result = solver.optimize_min([&trchull, binw, binh](double rot){
auto chull = trchull;
chull.rotate(rot);
auto bb = chull.bounding_box();
double bbw = bb.size()(X) * SCALING_FACTOR;
double bbh = bb.size()(Y) * SCALING_FACTOR;
auto wdiff = bbw - binw;
auto hdiff = bbh - binh;
double diff = 0;
if(wdiff < 0 && hdiff < 0) diff = wdiff + hdiff;
if(wdiff > 0) diff += wdiff;
if(hdiff > 0) diff += hdiff;
return diff;
}, opt::initvals(0.0), opt::bound(-PI/2, PI/2));
double r = std::get<0>(result.optimum);
Vec3d rt = oi->get_rotation(); rt(Z) += r;
oi->set_rotation(rt);
}
arr::find_new_position(model, o->instances, coord_t(mindist/SCALING_FACTOR), bed);
// Correct the z offset of the object which was corrupted be the rotation
o->ensure_on_bed();
@ -2713,12 +2829,15 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
wxMenuItem* item_delete = nullptr;
if (is_part) {
item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
[this](wxCommandEvent&) { q->remove_selected(); }, "brick_delete.png");
} else {
[this](wxCommandEvent&) { q->remove_selected(); }, "remove");
sidebar->obj_list()->append_menu_item_export_stl(menu);
}
else {
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")),
[this](wxCommandEvent&) { q->increase_instances(); }, "add.png");
[this](wxCommandEvent&) { q->increase_instances(); }, "instance_add");
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")),
[this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
[this](wxCommandEvent&) { q->decrease_instances(); }, "instance_remove");
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
@ -2728,7 +2847,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
[this](wxCommandEvent&) { q->remove_selected(); }, "brick_delete.png");
[this](wxCommandEvent&) { q->remove_selected(); }, "remove");
menu->AppendSeparator();
wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu);
@ -2745,10 +2864,11 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
append_menu_item(menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")),
[this](wxCommandEvent&) { reload_from_disk(); });
append_menu_item(menu, wxID_ANY, _(L("Export object as STL")) + dots, _(L("Export this single object as STL file")),
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")),
[this](wxCommandEvent&) { q->export_stl(true); });
menu->AppendSeparator();
}
menu->AppendSeparator();
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
@ -2782,11 +2902,11 @@ bool Plater::priv::complit_init_object_menu()
return false;
wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")),
[this](wxCommandEvent&) { split_object(); }, "shape_ungroup_o.png", &object_menu);
[this](wxCommandEvent&) { split_object(); }, "split_objects.png", &object_menu);
wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")),
[this](wxCommandEvent&) { split_volume(); }, "shape_ungroup_p.png", &object_menu);
[this](wxCommandEvent&) { split_volume(); }, "split_parts.png", &object_menu);
wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png");
wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object"))/*, "shape_ungroup.png"*/);
object_menu.AppendSeparator();
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
@ -2907,6 +3027,9 @@ bool Plater::priv::can_split() const
bool Plater::priv::layers_height_allowed() const
{
if (printer_technology != ptFFF)
return false;
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed();
}
@ -3243,11 +3366,8 @@ void Plater::export_stl(bool selection_only)
{
if (p->model.objects.empty()) { return; }
auto dialog = p->get_export_file(FT_STL);
if (! dialog) { return; }
// Store a binary STL
const wxString path = dialog->GetPath();
wxString path = p->get_export_file(FT_STL);
if (path.empty()) { return; }
const std::string path_u8 = into_u8(path);
wxBusyCursor wait;
@ -3259,10 +3379,25 @@ void Plater::export_stl(bool selection_only)
const auto obj_idx = selection.get_object_idx();
if (obj_idx == -1) { return; }
mesh = p->model.objects[obj_idx]->mesh();
} else {
mesh = p->model.mesh();
const ModelObject* model_object = p->model.objects[obj_idx];
if (selection.get_mode() == Selection::Instance)
{
if (selection.is_single_full_object())
mesh = model_object->mesh();
else
mesh = model_object->full_raw_mesh();
}
else
{
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
mesh = model_object->volumes[volume->volume_idx()]->mesh;
mesh.transform(volume->get_volume_transformation().get_matrix());
mesh.translate(-model_object->origin_translation.cast<float>());
}
}
else
mesh = p->model.mesh();
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path));
@ -3272,15 +3407,14 @@ void Plater::export_amf()
{
if (p->model.objects.empty()) { return; }
auto dialog = p->get_export_file(FT_AMF);
if (! dialog) { return; }
const wxString path = dialog->GetPath();
wxString path = p->get_export_file(FT_AMF);
if (path.empty()) { return; }
const std::string path_u8 = into_u8(path);
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
wxBusyCursor wait;
if (Slic3r::store_amf(path_u8.c_str(), &p->model, dialog->get_checkbox_value() ? &cfg : nullptr)) {
bool export_config = true;
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) {
// Success
p->statusbar()->set_status_text(wxString::Format(_(L("AMF file exported to %s")), path));
} else {
@ -3297,10 +3431,8 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
bool export_config = true;
if (output_path.empty())
{
auto dialog = p->get_export_file(FT_3MF);
if (!dialog) { return; }
path = dialog->GetPath();
export_config = dialog->get_checkbox_value();
path = p->get_export_file(FT_3MF);
if (path.empty()) { return; }
}
else
path = from_path(output_path);

View file

@ -4,6 +4,7 @@
#include "AppConfig.hpp"
#include "BitmapCache.hpp"
#include "I18N.hpp"
#include "wxExtensions.hpp"
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
@ -798,12 +799,14 @@ bool PresetCollection::delete_current_preset()
bool PresetCollection::load_bitmap_default(const std::string &file_name)
{
return m_bitmap_main_frame->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
// return m_bitmap_main_frame->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
return load_scaled_bitmap(&m_bitmap_main_frame, file_name);
}
bool PresetCollection::load_bitmap_add(const std::string &file_name)
{
return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
// return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
return load_scaled_bitmap(&m_bitmap_add, file_name);
}
const Preset* PresetCollection::get_selected_preset_parent() const

View file

@ -4,6 +4,7 @@
#include "BitmapCache.hpp"
#include "Plater.hpp"
#include "I18N.hpp"
#include "wxExtensions.hpp"
#include <algorithm>
#include <fstream>
@ -102,13 +103,14 @@ PresetBundle::PresetBundle() :
}
// Load the default preset bitmaps.
this->prints .load_bitmap_default("cog.png");
this->sla_prints .load_bitmap_default("package_green.png");
this->filaments .load_bitmap_default("spool.png");
this->sla_materials.load_bitmap_default("package_green.png");
this->printers .load_bitmap_default("printer_empty.png");
this->printers .load_bitmap_add("add.png");
this->load_compatible_bitmaps();
// #ys_FIXME_to_delete we'll load them later, using em_unit()
// this->prints .load_bitmap_default("cog");
// this->sla_prints .load_bitmap_default("package_green.png");
// this->filaments .load_bitmap_default("spool.png");
// this->sla_materials.load_bitmap_default("package_green.png");
// this->printers .load_bitmap_default("printer_empty.png");
// this->printers .load_bitmap_add("add.png");
// this->load_compatible_bitmaps();
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
this->prints .select_preset(0);
@ -400,14 +402,20 @@ bool PresetBundle::load_compatible_bitmaps()
const std::string path_bitmap_incompatible = "flag-red-icon.png";
const std::string path_bitmap_lock = "sys_lock.png";//"lock.png";
const std::string path_bitmap_lock_open = "sys_unlock.png";//"lock_open.png";
bool loaded_compatible = m_bitmapCompatible ->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_compatible).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_incompatible = m_bitmapIncompatible->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_incompatible).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_lock = m_bitmapLock->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_lock).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_lock_open = m_bitmapLockOpen->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_lock_open).c_str()), wxBITMAP_TYPE_PNG);
// bool loaded_compatible = m_bitmapCompatible ->LoadFile(
// wxString::FromUTF8(Slic3r::var(path_bitmap_compatible).c_str()), wxBITMAP_TYPE_PNG);
// bool loaded_incompatible = m_bitmapIncompatible->LoadFile(
// wxString::FromUTF8(Slic3r::var(path_bitmap_incompatible).c_str()), wxBITMAP_TYPE_PNG);
// bool loaded_lock = m_bitmapLock->LoadFile(
// wxString::FromUTF8(Slic3r::var(path_bitmap_lock).c_str()), wxBITMAP_TYPE_PNG);
// bool loaded_lock_open = m_bitmapLockOpen->LoadFile(
// wxString::FromUTF8(Slic3r::var(path_bitmap_lock_open).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_compatible = load_scaled_bitmap(&m_bitmapCompatible, path_bitmap_compatible);
bool loaded_incompatible = load_scaled_bitmap(&m_bitmapIncompatible,path_bitmap_incompatible);
bool loaded_lock = load_scaled_bitmap(&m_bitmapLock, path_bitmap_lock);
bool loaded_lock_open = load_scaled_bitmap(&m_bitmapLockOpen, path_bitmap_lock_open);
if (loaded_compatible) {
prints .set_bitmap_compatible(m_bitmapCompatible);
filaments .set_bitmap_compatible(m_bitmapCompatible);
@ -1438,6 +1446,17 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out
return true;
}
void PresetBundle::load_default_preset_bitmaps()
{
this->prints.load_bitmap_default("cog");
this->sla_prints.load_bitmap_default("cog");
this->filaments.load_bitmap_default("spool.png");
this->sla_materials.load_bitmap_default("package_green.png");
this->printers.load_bitmap_default("printer");
this->printers.load_bitmap_add("add.png");
this->load_compatible_bitmaps();
}
void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
{
if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA ||

View file

@ -127,6 +127,8 @@ public:
static bool parse_color(const std::string &scolor, unsigned char *rgb_out);
void load_default_preset_bitmaps();
private:
std::string load_system_presets();
// Merge one vendor's presets with the other vendor's presets, report duplicates.

View file

@ -6,6 +6,7 @@
#include "GUI_ObjectManipulation.hpp"
#include "GUI_ObjectList.hpp"
#include "Gizmos/GLGizmoBase.hpp"
#include "slic3r/GUI/3DScene.hpp"
#include <GL/glew.h>
@ -75,7 +76,7 @@ Selection::~Selection()
void Selection::set_volumes(GLVolumePtrs* volumes)
{
m_volumes = volumes;
_update_valid();
update_valid();
}
bool Selection::init(bool useVBOs)
@ -95,7 +96,7 @@ bool Selection::init(bool useVBOs)
void Selection::set_model(Model* model)
{
m_model = model;
_update_valid();
update_valid();
}
void Selection::add(unsigned int volume_idx, bool as_single_selection)
@ -134,18 +135,18 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection)
case Volume:
{
if ((volume->volume_idx() >= 0) && (is_empty() || (volume->instance_idx() == get_instance_idx())))
_add_volume(volume_idx);
do_add_volume(volume_idx);
break;
}
case Instance:
{
_add_instance(volume->object_idx(), volume->instance_idx());
do_add_instance(volume->object_idx(), volume->instance_idx());
break;
}
}
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -160,17 +161,17 @@ void Selection::remove(unsigned int volume_idx)
{
case Volume:
{
_remove_volume(volume_idx);
do_remove_volume(volume_idx);
break;
}
case Instance:
{
_remove_instance(volume->object_idx(), volume->instance_idx());
do_remove_instance(volume->object_idx(), volume->instance_idx());
break;
}
}
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -185,9 +186,9 @@ void Selection::add_object(unsigned int object_idx, bool as_single_selection)
m_mode = Instance;
_add_object(object_idx);
do_add_object(object_idx);
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -196,9 +197,9 @@ void Selection::remove_object(unsigned int object_idx)
if (!m_valid)
return;
_remove_object(object_idx);
do_remove_object(object_idx);
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -213,9 +214,9 @@ void Selection::add_instance(unsigned int object_idx, unsigned int instance_idx,
m_mode = Instance;
_add_instance(object_idx, instance_idx);
do_add_instance(object_idx, instance_idx);
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -224,9 +225,9 @@ void Selection::remove_instance(unsigned int object_idx, unsigned int instance_i
if (!m_valid)
return;
_remove_instance(object_idx, instance_idx);
do_remove_instance(object_idx, instance_idx);
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -247,11 +248,11 @@ void Selection::add_volume(unsigned int object_idx, unsigned int volume_idx, int
if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
{
if ((instance_idx != -1) && (v->instance_idx() == instance_idx))
_add_volume(i);
do_add_volume(i);
}
}
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -264,10 +265,10 @@ void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx)
{
GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
_remove_volume(i);
do_remove_volume(i);
}
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -282,10 +283,10 @@ void Selection::add_all()
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
if (!(*m_volumes)[i]->is_wipe_tower)
_add_volume(i);
do_add_volume(i);
}
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -301,7 +302,7 @@ void Selection::clear()
m_list.clear();
_update_type();
update_type();
m_bounding_box_dirty = true;
// resets the cache in the sidebar
@ -341,11 +342,11 @@ void Selection::volumes_changed(const std::vector<size_t> &map_volume_old_to_new
const GLVolume* volume = (*m_volumes)[i];
for (const std::pair<int, int> &model_instance : model_instances)
if (volume->object_idx() == model_instance.first && volume->instance_idx() == model_instance.second)
this->_add_volume(i);
do_add_volume(i);
}
}
_update_type();
update_type();
m_bounding_box_dirty = true;
}
@ -426,7 +427,7 @@ const GLVolume* Selection::get_volume(unsigned int volume_idx) const
const BoundingBoxf3& Selection::get_bounding_box() const
{
if (m_bounding_box_dirty)
_calc_bounding_box();
calc_bounding_box();
return m_bounding_box;
}
@ -436,7 +437,7 @@ void Selection::start_dragging()
if (!m_valid)
return;
_set_caches();
set_caches();
}
void Selection::translate(const Vec3d& displacement, bool local)
@ -460,7 +461,7 @@ void Selection::translate(const Vec3d& displacement, bool local)
}
else if (m_mode == Instance)
{
if (_is_from_fully_selected_instance(i))
if (is_from_fully_selected_instance(i))
(*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement);
else
{
@ -473,38 +474,14 @@ void Selection::translate(const Vec3d& displacement, bool local)
#if !DISABLE_INSTANCES_SYNCH
if (translation_type == Instance)
_synchronize_unselected_instances(SYNC_ROTATION_NONE);
synchronize_unselected_instances(SYNC_ROTATION_NONE);
else if (translation_type == Volume)
_synchronize_unselected_volumes();
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true;
}
static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
return
// From the current coordinate system to world.
Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
// From world to the initial coordinate system.
Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
}
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Vec3d axis = angle_axis.axis();
double angle = angle_axis.angle();
#ifndef NDEBUG
if (std::abs(angle) > 1e-8) {
assert(std::abs(axis.x()) < 1e-8);
assert(std::abs(axis.y()) < 1e-8);
}
#endif /* NDEBUG */
return (axis.z() < 0) ? -angle : angle;
}
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
{
@ -547,7 +524,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
assert(is_approx(rotation.z(), 0.0));
const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
const Vec3d &rotation = first_volume.get_instance_rotation();
double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
}
else {
@ -604,9 +581,9 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
_synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
else if (m_mode == Volume)
_synchronize_unselected_volumes();
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true;
@ -647,7 +624,7 @@ void Selection::flattening_rotate(const Vec3d& normal)
// we want to synchronize z-rotation as well, otherwise the flattening behaves funny
// when applied on one of several identical instances
if (m_mode == Instance)
_synchronize_unselected_instances(SYNC_ROTATION_FULL);
synchronize_unselected_instances(SYNC_ROTATION_FULL);
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true;
@ -694,12 +671,12 @@ void Selection::scale(const Vec3d& scale, bool local)
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
_synchronize_unselected_instances(SYNC_ROTATION_NONE);
synchronize_unselected_instances(SYNC_ROTATION_NONE);
else if (m_mode == Volume)
_synchronize_unselected_volumes();
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
_ensure_on_bed();
ensure_on_bed();
m_bounding_box_dirty = true;
}
@ -721,9 +698,9 @@ void Selection::mirror(Axis axis)
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
_synchronize_unselected_instances(SYNC_ROTATION_NONE);
synchronize_unselected_instances(SYNC_ROTATION_NONE);
else if (m_mode == Volume)
_synchronize_unselected_volumes();
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true;
@ -941,8 +918,8 @@ void Selection::render(float scale_factor) const
m_scale_factor = scale_factor;
// render cumulative bounding box of selected volumes
_render_selected_volumes();
_render_synchronized_volumes();
render_selected_volumes();
render_synchronized_volumes();
}
#if ENABLE_RENDER_SELECTION_CENTER
@ -953,17 +930,17 @@ void Selection::render_center() const
const Vec3d& center = get_bounding_box().center();
::glDisable(GL_DEPTH_TEST);
glsafe(::glDisable(GL_DEPTH_TEST)));
::glEnable(GL_LIGHTING);
glsafe(::glEnable(GL_LIGHTING));
::glColor3f(1.0f, 1.0f, 1.0f);
::glPushMatrix();
::glTranslated(center(0), center(1), center(2));
::gluSphere(m_quadric, 0.75, 32, 32);
::glPopMatrix();
glsafe(::glColor3f(1.0f, 1.0f, 1.0f));
glsafe(::glPushMatrix());
glsafe(::glTranslated(center(0), center(1), center(2)));
glsafe(::gluSphere(m_quadric, 0.75, 32, 32));
glsafe(::glPopMatrix());
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_LIGHTING));
}
#endif // ENABLE_RENDER_SELECTION_CENTER
@ -972,18 +949,18 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const
if (sidebar_field.empty())
return;
::glClear(GL_DEPTH_BUFFER_BIT);
::glEnable(GL_DEPTH_TEST);
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
::glEnable(GL_LIGHTING);
glsafe(::glEnable(GL_LIGHTING));
::glPushMatrix();
glsafe(::glPushMatrix());
const Vec3d& center = get_bounding_box().center();
if (is_single_full_instance())
{
::glTranslated(center(0), center(1), center(2));
glsafe(::glTranslated(center(0), center(1), center(2)));
if (!boost::starts_with(sidebar_field, "position"))
{
Transform3d orient_matrix = Transform3d::Identity();
@ -1003,40 +980,40 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const
}
}
::glMultMatrixd(orient_matrix.data());
glsafe(::glMultMatrixd(orient_matrix.data()));
}
}
else if (is_single_volume() || is_single_modifier())
{
::glTranslated(center(0), center(1), center(2));
glsafe(::glTranslated(center(0), center(1), center(2)));
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
if (!boost::starts_with(sidebar_field, "position"))
orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
glsafe(::glMultMatrixd(orient_matrix.data()));
}
else
{
::glTranslated(center(0), center(1), center(2));
glsafe(::glTranslated(center(0), center(1), center(2)));
if (requires_local_axes())
{
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
glsafe(::glMultMatrixd(orient_matrix.data()));
}
}
if (boost::starts_with(sidebar_field, "position"))
_render_sidebar_position_hints(sidebar_field);
render_sidebar_position_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "rotation"))
_render_sidebar_rotation_hints(sidebar_field);
render_sidebar_rotation_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "scale"))
_render_sidebar_scale_hints(sidebar_field);
render_sidebar_scale_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "size"))
_render_sidebar_size_hints(sidebar_field);
render_sidebar_size_hints(sidebar_field);
::glPopMatrix();
glsafe(::glPopMatrix());
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_LIGHTING));
}
bool Selection::requires_local_axes() const
@ -1044,12 +1021,12 @@ bool Selection::requires_local_axes() const
return (m_mode == Volume) && is_from_single_instance();
}
void Selection::_update_valid()
void Selection::update_valid()
{
m_valid = (m_volumes != nullptr) && (m_model != nullptr);
}
void Selection::_update_type()
void Selection::update_type()
{
m_cache.content.clear();
m_type = Mixed;
@ -1147,15 +1124,11 @@ void Selection::_update_type()
}
if (modifiers_count == 0)
{
m_type = MultipleVolume;
requires_disable = true;
}
else if (modifiers_count == (unsigned int)m_list.size())
{
m_type = MultipleModifier;
requires_disable = true;
}
requires_disable = true;
}
}
else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size()))
@ -1277,7 +1250,7 @@ void Selection::_update_type()
#endif // ENABLE_SELECTION_DEBUG_OUTPUT
}
void Selection::_set_caches()
void Selection::set_caches()
{
m_cache.volumes_data.clear();
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
@ -1288,33 +1261,33 @@ void Selection::_set_caches()
m_cache.dragging_center = get_bounding_box().center();
}
void Selection::_add_volume(unsigned int volume_idx)
void Selection::do_add_volume(unsigned int volume_idx)
{
m_list.insert(volume_idx);
(*m_volumes)[volume_idx]->selected = true;
}
void Selection::_add_instance(unsigned int object_idx, unsigned int instance_idx)
void Selection::do_add_instance(unsigned int object_idx, unsigned int instance_idx)
{
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
_add_volume(i);
do_add_volume(i);
}
}
void Selection::_add_object(unsigned int object_idx)
void Selection::do_add_object(unsigned int object_idx)
{
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
if (v->object_idx() == object_idx)
_add_volume(i);
do_add_volume(i);
}
}
void Selection::_remove_volume(unsigned int volume_idx)
void Selection::do_remove_volume(unsigned int volume_idx)
{
IndicesList::iterator v_it = m_list.find(volume_idx);
if (v_it == m_list.end())
@ -1325,27 +1298,27 @@ void Selection::_remove_volume(unsigned int volume_idx)
(*m_volumes)[volume_idx]->selected = false;
}
void Selection::_remove_instance(unsigned int object_idx, unsigned int instance_idx)
void Selection::do_remove_instance(unsigned int object_idx, unsigned int instance_idx)
{
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
_remove_volume(i);
do_remove_volume(i);
}
}
void Selection::_remove_object(unsigned int object_idx)
void Selection::do_remove_object(unsigned int object_idx)
{
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
if (v->object_idx() == object_idx)
_remove_volume(i);
do_remove_volume(i);
}
}
void Selection::_calc_bounding_box() const
void Selection::calc_bounding_box() const
{
m_bounding_box = BoundingBoxf3();
if (m_valid)
@ -1358,13 +1331,13 @@ void Selection::_calc_bounding_box() const
m_bounding_box_dirty = false;
}
void Selection::_render_selected_volumes() const
void Selection::render_selected_volumes() const
{
float color[3] = { 1.0f, 1.0f, 1.0f };
_render_bounding_box(get_bounding_box(), color);
render_bounding_box(get_bounding_box(), color);
}
void Selection::_render_synchronized_volumes() const
void Selection::render_synchronized_volumes() const
{
if (m_mode == Instance)
return;
@ -1386,12 +1359,12 @@ void Selection::_render_synchronized_volumes() const
if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
continue;
_render_bounding_box(v->transformed_convex_hull_bounding_box(), color);
render_bounding_box(v->transformed_convex_hull_bounding_box(), color);
}
}
}
void Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) const
void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) const
{
if (color == nullptr)
return;
@ -1400,10 +1373,10 @@ void Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) con
Vec3f b_max = box.max.cast<float>();
Vec3f size = 0.2f * box.size().cast<float>();
::glEnable(GL_DEPTH_TEST);
glsafe(::glEnable(GL_DEPTH_TEST));
::glColor3fv(color);
::glLineWidth(2.0f * m_scale_factor);
glsafe(::glColor3fv(color));
glsafe(::glLineWidth(2.0f * m_scale_factor));
::glBegin(GL_LINES);
@ -1439,109 +1412,109 @@ void Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) con
::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_max(2));
::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1), b_max(2) - size(2));
::glEnd();
glsafe(::glEnd());
}
void Selection::_render_sidebar_position_hints(const std::string& sidebar_field) const
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const
{
if (boost::ends_with(sidebar_field, "x"))
{
::glRotated(-90.0, 0.0, 0.0, 1.0);
_render_sidebar_position_hint(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);
render_sidebar_position_hint(Y);
else if (boost::ends_with(sidebar_field, "z"))
{
::glRotated(90.0, 1.0, 0.0, 0.0);
_render_sidebar_position_hint(Z);
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
render_sidebar_position_hint(Z);
}
}
void Selection::_render_sidebar_rotation_hints(const std::string& sidebar_field) const
void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const
{
if (boost::ends_with(sidebar_field, "x"))
{
::glRotated(90.0, 0.0, 1.0, 0.0);
_render_sidebar_rotation_hint(X);
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
render_sidebar_rotation_hint(X);
}
else if (boost::ends_with(sidebar_field, "y"))
{
::glRotated(-90.0, 1.0, 0.0, 0.0);
_render_sidebar_rotation_hint(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);
render_sidebar_rotation_hint(Z);
}
void Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) const
{
bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
if (boost::ends_with(sidebar_field, "x") || uniform_scale)
{
::glPushMatrix();
::glRotated(-90.0, 0.0, 0.0, 1.0);
_render_sidebar_scale_hint(X);
::glPopMatrix();
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)
{
::glPushMatrix();
_render_sidebar_scale_hint(Y);
::glPopMatrix();
glsafe(::glPushMatrix());
render_sidebar_scale_hint(Y);
glsafe(::glPopMatrix());
}
if (boost::ends_with(sidebar_field, "z") || uniform_scale)
{
::glPushMatrix();
::glRotated(90.0, 1.0, 0.0, 0.0);
_render_sidebar_scale_hint(Z);
::glPopMatrix();
glsafe(::glPushMatrix());
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
render_sidebar_scale_hint(Z);
glsafe(::glPopMatrix());
}
}
void Selection::_render_sidebar_size_hints(const std::string& sidebar_field) const
void Selection::render_sidebar_size_hints(const std::string& sidebar_field) const
{
_render_sidebar_scale_hints(sidebar_field);
render_sidebar_scale_hints(sidebar_field);
}
void Selection::_render_sidebar_position_hint(Axis axis) const
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
void Selection::render_sidebar_rotation_hint(Axis axis) const
{
m_curved_arrow.set_color(AXES_COLOR[axis], 3);
m_curved_arrow.render();
::glRotated(180.0, 0.0, 0.0, 1.0);
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
m_curved_arrow.render();
}
void Selection::_render_sidebar_scale_hint(Axis axis) const
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);
::glTranslated(0.0, 5.0, 0.0);
glsafe(::glTranslated(0.0, 5.0, 0.0));
m_arrow.render();
::glTranslated(0.0, -10.0, 0.0);
::glRotated(180.0, 0.0, 0.0, 1.0);
glsafe(::glTranslated(0.0, -10.0, 0.0));
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
m_arrow.render();
}
void Selection::_render_sidebar_size_hint(Axis axis, double length) const
void Selection::render_sidebar_size_hint(Axis axis, double length) const
{
}
#ifndef NDEBUG
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Vec3d axis = angle_axis.axis();
double angle = angle_axis.angle();
if (std::abs(angle) < 1e-8)
@ -1575,7 +1548,7 @@ static void verify_instances_rotation_synchronized(const Model &model, const GLV
}
#endif /* NDEBUG */
void Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type)
void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_type)
{
std::set<unsigned int> done; // prevent processing volumes twice
done.insert(m_list.begin(), m_list.end());
@ -1621,7 +1594,7 @@ void Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation
break;
case SYNC_ROTATION_GENERAL:
// generic rotation -> update instance z with the delta of the rotation.
double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
break;
}
@ -1638,7 +1611,7 @@ void Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation
#endif /* NDEBUG */
}
void Selection::_synchronize_unselected_volumes()
void Selection::synchronize_unselected_volumes()
{
for (unsigned int i : m_list)
{
@ -1671,7 +1644,7 @@ void Selection::_synchronize_unselected_volumes()
}
}
void Selection::_ensure_on_bed()
void Selection::ensure_on_bed()
{
typedef std::map<std::pair<int, int>, double> InstancesToZMap;
InstancesToZMap instances_min_z;
@ -1699,7 +1672,7 @@ void Selection::_ensure_on_bed()
}
}
bool Selection::_is_from_fully_selected_instance(unsigned int volume_idx) const
bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const
{
struct SameInstance
{

View file

@ -133,10 +133,12 @@ private:
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
};
public:
typedef std::map<unsigned int, VolumeCache> VolumesCache;
typedef std::set<int> InstanceIdxsList;
typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
private:
struct Cache
{
// Cache of GLVolume derived transformation matrices, valid during mouse dragging.
@ -265,27 +267,27 @@ public:
bool requires_local_axes() const;
private:
void _update_valid();
void _update_type();
void _set_caches();
void _add_volume(unsigned int volume_idx);
void _add_instance(unsigned int object_idx, unsigned int instance_idx);
void _add_object(unsigned int object_idx);
void _remove_volume(unsigned int volume_idx);
void _remove_instance(unsigned int object_idx, unsigned int instance_idx);
void _remove_object(unsigned int object_idx);
void _calc_bounding_box() const;
void _render_selected_volumes() const;
void _render_synchronized_volumes() const;
void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
void _render_sidebar_position_hints(const std::string& sidebar_field) const;
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_size_hints(const std::string& sidebar_field) const;
void _render_sidebar_position_hint(Axis axis) const;
void _render_sidebar_rotation_hint(Axis axis) const;
void _render_sidebar_scale_hint(Axis axis) const;
void _render_sidebar_size_hint(Axis axis, double length) const;
void update_valid();
void update_type();
void set_caches();
void do_add_volume(unsigned int volume_idx);
void do_add_instance(unsigned int object_idx, unsigned int instance_idx);
void do_add_object(unsigned int object_idx);
void do_remove_volume(unsigned int volume_idx);
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx);
void do_remove_object(unsigned int object_idx);
void calc_bounding_box() const;
void render_selected_volumes() const;
void render_synchronized_volumes() const;
void render_bounding_box(const BoundingBoxf3& box, float* color) const;
void render_sidebar_position_hints(const std::string& sidebar_field) const;
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_size_hints(const std::string& sidebar_field) const;
void render_sidebar_position_hint(Axis axis) const;
void render_sidebar_rotation_hint(Axis axis) const;
void render_sidebar_scale_hint(Axis axis) const;
void render_sidebar_size_hint(Axis axis, double length) const;
enum SyncRotationType {
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
SYNC_ROTATION_NONE = 0,
@ -294,10 +296,10 @@ private:
// Synchronize after rotation by an axis not parallel with Z.
SYNC_ROTATION_GENERAL = 2,
};
void _synchronize_unselected_instances(SyncRotationType sync_rotation_type);
void _synchronize_unselected_volumes();
void _ensure_on_bed();
bool _is_from_fully_selected_instance(unsigned int volume_idx) const;
void synchronize_unselected_instances(SyncRotationType sync_rotation_type);
void synchronize_unselected_volumes();
void ensure_on_bed();
bool is_from_fully_selected_instance(unsigned int volume_idx) const;
};
} // namespace GUI

View file

@ -52,9 +52,7 @@ SysInfoDialog::SysInfoDialog()
main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10);
// logo
// wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG);
// auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png"));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png", 192));
hsizer->Add(logo, 0, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);

View file

@ -116,18 +116,14 @@ void Tab::create_preset_tab()
//buttons
wxBitmap bmpMenu;
// bmpMenu = wxBitmap(from_u8(Slic3r::var("disk.png")), wxBITMAP_TYPE_PNG);
bmpMenu = create_scaled_bitmap("disk.png");
m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
if (wxMSW) m_btn_save_preset->SetBackgroundColour(color);
// bmpMenu = wxBitmap(from_u8(Slic3r::var("delete.png")), wxBITMAP_TYPE_PNG);
bmpMenu = create_scaled_bitmap("delete.png");
m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color);
m_show_incompatible_presets = false;
// m_bmp_show_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG);
// m_bmp_hide_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG);
m_bmp_show_incompatible_presets = create_scaled_bitmap("flag-red-icon.png");
m_bmp_hide_incompatible_presets = create_scaled_bitmap("flag-green-icon.png");
m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
@ -152,15 +148,10 @@ void Tab::create_preset_tab()
// Determine the theme color of OS (dark or light)
auto luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
// m_bmp_value_lock .LoadFile(from_u8(var("sys_lock.png")), wxBITMAP_TYPE_PNG);
// m_bmp_value_unlock .LoadFile(from_u8(var(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png")), wxBITMAP_TYPE_PNG);
m_bmp_value_lock = create_scaled_bitmap("sys_lock.png");
m_bmp_value_unlock = create_scaled_bitmap(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png");
m_bmp_non_system = &m_bmp_white_bullet;
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
// m_bmp_value_revert .LoadFile(from_u8(var(luma >= 128 ? "action_undo.png" : "action_undo_grey.png")), wxBITMAP_TYPE_PNG);
// m_bmp_white_bullet .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
// m_bmp_question .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
m_bmp_value_revert = create_scaled_bitmap(luma >= 128 ? "action_undo.png" : "action_undo_grey.png");
m_bmp_white_bullet = create_scaled_bitmap("bullet_white.png");
m_bmp_question = create_scaled_bitmap("question_mark_01.png");
@ -954,7 +945,7 @@ void TabPrint::build()
m_presets = &m_preset_bundle->prints;
load_initial_data();
auto page = add_options_page(_(L("Layers and perimeters")), "layers.png");
auto page = add_options_page(_(L("Layers and perimeters")), "layers");
auto optgroup = page->new_optgroup(_(L("Layer height")));
optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("first_layer_height");
@ -987,7 +978,7 @@ void TabPrint::build()
optgroup->append_single_option_line("seam_position");
optgroup->append_single_option_line("external_perimeters_first");
page = add_options_page(_(L("Infill")), "infill.png");
page = add_options_page(_(L("Infill")), "infill");
optgroup = page->new_optgroup(_(L("Infill")));
optgroup->append_single_option_line("fill_density");
optgroup->append_single_option_line("fill_pattern");
@ -1006,7 +997,7 @@ void TabPrint::build()
optgroup->append_single_option_line("only_retract_when_crossing_perimeters");
optgroup->append_single_option_line("infill_first");
page = add_options_page(_(L("Skirt and brim")), "box.png");
page = add_options_page(_(L("Skirt and brim")), "skirt+brim");
optgroup = page->new_optgroup(_(L("Skirt")));
optgroup->append_single_option_line("skirts");
optgroup->append_single_option_line("skirt_distance");
@ -1016,7 +1007,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Brim")));
optgroup->append_single_option_line("brim_width");
page = add_options_page(_(L("Support material")), "building.png");
page = add_options_page(_(L("Support material")), "support");
optgroup = page->new_optgroup(_(L("Support material")));
optgroup->append_single_option_line("support_material");
optgroup->append_single_option_line("support_material_auto");
@ -1041,7 +1032,7 @@ void TabPrint::build()
optgroup->append_single_option_line("dont_support_bridges");
optgroup->append_single_option_line("support_material_synchronize_layers");
page = add_options_page(_(L("Speed")), "time.png");
page = add_options_page(_(L("Speed")), "time");
optgroup = page->new_optgroup(_(L("Speed for print moves")));
optgroup->append_single_option_line("perimeter_speed");
optgroup->append_single_option_line("small_perimeter_speed");
@ -1075,7 +1066,7 @@ void TabPrint::build()
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative");
#endif /* HAS_PRESSURE_EQUALIZER */
page = add_options_page(_(L("Multiple Extruders")), "funnel.png");
page = add_options_page(_(L("Multiple Extruders")), "funnel");
optgroup = page->new_optgroup(_(L("Extruders")));
optgroup->append_single_option_line("perimeter_extruder");
optgroup->append_single_option_line("infill_extruder");
@ -1125,7 +1116,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Other")));
optgroup->append_single_option_line("clip_multipart_objects");
page = add_options_page(_(L("Output options")), "page_white_go.png");
page = add_options_page(_(L("Output options")), "output+page_white");
optgroup = page->new_optgroup(_(L("Sequential printing")));
optgroup->append_single_option_line("complete_objects");
line = { _(L("Extruder clearance (mm)")), "" };
@ -1446,7 +1437,7 @@ void TabFilament::build()
line.append_option(optgroup->get_option("bed_temperature"));
optgroup->append_line(line);
page = add_options_page(_(L("Cooling")), "hourglass.png");
page = add_options_page(_(L("Cooling")), "cooling");
optgroup = page->new_optgroup(_(L("Enable")));
optgroup->append_single_option_line("fan_always_on");
optgroup->append_single_option_line("cooling");
@ -1520,7 +1511,7 @@ void TabFilament::build()
const int gcode_field_height = 15 * m_em_unit; // 150
const int notes_field_height = 25 * m_em_unit; // 250
page = add_options_page(_(L("Custom G-code")), "cog.png");
page = add_options_page(_(L("Custom G-code")), "cog");
optgroup = page->new_optgroup(_(L("Start G-code")), 0);
Option option = optgroup->get_option("start_filament_gcode");
option.opt.full_width = true;
@ -1638,7 +1629,8 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
}
auto printhost_browse = [=](wxWindow* parent) {
auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots,
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap("zoom.png"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -1695,7 +1687,6 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
// btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG));
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap("zoom.png"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -1768,15 +1759,14 @@ void TabPrinter::build_fff()
m_sys_extruders_count = parent_preset == nullptr ? 0 :
static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size();
auto page = add_options_page(_(L("General")), "printer_empty.png");
auto page = add_options_page(_(L("General")), "printer");
auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(wxGetApp().small_font());
// btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
btn->SetBitmap(create_scaled_bitmap("printer_empty.png"));
btn->SetBitmap(create_scaled_bitmap("printer"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -1905,7 +1895,7 @@ void TabPrinter::build_fff()
const int gcode_field_height = 15 * m_em_unit; // 150
const int notes_field_height = 25 * m_em_unit; // 250
page = add_options_page(_(L("Custom G-code")), "cog.png");
page = add_options_page(_(L("Custom G-code")), "cog");
optgroup = page->new_optgroup(_(L("Start G-code")), 0);
option = optgroup->get_option("start_gcode");
option.opt.full_width = true;
@ -1970,15 +1960,14 @@ void TabPrinter::build_sla()
{
if (!m_pages.empty())
m_pages.resize(0);
auto page = add_options_page(_(L("General")), "printer_empty.png");
auto page = add_options_page(_(L("General")), "printer");
auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(wxGetApp().small_font());
// btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
btn->SetBitmap(create_scaled_bitmap("printer_empty.png"));
btn->SetBitmap(create_scaled_bitmap("printer"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -2080,7 +2069,7 @@ void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::s
PageShp TabPrinter::build_kinematics_page()
{
auto page = add_options_page(_(L("Machine limits")), "cog.png", true);
auto page = add_options_page(_(L("Machine limits")), "cog", true);
if (m_use_silent_mode) {
// Legend for OptionsGroups
@ -2172,7 +2161,7 @@ void TabPrinter::build_extruder_pages()
}
if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material") && !m_has_single_extruder_MM_page) {
// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png", true);
auto page = add_options_page(_(L("Single extruder MM setup")), "printer", true);
auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters")));
optgroup->append_single_option_line("cooling_tube_retraction");
optgroup->append_single_option_line("cooling_tube_length");
@ -2188,7 +2177,7 @@ void TabPrinter::build_extruder_pages()
//# build page
char buf[512];
sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1);
auto page = add_options_page(from_u8(buf), "funnel.png", true);
auto page = add_options_page(from_u8(buf), "funnel", true);
m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page);
auto optgroup = page->new_optgroup(_(L("Size")));
@ -2920,8 +2909,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
deps.btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
// deps.btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
deps.btn->SetBitmap(create_scaled_bitmap("printer_empty.png"));
deps.btn->SetBitmap(create_scaled_bitmap("printer"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL);
@ -3112,7 +3100,6 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
bmp_name = mode == comExpert ? "mode_expert_.png" :
mode == comAdvanced ? "mode_middle_.png" : "mode_simple_.png";
}
// auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG));
auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : create_scaled_bitmap(bmp_name));
bmp->SetBackgroundStyle(wxBG_STYLE_PAINT);
return bmp;
@ -3311,13 +3298,13 @@ void TabSLAPrint::build()
m_presets = &m_preset_bundle->sla_prints;
load_initial_data();
auto page = add_options_page(_(L("Layers and perimeters")), "package_green.png");
auto page = add_options_page(_(L("Layers and perimeters")), "layers");
auto optgroup = page->new_optgroup(_(L("Layers")));
optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("faded_layers");
page = add_options_page(_(L("Supports")), "building.png");
page = add_options_page(_(L("Supports")), "sla_supports");
optgroup = page->new_optgroup(_(L("Supports")));
optgroup->append_single_option_line("supports_enable");
@ -3355,17 +3342,17 @@ void TabSLAPrint::build()
// optgroup->append_single_option_line("pad_edge_radius");
optgroup->append_single_option_line("pad_wall_slope");
page = add_options_page(_(L("Advanced")), "wrench.png");
page = add_options_page(_(L("Advanced")), "wrench");
optgroup = page->new_optgroup(_(L("Slicing")));
optgroup->append_single_option_line("slice_closing_radius");
page = add_options_page(_(L("Output options")), "page_white_go.png");
page = add_options_page(_(L("Output options")), "output+page_white");
optgroup = page->new_optgroup(_(L("Output file")));
Option option = optgroup->get_option("output_filename_format");
option.opt.full_width = true;
optgroup->append_single_option_line(option);
page = add_options_page(_(L("Dependencies")), "wrench.png");
page = add_options_page(_(L("Dependencies")), "wrench");
optgroup = page->new_optgroup(_(L("Profile dependencies")));
Line line = optgroup->create_single_option_line("compatible_printers");//Line { _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent) {

View file

@ -8,6 +8,8 @@
#include <wx/dcclient.h>
#include <wx/numformatter.h>
#include <boost/algorithm/string/replace.hpp>
#include "BitmapCache.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
@ -416,31 +418,42 @@ void PrusaCollapsiblePaneMSW::Collapse(bool collapse)
}
#endif //__WXMSW__
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
bool load_scaled_bitmap(wxBitmap** bmp, const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /*= false*/)
{
static Slic3r::GUI::BitmapCache cache;
unsigned int height, width = height = 0;
unsigned int& scale_base = is_horizontal ? width : height;
scale_base = (unsigned int)(Slic3r::GUI::wxGetApp().em_unit() * px_cnt * 0.1f + 0.5f);
std::string bmp_name = bmp_name_in;
boost::replace_last(bmp_name, ".png", "");
*bmp = cache.load_svg(bmp_name, width, height);
if (*bmp == nullptr)
*bmp = cache.load_png(bmp_name, width, height);
return *bmp != nullptr;
}
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
wxBitmap create_scaled_bitmap(const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /* = false*/)
{
wxBitmap *bmp {nullptr};
load_scaled_bitmap(&bmp, bmp_name_in, px_cnt, is_horizontal);
return *bmp;
}
// *****************************************************************************
// ----------------------------------------------------------------------------
// PrusaObjectDataViewModelNode
// ----------------------------------------------------------------------------
wxBitmap create_scaled_bitmap(const std::string& bmp_name)
{
const double scale_f = Slic3r::GUI::wxGetApp().em_unit()* 0.1;//GetContentScaleFactor();
if (scale_f == 1.0)
return wxBitmap(Slic3r::GUI::from_u8(Slic3r::var(bmp_name)), wxBITMAP_TYPE_PNG);
// else if (scale_f == 2.0) // use biger icon
// return wxBitmap(Slic3r::GUI::from_u8(Slic3r::var(bmp_name_X2)), wxBITMAP_TYPE_PNG);
wxImage img = wxImage(Slic3r::GUI::from_u8(Slic3r::var(bmp_name)), wxBITMAP_TYPE_PNG);
const int sz_w = int(img.GetWidth()*scale_f);
const int sz_h = int(img.GetHeight()*scale_f);
img.Rescale(sz_w, sz_h, wxIMAGE_QUALITY_BILINEAR);
return wxBitmap(img);
}
void PrusaObjectDataViewModelNode::set_object_action_icon() {
m_action_icon = create_scaled_bitmap("add_object.png");
}
void PrusaObjectDataViewModelNode::set_part_action_icon() {
m_action_icon = create_scaled_bitmap(m_type == itVolume ? "cog.png" : "brick_go.png");
m_action_icon = create_scaled_bitmap(m_type == itVolume ? "cog" : "brick_go.png");
}
Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
@ -1239,6 +1252,32 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent,
return count;
}
void PrusaObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const
{
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)parent.GetID();
if (!node) {
for (auto object : m_objects)
array.Add(wxDataViewItem((void*)object));
}
else if (node->GetChildCount() == 0)
return;
else {
const size_t count = node->GetChildren().GetCount();
for (size_t pos = 0; pos < count; pos++) {
PrusaObjectDataViewModelNode *child = node->GetChildren().Item(pos);
array.Add(wxDataViewItem((void*)child));
}
}
wxDataViewItemArray new_array = array;
for (const auto item : new_array)
{
wxDataViewItemArray children;
GetAllChildren(item, children);
WX_APPEND_ARRAY(array, children);
}
}
ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const
{
if (!item.IsOk())
@ -1456,8 +1495,8 @@ PrusaDoubleSlider::PrusaDoubleSlider(wxWindow *parent,
if (!is_osx)
SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
m_bmp_thumb_higher = wxBitmap(create_scaled_bitmap(style == wxSL_HORIZONTAL ? "right_half_circle.png" : "up_half_circle.png"));
m_bmp_thumb_lower = wxBitmap(create_scaled_bitmap(style == wxSL_HORIZONTAL ? "left_half_circle.png" : "down_half_circle.png"));
m_bmp_thumb_higher = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap("right_half_circle.png") : create_scaled_bitmap("up_half_circle.png", 16, true));
m_bmp_thumb_lower = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap("left_half_circle.png" ) : create_scaled_bitmap("down_half_circle.png",16, true));
m_thumb_size = m_bmp_thumb_lower.GetSize();
m_bmp_add_tick_on = create_scaled_bitmap("colorchange_add_on.png");

View file

@ -31,7 +31,8 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin
wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
wxBitmap create_scaled_bitmap(const std::string& bmp_name);
bool load_scaled_bitmap(wxBitmap** bmp, const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false);
wxBitmap create_scaled_bitmap(const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false);
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
{
@ -511,7 +512,7 @@ public:
virtual bool IsContainer(const wxDataViewItem &item) const override;
virtual 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; }