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

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2016-06-03 11:35:39 +0300
committerbubnikv <bubnikv@gmail.com>2016-06-03 11:35:39 +0300
commit62b440ff6c454099d27327c0f64b6c3ddd15eb72 (patch)
tree0dcdb9dc5adff8b0372e6f302bd1bf3983e524e6 /lib
parent5573faec6b878a3f618618441eef070f4e7e8e95 (diff)
Fixes a performance issues on Windows, where the cut is being
refreshed many times for a single move of the Z plane. Fixes a problem on Windows, where the new wxWidgets always returned Cancel, even if the window was closed with the "Cut" button. Improved performance if the live preview is disabled or not needed, because both top and bottom parts shall be displayed.
Diffstat (limited to 'lib')
-rw-r--r--lib/Slic3r/GUI/Plater/ObjectCutDialog.pm107
1 files changed, 84 insertions, 23 deletions
diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm
index 8b9a2ed99..a523fb085 100644
--- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm
+++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm
@@ -15,6 +15,11 @@ sub new {
$self->{model_object_idx} = $params{model_object_idx};
$self->{model_object} = $params{model_object};
$self->{new_model_objects} = [];
+ # Mark whether the mesh cut is valid.
+ # If not, it needs to be recalculated by _update() on wxTheApp->CallAfter() or on exit of the dialog.
+ $self->{mesh_cut_valid} = 0;
+ # Note whether the window was already closed, so a pending update is not executed.
+ $self->{already_closed} = 0;
# cut options
$self->{cut_options} = {
@@ -31,11 +36,18 @@ sub new {
title => 'Cut',
on_change => sub {
my ($opt_id) = @_;
-
- $self->{cut_options}{$opt_id} = $optgroup->get_value($opt_id);
- wxTheApp->CallAfter(sub {
- $self->_update;
- });
+ # There seems to be an issue with wxWidgets 3.0.2/3.0.3, where the slider
+ # genates tens of events for a single value change.
+ # Only trigger the recalculation if the value changes
+ # or a live preview was activated and the mesh cut is not valid yet.
+ if ($self->{cut_options}{$opt_id} != $optgroup->get_value($opt_id) ||
+ ! $self->{mesh_cut_valid} && $self->_life_preview_active()) {
+ $self->{cut_options}{$opt_id} = $optgroup->get_value($opt_id);
+ $self->{mesh_cut_valid} = 0;
+ wxTheApp->CallAfter(sub {
+ $self->_update;
+ });
+ }
},
label_width => 120,
);
@@ -113,6 +125,10 @@ sub new {
$self->{sizer}->SetSizeHints($self);
EVT_BUTTON($self, $self->{btn_cut}, sub {
+ # Recalculate the cut if the preview was not active.
+ $self->_perform_cut() unless $self->{mesh_cut_valid};
+
+ # Adjust position / orientation of the split object halves.
if ($self->{new_model_objects}{lower}) {
if ($self->{cut_options}{rotate_lower}) {
$self->{new_model_objects}{lower}->rotate(PI, X);
@@ -123,41 +139,86 @@ sub new {
$self->{new_model_objects}{upper}->center_around_origin; # align to Z = 0
}
+ # Note that the window was already closed, so a pending update will not be executed.
+ $self->{already_closed} = 1;
$self->EndModal(wxID_OK);
- $self->Close;
+ $self->Destroy();
});
-
+
+ EVT_CLOSE($self, sub {
+ # Note that the window was already closed, so a pending update will not be executed.
+ $self->{already_closed} = 1;
+ $self->EndModal(wxID_CANCEL);
+ $self->Destroy();
+ });
+
$self->_update;
return $self;
}
+# scale Z down to original size since we're using the transformed mesh for 3D preview
+# and cut dialog but ModelObject::cut() needs Z without any instance transformation
+sub _mesh_slice_z_pos
+{
+ my ($self) = @_;
+ return $self->{cut_options}{z} / $self->{model_object}->instances->[0]->scaling_factor;
+}
+
+# Only perform live preview if just a single part of the object shall survive.
+sub _life_preview_active
+{
+ my ($self) = @_;
+ return $self->{cut_options}{preview} && ($self->{cut_options}{keep_upper} != $self->{cut_options}{keep_lower});
+}
+
+# Slice the mesh, keep the top / bottom part.
+sub _perform_cut
+{
+ my ($self) = @_;
+
+ # Early exit. If the cut is valid, don't recalculate it.
+ return if $self->{mesh_cut_valid};
+
+ my $z = $self->_mesh_slice_z_pos();
+
+ my ($new_model) = $self->{model_object}->cut($z);
+ my ($upper_object, $lower_object) = @{$new_model->objects};
+ $self->{new_model} = $new_model;
+ $self->{new_model_objects} = {};
+ if ($self->{cut_options}{keep_upper} && $upper_object->volumes_count > 0) {
+ $self->{new_model_objects}{upper} = $upper_object;
+ }
+ if ($self->{cut_options}{keep_lower} && $lower_object->volumes_count > 0) {
+ $self->{new_model_objects}{lower} = $lower_object;
+ }
+
+ $self->{mesh_cut_valid} = 1;
+}
+
sub _update {
my ($self) = @_;
-
+
+ # Don't update if the window was already closed.
+ # We are not sure whether the action planned by wxTheApp->CallAfter() may be triggered after the window is closed.
+ # Probably not, but better be safe than sorry, which is espetially true on multiple platforms.
+ return if $self->{already_closed};
+
+ # Only recalculate the cut, if the live cut preview is active.
+ my $life_preview_active = $self->_life_preview_active();
+ $self->_perform_cut() if $life_preview_active;
+
{
# scale Z down to original size since we're using the transformed mesh for 3D preview
# and cut dialog but ModelObject::cut() needs Z without any instance transformation
- my $z = $self->{cut_options}{z} / $self->{model_object}->instances->[0]->scaling_factor;
-
- {
- my ($new_model) = $self->{model_object}->cut($z);
- my ($upper_object, $lower_object) = @{$new_model->objects};
- $self->{new_model} = $new_model;
- $self->{new_model_objects} = {};
- if ($self->{cut_options}{keep_upper} && $upper_object->volumes_count > 0) {
- $self->{new_model_objects}{upper} = $upper_object;
- }
- if ($self->{cut_options}{keep_lower} && $lower_object->volumes_count > 0) {
- $self->{new_model_objects}{lower} = $lower_object;
- }
- }
+ my $z = $self->_mesh_slice_z_pos();
+
# update canvas
if ($self->{canvas}) {
# get volumes to render
my @objects = ();
- if ($self->{cut_options}{preview}) {
+ if ($life_preview_active) {
push @objects, values %{$self->{new_model_objects}};
} else {
push @objects, $self->{model_object};