diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 2e9bddd508..2af137d2bc 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -89,7 +89,7 @@ our $medium_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $medium_font->SetPointSize(12); our $grey = Wx::Colour->new(200,200,200); -our $VERSION_CHECK_EVENT : shared = Wx::NewEventType; +#our $VERSION_CHECK_EVENT : shared = Wx::NewEventType; our $DLP_projection_screen; @@ -181,10 +181,10 @@ sub OnInit { } $self->{mainframe}->config_wizard if $run_wizard; - $self->check_version - if $self->have_version_check - && ($Settings->{_}{version_check} // 1) - && (!$Settings->{_}{last_version_check} || (time - $Settings->{_}{last_version_check}) >= 86400); +# $self->check_version +# if $self->have_version_check +# && ($Settings->{_}{version_check} // 1) +# && (!$Settings->{_}{last_version_check} || (time - $Settings->{_}{last_version_check}) >= 86400); EVT_IDLE($frame, sub { while (my $cb = shift @cb) { @@ -192,24 +192,24 @@ sub OnInit { } }); - EVT_COMMAND($self, -1, $VERSION_CHECK_EVENT, sub { - my ($self, $event) = @_; - my ($success, $response, $manual_check) = @{$event->GetData}; - - if ($success) { - if ($response =~ /^obsolete ?= ?([a-z0-9.-]+,)*\Q$Slic3r::VERSION\E(?:,|$)/) { - my $res = Wx::MessageDialog->new(undef, "A new version is available. Do you want to open the Slic3r website now?", - 'Update', wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_INFORMATION | wxICON_ERROR)->ShowModal; - Wx::LaunchDefaultBrowser('http://slic3r.org/') if $res == wxID_YES; - } else { - Slic3r::GUI::show_info(undef, "You're using the latest version. No updates are available.") if $manual_check; - } - $Settings->{_}{last_version_check} = time(); - $self->save_settings; - } else { - Slic3r::GUI::show_error(undef, "Failed to check for updates. Try later.") if $manual_check; - } - }); +# EVT_COMMAND($self, -1, $VERSION_CHECK_EVENT, sub { +# my ($self, $event) = @_; +# my ($success, $response, $manual_check) = @{$event->GetData}; +# +# if ($success) { +# if ($response =~ /^obsolete ?= ?([a-z0-9.-]+,)*\Q$Slic3r::VERSION\E(?:,|$)/) { +# my $res = Wx::MessageDialog->new(undef, "A new version is available. Do you want to open the Slic3r website now?", +# 'Update', wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_INFORMATION | wxICON_ERROR)->ShowModal; +# Wx::LaunchDefaultBrowser('http://slic3r.org/') if $res == wxID_YES; +# } else { +# Slic3r::GUI::show_info(undef, "You're using the latest version. No updates are available.") if $manual_check; +# } +# $Settings->{_}{last_version_check} = time(); +# $self->save_settings; +# } else { +# Slic3r::GUI::show_error(undef, "Failed to check for updates. Try later.") if $manual_check; +# } +# }); return 1; } @@ -331,28 +331,28 @@ sub presets { return %presets; } -sub have_version_check { - my ($self) = @_; - - # return an explicit 0 - return ($Slic3r::have_threads && $Slic3r::build && $have_LWP) || 0; -} +#sub have_version_check { +# my ($self) = @_; +# +# # return an explicit 0 +# return ($Slic3r::have_threads && $Slic3r::build && $have_LWP) || 0; +#} -sub check_version { - my ($self, $manual_check) = @_; - - Slic3r::debugf "Checking for updates...\n"; - - @_ = (); - threads->create(sub { - my $ua = LWP::UserAgent->new; - $ua->timeout(10); - my $response = $ua->get('http://slic3r.org/updatecheck'); - Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $VERSION_CHECK_EVENT, - threads::shared::shared_clone([ $response->is_success, $response->decoded_content, $manual_check ]))); - Slic3r::thread_cleanup(); - })->detach; -} +#sub check_version { +# my ($self, $manual_check) = @_; +# +# Slic3r::debugf "Checking for updates...\n"; +# +# @_ = (); +# threads->create(sub { +# my $ua = LWP::UserAgent->new; +# $ua->timeout(10); +# my $response = $ua->get('http://slic3r.org/updatecheck'); +# Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $VERSION_CHECK_EVENT, +# threads::shared::shared_clone([ $response->is_success, $response->decoded_content, $manual_check ]))); +# Slic3r::thread_cleanup(); +# })->detach; +#} sub output_path { my ($self, $dir) = @_; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 5a215edebb..e4ac296380 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -34,7 +34,6 @@ use constant TB_SETTINGS => &Wx::NewId; use constant TB_LAYER_EDITING => &Wx::NewId; # package variables to avoid passing lexicals to threads -our $THUMBNAIL_DONE_EVENT : shared = Wx::NewEventType; our $PROGRESS_BAR_EVENT : shared = Wx::NewEventType; our $ERROR_EVENT : shared = Wx::NewEventType; # Emitted from the worker thread when the G-code export is finished. @@ -307,14 +306,6 @@ sub new { for grep defined($_), $self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D}, $self->{list}; - EVT_COMMAND($self, -1, $THUMBNAIL_DONE_EVENT, sub { - my ($self, $event) = @_; - my ($obj_idx) = @{$event->GetData}; - return if !$self->{objects}[$obj_idx]; # object was deleted before thumbnail generation completed - - $self->on_thumbnail_made($obj_idx); - }); - EVT_COMMAND($self, -1, $PROGRESS_BAR_EVENT, sub { my ($self, $event) = @_; my ($percent, $message) = @{$event->GetData}; @@ -803,7 +794,7 @@ sub load_model_objects { $self->{list}->SetItem($obj_idx, 1, $model_object->instances_count); $self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%"); - $self->make_thumbnail($obj_idx); + $self->reset_thumbnail($obj_idx); } $self->arrange if $need_arrange; $self->update; @@ -988,10 +979,7 @@ sub rotate { my $model_object = $self->{model}->objects->[$obj_idx]; my $model_instance = $model_object->instances->[0]; - - # we need thumbnail to be computed before allowing rotation - return if !$object->thumbnail; - + if (!defined $angle) { my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z'; my $default = $axis == Z ? rad2deg($model_instance->rotation) : 0; @@ -1016,7 +1004,7 @@ sub rotate { # realign object to Z = 0 $model_object->center_around_origin; - $self->make_thumbnail($obj_idx); + $self->reset_thumbnail($obj_idx); } $model_object->update_bounding_box; @@ -1048,7 +1036,7 @@ sub mirror { # realign object to Z = 0 $model_object->center_around_origin; - $self->make_thumbnail($obj_idx); + $self->reset_thumbnail($obj_idx); # update print and start background processing $self->stop_background_process; @@ -1068,9 +1056,6 @@ sub changescale { my $model_object = $self->{model}->objects->[$obj_idx]; my $model_instance = $model_object->instances->[0]; - # we need thumbnail to be computed before allowing scaling - return if !$object->thumbnail; - my $object_size = $model_object->bounding_box->size; my $bed_size = Slic3r::Polygon->new_scale(@{$self->{config}->bed_shape})->bounding_box->size; @@ -1101,7 +1086,7 @@ sub changescale { #FIXME Scale the layer height profile when $axis == Z? #FIXME Scale the layer height ranges $axis == Z? # object was already aligned to Z = 0, so no need to realign it - $self->make_thumbnail($obj_idx); + $self->reset_thumbnail($obj_idx); } else { my $scale; if ($tosize) { @@ -1621,12 +1606,6 @@ sub reload_from_disk { } $self->remove($obj_idx); - - # Trigger thumbnail generation again, because the remove() method altered - # object indexes before background thumbnail generation called its completion - # event, so the on_thumbnail_made callback is called with the wrong $obj_idx. - # When porting to C++ we'll probably have cleaner ways to do this. - $self->make_thumbnail($_-1) for @new_obj_idx; } sub export_object_stl { @@ -1674,36 +1653,9 @@ sub _get_export_file { return $output_file; } -sub make_thumbnail { - my $self = shift; - my ($obj_idx) = @_; - - my $plater_object = $self->{objects}[$obj_idx]; - $plater_object->thumbnail(Slic3r::ExPolygon::Collection->new); - my $cb = sub { - $plater_object->make_thumbnail($self->{model}, $obj_idx); - - if ($Slic3r::have_threads) { - Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $THUMBNAIL_DONE_EVENT, shared_clone([ $obj_idx ]))); - Slic3r::thread_cleanup(); - threads->exit; - } else { - $self->on_thumbnail_made($obj_idx); - } - }; - - @_ = (); - $Slic3r::have_threads - ? threads->create(sub { $cb->(); Slic3r::thread_cleanup(); })->detach - : $cb->(); -} - -sub on_thumbnail_made { - my $self = shift; - my ($obj_idx) = @_; - - $self->{objects}[$obj_idx]->transform_thumbnail($self->{model}, $obj_idx); - $self->{canvas}->Refresh; +sub reset_thumbnail { + my ($self, $obj_idx) = @_; + $self->{objects}[$obj_idx]->thumbnail(undef); } # this method gets called whenever print center is changed or the objects' bounding box changes @@ -1727,7 +1679,8 @@ sub update { } else { $self->resume_background_process; } - + + $self->{canvas}->reload_scene if $self->{canvas}; $self->{canvas3D}->reload_scene if $self->{canvas3D}; $self->{preview3D}->reload_print if $self->{preview3D}; } @@ -1942,7 +1895,7 @@ sub object_settings_dialog { if ($dlg->PartsChanged) { # recenter and re-align to Z = 0 $model_object->center_around_origin; - $self->make_thumbnail($obj_idx); + $self->reset_thumbnail($obj_idx); } # update print @@ -1950,6 +1903,7 @@ sub object_settings_dialog { $self->stop_background_process; $self->{print}->reload_object($obj_idx); $self->schedule_background_process; + $self->{canvas}->reload_scene if $self->{canvas}; $self->{canvas3D}->reload_scene if $self->{canvas3D}; } else { $self->resume_background_process; @@ -2245,18 +2199,19 @@ sub make_thumbnail { $self->thumbnail->clear; my $mesh = $model->objects->[$obj_idx]->raw_mesh; - if ($mesh->facets_count <= 5000) { - # remove polygons with area <= 1mm - my $area_threshold = Slic3r::Geometry::scale 1; - $self->thumbnail->append( - grep $_->area >= $area_threshold, - @{ $mesh->horizontal_projection }, # horizontal_projection returns scaled expolygons - ); - $self->thumbnail->simplify(0.5); - } else { +#FIXME The "correct" variant could be extremely slow. +# if ($mesh->facets_count <= 5000) { +# # remove polygons with area <= 1mm +# my $area_threshold = Slic3r::Geometry::scale 1; +# $self->thumbnail->append( +# grep $_->area >= $area_threshold, +# @{ $mesh->horizontal_projection }, # horizontal_projection returns scaled expolygons +# ); +# $self->thumbnail->simplify(0.5); +# } else { my $convex_hull = Slic3r::ExPolygon->new($mesh->convex_hull); $self->thumbnail->append($convex_hull); - } +# } return $self->thumbnail; } diff --git a/lib/Slic3r/GUI/Plater/2D.pm b/lib/Slic3r/GUI/Plater/2D.pm index a24a5a6ff5..8d7b35ac78 100644 --- a/lib/Slic3r/GUI/Plater/2D.pm +++ b/lib/Slic3r/GUI/Plater/2D.pm @@ -13,10 +13,6 @@ use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL); use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT EVT_ERASE_BACKGROUND EVT_SIZE); use base 'Wx::Panel'; -use constant CANVAS_TEXT => join('-', +(localtime)[3,4]) eq '13-8' - ? 'What do you want to print today? ™' # Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap. - : 'Drag your objects here'; - sub new { my $class = shift; my ($parent, $size, $objects, $model, $config) = @_; @@ -128,7 +124,11 @@ sub repaint { if (!@{$self->{objects}}) { $dc->SetTextForeground(Wx::Colour->new(150,50,50)); $dc->SetFont(Wx::Font->new(14, wxDEFAULT, wxNORMAL, wxNORMAL)); - $dc->DrawLabel(CANVAS_TEXT, Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + $dc->DrawLabel( + join('-', +(localtime)[3,4]) eq '13-8' + ? 'What do you want to print today? ™' # Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap. + : 'Drag your objects here', + Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); } # draw thumbnails @@ -340,4 +340,32 @@ sub point_to_model_units { ); } +sub reload_scene { + my ($self, $force) = @_; + + if (! $self->IsShown && ! $force) { + $self->{reload_delayed} = 1; + return; + } + + $self->{reload_delayed} = 0; + + foreach my $obj_idx (0..$#{$self->{model}->objects}) { + my $plater_object = $self->{objects}[$obj_idx]; + next if $plater_object->thumbnail; + # The thumbnail is not valid, update it with a convex hull of an object. + $plater_object->thumbnail(Slic3r::ExPolygon::Collection->new); + $plater_object->make_thumbnail($self->{model}, $obj_idx); + $plater_object->transform_thumbnail($self->{model}, $obj_idx); + } + + $self->Refresh; +} + +# Called by the Platter wxNotebook when this page is activated. +sub OnActivate { + my ($self) = @_; + $self->reload_scene(1) if ($self->{reload_delayed}); +} + 1; diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index 87aff6ef7a..836c8aec81 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -30,14 +30,14 @@ sub new { default => $Slic3r::GUI::Settings->{_}{mode}, width => 100, )); - $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( - opt_id => 'version_check', - type => 'bool', - label => 'Check for updates', - tooltip => 'If this is enabled, Slic3r will check for updates daily and display a reminder if a newer version is available.', - default => $Slic3r::GUI::Settings->{_}{version_check} // 1, - readonly => !wxTheApp->have_version_check, - )); +# $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( +# opt_id => 'version_check', +# type => 'bool', +# label => 'Check for updates', +# tooltip => 'If this is enabled, Slic3r will check for updates daily and display a reminder if a newer version is available.', +# default => $Slic3r::GUI::Settings->{_}{version_check} // 1, +# readonly => !wxTheApp->have_version_check, +# )); $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( opt_id => 'remember_output_path', type => 'bool', diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index b7cdacfa47..7e16944d86 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -492,9 +492,9 @@ TriangleMesh::merge(const TriangleMesh &mesh) stl_get_size(&this->stl); } -/* this will return scaled ExPolygons */ -ExPolygons -TriangleMesh::horizontal_projection() const +// Calculate projection of the mesh into the XY plane, in scaled coordinates. +//FIXME This could be extremely slow! Use it for tiny meshes only! +ExPolygons TriangleMesh::horizontal_projection() const { Polygons pp; pp.reserve(this->stl.stats.number_of_facets); @@ -502,26 +502,25 @@ TriangleMesh::horizontal_projection() const stl_facet* facet = &this->stl.facet_start[i]; Polygon p; p.points.resize(3); - p.points[0] = Point(facet->vertex[0].x / SCALING_FACTOR, facet->vertex[0].y / SCALING_FACTOR); - p.points[1] = Point(facet->vertex[1].x / SCALING_FACTOR, facet->vertex[1].y / SCALING_FACTOR); - p.points[2] = Point(facet->vertex[2].x / SCALING_FACTOR, facet->vertex[2].y / SCALING_FACTOR); + p.points[0] = Point::new_scale(facet->vertex[0].x, facet->vertex[0].y); + p.points[1] = Point::new_scale(facet->vertex[1].x, facet->vertex[1].y); + p.points[2] = Point::new_scale(facet->vertex[2].x, facet->vertex[2].y); p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that pp.push_back(p); } // the offset factor was tuned using groovemount.stl - return union_ex(offset(pp, 0.01 / SCALING_FACTOR), true); + return union_ex(offset(pp, scale_(0.01)), true); } -Polygon -TriangleMesh::convex_hull() +Polygon TriangleMesh::convex_hull() { this->require_shared_vertices(); Points pp; pp.reserve(this->stl.stats.shared_vertices); - for (int i = 0; i < this->stl.stats.shared_vertices; i++) { + for (int i = 0; i < this->stl.stats.shared_vertices; ++ i) { stl_vertex* v = &this->stl.v_shared[i]; - pp.push_back(Point(v->x / SCALING_FACTOR, v->y / SCALING_FACTOR)); + pp.emplace_back(Point::new_scale(v->x, v->y)); } return Slic3r::Geometry::convex_hull(pp); }