mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-11-01 05:01:10 -06:00
Looks like the reworked C++ preferences start to work again.
This commit is contained in:
parent
95c284c764
commit
e8b6d92d4d
26 changed files with 469 additions and 512 deletions
|
|
@ -12,14 +12,14 @@ use List::Util qw(first max);
|
|||
# The C++ counterpart is a constant singleton.
|
||||
our $Options = print_config_def();
|
||||
|
||||
# overwrite the hard-coded readonly value (this information is not available in XS)
|
||||
$Options->{threads}{readonly} = !$Slic3r::have_threads;
|
||||
|
||||
# generate accessors
|
||||
# Generate accessors.
|
||||
{
|
||||
no strict 'refs';
|
||||
for my $opt_key (keys %$Options) {
|
||||
*{$opt_key} = sub { $_[0]->get($opt_key) };
|
||||
*{$opt_key} = sub {
|
||||
#print "Slic3r::Config::accessor $opt_key\n";
|
||||
$_[0]->get($opt_key)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,61 +64,6 @@ sub new_from_cli {
|
|||
return $self;
|
||||
}
|
||||
|
||||
# CLASS METHODS:
|
||||
|
||||
# Write a "Windows" style ini file with categories enclosed in squre brackets.
|
||||
# Used by config-bundle-to-config.pl and to save slic3r.ini.
|
||||
sub write_ini {
|
||||
my $class = shift;
|
||||
my ($file, $ini) = @_;
|
||||
|
||||
Slic3r::open(\my $fh, '>', $file);
|
||||
binmode $fh, ':utf8';
|
||||
my $localtime = localtime;
|
||||
printf $fh "# generated by Slic3r $Slic3r::VERSION on %s\n", "$localtime";
|
||||
# make sure the _ category is the first one written
|
||||
foreach my $category (sort { ($a eq '_') ? -1 : ($a cmp $b) } keys %$ini) {
|
||||
printf $fh "\n[%s]\n", $category if $category ne '_';
|
||||
foreach my $key (sort keys %{$ini->{$category}}) {
|
||||
printf $fh "%s = %s\n", $key, $ini->{$category}{$key};
|
||||
}
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Parse a "Windows" style ini file with categories enclosed in squre brackets.
|
||||
# Returns a hash of hashes over strings.
|
||||
# {category}{name}=value
|
||||
# Non-categorized entries are stored under a category '_'.
|
||||
# Used by config-bundle-to-config.pl and to read slic3r.ini.
|
||||
sub read_ini {
|
||||
my $class = shift;
|
||||
my ($file) = @_;
|
||||
|
||||
local $/ = "\n";
|
||||
Slic3r::open(\my $fh, '<', $file)
|
||||
or die "Unable to open $file: $!\n";
|
||||
binmode $fh, ':utf8';
|
||||
|
||||
my $ini = { _ => {} };
|
||||
my $category = '_';
|
||||
while (<$fh>) {
|
||||
s/\R+$//;
|
||||
next if /^\s+/;
|
||||
next if /^$/;
|
||||
next if /^\s*#/;
|
||||
if (/^\[(.+?)\]$/) {
|
||||
$category = $1;
|
||||
next;
|
||||
}
|
||||
/^(\w+) *= *(.*)/ or die "Unreadable configuration file (invalid data at line $.)\n";
|
||||
$ini->{$category}{$1} = $2;
|
||||
}
|
||||
close $fh;
|
||||
|
||||
return $ini;
|
||||
}
|
||||
|
||||
package Slic3r::Config::Static;
|
||||
use parent 'Slic3r::Config';
|
||||
|
||||
|
|
|
|||
|
|
@ -53,25 +53,9 @@ use constant FILE_WILDCARDS => {
|
|||
use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(known stl obj amf prusa)};
|
||||
|
||||
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
|
||||
our $no_controller;
|
||||
our $no_plater;
|
||||
our $autosave;
|
||||
our @cb;
|
||||
|
||||
our $Settings = {
|
||||
_ => {
|
||||
version_check => 1,
|
||||
autocenter => 1,
|
||||
# Disable background processing by default as it is not stable.
|
||||
background_processing => 0,
|
||||
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
|
||||
# By default, Prusa has the controller hidden.
|
||||
no_controller => 1,
|
||||
# If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available.
|
||||
no_defaults => 1,
|
||||
},
|
||||
};
|
||||
|
||||
our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
$small_font->SetPointSize(11) if &Wx::wxMAC;
|
||||
our $small_bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
|
|
@ -89,91 +73,47 @@ sub OnInit {
|
|||
Slic3r::debugf "wxWidgets version %s, Wx version %s\n", &Wx::wxVERSION_STRING, $Wx::VERSION;
|
||||
|
||||
$self->{notifier} = Slic3r::GUI::Notifier->new;
|
||||
$self->{app_config} = Slic3r::GUI::AppConfig->new;
|
||||
$self->{preset_bundle} = Slic3r::GUI::PresetBundle->new;
|
||||
|
||||
# just checking for existence of Slic3r::data_dir is not enough: it may be an empty directory
|
||||
# supplied as argument to --datadir; in that case we should still run the wizard
|
||||
my $enc_datadir = Slic3r::encode_path(Slic3r::data_dir);
|
||||
Slic3r::debugf "Data directory: %s\n", $enc_datadir;
|
||||
my $run_wizard = (-d $enc_datadir && -e "$enc_datadir/slic3r.ini") ? 0 : 1;
|
||||
foreach my $dir ($enc_datadir, "$enc_datadir/print", "$enc_datadir/filament", "$enc_datadir/printer") {
|
||||
next if -d $dir;
|
||||
if (!mkdir $dir) {
|
||||
my $error = "Slic3r was unable to create its data directory at $dir ($!).";
|
||||
warn "$error\n";
|
||||
fatal_error(undef, $error);
|
||||
}
|
||||
eval { $self->{preset_bundle}->setup_directories() };
|
||||
if ($@) {
|
||||
warn $@ . "\n";
|
||||
fatal_error(undef, $@);
|
||||
}
|
||||
|
||||
my $run_wizard = ! $self->{app_config}->exists;
|
||||
# load settings
|
||||
my $last_version;
|
||||
if (-f "$enc_datadir/slic3r.ini") {
|
||||
my $ini = eval { Slic3r::Config->read_ini(Slic3r::data_dir . "/slic3r.ini") };
|
||||
$Settings = $ini if $ini;
|
||||
$last_version = $Settings->{_}{version};
|
||||
$Settings->{_}{autocenter} //= 1;
|
||||
$Settings->{_}{background_processing} //= 1;
|
||||
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
|
||||
$Settings->{_}{no_controller} //= 1;
|
||||
# If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available.
|
||||
$Settings->{_}{no_defaults} //= 1;
|
||||
}
|
||||
$Settings->{_}{version} = $Slic3r::VERSION;
|
||||
$self->save_settings;
|
||||
$self->{app_config}->load if ! $run_wizard;
|
||||
$self->{app_config}->set('version', $Slic3r::VERSION);
|
||||
$self->{app_config}->save;
|
||||
|
||||
# Suppress the '- default -' presets.
|
||||
$self->{preset_bundle}->set_default_suppressed($Slic3r::GUI::Settings->{_}{no_defaults} ? 1 : 0);
|
||||
eval { $self->{preset_bundle}->load_presets(Slic3r::data_dir) };
|
||||
$self->{preset_bundle}->set_default_suppressed($self->{app_config}->get('no_defaults') ? 1 : 0);
|
||||
eval {
|
||||
$self->{preset_bundle}->load_presets(Slic3r::data_dir);
|
||||
$self->{preset_bundle}->load_selections($self->{app_config});
|
||||
$run_wizard = 1 if $self->{preset_bundle}->has_defauls_only;
|
||||
};
|
||||
|
||||
# application frame
|
||||
Wx::Image::AddHandler(Wx::PNGHandler->new);
|
||||
$self->{mainframe} = my $frame = Slic3r::GUI::MainFrame->new(
|
||||
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
|
||||
no_controller => $no_controller // $Settings->{_}{no_controller},
|
||||
no_controller => $self->{app_config}->get('no_controller'),
|
||||
no_plater => $no_plater,
|
||||
);
|
||||
$self->SetTopWindow($frame);
|
||||
|
||||
# load init bundle
|
||||
#FIXME this is undocumented and the use case is unclear.
|
||||
# {
|
||||
# my @dirs = ($FindBin::Bin);
|
||||
# if (&Wx::wxMAC) {
|
||||
# push @dirs, qw();
|
||||
# } elsif (&Wx::wxMSW) {
|
||||
# push @dirs, qw();
|
||||
# }
|
||||
# my $init_bundle = first { -e $_ } map "$_/.init_bundle.ini", @dirs;
|
||||
# if ($init_bundle) {
|
||||
# Slic3r::debugf "Loading config bundle from %s\n", $init_bundle;
|
||||
# $self->{mainframe}->load_configbundle($init_bundle, 1);
|
||||
# $run_wizard = 0;
|
||||
# }
|
||||
# }
|
||||
|
||||
if (!$run_wizard && (!defined $last_version || $last_version ne $Slic3r::VERSION)) {
|
||||
# user was running another Slic3r version on this computer
|
||||
if (!defined $last_version || $last_version =~ /^0\./) {
|
||||
show_info($self->{mainframe}, "Hello! Support material was improved since the "
|
||||
. "last version of Slic3r you used. It is strongly recommended to revert "
|
||||
. "your support material settings to the factory defaults and start from "
|
||||
. "those. Enjoy and provide feedback!", "Support Material");
|
||||
}
|
||||
if (!defined $last_version || $last_version =~ /^(?:0|1\.[01])\./) {
|
||||
show_info($self->{mainframe}, "Hello! In this version a new Bed Shape option was "
|
||||
. "added. If the bed coordinates in the plater preview screen look wrong, go "
|
||||
. "to Print Settings and click the \"Set\" button next to \"Bed Shape\".", "Bed Shape");
|
||||
}
|
||||
}
|
||||
if ($run_wizard) {
|
||||
$self->{mainframe}->config_wizard;
|
||||
eval { $self->{preset_bundle}->load_presets(Slic3r::data_dir) };
|
||||
}
|
||||
|
||||
EVT_IDLE($frame, sub {
|
||||
while (my $cb = shift @cb) {
|
||||
$cb->();
|
||||
}
|
||||
$self->{app_config}->save if $self->{app_config}->dirty;
|
||||
});
|
||||
|
||||
return 1;
|
||||
|
|
@ -265,11 +205,6 @@ sub notify {
|
|||
$self->{notifier}->notify($message);
|
||||
}
|
||||
|
||||
sub save_settings {
|
||||
my ($self) = @_;
|
||||
Slic3r::Config->write_ini(Slic3r::data_dir . "/slic3r.ini", $Settings);
|
||||
}
|
||||
|
||||
# Called after the Preferences dialog is closed and the program settings are saved.
|
||||
# Update the UI based on the current preferences.
|
||||
sub update_ui_from_settings {
|
||||
|
|
@ -277,22 +212,11 @@ sub update_ui_from_settings {
|
|||
$self->{mainframe}->update_ui_from_settings;
|
||||
}
|
||||
|
||||
sub output_path {
|
||||
my ($self, $dir) = @_;
|
||||
|
||||
return ($Settings->{_}{last_output_path} && $Settings->{_}{remember_output_path})
|
||||
? $Settings->{_}{last_output_path}
|
||||
: $dir;
|
||||
}
|
||||
|
||||
sub open_model {
|
||||
my ($self, $window) = @_;
|
||||
|
||||
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory}
|
||||
|| $Slic3r::GUI::Settings->{recent}{config_directory}
|
||||
|| '';
|
||||
|
||||
my $dialog = Wx::FileDialog->new($window // $self->GetTopWindow, 'Choose one or more files (STL/OBJ/AMF/PRUSA):', $dir, "",
|
||||
my $dialog = Wx::FileDialog->new($window // $self->GetTopWindow, 'Choose one or more files (STL/OBJ/AMF/PRUSA):',
|
||||
$self->{app_config}->get_last_dir, "",
|
||||
MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||
if ($dialog->ShowModal != wxID_OK) {
|
||||
$dialog->Destroy;
|
||||
|
|
@ -308,31 +232,6 @@ sub CallAfter {
|
|||
push @cb, $cb;
|
||||
}
|
||||
|
||||
sub scan_serial_ports {
|
||||
my ($self) = @_;
|
||||
|
||||
my @ports = ();
|
||||
|
||||
if ($^O eq 'MSWin32') {
|
||||
# Windows
|
||||
if (eval "use Win32::TieRegistry; 1") {
|
||||
my $ts = Win32::TieRegistry->new("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM",
|
||||
{ Access => 'KEY_READ' });
|
||||
if ($ts) {
|
||||
# when no serial ports are available, the registry key doesn't exist and
|
||||
# TieRegistry->new returns undef
|
||||
$ts->Tie(\my %reg);
|
||||
push @ports, sort values %reg;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# UNIX and OS X
|
||||
push @ports, glob '/dev/{ttyUSB,ttyACM,tty.,cu.,rfcomm}*';
|
||||
}
|
||||
|
||||
return grep !/Bluetooth|FireFly/, @ports;
|
||||
}
|
||||
|
||||
sub append_menu_item {
|
||||
my ($self, $menu, $string, $description, $cb, $id, $icon, $kind) = @_;
|
||||
|
||||
|
|
@ -369,25 +268,24 @@ sub set_menu_item_icon {
|
|||
sub save_window_pos {
|
||||
my ($self, $window, $name) = @_;
|
||||
|
||||
$Settings->{_}{"${name}_pos"} = join ',', $window->GetScreenPositionXY;
|
||||
$Settings->{_}{"${name}_size"} = join ',', $window->GetSizeWH;
|
||||
$Settings->{_}{"${name}_maximized"} = $window->IsMaximized;
|
||||
$self->save_settings;
|
||||
$self->{app_config}->set("${name}_pos", join ',', $window->GetScreenPositionXY);
|
||||
$self->{app_config}->set("${name}_size", join ',', $window->GetSizeWH);
|
||||
$self->{app_config}->set("${name}_maximized", $window->IsMaximized);
|
||||
$self->{app_config}->save;
|
||||
}
|
||||
|
||||
sub restore_window_pos {
|
||||
my ($self, $window, $name) = @_;
|
||||
|
||||
if (defined $Settings->{_}{"${name}_pos"}) {
|
||||
my $size = [ split ',', $Settings->{_}{"${name}_size"}, 2 ];
|
||||
if ($self->{app_config}->has("${name}_pos")) {
|
||||
my $size = [ split ',', $self->{app_config}->get("${name}_size"), 2 ];
|
||||
$window->SetSize($size);
|
||||
|
||||
my $display = Wx::Display->new->GetClientArea();
|
||||
my $pos = [ split ',', $Settings->{_}{"${name}_pos"}, 2 ];
|
||||
my $pos = [ split ',', $self->{app_config}->get("${name}_pos"), 2 ];
|
||||
if (($pos->[0] + $size->[0]/2) < $display->GetRight && ($pos->[1] + $size->[1]/2) < $display->GetBottom) {
|
||||
$window->Move($pos);
|
||||
}
|
||||
$window->Maximize(1) if $Settings->{_}{"${name}_maximized"};
|
||||
$window->Maximize(1) if $self->{app_config}->get("${name}_maximized");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ sub OnActivate {
|
|||
}
|
||||
if (!%active) {
|
||||
# enable printers whose port is available
|
||||
my %ports = map { $_ => 1 } wxTheApp->scan_serial_ports;
|
||||
my %ports = map { $_ => 1 } Slic3r::GUI::scan_serial_ports;
|
||||
$active{$_} = 1
|
||||
for grep exists $ports{$presets{$_}->serial_port}, keys %presets;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ sub update_serial_ports {
|
|||
my $cb = $self->{serial_port_combobox};
|
||||
my $current = $cb->GetValue;
|
||||
$cb->Clear;
|
||||
$cb->Append($_) for wxTheApp->scan_serial_ports;
|
||||
$cb->Append($_) for Slic3r::GUI::scan_serial_ports;
|
||||
$cb->SetValue($current);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ sub new {
|
|||
}
|
||||
# save window size
|
||||
wxTheApp->save_window_pos($self, "main_frame");
|
||||
# Save the slic3r.ini. Usually the ini file is saved from "on idle" callback,
|
||||
# but in rare cases it may not have been called yet.
|
||||
wxTheApp->{app_config}->save;
|
||||
# propagate event
|
||||
$event->Skip;
|
||||
});
|
||||
|
|
@ -140,9 +143,11 @@ sub _init_tabpanel {
|
|||
my ($group, $name) = @_;
|
||||
$self->{options_tabs}{$group}->select_preset($name);
|
||||
});
|
||||
|
||||
# load initial config
|
||||
$self->{plater}->on_config_change(wxTheApp->{preset_bundle}->full_config);
|
||||
my $full_config = wxTheApp->{preset_bundle}->full_config;
|
||||
$self->{plater}->on_config_change($full_config);
|
||||
# Show a correct number of filament fields.
|
||||
$self->{plater}->on_extruders_change(int(@{$full_config->nozzle_diameter}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,14 +345,15 @@ sub quick_slice {
|
|||
my $progress_dialog;
|
||||
eval {
|
||||
# validate configuration
|
||||
my $config = $self->config;
|
||||
my $config = wxTheApp->{preset_bundle}->full_config();
|
||||
$config->validate;
|
||||
|
||||
# select input file
|
||||
my $input_file;
|
||||
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
|
||||
if (!$params{reslice}) {
|
||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):', $dir, "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):',
|
||||
wxTheApp->{app_config}->get_last_dir, "",
|
||||
&Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if ($dialog->ShowModal != wxID_OK) {
|
||||
$dialog->Destroy;
|
||||
return;
|
||||
|
|
@ -369,8 +375,7 @@ sub quick_slice {
|
|||
$input_file = $qs_last_input_file;
|
||||
}
|
||||
my $input_file_basename = basename($input_file);
|
||||
$Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_skein_dir(dirname($input_file));
|
||||
|
||||
my $print_center;
|
||||
{
|
||||
|
|
@ -392,11 +397,9 @@ sub quick_slice {
|
|||
$sprint->apply_config($config);
|
||||
$sprint->set_model($model);
|
||||
|
||||
{
|
||||
my $extra = $self->extra_variables;
|
||||
$sprint->placeholder_parser->set($_, $extra->{$_}) for keys %$extra;
|
||||
}
|
||||
|
||||
# Copy the names of active presets into the placeholder parser.
|
||||
wxTheApp->{preset_bundle}->export_selections_pp($sprint->placeholder_parser);
|
||||
|
||||
# select output file
|
||||
my $output_file;
|
||||
if ($params{reslice}) {
|
||||
|
|
@ -405,7 +408,7 @@ sub quick_slice {
|
|||
$output_file = $sprint->output_filepath;
|
||||
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/ if $params{export_svg};
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:',
|
||||
wxTheApp->output_path(dirname($output_file)),
|
||||
wxTheApp->{app_config}->get_last_output_dir(dirname($output_file)),
|
||||
basename($output_file), $params{export_svg} ? &Slic3r::GUI::FILE_WILDCARDS->{svg} : &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
|
|
@ -413,8 +416,7 @@ sub quick_slice {
|
|||
}
|
||||
$output_file = $dlg->GetPath;
|
||||
$qs_last_output_file = $output_file unless $params{export_svg};
|
||||
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($output_file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_last_output_dir(dirname($output_file));
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
|
|
@ -457,8 +459,9 @@ sub repair_stl {
|
|||
|
||||
my $input_file;
|
||||
{
|
||||
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
|
||||
my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:', $dir, "", &Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:',
|
||||
wxTheApp->{app_config}->get_last_dir, "",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if ($dialog->ShowModal != wxID_OK) {
|
||||
$dialog->Destroy;
|
||||
return;
|
||||
|
|
@ -487,15 +490,6 @@ sub repair_stl {
|
|||
Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair");
|
||||
}
|
||||
|
||||
# Extra variables for the placeholder parser generating a G-code.
|
||||
sub extra_variables {
|
||||
my $self = shift;
|
||||
my %extra_variables = ();
|
||||
$extra_variables{"${_}_preset"} = wxTheApp->{preset_bundle}->{$_}->get_current_preset_name
|
||||
for qw(print filament printer);
|
||||
return { %extra_variables };
|
||||
}
|
||||
|
||||
sub export_config {
|
||||
my $self = shift;
|
||||
# Generate a cummulative configuration for the selected print, filaments and printer.
|
||||
|
|
@ -504,15 +498,14 @@ sub export_config {
|
|||
eval { $config->validate; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
# Ask user for the file name for the config file.
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $filename = $last_config ? basename($last_config) : "config.ini";
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename,
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
$last_config ? basename($last_config) : "config.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef;
|
||||
$dlg->Destroy;
|
||||
if (defined $file) {
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
$last_config = $file;
|
||||
$config->save($file);
|
||||
}
|
||||
|
|
@ -523,9 +516,10 @@ sub load_config_file {
|
|||
my ($self, $file) = @_;
|
||||
if (!$file) {
|
||||
return unless $self->check_unsaved_changes;
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
||||
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
"config.ini",
|
||||
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
return unless $dlg->ShowModal == wxID_OK;
|
||||
$file = $dlg->GetPaths;
|
||||
$dlg->Destroy;
|
||||
|
|
@ -534,49 +528,51 @@ sub load_config_file {
|
|||
# Dont proceed further if the config file cannot be loaded.
|
||||
return if Slic3r::GUI::catch_error($self);
|
||||
$_->load_current_preset for (values %{$self->{options_tabs}});
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
$last_config = $file;
|
||||
}
|
||||
|
||||
sub export_configbundle {
|
||||
my $self = shift;
|
||||
my ($self) = @_;
|
||||
return unless $self->check_unsaved_changes;
|
||||
# validate current configuration in case it's dirty
|
||||
eval { $self->config->validate; };
|
||||
eval { wxTheApp->{preset_bundle}->full_config->validate; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
# Ask user for a file name.
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $filename = "Slic3r_config_bundle.ini";
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', $dir, $filename,
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
"Slic3r_config_bundle.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef;
|
||||
$dlg->Destroy;
|
||||
if (defined $file) {
|
||||
# Export the config bundle.
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
eval { $self->{presets}->export_configbundle($file); };
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
eval { wxTheApp->{preset_bundle}->export_configbundle($file); };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
}
|
||||
}
|
||||
|
||||
# Loading a config bundle with an external file name used to be used
|
||||
# to auto-install a config bundle on a fresh user account,
|
||||
# but that behavior was not documented and likely buggy.
|
||||
sub load_configbundle {
|
||||
my ($self, $file, $skip_no_id) = @_;
|
||||
|
||||
my ($self, $file) = @_;
|
||||
return unless $self->check_unsaved_changes;
|
||||
if (!$file) {
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
"config.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
return unless $dlg->ShowModal == wxID_OK;
|
||||
$file = $dlg->GetPaths;
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
|
||||
my $presets_imported = 0;
|
||||
eval { $presets_imported = $self->{presets}->load_configbundle($file); };
|
||||
eval { $presets_imported = wxTheApp->{preset_bundle}->load_configbundle($file); };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
# Load the currently selected preset into the GUI, update the preset selection box.
|
||||
|
|
@ -597,16 +593,18 @@ sub load_config {
|
|||
}
|
||||
|
||||
sub config_wizard {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
# Exit wizard if there are unsaved changes and the user cancels the action.
|
||||
return unless $self->check_unsaved_changes;
|
||||
if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) {
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
# Select the first visible preset.
|
||||
$tab->select_preset(undef);
|
||||
# Select the first visible preset, force.
|
||||
$tab->select_preset(undef, 1);
|
||||
}
|
||||
# Load the config over the previously selected defaults.
|
||||
$self->load_config($config);
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
# Save the settings under a new name, select the name.
|
||||
$tab->save_preset('My Settings');
|
||||
}
|
||||
}
|
||||
|
|
@ -666,7 +664,7 @@ sub _set_menu_item_icon {
|
|||
# Update the UI based on the current preferences.
|
||||
sub update_ui_from_settings {
|
||||
my ($self) = @_;
|
||||
$self->{menu_item_reslice_now}->Enable(! $Slic3r::GUI::Settings->{_}{background_processing});
|
||||
$self->{menu_item_reslice_now}->Enable(! wxTheApp->{app_config}->get("background_processing"));
|
||||
$self->{plater}->update_ui_from_settings if ($self->{plater});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,6 +124,10 @@ sub BUILD {
|
|||
});
|
||||
}
|
||||
|
||||
sub get_value {
|
||||
my ($self) = @_;
|
||||
return $self->wxWindow->GetValue ? 1 : 0;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::OptionsGroup::Field::SpinCtrl;
|
||||
use Moo;
|
||||
|
|
|
|||
|
|
@ -63,12 +63,7 @@ sub new {
|
|||
|
||||
$self->{print}->set_status_cb(sub {
|
||||
my ($percent, $message) = @_;
|
||||
|
||||
if ($Slic3r::have_threads) {
|
||||
Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([$percent, $message])));
|
||||
} else {
|
||||
$self->on_progress_event($percent, $message);
|
||||
}
|
||||
Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([$percent, $message])));
|
||||
});
|
||||
|
||||
# Initialize preview notebook
|
||||
|
|
@ -119,7 +114,7 @@ sub new {
|
|||
$self->GetFrame->{options_tabs}{print}->load_config($cfg);
|
||||
});
|
||||
$self->{canvas3D}->set_on_model_update(sub {
|
||||
if ($Slic3r::GUI::Settings->{_}{background_processing}) {
|
||||
if (wxTheApp->{app_config}->get("background_processing")) {
|
||||
$self->schedule_background_process;
|
||||
} else {
|
||||
# Hide the print info box, it is no more valid.
|
||||
|
|
@ -330,7 +325,7 @@ sub new {
|
|||
$self->on_process_completed($event->GetData);
|
||||
});
|
||||
|
||||
if ($Slic3r::have_threads) {
|
||||
{
|
||||
my $timer_id = Wx::NewId();
|
||||
$self->{apply_config_timer} = Wx::Timer->new($self, $timer_id);
|
||||
EVT_TIMER($self, $timer_id, sub {
|
||||
|
|
@ -448,7 +443,6 @@ sub new {
|
|||
$self->{"print_info_$field"}->SetFont($Slic3r::GUI::small_font);
|
||||
$grid_sizer->Add($self->{"print_info_$field"}, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
|
|
@ -510,13 +504,14 @@ sub _on_select_preset {
|
|||
wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection);
|
||||
}
|
||||
if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) {
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{preset_bundle}->update_platter_filament_ui_colors($idx, $choice);
|
||||
} else {
|
||||
# call GetSelection() in scalar context as it's context-aware
|
||||
$self->{on_select_preset}->($group, $choice->GetStringSelection)
|
||||
if $self->{on_select_preset};
|
||||
}
|
||||
# Synchronize config.ini with the current selections.
|
||||
wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config});
|
||||
# get new config and generate on_config_change() event for updating plater and other things
|
||||
$self->on_config_change(wxTheApp->{preset_bundle}->full_config);
|
||||
}
|
||||
|
|
@ -548,8 +543,8 @@ sub GetFrame {
|
|||
sub update_ui_from_settings
|
||||
{
|
||||
my ($self) = @_;
|
||||
if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! $Slic3r::GUI::Settings->{_}{background_processing})) {
|
||||
$self->{buttons_sizer}->Show($self->{btn_reslice}, ! $Slic3r::GUI::Settings->{_}{background_processing});
|
||||
if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! wxTheApp->{app_config}->get("background_processing"))) {
|
||||
$self->{buttons_sizer}->Show($self->{btn_reslice}, ! wxTheApp->{app_config}->get("background_processing"));
|
||||
$self->{buttons_sizer}->Layout;
|
||||
}
|
||||
}
|
||||
|
|
@ -587,6 +582,8 @@ sub update_presets {
|
|||
$choice_idx += 1;
|
||||
}
|
||||
}
|
||||
# Synchronize config.ini with the current selections.
|
||||
wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config});
|
||||
}
|
||||
|
||||
sub add {
|
||||
|
|
@ -655,8 +652,7 @@ sub load_files {
|
|||
}
|
||||
|
||||
# Note the current directory for the file open dialog.
|
||||
$Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_files->[-1]);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_skein_dir(dirname($input_files->[-1]));
|
||||
|
||||
$process_dialog->Destroy;
|
||||
$self->statusbar->SetStatusText("Loaded " . join(',', @loaded_files));
|
||||
|
|
@ -704,7 +700,7 @@ sub load_model_objects {
|
|||
}
|
||||
|
||||
# if user turned autocentering off, automatic arranging would disappoint them
|
||||
if (!$Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
if (! wxTheApp->{app_config}->get("autocenter")) {
|
||||
$need_arrange = 0;
|
||||
}
|
||||
|
||||
|
|
@ -817,7 +813,7 @@ sub increase {
|
|||
|
||||
# only autoarrange if user has autocentering enabled
|
||||
$self->stop_background_process;
|
||||
if ($Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
if (wxTheApp->{app_config}->get("autocenter")) {
|
||||
$self->arrange;
|
||||
} else {
|
||||
$self->update;
|
||||
|
|
@ -1130,7 +1126,7 @@ sub async_apply_config {
|
|||
# Hide the slicing results if the current slicing status is no more valid.
|
||||
$self->{"print_info_box_show"}->(0) if $invalidated;
|
||||
|
||||
if ($Slic3r::GUI::Settings->{_}{background_processing}) {
|
||||
if (wxTheApp->{app_config}->get("background_processing")) {
|
||||
if ($invalidated) {
|
||||
# kill current thread if any
|
||||
$self->stop_background_process;
|
||||
|
|
@ -1152,7 +1148,6 @@ sub async_apply_config {
|
|||
sub start_background_process {
|
||||
my ($self) = @_;
|
||||
|
||||
return if !$Slic3r::have_threads;
|
||||
return if !@{$self->{objects}};
|
||||
return if $self->{process_thread};
|
||||
|
||||
|
|
@ -1171,11 +1166,8 @@ sub start_background_process {
|
|||
return;
|
||||
}
|
||||
|
||||
# apply extra variables
|
||||
{
|
||||
my $extra = $self->GetFrame->extra_variables;
|
||||
$self->{print}->placeholder_parser->set($_, $extra->{$_}) for keys %$extra;
|
||||
}
|
||||
# Copy the names of active presets into the placeholder parser.
|
||||
wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser);
|
||||
|
||||
# start thread
|
||||
@_ = ();
|
||||
|
|
@ -1246,7 +1238,7 @@ sub reslice {
|
|||
# explicitly cancel a previous thread and start a new one.
|
||||
my ($self) = @_;
|
||||
# Don't reslice if export of G-code or sending to OctoPrint is running.
|
||||
if ($Slic3r::have_threads && ! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) {
|
||||
if (! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) {
|
||||
# Stop the background processing threads, stop the async update timer.
|
||||
$self->stop_background_process;
|
||||
# Rather perform one additional unnecessary update of the print object instead of skipping a pending async update.
|
||||
|
|
@ -1289,52 +1281,41 @@ sub export_gcode {
|
|||
$self->{print}->apply_config($config);
|
||||
$self->{print}->validate;
|
||||
};
|
||||
if (!$Slic3r::have_threads) {
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
}
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
# select output file
|
||||
if ($output_file) {
|
||||
$self->{export_gcode_output_file} = $self->{print}->output_filepath($output_file);
|
||||
} else {
|
||||
my $default_output_file = $self->{print}->output_filepath($main::opt{output} // '');
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', wxTheApp->output_path(dirname($default_output_file)),
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:',
|
||||
wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)),
|
||||
basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
return;
|
||||
}
|
||||
my $path = $dlg->GetPath;
|
||||
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($path);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_last_output_dir(dirname($path));
|
||||
$self->{export_gcode_output_file} = $path;
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
$self->statusbar->StartBusy;
|
||||
|
||||
if ($Slic3r::have_threads) {
|
||||
$self->statusbar->SetCancelCallback(sub {
|
||||
$self->stop_background_process;
|
||||
$self->statusbar->SetStatusText("Export cancelled");
|
||||
$self->{export_gcode_output_file} = undef;
|
||||
$self->{send_gcode_file} = undef;
|
||||
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
});
|
||||
$self->statusbar->SetCancelCallback(sub {
|
||||
$self->stop_background_process;
|
||||
$self->statusbar->SetStatusText("Export cancelled");
|
||||
$self->{export_gcode_output_file} = undef;
|
||||
$self->{send_gcode_file} = undef;
|
||||
|
||||
# start background process, whose completion event handler
|
||||
# will detect $self->{export_gcode_output_file} and proceed with export
|
||||
$self->start_background_process;
|
||||
} else {
|
||||
eval {
|
||||
$self->{print}->process;
|
||||
$self->{print}->export_gcode(output_file => $self->{export_gcode_output_file});
|
||||
};
|
||||
my $result = !Slic3r::GUI::catch_error($self);
|
||||
$self->on_export_completed($result);
|
||||
}
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
});
|
||||
|
||||
# start background process, whose completion event handler
|
||||
# will detect $self->{export_gcode_output_file} and proceed with export
|
||||
$self->start_background_process;
|
||||
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
|
|
@ -1577,7 +1558,7 @@ sub reset_thumbnail {
|
|||
sub update {
|
||||
my ($self, $force_autocenter) = @_;
|
||||
|
||||
if ($Slic3r::GUI::Settings->{_}{autocenter} || $force_autocenter) {
|
||||
if (wxTheApp->{app_config}->get("autocenter") || $force_autocenter) {
|
||||
$self->{model}->center_instances_around_point($self->bed_centerf);
|
||||
}
|
||||
|
||||
|
|
@ -1604,9 +1585,7 @@ sub update {
|
|||
# and some reasonable default has to be selected for the additional extruders.
|
||||
sub on_extruders_change {
|
||||
my ($self, $num_extruders) = @_;
|
||||
|
||||
my $choices = $self->{preset_choosers}{filament};
|
||||
wxTheApp->{preset_bundle}->update_multi_material_filament_presets;
|
||||
|
||||
while (int(@$choices) < $num_extruders) {
|
||||
# copy strings from first choice
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use utf8;
|
|||
use List::Util qw(min max first);
|
||||
use Slic3r::Geometry qw(X Y scale unscale convex_hull);
|
||||
use Slic3r::Geometry::Clipper qw(offset JT_ROUND intersection_pl);
|
||||
use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL);
|
||||
use Wx qw(wxTheApp :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';
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ sub repaint {
|
|||
}
|
||||
|
||||
# draw print center
|
||||
if (@{$self->{objects}} && $Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
if (@{$self->{objects}} && wxTheApp->{app_config}->get("autocenter")) {
|
||||
my $center = $self->unscaled_point_to_pixel($self->{print_center});
|
||||
$dc->SetPen($self->{print_center_pen});
|
||||
$dc->DrawLine($center->[X], 0, $center->[X], $size[Y]);
|
||||
|
|
@ -197,7 +197,6 @@ sub repaint {
|
|||
|
||||
sub mouse_event {
|
||||
my ($self, $event) = @_;
|
||||
|
||||
my $pos = $event->GetPosition;
|
||||
my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]]
|
||||
if ($event->ButtonDown) {
|
||||
|
|
@ -257,7 +256,7 @@ sub mouse_event {
|
|||
}
|
||||
|
||||
sub update_bed_size {
|
||||
my $self = shift;
|
||||
my ($self) = @_;
|
||||
|
||||
# when the canvas is not rendered yet, its GetSize() method returns 0,0
|
||||
my $canvas_size = $self->GetSize;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ sub new {
|
|||
my $self = $class->SUPER::new($parent, -1, "Preferences", wxDefaultPosition, wxDefaultSize);
|
||||
$self->{values} = {};
|
||||
|
||||
my $app_config = wxTheApp->{app_config};
|
||||
my $optgroup;
|
||||
$optgroup = Slic3r::GUI::OptionsGroup->new(
|
||||
parent => $self,
|
||||
|
|
@ -25,7 +26,7 @@ sub new {
|
|||
# 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,
|
||||
# default => $app_config->get("version_check") // 1,
|
||||
# readonly => !wxTheApp->have_version_check,
|
||||
# ));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
|
|
@ -33,36 +34,35 @@ sub new {
|
|||
type => 'bool',
|
||||
label => 'Remember output directory',
|
||||
tooltip => 'If this is enabled, Slic3r will prompt the last output directory instead of the one containing the input files.',
|
||||
default => $Slic3r::GUI::Settings->{_}{remember_output_path},
|
||||
default => $app_config->get("remember_output_path"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'autocenter',
|
||||
type => 'bool',
|
||||
label => 'Auto-center parts',
|
||||
tooltip => 'If this is enabled, Slic3r will auto-center objects around the print bed center.',
|
||||
default => $Slic3r::GUI::Settings->{_}{autocenter},
|
||||
default => $app_config->get("autocenter"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'background_processing',
|
||||
type => 'bool',
|
||||
label => 'Background processing',
|
||||
tooltip => 'If this is enabled, Slic3r will pre-process objects as soon as they\'re loaded in order to save time when exporting G-code.',
|
||||
default => $Slic3r::GUI::Settings->{_}{background_processing},
|
||||
readonly => !$Slic3r::have_threads,
|
||||
default => $app_config->get("background_processing"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'no_controller',
|
||||
type => 'bool',
|
||||
label => 'Disable USB/serial connection',
|
||||
tooltip => 'Disable communication with the printer over a serial / USB cable. This simplifies the user interface in case the printer is never attached to the computer.',
|
||||
default => $Slic3r::GUI::Settings->{_}{no_controller},
|
||||
default => $app_config->get("no_controller"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'no_defaults',
|
||||
type => 'bool',
|
||||
label => 'Suppress "- default -" presets',
|
||||
tooltip => 'Suppress "- default -" presets in the Print / Filament / Printer selections once there are any other valid presets available.',
|
||||
default => $Slic3r::GUI::Settings->{_}{no_defaults},
|
||||
default => $app_config->get("no_defaults"),
|
||||
));
|
||||
|
||||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
|
|
@ -79,15 +79,15 @@ sub new {
|
|||
}
|
||||
|
||||
sub _accept {
|
||||
my $self = shift;
|
||||
my ($self) = @_;
|
||||
|
||||
if (defined($self->{values}{no_controller}) ||
|
||||
defined($self->{values}{no_defaults})) {
|
||||
Slic3r::GUI::warning_catcher($self)->("You need to restart Slic3r to make the changes effective.");
|
||||
}
|
||||
|
||||
$Slic3r::GUI::Settings->{_}{$_} = $self->{values}{$_} for keys %{$self->{values}};
|
||||
wxTheApp->save_settings;
|
||||
my $app_config = wxTheApp->{app_config};
|
||||
$app_config->set($_, $self->{values}{$_}) for keys %{$self->{values}};
|
||||
|
||||
$self->EndModal(wxID_OK);
|
||||
$self->Close; # needed on Linux
|
||||
|
|
|
|||
|
|
@ -125,15 +125,9 @@ sub save_preset {
|
|||
$self->{treectrl}->SetFocus;
|
||||
|
||||
if (!defined $name) {
|
||||
my $preset = $self->{presets}->get_edited_preset;
|
||||
my $preset = $self->{presets}->get_selected_preset;
|
||||
my $default_name = $preset->default ? 'Untitled' : $preset->name;
|
||||
$default_name =~ s/\.[iI][nN][iI]$//;
|
||||
|
||||
my @prsts = @{$self->{presets}};
|
||||
print "Num of presets: ". int(@prsts) . "\n";
|
||||
for my $pr (@prsts) {
|
||||
print "Name: " . $pr->name . " default " . $pr->default . "\n";
|
||||
}
|
||||
my $dlg = Slic3r::GUI::SavePresetWindow->new($self,
|
||||
title => lc($self->title),
|
||||
default => $default_name,
|
||||
|
|
@ -156,16 +150,16 @@ sub delete_preset {
|
|||
my ($self) = @_;
|
||||
my $current_preset = $self->{presets}->get_selected_preset;
|
||||
# Don't let the user delete the '- default -' configuration.
|
||||
my $msg = 'Are you sure you want to ' . ($current_preset->external ? 'remove' : 'delete') . ' the selected preset?';
|
||||
my $title = ($current_preset->external ? 'Remove' : 'Delete') . ' Preset';
|
||||
return if $current_preset->default ||
|
||||
wxID_YES != Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal;
|
||||
wxID_YES != Wx::MessageDialog->new($self, $msg, $title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal;
|
||||
# Delete the file and select some other reasonable preset.
|
||||
# The 'external' presets will only be removed from the preset list, their files will not be deleted.
|
||||
eval { $self->{presets}->delete_current_preset; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
# Delete the item from the UI component and activate another preset.
|
||||
$self->{presets}->update_tab_ui($self->{presets_choice});
|
||||
# Update the selection boxes at the patter.
|
||||
$self->_on_presets_changed;
|
||||
# Load the newly selected preset into the UI, update selection combo boxes with their dirty flags.
|
||||
$self->load_current_preset;
|
||||
}
|
||||
|
||||
# Register the on_value_change callback.
|
||||
|
|
@ -203,7 +197,6 @@ sub _update {}
|
|||
# to uddate number of "filament" selection boxes when the number of extruders change.
|
||||
sub _on_presets_changed {
|
||||
my ($self) = @_;
|
||||
print "Tab::_on_presets_changed\n";
|
||||
$self->{on_presets_changed}->($self->{presets}) if $self->{on_presets_changed};
|
||||
}
|
||||
|
||||
|
|
@ -237,38 +230,34 @@ sub may_discard_current_preset_if_dirty
|
|||
}
|
||||
|
||||
# Called by the UI combo box when the user switches profiles.
|
||||
# Select a preset by a name. If ! defined(name), then the first visible preset is selected.
|
||||
# Select a preset by a name. If ! defined(name), then the default preset is selected.
|
||||
# If the current profile is modified, user is asked to save the changes.
|
||||
sub select_preset {
|
||||
my ($self, $name, $force) = @_;
|
||||
print "select_preset 1\n";
|
||||
if (! $self->may_discard_current_preset_if_dirty) {
|
||||
$force //= 0;
|
||||
if (! $force && ! $self->may_discard_current_preset_if_dirty) {
|
||||
$self->{presets}->update_tab_ui($self->{presets_choice});
|
||||
# Trigger the on_presets_changed event so that we also restore the previous value in the plater selector.
|
||||
$self->_on_presets_changed;
|
||||
return;
|
||||
}
|
||||
print "select_preset 2\n";
|
||||
$self->{presets}->select_preset_by_name(defined $name ? $name : "");
|
||||
print "select_preset 3\n";
|
||||
if (defined $name) {
|
||||
$self->{presets}->select_preset_by_name($name);
|
||||
} else {
|
||||
$self->{presets}->select_preset(0);
|
||||
}
|
||||
# Initialize the UI from the current preset.
|
||||
$self->load_current_preset;
|
||||
print "select_preset 4\n";
|
||||
# Save the current application settings with the newly selected preset name.
|
||||
wxTheApp->save_settings;
|
||||
print "select_preset 5\n";
|
||||
}
|
||||
|
||||
# Initialize the UI from the current preset.
|
||||
sub load_current_preset {
|
||||
my ($self) = @_;
|
||||
print "load_current_preset 1\n";
|
||||
$self->{presets}->update_tab_ui($self->{presets_choice});
|
||||
print "load_current_preset 2\n";
|
||||
my $preset = $self->{presets}->get_current_preset;
|
||||
eval {
|
||||
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
|
||||
my $method = ($preset->default || $preset->external) ? 'Disable' : 'Enable';
|
||||
my $method = $preset->default ? 'Disable' : 'Enable';
|
||||
$self->{btn_delete_preset}->$method;
|
||||
$self->_update;
|
||||
# For the printer profile, generate the extruder pages.
|
||||
|
|
@ -281,8 +270,9 @@ sub load_current_preset {
|
|||
# preset dirty again
|
||||
# (not sure this is true anymore now that update_dirty is idempotent)
|
||||
wxTheApp->CallAfter(sub {
|
||||
$self->_on_presets_changed;
|
||||
$self->update_dirty;
|
||||
#the following is called by update_dirty
|
||||
#$self->_on_presets_changed;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +394,7 @@ sub build {
|
|||
my $self = shift;
|
||||
|
||||
$self->{presets} = wxTheApp->{preset_bundle}->print;
|
||||
$self->{config} = $self->{presets}->get_edited_preset->config_ref;
|
||||
$self->{config} = $self->{presets}->get_edited_preset->config;
|
||||
|
||||
{
|
||||
my $page = $self->add_options_page('Layers and perimeters', 'layers.png');
|
||||
|
|
@ -608,7 +598,7 @@ sub build {
|
|||
$optgroup->append_single_option_line('clip_multipart_objects');
|
||||
$optgroup->append_single_option_line('elefant_foot_compensation');
|
||||
$optgroup->append_single_option_line('xy_size_compensation');
|
||||
# $optgroup->append_single_option_line('threads') if $Slic3r::have_threads;
|
||||
# $optgroup->append_single_option_line('threads');
|
||||
$optgroup->append_single_option_line('resolution');
|
||||
}
|
||||
}
|
||||
|
|
@ -675,7 +665,7 @@ sub _update {
|
|||
my ($self) = @_;
|
||||
$self->Freeze;
|
||||
|
||||
my $config = $self->{presets}->get_edited_preset->config_ref;
|
||||
my $config = $self->{config};
|
||||
|
||||
if ($config->spiral_vase && !($config->perimeters == 1 && $config->top_solid_layers == 0 && $config->fill_density == 0)) {
|
||||
my $dialog = Wx::MessageDialog->new($self,
|
||||
|
|
@ -882,7 +872,7 @@ sub build {
|
|||
my $self = shift;
|
||||
|
||||
$self->{presets} = wxTheApp->{preset_bundle}->filament;
|
||||
$self->{config} = $self->{presets}->get_edited_preset->config_ref;
|
||||
$self->{config} = $self->{presets}->get_edited_preset->config;
|
||||
|
||||
{
|
||||
my $page = $self->add_options_page('Filament', 'spool.png');
|
||||
|
|
@ -1061,8 +1051,9 @@ sub build {
|
|||
my ($self, %params) = @_;
|
||||
|
||||
$self->{presets} = wxTheApp->{preset_bundle}->printer;
|
||||
$self->{config} = $self->{presets}->get_edited_preset->config_ref;
|
||||
|
||||
$self->{config} = $self->{presets}->get_edited_preset->config;
|
||||
$self->{extruders_count} = scalar @{$self->{config}->nozzle_diameter};
|
||||
|
||||
my $bed_shape_widget = sub {
|
||||
my ($parent) = @_;
|
||||
|
||||
|
|
@ -1086,9 +1077,7 @@ sub build {
|
|||
|
||||
return $sizer;
|
||||
};
|
||||
|
||||
$self->{extruders_count} = 1;
|
||||
|
||||
|
||||
{
|
||||
my $page = $self->add_options_page('General', 'printer_empty.png');
|
||||
{
|
||||
|
|
@ -1117,13 +1106,16 @@ sub build {
|
|||
$optgroup->append_single_option_line('single_extruder_multi_material');
|
||||
}
|
||||
$optgroup->on_change(sub {
|
||||
my ($opt_id) = @_;
|
||||
if ($opt_id eq 'extruders_count') {
|
||||
wxTheApp->CallAfter(sub {
|
||||
my ($opt_key, $value) = @_;
|
||||
wxTheApp->CallAfter(sub {
|
||||
if ($opt_key eq 'extruders_count') {
|
||||
$self->_extruders_count_changed($optgroup->get_value('extruders_count'));
|
||||
});
|
||||
$self->update_dirty;
|
||||
}
|
||||
$self->update_dirty;
|
||||
} else {
|
||||
$self->update_dirty;
|
||||
$self->_on_value_change($opt_key, $value);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (!$params{no_controller})
|
||||
|
|
@ -1326,43 +1318,23 @@ sub build {
|
|||
sub _update_serial_ports {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->get_field('serial_port')->set_values([ wxTheApp->scan_serial_ports ]);
|
||||
$self->get_field('serial_port')->set_values([ Slic3r::GUI::scan_serial_ports ]);
|
||||
}
|
||||
|
||||
sub _extruders_count_changed {
|
||||
my ($self, $extruders_count) = @_;
|
||||
|
||||
$self->{extruders_count} = $extruders_count;
|
||||
wxTheApp->{preset_bundle}->printer->get_edited_preset->set_num_extruders($extruders_count);
|
||||
wxTheApp->{preset_bundle}->update_multi_material_filament_presets;
|
||||
$self->_build_extruder_pages;
|
||||
$self->_on_value_change('extruders_count', $extruders_count);
|
||||
}
|
||||
|
||||
sub _extruder_options {
|
||||
qw(nozzle_diameter min_layer_height max_layer_height extruder_offset
|
||||
retract_length retract_lift retract_lift_above retract_lift_below retract_speed deretract_speed
|
||||
retract_before_wipe retract_restart_extra retract_before_travel wipe
|
||||
retract_layer_change retract_length_toolchange retract_restart_extra_toolchange extruder_colour) }
|
||||
|
||||
sub _build_extruder_pages {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
my $default_config = Slic3r::Config::Full->new;
|
||||
|
||||
|
||||
foreach my $extruder_idx (@{$self->{extruder_pages}} .. $self->{extruders_count}-1) {
|
||||
# extend options
|
||||
foreach my $opt_key ($self->_extruder_options) {
|
||||
my $values = $self->{config}->get($opt_key);
|
||||
if (!defined $values) {
|
||||
$values = [ $default_config->get_at($opt_key, 0) ];
|
||||
} else {
|
||||
# use last extruder's settings for the new one
|
||||
my $last_value = $values->[-1];
|
||||
$values->[$extruder_idx] //= $last_value;
|
||||
}
|
||||
$self->{config}->set($opt_key, $values)
|
||||
or die "Unable to extend $opt_key";
|
||||
}
|
||||
|
||||
# build page
|
||||
my $page = $self->{extruder_pages}[$extruder_idx] = $self->add_options_page("Extruder " . ($extruder_idx + 1), 'funnel.png');
|
||||
{
|
||||
|
|
@ -1412,14 +1384,6 @@ sub _build_extruder_pages {
|
|||
splice @{$self->{extruder_pages}}, $self->{extruders_count};
|
||||
}
|
||||
|
||||
# remove extra config values
|
||||
foreach my $opt_key ($self->_extruder_options) {
|
||||
my $values = $self->{config}->get($opt_key);
|
||||
splice @$values, $self->{extruders_count} if $self->{extruders_count} <= $#$values;
|
||||
$self->{config}->set($opt_key, $values)
|
||||
or die "Unable to truncate $opt_key";
|
||||
}
|
||||
|
||||
# rebuild page list
|
||||
my @pages_without_extruders = (grep $_->{title} !~ /^Extruder \d+/, @{$self->{pages}});
|
||||
my $page_notes = pop @pages_without_extruders;
|
||||
|
|
@ -1513,15 +1477,12 @@ sub _update {
|
|||
|
||||
# this gets executed after preset is loaded and before GUI fields are updated
|
||||
sub on_preset_loaded {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
# update the extruders count field
|
||||
{
|
||||
# update the GUI field according to the number of nozzle diameters supplied
|
||||
my $extruders_count = scalar @{ $self->{config}->nozzle_diameter };
|
||||
$self->set_value('extruders_count', $extruders_count);
|
||||
$self->_extruders_count_changed($extruders_count);
|
||||
}
|
||||
my $extruders_count = scalar @{ $self->{config}->nozzle_diameter };
|
||||
$self->set_value('extruders_count', $extruders_count);
|
||||
# update the GUI field according to the number of nozzle diameters supplied
|
||||
$self->_extruders_count_changed($extruders_count);
|
||||
}
|
||||
|
||||
# Single Tab page containing a {vsizer} of {optgroups}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue