mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-24 07:03:59 -06:00
Merge branch 'master' into wipe_tower_improvements
This commit is contained in:
commit
1c6fa6660e
79 changed files with 34645 additions and 10116 deletions
|
@ -1172,18 +1172,17 @@ sub Render {
|
|||
glLightfv_p(GL_LIGHT1, GL_POSITION, 1, 0, 1, 0);
|
||||
|
||||
if ($self->enable_picking) {
|
||||
# Render the object for picking.
|
||||
# FIXME This cannot possibly work in a multi-sampled context as the color gets mangled by the anti-aliasing.
|
||||
# Better to use software ray-casting on a bounding-box hierarchy.
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_MULTISAMPLE) if ($self->{can_multisample});
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
$self->draw_volumes(1);
|
||||
glFlush();
|
||||
glFinish();
|
||||
|
||||
if (my $pos = $self->_mouse_pos) {
|
||||
# Render the object for picking.
|
||||
# FIXME This cannot possibly work in a multi-sampled context as the color gets mangled by the anti-aliasing.
|
||||
# Better to use software ray-casting on a bounding-box hierarchy.
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_MULTISAMPLE) if ($self->{can_multisample});
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
$self->draw_volumes(1);
|
||||
glPopAttrib();
|
||||
glFlush();
|
||||
my $col = [ glReadPixels_p($pos->x, $self->GetSize->GetHeight - $pos->y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE) ];
|
||||
my $volume_idx = $col->[0] + $col->[1]*256 + $col->[2]*256*256;
|
||||
$self->_hover_volume_idx(undef);
|
||||
|
@ -1199,11 +1198,8 @@ sub Render {
|
|||
|
||||
$self->on_hover->($volume_idx) if $self->on_hover;
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glFlush();
|
||||
glFinish();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
# draw fixed background
|
||||
|
@ -1337,9 +1333,6 @@ sub Render {
|
|||
$self->draw_active_object_annotations;
|
||||
|
||||
$self->SwapBuffers();
|
||||
|
||||
# Calling glFinish has a performance penalty, but it seems to fix some OpenGL driver hang-up with extremely large scenes.
|
||||
# glFinish();
|
||||
}
|
||||
|
||||
sub draw_volumes {
|
||||
|
@ -2051,4 +2044,11 @@ sub reset_legend_texture {
|
|||
Slic3r::GUI::_3DScene::reset_legend_texture();
|
||||
}
|
||||
|
||||
sub get_current_print_zs {
|
||||
my ($self) = @_;
|
||||
|
||||
my $count = $self->volumes->get_current_print_zs();
|
||||
return $count;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -14,6 +14,8 @@ use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedi
|
|||
use Wx::Event qw(EVT_CLOSE EVT_COMMAND EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED);
|
||||
use base 'Wx::Frame';
|
||||
|
||||
use Wx::Locale gettext => 'L';
|
||||
|
||||
our $qs_last_input_file;
|
||||
our $qs_last_output_file;
|
||||
our $last_config;
|
||||
|
@ -48,7 +50,8 @@ sub new {
|
|||
$self->{no_plater} = $params{no_plater};
|
||||
$self->{loaded} = 0;
|
||||
$self->{lang_ch_event} = $params{lang_ch_event};
|
||||
|
||||
$self->{preferences_event} = $params{preferences_event};
|
||||
|
||||
# initialize tabpanel and menubar
|
||||
$self->_init_tabpanel;
|
||||
$self->_init_menubar;
|
||||
|
@ -60,7 +63,7 @@ sub new {
|
|||
|
||||
# initialize status bar
|
||||
$self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, -1);
|
||||
$self->{statusbar}->SetStatusText("Version $Slic3r::VERSION - Remember to check for updates at http://github.com/prusa3d/slic3r/releases");
|
||||
$self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"));
|
||||
$self->SetStatusBar($self->{statusbar});
|
||||
|
||||
$self->{loaded} = 1;
|
||||
|
@ -112,9 +115,9 @@ sub _init_tabpanel {
|
|||
});
|
||||
|
||||
if (!$self->{no_plater}) {
|
||||
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater");
|
||||
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), L("Plater"));
|
||||
if (!$self->{no_controller}) {
|
||||
$panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), "Controller");
|
||||
$panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +174,6 @@ sub _init_tabpanel {
|
|||
EVT_COMMAND($self, -1, $BUTTON_BROWSE_EVENT, sub {
|
||||
my ($self, $event) = @_;
|
||||
my $msg = $event->GetString;
|
||||
print "BUTTON_BROWSE_EVENT: ", $msg, "\n";
|
||||
|
||||
# look for devices
|
||||
my $entries;
|
||||
|
@ -186,7 +188,7 @@ sub _init_tabpanel {
|
|||
$tab->load_key_value('octoprint_host', $dlg->GetValue . ":" . $dlg->GetPort)
|
||||
if $dlg->ShowModal == wxID_OK;
|
||||
} else {
|
||||
Wx::MessageDialog->new($self, 'No Bonjour device found', 'Device Browser', wxOK | wxICON_INFORMATION)->ShowModal;
|
||||
Wx::MessageDialog->new($self, L('No Bonjour device found'), L('Device Browser'), wxOK | wxICON_INFORMATION)->ShowModal;
|
||||
}
|
||||
});
|
||||
# The following event is emited by the C++ Tab implementation ,
|
||||
|
@ -194,7 +196,6 @@ sub _init_tabpanel {
|
|||
EVT_COMMAND($self, -1, $BUTTON_TEST_EVENT, sub {
|
||||
my ($self, $event) = @_;
|
||||
my $msg = $event->GetString;
|
||||
print "BUTTON_TEST_EVENT: ", $msg, "\n";
|
||||
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->timeout(10);
|
||||
|
@ -205,19 +206,19 @@ sub _init_tabpanel {
|
|||
'X-Api-Key' => $config->octoprint_apikey,
|
||||
);
|
||||
if ($res->is_success) {
|
||||
Slic3r::GUI::show_info($self, "Connection to OctoPrint works correctly.", "Success!");
|
||||
Slic3r::GUI::show_info($self, L("Connection to OctoPrint works correctly."), _L("Success!"));
|
||||
} else {
|
||||
Slic3r::GUI::show_error($self,
|
||||
"I wasn't able to connect to OctoPrint (" . $res->status_line . "). "
|
||||
. "Check hostname and OctoPrint version (at least 1.1.0 is required).");
|
||||
L("I wasn't able to connect to OctoPrint (") . $res->status_line .
|
||||
L("). Check hostname and OctoPrint version (at least 1.1.0 is required)."));
|
||||
}
|
||||
});
|
||||
# A variable to inform C++ Tab implementation about disabling of Browse button
|
||||
$self->{is_disabled_button_browse} = (!eval "use Net::Bonjour; 1") ? 1 : 0 ;
|
||||
# A variable to inform C++ Tab implementation about user_agent
|
||||
$self->{is_user_agent} = (eval "use LWP::UserAgent; 1") ? 1 : 0 ;
|
||||
Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, wxTheApp->{app_config},
|
||||
$self->{no_controller}, $self->{is_disabled_button_browse},
|
||||
Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, $self->{no_controller},
|
||||
$self->{is_disabled_button_browse},
|
||||
$self->{is_user_agent},
|
||||
$VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT,
|
||||
$BUTTON_BROWSE_EVENT, $BUTTON_TEST_EVENT);
|
||||
|
@ -245,59 +246,60 @@ sub _init_menubar {
|
|||
# File menu
|
||||
my $fileMenu = Wx::Menu->new;
|
||||
{
|
||||
wxTheApp->append_menu_item($fileMenu, "Open STL/OBJ/AMF…\tCtrl+O", 'Open a model', sub {
|
||||
wxTheApp->append_menu_item($fileMenu, L("Open STL/OBJ/AMF…\tCtrl+O"), L('Open a model'), sub {
|
||||
$self->{plater}->add if $self->{plater};
|
||||
}, undef, undef); #'brick_add.png');
|
||||
$self->_append_menu_item($fileMenu, "&Load Config…\tCtrl+L", 'Load exported configuration file', sub {
|
||||
$self->_append_menu_item($fileMenu, L("&Load Config…\tCtrl+L"), L('Load exported configuration file'), sub {
|
||||
$self->load_config_file;
|
||||
}, undef, 'plugin_add.png');
|
||||
$self->_append_menu_item($fileMenu, "&Export Config…\tCtrl+E", 'Export current configuration to file', sub {
|
||||
$self->_append_menu_item($fileMenu, L("&Export Config…\tCtrl+E"), L('Export current configuration to file'), sub {
|
||||
$self->export_config;
|
||||
}, undef, 'plugin_go.png');
|
||||
$self->_append_menu_item($fileMenu, "&Load Config Bundle…", 'Load presets from a bundle', sub {
|
||||
$self->_append_menu_item($fileMenu, L("&Load Config Bundle…"), L('Load presets from a bundle'), sub {
|
||||
$self->load_configbundle;
|
||||
}, undef, 'lorry_add.png');
|
||||
$self->_append_menu_item($fileMenu, "&Export Config Bundle…", 'Export all presets to file', sub {
|
||||
$self->_append_menu_item($fileMenu, L("&Export Config Bundle…"), L('Export all presets to file'), sub {
|
||||
$self->export_configbundle;
|
||||
}, undef, 'lorry_go.png');
|
||||
$fileMenu->AppendSeparator();
|
||||
my $repeat;
|
||||
$self->_append_menu_item($fileMenu, "Q&uick Slice…\tCtrl+U", 'Slice a file into a G-code', sub {
|
||||
$self->_append_menu_item($fileMenu, L("Q&uick Slice…\tCtrl+U"), L('Slice a file into a G-code'), sub {
|
||||
wxTheApp->CallAfter(sub {
|
||||
$self->quick_slice;
|
||||
$repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
|
||||
});
|
||||
}, undef, 'cog_go.png');
|
||||
$self->_append_menu_item($fileMenu, "Quick Slice and Save &As…\tCtrl+Alt+U", 'Slice a file into a G-code, save as', sub {
|
||||
$self->_append_menu_item($fileMenu, L("Quick Slice and Save &As…\tCtrl+Alt+U"), L('Slice a file into a G-code, save as'), sub {
|
||||
wxTheApp->CallAfter(sub {
|
||||
$self->quick_slice(save_as => 1);
|
||||
$repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
|
||||
});
|
||||
}, undef, 'cog_go.png');
|
||||
$repeat = $self->_append_menu_item($fileMenu, "&Repeat Last Quick Slice\tCtrl+Shift+U", 'Repeat last quick slice', sub {
|
||||
$repeat = $self->_append_menu_item($fileMenu, L("&Repeat Last Quick Slice\tCtrl+Shift+U"), L('Repeat last quick slice'), sub {
|
||||
wxTheApp->CallAfter(sub {
|
||||
$self->quick_slice(reslice => 1);
|
||||
});
|
||||
}, undef, 'cog_go.png');
|
||||
$repeat->Enable(0);
|
||||
$fileMenu->AppendSeparator();
|
||||
$self->_append_menu_item($fileMenu, "Slice to SV&G…\tCtrl+G", 'Slice file to a multi-layer SVG', sub {
|
||||
$self->_append_menu_item($fileMenu, L("Slice to SV&G…\tCtrl+G"), L('Slice file to a multi-layer SVG'), sub {
|
||||
$self->quick_slice(save_as => 1, export_svg => 1);
|
||||
}, undef, 'shape_handles.png');
|
||||
$self->{menu_item_reslice_now} = $self->_append_menu_item(
|
||||
$fileMenu, "(&Re)Slice Now\tCtrl+S", 'Start new slicing process',
|
||||
$fileMenu, L("(&Re)Slice Now\tCtrl+S"), L('Start new slicing process'),
|
||||
sub { $self->reslice_now; }, undef, 'shape_handles.png');
|
||||
$fileMenu->AppendSeparator();
|
||||
$self->_append_menu_item($fileMenu, "Repair STL file…", 'Automatically repair an STL file', sub {
|
||||
$self->_append_menu_item($fileMenu, L("Repair STL file…"), L('Automatically repair an STL file'), sub {
|
||||
$self->repair_stl;
|
||||
}, undef, 'wrench.png');
|
||||
$fileMenu->AppendSeparator();
|
||||
# Cmd+, is standard on OS X - what about other operating systems?
|
||||
$self->_append_menu_item($fileMenu, "Preferences…\tCtrl+,", 'Application preferences', sub {
|
||||
Slic3r::GUI::Preferences->new($self)->ShowModal;
|
||||
$self->_append_menu_item($fileMenu, L("Preferences…\tCtrl+,"), L('Application preferences'), sub {
|
||||
# Opening the C++ preferences dialog.
|
||||
Slic3r::GUI::open_preferences_dialog($self->{preferences_event});
|
||||
}, wxID_PREFERENCES);
|
||||
$fileMenu->AppendSeparator();
|
||||
$self->_append_menu_item($fileMenu, "&Quit", 'Quit Slic3r', sub {
|
||||
$self->_append_menu_item($fileMenu, L("&Quit"), L('Quit Slic3r'), sub {
|
||||
$self->Close(0);
|
||||
}, wxID_EXIT);
|
||||
}
|
||||
|
@ -307,16 +309,16 @@ sub _init_menubar {
|
|||
my $plater = $self->{plater};
|
||||
|
||||
$self->{plater_menu} = Wx::Menu->new;
|
||||
$self->_append_menu_item($self->{plater_menu}, "Export G-code...", 'Export current plate as G-code', sub {
|
||||
$self->_append_menu_item($self->{plater_menu}, L("Export G-code..."), L('Export current plate as G-code'), sub {
|
||||
$plater->export_gcode;
|
||||
}, undef, 'cog_go.png');
|
||||
$self->_append_menu_item($self->{plater_menu}, "Export plate as STL...", 'Export current plate as STL', sub {
|
||||
$self->_append_menu_item($self->{plater_menu}, L("Export plate as STL..."), L('Export current plate as STL'), sub {
|
||||
$plater->export_stl;
|
||||
}, undef, 'brick_go.png');
|
||||
$self->_append_menu_item($self->{plater_menu}, "Export plate as AMF...", 'Export current plate as AMF', sub {
|
||||
$self->_append_menu_item($self->{plater_menu}, L("Export plate as AMF..."), L('Export current plate as AMF'), sub {
|
||||
$plater->export_amf;
|
||||
}, undef, 'brick_go.png');
|
||||
$self->_append_menu_item($self->{plater_menu}, "Export plate as 3MF...", 'Export current plate as 3MF', sub {
|
||||
$self->_append_menu_item($self->{plater_menu}, L("Export plate as 3MF..."), L('Export current plate as 3MF'), sub {
|
||||
$plater->export_3mf;
|
||||
}, undef, 'brick_go.png');
|
||||
|
||||
|
@ -329,13 +331,13 @@ sub _init_menubar {
|
|||
{
|
||||
my $tab_offset = 0;
|
||||
if (!$self->{no_plater}) {
|
||||
$self->_append_menu_item($windowMenu, "Select &Plater Tab\tCtrl+1", 'Show the plater', sub {
|
||||
$self->_append_menu_item($windowMenu, L("Select &Plater Tab\tCtrl+1"), L('Show the plater'), sub {
|
||||
$self->select_tab(0);
|
||||
}, undef, 'application_view_tile.png');
|
||||
$tab_offset += 1;
|
||||
}
|
||||
if (!$self->{no_controller}) {
|
||||
$self->_append_menu_item($windowMenu, "Select &Controller Tab\tCtrl+T", 'Show the printer controller', sub {
|
||||
$self->_append_menu_item($windowMenu, L("Select &Controller Tab\tCtrl+T"), L('Show the printer controller'), sub {
|
||||
$self->select_tab(1);
|
||||
}, undef, 'printer_empty.png');
|
||||
$tab_offset += 1;
|
||||
|
@ -343,13 +345,13 @@ sub _init_menubar {
|
|||
if ($tab_offset > 0) {
|
||||
$windowMenu->AppendSeparator();
|
||||
}
|
||||
$self->_append_menu_item($windowMenu, "Select P&rint Settings Tab\tCtrl+2", 'Show the print settings', sub {
|
||||
$self->_append_menu_item($windowMenu, L("Select P&rint Settings Tab\tCtrl+2"), L('Show the print settings'), sub {
|
||||
$self->select_tab($tab_offset+0);
|
||||
}, undef, 'cog.png');
|
||||
$self->_append_menu_item($windowMenu, "Select &Filament Settings Tab\tCtrl+3", 'Show the filament settings', sub {
|
||||
$self->_append_menu_item($windowMenu, L("Select &Filament Settings Tab\tCtrl+3"), L('Show the filament settings'), sub {
|
||||
$self->select_tab($tab_offset+1);
|
||||
}, undef, 'spool.png');
|
||||
$self->_append_menu_item($windowMenu, "Select Print&er Settings Tab\tCtrl+4", 'Show the printer settings', sub {
|
||||
$self->_append_menu_item($windowMenu, L("Select Print&er Settings Tab\tCtrl+4"), L('Show the printer settings'), sub {
|
||||
$self->select_tab($tab_offset+2);
|
||||
}, undef, 'printer_empty.png');
|
||||
}
|
||||
|
@ -361,66 +363,66 @@ sub _init_menubar {
|
|||
# as the simple numeric accelerators spoil all numeric data entry.
|
||||
# The camera control accelerators are captured by 3DScene Perl module instead.
|
||||
my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] };
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Iso', '0'), 'Iso View' , sub { $self->select_view('iso' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Top', '1'), 'Top View' , sub { $self->select_view('top' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Bottom', '2'), 'Bottom View' , sub { $self->select_view('bottom' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Front', '3'), 'Front View' , sub { $self->select_view('front' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Rear', '4'), 'Rear View' , sub { $self->select_view('rear' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Left', '5'), 'Left View' , sub { $self->select_view('left' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Right', '6'), 'Right View' , sub { $self->select_view('right' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Iso'), '0'), L('Iso View') , sub { $self->select_view('iso' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Top'), '1'), L('Top View') , sub { $self->select_view('top' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Bottom'), '2'), L('Bottom View') , sub { $self->select_view('bottom' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Front'), '3'), L('Front View') , sub { $self->select_view('front' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Rear'), '4'), L('Rear View') , sub { $self->select_view('rear' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Left'), '5'), L('Left View') , sub { $self->select_view('left' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->(L('Right'), '6'), L('Right View') , sub { $self->select_view('right' ); });
|
||||
}
|
||||
|
||||
# Help menu
|
||||
my $helpMenu = Wx::Menu->new;
|
||||
{
|
||||
$self->_append_menu_item($helpMenu, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…", "Run Configuration $Slic3r::GUI::ConfigWizard::wizard", sub {
|
||||
$self->_append_menu_item($helpMenu, L("&Configuration ").$Slic3r::GUI::ConfigWizard::wizard."…", L("Run Configuration ").$Slic3r::GUI::ConfigWizard::wizard, sub {
|
||||
# Run the config wizard, offer the "reset user profile" checkbox.
|
||||
$self->config_wizard(0);
|
||||
});
|
||||
$helpMenu->AppendSeparator();
|
||||
$self->_append_menu_item($helpMenu, "Prusa 3D Drivers", 'Open the Prusa3D drivers download page in your browser', sub {
|
||||
$self->_append_menu_item($helpMenu, L("Prusa 3D Drivers"), L('Open the Prusa3D drivers download page in your browser'), sub {
|
||||
Wx::LaunchDefaultBrowser('http://www.prusa3d.com/drivers/');
|
||||
});
|
||||
$self->_append_menu_item($helpMenu, "Prusa Edition Releases", 'Open the Prusa Edition releases page in your browser', sub {
|
||||
$self->_append_menu_item($helpMenu, L("Prusa Edition Releases"), L('Open the Prusa Edition releases page in your browser'), sub {
|
||||
Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/releases');
|
||||
});
|
||||
# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", 'Check for new Slic3r versions', sub {
|
||||
# wxTheApp->check_version(1);
|
||||
# });
|
||||
# $versioncheck->Enable(wxTheApp->have_version_check);
|
||||
$self->_append_menu_item($helpMenu, "Slic3r &Website", 'Open the Slic3r website in your browser', sub {
|
||||
$self->_append_menu_item($helpMenu, L("Slic3r &Website"), L('Open the Slic3r website in your browser'), sub {
|
||||
Wx::LaunchDefaultBrowser('http://slic3r.org/');
|
||||
});
|
||||
$self->_append_menu_item($helpMenu, "Slic3r &Manual", 'Open the Slic3r manual in your browser', sub {
|
||||
$self->_append_menu_item($helpMenu, L("Slic3r &Manual"), L('Open the Slic3r manual in your browser'), sub {
|
||||
Wx::LaunchDefaultBrowser('http://manual.slic3r.org/');
|
||||
});
|
||||
$helpMenu->AppendSeparator();
|
||||
$self->_append_menu_item($helpMenu, "System Info", 'Show system information', sub {
|
||||
$self->_append_menu_item($helpMenu, L("System Info"), L('Show system information'), sub {
|
||||
wxTheApp->system_info;
|
||||
});
|
||||
$self->_append_menu_item($helpMenu, "Report an Issue", 'Report an issue on the Slic3r Prusa Edition', sub {
|
||||
$self->_append_menu_item($helpMenu, L("Report an Issue"), L('Report an issue on the Slic3r Prusa Edition'), sub {
|
||||
Wx::LaunchDefaultBrowser('http://github.com/prusa3d/slic3r/issues/new');
|
||||
});
|
||||
$self->_append_menu_item($helpMenu, "&About Slic3r", 'Show about dialog', sub {
|
||||
$self->_append_menu_item($helpMenu, L("&About Slic3r"), L('Show about dialog'), sub {
|
||||
wxTheApp->about;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
# menubar
|
||||
# assign menubar to frame after appending items, otherwise special items
|
||||
# will not be handled correctly
|
||||
{
|
||||
my $menubar = Wx::MenuBar->new;
|
||||
$menubar->Append($fileMenu, "&File");
|
||||
$menubar->Append($self->{plater_menu}, "&Plater") if $self->{plater_menu};
|
||||
$menubar->Append($self->{object_menu}, "&Object") if $self->{object_menu};
|
||||
$menubar->Append($windowMenu, "&Window");
|
||||
$menubar->Append($self->{viewMenu}, "&View") if $self->{viewMenu};
|
||||
$menubar->Append($fileMenu, L("&File"));
|
||||
$menubar->Append($self->{plater_menu}, L("&Plater")) if $self->{plater_menu};
|
||||
$menubar->Append($self->{object_menu}, L("&Object")) if $self->{object_menu};
|
||||
$menubar->Append($windowMenu, L("&Window"));
|
||||
$menubar->Append($self->{viewMenu}, L("&View")) if $self->{viewMenu};
|
||||
# Add an optional debug menu
|
||||
# (Select application language from the list of installed languages)
|
||||
# In production code, the add_debug_menu() call should do nothing.
|
||||
Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event});
|
||||
$menubar->Append($helpMenu, "&Help");
|
||||
$menubar->Append($helpMenu, L("&Help"));
|
||||
# Add an optional debug menu. In production code, the add_debug_menu() call should do nothing.
|
||||
$self->SetMenuBar($menubar);
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +453,7 @@ sub quick_slice {
|
|||
# select input file
|
||||
my $input_file;
|
||||
if (!$params{reslice}) {
|
||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):',
|
||||
my $dialog = Wx::FileDialog->new($self, L('Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):'),
|
||||
wxTheApp->{app_config}->get_last_dir, "",
|
||||
&Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if ($dialog->ShowModal != wxID_OK) {
|
||||
|
@ -463,13 +465,13 @@ sub quick_slice {
|
|||
$qs_last_input_file = $input_file unless $params{export_svg};
|
||||
} else {
|
||||
if (!defined $qs_last_input_file) {
|
||||
Wx::MessageDialog->new($self, "No previously sliced file.",
|
||||
'Error', wxICON_ERROR | wxOK)->ShowModal();
|
||||
Wx::MessageDialog->new($self, L("No previously sliced file."),
|
||||
L('Error'), wxICON_ERROR | wxOK)->ShowModal();
|
||||
return;
|
||||
}
|
||||
if (! -e $qs_last_input_file) {
|
||||
Wx::MessageDialog->new($self, "Previously sliced file ($qs_last_input_file) not found.",
|
||||
'File Not Found', wxICON_ERROR | wxOK)->ShowModal();
|
||||
Wx::MessageDialog->new($self, L("Previously sliced file (").$qs_last_input_file.L(") not found."),
|
||||
L('File Not Found'), wxICON_ERROR | wxOK)->ShowModal();
|
||||
return;
|
||||
}
|
||||
$input_file = $qs_last_input_file;
|
||||
|
@ -508,7 +510,7 @@ sub quick_slice {
|
|||
# The following line may die if the output_filename_format template substitution fails.
|
||||
$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:',
|
||||
my $dlg = Wx::FileDialog->new($self, L('Save ') . ($params{export_svg} ? L('SVG') : L('G-code')) . L(' file as:'),
|
||||
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) {
|
||||
|
@ -522,7 +524,7 @@ sub quick_slice {
|
|||
}
|
||||
|
||||
# show processbar dialog
|
||||
$progress_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…",
|
||||
$progress_dialog = Wx::ProgressDialog->new(L('Slicing…'), L("Processing ").$input_file_basename."…",
|
||||
100, $self, 0);
|
||||
$progress_dialog->Pulse;
|
||||
|
||||
|
@ -542,9 +544,9 @@ sub quick_slice {
|
|||
$progress_dialog->Destroy;
|
||||
undef $progress_dialog;
|
||||
|
||||
my $message = "$input_file_basename was successfully sliced.";
|
||||
my $message = $input_file_basename.L(" was successfully sliced.");
|
||||
wxTheApp->notify($message);
|
||||
Wx::MessageDialog->new($self, $message, 'Slicing Done!',
|
||||
Wx::MessageDialog->new($self, $message, L('Slicing Done!'),
|
||||
wxOK | wxICON_INFORMATION)->ShowModal;
|
||||
};
|
||||
Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog });
|
||||
|
@ -560,7 +562,7 @@ sub repair_stl {
|
|||
|
||||
my $input_file;
|
||||
{
|
||||
my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:',
|
||||
my $dialog = Wx::FileDialog->new($self, L('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) {
|
||||
|
@ -574,7 +576,7 @@ sub repair_stl {
|
|||
my $output_file = $input_file;
|
||||
{
|
||||
$output_file =~ s/\.[sS][tT][lL]$/_fixed.obj/;
|
||||
my $dlg = Wx::FileDialog->new($self, "Save OBJ file (less prone to coordinate errors than STL) as:", dirname($output_file),
|
||||
my $dlg = Wx::FileDialog->new($self, L("Save OBJ file (less prone to coordinate errors than STL) as:"), dirname($output_file),
|
||||
basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{obj}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
|
@ -588,7 +590,7 @@ sub repair_stl {
|
|||
$tmesh->ReadSTLFile($input_file);
|
||||
$tmesh->repair;
|
||||
$tmesh->WriteOBJFile($output_file);
|
||||
Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair");
|
||||
Slic3r::GUI::show_info($self, L("Your file was repaired."), L("Repair"));
|
||||
}
|
||||
|
||||
sub export_config {
|
||||
|
@ -599,7 +601,7 @@ sub export_config {
|
|||
eval { $config->validate; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
# Ask user for the file name for the config file.
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:',
|
||||
my $dlg = Wx::FileDialog->new($self, L('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);
|
||||
|
@ -617,7 +619,7 @@ sub load_config_file {
|
|||
my ($self, $file) = @_;
|
||||
if (!$file) {
|
||||
return unless $self->check_unsaved_changes;
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:',
|
||||
my $dlg = Wx::FileDialog->new($self, L('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);
|
||||
|
@ -640,7 +642,7 @@ sub export_configbundle {
|
|||
eval { wxTheApp->{preset_bundle}->full_config->validate; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
# Ask user for a file name.
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:',
|
||||
my $dlg = Wx::FileDialog->new($self, L('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);
|
||||
|
@ -661,7 +663,7 @@ sub load_configbundle {
|
|||
my ($self, $file, $reset_user_profile) = @_;
|
||||
return unless $self->check_unsaved_changes;
|
||||
if (!$file) {
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:',
|
||||
my $dlg = Wx::FileDialog->new($self, L('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);
|
||||
|
@ -681,7 +683,7 @@ sub load_configbundle {
|
|||
$tab->load_current_preset;
|
||||
}
|
||||
|
||||
my $message = sprintf "%d presets successfully imported.", $presets_imported;
|
||||
my $message = sprintf L("%d presets successfully imported."), $presets_imported;
|
||||
Slic3r::GUI::show_info($self, $message);
|
||||
}
|
||||
|
||||
|
@ -743,8 +745,8 @@ sub check_unsaved_changes {
|
|||
|
||||
if (@dirty) {
|
||||
my $titles = join ', ', @dirty;
|
||||
my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?",
|
||||
'Unsaved Presets', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
|
||||
my $confirm = Wx::MessageDialog->new($self, L("You have unsaved changes ").($titles).L(". Discard changes and continue anyway?"),
|
||||
L('Unsaved Presets'), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
|
||||
return $confirm->ShowModal == wxID_YES;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ use constant TB_CUT => &Wx::NewId;
|
|||
use constant TB_SETTINGS => &Wx::NewId;
|
||||
use constant TB_LAYER_EDITING => &Wx::NewId;
|
||||
|
||||
use Wx::Locale gettext => 'L';
|
||||
|
||||
# package variables to avoid passing lexicals to threads
|
||||
our $PROGRESS_BAR_EVENT : shared = Wx::NewEventType;
|
||||
our $ERROR_EVENT : shared = Wx::NewEventType;
|
||||
|
@ -50,7 +52,7 @@ sub new {
|
|||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
$self->{config} = Slic3r::Config::new_from_defaults_keys([qw(
|
||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||
serial_port serial_speed octoprint_host octoprint_apikey
|
||||
serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile
|
||||
nozzle_diameter single_extruder_multi_material
|
||||
wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe wipe_tower_rotation_angle extruder_colour filament_colour
|
||||
)]);
|
||||
|
@ -99,7 +101,7 @@ sub new {
|
|||
# Initialize 3D plater
|
||||
if ($Slic3r::GUI::have_OpenGL) {
|
||||
$self->{canvas3D} = Slic3r::GUI::Plater::3D->new($self->{preview_notebook}, $self->{objects}, $self->{model}, $self->{print}, $self->{config});
|
||||
$self->{preview_notebook}->AddPage($self->{canvas3D}, '3D');
|
||||
$self->{preview_notebook}->AddPage($self->{canvas3D}, L('3D'));
|
||||
$self->{canvas3D}->set_on_select_object($on_select_object);
|
||||
$self->{canvas3D}->set_on_double_click($on_double_click);
|
||||
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); });
|
||||
|
@ -133,7 +135,7 @@ sub new {
|
|||
|
||||
# Initialize 2D preview canvas
|
||||
$self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
|
||||
$self->{preview_notebook}->AddPage($self->{canvas}, '2D');
|
||||
$self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
|
||||
$self->{canvas}->on_select_object($on_select_object);
|
||||
$self->{canvas}->on_double_click($on_double_click);
|
||||
$self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
|
||||
|
@ -145,14 +147,14 @@ sub new {
|
|||
$self->{preview3D}->canvas->on_viewport_changed(sub {
|
||||
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas);
|
||||
});
|
||||
$self->{preview_notebook}->AddPage($self->{preview3D}, 'Preview');
|
||||
$self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
|
||||
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
|
||||
}
|
||||
|
||||
# Initialize toolpaths preview
|
||||
if ($Slic3r::GUI::have_OpenGL) {
|
||||
$self->{toolpaths2D} = Slic3r::GUI::Plater::2DToolpaths->new($self->{preview_notebook}, $self->{print});
|
||||
$self->{preview_notebook}->AddPage($self->{toolpaths2D}, 'Layers');
|
||||
$self->{preview_notebook}->AddPage($self->{toolpaths2D}, L('Layers'));
|
||||
}
|
||||
|
||||
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
|
||||
|
@ -172,37 +174,37 @@ sub new {
|
|||
if (!&Wx::wxMSW) {
|
||||
Wx::ToolTip::Enable(1);
|
||||
$self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT | wxBORDER_SIMPLE | wxTAB_TRAVERSAL);
|
||||
$self->{htoolbar}->AddTool(TB_ADD, "Add…", Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_REMOVE, "Delete", Wx::Bitmap->new(Slic3r::var("brick_delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_RESET, "Delete All", Wx::Bitmap->new(Slic3r::var("cross.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ARRANGE, "Arrange", Wx::Bitmap->new(Slic3r::var("bricks.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ADD, L("Add…"), Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_REMOVE, L("Delete"), Wx::Bitmap->new(Slic3r::var("brick_delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_RESET, L("Delete All"), Wx::Bitmap->new(Slic3r::var("cross.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ARRANGE, L("Arrange"), Wx::Bitmap->new(Slic3r::var("bricks.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_FEWER, "Fewer", Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_MORE, L("More"), Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_FEWER, L("Fewer"), Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new(Slic3r::var("arrow_rotate_anticlockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new(Slic3r::var("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new(Slic3r::var("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new(Slic3r::var("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new(Slic3r::var("package.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_45CCW, L("45° ccw"), Wx::Bitmap->new(Slic3r::var("arrow_rotate_anticlockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_45CW, L("45° cw"), Wx::Bitmap->new(Slic3r::var("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SCALE, L("Scale…"), Wx::Bitmap->new(Slic3r::var("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SPLIT, L("Split"), Wx::Bitmap->new(Slic3r::var("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_CUT, L("Cut…"), Wx::Bitmap->new(Slic3r::var("package.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_LAYER_EDITING, 'Layer Editing', Wx::Bitmap->new(Slic3r::var("variable_layer_height.png"), wxBITMAP_TYPE_PNG), wxNullBitmap, 1, 0, 'Layer Editing');
|
||||
$self->{htoolbar}->AddTool(TB_SETTINGS, L("Settings…"), Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_LAYER_EDITING, L('Layer Editing'), Wx::Bitmap->new(Slic3r::var("variable_layer_height.png"), wxBITMAP_TYPE_PNG), wxNullBitmap, 1, 0, 'Layer Editing');
|
||||
} else {
|
||||
my %tbar_buttons = (
|
||||
add => "Add…",
|
||||
remove => "Delete",
|
||||
reset => "Delete All",
|
||||
arrange => "Arrange",
|
||||
add => L("Add…"),
|
||||
remove => L("Delete"),
|
||||
reset => L("Delete All"),
|
||||
arrange => L("Arrange"),
|
||||
increase => "",
|
||||
decrease => "",
|
||||
rotate45ccw => "",
|
||||
rotate45cw => "",
|
||||
changescale => "Scale…",
|
||||
split => "Split",
|
||||
cut => "Cut…",
|
||||
settings => "Settings…",
|
||||
layer_editing => "Layer editing",
|
||||
changescale => L("Scale…"),
|
||||
split => L("Split"),
|
||||
cut => L("Cut…"),
|
||||
settings => L("Settings…"),
|
||||
layer_editing => L("Layer editing"),
|
||||
);
|
||||
$self->{btoolbar} = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
for (qw(add remove reset arrange increase decrease rotate45ccw rotate45cw changescale split cut settings)) {
|
||||
|
@ -215,9 +217,9 @@ sub new {
|
|||
|
||||
$self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, wxDefaultSize,
|
||||
wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS );
|
||||
$self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 145);
|
||||
$self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 45);
|
||||
$self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
|
||||
$self->{list}->InsertColumn(0, L("Name"), wxLIST_FORMAT_LEFT, 145);
|
||||
$self->{list}->InsertColumn(1, L("Copies"), wxLIST_FORMAT_CENTER, 45);
|
||||
$self->{list}->InsertColumn(2, L("Scale"), wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
|
||||
EVT_LIST_ITEM_SELECTED($self, $self->{list}, \&list_item_selected);
|
||||
EVT_LIST_ITEM_DESELECTED($self, $self->{list}, \&list_item_deselected);
|
||||
EVT_LIST_ITEM_ACTIVATED($self, $self->{list}, \&list_item_activated);
|
||||
|
@ -231,11 +233,11 @@ sub new {
|
|||
});
|
||||
|
||||
# right pane buttons
|
||||
$self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_reslice} = Wx::Button->new($self, -1, "Slice now", wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_print} = Wx::Button->new($self, -1, "Print…", wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_send_gcode} = Wx::Button->new($self, -1, "Send to printer", wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_export_gcode} = Wx::Button->new($self, -1, L("Export G-code…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_reslice} = Wx::Button->new($self, -1, L("Slice now"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_print} = Wx::Button->new($self, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_send_gcode} = Wx::Button->new($self, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
$self->{btn_export_stl} = Wx::Button->new($self, -1, L("Export STL…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
|
||||
#$self->{btn_export_gcode}->SetFont($Slic3r::GUI::small_font);
|
||||
#$self->{btn_export_stl}->SetFont($Slic3r::GUI::small_font);
|
||||
$self->{btn_print}->Hide;
|
||||
|
@ -362,9 +364,9 @@ sub new {
|
|||
$presets->AddGrowableCol(1, 1);
|
||||
$presets->SetFlexibleDirection(wxHORIZONTAL);
|
||||
my %group_labels = (
|
||||
print => 'Print settings',
|
||||
filament => 'Filament',
|
||||
printer => 'Printer',
|
||||
print => L('Print settings'),
|
||||
filament => L('Filament'),
|
||||
printer => L('Printer'),
|
||||
);
|
||||
# UI Combo boxes for a print, multiple filaments, and a printer.
|
||||
# Initially a single filament combo box is created, but the number of combo boxes for the filament selection may increase,
|
||||
|
@ -393,7 +395,7 @@ sub new {
|
|||
|
||||
my $object_info_sizer;
|
||||
{
|
||||
my $box = Wx::StaticBox->new($self, -1, "Info");
|
||||
my $box = Wx::StaticBox->new($self, -1, L("Info"));
|
||||
$object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
|
||||
$object_info_sizer->SetMinSize([350,-1]);
|
||||
my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5);
|
||||
|
@ -403,11 +405,11 @@ sub new {
|
|||
$object_info_sizer->Add($grid_sizer, 0, wxEXPAND);
|
||||
|
||||
my @info = (
|
||||
size => "Size",
|
||||
volume => "Volume",
|
||||
facets => "Facets",
|
||||
materials => "Materials",
|
||||
manifold => "Manifold",
|
||||
size => L("Size"),
|
||||
volume => L("Volume"),
|
||||
facets => L("Facets"),
|
||||
materials => L("Materials"),
|
||||
manifold => L("Manifold"),
|
||||
);
|
||||
while (my $field = shift @info) {
|
||||
my $label = shift @info;
|
||||
|
@ -433,7 +435,7 @@ sub new {
|
|||
|
||||
my $print_info_sizer;
|
||||
{
|
||||
my $box = Wx::StaticBox->new($self, -1, "Sliced Info");
|
||||
my $box = Wx::StaticBox->new($self, -1, L("Sliced Info"));
|
||||
$print_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
|
||||
$print_info_sizer->SetMinSize([350,-1]);
|
||||
my $grid_sizer = Wx::FlexGridSizer->new(2, 2, 5, 5);
|
||||
|
@ -442,11 +444,11 @@ sub new {
|
|||
$grid_sizer->AddGrowableCol(3, 1);
|
||||
$print_info_sizer->Add($grid_sizer, 0, wxEXPAND);
|
||||
my @info = (
|
||||
fil_m => "Used Filament (m)",
|
||||
fil_mm3 => "Used Filament (mm\x{00B3})",
|
||||
fil_g => "Used Filament (g)",
|
||||
cost => "Cost",
|
||||
time => "Estimated printing time",
|
||||
fil_m => L("Used Filament (m)"),
|
||||
fil_mm3 => L("Used Filament (mm³)"),
|
||||
fil_g => L("Used Filament (g)"),
|
||||
cost => L("Cost"),
|
||||
time => L("Estimated printing time"),
|
||||
);
|
||||
while (my $field = shift @info) {
|
||||
my $label = shift @info;
|
||||
|
@ -624,7 +626,7 @@ sub load_files {
|
|||
my $one_by_one = (@$nozzle_dmrs <= 1) || (@$input_files == 1) ||
|
||||
defined(first { $_ =~ /.[aA][mM][fF]$/ || $_ =~ /.[aA][mM][fF].[xX][mM][lL]$/ || $_ =~ /.[zZ][iI][pP].[aA][mM][fF]$/ || $_ =~ /.3[mM][fF]$/ || $_ =~ /.[pP][rR][uI][sS][aA]$/ } @$input_files);
|
||||
|
||||
my $process_dialog = Wx::ProgressDialog->new('Loading…', "Processing input file\n" . basename($input_files->[0]), 100, $self, 0);
|
||||
my $process_dialog = Wx::ProgressDialog->new(L('Loading…'), L("Processing input file\n") . basename($input_files->[0]), 100, $self, 0);
|
||||
$process_dialog->Pulse;
|
||||
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
|
||||
|
||||
|
@ -638,7 +640,7 @@ sub load_files {
|
|||
# For all input files.
|
||||
for (my $i = 0; $i < @$input_files; $i += 1) {
|
||||
my $input_file = $input_files->[$i];
|
||||
$process_dialog->Update(100. * $i / @$input_files, "Processing input file\n" . basename($input_file));
|
||||
$process_dialog->Update(100. * $i / @$input_files, L("Processing input file\n") . basename($input_file));
|
||||
|
||||
my $model;
|
||||
if (($input_file =~ /.3[mM][fF]$/) || ($input_file =~ /.[zZ][iI][pP].[aA][mM][fF]$/))
|
||||
|
@ -658,10 +660,10 @@ sub load_files {
|
|||
|
||||
if ($model->looks_like_multipart_object) {
|
||||
my $dialog = Wx::MessageDialog->new($self,
|
||||
"This file contains several objects positioned at multiple heights. "
|
||||
L("This file contains several objects positioned at multiple heights. "
|
||||
. "Instead of considering them as multiple objects, should I consider\n"
|
||||
. "this file as a single object having multiple parts?\n",
|
||||
'Multi-part object detected', wxICON_WARNING | wxYES | wxNO);
|
||||
. "this file as a single object having multiple parts?\n"),
|
||||
L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO);
|
||||
$model->convert_multipart_object if $dialog->ShowModal() == wxID_YES;
|
||||
}
|
||||
|
||||
|
@ -675,10 +677,10 @@ sub load_files {
|
|||
|
||||
if ($new_model) {
|
||||
my $dialog = Wx::MessageDialog->new($self,
|
||||
"Multiple objects were loaded for a multi-material printer.\n"
|
||||
L("Multiple objects were loaded for a multi-material printer.\n"
|
||||
. "Instead of considering them as multiple objects, should I consider\n"
|
||||
. "these files to represent a single object having multiple parts?\n",
|
||||
'Multi-part object detected', wxICON_WARNING | wxYES | wxNO);
|
||||
. "these files to represent a single object having multiple parts?\n"),
|
||||
L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO);
|
||||
$new_model->convert_multipart_object if $dialog->ShowModal() == wxID_YES;
|
||||
push @obj_idx, $self->load_model_objects(@{$new_model->objects});
|
||||
}
|
||||
|
@ -687,7 +689,7 @@ sub load_files {
|
|||
wxTheApp->{app_config}->update_skein_dir(dirname($input_files->[-1]));
|
||||
|
||||
$process_dialog->Destroy;
|
||||
$self->statusbar->SetStatusText("Loaded " . join(',', @loaded_files));
|
||||
$self->statusbar->SetStatusText(L("Loaded ") . join(',', @loaded_files));
|
||||
return @obj_idx;
|
||||
}
|
||||
|
||||
|
@ -739,8 +741,8 @@ sub load_model_objects {
|
|||
if ($scaled_down) {
|
||||
Slic3r::GUI::show_info(
|
||||
$self,
|
||||
'Your object appears to be too large, so it was automatically scaled down to fit your print bed.',
|
||||
'Object too large?',
|
||||
L('Your object appears to be too large, so it was automatically scaled down to fit your print bed.'),
|
||||
L('Object too large?'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -895,7 +897,7 @@ sub set_number_of_copies {
|
|||
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||
|
||||
# prompt user
|
||||
my $copies = Wx::GetNumberFromUser("", "Enter the number of copies of the selected object:", "Copies", $model_object->instances_count, 0, 1000, $self);
|
||||
my $copies = Wx::GetNumberFromUser("", L("Enter the number of copies of the selected object:"), L("Copies"), $model_object->instances_count, 0, 1000, $self);
|
||||
my $diff = $copies - $model_object->instances_count;
|
||||
if ($diff == 0) {
|
||||
# no variation
|
||||
|
@ -922,9 +924,9 @@ sub _get_number_from_user {
|
|||
Wx::MessageBox(
|
||||
$error_message .
|
||||
(($only_positive && $value <= 0) ?
|
||||
": $value\nNon-positive value." :
|
||||
": $value\nNot a numeric value."),
|
||||
"Slic3r Error", wxOK | wxICON_EXCLAMATION, $self);
|
||||
": ".$value.L("\nNon-positive value.") :
|
||||
": ".$value.L("\nNot a numeric value.")),
|
||||
L("Slic3r Error"), wxOK | wxICON_EXCLAMATION, $self);
|
||||
$default = $value;
|
||||
}
|
||||
}
|
||||
|
@ -945,7 +947,7 @@ sub rotate {
|
|||
if (!defined $angle) {
|
||||
my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z';
|
||||
my $default = $axis == Z ? rad2deg($model_instance->rotation) : 0;
|
||||
$angle = $self->_get_number_from_user("Enter the rotation angle:", "Rotate around $axis_name axis", "Invalid rotation angle entered", $default);
|
||||
$angle = $self->_get_number_from_user(L("Enter the rotation angle:"), L("Rotate around ").$axis_name.(" axis"), L("Invalid rotation angle entered"), $default);
|
||||
return if $angle eq '';
|
||||
}
|
||||
|
||||
|
@ -1025,12 +1027,12 @@ sub changescale {
|
|||
if ($tosize) {
|
||||
my $cursize = $object_size->[$axis];
|
||||
my $newsize = $self->_get_number_from_user(
|
||||
sprintf('Enter the new size for the selected object (print bed: %smm):', unscale($bed_size->[$axis])),
|
||||
"Scale along $axis_name", 'Invalid scaling value entered', $cursize, 1);
|
||||
sprintf(L('Enter the new size for the selected object (print bed: %smm):'), unscale($bed_size->[$axis])),
|
||||
L("Scale along ").$axis_name, L('Invalid scaling value entered'), $cursize, 1);
|
||||
return if $newsize eq '';
|
||||
$scale = $newsize / $cursize * 100;
|
||||
} else {
|
||||
$scale = $self->_get_number_from_user('Enter the scale % for the selected object:', "Scale along $axis_name", 'Invalid scaling value entered', 100, 1);
|
||||
$scale = $self->_get_number_from_user(L('Enter the scale % for the selected object:'), L("Scale along ").$axis_name, L('Invalid scaling value entered'), 100, 1);
|
||||
return if $scale eq '';
|
||||
}
|
||||
|
||||
|
@ -1051,12 +1053,12 @@ sub changescale {
|
|||
my $scale;
|
||||
if ($tosize) {
|
||||
my $cursize = max(@$object_size);
|
||||
my $newsize = $self->_get_number_from_user('Enter the new max size for the selected object:', 'Scale', 'Invalid scaling value entered', $cursize, 1);
|
||||
my $newsize = $self->_get_number_from_user(L('Enter the new max size for the selected object:'), L('Scale'), L('Invalid scaling value entered'), $cursize, 1);
|
||||
return if ! defined($newsize) || $newsize eq '';
|
||||
$scale = $model_instance->scaling_factor * $newsize / $cursize * 100;
|
||||
} else {
|
||||
# max scale factor should be above 2540 to allow importing files exported in inches
|
||||
$scale = $self->_get_number_from_user('Enter the scale % for the selected object:', 'Scale', 'Invalid scaling value entered', $model_instance->scaling_factor*100, 1);
|
||||
$scale = $self->_get_number_from_user(L('Enter the scale % for the selected object:'), L('Scale'), L('Invalid scaling value entered'), $model_instance->scaling_factor*100, 1);
|
||||
return if ! defined($scale) || $scale eq '';
|
||||
}
|
||||
|
||||
|
@ -1107,7 +1109,7 @@ sub split_object {
|
|||
my $current_model_object = $new_model->get_object($obj_idx);
|
||||
|
||||
if ($current_model_object->volumes_count > 1) {
|
||||
Slic3r::GUI::warning_catcher($self)->("The selected object can't be split because it contains more than one volume/material.");
|
||||
Slic3r::GUI::warning_catcher($self)->(L("The selected object can't be split because it contains more than one volume/material."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1116,7 +1118,7 @@ sub split_object {
|
|||
my @model_objects = @{$current_model_object->split_object};
|
||||
if (@model_objects == 1) {
|
||||
$self->resume_background_process;
|
||||
Slic3r::GUI::warning_catcher($self)->("The selected object couldn't be split because it contains only one part.");
|
||||
Slic3r::GUI::warning_catcher($self)->(L("The selected object couldn't be split because it contains only one part."));
|
||||
$self->resume_background_process;
|
||||
return;
|
||||
}
|
||||
|
@ -1281,7 +1283,7 @@ sub reslice {
|
|||
$self->async_apply_config;
|
||||
$self->statusbar->SetCancelCallback(sub {
|
||||
$self->stop_background_process;
|
||||
$self->statusbar->SetStatusText("Slicing cancelled");
|
||||
$self->statusbar->SetStatusText(L("Slicing cancelled"));
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
});
|
||||
|
@ -1295,7 +1297,7 @@ sub export_gcode {
|
|||
return if !@{$self->{objects}};
|
||||
|
||||
if ($self->{export_gcode_output_file}) {
|
||||
Wx::MessageDialog->new($self, "Another export job is currently running.", 'Error', wxOK | wxICON_ERROR)->ShowModal;
|
||||
Wx::MessageDialog->new($self, L("Another export job is currently running."), L('Error'), wxOK | wxICON_ERROR)->ShowModal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1326,7 +1328,7 @@ sub export_gcode {
|
|||
} else {
|
||||
my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:',
|
||||
my $dlg = Wx::FileDialog->new($self, L('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) {
|
||||
|
@ -1343,7 +1345,7 @@ sub export_gcode {
|
|||
|
||||
$self->statusbar->SetCancelCallback(sub {
|
||||
$self->stop_background_process;
|
||||
$self->statusbar->SetStatusText("Export cancelled");
|
||||
$self->statusbar->SetStatusText(L("Export cancelled"));
|
||||
$self->{export_gcode_output_file} = undef;
|
||||
$self->{send_gcode_file} = undef;
|
||||
|
||||
|
@ -1440,24 +1442,29 @@ sub on_export_completed {
|
|||
if ($result) {
|
||||
# G-code file exported successfully.
|
||||
if ($self->{print_file}) {
|
||||
$message = "File added to print queue";
|
||||
$message = L("File added to print queue");
|
||||
$do_print = 1;
|
||||
} elsif ($self->{send_gcode_file}) {
|
||||
$message = "Sending G-code file to the OctoPrint server...";
|
||||
$message = L("Sending G-code file to the OctoPrint server...");
|
||||
$send_gcode = 1;
|
||||
} else {
|
||||
$message = "G-code file exported to " . $self->{export_gcode_output_file};
|
||||
$message = L("G-code file exported to ") . $self->{export_gcode_output_file};
|
||||
}
|
||||
} else {
|
||||
$message = "Export failed";
|
||||
$message = L("Export failed");
|
||||
}
|
||||
$self->{export_gcode_output_file} = undef;
|
||||
$self->statusbar->SetStatusText($message);
|
||||
wxTheApp->notify($message);
|
||||
|
||||
$self->do_print if $do_print;
|
||||
|
||||
# Send $self->{send_gcode_file} to OctoPrint.
|
||||
$self->send_gcode if $send_gcode;
|
||||
if ($send_gcode) {
|
||||
my $op = Slic3r::OctoPrint->new($self->{config});
|
||||
$op->send_gcode($self->GetId(), $PROGRESS_BAR_EVENT, $ERROR_EVENT, $self->{send_gcode_file});
|
||||
}
|
||||
|
||||
$self->{print_file} = undef;
|
||||
$self->{send_gcode_file} = undef;
|
||||
$self->{"print_info_cost"}->SetLabel(sprintf("%.2f" , $self->{print}->total_cost));
|
||||
|
@ -1486,45 +1493,6 @@ sub do_print {
|
|||
my $filament_names = wxTheApp->{preset_bundle}->filament_presets;
|
||||
$filament_stats = { map { $filament_names->[$_] => $filament_stats->{$_} } keys %$filament_stats };
|
||||
$printer_panel->load_print_job($self->{print_file}, $filament_stats);
|
||||
|
||||
$self->GetFrame->select_tab(1);
|
||||
}
|
||||
|
||||
# Send $self->{send_gcode_file} to OctoPrint.
|
||||
#FIXME Currently this call blocks the UI. Make it asynchronous.
|
||||
sub send_gcode {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->statusbar->StartBusy;
|
||||
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->timeout(180);
|
||||
|
||||
my $res = $ua->post(
|
||||
"http://" . $self->{config}->octoprint_host . "/api/files/local",
|
||||
Content_Type => 'form-data',
|
||||
'X-Api-Key' => $self->{config}->octoprint_apikey,
|
||||
Content => [
|
||||
file => [
|
||||
# On Windows, the path has to be encoded in local code page for perl to be able to open it.
|
||||
Slic3r::encode_path($self->{send_gcode_file}),
|
||||
# Remove the UTF-8 flag from the perl string, so the LWP::UserAgent can insert
|
||||
# the UTF-8 encoded string into the request as a byte stream.
|
||||
Slic3r::path_to_filename_raw($self->{send_gcode_file})
|
||||
],
|
||||
print => $self->{send_gcode_file_print} ? 1 : 0,
|
||||
],
|
||||
);
|
||||
|
||||
$self->statusbar->StopBusy;
|
||||
|
||||
if ($res->is_success) {
|
||||
$self->statusbar->SetStatusText("G-code file successfully uploaded to the OctoPrint server");
|
||||
} else {
|
||||
my $message = "Error while uploading to the OctoPrint server: " . $res->status_line;
|
||||
Slic3r::GUI::show_error($self, $message);
|
||||
$self->statusbar->SetStatusText($message);
|
||||
}
|
||||
}
|
||||
|
||||
sub export_stl {
|
||||
|
@ -1534,7 +1502,7 @@ sub export_stl {
|
|||
my $output_file = $self->_get_export_file('STL') or return;
|
||||
# Store a binary STL.
|
||||
$self->{model}->store_stl($output_file, 1);
|
||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
||||
$self->statusbar->SetStatusText(L("STL file exported to ").$output_file);
|
||||
}
|
||||
|
||||
sub reload_from_disk {
|
||||
|
@ -1576,7 +1544,7 @@ sub export_object_stl {
|
|||
# Ask user for a file name to write into.
|
||||
my $output_file = $self->_get_export_file('STL') or return;
|
||||
$model_object->mesh->write_binary($output_file);
|
||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
||||
$self->statusbar->SetStatusText(L("STL file exported to ").$output_file);
|
||||
}
|
||||
|
||||
sub export_amf {
|
||||
|
@ -1587,11 +1555,11 @@ sub export_amf {
|
|||
my $res = $self->{model}->store_amf($output_file, $self->{print});
|
||||
if ($res)
|
||||
{
|
||||
$self->statusbar->SetStatusText("AMF file exported to $output_file");
|
||||
$self->statusbar->SetStatusText(L("AMF file exported to ").$output_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->statusbar->SetStatusText("Error exporting AMF file $output_file");
|
||||
$self->statusbar->SetStatusText(L("Error exporting AMF file ").$output_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1603,11 +1571,11 @@ sub export_3mf {
|
|||
my $res = $self->{model}->store_3mf($output_file, $self->{print});
|
||||
if ($res)
|
||||
{
|
||||
$self->statusbar->SetStatusText("3MF file exported to $output_file");
|
||||
$self->statusbar->SetStatusText(L("3MF file exported to ").$output_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->statusbar->SetStatusText("Error exporting 3MF file $output_file");
|
||||
$self->statusbar->SetStatusText(L("Error exporting 3MF file ").$output_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1616,23 +1584,32 @@ sub export_3mf {
|
|||
sub _get_export_file {
|
||||
my ($self, $format) = @_;
|
||||
my $suffix = '';
|
||||
my $wildcard = 'known';
|
||||
if ($format eq 'STL')
|
||||
{
|
||||
$suffix = '.stl';
|
||||
$wildcard = 'stl';
|
||||
}
|
||||
elsif ($format eq 'AMF')
|
||||
{
|
||||
$suffix = '.zip.amf';
|
||||
if (&Wx::wxMAC) {
|
||||
# It seems that MacOS does not like double extension
|
||||
$suffix = '.amf';
|
||||
} else {
|
||||
$suffix = '.zip.amf';
|
||||
}
|
||||
$wildcard = 'amf';
|
||||
}
|
||||
elsif ($format eq '3MF')
|
||||
{
|
||||
$suffix = '.3mf';
|
||||
$wildcard = 'threemf';
|
||||
}
|
||||
my $output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
|
||||
Slic3r::GUI::catch_error($self) and return undef;
|
||||
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/;
|
||||
my $dlg = Wx::FileDialog->new($self, "Save $format file as:", dirname($output_file),
|
||||
basename($output_file), &Slic3r::GUI::MODEL_WILDCARD, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
my $dlg = Wx::FileDialog->new($self, L("Save ").$format.L(" file as:"), dirname($output_file),
|
||||
basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{$wildcard}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
return undef;
|
||||
|
@ -1834,7 +1811,7 @@ sub object_cut_dialog {
|
|||
}
|
||||
|
||||
if (!$Slic3r::GUI::have_OpenGL) {
|
||||
Slic3r::GUI::show_error($self, "Please install the OpenGL modules to use this feature (see build instructions).");
|
||||
Slic3r::GUI::show_error($self, L("Please install the OpenGL modules to use this feature (see build instructions)."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1944,19 +1921,19 @@ sub selection_changed {
|
|||
|
||||
if (my $stats = $model_object->mesh_stats) {
|
||||
$self->{object_info_volume}->SetLabel(sprintf('%.2f', $stats->{volume} * ($model_instance->scaling_factor**3)));
|
||||
$self->{object_info_facets}->SetLabel(sprintf('%d (%d shells)', $model_object->facets_count, $stats->{number_of_parts}));
|
||||
$self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts}));
|
||||
if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) {
|
||||
$self->{object_info_manifold}->SetLabel(sprintf("Auto-repaired (%d errors)", $errors));
|
||||
$self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors));
|
||||
$self->{object_info_manifold_warning_icon}->Show;
|
||||
|
||||
# we don't show normals_fixed because we never provide normals
|
||||
# to admesh, so it generates normals for all facets
|
||||
my $message = sprintf '%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges',
|
||||
my $message = sprintf L('%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges'),
|
||||
@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)};
|
||||
$self->{object_info_manifold}->SetToolTipString($message);
|
||||
$self->{object_info_manifold_warning_icon}->SetToolTipString($message);
|
||||
} else {
|
||||
$self->{object_info_manifold}->SetLabel("Yes");
|
||||
$self->{object_info_manifold}->SetLabel(L("Yes"));
|
||||
}
|
||||
} else {
|
||||
$self->{object_info_facets}->SetLabel($object->facets);
|
||||
|
@ -2007,99 +1984,99 @@ sub object_menu {
|
|||
my $frame = $self->GetFrame;
|
||||
my $menu = Wx::Menu->new;
|
||||
my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] };
|
||||
$frame->_append_menu_item($menu, $accel->('Delete', 'Del'), 'Remove the selected object', sub {
|
||||
$frame->_append_menu_item($menu, $accel->(L('Delete'), 'Del'), L('Remove the selected object'), sub {
|
||||
$self->remove;
|
||||
}, undef, 'brick_delete.png');
|
||||
$frame->_append_menu_item($menu, $accel->('Increase copies', '+'), 'Place one more copy of the selected object', sub {
|
||||
$frame->_append_menu_item($menu, $accel->(L('Increase copies'), '+'), L('Place one more copy of the selected object'), sub {
|
||||
$self->increase;
|
||||
}, undef, 'add.png');
|
||||
$frame->_append_menu_item($menu, $accel->('Decrease copies', '-'), 'Remove one copy of the selected object', sub {
|
||||
$frame->_append_menu_item($menu, $accel->(L('Decrease copies'), '-'), L('Remove one copy of the selected object'), sub {
|
||||
$self->decrease;
|
||||
}, undef, 'delete.png');
|
||||
$frame->_append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub {
|
||||
$frame->_append_menu_item($menu, L("Set number of copies…"), L('Change the number of copies of the selected object'), sub {
|
||||
$self->set_number_of_copies;
|
||||
}, undef, 'textfield.png');
|
||||
$menu->AppendSeparator();
|
||||
$frame->_append_menu_item($menu, $accel->('Rotate 45° clockwise', 'l'), 'Rotate the selected object by 45° clockwise', sub {
|
||||
$frame->_append_menu_item($menu, $accel->(L('Rotate 45° clockwise'), 'l'), L('Rotate the selected object by 45° clockwise'), sub {
|
||||
$self->rotate(-45, Z, 'relative');
|
||||
}, undef, 'arrow_rotate_clockwise.png');
|
||||
$frame->_append_menu_item($menu, $accel->('Rotate 45° counter-clockwise', 'r'), 'Rotate the selected object by 45° counter-clockwise', sub {
|
||||
$frame->_append_menu_item($menu, $accel->(L('Rotate 45° counter-clockwise'), 'r'), L('Rotate the selected object by 45° counter-clockwise'), sub {
|
||||
$self->rotate(+45, Z, 'relative');
|
||||
}, undef, 'arrow_rotate_anticlockwise.png');
|
||||
|
||||
my $rotateMenu = Wx::Menu->new;
|
||||
my $rotateMenuItem = $menu->AppendSubMenu($rotateMenu, "Rotate", 'Rotate the selected object by an arbitrary angle');
|
||||
my $rotateMenuItem = $menu->AppendSubMenu($rotateMenu, L("Rotate"), L('Rotate the selected object by an arbitrary angle'));
|
||||
$frame->_set_menu_item_icon($rotateMenuItem, 'textfield.png');
|
||||
$frame->_append_menu_item($rotateMenu, "Around X axis…", 'Rotate the selected object by an arbitrary angle around X axis', sub {
|
||||
$frame->_append_menu_item($rotateMenu, L("Around X axis…"), L('Rotate the selected object by an arbitrary angle around X axis'), sub {
|
||||
$self->rotate(undef, X);
|
||||
}, undef, 'bullet_red.png');
|
||||
$frame->_append_menu_item($rotateMenu, "Around Y axis…", 'Rotate the selected object by an arbitrary angle around Y axis', sub {
|
||||
$frame->_append_menu_item($rotateMenu, L("Around Y axis…"), L('Rotate the selected object by an arbitrary angle around Y axis'), sub {
|
||||
$self->rotate(undef, Y);
|
||||
}, undef, 'bullet_green.png');
|
||||
$frame->_append_menu_item($rotateMenu, "Around Z axis…", 'Rotate the selected object by an arbitrary angle around Z axis', sub {
|
||||
$frame->_append_menu_item($rotateMenu, L("Around Z axis…"), L('Rotate the selected object by an arbitrary angle around Z axis'), sub {
|
||||
$self->rotate(undef, Z);
|
||||
}, undef, 'bullet_blue.png');
|
||||
|
||||
my $mirrorMenu = Wx::Menu->new;
|
||||
my $mirrorMenuItem = $menu->AppendSubMenu($mirrorMenu, "Mirror", 'Mirror the selected object');
|
||||
my $mirrorMenuItem = $menu->AppendSubMenu($mirrorMenu, L("Mirror"), L('Mirror the selected object'));
|
||||
$frame->_set_menu_item_icon($mirrorMenuItem, 'shape_flip_horizontal.png');
|
||||
$frame->_append_menu_item($mirrorMenu, "Along X axis…", 'Mirror the selected object along the X axis', sub {
|
||||
$frame->_append_menu_item($mirrorMenu, L("Along X axis…"), L('Mirror the selected object along the X axis'), sub {
|
||||
$self->mirror(X);
|
||||
}, undef, 'bullet_red.png');
|
||||
$frame->_append_menu_item($mirrorMenu, "Along Y axis…", 'Mirror the selected object along the Y axis', sub {
|
||||
$frame->_append_menu_item($mirrorMenu, L("Along Y axis…"), L('Mirror the selected object along the Y axis'), sub {
|
||||
$self->mirror(Y);
|
||||
}, undef, 'bullet_green.png');
|
||||
$frame->_append_menu_item($mirrorMenu, "Along Z axis…", 'Mirror the selected object along the Z axis', sub {
|
||||
$frame->_append_menu_item($mirrorMenu, L("Along Z axis…"), L('Mirror the selected object along the Z axis'), sub {
|
||||
$self->mirror(Z);
|
||||
}, undef, 'bullet_blue.png');
|
||||
|
||||
my $scaleMenu = Wx::Menu->new;
|
||||
my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, "Scale", 'Scale the selected object along a single axis');
|
||||
my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, L("Scale"), L('Scale the selected object along a single axis'));
|
||||
$frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png');
|
||||
$frame->_append_menu_item($scaleMenu, $accel->('Uniformly…', 's'), 'Scale the selected object along the XYZ axes', sub {
|
||||
$frame->_append_menu_item($scaleMenu, $accel->(L('Uniformly…'), 's'), L('Scale the selected object along the XYZ axes'), sub {
|
||||
$self->changescale(undef);
|
||||
});
|
||||
$frame->_append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub {
|
||||
$frame->_append_menu_item($scaleMenu, L("Along X axis…"), L('Scale the selected object along the X axis'), sub {
|
||||
$self->changescale(X);
|
||||
}, undef, 'bullet_red.png');
|
||||
$frame->_append_menu_item($scaleMenu, "Along Y axis…", 'Scale the selected object along the Y axis', sub {
|
||||
$frame->_append_menu_item($scaleMenu, L("Along Y axis…"), L('Scale the selected object along the Y axis'), sub {
|
||||
$self->changescale(Y);
|
||||
}, undef, 'bullet_green.png');
|
||||
$frame->_append_menu_item($scaleMenu, "Along Z axis…", 'Scale the selected object along the Z axis', sub {
|
||||
$frame->_append_menu_item($scaleMenu, L("Along Z axis…"), L('Scale the selected object along the Z axis'), sub {
|
||||
$self->changescale(Z);
|
||||
}, undef, 'bullet_blue.png');
|
||||
|
||||
my $scaleToSizeMenu = Wx::Menu->new;
|
||||
my $scaleToSizeMenuItem = $menu->AppendSubMenu($scaleToSizeMenu, "Scale to size", 'Scale the selected object along a single axis');
|
||||
my $scaleToSizeMenuItem = $menu->AppendSubMenu($scaleToSizeMenu, L("Scale to size"), L('Scale the selected object along a single axis'));
|
||||
$frame->_set_menu_item_icon($scaleToSizeMenuItem, 'arrow_out.png');
|
||||
$frame->_append_menu_item($scaleToSizeMenu, "Uniformly…", 'Scale the selected object along the XYZ axes', sub {
|
||||
$frame->_append_menu_item($scaleToSizeMenu, L("Uniformly…"), L('Scale the selected object along the XYZ axes'), sub {
|
||||
$self->changescale(undef, 1);
|
||||
});
|
||||
$frame->_append_menu_item($scaleToSizeMenu, "Along X axis…", 'Scale the selected object along the X axis', sub {
|
||||
$frame->_append_menu_item($scaleToSizeMenu, L("Along X axis…"), L('Scale the selected object along the X axis'), sub {
|
||||
$self->changescale(X, 1);
|
||||
}, undef, 'bullet_red.png');
|
||||
$frame->_append_menu_item($scaleToSizeMenu, "Along Y axis…", 'Scale the selected object along the Y axis', sub {
|
||||
$frame->_append_menu_item($scaleToSizeMenu, L("Along Y axis…"), L('Scale the selected object along the Y axis'), sub {
|
||||
$self->changescale(Y, 1);
|
||||
}, undef, 'bullet_green.png');
|
||||
$frame->_append_menu_item($scaleToSizeMenu, "Along Z axis…", 'Scale the selected object along the Z axis', sub {
|
||||
$frame->_append_menu_item($scaleToSizeMenu, L("Along Z axis…"), L('Scale the selected object along the Z axis'), sub {
|
||||
$self->changescale(Z, 1);
|
||||
}, undef, 'bullet_blue.png');
|
||||
|
||||
$frame->_append_menu_item($menu, "Split", 'Split the selected object into individual parts', sub {
|
||||
$frame->_append_menu_item($menu, L("Split"), L('Split the selected object into individual parts'), sub {
|
||||
$self->split_object;
|
||||
}, undef, 'shape_ungroup.png');
|
||||
$frame->_append_menu_item($menu, "Cut…", 'Open the 3D cutting tool', sub {
|
||||
$frame->_append_menu_item($menu, L("Cut…"), L('Open the 3D cutting tool'), sub {
|
||||
$self->object_cut_dialog;
|
||||
}, undef, 'package.png');
|
||||
$menu->AppendSeparator();
|
||||
$frame->_append_menu_item($menu, "Settings…", 'Open the object editor dialog', sub {
|
||||
$frame->_append_menu_item($menu, L("Settings…"), L('Open the object editor dialog'), sub {
|
||||
$self->object_settings_dialog;
|
||||
}, undef, 'cog.png');
|
||||
$menu->AppendSeparator();
|
||||
$frame->_append_menu_item($menu, "Reload from Disk", 'Reload the selected file from Disk', sub {
|
||||
$frame->_append_menu_item($menu, L("Reload from Disk"), L('Reload the selected file from Disk'), sub {
|
||||
$self->reload_from_disk;
|
||||
}, undef, 'arrow_refresh.png');
|
||||
$frame->_append_menu_item($menu, "Export object as STL…", 'Export this single object as STL file', sub {
|
||||
$frame->_append_menu_item($menu, L("Export object as STL…"), L('Export this single object as STL file'), sub {
|
||||
$self->export_object_stl;
|
||||
}, undef, 'brick_go.png');
|
||||
|
||||
|
@ -2110,8 +2087,8 @@ sub object_menu {
|
|||
sub select_view {
|
||||
my ($self, $direction) = @_;
|
||||
my $idx_page = $self->{preview_notebook}->GetSelection;
|
||||
my $page = ($idx_page == &Wx::wxNOT_FOUND) ? '3D' : $self->{preview_notebook}->GetPageText($idx_page);
|
||||
if ($page eq 'Preview') {
|
||||
my $page = ($idx_page == &Wx::wxNOT_FOUND) ? L('3D') : $self->{preview_notebook}->GetPageText($idx_page);
|
||||
if ($page eq L('Preview')) {
|
||||
$self->{preview3D}->canvas->select_view($direction);
|
||||
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas);
|
||||
} else {
|
||||
|
|
|
@ -13,6 +13,8 @@ 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';
|
||||
|
||||
use Wx::Locale gettext => 'L';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent, $size, $objects, $model, $config) = @_;
|
||||
|
@ -126,8 +128,8 @@ sub repaint {
|
|||
$dc->SetFont(Wx::Font->new(14, wxDEFAULT, wxNORMAL, wxNORMAL));
|
||||
$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',
|
||||
? L('What do you want to print today? ™') # Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap.
|
||||
: L('Drag your objects here'),
|
||||
Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
|
|
|
@ -338,7 +338,6 @@ sub Render {
|
|||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (!$self->GetParent->enabled || !$self->layers) {
|
||||
glFlush();
|
||||
$self->SwapBuffers;
|
||||
return;
|
||||
}
|
||||
|
@ -486,7 +485,6 @@ sub Render {
|
|||
}
|
||||
|
||||
gluDeleteTess($tess) if $tess;
|
||||
glFlush();
|
||||
$self->SwapBuffers;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE wxCB_READONLY);
|
|||
use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN EVT_CHECKBOX EVT_CHOICE EVT_CHECKLISTBOX);
|
||||
use base qw(Wx::Panel Class::Accessor);
|
||||
|
||||
use Wx::Locale gettext => 'L';
|
||||
|
||||
__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer auto_zoom));
|
||||
|
||||
sub new {
|
||||
|
@ -58,34 +60,42 @@ sub new {
|
|||
$z_label_high->SetFont($Slic3r::GUI::small_font);
|
||||
|
||||
$self->single_layer(0);
|
||||
my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, "1 Layer");
|
||||
my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, L("1 Layer"));
|
||||
|
||||
my $label_view_type = $self->{label_view_type} = Wx::StaticText->new($self, -1, "View");
|
||||
my $label_view_type = $self->{label_view_type} = Wx::StaticText->new($self, -1, L("View"));
|
||||
|
||||
my $choice_view_type = $self->{choice_view_type} = Wx::Choice->new($self, -1);
|
||||
$choice_view_type->Append("Feature type");
|
||||
$choice_view_type->Append("Height");
|
||||
$choice_view_type->Append("Width");
|
||||
$choice_view_type->Append("Speed");
|
||||
$choice_view_type->Append("Tool");
|
||||
$choice_view_type->Append(L("Feature type"));
|
||||
$choice_view_type->Append(L("Height"));
|
||||
$choice_view_type->Append(L("Width"));
|
||||
$choice_view_type->Append(L("Speed"));
|
||||
$choice_view_type->Append(L("Tool"));
|
||||
$choice_view_type->SetSelection(0);
|
||||
|
||||
my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, "Show");
|
||||
my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, L("Show"));
|
||||
|
||||
my $combochecklist_features = $self->{combochecklist_features} = Wx::ComboCtrl->new();
|
||||
$combochecklist_features->Create($self, -1, "Feature types", wxDefaultPosition, [200, -1], wxCB_READONLY);
|
||||
#FIXME If the following line is removed, the combo box popup list will not react to mouse clicks.
|
||||
# On the other side, with this line the combo box popup cannot be closed by clicking on the combo button on Windows 10.
|
||||
$combochecklist_features->UseAltPopupWindow();
|
||||
$combochecklist_features->EnablePopupAnimation(0);
|
||||
my $feature_text = "Feature types";
|
||||
my $feature_items = "Perimeter|External perimeter|Overhang perimeter|Internal infill|Solid infill|Top solid infill|Bridge infill|Gap fill|Skirt|Support material|Support material interface|Wipe tower";
|
||||
$combochecklist_features->Create($self, -1, L("Feature types"), wxDefaultPosition, [200, -1], wxCB_READONLY);
|
||||
my $feature_text = L("Feature types");
|
||||
my $feature_items = L("Perimeter")."|"
|
||||
.L("External perimeter")."|"
|
||||
.L("Overhang perimeter")."|"
|
||||
.L("Internal infill")."|"
|
||||
.L("Solid infill")."|"
|
||||
.L("Top solid infill")."|"
|
||||
.L("Bridge infill")."|"
|
||||
.L("Gap fill")."|"
|
||||
.L("Skirt")."|"
|
||||
.L("Support material")."|"
|
||||
.L("Support material interface")."|"
|
||||
.L("Wipe tower")."|"
|
||||
.L("Custom");
|
||||
Slic3r::GUI::create_combochecklist($combochecklist_features, $feature_text, $feature_items, 1);
|
||||
|
||||
my $checkbox_travel = $self->{checkbox_travel} = Wx::CheckBox->new($self, -1, "Travel");
|
||||
my $checkbox_retractions = $self->{checkbox_retractions} = Wx::CheckBox->new($self, -1, "Retractions");
|
||||
my $checkbox_unretractions = $self->{checkbox_unretractions} = Wx::CheckBox->new($self, -1, "Unretractions");
|
||||
my $checkbox_shells = $self->{checkbox_shells} = Wx::CheckBox->new($self, -1, "Shells");
|
||||
my $checkbox_travel = $self->{checkbox_travel} = Wx::CheckBox->new($self, -1, L("Travel"));
|
||||
my $checkbox_retractions = $self->{checkbox_retractions} = Wx::CheckBox->new($self, -1, L("Retractions"));
|
||||
my $checkbox_unretractions = $self->{checkbox_unretractions} = Wx::CheckBox->new($self, -1, L("Unretractions"));
|
||||
my $checkbox_shells = $self->{checkbox_shells} = Wx::CheckBox->new($self, -1, L("Shells"));
|
||||
|
||||
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
|
@ -255,6 +265,7 @@ sub new {
|
|||
'Support material' => '00FF00',
|
||||
'Support material interface' => '008000',
|
||||
'Wipe tower' => 'B3E3AB',
|
||||
'Custom' => 'FFFF00',
|
||||
);
|
||||
$self->gcode_preview_data->set_extrusion_paths_colors(\@extrusion_roles_colors);
|
||||
|
||||
|
@ -322,31 +333,9 @@ sub load_print {
|
|||
return;
|
||||
}
|
||||
|
||||
my $z_idx_low = $self->slider_low->GetValue;
|
||||
my $z_idx_high = $self->slider_high->GetValue;
|
||||
$self->enabled(1);
|
||||
$self->slider_low->SetRange(0, $n_layers - 1);
|
||||
$self->slider_high->SetRange(0, $n_layers - 1);
|
||||
if ($z_idx_high < $n_layers && ($self->single_layer || $z_idx_high != 0)) {
|
||||
# use $z_idx
|
||||
} else {
|
||||
# Out of range. Disable 'single layer' view.
|
||||
$self->single_layer(0);
|
||||
$self->{checkbox_singlelayer}->SetValue(0);
|
||||
$z_idx_low = 0;
|
||||
$z_idx_high = $n_layers - 1;
|
||||
}
|
||||
if ($self->single_layer) {
|
||||
$z_idx_low = $z_idx_high;
|
||||
} elsif ($z_idx_low > $z_idx_high) {
|
||||
$z_idx_low = 0;
|
||||
}
|
||||
$self->slider_low->SetValue($z_idx_low);
|
||||
$self->slider_high->SetValue($z_idx_high);
|
||||
$self->slider_low->Show;
|
||||
$self->slider_high->Show;
|
||||
$self->Layout;
|
||||
|
||||
# used to set the sliders to the extremes of the current zs range
|
||||
$self->{force_sliders_full_range} = 0;
|
||||
|
||||
if ($self->{preferred_color_mode} eq 'tool_or_feature') {
|
||||
# It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature.
|
||||
# Color by feature if it is a single extruder print.
|
||||
|
@ -384,16 +373,58 @@ sub load_print {
|
|||
}
|
||||
$self->show_hide_ui_elements('simple');
|
||||
} else {
|
||||
$self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0) && $self->auto_zoom;
|
||||
$self->canvas->load_gcode_preview($self->print, $self->gcode_preview_data, \@colors);
|
||||
$self->show_hide_ui_elements('full');
|
||||
|
||||
# recalculates zs and update sliders accordingly
|
||||
$self->{layers_z} = $self->canvas->get_current_print_zs();
|
||||
$n_layers = scalar(@{$self->{layers_z}});
|
||||
}
|
||||
|
||||
$self->update_sliders($n_layers);
|
||||
|
||||
if ($self->auto_zoom) {
|
||||
$self->canvas->zoom_to_volumes;
|
||||
}
|
||||
$self->_loaded(1);
|
||||
}
|
||||
}
|
||||
|
||||
sub update_sliders
|
||||
{
|
||||
my ($self, $n_layers) = @_;
|
||||
|
||||
my $z_idx_low = $self->slider_low->GetValue;
|
||||
my $z_idx_high = $self->slider_high->GetValue;
|
||||
$self->enabled(1);
|
||||
$self->slider_low->SetRange(0, $n_layers - 1);
|
||||
$self->slider_high->SetRange(0, $n_layers - 1);
|
||||
|
||||
if ($self->{force_sliders_full_range}) {
|
||||
$z_idx_low = 0;
|
||||
$z_idx_high = $n_layers - 1;
|
||||
} elsif ($z_idx_high < $n_layers && ($self->single_layer || $z_idx_high != 0)) {
|
||||
# use $z_idx
|
||||
} else {
|
||||
# Out of range. Disable 'single layer' view.
|
||||
$self->single_layer(0);
|
||||
$self->{checkbox_singlelayer}->SetValue(0);
|
||||
$z_idx_low = 0;
|
||||
$z_idx_high = $n_layers - 1;
|
||||
}
|
||||
if ($self->single_layer) {
|
||||
$z_idx_low = $z_idx_high;
|
||||
} elsif ($z_idx_low > $z_idx_high) {
|
||||
$z_idx_low = 0;
|
||||
}
|
||||
|
||||
$self->slider_low->SetValue($z_idx_low);
|
||||
$self->slider_high->SetValue($z_idx_high);
|
||||
$self->slider_low->Show;
|
||||
$self->slider_high->Show;
|
||||
$self->set_z_range($self->{layers_z}[$z_idx_low], $self->{layers_z}[$z_idx_high]);
|
||||
$self->Layout;
|
||||
}
|
||||
|
||||
sub set_z_range
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
# Preferences dialog, opens from Menu: File->Preferences
|
||||
|
||||
package Slic3r::GUI::Preferences;
|
||||
use Wx qw(:dialog :id :misc :sizer :systemsettings wxTheApp);
|
||||
use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER);
|
||||
use base 'Wx::Dialog';
|
||||
|
||||
sub new {
|
||||
my ($class, $parent) = @_;
|
||||
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,
|
||||
title => 'General',
|
||||
on_change => sub {
|
||||
my ($opt_id) = @_;
|
||||
$self->{values}{$opt_id} = $optgroup->get_value($opt_id);
|
||||
},
|
||||
label_width => 200,
|
||||
);
|
||||
# $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 => $app_config->get("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',
|
||||
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 => $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 => $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 => $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 => $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 => $app_config->get("no_defaults"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'show_incompatible_presets',
|
||||
type => 'bool',
|
||||
label => 'Show incompatible print and filament presets',
|
||||
tooltip => 'When checked, the print and filament presets are shown in the preset editor even ' .
|
||||
'if they are marked as incompatible with the active printer',
|
||||
default => $app_config->get("show_incompatible_presets"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'use_legacy_opengl',
|
||||
type => 'bool',
|
||||
label => 'Use legacy OpenGL 1.1 rendering',
|
||||
tooltip => 'If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may try to check this checkbox. This will disable the layer height editing and anti aliasing, so it is likely better to upgrade your graphics driver.',
|
||||
default => $app_config->get("use_legacy_opengl"),
|
||||
));
|
||||
|
||||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
$sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
my $buttons = $self->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
||||
EVT_BUTTON($self, wxID_OK, sub { $self->_accept });
|
||||
$sizer->Add($buttons, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
$self->SetSizer($sizer);
|
||||
$sizer->SetSizeHints($self);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub _accept {
|
||||
my ($self) = @_;
|
||||
|
||||
if (defined($self->{values}{no_controller}) ||
|
||||
defined($self->{values}{no_defaults}) ||
|
||||
defined($self->{values}{use_legacy_opengl})) {
|
||||
Slic3r::GUI::warning_catcher($self)->("You need to restart Slic3r to make the changes effective.");
|
||||
}
|
||||
|
||||
my $app_config = wxTheApp->{app_config};
|
||||
$app_config->set($_, $self->{values}{$_}) for keys %{$self->{values}};
|
||||
|
||||
$self->EndModal(wxID_OK);
|
||||
$self->Close; # needed on Linux
|
||||
|
||||
# Nothify the UI to update itself from the ini file.
|
||||
wxTheApp->update_ui_from_settings;
|
||||
}
|
||||
|
||||
1;
|
Loading…
Add table
Add a link
Reference in a new issue