diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index fcb54c018..9cd7cc1a3 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -19,7 +19,7 @@ package Slic3r::GUI::3DScene::Base; use strict; use warnings; -use Wx qw(:timer); +use Wx qw(:timer :bitmap); use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_TIMER); # must load OpenGL *before* Wx::GLCanvas use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants); @@ -173,7 +173,7 @@ sub new { my ($self, $event) = @_; return if ! $self->_layer_height_edited; return if $self->{layer_height_edit_last_object_id} == -1; - $self->_variable_layer_thickness_action(undef, 1); + $self->_variable_layer_thickness_action(undef); }); return $self; @@ -262,7 +262,7 @@ sub mouse_event { # A volume is selected and the mouse is hovering over a layer thickness bar. # Start editing the layer height. $self->_layer_height_edited(1); - $self->_variable_layer_thickness_action($e, 1); + $self->_variable_layer_thickness_action($e); } else { # Select volume in this 3D canvas. # Don't deselect a volume if layer editing is enabled. We want the object to stay selected @@ -325,7 +325,7 @@ sub mouse_event { $self->Refresh; } elsif ($e->Dragging) { if ($self->_layer_height_edited && $object_idx_selected != -1) { - $self->_variable_layer_thickness_action($e, 0); + $self->_variable_layer_thickness_action($e); } elsif ($e->LeftIsDown) { # if dragging over blank area with left button, rotate if (defined $self->_drag_start_pos) { @@ -1125,7 +1125,16 @@ sub draw_volumes { my $volume = $self->volumes->[$volume_idx]; my $shader_active = 0; - if ($self->layer_editing_enabled && ! $fakecolor && $volume->selected && $self->{shader} && $volume->{layer_height_texture_data} && $volume->{layer_height_texture_cells}) { + if ($self->layer_editing_enabled && ! $fakecolor && $volume->selected && $self->{shader} && $volume->{layer_height_texture_data}) { + my $print_object = $self->{print}->get_object(int($volume->select_group_id / 1000000)); + if (! defined($volume->{layer_height_texture_cells}) || $print_object->update_layer_height_profile) { + # Layer height profile was invalid before, now filled in with default data from layer height configuration + # and possibly from the layer height modifiers. Update the height texture. + $volume->{layer_height_texture_cells} = $print_object->generate_layer_height_texture( + $volume->{layer_height_texture_data}->ptr, + $self->{layer_preview_z_texture_height}, + $self->{layer_preview_z_texture_width}); + } $self->{shader}->Enable; my $z_to_texture_row_id = $self->{shader}->Map('z_to_texture_row'); my $z_texture_row_to_normalized_id = $self->{shader}->Map('z_texture_row_to_normalized'); @@ -1263,6 +1272,45 @@ sub draw_volumes { glDisableClientState(GL_VERTEX_ARRAY); } +sub _variable_layer_thickness_load_overlay_image { + my ($self) = @_; + + if (! $self->{layer_preview_annotation}->{loaded}) { + # Load a PNG with an alpha channel. + my $img = Wx::Image->new; + $img->LoadFile($Slic3r::var->("variable_layer_height_tooltip.png"), wxBITMAP_TYPE_PNG); + # Get RGB & alpha raw data from wxImage, interleave them into a Perl array. + my @rgb = unpack 'C*', $img->GetData(); + my @alpha = unpack 'C*', $img->GetAlpha(); + my $n_pixels = int(@alpha); + my @data = (0)x($n_pixels * 4); + for (my $i = 0; $i < $n_pixels; $i += 1) { + $data[$i*4 ] = $rgb[$i*3]; + $data[$i*4+1] = $rgb[$i*3+1]; + $data[$i*4+2] = $rgb[$i*3+2]; + $data[$i*4+3] = $alpha[$i]; + } + # Initialize a raw bitmap data. + my $params = $self->{layer_preview_annotation} = { + loaded => 1, + valid => $n_pixels > 0, + width => $img->GetWidth, + height => $img->GetHeight, + data => OpenGL::Array->new_list(GL_UNSIGNED_BYTE, @data), + texture_id => glGenTextures_p(1) + }; + # Create and initialize a texture with the raw data. + glBindTexture(GL_TEXTURE_2D, $params->{texture_id}); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); + glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $params->{width}, $params->{height}, 0, GL_RGBA, GL_UNSIGNED_BYTE, $params->{data}->ptr); + glBindTexture(GL_TEXTURE_2D, 0); + } + + return $self->{layer_preview_annotation}->{valid}; +} + sub draw_active_object_annotations { # $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking. my ($self) = @_; @@ -1324,6 +1372,28 @@ sub draw_active_object_annotations { glBindTexture(GL_TEXTURE_2D, 0); $self->{shader}->Disable; + # Paint the tooltip. + if ($self->_variable_layer_thickness_load_overlay_image) { + glColor4f(1.,1.,1.,1.); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, $self->{layer_preview_annotation}->{texture_id}); + glBegin(GL_QUADS); + my $gap = 10/$self->_zoom; + my ($l, $r, $t, $b) = ($bar_left - $self->{layer_preview_annotation}->{width}/$self->_zoom - $gap, $bar_left - $gap, $bar_bottom + $self->{layer_preview_annotation}->{height}/$self->_zoom + $gap, $bar_bottom + $gap); + glTexCoord2d(0.,1.); glVertex3f($l, $b, 0); + glTexCoord2d(1.,1.); glVertex3f($r, $b, 0); + glTexCoord2d(1.,0.); glVertex3f($r, $t, 0); + glTexCoord2d(0.,0.); glVertex3f($l, $t, 0); + glEnd(); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glEnable(GL_LIGHTING); + } + # Paint the graph. my $object_idx = int($volume->select_group_id / 1000000); my $print_object = $self->{print}->get_object($object_idx); @@ -1593,11 +1663,6 @@ sub load_object { if ($print && $obj_idx < $print->object_count) { # Generate the layer height texture. Allocate data for the 0th and 1st mipmap levels. $layer_height_texture_data = OpenGL::Array->new($self->{layer_preview_z_texture_width}*$self->{layer_preview_z_texture_height}*5, GL_UNSIGNED_BYTE); -# $print->get_object($obj_idx)->update_layer_height_profile_from_ranges(); - $layer_height_texture_cells = $print->get_object($obj_idx)->generate_layer_height_texture( - $layer_height_texture_data->ptr, - $self->{layer_preview_z_texture_height}, - $self->{layer_preview_z_texture_width}); } my @volumes_idx = (); diff --git a/var/variable_layer_height_tooltip.png b/var/variable_layer_height_tooltip.png new file mode 100644 index 000000000..182005292 Binary files /dev/null and b/var/variable_layer_height_tooltip.png differ diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 963bd7c85..e6e98bc01 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -114,6 +114,9 @@ public: DynamicPrintConfig config; // Variation of a layer thickness for spans of Z coordinates. t_layer_height_ranges layer_height_ranges; + // Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers. + // The pairs of are packed into a 1D array to simplify handling by the Perl XS. + std::vector layer_height_profile; /* This vector accumulates the total translation applied to the object by the center_around_origin() method. Callers might want to apply the same translation diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 6e2fdb4f3..539562a16 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -8,43 +8,6 @@ namespace Slic3r { -template -bool -PrintState::is_started(StepClass step) const -{ - return this->started.find(step) != this->started.end(); -} - -template -bool -PrintState::is_done(StepClass step) const -{ - return this->done.find(step) != this->done.end(); -} - -template -void -PrintState::set_started(StepClass step) -{ - this->started.insert(step); -} - -template -void -PrintState::set_done(StepClass step) -{ - this->done.insert(step); -} - -template -bool -PrintState::invalidate(StepClass step) -{ - bool invalidated = this->started.erase(step) > 0; - this->done.erase(step); - return invalidated; -} - template class PrintState; template class PrintState; diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index a0392290d..99582d65d 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -33,14 +33,18 @@ enum PrintObjectStep { template class PrintState { - public: +public: std::set started, done; - bool is_started(StepType step) const; - bool is_done(StepType step) const; - void set_started(StepType step); - void set_done(StepType step); - bool invalidate(StepType step); + bool is_started(StepType step) const { return this->started.find(step) != this->started.end(); } + bool is_done(StepType step) const { return this->done.find(step) != this->done.end(); } + void set_started(StepType step) { this->started.insert(step); } + void set_done(StepType step) { this->done.insert(step); } + bool invalidate(StepType step) { + bool invalidated = this->started.erase(step) > 0; + this->done.erase(step); + return invalidated; + } }; // A PrintRegion object represents a group of volumes to print @@ -143,7 +147,7 @@ public: // Process layer_height_ranges, the raft layers and first layer thickness into layer_height_profile. // The layer_height_profile may be later modified interactively by the user to refine layers at sloping surfaces. - void update_layer_height_profile(); + bool update_layer_height_profile(); // Collect the slicing parameters, to be used by variable layer thickness algorithm, // by the interactive layer height editor and by the printing process itself. diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 94001cb38..8091db973 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -49,6 +49,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding this->reload_model_instances(); this->layer_height_ranges = model_object->layer_height_ranges; + this->layer_height_profile = model_object->layer_height_profile; } bool @@ -949,8 +950,9 @@ SlicingParameters PrintObject::slicing_parameters() const unscale(this->size.z), this->print()->object_extruders()); } -void PrintObject::update_layer_height_profile() +bool PrintObject::update_layer_height_profile() { + bool updated = false; if (this->layer_height_profile.empty()) { if (0) // if (this->layer_height_profile.empty()) @@ -958,7 +960,9 @@ void PrintObject::update_layer_height_profile() this->model_object()->volumes); else this->layer_height_profile = layer_height_profile_from_ranges(this->slicing_parameters(), this->layer_height_ranges); + updated = true; } + return updated; } // 1) Decides Z positions of the layers, diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index aedc1f7dc..1859779b9 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -4,6 +4,7 @@ #include #include "libslic3r/Model.hpp" #include "libslic3r/PrintConfig.hpp" +#include "libslic3r/Slicing.hpp" %} %name{Slic3r::Model} class Model { @@ -169,6 +170,7 @@ ModelMaterial::attributes() void set_layer_height_ranges(t_layer_height_ranges ranges) %code%{ THIS->layer_height_ranges = ranges; %}; + Ref origin_translation() %code%{ RETVAL = &THIS->origin_translation; %}; void set_origin_translation(Pointf3* point) diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index d2fca6105..f7a3fa118 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -3,7 +3,6 @@ %{ #include #include "libslic3r/Print.hpp" -#include "libslic3r/Slicing.hpp" #include "libslic3r/PlaceholderParser.hpp" %} @@ -121,6 +120,8 @@ _constant() void _infill(); void _generate_support_material(); + bool update_layer_height_profile(); + void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action) %code%{ THIS->update_layer_height_profile();