This commit is contained in:
YuSanka 2019-01-21 13:05:59 +01:00
commit 7a30dd250a
38 changed files with 784 additions and 711 deletions

View file

@ -386,58 +386,6 @@ void GLVolume::render() const
::glPopMatrix();
}
void GLVolume::render_using_layer_height() const
{
if (!is_active)
return;
GLint current_program_id;
glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id);
if ((layer_height_texture_data.shader_id > 0) && (layer_height_texture_data.shader_id != current_program_id))
glUseProgram(layer_height_texture_data.shader_id);
GLint z_to_texture_row_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_to_texture_row") : -1;
GLint z_texture_row_to_normalized_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_texture_row_to_normalized") : -1;
GLint z_cursor_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_cursor") : -1;
GLint z_cursor_band_width_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_cursor_band_width") : -1;
GLint world_matrix_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "volume_world_matrix") : -1;
if (z_to_texture_row_id >= 0)
glUniform1f(z_to_texture_row_id, (GLfloat)layer_height_texture_z_to_row_id());
if (z_texture_row_to_normalized_id >= 0)
glUniform1f(z_texture_row_to_normalized_id, (GLfloat)(1.0f / layer_height_texture_height()));
if (z_cursor_id >= 0)
glUniform1f(z_cursor_id, (GLfloat)(layer_height_texture_data.print_object->model_object()->bounding_box().max(2) * layer_height_texture_data.z_cursor_relative));
if (z_cursor_band_width_id >= 0)
glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width);
if (world_matrix_id >= 0)
::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data());
GLsizei w = (GLsizei)layer_height_texture_width();
GLsizei h = (GLsizei)layer_height_texture_height();
GLsizei half_w = w / 2;
GLsizei half_h = h / 2;
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, layer_height_texture_data.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, layer_height_texture_data_ptr_level0());
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, layer_height_texture_data_ptr_level1());
render();
glBindTexture(GL_TEXTURE_2D, 0);
if ((current_program_id > 0) && (layer_height_texture_data.shader_id != current_program_id))
glUseProgram(current_program_id);
}
void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) const
{
if (!is_active)
@ -446,16 +394,6 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
if (!indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)
return;
if (layer_height_texture_data.can_use())
{
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
render_using_layer_height();
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
return;
}
GLsizei n_triangles = GLsizei(std::min(indexed_vertex_array.triangle_indices_size, tverts_range.second - tverts_range.first));
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
if (n_triangles + n_quads == 0)
@ -558,44 +496,6 @@ void GLVolume::render_legacy() const
::glPopMatrix();
}
double GLVolume::layer_height_texture_z_to_row_id() const
{
return (this->layer_height_texture.get() == nullptr) ? 0.0 : double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * this->layer_height_texture_data.print_object->model_object()->bounding_box().max(2));
}
void GLVolume::generate_layer_height_texture(const PrintObject *print_object, bool force)
{
LayersTexture *tex = this->layer_height_texture.get();
if (tex == nullptr)
// No layer_height_texture is assigned to this GLVolume, therefore the layer height texture cannot be filled.
return;
// Always try to update the layer height profile.
bool update = print_object->update_layer_height_profile(const_cast<ModelObject*>(print_object->model_object())->layer_height_profile) || force;
// Update if the layer height profile was changed, or when the texture is not valid.
if (! update && ! tex->data.empty() && tex->cells > 0)
// Texture is valid, don't update.
return;
if (tex->data.empty()) {
tex->width = 1024;
tex->height = 1024;
tex->levels = 2;
tex->data.assign(tex->width * tex->height * 5, 0);
}
SlicingParameters slicing_params = print_object->slicing_parameters();
bool level_of_detail_2nd_level = true;
tex->cells = Slic3r::generate_layer_height_texture(
slicing_params,
Slic3r::generate_object_layers(slicing_params, print_object->model_object()->layer_height_profile),
tex->data.data(), tex->height, tex->width, level_of_detail_2nd_level);
}
// 512x512 bitmaps are supported everywhere, but that may not be sufficent for super large print volumes.
#define LAYER_HEIGHT_TEXTURE_WIDTH 1024
#define LAYER_HEIGHT_TEXTURE_HEIGHT 1024
std::vector<int> GLVolumeCollection::load_object(
const ModelObject *model_object,
int obj_idx,
@ -603,19 +503,15 @@ std::vector<int> GLVolumeCollection::load_object(
const std::string &color_by,
bool use_VBOs)
{
// Object will share a single common layer height texture between all printable volumes.
std::shared_ptr<LayersTexture> layer_height_texture = std::make_shared<LayersTexture>();
std::vector<int> volumes_idx;
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++ volume_idx)
for (int instance_idx : instance_idxs)
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, layer_height_texture, obj_idx, volume_idx, instance_idx, color_by, use_VBOs));
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, use_VBOs));
return volumes_idx;
}
int GLVolumeCollection::load_object_volume(
const ModelObject *model_object,
// Layer height texture is shared between all printable volumes of a single ModelObject.
std::shared_ptr<LayersTexture> &layer_height_texture,
int obj_idx,
int volume_idx,
int instance_idx,
@ -666,7 +562,6 @@ int GLVolumeCollection::load_object_volume(
v.set_convex_hull(&model_volume->get_convex_hull(), false);
if (extruder_id != -1)
v.extruder_id = extruder_id;
v.layer_height_texture = layer_height_texture;
}
v.is_modifier = ! model_volume->is_model_part();
v.shader_outside_printer_detection_enabled = model_volume->is_model_part();
@ -696,7 +591,6 @@ void GLVolumeCollection::load_object_auxiliary(
mesh.transform(mesh_trafo_inv);
// Convex hull is required for out of print bed detection.
TriangleMesh convex_hull = mesh.convex_hull_3d();
convex_hull.transform(mesh_trafo_inv);
for (const std::pair<size_t, size_t> &instance_idx : instances) {
const ModelInstance &model_instance = *print_object->model_object()->instances[instance_idx.first];
const SLAPrintObject::Instance &print_instance = print_object->instances()[instance_idx.second];
@ -796,17 +690,19 @@ int GLVolumeCollection::load_wipe_tower_preview(
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
typedef std::pair<GLVolume*, double> GLVolumeWithZ;
typedef std::vector<GLVolumeWithZ> GLVolumesWithZList;
GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type)
static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, std::function<bool(const GLVolume&)> filter_func)
{
GLVolumesWithZList list;
list.reserve(volumes.size());
for (GLVolume* volume : volumes)
{
bool is_transparent = (volume->render_color[3] < 1.0f);
if (((type == GLVolumeCollection::Opaque) && !is_transparent) ||
((type == GLVolumeCollection::Transparent) && is_transparent) ||
(type == GLVolumeCollection::All))
list.push_back(std::make_pair(volume, 0.0));
if ((((type == GLVolumeCollection::Opaque) && !is_transparent) ||
((type == GLVolumeCollection::Transparent) && is_transparent) ||
(type == GLVolumeCollection::All)) &&
(! filter_func || filter_func(*volume)))
list.emplace_back(std::make_pair(volume, 0.0));
}
if ((type == GLVolumeCollection::Transparent) && (list.size() > 1))
@ -827,7 +723,7 @@ GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollec
return list;
}
void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface) const
void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface, std::function<bool(const GLVolume&)> filter_func) const
#else
void GLVolumeCollection::render_VBOs() const
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
@ -863,26 +759,17 @@ void GLVolumeCollection::render_VBOs() const
::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type);
for (GLVolumeWithZ& volume : to_render)
{
if (volume.first->layer_height_texture_data.can_use())
volume.first->generate_layer_height_texture(volume.first->layer_height_texture_data.print_object, false);
else
volume.first->set_render_color();
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, 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);
}
#else
for (GLVolume *volume : this->volumes)
{
if (volume->layer_height_texture_data.can_use())
volume->generate_layer_height_texture(volume->layer_height_texture_data.print_object, false);
else
if (! filter_func || filter_func(*volume)) {
volume->set_render_color();
volume->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
}
volume->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
}
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
::glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -918,7 +805,7 @@ void GLVolumeCollection::render_legacy() const
glEnableClientState(GL_NORMAL_ARRAY);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type);
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, std::function<bool(const GLVolume&)>());
for (GLVolumeWithZ& volume : to_render)
{
volume.first->set_render_color();

View file

@ -9,6 +9,8 @@
#include "libslic3r/Model.hpp"
#include "slic3r/GUI/GLCanvas3DManager.hpp"
#include <functional>
namespace Slic3r {
class Print;
@ -199,50 +201,7 @@ private:
}
};
class LayersTexture
{
public:
LayersTexture() : width(0), height(0), levels(0), cells(0) {}
// Texture data
std::vector<char> data;
// Width of the texture, top level.
size_t width;
// Height of the texture, top level.
size_t height;
// For how many levels of detail is the data allocated?
size_t levels;
// Number of texture cells allocated for the height texture.
size_t cells;
};
class GLVolume {
struct LayerHeightTextureData
{
// ID of the layer height texture
unsigned int texture_id;
// ID of the shader used to render with the layer height texture
unsigned int shader_id;
// The print object to update when generating the layer height texture
const PrintObject* print_object;
float z_cursor_relative;
float edit_band_width;
LayerHeightTextureData() { reset(); }
void reset()
{
texture_id = 0;
shader_id = 0;
print_object = nullptr;
z_cursor_relative = 0.0f;
edit_band_width = 0.0f;
}
bool can_use() const { return (texture_id > 0) && (shader_id > 0) && (print_object != nullptr); }
};
public:
static const float SELECTED_COLOR[4];
static const float HOVER_COLOR[4];
@ -406,7 +365,7 @@ public:
int volume_idx() const { return this->composite_id.volume_id; }
int instance_idx() const { return this->composite_id.instance_id; }
Transform3d world_matrix() const;
Transform3d world_matrix() const;
const BoundingBoxf3& transformed_bounding_box() const;
const BoundingBoxf3& transformed_convex_hull_bounding_box() const;
@ -416,49 +375,13 @@ public:
void set_range(coordf_t low, coordf_t high);
void render() const;
void render_using_layer_height() const;
void render_VBOs(int color_id, int detection_id, int worldmatrix_id) const;
void render_legacy() const;
void finalize_geometry(bool use_VBOs) { this->indexed_vertex_array.finalize_geometry(use_VBOs); }
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
/************************************************ Layer height texture ****************************************************/
std::shared_ptr<LayersTexture> layer_height_texture;
// Data to render this volume using the layer height texture
LayerHeightTextureData layer_height_texture_data;
bool has_layer_height_texture() const
{ return this->layer_height_texture.get() != nullptr; }
size_t layer_height_texture_width() const
{ return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->width; }
size_t layer_height_texture_height() const
{ return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->height; }
size_t layer_height_texture_cells() const
{ return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->cells; }
void* layer_height_texture_data_ptr_level0() const {
return (layer_height_texture.get() == nullptr) ? 0 :
(void*)layer_height_texture->data.data();
}
void* layer_height_texture_data_ptr_level1() const {
return (layer_height_texture.get() == nullptr) ? 0 :
(void*)(layer_height_texture->data.data() + layer_height_texture->width * layer_height_texture->height * 4);
}
double layer_height_texture_z_to_row_id() const;
void generate_layer_height_texture(const PrintObject *print_object, bool force);
void set_layer_height_texture_data(unsigned int texture_id, unsigned int shader_id, const PrintObject* print_object, float z_cursor_relative, float edit_band_width)
{
layer_height_texture_data.texture_id = texture_id;
layer_height_texture_data.shader_id = shader_id;
layer_height_texture_data.print_object = print_object;
layer_height_texture_data.z_cursor_relative = z_cursor_relative;
layer_height_texture_data.edit_band_width = edit_band_width;
}
void reset_layer_height_texture_data() { layer_height_texture_data.reset(); }
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
};
typedef std::vector<GLVolume*> GLVolumePtrs;
@ -498,7 +421,6 @@ public:
int load_object_volume(
const ModelObject *model_object,
std::shared_ptr<LayersTexture> &layer_height_texture,
int obj_idx,
int volume_idx,
int instance_idx,
@ -521,7 +443,7 @@ public:
// Render the volumes by OpenGL.
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
void render_VBOs(ERenderType type, bool disable_cullface) const;
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) const;
#else
void render_VBOs() const;

View file

@ -819,12 +819,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(new SlicingParameters)
, 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 +839,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 +859,20 @@ bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename,
return true;
}
void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
{
m_model_object = (object_id >= 0) ? model.objects[object_id] : nullptr;
m_object_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->bounding_box().max.z();
if (m_model_object == nullptr || this->last_object_id != object_id) {
m_layer_height_profile.clear();
m_layer_height_profile_modified = false;
}
this->last_object_id = object_id;
}
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 +890,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 +907,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 +916,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,21 +1028,19 @@ 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;
@ -1045,8 +1048,8 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas
::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());
::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);
// Render the color bar
float l = bar_rect.get_left();
@ -1057,25 +1060,24 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas
::glBegin(GL_QUADS);
::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.
//FIXME show some kind of legend.
// Get a maximum layer height value.
// FIXME This is a duplicate code of Slicing.cpp.
//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;
const std::vector<double>& nozzle_diameters = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"))->values;
const std::vector<double>& layer_heights_min = dynamic_cast<const ConfigOptionFloats*>(m_config->option("min_layer_height"))->values;
const std::vector<double>& layer_heights_max = dynamic_cast<const ConfigOptionFloats*>(m_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]);
@ -1086,15 +1088,19 @@ void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object,
// 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;
// Get global layer height.
double layer_height = dynamic_cast<const ConfigOptionFloat*>(m_config->option("layer_height"))->value;
// Override the global layer height with object's layer height if set.
const ConfigOption *opt_object_layer_height = m_model_object->config.option("layer_height");
if (opt_object_layer_height != nullptr)
layer_height = dynamic_cast<const ConfigOptionFloat*>(opt_object_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 scale_y = h / m_object_max_z;
float x = l + (float)layer_height * scale_x;
// Baseline
@ -1105,19 +1111,129 @@ void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object,
::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(l + (float)m_layer_height_profile[i + 1] * scale_x, b + (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();
}
::glEnd();
// 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()
{
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object);
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::generate_layer_height_texture()
{
// Always try to update the layer height profile.
bool update = ! m_layers_texture.valid;
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object);
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));
}
}
m_layer_height_profile_modified = false;
}
const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX);
@ -1668,11 +1784,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.)));
@ -2800,13 +2919,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);
}
@ -3689,7 +3808,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);
@ -3718,7 +3836,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)
@ -3912,9 +4034,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)
@ -3937,7 +4060,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;
}
@ -4032,10 +4159,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)
{
@ -4116,6 +4245,9 @@ void GLCanvas3D::set_viewport_from_scene(const GLCanvas3D& other)
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;
}
@ -4168,8 +4300,18 @@ void GLCanvas3D::render()
#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();
@ -4239,7 +4381,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();
@ -4479,8 +4622,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 +4631,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 +4639,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;
}
}
}
}
@ -4922,10 +5032,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)
@ -4944,7 +5052,7 @@ 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;
@ -5009,10 +5117,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_model->objects[layer_editing_object_idx]->layer_height_profile.clear();
// Index 2 means no editing, just wait for mouse up event.
m_layers_editing.state = LayersEditing::Completed;
@ -5273,9 +5379,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)
{
@ -5365,9 +5469,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
@ -5452,7 +5555,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
@ -5737,11 +5842,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()
{
@ -5783,7 +5890,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;
@ -5791,7 +5898,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;
@ -5799,7 +5906,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;
@ -5807,7 +5914,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;
@ -5818,7 +5925,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;
@ -5826,7 +5933,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;
@ -5973,7 +6080,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
}
}
@ -6044,28 +6155,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())
@ -6075,11 +6164,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
}
}
@ -6207,7 +6300,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)
{
@ -6228,8 +6322,18 @@ void GLCanvas3D::_render_objects() const
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();
@ -6310,39 +6414,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;
@ -6742,55 +6813,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);
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);
}
// 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_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.

View file

@ -29,6 +29,8 @@ class GLShader;
class ExPolygon;
class BackgroundSlicingProcess;
class GCodePreviewData;
struct SlicingParameters;
enum LayerHeightEditActionType : unsigned int;
namespace GUI {
@ -101,7 +103,6 @@ wxDECLARE_EVENT(EVT_GLCANVAS_INIT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent);
@ -293,12 +294,42 @@ class GLCanvas3D
};
private:
bool m_use_legacy_opengl;
bool m_enabled;
Shader m_shader;
unsigned int m_z_texture_id;
mutable GLTexture m_tooltip_texture;
mutable GLTexture m_reset_texture;
bool m_use_legacy_opengl;
bool m_enabled;
Shader m_shader;
unsigned int m_z_texture_id;
mutable GLTexture m_tooltip_texture;
mutable GLTexture m_reset_texture;
// Not owned by LayersEditing.
const DynamicPrintConfig *m_config;
// ModelObject for the currently selected object (Model::objects[last_object_id]).
const ModelObject *m_model_object;
// Maximum z of the currently selected object (Model::objects[last_object_id]).
float m_object_max_z;
// Owned by LayersEditing.
SlicingParameters *m_slicing_parameters;
std::vector<coordf_t> m_layer_height_profile;
bool m_layer_height_profile_modified;
class LayersTexture
{
public:
LayersTexture() : width(0), height(0), levels(0), cells(0), valid(false) {}
// Texture data
std::vector<char> data;
// Width of the texture, top level.
size_t width;
// Height of the texture, top level.
size_t height;
// For how many levels of detail is the data allocated?
size_t levels;
// Number of texture cells allocated for the height texture.
size_t cells;
// Does it need to be refreshed?
bool valid;
};
LayersTexture m_layers_texture;
public:
EState state;
@ -306,12 +337,14 @@ class GLCanvas3D
float strength;
int last_object_id;
float last_z;
unsigned int last_action;
LayerHeightEditActionType last_action;
LayersEditing();
~LayersEditing();
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
void set_config(const DynamicPrintConfig* config) { m_config = config; }
void select_object(const Model &model, int object_id);
bool is_allowed() const;
void set_use_legacy_opengl(bool use_legacy_opengl);
@ -319,11 +352,12 @@ class GLCanvas3D
bool is_enabled() const;
void set_enabled(bool enabled);
unsigned int get_z_texture_id() const;
void render_overlay(const GLCanvas3D& canvas) const;
void render_volumes(const GLCanvas3D& canvas, const GLVolumeCollection& volumes) const;
void render(const GLCanvas3D& canvas, const PrintObject& print_object, const GLVolume& volume) const;
int get_shader_program_id() const;
void generate_layer_height_texture();
void adjust_layer_height_profile();
void accept_changes(GLCanvas3D& canvas);
static float get_cursor_z_relative(const GLCanvas3D& canvas);
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
@ -333,12 +367,14 @@ class GLCanvas3D
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
static Rect get_reset_rect_viewport(const GLCanvas3D& canvas);
float object_max_z() const { return m_object_max_z; }
private:
bool _is_initialized() const;
void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const;
void _render_reset_texture(const Rect& reset_rect) const;
void _render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const;
void _render_profile(const PrintObject& print_object, const Rect& bar_rect) const;
void _render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const;
void _render_profile(const Rect& bar_rect) const;
};
struct Mouse
@ -821,7 +857,7 @@ private:
mutable GLVolumeCollection m_volumes;
Selection m_selection;
DynamicPrintConfig* m_config;
const DynamicPrintConfig* m_config;
Model* m_model;
BackgroundSlicingProcess *m_process;
@ -829,7 +865,11 @@ private:
bool m_dirty;
bool m_initialized;
bool m_use_VBOs;
#if ENABLE_REWORKED_BED_SHAPE_CHANGE
bool m_requires_zoom_to_bed;
#else
bool m_force_zoom_to_bed_enabled;
#endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
bool m_apply_zoom_to_volumes_filter;
mutable int m_hover_volume_id;
bool m_toolbar_action_running;
@ -877,7 +917,7 @@ public:
void reset_volumes();
int check_volumes_outside_state() const;
void set_config(DynamicPrintConfig* config);
void set_config(const DynamicPrintConfig* config);
void set_process(BackgroundSlicingProcess* process);
void set_model(Model* model);
@ -920,7 +960,9 @@ public:
void enable_moving(bool enable);
void enable_gizmos(bool enable);
void enable_toolbar(bool enable);
#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
void enable_force_zoom_to_bed(bool enable);
#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
void enable_dynamic_background(bool enable);
void allow_multisample(bool allow);
@ -1001,7 +1043,9 @@ public:
private:
bool _is_shown_on_screen() const;
#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
void _force_zoom_to_bed();
#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
bool _init_toolbar();
@ -1015,7 +1059,6 @@ private:
void _zoom_to_bounding_box(const BoundingBoxf3& bbox);
float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const;
void _mark_volumes_for_layer_height() const;
void _refresh_if_shown_on_screen();
void _camera_tranform() const;
@ -1030,7 +1073,6 @@ private:
#endif // ENABLE_RENDER_SELECTION_CENTER
void _render_warning_texture() const;
void _render_legend_texture() const;
void _render_layer_editing_overlay() const;
void _render_volumes(bool fake_colors) const;
void _render_current_gizmo() const;
void _render_gizmos_overlay() const;
@ -1047,7 +1089,6 @@ private:
void _update_volumes_hover_state() const;
void _update_gizmos_data();
float _get_layers_editing_cursor_z_relative() const;
void _perform_layer_editing_action(wxMouseEvent* evt = nullptr);
// Convert the screen space coordinate to an object space coordinate.

View file

@ -748,7 +748,7 @@ bool GLGizmoRotate3D::on_init()
std::string GLGizmoRotate3D::on_get_name() const
{
return L("Rotate");
return L("Rotate [R]");
}
void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection)
@ -838,7 +838,7 @@ bool GLGizmoScale3D::on_init()
std::string GLGizmoScale3D::on_get_name() const
{
return L("Scale");
return L("Scale [S]");
}
void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection)
@ -1197,7 +1197,7 @@ bool GLGizmoMove3D::on_init()
std::string GLGizmoMove3D::on_get_name() const
{
return L("Move");
return L("Move [M]");
}
void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection)
@ -1427,7 +1427,7 @@ bool GLGizmoFlatten::on_init()
std::string GLGizmoFlatten::on_get_name() const
{
return L("Place on face");
return L("Place on face [F]");
}
bool GLGizmoFlatten::on_is_activable(const GLCanvas3D::Selection& selection) const
@ -1526,10 +1526,9 @@ void GLGizmoFlatten::update_planes()
vol_ch.transform(vol->get_matrix());
ch.merge(vol_ch);
}
ch = ch.convex_hull_3d();
m_planes.clear();
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix();
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix(true);
// Following constants are used for discarding too small polygons.
const float minimal_area = 5.f; // in square mm (world coordinates)
@ -1559,7 +1558,7 @@ void GLGizmoFlatten::update_planes()
while (facet_queue_cnt > 0) {
int facet_idx = facet_queue[-- facet_queue_cnt];
const stl_normal& this_normal = ch.stl.facet_start[facet_idx].normal;
if (this_normal.isApprox(*normal_ptr)) {
if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) {
stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex;
for (int j=0; j<3; ++j)
m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2));
@ -1696,10 +1695,6 @@ void GLGizmoFlatten::update_planes()
// Transform back to 3D (and also back to mesh coordinates)
polygon = transform(polygon, inst_matrix.inverse() * m.inverse());
// make sure the points are in correct order:
if ( ((inst_matrix.inverse() * m.inverse()) * Vec3d(0., 0., 1.)).dot(normal) > 0.)
std::reverse(polygon.begin(),polygon.end());
}
// We'll sort the planes by area and only keep the 254 largest ones (because of the picking pass limitations):
@ -1714,6 +1709,7 @@ void GLGizmoFlatten::update_planes()
m_volumes_types.push_back(vol->type());
}
m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor();
m_first_instance_mirror = m_model_object->instances.front()->get_mirror();
}
@ -1726,7 +1722,8 @@ bool GLGizmoFlatten::is_plane_update_necessary() const
return true;
// We want to recalculate when the scale changes - some planes could (dis)appear.
if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale))
if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale)
|| ! m_model_object->instances.front()->get_mirror().isApprox(m_first_instance_mirror))
return true;
for (unsigned int i=0; i < m_model_object->volumes.size(); ++i)
@ -2240,9 +2237,8 @@ bool GLGizmoSlaSupports::on_is_selectable() const
}
std::string GLGizmoSlaSupports::on_get_name() const
{
return L("SLA Support Points");
return L("SLA Support Points [L]");
}
@ -2353,7 +2349,7 @@ bool GLGizmoCut::on_init()
std::string GLGizmoCut::on_get_name() const
{
return L("Cut");
return L("Cut [C]");
}
void GLGizmoCut::on_set_state()
@ -2467,11 +2463,13 @@ void GLGizmoCut::on_render_input_window(float x, float y, const GLCanvas3D::Sele
m_imgui->checkbox(_(L("Keep lower part")), m_keep_lower);
m_imgui->checkbox(_(L("Rotate lower part upwards")), m_rotate_lower);
m_imgui->disabled_begin(!m_keep_upper && !m_keep_lower);
const bool cut_clicked = m_imgui->button(_(L("Perform cut")));
m_imgui->disabled_end();
m_imgui->end();
if (cut_clicked) {
if (cut_clicked && (m_keep_upper || m_keep_lower)) {
perform_cut(selection);
}
}

View file

@ -405,6 +405,7 @@ private:
std::vector<Transform3d> m_volumes_matrices;
std::vector<ModelVolume::Type> m_volumes_types;
Vec3d m_first_instance_scale;
Vec3d m_first_instance_mirror;
std::vector<PlaneData> m_planes;
mutable Vec3d m_starting_center;

View file

@ -530,6 +530,8 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
GLToolbarItem::EState state = item->get_state();
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
if (inside)
tooltip = item->get_tooltip();
switch (state)
{
@ -545,9 +547,7 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
}
case GLToolbarItem::Hover:
{
if (inside)
tooltip = item->get_tooltip();
else
if (!inside)
{
item->set_state(GLToolbarItem::Normal);
parent.set_as_dirty();
@ -567,9 +567,7 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
}
case GLToolbarItem::HoverPressed:
{
if (inside)
tooltip = item->get_tooltip();
else
if (!inside)
{
item->set_state(GLToolbarItem::Pressed);
parent.set_as_dirty();
@ -623,6 +621,8 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
GLToolbarItem::EState state = item->get_state();
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
if (inside)
tooltip = item->get_tooltip();
switch (state)
{
@ -638,9 +638,7 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
}
case GLToolbarItem::Hover:
{
if (inside)
tooltip = item->get_tooltip();
else
if (!inside)
{
item->set_state(GLToolbarItem::Normal);
parent.set_as_dirty();
@ -660,9 +658,7 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
}
case GLToolbarItem::HoverPressed:
{
if (inside)
tooltip = item->get_tooltip();
else
if (!inside)
{
item->set_state(GLToolbarItem::Pressed);
parent.set_as_dirty();

View file

@ -27,7 +27,7 @@
namespace Slic3r {
namespace GUI {
View3D::View3D(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
View3D::View3D(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
: m_canvas_widget(nullptr)
, m_canvas(nullptr)
#if !ENABLE_IMGUI
@ -69,7 +69,9 @@ bool View3D::init(wxWindow* parent, Model* model, DynamicPrintConfig* config, Ba
m_canvas->set_config(config);
m_canvas->enable_gizmos(true);
m_canvas->enable_toolbar(true);
#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
m_canvas->enable_force_zoom_to_bed(true);
#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
#if !ENABLE_IMGUI
m_gizmo_widget = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
@ -107,7 +109,9 @@ void View3D::set_bed_shape(const Pointfs& shape)
if (m_canvas != nullptr)
{
m_canvas->set_bed_shape(shape);
#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
m_canvas->zoom_to_bed();
#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
}
}

View file

@ -12,6 +12,8 @@
#include <GL/glew.h>
#include <imgui/imgui_internal.h>
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
#include "GUI.hpp"
@ -23,6 +25,7 @@ namespace GUI {
ImGuiWrapper::ImGuiWrapper()
: m_font_texture(0)
, m_mouse_buttons(0)
, m_disabled(false)
{
}
@ -154,6 +157,26 @@ void ImGuiWrapper::text(const wxString &label)
ImGui::Text(label_utf8.c_str(), NULL);
}
void ImGuiWrapper::disabled_begin(bool disabled)
{
wxCHECK_RET(!m_disabled, "ImGUI: Unbalanced disabled_begin() call");
if (disabled) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
m_disabled = true;
}
}
void ImGuiWrapper::disabled_end()
{
if (m_disabled) {
ImGui::PopItemFlag();
ImGui::PopStyleVar();
m_disabled = false;
}
}
bool ImGuiWrapper::want_mouse() const
{
return ImGui::GetIO().WantCaptureMouse;

View file

@ -21,8 +21,8 @@ class ImGuiWrapper
FontsMap m_fonts;
unsigned m_font_texture;
unsigned m_mouse_buttons;
bool m_disabled;
public:
ImGuiWrapper();
@ -50,6 +50,9 @@ public:
bool checkbox(const wxString &label, bool &value);
void text(const wxString &label);
void disabled_begin(bool disabled);
void disabled_end();
bool want_mouse() const;
bool want_keyboard() const;
bool want_text_input() const;

View file

@ -120,8 +120,7 @@ void KBShortcutsDialog::fill_shortcuts()
main_shortcuts.push_back(Shortcut("+" ,L("Add Instance to selected object ")));
main_shortcuts.push_back(Shortcut("-" ,L("Remove Instance from selected object")));
main_shortcuts.push_back(Shortcut("?" ,L("Show keyboard shortcuts list")));
main_shortcuts.push_back(Shortcut("PgUp/PgDn" ,L("Switch between 3D and Preview")));
main_shortcuts.push_back(Shortcut("Shift+LeftMouse" ,L("Select multiple object/Move multiple object")));
main_shortcuts.push_back(Shortcut("Shift+LeftMouse", L("Select multiple object/Move multiple object")));
m_full_shortcuts.emplace(_(L("Main Shortcuts")), main_shortcuts);

View file

@ -159,6 +159,7 @@ void MainFrame::create_preset_tabs()
add_created_tab(new TabSLAPrint(m_tabpanel));
add_created_tab(new TabSLAMaterial(m_tabpanel));
add_created_tab(new TabPrinter(m_tabpanel));
GUI::wxGetApp().load_current_presets();
}
void MainFrame::add_created_tab(Tab* panel)

View file

@ -1088,7 +1088,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host",
"printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle",
"extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology"
"extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology",
// The following three layer height config values are passed here for View3D::m_canvas to receive
// layer height updates for the layer height.
"min_layer_height", "max_layer_height", "layer_height", "first_layer_height"
}))
, sidebar(new Sidebar(q))
, delayed_scene_refresh(false)
@ -1125,9 +1128,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
this->background_process_timer.SetOwner(this->q, 0);
this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->update_restart_background_process(false, false); });
#if !ENABLE_REWORKED_BED_SHAPE_CHANGE
auto *bed_shape = config->opt<ConfigOptionPoints>("bed_shape");
view3D->set_bed_shape(bed_shape->values);
preview->set_bed_shape(bed_shape->values);
#endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
update();
@ -1155,7 +1160,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this);
view3D_canvas->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this);
view3D_canvas->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this);
view3D_canvas->Bind(EVT_GLCANVAS_MODEL_UPDATE, [this](SimpleEvent&) { this->schedule_background_process(); });
view3D_canvas->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); });
view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); });
view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
@ -2033,7 +2037,7 @@ void Plater::priv::reload_from_disk()
}
}
// XXX: Restore more: layer_height_ranges, layer_height_profile, layer_height_profile_valid (?)
// XXX: Restore more: layer_height_ranges, layer_height_profile (?)
}
remove(obj_orig_idx);
@ -2064,7 +2068,7 @@ void Plater::priv::fix_through_netfabb(const int obj_idx)
o->volumes[i]->config.apply(model_object->volumes[i]->config);
}
}
// FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile, layer_height_profile_valid,
// FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile
}
remove(obj_idx);
@ -2490,7 +2494,7 @@ void Plater::priv::init_view_toolbar()
GLToolbarItem::Data item;
item.name = "3D";
item.tooltip = GUI::L_str("3D editor view");
item.tooltip = GUI::L_str("3D editor view [Ctrl+5]");
item.sprite_id = 0;
item.action_event = EVT_GLVIEWTOOLBAR_3D;
item.is_toggable = false;
@ -2498,7 +2502,7 @@ void Plater::priv::init_view_toolbar()
return;
item.name = "Preview";
item.tooltip = GUI::L_str("Preview");
item.tooltip = GUI::L_str("Preview [Ctrl+6]");
item.sprite_id = 1;
item.action_event = EVT_GLVIEWTOOLBAR_PREVIEW;
item.is_toggable = false;
@ -2765,6 +2769,10 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
if (!keep_upper && !keep_lower) {
return;
}
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
remove(obj_idx);
@ -2965,7 +2973,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
p->config->set_key_value(opt_key, config.option(opt_key)->clone());
if (opt_key == "printer_technology")
this->set_printer_technology(config.opt_enum<PrinterTechnology>(opt_key));
else if (opt_key == "bed_shape") {
else if (opt_key == "bed_shape") {
if (p->view3D) p->view3D->set_bed_shape(p->config->option<ConfigOptionPoints>(opt_key)->values);
if (p->preview) p->preview->set_bed_shape(p->config->option<ConfigOptionPoints>(opt_key)->values);
update_scheduled = true;
@ -2990,12 +2998,14 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
p->preview->set_number_extruders(p->config->option<ConfigOptionStrings>(opt_key)->values.size());
} else if(opt_key == "max_print_height") {
update_scheduled = true;
} else if(opt_key == "printer_model") {
}
else if (opt_key == "printer_model") {
// update to force bed selection(for texturing)
if (p->view3D) p->view3D->set_bed_shape(p->config->option<ConfigOptionPoints>("bed_shape")->values);
if (p->preview) p->preview->set_bed_shape(p->config->option<ConfigOptionPoints>("bed_shape")->values);
update_scheduled = true;
} else if (opt_key == "host_type" && this->p->printer_technology == ptSLA) {
}
else if (opt_key == "host_type" && this->p->printer_technology == ptSLA) {
p->config->option<ConfigOptionEnum<PrintHostType>>(opt_key)->value = htSL1;
}
}

View file

@ -1,4 +1,4 @@
#include "libslic3r/GCodeSender.hpp"
// #include "libslic3r/GCodeSender.hpp"
#include "Tab.hpp"
#include "PresetBundle.hpp"
#include "PresetHints.hpp"
@ -245,9 +245,6 @@ void Tab::create_preset_tab()
// Initialize the DynamicPrintConfig by default keys/values.
build();
rebuild_page_tree();
// update();
// Load the currently selected preset into the GUI, update the preset selection box.
load_current_preset();
}
void Tab::load_initial_data()

View file

@ -288,7 +288,7 @@ bool PrusaCollapsiblePaneMSW::Create(wxWindow *parent, wxWindowID id, const wxSt
{
if (!wxControl::Create(parent, id, pos, size, style, val, name))
return false;
m_pStaticLine = NULL;
// m_pStaticLine = NULL;
m_strLabel = label;
// sizer containing the expand button and possibly a static line