mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 20:25:54 +08:00
Merge branch 'gcode_preview'
This commit is contained in:
commit
f38e0f2b4f
@ -66,6 +66,9 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init
|
|||||||
_camera_target
|
_camera_target
|
||||||
_camera_distance
|
_camera_distance
|
||||||
_zoom
|
_zoom
|
||||||
|
|
||||||
|
_legend_enabled
|
||||||
|
|
||||||
) );
|
) );
|
||||||
|
|
||||||
use constant TRACKBALLSIZE => 0.8;
|
use constant TRACKBALLSIZE => 0.8;
|
||||||
@ -137,6 +140,7 @@ sub new {
|
|||||||
$self->_stheta(45);
|
$self->_stheta(45);
|
||||||
$self->_sphi(45);
|
$self->_sphi(45);
|
||||||
$self->_zoom(1);
|
$self->_zoom(1);
|
||||||
|
$self->_legend_enabled(0);
|
||||||
$self->use_plain_shader(0);
|
$self->use_plain_shader(0);
|
||||||
|
|
||||||
# Collection of GLVolume objects
|
# Collection of GLVolume objects
|
||||||
@ -209,6 +213,11 @@ sub new {
|
|||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub set_legend_enabled {
|
||||||
|
my ($self, $value) = @_;
|
||||||
|
$self->_legend_enabled($value);
|
||||||
|
}
|
||||||
|
|
||||||
sub Destroy {
|
sub Destroy {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
$self->{layer_height_edit_timer}->Stop;
|
$self->{layer_height_edit_timer}->Stop;
|
||||||
@ -1316,6 +1325,9 @@ sub Render {
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# draw gcode preview legend
|
||||||
|
$self->draw_legend;
|
||||||
|
|
||||||
$self->draw_active_object_annotations;
|
$self->draw_active_object_annotations;
|
||||||
|
|
||||||
$self->SwapBuffers();
|
$self->SwapBuffers();
|
||||||
@ -1449,12 +1461,18 @@ sub _variable_layer_thickness_load_reset_image {
|
|||||||
# Paint the tooltip.
|
# Paint the tooltip.
|
||||||
sub _render_image {
|
sub _render_image {
|
||||||
my ($self, $image, $l, $r, $b, $t) = @_;
|
my ($self, $image, $l, $r, $b, $t) = @_;
|
||||||
|
$self->_render_texture($image->{texture_id}, $l, $r, $b, $t);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _render_texture {
|
||||||
|
my ($self, $tex_id, $l, $r, $b, $t) = @_;
|
||||||
|
|
||||||
glColor4f(1.,1.,1.,1.);
|
glColor4f(1.,1.,1.,1.);
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, $image->{texture_id});
|
glBindTexture(GL_TEXTURE_2D, $tex_id);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2d(0.,1.); glVertex3f($l, $b, 0);
|
glTexCoord2d(0.,1.); glVertex3f($l, $b, 0);
|
||||||
glTexCoord2d(1.,1.); glVertex3f($r, $b, 0);
|
glTexCoord2d(1.,1.); glVertex3f($r, $b, 0);
|
||||||
@ -1579,6 +1597,37 @@ sub draw_active_object_annotations {
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub draw_legend {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
if ($self->_legend_enabled)
|
||||||
|
{
|
||||||
|
my $tex_id = Slic3r::GUI::_3DScene::get_legend_texture_id;
|
||||||
|
if ($tex_id > 0)
|
||||||
|
{
|
||||||
|
my $tex_w = Slic3r::GUI::_3DScene::get_legend_texture_width;
|
||||||
|
my $tex_h = Slic3r::GUI::_3DScene::get_legend_texture_height;
|
||||||
|
if (($tex_w > 0) && ($tex_h > 0))
|
||||||
|
{
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
my ($cw, $ch) = $self->GetSizeWH;
|
||||||
|
|
||||||
|
my $l = (-0.5 * $cw) / $self->_zoom;
|
||||||
|
my $t = (0.5 * $ch) / $self->_zoom;
|
||||||
|
my $r = $l + $tex_w / $self->_zoom;
|
||||||
|
my $b = $t - $tex_h / $self->_zoom;
|
||||||
|
$self->_render_texture($tex_id, $l, $r, $b, $t);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub opengl_info
|
sub opengl_info
|
||||||
{
|
{
|
||||||
my ($self, %params) = @_;
|
my ($self, %params) = @_;
|
||||||
@ -1979,9 +2028,20 @@ sub load_wipe_tower_toolpaths {
|
|||||||
if ($print->step_done(STEP_WIPE_TOWER));
|
if ($print->step_done(STEP_WIPE_TOWER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub load_gcode_preview {
|
||||||
|
my ($self, $print, $colors) = @_;
|
||||||
|
|
||||||
|
$self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||||
|
Slic3r::GUI::_3DScene::load_gcode_preview($print, $self->volumes, $colors, $self->UseVBOs);
|
||||||
|
}
|
||||||
|
|
||||||
sub set_toolpaths_range {
|
sub set_toolpaths_range {
|
||||||
my ($self, $min_z, $max_z) = @_;
|
my ($self, $min_z, $max_z) = @_;
|
||||||
$self->volumes->set_range($min_z, $max_z);
|
$self->volumes->set_range($min_z, $max_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub reset_legend_texture {
|
||||||
|
Slic3r::GUI::_3DScene::reset_legend_texture();
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -156,7 +156,14 @@ sub new {
|
|||||||
|
|
||||||
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
|
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
|
||||||
my $preview = $self->{preview_notebook}->GetCurrentPage;
|
my $preview = $self->{preview_notebook}->GetCurrentPage;
|
||||||
$self->{preview3D}->load_print(1) if ($preview == $self->{preview3D});
|
if ($preview == $self->{preview3D})
|
||||||
|
{
|
||||||
|
$self->{preview3D}->canvas->set_legend_enabled(1);
|
||||||
|
$self->{preview3D}->load_print(1);
|
||||||
|
} else {
|
||||||
|
$self->{preview3D}->canvas->set_legend_enabled(0);
|
||||||
|
}
|
||||||
|
|
||||||
$preview->OnActivate if $preview->can('OnActivate');
|
$preview->OnActivate if $preview->can('OnActivate');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -778,6 +785,7 @@ sub remove {
|
|||||||
splice @{$self->{objects}}, $obj_idx, 1;
|
splice @{$self->{objects}}, $obj_idx, 1;
|
||||||
$self->{model}->delete_object($obj_idx);
|
$self->{model}->delete_object($obj_idx);
|
||||||
$self->{print}->delete_object($obj_idx);
|
$self->{print}->delete_object($obj_idx);
|
||||||
|
$self->{print}->clear_gcode_preview_data;
|
||||||
$self->{list}->DeleteItem($obj_idx);
|
$self->{list}->DeleteItem($obj_idx);
|
||||||
$self->object_list_changed;
|
$self->object_list_changed;
|
||||||
|
|
||||||
@ -798,6 +806,7 @@ sub reset {
|
|||||||
@{$self->{objects}} = ();
|
@{$self->{objects}} = ();
|
||||||
$self->{model}->clear_objects;
|
$self->{model}->clear_objects;
|
||||||
$self->{print}->clear_objects;
|
$self->{print}->clear_objects;
|
||||||
|
$self->{print}->clear_gcode_preview_data;
|
||||||
$self->{list}->DeleteAllItems;
|
$self->{list}->DeleteAllItems;
|
||||||
$self->object_list_changed;
|
$self->object_list_changed;
|
||||||
|
|
||||||
@ -1257,6 +1266,8 @@ sub reslice {
|
|||||||
$self->stop_background_process;
|
$self->stop_background_process;
|
||||||
# Rather perform one additional unnecessary update of the print object instead of skipping a pending async update.
|
# Rather perform one additional unnecessary update of the print object instead of skipping a pending async update.
|
||||||
$self->async_apply_config;
|
$self->async_apply_config;
|
||||||
|
# Reset gcode data
|
||||||
|
$self->{print}->clear_gcode_preview_data;
|
||||||
$self->statusbar->SetCancelCallback(sub {
|
$self->statusbar->SetCancelCallback(sub {
|
||||||
$self->stop_background_process;
|
$self->stop_background_process;
|
||||||
$self->statusbar->SetStatusText("Slicing cancelled");
|
$self->statusbar->SetStatusText("Slicing cancelled");
|
||||||
@ -1447,6 +1458,10 @@ sub on_export_completed {
|
|||||||
|
|
||||||
# this updates buttons status
|
# this updates buttons status
|
||||||
$self->object_list_changed;
|
$self->object_list_changed;
|
||||||
|
|
||||||
|
# refresh preview
|
||||||
|
$self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
|
||||||
|
$self->{preview3D}->reload_print if $self->{preview3D};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub do_print {
|
sub do_print {
|
||||||
|
@ -4,11 +4,11 @@ use warnings;
|
|||||||
use utf8;
|
use utf8;
|
||||||
|
|
||||||
use Slic3r::Print::State ':steps';
|
use Slic3r::Print::State ':steps';
|
||||||
use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE);
|
use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE wxCB_READONLY);
|
||||||
use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN EVT_CHECKBOX);
|
use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN EVT_CHECKBOX EVT_CHOICE EVT_CHECKLISTBOX);
|
||||||
use base qw(Wx::Panel Class::Accessor);
|
use base qw(Wx::Panel Class::Accessor);
|
||||||
|
|
||||||
__PACKAGE__->mk_accessors(qw(print enabled _loaded canvas slider_low slider_high single_layer));
|
__PACKAGE__->mk_accessors(qw(print enabled _loaded canvas slider_low slider_high single_layer auto_zoom));
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
@ -17,7 +17,7 @@ sub new {
|
|||||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition);
|
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition);
|
||||||
$self->{config} = $config;
|
$self->{config} = $config;
|
||||||
$self->{number_extruders} = 1;
|
$self->{number_extruders} = 1;
|
||||||
$self->{preferred_color_mode} = 'feature';
|
$self->auto_zoom(1);
|
||||||
|
|
||||||
# init GUI elements
|
# init GUI elements
|
||||||
my $canvas = Slic3r::GUI::3DScene->new($self);
|
my $canvas = Slic3r::GUI::3DScene->new($self);
|
||||||
@ -56,9 +56,34 @@ sub new {
|
|||||||
$z_label_high->SetFont($Slic3r::GUI::small_font);
|
$z_label_high->SetFont($Slic3r::GUI::small_font);
|
||||||
|
|
||||||
$self->single_layer(0);
|
$self->single_layer(0);
|
||||||
$self->{color_by_extruder} = 0;
|
|
||||||
my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, "1 Layer");
|
my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, "1 Layer");
|
||||||
my $checkbox_color_by_extruder = $self->{checkbox_color_by_extruder} = Wx::CheckBox->new($self, -1, "Tool");
|
|
||||||
|
my $label_view_type = $self->{label_view_type} = Wx::StaticText->new($self, -1, "View");
|
||||||
|
|
||||||
|
my $choice_view_type = Wx::Choice->new($self, -1);
|
||||||
|
$choice_view_type->Append("Feature type");
|
||||||
|
$choice_view_type->Append("Height");
|
||||||
|
$choice_view_type->Append("Width");
|
||||||
|
$choice_view_type->Append("Speed");
|
||||||
|
$choice_view_type->Append("Tool");
|
||||||
|
$choice_view_type->SetSelection(0);
|
||||||
|
|
||||||
|
my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, "Show");
|
||||||
|
|
||||||
|
my $combochecklist_features = Wx::ComboCtrl->new();
|
||||||
|
$combochecklist_features->Create($self, -1, "Feature types", wxDefaultPosition, [200, -1], wxCB_READONLY);
|
||||||
|
#FIXME If the following line is removed, the combo box popup list will not react to mouse clicks.
|
||||||
|
# On the other side, with this line the combo box popup cannot be closed by clicking on the combo button on Windows 10.
|
||||||
|
$combochecklist_features->UseAltPopupWindow();
|
||||||
|
$combochecklist_features->EnablePopupAnimation(0);
|
||||||
|
my $feature_text = "Feature types";
|
||||||
|
my $feature_items = "Perimeter|External perimeter|Overhang perimeter|Internal infill|Solid infill|Top solid infill|Bridge infill|Gap fill|Skirt|Support material|Support material interface|Wipe tower";
|
||||||
|
Slic3r::GUI::create_combochecklist($combochecklist_features, $feature_text, $feature_items, 1);
|
||||||
|
|
||||||
|
my $checkbox_travel = Wx::CheckBox->new($self, -1, "Travel");
|
||||||
|
my $checkbox_retractions = Wx::CheckBox->new($self, -1, "Retractions");
|
||||||
|
my $checkbox_unretractions = Wx::CheckBox->new($self, -1, "Unretractions");
|
||||||
|
my $checkbox_shells = Wx::CheckBox->new($self, -1, "Shells");
|
||||||
|
|
||||||
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
|
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
@ -72,12 +97,30 @@ sub new {
|
|||||||
$hsizer->Add($vsizer, 0, wxEXPAND, 0);
|
$hsizer->Add($vsizer, 0, wxEXPAND, 0);
|
||||||
$vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0);
|
$vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||||
$vsizer_outer->Add($checkbox_singlelayer, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5);
|
$vsizer_outer->Add($checkbox_singlelayer, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5);
|
||||||
$vsizer_outer->Add($checkbox_color_by_extruder, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5);
|
|
||||||
|
my $bottom_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
$bottom_sizer->Add($label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->Add($choice_view_type, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->AddSpacer(10);
|
||||||
|
$bottom_sizer->Add($label_show_features, 0, wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->Add($combochecklist_features, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->AddSpacer(20);
|
||||||
|
$bottom_sizer->Add($checkbox_travel, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->AddSpacer(10);
|
||||||
|
$bottom_sizer->Add($checkbox_retractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->AddSpacer(10);
|
||||||
|
$bottom_sizer->Add($checkbox_unretractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
$bottom_sizer->AddSpacer(10);
|
||||||
|
$bottom_sizer->Add($checkbox_shells, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
|
||||||
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
$sizer->Add($canvas, 1, wxALL | wxEXPAND, 0);
|
$sizer->Add($canvas, 1, wxALL | wxEXPAND, 0);
|
||||||
$sizer->Add($vsizer_outer, 0, wxTOP | wxBOTTOM | wxEXPAND, 5);
|
$sizer->Add($vsizer_outer, 0, wxTOP | wxBOTTOM | wxEXPAND, 5);
|
||||||
|
|
||||||
|
my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
|
$main_sizer->Add($sizer, 1, wxALL | wxEXPAND, 0);
|
||||||
|
$main_sizer->Add($bottom_sizer, 0, wxALL | wxEXPAND, 0);
|
||||||
|
|
||||||
EVT_SLIDER($self, $slider_low, sub {
|
EVT_SLIDER($self, $slider_low, sub {
|
||||||
$slider_high->SetValue($slider_low->GetValue) if $self->single_layer;
|
$slider_high->SetValue($slider_low->GetValue) if $self->single_layer;
|
||||||
$self->set_z_idx_low ($slider_low ->GetValue)
|
$self->set_z_idx_low ($slider_low ->GetValue)
|
||||||
@ -147,18 +190,70 @@ sub new {
|
|||||||
$self->set_z_idx_high($slider_high->GetValue);
|
$self->set_z_idx_high($slider_high->GetValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
EVT_CHECKBOX($self, $checkbox_color_by_extruder, sub {
|
EVT_CHOICE($self, $choice_view_type, sub {
|
||||||
$self->{color_by_extruder} = $checkbox_color_by_extruder->GetValue();
|
my $selection = $choice_view_type->GetCurrentSelection();
|
||||||
$self->{preferred_color_mode} = $self->{color_by_extruder} ? 'tool' : 'feature';
|
$self->print->set_gcode_preview_type($selection);
|
||||||
|
$self->auto_zoom(0);
|
||||||
$self->reload_print;
|
$self->reload_print;
|
||||||
|
$self->auto_zoom(1);
|
||||||
|
});
|
||||||
|
EVT_CHECKLISTBOX($self, $combochecklist_features, sub {
|
||||||
|
my $flags = Slic3r::GUI::combochecklist_get_flags($combochecklist_features);
|
||||||
|
|
||||||
|
$self->print->set_gcode_preview_extrusion_flags($flags);
|
||||||
|
$self->auto_zoom(0);
|
||||||
|
$self->refresh_print;
|
||||||
|
$self->auto_zoom(1);
|
||||||
|
});
|
||||||
|
EVT_CHECKBOX($self, $checkbox_travel, sub {
|
||||||
|
$self->print->set_gcode_preview_travel_visible($checkbox_travel->IsChecked());
|
||||||
|
$self->auto_zoom(0);
|
||||||
|
$self->refresh_print;
|
||||||
|
$self->auto_zoom(1);
|
||||||
|
});
|
||||||
|
EVT_CHECKBOX($self, $checkbox_retractions, sub {
|
||||||
|
$self->print->set_gcode_preview_retractions_visible($checkbox_retractions->IsChecked());
|
||||||
|
$self->auto_zoom(0);
|
||||||
|
$self->refresh_print;
|
||||||
|
$self->auto_zoom(1);
|
||||||
|
});
|
||||||
|
EVT_CHECKBOX($self, $checkbox_unretractions, sub {
|
||||||
|
$self->print->set_gcode_preview_unretractions_visible($checkbox_unretractions->IsChecked());
|
||||||
|
$self->auto_zoom(0);
|
||||||
|
$self->refresh_print;
|
||||||
|
$self->auto_zoom(1);
|
||||||
|
});
|
||||||
|
EVT_CHECKBOX($self, $checkbox_shells, sub {
|
||||||
|
$self->print->set_gcode_preview_shells_visible($checkbox_shells->IsChecked());
|
||||||
|
$self->auto_zoom(0);
|
||||||
|
$self->refresh_print;
|
||||||
|
$self->auto_zoom(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
$self->SetSizer($sizer);
|
$self->SetSizer($main_sizer);
|
||||||
$self->SetMinSize($self->GetSize);
|
$self->SetMinSize($self->GetSize);
|
||||||
$sizer->SetSizeHints($self);
|
$sizer->SetSizeHints($self);
|
||||||
|
|
||||||
# init canvas
|
# init canvas
|
||||||
$self->print($print);
|
$self->print($print);
|
||||||
|
|
||||||
|
# sets colors for gcode preview extrusion roles
|
||||||
|
my @extrusion_roles_colors = (
|
||||||
|
'Perimeter' => 'FF0000',
|
||||||
|
'External perimeter' => '00FF00',
|
||||||
|
'Overhang perimeter' => '0000FF',
|
||||||
|
'Internal infill' => 'FFFF00',
|
||||||
|
'Solid infill' => 'FF00FF',
|
||||||
|
'Top solid infill' => '00FFFF',
|
||||||
|
'Bridge infill' => '7F7F7F',
|
||||||
|
'Gap fill' => 'FFFFFF',
|
||||||
|
'Skirt' => '7F0000',
|
||||||
|
'Support material' => '007F00',
|
||||||
|
'Support material interface' => '00007F',
|
||||||
|
'Wipe tower' => 'B3E3AB',
|
||||||
|
);
|
||||||
|
$self->print->set_gcode_extrusion_paths_colors(\@extrusion_roles_colors);
|
||||||
|
|
||||||
$self->reload_print;
|
$self->reload_print;
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
@ -171,7 +266,19 @@ sub reload_print {
|
|||||||
$self->_loaded(0);
|
$self->_loaded(0);
|
||||||
|
|
||||||
if (! $self->IsShown && ! $force) {
|
if (! $self->IsShown && ! $force) {
|
||||||
$self->{reload_delayed} = 1;
|
# $self->{reload_delayed} = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->load_print;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub refresh_print {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
$self->_loaded(0);
|
||||||
|
|
||||||
|
if (! $self->IsShown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +310,9 @@ sub load_print {
|
|||||||
$self->set_z_range(0,0);
|
$self->set_z_range(0,0);
|
||||||
$self->slider_low->Hide;
|
$self->slider_low->Hide;
|
||||||
$self->slider_high->Hide;
|
$self->slider_high->Hide;
|
||||||
|
$self->{z_label_low}->SetLabel("");
|
||||||
|
$self->{z_label_high}->SetLabel("");
|
||||||
|
$self->canvas->reset_legend_texture();
|
||||||
$self->canvas->Refresh; # clears canvas
|
$self->canvas->Refresh; # clears canvas
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -232,44 +342,35 @@ sub load_print {
|
|||||||
$self->slider_high->Show;
|
$self->slider_high->Show;
|
||||||
$self->Layout;
|
$self->Layout;
|
||||||
|
|
||||||
my $by_tool = $self->{color_by_extruder};
|
|
||||||
if ($self->{preferred_color_mode} eq 'tool_or_feature') {
|
|
||||||
# It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature.
|
|
||||||
# Color by feature if it is a single extruder print.
|
|
||||||
my $extruders = $self->{print}->extruders;
|
|
||||||
$by_tool = scalar(@{$extruders}) > 1;
|
|
||||||
$self->{color_by_extruder} = $by_tool;
|
|
||||||
$self->{checkbox_color_by_extruder}->SetValue($by_tool);
|
|
||||||
$self->{preferred_color_mode} = 'tool_or_feature';
|
|
||||||
}
|
|
||||||
|
|
||||||
# Collect colors per extruder.
|
# Collect colors per extruder.
|
||||||
# Leave it empty, if the print should be colored by a feature.
|
|
||||||
my @colors = ();
|
my @colors = ();
|
||||||
if ($by_tool) {
|
my @extruder_colors = @{$self->{config}->extruder_colour};
|
||||||
my @extruder_colors = @{$self->{config}->extruder_colour};
|
my @filament_colors = @{$self->{config}->filament_colour};
|
||||||
my @filament_colors = @{$self->{config}->filament_colour};
|
for (my $i = 0; $i <= $#extruder_colors; $i += 1) {
|
||||||
for (my $i = 0; $i <= $#extruder_colors; $i += 1) {
|
my $color = $extruder_colors[$i];
|
||||||
my $color = $extruder_colors[$i];
|
$color = $filament_colors[$i] if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/);
|
||||||
$color = $filament_colors[$i] if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/);
|
$color = '#FFFFFF' if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/);
|
||||||
$color = '#FFFFFF' if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/);
|
push @colors, $color;
|
||||||
push @colors, $color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($self->IsShown) {
|
if ($self->IsShown) {
|
||||||
# load skirt and brim
|
$self->canvas->load_gcode_preview($self->print, \@colors);
|
||||||
$self->canvas->load_print_toolpaths($self->print, \@colors);
|
|
||||||
$self->canvas->load_wipe_tower_toolpaths($self->print, \@colors);
|
|
||||||
|
|
||||||
foreach my $object (@{$self->print->objects}) {
|
# # load skirt and brim
|
||||||
$self->canvas->load_print_object_toolpaths($object, \@colors);
|
# $self->canvas->load_print_toolpaths($self->print, \@colors);
|
||||||
|
# $self->canvas->load_wipe_tower_toolpaths($self->print, \@colors);
|
||||||
# Show the objects in very transparent color.
|
#
|
||||||
#my @volume_ids = $self->canvas->load_object($object->model_object);
|
# foreach my $object (@{$self->print->objects}) {
|
||||||
#$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
|
# $self->canvas->load_print_object_toolpaths($object, \@colors);
|
||||||
|
#
|
||||||
|
# # Show the objects in very transparent color.
|
||||||
|
# #my @volume_ids = $self->canvas->load_object($object->model_object);
|
||||||
|
# #$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
|
||||||
|
# }
|
||||||
|
if ($self->auto_zoom)
|
||||||
|
{
|
||||||
|
$self->canvas->zoom_to_volumes;
|
||||||
}
|
}
|
||||||
$self->canvas->zoom_to_volumes;
|
|
||||||
$self->_loaded(1);
|
$self->_loaded(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,17 +423,13 @@ sub set_number_extruders {
|
|||||||
my ($self, $number_extruders) = @_;
|
my ($self, $number_extruders) = @_;
|
||||||
if ($self->{number_extruders} != $number_extruders) {
|
if ($self->{number_extruders} != $number_extruders) {
|
||||||
$self->{number_extruders} = $number_extruders;
|
$self->{number_extruders} = $number_extruders;
|
||||||
my $by_tool = $number_extruders > 1;
|
|
||||||
$self->{color_by_extruder} = $by_tool;
|
|
||||||
$self->{checkbox_color_by_extruder}->SetValue($by_tool);
|
|
||||||
$self->{preferred_color_mode} = $by_tool ? 'tool_or_feature' : 'feature';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Called by the Platter wxNotebook when this page is activated.
|
# Called by the Platter wxNotebook when this page is activated.
|
||||||
sub OnActivate {
|
sub OnActivate {
|
||||||
my ($self) = @_;
|
# my ($self) = @_;
|
||||||
$self->reload_print(1) if ($self->{reload_delayed});
|
# $self->reload_print(1) if ($self->{reload_delayed});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -122,16 +122,19 @@ sub load_print {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($self->IsShown) {
|
if ($self->IsShown) {
|
||||||
# load skirt and brim
|
$self->canvas->load_gcode_preview($self->print);
|
||||||
$self->canvas->load_print_toolpaths($self->print);
|
|
||||||
|
|
||||||
foreach my $object (@{$self->print->objects}) {
|
# # load skirt and brim
|
||||||
$self->canvas->load_print_object_toolpaths($object);
|
# $self->canvas->load_print_toolpaths($self->print);
|
||||||
|
#
|
||||||
|
# foreach my $object (@{$self->print->objects}) {
|
||||||
|
# $self->canvas->load_print_object_toolpaths($object);
|
||||||
|
#
|
||||||
|
# # 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;
|
||||||
|
# }
|
||||||
|
|
||||||
# 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;
|
|
||||||
}
|
|
||||||
$self->canvas->zoom_to_volumes;
|
$self->canvas->zoom_to_volumes;
|
||||||
$self->_loaded(1);
|
$self->_loaded(1);
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,8 @@ add_library(libslic3r_gui STATIC
|
|||||||
${LIBDIR}/slic3r/GUI/PresetHints.hpp
|
${LIBDIR}/slic3r/GUI/PresetHints.hpp
|
||||||
${LIBDIR}/slic3r/GUI/GUI.cpp
|
${LIBDIR}/slic3r/GUI/GUI.cpp
|
||||||
${LIBDIR}/slic3r/GUI/GUI.hpp
|
${LIBDIR}/slic3r/GUI/GUI.hpp
|
||||||
|
${LIBDIR}/slic3r/GUI/wxExtensions.cpp
|
||||||
|
${LIBDIR}/slic3r/GUI/wxExtensions.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(admesh STATIC
|
add_library(admesh STATIC
|
||||||
|
@ -4,38 +4,9 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
template <class PointClass>
|
|
||||||
BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &points)
|
|
||||||
{
|
|
||||||
if (points.empty())
|
|
||||||
CONFESS("Empty point set supplied to BoundingBoxBase constructor");
|
|
||||||
typename std::vector<PointClass>::const_iterator it = points.begin();
|
|
||||||
this->min.x = this->max.x = it->x;
|
|
||||||
this->min.y = this->max.y = it->y;
|
|
||||||
for (++it; it != points.end(); ++it) {
|
|
||||||
this->min.x = std::min(it->x, this->min.x);
|
|
||||||
this->min.y = std::min(it->y, this->min.y);
|
|
||||||
this->max.x = std::max(it->x, this->max.x);
|
|
||||||
this->max.y = std::max(it->y, this->max.y);
|
|
||||||
}
|
|
||||||
this->defined = true;
|
|
||||||
}
|
|
||||||
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
|
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
|
||||||
template BoundingBoxBase<Pointf>::BoundingBoxBase(const std::vector<Pointf> &points);
|
template BoundingBoxBase<Pointf>::BoundingBoxBase(const std::vector<Pointf> &points);
|
||||||
|
|
||||||
template <class PointClass>
|
|
||||||
BoundingBox3Base<PointClass>::BoundingBox3Base(const std::vector<PointClass> &points)
|
|
||||||
: BoundingBoxBase<PointClass>(points)
|
|
||||||
{
|
|
||||||
if (points.empty())
|
|
||||||
CONFESS("Empty point set supplied to BoundingBox3Base constructor");
|
|
||||||
typename std::vector<PointClass>::const_iterator it = points.begin();
|
|
||||||
this->min.z = this->max.z = it->z;
|
|
||||||
for (++it; it != points.end(); ++it) {
|
|
||||||
this->min.z = std::min(it->z, this->min.z);
|
|
||||||
this->max.z = std::max(it->z, this->max.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template BoundingBox3Base<Pointf3>::BoundingBox3Base(const std::vector<Pointf3> &points);
|
template BoundingBox3Base<Pointf3>::BoundingBox3Base(const std::vector<Pointf3> &points);
|
||||||
|
|
||||||
BoundingBox::BoundingBox(const Lines &lines)
|
BoundingBox::BoundingBox(const Lines &lines)
|
||||||
|
@ -23,7 +23,23 @@ public:
|
|||||||
BoundingBoxBase() : defined(false) {};
|
BoundingBoxBase() : defined(false) {};
|
||||||
BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) :
|
BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) :
|
||||||
min(pmin), max(pmax), defined(pmin.x < pmax.x && pmin.y < pmax.y) {}
|
min(pmin), max(pmax), defined(pmin.x < pmax.x && pmin.y < pmax.y) {}
|
||||||
BoundingBoxBase(const std::vector<PointClass> &points);
|
BoundingBoxBase(const std::vector<PointClass>& points)
|
||||||
|
{
|
||||||
|
if (points.empty())
|
||||||
|
CONFESS("Empty point set supplied to BoundingBoxBase constructor");
|
||||||
|
|
||||||
|
typename std::vector<PointClass>::const_iterator it = points.begin();
|
||||||
|
this->min.x = this->max.x = it->x;
|
||||||
|
this->min.y = this->max.y = it->y;
|
||||||
|
for (++it; it != points.end(); ++it)
|
||||||
|
{
|
||||||
|
this->min.x = std::min(it->x, this->min.x);
|
||||||
|
this->min.y = std::min(it->y, this->min.y);
|
||||||
|
this->max.x = std::max(it->x, this->max.x);
|
||||||
|
this->max.y = std::max(it->y, this->max.y);
|
||||||
|
}
|
||||||
|
this->defined = (this->min.x < this->max.x) && (this->min.y < this->max.y);
|
||||||
|
}
|
||||||
void merge(const PointClass &point);
|
void merge(const PointClass &point);
|
||||||
void merge(const std::vector<PointClass> &points);
|
void merge(const std::vector<PointClass> &points);
|
||||||
void merge(const BoundingBoxBase<PointClass> &bb);
|
void merge(const BoundingBoxBase<PointClass> &bb);
|
||||||
@ -54,7 +70,21 @@ public:
|
|||||||
BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) :
|
BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) :
|
||||||
BoundingBoxBase<PointClass>(pmin, pmax)
|
BoundingBoxBase<PointClass>(pmin, pmax)
|
||||||
{ if (pmin.z >= pmax.z) BoundingBoxBase<PointClass>::defined = false; }
|
{ if (pmin.z >= pmax.z) BoundingBoxBase<PointClass>::defined = false; }
|
||||||
BoundingBox3Base(const std::vector<PointClass> &points);
|
BoundingBox3Base(const std::vector<PointClass>& points)
|
||||||
|
: BoundingBoxBase<PointClass>(points)
|
||||||
|
{
|
||||||
|
if (points.empty())
|
||||||
|
CONFESS("Empty point set supplied to BoundingBox3Base constructor");
|
||||||
|
|
||||||
|
typename std::vector<PointClass>::const_iterator it = points.begin();
|
||||||
|
this->min.z = this->max.z = it->z;
|
||||||
|
for (++it; it != points.end(); ++it)
|
||||||
|
{
|
||||||
|
this->min.z = std::min(it->z, this->min.z);
|
||||||
|
this->max.z = std::max(it->z, this->max.z);
|
||||||
|
}
|
||||||
|
this->defined &= (this->min.z < this->max.z);
|
||||||
|
}
|
||||||
void merge(const PointClass &point);
|
void merge(const PointClass &point);
|
||||||
void merge(const std::vector<PointClass> &points);
|
void merge(const std::vector<PointClass> &points);
|
||||||
void merge(const BoundingBox3Base<PointClass> &bb);
|
void merge(const BoundingBox3Base<PointClass> &bb);
|
||||||
@ -92,7 +122,7 @@ class BoundingBox3 : public BoundingBox3Base<Point3>
|
|||||||
public:
|
public:
|
||||||
BoundingBox3() : BoundingBox3Base<Point3>() {};
|
BoundingBox3() : BoundingBox3Base<Point3>() {};
|
||||||
BoundingBox3(const Point3 &pmin, const Point3 &pmax) : BoundingBox3Base<Point3>(pmin, pmax) {};
|
BoundingBox3(const Point3 &pmin, const Point3 &pmax) : BoundingBox3Base<Point3>(pmin, pmax) {};
|
||||||
BoundingBox3(const std::vector<Point3> &points) : BoundingBox3Base<Point3>(points) {};
|
BoundingBox3(const Points3& points) : BoundingBox3Base<Point3>(points) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class BoundingBoxf : public BoundingBoxBase<Pointf>
|
class BoundingBoxf : public BoundingBoxBase<Pointf>
|
||||||
|
@ -25,6 +25,7 @@ enum ExtrusionRole {
|
|||||||
erSkirt,
|
erSkirt,
|
||||||
erSupportMaterial,
|
erSupportMaterial,
|
||||||
erSupportMaterialInterface,
|
erSupportMaterialInterface,
|
||||||
|
erWipeTower,
|
||||||
// Extrusion role for a collection with multiple extrusion roles.
|
// Extrusion role for a collection with multiple extrusion roles.
|
||||||
erMixed,
|
erMixed,
|
||||||
};
|
};
|
||||||
@ -104,15 +105,19 @@ public:
|
|||||||
float width;
|
float width;
|
||||||
// Height of the extrusion, used for visualization purposed.
|
// Height of the extrusion, used for visualization purposed.
|
||||||
float height;
|
float height;
|
||||||
|
// Feedrate of the extrusion, used for visualization purposed.
|
||||||
|
float feedrate;
|
||||||
|
// Id of the extruder, used for visualization purposed.
|
||||||
|
unsigned int extruder_id;
|
||||||
|
|
||||||
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role) {};
|
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), m_role(role) {};
|
||||||
ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {};
|
ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), m_role(role) {};
|
||||||
ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role) {}
|
ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), m_role(rhs.m_role) {}
|
||||||
ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role) {}
|
ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), m_role(rhs.m_role) {}
|
||||||
// ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height) {};
|
// ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f), extruder_id(0) {};
|
||||||
|
|
||||||
ExtrusionPath& operator=(const ExtrusionPath &rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->polyline = rhs.polyline; return *this; }
|
ExtrusionPath& operator=(const ExtrusionPath &rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->polyline = rhs.polyline; return *this; }
|
||||||
ExtrusionPath& operator=(ExtrusionPath &&rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->polyline = std::move(rhs.polyline); return *this; }
|
ExtrusionPath& operator=(ExtrusionPath &&rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->polyline = std::move(rhs.polyline); return *this; }
|
||||||
|
|
||||||
ExtrusionPath* clone() const { return new ExtrusionPath (*this); }
|
ExtrusionPath* clone() const { return new ExtrusionPath (*this); }
|
||||||
void reverse() { this->polyline.reverse(); }
|
void reverse() { this->polyline.reverse(); }
|
||||||
|
@ -402,6 +402,14 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||||||
m_time_estimator.reset();
|
m_time_estimator.reset();
|
||||||
m_time_estimator.set_dialect(print.config.gcode_flavor);
|
m_time_estimator.set_dialect(print.config.gcode_flavor);
|
||||||
|
|
||||||
|
// resets analyzer
|
||||||
|
m_analyzer.reset();
|
||||||
|
|
||||||
|
// resets analyzer's tracking data
|
||||||
|
m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm;
|
||||||
|
m_last_width = GCodeAnalyzer::Default_Width;
|
||||||
|
m_last_height = GCodeAnalyzer::Default_Height;
|
||||||
|
|
||||||
// How many times will be change_layer() called?
|
// How many times will be change_layer() called?
|
||||||
// change_layer() in turn increments the progress bar status.
|
// change_layer() in turn increments the progress bar status.
|
||||||
m_layer_count = 0;
|
m_layer_count = 0;
|
||||||
@ -810,6 +818,9 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||||||
_write_format(file, "; %s = %s\n", key.c_str(), cfg->serialize(key).c_str());
|
_write_format(file, "; %s = %s\n", key.c_str(), cfg->serialize(key).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// starts analizer calculations
|
||||||
|
m_analyzer.calc_gcode_preview_data(print);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override)
|
std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override)
|
||||||
@ -1301,12 +1312,7 @@ void GCode::process_layer(
|
|||||||
if (print_object == nullptr)
|
if (print_object == nullptr)
|
||||||
// This layer is empty for this particular object, it has neither object extrusions nor support extrusions at this print_z.
|
// This layer is empty for this particular object, it has neither object extrusions nor support extrusions at this print_z.
|
||||||
continue;
|
continue;
|
||||||
if (m_enable_analyzer_markers) {
|
|
||||||
// Store the binary pointer to the layer object directly into the G-code to be accessed by the GCodeAnalyzer.
|
|
||||||
char buf[64];
|
|
||||||
sprintf(buf, ";_LAYEROBJ:%p\n", m_layer);
|
|
||||||
gcode += buf;
|
|
||||||
}
|
|
||||||
m_config.apply(print_object->config, true);
|
m_config.apply(print_object->config, true);
|
||||||
m_layer = layers[layer_id].layer();
|
m_layer = layers[layer_id].layer();
|
||||||
if (m_config.avoid_crossing_perimeters)
|
if (m_config.avoid_crossing_perimeters)
|
||||||
@ -1448,7 +1454,9 @@ static inline const char* ExtrusionRole2String(const ExtrusionRole role)
|
|||||||
case erSkirt: return "erSkirt";
|
case erSkirt: return "erSkirt";
|
||||||
case erSupportMaterial: return "erSupportMaterial";
|
case erSupportMaterial: return "erSupportMaterial";
|
||||||
case erSupportMaterialInterface: return "erSupportMaterialInterface";
|
case erSupportMaterialInterface: return "erSupportMaterialInterface";
|
||||||
|
case erWipeTower: return "erWipeTower";
|
||||||
case erMixed: return "erMixed";
|
case erMixed: return "erMixed";
|
||||||
|
|
||||||
default: return "erInvalid";
|
default: return "erInvalid";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1998,13 +2006,16 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
|||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCode::_write(FILE* file, const char *what, size_t size)
|
void GCode::_write(FILE* file, const char *what)
|
||||||
{
|
{
|
||||||
if (size > 0) {
|
if (what != nullptr) {
|
||||||
|
// apply analyzer, if enabled
|
||||||
|
const char* gcode = m_enable_analyzer ? m_analyzer.process_gcode(what).c_str() : what;
|
||||||
|
|
||||||
// writes string to file
|
// writes string to file
|
||||||
fwrite(what, 1, size, file);
|
fwrite(gcode, 1, ::strlen(gcode), file);
|
||||||
// updates time estimator and gcode lines vector
|
// updates time estimator and gcode lines vector
|
||||||
m_time_estimator.add_gcode_block(what);
|
m_time_estimator.add_gcode_block(gcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2038,7 +2049,8 @@ void GCode::_write_format(FILE* file, const char* format, ...)
|
|||||||
char *bufptr = buffer_dynamic ? (char*)malloc(buflen) : buffer;
|
char *bufptr = buffer_dynamic ? (char*)malloc(buflen) : buffer;
|
||||||
int res = ::vsnprintf(bufptr, buflen, format, args);
|
int res = ::vsnprintf(bufptr, buflen, format, args);
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
_write(file, bufptr, res);
|
_write(file, bufptr);
|
||||||
|
|
||||||
if (buffer_dynamic)
|
if (buffer_dynamic)
|
||||||
free(bufptr);
|
free(bufptr);
|
||||||
|
|
||||||
@ -2123,14 +2135,57 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||||||
double F = speed * 60; // convert mm/sec to mm/min
|
double F = speed * 60; // convert mm/sec to mm/min
|
||||||
|
|
||||||
// extrude arc or line
|
// extrude arc or line
|
||||||
if (m_enable_extrusion_role_markers || m_enable_analyzer_markers) {
|
if (m_enable_extrusion_role_markers || m_enable_analyzer)
|
||||||
if (path.role() != m_last_extrusion_role) {
|
{
|
||||||
|
if (path.role() != m_last_extrusion_role)
|
||||||
|
{
|
||||||
m_last_extrusion_role = path.role();
|
m_last_extrusion_role = path.role();
|
||||||
|
if (m_enable_extrusion_role_markers)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";_EXTRUSION_ROLE:%d\n", int(m_last_extrusion_role));
|
||||||
|
gcode += buf;
|
||||||
|
}
|
||||||
|
if (m_enable_analyzer)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), int(m_last_extrusion_role));
|
||||||
|
gcode += buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds analyzer tags and updates analyzer's tracking data
|
||||||
|
if (m_enable_analyzer)
|
||||||
|
{
|
||||||
|
if (m_last_mm3_per_mm != path.mm3_per_mm)
|
||||||
|
{
|
||||||
|
m_last_mm3_per_mm = path.mm3_per_mm;
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
sprintf(buf, ";_EXTRUSION_ROLE:%d\n", int(path.role()));
|
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||||
|
gcode += buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_last_width != path.width)
|
||||||
|
{
|
||||||
|
m_last_width = path.width;
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), m_last_width);
|
||||||
|
gcode += buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_last_height != path.height)
|
||||||
|
{
|
||||||
|
m_last_height = path.height;
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_last_height);
|
||||||
gcode += buf;
|
gcode += buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string comment;
|
std::string comment;
|
||||||
if (m_enable_cooling_markers) {
|
if (m_enable_cooling_markers) {
|
||||||
if (is_bridge(path.role()))
|
if (is_bridge(path.role()))
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "GCode/WipeTower.hpp"
|
#include "GCode/WipeTower.hpp"
|
||||||
#include "GCodeTimeEstimator.hpp"
|
#include "GCodeTimeEstimator.hpp"
|
||||||
#include "EdgeGrid.hpp"
|
#include "EdgeGrid.hpp"
|
||||||
|
#include "GCode/Analyzer.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -118,13 +119,16 @@ public:
|
|||||||
m_enable_loop_clipping(true),
|
m_enable_loop_clipping(true),
|
||||||
m_enable_cooling_markers(false),
|
m_enable_cooling_markers(false),
|
||||||
m_enable_extrusion_role_markers(false),
|
m_enable_extrusion_role_markers(false),
|
||||||
m_enable_analyzer_markers(false),
|
m_enable_analyzer(true),
|
||||||
m_layer_count(0),
|
m_layer_count(0),
|
||||||
m_layer_index(-1),
|
m_layer_index(-1),
|
||||||
m_layer(nullptr),
|
m_layer(nullptr),
|
||||||
m_volumetric_speed(0),
|
m_volumetric_speed(0),
|
||||||
m_last_pos_defined(false),
|
m_last_pos_defined(false),
|
||||||
m_last_extrusion_role(erNone),
|
m_last_extrusion_role(erNone),
|
||||||
|
m_last_mm3_per_mm(GCodeAnalyzer::Default_mm3_per_mm),
|
||||||
|
m_last_width(GCodeAnalyzer::Default_Width),
|
||||||
|
m_last_height(GCodeAnalyzer::Default_Height),
|
||||||
m_brim_done(false),
|
m_brim_done(false),
|
||||||
m_second_layer_things_done(false),
|
m_second_layer_things_done(false),
|
||||||
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
|
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
|
||||||
@ -149,6 +153,8 @@ public:
|
|||||||
// inside the generated string and after the G-code export finishes.
|
// inside the generated string and after the G-code export finishes.
|
||||||
std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
|
std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
|
||||||
bool enable_cooling_markers() const { return m_enable_cooling_markers; }
|
bool enable_cooling_markers() const { return m_enable_cooling_markers; }
|
||||||
|
bool enable_analyzer() const { return m_enable_analyzer; }
|
||||||
|
void enable_analyzer(bool enable) { m_enable_analyzer = enable; }
|
||||||
|
|
||||||
// For Perl bindings, to be used exclusively by unit tests.
|
// For Perl bindings, to be used exclusively by unit tests.
|
||||||
unsigned int layer_count() const { return m_layer_count; }
|
unsigned int layer_count() const { return m_layer_count; }
|
||||||
@ -241,9 +247,10 @@ protected:
|
|||||||
// Markers for the Pressure Equalizer to recognize the extrusion type.
|
// Markers for the Pressure Equalizer to recognize the extrusion type.
|
||||||
// The Pressure Equalizer removes the markers from the final G-code.
|
// The Pressure Equalizer removes the markers from the final G-code.
|
||||||
bool m_enable_extrusion_role_markers;
|
bool m_enable_extrusion_role_markers;
|
||||||
// Extended markers for the G-code Analyzer.
|
// Enableds the G-code Analyzer.
|
||||||
|
// Extended markers will be added during G-code generation.
|
||||||
// The G-code Analyzer will remove these comments from the final G-code.
|
// The G-code Analyzer will remove these comments from the final G-code.
|
||||||
bool m_enable_analyzer_markers;
|
bool m_enable_analyzer;
|
||||||
// How many times will change_layer() be called?
|
// How many times will change_layer() be called?
|
||||||
// change_layer() will update the progress bar.
|
// change_layer() will update the progress bar.
|
||||||
unsigned int m_layer_count;
|
unsigned int m_layer_count;
|
||||||
@ -256,6 +263,10 @@ protected:
|
|||||||
double m_volumetric_speed;
|
double m_volumetric_speed;
|
||||||
// Support for the extrusion role markers. Which marker is active?
|
// Support for the extrusion role markers. Which marker is active?
|
||||||
ExtrusionRole m_last_extrusion_role;
|
ExtrusionRole m_last_extrusion_role;
|
||||||
|
// Support for G-Code Analyzer
|
||||||
|
double m_last_mm3_per_mm;
|
||||||
|
float m_last_width;
|
||||||
|
float m_last_height;
|
||||||
|
|
||||||
Point m_last_pos;
|
Point m_last_pos;
|
||||||
bool m_last_pos_defined;
|
bool m_last_pos_defined;
|
||||||
@ -277,9 +288,12 @@ protected:
|
|||||||
// Time estimator
|
// Time estimator
|
||||||
GCodeTimeEstimator m_time_estimator;
|
GCodeTimeEstimator m_time_estimator;
|
||||||
|
|
||||||
|
// Analyzer
|
||||||
|
GCodeAnalyzer m_analyzer;
|
||||||
|
|
||||||
// Write a string into a file.
|
// Write a string into a file.
|
||||||
void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str(), what.size()); }
|
void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str()); }
|
||||||
void _write(FILE* file, const char *what, size_t size);
|
void _write(FILE* file, const char *what);
|
||||||
|
|
||||||
// Write a string into a file.
|
// Write a string into a file.
|
||||||
// Add a newline, if the string does not end with a newline already.
|
// Add a newline, if the string does not end with a newline already.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,152 +1,417 @@
|
|||||||
#ifndef slic3r_GCode_PressureEqualizer_hpp_
|
#ifndef slic3r_GCode_Analyzer_hpp_
|
||||||
#define slic3r_GCode_PressureEqualizer_hpp_
|
#define slic3r_GCode_Analyzer_hpp_
|
||||||
|
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
#include "../PrintConfig.hpp"
|
#include "../PrintConfig.hpp"
|
||||||
#include "../ExtrusionEntity.hpp"
|
#include "../ExtrusionEntity.hpp"
|
||||||
|
|
||||||
|
#include "Point.hpp"
|
||||||
|
#include "GCodeReader.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
enum GCodeMoveType
|
class Print;
|
||||||
{
|
|
||||||
GCODE_MOVE_TYPE_NOOP,
|
|
||||||
GCODE_MOVE_TYPE_RETRACT,
|
|
||||||
GCODE_MOVE_TYPE_UNRETRACT,
|
|
||||||
GCODE_MOVE_TYPE_TOOL_CHANGE,
|
|
||||||
GCODE_MOVE_TYPE_MOVE,
|
|
||||||
GCODE_MOVE_TYPE_EXTRUDE,
|
|
||||||
};
|
|
||||||
|
|
||||||
// For visualization purposes, for the purposes of the G-code analysis and timing.
|
|
||||||
// The size of this structure is 56B.
|
|
||||||
// Keep the size of this structure as small as possible, because all moves of a complete print
|
|
||||||
// may be held in RAM.
|
|
||||||
struct GCodeMove
|
|
||||||
{
|
|
||||||
bool moving_xy(const float* pos_start) const { return fabs(pos_end[0] - pos_start[0]) > 0.f || fabs(pos_end[1] - pos_start[1]) > 0.f; }
|
|
||||||
bool moving_xy() const { return moving_xy(get_pos_start()); }
|
|
||||||
bool moving_z (const float* pos_start) const { return fabs(pos_end[2] - pos_start[2]) > 0.f; }
|
|
||||||
bool moving_z () const { return moving_z(get_pos_start()); }
|
|
||||||
bool extruding(const float* pos_start) const { return moving_xy() && pos_end[3] > pos_start[3]; }
|
|
||||||
bool extruding() const { return extruding(get_pos_start()); }
|
|
||||||
bool retracting(const float* pos_start) const { return pos_end[3] < pos_start[3]; }
|
|
||||||
bool retracting() const { return retracting(get_pos_start()); }
|
|
||||||
bool deretracting(const float* pos_start) const { return ! moving_xy() && pos_end[3] > pos_start[3]; }
|
|
||||||
bool deretracting() const { return deretracting(get_pos_start()); }
|
|
||||||
|
|
||||||
float dist_xy2(const float* pos_start) const { return (pos_end[0] - pos_start[0]) * (pos_end[0] - pos_start[0]) + (pos_end[1] - pos_start[1]) * (pos_end[1] - pos_start[1]); }
|
|
||||||
float dist_xy2() const { return dist_xy2(get_pos_start()); }
|
|
||||||
float dist_xyz2(const float* pos_start) const { return (pos_end[0] - pos_start[0]) * (pos_end[0] - pos_start[0]) + (pos_end[1] - pos_start[1]) * (pos_end[1] - pos_start[1]) + (pos_end[2] - pos_start[2]) * (pos_end[2] - pos_start[2]); }
|
|
||||||
float dist_xyz2() const { return dist_xyz2(get_pos_start()); }
|
|
||||||
|
|
||||||
float dist_xy(const float* pos_start) const { return sqrt(dist_xy2(pos_start)); }
|
|
||||||
float dist_xy() const { return dist_xy(get_pos_start()); }
|
|
||||||
float dist_xyz(const float* pos_start) const { return sqrt(dist_xyz2(pos_start)); }
|
|
||||||
float dist_xyz() const { return dist_xyz(get_pos_start()); }
|
|
||||||
|
|
||||||
float dist_e(const float* pos_start) const { return fabs(pos_end[3] - pos_start[3]); }
|
|
||||||
float dist_e() const { return dist_e(get_pos_start()); }
|
|
||||||
|
|
||||||
float feedrate() const { return pos_end[4]; }
|
|
||||||
float time(const float* pos_start) const { return dist_xyz(pos_start) / feedrate(); }
|
|
||||||
float time() const { return time(get_pos_start()); }
|
|
||||||
float time_inv(const float* pos_start) const { return feedrate() / dist_xyz(pos_start); }
|
|
||||||
float time_inv() const { return time_inv(get_pos_start()); }
|
|
||||||
|
|
||||||
const float* get_pos_start() const { assert(type != GCODE_MOVE_TYPE_NOOP); return this[-1].pos_end; }
|
|
||||||
|
|
||||||
// Pack the enums to conserve space. With C++x11 the allocation size could be declared for enums, but for old C++ this is the only portable way.
|
|
||||||
// GCodeLineType
|
|
||||||
uint8_t type;
|
|
||||||
// Index of the active extruder.
|
|
||||||
uint8_t extruder_id;
|
|
||||||
// ExtrusionRole
|
|
||||||
uint8_t extrusion_role;
|
|
||||||
// For example, is it a bridge flow? Is the fan on?
|
|
||||||
uint8_t flags;
|
|
||||||
// X,Y,Z,E,F. Storing the state of the currently active extruder only.
|
|
||||||
float pos_end[5];
|
|
||||||
// Extrusion width, height for this segment in um.
|
|
||||||
uint16_t extrusion_width;
|
|
||||||
uint16_t extrusion_height;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<GCodeMove> GCodeMoves;
|
|
||||||
|
|
||||||
struct GCodeLayer
|
|
||||||
{
|
|
||||||
// Index of an object printed.
|
|
||||||
size_t object_idx;
|
|
||||||
// Index of an object instance printed.
|
|
||||||
size_t object_instance_idx;
|
|
||||||
// Index of the layer printed.
|
|
||||||
size_t layer_idx;
|
|
||||||
// Top z coordinate of the layer printed.
|
|
||||||
float layer_z_top;
|
|
||||||
|
|
||||||
// Moves over this layer. The 0th move is always of type GCODELINETYPE_NOOP and
|
|
||||||
// it sets the initial position and tool for the layer.
|
|
||||||
GCodeMoves moves;
|
|
||||||
|
|
||||||
// Indices into m_moves, where the tool changes happen.
|
|
||||||
// This is useful, if one wants to display just only a piece of the path quickly.
|
|
||||||
std::vector<size_t> tool_changes;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<GCodeLayer*> GCodeLayerPtrs;
|
|
||||||
|
|
||||||
class GCodeMovesDB
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GCodeMovesDB() {};
|
|
||||||
~GCodeMovesDB() { reset(); }
|
|
||||||
void reset();
|
|
||||||
GCodeLayerPtrs m_layers;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Processes a G-code to extract moves and their types.
|
|
||||||
// This information is then used to render the print simulation colored by the extrusion type
|
|
||||||
// or various speeds.
|
|
||||||
// The GCodeAnalyzer is employed as a G-Code filter. It reads the G-code as it is generated,
|
|
||||||
// parses the comments generated by Slic3r just for the analyzer, and removes these comments.
|
|
||||||
class GCodeAnalyzer
|
class GCodeAnalyzer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GCodeAnalyzer(const Slic3r::GCodeConfig *config);
|
static const std::string Extrusion_Role_Tag;
|
||||||
~GCodeAnalyzer();
|
static const std::string Mm3_Per_Mm_Tag;
|
||||||
|
static const std::string Width_Tag;
|
||||||
|
static const std::string Height_Tag;
|
||||||
|
|
||||||
void reset();
|
static const double Default_mm3_per_mm;
|
||||||
|
static const float Default_Width;
|
||||||
|
static const float Default_Height;
|
||||||
|
|
||||||
// Process a next batch of G-code lines. Flush the internal buffers if asked for.
|
enum EUnits : unsigned char
|
||||||
const char* process(const char *szGCode, bool flush);
|
{
|
||||||
// Length of the buffer returned by process().
|
Millimeters,
|
||||||
size_t get_output_buffer_length() const { return output_buffer_length; }
|
Inches
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EAxis : unsigned char
|
||||||
|
{
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
E,
|
||||||
|
Num_Axis
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EPositioningType : unsigned char
|
||||||
|
{
|
||||||
|
Absolute,
|
||||||
|
Relative
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Metadata
|
||||||
|
{
|
||||||
|
ExtrusionRole extrusion_role;
|
||||||
|
unsigned int extruder_id;
|
||||||
|
double mm3_per_mm;
|
||||||
|
float width; // mm
|
||||||
|
float height; // mm
|
||||||
|
float feedrate; // mm/s
|
||||||
|
|
||||||
|
Metadata();
|
||||||
|
Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate);
|
||||||
|
|
||||||
|
bool operator != (const Metadata& other) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCodeMove
|
||||||
|
{
|
||||||
|
enum EType : unsigned char
|
||||||
|
{
|
||||||
|
Noop,
|
||||||
|
Retract,
|
||||||
|
Unretract,
|
||||||
|
Tool_change,
|
||||||
|
Move,
|
||||||
|
Extrude,
|
||||||
|
Num_Types
|
||||||
|
};
|
||||||
|
|
||||||
|
EType type;
|
||||||
|
Metadata data;
|
||||||
|
Pointf3 start_position;
|
||||||
|
Pointf3 end_position;
|
||||||
|
float delta_extruder;
|
||||||
|
|
||||||
|
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder);
|
||||||
|
GCodeMove(EType type, const Metadata& data, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<GCodeMove> GCodeMovesList;
|
||||||
|
typedef std::map<GCodeMove::EType, GCodeMovesList> TypeToMovesMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Keeps the reference, does not own the config.
|
struct State
|
||||||
const Slic3r::GCodeConfig *m_config;
|
{
|
||||||
|
EUnits units;
|
||||||
|
EPositioningType positioning_xyz_type;
|
||||||
|
EPositioningType positioning_e_type;
|
||||||
|
Metadata data;
|
||||||
|
Pointf3 start_position;
|
||||||
|
float start_extrusion;
|
||||||
|
float position[Num_Axis];
|
||||||
|
};
|
||||||
|
|
||||||
// Internal data.
|
public:
|
||||||
// X,Y,Z,E,F
|
struct PreviewData
|
||||||
float m_current_pos[5];
|
{
|
||||||
size_t m_current_extruder;
|
struct Color
|
||||||
ExtrusionRole m_current_extrusion_role;
|
{
|
||||||
uint16_t m_current_extrusion_width;
|
float rgba[4];
|
||||||
uint16_t m_current_extrusion_height;
|
|
||||||
bool m_retracted;
|
|
||||||
|
|
||||||
GCodeMovesDB *m_moves;
|
Color();
|
||||||
|
Color(float r, float g, float b, float a);
|
||||||
|
|
||||||
// Output buffer will only grow. It will not be reallocated over and over.
|
std::vector<unsigned char> as_bytes() const;
|
||||||
std::vector<char> output_buffer;
|
|
||||||
size_t output_buffer_length;
|
|
||||||
|
|
||||||
bool process_line(const char *line, const size_t len);
|
static const Color Dummy;
|
||||||
|
};
|
||||||
|
|
||||||
// Push the text to the end of the output_buffer.
|
struct Range
|
||||||
void push_to_output(const char *text, const size_t len, bool add_eol = true);
|
{
|
||||||
|
static const unsigned int Colors_Count = 10;
|
||||||
|
static const Color Default_Colors[Colors_Count];
|
||||||
|
|
||||||
|
Color colors[Colors_Count];
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
|
||||||
|
Range();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
bool empty() const;
|
||||||
|
void update_from(float value);
|
||||||
|
void set_from(const Range& other);
|
||||||
|
float step_size() const;
|
||||||
|
|
||||||
|
const Color& get_color_at(float value) const;
|
||||||
|
const Color& get_color_at_max() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LegendItem
|
||||||
|
{
|
||||||
|
std::string text;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
LegendItem(const std::string& text, const Color& color);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<LegendItem> LegendItemsList;
|
||||||
|
|
||||||
|
struct Extrusion
|
||||||
|
{
|
||||||
|
enum EViewType : unsigned char
|
||||||
|
{
|
||||||
|
FeatureType,
|
||||||
|
Height,
|
||||||
|
Width,
|
||||||
|
Feedrate,
|
||||||
|
Tool,
|
||||||
|
Num_View_Types
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1;
|
||||||
|
static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles];
|
||||||
|
static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles];
|
||||||
|
static const EViewType Default_View_Type;
|
||||||
|
|
||||||
|
struct Ranges
|
||||||
|
{
|
||||||
|
Range height;
|
||||||
|
Range width;
|
||||||
|
Range feedrate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Layer
|
||||||
|
{
|
||||||
|
float z;
|
||||||
|
ExtrusionPaths paths;
|
||||||
|
|
||||||
|
Layer(float z, const ExtrusionPaths& paths);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Layer> LayersList;
|
||||||
|
|
||||||
|
EViewType view_type;
|
||||||
|
Color role_colors[Num_Extrusion_Roles];
|
||||||
|
std::string role_names[Num_Extrusion_Roles];
|
||||||
|
Ranges ranges;
|
||||||
|
LayersList layers;
|
||||||
|
unsigned int role_flags;
|
||||||
|
|
||||||
|
void set_default();
|
||||||
|
bool is_role_flag_set(ExtrusionRole role) const;
|
||||||
|
|
||||||
|
static bool is_role_flag_set(unsigned int flags, ExtrusionRole role);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Travel
|
||||||
|
{
|
||||||
|
enum EType : unsigned char
|
||||||
|
{
|
||||||
|
Move,
|
||||||
|
Extrude,
|
||||||
|
Retract,
|
||||||
|
Num_Types
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float Default_Width;
|
||||||
|
static const float Default_Height;
|
||||||
|
static const Color Default_Type_Colors[Num_Types];
|
||||||
|
|
||||||
|
struct Polyline
|
||||||
|
{
|
||||||
|
enum EDirection
|
||||||
|
{
|
||||||
|
Vertical,
|
||||||
|
Generic,
|
||||||
|
Num_Directions
|
||||||
|
};
|
||||||
|
|
||||||
|
EType type;
|
||||||
|
EDirection direction;
|
||||||
|
float feedrate;
|
||||||
|
unsigned int extruder_id;
|
||||||
|
Polyline3 polyline;
|
||||||
|
|
||||||
|
Polyline(EType type, EDirection direction, float feedrate, unsigned int extruder_id, const Polyline3& polyline);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Polyline> PolylinesList;
|
||||||
|
|
||||||
|
PolylinesList polylines;
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
Color type_colors[Num_Types];
|
||||||
|
bool is_visible;
|
||||||
|
|
||||||
|
void set_default();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Retraction
|
||||||
|
{
|
||||||
|
static const Color Default_Color;
|
||||||
|
|
||||||
|
struct Position
|
||||||
|
{
|
||||||
|
Point3 position;
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
|
||||||
|
Position(const Point3& position, float width, float height);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Position> PositionsList;
|
||||||
|
|
||||||
|
PositionsList positions;
|
||||||
|
Color color;
|
||||||
|
bool is_visible;
|
||||||
|
|
||||||
|
void set_default();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Shell
|
||||||
|
{
|
||||||
|
bool is_visible;
|
||||||
|
|
||||||
|
void set_default();
|
||||||
|
};
|
||||||
|
|
||||||
|
Extrusion extrusion;
|
||||||
|
Travel travel;
|
||||||
|
Retraction retraction;
|
||||||
|
Retraction unretraction;
|
||||||
|
Shell shell;
|
||||||
|
|
||||||
|
PreviewData();
|
||||||
|
|
||||||
|
void set_default();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
const Color& get_extrusion_role_color(ExtrusionRole role) const;
|
||||||
|
const Color& get_extrusion_height_color(float height) const;
|
||||||
|
const Color& get_extrusion_width_color(float width) const;
|
||||||
|
const Color& get_extrusion_feedrate_color(float feedrate) const;
|
||||||
|
|
||||||
|
void set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha);
|
||||||
|
|
||||||
|
std::string get_legend_title() const;
|
||||||
|
LegendItemsList get_legend_items(const std::vector<float>& tool_colors) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
State m_state;
|
||||||
|
GCodeReader m_parser;
|
||||||
|
TypeToMovesMap m_moves_map;
|
||||||
|
|
||||||
|
// The output of process_layer()
|
||||||
|
std::string m_process_output;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GCodeAnalyzer();
|
||||||
|
|
||||||
|
// Reinitialize the analyzer
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
// Adds the gcode contained in the given string to the analysis and returns it after removing the workcodes
|
||||||
|
const std::string& process_gcode(const std::string& gcode);
|
||||||
|
|
||||||
|
// Calculates all data needed for gcode visualization
|
||||||
|
void calc_gcode_preview_data(Print& print);
|
||||||
|
|
||||||
|
static bool is_valid_extrusion_role(ExtrusionRole role);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Processes the given gcode line
|
||||||
|
void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Move
|
||||||
|
void _processG1(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Firmware controlled Retract
|
||||||
|
void _processG22(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Firmware controlled Unretract
|
||||||
|
void _processG23(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Set to Absolute Positioning
|
||||||
|
void _processG90(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Set to Relative Positioning
|
||||||
|
void _processG91(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Set Position
|
||||||
|
void _processG92(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Set extruder to absolute mode
|
||||||
|
void _processM82(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Set extruder to relative mode
|
||||||
|
void _processM83(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Processes T line (Select Tool)
|
||||||
|
void _processT(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Processes the tags
|
||||||
|
// Returns true if any tag has been processed
|
||||||
|
bool _process_tags(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
// Processes extrusion role tag
|
||||||
|
void _process_extrusion_role_tag(const std::string& comment, size_t pos);
|
||||||
|
|
||||||
|
// Processes mm3_per_mm tag
|
||||||
|
void _process_mm3_per_mm_tag(const std::string& comment, size_t pos);
|
||||||
|
|
||||||
|
// Processes width tag
|
||||||
|
void _process_width_tag(const std::string& comment, size_t pos);
|
||||||
|
|
||||||
|
// Processes height tag
|
||||||
|
void _process_height_tag(const std::string& comment, size_t pos);
|
||||||
|
|
||||||
|
void _set_units(EUnits units);
|
||||||
|
EUnits _get_units() const;
|
||||||
|
|
||||||
|
void _set_positioning_xyz_type(EPositioningType type);
|
||||||
|
EPositioningType _get_positioning_xyz_type() const;
|
||||||
|
|
||||||
|
void _set_positioning_e_type(EPositioningType type);
|
||||||
|
EPositioningType _get_positioning_e_type() const;
|
||||||
|
|
||||||
|
void _set_extrusion_role(ExtrusionRole extrusion_role);
|
||||||
|
ExtrusionRole _get_extrusion_role() const;
|
||||||
|
|
||||||
|
void _set_extruder_id(unsigned int id);
|
||||||
|
unsigned int _get_extruder_id() const;
|
||||||
|
|
||||||
|
void _set_mm3_per_mm(double value);
|
||||||
|
double _get_mm3_per_mm() const;
|
||||||
|
|
||||||
|
void _set_width(float width);
|
||||||
|
float _get_width() const;
|
||||||
|
|
||||||
|
void _set_height(float height);
|
||||||
|
float _get_height() const;
|
||||||
|
|
||||||
|
void _set_feedrate(float feedrate_mm_sec);
|
||||||
|
float _get_feedrate() const;
|
||||||
|
|
||||||
|
void _set_axis_position(EAxis axis, float position);
|
||||||
|
float _get_axis_position(EAxis axis) const;
|
||||||
|
|
||||||
|
// Sets axes position to zero
|
||||||
|
void _reset_axes_position();
|
||||||
|
|
||||||
|
void _set_start_position(const Pointf3& position);
|
||||||
|
const Pointf3& _get_start_position() const;
|
||||||
|
|
||||||
|
void _set_start_extrusion(float extrusion);
|
||||||
|
float _get_start_extrusion() const;
|
||||||
|
float _get_delta_extrusion() const;
|
||||||
|
|
||||||
|
// Returns current xyz position (from m_state.position[])
|
||||||
|
Pointf3 _get_end_position() const;
|
||||||
|
|
||||||
|
// Adds a new move with the given data
|
||||||
|
void _store_move(GCodeMove::EType type);
|
||||||
|
|
||||||
|
// Checks if the given int is a valid extrusion role (contained into enum ExtrusionRole)
|
||||||
|
bool _is_valid_extrusion_role(int value) const;
|
||||||
|
|
||||||
|
void _calc_gcode_preview_extrusion_layers(Print& print);
|
||||||
|
void _calc_gcode_preview_travel(Print& print);
|
||||||
|
void _calc_gcode_preview_retractions(Print& print);
|
||||||
|
void _calc_gcode_preview_unretractions(Print& print);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GCodeAnalyzer::PreviewData::Color operator + (const GCodeAnalyzer::PreviewData::Color& c1, const GCodeAnalyzer::PreviewData::Color& c2);
|
||||||
|
GCodeAnalyzer::PreviewData::Color operator * (float f, const GCodeAnalyzer::PreviewData::Color& color);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif /* slic3r_GCode_PressureEqualizer_hpp_ */
|
#endif /* slic3r_GCode_Analyzer_hpp_ */
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Analyzer.hpp"
|
||||||
|
|
||||||
#if defined(__linux) || defined(__GNUC__ )
|
#if defined(__linux) || defined(__GNUC__ )
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#endif /* __linux */
|
#endif /* __linux */
|
||||||
@ -419,6 +421,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
|
|||||||
// Increase the extruder driver current to allow fast ramming.
|
// Increase the extruder driver current to allow fast ramming.
|
||||||
.set_extruder_trimpot(750);
|
.set_extruder_trimpot(750);
|
||||||
|
|
||||||
|
// adds tag for analyzer
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
|
||||||
|
writer.append(buf);
|
||||||
|
|
||||||
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
|
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
|
||||||
float y_end = 0.f;
|
float y_end = 0.f;
|
||||||
for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
|
for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
|
||||||
@ -554,6 +561,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
|
|||||||
writer.set_initial_position(initial_position);
|
writer.set_initial_position(initial_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adds tag for analyzer
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
|
||||||
|
writer.append(buf);
|
||||||
|
|
||||||
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
|
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
|
||||||
// Increase the extruder driver current to allow fast ramming.
|
// Increase the extruder driver current to allow fast ramming.
|
||||||
writer.set_extruder_trimpot(750);
|
writer.set_extruder_trimpot(750);
|
||||||
@ -637,6 +649,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b
|
|||||||
else
|
else
|
||||||
writer.set_initial_position(initial_position);
|
writer.set_initial_position(initial_position);
|
||||||
|
|
||||||
|
// adds tag for analyzer
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
|
||||||
|
writer.append(buf);
|
||||||
|
|
||||||
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
|
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
|
||||||
// Prime the extruder 10*m_perimeter_width left along the vertical edge of the wipe tower.
|
// Prime the extruder 10*m_perimeter_width left along the vertical edge of the wipe tower.
|
||||||
writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0),
|
writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0),
|
||||||
|
@ -218,6 +218,16 @@ Line::ccw(const Point& point) const
|
|||||||
return point.ccw(*this);
|
return point.ccw(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Line3::length() const
|
||||||
|
{
|
||||||
|
return a.distance_to(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Line3::vector() const
|
||||||
|
{
|
||||||
|
return Vector3(b.x - a.x, b.y - a.y, b.z - a.z);
|
||||||
|
}
|
||||||
|
|
||||||
Pointf3
|
Pointf3
|
||||||
Linef3::intersect_plane(double z) const
|
Linef3::intersect_plane(double z) const
|
||||||
{
|
{
|
||||||
|
@ -7,10 +7,12 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class Line;
|
class Line;
|
||||||
|
class Line3;
|
||||||
class Linef3;
|
class Linef3;
|
||||||
class Polyline;
|
class Polyline;
|
||||||
class ThickLine;
|
class ThickLine;
|
||||||
typedef std::vector<Line> Lines;
|
typedef std::vector<Line> Lines;
|
||||||
|
typedef std::vector<Line3> Lines3;
|
||||||
typedef std::vector<ThickLine> ThickLines;
|
typedef std::vector<ThickLine> ThickLines;
|
||||||
|
|
||||||
class Line
|
class Line
|
||||||
@ -56,6 +58,19 @@ class ThickLine : public Line
|
|||||||
ThickLine(Point _a, Point _b) : Line(_a, _b), a_width(0), b_width(0) {};
|
ThickLine(Point _a, Point _b) : Line(_a, _b), a_width(0), b_width(0) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Line3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Point3 a;
|
||||||
|
Point3 b;
|
||||||
|
|
||||||
|
Line3() {}
|
||||||
|
Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {}
|
||||||
|
|
||||||
|
double length() const;
|
||||||
|
Vector3 vector() const;
|
||||||
|
};
|
||||||
|
|
||||||
class Linef
|
class Linef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -214,6 +214,61 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiPoint3::translate(double x, double y)
|
||||||
|
{
|
||||||
|
for (Point3& p : points)
|
||||||
|
{
|
||||||
|
p.translate(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiPoint3::translate(const Point& vector)
|
||||||
|
{
|
||||||
|
translate(vector.x, vector.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double MultiPoint3::length() const
|
||||||
|
{
|
||||||
|
Lines3 lines = this->lines();
|
||||||
|
double len = 0.0;
|
||||||
|
for (const Line3& line : lines)
|
||||||
|
{
|
||||||
|
len += line.length();
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBox3 MultiPoint3::bounding_box() const
|
||||||
|
{
|
||||||
|
return BoundingBox3(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MultiPoint3::remove_duplicate_points()
|
||||||
|
{
|
||||||
|
size_t j = 0;
|
||||||
|
for (size_t i = 1; i < points.size(); ++i)
|
||||||
|
{
|
||||||
|
if (points[j].coincides_with(points[i]))
|
||||||
|
{
|
||||||
|
// Just increase index i.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++j;
|
||||||
|
if (j < i)
|
||||||
|
points[j] = points[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++j < points.size())
|
||||||
|
{
|
||||||
|
points.erase(points.begin() + j, points.end());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox get_extents(const MultiPoint &mp)
|
BoundingBox get_extents(const MultiPoint &mp)
|
||||||
{
|
{
|
||||||
return BoundingBox(mp.points);
|
return BoundingBox(mp.points);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class BoundingBox;
|
class BoundingBox;
|
||||||
|
class BoundingBox3;
|
||||||
|
|
||||||
class MultiPoint
|
class MultiPoint
|
||||||
{
|
{
|
||||||
@ -79,6 +80,25 @@ public:
|
|||||||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MultiPoint3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Points3 points;
|
||||||
|
|
||||||
|
void append(const Point3& point) { this->points.push_back(point); }
|
||||||
|
|
||||||
|
void translate(double x, double y);
|
||||||
|
void translate(const Point& vector);
|
||||||
|
virtual Lines3 lines() const = 0;
|
||||||
|
double length() const;
|
||||||
|
bool is_valid() const { return this->points.size() >= 2; }
|
||||||
|
|
||||||
|
BoundingBox3 bounding_box() const;
|
||||||
|
|
||||||
|
// Remove exact duplicates, return true if any duplicate has been removed.
|
||||||
|
bool remove_duplicate_points();
|
||||||
|
};
|
||||||
|
|
||||||
extern BoundingBox get_extents(const MultiPoint &mp);
|
extern BoundingBox get_extents(const MultiPoint &mp);
|
||||||
extern BoundingBox get_extents_rotated(const std::vector<Point> &points, double angle);
|
extern BoundingBox get_extents_rotated(const std::vector<Point> &points, double angle);
|
||||||
extern BoundingBox get_extents_rotated(const MultiPoint &mp, double angle);
|
extern BoundingBox get_extents_rotated(const MultiPoint &mp, double angle);
|
||||||
|
@ -14,14 +14,17 @@ class Line;
|
|||||||
class Linef;
|
class Linef;
|
||||||
class MultiPoint;
|
class MultiPoint;
|
||||||
class Point;
|
class Point;
|
||||||
|
class Point3;
|
||||||
class Pointf;
|
class Pointf;
|
||||||
class Pointf3;
|
class Pointf3;
|
||||||
typedef Point Vector;
|
typedef Point Vector;
|
||||||
|
typedef Point3 Vector3;
|
||||||
typedef Pointf Vectorf;
|
typedef Pointf Vectorf;
|
||||||
typedef Pointf3 Vectorf3;
|
typedef Pointf3 Vectorf3;
|
||||||
typedef std::vector<Point> Points;
|
typedef std::vector<Point> Points;
|
||||||
typedef std::vector<Point*> PointPtrs;
|
typedef std::vector<Point*> PointPtrs;
|
||||||
typedef std::vector<const Point*> PointConstPtrs;
|
typedef std::vector<const Point*> PointConstPtrs;
|
||||||
|
typedef std::vector<Point3> Points3;
|
||||||
typedef std::vector<Pointf> Pointfs;
|
typedef std::vector<Pointf> Pointfs;
|
||||||
typedef std::vector<Pointf3> Pointf3s;
|
typedef std::vector<Pointf3> Pointf3s;
|
||||||
|
|
||||||
@ -185,10 +188,11 @@ public:
|
|||||||
static Point3 new_scale(coordf_t x, coordf_t y, coordf_t z) { return Point3(coord_t(scale_(x)), coord_t(scale_(y)), coord_t(scale_(z))); }
|
static Point3 new_scale(coordf_t x, coordf_t y, coordf_t z) { return Point3(coord_t(scale_(x)), coord_t(scale_(y)), coord_t(scale_(z))); }
|
||||||
bool operator==(const Point3 &rhs) const { return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z; }
|
bool operator==(const Point3 &rhs) const { return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z; }
|
||||||
bool operator!=(const Point3 &rhs) const { return ! (*this == rhs); }
|
bool operator!=(const Point3 &rhs) const { return ! (*this == rhs); }
|
||||||
|
bool coincides_with(const Point3& rhs) const { return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z; }
|
||||||
private:
|
private:
|
||||||
// Hide the following inherited methods:
|
// Hide the following inherited methods:
|
||||||
bool operator==(const Point &rhs);
|
bool operator==(const Point &rhs) const;
|
||||||
bool operator!=(const Point &rhs);
|
bool operator!=(const Point &rhs) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &stm, const Pointf &pointf);
|
std::ostream& operator<<(std::ostream &stm, const Pointf &pointf);
|
||||||
@ -243,6 +247,7 @@ public:
|
|||||||
static Pointf3 new_unscale(coord_t x, coord_t y, coord_t z) {
|
static Pointf3 new_unscale(coord_t x, coord_t y, coord_t z) {
|
||||||
return Pointf3(unscale(x), unscale(y), unscale(z));
|
return Pointf3(unscale(x), unscale(y), unscale(z));
|
||||||
};
|
};
|
||||||
|
static Pointf3 new_unscale(const Point3& p) { return Pointf3(unscale(p.x), unscale(p.y), unscale(p.z)); }
|
||||||
void scale(double factor);
|
void scale(double factor);
|
||||||
void translate(const Vectorf3 &vector);
|
void translate(const Vectorf3 &vector);
|
||||||
void translate(double x, double y, double z);
|
void translate(double x, double y, double z);
|
||||||
@ -255,10 +260,23 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Hide the following inherited methods:
|
// Hide the following inherited methods:
|
||||||
bool operator==(const Pointf &rhs);
|
bool operator==(const Pointf &rhs) const;
|
||||||
bool operator!=(const Pointf &rhs);
|
bool operator!=(const Pointf &rhs) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Pointf3 operator+(const Pointf3& p1, const Pointf3& p2) { return Pointf3(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z); }
|
||||||
|
inline Pointf3 operator-(const Pointf3& p1, const Pointf3& p2) { return Pointf3(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z); }
|
||||||
|
inline Pointf3 operator-(const Pointf3& p) { return Pointf3(-p.x, -p.y, -p.z); }
|
||||||
|
inline Pointf3 operator*(double scalar, const Pointf3& p) { return Pointf3(scalar * p.x, scalar * p.y, scalar * p.z); }
|
||||||
|
inline Pointf3 operator*(const Pointf3& p, double scalar) { return Pointf3(scalar * p.x, scalar * p.y, scalar * p.z); }
|
||||||
|
inline Pointf3 cross(const Pointf3& v1, const Pointf3& v2) { return Pointf3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); }
|
||||||
|
inline coordf_t dot(const Pointf3& v1, const Pointf3& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; }
|
||||||
|
inline Pointf3 normalize(const Pointf3& v)
|
||||||
|
{
|
||||||
|
coordf_t len = ::sqrt(sqr(v.x) + sqr(v.y) + sqr(v.z));
|
||||||
|
return (len != 0.0) ? 1.0 / len * v : Pointf3(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename TO> inline TO convert_to(const Point &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y)); }
|
template<typename TO> inline TO convert_to(const Point &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y)); }
|
||||||
template<typename TO> inline TO convert_to(const Pointf &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y)); }
|
template<typename TO> inline TO convert_to(const Pointf &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y)); }
|
||||||
template<typename TO> inline TO convert_to(const Point3 &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y), typename TO::coord_type(src.z)); }
|
template<typename TO> inline TO convert_to(const Point3 &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y), typename TO::coord_type(src.z)); }
|
||||||
|
@ -278,4 +278,18 @@ ThickPolyline::reverse()
|
|||||||
std::swap(this->endpoints.first, this->endpoints.second);
|
std::swap(this->endpoints.first, this->endpoints.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lines3 Polyline3::lines() const
|
||||||
|
{
|
||||||
|
Lines3 lines;
|
||||||
|
if (points.size() >= 2)
|
||||||
|
{
|
||||||
|
lines.reserve(points.size() - 1);
|
||||||
|
for (Points3::const_iterator it = points.begin(); it != points.end() - 1; ++it)
|
||||||
|
{
|
||||||
|
lines.emplace_back(*it, *(it + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,14 @@ class ThickPolyline : public Polyline {
|
|||||||
void reverse();
|
void reverse();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Polyline3 : public MultiPoint3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual Lines3 lines() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Polyline3> Polylines3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,6 +66,89 @@ bool Print::reload_model_instances()
|
|||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Print::clear_gcode_preview_data()
|
||||||
|
{
|
||||||
|
gcode_preview.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_preview_type(unsigned char type)
|
||||||
|
{
|
||||||
|
if ((0 <= type) && (type < GCodeAnalyzer::PreviewData::Extrusion::Num_View_Types))
|
||||||
|
gcode_preview.extrusion.view_type = (GCodeAnalyzer::PreviewData::Extrusion::EViewType)type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_preview_extrusion_flags(unsigned int flags)
|
||||||
|
{
|
||||||
|
gcode_preview.extrusion.role_flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Print::is_gcode_preview_extrusion_role_enabled(ExtrusionRole role)
|
||||||
|
{
|
||||||
|
return gcode_preview.extrusion.is_role_flag_set(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_preview_travel_visible(bool visible)
|
||||||
|
{
|
||||||
|
gcode_preview.travel.is_visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_preview_retractions_visible(bool visible)
|
||||||
|
{
|
||||||
|
gcode_preview.retraction.is_visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_preview_unretractions_visible(bool visible)
|
||||||
|
{
|
||||||
|
gcode_preview.unretraction.is_visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_preview_shells_visible(bool visible)
|
||||||
|
{
|
||||||
|
gcode_preview.shell.is_visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::set_gcode_extrusion_paths_colors(const std::vector<std::string>& colors)
|
||||||
|
{
|
||||||
|
unsigned int size = (unsigned int)colors.size();
|
||||||
|
|
||||||
|
if (size % 2 != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < size; i += 2)
|
||||||
|
{
|
||||||
|
const std::string& color_str = colors[i + 1];
|
||||||
|
|
||||||
|
if (color_str.size() == 6)
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
for (int c = 0; c < 6; ++c)
|
||||||
|
{
|
||||||
|
if (::isxdigit(color_str[c]) == 0)
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
unsigned int color;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::hex << color_str;
|
||||||
|
ss >> color;
|
||||||
|
|
||||||
|
float den = 1.0f / 255.0f;
|
||||||
|
|
||||||
|
float r = (float)((color & 0xFF0000) >> 16) * den;
|
||||||
|
float g = (float)((color & 0x00FF00) >> 8) * den;
|
||||||
|
float b = (float)(color & 0x0000FF) * den;
|
||||||
|
|
||||||
|
gcode_preview.set_extrusion_role_color(colors[i], r, g, b, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PrintRegion* Print::add_region()
|
PrintRegion* Print::add_region()
|
||||||
{
|
{
|
||||||
regions.push_back(new PrintRegion(this));
|
regions.push_back(new PrintRegion(this));
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Slicing.hpp"
|
#include "Slicing.hpp"
|
||||||
#include "GCode/ToolOrdering.hpp"
|
#include "GCode/ToolOrdering.hpp"
|
||||||
#include "GCode/WipeTower.hpp"
|
#include "GCode/WipeTower.hpp"
|
||||||
|
#include "GCode/Analyzer.hpp"
|
||||||
|
|
||||||
#include "tbb/atomic.h"
|
#include "tbb/atomic.h"
|
||||||
|
|
||||||
@ -240,6 +241,7 @@ public:
|
|||||||
|
|
||||||
// ordered collections of extrusion paths to build skirt loops and brim
|
// ordered collections of extrusion paths to build skirt loops and brim
|
||||||
ExtrusionEntityCollection skirt, brim;
|
ExtrusionEntityCollection skirt, brim;
|
||||||
|
GCodeAnalyzer::PreviewData gcode_preview;
|
||||||
|
|
||||||
Print() : total_used_filament(0), total_extruded_volume(0) { restart(); }
|
Print() : total_used_filament(0), total_extruded_volume(0) { restart(); }
|
||||||
~Print() { clear_objects(); }
|
~Print() { clear_objects(); }
|
||||||
@ -253,6 +255,27 @@ public:
|
|||||||
void reload_object(size_t idx);
|
void reload_object(size_t idx);
|
||||||
bool reload_model_instances();
|
bool reload_model_instances();
|
||||||
|
|
||||||
|
void clear_gcode_preview_data();
|
||||||
|
void set_gcode_preview_type(unsigned char type);
|
||||||
|
void set_gcode_preview_extrusion_flags(unsigned int flags);
|
||||||
|
bool is_gcode_preview_extrusion_role_enabled(ExtrusionRole role);
|
||||||
|
void set_gcode_preview_travel_visible(bool visible);
|
||||||
|
void set_gcode_preview_retractions_visible(bool visible);
|
||||||
|
void set_gcode_preview_unretractions_visible(bool visible);
|
||||||
|
void set_gcode_preview_shells_visible(bool visible);
|
||||||
|
|
||||||
|
// Sets the extrusion path colors from the given strings vector.
|
||||||
|
// Data in the vector should be formatted as follows:
|
||||||
|
// std::vector<std::string> role_colors =
|
||||||
|
// { <role_1>, <color_1>,
|
||||||
|
// <role_2>, <color_2>,
|
||||||
|
// <role_3>, <color_3>,
|
||||||
|
// ...
|
||||||
|
// <role_N>, <color_N> };
|
||||||
|
// where <role_X> should be a string from GCodeAnalyzer::PreviewData::Extrusion::Default_Extrusion_Role_Names[]
|
||||||
|
// and <color_X> an RGB color in hex format (i.e. red = FF0000)
|
||||||
|
void set_gcode_extrusion_paths_colors(const std::vector<std::string>& colors);
|
||||||
|
|
||||||
// methods for handling regions
|
// methods for handling regions
|
||||||
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
|
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
|
||||||
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }
|
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }
|
||||||
|
@ -163,11 +163,11 @@ static inline T clamp(const T low, const T high, const T value)
|
|||||||
return std::max(low, std::min(high, value));
|
return std::max(low, std::min(high, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Number>
|
||||||
static inline T lerp(const T a, const T b, const T t)
|
static inline T lerp(const T& a, const T& b, Number t)
|
||||||
{
|
{
|
||||||
assert(t >= T(-EPSILON) && t <= T(1.+EPSILON));
|
assert((t >= Number(-EPSILON)) && (t <= Number(1) + Number(EPSILON)));
|
||||||
return (1. - t) * a + t * b;
|
return (Number(1) - t) * a + t * b;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,8 @@
|
|||||||
#include "../../libslic3r/TriangleMesh.hpp"
|
#include "../../libslic3r/TriangleMesh.hpp"
|
||||||
#include "../../libslic3r/Utils.hpp"
|
#include "../../libslic3r/Utils.hpp"
|
||||||
|
|
||||||
|
class wxBitmap;
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class Print;
|
class Print;
|
||||||
@ -106,6 +108,10 @@ public:
|
|||||||
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void push_geometry(const Pointf3& p, const Vectorf3& n) {
|
||||||
|
push_geometry(p.x, p.y, p.z, n.x, n.y, n.z);
|
||||||
|
}
|
||||||
|
|
||||||
inline void push_triangle(int idx1, int idx2, int idx3) {
|
inline void push_triangle(int idx1, int idx2, int idx3) {
|
||||||
if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity())
|
if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity())
|
||||||
this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3));
|
this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3));
|
||||||
@ -207,6 +213,7 @@ public:
|
|||||||
select_group_id(-1),
|
select_group_id(-1),
|
||||||
drag_group_id(-1),
|
drag_group_id(-1),
|
||||||
selected(false),
|
selected(false),
|
||||||
|
is_active(true),
|
||||||
hover(false),
|
hover(false),
|
||||||
tverts_range(0, size_t(-1)),
|
tverts_range(0, size_t(-1)),
|
||||||
qverts_range(0, size_t(-1))
|
qverts_range(0, size_t(-1))
|
||||||
@ -243,6 +250,8 @@ public:
|
|||||||
int drag_group_id;
|
int drag_group_id;
|
||||||
// Is this object selected?
|
// Is this object selected?
|
||||||
bool selected;
|
bool selected;
|
||||||
|
// Whether or not this volume is active for rendering
|
||||||
|
bool is_active;
|
||||||
// Boolean: Is mouse over this object?
|
// Boolean: Is mouse over this object?
|
||||||
bool hover;
|
bool hover;
|
||||||
|
|
||||||
@ -258,6 +267,7 @@ public:
|
|||||||
// Offset into qverts & tverts, or offsets into indices stored into an OpenGL name_index_buffer.
|
// Offset into qverts & tverts, or offsets into indices stored into an OpenGL name_index_buffer.
|
||||||
std::vector<size_t> offsets;
|
std::vector<size_t> offsets;
|
||||||
|
|
||||||
|
|
||||||
int object_idx() const { return this->composite_id / 1000000; }
|
int object_idx() const { return this->composite_id / 1000000; }
|
||||||
int volume_idx() const { return (this->composite_id / 1000) % 1000; }
|
int volume_idx() const { return (this->composite_id / 1000) % 1000; }
|
||||||
int instance_idx() const { return this->composite_id % 1000; }
|
int instance_idx() const { return this->composite_id % 1000; }
|
||||||
@ -299,6 +309,28 @@ public:
|
|||||||
|
|
||||||
class GLVolumeCollection
|
class GLVolumeCollection
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
struct RenderInterleavedOnlyVolumes
|
||||||
|
{
|
||||||
|
bool enabled;
|
||||||
|
float alpha; // [0..1]
|
||||||
|
|
||||||
|
RenderInterleavedOnlyVolumes()
|
||||||
|
: enabled(false)
|
||||||
|
, alpha(0.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderInterleavedOnlyVolumes(bool enabled, float alpha)
|
||||||
|
: enabled(enabled)
|
||||||
|
, alpha(alpha)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
RenderInterleavedOnlyVolumes _render_interleaved_only_volumes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<GLVolume*> volumes;
|
std::vector<GLVolume*> volumes;
|
||||||
|
|
||||||
@ -334,6 +366,8 @@ public:
|
|||||||
bool empty() const { return volumes.empty(); }
|
bool empty() const { return volumes.empty(); }
|
||||||
void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); }
|
void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); }
|
||||||
|
|
||||||
|
void set_render_interleaved_only_volumes(const RenderInterleavedOnlyVolumes& render_interleaved_only_volumes) { _render_interleaved_only_volumes = render_interleaved_only_volumes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLVolumeCollection(const GLVolumeCollection &other);
|
GLVolumeCollection(const GLVolumeCollection &other);
|
||||||
GLVolumeCollection& operator=(const GLVolumeCollection &);
|
GLVolumeCollection& operator=(const GLVolumeCollection &);
|
||||||
@ -341,9 +375,79 @@ private:
|
|||||||
|
|
||||||
class _3DScene
|
class _3DScene
|
||||||
{
|
{
|
||||||
|
struct GCodePreviewData
|
||||||
|
{
|
||||||
|
enum EType
|
||||||
|
{
|
||||||
|
Extrusion,
|
||||||
|
Travel,
|
||||||
|
Retraction,
|
||||||
|
Unretraction,
|
||||||
|
Shell,
|
||||||
|
Num_Geometry_Types
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FirstVolume
|
||||||
|
{
|
||||||
|
EType type;
|
||||||
|
unsigned int flag;
|
||||||
|
unsigned int id;
|
||||||
|
|
||||||
|
FirstVolume(EType type, unsigned int flag, unsigned int id);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<FirstVolume> first_volumes;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
static GCodePreviewData s_gcode_preview_data;
|
||||||
|
|
||||||
|
class LegendTexture
|
||||||
|
{
|
||||||
|
static const unsigned int Px_Title_Offset = 5;
|
||||||
|
static const unsigned int Px_Text_Offset = 5;
|
||||||
|
static const unsigned int Px_Square = 20;
|
||||||
|
static const unsigned int Px_Square_Contour = 1;
|
||||||
|
static const unsigned int Px_Border = Px_Square / 2;
|
||||||
|
static const unsigned char Squares_Border_Color[3];
|
||||||
|
static const unsigned char Background_Color[3];
|
||||||
|
static const unsigned char Opacity;
|
||||||
|
|
||||||
|
unsigned int m_tex_id;
|
||||||
|
unsigned int m_tex_width;
|
||||||
|
unsigned int m_tex_height;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LegendTexture();
|
||||||
|
~LegendTexture();
|
||||||
|
|
||||||
|
bool generate_texture(const Print& print, const std::vector<float>& tool_colors);
|
||||||
|
|
||||||
|
unsigned int get_texture_id() const;
|
||||||
|
unsigned int get_texture_width() const;
|
||||||
|
unsigned int get_texture_height() const;
|
||||||
|
|
||||||
|
void reset_texture();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _create_texture(const Print& print, const wxBitmap& bitmap);
|
||||||
|
void _destroy_texture();
|
||||||
|
};
|
||||||
|
|
||||||
|
static LegendTexture s_legend_texture;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void _glew_init();
|
static void _glew_init();
|
||||||
|
|
||||||
|
static void load_gcode_preview(const Print* print, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs);
|
||||||
|
|
||||||
|
static unsigned int get_legend_texture_id();
|
||||||
|
static unsigned int get_legend_texture_width();
|
||||||
|
static unsigned int get_legend_texture_height();
|
||||||
|
|
||||||
|
static void reset_legend_texture();
|
||||||
|
|
||||||
static void _load_print_toolpaths(
|
static void _load_print_toolpaths(
|
||||||
const Print *print,
|
const Print *print,
|
||||||
GLVolumeCollection *volumes,
|
GLVolumeCollection *volumes,
|
||||||
@ -356,12 +460,30 @@ public:
|
|||||||
const std::vector<std::string> &tool_colors,
|
const std::vector<std::string> &tool_colors,
|
||||||
bool use_VBOs);
|
bool use_VBOs);
|
||||||
|
|
||||||
|
|
||||||
static void _load_wipe_tower_toolpaths(
|
static void _load_wipe_tower_toolpaths(
|
||||||
const Print *print,
|
const Print *print,
|
||||||
GLVolumeCollection *volumes,
|
GLVolumeCollection *volumes,
|
||||||
const std::vector<std::string> &tool_colors_str,
|
const std::vector<std::string> &tool_colors_str,
|
||||||
bool use_VBOs);
|
bool use_VBOs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// generates gcode extrusion paths geometry
|
||||||
|
static void _load_gcode_extrusion_paths(const Print& print, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
|
||||||
|
// generates gcode travel paths geometry
|
||||||
|
static void _load_gcode_travel_paths(const Print& print, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
|
||||||
|
static bool _travel_paths_by_type(const Print& print, GLVolumeCollection& volumes);
|
||||||
|
static bool _travel_paths_by_feedrate(const Print& print, GLVolumeCollection& volumes);
|
||||||
|
static bool _travel_paths_by_tool(const Print& print, GLVolumeCollection& volumes, const std::vector<float>& tool_colors);
|
||||||
|
// generates gcode retractions geometry
|
||||||
|
static void _load_gcode_retractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
|
||||||
|
// generates gcode unretractions geometry
|
||||||
|
static void _load_gcode_unretractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
|
||||||
|
// sets gcode geometry visibility according to user selection
|
||||||
|
static void _update_gcode_volumes_visibility(const Print& print, GLVolumeCollection& volumes);
|
||||||
|
// generates the legend texture in dependence of the current shown view type
|
||||||
|
static void _generate_legend_texture(const Print& print, const std::vector<float>& tool_colors);
|
||||||
|
// generates objects and wipe tower geometry
|
||||||
|
static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/split.hpp>
|
||||||
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
#import <IOKit/pwr_mgt/IOPMLib.h>
|
#import <IOKit/pwr_mgt/IOPMLib.h>
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
@ -20,6 +23,9 @@
|
|||||||
#include <wx/notebook.h>
|
#include <wx/notebook.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/combo.h>
|
||||||
|
|
||||||
|
#include "wxExtensions.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
@ -183,4 +189,49 @@ void create_preset_tab(const char *name)
|
|||||||
g_wxTabPanel->AddPage(panel, name);
|
g_wxTabPanel->AddPage(panel, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value)
|
||||||
|
{
|
||||||
|
if (comboCtrl == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxCheckListBoxComboPopup* popup = new wxCheckListBoxComboPopup;
|
||||||
|
if (popup != nullptr)
|
||||||
|
{
|
||||||
|
comboCtrl->SetPopupControl(popup);
|
||||||
|
popup->SetStringValue(text);
|
||||||
|
popup->Connect(wxID_ANY, wxEVT_CHECKLISTBOX, wxCommandEventHandler(wxCheckListBoxComboPopup::OnCheckListBox), nullptr, popup);
|
||||||
|
popup->Connect(wxID_ANY, wxEVT_LISTBOX, wxCommandEventHandler(wxCheckListBoxComboPopup::OnListBoxSelection), nullptr, popup);
|
||||||
|
|
||||||
|
std::vector<std::string> items_str;
|
||||||
|
boost::split(items_str, items, boost::is_any_of("|"), boost::token_compress_off);
|
||||||
|
|
||||||
|
for (const std::string& item : items_str)
|
||||||
|
{
|
||||||
|
popup->Append(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < popup->GetCount(); ++i)
|
||||||
|
{
|
||||||
|
popup->Check(i, initial_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int combochecklist_get_flags(wxComboCtrl* comboCtrl)
|
||||||
|
{
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
wxCheckListBoxComboPopup* popup = wxDynamicCast(comboCtrl->GetPopupControl(), wxCheckListBoxComboPopup);
|
||||||
|
if (popup != nullptr)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < popup->GetCount(); ++i)
|
||||||
|
{
|
||||||
|
if (popup->IsChecked(i))
|
||||||
|
flags |= 1 << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
@ -8,6 +8,7 @@ class wxApp;
|
|||||||
class wxFrame;
|
class wxFrame;
|
||||||
class wxMenuBar;
|
class wxMenuBar;
|
||||||
class wxNotebook;
|
class wxNotebook;
|
||||||
|
class wxComboCtrl;
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
@ -27,6 +28,16 @@ void add_debug_menu(wxMenuBar *menu);
|
|||||||
// add it at the end of the tab panel.
|
// add it at the end of the tab panel.
|
||||||
void create_preset_tab(const char *name);
|
void create_preset_tab(const char *name);
|
||||||
|
|
||||||
} }
|
// Creates a wxCheckListBoxComboPopup inside the given wxComboCtrl, filled with the given text and items.
|
||||||
|
// Items are all initialized to the given value.
|
||||||
|
// Items must be separated by '|', for example "Item1|Item2|Item3", and so on.
|
||||||
|
void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value);
|
||||||
|
|
||||||
|
// Returns the current state of the items listed in the wxCheckListBoxComboPopup contained in the given wxComboCtrl,
|
||||||
|
// encoded inside an int.
|
||||||
|
int combochecklist_get_flags(wxComboCtrl* comboCtrl);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
68
xs/src/slic3r/GUI/wxExtensions.cpp
Normal file
68
xs/src/slic3r/GUI/wxExtensions.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "wxExtensions.hpp"
|
||||||
|
|
||||||
|
const unsigned int wxCheckListBoxComboPopup::Height = 210;
|
||||||
|
|
||||||
|
bool wxCheckListBoxComboPopup::Create(wxWindow* parent)
|
||||||
|
{
|
||||||
|
return wxCheckListBox::Create(parent, wxID_HIGHEST + 1, wxPoint(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxWindow* wxCheckListBoxComboPopup::GetControl()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxCheckListBoxComboPopup::SetStringValue(const wxString& value)
|
||||||
|
{
|
||||||
|
m_text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxCheckListBoxComboPopup::GetStringValue() const
|
||||||
|
{
|
||||||
|
return m_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxSize wxCheckListBoxComboPopup::GetAdjustedSize(int minWidth, int prefHeight, int maxHeight)
|
||||||
|
{
|
||||||
|
// matches owner wxComboCtrl's width
|
||||||
|
|
||||||
|
wxComboCtrl* cmb = GetComboCtrl();
|
||||||
|
if (cmb != nullptr)
|
||||||
|
{
|
||||||
|
wxSize size = GetComboCtrl()->GetSize();
|
||||||
|
size.SetHeight(Height);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return wxSize(200, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxCheckListBoxComboPopup::OnCheckListBox(wxCommandEvent& evt)
|
||||||
|
{
|
||||||
|
// forwards the checklistbox event to the owner wxComboCtrl
|
||||||
|
|
||||||
|
wxComboCtrl* cmb = GetComboCtrl();
|
||||||
|
if (cmb != nullptr)
|
||||||
|
{
|
||||||
|
wxCommandEvent event(wxEVT_CHECKLISTBOX, cmb->GetId());
|
||||||
|
event.SetEventObject(cmb);
|
||||||
|
cmb->ProcessWindowEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxCheckListBoxComboPopup::OnListBoxSelection(wxCommandEvent& evt)
|
||||||
|
{
|
||||||
|
// transforms list box item selection event into checklistbox item toggle event
|
||||||
|
|
||||||
|
int selId = GetSelection();
|
||||||
|
if (selId != wxNOT_FOUND)
|
||||||
|
{
|
||||||
|
Check((unsigned int)selId, !IsChecked((unsigned int)selId));
|
||||||
|
SetSelection(wxNOT_FOUND);
|
||||||
|
|
||||||
|
wxCommandEvent event(wxEVT_CHECKLISTBOX, GetId());
|
||||||
|
event.SetInt(selId);
|
||||||
|
event.SetEventObject(this);
|
||||||
|
ProcessEvent(event);
|
||||||
|
}
|
||||||
|
}
|
24
xs/src/slic3r/GUI/wxExtensions.hpp
Normal file
24
xs/src/slic3r/GUI/wxExtensions.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef slic3r_GUI_wxExtensions_hpp_
|
||||||
|
#define slic3r_GUI_wxExtensions_hpp_
|
||||||
|
|
||||||
|
#include <wx/checklst.h>
|
||||||
|
#include <wx/combo.h>
|
||||||
|
|
||||||
|
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
|
||||||
|
{
|
||||||
|
static const unsigned int Height;
|
||||||
|
|
||||||
|
wxString m_text;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool Create(wxWindow* parent);
|
||||||
|
virtual wxWindow* GetControl();
|
||||||
|
virtual void SetStringValue(const wxString& value);
|
||||||
|
virtual wxString GetStringValue() const;
|
||||||
|
virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
|
||||||
|
|
||||||
|
void OnCheckListBox(wxCommandEvent& evt);
|
||||||
|
void OnListBoxSelection(wxCommandEvent& evt);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // slic3r_GUI_wxExtensions_hpp_
|
@ -37,3 +37,10 @@ void add_debug_menu(SV *ui)
|
|||||||
|
|
||||||
void create_preset_tab(const char *name)
|
void create_preset_tab(const char *name)
|
||||||
%code%{ Slic3r::GUI::create_preset_tab(name); %};
|
%code%{ Slic3r::GUI::create_preset_tab(name); %};
|
||||||
|
|
||||||
|
void create_combochecklist(SV *ui, std::string text, std::string items, bool initial_value)
|
||||||
|
%code%{ Slic3r::GUI::create_combochecklist((wxComboCtrl*)wxPli_sv_2_object(aTHX_ ui, "Wx::ComboCtrl"), text, items, initial_value); %};
|
||||||
|
|
||||||
|
int combochecklist_get_flags(SV *ui)
|
||||||
|
%code%{ RETVAL=Slic3r::GUI::combochecklist_get_flags((wxComboCtrl*)wxPli_sv_2_object(aTHX_ ui, "Wx::ComboCtrl")); %};
|
||||||
|
|
@ -141,6 +141,32 @@ _glew_init()
|
|||||||
CODE:
|
CODE:
|
||||||
_3DScene::_glew_init();
|
_3DScene::_glew_init();
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
get_legend_texture_id()
|
||||||
|
CODE:
|
||||||
|
RETVAL = _3DScene::get_legend_texture_id();
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
get_legend_texture_width()
|
||||||
|
CODE:
|
||||||
|
RETVAL = _3DScene::get_legend_texture_width();
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
get_legend_texture_height()
|
||||||
|
CODE:
|
||||||
|
RETVAL = _3DScene::get_legend_texture_height();
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
void
|
||||||
|
reset_legend_texture()
|
||||||
|
CODE:
|
||||||
|
_3DScene::reset_legend_texture();
|
||||||
|
|
||||||
void
|
void
|
||||||
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs)
|
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs)
|
||||||
Print *print;
|
Print *print;
|
||||||
@ -168,4 +194,13 @@ _load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs)
|
|||||||
CODE:
|
CODE:
|
||||||
_3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
_3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
||||||
|
|
||||||
|
void
|
||||||
|
load_gcode_preview(print, volumes, str_tool_colors, use_VBOs)
|
||||||
|
Print *print;
|
||||||
|
GLVolumeCollection *volumes;
|
||||||
|
std::vector<std::string> str_tool_colors;
|
||||||
|
int use_VBOs;
|
||||||
|
CODE:
|
||||||
|
_3DScene::load_gcode_preview(print, volumes, str_tool_colors, use_VBOs != 0);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
@ -165,6 +165,15 @@ _constant()
|
|||||||
size_t object_count()
|
size_t object_count()
|
||||||
%code%{ RETVAL = THIS->objects.size(); %};
|
%code%{ RETVAL = THIS->objects.size(); %};
|
||||||
|
|
||||||
|
void clear_gcode_preview_data();
|
||||||
|
void set_gcode_preview_type(unsigned char type);
|
||||||
|
void set_gcode_preview_extrusion_flags(unsigned int flags);
|
||||||
|
void set_gcode_preview_travel_visible(bool visible);
|
||||||
|
void set_gcode_preview_retractions_visible(bool visible);
|
||||||
|
void set_gcode_preview_unretractions_visible(bool visible);
|
||||||
|
void set_gcode_preview_shells_visible(bool visible);
|
||||||
|
void set_gcode_extrusion_paths_colors(std::vector<std::string> colors);
|
||||||
|
|
||||||
PrintRegionPtrs* regions()
|
PrintRegionPtrs* regions()
|
||||||
%code%{ RETVAL = &THIS->regions; %};
|
%code%{ RETVAL = &THIS->regions; %};
|
||||||
Ref<PrintRegion> get_region(int idx);
|
Ref<PrintRegion> get_region(int idx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user