Merge remote-tracking branch 'origin/master' into feature_arrange_with_libnest2d
This commit is contained in:
commit
4e901a9db7
39 changed files with 5598 additions and 3029 deletions
|
@ -128,8 +128,8 @@ sub new {
|
|||
}
|
||||
$_->set_scaling_factor($scale) for @{ $model_object->instances };
|
||||
|
||||
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
|
||||
$object->transform_thumbnail($self->{model}, $obj_idx);
|
||||
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
|
||||
# $object->transform_thumbnail($self->{model}, $obj_idx);
|
||||
|
||||
#update print and start background processing
|
||||
$self->{print}->add_model_object($model_object, $obj_idx);
|
||||
|
@ -203,18 +203,19 @@ sub new {
|
|||
Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{canvas3D}, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{preview3D}->canvas, $self->{canvas3D}); });
|
||||
}
|
||||
|
||||
# Initialize 2D preview canvas
|
||||
$self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
|
||||
$self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
|
||||
$self->{canvas}->on_select_object($on_select_object);
|
||||
$self->{canvas}->on_double_click($on_double_click);
|
||||
$self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
|
||||
$self->{canvas}->on_instances_moved($on_instances_moved);
|
||||
# # Initialize 2D preview canvas
|
||||
# $self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
|
||||
# $self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
|
||||
# $self->{canvas}->on_select_object($on_select_object);
|
||||
# $self->{canvas}->on_double_click($on_double_click);
|
||||
# $self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
|
||||
# $self->{canvas}->on_instances_moved($on_instances_moved);
|
||||
|
||||
# Initialize 3D toolpaths preview
|
||||
if ($Slic3r::GUI::have_OpenGL) {
|
||||
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
|
||||
Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
|
||||
Slic3r::GUI::_3DScene::enable_dynamic_background($self->{preview3D}->canvas, 1);
|
||||
Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
|
||||
$self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
|
||||
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
|
||||
|
@ -312,6 +313,9 @@ sub new {
|
|||
my ($list, $event) = @_;
|
||||
if ($event->GetKeyCode == WXK_TAB) {
|
||||
$list->Navigate($event->ShiftDown ? &Wx::wxNavigateBackward : &Wx::wxNavigateForward);
|
||||
} elsif ($event->GetKeyCode == WXK_DELETE ||
|
||||
($event->GetKeyCode == WXK_BACK && &Wx::wxMAC) ) {
|
||||
$self->remove;
|
||||
} else {
|
||||
$event->Skip;
|
||||
}
|
||||
|
@ -401,7 +405,8 @@ sub new {
|
|||
|
||||
$_->SetDropTarget(Slic3r::GUI::Plater::DropTarget->new($self))
|
||||
for grep defined($_),
|
||||
$self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D}, $self->{list};
|
||||
$self, $self->{canvas3D}, $self->{preview3D}, $self->{list};
|
||||
# $self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D}, $self->{list};
|
||||
|
||||
EVT_COMMAND($self, -1, $PROGRESS_BAR_EVENT, sub {
|
||||
my ($self, $event) = @_;
|
||||
|
@ -432,7 +437,7 @@ sub new {
|
|||
});
|
||||
}
|
||||
|
||||
$self->{canvas}->update_bed_size;
|
||||
# $self->{canvas}->update_bed_size;
|
||||
if ($self->{canvas3D}) {
|
||||
Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape);
|
||||
Slic3r::GUI::_3DScene::zoom_to_bed($self->{canvas3D});
|
||||
|
@ -847,8 +852,8 @@ sub load_model_objects {
|
|||
|
||||
$self->{list}->SetItem($obj_idx, 1, $model_object->instances_count);
|
||||
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
|
||||
|
||||
$self->reset_thumbnail($obj_idx);
|
||||
|
||||
# $self->reset_thumbnail($obj_idx);
|
||||
}
|
||||
$self->arrange if $need_arrange;
|
||||
$self->update;
|
||||
|
@ -1057,7 +1062,7 @@ sub rotate {
|
|||
$inst->set_rotation($rotation);
|
||||
Slic3r::GUI::_3DScene::update_gizmos_data($self->{canvas3D}) if ($self->{canvas3D});
|
||||
}
|
||||
$object->transform_thumbnail($self->{model}, $obj_idx);
|
||||
# $object->transform_thumbnail($self->{model}, $obj_idx);
|
||||
} else {
|
||||
# rotation around X and Y needs to be performed on mesh
|
||||
# so we first apply any Z rotation
|
||||
|
@ -1067,9 +1072,9 @@ sub rotate {
|
|||
}
|
||||
$model_object->rotate(deg2rad($angle), $axis);
|
||||
|
||||
# realign object to Z = 0
|
||||
$model_object->center_around_origin;
|
||||
$self->reset_thumbnail($obj_idx);
|
||||
# # realign object to Z = 0
|
||||
# $model_object->center_around_origin;
|
||||
# $self->reset_thumbnail($obj_idx);
|
||||
}
|
||||
|
||||
# update print and start background processing
|
||||
|
@ -1097,9 +1102,9 @@ sub mirror {
|
|||
|
||||
$model_object->mirror($axis);
|
||||
|
||||
# realign object to Z = 0
|
||||
$model_object->center_around_origin;
|
||||
$self->reset_thumbnail($obj_idx);
|
||||
# # realign object to Z = 0
|
||||
# $model_object->center_around_origin;
|
||||
# $self->reset_thumbnail($obj_idx);
|
||||
|
||||
# update print and start background processing
|
||||
$self->stop_background_process;
|
||||
|
@ -1149,7 +1154,7 @@ sub changescale {
|
|||
#FIXME Scale the layer height profile when $axis == Z?
|
||||
#FIXME Scale the layer height ranges $axis == Z?
|
||||
# object was already aligned to Z = 0, so no need to realign it
|
||||
$self->reset_thumbnail($obj_idx);
|
||||
# $self->reset_thumbnail($obj_idx);
|
||||
} else {
|
||||
my $scale;
|
||||
if ($tosize) {
|
||||
|
@ -1173,7 +1178,7 @@ sub changescale {
|
|||
$range->[1] *= $variation;
|
||||
}
|
||||
$_->set_scaling_factor($scale) for @{ $model_object->instances };
|
||||
$object->transform_thumbnail($self->{model}, $obj_idx);
|
||||
# $object->transform_thumbnail($self->{model}, $obj_idx);
|
||||
}
|
||||
|
||||
# update print and start background processing
|
||||
|
@ -1804,10 +1809,10 @@ sub _get_export_file {
|
|||
return $output_file;
|
||||
}
|
||||
|
||||
sub reset_thumbnail {
|
||||
my ($self, $obj_idx) = @_;
|
||||
$self->{objects}[$obj_idx]->thumbnail(undef);
|
||||
}
|
||||
#sub reset_thumbnail {
|
||||
# my ($self, $obj_idx) = @_;
|
||||
# $self->{objects}[$obj_idx]->thumbnail(undef);
|
||||
#}
|
||||
|
||||
# this method gets called whenever print center is changed or the objects' bounding box changes
|
||||
# (i.e. when an object is added/removed/moved/rotated/scaled)
|
||||
|
@ -1831,7 +1836,7 @@ sub update {
|
|||
$self->resume_background_process;
|
||||
}
|
||||
|
||||
$self->{canvas}->reload_scene if $self->{canvas};
|
||||
# $self->{canvas}->reload_scene if $self->{canvas};
|
||||
my $selections = $self->collect_selections;
|
||||
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
|
||||
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
|
||||
|
@ -1888,7 +1893,7 @@ sub on_config_change {
|
|||
foreach my $opt_key (@{$self->{config}->diff($config)}) {
|
||||
$self->{config}->set($opt_key, $config->get($opt_key));
|
||||
if ($opt_key eq 'bed_shape') {
|
||||
$self->{canvas}->update_bed_size;
|
||||
# $self->{canvas}->update_bed_size;
|
||||
Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape) if $self->{canvas3D};
|
||||
Slic3r::GUI::_3DScene::set_bed_shape($self->{preview3D}->canvas, $self->{config}->bed_shape) if $self->{preview3D};
|
||||
$update_scheduled = 1;
|
||||
|
@ -1948,7 +1953,7 @@ sub list_item_deselected {
|
|||
$self->{_lecursor} = Wx::BusyCursor->new();
|
||||
if ($self->{list}->GetFirstSelected == -1) {
|
||||
$self->select_object(undef);
|
||||
$self->{canvas}->Refresh;
|
||||
# $self->{canvas}->Refresh;
|
||||
Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D}) if $self->{canvas3D};
|
||||
Slic3r::GUI::_3DScene::render($self->{canvas3D}) if $self->{canvas3D};
|
||||
}
|
||||
|
@ -1961,7 +1966,7 @@ sub list_item_selected {
|
|||
$self->{_lecursor} = Wx::BusyCursor->new();
|
||||
my $obj_idx = $event->GetIndex;
|
||||
$self->select_object($obj_idx);
|
||||
$self->{canvas}->Refresh;
|
||||
# $self->{canvas}->Refresh;
|
||||
if ($self->{canvas3D}) {
|
||||
my $selections = $self->collect_selections;
|
||||
Slic3r::GUI::_3DScene::update_volumes_selection($self->{canvas3D}, \@$selections);
|
||||
|
@ -2058,19 +2063,19 @@ sub object_settings_dialog {
|
|||
$self->pause_background_process;
|
||||
$dlg->ShowModal;
|
||||
|
||||
# update thumbnail since parts may have changed
|
||||
if ($dlg->PartsChanged) {
|
||||
# recenter and re-align to Z = 0
|
||||
$model_object->center_around_origin;
|
||||
$self->reset_thumbnail($obj_idx);
|
||||
}
|
||||
# # update thumbnail since parts may have changed
|
||||
# if ($dlg->PartsChanged) {
|
||||
# # recenter and re-align to Z = 0
|
||||
# $model_object->center_around_origin;
|
||||
# $self->reset_thumbnail($obj_idx);
|
||||
# }
|
||||
|
||||
# update print
|
||||
if ($dlg->PartsChanged || $dlg->PartSettingsChanged) {
|
||||
$self->stop_background_process;
|
||||
$self->{print}->reload_object($obj_idx);
|
||||
$self->schedule_background_process;
|
||||
$self->{canvas}->reload_scene if $self->{canvas};
|
||||
# $self->{canvas}->reload_scene if $self->{canvas};
|
||||
my $selections = $self->collect_selections;
|
||||
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
|
||||
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
|
||||
|
@ -2356,48 +2361,48 @@ package Slic3r::GUI::Plater::Object;
|
|||
use Moo;
|
||||
|
||||
has 'name' => (is => 'rw', required => 1);
|
||||
has 'thumbnail' => (is => 'rw'); # ExPolygon::Collection in scaled model units with no transforms
|
||||
has 'transformed_thumbnail' => (is => 'rw');
|
||||
has 'instance_thumbnails' => (is => 'ro', default => sub { [] }); # array of ExPolygon::Collection objects, each one representing the actual placed thumbnail of each instance in pixel units
|
||||
#has 'thumbnail' => (is => 'rw'); # ExPolygon::Collection in scaled model units with no transforms
|
||||
#has 'transformed_thumbnail' => (is => 'rw');
|
||||
#has 'instance_thumbnails' => (is => 'ro', default => sub { [] }); # array of ExPolygon::Collection objects, each one representing the actual placed thumbnail of each instance in pixel units
|
||||
has 'selected' => (is => 'rw', default => sub { 0 });
|
||||
|
||||
sub make_thumbnail {
|
||||
my ($self, $model, $obj_idx) = @_;
|
||||
# make method idempotent
|
||||
$self->thumbnail->clear;
|
||||
# raw_mesh is the non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
|
||||
my $mesh = $model->objects->[$obj_idx]->raw_mesh;
|
||||
#FIXME The "correct" variant could be extremely slow.
|
||||
# if ($mesh->facets_count <= 5000) {
|
||||
# # remove polygons with area <= 1mm
|
||||
# my $area_threshold = Slic3r::Geometry::scale 1;
|
||||
# $self->thumbnail->append(
|
||||
# grep $_->area >= $area_threshold,
|
||||
# @{ $mesh->horizontal_projection }, # horizontal_projection returns scaled expolygons
|
||||
# );
|
||||
# $self->thumbnail->simplify(0.5);
|
||||
# } else {
|
||||
my $convex_hull = Slic3r::ExPolygon->new($mesh->convex_hull);
|
||||
$self->thumbnail->append($convex_hull);
|
||||
# }
|
||||
return $self->thumbnail;
|
||||
}
|
||||
|
||||
sub transform_thumbnail {
|
||||
my ($self, $model, $obj_idx) = @_;
|
||||
|
||||
return unless defined $self->thumbnail;
|
||||
|
||||
my $model_object = $model->objects->[$obj_idx];
|
||||
my $model_instance = $model_object->instances->[0];
|
||||
|
||||
# the order of these transformations MUST be the same everywhere, including
|
||||
# in Slic3r::Print->add_model_object()
|
||||
my $t = $self->thumbnail->clone;
|
||||
$t->rotate($model_instance->rotation, Slic3r::Point->new(0,0));
|
||||
$t->scale($model_instance->scaling_factor);
|
||||
|
||||
$self->transformed_thumbnail($t);
|
||||
}
|
||||
#sub make_thumbnail {
|
||||
# my ($self, $model, $obj_idx) = @_;
|
||||
# # make method idempotent
|
||||
# $self->thumbnail->clear;
|
||||
# # raw_mesh is the non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
|
||||
# my $mesh = $model->objects->[$obj_idx]->raw_mesh;
|
||||
##FIXME The "correct" variant could be extremely slow.
|
||||
## if ($mesh->facets_count <= 5000) {
|
||||
## # remove polygons with area <= 1mm
|
||||
## my $area_threshold = Slic3r::Geometry::scale 1;
|
||||
## $self->thumbnail->append(
|
||||
## grep $_->area >= $area_threshold,
|
||||
## @{ $mesh->horizontal_projection }, # horizontal_projection returns scaled expolygons
|
||||
## );
|
||||
## $self->thumbnail->simplify(0.5);
|
||||
## } else {
|
||||
# my $convex_hull = Slic3r::ExPolygon->new($mesh->convex_hull);
|
||||
# $self->thumbnail->append($convex_hull);
|
||||
## }
|
||||
# return $self->thumbnail;
|
||||
#}
|
||||
#
|
||||
#sub transform_thumbnail {
|
||||
# my ($self, $model, $obj_idx) = @_;
|
||||
#
|
||||
# return unless defined $self->thumbnail;
|
||||
#
|
||||
# my $model_object = $model->objects->[$obj_idx];
|
||||
# my $model_instance = $model_object->instances->[0];
|
||||
#
|
||||
# # the order of these transformations MUST be the same everywhere, including
|
||||
# # in Slic3r::Print->add_model_object()
|
||||
# my $t = $self->thumbnail->clone;
|
||||
# $t->rotate($model_instance->rotation, Slic3r::Point->new(0,0));
|
||||
# $t->scale($model_instance->scaling_factor);
|
||||
#
|
||||
# $self->transformed_thumbnail($t);
|
||||
#}
|
||||
|
||||
1;
|
||||
|
|
|
@ -25,6 +25,7 @@ sub new {
|
|||
# init GUI elements
|
||||
my $canvas = Slic3r::GUI::3DScene->new($self);
|
||||
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,
|
||||
|
@ -365,16 +366,8 @@ sub load_print {
|
|||
if ($self->gcode_preview_data->empty) {
|
||||
# load skirt and brim
|
||||
Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
|
||||
Slic3r::GUI::_3DScene::load_print_toolpaths($self->canvas);
|
||||
Slic3r::GUI::_3DScene::load_wipe_tower_toolpaths($self->canvas, \@colors);
|
||||
foreach my $object (@{$self->print->objects}) {
|
||||
Slic3r::GUI::_3DScene::load_print_object_toolpaths($self->canvas, $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::load_preview($self->canvas, \@colors);
|
||||
$self->show_hide_ui_elements('simple');
|
||||
Slic3r::GUI::_3DScene::reset_legend_texture();
|
||||
} else {
|
||||
$self->{force_sliders_full_range} = (Slic3r::GUI::_3DScene::get_volumes_count($self->canvas) == 0);
|
||||
Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 41 KiB |
BIN
resources/icons/printers/PrusaResearch_MK3MMU2.png
Normal file
BIN
resources/icons/printers/PrusaResearch_MK3MMU2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,5 @@
|
|||
min_slic3r_version = 1.41.0-alpha
|
||||
0.2.0-alpha3
|
||||
0.2.0-alpha2 Renamed the key MK3SMMU to MK3MMU2, added a generic PLA MMU2 material
|
||||
0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0
|
||||
0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
name = Prusa Research
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the Slic3r configuration to be downgraded.
|
||||
config_version = 0.2.0-alpha2
|
||||
config_version = 0.2.0-alpha3
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/
|
||||
|
||||
|
@ -14,26 +14,27 @@ config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/ma
|
|||
#TODO: One day we may differentiate variants of the nozzles / hot ends,
|
||||
#for example by the melt zone size, or whether the nozzle is hardened.
|
||||
# Printer model name will be shown by the installation wizard.
|
||||
|
||||
[printer_model:MK3]
|
||||
name = Original Prusa i3 MK3
|
||||
variants = 0.4; 0.25; 0.6
|
||||
|
||||
[printer_model:MK2S]
|
||||
name = Original Prusa i3 MK2S
|
||||
variants = 0.4; 0.25; 0.6
|
||||
|
||||
[printer_model:MK2.5]
|
||||
name = Original Prusa i3 MK2.5
|
||||
variants = 0.4; 0.25; 0.6
|
||||
|
||||
[printer_model:MK2SMM]
|
||||
name = Original Prusa i3 MK2S Multi Material Upgrade
|
||||
variants = 0.4; 0.6
|
||||
[printer_model:MK2S]
|
||||
name = Original Prusa i3 MK2/S
|
||||
variants = 0.4; 0.25; 0.6
|
||||
|
||||
[printer_model:MK3MM2]
|
||||
name = Original Prusa i3 MK3 Multi Material Upgrade 2.0
|
||||
[printer_model:MK3MMU2]
|
||||
name = Original Prusa i3 MK3 MMU 2.0
|
||||
variants = 0.4
|
||||
|
||||
[printer_model:MK2SMM]
|
||||
name = Original Prusa i3 MK2/S MMU 1.0
|
||||
variants = 0.4; 0.6
|
||||
|
||||
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||
# not make it into the user interface.
|
||||
|
||||
|
@ -85,7 +86,7 @@ notes =
|
|||
overhangs = 0
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = [input_filename_base].gcode
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}.gcode
|
||||
perimeters = 2
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0.45
|
||||
|
@ -131,8 +132,8 @@ wipe_tower = 1
|
|||
wipe_tower_bridging = 10
|
||||
wipe_tower_rotation_angle = 0
|
||||
wipe_tower_width = 60
|
||||
wipe_tower_x = 180
|
||||
wipe_tower_y = 140
|
||||
wipe_tower_x = 200
|
||||
wipe_tower_y = 155
|
||||
xy_size_compensation = 0
|
||||
|
||||
# Print parameters common to a 0.25mm diameter nozzle.
|
||||
|
@ -259,7 +260,7 @@ bridge_speed = 30
|
|||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -286,7 +287,7 @@ bridge_speed = 30
|
|||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -299,7 +300,7 @@ bridge_speed = 30
|
|||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -362,10 +363,10 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and
|
|||
[print:0.15mm OPTIMAL MK3]
|
||||
inherits = *0.15mm*
|
||||
bridge_speed = 30
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -397,7 +398,7 @@ bridge_speed = 30
|
|||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -408,7 +409,7 @@ inherits = *common*
|
|||
bottom_solid_layers = 4
|
||||
bridge_flow_ratio = 0.95
|
||||
external_perimeter_speed = 40
|
||||
infill_acceleration = 2000
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 60
|
||||
layer_height = 0.2
|
||||
perimeter_acceleration = 800
|
||||
|
@ -423,39 +424,13 @@ bridge_speed = 30
|
|||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 200
|
||||
top_solid_infill_speed = 50
|
||||
|
||||
[print:0.15mm OPTIMAL MK3 MMU2]
|
||||
inherits = 0.15mm OPTIMAL MK3
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material
|
||||
bottom_solid_layers = 4
|
||||
external_perimeter_speed = 40
|
||||
fill_density = 10%
|
||||
infill_overlap = 15%
|
||||
perimeter_speed = 60
|
||||
small_perimeter_speed = 20
|
||||
support_material_threshold = 20
|
||||
top_solid_layers = 5
|
||||
|
||||
[print:0.20mm FAST MK3 MMU2]
|
||||
inherits = 0.20mm FAST MK3
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material
|
||||
bridge_flow_ratio = 0.8
|
||||
external_perimeter_speed = 40
|
||||
fill_density = 15%
|
||||
infill_overlap = 35%
|
||||
infill_speed = 150
|
||||
perimeter_speed = 50
|
||||
small_perimeter_speed = 20
|
||||
solid_infill_speed = 150
|
||||
wipe_tower_x = 169
|
||||
wipe_tower_y = 137
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.20mm ---XXX
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
|
@ -475,10 +450,10 @@ top_solid_infill_speed = 70
|
|||
[print:0.20mm FAST MK3]
|
||||
inherits = *0.20mm*
|
||||
bridge_speed = 30
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -516,7 +491,7 @@ bridge_speed = 30
|
|||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
fill_pattern = grid
|
||||
infill_acceleration = 1500
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
|
@ -680,6 +655,8 @@ inherits = *PLA*
|
|||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 80.65
|
||||
filament_density = 4
|
||||
filament_colour = #804040
|
||||
filament_max_volumetric_speed = 10
|
||||
|
||||
|
@ -700,12 +677,16 @@ temperature = 270
|
|||
|
||||
[filament:ColorFabb PLA-PHA]
|
||||
inherits = *PLA*
|
||||
filament_cost = 55.5
|
||||
filament_density = 1.24
|
||||
|
||||
[filament:ColorFabb Woodfil]
|
||||
inherits = *PLA*
|
||||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 62.9
|
||||
filament_density = 1.15
|
||||
filament_colour = #804040
|
||||
filament_max_volumetric_speed = 10
|
||||
first_layer_temperature = 200
|
||||
|
@ -714,7 +695,9 @@ temperature = 200
|
|||
|
||||
[filament:ColorFabb XT]
|
||||
inherits = *PET*
|
||||
filament_type = PLA
|
||||
filament_type = PET
|
||||
filament_cost = 62.9
|
||||
filament_density = 1.27
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 260
|
||||
temperature = 270
|
||||
|
@ -722,6 +705,8 @@ temperature = 270
|
|||
[filament:ColorFabb XT-CF20]
|
||||
inherits = *PET*
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 80.65
|
||||
filament_density = 1.35
|
||||
filament_colour = #804040
|
||||
filament_max_volumetric_speed = 1
|
||||
first_layer_bed_temperature = 90
|
||||
|
@ -731,6 +716,8 @@ temperature = 260
|
|||
|
||||
[filament:ColorFabb nGen]
|
||||
inherits = *PET*
|
||||
filament_cost = 21.2
|
||||
filament_density = 1.2
|
||||
bridge_fan_speed = 40
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 10
|
||||
|
@ -741,6 +728,8 @@ min_fan_speed = 20
|
|||
|
||||
[filament:ColorFabb nGen flex]
|
||||
inherits = *FLEX*
|
||||
filament_cost = 0
|
||||
filament_density = 1
|
||||
bed_temperature = 85
|
||||
bridge_fan_speed = 40
|
||||
cooling = 1
|
||||
|
@ -756,26 +745,36 @@ temperature = 260
|
|||
|
||||
[filament:E3D Edge]
|
||||
inherits = *PET*
|
||||
filament_cost = 0
|
||||
filament_density = 1.26
|
||||
filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG"
|
||||
|
||||
[filament:E3D PC-ABS]
|
||||
inherits = *ABS*
|
||||
filament_cost = 0
|
||||
filament_density = 1.05
|
||||
first_layer_temperature = 270
|
||||
temperature = 270
|
||||
|
||||
[filament:Fillamentum ABS]
|
||||
inherits = *ABS*
|
||||
filament_cost = 0
|
||||
filament_density = 1.04
|
||||
first_layer_temperature = 240
|
||||
temperature = 240
|
||||
|
||||
[filament:Fillamentum ASA]
|
||||
inherits = *ABS*
|
||||
filament_cost = 0
|
||||
filament_density = 1.04
|
||||
fan_always_on = 1
|
||||
first_layer_temperature = 265
|
||||
temperature = 265
|
||||
|
||||
[filament:Fillamentum CPE HG100 HM100]
|
||||
inherits = *PET*
|
||||
filament_cost = 0
|
||||
filament_density = 1.25
|
||||
filament_notes = "CPE HG100 , CPE HM100"
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 275
|
||||
|
@ -788,6 +787,8 @@ inherits = *PLA*
|
|||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 0
|
||||
filament_density = 1.15
|
||||
filament_colour = #804040
|
||||
filament_max_volumetric_speed = 10
|
||||
first_layer_temperature = 190
|
||||
|
@ -796,14 +797,20 @@ temperature = 190
|
|||
|
||||
[filament:Generic ABS]
|
||||
inherits = *ABS*
|
||||
filament_cost = 0
|
||||
filament_density = 1.04
|
||||
filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS"
|
||||
|
||||
[filament:Generic PET]
|
||||
inherits = *PET*
|
||||
filament_cost = 0
|
||||
filament_density = 1.24
|
||||
filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG"
|
||||
|
||||
[filament:Generic PLA]
|
||||
inherits = *PLA*
|
||||
filament_cost = 0
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
|
||||
[filament:Polymaker PC-Max]
|
||||
|
@ -830,8 +837,25 @@ temperature = 195
|
|||
|
||||
[filament:Prusa ABS]
|
||||
inherits = *ABS*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS"
|
||||
|
||||
[filament:*ABS MMU2*]
|
||||
inherits = Prusa ABS
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material
|
||||
filament_cooling_final_speed = 50
|
||||
filament_cooling_initial_speed = 10
|
||||
filament_cooling_moves = 5
|
||||
filament_loading_speed = 14
|
||||
filament_ramming_parameters = "120 110 5.32258 5.45161 5.67742 6 6.48387 7.12903 7.90323 8.70968 9.3871 9.83871 10.0968 10.2258| 0.05 5.30967 0.45 5.50967 0.95 6.1871 1.45 7.39677 1.95 9.05484 2.45 10 2.95 10.3098 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6";
|
||||
|
||||
[filament:Generic ABS MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
|
||||
[filament:Prusa ABS MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
|
||||
[filament:Prusa HIPS]
|
||||
inherits = *ABS*
|
||||
bridge_fan_speed = 50
|
||||
|
@ -850,10 +874,14 @@ temperature = 220
|
|||
|
||||
[filament:Prusa PET]
|
||||
inherits = *PET*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG"
|
||||
|
||||
[filament:Prusa PLA]
|
||||
inherits = *PLA*
|
||||
filament_cost = 25.4
|
||||
filament_density = 1.24
|
||||
filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
|
||||
[filament:*PLA MMU2*]
|
||||
|
@ -873,6 +901,8 @@ inherits = *PLA MMU2*
|
|||
|
||||
[filament:SemiFlex or Flexfill 98A]
|
||||
inherits = *FLEX*
|
||||
filament_cost = 0
|
||||
filament_density = 1.22
|
||||
|
||||
[filament:Taulman Bridge]
|
||||
inherits = *common*
|
||||
|
@ -956,7 +986,7 @@ extruder_offset = 0x0
|
|||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
machine_max_acceleration_e = 10000
|
||||
machine_max_acceleration_extruding = 1500
|
||||
machine_max_acceleration_extruding = 2000
|
||||
machine_max_acceleration_retracting = 1500
|
||||
machine_max_acceleration_x = 9000
|
||||
machine_max_acceleration_y = 9000
|
||||
|
@ -1118,11 +1148,11 @@ start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM83 ; extruder rela
|
|||
[printer:Original Prusa i3 MK3]
|
||||
inherits = *common*
|
||||
end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors
|
||||
machine_max_acceleration_e = 9000,9000
|
||||
machine_max_acceleration_extruding = 1250,960
|
||||
machine_max_acceleration_e = 5000,5000
|
||||
machine_max_acceleration_extruding = 1250,1250
|
||||
machine_max_acceleration_retracting = 1250,1250
|
||||
machine_max_acceleration_x = 1000,1000
|
||||
machine_max_acceleration_y = 1000,1000
|
||||
machine_max_acceleration_x = 1000,960
|
||||
machine_max_acceleration_y = 1000,960
|
||||
machine_max_acceleration_z = 1000,1000
|
||||
machine_max_feedrate_e = 120,120
|
||||
machine_max_feedrate_x = 200,172
|
||||
|
@ -1167,8 +1197,8 @@ cooling_tube_retraction = 30
|
|||
parking_pos_retraction = 85
|
||||
retract_length_toolchange = 3
|
||||
extra_loading_move = -13
|
||||
printer_model = MK3MM2
|
||||
default_print_profile = 0.15mm OPTIMAL MK3 MMU2
|
||||
printer_model = MK3MMU2
|
||||
default_print_profile = 0.15mm OPTIMAL MK3
|
||||
default_filament_profile = Prusa PLA MMU2
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2 Single]
|
||||
|
@ -1182,11 +1212,11 @@ inherits = *mm2*
|
|||
# (for example the retract values) are duplicaed from the first value, so they do not need
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FFFF00;#FFFFFF;#804040;#0000FF;#C0C0C0
|
||||
extruder_colour = #FF8000;#0080FF;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M107\n\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = G1 E-15.0000 F3000\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
|
||||
|
||||
# The obsolete presets will be removed when upgrading from the legacy configuration structure (up to Slic3r 1.39.2) to 1.40.0 and newer.
|
||||
[obsolete_presets]
|
||||
print="0.05mm DETAIL 0.25 nozzle";"0.05mm DETAIL MK3";"0.05mm DETAIL";"0.20mm NORMAL MK3";"0.35mm FAST MK3"
|
||||
print="0.05mm DETAIL 0.25 nozzle";"0.05mm DETAIL MK3";"0.05mm DETAIL";"0.20mm NORMAL MK3";"0.35mm FAST MK3";"print:0.15mm OPTIMAL MK3 MMU2";"print:0.20mm FAST MK3 MMU2"
|
||||
filament="ColorFabb Brass Bronze 1.75mm";"ColorFabb HT 1.75mm";"ColorFabb nGen 1.75mm";"ColorFabb Woodfil 1.75mm";"ColorFabb XT 1.75mm";"ColorFabb XT-CF20 1.75mm";"E3D PC-ABS 1.75mm";"Fillamentum ABS 1.75mm";"Fillamentum ASA 1.75mm";"Generic ABS 1.75mm";"Generic PET 1.75mm";"Generic PLA 1.75mm";"Prusa ABS 1.75mm";"Prusa HIPS 1.75mm";"Prusa PET 1.75mm";"Prusa PLA 1.75mm";"Taulman Bridge 1.75mm";"Taulman T-Glase 1.75mm"
|
||||
|
|
|
@ -26,7 +26,7 @@ include_directories(${LIBDIR}/libslic3r)
|
|||
|
||||
if(WIN32)
|
||||
# BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking.
|
||||
add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB)
|
||||
add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601)
|
||||
# -D_ITERATOR_DEBUG_LEVEL)
|
||||
if(WIN10SDK_PATH)
|
||||
message("Building with Win10 Netfabb STL fixing service support")
|
||||
|
@ -258,6 +258,8 @@ add_library(libslic3r_gui STATIC
|
|||
${LIBDIR}/slic3r/Utils/PresetUpdater.hpp
|
||||
${LIBDIR}/slic3r/Utils/Time.cpp
|
||||
${LIBDIR}/slic3r/Utils/Time.hpp
|
||||
${LIBDIR}/slic3r/Utils/HexFile.cpp
|
||||
${LIBDIR}/slic3r/Utils/HexFile.hpp
|
||||
${LIBDIR}/slic3r/IProgressIndicator.hpp
|
||||
${LIBDIR}/slic3r/AppController.hpp
|
||||
${LIBDIR}/slic3r/AppController.cpp
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
|
||||
add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE) # To enable various useful macros and functions on Unices
|
||||
|
@ -13,67 +14,74 @@ endif()
|
|||
|
||||
|
||||
set(AVRDUDE_SOURCES
|
||||
${LIBDIR}/avrdude/arduino.c
|
||||
${LIBDIR}/avrdude/avr.c
|
||||
# ${LIBDIR}/avrdude/avrftdi.c
|
||||
# ${LIBDIR}/avrdude/avrftdi_tpi.c
|
||||
${LIBDIR}/avrdude/avrpart.c
|
||||
${LIBDIR}/avrdude/avr910.c
|
||||
${LIBDIR}/avrdude/bitbang.c
|
||||
${LIBDIR}/avrdude/buspirate.c
|
||||
${LIBDIR}/avrdude/butterfly.c
|
||||
${LIBDIR}/avrdude/config.c
|
||||
${LIBDIR}/avrdude/config_gram.c
|
||||
# ${LIBDIR}/avrdude/confwin.c
|
||||
${LIBDIR}/avrdude/crc16.c
|
||||
# ${LIBDIR}/avrdude/dfu.c
|
||||
${LIBDIR}/avrdude/fileio.c
|
||||
# ${LIBDIR}/avrdude/flip1.c
|
||||
# ${LIBDIR}/avrdude/flip2.c
|
||||
# ${LIBDIR}/avrdude/ft245r.c
|
||||
# ${LIBDIR}/avrdude/jtagmkI.c
|
||||
# ${LIBDIR}/avrdude/jtagmkII.c
|
||||
# ${LIBDIR}/avrdude/jtag3.c
|
||||
${LIBDIR}/avrdude/lexer.c
|
||||
${LIBDIR}/avrdude/linuxgpio.c
|
||||
${LIBDIR}/avrdude/lists.c
|
||||
# ${LIBDIR}/avrdude/par.c
|
||||
${LIBDIR}/avrdude/pgm.c
|
||||
${LIBDIR}/avrdude/pgm_type.c
|
||||
${LIBDIR}/avrdude/pickit2.c
|
||||
${LIBDIR}/avrdude/pindefs.c
|
||||
# ${LIBDIR}/avrdude/ppi.c
|
||||
# ${LIBDIR}/avrdude/ppiwin.c
|
||||
${LIBDIR}/avrdude/safemode.c
|
||||
${LIBDIR}/avrdude/ser_avrdoper.c
|
||||
${LIBDIR}/avrdude/serbb_posix.c
|
||||
${LIBDIR}/avrdude/serbb_win32.c
|
||||
${LIBDIR}/avrdude/ser_posix.c
|
||||
${LIBDIR}/avrdude/ser_win32.c
|
||||
${LIBDIR}/avrdude/stk500.c
|
||||
${LIBDIR}/avrdude/stk500generic.c
|
||||
${LIBDIR}/avrdude/stk500v2.c
|
||||
${LIBDIR}/avrdude/term.c
|
||||
${LIBDIR}/avrdude/update.c
|
||||
# ${LIBDIR}/avrdude/usbasp.c
|
||||
# ${LIBDIR}/avrdude/usb_hidapi.c
|
||||
# ${LIBDIR}/avrdude/usb_libusb.c
|
||||
# ${LIBDIR}/avrdude/usbtiny.c
|
||||
${LIBDIR}/avrdude/wiring.c
|
||||
arduino.c
|
||||
avr.c
|
||||
# avrftdi.c
|
||||
# avrftdi_tpi.c
|
||||
avrpart.c
|
||||
avr910.c
|
||||
bitbang.c
|
||||
buspirate.c
|
||||
butterfly.c
|
||||
config.c
|
||||
config_gram.c
|
||||
# confwin.c
|
||||
crc16.c
|
||||
# dfu.c
|
||||
fileio.c
|
||||
# flip1.c
|
||||
# flip2.c
|
||||
# ft245r.c
|
||||
# jtagmkI.c
|
||||
# jtagmkII.c
|
||||
# jtag3.c
|
||||
lexer.c
|
||||
linuxgpio.c
|
||||
lists.c
|
||||
# par.c
|
||||
pgm.c
|
||||
pgm_type.c
|
||||
pickit2.c
|
||||
pindefs.c
|
||||
# ppi.c
|
||||
# ppiwin.c
|
||||
safemode.c
|
||||
ser_avrdoper.c
|
||||
serbb_posix.c
|
||||
serbb_win32.c
|
||||
ser_posix.c
|
||||
ser_win32.c
|
||||
stk500.c
|
||||
stk500generic.c
|
||||
stk500v2.c
|
||||
term.c
|
||||
update.c
|
||||
# usbasp.c
|
||||
# usb_hidapi.c
|
||||
# usb_libusb.c
|
||||
# usbtiny.c
|
||||
wiring.c
|
||||
|
||||
${LIBDIR}/avrdude/main.c
|
||||
${LIBDIR}/avrdude/avrdude-slic3r.hpp
|
||||
${LIBDIR}/avrdude/avrdude-slic3r.cpp
|
||||
main.c
|
||||
avrdude-slic3r.hpp
|
||||
avrdude-slic3r.cpp
|
||||
)
|
||||
if (WIN32)
|
||||
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
|
||||
${LIBDIR}/avrdude/windows/unistd.cpp
|
||||
${LIBDIR}/avrdude/windows/getopt.c
|
||||
windows/unistd.cpp
|
||||
windows/getopt.c
|
||||
)
|
||||
endif()
|
||||
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
||||
|
||||
set(STANDALONE_SOURCES
|
||||
main-standalone.c
|
||||
)
|
||||
add_executable(avrdude-slic3r ${STANDALONE_SOURCES})
|
||||
target_link_libraries(avrdude-slic3r avrdude)
|
||||
set_target_properties(avrdude-slic3r PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
if (WIN32)
|
||||
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
|
||||
target_include_directories(avrdude SYSTEM PRIVATE ${LIBDIR}/avrdude/windows) # So that sources find the getopt.h windows drop-in
|
||||
target_include_directories(avrdude SYSTEM PRIVATE windows) # So that sources find the getopt.h windows drop-in
|
||||
endif()
|
||||
|
|
54
xs/src/avrdude/Makefile.standalone
Normal file
54
xs/src/avrdude/Makefile.standalone
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
TARGET = avrdude-slic3r
|
||||
|
||||
SOURCES = \
|
||||
arduino.c \
|
||||
avr.c \
|
||||
avrpart.c \
|
||||
avr910.c \
|
||||
bitbang.c \
|
||||
buspirate.c \
|
||||
butterfly.c \
|
||||
config.c \
|
||||
config_gram.c \
|
||||
crc16.c \
|
||||
fileio.c \
|
||||
lexer.c \
|
||||
linuxgpio.c \
|
||||
lists.c \
|
||||
pgm.c \
|
||||
pgm_type.c \
|
||||
pickit2.c \
|
||||
pindefs.c \
|
||||
safemode.c \
|
||||
ser_avrdoper.c \
|
||||
serbb_posix.c \
|
||||
serbb_win32.c \
|
||||
ser_posix.c \
|
||||
ser_win32.c \
|
||||
stk500.c \
|
||||
stk500generic.c \
|
||||
stk500v2.c \
|
||||
term.c \
|
||||
update.c \
|
||||
wiring.c \
|
||||
main.c \
|
||||
main-standalone.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
CFLAGS = -std=c99 -Wall -D_BSD_SOURCE -D_DEFAULT_SOURCE -O3 -DNDEBUG -fPIC
|
||||
LDFLAGS = -lm
|
||||
|
||||
CC = gcc
|
||||
RM = rm
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) -o ./$@ $(OBJECTS) $(LDFLAGS)
|
||||
|
||||
$(OBJECTS): %.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
$(RM) -f $(OBJECTS) $(TARGET)
|
|
@ -36,6 +36,7 @@ struct AvrDude::priv
|
|||
std::string sys_config;
|
||||
std::deque<std::vector<std::string>> args;
|
||||
size_t current_args_set = 0;
|
||||
bool cancelled = false;
|
||||
RunFn run_fn;
|
||||
MessageFn message_fn;
|
||||
ProgressFn progress_fn;
|
||||
|
@ -141,11 +142,16 @@ AvrDude::Ptr AvrDude::run()
|
|||
|
||||
if (self->p) {
|
||||
auto avrdude_thread = std::thread([self]() {
|
||||
bool cancel = false;
|
||||
int res = -1;
|
||||
|
||||
if (self->p->run_fn) {
|
||||
self->p->run_fn();
|
||||
self->p->run_fn(*self);
|
||||
}
|
||||
|
||||
auto res = self->p->run();
|
||||
if (! self->p->cancelled) {
|
||||
res = self->p->run();
|
||||
}
|
||||
|
||||
if (self->p->complete_fn) {
|
||||
self->p->complete_fn(res, self->p->current_args_set);
|
||||
|
@ -160,7 +166,10 @@ AvrDude::Ptr AvrDude::run()
|
|||
|
||||
void AvrDude::cancel()
|
||||
{
|
||||
::avrdude_cancel();
|
||||
if (p) {
|
||||
p->cancelled = true;
|
||||
::avrdude_cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void AvrDude::join()
|
||||
|
|
|
@ -12,7 +12,7 @@ class AvrDude
|
|||
{
|
||||
public:
|
||||
typedef std::shared_ptr<AvrDude> Ptr;
|
||||
typedef std::function<void()> RunFn;
|
||||
typedef std::function<void(AvrDude&)> RunFn;
|
||||
typedef std::function<void(const char * /* msg */, unsigned /* size */)> MessageFn;
|
||||
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
|
||||
typedef std::function<void(int /* exit status */, size_t /* args_id */)> CompleteFn;
|
||||
|
@ -31,7 +31,8 @@ public:
|
|||
AvrDude& push_args(std::vector<std::string> args);
|
||||
|
||||
// Set a callback to be called just after run() before avrdude is ran
|
||||
// This can be used to perform any needed setup tasks from the background thread.
|
||||
// This can be used to perform any needed setup tasks from the background thread,
|
||||
// and, optionally, to cancel by writing true to the `cancel` argument.
|
||||
// This has no effect when using run_sync().
|
||||
AvrDude& on_run(RunFn fn);
|
||||
|
||||
|
|
|
@ -98,11 +98,11 @@ static int fileio_num(struct fioparms * fio,
|
|||
char * filename, FILE * f, AVRMEM * mem, int size,
|
||||
FILEFMT fmt);
|
||||
|
||||
static int fmt_autodetect(char * fname, size_t offset);
|
||||
static int fmt_autodetect(char * fname, unsigned section);
|
||||
|
||||
|
||||
|
||||
static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offset)
|
||||
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
|
||||
{
|
||||
FILE *file;
|
||||
// On Windows we need to convert the filename to UTF-16
|
||||
|
@ -118,16 +118,38 @@ static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offse
|
|||
file = fopen(filename, mode);
|
||||
#endif
|
||||
|
||||
if (file != NULL) {
|
||||
// Some systems allow seeking past the end of file, so we need check for that first and disallow
|
||||
if (fseek(file, 0, SEEK_END) != 0
|
||||
|| offset >= ftell(file)
|
||||
|| fseek(file, offset, SEEK_SET) != 0
|
||||
) {
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
errno = EINVAL;
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Seek to the specified 'section'
|
||||
static const char *hex_terminator = ":00000001FF\r";
|
||||
unsigned terms_seen = 0;
|
||||
char buffer[MAX_LINE_LEN + 1];
|
||||
|
||||
while (terms_seen < section && fgets(buffer, MAX_LINE_LEN, file) != NULL) {
|
||||
size_t len = strlen(buffer);
|
||||
|
||||
if (buffer[len - 1] == '\n') {
|
||||
len--;
|
||||
buffer[len] = 0;
|
||||
}
|
||||
if (buffer[len - 1] != '\r') {
|
||||
buffer[len] = '\r';
|
||||
len++;
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
if (strcmp(buffer, hex_terminator) == 0) {
|
||||
// Found a section terminator
|
||||
terms_seen++;
|
||||
}
|
||||
}
|
||||
|
||||
if (feof(file)) {
|
||||
// Section not found
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file;
|
||||
|
@ -1392,7 +1414,7 @@ int fileio_setparms(int op, struct fioparms * fp,
|
|||
|
||||
|
||||
|
||||
static int fmt_autodetect(char * fname, size_t offset)
|
||||
static int fmt_autodetect(char * fname, unsigned section)
|
||||
{
|
||||
FILE * f;
|
||||
unsigned char buf[MAX_LINE_LEN];
|
||||
|
@ -1402,9 +1424,9 @@ static int fmt_autodetect(char * fname, size_t offset)
|
|||
int first = 1;
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
f = fopen_and_seek(fname, "r", offset);
|
||||
f = fopen_and_seek(fname, "r", section);
|
||||
#else
|
||||
f = fopen_and_seek(fname, "rb", offset);
|
||||
f = fopen_and_seek(fname, "rb", section);
|
||||
#endif
|
||||
|
||||
if (f == NULL) {
|
||||
|
@ -1480,7 +1502,7 @@ static int fmt_autodetect(char * fname, size_t offset)
|
|||
|
||||
|
||||
int fileio(int op, char * filename, FILEFMT format,
|
||||
struct avrpart * p, char * memtype, int size, size_t offset)
|
||||
struct avrpart * p, char * memtype, int size, unsigned section)
|
||||
{
|
||||
int rc;
|
||||
FILE * f;
|
||||
|
@ -1539,7 +1561,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
|||
return -1;
|
||||
}
|
||||
|
||||
format_detect = fmt_autodetect(fname, offset);
|
||||
format_detect = fmt_autodetect(fname, section);
|
||||
if (format_detect < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n",
|
||||
progname, fname);
|
||||
|
@ -1570,7 +1592,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
|||
|
||||
if (format != FMT_IMM) {
|
||||
if (!using_stdio) {
|
||||
f = fopen_and_seek(fname, fio.mode, offset);
|
||||
f = fopen_and_seek(fname, fio.mode, section);
|
||||
if (f == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
|
||||
progname, fio.iodesc, fname, strerror(errno));
|
||||
|
|
|
@ -821,7 +821,7 @@ extern "C" {
|
|||
char * fmtstr(FILEFMT format);
|
||||
|
||||
int fileio(int op, char * filename, FILEFMT format,
|
||||
struct avrpart * p, char * memtype, int size, size_t offset);
|
||||
struct avrpart * p, char * memtype, int size, unsigned section);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -870,7 +870,7 @@ enum updateflags {
|
|||
typedef struct update_t {
|
||||
char * memtype;
|
||||
int op;
|
||||
size_t offset;
|
||||
unsigned section;
|
||||
char * filename;
|
||||
int format;
|
||||
} UPDATE;
|
||||
|
@ -882,7 +882,7 @@ extern "C" {
|
|||
extern UPDATE * parse_op(char * s);
|
||||
extern UPDATE * dup_update(UPDATE * upd);
|
||||
extern UPDATE * new_update(int op, char * memtype, int filefmt,
|
||||
char * filename, size_t offset);
|
||||
char * filename, unsigned section);
|
||||
extern void free_update(UPDATE * upd);
|
||||
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
|
||||
enum updateflags flags);
|
||||
|
|
9
xs/src/avrdude/main-standalone.c
Normal file
9
xs/src/avrdude/main-standalone.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "avrdude.h"
|
||||
|
||||
|
||||
static const char* SYS_CONFIG = "/etc/avrdude-slic3r.conf";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return avrdude_main(argc, argv, SYS_CONFIG);
|
||||
}
|
|
@ -194,7 +194,7 @@ static void usage(void)
|
|||
" -F Override invalid signature check.\n"
|
||||
" -e Perform a chip erase.\n"
|
||||
" -O Perform RC oscillator calibration (see AVR053). \n"
|
||||
" -U <memtype>:r|w|v:<offset>:<filename>[:format]\n"
|
||||
" -U <memtype>:r|w|v:<section>:<filename>[:format]\n"
|
||||
" Memory operation specification.\n"
|
||||
" Multiple -U options are allowed, each request\n"
|
||||
" is performed in the order specified.\n"
|
||||
|
|
|
@ -311,8 +311,10 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
|||
static void ser_close(union filedescriptor *fd)
|
||||
{
|
||||
if (serial_over_ethernet) {
|
||||
#ifdef HAVE_LIBWS2_32
|
||||
closesocket(fd->ifd);
|
||||
WSACleanup();
|
||||
#endif
|
||||
} else {
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
if (hComPort != INVALID_HANDLE_VALUE)
|
||||
|
|
|
@ -101,22 +101,22 @@ UPDATE * parse_op(char * s)
|
|||
|
||||
p++;
|
||||
|
||||
// Extension: Parse file contents offset
|
||||
size_t offset = 0;
|
||||
// Extension: Parse file section number
|
||||
unsigned section = 0;
|
||||
|
||||
for (; *p != ':'; p++) {
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
offset *= 10;
|
||||
offset += *p - 0x30;
|
||||
section *= 10;
|
||||
section += *p - 0x30;
|
||||
} else {
|
||||
avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname);
|
||||
avrdude_message(MSG_INFO, "%s: invalid update specification: <section> is not a number\n", progname);
|
||||
free(upd->memtype);
|
||||
free(upd);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
upd->offset = offset;
|
||||
upd->section = section;
|
||||
p++;
|
||||
|
||||
/*
|
||||
|
@ -194,7 +194,7 @@ UPDATE * dup_update(UPDATE * upd)
|
|||
return u;
|
||||
}
|
||||
|
||||
UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t offset)
|
||||
UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, unsigned section)
|
||||
{
|
||||
UPDATE * u;
|
||||
|
||||
|
@ -208,7 +208,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t
|
|||
u->filename = strdup(filename);
|
||||
u->op = op;
|
||||
u->format = filefmt;
|
||||
u->offset = offset;
|
||||
u->section = section;
|
||||
|
||||
return u;
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
progname,
|
||||
strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
|
||||
}
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
||||
progname, upd->filename);
|
||||
|
@ -351,7 +351,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
progname, mem->desc, upd->filename);
|
||||
}
|
||||
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
||||
progname, upd->filename);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
@ -568,16 +569,12 @@ GCodeSender::set_DTR(bool on)
|
|||
void
|
||||
GCodeSender::reset()
|
||||
{
|
||||
this->set_DTR(false);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
this->set_DTR(true);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
this->set_DTR(false);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
this->can_send = true;
|
||||
}
|
||||
set_DTR(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
set_DTR(true);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
set_DTR(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -611,14 +611,13 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
|
|||
// The score is a weighted sum of the distance from pile center
|
||||
// and the pile size
|
||||
score = GRAVITY_RATIO * dist + DENSITY_RATIO * density;
|
||||
std::cout << "big " << std::endl;
|
||||
|
||||
} else if(itemnormarea < BIG_ITEM_TRESHOLD && bigs.empty()) {
|
||||
// If there are no big items, only small, we should consider the
|
||||
// density here as well to not get silly results
|
||||
auto bindist = pl::distance(ibb.center(), bin.center()) / norm;
|
||||
auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm;
|
||||
score = GRAVITY_RATIO* bindist + DENSITY_RATIO * density;
|
||||
score = GRAVITY_RATIO * bindist + DENSITY_RATIO * density;
|
||||
} else {
|
||||
// Here there are the small items that should be placed around the
|
||||
// already processed bigger items.
|
||||
|
|
|
@ -210,11 +210,12 @@ GLVolume::GLVolume(float r, float g, float b, float a)
|
|||
, selected(false)
|
||||
, is_active(true)
|
||||
, zoom_to_volumes(true)
|
||||
, outside_printer_detection_enabled(true)
|
||||
, shader_outside_printer_detection_enabled(false)
|
||||
, is_outside(false)
|
||||
, hover(false)
|
||||
, is_modifier(false)
|
||||
, is_wipe_tower(false)
|
||||
, is_extrusion_path(false)
|
||||
, tverts_range(0, size_t(-1))
|
||||
, qverts_range(0, size_t(-1))
|
||||
{
|
||||
|
@ -250,7 +251,7 @@ void GLVolume::set_render_color()
|
|||
set_render_color(is_outside ? SELECTED_OUTSIDE_COLOR : SELECTED_COLOR, 4);
|
||||
else if (hover)
|
||||
set_render_color(HOVER_COLOR, 4);
|
||||
else if (is_outside)
|
||||
else if (is_outside && shader_outside_printer_detection_enabled)
|
||||
set_render_color(OUTSIDE_COLOR, 4);
|
||||
else
|
||||
set_render_color(color, 4);
|
||||
|
@ -441,7 +442,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
|
|||
::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||
|
||||
if (detection_id != -1)
|
||||
::glUniform1i(detection_id, outside_printer_detection_enabled ? 1 : 0);
|
||||
::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
|
||||
|
||||
if (worldmatrix_id != -1)
|
||||
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
|
||||
|
@ -460,7 +461,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
|
|||
::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||
|
||||
if (detection_id != -1)
|
||||
::glUniform1i(detection_id, outside_printer_detection_enabled ? 1 : 0);
|
||||
::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
|
||||
|
||||
if (worldmatrix_id != -1)
|
||||
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
|
||||
|
@ -633,7 +634,7 @@ std::vector<int> GLVolumeCollection::load_object(
|
|||
v.extruder_id = extruder_id;
|
||||
}
|
||||
v.is_modifier = model_volume->modifier;
|
||||
v.outside_printer_detection_enabled = !model_volume->modifier;
|
||||
v.shader_outside_printer_detection_enabled = !model_volume->modifier;
|
||||
v.set_origin(Pointf3(instance->offset.x, instance->offset.y, 0.0));
|
||||
v.set_angle_z(instance->rotation);
|
||||
v.set_scale_factor(instance->scaling_factor);
|
||||
|
@ -1786,6 +1787,11 @@ void _3DScene::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable)
|
|||
s_canvas_mgr.enable_force_zoom_to_bed(canvas, enable);
|
||||
}
|
||||
|
||||
void _3DScene::enable_dynamic_background(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
s_canvas_mgr.enable_dynamic_background(canvas, enable);
|
||||
}
|
||||
|
||||
void _3DScene::allow_multisample(wxGLCanvas* canvas, bool allow)
|
||||
{
|
||||
s_canvas_mgr.allow_multisample(canvas, allow);
|
||||
|
@ -1968,26 +1974,16 @@ void _3DScene::reload_scene(wxGLCanvas* canvas, bool force)
|
|||
s_canvas_mgr.reload_scene(canvas, force);
|
||||
}
|
||||
|
||||
void _3DScene::load_print_toolpaths(wxGLCanvas* canvas)
|
||||
{
|
||||
s_canvas_mgr.load_print_toolpaths(canvas);
|
||||
}
|
||||
|
||||
void _3DScene::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
s_canvas_mgr.load_print_object_toolpaths(canvas, print_object, str_tool_colors);
|
||||
}
|
||||
|
||||
void _3DScene::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
s_canvas_mgr.load_wipe_tower_toolpaths(canvas, str_tool_colors);
|
||||
}
|
||||
|
||||
void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
|
||||
}
|
||||
|
||||
void _3DScene::load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
s_canvas_mgr.load_preview(canvas, str_tool_colors);
|
||||
}
|
||||
|
||||
void _3DScene::reset_legend_texture()
|
||||
{
|
||||
s_canvas_mgr.reset_legend_texture();
|
||||
|
|
|
@ -289,8 +289,8 @@ public:
|
|||
bool is_active;
|
||||
// Whether or not to use this volume when applying zoom_to_volumes()
|
||||
bool zoom_to_volumes;
|
||||
// Wheter or not this volume is enabled for outside print volume detection.
|
||||
bool outside_printer_detection_enabled;
|
||||
// Wheter or not this volume is enabled for outside print volume detection in shader.
|
||||
bool shader_outside_printer_detection_enabled;
|
||||
// Wheter or not this volume is outside print volume.
|
||||
bool is_outside;
|
||||
// Boolean: Is mouse over this object?
|
||||
|
@ -299,6 +299,8 @@ public:
|
|||
bool is_modifier;
|
||||
// Wheter or not this volume has been generated from the wipe tower
|
||||
bool is_wipe_tower;
|
||||
// Wheter or not this volume has been generated from an extrusion path
|
||||
bool is_extrusion_path;
|
||||
|
||||
// Interleaved triangles & normals with indexed triangles & quads.
|
||||
GLIndexedVertexArray indexed_vertex_array;
|
||||
|
@ -497,6 +499,7 @@ public:
|
|||
static void enable_gizmos(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_shader(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
|
||||
static void enable_dynamic_background(wxGLCanvas* canvas, bool enable);
|
||||
static void allow_multisample(wxGLCanvas* canvas, bool allow);
|
||||
|
||||
static void zoom_to_bed(wxGLCanvas* canvas);
|
||||
|
@ -536,10 +539,8 @@ public:
|
|||
|
||||
static void reload_scene(wxGLCanvas* canvas, bool force);
|
||||
|
||||
static void load_print_toolpaths(wxGLCanvas* canvas);
|
||||
static void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors);
|
||||
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
static void load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
static void reset_legend_texture();
|
||||
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
#include "FirmwareDialog.hpp"
|
||||
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <stdexcept>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "avrdude/avrdude-slic3r.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "../Utils/HexFile.hpp"
|
||||
#include "../Utils/Serial.hpp"
|
||||
|
||||
// wx includes need to come after asio because of the WinSock.h problem
|
||||
#include "FirmwareDialog.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/sizer.h>
|
||||
|
@ -22,16 +33,18 @@
|
|||
#include <wx/collpane.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "avrdude/avrdude-slic3r.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "../Utils/Serial.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace asio = boost::asio;
|
||||
using boost::system::error_code;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using Utils::HexFile;
|
||||
using Utils::SerialPortInfo;
|
||||
using Utils::Serial;
|
||||
|
||||
|
||||
// This enum discriminates the kind of information in EVT_AVRDUDE,
|
||||
// it's stored in the ExtraLong field of wxCommandEvent.
|
||||
|
@ -40,6 +53,7 @@ enum AvrdudeEvent
|
|||
AE_MESSAGE,
|
||||
AE_PROGRESS,
|
||||
AE_EXIT,
|
||||
AE_ERROR,
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_AVRDUDE, wxCommandEvent);
|
||||
|
@ -52,7 +66,6 @@ struct FirmwareDialog::priv
|
|||
{
|
||||
enum AvrDudeComplete
|
||||
{
|
||||
AC_NONE,
|
||||
AC_SUCCESS,
|
||||
AC_FAILURE,
|
||||
AC_CANCEL,
|
||||
|
@ -61,7 +74,7 @@ struct FirmwareDialog::priv
|
|||
FirmwareDialog *q; // PIMPL back pointer ("Q-Pointer")
|
||||
|
||||
wxComboBox *port_picker;
|
||||
std::vector<Utils::SerialPortInfo> ports;
|
||||
std::vector<SerialPortInfo> ports;
|
||||
wxFilePickerCtrl *hex_picker;
|
||||
wxStaticText *txt_status;
|
||||
wxGauge *progressbar;
|
||||
|
@ -80,7 +93,9 @@ struct FirmwareDialog::priv
|
|||
AvrDude::Ptr avrdude;
|
||||
std::string avrdude_config;
|
||||
unsigned progress_tasks_done;
|
||||
unsigned progress_tasks_bar;
|
||||
bool cancelled;
|
||||
const bool extra_verbose; // For debugging
|
||||
|
||||
priv(FirmwareDialog *q) :
|
||||
q(q),
|
||||
|
@ -89,16 +104,25 @@ struct FirmwareDialog::priv
|
|||
timer_pulse(q),
|
||||
avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
|
||||
progress_tasks_done(0),
|
||||
cancelled(false)
|
||||
progress_tasks_bar(0),
|
||||
cancelled(false),
|
||||
extra_verbose(false)
|
||||
{}
|
||||
|
||||
void find_serial_ports();
|
||||
void flashing_start(bool flashing_l10n);
|
||||
void flashing_start(unsigned tasks);
|
||||
void flashing_done(AvrDudeComplete complete);
|
||||
size_t hex_lang_offset(const wxString &path);
|
||||
void check_model_id(const HexFile &metadata, const SerialPortInfo &port);
|
||||
|
||||
void prepare_common(AvrDude &, const SerialPortInfo &port, const std::string &filename);
|
||||
void prepare_mk2(AvrDude &, const SerialPortInfo &port, const std::string &filename);
|
||||
void prepare_mk3(AvrDude &, const SerialPortInfo &port, const std::string &filename);
|
||||
void prepare_mm_control(AvrDude &, const SerialPortInfo &port, const std::string &filename);
|
||||
void perform_upload();
|
||||
|
||||
void cancel();
|
||||
void on_avrdude(const wxCommandEvent &evt);
|
||||
void ensure_joined();
|
||||
};
|
||||
|
||||
void FirmwareDialog::priv::find_serial_ports()
|
||||
|
@ -108,7 +132,7 @@ void FirmwareDialog::priv::find_serial_ports()
|
|||
this->ports = new_ports;
|
||||
port_picker->Clear();
|
||||
for (const auto &port : this->ports)
|
||||
port_picker->Append(port.friendly_name);
|
||||
port_picker->Append(wxString::FromUTF8(port.friendly_name.data()));
|
||||
if (ports.size() > 0) {
|
||||
int idx = port_picker->GetValue().IsEmpty() ? 0 : -1;
|
||||
for (int i = 0; i < (int)this->ports.size(); ++ i)
|
||||
|
@ -122,7 +146,7 @@ void FirmwareDialog::priv::find_serial_ports()
|
|||
}
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::flashing_start(bool flashing_l10n)
|
||||
void FirmwareDialog::priv::flashing_start(unsigned tasks)
|
||||
{
|
||||
txt_stdout->Clear();
|
||||
txt_status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
|
||||
|
@ -132,9 +156,10 @@ void FirmwareDialog::priv::flashing_start(bool flashing_l10n)
|
|||
hex_picker->Disable();
|
||||
btn_close->Disable();
|
||||
btn_flash->SetLabel(btn_flash_label_flashing);
|
||||
progressbar->SetRange(flashing_l10n ? 500 : 200); // See progress callback below
|
||||
progressbar->SetRange(200 * tasks); // See progress callback below
|
||||
progressbar->SetValue(0);
|
||||
progress_tasks_done = 0;
|
||||
progress_tasks_bar = 0;
|
||||
cancelled = false;
|
||||
timer_pulse.Start(50);
|
||||
}
|
||||
|
@ -158,63 +183,49 @@ void FirmwareDialog::priv::flashing_done(AvrDudeComplete complete)
|
|||
}
|
||||
}
|
||||
|
||||
size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path)
|
||||
void FirmwareDialog::priv::check_model_id(const HexFile &metadata, const SerialPortInfo &port)
|
||||
{
|
||||
fs::ifstream file(fs::path(path.wx_str()));
|
||||
if (! file.good()) {
|
||||
return 0;
|
||||
if (metadata.model_id.empty()) {
|
||||
// No data to check against
|
||||
return;
|
||||
}
|
||||
|
||||
asio::io_service io;
|
||||
Serial serial(io, port.port, 115200);
|
||||
serial.printer_setup();
|
||||
|
||||
enum {
|
||||
TIMEOUT = 1000,
|
||||
RETREIES = 3,
|
||||
};
|
||||
|
||||
if (! serial.printer_ready_wait(RETREIES, TIMEOUT)) {
|
||||
throw wxString::Format(_(L("Could not connect to the printer at %s")), port.port);
|
||||
}
|
||||
|
||||
static const char *hex_terminator = ":00000001FF\r";
|
||||
size_t res = 0;
|
||||
std::string line;
|
||||
while (getline(file, line, '\n').good()) {
|
||||
// Account for LF vs CRLF
|
||||
if (!line.empty() && line.back() != '\r') {
|
||||
line.push_back('\r');
|
||||
error_code ec;
|
||||
serial.printer_write_line("PRUSA Rev");
|
||||
while (serial.read_line(TIMEOUT, line, ec)) {
|
||||
if (ec) { throw wxString::Format(_(L("Could not connect to the printer at %s")), port.port); }
|
||||
if (line == "ok") { continue; }
|
||||
|
||||
if (line == metadata.model_id) {
|
||||
return;
|
||||
} else {
|
||||
throw wxString::Format(_(L(
|
||||
"The firmware hex file does not match the printer model.\n"
|
||||
"The hex file is intended for:\n %s\n"
|
||||
"Printer reports:\n %s"
|
||||
)), metadata.model_id, line);
|
||||
}
|
||||
|
||||
if (line == hex_terminator) {
|
||||
if (res == 0) {
|
||||
// This is the first terminator seen, save the position
|
||||
res = file.tellg();
|
||||
} else {
|
||||
// We've found another terminator, return the offset just after the first one
|
||||
// which is the start of the second 'section'.
|
||||
return res;
|
||||
}
|
||||
}
|
||||
line.clear();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::perform_upload()
|
||||
void FirmwareDialog::priv::prepare_common(AvrDude &avrdude, const SerialPortInfo &port, const std::string &filename)
|
||||
{
|
||||
auto filename = hex_picker->GetPath();
|
||||
std::string port = port_picker->GetValue().ToStdString();
|
||||
int selection = port_picker->GetSelection();
|
||||
if (selection != -1) {
|
||||
// Verify whether the combo box list selection equals to the combo box edit value.
|
||||
if (this->ports[selection].friendly_name == port)
|
||||
port = this->ports[selection].port;
|
||||
}
|
||||
if (filename.IsEmpty() || port.empty()) { return; }
|
||||
|
||||
const bool extra_verbose = false; // For debugging
|
||||
const auto lang_offset = hex_lang_offset(filename);
|
||||
const auto filename_utf8 = filename.utf8_str();
|
||||
|
||||
flashing_start(lang_offset > 0);
|
||||
|
||||
// It is ok here to use the q-pointer to the FirmwareDialog
|
||||
// because the dialog ensures it doesn't exit before the background thread is done.
|
||||
auto q = this->q;
|
||||
|
||||
// Init the avrdude object
|
||||
AvrDude avrdude(avrdude_config);
|
||||
|
||||
// Build argument list(s)
|
||||
std::vector<std::string> args {{
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
|
@ -222,11 +233,10 @@ void FirmwareDialog::priv::perform_upload()
|
|||
// The Prusa's avrdude is patched to never send semicolons inside the data packets, as the USB to serial chip
|
||||
// is flashed with a buggy firmware.
|
||||
"-c", "wiring",
|
||||
"-P", port,
|
||||
"-P", port.port,
|
||||
"-b", "115200", // TODO: Allow other rates? Ditto below.
|
||||
"-D",
|
||||
// XXX: Safe mode?
|
||||
"-U", (boost::format("flash:w:0:%1%:i") % filename_utf8.data()).str(),
|
||||
"-U", (boost::format("flash:w:0:%1%:i") % filename).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
|
||||
|
@ -235,32 +245,167 @@ void FirmwareDialog::priv::perform_upload()
|
|||
});
|
||||
|
||||
avrdude.push_args(std::move(args));
|
||||
|
||||
if (lang_offset > 0) {
|
||||
// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
|
||||
// This is done via another avrdude invocation, here we build arg list for that:
|
||||
std::vector<std::string> args_l10n {{
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
// Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2).
|
||||
// The Prusa's avrdude is patched again to never send semicolons inside the data packets.
|
||||
"-c", "arduino",
|
||||
"-P", port,
|
||||
"-b", "115200",
|
||||
"-D",
|
||||
"-u", // disable safe mode
|
||||
"-U", (boost::format("flash:w:%1%:%2%:i") % lang_offset % filename_utf8.data()).str(),
|
||||
}};
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "
|
||||
<< std::accumulate(std::next(args_l10n.begin()), args_l10n.end(), args_l10n[0], [](std::string a, const std::string &b) {
|
||||
return a + ' ' + b;
|
||||
});
|
||||
void FirmwareDialog::priv::prepare_mk2(AvrDude &avrdude, const SerialPortInfo &port, const std::string &filename)
|
||||
{
|
||||
prepare_common(avrdude, port, filename);
|
||||
}
|
||||
|
||||
avrdude.push_args(std::move(args_l10n));
|
||||
void FirmwareDialog::priv::prepare_mk3(AvrDude &avrdude, const SerialPortInfo &port, const std::string &filename)
|
||||
{
|
||||
prepare_common(avrdude, port, filename);
|
||||
|
||||
// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
|
||||
// This is done via another avrdude invocation, here we build arg list for that:
|
||||
std::vector<std::string> args_l10n {{
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
// Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2).
|
||||
// The Prusa's avrdude is patched again to never send semicolons inside the data packets.
|
||||
"-c", "arduino",
|
||||
"-P", port.port,
|
||||
"-b", "115200",
|
||||
"-D",
|
||||
"-u", // disable safe mode
|
||||
"-U", (boost::format("flash:w:1:%1%:i") % filename).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "
|
||||
<< std::accumulate(std::next(args_l10n.begin()), args_l10n.end(), args_l10n[0], [](std::string a, const std::string &b) {
|
||||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
avrdude.push_args(std::move(args_l10n));
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::prepare_mm_control(AvrDude &avrdude, const SerialPortInfo &port_in, const std::string &filename)
|
||||
{
|
||||
// Check if the port has the PID/VID of 0x2c99/3
|
||||
// If not, check if it is the MMU (0x2c99/4) and reboot the by opening @ 1200 bauds
|
||||
BOOST_LOG_TRIVIAL(info) << "Flashing MMU 2.0, looking for VID/PID 0x2c99/3 or 0x2c99/4 ...";
|
||||
SerialPortInfo port = port_in;
|
||||
if (! port.id_match(0x2c99, 3)) {
|
||||
if (! port.id_match(0x2c99, 4)) {
|
||||
// This is not a Prusa MMU 2.0 device
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Not a Prusa MMU 2.0 device: `%1%`") % port.port;
|
||||
throw wxString::Format(_(L("The device at `%s` is not am Original Prusa i3 MMU 2.0 device")), port.port);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Found VID/PID 0x2c99/4 at `%1%`, rebooting the device ...") % port.port;
|
||||
|
||||
{
|
||||
asio::io_service io;
|
||||
Serial serial(io, port.port, 1200);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
// Wait for the bootloader to show up
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
||||
|
||||
// Look for the rebooted device
|
||||
BOOST_LOG_TRIVIAL(info) << "... looking for VID/PID 0x2c99/3 ...";
|
||||
auto new_ports = Utils::scan_serial_ports_extended();
|
||||
unsigned hits = 0;
|
||||
for (auto &&new_port : new_ports) {
|
||||
if (new_port.id_match(0x2c99, 3)) {
|
||||
hits++;
|
||||
port = std::move(new_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (hits == 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << "No VID/PID 0x2c99/3 device found after rebooting the MMU 2.0";
|
||||
throw wxString::Format(_(L("Failed to reboot the device at `%s` for programming")), port.port);
|
||||
} else if (hits > 1) {
|
||||
// We found multiple 0x2c99/3 devices, this is bad, because there's no way to find out
|
||||
// which one is the one user wants to flash.
|
||||
BOOST_LOG_TRIVIAL(error) << "Several VID/PID 0x2c99/3 devices found after rebooting the MMU 2.0";
|
||||
throw wxString::Format(_(L("Multiple Original Prusa i3 MMU 2.0 devices found. Please only connect one at a time for flashing.")), port.port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Found VID/PID 0x2c99/3 at `%1%`, flashing ...") % port.port;
|
||||
|
||||
std::vector<std::string> args {{
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega32u4",
|
||||
"-c", "avr109",
|
||||
"-P", port.port,
|
||||
"-b", "57600",
|
||||
"-D",
|
||||
"-U", (boost::format("flash:w:0:%1%:i") % filename).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
|
||||
<< std::accumulate(std::next(args.begin()), args.end(), args[0], [](std::string a, const std::string &b) {
|
||||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
avrdude.push_args(std::move(args));
|
||||
}
|
||||
|
||||
|
||||
void FirmwareDialog::priv::perform_upload()
|
||||
{
|
||||
auto filename = hex_picker->GetPath();
|
||||
if (filename.IsEmpty()) { return; }
|
||||
|
||||
int selection = port_picker->GetSelection();
|
||||
if (selection == wxNOT_FOUND) { return; }
|
||||
|
||||
const SerialPortInfo &port = this->ports[selection];
|
||||
// Verify whether the combo box list selection equals to the combo box edit value.
|
||||
if (wxString::FromUTF8(this->ports[selection].friendly_name.data()) != port_picker->GetValue()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool extra_verbose = false; // For debugging
|
||||
HexFile metadata(filename.wx_str());
|
||||
const std::string filename_utf8(filename.utf8_str().data());
|
||||
|
||||
flashing_start(metadata.device == HexFile::DEV_MK3 ? 2 : 1);
|
||||
|
||||
// Init the avrdude object
|
||||
AvrDude avrdude(avrdude_config);
|
||||
|
||||
// It is ok here to use the q-pointer to the FirmwareDialog
|
||||
// because the dialog ensures it doesn't exit before the background thread is done.
|
||||
auto q = this->q;
|
||||
|
||||
this->avrdude = avrdude
|
||||
.on_run([=](AvrDude &avrdude) {
|
||||
auto queue_error = [&](wxString message) {
|
||||
avrdude.cancel();
|
||||
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, this->q->GetId());
|
||||
evt->SetExtraLong(AE_ERROR);
|
||||
evt->SetString(std::move(message));
|
||||
wxQueueEvent(this->q, evt);
|
||||
};
|
||||
|
||||
try {
|
||||
switch (metadata.device) {
|
||||
case HexFile::DEV_MK3:
|
||||
this->check_model_id(metadata, port);
|
||||
this->prepare_mk3(avrdude, port, filename_utf8);
|
||||
break;
|
||||
|
||||
case HexFile::DEV_MM_CONTROL:
|
||||
this->check_model_id(metadata, port);
|
||||
this->prepare_mm_control(avrdude, port, filename_utf8);
|
||||
break;
|
||||
|
||||
default:
|
||||
this->prepare_mk2(avrdude, port, filename_utf8);
|
||||
break;
|
||||
}
|
||||
} catch (const wxString &message) {
|
||||
queue_error(message);
|
||||
} catch (const std::exception &ex) {
|
||||
queue_error(wxString::Format(_(L("Error accessing port at %s: %s")), port.port, ex.what()));
|
||||
}
|
||||
})
|
||||
.on_message(std::move([q, extra_verbose](const char *msg, unsigned /* size */) {
|
||||
if (extra_verbose) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "avrdude: " << msg;
|
||||
|
@ -313,12 +458,15 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
// and then display overall progress during the latter tasks.
|
||||
|
||||
if (progress_tasks_done > 0) {
|
||||
progressbar->SetValue(progress_tasks_done - 100 + evt.GetInt());
|
||||
progressbar->SetValue(progress_tasks_bar + evt.GetInt());
|
||||
}
|
||||
|
||||
if (evt.GetInt() == 100) {
|
||||
timer_pulse.Stop();
|
||||
progress_tasks_done += 100;
|
||||
if (progress_tasks_done % 3 != 0) {
|
||||
progress_tasks_bar += 100;
|
||||
}
|
||||
progress_tasks_done++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -328,11 +476,17 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
|
||||
complete_kind = cancelled ? AC_CANCEL : (evt.GetInt() == 0 ? AC_SUCCESS : AC_FAILURE);
|
||||
flashing_done(complete_kind);
|
||||
ensure_joined();
|
||||
break;
|
||||
|
||||
// Make sure the background thread is collected and the AvrDude object reset
|
||||
if (avrdude) { avrdude->join(); }
|
||||
avrdude.reset();
|
||||
|
||||
case AE_ERROR:
|
||||
txt_stdout->AppendText(evt.GetString());
|
||||
flashing_done(AC_FAILURE);
|
||||
ensure_joined();
|
||||
{
|
||||
GUI::ErrorDialog dlg(this->q, evt.GetString());
|
||||
dlg.ShowModal();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -340,6 +494,13 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
}
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::ensure_joined()
|
||||
{
|
||||
// Make sure the background thread is collected and the AvrDude object reset
|
||||
if (avrdude) { avrdude->join(); }
|
||||
avrdude.reset();
|
||||
}
|
||||
|
||||
|
||||
// Public
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -449,6 +449,7 @@ private:
|
|||
bool m_picking_enabled;
|
||||
bool m_moving_enabled;
|
||||
bool m_shader_enabled;
|
||||
bool m_dynamic_background_enabled;
|
||||
bool m_multisample_allowed;
|
||||
|
||||
std::string m_color_by;
|
||||
|
@ -539,6 +540,7 @@ public:
|
|||
void enable_gizmos(bool enable);
|
||||
void enable_shader(bool enable);
|
||||
void enable_force_zoom_to_bed(bool enable);
|
||||
void enable_dynamic_background(bool enable);
|
||||
void allow_multisample(bool allow);
|
||||
|
||||
void zoom_to_bed();
|
||||
|
@ -559,16 +561,8 @@ public:
|
|||
|
||||
void reload_scene(bool force);
|
||||
|
||||
// Create 3D thick extrusion lines for a skirt and brim.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||
void load_print_toolpaths();
|
||||
// Create 3D thick extrusion lines for object forming extrusions.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||
// one for perimeters, one for infill and one for supports.
|
||||
void load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
|
||||
// Create 3D thick extrusion lines for wipe tower extrusions
|
||||
void load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
|
||||
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
void load_preview(const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
void register_on_viewport_changed_callback(void* callback);
|
||||
void register_on_double_click_callback(void* callback);
|
||||
|
@ -650,7 +644,17 @@ private:
|
|||
void _stop_timer();
|
||||
|
||||
int _get_first_selected_object_id() const;
|
||||
int _get_first_selected_volume_id() const;
|
||||
int _get_first_selected_volume_id(int object_id) const;
|
||||
|
||||
// Create 3D thick extrusion lines for a skirt and brim.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||
void _load_print_toolpaths();
|
||||
// Create 3D thick extrusion lines for object forming extrusions.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||
// one for perimeters, one for infill and one for supports.
|
||||
void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
|
||||
// Create 3D thick extrusion lines for wipe tower extrusions
|
||||
void _load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
// generates gcode extrusion paths geometry
|
||||
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
|
@ -667,6 +671,8 @@ private:
|
|||
void _load_shells();
|
||||
// sets gcode geometry visibility according to user selection
|
||||
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
||||
void _update_toolpath_volumes_outside_state();
|
||||
void _show_warning_texture_if_needed();
|
||||
|
||||
void _on_move(const std::vector<int>& volume_idxs);
|
||||
void _on_select(int volume_idx);
|
||||
|
@ -678,6 +684,8 @@ private:
|
|||
void _generate_warning_texture(const std::string& msg);
|
||||
void _reset_warning_texture();
|
||||
|
||||
bool _is_any_volume_outside() const;
|
||||
|
||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||
};
|
||||
|
||||
|
|
|
@ -418,6 +418,13 @@ void GLCanvas3DManager::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable
|
|||
it->second->enable_force_zoom_to_bed(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::enable_dynamic_background(wxGLCanvas* canvas, bool enable)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->enable_dynamic_background(enable);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::allow_multisample(wxGLCanvas* canvas, bool allow)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
|
@ -516,30 +523,6 @@ void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force)
|
|||
it->second->reload_scene(force);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_print_toolpaths(wxGLCanvas* canvas)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_print_toolpaths();
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors)
|
||||
{
|
||||
if (print_object == nullptr)
|
||||
return;
|
||||
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_print_object_toolpaths(*print_object, tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_wipe_tower_toolpaths(str_tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
if (preview_data == nullptr)
|
||||
|
@ -550,6 +533,13 @@ void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePrevie
|
|||
it->second->load_gcode_preview(*preview_data, str_tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->load_preview(str_tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::reset_legend_texture()
|
||||
{
|
||||
for (CanvasesMap::value_type& canvas : m_canvases)
|
||||
|
|
|
@ -112,6 +112,7 @@ public:
|
|||
void enable_gizmos(wxGLCanvas* canvas, bool enable);
|
||||
void enable_shader(wxGLCanvas* canvas, bool enable);
|
||||
void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
|
||||
void enable_dynamic_background(wxGLCanvas* canvas, bool enable);
|
||||
void allow_multisample(wxGLCanvas* canvas, bool allow);
|
||||
|
||||
void zoom_to_bed(wxGLCanvas* canvas);
|
||||
|
@ -132,10 +133,8 @@ public:
|
|||
|
||||
void reload_scene(wxGLCanvas* canvas, bool force);
|
||||
|
||||
void load_print_toolpaths(wxGLCanvas* canvas);
|
||||
void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors);
|
||||
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
void load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
void reset_legend_texture();
|
||||
|
||||
|
|
|
@ -250,6 +250,7 @@ bool select_language(wxArrayString & names,
|
|||
g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir()));
|
||||
g_wxLocale->AddCatalog(g_wxApp->GetAppName());
|
||||
wxSetlocale(LC_NUMERIC, "C");
|
||||
Preset::update_suffix_modified();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -275,6 +276,7 @@ bool load_language()
|
|||
g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir()));
|
||||
g_wxLocale->AddCatalog(g_wxApp->GetAppName());
|
||||
wxSetlocale(LC_NUMERIC, "C");
|
||||
Preset::update_suffix_modified();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,6 +146,11 @@ const std::string& Preset::suffix_modified()
|
|||
{
|
||||
return g_suffix_modified;
|
||||
}
|
||||
|
||||
void Preset::update_suffix_modified()
|
||||
{
|
||||
g_suffix_modified = (" (" + _(L("modified")) + ")").ToUTF8().data();
|
||||
}
|
||||
// Remove an optional "(modified)" suffix from a name.
|
||||
// This converts a UI name to a unique preset identifier.
|
||||
std::string Preset::remove_suffix_modified(const std::string &name)
|
||||
|
|
|
@ -167,6 +167,7 @@ public:
|
|||
static const std::vector<std::string>& printer_options();
|
||||
// Nozzle options of the printer options.
|
||||
static const std::vector<std::string>& nozzle_options();
|
||||
static void update_suffix_modified();
|
||||
|
||||
protected:
|
||||
friend class PresetCollection;
|
||||
|
@ -260,7 +261,7 @@ public:
|
|||
// used to update preset_choice from Tab
|
||||
const std::deque<Preset>& get_presets() { return m_presets; }
|
||||
int get_idx_selected() { return m_idx_selected; }
|
||||
const std::string& get_suffix_modified();
|
||||
static const std::string& get_suffix_modified();
|
||||
|
||||
// Return a preset possibly with modifications.
|
||||
Preset& default_preset() { return m_presets.front(); }
|
||||
|
|
|
@ -552,6 +552,8 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
std::string &inherits = Preset::inherits(config);
|
||||
compatible_printers_condition_values.resize(num_extruders + 2, std::string());
|
||||
inherits_values.resize(num_extruders + 2, std::string());
|
||||
// The "default_filament_profile" will be later extracted into the printer profile.
|
||||
config.option<ConfigOptionStrings>("default_filament_profile", true)->values.resize(num_extruders, std::string());
|
||||
|
||||
// 1) Create a name from the file name.
|
||||
// Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles.
|
||||
|
@ -576,7 +578,6 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
// 3) Now load the filaments. If there are multiple filament presets, split them and load them.
|
||||
auto old_filament_profile_names = config.option<ConfigOptionStrings>("filament_settings_id", true);
|
||||
old_filament_profile_names->values.resize(num_extruders, std::string());
|
||||
config.option<ConfigOptionStrings>("default_filament_profile", true)->values.resize(num_extruders, std::string());
|
||||
|
||||
if (num_extruders <= 1) {
|
||||
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
|
||||
|
|
|
@ -2728,7 +2728,7 @@ void SavePresetWindow::accept()
|
|||
const char* unusable_symbols = "<>:/\\|?*\"";
|
||||
bool is_unusable_symbol = false;
|
||||
bool is_unusable_postfix = false;
|
||||
const std::string unusable_postfix = "(modified)";
|
||||
const std::string unusable_postfix = PresetCollection::get_suffix_modified();//"(modified)";
|
||||
for (size_t i = 0; i < std::strlen(unusable_symbols); i++){
|
||||
if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos){
|
||||
is_unusable_symbol = true;
|
||||
|
@ -2743,8 +2743,9 @@ void SavePresetWindow::accept()
|
|||
_(L("the following characters are not allowed:")) + " <>:/\\|?*\"");
|
||||
}
|
||||
else if (is_unusable_postfix){
|
||||
show_error(this, _(L("The supplied name is not valid;")) + "\n" +
|
||||
_(L("the following postfix are not allowed:")) + "\n\t" + unusable_postfix);
|
||||
show_error(this,_(L("The supplied name is not valid;")) + "\n" +
|
||||
_(L("the following postfix are not allowed:")) + "\n\t" + //unusable_postfix);
|
||||
wxString::FromUTF8(unusable_postfix.c_str()));
|
||||
}
|
||||
else if (m_chosen_name.compare("- default -") == 0) {
|
||||
show_error(this, _(L("The supplied name is not available.")));
|
||||
|
|
107
xs/src/slic3r/Utils/HexFile.cpp
Normal file
107
xs/src/slic3r/Utils/HexFile.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
#include "HexFile.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
|
||||
static HexFile::DeviceKind parse_device_kind(const std::string &str)
|
||||
{
|
||||
if (str == "mk2") { return HexFile::DEV_MK2; }
|
||||
else if (str == "mk3") { return HexFile::DEV_MK3; }
|
||||
else if (str == "mm-control") { return HexFile::DEV_MM_CONTROL; }
|
||||
else { return HexFile::DEV_GENERIC; }
|
||||
}
|
||||
|
||||
static size_t hex_num_sections(fs::ifstream &file)
|
||||
{
|
||||
file.seekg(0);
|
||||
if (! file.good()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *hex_terminator = ":00000001FF\r";
|
||||
size_t res = 0;
|
||||
std::string line;
|
||||
while (getline(file, line, '\n').good()) {
|
||||
// Account for LF vs CRLF
|
||||
if (!line.empty() && line.back() != '\r') {
|
||||
line.push_back('\r');
|
||||
}
|
||||
|
||||
if (line == hex_terminator) {
|
||||
res++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
HexFile::HexFile(fs::path path) :
|
||||
path(std::move(path)),
|
||||
device(DEV_GENERIC)
|
||||
{
|
||||
fs::ifstream file(this->path);
|
||||
if (! file.good()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
std::stringstream header_ini;
|
||||
while (std::getline(file, line, '\n').good()) {
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Account for LF vs CRLF
|
||||
if (!line.empty() && line.back() == '\r') {
|
||||
line.pop_back();
|
||||
}
|
||||
|
||||
if (line.front() == ';') {
|
||||
line.front() = ' ';
|
||||
header_ini << line << std::endl;
|
||||
} else if (line.front() == ':') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pt::ptree ptree;
|
||||
try {
|
||||
pt::read_ini(header_ini, ptree);
|
||||
} catch (std::exception &e) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool has_device_meta = false;
|
||||
const auto device = ptree.find("device");
|
||||
if (device != ptree.not_found()) {
|
||||
this->device = parse_device_kind(device->second.data());
|
||||
has_device_meta = true;
|
||||
}
|
||||
|
||||
const auto model_id = ptree.find("model_id");
|
||||
if (model_id != ptree.not_found()) {
|
||||
this->model_id = model_id->second.data();
|
||||
}
|
||||
|
||||
if (! has_device_meta) {
|
||||
// No device metadata, look at the number of 'sections'
|
||||
if (hex_num_sections(file) == 2) {
|
||||
// Looks like a pre-metadata l10n firmware for the MK3, assume that's the case
|
||||
this->device = DEV_MK3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
32
xs/src/slic3r/Utils/HexFile.hpp
Normal file
32
xs/src/slic3r/Utils/HexFile.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef slic3r_Hex_hpp_
|
||||
#define slic3r_Hex_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
|
||||
struct HexFile
|
||||
{
|
||||
enum DeviceKind {
|
||||
DEV_GENERIC,
|
||||
DEV_MK2,
|
||||
DEV_MK3,
|
||||
DEV_MM_CONTROL,
|
||||
};
|
||||
|
||||
boost::filesystem::path path;
|
||||
DeviceKind device;
|
||||
std::string model_id;
|
||||
|
||||
HexFile(boost::filesystem::path path);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,17 +3,22 @@
|
|||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#if _WIN32
|
||||
#include <Windows.h>
|
||||
#include <Setupapi.h>
|
||||
#include <initguid.h>
|
||||
#include <devguid.h>
|
||||
#include <regex>
|
||||
// Undefine min/max macros incompatible with the standard library
|
||||
// For example, std::numeric_limits<std::streamsize>::max()
|
||||
// produces some weird errors
|
||||
|
@ -34,6 +39,23 @@
|
|||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#include <termios.h>
|
||||
#elif defined __linux__
|
||||
#include <fcntl.h>
|
||||
#include <asm-generic/ioctls.h>
|
||||
#endif
|
||||
|
||||
using boost::optional;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
|
@ -42,15 +64,43 @@ static bool looks_like_printer(const std::string &friendly_name)
|
|||
return friendly_name.find("Original Prusa") != std::string::npos;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static std::string get_tty_friendly_name(const std::string &path, const std::string &name)
|
||||
#if _WIN32
|
||||
void parse_hardware_id(const std::string &hardware_id, SerialPortInfo &spi)
|
||||
{
|
||||
const auto sysfs_product = (boost::format("/sys/class/tty/%1%/device/../product") % name).str();
|
||||
std::ifstream file(sysfs_product);
|
||||
std::string product;
|
||||
unsigned vid, pid;
|
||||
std::regex pattern("USB\\\\.*VID_([[:xdigit:]]+)&PID_([[:xdigit:]]+).*");
|
||||
std::smatch matches;
|
||||
if (std::regex_match(hardware_id, matches, pattern)) {
|
||||
try {
|
||||
vid = std::stoul(matches[1].str(), 0, 16);
|
||||
pid = std::stoul(matches[2].str(), 0, 16);
|
||||
spi.id_vendor = vid;
|
||||
spi.id_product = pid;
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::getline(file, product);
|
||||
return file.good() ? (boost::format("%1% (%2%)") % product % path).str() : path;
|
||||
#ifdef __linux__
|
||||
optional<std::string> sysfs_tty_prop(const std::string &tty_dev, const std::string &name)
|
||||
{
|
||||
const auto prop_path = (boost::format("/sys/class/tty/%1%/device/../%2%") % tty_dev % name).str();
|
||||
std::ifstream file(prop_path);
|
||||
std::string res;
|
||||
|
||||
std::getline(file, res);
|
||||
if (file.good()) { return res; }
|
||||
else { return boost::none; }
|
||||
}
|
||||
|
||||
optional<unsigned long> sysfs_tty_prop_hex(const std::string &tty_dev, const std::string &name)
|
||||
{
|
||||
auto prop = sysfs_tty_prop(tty_dev, name);
|
||||
if (!prop) { return boost::none; }
|
||||
|
||||
try { return std::stoul(*prop, 0, 16); }
|
||||
catch (...) { return boost::none; }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -80,6 +130,7 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
|
|||
if (port_info.port.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the size required to hold the device info.
|
||||
DWORD regDataType;
|
||||
DWORD reqSize = 0;
|
||||
|
@ -88,7 +139,8 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
|
|||
// Now store it in a buffer.
|
||||
if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, (BYTE*)hardware_id.data(), reqSize, nullptr))
|
||||
continue;
|
||||
port_info.hardware_id = boost::nowide::narrow(hardware_id.data());
|
||||
parse_hardware_id(boost::nowide::narrow(hardware_id.data()), port_info);
|
||||
|
||||
// Find the size required to hold the friendly name.
|
||||
reqSize = 0;
|
||||
SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize);
|
||||
|
@ -120,6 +172,8 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
|
|||
if (result) {
|
||||
SerialPortInfo port_info;
|
||||
port_info.port = path;
|
||||
|
||||
// Attempt to read out the device friendly name
|
||||
if ((cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
|
||||
CFSTR("USB Interface Name"), kCFAllocatorDefault,
|
||||
kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
|
||||
|
@ -141,6 +195,23 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
|
|||
}
|
||||
if (port_info.friendly_name.empty())
|
||||
port_info.friendly_name = port_info.port;
|
||||
|
||||
// Attempt to read out the VID & PID
|
||||
int vid, pid;
|
||||
auto cf_vendor = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idVendor"),
|
||||
kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
|
||||
auto cf_product = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idProduct"),
|
||||
kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
|
||||
if (cf_vendor && cf_product) {
|
||||
if (CFNumberGetValue((CFNumberRef)cf_vendor, kCFNumberIntType, &vid) &&
|
||||
CFNumberGetValue((CFNumberRef)cf_product, kCFNumberIntType, &pid)) {
|
||||
port_info.id_vendor = vid;
|
||||
port_info.id_product = pid;
|
||||
}
|
||||
}
|
||||
if (cf_vendor) { CFRelease(cf_vendor); }
|
||||
if (cf_product) { CFRelease(cf_product); }
|
||||
|
||||
output.emplace_back(std::move(port_info));
|
||||
}
|
||||
}
|
||||
|
@ -158,9 +229,15 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
|
|||
const auto path = dir_entry.path().string();
|
||||
SerialPortInfo spi;
|
||||
spi.port = path;
|
||||
spi.hardware_id = path;
|
||||
#ifdef __linux__
|
||||
spi.friendly_name = get_tty_friendly_name(path, name);
|
||||
auto friendly_name = sysfs_tty_prop(name, "product");
|
||||
spi.friendly_name = friendly_name ? (boost::format("%1% (%2%)") % *friendly_name % path).str() : path;
|
||||
auto vid = sysfs_tty_prop_hex(name, "idVendor");
|
||||
auto pid = sysfs_tty_prop_hex(name, "idProduct");
|
||||
if (vid && pid) {
|
||||
spi.id_vendor = *vid;
|
||||
spi.id_product = *pid;
|
||||
}
|
||||
#else
|
||||
spi.friendly_name = path;
|
||||
#endif
|
||||
|
@ -189,5 +266,224 @@ std::vector<std::string> scan_serial_ports()
|
|||
return output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Class Serial
|
||||
|
||||
namespace asio = boost::asio;
|
||||
using boost::system::error_code;
|
||||
|
||||
Serial::Serial(asio::io_service& io_service) :
|
||||
asio::serial_port(io_service)
|
||||
{}
|
||||
|
||||
Serial::Serial(asio::io_service& io_service, const std::string &name, unsigned baud_rate) :
|
||||
asio::serial_port(io_service, name)
|
||||
{
|
||||
set_baud_rate(baud_rate);
|
||||
}
|
||||
|
||||
Serial::~Serial() {}
|
||||
|
||||
void Serial::set_baud_rate(unsigned baud_rate)
|
||||
{
|
||||
try {
|
||||
// This does not support speeds > 115200
|
||||
set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
|
||||
} catch (boost::system::system_error &) {
|
||||
auto handle = native_handle();
|
||||
|
||||
auto handle_errno = [](int retval) {
|
||||
if (retval != 0) {
|
||||
throw std::runtime_error(
|
||||
(boost::format("Could not set baud rate: %1%") % strerror(errno)).str()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
#if __APPLE__
|
||||
termios ios;
|
||||
handle_errno(::tcgetattr(handle, &ios));
|
||||
handle_errno(::cfsetspeed(&ios, baud_rate));
|
||||
speed_t newSpeed = baud_rate;
|
||||
handle_errno(::ioctl(handle, IOSSIOSPEED, &newSpeed));
|
||||
handle_errno(::tcsetattr(handle, TCSANOW, &ios));
|
||||
#elif __linux
|
||||
|
||||
/* The following definitions are kindly borrowed from:
|
||||
/usr/include/asm-generic/termbits.h
|
||||
Unfortunately we cannot just include that one because
|
||||
it would redefine the "struct termios" already defined
|
||||
the <termios.h> already included by Boost.ASIO. */
|
||||
#define K_NCCS 19
|
||||
struct termios2 {
|
||||
tcflag_t c_iflag;
|
||||
tcflag_t c_oflag;
|
||||
tcflag_t c_cflag;
|
||||
tcflag_t c_lflag;
|
||||
cc_t c_line;
|
||||
cc_t c_cc[K_NCCS];
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
};
|
||||
#define BOTHER CBAUDEX
|
||||
|
||||
termios2 ios;
|
||||
handle_errno(::ioctl(handle, TCGETS2, &ios));
|
||||
ios.c_ispeed = ios.c_ospeed = baud_rate;
|
||||
ios.c_cflag &= ~CBAUD;
|
||||
ios.c_cflag |= BOTHER | CLOCAL | CREAD;
|
||||
ios.c_cc[VMIN] = 1; // Minimum of characters to read, prevents eof errors when 0 bytes are read
|
||||
ios.c_cc[VTIME] = 1;
|
||||
handle_errno(::ioctl(handle, TCSETS2, &ios));
|
||||
|
||||
#elif __OpenBSD__
|
||||
struct termios ios;
|
||||
handle_errno(::tcgetattr(handle, &ios));
|
||||
handle_errno(::cfsetspeed(&ios, baud_rate));
|
||||
handle_errno(::tcsetattr(handle, TCSAFLUSH, &ios));
|
||||
#else
|
||||
throw std::runtime_error("Custom baud rates are not currently supported on this OS");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Serial::set_DTR(bool on)
|
||||
{
|
||||
auto handle = native_handle();
|
||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
||||
if (! EscapeCommFunction(handle, on ? SETDTR : CLRDTR)) {
|
||||
throw std::runtime_error("Could not set serial port DTR");
|
||||
}
|
||||
#else
|
||||
int status;
|
||||
if (::ioctl(handle, TIOCMGET, &status) == 0) {
|
||||
on ? status |= TIOCM_DTR : status &= ~TIOCM_DTR;
|
||||
if (::ioctl(handle, TIOCMSET, &status) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error(
|
||||
(boost::format("Could not set serial port DTR: %1%") % strerror(errno)).str()
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Serial::reset_line_num()
|
||||
{
|
||||
// See https://github.com/MarlinFirmware/Marlin/wiki/M110
|
||||
printer_write_line("M110 N0", 0);
|
||||
m_line_num = 0;
|
||||
}
|
||||
|
||||
bool Serial::read_line(unsigned timeout, std::string &line, error_code &ec)
|
||||
{
|
||||
auto &io_service = get_io_service();
|
||||
asio::deadline_timer timer(io_service);
|
||||
char c = 0;
|
||||
bool fail = false;
|
||||
|
||||
while (true) {
|
||||
io_service.reset();
|
||||
|
||||
asio::async_read(*this, boost::asio::buffer(&c, 1), [&](const error_code &read_ec, size_t size) {
|
||||
if (ec || size == 0) {
|
||||
fail = true;
|
||||
ec = read_ec;
|
||||
}
|
||||
timer.cancel();
|
||||
});
|
||||
|
||||
if (timeout > 0) {
|
||||
timer.expires_from_now(boost::posix_time::milliseconds(timeout));
|
||||
timer.async_wait([&](const error_code &ec) {
|
||||
// Ignore timer aborts
|
||||
if (!ec) {
|
||||
fail = true;
|
||||
this->cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
io_service.run();
|
||||
|
||||
if (fail) {
|
||||
return false;
|
||||
} else if (c != '\n') {
|
||||
line += c;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Serial::printer_setup()
|
||||
{
|
||||
printer_reset();
|
||||
write_string("\r\r\r\r\r\r\r\r\r\r"); // Gets rid of line noise, if any
|
||||
}
|
||||
|
||||
size_t Serial::write_string(const std::string &str)
|
||||
{
|
||||
// TODO: might be wise to timeout here as well
|
||||
return asio::write(*this, asio::buffer(str));
|
||||
}
|
||||
|
||||
bool Serial::printer_ready_wait(unsigned retries, unsigned timeout)
|
||||
{
|
||||
std::string line;
|
||||
error_code ec;
|
||||
|
||||
for (; retries > 0; retries--) {
|
||||
reset_line_num();
|
||||
|
||||
while (read_line(timeout, line, ec)) {
|
||||
if (line == "ok") {
|
||||
return true;
|
||||
}
|
||||
line.clear();
|
||||
}
|
||||
line.clear();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t Serial::printer_write_line(const std::string &line, unsigned line_num)
|
||||
{
|
||||
const auto formatted_line = Utils::Serial::printer_format_line(line, line_num);
|
||||
return write_string(formatted_line);
|
||||
}
|
||||
|
||||
size_t Serial::printer_write_line(const std::string &line)
|
||||
{
|
||||
m_line_num++;
|
||||
return printer_write_line(line, m_line_num);
|
||||
}
|
||||
|
||||
void Serial::printer_reset()
|
||||
{
|
||||
this->set_DTR(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
this->set_DTR(true);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
this->set_DTR(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
||||
}
|
||||
|
||||
std::string Serial::printer_format_line(const std::string &line, unsigned line_num)
|
||||
{
|
||||
const auto line_num_str = std::to_string(line_num);
|
||||
|
||||
unsigned checksum = 'N';
|
||||
for (auto c : line_num_str) { checksum ^= c; }
|
||||
checksum ^= ' ';
|
||||
for (auto c : line) { checksum ^= c; }
|
||||
|
||||
return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -1,31 +1,80 @@
|
|||
#ifndef slic3r_GUI_Utils_Serial_hpp_
|
||||
#define slic3r_GUI_Utils_Serial_hpp_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
struct SerialPortInfo {
|
||||
std::string port;
|
||||
std::string hardware_id;
|
||||
unsigned id_vendor = -1;
|
||||
unsigned id_product = -1;
|
||||
std::string friendly_name;
|
||||
bool is_printer = false;
|
||||
bool is_printer = false;
|
||||
|
||||
bool id_match(unsigned id_vendor, unsigned id_product) const { return id_vendor == this->id_vendor && id_product == this->id_product; }
|
||||
};
|
||||
|
||||
inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2)
|
||||
inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2)
|
||||
{
|
||||
return sp1.port == sp2.port &&
|
||||
sp1.hardware_id == sp2.hardware_id &&
|
||||
sp1.is_printer == sp2.is_printer;
|
||||
return
|
||||
sp1.port == sp2.port &&
|
||||
sp1.id_vendor == sp2.id_vendor &&
|
||||
sp1.id_product == sp2.id_product &&
|
||||
sp1.is_printer == sp2.is_printer;
|
||||
}
|
||||
|
||||
extern std::vector<std::string> scan_serial_ports();
|
||||
extern std::vector<SerialPortInfo> scan_serial_ports_extended();
|
||||
|
||||
|
||||
class Serial : public boost::asio::serial_port
|
||||
{
|
||||
public:
|
||||
Serial(boost::asio::io_service &io_service);
|
||||
Serial(boost::asio::io_service &io_service, const std::string &name, unsigned baud_rate);
|
||||
Serial(const Serial &) = delete;
|
||||
Serial &operator=(const Serial &) = delete;
|
||||
~Serial();
|
||||
|
||||
void set_baud_rate(unsigned baud_rate);
|
||||
void set_DTR(bool on);
|
||||
|
||||
// Resets the line number both internally as well as with the firmware using M110
|
||||
void reset_line_num();
|
||||
|
||||
// Reads a line or times out, the timeout is in milliseconds
|
||||
bool read_line(unsigned timeout, std::string &line, boost::system::error_code &ec);
|
||||
|
||||
// Perform setup for communicating with a printer
|
||||
void printer_setup();
|
||||
|
||||
// Write data from a string
|
||||
size_t write_string(const std::string &str);
|
||||
|
||||
bool printer_ready_wait(unsigned retries, unsigned timeout);
|
||||
|
||||
// Write Marlin-formatted line, with a line number and a checksum
|
||||
size_t printer_write_line(const std::string &line, unsigned line_num);
|
||||
|
||||
// Same as above, but with internally-managed line number
|
||||
size_t printer_write_line(const std::string &line);
|
||||
|
||||
// Toggles DTR to reset the printer
|
||||
void printer_reset();
|
||||
|
||||
// Formats a line Marlin-style, ie. with a sequential number and a checksum
|
||||
static std::string printer_format_line(const std::string &line, unsigned line_num);
|
||||
private:
|
||||
unsigned m_line_num = 0;
|
||||
};
|
||||
|
||||
|
||||
} // Utils
|
||||
} // Slic3r
|
||||
|
||||
|
|
|
@ -430,6 +430,13 @@ enable_force_zoom_to_bed(canvas, enable)
|
|||
CODE:
|
||||
_3DScene::enable_force_zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
enable_dynamic_background(canvas, enable)
|
||||
SV *canvas;
|
||||
bool enable;
|
||||
CODE:
|
||||
_3DScene::enable_dynamic_background((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
|
||||
|
||||
void
|
||||
allow_multisample(canvas, allow)
|
||||
SV *canvas;
|
||||
|
@ -657,27 +664,6 @@ reload_scene(canvas, force)
|
|||
CODE:
|
||||
_3DScene::reload_scene((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), force);
|
||||
|
||||
void
|
||||
load_print_toolpaths(canvas)
|
||||
SV *canvas;
|
||||
CODE:
|
||||
_3DScene::load_print_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||
|
||||
void
|
||||
load_print_object_toolpaths(canvas, print_object, tool_colors)
|
||||
SV *canvas;
|
||||
PrintObject *print_object;
|
||||
std::vector<std::string> tool_colors;
|
||||
CODE:
|
||||
_3DScene::load_print_object_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print_object, tool_colors);
|
||||
|
||||
void
|
||||
load_wipe_tower_toolpaths(canvas, tool_colors)
|
||||
SV *canvas;
|
||||
std::vector<std::string> tool_colors;
|
||||
CODE:
|
||||
_3DScene::load_wipe_tower_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), tool_colors);
|
||||
|
||||
void
|
||||
load_gcode_preview(canvas, preview_data, str_tool_colors)
|
||||
SV *canvas;
|
||||
|
@ -685,5 +671,12 @@ load_gcode_preview(canvas, preview_data, str_tool_colors)
|
|||
std::vector<std::string> str_tool_colors;
|
||||
CODE:
|
||||
_3DScene::load_gcode_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), preview_data, str_tool_colors);
|
||||
|
||||
|
||||
void
|
||||
load_preview(canvas, str_tool_colors)
|
||||
SV *canvas;
|
||||
std::vector<std::string> str_tool_colors;
|
||||
CODE:
|
||||
_3DScene::load_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), str_tool_colors);
|
||||
|
||||
%}
|
||||
|
|
Loading…
Add table
Reference in a new issue