Merge branch 'master' into cppgui

This commit is contained in:
Joseph Lenox 2018-04-24 17:33:52 -05:00
commit 6505e6df7b
16 changed files with 388 additions and 111 deletions

6
.gitignore vendored
View File

@ -16,3 +16,9 @@ package/osx/Slic3r*.app
*.dmg
*.swp
*.swo
CMakeFiles
*.orig
*.a
core
CMakeCache.txt
*.cmake

View File

@ -84,7 +84,7 @@ The main author of Slic3r is Alessandro Ranellucci (@alexrj, *Sound* in IRC, [@a
Joseph Lenox (@lordofhyphens, *Loh* in IRC) is the current co-maintainer.
Contributions by Henrik Brix Andersen, Vojtech Bubnik, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Y. Sapir, Mike Sheldrake, Kliment Yanev and numerous others. Original manual by Gary Hodgson. Slic3r logo designed by Corey Daniels, <a href="http://www.famfamfam.com/lab/icons/silk/">Silk Icon Set</a> designed by Mark James.
Contributions by Henrik Brix Andersen, Vojtech Bubnik, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Y. Sapir, Mike Sheldrake, Kliment Yanev and numerous others. Original manual by Gary Hodgson. Slic3r logo designed by Corey Daniels, <a href="http://www.famfamfam.com/lab/icons/silk/">Silk Icon Set</a> designed by Mark James, stl and gcode file icons designed by Akira Yasuda.
### How can I invoke Slic3r using the command line?

View File

@ -52,6 +52,7 @@ use Slic3r::GUI::Preset;
use Slic3r::GUI::PresetEditor;
use Slic3r::GUI::PresetEditorDialog;
use Slic3r::GUI::SLAPrintOptions;
use Slic3r::GUI::ReloadDialog;
our $have_OpenGL = eval "use Slic3r::GUI::3DScene; 1";
our $have_LWP = eval "use LWP::UserAgent; 1";
@ -91,7 +92,9 @@ our $Settings = {
color_toolpaths_by => 'role',
tabbed_preset_editors => 1,
show_host => 0,
nudge_val => 1
nudge_val => 1,
reload_hide_dialog => 0,
reload_behavior => 0
},
};

View File

@ -1177,7 +1177,7 @@ sub add_tin {
sub load_file {
my $self = shift;
my ($input_file, $obj_idx) = @_;
my ($input_file, $obj_idx_to_load) = @_;
$Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file);
wxTheApp->save_settings;
@ -1203,14 +1203,27 @@ sub load_file {
}
}
if (defined $obj_idx) {
return () if $obj_idx >= $model->objects_count;
@obj_idx = $self->load_model_objects($model->get_object($obj_idx));
for my $obj_idx (0..($model->objects_count-1)) {
my $object = $model->objects->[$obj_idx];
$object->set_input_file($input_file);
for my $vol_idx (0..($object->volumes_count-1)) {
my $volume = $object->get_volume($vol_idx);
$volume->set_input_file($input_file);
$volume->set_input_file_obj_idx($obj_idx);
$volume->set_input_file_obj_idx($vol_idx);
}
}
my $i = 0;
if (defined $obj_idx_to_load) {
return () if $obj_idx_to_load >= $model->objects_count;
@obj_idx = $self->load_model_objects($model->get_object($obj_idx_to_load));
$i = $obj_idx_to_load;
} else {
@obj_idx = $self->load_model_objects(@{$model->objects});
}
my $i = 0;
foreach my $obj_idx (@obj_idx) {
$self->{objects}[$obj_idx]->input_file($input_file);
$self->{objects}[$obj_idx]->input_file_obj_idx($i++);
@ -2306,26 +2319,141 @@ sub reload_from_disk {
my ($obj_idx, $object) = $self->selected_object;
return if !defined $obj_idx;
return if !$object->input_file
|| !-e $object->input_file;
if (!$object->input_file) {
Slic3r::GUI::warning_catcher($self)->("The selected object couldn't be reloaded because it isn't referenced to its input file any more. This is the case after performing operations like cut or split.");
return;
}
if (!-e $object->input_file) {
Slic3r::GUI::warning_catcher($self)->("The selected object couldn't be reloaded because the file doesn't exist anymore on the disk.");
return;
}
# Only reload the selected object and not all objects from the input file.
my @new_obj_idx = $self->load_file($object->input_file, $object->input_file_obj_idx);
return if !@new_obj_idx;
if (!@new_obj_idx) {
Slic3r::GUI::warning_catcher($self)->("The selected object couldn't be reloaded because the new file doesn't contain the object.");
return;
}
my $model_object = $self->{model}->objects->[$obj_idx];
foreach my $new_obj_idx (@new_obj_idx) {
my $o = $self->{model}->objects->[$new_obj_idx];
$o->clear_instances;
$o->add_instance($_) for @{$model_object->instances};
my $org_obj = $self->{model}->objects->[$obj_idx];
if ($o->volumes_count == $model_object->volumes_count) {
for my $i (0..($o->volumes_count-1)) {
$o->get_volume($i)->config->apply($model_object->get_volume($i)->config);
}
# check if the object is dependant of more than one file
my $org_obj_has_modifiers=0;
for my $i (0..($org_obj->volumes_count-1)) {
if ($org_obj->input_file ne $org_obj->get_volume($i)->input_file) {
$org_obj_has_modifiers=1;
last;
}
}
my $reload_behavior = $Slic3r::GUI::Settings->{_}{reload_behavior};
# ask the user how to proceed, if option is selected in preferences
if ($org_obj_has_modifiers && !$Slic3r::GUI::Settings->{_}{reload_hide_dialog}) {
my $dlg = Slic3r::GUI::ReloadDialog->new(undef,$reload_behavior);
my $res = $dlg->ShowModal;
if ($res==wxID_CANCEL) {
$self->remove($_) for @new_obj_idx;
$dlg->Destroy;
return;
}
$reload_behavior = $dlg->GetSelection;
my $save = 0;
if ($reload_behavior != $Slic3r::GUI::Settings->{_}{reload_behavior}) {
$Slic3r::GUI::Settings->{_}{reload_behavior} = $reload_behavior;
$save = 1;
}
if ($dlg->GetHideOnNext) {
$Slic3r::GUI::Settings->{_}{reload_hide_dialog} = 1;
$save = 1;
}
Slic3r::GUI->save_settings if $save;
$dlg->Destroy;
}
my $volume_unmatched=0;
foreach my $new_obj_idx (@new_obj_idx) {
my $new_obj = $self->{model}->objects->[$new_obj_idx];
$new_obj->clear_instances;
$new_obj->add_instance($_) for @{$org_obj->instances};
$new_obj->config->apply($org_obj->config);
my $new_vol_idx = 0;
my $org_vol_idx = 0;
my $new_vol_count=$new_obj->volumes_count;
my $org_vol_count=$org_obj->volumes_count;
while ($new_vol_idx<=$new_vol_count-1) {
if (($org_vol_idx<=$org_vol_count-1) && ($org_obj->get_volume($org_vol_idx)->input_file eq $new_obj->input_file)) {
# apply config from the matching volumes
$new_obj->get_volume($new_vol_idx++)->config->apply($org_obj->get_volume($org_vol_idx++)->config);
} else {
# reload has more volumes than original (first file), apply config from the first volume
$new_obj->get_volume($new_vol_idx++)->config->apply($org_obj->get_volume(0)->config);
$volume_unmatched=1;
}
}
$org_vol_idx=$org_vol_count if $reload_behavior==2; # Reload behavior: discard
while (($org_vol_idx<=$org_vol_count-1) && ($org_obj->get_volume($org_vol_idx)->input_file eq $new_obj->input_file)) {
# original has more volumes (first file), skip those
$org_vol_idx++;
$volume_unmatched=1;
}
while ($org_vol_idx<=$org_vol_count-1) {
if ($reload_behavior==1) { # Reload behavior: copy
my $new_volume = $new_obj->add_volume($org_obj->get_volume($org_vol_idx));
$new_volume->mesh->translate(@{$org_obj->origin_translation->negative});
$new_volume->mesh->translate(@{$new_obj->origin_translation});
if ($new_volume->name =~ m/link to path\z/) {
my $new_name = $new_volume->name;
$new_name =~ s/ - no link to path$/ - copied/;
$new_volume->set_name($new_name);
}elsif(!($new_volume->name =~ m/copied\z/)) {
$new_volume->set_name($new_volume->name . " - copied");
}
}else{ # Reload behavior: Reload all, also fallback solution if ini was manually edited to a wrong value
if ($org_obj->get_volume($org_vol_idx)->input_file) {
my $model = eval { Slic3r::Model->read_from_file($org_obj->get_volume($org_vol_idx)->input_file) };
if ($@) {
$org_obj->get_volume($org_vol_idx)->set_input_file("");
}elsif ($org_obj->get_volume($org_vol_idx)->input_file_obj_idx > ($model->objects_count-1)) {
# Object Index for that part / modifier not found in current version of the file
$org_obj->get_volume($org_vol_idx)->set_input_file("");
}else{
my $prt_mod_obj = $model->objects->[$org_obj->get_volume($org_vol_idx)->input_file_obj_idx];
if ($org_obj->get_volume($org_vol_idx)->input_file_vol_idx > ($prt_mod_obj->volumes_count-1)) {
# Volume Index for that part / modifier not found in current version of the file
$org_obj->get_volume($org_vol_idx)->set_input_file("");
}else{
# all checks passed, load new mesh and copy metadata
my $new_volume = $new_obj->add_volume($prt_mod_obj->get_volume($org_obj->get_volume($org_vol_idx)->input_file_vol_idx));
$new_volume->set_input_file($org_obj->get_volume($org_vol_idx)->input_file);
$new_volume->set_input_file_obj_idx($org_obj->get_volume($org_vol_idx)->input_file_obj_idx);
$new_volume->set_input_file_vol_idx($org_obj->get_volume($org_vol_idx)->input_file_vol_idx);
$new_volume->config->apply($org_obj->get_volume($org_vol_idx)->config);
$new_volume->set_modifier($org_obj->get_volume($org_vol_idx)->modifier);
$new_volume->mesh->translate(@{$new_obj->origin_translation});
}
}
}
if (!$org_obj->get_volume($org_vol_idx)->input_file) {
my $new_volume = $new_obj->add_volume($org_obj->get_volume($org_vol_idx)); # error -> copy old mesh
$new_volume->mesh->translate(@{$org_obj->origin_translation->negative});
$new_volume->mesh->translate(@{$new_obj->origin_translation});
if ($new_volume->name =~ m/copied\z/) {
my $new_name = $new_volume->name;
$new_name =~ s/ - copied$/ - no link to path/;
$new_volume->set_name($new_name);
}elsif(!($new_volume->name =~ m/link to path\z/)) {
$new_volume->set_name($new_volume->name . " - no link to path");
}
$volume_unmatched=1;
}
}
$org_vol_idx++;
}
}
$self->remove($obj_idx);
# TODO: refresh object list which contains wrong count and scale
@ -2336,8 +2464,17 @@ sub reload_from_disk {
# When porting to C++ we'll probably have cleaner ways to do this.
$self->make_thumbnail($_-1) for @new_obj_idx;
# update print
$self->stop_background_process;
$self->{print}->reload_object($_-1) for @new_obj_idx;
$self->on_model_change;
# Empty the redo stack
$self->{redo_stack} = [];
if ($volume_unmatched) {
Slic3r::GUI::warning_catcher($self)->("At least 1 volume couldn't be matched between the original object and the reloaded one.");
}
}
sub export_object_stl {

View File

@ -353,12 +353,18 @@ sub on_btn_load {
next;
}
foreach my $object (@{$model->objects}) {
foreach my $volume (@{$object->volumes}) {
my $new_volume = $self->{model_object}->add_volume($volume);
for my $obj_idx (0..($model->objects_count-1)) {
my $object = $model->objects->[$obj_idx];
for my $vol_idx (0..($object->volumes_count-1)) {
my $new_volume = $self->{model_object}->add_volume($object->get_volume($vol_idx));
$new_volume->set_modifier($is_modifier);
$new_volume->set_name(basename($input_file));
# input_file needed to reload / update modifiers' volumes
$new_volume->set_input_file($input_file);
$new_volume->set_input_file_obj_idx($obj_idx);
$new_volume->set_input_file_vol_idx($vol_idx);
# apply the same translation we applied to the object
$new_volume->mesh->translate(@{$self->{model_object}->origin_translation});

View File

@ -92,6 +92,23 @@ sub new {
tooltip => 'In 2D plater, Move objects using keyboard by nudge value of',
default => $Slic3r::GUI::Settings->{_}{nudge_val},
));
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( # reload hide dialog
opt_id => 'reload_hide_dialog',
type => 'bool',
label => 'Hide Dialog on Reload',
tooltip => 'When checked, the dialog on reloading files with added parts & modifiers is suppressed. The reload is performed according to the option given in \'Default Reload Behavior\'',
default => $Slic3r::GUI::Settings->{_}{reload_hide_dialog},
));
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( # default reload behavior
opt_id => 'reload_behavior',
type => 'select',
label => 'Default Reload Behavior',
tooltip => 'Choose the default behavior of the \'Reload from disk\' function regarding additional parts and modifiers.',
labels => ['Reload all','Reload main, copy added','Reload main, discard added'],
values => [0, 1, 2],
default => $Slic3r::GUI::Settings->{_}{reload_behavior},
width => 180,
));
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( # colorscheme
opt_id => 'colorscheme',
type => 'select',
@ -100,7 +117,7 @@ sub new {
labels => ['Default','Solarized'], # add more schemes, if you want in ColorScheme.pm.
values => ['getDefault','getSolarized'], # add more schemes, if you want - those are the names of the corresponding function in ColorScheme.pm.
default => $Slic3r::GUI::Settings->{_}{colorscheme} // 'getDefault',
width => 130,
width => 180,
));
my $sizer = Wx::BoxSizer->new(wxVERTICAL);

View File

@ -0,0 +1,60 @@
# A tiny dialog to select how to reload an object that has additional parts or modifiers.
package Slic3r::GUI::ReloadDialog;
use strict;
use warnings;
use utf8;
use Wx qw(:button :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_selection) = @_;
my $self = $class->SUPER::new($parent, -1, "Additional parts and modifiers detected", wxDefaultPosition, [350,100], wxDEFAULT_DIALOG_STYLE);
# label
my $text = Wx::StaticText->new($self, -1, "Additional parts and modifiers are loaded in the current model. \n\nHow do you want to proceed?", wxDefaultPosition, wxDefaultSize);
# selector
$self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []);
$choice->Append("Reload all linked files");
$choice->Append("Reload main file, copy added parts & modifiers");
$choice->Append("Reload main file, discard added parts & modifiers");
$choice->SetSelection($default_selection);
# checkbox
$self->{checkbox} = my $checkbox = Wx::CheckBox->new($self, -1, "Don't ask again");
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
$vsizer->Add($text, 0, wxEXPAND | wxALL, 10);
$vsizer->Add($choice, 0, wxEXPAND | wxALL, 10);
$hsizer->Add($checkbox, 1, wxEXPAND | wxALL, 10);
$hsizer->Add($self->CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 10);
$vsizer->Add($hsizer, 0, wxEXPAND | wxALL, 0);
$self->SetSizer($vsizer);
$self->SetMinSize($self->GetSize);
$vsizer->SetSizeHints($self);
# needed to actually free memory
EVT_CLOSE($self, sub {
$self->EndModal(wxID_CANCEL);
$self->Destroy;
});
return $self;
}
sub GetSelection {
my ($self) = @_;
return $self->{choice}->GetSelection;
}
sub GetHideOnNext {
my ($self) = @_;
return $self->{checkbox}->GetValue;
}
1;

View File

@ -79,6 +79,8 @@ mkdir -p $resourcefolder
echo "Copying resources..."
cp -rf $SLIC3R_DIR/var $resourcefolder/
mv $resourcefolder/var/Slic3r.icns $resourcefolder
mv $resourcefolder/var/stl.icns $resourcefolder
mv $resourcefolder/var/gcode.icns $resourcefolder
echo "Copying Slic3r..."
cp $SLIC3R_DIR/slic3r.pl $macosfolder/slic3r.pl

View File

@ -36,66 +36,83 @@ cat << EOF >> $plistfile
<key>CFBundleVersion</key>
<string>${SLIC3R_BUILD_ID}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>stl</string>
<string>STL</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Slic3r.icns</string>
<key>CFBundleTypeName</key>
<string>STL</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>obj</string>
<string>OBJ</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Slic3r.icns</string>
<key>CFBundleTypeName</key>
<string>STL</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>amf</string>
<string>AMF</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Slic3r.icns</string>
<key>CFBundleTypeName</key>
<string>STL</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>
<key>LSMinimumSystemVersion</key>
<string>10.7</string>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>stl</string>
<string>STL</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>stl.icns</string>
<key>CFBundleTypeName</key>
<string>STL</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>obj</string>
<string>OBJ</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Slic3r.icns</string>
<key>CFBundleTypeName</key>
<string>STL</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>amf</string>
<string>AMF</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Slic3r.icns</string>
<key>CFBundleTypeName</key>
<string>STL</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>gcode</string>
<string>GCODE</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>gcode.icns</string>
<key>CFBundleTypeName</key>
<string>GCODE</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LISsAppleDefaultForType</key>
<true/>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>
<key>LSMinimumSystemVersion</key>
<string>10.7</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</dict>
</plist>
EOF

BIN
var/gcode.icns Executable file

Binary file not shown.

BIN
var/gcode.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
var/slt.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
var/stl.icns Executable file

Binary file not shown.

View File

@ -936,12 +936,18 @@ ModelObject::print_info() const
ModelVolume::ModelVolume(ModelObject* object, const TriangleMesh &mesh)
: mesh(mesh), modifier(false), object(object)
: mesh(mesh), modifier(false), input_file(""), object(object)
{}
ModelVolume::ModelVolume(ModelObject* object, const ModelVolume &other)
: name(other.name), mesh(other.mesh), config(other.config),
modifier(other.modifier), object(object)
: name(other.name),
mesh(other.mesh),
config(other.config),
modifier(other.modifier),
input_file(other.input_file),
input_file_obj_idx(other.input_file_obj_idx),
input_file_vol_idx(other.input_file_vol_idx),
object(object)
{
this->material_id(other.material_id());
}
@ -959,6 +965,10 @@ ModelVolume::swap(ModelVolume &other)
std::swap(this->mesh, other.mesh);
std::swap(this->config, other.config);
std::swap(this->modifier, other.modifier);
std::swap(this->input_file, other.input_file);
std::swap(this->input_file_obj_idx, other.input_file_obj_idx);
std::swap(this->input_file_vol_idx, other.input_file_vol_idx);
}
t_model_material_id

View File

@ -458,6 +458,11 @@ class ModelVolume
///< Configuration parameters specific to an object model geometry or a modifier volume,
///< overriding the global Slic3r settings and the ModelObject settings.
/// Input file path needed for reloading the volume from disk
std::string input_file; ///< Input file path
int input_file_obj_idx; ///< Input file object index
int input_file_vol_idx; ///< Input file volume index
bool modifier; ///< Is it an object to be printed, or a modifier volume?
/// Get the parent object owning this modifier volume.

View File

@ -258,6 +258,20 @@ ModelMaterial::attributes()
%code%{ RETVAL = THIS->name; %};
void set_name(std::string value)
%code%{ THIS->name = value; %};
std::string input_file()
%code%{ RETVAL = THIS->input_file; %};
void set_input_file(std::string value)
%code%{ THIS->input_file = value; %};
int input_file_obj_idx()
%code%{ RETVAL = THIS->input_file_obj_idx; %};
void set_input_file_obj_idx(int obj_idx)
%code%{ THIS->input_file_obj_idx = obj_idx; %};
int input_file_vol_idx()
%code%{ RETVAL = THIS->input_file_vol_idx; %};
void set_input_file_vol_idx(int vol_idx)
%code%{ THIS->input_file_vol_idx = vol_idx; %};
t_model_material_id material_id();
void set_material_id(t_model_material_id material_id)
%code%{ THIS->material_id(material_id); %};