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

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/slic3r/GUI/GLCanvas3D.cpp')
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp1263
1 files changed, 707 insertions, 556 deletions
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 48e87f66e..9a63986c5 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -2,6 +2,7 @@
#include "GLCanvas3D.hpp"
#include "admesh/stl.h"
+#include "polypartition.h"
#include "libslic3r/libslic3r.h"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/PrintConfig.hpp"
@@ -72,11 +73,8 @@ static const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f };
static const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f };
static const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f };
-
-#if ENABLE_SIDEBAR_VISUAL_HINTS
static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f };
static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
namespace Slic3r {
namespace GUI {
@@ -299,9 +297,16 @@ std::string GLCanvas3D::Camera::get_type_as_string() const
};
}
-void GLCanvas3D::Camera::set_theta(float theta)
+void GLCanvas3D::Camera::set_theta(float theta, bool apply_limit)
{
- m_theta = clamp(0.0f, GIMBALL_LOCK_THETA_MAX, theta);
+ if (apply_limit)
+ m_theta = clamp(0.0f, GIMBALL_LOCK_THETA_MAX, theta);
+ else
+ {
+ m_theta = fmod(theta, 360.0f);
+ if (m_theta < 0.0f)
+ m_theta += 360.0f;
+ }
}
void GLCanvas3D::Camera::set_target(const Vec3d& target, GLCanvas3D& canvas)
@@ -513,14 +518,13 @@ GLCanvas3D::Bed::EType GLCanvas3D::Bed::_detect_type() const
{
if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research"))
{
- if (boost::contains(curr->name, "MK2"))
+ if (boost::contains(curr->name, "MK3") || boost::contains(curr->name, "MK2.5"))
{
- type = MK2;
+ type = MK3;
break;
- }
- else if (boost::contains(curr->name, "MK3"))
+ } else if (boost::contains(curr->name, "MK2"))
{
- type = MK3;
+ type = MK2;
break;
}
}
@@ -545,6 +549,11 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
std::string model_path = resources_dir() + "/models/" + key;
#endif // ENABLE_PRINT_BED_MODELS
+#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+ GLfloat max_anisotropy = 0.0f;
+ ::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
+#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+
std::string filename = tex_path + "_top.png";
if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))
{
@@ -553,6 +562,14 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
_render_custom();
return;
}
+#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+ if (max_anisotropy > 0.0f)
+ {
+ ::glBindTexture(GL_TEXTURE_2D, m_top_texture.get_id());
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+ }
+#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
}
filename = tex_path + "_bottom.png";
@@ -563,14 +580,28 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
_render_custom();
return;
}
+#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
+ if (max_anisotropy > 0.0f)
+ {
+ ::glBindTexture(GL_TEXTURE_2D, m_bottom_texture.get_id());
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+ }
+#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
}
#if ENABLE_PRINT_BED_MODELS
if (theta <= 90.0f)
{
filename = model_path + "_bed.stl";
- if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs))
- m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 1.0 + 0.5 * m_model.get_bounding_box().size()(2)));
+ if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs)) {
+ Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.1 + 0.5 * m_model.get_bounding_box().size()(2));
+ if (key == "mk2")
+ offset.y() += 15. / 2.;
+ else if (key == "mk3")
+ offset += Vec3d(0., (19. - 8.) / 2., 2.);
+ m_model.center_around(offset);
+ }
if (!m_model.get_filename().empty())
{
@@ -819,12 +850,16 @@ GLCanvas3D::LayersEditing::LayersEditing()
: m_use_legacy_opengl(false)
, m_enabled(false)
, m_z_texture_id(0)
+ , m_model_object(nullptr)
+ , m_object_max_z(0.f)
+ , m_slicing_parameters(nullptr)
+ , m_layer_height_profile_modified(false)
, state(Unknown)
, band_width(2.0f)
, strength(0.005f)
, last_object_id(-1)
, last_z(0.0f)
- , last_action(0)
+ , last_action(LAYER_HEIGHT_EDIT_ACTION_INCREASE)
{
}
@@ -835,6 +870,7 @@ GLCanvas3D::LayersEditing::~LayersEditing()
::glDeleteTextures(1, &m_z_texture_id);
m_z_texture_id = 0;
}
+ delete m_slicing_parameters;
}
bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename)
@@ -854,9 +890,32 @@ bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename,
return true;
}
+void GLCanvas3D::LayersEditing::set_config(const DynamicPrintConfig* config)
+{
+ m_config = config;
+ delete m_slicing_parameters;
+ m_slicing_parameters = nullptr;
+ m_layers_texture.valid = false;
+}
+
+void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
+{
+ const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr;
+ if (model_object_new == nullptr || this->last_object_id != object_id || m_model_object != model_object_new || m_model_object->id() != model_object_new->id()) {
+ m_layer_height_profile.clear();
+ m_layer_height_profile_modified = false;
+ delete m_slicing_parameters;
+ m_slicing_parameters = nullptr;
+ m_layers_texture.valid = false;
+ }
+ this->last_object_id = object_id;
+ m_model_object = model_object_new;
+ m_object_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->bounding_box().max.z();
+}
+
bool GLCanvas3D::LayersEditing::is_allowed() const
{
- return !m_use_legacy_opengl && m_shader.is_initialized();
+ return !m_use_legacy_opengl && m_shader.is_initialized() && m_shader.get_shader()->shader_program_id > 0 && m_z_texture_id > 0;
}
void GLCanvas3D::LayersEditing::set_use_legacy_opengl(bool use_legacy_opengl)
@@ -874,12 +933,7 @@ void GLCanvas3D::LayersEditing::set_enabled(bool enabled)
m_enabled = is_allowed() && enabled;
}
-unsigned int GLCanvas3D::LayersEditing::get_z_texture_id() const
-{
- return m_z_texture_id;
-}
-
-void GLCanvas3D::LayersEditing::render(const GLCanvas3D& canvas, const PrintObject& print_object, const GLVolume& volume) const
+void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
{
if (!m_enabled)
return;
@@ -896,8 +950,8 @@ void GLCanvas3D::LayersEditing::render(const GLCanvas3D& canvas, const PrintObje
_render_tooltip_texture(canvas, bar_rect, reset_rect);
_render_reset_texture(reset_rect);
- _render_active_object_annotations(canvas, volume, print_object, bar_rect);
- _render_profile(print_object, bar_rect);
+ _render_active_object_annotations(canvas, bar_rect);
+ _render_profile(bar_rect);
// Revert the matrices.
::glPopMatrix();
@@ -905,12 +959,6 @@ void GLCanvas3D::LayersEditing::render(const GLCanvas3D& canvas, const PrintObje
::glEnable(GL_DEPTH_TEST);
}
-int GLCanvas3D::LayersEditing::get_shader_program_id() const
-{
- const GLShader* shader = m_shader.get_shader();
- return (shader != nullptr) ? shader->shader_program_id : -1;
-}
-
float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas)
{
const Point& mouse_pos = canvas.get_local_mouse_position();
@@ -1023,30 +1071,24 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) co
GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top());
}
-void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const
+void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const
{
- float max_z = print_object.model_object()->bounding_box().max(2);
-
m_shader.start_using();
- m_shader.set_uniform("z_to_texture_row", (float)volume.layer_height_texture_z_to_row_id());
- m_shader.set_uniform("z_texture_row_to_normalized", 1.0f / (float)volume.layer_height_texture_height());
- m_shader.set_uniform("z_cursor", max_z * get_cursor_z_relative(canvas));
+ m_shader.set_uniform("z_to_texture_row", float(m_layers_texture.cells - 1) / (float(m_layers_texture.width) * m_object_max_z));
+ m_shader.set_uniform("z_texture_row_to_normalized", 1.0f / (float)m_layers_texture.height);
+ m_shader.set_uniform("z_cursor", m_object_max_z * this->get_cursor_z_relative(canvas));
m_shader.set_uniform("z_cursor_band_width", band_width);
// The shader requires the original model coordinates when rendering to the texture, so we pass it the unit matrix
m_shader.set_uniform("volume_world_matrix", UNIT_MATRIX);
- GLsizei w = (GLsizei)volume.layer_height_texture_width();
- GLsizei h = (GLsizei)volume.layer_height_texture_height();
+ GLsizei w = (GLsizei)m_layers_texture.width;
+ GLsizei h = (GLsizei)m_layers_texture.height;
GLsizei half_w = w / 2;
GLsizei half_h = h / 2;
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glBindTexture(GL_TEXTURE_2D, m_z_texture_id);
- ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- ::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- ::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, volume.layer_height_texture_data_ptr_level0());
- ::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, volume.layer_height_texture_data_ptr_level1());
// Render the color bar
float l = bar_rect.get_left();
@@ -1055,78 +1097,190 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas
float b = bar_rect.get_bottom();
::glBegin(GL_QUADS);
+ ::glNormal3f(0.0f, 0.0f, 1.0f);
::glVertex3f(l, b, 0.0f);
::glVertex3f(r, b, 0.0f);
- ::glVertex3f(r, t, max_z);
- ::glVertex3f(l, t, max_z);
+ ::glVertex3f(r, t, m_object_max_z);
+ ::glVertex3f(l, t, m_object_max_z);
::glEnd();
::glBindTexture(GL_TEXTURE_2D, 0);
m_shader.stop_using();
}
-void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object, const Rect& bar_rect) const
+void GLCanvas3D::LayersEditing::_render_profile(const Rect& bar_rect) const
{
- // FIXME show some kind of legend.
-
- // Get a maximum layer height value.
- // FIXME This is a duplicate code of Slicing.cpp.
- double layer_height_max = DBL_MAX;
- const PrintConfig& print_config = print_object.print()->config();
- const std::vector<double>& nozzle_diameters = dynamic_cast<const ConfigOptionFloats*>(print_config.option("nozzle_diameter"))->values;
- const std::vector<double>& layer_heights_min = dynamic_cast<const ConfigOptionFloats*>(print_config.option("min_layer_height"))->values;
- const std::vector<double>& layer_heights_max = dynamic_cast<const ConfigOptionFloats*>(print_config.option("max_layer_height"))->values;
- for (unsigned int i = 0; i < (unsigned int)nozzle_diameters.size(); ++i)
- {
- double lh_min = (layer_heights_min[i] == 0.0) ? 0.07 : std::max(0.01, layer_heights_min[i]);
- double lh_max = (layer_heights_max[i] == 0.0) ? (0.75 * nozzle_diameters[i]) : layer_heights_max[i];
- layer_height_max = std::min(layer_height_max, std::max(lh_min, lh_max));
- }
+ //FIXME show some kind of legend.
// Make the vertical bar a bit wider so the layer height curve does not touch the edge of the bar region.
- layer_height_max *= 1.12;
-
- double max_z = unscale<double>(print_object.size(2));
- double layer_height = dynamic_cast<const ConfigOptionFloat*>(print_object.config().option("layer_height"))->value;
- float l = bar_rect.get_left();
- float w = bar_rect.get_right() - l;
- float b = bar_rect.get_bottom();
- float t = bar_rect.get_top();
- float h = t - b;
- float scale_x = w / (float)layer_height_max;
- float scale_y = h / (float)max_z;
- float x = l + (float)layer_height * scale_x;
+ assert(m_slicing_parameters != nullptr);
+ float scale_x = bar_rect.get_width() / (float)(1.12 * m_slicing_parameters->max_layer_height);
+ float scale_y = bar_rect.get_height() / m_object_max_z;
+ float x = bar_rect.get_left() + (float)m_slicing_parameters->layer_height * scale_x;
// Baseline
::glColor3f(0.0f, 0.0f, 0.0f);
::glBegin(GL_LINE_STRIP);
- ::glVertex2f(x, b);
- ::glVertex2f(x, t);
+ ::glVertex2f(x, bar_rect.get_bottom());
+ ::glVertex2f(x, bar_rect.get_top());
::glEnd();
// Curve
- const ModelObject* model_object = print_object.model_object();
- if (model_object->layer_height_profile_valid)
- {
- const std::vector<double>& profile = model_object->layer_height_profile;
+ ::glColor3f(0.0f, 0.0f, 1.0f);
+ ::glBegin(GL_LINE_STRIP);
+ for (unsigned int i = 0; i < m_layer_height_profile.size(); i += 2)
+ ::glVertex2f(bar_rect.get_left() + (float)m_layer_height_profile[i + 1] * scale_x, bar_rect.get_bottom() + (float)m_layer_height_profile[i] * scale_y);
+ ::glEnd();
+}
- ::glColor3f(0.0f, 0.0f, 1.0f);
- ::glBegin(GL_LINE_STRIP);
- for (unsigned int i = 0; i < profile.size(); i += 2)
- {
- ::glVertex2f(l + (float)profile[i + 1] * scale_x, b + (float)profile[i] * scale_y);
+void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const GLVolumeCollection &volumes) const
+{
+ assert(this->is_allowed());
+ assert(this->last_object_id != -1);
+ GLint shader_id = m_shader.get_shader()->shader_program_id;
+ assert(shader_id > 0);
+
+ GLint current_program_id;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id);
+ if (shader_id > 0 && shader_id != current_program_id)
+ // The layer editing shader is not yet active. Activate it.
+ glUseProgram(shader_id);
+ else
+ // The layer editing shader was already active.
+ current_program_id = -1;
+
+ GLint z_to_texture_row_id = glGetUniformLocation(shader_id, "z_to_texture_row");
+ GLint z_texture_row_to_normalized_id = glGetUniformLocation(shader_id, "z_texture_row_to_normalized");
+ GLint z_cursor_id = glGetUniformLocation(shader_id, "z_cursor");
+ GLint z_cursor_band_width_id = glGetUniformLocation(shader_id, "z_cursor_band_width");
+ GLint world_matrix_id = glGetUniformLocation(shader_id, "volume_world_matrix");
+
+ if (z_to_texture_row_id != -1 && z_texture_row_to_normalized_id != -1 && z_cursor_id != -1 && z_cursor_band_width_id != -1 && world_matrix_id != -1)
+ {
+ const_cast<LayersEditing*>(this)->generate_layer_height_texture();
+
+ // Uniforms were resolved, go ahead using the layer editing shader.
+ glUniform1f(z_to_texture_row_id, GLfloat(m_layers_texture.cells - 1) / (GLfloat(m_layers_texture.width) * GLfloat(m_object_max_z)));
+ glUniform1f(z_texture_row_to_normalized_id, GLfloat(1.0f / m_layers_texture.height));
+ glUniform1f(z_cursor_id, GLfloat(m_object_max_z) * GLfloat(this->get_cursor_z_relative(canvas)));
+ glUniform1f(z_cursor_band_width_id, GLfloat(this->band_width));
+ // Initialize the layer height texture mapping.
+ GLsizei w = (GLsizei)m_layers_texture.width;
+ GLsizei h = (GLsizei)m_layers_texture.height;
+ GLsizei half_w = w / 2;
+ GLsizei half_h = h / 2;
+ ::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glBindTexture(GL_TEXTURE_2D, m_z_texture_id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data());
+ glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4);
+ for (const GLVolume *glvolume : volumes.volumes) {
+ // Render the object using the layer editing shader and texture.
+ if (! glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
+ continue;
+ ::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)glvolume->world_matrix().cast<float>().data());
+ glvolume->render();
+ }
+ // Revert back to the previous shader.
+ glBindTexture(GL_TEXTURE_2D, 0);
+ if (current_program_id > 0)
+ glUseProgram(current_program_id);
+ }
+ else
+ {
+ // Something went wrong. Just render the object.
+ assert(false);
+ for (const GLVolume *glvolume : volumes.volumes) {
+ // Render the object using the layer editing shader and texture.
+ if (!glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
+ continue;
+ ::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)glvolume->world_matrix().cast<float>().data());
+ glvolume->render();
+ }
+ }
+}
+
+void GLCanvas3D::LayersEditing::adjust_layer_height_profile()
+{
+ this->update_slicing_parameters();
+ PrintObject::update_layer_height_profile(*m_model_object, *m_slicing_parameters, m_layer_height_profile);
+ Slic3r::adjust_layer_height_profile(*m_slicing_parameters, m_layer_height_profile, this->last_z, this->strength, this->band_width, this->last_action);
+ m_layer_height_profile_modified = true;
+ m_layers_texture.valid = false;
+}
+
+void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
+{
+ const_cast<ModelObject*>(m_model_object)->layer_height_profile.clear();
+ m_layer_height_profile.clear();
+ m_layers_texture.valid = false;
+ canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
+}
+
+void GLCanvas3D::LayersEditing::generate_layer_height_texture()
+{
+ this->update_slicing_parameters();
+ // Always try to update the layer height profile.
+ bool update = ! m_layers_texture.valid;
+ if (PrintObject::update_layer_height_profile(*m_model_object, *m_slicing_parameters, m_layer_height_profile)) {
+ // Initialized to the default value.
+ m_layer_height_profile_modified = false;
+ update = true;
+ }
+ // Update if the layer height profile was changed, or when the texture is not valid.
+ if (! update && ! m_layers_texture.data.empty() && m_layers_texture.cells > 0)
+ // Texture is valid, don't update.
+ return;
+
+ if (m_layers_texture.data.empty()) {
+ m_layers_texture.width = 1024;
+ m_layers_texture.height = 1024;
+ m_layers_texture.levels = 2;
+ m_layers_texture.data.assign(m_layers_texture.width * m_layers_texture.height * 5, 0);
+ }
+
+ bool level_of_detail_2nd_level = true;
+ m_layers_texture.cells = Slic3r::generate_layer_height_texture(
+ *m_slicing_parameters,
+ Slic3r::generate_object_layers(*m_slicing_parameters, m_layer_height_profile),
+ m_layers_texture.data.data(), m_layers_texture.height, m_layers_texture.width, level_of_detail_2nd_level);
+ m_layers_texture.valid = true;
+}
+
+void GLCanvas3D::LayersEditing::accept_changes(GLCanvas3D& canvas)
+{
+ if (last_object_id >= 0) {
+ if (m_layer_height_profile_modified) {
+ const_cast<ModelObject*>(m_model_object)->layer_height_profile = m_layer_height_profile;
+ canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
- ::glEnd();
+ }
+ m_layer_height_profile_modified = false;
+}
+
+void GLCanvas3D::LayersEditing::update_slicing_parameters()
+{
+ if (m_slicing_parameters == nullptr) {
+ m_slicing_parameters = new SlicingParameters();
+ *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object);
}
}
const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX);
const Vec3d GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX);
+#if ENABLE_MOVE_MIN_THRESHOLD
+const int GLCanvas3D::Mouse::Drag::MoveThresholdPx = 5;
+#endif // ENABLE_MOVE_MIN_THRESHOLD
GLCanvas3D::Mouse::Drag::Drag()
: start_position_2D(Invalid_2D_Point)
, start_position_3D(Invalid_3D_Point)
, move_volume_idx(-1)
+#if ENABLE_MOVE_MIN_THRESHOLD
+ , move_requires_threshold(false)
+ , move_start_threshold_position_2D(Invalid_2D_Point)
+#endif // ENABLE_MOVE_MIN_THRESHOLD
{
}
@@ -1139,26 +1293,6 @@ GLCanvas3D::Mouse::Mouse()
{
}
-void GLCanvas3D::Mouse::set_start_position_2D_as_invalid()
-{
- drag.start_position_2D = Drag::Invalid_2D_Point;
-}
-
-void GLCanvas3D::Mouse::set_start_position_3D_as_invalid()
-{
- drag.start_position_3D = Drag::Invalid_3D_Point;
-}
-
-bool GLCanvas3D::Mouse::is_start_position_2D_defined() const
-{
- return (drag.start_position_2D != Drag::Invalid_2D_Point);
-}
-
-bool GLCanvas3D::Mouse::is_start_position_3D_defined() const
-{
- return (drag.start_position_3D != Drag::Invalid_3D_Point);
-}
-
GLCanvas3D::Selection::VolumeCache::TransformCache::TransformCache()
: position(Vec3d::Zero())
, rotation(Vec3d::Zero())
@@ -1217,7 +1351,6 @@ void GLCanvas3D::Selection::set_volumes(GLVolumePtrs* volumes)
_update_valid();
}
-#if ENABLE_SIDEBAR_VISUAL_HINTS
bool GLCanvas3D::Selection::init(bool useVBOs)
{
if (!m_arrow.init(useVBOs))
@@ -1231,7 +1364,6 @@ bool GLCanvas3D::Selection::init(bool useVBOs)
m_curved_arrow.set_scale(5.0 * Vec3d::Ones());
return true;
}
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
void GLCanvas3D::Selection::set_model(Model* model)
{
@@ -1605,7 +1737,6 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
for (unsigned int i : m_list)
{
if (is_single_full_instance())
-#if ENABLE_WORLD_ROTATIONS
{
if (local)
(*m_volumes)[i]->set_instance_rotation(rotation);
@@ -1616,25 +1747,17 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
(*m_volumes)[i]->set_instance_rotation(new_rotation);
}
}
-#else
- (*m_volumes)[i]->set_instance_rotation(rotation);
-#endif // ENABLE_WORLD_ROTATIONS
else if (is_single_volume() || is_single_modifier())
-#if ENABLE_WORLD_ROTATIONS
{
- if (requires_local_axes())
+ if (local)
(*m_volumes)[i]->set_volume_rotation(rotation);
else
{
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
- const Transform3d& inst_m = m_cache.volumes_data[i].get_instance_rotation_matrix();
- Vec3d new_rotation = Geometry::extract_euler_angles(inst_m.inverse() * m * inst_m * m_cache.volumes_data[i].get_volume_rotation_matrix());
+ Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
(*m_volumes)[i]->set_volume_rotation(new_rotation);
}
}
-#else
- (*m_volumes)[i]->set_volume_rotation(rotation);
-#endif // ENABLE_WORLD_ROTATIONS
else
{
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
@@ -1682,11 +1805,14 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal)
for (unsigned int i : m_list)
{
- Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_volume_scale_matrix();
+ Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix();
Vec3d scaling_factor = Vec3d(1./wst(0,0), 1./wst(1,1), 1./wst(2,2));
- Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_volume_rotation_matrix());
- Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor) * normal;
+ Transform3d wmt = m_cache.volumes_data[i].get_instance_mirror_matrix();
+ Vec3d mirror(wmt(0,0), wmt(1,1), wmt(2,2));
+
+ Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix());
+ Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor, mirror) * normal;
transformed_normal.normalize();
Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.)));
@@ -1700,8 +1826,10 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal)
}
#if !DISABLE_INSTANCES_SYNCH
+ // 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();
+ _synchronize_unselected_instances(true);
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true;
@@ -1753,9 +1881,7 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale, bool local)
_synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
-#if ENABLE_ENSURE_ON_BED_WHILE_SCALING
_ensure_on_bed();
-#endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING
m_bounding_box_dirty = true;
}
@@ -1892,8 +2018,6 @@ void GLCanvas3D::Selection::erase()
}
wxGetApp().obj_list()->delete_from_model_and_list(items);
}
- else if (is_single_full_instance())
- wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itInstance, get_object_idx(), get_instance_idx());
else if (is_multiple_full_instance())
{
std::set<std::pair<int, int>> instances_idxs;
@@ -1911,9 +2035,10 @@ void GLCanvas3D::Selection::erase()
{
items.emplace_back(ItemType::itInstance, i.first, i.second);
}
-
wxGetApp().obj_list()->delete_from_model_and_list(items);
}
+ else if (is_single_full_instance())
+ wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itInstance, get_object_idx(), get_instance_idx());
else if (is_mixed())
{
std::set<ItemForDelete> items_set;
@@ -2022,7 +2147,6 @@ void GLCanvas3D::Selection::render_center() const
}
#endif // ENABLE_RENDER_SELECTION_CENTER
-#if ENABLE_SIDEBAR_VISUAL_HINTS
void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_field) const
{
if (sidebar_field.empty())
@@ -2038,14 +2162,18 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
const Vec3d& center = get_bounding_box().center();
if (is_single_full_instance())
+ {
::glTranslated(center(0), center(1), center(2));
+ if (!boost::starts_with(sidebar_field, "position"))
+ {
+ Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
+ ::glMultMatrixd(orient_matrix.data());
+ }
+ }
else if (is_single_volume() || is_single_modifier())
{
- const GLVolume* volume = (*m_volumes)[*m_list.begin()];
- Transform3d orient_matrix = volume->get_instance_transformation().get_matrix(true, false, true, true);
- const Vec3d& offset = get_bounding_box().center();
-
- ::glTranslated(offset(0), offset(1), offset(2));
+ Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
+ ::glTranslated(center(0), center(1), center(2));
::glMultMatrixd(orient_matrix.data());
}
else
@@ -2053,8 +2181,7 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
::glTranslated(center(0), center(1), center(2));
if (requires_local_axes())
{
- const GLVolume* volume = (*m_volumes)[*m_list.begin()];
- Transform3d orient_matrix = volume->get_instance_transformation().get_matrix(true, false, true, true);
+ Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
}
}
@@ -2072,7 +2199,6 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
::glDisable(GL_LIGHTING);
}
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
bool GLCanvas3D::Selection::requires_local_axes() const
{
@@ -2315,7 +2441,7 @@ void GLCanvas3D::Selection::_update_type()
void GLCanvas3D::Selection::_set_caches()
{
m_cache.volumes_data.clear();
- for (unsigned int i : m_list)
+ for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
const GLVolume* v = (*m_volumes)[i];
m_cache.volumes_data.emplace(i, VolumeCache(v->get_volume_transformation(), v->get_instance_transformation()));
@@ -2477,7 +2603,6 @@ void GLCanvas3D::Selection::_render_bounding_box(const BoundingBoxf3& box, float
::glEnd();
}
-#if ENABLE_SIDEBAR_VISUAL_HINTS
void GLCanvas3D::Selection::_render_sidebar_position_hints(const std::string& sidebar_field) const
{
if (boost::ends_with(sidebar_field, "x"))
@@ -2512,7 +2637,9 @@ void GLCanvas3D::Selection::_render_sidebar_rotation_hints(const std::string& si
void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
{
- if (boost::ends_with(sidebar_field, "x") || requires_uniform_scale())
+ 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);
@@ -2520,14 +2647,14 @@ void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sideb
::glPopMatrix();
}
- if (boost::ends_with(sidebar_field, "y") || requires_uniform_scale())
+ if (boost::ends_with(sidebar_field, "y") || uniform_scale)
{
::glPushMatrix();
_render_sidebar_scale_hint(Y);
::glPopMatrix();
}
- if (boost::ends_with(sidebar_field, "z") || requires_uniform_scale())
+ if (boost::ends_with(sidebar_field, "z") || uniform_scale)
{
::glPushMatrix();
::glRotated(90.0, 1.0, 0.0, 0.0);
@@ -2558,7 +2685,7 @@ void GLCanvas3D::Selection::_render_sidebar_rotation_hint(Axis axis) const
void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const
{
- m_arrow.set_color((requires_uniform_scale() ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
+ 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);
m_arrow.render();
@@ -2571,9 +2698,8 @@ void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const
void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) const
{
}
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
-void GLCanvas3D::Selection::_synchronize_unselected_instances()
+void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z)
{
std::set<unsigned int> done; // prevent processing volumes twice
done.insert(m_list.begin(), m_list.end());
@@ -2606,7 +2732,20 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances()
if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx))
continue;
- v->set_instance_rotation(Vec3d(rotation(0), rotation(1), v->get_instance_rotation()(2)));
+ auto is_approx = [](double value, double test_value) -> bool { return std::abs(value - test_value) < EPSILON; };
+
+ double z;
+ if (including_z)
+ // rotation comes from place on face -> force given z
+ z = rotation(2);
+ else if (is_approx(rotation(0), m_cache.volumes_data[j].get_instance_rotation()(0)) && is_approx(rotation(1), m_cache.volumes_data[j].get_instance_rotation()(1)))
+ // z only rotation -> keep instance z
+ z = v->get_instance_rotation()(2);
+ else
+ // generic rotation -> update instance z
+ z = m_cache.volumes_data[j].get_instance_rotation()(2) + rotation(2);
+
+ v->set_instance_rotation(Vec3d(rotation(0), rotation(1), z));
v->set_instance_scaling_factor(scaling_factor);
v->set_instance_mirror(mirror);
@@ -2648,7 +2787,6 @@ void GLCanvas3D::Selection::_synchronize_unselected_volumes()
}
}
-#if ENABLE_ENSURE_ON_BED_WHILE_SCALING
void GLCanvas3D::Selection::_ensure_on_bed()
{
typedef std::map<std::pair<int, int>, double> InstancesToZMap;
@@ -2676,7 +2814,6 @@ void GLCanvas3D::Selection::_ensure_on_bed()
volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second);
}
}
-#endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING
const float GLCanvas3D::Gizmos::OverlayIconsScale = 1.0f;
const float GLCanvas3D::Gizmos::OverlayBorder = 5.0f;
@@ -2806,13 +2943,13 @@ std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, con
float icon_size = (float)it->second->get_textures_size() * OverlayIconsScale;
+ bool inside = (OverlayBorder <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= OverlayBorder + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size);
+ if (inside)
+ name = it->second->get_name();
+
if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On))
- {
- bool inside = (OverlayBorder <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= OverlayBorder + icon_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + icon_size);
it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
- if (inside)
- name = it->second->get_name();
- }
+
top_y += (icon_size + OverlayGapY);
}
@@ -2949,14 +3086,14 @@ bool GLCanvas3D::Gizmos::grabber_contains_mouse() const
return (curr != nullptr) ? (curr->get_hover_id() != -1) : false;
}
-void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray, bool shift_down, const Point* mouse_pos)
+void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos)
{
if (!m_enabled)
return;
GLGizmoBase* curr = _get_current();
if (curr != nullptr)
- curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos, shift_down));
+ curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos, shift_down), selection);
}
GLCanvas3D::Gizmos::EType GLCanvas3D::Gizmos::get_current_type() const
@@ -2975,7 +3112,7 @@ bool GLCanvas3D::Gizmos::is_running() const
bool GLCanvas3D::Gizmos::handle_shortcut(int key, const Selection& selection)
{
- if (!m_enabled)
+ if (!m_enabled || selection.is_empty())
return false;
bool handled = false;
@@ -3695,7 +3832,6 @@ wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent);
-wxDEFINE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent);
@@ -3724,7 +3860,11 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
, m_dirty(true)
, m_initialized(false)
, m_use_VBOs(false)
+#if ENABLE_REWORKED_BED_SHAPE_CHANGE
+ , m_requires_zoom_to_bed(false)
+#else
, m_force_zoom_to_bed_enabled(false)
+#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
, m_apply_zoom_to_volumes_filter(false)
, m_hover_volume_id(-1)
, m_toolbar_action_running(false)
@@ -3743,12 +3883,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
#endif // not ENABLE_IMGUI
{
if (m_canvas != nullptr)
- {
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- m_context = new wxGLContext(m_canvas);
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
m_timer.SetOwner(m_canvas);
- }
m_selection.set_volumes(&m_volumes.volumes);
}
@@ -3756,14 +3891,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
GLCanvas3D::~GLCanvas3D()
{
reset_volumes();
-
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- if (m_context != nullptr)
- {
- delete m_context;
- m_context = nullptr;
- }
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
}
void GLCanvas3D::post_event(wxEvent &&event)
@@ -3859,10 +3986,8 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
if (!_init_toolbar())
return false;
-#if ENABLE_SIDEBAR_VISUAL_HINTS
if (!m_selection.init(m_use_VBOs))
return false;
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
post_event(SimpleEvent(EVT_GLCANVAS_INIT));
@@ -3871,16 +3996,6 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
return true;
}
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
-bool GLCanvas3D::set_current()
-{
- if ((m_canvas != nullptr) && (m_context != nullptr))
- return m_canvas->SetCurrent(*m_context);
-
- return false;
-}
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
void GLCanvas3D::set_as_dirty()
{
m_dirty = true;
@@ -3895,12 +4010,6 @@ void GLCanvas3D::reset_volumes()
{
if (!m_volumes.empty())
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- // ensures this canvas is current
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
m_selection.clear();
m_volumes.release_geometry();
m_volumes.clear();
@@ -3918,9 +4027,10 @@ int GLCanvas3D::check_volumes_outside_state() const
return (int)state;
}
-void GLCanvas3D::set_config(DynamicPrintConfig* config)
+void GLCanvas3D::set_config(const DynamicPrintConfig* config)
{
m_config = config;
+ m_layers_editing.set_config(config);
}
void GLCanvas3D::set_process(BackgroundSlicingProcess *process)
@@ -3943,7 +4053,11 @@ void GLCanvas3D::set_bed_shape(const Pointfs& shape)
set_bed_axes_length(0.1 * m_bed.get_bounding_box().max_size());
if (new_shape)
+#if ENABLE_REWORKED_BED_SHAPE_CHANGE
+ m_requires_zoom_to_bed = true;
+#else
zoom_to_bed();
+#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
m_dirty = true;
}
@@ -3978,6 +4092,12 @@ BoundingBoxf3 GLCanvas3D::scene_bounding_box() const
{
BoundingBoxf3 bb = volumes_bounding_box();
bb.merge(m_bed.get_bounding_box());
+ if (m_config != nullptr)
+ {
+ double h = m_config->opt_float("max_print_height");
+ bb.min(2) = std::min(bb.min(2), -h);
+ bb.max(2) = std::max(bb.max(2), h);
+ }
return bb;
}
@@ -4032,10 +4152,12 @@ void GLCanvas3D::enable_toolbar(bool enable)
m_toolbar.set_enabled(enable);
}
+#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
void GLCanvas3D::enable_force_zoom_to_bed(bool enable)
{
m_force_zoom_to_bed_enabled = enable;
}
+#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
void GLCanvas3D::enable_dynamic_background(bool enable)
{
@@ -4100,7 +4222,7 @@ void GLCanvas3D::select_view(const std::string& direction)
if (dir_vec != nullptr)
{
m_camera.phi = dir_vec[0];
- m_camera.set_theta(dir_vec[1]);
+ m_camera.set_theta(dir_vec[1], false);
viewport_changed();
@@ -4112,10 +4234,13 @@ void GLCanvas3D::select_view(const std::string& direction)
void GLCanvas3D::set_viewport_from_scene(const GLCanvas3D& other)
{
m_camera.phi = other.m_camera.phi;
- m_camera.set_theta(other.m_camera.get_theta());
+ m_camera.set_theta(other.m_camera.get_theta(), false);
m_camera.set_scene_box(other.m_camera.get_scene_box(), *this);
m_camera.set_target(other.m_camera.get_target(), *this);
m_camera.zoom = other.m_camera.zoom;
+#if ENABLE_REWORKED_BED_SHAPE_CHANGE
+ m_requires_zoom_to_bed = false;
+#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
m_dirty = true;
}
@@ -4161,15 +4286,21 @@ void GLCanvas3D::render()
return;
// ensures this canvas is current and initialized
-#if ENABLE_USE_UNIQUE_GLCONTEXT
if (!_set_current() || !_3DScene::init(m_canvas))
-#else
- if (!set_current() || !_3DScene::init(m_canvas))
-#endif // ENABLE_USE_UNIQUE_GLCONTEXT
return;
+#if ENABLE_REWORKED_BED_SHAPE_CHANGE
+ if (m_requires_zoom_to_bed)
+ {
+ zoom_to_bed();
+ const Size& cnv_size = get_canvas_size();
+ _resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
+ m_requires_zoom_to_bed = false;
+ }
+#else
if (m_force_zoom_to_bed_enabled)
_force_zoom_to_bed();
+#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
_camera_tranform();
@@ -4179,6 +4310,10 @@ void GLCanvas3D::render()
::glLightfv(GL_LIGHT0, GL_POSITION, position_top);
float theta = m_camera.get_theta();
+ if (theta > 180.f)
+ // absolute value of the rotation
+ theta = 360.f - theta;
+
bool is_custom_bed = m_bed.is_custom();
#if ENABLE_IMGUI
@@ -4192,13 +4327,9 @@ void GLCanvas3D::render()
::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_render_background();
-#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// textured bed needs to be rendered after objects if the texture is transparent
bool early_bed_render = is_custom_bed || (theta <= 90.0f);
if (early_bed_render)
-#else
- if (is_custom_bed) // untextured bed needs to be rendered before objects
-#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
_render_bed(theta);
_render_objects();
@@ -4207,11 +4338,7 @@ void GLCanvas3D::render()
_render_axes();
-#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (!early_bed_render)
-#else
- if (!is_custom_bed) // textured bed needs to be rendered after objects
-#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
_render_bed(theta);
#if ENABLE_RENDER_SELECTION_CENTER
@@ -4223,9 +4350,7 @@ void GLCanvas3D::render()
// this position is used later into on_mouse() to drag the objects
m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast<int>());
-#if ENABLE_SIDEBAR_VISUAL_HINTS
_render_selection_sidebar_hints();
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
_render_current_gizmo();
#if ENABLE_SHOW_CAMERA_TARGET
@@ -4239,7 +4364,8 @@ void GLCanvas3D::render()
_resize_toolbars();
_render_toolbar();
_render_view_toolbar();
- _render_layer_editing_overlay();
+ if (m_layers_editing.last_object_id >= 0)
+ m_layers_editing.render_overlay(*this);
#if ENABLE_IMGUI
wxGetApp().imgui()->render();
@@ -4338,11 +4464,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
{
if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr))
return;
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- // ensures this canvas is current
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
struct ModelVolumeState {
ModelVolumeState(const GLVolume *volume) :
@@ -4479,8 +4600,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_volumes.volumes = std::move(glvolumes_new);
for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++ obj_idx) {
const ModelObject &model_object = *m_model->objects[obj_idx];
- // Object will share a single common layer height texture between all printable volumes.
- std::shared_ptr<LayersTexture> layer_height_texture;
for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) {
const ModelVolume &model_volume = *model_object.volumes[volume_idx];
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
@@ -4490,33 +4609,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
if (it->new_geometry()) {
// New volume.
- if (model_volume.is_model_part() && ! layer_height_texture) {
- // New object part needs to have the layer height texture assigned, which is shared with the other volumes of the same part.
- // Search for the layer height texture in the other volumes.
- for (int iv = volume_idx; iv < (int)model_object.volumes.size(); ++ iv) {
- const ModelVolume &mv = *model_object.volumes[iv];
- if (mv.is_model_part())
- for (int ii = instance_idx; ii < (int)model_object.instances.size(); ++ ii) {
- const ModelInstance &mi = *model_object.instances[ii];
- ModelVolumeState key(mv.id(), mi.id());
- auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
- assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
- if (! it->new_geometry()) {
- // Found an old printable GLVolume (existing before this function was called).
- assert(m_volumes.volumes[it->volume_idx]->geometry_id == key.geometry_id);
- // Reuse the layer height texture.
- const GLVolume *volume = m_volumes.volumes[it->volume_idx];
- assert(volume->layer_height_texture);
- layer_height_texture = volume->layer_height_texture;
- goto iv_end;
- }
- }
- }
- iv_end:
- if (! layer_height_texture)
- layer_height_texture = std::make_shared<LayersTexture>();
- }
- m_volumes.load_object_volume(&model_object, layer_height_texture, obj_idx, volume_idx, instance_idx, m_color_by, m_use_VBOs && m_initialized);
+ m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_use_VBOs && m_initialized);
m_volumes.volumes.back()->geometry_id = key.geometry_id;
} else {
// Recycling an old GLVolume.
@@ -4524,11 +4617,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
assert(existing_volume.geometry_id == key.geometry_id);
// Update the Object/Volume/Instance indices into the current Model.
existing_volume.composite_id = it->composite_id;
- if (model_volume.is_model_part() && ! layer_height_texture) {
- assert(existing_volume.layer_height_texture);
- // cache its layer height texture
- layer_height_texture = existing_volume.layer_height_texture;
- }
}
}
}
@@ -4661,6 +4749,19 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_camera.set_scene_box(scene_bounding_box(), *this);
m_camera.set_target(m_camera.get_target(), *this);
+ if (m_selection.is_empty())
+ {
+ // If no object is selected, deactivate the active gizmo, if any
+ // Otherwise it may be shown after cleaning the scene (if it was active while the objects were deleted)
+ m_gizmos.reset_all_states();
+
+ // If no object is selected, reset the objects manipulator on the sidebar
+ // to force a reset of its cache
+ auto manip = wxGetApp().obj_manipul();
+ if (manip != nullptr)
+ manip->update_settings_value(m_selection);
+ }
+
// and force this canvas to be redrawn.
m_dirty = true;
}
@@ -4670,12 +4771,6 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
const Print *print = this->fff_print();
if ((m_canvas != nullptr) && (print != nullptr))
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- // ensures that this canvas is current
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
if (m_volumes.empty())
@@ -4909,10 +5004,8 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
void GLCanvas3D::on_timer(wxTimerEvent& evt)
{
- if (m_layers_editing.state != LayersEditing::Editing)
- return;
-
- _perform_layer_editing_action();
+ if (m_layers_editing.state == LayersEditing::Editing)
+ _perform_layer_editing_action();
}
void GLCanvas3D::on_mouse(wxMouseEvent& evt)
@@ -4931,15 +5024,24 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
int selected_object_idx = m_selection.get_object_idx();
int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
- m_layers_editing.last_object_id = layer_editing_object_idx;
+ m_layers_editing.select_object(*m_model, layer_editing_object_idx);
bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position);
int toolbar_contains_mouse = m_toolbar.contains_mouse(m_mouse.position, *this);
int view_toolbar_contains_mouse = (m_view_toolbar != nullptr) ? m_view_toolbar->contains_mouse(m_mouse.position, *this) : -1;
+#if ENABLE_MOVE_MIN_THRESHOLD
+ if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
+ {
+ m_mouse.drag.move_requires_threshold = false;
+ m_mouse.set_move_start_threshold_position_2D_as_invalid();
+ }
+#endif // ENABLE_MOVE_MIN_THRESHOLD
+
if (evt.Entering())
{
-#if defined(__WXMSW__) || defined(__linux__)
- // On Windows and Linux needs focus in order to catch key events
+//#if defined(__WXMSW__) || defined(__linux__)
+// // On Windows and Linux needs focus in order to catch key events
+ // Set focus in order to remove it from sidebar fields
if (m_canvas != nullptr) {
// Only set focus, if the top level window of this canvas is active.
auto p = dynamic_cast<wxWindow*>(evt.GetEventObject());
@@ -4951,8 +5053,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
m_mouse.set_start_position_2D_as_invalid();
- m_mouse.set_start_position_3D_as_invalid();
-#endif
+//#endif
}
else if (evt.Leaving())
{
@@ -4963,6 +5064,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
{
m_toolbar_action_running = true;
+ m_mouse.set_start_position_3D_as_invalid();
m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
}
else if (evt.LeftDClick() && (m_gizmos.get_current_type() != Gizmos::Undefined))
@@ -4987,10 +5089,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
if (evt.LeftDown())
{
- // A volume is selected and the mouse is inside the reset button.
- // The PrintObject::adjust_layer_height_profile() call adjusts the profile of its associated ModelObject, it does not modify the profile of the PrintObject itself,
- // therefore it is safe to call it while the background processing is running.
- const_cast<PrintObject*>(this->fff_print()->get_object(layer_editing_object_idx))->reset_layer_height_profile();
+ // A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
+ m_layers_editing.reset_layer_height_profile(*this);
// Index 2 means no editing, just wait for mouse up event.
m_layers_editing.state = LayersEditing::Completed;
@@ -5040,6 +5140,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
else if (toolbar_contains_mouse != -1)
{
m_toolbar_action_running = true;
+ m_mouse.set_start_position_3D_as_invalid();
m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
m_mouse.left_down = false;
}
@@ -5066,6 +5167,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
bool add_as_single = !already_selected && !shift_down;
m_selection.add(m_hover_volume_id, add_as_single);
+#if ENABLE_MOVE_MIN_THRESHOLD
+ m_mouse.drag.move_requires_threshold = !already_selected;
+ if (already_selected)
+ m_mouse.set_move_start_threshold_position_2D_as_invalid();
+ else
+ m_mouse.drag.move_start_threshold_position_2D = pos;
+#endif // ENABLE_MOVE_MIN_THRESHOLD
}
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
@@ -5116,7 +5224,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (m_volumes.volumes[m_hover_volume_id]->hover && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower)
{
// forces the selection of the volume
- m_selection.add(m_hover_volume_id);
+ if (!m_selection.is_multiple_full_instance())
+ m_selection.add(m_hover_volume_id);
m_gizmos.update_on_off_state(m_selection);
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
_update_gizmos_data();
@@ -5132,19 +5241,26 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.move_volume_idx != -1))
{
- m_mouse.dragging = true;
+#if ENABLE_MOVE_MIN_THRESHOLD
+ if (!m_mouse.drag.move_requires_threshold)
+ {
+#endif // ENABLE_MOVE_MIN_THRESHOLD
+ m_mouse.dragging = true;
- // Get new position at the same Z of the initial click point.
- float z0 = 0.0f;
- float z1 = 1.0f;
- // we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag
- Vec3d cur_pos = m_selection.contains_volume(m_hover_volume_id) ? Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)) : m_mouse.drag.start_position_3D;
+ // Get new position at the same Z of the initial click point.
+ float z0 = 0.0f;
+ float z1 = 1.0f;
+ // we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag
+ Vec3d cur_pos = m_selection.contains_volume(m_hover_volume_id) ? Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)) : m_mouse.drag.start_position_3D;
- m_regenerate_volumes = false;
- m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
- wxGetApp().obj_manipul()->update_settings_value(m_selection);
+ m_regenerate_volumes = false;
+ m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
+ wxGetApp().obj_manipul()->update_settings_value(m_selection);
- m_dirty = true;
+ m_dirty = true;
+#if ENABLE_MOVE_MIN_THRESHOLD
+ }
+#endif // ENABLE_MOVE_MIN_THRESHOLD
}
else if (evt.Dragging() && m_gizmos.is_dragging())
{
@@ -5152,7 +5268,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_canvas->CaptureMouse();
m_mouse.dragging = true;
- m_gizmos.update(mouse_ray(pos), evt.ShiftDown(), &pos);
+ m_gizmos.update(mouse_ray(pos), m_selection, evt.ShiftDown(), &pos);
switch (m_gizmos.get_current_type())
{
@@ -5195,11 +5311,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
else if (evt.LeftIsDown())
{
// if dragging over blank area with left button, rotate
+#if ENABLE_MOVE_MIN_THRESHOLD
+ if ((m_hover_volume_id == -1) && m_mouse.is_start_position_3D_defined())
+#else
if (m_mouse.is_start_position_3D_defined())
+#endif // ENABLE_MOVE_MIN_THRESHOLD
{
const Vec3d& orig = m_mouse.drag.start_position_3D;
m_camera.phi += (((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE);
- m_camera.set_theta(m_camera.get_theta() - ((float)pos(1) - (float)orig(1)) * TRACKBALLSIZE);
+ m_camera.set_theta(m_camera.get_theta() - ((float)pos(1) - (float)orig(1)) * TRACKBALLSIZE, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA);
viewport_changed();
@@ -5232,9 +5352,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
m_layers_editing.state = LayersEditing::Unknown;
_stop_timer();
-
- if (layer_editing_object_idx != -1)
- post_event(SimpleEvent(EVT_GLCANVAS_MODEL_UPDATE));
+ m_layers_editing.accept_changes(*this);
}
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
{
@@ -5261,8 +5379,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_selection.clear();
m_selection.set_mode(Selection::Instance);
wxGetApp().obj_manipul()->update_settings_value(m_selection);
- post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
+ m_gizmos.reset_all_states();
_update_gizmos_data();
+ post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
}
m_mouse.ignore_up_event = false;
}
@@ -5294,9 +5413,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
break;
}
m_gizmos.stop_dragging();
-#if ENABLE_WORLD_ROTATIONS
_update_gizmos_data();
-#endif // ENABLE_WORLD_ROTATIONS
wxGetApp().obj_manipul()->update_settings_value(m_selection);
// Let the platter know that the dragging finished, so a delayed refresh
@@ -5324,9 +5441,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
std::string tooltip = "";
// updates gizmos overlay
- if (!m_selection.is_empty())
- tooltip = m_gizmos.update_hover_state(*this, m_mouse.position, m_selection);
- else
+ tooltip = m_gizmos.update_hover_state(*this, m_mouse.position, m_selection);
+ if (m_selection.is_empty())
m_gizmos.reset_all_states();
// updates toolbar overlay
@@ -5396,11 +5512,6 @@ Point GLCanvas3D::get_local_mouse_position() const
void GLCanvas3D::reset_legend_texture()
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
m_legend_texture.reset();
}
@@ -5411,7 +5522,9 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const
wxToolTip* t = m_canvas->GetToolTip();
if (t != nullptr)
{
- if (t->GetTip() != tooltip)
+ if (tooltip.empty())
+ m_canvas->UnsetToolTip();
+ else
t->SetTip(tooltip);
}
else
@@ -5667,7 +5780,7 @@ void GLCanvas3D::set_camera_zoom(float zoom)
// Don't allow to zoom too far outside the scene.
float zoom_min = _get_zoom_to_bounding_box_factor(_max_bounding_box());
if (zoom_min > 0.0f)
- zoom = std::max(zoom, zoom_min * 0.8f);
+ zoom = std::max(zoom, zoom_min * 0.7f);
m_camera.zoom = zoom;
viewport_changed();
@@ -5677,6 +5790,7 @@ void GLCanvas3D::set_camera_zoom(float zoom)
void GLCanvas3D::update_gizmos_on_off_state()
{
set_as_dirty();
+ _update_gizmos_data();
m_gizmos.update_on_off_state(get_selection());
}
@@ -5696,11 +5810,13 @@ bool GLCanvas3D::_is_shown_on_screen() const
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
}
+#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
void GLCanvas3D::_force_zoom_to_bed()
{
zoom_to_bed();
m_force_zoom_to_bed_enabled = false;
}
+#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
bool GLCanvas3D::_init_toolbar()
{
@@ -5742,7 +5858,7 @@ bool GLCanvas3D::_init_toolbar()
GLToolbarItem::Data item;
item.name = "add";
- item.tooltip = GUI::L_str("Add...");
+ item.tooltip = GUI::L_str("Add... [Ctrl+I]");
item.sprite_id = 0;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_ADD;
@@ -5750,7 +5866,7 @@ bool GLCanvas3D::_init_toolbar()
return false;
item.name = "delete";
- item.tooltip = GUI::L_str("Delete");
+ item.tooltip = GUI::L_str("Delete [Del]");
item.sprite_id = 1;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_DELETE;
@@ -5758,7 +5874,7 @@ bool GLCanvas3D::_init_toolbar()
return false;
item.name = "deleteall";
- item.tooltip = GUI::L_str("Delete all");
+ item.tooltip = GUI::L_str("Delete all [Ctrl+Del]");
item.sprite_id = 2;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
@@ -5766,7 +5882,7 @@ bool GLCanvas3D::_init_toolbar()
return false;
item.name = "arrange";
- item.tooltip = GUI::L_str("Arrange");
+ item.tooltip = GUI::L_str("Arrange [A]");
item.sprite_id = 3;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_ARRANGE;
@@ -5777,7 +5893,7 @@ bool GLCanvas3D::_init_toolbar()
return false;
item.name = "more";
- item.tooltip = GUI::L_str("Add instance");
+ item.tooltip = GUI::L_str("Add instance [+]");
item.sprite_id = 4;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_MORE;
@@ -5785,7 +5901,7 @@ bool GLCanvas3D::_init_toolbar()
return false;
item.name = "fewer";
- item.tooltip = GUI::L_str("Remove instance");
+ item.tooltip = GUI::L_str("Remove instance [-]");
item.sprite_id = 5;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_FEWER;
@@ -5827,7 +5943,6 @@ bool GLCanvas3D::_init_toolbar()
return true;
}
-#if ENABLE_USE_UNIQUE_GLCONTEXT
bool GLCanvas3D::_set_current()
{
if ((m_canvas != nullptr) && (m_context != nullptr))
@@ -5835,7 +5950,6 @@ bool GLCanvas3D::_set_current()
return false;
}
-#endif ENABLE_USE_UNIQUE_GLCONTEXT
void GLCanvas3D::_resize(unsigned int w, unsigned int h)
{
@@ -5847,11 +5961,7 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
#endif // ENABLE_IMGUI
// ensures that this canvas is current
-#if ENABLE_USE_UNIQUE_GLCONTEXT
_set_current();
-#else
- set_current();
-#endif // ENABLE_USE_UNIQUE_GLCONTEXT
::glViewport(0, 0, w, h);
::glMatrixMode(GL_PROJECTION);
@@ -5932,7 +6042,11 @@ void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox)
viewport_changed();
+#if ENABLE_REWORKED_BED_SHAPE_CHANGE
+ m_dirty = true;
+#else
_refresh_if_shown_on_screen();
+#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
}
}
@@ -6003,28 +6117,6 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co
return (float)std::min((double)cnv_size.get_width() / max_x, (double)cnv_size.get_height() / max_y);
}
-void GLCanvas3D::_mark_volumes_for_layer_height() const
-{
- const Print *print = (m_process == nullptr) ? nullptr : m_process->fff_print();
- if (print == nullptr)
- return;
-
- for (GLVolume* vol : m_volumes.volumes)
- {
- int object_id = vol->object_idx();
- int shader_id = m_layers_editing.get_shader_program_id();
-
- if (is_layers_editing_enabled() && (shader_id != -1) && vol->selected &&
- vol->has_layer_height_texture() && (object_id < (int)print->objects().size()))
- {
- vol->set_layer_height_texture_data(m_layers_editing.get_z_texture_id(), shader_id,
- print->get_object(object_id), _get_layers_editing_cursor_z_relative(), m_layers_editing.band_width);
- }
- else
- vol->reset_layer_height_texture_data();
- }
-}
-
void GLCanvas3D::_refresh_if_shown_on_screen()
{
if (_is_shown_on_screen())
@@ -6034,11 +6126,15 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
// Because of performance problems on macOS, where PaintEvents are not delivered
// frequently enough, we call render() here directly when we can.
+#if ENABLE_REWORKED_BED_SHAPE_CHANGE
+ render();
+#else
// We can't do that when m_force_zoom_to_bed_enabled == true, because then render()
// ends up calling back here via _force_zoom_to_bed(), causing a stack overflow.
if (m_canvas != nullptr) {
m_force_zoom_to_bed_enabled ? m_canvas->Refresh() : render();
}
+#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
}
}
@@ -6166,7 +6262,8 @@ void GLCanvas3D::_render_objects() const
{
if (m_picking_enabled)
{
- _mark_volumes_for_layer_height();
+ // Update the layer editing selection to the first object selected, update the current object maximum Z.
+ const_cast<LayersEditing&>(m_layers_editing).select_object(*m_model, this->is_layers_editing_enabled() ? m_selection.get_object_idx() : -1);
if (m_config != nullptr)
{
@@ -6174,10 +6271,6 @@ void GLCanvas3D::_render_objects() const
m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height"));
m_volumes.check_outside_state(m_config, nullptr);
}
-#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
- // do not cull backfaces to show broken geometry, if any
- ::glDisable(GL_CULL_FACE);
-#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
}
if (m_use_clipping_planes)
@@ -6186,19 +6279,20 @@ void GLCanvas3D::_render_objects() const
m_volumes.set_z_range(-FLT_MAX, FLT_MAX);
m_shader.start_using();
-#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
- // do not cull backfaces to show broken geometry, if any
- m_volumes.render_VBOs(GLVolumeCollection::Opaque, m_picking_enabled);
+ if (m_picking_enabled && m_layers_editing.is_enabled() && m_layers_editing.last_object_id != -1) {
+ int object_id = m_layers_editing.last_object_id;
+ m_volumes.render_VBOs(GLVolumeCollection::Opaque, false, [object_id](const GLVolume &volume) {
+ // Which volume to paint without the layer height profile shader?
+ return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
+ });
+ // Let LayersEditing handle rendering of the active object using the layer height profile shader.
+ m_layers_editing.render_volumes(*this, this->m_volumes);
+ } else {
+ // do not cull backfaces to show broken geometry, if any
+ m_volumes.render_VBOs(GLVolumeCollection::Opaque, m_picking_enabled);
+ }
m_volumes.render_VBOs(GLVolumeCollection::Transparent, false);
-#else
- m_volumes.render_VBOs();
-#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
m_shader.stop_using();
-
-#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
- if (m_picking_enabled)
- ::glEnable(GL_CULL_FACE);
-#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
}
else
{
@@ -6210,24 +6304,9 @@ void GLCanvas3D::_render_objects() const
::glEnable(GL_CLIP_PLANE1);
}
-#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
- // do not cull backfaces to show broken geometry, if any
- if (m_picking_enabled)
- ::glDisable(GL_CULL_FACE);
-#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
-
-#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// do not cull backfaces to show broken geometry, if any
m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled);
m_volumes.render_legacy(GLVolumeCollection::Transparent, false);
-#else
- m_volumes.render_legacy();
-#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
-
-#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
- if (m_picking_enabled)
- ::glEnable(GL_CULL_FACE);
-#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (m_use_clipping_planes)
{
@@ -6269,39 +6348,6 @@ void GLCanvas3D::_render_legend_texture() const
m_legend_texture.render(*this);
}
-void GLCanvas3D::_render_layer_editing_overlay() const
-{
- const Print *print = this->fff_print();
- if ((print == nullptr) || print->objects().empty())
- return;
-
- GLVolume* volume = nullptr;
-
- for (GLVolume* vol : m_volumes.volumes)
- {
- if ((vol != nullptr) && vol->selected && vol->has_layer_height_texture())
- {
- volume = vol;
- break;
- }
- }
-
- if (volume == nullptr)
- return;
-
- // If the active object was not allocated at the Print, go away.This should only be a momentary case between an object addition / deletion
- // and an update by Platter::async_apply_config.
- int object_idx = volume->object_idx();
- if ((int)print->objects().size() <= object_idx)
- return;
-
- const PrintObject* print_object = print->get_object(object_idx);
- if (print_object == nullptr)
- return;
-
- m_layers_editing.render(*this, *print_object, *volume);
-}
-
void GLCanvas3D::_render_volumes(bool fake_colors) const
{
static const GLfloat INV_255 = 1.0f / 255.0f;
@@ -6398,6 +6444,230 @@ void GLCanvas3D::_render_camera_target() const
}
#endif // ENABLE_SHOW_CAMERA_TARGET
+class TessWrapper {
+public:
+ static Pointf3s tesselate(const ExPolygon &expoly, double z_, bool flipped_)
+ {
+ z = z_;
+ flipped = flipped_;
+ triangles.clear();
+ intersection_points.clear();
+ std::vector<GLdouble> coords;
+ {
+ size_t num_coords = expoly.contour.points.size();
+ for (const Polygon &poly : expoly.holes)
+ num_coords += poly.points.size();
+ coords.reserve(num_coords * 3);
+ }
+ GLUtesselator *tess = gluNewTess(); // create a tessellator
+ // register callback functions
+#ifndef _GLUfuncptr
+ #ifdef _MSC_VER
+ typedef void (__stdcall *_GLUfuncptr)(void);
+ #else /* _MSC_VER */
+ #ifdef GLAPIENTRYP
+ typedef void (GLAPIENTRYP _GLUfuncptr)(void);
+ #else /* GLAPIENTRYP */
+ typedef void (*_GLUfuncptr)(void);
+ #endif
+ #endif /* _MSC_VER */
+#endif /* _GLUfuncptr */
+ gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tessBeginCB);
+ gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)tessEndCB);
+ gluTessCallback(tess, GLU_TESS_ERROR, (_GLUfuncptr)tessErrorCB);
+ gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tessVertexCB);
+ gluTessCallback(tess, GLU_TESS_COMBINE, (_GLUfuncptr)tessCombineCB);
+ gluTessBeginPolygon(tess, 0); // with NULL data
+ gluTessBeginContour(tess);
+ for (const Point &pt : expoly.contour.points) {
+ coords.emplace_back(unscale<double>(pt[0]));
+ coords.emplace_back(unscale<double>(pt[1]));
+ coords.emplace_back(0.);
+ gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]);
+ }
+ gluTessEndContour(tess);
+ for (const Polygon &poly : expoly.holes) {
+ gluTessBeginContour(tess);
+ for (const Point &pt : poly.points) {
+ coords.emplace_back(unscale<double>(pt[0]));
+ coords.emplace_back(unscale<double>(pt[1]));
+ coords.emplace_back(0.);
+ gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]);
+ }
+ gluTessEndContour(tess);
+ }
+ gluTessEndPolygon(tess);
+ gluDeleteTess(tess);
+ return std::move(triangles);
+ }
+
+private:
+ static void tessBeginCB(GLenum which)
+ {
+ assert(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP);
+ if (!(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP))
+ printf("Co je to za haluz!?\n");
+ primitive_type = which;
+ num_points = 0;
+ }
+
+ static void tessEndCB()
+ {
+ num_points = 0;
+ }
+
+ static void tessVertexCB(const GLvoid *data)
+ {
+ if (data == nullptr)
+ return;
+ const GLdouble *ptr = (const GLdouble*)data;
+ ++ num_points;
+ if (num_points == 1) {
+ memcpy(pt0, ptr, sizeof(GLdouble) * 3);
+ } else if (num_points == 2) {
+ memcpy(pt1, ptr, sizeof(GLdouble) * 3);
+ } else {
+ bool flip = flipped;
+ if (primitive_type == GL_TRIANGLE_STRIP && num_points == 4) {
+ flip = !flip;
+ num_points = 2;
+ }
+ triangles.emplace_back(pt0[0], pt0[1], z);
+ if (flip) {
+ triangles.emplace_back(ptr[0], ptr[1], z);
+ triangles.emplace_back(pt1[0], pt1[1], z);
+ } else {
+ triangles.emplace_back(pt1[0], pt1[1], z);
+ triangles.emplace_back(ptr[0], ptr[1], z);
+ }
+ if (primitive_type == GL_TRIANGLE_STRIP) {
+ memcpy(pt0, pt1, sizeof(GLdouble) * 3);
+ memcpy(pt1, ptr, sizeof(GLdouble) * 3);
+ } else if (primitive_type == GL_TRIANGLE_FAN) {
+ memcpy(pt1, ptr, sizeof(GLdouble) * 3);
+ } else {
+ assert(primitive_type == GL_TRIANGLES);
+ assert(num_points == 3);
+ num_points = 0;
+ }
+ }
+ }
+
+ static void tessCombineCB(const GLdouble newVertex[3], const GLdouble *neighborVertex[4], const GLfloat neighborWeight[4], GLdouble **outData)
+ {
+ intersection_points.emplace_back(newVertex[0], newVertex[1], newVertex[2]);
+ *outData = intersection_points.back().data();
+ }
+
+ static void tessErrorCB(GLenum errorCode)
+ {
+ const GLubyte *errorStr;
+ errorStr = gluErrorString(errorCode);
+ printf("Error: %s\n", (const char*)errorStr);
+ }
+
+ static GLenum primitive_type;
+ static GLdouble pt0[3];
+ static GLdouble pt1[3];
+ static int num_points;
+ static Pointf3s triangles;
+ static std::deque<Vec3d> intersection_points;
+ static double z;
+ static bool flipped;
+};
+
+GLenum TessWrapper::primitive_type;
+GLdouble TessWrapper::pt0[3];
+GLdouble TessWrapper::pt1[3];
+int TessWrapper::num_points;
+Pointf3s TessWrapper::triangles;
+std::deque<Vec3d> TessWrapper::intersection_points;
+double TessWrapper::z;
+bool TessWrapper::flipped;
+
+static Pointf3s triangulate_expolygons(const ExPolygons &polys, coordf_t z, bool flip)
+{
+ Pointf3s triangles;
+#if 0
+ for (const ExPolygon& poly : polys) {
+ Polygons poly_triangles;
+ // poly.triangulate() is based on a trapezoidal decomposition implemented in an extremely expensive way by clipping the whole input contour with a polygon!
+ poly.triangulate(&poly_triangles);
+ // poly.triangulate_p2t() is based on the poly2tri library, which is not quite stable, it often ends up in a nice stack overflow!
+ // poly.triangulate_p2t(&poly_triangles);
+ for (const Polygon &t : poly_triangles)
+ if (flip) {
+ triangles.emplace_back(to_3d(unscale(t.points[2]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[1]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[0]), z));
+ } else {
+ triangles.emplace_back(to_3d(unscale(t.points[0]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[1]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[2]), z));
+ }
+ }
+#else
+
+// for (const ExPolygon &poly : union_ex(simplify_polygons(to_polygons(polys), true))) {
+ for (const ExPolygon &poly : polys) {
+ append(triangles, TessWrapper::tesselate(poly, z, flip));
+ continue;
+
+ std::list<TPPLPoly> input = expoly_to_polypartition_input(poly);
+ std::list<TPPLPoly> output;
+ // int res = TPPLPartition().Triangulate_MONO(&input, &output);
+ int res = TPPLPartition().Triangulate_EC(&input, &output);
+ if (res == 1) {
+ // Triangulation succeeded. Convert to triangles.
+ size_t num_triangles = 0;
+ for (const TPPLPoly &poly : output)
+ if (poly.GetNumPoints() >= 3)
+ num_triangles += (size_t)poly.GetNumPoints() - 2;
+ triangles.reserve(triangles.size() + num_triangles * 3);
+ for (const TPPLPoly &poly : output) {
+ long num_points = poly.GetNumPoints();
+ if (num_points >= 3) {
+ const TPPLPoint *pt0 = &poly[0];
+ const TPPLPoint *pt1 = nullptr;
+ const TPPLPoint *pt2 = &poly[1];
+ for (long i = 2; i < num_points; ++i) {
+ pt1 = pt2;
+ pt2 = &poly[i];
+ if (flip) {
+ triangles.emplace_back(unscale<double>(pt2->x), unscale<double>(pt2->y), z);
+ triangles.emplace_back(unscale<double>(pt1->x), unscale<double>(pt1->y), z);
+ triangles.emplace_back(unscale<double>(pt0->x), unscale<double>(pt0->y), z);
+ } else {
+ triangles.emplace_back(unscale<double>(pt0->x), unscale<double>(pt0->y), z);
+ triangles.emplace_back(unscale<double>(pt1->x), unscale<double>(pt1->y), z);
+ triangles.emplace_back(unscale<double>(pt2->x), unscale<double>(pt2->y), z);
+ }
+ }
+ }
+ }
+ } else {
+ // Triangulation by polypartition failed. Use the expensive slow implementation.
+ Polygons poly_triangles;
+ // poly.triangulate() is based on a trapezoidal decomposition implemented in an extremely expensive way by clipping the whole input contour with a polygon!
+ poly.triangulate(&poly_triangles);
+ // poly.triangulate_p2t() is based on the poly2tri library, which is not quite stable, it often ends up in a nice stack overflow!
+ // poly.triangulate_p2t(&poly_triangles);
+ for (const Polygon &t : poly_triangles)
+ if (flip) {
+ triangles.emplace_back(to_3d(unscale(t.points[2]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[1]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[0]), z));
+ } else {
+ triangles.emplace_back(to_3d(unscale(t.points[0]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[1]), z));
+ triangles.emplace_back(to_3d(unscale(t.points[2]), z));
+ }
+ }
+ }
+#endif
+ return triangles;
+}
+
void GLCanvas3D::_render_sla_slices() const
{
if (!m_use_clipping_planes || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
@@ -6415,34 +6685,32 @@ void GLCanvas3D::_render_sla_slices() const
{
const SLAPrintObject* obj = print_objects[i];
- Pointf3s bottom_obj_triangles;
- Pointf3s bottom_sup_triangles;
- Pointf3s top_obj_triangles;
- Pointf3s top_sup_triangles;
-
double shift_z = obj->get_current_elevation();
double min_z = clip_min_z - shift_z;
double max_z = clip_max_z - shift_z;
- if (m_sla_caps[0].matches(min_z))
+ SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
+ SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i);
{
- SlaCap::ObjectIdToTrianglesMap::const_iterator it = m_sla_caps[0].triangles.find(i);
- if (it != m_sla_caps[0].triangles.end())
- {
- bottom_obj_triangles = it->second.object;
- bottom_sup_triangles = it->second.suppports;
+ if (it_caps_bottom == m_sla_caps[0].triangles.end())
+ it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first;
+ if (! m_sla_caps[0].matches(min_z)) {
+ m_sla_caps[0].z = min_z;
+ it_caps_bottom->second.object.clear();
+ it_caps_bottom->second.supports.clear();
}
- }
-
- if (m_sla_caps[1].matches(max_z))
- {
- SlaCap::ObjectIdToTrianglesMap::const_iterator it = m_sla_caps[1].triangles.find(i);
- if (it != m_sla_caps[1].triangles.end())
- {
- top_obj_triangles = it->second.object;
- top_sup_triangles = it->second.suppports;
+ if (it_caps_top == m_sla_caps[1].triangles.end())
+ it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first;
+ if (! m_sla_caps[1].matches(max_z)) {
+ m_sla_caps[1].z = max_z;
+ it_caps_top->second.object.clear();
+ it_caps_top->second.supports.clear();
}
}
+ Pointf3s &bottom_obj_triangles = it_caps_bottom->second.object;
+ Pointf3s &bottom_sup_triangles = it_caps_bottom->second.supports;
+ Pointf3s &top_obj_triangles = it_caps_top->second.object;
+ Pointf3s &top_sup_triangles = it_caps_top->second.supports;
const std::vector<SLAPrintObject::Instance>& instances = obj->instances();
struct InstanceTransform
@@ -6468,86 +6736,22 @@ void GLCanvas3D::_render_sla_slices() const
if (it_min_z != index.end())
{
+ // calculate model bottom cap
if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
- {
- // calculate model bottom cap
- const ExPolygons& polys = model_slices[it_min_z->second.model_slices_idx];
- for (const ExPolygon& poly : polys)
- {
- Polygons poly_triangles;
- poly.triangulate(&poly_triangles);
- for (const Polygon& t : poly_triangles)
- {
- for (int v = 2; v >= 0; --v)
- {
- bottom_obj_triangles.emplace_back(to_3d(unscale(t.points[v]), min_z));
- }
- }
- }
- }
-
+ bottom_obj_triangles = triangulate_expolygons(model_slices[it_min_z->second.model_slices_idx], min_z, true);
+ // calculate support bottom cap
if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size()))
- {
- // calculate support bottom cap
- const ExPolygons& polys = support_slices[it_min_z->second.support_slices_idx];
- for (const ExPolygon& poly : polys)
- {
- Polygons poly_triangles;
- poly.triangulate(&poly_triangles);
- for (const Polygon& t : poly_triangles)
- {
- for (int v = 2; v >= 0; --v)
- {
- bottom_sup_triangles.emplace_back(to_3d(unscale(t.points[v]), min_z));
- }
- }
- }
-
- m_sla_caps[0].triangles.insert(SlaCap::ObjectIdToTrianglesMap::value_type(i, { bottom_obj_triangles, bottom_sup_triangles }));
- m_sla_caps[0].z = min_z;
- }
+ bottom_sup_triangles = triangulate_expolygons(support_slices[it_min_z->second.support_slices_idx], min_z, true);
}
if (it_max_z != index.end())
{
+ // calculate model top cap
if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size()))
- {
- // calculate model top cap
- const ExPolygons& polys = model_slices[it_max_z->second.model_slices_idx];
- for (const ExPolygon& poly : polys)
- {
- Polygons poly_triangles;
- poly.triangulate(&poly_triangles);
- for (const Polygon& t : poly_triangles)
- {
- for (int v = 0; v < 3; ++v)
- {
- top_obj_triangles.emplace_back(to_3d(unscale(t.points[v]), max_z));
- }
- }
- }
- }
-
+ top_obj_triangles = triangulate_expolygons(model_slices[it_max_z->second.model_slices_idx], max_z, false);
+ // calculate support top cap
if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size()))
- {
- // calculate support top cap
- const ExPolygons& polys = support_slices[it_max_z->second.support_slices_idx];
- for (const ExPolygon& poly : polys)
- {
- Polygons poly_triangles;
- poly.triangulate(&poly_triangles);
- for (const Polygon& t : poly_triangles)
- {
- for (int v = 0; v < 3; ++v)
- {
- top_sup_triangles.emplace_back(to_3d(unscale(t.points[v]), max_z));
- }
- }
- }
- }
-
- m_sla_caps[1].triangles.insert(SlaCap::ObjectIdToTrianglesMap::value_type(i, { top_obj_triangles, top_sup_triangles }));
- m_sla_caps[1].z = max_z;
+ top_sup_triangles = triangulate_expolygons(support_slices[it_max_z->second.support_slices_idx], max_z, false);
}
}
@@ -6593,7 +6797,6 @@ void GLCanvas3D::_render_sla_slices() const
}
}
-#if ENABLE_SIDEBAR_VISUAL_HINTS
void GLCanvas3D::_render_selection_sidebar_hints() const
{
if (m_use_VBOs)
@@ -6604,7 +6807,6 @@ void GLCanvas3D::_render_selection_sidebar_hints() const
if (m_use_VBOs)
m_shader.stop_using();
}
-#endif // ENABLE_SIDEBAR_VISUAL_HINTS
void GLCanvas3D::_update_volumes_hover_state() const
{
@@ -6659,11 +6861,7 @@ void GLCanvas3D::_update_gizmos_data()
// all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
m_gizmos.set_scale(volume->get_instance_scaling_factor());
-#if ENABLE_WORLD_ROTATIONS
m_gizmos.set_rotation(Vec3d::Zero());
-#else
- m_gizmos.set_rotation(volume->get_instance_rotation());
-#endif // ENABLE_WORLD_ROTATIONS
ModelObject* model_object = m_model->objects[m_selection.get_object_idx()];
m_gizmos.set_flattening_data(model_object);
#if ENABLE_SLA_SUPPORT_GIZMO_MOD
@@ -6676,11 +6874,7 @@ void GLCanvas3D::_update_gizmos_data()
{
const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
m_gizmos.set_scale(volume->get_volume_scaling_factor());
-#if ENABLE_WORLD_ROTATIONS
m_gizmos.set_rotation(Vec3d::Zero());
-#else
- m_gizmos.set_rotation(volume->get_volume_rotation());
-#endif // ENABLE_WORLD_ROTATIONS
m_gizmos.set_flattening_data(nullptr);
#if ENABLE_SLA_SUPPORT_GIZMO_MOD
m_gizmos.set_sla_support_data(nullptr, m_selection);
@@ -6701,55 +6895,24 @@ void GLCanvas3D::_update_gizmos_data()
}
}
-float GLCanvas3D::_get_layers_editing_cursor_z_relative() const
-{
- return m_layers_editing.get_cursor_z_relative(*this);
-}
-
void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
{
int object_idx_selected = m_layers_editing.last_object_id;
if (object_idx_selected == -1)
return;
- const Print *print = this->fff_print();
- if (print == nullptr)
- return;
-
- const PrintObject* selected_obj = print->get_object(object_idx_selected);
- if (selected_obj == nullptr)
- return;
-
// A volume is selected. Test, whether hovering over a layer thickness bar.
if (evt != nullptr)
{
const Rect& rect = LayersEditing::get_bar_rect_screen(*this);
float b = rect.get_bottom();
- m_layers_editing.last_z = unscale<double>(selected_obj->size(2)) * (b - evt->GetY() - 1.0f) / (b - rect.get_top());
- m_layers_editing.last_action = evt->ShiftDown() ? (evt->RightIsDown() ? 3 : 2) : (evt->RightIsDown() ? 0 : 1);
- }
-
- // Mark the volume as modified, so Print will pick its layer height profile ? Where to mark it ?
- // Start a timer to refresh the print ? schedule_background_process() ?
- // The PrintObject::adjust_layer_height_profile() call adjusts the profile of its associated ModelObject, it does not modify the profile of the PrintObject itself,
- // therefore it is safe to call it while the background processing is running.
- const_cast<PrintObject*>(selected_obj)->adjust_layer_height_profile(m_layers_editing.last_z, m_layers_editing.strength, m_layers_editing.band_width, m_layers_editing.last_action);
-
- // searches the id of the first volume of the selected object
- int volume_idx = 0;
- for (int i = 0; i < object_idx_selected; ++i)
- {
- const PrintObject* obj = print->get_object(i);
- if (obj != nullptr)
- {
- for (int j = 0; j < (int)obj->region_volumes.size(); ++j)
- {
- volume_idx += (int)obj->region_volumes[j].size();
- }
- }
+ m_layers_editing.last_z = m_layers_editing.object_max_z() * (b - evt->GetY() - 1.0f) / (b - rect.get_top());
+ m_layers_editing.last_action =
+ evt->ShiftDown() ? (evt->RightIsDown() ? LAYER_HEIGHT_EDIT_ACTION_SMOOTH : LAYER_HEIGHT_EDIT_ACTION_REDUCE) :
+ (evt->RightIsDown() ? LAYER_HEIGHT_EDIT_ACTION_INCREASE : LAYER_HEIGHT_EDIT_ACTION_DECREASE);
}
- m_volumes.volumes[volume_idx]->generate_layer_height_texture(selected_obj, 1);
+ m_layers_editing.adjust_layer_height_profile();
_refresh_if_shown_on_screen();
// Automatic action on mouse down with the same coordinate.
@@ -6806,12 +6969,6 @@ void GLCanvas3D::_stop_timer()
void GLCanvas3D::_load_print_toolpaths()
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- // ensures this canvas is current
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
const Print *print = this->fff_print();
if (print == nullptr)
return;
@@ -6899,22 +7056,31 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
}
} ctxt;
+ ctxt.has_perimeters = print_object.is_step_done(posPerimeters);
+ ctxt.has_infill = print_object.is_step_done(posInfill);
+ ctxt.has_support = print_object.is_step_done(posSupportMaterial);
+ ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
+
ctxt.shifted_copies = &print_object.copies();
// order layers by print_z
- ctxt.layers.reserve(print_object.layers().size() + print_object.support_layers().size());
- for (const Layer *layer : print_object.layers())
- ctxt.layers.push_back(layer);
- for (const Layer *layer : print_object.support_layers())
- ctxt.layers.push_back(layer);
+ {
+ size_t nlayers = 0;
+ if (ctxt.has_perimeters || ctxt.has_infill)
+ nlayers = print_object.layers().size();
+ if (ctxt.has_support)
+ nlayers += print_object.support_layers().size();
+ ctxt.layers.reserve(nlayers);
+ }
+ if (ctxt.has_perimeters || ctxt.has_infill)
+ for (const Layer *layer : print_object.layers())
+ ctxt.layers.push_back(layer);
+ if (ctxt.has_support)
+ for (const Layer *layer : print_object.support_layers())
+ ctxt.layers.push_back(layer);
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
// Maximum size of an allocation block: 32MB / sizeof(float)
- ctxt.has_perimeters = print_object.is_step_done(posPerimeters);
- ctxt.has_infill = print_object.is_step_done(posInfill);
- ctxt.has_support = print_object.is_step_done(posSupportMaterial);
- ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
-
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
//FIXME Improve the heuristics for a grain size.
@@ -7948,31 +8114,16 @@ std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& col
void GLCanvas3D::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
m_legend_texture.generate(preview_data, tool_colors, *this, m_dynamic_background_enabled && _is_any_volume_outside());
}
void GLCanvas3D::_generate_warning_texture(const std::string& msg)
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
m_warning_texture.generate(msg);
}
void GLCanvas3D::_reset_warning_texture()
{
-#if !ENABLE_USE_UNIQUE_GLCONTEXT
- if (!set_current())
- return;
-#endif // !ENABLE_USE_UNIQUE_GLCONTEXT
-
m_warning_texture.reset();
}