mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-05 08:50:42 +08:00
moved interactive layer control to settings dialog
This commit is contained in:
parent
8f2ff28cd9
commit
95d33df2f0
@ -25,7 +25,6 @@ use Slic3r::GUI::Plater::3D;
|
|||||||
use Slic3r::GUI::Plater::3DPreview;
|
use Slic3r::GUI::Plater::3DPreview;
|
||||||
use Slic3r::GUI::Plater::ObjectPartsPanel;
|
use Slic3r::GUI::Plater::ObjectPartsPanel;
|
||||||
use Slic3r::GUI::Plater::ObjectCutDialog;
|
use Slic3r::GUI::Plater::ObjectCutDialog;
|
||||||
use Slic3r::GUI::Plater::ObjectLayersDialog;
|
|
||||||
use Slic3r::GUI::Plater::ObjectSettingsDialog;
|
use Slic3r::GUI::Plater::ObjectSettingsDialog;
|
||||||
use Slic3r::GUI::Plater::LambdaObjectDialog;
|
use Slic3r::GUI::Plater::LambdaObjectDialog;
|
||||||
use Slic3r::GUI::Plater::OverrideSettingsPanel;
|
use Slic3r::GUI::Plater::OverrideSettingsPanel;
|
||||||
|
@ -172,7 +172,7 @@ sub new {
|
|||||||
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new($Slic3r::var->("package.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new($Slic3r::var->("package.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
$self->{htoolbar}->AddSeparator;
|
$self->{htoolbar}->AddSeparator;
|
||||||
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
$self->{htoolbar}->AddTool(TB_LAYERS, "Layer heights…", Wx::Bitmap->new($Slic3r::var->("layers.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_LAYERS, "Layer heights…", Wx::Bitmap->new($Slic3r::var->("variable_layer_height.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
} else {
|
} else {
|
||||||
my %tbar_buttons = (
|
my %tbar_buttons = (
|
||||||
add => "Add…",
|
add => "Add…",
|
||||||
@ -1386,7 +1386,7 @@ sub async_apply_config {
|
|||||||
# reset preview canvases (invalidated contents will be hidden)
|
# reset preview canvases (invalidated contents will be hidden)
|
||||||
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
||||||
$self->{preview3D}->reload_print if $self->{preview3D};
|
$self->{preview3D}->reload_print if $self->{preview3D};
|
||||||
$self->{ObjectLayersDialog}->reload_preview if $self->{ObjectLayersDialog};
|
$self->{AdaptiveLayersDialog}->reload_preview if $self->{AdaptiveLayersDialog};
|
||||||
|
|
||||||
if ($invalidated) {
|
if ($invalidated) {
|
||||||
if (!$Slic3r::GUI::Settings->{_}{background_processing}) {
|
if (!$Slic3r::GUI::Settings->{_}{background_processing}) {
|
||||||
@ -1463,7 +1463,7 @@ sub stop_background_process {
|
|||||||
|
|
||||||
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
||||||
$self->{preview3D}->reload_print if $self->{preview3D};
|
$self->{preview3D}->reload_print if $self->{preview3D};
|
||||||
$self->{ObjectLayersDialog}->reload_preview if $self->{ObjectLayersDialog};
|
$self->{AdaptiveLayersDialog}->reload_preview if $self->{AdaptiveLayersDialog};
|
||||||
|
|
||||||
if ($self->{process_thread}) {
|
if ($self->{process_thread}) {
|
||||||
Slic3r::debugf "Killing background process.\n";
|
Slic3r::debugf "Killing background process.\n";
|
||||||
@ -1610,7 +1610,7 @@ sub on_process_completed {
|
|||||||
return if $error;
|
return if $error;
|
||||||
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
||||||
$self->{preview3D}->reload_print if $self->{preview3D};
|
$self->{preview3D}->reload_print if $self->{preview3D};
|
||||||
$self->{ObjectLayersDialog}->reload_preview if $self->{ObjectLayersDialog};
|
$self->{AdaptiveLayersDialog}->reload_preview if $self->{AdaptiveLayersDialog};
|
||||||
|
|
||||||
# if we have an export filename, start a new thread for exporting G-code
|
# if we have an export filename, start a new thread for exporting G-code
|
||||||
if ($self->{export_gcode_output_file}) {
|
if ($self->{export_gcode_output_file}) {
|
||||||
@ -2108,32 +2108,12 @@ sub object_layers_dialog {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($obj_idx) = @_;
|
my ($obj_idx) = @_;
|
||||||
|
|
||||||
if (!defined $obj_idx) {
|
$self->object_settings_dialog($obj_idx, adaptive_layers => 1);
|
||||||
($obj_idx, undef) = $self->selected_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$Slic3r::GUI::have_OpenGL) {
|
|
||||||
Slic3r::GUI::show_error($self, "Please install the OpenGL modules to use this feature (see build instructions).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->{ObjectLayersDialog} = Slic3r::GUI::Plater::ObjectLayersDialog->new($self,
|
|
||||||
object => $self->{objects}[$obj_idx],
|
|
||||||
model_object => $self->{model}->objects->[$obj_idx],
|
|
||||||
obj_idx => $obj_idx,
|
|
||||||
);
|
|
||||||
$self->{ObjectLayersDialog}->Show();
|
|
||||||
|
|
||||||
EVT_CLOSE($self->{ObjectLayersDialog}, sub {
|
|
||||||
my ($dlg, $event) = @_;
|
|
||||||
$dlg->Destroy;
|
|
||||||
$self->{ObjectLayersDialog} = undef;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub object_settings_dialog {
|
sub object_settings_dialog {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($obj_idx) = @_;
|
my ($obj_idx, %params) = @_;
|
||||||
|
|
||||||
if (!defined $obj_idx) {
|
if (!defined $obj_idx) {
|
||||||
($obj_idx, undef) = $self->selected_object;
|
($obj_idx, undef) = $self->selected_object;
|
||||||
@ -2148,9 +2128,15 @@ sub object_settings_dialog {
|
|||||||
my $dlg = Slic3r::GUI::Plater::ObjectSettingsDialog->new($self,
|
my $dlg = Slic3r::GUI::Plater::ObjectSettingsDialog->new($self,
|
||||||
object => $self->{objects}[$obj_idx],
|
object => $self->{objects}[$obj_idx],
|
||||||
model_object => $model_object,
|
model_object => $model_object,
|
||||||
|
obj_idx => $obj_idx,
|
||||||
);
|
);
|
||||||
|
# store pointer to the adaptive layer tab to push preview updates
|
||||||
|
$self->{AdaptiveLayersDialog} = $dlg->{adaptive_layers};
|
||||||
|
# and jump directly to the tab if called by "promo-button"
|
||||||
|
$dlg->{tabpanel}->SetSelection(1) if $params{adaptive_layers};
|
||||||
$self->pause_background_process;
|
$self->pause_background_process;
|
||||||
$dlg->ShowModal;
|
$dlg->ShowModal;
|
||||||
|
$self->{AdaptiveLayersDialog} = undef;
|
||||||
|
|
||||||
# update thumbnail since parts may have changed
|
# update thumbnail since parts may have changed
|
||||||
if ($dlg->PartsChanged) {
|
if ($dlg->PartsChanged) {
|
||||||
|
@ -1,150 +0,0 @@
|
|||||||
package Slic3r::GUI::Plater::ObjectLayersDialog;
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
use utf8;
|
|
||||||
|
|
||||||
use Slic3r::Geometry qw(PI X Y Z scale unscale);
|
|
||||||
use Slic3r::Print::State ':steps';
|
|
||||||
use List::Util qw(min max sum first);
|
|
||||||
use Wx qw(wxTheApp :dialog :id :misc :sizer :slider :statictext wxTAB_TRAVERSAL);
|
|
||||||
use Wx::Event qw(EVT_CLOSE EVT_BUTTON EVT_SLIDER);
|
|
||||||
use base 'Wx::Dialog';
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
my $class = shift;
|
|
||||||
my ($parent, %params) = @_;
|
|
||||||
my $self = $class->SUPER::new($parent, -1, $params{object}->name, wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
|
||||||
$self->{model_object} = $params{model_object};
|
|
||||||
my $model_object = $self->{model_object} = $params{model_object};
|
|
||||||
my $obj_idx = $self->{obj_idx} = $params{obj_idx};
|
|
||||||
my $plater = $self->{plater} = $parent;
|
|
||||||
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
|
||||||
|
|
||||||
$self->{update_spline_control} = 0;
|
|
||||||
|
|
||||||
# Initialize 3D toolpaths preview
|
|
||||||
if ($Slic3r::GUI::have_OpenGL) {
|
|
||||||
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self, $plater->{print});
|
|
||||||
$self->{preview3D}->canvas->set_auto_bed_shape;
|
|
||||||
$self->{preview3D}->canvas->SetSize([500,500]);
|
|
||||||
$self->{preview3D}->canvas->SetMinSize($self->{preview3D}->canvas->GetSize);
|
|
||||||
$self->{preview3D}->load_print;
|
|
||||||
$self->{preview3D}->canvas->zoom_to_volumes;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->{splineControl} = Slic3r::GUI::Plater::SplineControl->new($self, Wx::Size->new(150, 200), $model_object);
|
|
||||||
|
|
||||||
my $optgroup;
|
|
||||||
$optgroup = $self->{optgroup} = Slic3r::GUI::OptionsGroup->new(
|
|
||||||
parent => $self,
|
|
||||||
title => 'Adaptive quality %',
|
|
||||||
on_change => sub {
|
|
||||||
my ($opt_id) = @_;
|
|
||||||
# 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->{adaptive_quality} != $optgroup->get_value($opt_id)) {
|
|
||||||
$self->{adaptive_quality} = $optgroup->get_value($opt_id);
|
|
||||||
$self->{model_object}->config->set('adaptive_slicing_quality', $optgroup->get_value($opt_id));
|
|
||||||
# trigger re-slicing
|
|
||||||
$self->_trigger_slicing;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
label_width => 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
|
||||||
opt_id => 'adaptive_slicing_quality',
|
|
||||||
type => 'slider',
|
|
||||||
label => '',
|
|
||||||
default => $object->config->get('adaptive_slicing_quality'),
|
|
||||||
min => 0,
|
|
||||||
max => 100,
|
|
||||||
full_width => 1,
|
|
||||||
));
|
|
||||||
$optgroup->get_field('adaptive_slicing_quality')->set_scale(1);
|
|
||||||
$self->{adaptive_quality} = $object->config->get('adaptive_slicing_quality');
|
|
||||||
# init quality slider
|
|
||||||
if(!$object->config->get('adaptive_slicing')) {
|
|
||||||
# disable slider
|
|
||||||
$optgroup->get_field('adaptive_slicing_quality')->disable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
|
||||||
$right_sizer->Add($self->{splineControl}, 1, wxEXPAND | wxALL, 0);
|
|
||||||
$right_sizer->Add($optgroup->sizer, 0, wxEXPAND | wxALL, 0);
|
|
||||||
|
|
||||||
|
|
||||||
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
|
|
||||||
$self->{sizer}->Add($self->{preview3D}, 3, wxEXPAND | wxTOP | wxBOTTOM, 0) if $self->{preview3D};
|
|
||||||
$self->{sizer}->Add($right_sizer, 1, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
|
||||||
|
|
||||||
$self->SetSizerAndFit($self->{sizer});
|
|
||||||
$self->SetSize([800, 600]);
|
|
||||||
$self->SetMinSize($self->GetSize);
|
|
||||||
|
|
||||||
# init spline control values
|
|
||||||
# determine min and max layer height from perimeter extruder capabilities.
|
|
||||||
my %extruders;
|
|
||||||
for my $region_id (0 .. ($object->region_count - 1)) {
|
|
||||||
foreach (qw(perimeter_extruder infill_extruder solid_infill_extruder)) {
|
|
||||||
my $extruder_id = $self->{plater}->{print}->get_region($region_id)->config->get($_)-1;
|
|
||||||
$extruders{$extruder_id} = $extruder_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
my $min_height = max(map {$self->{plater}->{print}->config->get_at('min_layer_height', $_)} (values %extruders));
|
|
||||||
my $max_height = min(map {$self->{plater}->{print}->config->get_at('max_layer_height', $_)} (values %extruders));
|
|
||||||
|
|
||||||
$self->{splineControl}->set_size_parameters($min_height, $max_height, unscale($object->size->z));
|
|
||||||
|
|
||||||
|
|
||||||
$self->{splineControl}->on_layer_update(sub {
|
|
||||||
# trigger re-slicing
|
|
||||||
$self->_trigger_slicing;
|
|
||||||
});
|
|
||||||
|
|
||||||
$self->{splineControl}->on_z_indicator(sub {
|
|
||||||
my ($z) = @_;
|
|
||||||
$self->{preview3D}->canvas->SetCuttingPlane(Z, $z, []);
|
|
||||||
$self->{preview3D}->canvas->Render;
|
|
||||||
});
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _trigger_slicing {
|
|
||||||
my ($self) = @_;
|
|
||||||
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
|
||||||
$self->{plater}->pause_background_process;
|
|
||||||
$self->{plater}->stop_background_process;
|
|
||||||
if (!$Slic3r::GUI::Settings->{_}{background_processing}) {
|
|
||||||
$self->{plater}->statusbar->SetCancelCallback(sub {
|
|
||||||
$self->{plater}->stop_background_process;
|
|
||||||
$self->{plater}->statusbar->SetStatusText("Slicing cancelled");
|
|
||||||
$self->{plater}->preview_notebook->SetSelection(0);
|
|
||||||
});
|
|
||||||
$self->{plater}->{print}->reload_object($self->{obj_idx});
|
|
||||||
$self->{plater}->on_model_change;
|
|
||||||
$self->{plater}->start_background_process;
|
|
||||||
}else{
|
|
||||||
$self->{plater}->{print}->reload_object($self->{obj_idx});
|
|
||||||
$self->{plater}->on_model_change;
|
|
||||||
$self->{plater}->schedule_background_process;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub reload_preview {
|
|
||||||
my ($self) = @_;
|
|
||||||
$self->{splineControl}->update;
|
|
||||||
$self->{preview3D}->reload_print;
|
|
||||||
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
|
||||||
if($object->layer_count-1 > 0) {
|
|
||||||
# causes segfault...
|
|
||||||
my $top_layer = $object->get_layer($object->layer_count-1);
|
|
||||||
$self->{preview3D}->set_z($top_layer->print_z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -14,11 +14,16 @@ use base 'Wx::Dialog';
|
|||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my ($parent, %params) = @_;
|
my ($parent, %params) = @_;
|
||||||
my $self = $class->SUPER::new($parent, -1, "Settings for " . $params{object}->name, wxDefaultPosition, [700,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
my $self = $class->SUPER::new($parent, -1, "Settings for " . $params{object}->name, wxDefaultPosition, [1000,700], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||||
$self->{$_} = $params{$_} for keys %params;
|
$self->{$_} = $params{$_} for keys %params;
|
||||||
|
|
||||||
$self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
$self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
||||||
$self->{tabpanel}->AddPage($self->{parts} = Slic3r::GUI::Plater::ObjectPartsPanel->new($self->{tabpanel}, model_object => $params{model_object}), "Parts");
|
$self->{tabpanel}->AddPage($self->{parts} = Slic3r::GUI::Plater::ObjectPartsPanel->new($self->{tabpanel}, model_object => $params{model_object}), "Parts");
|
||||||
|
$self->{tabpanel}->AddPage($self->{adaptive_layers} = Slic3r::GUI::Plater::ObjectDialog::AdaptiveLayersTab->new( $self->{tabpanel},
|
||||||
|
plater => $parent,
|
||||||
|
model_object => $params{model_object},
|
||||||
|
obj_idx => $params{obj_idx}
|
||||||
|
), "Adaptive Layers");
|
||||||
$self->{tabpanel}->AddPage($self->{layers} = Slic3r::GUI::Plater::ObjectDialog::LayersTab->new($self->{tabpanel}), "Layers");
|
$self->{tabpanel}->AddPage($self->{layers} = Slic3r::GUI::Plater::ObjectDialog::LayersTab->new($self->{tabpanel}), "Layers");
|
||||||
|
|
||||||
my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
|
my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
|
||||||
@ -62,6 +67,157 @@ sub model_object {
|
|||||||
return $self->GetParent->GetParent->{model_object};
|
return $self->GetParent->GetParent->{model_object};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package Slic3r::GUI::Plater::ObjectDialog::AdaptiveLayersTab;
|
||||||
|
use Slic3r::Geometry qw(X Y Z scale unscale);
|
||||||
|
use List::Util qw(min max sum first);
|
||||||
|
use Wx qw(wxTheApp :dialog :id :misc :sizer :systemsettings :statictext wxTAB_TRAVERSAL);
|
||||||
|
use base 'Slic3r::GUI::Plater::ObjectDialog::BaseTab';
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my ($parent, %params) = @_;
|
||||||
|
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
|
||||||
|
my $model_object = $self->{model_object} = $params{model_object};
|
||||||
|
my $obj_idx = $self->{obj_idx} = $params{obj_idx};
|
||||||
|
my $plater = $self->{plater} = $params{plater};
|
||||||
|
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
||||||
|
|
||||||
|
# Initialize 3D toolpaths preview
|
||||||
|
if ($Slic3r::GUI::have_OpenGL) {
|
||||||
|
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self, $plater->{print});
|
||||||
|
$self->{preview3D}->canvas->set_auto_bed_shape;
|
||||||
|
$self->{preview3D}->canvas->SetSize([500,500]);
|
||||||
|
$self->{preview3D}->canvas->SetMinSize($self->{preview3D}->canvas->GetSize);
|
||||||
|
# object already processed?
|
||||||
|
wxTheApp->CallAfter(sub {
|
||||||
|
if (!$plater->{processed}) {
|
||||||
|
$self->_trigger_slicing;
|
||||||
|
}else{
|
||||||
|
$self->{preview3D}->load_print;
|
||||||
|
$self->{preview3D}->canvas->zoom_to_volumes;
|
||||||
|
$self->{preview_zoomed} = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{splineControl} = Slic3r::GUI::Plater::SplineControl->new($self, Wx::Size->new(150, 200), $model_object);
|
||||||
|
|
||||||
|
my $optgroup;
|
||||||
|
$optgroup = $self->{optgroup} = Slic3r::GUI::OptionsGroup->new(
|
||||||
|
parent => $self,
|
||||||
|
title => 'Adaptive quality %',
|
||||||
|
on_change => sub {
|
||||||
|
my ($opt_id) = @_;
|
||||||
|
# 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->{adaptive_quality} != $optgroup->get_value($opt_id)) {
|
||||||
|
$self->{adaptive_quality} = $optgroup->get_value($opt_id);
|
||||||
|
$self->{model_object}->config->set('adaptive_slicing_quality', $optgroup->get_value($opt_id));
|
||||||
|
# trigger re-slicing
|
||||||
|
$self->_trigger_slicing;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label_width => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||||
|
opt_id => 'adaptive_slicing_quality',
|
||||||
|
type => 'slider',
|
||||||
|
label => '',
|
||||||
|
default => $object->config->get('adaptive_slicing_quality'),
|
||||||
|
min => 0,
|
||||||
|
max => 100,
|
||||||
|
full_width => 1,
|
||||||
|
));
|
||||||
|
$optgroup->get_field('adaptive_slicing_quality')->set_scale(1);
|
||||||
|
$self->{adaptive_quality} = $object->config->get('adaptive_slicing_quality');
|
||||||
|
# init quality slider
|
||||||
|
if(!$object->config->get('adaptive_slicing')) {
|
||||||
|
# disable slider
|
||||||
|
$optgroup->get_field('adaptive_slicing_quality')->disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
|
$right_sizer->Add($self->{splineControl}, 1, wxEXPAND | wxALL, 0);
|
||||||
|
$right_sizer->Add($optgroup->sizer, 0, wxEXPAND | wxALL, 0);
|
||||||
|
|
||||||
|
|
||||||
|
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
$self->{sizer}->Add($self->{preview3D}, 3, wxEXPAND | wxTOP | wxBOTTOM, 0) if $self->{preview3D};
|
||||||
|
$self->{sizer}->Add($right_sizer, 1, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
||||||
|
|
||||||
|
$self->SetSizerAndFit($self->{sizer});
|
||||||
|
|
||||||
|
# init spline control values
|
||||||
|
# determine min and max layer height from perimeter extruder capabilities.
|
||||||
|
my %extruders;
|
||||||
|
for my $region_id (0 .. ($object->region_count - 1)) {
|
||||||
|
foreach (qw(perimeter_extruder infill_extruder solid_infill_extruder)) {
|
||||||
|
my $extruder_id = $self->{plater}->{print}->get_region($region_id)->config->get($_)-1;
|
||||||
|
$extruders{$extruder_id} = $extruder_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my $min_height = max(map {$self->{plater}->{print}->config->get_at('min_layer_height', $_)} (values %extruders));
|
||||||
|
my $max_height = min(map {$self->{plater}->{print}->config->get_at('max_layer_height', $_)} (values %extruders));
|
||||||
|
|
||||||
|
$self->{splineControl}->set_size_parameters($min_height, $max_height, unscale($object->size->z));
|
||||||
|
|
||||||
|
$self->{splineControl}->on_layer_update(sub {
|
||||||
|
# trigger re-slicing
|
||||||
|
$self->_trigger_slicing;
|
||||||
|
});
|
||||||
|
|
||||||
|
$self->{splineControl}->on_z_indicator(sub {
|
||||||
|
my ($z) = @_;
|
||||||
|
$self->{preview3D}->canvas->SetCuttingPlane(Z, $z, []);
|
||||||
|
$self->{preview3D}->canvas->Render;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
# This is called by the plater after processing to update the preview and spline
|
||||||
|
sub reload_preview {
|
||||||
|
my ($self) = @_;
|
||||||
|
$self->{splineControl}->update;
|
||||||
|
$self->{preview3D}->reload_print;
|
||||||
|
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
||||||
|
if($object->layer_count-1 > 0) {
|
||||||
|
my $top_layer = $object->get_layer($object->layer_count-1);
|
||||||
|
$self->{preview3D}->set_z($top_layer->print_z);
|
||||||
|
if(!$self->{preview_zoomed}) {
|
||||||
|
$self->{preview3D}->canvas->set_auto_bed_shape;
|
||||||
|
$self->{preview3D}->canvas->zoom_to_volumes;
|
||||||
|
$self->{preview_zoomed} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trigger background slicing at the plater
|
||||||
|
sub _trigger_slicing {
|
||||||
|
my ($self) = @_;
|
||||||
|
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
||||||
|
$self->{plater}->pause_background_process;
|
||||||
|
$self->{plater}->stop_background_process;
|
||||||
|
if (!$Slic3r::GUI::Settings->{_}{background_processing}) {
|
||||||
|
$self->{plater}->statusbar->SetCancelCallback(sub {
|
||||||
|
$self->{plater}->stop_background_process;
|
||||||
|
$self->{plater}->statusbar->SetStatusText("Slicing cancelled");
|
||||||
|
$self->{plater}->preview_notebook->SetSelection(0);
|
||||||
|
});
|
||||||
|
$self->{plater}->{print}->reload_object($self->{obj_idx});
|
||||||
|
$self->{plater}->on_model_change;
|
||||||
|
$self->{plater}->start_background_process;
|
||||||
|
}else{
|
||||||
|
$self->{plater}->{print}->reload_object($self->{obj_idx});
|
||||||
|
$self->{plater}->on_model_change;
|
||||||
|
$self->{plater}->schedule_background_process;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
package Slic3r::GUI::Plater::ObjectDialog::LayersTab;
|
package Slic3r::GUI::Plater::ObjectDialog::LayersTab;
|
||||||
use Wx qw(:dialog :id :misc :sizer :systemsettings);
|
use Wx qw(:dialog :id :misc :sizer :systemsettings);
|
||||||
use Wx::Grid;
|
use Wx::Grid;
|
||||||
|
@ -16,6 +16,7 @@ sub new {
|
|||||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, $size, wxTAB_TRAVERSAL);
|
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, $size, wxTAB_TRAVERSAL);
|
||||||
|
|
||||||
$self->{object} = $object;
|
$self->{object} = $object;
|
||||||
|
$self->{is_valid} = 0;
|
||||||
|
|
||||||
# This has only effect on MacOS. On Windows and Linux/GTK, the background is painted by $self->repaint().
|
# This has only effect on MacOS. On Windows and Linux/GTK, the background is painted by $self->repaint().
|
||||||
$self->SetBackgroundColour(Wx::wxWHITE);
|
$self->SetBackgroundColour(Wx::wxWHITE);
|
||||||
@ -74,31 +75,33 @@ sub repaint {
|
|||||||
$dc->DrawLabel(sprintf('%.4g', $self->{min_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_LEFT | wxALIGN_BOTTOM);
|
$dc->DrawLabel(sprintf('%.4g', $self->{min_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_LEFT | wxALIGN_BOTTOM);
|
||||||
$dc->DrawLabel(sprintf('%.4g', $self->{max_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_RIGHT | wxALIGN_BOTTOM);
|
$dc->DrawLabel(sprintf('%.4g', $self->{max_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_RIGHT | wxALIGN_BOTTOM);
|
||||||
|
|
||||||
|
if($self->{is_valid}) {
|
||||||
|
|
||||||
# draw original spline as reference
|
# draw original spline as reference
|
||||||
if($self->{original_height_spline}) {
|
if($self->{original_height_spline}) {
|
||||||
#draw spline
|
#draw spline
|
||||||
$self->_draw_layer_height_spline($dc, $self->{original_height_spline}, $self->{original_pen});
|
$self->_draw_layer_height_spline($dc, $self->{original_height_spline}, $self->{original_pen});
|
||||||
}
|
}
|
||||||
|
|
||||||
# draw interactive (currently modified by the user) layers as lines and spline
|
# draw interactive (currently modified by the user) layers as lines and spline
|
||||||
if($self->{interactive_height_spline}) {
|
if($self->{interactive_height_spline}) {
|
||||||
# draw layer lines
|
# draw layer lines
|
||||||
my @interpolated_layers = @{$self->{interactive_height_spline}->getInterpolatedLayers};
|
my @interpolated_layers = @{$self->{interactive_height_spline}->getInterpolatedLayers};
|
||||||
$self->_draw_layers_as_lines($dc, $self->{interactive_pen}, \@interpolated_layers);
|
$self->_draw_layers_as_lines($dc, $self->{interactive_pen}, \@interpolated_layers);
|
||||||
|
|
||||||
#draw spline
|
#draw spline
|
||||||
$self->_draw_layer_height_spline($dc, $self->{interactive_height_spline}, $self->{interactive_pen});
|
$self->_draw_layer_height_spline($dc, $self->{interactive_height_spline}, $self->{interactive_pen});
|
||||||
|
}
|
||||||
|
|
||||||
|
# draw resulting layers as lines
|
||||||
|
unless($self->{interactive_heights}) {
|
||||||
|
$self->_draw_layers_as_lines($dc, $self->{resulting_pen}, $self->{interpolated_layers});
|
||||||
|
}
|
||||||
|
|
||||||
|
# Always draw current BSpline, gives a reference during a modification
|
||||||
|
$self->_draw_layer_height_spline($dc, $self->{object}->layer_height_spline, $self->{line_pen});
|
||||||
}
|
}
|
||||||
|
|
||||||
# draw resulting layers as lines
|
|
||||||
unless($self->{interactive_heights}) {
|
|
||||||
$self->_draw_layers_as_lines($dc, $self->{resulting_pen}, $self->{interpolated_layers});
|
|
||||||
}
|
|
||||||
|
|
||||||
# Always draw current BSpline, gives a reference during a modification
|
|
||||||
$self->_draw_layer_height_spline($dc, $self->{object}->layer_height_spline, $self->{line_pen});
|
|
||||||
|
|
||||||
$event->Skip;
|
$event->Skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +123,7 @@ sub set_size_parameters {
|
|||||||
sub update {
|
sub update {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
if($self->{object}->layer_height_spline->layersUpdated || !$self->{heights}) {
|
if(($self->{object}->layer_height_spline->layersUpdated || !$self->{heights}) && $self->{object}->layer_height_spline->hasData) {
|
||||||
$self->{original_height_spline} = $self->{object}->layer_height_spline->clone; # make a copy to display the unmodified original spline
|
$self->{original_height_spline} = $self->{object}->layer_height_spline->clone; # make a copy to display the unmodified original spline
|
||||||
$self->{original_layers} = $self->{object}->layer_height_spline->getOriginalLayers;
|
$self->{original_layers} = $self->{object}->layer_height_spline->getOriginalLayers;
|
||||||
$self->{interpolated_layers} = $self->{object}->layer_height_spline->getInterpolatedLayers; # Initialize to current values
|
$self->{interpolated_layers} = $self->{object}->layer_height_spline->getInterpolatedLayers; # Initialize to current values
|
||||||
@ -131,6 +134,7 @@ sub update {
|
|||||||
foreach my $z (@{$self->{original_layers}}) {
|
foreach my $z (@{$self->{original_layers}}) {
|
||||||
push (@{$self->{heights}}, $self->{object}->layer_height_spline->getLayerHeightAt($z));
|
push (@{$self->{heights}}, $self->{object}->layer_height_spline->getLayerHeightAt($z));
|
||||||
}
|
}
|
||||||
|
$self->{is_valid} = 1;
|
||||||
}
|
}
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user