Merged with dev

This commit is contained in:
bubnikv 2018-09-12 11:59:02 +02:00
commit 0235f1a821
1491 changed files with 514153 additions and 29226 deletions

View File

@ -12,6 +12,7 @@ my %prereqs = qw(
ExtUtils::ParseXS 3.22
ExtUtils::XSpp 0
ExtUtils::Typemaps 0
ExtUtils::Typemaps::Basic 0
File::Basename 0
File::Spec 0
Getopt::Long 0
@ -35,7 +36,6 @@ if ($gui) {
%prereqs = qw(
Class::Accessor 0
Wx 0.9918
Socket 2.016
);
%recommends = qw(
Wx::GLCanvas 0

View File

@ -1,5 +1,4 @@
# Boost 1.63 requires CMake 3.7 or newer
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.2)
project(Slic3r)
@ -22,8 +21,8 @@ option(SLIC3R_STATIC "Compile Slic3r with static libraries (Boost, TBB, glew)
option(SLIC3R_GUI "Compile Slic3r with GUI components (OpenGL, wxWidgets)" 1)
option(SLIC3R_PRUSACONTROL "Compile Slic3r with the PrusaControl prject file format (requires wxWidgets base library)" 1)
option(SLIC3R_PROFILE "Compile Slic3r with an invasive Shiny profiler" 0)
option(SLIC3R_HAS_BROKEN_CROAK "Compile Slic3r for a broken Strawberry Perl 64bit" 0)
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
if (MSVC AND SLIC3R_MSVC_COMPILE_PARALLEL)
add_compile_options(/MP)
@ -37,10 +36,18 @@ else()
set(ENV_PATH_SEPARATOR ":")
endif()
set(ENV{PATH} "${PROJECT_SOURCE_DIR}/local-lib/bin${ENV_PATH_SEPARATOR}$ENV{PATH}")
set(ENV{PERL5LIB} "${PROJECT_SOURCE_DIR}/local-lib/lib/perl${ENV_PATH_SEPARATOR}$ENV{PERL5LIB}")
set(PERL_INCLUDE "${PROJECT_SOURCE_DIR}/local-lib/lib/perl5${ENV_PATH_SEPARATOR}$ENV{PERL5LIB}")
message("PATH: $ENV{PATH}")
message("PERL5LIB: $ENV{PERL5LIB}")
message("PERL_INCLUDE: ${PERL_INCLUDE}")
find_package(Perl REQUIRED)
if (WIN32)
# On Windows passing the PERL5LIB variable causes various problems (such as with MAX_PATH and others),
# basically I've found no good way to do it on Windows.
set(PERL5LIB_ENV_CMD "")
else()
set(PERL5LIB_ENV_CMD ${CMAKE_COMMAND} -E env PERL5LIB=${PERL_INCLUDE})
endif()
# CMAKE_PREFIX_PATH is used to point CMake to the remaining dependencies (Boost, TBB, ...)
# We pick it from environment if it is not defined in another way
@ -50,6 +57,24 @@ if(NOT DEFINED CMAKE_PREFIX_PATH)
endif()
endif()
enable_testing ()
# WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory.
# We pick it from environment if it is not defined in another way
if(WIN32)
if(NOT DEFINED WIN10SDK_PATH)
if(DEFINED ENV{WIN10SDK_PATH})
set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
endif()
endif()
if(DEFINED WIN10SDK_PATH AND NOT EXISTS "${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h")
message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}")
message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found")
message("STL fixing by the Netfabb service will not be compiled")
unset(WIN10SDK_PATH)
endif()
endif()
add_subdirectory(xs)
get_filename_component(PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY)
@ -64,7 +89,6 @@ else ()
set(PERL_PROVE "${PERL_BIN_PATH}/prove")
endif ()
enable_testing ()
add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/xs)
add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})

View File

@ -128,6 +128,7 @@ The author of the Silk icon set is Mark James.
--post-process Generated G-code will be processed with the supplied script;
call this more than once to process through multiple scripts.
--export-svg Export a SVG file containing slices instead of G-code.
--export-png Export zipped PNG files containing slices instead of G-code.
-m, --merge If multiple files are supplied, they will be composed into a single
print rather than processed individually.
@ -385,4 +386,4 @@ If you want to change a preset file, just do
If you want to slice a file overriding an option contained in your preset file:
slic3r.pl --load config.ini --layer-height 0.25 file.stl
slic3r.pl --load config.ini --layer-height 0.25 file.stl

View File

@ -49,6 +49,7 @@ my \$defines = ' ' . Alien::wxWidgets->defines;
my \$cflags = Alien::wxWidgets->c_flags;
my \$linkflags = Alien::wxWidgets->link_flags;
my \$libraries = ' ' . Alien::wxWidgets->libraries(@components);
my \$gui_toolkit = Alien::wxWidgets->config->{toolkit};
#my @libraries = Alien::wxWidgets->link_libraries(@components);
#my @implib = Alien::wxWidgets->import_libraries(@components);
#my @shrlib = Alien::wxWidgets->shared_libraries(@components);
@ -82,6 +83,7 @@ cmake_set_var('LIBRARIES', \$libraries);
cmake_set_var('DEFINITIONS', \$defines);
#cmake_set_var('DEFINITIONS_DEBUG', );
cmake_set_var('CXX_FLAGS', \$cflags);
cmake_set_var('GUI_TOOLKIT', \$gui_toolkit);
close \$fh;
")
include(${AlienWx_TEMP_INCLUDE})
@ -96,6 +98,7 @@ if (AlienWx_DEBUG)
message(STATUS " AlienWx_DEFINITIONS = ${AlienWx_DEFINITIONS}")
message(STATUS " AlienWx_DEFINITIONS_DEBUG = ${AlienWx_DEFINITIONS_DEBUG}")
message(STATUS " AlienWx_CXX_FLAGS = ${AlienWx_CXX_FLAGS}")
message(STATUS " AlienWx_GUI_TOOLKIT = ${AlienWx_GUI_TOOLKIT}")
endif()
include(FindPackageHandleStandardArgs)

View File

@ -0,0 +1,28 @@
###############################################################################
# Find Flann
#
# This sets the following variables:
# FLANN_FOUND - True if FLANN was found.
# FLANN_INCLUDE_DIRS - Directories containing the FLANN include files.
# FLANN_LIBRARIES - Libraries needed to use FLANN.
# FLANN_DEFINITIONS - Compiler flags for FLANN.
find_package(PkgConfig)
pkg_check_modules(PC_FLANN flann)
set(FLANN_DEFINITIONS ${PC_FLANN_CFLAGS_OTHER})
find_path(FLANN_INCLUDE_DIR flann/flann.hpp
HINTS ${PC_FLANN_INCLUDEDIR} ${PC_FLANN_INCLUDE_DIRS})
find_library(FLANN_LIBRARY flann_cpp
HINTS ${PC_FLANN_LIBDIR} ${PC_FLANN_LIBRARY_DIRS})
set(FLANN_INCLUDE_DIRS ${FLANN_INCLUDE_DIR})
set(FLANN_LIBRARIES ${FLANN_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Flann DEFAULT_MSG
FLANN_LIBRARY FLANN_INCLUDE_DIR)
mark_as_advanced(FLANN_LIBRARY FLANN_INCLUDE_DIR)

View File

@ -1,18 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is autogenerated by CMake
Note: In the .in template file, the $ {}-style variables are interpreted by CMake while the $()-style variables belong to MSVC
-->
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets">
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<ExecutablePath>$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH);c:\wperl64d\bin\;</ExecutablePath>
<ExecutablePath>$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH);${PROPS_PERL_BIN_PATH}\;</ExecutablePath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
<PropertyGroup>
<LocalDebuggerCommand>C:\wperl64d\bin\perl.exe</LocalDebuggerCommand>
<LocalDebuggerCommand>${PROPS_PERL_EXECUTABLE}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>slic3r.pl</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>..\..</LocalDebuggerWorkingDirectory>
<LocalDebuggerWorkingDirectory>${PROPS_CMAKE_SOURCE_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
</Project>

View File

@ -1,8 +1,9 @@
# Building Slic3r PE on Microsoft Windows
The currently supported way of building Slic3r PE on Windows is with MS Visual Studio 2013
The currently supported way of building Slic3r PE on Windows is with CMake and MS Visual Studio 2013
using our Perl binary distribution (compiled from official Perl sources).
You can use the free [Visual Studio 2013 Community Edition](https://www.visualstudio.com/vs/older-downloads/).
CMake installer can be downloaded from [the official website](https://cmake.org/download/).
Other setups (such as mingw + Strawberry Perl) _may_ work, but we cannot guarantee this will work
and cannot provide guidance.
@ -26,8 +27,8 @@ Apart from wxWidgets and Perl, you will also need additional dependencies:
We have prepared a binary package of the listed libraries:
- 32 bit: [slic3r-destdir-32.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=slic3r-destdir-32.7z)
- 64 bit: [slic3r-destdir-64.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=slic3r-destdir-64.7z)
- 32 bit: [slic3r-destdir-32.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=2%2Fslic3r-destdir-32.7z)
- 64 bit: [slic3r-destdir-64.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=2%2Fslic3r-destdir-64.7z)
It is recommended you unpack this package into `C:\local\` as the environment
setup script expects it there.

View File

@ -37,7 +37,7 @@ if ($destdir -eq "") {
}
$BOOST = 'boost_1_63_0'
$CURL = 'curl-7.28.0'
$CURL = 'curl-7.58.0'
$TBB_SHA = 'a0dc9bf76d0120f917b641ed095360448cabc85b'
$TBB = "tbb-$TBB_SHA"

52
doc/updating/Updatig.md Normal file
View File

@ -0,0 +1,52 @@
# Slic3r PE 1.40 configuration update
Slic3r PE 1.40.0 comes with a major re-work of the way configuration presets work.
There are three new features:
+ A two-tier system of presets being divided into _System_ and _User_ groups
+ Configuration snapshots
+ Configuration updating from the internet
## System and User presets
- _System preset_: These are the presets that come with Slic3r PE installation. They come from a vendor configuration bundle (not individual files like before). They are **read-only** a user cannot modify them, but may instead create a derived User preset based on a System preset
- _User preset_: These are regular presets stored in files just like before. Additionally, they may be derived (inherited) from one of the System presets
A derived User preset keeps track of wich settings are inherited from the parent System preset and which are modified by the user. When a system preset is updated (either via installation of a new Slic3r or automatically from the internet), in a User preset the settings that are modified by the user will stay that way, while the ones that are inherited reflect the updated System preset.
This system ensures that we don't overwrite user's settings when there is an update to the built in presets.
Slic3r GUI now displays accurately which settings are inherited and which are modified.
A setting derived from a System preset is represented by green label and a locked lock icon:
![a system setting](setting_sys.png)
A settings modified in a User preset has an open lock icon:
![a user setting](setting_user.png)
Clickign the open lock icon restored the system setting.
Additionaly, any setting that is modified but not yet saved onto disk is represented by orange label and a back-arrow:
![a modified setting](setting_mod.png)
Clicking the back-arrow restores the value that was previously saved in this Preset.
## Configuration snapshots
Configuration snapshots can now be taken via the _Configuration_ menu.
A snapshot contains complete configuration from the point when the snapshot was taken.
Users may move back and forth between snapshots at will using a dialog:
![snapshots dialog](snapshots_dialog.png)
# Updating from the internet
Slic3r PE 1.40.0 checks for updates of the built-in System presets and downloads them.
The first-time configuration assistant will ask you if you want to enable this feature - it is **not** mandatory.
Updates are checked for and downloaded in the background. If there's is an update, Slic3r will prompt about it
next time it is launched, never during normal program operation. An update may be either accepted or refused.
Before any update is applied a configuration snapshot (as described above) is taken.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -7,12 +7,6 @@ use warnings;
use List::Util qw(first);
use Slic3r::Geometry::Clipper qw(union_ex diff_pl);
sub wkt {
my $self = shift;
return sprintf "POLYGON(%s)",
join ',', map "($_)", map { join ',', map "$_->[0] $_->[1]", @$_ } @$self;
}
sub offset {
my $self = shift;
return Slic3r::Geometry::Clipper::offset(\@$self, @_);

View File

@ -7,9 +7,6 @@ use File::Basename qw(basename);
use FindBin;
use List::Util qw(first);
use Slic3r::GUI::2DBed;
use Slic3r::GUI::AboutDialog;
use Slic3r::GUI::BedShapeDialog;
use Slic3r::GUI::ConfigWizard;
use Slic3r::GUI::Controller;
use Slic3r::GUI::Controller::ManualControlDialog;
use Slic3r::GUI::Controller::PrinterPanel;
@ -70,6 +67,8 @@ our $grey = Wx::Colour->new(200,200,200);
our $LANGUAGE_CHANGE_EVENT = Wx::NewEventType;
# 2) To inform about a change of Preferences.
our $PREFERENCES_EVENT = Wx::NewEventType;
# To inform AppConfig about Slic3r version available online
our $VERSION_ONLINE_EVENT = Wx::NewEventType;
sub OnInit {
my ($self) = @_;
@ -86,7 +85,9 @@ sub OnInit {
Slic3r::GUI::set_wxapp($self);
$self->{app_config} = Slic3r::GUI::AppConfig->new;
Slic3r::GUI::set_app_config($self->{app_config});
$self->{preset_bundle} = Slic3r::GUI::PresetBundle->new;
Slic3r::GUI::set_preset_bundle($self->{preset_bundle});
# 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
@ -95,28 +96,27 @@ sub OnInit {
warn $@ . "\n";
fatal_error(undef, $@);
}
my $run_wizard = ! $self->{app_config}->exists;
my $app_conf_exists = $self->{app_config}->exists;
# load settings
$self->{app_config}->load if ! $run_wizard;
$self->{app_config}->load if $app_conf_exists;
$self->{app_config}->set('version', $Slic3r::VERSION);
$self->{app_config}->save;
Slic3r::GUI::set_app_config($self->{app_config});
$self->{preset_updater} = Slic3r::PresetUpdater->new($VERSION_ONLINE_EVENT);
Slic3r::GUI::set_preset_updater($self->{preset_updater});
Slic3r::GUI::load_language();
# Suppress the '- default -' presets.
$self->{preset_bundle}->set_default_suppressed($self->{app_config}->get('no_defaults') ? 1 : 0);
eval { $self->{preset_bundle}->load_presets };
eval { $self->{preset_bundle}->load_presets($self->{app_config}); };
if ($@) {
warn $@ . "\n";
show_error(undef, $@);
}
eval { $self->{preset_bundle}->load_selections($self->{app_config}) };
$run_wizard = 1 if $self->{preset_bundle}->has_defauls_only;
Slic3r::GUI::set_preset_bundle($self->{preset_bundle});
# application frame
print STDERR "Creating main frame...\n";
Wx::Image::FindHandlerType(wxBITMAP_TYPE_PNG) || 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.
@ -127,7 +127,7 @@ sub OnInit {
);
$self->SetTopWindow($frame);
#EVT_IDLE($frame, sub {
# This makes CallAfter() work
EVT_IDLE($self->{mainframe}, sub {
while (my $cb = shift @cb) {
$cb->();
@ -135,17 +135,32 @@ sub OnInit {
$self->{app_config}->save if $self->{app_config}->dirty;
});
if ($run_wizard) {
# On OSX the UI was not initialized correctly if the wizard was called
# before the UI was up and running.
$self->CallAfter(sub {
# Run the config wizard, don't offer the "reset user profile" checkbox.
$self->{mainframe}->config_wizard(1);
});
}
# On OS X the UI tends to freeze in weird ways if modal dialogs (config wizard, update notifications, ...)
# are shown before or in the same event callback with the main frame creation.
# Therefore we schedule them for later using CallAfter.
$self->CallAfter(sub {
eval {
if (! $self->{preset_updater}->config_update()) {
$self->{mainframe}->Close;
}
};
if ($@) {
show_error(undef, $@);
$self->{mainframe}->Close;
}
});
$self->CallAfter(sub {
if (! Slic3r::GUI::config_wizard_startup($app_conf_exists)) {
# Only notify if there was not wizard so as not to bother too much ...
$self->{preset_updater}->slic3r_update_notify();
}
$self->{preset_updater}->sync($self->{preset_bundle});
});
# The following event is emited by the C++ menu implementation of application language change.
EVT_COMMAND($self, -1, $LANGUAGE_CHANGE_EVENT, sub{
print STDERR "LANGUAGE_CHANGE_EVENT\n";
$self->recreate_GUI;
});
@ -154,10 +169,20 @@ sub OnInit {
$self->update_ui_from_settings;
});
# The following event is emited by PresetUpdater (C++) to inform about
# the newer Slic3r application version avaiable online.
EVT_COMMAND($self, -1, $VERSION_ONLINE_EVENT, sub {
my ($self, $event) = @_;
my $version = $event->GetString;
$self->{app_config}->set('version_online', $version);
$self->{app_config}->save;
});
return 1;
}
sub recreate_GUI{
print STDERR "recreate_GUI\n";
my ($self) = @_;
my $topwindow = $self->GetTopWindow();
$self->{mainframe} = my $frame = Slic3r::GUI::MainFrame->new(
@ -174,22 +199,19 @@ sub recreate_GUI{
$topwindow->Destroy;
}
my $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only;
if ($run_wizard) {
# On OSX the UI was not initialized correctly if the wizard was called
# before the UI was up and running.
$self->CallAfter(sub {
# Run the config wizard, don't offer the "reset user profile" checkbox.
$self->{mainframe}->config_wizard(1);
});
}
}
EVT_IDLE($self->{mainframe}, sub {
while (my $cb = shift @cb) {
$cb->();
}
$self->{app_config}->save if $self->{app_config}->dirty;
});
sub about {
my ($self) = @_;
my $about = Slic3r::GUI::AboutDialog->new(undef);
$about->ShowModal;
$about->Destroy;
# On OSX the UI was not initialized correctly if the wizard was called
# before the UI was up and running.
$self->CallAfter(sub {
# Run the config wizard, don't offer the "reset user profile" checkbox.
Slic3r::GUI::config_wizard_startup(1);
});
}
sub system_info {
@ -201,8 +223,8 @@ sub system_info {
my $opengl_info_txt = '';
if (defined($self->{mainframe}) && defined($self->{mainframe}->{plater}) &&
defined($self->{mainframe}->{plater}->{canvas3D})) {
$opengl_info = $self->{mainframe}->{plater}->{canvas3D}->opengl_info(format => 'html');
$opengl_info_txt = $self->{mainframe}->{plater}->{canvas3D}->opengl_info;
$opengl_info = Slic3r::GUI::_3DScene::get_gl_info(1, 1);
$opengl_info_txt = Slic3r::GUI::_3DScene::get_gl_info(0, 1);
}
my $about = Slic3r::GUI::SystemInfo->new(
parent => undef,
@ -232,7 +254,7 @@ sub catch_error {
# static method accepting a wxWindow object as first parameter
sub show_error {
my ($parent, $message) = @_;
Wx::MessageDialog->new($parent, $message, 'Error', wxOK | wxICON_ERROR)->ShowModal;
Slic3r::GUI::show_error_id($parent ? $parent->GetId() : 0, $message);
}
# static method accepting a wxWindow object as first parameter

View File

@ -1,4 +1,5 @@
# Bed shape dialog
# still used by the Slic3r::GUI::Controller::ManualControlDialog Perl module.
package Slic3r::GUI::2DBed;
use strict;

File diff suppressed because it is too large Load Diff

View File

@ -1,122 +0,0 @@
package Slic3r::GUI::AboutDialog;
use strict;
use warnings;
use utf8;
use Wx qw(:font :html :misc :dialog :sizer :systemsettings :frame :id);
use Wx::Event qw(EVT_HTML_LINK_CLICKED EVT_LEFT_DOWN EVT_BUTTON);
use Wx::Print;
use Wx::Html;
use base 'Wx::Dialog';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, -1, 'About Slic3r', wxDefaultPosition, [600, 340], wxCAPTION);
$self->SetBackgroundColour(Wx::wxWHITE);
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
$self->SetSizer($hsizer);
# logo
my $logo = Slic3r::GUI::AboutDialog::Logo->new($self, -1, wxDefaultPosition, wxDefaultSize);
$logo->SetBackgroundColour(Wx::wxWHITE);
$hsizer->Add($logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30);
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
$hsizer->Add($vsizer, 1, wxEXPAND, 0);
# title
my $title = Wx::StaticText->new($self, -1, $Slic3r::FORK_NAME, wxDefaultPosition, wxDefaultSize);
my $title_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
$title_font->SetWeight(wxFONTWEIGHT_BOLD);
$title_font->SetFamily(wxFONTFAMILY_ROMAN);
$title_font->SetPointSize(24);
$title->SetFont($title_font);
$vsizer->Add($title, 0, wxALIGN_LEFT | wxTOP, 30);
# version
my $version = Wx::StaticText->new($self, -1, "Version $Slic3r::VERSION", wxDefaultPosition, wxDefaultSize);
my $version_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
$version_font->SetPointSize(&Wx::wxMSW ? 9 : 11);
$version->SetFont($version_font);
$vsizer->Add($version, 0, wxALIGN_LEFT | wxBOTTOM, 10);
# text
my $text =
'<html>' .
'<body bgcolor="#ffffff" link="#808080">' .
'<font color="#808080">' .
'Copyright &copy; 2016 Vojtech Bubnik, Prusa Research. <br />' .
'Copyright &copy; 2011-2016 Alessandro Ranellucci. <br />' .
'<a href="http://slic3r.org/">Slic3r</a> is licensed under the ' .
'<a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License, version 3</a>.' .
'<br /><br /><br />' .
'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Y. Sapir, Mike Sheldrake and numerous others. ' .
'Manual by Gary Hodgson. Inspired by the RepRap community. <br />' .
'Slic3r logo designed by Corey Daniels, <a href="http://www.famfamfam.com/lab/icons/silk/">Silk Icon Set</a> designed by Mark James. ' .
'</font>' .
'</body>' .
'</html>';
my $html = Wx::HtmlWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER);
my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
my $size = &Wx::wxMSW ? 8 : 10;
$html->SetFonts($font->GetFaceName, $font->GetFaceName, [$size, $size, $size, $size, $size, $size, $size]);
$html->SetBorders(2);
$html->SetPage($text);
$vsizer->Add($html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 20);
EVT_HTML_LINK_CLICKED($self, $html, \&link_clicked);
my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
$self->SetEscapeId(wxID_CLOSE);
EVT_BUTTON($self, wxID_CLOSE, sub {
$self->EndModal(wxID_CLOSE);
$self->Close;
});
$vsizer->Add($buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
EVT_LEFT_DOWN($self, sub { $self->Close });
EVT_LEFT_DOWN($logo, sub { $self->Close });
return $self;
}
sub link_clicked {
my ($self, $event) = @_;
Wx::LaunchDefaultBrowser($event->GetLinkInfo->GetHref);
$event->Skip(0);
}
package Slic3r::GUI::AboutDialog::Logo;
use Wx qw(:bitmap :dc);
use Wx::Event qw(EVT_PAINT);
use base 'Wx::Panel';
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{logo} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px.png"), wxBITMAP_TYPE_PNG);
$self->SetMinSize(Wx::Size->new($self->{logo}->GetWidth, $self->{logo}->GetHeight));
EVT_PAINT($self, \&repaint);
return $self;
}
sub repaint {
my ($self, $event) = @_;
my $dc = Wx::PaintDC->new($self);
$dc->SetBackgroundMode(wxTRANSPARENT);
my $size = $self->GetSize;
my $logo_w = $self->{logo}->GetWidth;
my $logo_h = $self->{logo}->GetHeight;
$dc->DrawBitmap($self->{logo}, ($size->GetWidth - $logo_w) / 2, ($size->GetHeight - $logo_h) / 2, 1);
$event->Skip;
}
1;

View File

@ -1,316 +0,0 @@
# The bed shape dialog.
# The dialog opens from Print Settins tab -> Bed Shape: Set...
package Slic3r::GUI::BedShapeDialog;
use strict;
use warnings;
use utf8;
use List::Util qw(min max);
use Slic3r::Geometry qw(X Y unscale);
use Wx qw(:dialog :id :misc :sizer :choicebook wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_CLOSE);
use base 'Wx::Dialog';
sub new {
my $class = shift;
my ($parent, $default) = @_;
my $self = $class->SUPER::new($parent, -1, "Bed Shape", wxDefaultPosition, [350,700], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
$self->{panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $default);
my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
$main_sizer->Add($panel, 1, wxEXPAND);
$main_sizer->Add($self->CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND);
$self->SetSizer($main_sizer);
$self->SetMinSize($self->GetSize);
$main_sizer->SetSizeHints($self);
# needed to actually free memory
EVT_CLOSE($self, sub {
$self->EndModal(wxID_OK);
$self->Destroy;
});
return $self;
}
sub GetValue {
my ($self) = @_;
return $self->{panel}->GetValue;
}
package Slic3r::GUI::BedShapePanel;
use List::Util qw(min max sum first);
use Scalar::Util qw(looks_like_number);
use Slic3r::Geometry qw(PI X Y unscale scaled_epsilon);
use Wx qw(:font :id :misc :sizer :choicebook :filedialog :pen :brush wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_CLOSE EVT_CHOICEBOOK_PAGE_CHANGED EVT_BUTTON);
use base 'Wx::Panel';
use constant SHAPE_RECTANGULAR => 0;
use constant SHAPE_CIRCULAR => 1;
use constant SHAPE_CUSTOM => 2;
sub new {
my $class = shift;
my ($parent, $default) = @_;
my $self = $class->SUPER::new($parent, -1);
$self->on_change(undef);
my $box = Wx::StaticBox->new($self, -1, "Shape");
my $sbsizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
# shape options
$self->{shape_options_book} = Wx::Choicebook->new($self, -1, wxDefaultPosition, [300,-1], wxCHB_TOP);
$sbsizer->Add($self->{shape_options_book});
$self->{optgroups} = [];
{
my $optgroup = $self->_init_shape_options_page('Rectangular');
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
opt_id => 'rect_size',
type => 'point',
label => 'Size',
tooltip => 'Size in X and Y of the rectangular plate.',
default => [200,200],
));
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
opt_id => 'rect_origin',
type => 'point',
label => 'Origin',
tooltip => 'Distance of the 0,0 G-code coordinate from the front left corner of the rectangle.',
default => [0,0],
));
}
{
my $optgroup = $self->_init_shape_options_page('Circular');
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
opt_id => 'diameter',
type => 'f',
label => 'Diameter',
tooltip => 'Diameter of the print bed. It is assumed that origin (0,0) is located in the center.',
sidetext => 'mm',
default => 200,
));
}
{
my $optgroup = $self->_init_shape_options_page('Custom');
$optgroup->append_line(Slic3r::GUI::OptionsGroup::Line->new(
full_width => 1,
widget => sub {
my ($parent) = @_;
my $btn = Wx::Button->new($parent, -1, "Load shape from STL...", wxDefaultPosition, wxDefaultSize);
EVT_BUTTON($self, $btn, sub { $self->_load_stl });
return $btn;
}
));
}
EVT_CHOICEBOOK_PAGE_CHANGED($self, -1, sub {
$self->_update_shape;
});
# right pane with preview canvas
my $canvas = $self->{canvas} = Slic3r::GUI::2DBed->new($self);
# main sizer
my $top_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$top_sizer->Add($sbsizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
$top_sizer->Add($canvas, 1, wxEXPAND | wxALL, 10) if $canvas;
$self->SetSizerAndFit($top_sizer);
$self->_set_shape($default);
$self->_update_preview;
return $self;
}
sub on_change {
my ($self, $cb) = @_;
$self->{on_change} = $cb // sub {};
}
# Called from the constructor.
# Set the initial bed shape from a list of points.
# Deduce the bed shape type (rect, circle, custom)
# This routine shall be smart enough if the user messes up
# with the list of points in the ini file directly.
sub _set_shape {
my ($self, $points) = @_;
# is this a rectangle?
if (@$points == 4) {
my $polygon = Slic3r::Polygon->new_scale(@$points);
my $lines = $polygon->lines;
if ($lines->[0]->parallel_to_line($lines->[2]) && $lines->[1]->parallel_to_line($lines->[3])) {
# okay, it's a rectangle
# find origin
# the || 0 hack prevents "-0" which might confuse the user
my $x_min = min(map $_->[X], @$points) || 0;
my $x_max = max(map $_->[X], @$points) || 0;
my $y_min = min(map $_->[Y], @$points) || 0;
my $y_max = max(map $_->[Y], @$points) || 0;
my $origin = [-$x_min, -$y_min];
$self->{shape_options_book}->SetSelection(SHAPE_RECTANGULAR);
my $optgroup = $self->{optgroups}[SHAPE_RECTANGULAR];
$optgroup->set_value('rect_size', [ $x_max-$x_min, $y_max-$y_min ]);
$optgroup->set_value('rect_origin', $origin);
$self->_update_shape;
return;
}
}
# is this a circle?
{
# Analyze the array of points. Do they reside on a circle?
my $polygon = Slic3r::Polygon->new_scale(@$points);
my $center = $polygon->bounding_box->center;
my @vertex_distances = map $center->distance_to($_), @$polygon;
my $avg_dist = sum(@vertex_distances)/@vertex_distances;
if (!defined first { abs($_ - $avg_dist) > 10*scaled_epsilon } @vertex_distances) {
# all vertices are equidistant to center
$self->{shape_options_book}->SetSelection(SHAPE_CIRCULAR);
my $optgroup = $self->{optgroups}[SHAPE_CIRCULAR];
$optgroup->set_value('diameter', sprintf("%.0f", unscale($avg_dist*2)));
$self->_update_shape;
return;
}
}
if (@$points < 3) {
# Invalid polygon. Revert to default bed dimensions.
$self->{shape_options_book}->SetSelection(SHAPE_RECTANGULAR);
my $optgroup = $self->{optgroups}[SHAPE_RECTANGULAR];
$optgroup->set_value('rect_size', [200, 200]);
$optgroup->set_value('rect_origin', [0, 0]);
$self->_update_shape;
return;
}
# This is a custom bed shape, use the polygon provided.
$self->{shape_options_book}->SetSelection(SHAPE_CUSTOM);
# Copy the polygon to the canvas, make a copy of the array.
$self->{canvas}->bed_shape([@$points]);
$self->_update_shape;
}
# Update the bed shape from the dialog fields.
sub _update_shape {
my ($self) = @_;
my $page_idx = $self->{shape_options_book}->GetSelection;
if ($page_idx == SHAPE_RECTANGULAR) {
my $rect_size = $self->{optgroups}[SHAPE_RECTANGULAR]->get_value('rect_size');
my $rect_origin = $self->{optgroups}[SHAPE_RECTANGULAR]->get_value('rect_origin');
my ($x, $y) = @$rect_size;
return if !looks_like_number($x) || !looks_like_number($y); # empty strings or '-' or other things
return if !$x || !$y or $x == 0 or $y == 0;
my ($x0, $y0) = (0,0);
my ($x1, $y1) = ($x ,$y);
{
my ($dx, $dy) = @$rect_origin;
return if !looks_like_number($dx) || !looks_like_number($dy); # empty strings or '-' or other things
$x0 -= $dx;
$x1 -= $dx;
$y0 -= $dy;
$y1 -= $dy;
}
$self->{canvas}->bed_shape([
[$x0,$y0],
[$x1,$y0],
[$x1,$y1],
[$x0,$y1],
]);
} elsif ($page_idx == SHAPE_CIRCULAR) {
my $diameter = $self->{optgroups}[SHAPE_CIRCULAR]->get_value('diameter');
return if !$diameter or $diameter == 0;
my $r = $diameter/2;
my $twopi = 2*PI;
my $edges = 60;
my $polygon = Slic3r::Polygon->new_scale(
map [ $r * cos $_, $r * sin $_ ],
map { $twopi/$edges*$_ } 1..$edges
);
$self->{canvas}->bed_shape([
map [ unscale($_->x), unscale($_->y) ], @$polygon #))
]);
}
$self->{on_change}->();
$self->_update_preview;
}
sub _update_preview {
my ($self) = @_;
$self->{canvas}->Refresh if $self->{canvas};
$self->Refresh;
}
# Called from the constructor.
# Create a panel for a rectangular / circular / custom bed shape.
sub _init_shape_options_page {
my ($self, $title) = @_;
my $panel = Wx::Panel->new($self->{shape_options_book});
my $optgroup;
push @{$self->{optgroups}}, $optgroup = Slic3r::GUI::OptionsGroup->new(
parent => $panel,
title => 'Settings',
label_width => 100,
on_change => sub {
my ($opt_id) = @_;
#$self->{"_$opt_id"} = $optgroup->get_value($opt_id);
$self->_update_shape;
},
);
$panel->SetSizerAndFit($optgroup->sizer);
$self->{shape_options_book}->AddPage($panel, $title);
return $optgroup;
}
# Loads an stl file, projects it to the XY plane and calculates a polygon.
sub _load_stl {
my ($self) = @_;
my $dialog = Wx::FileDialog->new($self, 'Choose a file to import bed shape from (STL/OBJ/AMF/PRUSA):', "", "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if ($dialog->ShowModal != wxID_OK) {
$dialog->Destroy;
return;
}
my $input_file = $dialog->GetPaths;
$dialog->Destroy;
my $model = Slic3r::Model->read_from_file($input_file);
my $mesh = $model->mesh;
my $expolygons = $mesh->horizontal_projection;
if (@$expolygons == 0) {
Slic3r::GUI::show_error($self, "The selected file contains no geometry.");
return;
}
if (@$expolygons > 1) {
Slic3r::GUI::show_error($self, "The selected file contains several disjoint areas. This is not supported.");
return;
}
my $polygon = $expolygons->[0]->contour;
$self->{canvas}->bed_shape([ map [ unscale($_->x), unscale($_->y) ], @$polygon ]);
$self->_update_preview();
}
# Returns the resulting bed shape polygon. This value will be stored to the ini file.
sub GetValue {
my ($self) = @_;
return $self->{canvas}->bed_shape;
}
1;

View File

@ -1,458 +0,0 @@
# The config wizard is executed when the Slic3r is first started.
# The wizard helps the user to specify the 3D printer properties.
package Slic3r::GUI::ConfigWizard;
use strict;
use warnings;
use utf8;
use Wx;
use base 'Wx::Wizard';
# adhere to various human interface guidelines
our $wizard = 'Wizard';
$wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK;
sub new {
my ($class, $parent, $presets, $fresh_start) = @_;
my $self = $class->SUPER::new($parent, -1, "Configuration $wizard");
# initialize an empty repository
$self->{config} = Slic3r::Config->new;
my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self, $fresh_start);
$self->add_page($welcome_page);
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self));
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self));
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Nozzle->new($self));
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Filament->new($self));
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Temperature->new($self));
$self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self));
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Finished->new($self));
$_->build_index for @{$self->{pages}};
$welcome_page->set_selection_presets([@{$presets}, 'Other']);
return $self;
}
sub add_page {
my ($self, $page) = @_;
my $n = push @{$self->{pages}}, $page;
# add first page to the page area sizer
$self->GetPageAreaSizer->Add($page) if $n == 1;
# link pages
$self->{pages}[$n-2]->set_next_page($page) if $n >= 2;
$page->set_previous_page($self->{pages}[$n-2]) if $n >= 2;
}
sub run {
my ($self) = @_;
my $result;
if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) {
my $preset_name = $self->{pages}[0]->{preset_name};
$result = {
preset_name => $preset_name,
reset_user_profile => $self->{pages}[0]->{reset_user_profile}
};
if ($preset_name eq 'Other') {
# it would be cleaner to have these defined inside each page class,
# in some event getting called before leaving the page
# set first_layer_height + layer_height based on nozzle_diameter
my $nozzle = $self->{config}->nozzle_diameter;
$self->{config}->set('first_layer_height', $nozzle->[0]);
$self->{config}->set('layer_height', $nozzle->[0] - 0.1);
# set first_layer_temperature to temperature + 5
$self->{config}->set('first_layer_temperature', [$self->{config}->temperature->[0] + 5]);
# set first_layer_bed_temperature to temperature + 5
$self->{config}->set('first_layer_bed_temperature',
[ ($self->{config}->bed_temperature->[0] > 0) ? ($self->{config}->bed_temperature->[0] + 5) : 0 ]);
$result->{config} = $self->{config};
}
}
$self->Destroy;
return $result;
}
package Slic3r::GUI::ConfigWizard::Index;
use Wx qw(:bitmap :dc :font :misc :sizer :systemsettings :window);
use Wx::Event qw(EVT_ERASE_BACKGROUND EVT_PAINT);
use base 'Wx::Panel';
sub new {
my $class = shift;
my ($parent, $title) = @_;
my $self = $class->SUPER::new($parent);
push @{$self->{titles}}, $title;
$self->{own_index} = 0;
$self->{bullets}->{before} = Wx::Bitmap->new(Slic3r::var("bullet_black.png"), wxBITMAP_TYPE_PNG);
$self->{bullets}->{own} = Wx::Bitmap->new(Slic3r::var("bullet_blue.png"), wxBITMAP_TYPE_PNG);
$self->{bullets}->{after} = Wx::Bitmap->new(Slic3r::var("bullet_white.png"), wxBITMAP_TYPE_PNG);
$self->{background} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px_transparent.png"), wxBITMAP_TYPE_PNG);
$self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight));
EVT_PAINT($self, \&repaint);
return $self;
}
sub repaint {
my ($self, $event) = @_;
my $size = $self->GetClientSize;
my $gap = 5;
my $dc = Wx::PaintDC->new($self);
$dc->SetBackgroundMode(wxTRANSPARENT);
$dc->SetFont($self->GetFont);
$dc->SetTextForeground($self->GetForegroundColour);
my $background_h = $self->{background}->GetHeight;
my $background_w = $self->{background}->GetWidth;
$dc->DrawBitmap($self->{background}, ($size->GetWidth - $background_w) / 2, ($size->GetHeight - $background_h) / 2, 1);
my $label_h = $self->{bullets}->{own}->GetHeight;
$label_h = $dc->GetCharHeight if $dc->GetCharHeight > $label_h;
my $label_w = $size->GetWidth;
my $i = 0;
foreach (@{$self->{titles}}) {
my $bullet = $self->{bullets}->{own};
$bullet = $self->{bullets}->{before} if $i < $self->{own_index};
$bullet = $self->{bullets}->{after} if $i > $self->{own_index};
$dc->SetTextForeground(Wx::Colour->new(128, 128, 128)) if $i > $self->{own_index};
$dc->DrawLabel($_, $bullet, Wx::Rect->new(0, $i * ($label_h + $gap), $label_w, $label_h));
# Only show the first bullet if this is the only wizard page to be displayed.
last if $i == 0 && $self->{just_welcome};
$i++;
}
$event->Skip;
}
sub prepend_title {
my $self = shift;
my ($title) = @_;
unshift @{$self->{titles}}, $title;
$self->{own_index}++;
$self->Refresh;
}
sub append_title {
my $self = shift;
my ($title) = @_;
push @{$self->{titles}}, $title;
$self->Refresh;
}
package Slic3r::GUI::ConfigWizard::Page;
use Wx qw(:font :misc :sizer :staticline :systemsettings);
use base 'Wx::WizardPage';
sub new {
my $class = shift;
my ($parent, $title, $short_title) = @_;
my $self = $class->SUPER::new($parent);
my $sizer = Wx::FlexGridSizer->new(0, 2, 10, 10);
$sizer->AddGrowableCol(1, 1);
$sizer->AddGrowableRow(1, 1);
$sizer->AddStretchSpacer(0);
$self->SetSizer($sizer);
# title
my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
$bold_font->SetWeight(wxFONTWEIGHT_BOLD);
$bold_font->SetPointSize(14);
$text->SetFont($bold_font);
$sizer->Add($text, 0, wxALIGN_LEFT, 0);
# index
$self->{short_title} = $short_title ? $short_title : $title;
$self->{index} = Slic3r::GUI::ConfigWizard::Index->new($self, $self->{short_title});
$sizer->Add($self->{index}, 1, wxEXPAND | wxTOP | wxRIGHT, 10);
# contents
$self->{width} = 430;
$self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL);
$sizer->Add($self->{vsizer}, 1);
return $self;
}
sub append_text {
my $self = shift;
my ($text) = @_;
my $para = Wx::StaticText->new($self, -1, $text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$para->Wrap($self->{width});
$para->SetMinSize([$self->{width}, -1]);
$self->{vsizer}->Add($para, 0, wxALIGN_LEFT | wxTOP | wxBOTTOM, 10);
}
sub append_option {
my $self = shift;
my ($full_key) = @_;
# populate repository with the factory default
my ($opt_key, $opt_index) = split /#/, $full_key, 2;
$self->config->apply(Slic3r::Config::new_from_defaults_keys([$opt_key]));
# draw the control
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
parent => $self,
title => '',
config => $self->config,
full_labels => 1,
);
$optgroup->append_single_option_line($opt_key, $opt_index);
$self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
}
sub append_panel {
my ($self, $panel) = @_;
$self->{vsizer}->Add($panel, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
}
sub set_previous_page {
my $self = shift;
my ($previous_page) = @_;
$self->{previous_page} = $previous_page;
}
sub GetPrev {
my $self = shift;
return $self->{previous_page};
}
sub set_next_page {
my $self = shift;
my ($next_page) = @_;
$self->{next_page} = $next_page;
}
sub GetNext {
my $self = shift;
return $self->{next_page};
}
sub get_short_title {
my $self = shift;
return $self->{short_title};
}
sub build_index {
my $self = shift;
my $page = $self;
$self->{index}->prepend_title($page->get_short_title) while ($page = $page->GetPrev);
$page = $self;
$self->{index}->append_title($page->get_short_title) while ($page = $page->GetNext);
}
sub config {
my ($self) = @_;
return $self->GetParent->{config};
}
package Slic3r::GUI::ConfigWizard::Page::Welcome;
use base 'Slic3r::GUI::ConfigWizard::Page';
use Wx qw(:misc :sizer wxID_FORWARD);
use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE EVT_CHECKBOX);
sub new {
my ($class, $parent, $fresh_start) = @_;
my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome');
$self->{full_wizard_workflow} = 1;
$self->{reset_user_profile} = 0;
# Test for the existence of the old config path.
my $message_has_legacy;
{
my $datadir = Slic3r::data_dir;
if ($datadir =~ /Slic3rPE/) {
# Check for existence of the legacy Slic3r directory.
my $datadir_legacy = substr $datadir, 0, -2;
my $dir_enc = Slic3r::encode_path($datadir_legacy);
if (-e $dir_enc && -d $dir_enc &&
-e ($dir_enc . '/print') && -d ($dir_enc . '/print') &&
-e ($dir_enc . '/filament') && -d ($dir_enc . '/filament') &&
-e ($dir_enc . '/printer') && -d ($dir_enc . '/printer') &&
-e ($dir_enc . '/slic3r.ini')) {
$message_has_legacy = "Starting with Slic3r 1.38.4, the user profile directory has been renamed to $datadir. You may consider closing Slic3r and renaming $datadir_legacy to $datadir.";
}
}
}
$self->append_text('Hello, welcome to Slic3r Prusa Edition! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.');
$self->append_text('Please select your printer vendor and printer type. If your printer is not listed, you may try your luck and select a similar one. If you select "Other", this ' . lc($wizard) . ' will let you set the basic 3D printer parameters.');
$self->append_text($message_has_legacy) if defined $message_has_legacy;
# To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.');
$self->append_text('If you received a configuration file or a config bundle from your 3D printer vendor, cancel this '.lc($wizard).' and use the "File->Load Config" or "File->Load Config Bundle" menu.');
$self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []);
$self->{vsizer}->Add($choice, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
if (! $fresh_start) {
$self->{reset_checkbox} = Wx::CheckBox->new($self, -1, "Reset user profile, install from scratch");
$self->{vsizer}->Add($self->{reset_checkbox}, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
}
EVT_CHOICE($parent, $choice, sub {
my $sel = $self->{choice}->GetStringSelection;
$self->{preset_name} = $sel;
$self->set_full_wizard_workflow(($sel eq 'Other') || ($sel eq ''));
});
if (! $fresh_start) {
EVT_CHECKBOX($self, $self->{reset_checkbox}, sub {
$self->{reset_user_profile} = $self->{reset_checkbox}->GetValue();
});
}
EVT_ACTIVATE($parent, sub {
$self->set_full_wizard_workflow($self->{preset_name} eq 'Other');
});
return $self;
}
sub set_full_wizard_workflow {
my ($self, $full_workflow) = @_;
$self->{full_wizard_workflow} = $full_workflow;
$self->{index}->{just_welcome} = !$full_workflow;
$self->{index}->Refresh;
my $next_button = $self->GetParent->FindWindow(wxID_FORWARD);
$next_button->SetLabel($full_workflow ? "&Next >" : "&Finish");
}
# Set the preset names, select the first item.
sub set_selection_presets {
my ($self, $names) = @_;
$self->{choice}->Append($names);
$self->{choice}->SetSelection(0);
$self->{preset_name} = $names->[0];
}
sub GetNext {
my $self = shift;
return $self->{full_wizard_workflow} ? $self->{next_page} : undef;
}
package Slic3r::GUI::ConfigWizard::Page::Firmware;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Firmware Type');
$self->append_text('Choose the type of firmware used by your printer, then click Next.');
$self->append_option('gcode_flavor');
return $self;
}
package Slic3r::GUI::ConfigWizard::Page::Bed;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Bed Size');
$self->append_text('Set the shape of your printer\'s bed, then click Next.');
$self->config->apply(Slic3r::Config::new_from_defaults_keys(['bed_shape']));
$self->{bed_shape_panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $self->config->bed_shape);
$self->{bed_shape_panel}->on_change(sub {
$self->config->set('bed_shape', $self->{bed_shape_panel}->GetValue);
});
$self->append_panel($self->{bed_shape_panel});
return $self;
}
package Slic3r::GUI::ConfigWizard::Page::Nozzle;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Nozzle Diameter');
$self->append_text('Enter the diameter of your printer\'s hot end nozzle, then click Next.');
$self->append_option('nozzle_diameter#0');
return $self;
}
package Slic3r::GUI::ConfigWizard::Page::Filament;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Filament Diameter');
$self->append_text('Enter the diameter of your filament, then click Next.');
$self->append_text('Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.');
$self->append_option('filament_diameter#0');
return $self;
}
package Slic3r::GUI::ConfigWizard::Page::Temperature;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Extrusion Temperature');
$self->append_text('Enter the temperature needed for extruding your filament, then click Next.');
$self->append_text('A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS.');
$self->append_option('temperature#0');
return $self;
}
package Slic3r::GUI::ConfigWizard::Page::BedTemperature;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Bed Temperature');
$self->append_text('Enter the bed temperature needed for getting your filament to stick to your heated bed, then click Next.');
$self->append_text('A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed.');
$self->append_option('bed_temperature#0');
return $self;
}
package Slic3r::GUI::ConfigWizard::Page::Finished;
use base 'Slic3r::GUI::ConfigWizard::Page';
sub new {
my $class = shift;
my ($parent) = @_;
my $self = $class->SUPER::new($parent, 'Congratulations!', 'Finish');
$self->append_text("You have successfully completed the Slic3r Configuration $wizard. " .
'Slic3r is now configured for your printer and filament.');
$self->append_text('To close this '.lc($wizard).' and apply the newly created configuration, click Finish.');
return $self;
}
1;

View File

@ -7,7 +7,7 @@ use strict;
use warnings;
use utf8;
use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button :icon :dialog);
use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button :icon :dialog wxBORDER_NONE);
use Wx::Event qw(EVT_CLOSE EVT_LEFT_DOWN EVT_MENU);
use base qw(Wx::ScrolledWindow Class::Accessor);
use List::Util qw(first);
@ -34,7 +34,7 @@ sub new {
# button for adding new printer panels
{
my $btn = $self->{btn_add} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG),
wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
$btn->SetToolTipString("Add printer…")
if $btn->can('SetToolTipString');

View File

@ -9,7 +9,7 @@ use File::Basename qw(basename dirname);
use FindBin;
use List::Util qw(min first);
use Slic3r::Geometry qw(X Y);
use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog
use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog :dirdialog
:font :icon wxTheApp);
use Wx::Event qw(EVT_CLOSE EVT_COMMAND EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED);
use base 'Wx::Frame';
@ -19,6 +19,7 @@ use Wx::Locale gettext => 'L';
our $qs_last_input_file;
our $qs_last_output_file;
our $last_config;
our $appController;
# Events to be sent from a C++ Tab implementation:
# 1) To inform about a change of a configuration value.
@ -29,12 +30,23 @@ our $PRESETS_CHANGED_EVENT = Wx::NewEventType;
our $PROGRESS_BAR_EVENT = Wx::NewEventType;
# 4) To display an error dialog box from a thread on the UI thread.
our $ERROR_EVENT = Wx::NewEventType;
# 5) To inform about a change of object selection
our $OBJECT_SELECTION_CHANGED_EVENT = Wx::NewEventType;
# 6) To inform about a change of object settings
our $OBJECT_SETTINGS_CHANGED_EVENT = Wx::NewEventType;
# 7) To inform about a remove of object
our $OBJECT_REMOVE_EVENT = Wx::NewEventType;
# 8) To inform about a update of the scene
our $UPDATE_SCENE_EVENT = Wx::NewEventType;
sub new {
my ($class, %params) = @_;
my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE);
Slic3r::GUI::set_main_frame($self);
Slic3r::GUI::set_main_frame($self);
$appController = Slic3r::AppController->new();
if ($^O eq 'MSWin32') {
# Load the icon either from the exe, or from the ico file.
my $iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe';
@ -43,7 +55,7 @@ sub new {
} else {
$self->SetIcon(Wx::Icon->new(Slic3r::var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG));
}
# store input params
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
$self->{no_controller} = $params{no_controller};
@ -52,11 +64,6 @@ sub new {
$self->{lang_ch_event} = $params{lang_ch_event};
$self->{preferences_event} = $params{preferences_event};
# initialize status bar
$self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, -1);
$self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"));
$self->SetStatusBar($self->{statusbar});
# initialize tabpanel and menubar
$self->_init_tabpanel;
$self->_init_menubar;
@ -65,9 +72,21 @@ sub new {
# SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values
# (SetAutoPop is not available on GTK.)
eval { Wx::ToolTip::SetAutoPop(32767) };
$self->{loaded} = 1;
# initialize status bar
$self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new();
$self->{statusbar}->Embed;
$self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"));
# Make the global status bar and its progress indicator available in C++
$appController->set_global_progress_indicator($self->{statusbar});
$appController->set_model($self->{plater}->{model});
$appController->set_print($self->{plater}->{print});
$self->{plater}->{appController} = $appController;
$self->{loaded} = 1;
# initialize layout
{
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
@ -85,7 +104,7 @@ sub new {
# declare events
EVT_CLOSE($self, sub {
my (undef, $event) = @_;
if ($event->CanVeto && !$self->check_unsaved_changes) {
if ($event->CanVeto && !Slic3r::GUI::check_unsaved_changes) {
$event->Veto;
return;
}
@ -94,12 +113,17 @@ sub new {
# 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;
$self->{plater}->{print} = undef if($self->{plater});
Slic3r::GUI::_3DScene::remove_all_canvases();
Slic3r::GUI::deregister_on_request_update_callback();
# propagate event
$event->Skip;
});
$self->update_ui_from_settings;
Slic3r::GUI::update_mode();
return $self;
}
@ -112,10 +136,19 @@ sub _init_tabpanel {
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub {
my $panel = $self->{tabpanel}->GetCurrentPage;
$panel->OnActivate if $panel->can('OnActivate');
for my $tab_name (qw(print filament printer)) {
Slic3r::GUI::get_preset_tab("$tab_name")->OnActivate if ("$tab_name" eq $panel->GetName);
}
});
if (!$self->{no_plater}) {
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), L("Plater"));
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel,
event_object_selection_changed => $OBJECT_SELECTION_CHANGED_EVENT,
event_object_settings_changed => $OBJECT_SETTINGS_CHANGED_EVENT,
event_remove_object => $OBJECT_REMOVE_EVENT,
event_update_scene => $UPDATE_SCENE_EVENT,
), L("Plater"));
if (!$self->{no_controller}) {
$panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller"));
}
@ -136,6 +169,10 @@ sub _init_tabpanel {
my $value = $event->GetInt();
$self->{plater}->on_extruders_change($value);
}
if ($opt_key eq 'printer_technology'){
my $value = $event->GetInt();# 0 ~ "ptFFF"; 1 ~ "ptSLA"
$self->{plater}->show_preset_comboboxes($value);
}
}
# don't save while loading for the first time
$self->config->save($Slic3r::GUI::autosave) if $Slic3r::GUI::autosave && $self->{loaded};
@ -148,14 +185,15 @@ sub _init_tabpanel {
my $tab = Slic3r::GUI::get_preset_tab($tab_name);
if ($self->{plater}) {
# Update preset combo boxes (Print settings, Filament, Printer) from their respective tabs.
# Update preset combo boxes (Print settings, Filament, Material, Printer) from their respective tabs.
my $presets = $tab->get_presets;
if (defined $presets){
my $reload_dependent_tabs = $tab->get_dependent_tabs;
$self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets);
$self->{plater}->{"selected_item_$tab_name"} = $tab->get_selected_preset_item;
if ($tab_name eq 'printer') {
# Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
for my $tab_name_other (qw(print filament)) {
for my $tab_name_other (qw(print filament sla_material)) {
# If the printer tells us that the print or filament preset has been switched or invalidated,
# refresh the print or filament tab page. Otherwise just refresh the combo box.
my $update_action = ($reload_dependent_tabs && (first { $_ eq $tab_name_other } (@{$reload_dependent_tabs})))
@ -169,9 +207,43 @@ sub _init_tabpanel {
}
}
});
# The following event is emited by the C++ Tab implementation on object selection change.
EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub {
my ($self, $event) = @_;
my $obj_idx = $event->GetId;
my $child = $event->GetInt == 1 ? 1 : undef;
$self->{plater}->select_object($obj_idx < 0 ? undef: $obj_idx, $child);
$self->{plater}->item_changed_selection($obj_idx);
});
# The following event is emited by the C++ GUI implementation on object settings change.
EVT_COMMAND($self, -1, $OBJECT_SETTINGS_CHANGED_EVENT, sub {
my ($self, $event) = @_;
my $line = $event->GetString;
my ($obj_idx, $parts_changed, $part_settings_changed) = split('',$line);
$self->{plater}->changed_object_settings($obj_idx, $parts_changed, $part_settings_changed);
});
# The following event is emited by the C++ GUI implementation on object remove.
EVT_COMMAND($self, -1, $OBJECT_REMOVE_EVENT, sub {
my ($self, $event) = @_;
$self->{plater}->remove();
});
# The following event is emited by the C++ GUI implementation on extruder change for object.
EVT_COMMAND($self, -1, $UPDATE_SCENE_EVENT, sub {
my ($self, $event) = @_;
$self->{plater}->update();
});
Slic3r::GUI::create_preset_tabs($self->{no_controller}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT);
$self->{options_tabs} = {};
for my $tab_name (qw(print filament printer)) {
for my $tab_name (qw(print filament sla_material printer)) {
$self->{options_tabs}{$tab_name} = Slic3r::GUI::get_preset_tab("$tab_name");
}
@ -201,8 +273,14 @@ sub _init_tabpanel {
# load initial 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}));
if (defined $full_config->nozzle_diameter){ # nozzle_diameter is undefined when SLA printer is selected
$self->{plater}->on_extruders_change(int(@{$full_config->nozzle_diameter}));
}
# Show correct preset comboboxes according to the printer_technology
$self->{plater}->show_preset_comboboxes(($full_config->printer_technology eq "FFF") ? 0 : 1);
}
}
@ -212,7 +290,7 @@ sub _init_menubar {
# File menu
my $fileMenu = Wx::Menu->new;
{
wxTheApp->append_menu_item($fileMenu, L("Open STL/OBJ/AMF…\tCtrl+O"), L('Open a model'), sub {
wxTheApp->append_menu_item($fileMenu, L("Open STL/OBJ/AMF/3MF…\tCtrl+O"), L('Open a model'), sub {
$self->{plater}->add if $self->{plater};
}, undef, undef); #'brick_add.png');
$self->_append_menu_item($fileMenu, L("&Load Config…\tCtrl+L"), L('Load exported configuration file'), sub {
@ -251,6 +329,9 @@ sub _init_menubar {
$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->_append_menu_item($fileMenu, L("Slice to PNG…"), L('Slice file to a set of PNG files'), sub {
$self->slice_to_png; #$self->quick_slice(save_as => 0, export_png => 1);
}, undef, 'shape_handles.png');
$self->{menu_item_reslice_now} = $self->_append_menu_item(
$fileMenu, L("(&Re)Slice Now\tCtrl+S"), L('Start new slicing process'),
sub { $self->reslice_now; }, undef, 'shape_handles.png');
@ -259,12 +340,6 @@ sub _init_menubar {
$self->repair_stl;
}, undef, 'wrench.png');
$fileMenu->AppendSeparator();
# Cmd+, is standard on OS X - what about other operating systems?
$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, L("&Quit"), L('Quit Slic3r'), sub {
$self->Close(0);
}, wxID_EXIT);
@ -341,11 +416,6 @@ sub _init_menubar {
# Help menu
my $helpMenu = Wx::Menu->new;
{
$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, L("Prusa 3D Drivers"), L('Open the Prusa3D drivers download page in your browser'), sub {
Wx::LaunchDefaultBrowser('http://www.prusa3d.com/drivers/');
});
@ -366,11 +436,14 @@ sub _init_menubar {
$self->_append_menu_item($helpMenu, L("System Info"), L('Show system information'), sub {
wxTheApp->system_info;
});
$self->_append_menu_item($helpMenu, L("Show &Configuration Folder"), L('Show user configuration folder (datadir)'), sub {
Slic3r::GUI::desktop_open_datadir_folder();
});
$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, L("&About Slic3r"), L('Show about dialog'), sub {
wxTheApp->about;
Slic3r::GUI::about;
});
}
@ -384,11 +457,9 @@ sub _init_menubar {
$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)
Slic3r::GUI::add_debug_menu($menubar, $self->{lang_ch_event});
# Add additional menus from C++
Slic3r::GUI::add_menus($menubar, $self->{preferences_event}, $self->{lang_ch_event});
$menubar->Append($helpMenu, L("&Help"));
# Add an optional debug menu. In production code, the add_debug_menu() call should do nothing.
$self->SetMenuBar($menubar);
}
}
@ -406,10 +477,18 @@ sub on_plater_selection_changed {
for $self->{object_menu}->GetMenuItems;
}
sub slice_to_png {
my $self = shift;
$self->{plater}->stop_background_process;
$self->{plater}->async_apply_config;
$appController->print_ctl()->slice_to_png();
}
# To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG".
sub quick_slice {
my ($self, %params) = @_;
my $progress_dialog;
eval {
# validate configuration
my $config = wxTheApp->{preset_bundle}->full_config();
@ -482,12 +561,25 @@ sub quick_slice {
$qs_last_output_file = $output_file unless $params{export_svg};
wxTheApp->{app_config}->update_last_output_dir(dirname($output_file));
$dlg->Destroy;
} elsif($params{export_png}) {
$output_file = $sprint->output_filepath;
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/.zip/;
# my $dlg = Wx::DirDialog->new($self, L('Choose output directory'));
my $dlg = Wx::FileDialog->new($self, L('Save zip file as:'),
wxTheApp->{app_config}->get_last_output_dir(dirname($output_file)),
basename($output_file), '*.zip', wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ($dlg->ShowModal != wxID_OK) {
$dlg->Destroy;
return;
}
$output_file = $dlg->GetPath;
$dlg->Destroy;
}
# show processbar dialog
$self->{progress_dialog} = Wx::ProgressDialog->new(L('Slicing…'), L("Processing ").$input_file_basename."…",
100, $self, 0);
$self->{progress_dialog}->Pulse;
$progress_dialog = Wx::ProgressDialog->new(L('Slicing…'), L("Processing ").$input_file_basename."…",
100, $self, 4);
$progress_dialog->Pulse;
{
my @warnings = ();
@ -496,7 +588,11 @@ sub quick_slice {
$sprint->output_file($output_file);
if ($params{export_svg}) {
$sprint->export_svg;
} else {
}
elsif($params{export_png}) {
$sprint->export_png;
}
else {
$sprint->export_gcode;
}
Slic3r::GUI::warning_catcher($self)->($_) for @warnings;
@ -578,7 +674,7 @@ sub export_config {
sub load_config_file {
my ($self, $file) = @_;
if (!$file) {
return unless $self->check_unsaved_changes;
return unless Slic3r::GUI::check_unsaved_changes;
my $dlg = Wx::FileDialog->new($self, L('Select configuration to load:'),
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
"config.ini",
@ -597,7 +693,7 @@ sub load_config_file {
sub export_configbundle {
my ($self) = @_;
return unless $self->check_unsaved_changes;
return unless Slic3r::GUI::check_unsaved_changes;
# validate current configuration in case it's dirty
eval { wxTheApp->{preset_bundle}->full_config->validate; };
Slic3r::GUI::catch_error($self) and return;
@ -621,7 +717,7 @@ sub export_configbundle {
# but that behavior was not documented and likely buggy.
sub load_configbundle {
my ($self, $file, $reset_user_profile) = @_;
return unless $self->check_unsaved_changes;
return unless Slic3r::GUI::check_unsaved_changes;
if (!$file) {
my $dlg = Wx::FileDialog->new($self, L('Select configuration to load:'),
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
@ -655,64 +751,6 @@ sub load_config {
$self->{plater}->on_config_change($config) if $self->{plater};
}
sub config_wizard {
my ($self, $fresh_start) = @_;
# Exit wizard if there are unsaved changes and the user cancels the action.
return unless $self->check_unsaved_changes;
# Enumerate the profiles bundled with the Slic3r installation under resources/profiles.
my $directory = Slic3r::resources_dir() . "/profiles";
my @profiles = ();
if (opendir(DIR, Slic3r::encode_path($directory))) {
while (my $file = readdir(DIR)) {
if ($file =~ /\.ini$/) {
$file =~ s/\.ini$//;
push @profiles, Slic3r::decode_path($file);
}
}
closedir(DIR);
}
# Open the wizard.
if (my $result = Slic3r::GUI::ConfigWizard->new($self, \@profiles, $fresh_start)->run) {
eval {
if ($result->{reset_user_profile}) {
wxTheApp->{preset_bundle}->reset(1);
}
if (defined $result->{config}) {
# Load and save the settings into print, filament and printer presets.
wxTheApp->{preset_bundle}->load_config('My Settings', $result->{config});
} else {
# Wizard returned a name of a preset bundle bundled with the installation. Unpack it.
wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $result->{preset_name} . '.ini');
}
};
Slic3r::GUI::catch_error($self) and return;
# Load the currently selected preset into the GUI, update the preset selection box.
foreach my $tab (values %{$self->{options_tabs}}) {
$tab->load_current_preset;
}
}
}
# This is called when closing the application, when loading a config file or when starting the config wizard
# to notify the user whether he is aware that some preset changes will be lost.
sub check_unsaved_changes {
my $self = shift;
my @dirty = ();
foreach my $tab (values %{$self->{options_tabs}}) {
push @dirty, $tab->title if $tab->current_preset_is_dirty;
}
if (@dirty) {
my $titles = join ', ', @dirty;
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;
}
return 1;
}
sub select_tab {
my ($self, $tab) = @_;
$self->{tabpanel}->SetSelection($tab);

View File

@ -552,8 +552,9 @@ sub BUILD {
$sizer->Add($textctrl, 0, wxALIGN_CENTER_VERTICAL, 0);
EVT_SLIDER($self->parent, $slider, sub {
if (! $self->disable_change_event) {
$self->textctrl->SetLabel($self->get_value);
if (! $self->disable_change_event) {
# wxTextCtrl::SetLabel() does not work on Linux, use wxTextCtrl::SetValue() instead
$self->textctrl->SetValue($self->get_value);
$self->_on_change($self->option->opt_id);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -222,7 +222,7 @@ sub mouse_event {
];
$self->{drag_object} = [ $obj_idx, $instance_idx ];
} elsif ($event->RightDown) {
$self->{on_right_click}->($pos);
$self->{on_right_click}->($pos->x, $pos->y);
}
last OBJECTS;
@ -231,8 +231,9 @@ sub mouse_event {
}
$self->Refresh;
} elsif ($event->LeftUp) {
$self->{on_instances_moved}->()
if $self->{drag_object};
if ($self->{drag_object}) {
$self->{on_instances_moved}->();
}
$self->{drag_start_pos} = undef;
$self->{drag_object} = undef;
$self->SetCursor(wxSTANDARD_CURSOR);

View File

@ -193,11 +193,11 @@ sub new {
my $old_zoom = $self->_zoom;
# Calculate the zoom delta and apply it to the current zoom factor
my $zoom = $e->GetWheelRotation() / $e->GetWheelDelta();
my $zoom = -$e->GetWheelRotation() / $e->GetWheelDelta();
$zoom = max(min($zoom, 4), -4);
$zoom /= 10;
$self->_zoom($self->_zoom / (1-$zoom));
$self->_zoom(1) if $self->_zoom > 1; # prevent from zooming out too much
$self->_zoom(1.25) if $self->_zoom > 1.25; # prevent from zooming out too much
{
# In order to zoom around the mouse point we need to translate
@ -221,7 +221,6 @@ sub new {
}
$self->_dirty(1);
$self->Refresh;
});
EVT_MOUSE_EVENTS($self, \&mouse_event);
@ -249,8 +248,8 @@ sub mouse_event {
return if !$self->GetParent->enabled;
my $pos = Slic3r::Pointf->new($e->GetPositionXY);
if ($e->Entering && &Wx::wxMSW) {
# wxMSW needs focus in order to catch mouse wheel events
if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) {
# wxMSW and Linux needs focus in order to catch key events
$self->SetFocus;
} elsif ($e->Dragging) {
if ($e->LeftIsDown || $e->MiddleIsDown || $e->RightIsDown) {
@ -270,7 +269,6 @@ sub mouse_event {
);
$self->_dirty(1);
$self->Refresh;
}
$self->_drag_start_xy($pos);
}
@ -625,6 +623,27 @@ sub Resize {
glLoadIdentity();
my $bb = $self->bb->clone;
# rescale in dependence of window aspect ratio
my $bb_size = $bb->size;
my $ratio_x = ($x != 0.0) ? $bb_size->x / $x : 1.0;
my $ratio_y = ($y != 0.0) ? $bb_size->y / $y : 1.0;
if ($ratio_y < $ratio_x) {
if ($ratio_y != 0.0) {
my $new_size_y = $bb_size->y * $ratio_x / $ratio_y;
my $half_delta_size_y = 0.5 * ($new_size_y - $bb_size->y);
$bb->set_y_min($bb->y_min - $half_delta_size_y);
$bb->set_y_max($bb->y_max + $half_delta_size_y);
}
} elsif ($ratio_x < $ratio_y) {
if ($ratio_x != 0.0) {
my $new_size_x = $bb_size->x * $ratio_y / $ratio_x;
my $half_delta_size_x = 0.5 * ($new_size_x - $bb_size->x);
$bb->set_x_min($bb->x_min - $half_delta_size_x);
$bb->set_x_max($bb->x_max + $half_delta_size_x);
}
}
# center bounding box around origin before scaling it
my $bb_center = $bb->center;
@ -639,25 +658,25 @@ sub Resize {
# translate camera
$bb->translate(@{$self->_camera_target});
# keep camera_bb within total bb
# (i.e. prevent user from panning outside the bounding box)
{
my @translate = (0,0);
if ($bb->x_min < $self->bb->x_min) {
$translate[X] += $self->bb->x_min - $bb->x_min;
}
if ($bb->y_min < $self->bb->y_min) {
$translate[Y] += $self->bb->y_min - $bb->y_min;
}
if ($bb->x_max > $self->bb->x_max) {
$translate[X] -= $bb->x_max - $self->bb->x_max;
}
if ($bb->y_max > $self->bb->y_max) {
$translate[Y] -= $bb->y_max - $self->bb->y_max;
}
$self->_camera_target->translate(@translate);
$bb->translate(@translate);
}
# # keep camera_bb within total bb
# # (i.e. prevent user from panning outside the bounding box)
# {
# my @translate = (0,0);
# if ($bb->x_min < $self->bb->x_min) {
# $translate[X] += $self->bb->x_min - $bb->x_min;
# }
# if ($bb->y_min < $self->bb->y_min) {
# $translate[Y] += $self->bb->y_min - $bb->y_min;
# }
# if ($bb->x_max > $self->bb->x_max) {
# $translate[X] -= $bb->x_max - $self->bb->x_max;
# }
# if ($bb->y_max > $self->bb->y_max) {
# $translate[Y] -= $bb->y_max - $self->bb->y_max;
# }
# $self->_camera_target->translate(@translate);
# $bb->translate(@translate);
# }
# save camera
$self->_camera_bb($bb);

View File

@ -5,235 +5,22 @@ use utf8;
use List::Util qw();
use Wx qw(:misc :pen :brush :sizer :font :cursor :keycode wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR);
use base qw(Slic3r::GUI::3DScene Class::Accessor);
use Wx::Locale gettext => 'L';
__PACKAGE__->mk_accessors(qw(
on_arrange on_rotate_object_left on_rotate_object_right on_scale_object_uniformly
on_remove_object on_increase_objects on_decrease_objects));
sub new {
my $class = shift;
my ($parent, $objects, $model, $print, $config) = @_;
my $self = $class->SUPER::new($parent);
$self->enable_picking(1);
$self->enable_moving(1);
$self->select_by('object');
$self->drag_by('instance');
$self->{objects} = $objects;
$self->{model} = $model;
$self->{print} = $print;
$self->{config} = $config;
$self->{on_select_object} = sub {};
$self->{on_instances_moved} = sub {};
$self->{on_wipe_tower_moved} = sub {};
$self->on_select(sub {
my ($volume_idx) = @_;
$self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx)
if ($self->{on_select_object});
});
$self->on_move(sub {
my @volume_idxs = @_;
my %done = (); # prevent moving instances twice
my $object_moved;
my $wipe_tower_moved;
foreach my $volume_idx (@volume_idxs) {
my $volume = $self->volumes->[$volume_idx];
my $obj_idx = $volume->object_idx;
my $instance_idx = $volume->instance_idx;
next if $done{"${obj_idx}_${instance_idx}"};
$done{"${obj_idx}_${instance_idx}"} = 1;
if ($obj_idx < 1000) {
# Move a regular object.
my $model_object = $self->{model}->get_object($obj_idx);
$model_object
->instances->[$instance_idx]
->offset
->translate($volume->origin->x, $volume->origin->y); #))
$model_object->invalidate_bounding_box;
$object_moved = 1;
} elsif ($obj_idx == 1000) {
# Move a wipe tower proxy.
$wipe_tower_moved = $volume->origin;
}
}
$self->{on_instances_moved}->()
if $object_moved && $self->{on_instances_moved};
$self->{on_wipe_tower_moved}->($wipe_tower_moved)
if $wipe_tower_moved && $self->{on_wipe_tower_moved};
});
EVT_KEY_DOWN($self, sub {
my ($s, $event) = @_;
if ($event->HasModifiers) {
$event->Skip;
} else {
my $key = $event->GetKeyCode;
if ($key == WXK_DELETE) {
$self->on_remove_object->() if $self->on_remove_object;
} else {
$event->Skip;
}
}
});
EVT_CHAR($self, sub {
my ($s, $event) = @_;
if ($event->HasModifiers) {
$event->Skip;
} else {
my $key = $event->GetKeyCode;
if ($key == ord('a')) {
$self->on_arrange->() if $self->on_arrange;
} elsif ($key == ord('l')) {
$self->on_rotate_object_left->() if $self->on_rotate_object_left;
} elsif ($key == ord('r')) {
$self->on_rotate_object_right->() if $self->on_rotate_object_right;
} elsif ($key == ord('s')) {
$self->on_scale_object_uniformly->() if $self->on_scale_object_uniformly;
} elsif ($key == ord('+')) {
$self->on_increase_objects->() if $self->on_increase_objects;
} elsif ($key == ord('-')) {
$self->on_decrease_objects->() if $self->on_decrease_objects;
} else {
$event->Skip;
}
}
});
Slic3r::GUI::_3DScene::enable_picking($self, 1);
Slic3r::GUI::_3DScene::enable_moving($self, 1);
Slic3r::GUI::_3DScene::set_select_by($self, 'object');
Slic3r::GUI::_3DScene::set_drag_by($self, 'instance');
Slic3r::GUI::_3DScene::set_model($self, $model);
Slic3r::GUI::_3DScene::set_print($self, $print);
Slic3r::GUI::_3DScene::set_config($self, $config);
return $self;
}
sub set_on_select_object {
my ($self, $cb) = @_;
$self->{on_select_object} = $cb;
}
sub set_on_double_click {
my ($self, $cb) = @_;
$self->on_double_click($cb);
}
sub set_on_right_click {
my ($self, $cb) = @_;
$self->on_right_click($cb);
}
sub set_on_arrange {
my ($self, $cb) = @_;
$self->on_arrange($cb);
}
sub set_on_rotate_object_left {
my ($self, $cb) = @_;
$self->on_rotate_object_left($cb);
}
sub set_on_rotate_object_right {
my ($self, $cb) = @_;
$self->on_rotate_object_right($cb);
}
sub set_on_scale_object_uniformly {
my ($self, $cb) = @_;
$self->on_scale_object_uniformly($cb);
}
sub set_on_increase_objects {
my ($self, $cb) = @_;
$self->on_increase_objects($cb);
}
sub set_on_decrease_objects {
my ($self, $cb) = @_;
$self->on_decrease_objects($cb);
}
sub set_on_remove_object {
my ($self, $cb) = @_;
$self->on_remove_object($cb);
}
sub set_on_instances_moved {
my ($self, $cb) = @_;
$self->{on_instances_moved} = $cb;
}
sub set_on_wipe_tower_moved {
my ($self, $cb) = @_;
$self->{on_wipe_tower_moved} = $cb;
}
sub set_on_model_update {
my ($self, $cb) = @_;
$self->on_model_update($cb);
}
sub reload_scene {
my ($self, $force) = @_;
$self->reset_objects;
$self->update_bed_size;
if (! $self->IsShown && ! $force) {
$self->{reload_delayed} = 1;
return;
}
$self->{reload_delayed} = 0;
foreach my $obj_idx (0..$#{$self->{model}->objects}) {
my @volume_idxs = $self->load_object($self->{model}, $self->{print}, $obj_idx);
if ($self->{objects}[$obj_idx]->selected) {
$self->select_volume($_) for @volume_idxs;
}
}
if (defined $self->{config}->nozzle_diameter) {
# Should the wipe tower be visualized?
my $extruders_count = scalar @{ $self->{config}->nozzle_diameter };
# Height of a print.
my $height = $self->{model}->bounding_box->z_max;
# Show at least a slab.
$height = 10 if $height < 10;
if ($extruders_count > 1 && $self->{config}->single_extruder_multi_material && $self->{config}->wipe_tower &&
! $self->{config}->complete_objects) {
$self->volumes->load_wipe_tower_preview(1000,
$self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y,
$self->{config}->wipe_tower_width, $self->{config}->wipe_tower_per_color_wipe * ($extruders_count - 1),
$self->{model}->bounding_box->z_max, $self->UseVBOs);
}
}
# checks for geometry outside the print volume to render it accordingly
if (scalar @{$self->volumes} > 0)
{
if (!$self->{model}->fits_print_volume($self->{config})) {
$self->set_warning_enabled(1);
Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume"));
} else {
$self->set_warning_enabled(0);
$self->volumes->update_outside_state($self->{config}, 1);
Slic3r::GUI::_3DScene::reset_warning_texture();
}
}
}
sub update_bed_size {
my ($self) = @_;
$self->set_bed_shape($self->{config}->bed_shape);
}
# Called by the Platter wxNotebook when this page is activated.
sub OnActivate {
my ($self) = @_;
$self->reload_scene(1) if ($self->{reload_delayed});
}
1;

View File

@ -10,7 +10,7 @@ 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));
__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer));
sub new {
my $class = shift;
@ -21,11 +21,11 @@ sub new {
$self->{number_extruders} = 1;
# Show by feature type by default.
$self->{preferred_color_mode} = 'feature';
$self->auto_zoom(1);
# init GUI elements
my $canvas = Slic3r::GUI::3DScene->new($self);
$canvas->use_plain_shader(1);
Slic3r::GUI::_3DScene::enable_shader($canvas, 1);
Slic3r::GUI::_3DScene::set_config($canvas, $config);
$self->canvas($canvas);
my $slider_low = Wx::Slider->new(
$self, -1,
@ -59,6 +59,13 @@ sub new {
[40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_high->SetFont($Slic3r::GUI::small_font);
my $z_label_low_idx = $self->{z_label_low_idx} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
[40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_low_idx->SetFont($Slic3r::GUI::small_font);
my $z_label_high_idx = $self->{z_label_high_idx} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
[40,-1], wxALIGN_CENTRE_HORIZONTAL);
$z_label_high_idx->SetFont($Slic3r::GUI::small_font);
$self->single_layer(0);
my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, L("1 Layer"));
@ -69,9 +76,13 @@ sub new {
$choice_view_type->Append(L("Height"));
$choice_view_type->Append(L("Width"));
$choice_view_type->Append(L("Speed"));
$choice_view_type->Append(L("Volumetric flow rate"));
$choice_view_type->Append(L("Tool"));
$choice_view_type->SetSelection(0);
# the following value needs to be changed if new items are added into $choice_view_type before "Tool"
$self->{tool_idx} = 5;
my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, L("Show"));
my $combochecklist_features = $self->{combochecklist_features} = Wx::ComboCtrl->new();
@ -100,11 +111,13 @@ sub new {
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
my $vsizer_outer = Wx::BoxSizer->new(wxVERTICAL);
$vsizer->Add($slider_low, 3, 0, 0);
$vsizer->Add($z_label_low, 0, 0, 0);
$vsizer->Add($slider_low, 3, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_low_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_low, 0, wxALIGN_CENTER_HORIZONTAL, 0);
$hsizer->Add($vsizer, 0, wxEXPAND, 0);
$vsizer = Wx::BoxSizer->new(wxVERTICAL);
$vsizer->Add($slider_high, 3, 0, 0);
$vsizer->Add($slider_high, 3, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_high_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0);
$vsizer->Add($z_label_high, 0, 0, 0);
$hsizer->Add($vsizer, 0, wxEXPAND, 0);
$vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0);
@ -204,43 +217,31 @@ sub new {
});
EVT_CHOICE($self, $choice_view_type, sub {
my $selection = $choice_view_type->GetCurrentSelection();
$self->{preferred_color_mode} = ($selection == 4) ? 'tool' : 'feature';
$self->{preferred_color_mode} = ($selection == $self->{tool_idx}) ? 'tool' : 'feature';
$self->gcode_preview_data->set_type($selection);
$self->auto_zoom(0);
$self->reload_print;
$self->auto_zoom(1);
});
EVT_CHECKLISTBOX($self, $combochecklist_features, sub {
my $flags = Slic3r::GUI::combochecklist_get_flags($combochecklist_features);
$self->gcode_preview_data->set_extrusion_flags($flags);
$self->auto_zoom(0);
$self->refresh_print;
$self->auto_zoom(1);
});
EVT_CHECKBOX($self, $checkbox_travel, sub {
$self->gcode_preview_data->set_travel_visible($checkbox_travel->IsChecked());
$self->auto_zoom(0);
$self->refresh_print;
$self->auto_zoom(1);
});
EVT_CHECKBOX($self, $checkbox_retractions, sub {
$self->gcode_preview_data->set_retractions_visible($checkbox_retractions->IsChecked());
$self->auto_zoom(0);
$self->refresh_print;
$self->auto_zoom(1);
});
EVT_CHECKBOX($self, $checkbox_unretractions, sub {
$self->gcode_preview_data->set_unretractions_visible($checkbox_unretractions->IsChecked());
$self->auto_zoom(0);
$self->refresh_print;
$self->auto_zoom(1);
});
EVT_CHECKBOX($self, $checkbox_shells, sub {
$self->gcode_preview_data->set_shells_visible($checkbox_shells->IsChecked());
$self->auto_zoom(0);
$self->refresh_print;
$self->auto_zoom(1);
});
$self->SetSizer($main_sizer);
@ -277,8 +278,8 @@ sub new {
sub reload_print {
my ($self, $force) = @_;
$self->canvas->reset_objects;
Slic3r::GUI::_3DScene::reset_volumes($self->canvas);
$self->_loaded(0);
if (! $self->IsShown && ! $force) {
@ -301,6 +302,12 @@ sub refresh_print {
$self->load_print;
}
sub reset_gcode_preview_data {
my ($self) = @_;
$self->gcode_preview_data->reset;
Slic3r::GUI::_3DScene::reset_legend_texture();
}
sub load_print {
my ($self) = @_;
@ -322,25 +329,17 @@ sub load_print {
}
if ($n_layers == 0) {
$self->enabled(0);
$self->set_z_range(0,0);
$self->slider_low->Hide;
$self->slider_high->Hide;
$self->{z_label_low}->SetLabel("");
$self->{z_label_high}->SetLabel("");
$self->canvas->reset_legend_texture();
$self->reset_sliders;
Slic3r::GUI::_3DScene::reset_legend_texture();
$self->canvas->Refresh; # clears canvas
return;
}
# 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.
my $extruders = $self->{print}->extruders;
my $type = (scalar(@{$extruders}) > 1) ? 4 : 0;
my $type = (scalar(@{$extruders}) > 1) ? $self->{tool_idx} : 0;
$self->gcode_preview_data->set_type($type);
$self->{choice_view_type}->SetSelection($type);
# If the ->SetSelection changed the following line, revert it to "decide yourself".
@ -349,7 +348,7 @@ sub load_print {
# Collect colors per extruder.
my @colors = ();
if (! $self->gcode_preview_data->empty() || $self->gcode_preview_data->type == 4) {
if (! $self->gcode_preview_data->empty() || $self->gcode_preview_data->type == $self->{tool_idx}) {
my @extruder_colors = @{$self->{config}->extruder_colour};
my @filament_colors = @{$self->{config}->filament_colour};
for (my $i = 0; $i <= $#extruder_colors; $i += 1) {
@ -361,36 +360,47 @@ sub load_print {
}
if ($self->IsShown) {
# used to set the sliders to the extremes of the current zs range
$self->{force_sliders_full_range} = 0;
if ($self->gcode_preview_data->empty) {
# load skirt and brim
$self->canvas->load_print_toolpaths($self->print, \@colors);
$self->canvas->load_wipe_tower_toolpaths($self->print, \@colors);
foreach my $object (@{$self->print->objects}) {
$self->canvas->load_print_object_toolpaths($object, \@colors);
# Show the objects in very transparent color.
#my @volume_ids = $self->canvas->load_object($object->model_object);
#$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
}
Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
Slic3r::GUI::_3DScene::load_preview($self->canvas, \@colors);
$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->{force_sliders_full_range} = (Slic3r::GUI::_3DScene::get_volumes_count($self->canvas) == 0);
Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
Slic3r::GUI::_3DScene::load_gcode_preview($self->canvas, $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();
$self->{layers_z} = Slic3r::GUI::_3DScene::get_current_print_zs($self->canvas, 1);
$n_layers = scalar(@{$self->{layers_z}});
}
if ($n_layers == 0) {
# all layers filtered out
$self->reset_sliders;
$self->canvas->Refresh; # clears canvas
}
}
$self->update_sliders($n_layers);
if ($self->auto_zoom) {
$self->canvas->zoom_to_volumes;
}
$self->update_sliders($n_layers) if ($n_layers > 0);
$self->_loaded(1);
}
}
sub reset_sliders {
my ($self) = @_;
$self->enabled(0);
$self->set_z_range(0,0);
$self->slider_low->Hide;
$self->slider_high->Hide;
$self->{z_label_low}->SetLabel("");
$self->{z_label_high}->SetLabel("");
$self->{z_label_low_idx}->SetLabel("");
$self->{z_label_high_idx}->SetLabel("");
}
sub update_sliders
{
my ($self, $n_layers) = @_;
@ -405,18 +415,32 @@ sub update_sliders
$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 {
# search new indices for nearest z (size of $self->{layers_z} may change in dependence of what is shown)
if (defined($self->{z_low})) {
for (my $i = scalar(@{$self->{layers_z}}) - 1; $i >= 0; $i -= 1) {
if ($self->{layers_z}[$i] <= $self->{z_low}) {
$z_idx_low = $i;
last;
}
}
}
if (defined($self->{z_high})) {
for (my $i = scalar(@{$self->{layers_z}}) - 1; $i >= 0; $i -= 1) {
if ($self->{layers_z}[$i] <= $self->{z_high}) {
$z_idx_high = $i;
last;
}
}
}
} elsif ($z_idx_high >= $n_layers) {
# 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) {
} else {
$z_idx_low = 0;
$z_idx_high = $n_layers - 1;
}
$self->slider_low->SetValue($z_idx_low);
@ -432,9 +456,26 @@ sub set_z_range
my ($self, $z_low, $z_high) = @_;
return if !$self->enabled;
$self->{z_low} = $z_low;
$self->{z_high} = $z_high;
$self->{z_label_low}->SetLabel(sprintf '%.2f', $z_low);
$self->{z_label_high}->SetLabel(sprintf '%.2f', $z_high);
$self->canvas->set_toolpaths_range($z_low - 1e-6, $z_high + 1e-6);
my $layers_z = Slic3r::GUI::_3DScene::get_current_print_zs($self->canvas, 0);
for (my $i = 0; $i < scalar(@{$layers_z}); $i += 1) {
if (($z_low - 1e-6 < @{$layers_z}[$i]) && (@{$layers_z}[$i] < $z_low + 1e-6)) {
$self->{z_label_low_idx}->SetLabel(sprintf '%d', $i + 1);
last;
}
}
for (my $i = 0; $i < scalar(@{$layers_z}); $i += 1) {
if (($z_high - 1e-6 < @{$layers_z}[$i]) && (@{$layers_z}[$i] < $z_high + 1e-6)) {
$self->{z_label_high_idx}->SetLabel(sprintf '%d', $i + 1);
last;
}
}
Slic3r::GUI::_3DScene::set_toolpaths_range($self->canvas, $z_low - 1e-6, $z_high + 1e-6);
$self->canvas->Refresh if $self->IsShown;
}
@ -464,21 +505,16 @@ sub set_z_idx_high
}
}
sub set_bed_shape {
my ($self, $bed_shape) = @_;
$self->canvas->set_bed_shape($bed_shape);
}
sub set_number_extruders {
my ($self, $number_extruders) = @_;
if ($self->{number_extruders} != $number_extruders) {
$self->{number_extruders} = $number_extruders;
my $type = ($number_extruders > 1) ?
4 # color by a tool number
$self->{tool_idx} # color by a tool number
: 0; # color by a feature type
$self->{choice_view_type}->SetSelection($type);
$self->gcode_preview_data->set_type($type);
$self->{preferred_color_mode} = ($type == 4) ? 'tool_or_feature' : 'feature';
$self->{preferred_color_mode} = ($type == $self->{tool_idx}) ? 'tool_or_feature' : 'feature';
}
}

View File

@ -9,6 +9,7 @@ use utf8;
use Slic3r::Geometry qw(PI X);
use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
use List::Util qw(max);
use base 'Wx::Dialog';
sub new {
@ -60,7 +61,7 @@ sub new {
label => 'Z',
default => $self->{cut_options}{z},
min => 0,
max => $self->{model_object}->bounding_box->size->z * $self->{model_object}->instances->[0]->scaling_factor,
max => $self->{model_object}->bounding_box->size->z,
full_width => 1,
));
{
@ -112,11 +113,13 @@ sub new {
my $canvas;
if ($Slic3r::GUI::have_OpenGL) {
$canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self);
$canvas->load_object($self->{model_object}, undef, undef, [0]);
$canvas->set_auto_bed_shape;
Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
Slic3r::GUI::_3DScene::set_auto_bed_shape($canvas);
Slic3r::GUI::_3DScene::set_axes_length($canvas, 2.0 * max(@{ Slic3r::GUI::_3DScene::get_volumes_bounding_box($canvas)->size }));
$canvas->SetSize([500,500]);
$canvas->SetMinSize($canvas->GetSize);
$canvas->zoom_to_volumes;
Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->{config});
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
}
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
@ -134,7 +137,7 @@ sub new {
# Adjust position / orientation of the split object halves.
if ($self->{new_model_objects}{lower}) {
if ($self->{cut_options}{rotate_lower}) {
$self->{new_model_objects}{lower}->rotate(PI, X);
$self->{new_model_objects}{lower}->rotate(PI, Slic3r::Pointf3->new(1,0,0));
$self->{new_model_objects}{lower}->center_around_origin; # align to Z = 0
}
}
@ -145,6 +148,7 @@ sub new {
# Note that the window was already closed, so a pending update will not be executed.
$self->{already_closed} = 1;
$self->EndModal(wxID_OK);
$self->{canvas}->Destroy;
$self->Destroy();
});
@ -152,6 +156,7 @@ sub new {
# Note that the window was already closed, so a pending update will not be executed.
$self->{already_closed} = 1;
$self->EndModal(wxID_CANCEL);
$self->{canvas}->Destroy;
$self->Destroy();
});
@ -227,12 +232,14 @@ sub _update {
push @objects, $self->{model_object};
}
my $z_cut = $z + $self->{model_object}->bounding_box->z_min;
# get section contour
my @expolygons = ();
foreach my $volume (@{$self->{model_object}->volumes}) {
next if !$volume->mesh;
next if $volume->modifier;
my $expp = $volume->mesh->slice([ $z + $volume->mesh->bounding_box->z_min ])->[0];
my $expp = $volume->mesh->slice([ $z_cut ])->[0];
push @expolygons, @$expp;
}
foreach my $expolygon (@expolygons) {
@ -240,14 +247,12 @@ sub _update {
for @$expolygon;
$expolygon->translate(map Slic3r::Geometry::scale($_), @{ $self->{model_object}->instances->[0]->offset });
}
$self->{canvas}->reset_objects;
$self->{canvas}->load_object($_, undef, undef, [0]) for @objects;
$self->{canvas}->SetCuttingPlane(
$self->{cut_options}{z},
[@expolygons],
);
$self->{canvas}->Render;
Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $_, 0, [0]) for @objects;
Slic3r::GUI::_3DScene::set_cutting_plane($self->{canvas}, $self->{cut_options}{z}, [@expolygons]);
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
Slic3r::GUI::_3DScene::render($self->{canvas});
}
}

View File

@ -9,7 +9,8 @@ use utf8;
use File::Basename qw(basename);
use Wx qw(:misc :sizer :treectrl :button :keycode wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG wxID_CANCEL wxMOD_CONTROL
wxTheApp);
use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN);
use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN EVT_KEY_DOWN);
use List::Util qw(max);
use base 'Wx::Panel';
use constant ICON_OBJECT => 0;
@ -88,7 +89,7 @@ sub new {
$self->{btn_move_down}->SetFont($Slic3r::GUI::small_font);
# part settings panel
$self->{settings_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { $self->{part_settings_changed} = 1; });
$self->{settings_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { $self->{part_settings_changed} = 1; $self->_update_canvas; });
my $settings_sizer = Wx::StaticBoxSizer->new($self->{staticbox} = Wx::StaticBox->new($self, -1, "Part Settings"), wxVERTICAL);
$settings_sizer->Add($self->{settings_panel}, 1, wxEXPAND | wxALL, 0);
@ -150,19 +151,19 @@ sub new {
my $canvas;
if ($Slic3r::GUI::have_OpenGL) {
$canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self);
$canvas->enable_picking(1);
$canvas->select_by('volume');
$canvas->on_select(sub {
Slic3r::GUI::_3DScene::enable_picking($canvas, 1);
Slic3r::GUI::_3DScene::set_select_by($canvas, 'volume');
Slic3r::GUI::_3DScene::register_on_select_object_callback($canvas, sub {
my ($volume_idx) = @_;
# convert scene volume to model object volume
$self->reload_tree(($volume_idx == -1) ? undef : $canvas->volumes->[$volume_idx]->volume_idx);
$self->reload_tree($volume_idx);
});
$canvas->load_object($self->{model_object}, undef, undef, [0]);
$canvas->set_auto_bed_shape;
Slic3r::GUI::_3DScene::load_model_object($canvas, $self->{model_object}, 0, [0]);
Slic3r::GUI::_3DScene::set_auto_bed_shape($canvas);
Slic3r::GUI::_3DScene::set_axes_length($canvas, 2.0 * max(@{ Slic3r::GUI::_3DScene::get_volumes_bounding_box($canvas)->size }));
$canvas->SetSize([500,700]);
$canvas->zoom_to_volumes;
Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->GetParent->GetParent->{config});
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($canvas);
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
}
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
@ -190,6 +191,14 @@ sub new {
EVT_BUTTON($self, $self->{btn_split}, \&on_btn_split);
EVT_BUTTON($self, $self->{btn_move_up}, \&on_btn_move_up);
EVT_BUTTON($self, $self->{btn_move_down}, \&on_btn_move_down);
EVT_KEY_DOWN($canvas, sub {
my ($canvas, $event) = @_;
if ($event->GetKeyCode == WXK_DELETE) {
$canvas->GetParent->on_btn_delete;
} else {
$event->Skip;
}
});
$self->reload_tree;
@ -254,7 +263,7 @@ sub selection_changed {
# deselect all meshes
if ($self->{canvas}) {
$_->set_selected(0) for @{$self->{canvas}->volumes};
Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas});
}
# disable things as if nothing is selected
@ -282,7 +291,7 @@ sub selection_changed {
if ($itemData->{type} eq 'volume') {
# select volume in 3D preview
if ($self->{canvas}) {
$self->{canvas}->volumes->[ $itemData->{volume_id} ]->set_selected(1);
Slic3r::GUI::_3DScene::select_volume($self->{canvas}, $itemData->{volume_id});
}
$self->{btn_delete}->Enable;
$self->{btn_split}->Enable;
@ -313,7 +322,13 @@ sub selection_changed {
}
# get default values
my $default_config = Slic3r::Config::new_from_defaults_keys(\@opt_keys);
# decide which settings will be shown by default
if ($itemData->{type} eq 'object') {
$config->set_ifndef('wipe_into_objects', 0);
$config->set_ifndef('wipe_into_infill', 0);
}
# append default extruder
push @opt_keys, 'extruder';
$default_config->set('extruder', 0);
@ -321,11 +336,18 @@ sub selection_changed {
$self->{settings_panel}->set_default_config($default_config);
$self->{settings_panel}->set_config($config);
$self->{settings_panel}->set_opt_keys(\@opt_keys);
$self->{settings_panel}->set_fixed_options([qw(extruder)]);
# disable minus icon to remove the settings
if ($itemData->{type} eq 'object') {
$self->{settings_panel}->set_fixed_options([qw(extruder), qw(wipe_into_infill), qw(wipe_into_objects)]);
} else {
$self->{settings_panel}->set_fixed_options([qw(extruder)]);
}
$self->{settings_panel}->enable;
}
$self->{canvas}->Render if $self->{canvas};
Slic3r::GUI::_3DScene::render($self->{canvas}) if $self->{canvas};
}
sub on_btn_load {
@ -355,7 +377,8 @@ sub on_btn_load {
}
}
}
$self->{model_object}->center_around_origin if $self->{parts_changed};
$self->_parts_changed;
}
@ -400,14 +423,17 @@ sub on_tree_key_down {
my ($self, $event) = @_;
my $keycode = $event->GetKeyCode;
# Wx >= 0.9911
if (defined(&Wx::TreeEvent::GetKeyEvent) &&
($event->GetKeyEvent->GetModifiers & wxMOD_CONTROL)) {
if ($keycode == WXK_UP) {
$event->Skip;
$self->on_btn_move_up;
} elsif ($keycode == WXK_DOWN) {
$event->Skip;
$self->on_btn_move_down;
if (defined(&Wx::TreeEvent::GetKeyEvent)) {
if ($event->GetKeyEvent->GetModifiers & wxMOD_CONTROL) {
if ($keycode == WXK_UP) {
$event->Skip;
$self->on_btn_move_up;
} elsif ($keycode == WXK_DOWN) {
$event->Skip;
$self->on_btn_move_down;
}
} elsif ($keycode == WXK_DELETE) {
$self->on_btn_delete;
}
}
}
@ -418,7 +444,7 @@ sub on_btn_move_up {
if ($itemData && $itemData->{type} eq 'volume') {
my $volume_id = $itemData->{volume_id};
if ($self->{model_object}->move_volume_up($volume_id)) {
$self->{canvas}->volumes->move_volume_up($volume_id);
Slic3r::GUI::_3DScene::move_volume_up($self->{canvas}, $volume_id);
$self->{parts_changed} = 1;
$self->reload_tree($volume_id - 1);
}
@ -431,7 +457,7 @@ sub on_btn_move_down {
if ($itemData && $itemData->{type} eq 'volume') {
my $volume_id = $itemData->{volume_id};
if ($self->{model_object}->move_volume_down($volume_id)) {
$self->{canvas}->volumes->move_volume_down($volume_id);
Slic3r::GUI::_3DScene::move_volume_down($self->{canvas}, $volume_id);
$self->{parts_changed} = 1;
$self->reload_tree($volume_id + 1);
}
@ -454,7 +480,8 @@ sub on_btn_delete {
$self->{model_object}->delete_volume($itemData->{volume_id});
$self->{parts_changed} = 1;
}
$self->{model_object}->center_around_origin if $self->{parts_changed};
$self->_parts_changed;
}
@ -464,7 +491,8 @@ sub on_btn_split {
my $itemData = $self->get_selection;
if ($itemData && $itemData->{type} eq 'volume') {
my $volume = $self->{model_object}->volumes->[$itemData->{volume_id}];
$self->{parts_changed} = 1 if $volume->split > 1;
my $nozzle_dmrs = $self->GetParent->GetParent->GetParent->{config}->get('nozzle_diameter');
$self->{parts_changed} = 1 if $volume->split(scalar(@$nozzle_dmrs)) > 1;
}
$self->_parts_changed;
@ -475,10 +503,11 @@ sub _parts_changed {
$self->reload_tree;
if ($self->{canvas}) {
$self->{canvas}->reset_objects;
$self->{canvas}->load_object($self->{model_object});
$self->{canvas}->zoom_to_volumes;
$self->{canvas}->Render;
Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas});
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
Slic3r::GUI::_3DScene::render($self->{canvas});
}
}
@ -498,6 +527,11 @@ sub CanClose {
return ! Slic3r::GUI::catch_error($self);
}
sub Destroy {
my ($self) = @_;
$self->{canvas}->Destroy if ($self->{canvas});
}
sub PartsChanged {
my ($self) = @_;
return $self->{parts_changed};
@ -508,6 +542,25 @@ sub PartSettingsChanged {
return $self->{part_settings_changed};
}
sub _update_canvas {
my ($self) = @_;
if ($self->{canvas}) {
Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
# restore selection, if any
if (my $itemData = $self->get_selection) {
if ($itemData->{type} eq 'volume') {
Slic3r::GUI::_3DScene::select_volume($self->{canvas}, $itemData->{volume_id});
}
}
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
Slic3r::GUI::_3DScene::render($self->{canvas});
}
}
sub _update {
my ($self) = @_;
my ($m_x, $m_y, $m_z) = ($self->{move_options}{x}, $self->{move_options}{y}, $self->{move_options}{z});
@ -526,9 +579,10 @@ sub _update {
$self->{parts_changed} = 1;
my @objects = ();
push @objects, $self->{model_object};
$self->{canvas}->reset_objects;
$self->{canvas}->load_object($_, undef, [0]) for @objects;
$self->{canvas}->Render;
Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $_, 0, [0]) for @objects;
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
Slic3r::GUI::_3DScene::render($self->{canvas});
}
1;

View File

@ -36,6 +36,7 @@ sub new {
wxTheApp->save_window_pos($self, "object_settings");
$self->EndModal(wxID_OK);
$self->{parts}->Destroy;
$self->Destroy;
});
@ -46,6 +47,8 @@ sub new {
$self->SetSizer($sizer);
$self->SetMinSize($self->GetSize);
$self->Layout;
wxTheApp->restore_window_pos($self, "object_settings");
return $self;

View File

@ -136,7 +136,7 @@ sub update_optgroup {
full_labels => 1,
label_font => $Slic3r::GUI::small_font,
sidetext_font => $Slic3r::GUI::small_font,
label_width => 120,
label_width => 150,
on_change => sub { $self->{on_change}->() if $self->{on_change} },
extra_column => sub {
my ($line) = @_;

View File

@ -1,144 +1,18 @@
# Status bar at the bottom of the main screen.
# Now it just implements cancel cb on perl side, every other functionality is
# in C++
package Slic3r::GUI::ProgressStatusBar;
package Slic3r::GUI::ProgressStatusBar;
use strict;
use warnings;
use Wx qw(:gauge :misc);
use base 'Wx::StatusBar';
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{busy} = 0;
$self->{timer} = Wx::Timer->new($self);
$self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize);
$self->{prog}->Hide;
$self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize);
$self->{cancelbutton}->Hide;
$self->SetFieldsCount(3);
$self->SetStatusWidths(-1, 150, 155);
Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer});
Wx::Event::EVT_SIZE($self, \&OnSize);
Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub {
$self->{cancel_cb}->();
$self->{cancelbutton}->Hide;
});
return $self;
}
sub DESTROY {
my $self = shift;
$self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning;
}
sub OnSize {
my ($self, $event) = @_;
my %fields = (
# 0 is reserved for status text
1 => $self->{cancelbutton},
2 => $self->{prog},
);
foreach (keys %fields) {
my $rect = $self->GetFieldRect($_);
my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK
my $pos = [$rect->GetX + $offset, $rect->GetY + $offset];
$fields{$_}->Move($pos);
$fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight);
}
$event->Skip;
}
sub OnTimer {
my ($self, $event) = @_;
if ($self->{prog}->IsShown) {
$self->{timer}->Stop;
}
$self->{prog}->Pulse if $self->{_busy};
}
our $cancel_cb;
sub SetCancelCallback {
my $self = shift;
my ($cb) = @_;
$self->{cancel_cb} = $cb;
$cb ? $self->{cancelbutton}->Show : $self->{cancelbutton}->Hide;
}
sub Run {
my $self = shift;
my $rate = shift || 100;
if (!$self->{timer}->IsRunning) {
$self->{timer}->Start($rate);
}
}
sub GetProgress {
my $self = shift;
return $self->{prog}->GetValue;
}
sub SetProgress {
my $self = shift;
my ($val) = @_;
if (!$self->{prog}->IsShown) {
$self->ShowProgress(1);
}
if ($val == $self->{prog}->GetRange) {
$self->{prog}->SetValue(0);
$self->ShowProgress(0);
} else {
$self->{prog}->SetValue($val);
}
}
sub SetRange {
my $self = shift;
my ($val) = @_;
if ($val != $self->{prog}->GetRange) {
$self->{prog}->SetRange($val);
}
}
sub ShowProgress {
my $self = shift;
my ($show) = @_;
$self->{prog}->Show($show);
$self->{prog}->Pulse;
}
sub StartBusy {
my $self = shift;
my $rate = shift || 100;
$self->{_busy} = 1;
$self->ShowProgress(1);
if (!$self->{timer}->IsRunning) {
$self->{timer}->Start($rate);
}
}
sub StopBusy {
my $self = shift;
$self->{timer}->Stop;
$self->ShowProgress(0);
$self->{prog}->SetValue(0);
$self->{_busy} = 0;
}
sub IsBusy {
my $self = shift;
return $self->{_busy};
$cancel_cb = $cb;
$cb ? $self->ShowCancelButton : $self->HideCancelButton;
}
1;

View File

@ -35,7 +35,12 @@ sub run_post_process_scripts {
die "The configured post-processing script is not executable: check permissions. ($script)\n";
}
if ($^O eq 'MSWin32' && $script =~ /\.[pP][lL]/) {
system($^X, $script, $output_file);
# The current process (^X) may be slic3r.exe or slic3r-console.exe.
# Replace it with the current perl interpreter.
my($filename, $directories, $suffix) = fileparse($^X);
$filename =~ s/^slic3r.*$/perl5\.24\.0\.exe/;
my $interpreter = $directories . $filename;
system($interpreter, $script, $output_file);
} else {
system($script, $output_file);
}
@ -43,13 +48,37 @@ sub run_post_process_scripts {
}
}
sub export_png {
my $self = shift;
my %params = @_;
my @sobjects = @{$self->objects};
my $objnum = scalar @sobjects;
for(my $oi = 0; $oi < $objnum; $oi++)
{
$sobjects[$oi]->slice;
$self->status_cb->(($oi + 1)*100/$objnum - 1, "Slicing...");
}
my $fh = $params{output_file};
$self->status_cb->(90, "Exporting zipped archive...");
$self->print_to_png($fh);
$self->status_cb->(100, "Done.");
}
# Export SVG slices for the offline SLA printing.
# The export_svg is expected to be executed inside an eval block.
sub export_svg {
my $self = shift;
my %params = @_;
$_->slice for @{$self->objects};
my @sobjects = @{$self->objects};
my $objnum = scalar @sobjects;
for(my $oi = 0; $oi < $objnum; $oi++)
{
$sobjects[$oi]->slice;
$self->status_cb->(($oi + 1)*100/$objnum - 1, "Slicing...");
}
my $fh = $params{output_fh};
if (!$fh) {

View File

@ -97,4 +97,14 @@ sub export_svg {
$self->_print->export_svg(output_file => $self->output_file);
}
sub export_png {
my ($self) = @_;
$self->_before_export;
$self->_print->export_png(output_file => $self->output_file);
$self->_after_export;
}
1;

14972
resources/avrdude/avrdude.conf Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 B

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

BIN
resources/icons/erase.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
resources/icons/lambda.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

BIN
resources/icons/lambda_.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

BIN
resources/icons/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

BIN
resources/icons/object.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

BIN
resources/icons/split.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

BIN
resources/icons/toolbar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,28 @@
xs/src/slic3r/GUI/AboutDialog.cpp
xs/src/slic3r/GUI/BedShapeDialog.cpp
xs/src/slic3r/GUI/BedShapeDialog.hpp
xs/src/slic3r/GUI/BonjourDialog.cpp
xs/src/slic3r/GUI/ButtonsDescription.cpp
xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp
xs/src/slic3r/GUI/ConfigWizard.cpp
xs/src/slic3r/GUI/FirmwareDialog.cpp
xs/src/slic3r/GUI/GLCanvas3D.cpp
xs/src/slic3r/GUI/GUI.cpp
xs/src/slic3r/GUI/MsgDialog.cpp
xs/src/slic3r/GUI/Tab.cpp
xs/src/slic3r/GUI/Tab.hpp
xs/src/slic3r/GUI/Field.cpp
xs/src/slic3r/GUI/OptionsGroup.cpp
xs/src/slic3r/GUI/2DBed.cpp
xs/src/slic3r/GUI/Preset.cpp
xs/src/slic3r/GUI/PresetBundle.cpp
xs/src/slic3r/GUI/PresetHints.cpp
xs/src/slic3r/GUI/Preferences.hpp
xs/src/slic3r/GUI/Preferences.cpp
xs/src/slic3r/GUI/BonjourDialog.cpp
xs/src/slic3r/GUI/RammingChart.cpp
xs/src/slic3r/GUI/UpdateDialogs.cpp
xs/src/slic3r/GUI/WipeTowerDialog.cpp
xs/src/slic3r/Utils/OctoPrint.cpp
xs/src/slic3r/Utils/PresetUpdater.cpp
xs/src/libslic3r/Print.cpp
xs/src/libslic3r/PrintConfig.cpp
xs/src/libslic3r/GCode/PreviewData.cpp
lib/Slic3r/GUI.pm

Some files were not shown because too many files have changed in this diff Show More