New config field extruder_color for preview of extruder assignment.
This commit is contained in:
parent
2713aa1772
commit
7d64c465c0
@ -1871,10 +1871,10 @@ sub load_object {
|
||||
# Create 3D thick extrusion lines for a skirt and brim.
|
||||
# Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes.
|
||||
sub load_print_toolpaths {
|
||||
my ($self, $print) = @_;
|
||||
my ($self, $print, $colors) = @_;
|
||||
|
||||
$self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||
Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $self->UseVBOs)
|
||||
Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $colors, $self->UseVBOs)
|
||||
if ($print->step_done(STEP_SKIRT) && $print->step_done(STEP_BRIM));
|
||||
}
|
||||
|
||||
@ -1882,10 +1882,10 @@ sub load_print_toolpaths {
|
||||
# Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||
# one for perimeters, one for infill and one for supports.
|
||||
sub load_print_object_toolpaths {
|
||||
my ($self, $object) = @_;
|
||||
my ($self, $object, $colors) = @_;
|
||||
|
||||
$self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||
Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $self->UseVBOs);
|
||||
Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $colors, $self->UseVBOs);
|
||||
}
|
||||
|
||||
sub set_toolpaths_range {
|
||||
|
@ -280,6 +280,7 @@ has 'label_tooltip' => (is => 'rw', default => sub { "" });
|
||||
has 'sizer' => (is => 'rw');
|
||||
has 'widget' => (is => 'rw');
|
||||
has '_options' => (is => 'ro', default => sub { [] });
|
||||
# Extra UI components after the label and the edit widget of the option.
|
||||
has '_extra_widgets' => (is => 'ro', default => sub { [] });
|
||||
|
||||
# this method accepts a Slic3r::GUI::OptionsGroup::Option object
|
||||
@ -304,6 +305,8 @@ sub get_extra_widgets {
|
||||
}
|
||||
|
||||
|
||||
# Configuration of an option.
|
||||
# This very much reflects the content of the C++ ConfigOptionDef class.
|
||||
package Slic3r::GUI::OptionsGroup::Option;
|
||||
use Moo;
|
||||
|
||||
@ -349,6 +352,8 @@ sub get_option {
|
||||
my $opt_id = ($opt_index == -1 ? $opt_key : "${opt_key}#${opt_index}");
|
||||
$self->_opt_map->{$opt_id} = [ $opt_key, $opt_index ];
|
||||
|
||||
# Slic3r::Config::Options is a C++ Slic3r::PrintConfigDef exported as a Perl hash of hashes.
|
||||
# The C++ counterpart is a constant singleton.
|
||||
my $optdef = $Slic3r::Config::Options->{$opt_key}; # we should access this from $self->config
|
||||
my $default_value = $self->_get_config_value($opt_key, $opt_index, $optdef->{gui_flags} =~ /\bserialized\b/);
|
||||
|
||||
@ -463,6 +468,8 @@ sub _on_kill_focus {
|
||||
$self->reload_config;
|
||||
}
|
||||
|
||||
# Static text shown among the options.
|
||||
# Currently used for the filament cooling legend only.
|
||||
package Slic3r::GUI::OptionsGroup::StaticText;
|
||||
use Wx qw(:misc :systemsettings);
|
||||
use base 'Wx::StaticText';
|
||||
|
@ -425,6 +425,8 @@ sub _string_to_colour {
|
||||
my ($self, $string) = @_;
|
||||
|
||||
$string =~ s/^#//;
|
||||
# If the color is in an invalid format, set it to white.
|
||||
$string = 'FFFFFF' if ($string !~ m/^[[:xdigit:]]{6}/);
|
||||
return Wx::Colour->new(unpack 'C*', pack 'H*', $string);
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,10 @@ use List::Util qw(sum first max);
|
||||
use Slic3r::Geometry qw(X Y Z MIN MAX scale unscale deg2rad rad2deg);
|
||||
use LWP::UserAgent;
|
||||
use threads::shared qw(shared_clone);
|
||||
use Wx qw(:button :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc
|
||||
use Wx qw(:button :colour :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc
|
||||
:panel :sizer :toolbar :window wxTheApp :notebook :combobox wxNullBitmap);
|
||||
use Wx::Event qw(EVT_BUTTON EVT_TOGGLEBUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_ACTIVATED
|
||||
EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL
|
||||
EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_LEFT_DOWN EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL
|
||||
EVT_CHOICE EVT_COMBOBOX EVT_TIMER EVT_NOTEBOOK_PAGE_CHANGED);
|
||||
use base 'Wx::Panel';
|
||||
|
||||
@ -54,7 +54,7 @@ sub new {
|
||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||
serial_port serial_speed octoprint_host octoprint_apikey
|
||||
nozzle_diameter single_extruder_multi_material
|
||||
wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe
|
||||
wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe extruder_colour filament_colour
|
||||
));
|
||||
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
||||
$self->{model} = Slic3r::Model->new;
|
||||
@ -138,7 +138,7 @@ sub new {
|
||||
|
||||
# Initialize 3D toolpaths preview
|
||||
if ($Slic3r::GUI::have_OpenGL) {
|
||||
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print});
|
||||
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{config});
|
||||
$self->{preview3D}->canvas->on_viewport_changed(sub {
|
||||
$self->{canvas3D}->set_viewport_from_scene($self->{preview3D}->canvas);
|
||||
});
|
||||
@ -378,6 +378,7 @@ sub new {
|
||||
my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
|
||||
$text->SetFont($Slic3r::GUI::small_font);
|
||||
my $choice = Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY);
|
||||
EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down(0, @_); } );
|
||||
$self->{preset_choosers}{$group} = [$choice];
|
||||
$self->{preset_choosers_default_suppressed}{$group} = 0;
|
||||
# setup the listener
|
||||
@ -524,12 +525,12 @@ sub _on_select_preset {
|
||||
$Slic3r::GUI::Settings->{presets}{"filament_${_}"} = $choice->GetString($filament_presets[$_] - $default_suppressed)
|
||||
for 1 .. $#filament_presets;
|
||||
wxTheApp->save_settings;
|
||||
return;
|
||||
}
|
||||
|
||||
# call GetSelection() in scalar context as it's context-aware
|
||||
$self->{on_select_preset}->($group, scalar($choice->GetSelection) + $default_suppressed)
|
||||
if $self->{on_select_preset};
|
||||
$self->update_filament_colors_preview($choice);
|
||||
} else {
|
||||
# call GetSelection() in scalar context as it's context-aware
|
||||
$self->{on_select_preset}->($group, scalar($choice->GetSelection) + $default_suppressed)
|
||||
if $self->{on_select_preset};
|
||||
}
|
||||
|
||||
# get new config and generate on_config_change() event for updating plater and other things
|
||||
$self->on_config_change($self->GetFrame->config);
|
||||
@ -584,6 +585,7 @@ sub update_presets {
|
||||
my ($group, $presets, $default_suppressed, $selected, $is_dirty) = @_;
|
||||
|
||||
my @choosers = @{ $self->{preset_choosers}{$group} };
|
||||
my $choice_idx = 0;
|
||||
foreach my $choice (@choosers) {
|
||||
if ($group eq 'filament' && @choosers > 1) {
|
||||
# if we have more than one filament chooser, keep our selection
|
||||
@ -596,17 +598,7 @@ sub update_presets {
|
||||
next if ($preset->default && $default_suppressed);
|
||||
my $bitmap;
|
||||
if ($group eq 'filament') {
|
||||
my $config = $preset->config(['filament_colour']);
|
||||
my $rgb_hex = $config->filament_colour->[0];
|
||||
if ($preset->default) {
|
||||
$bitmap = Wx::Bitmap->new($Slic3r::var->("spool.png"), wxBITMAP_TYPE_PNG);
|
||||
} else {
|
||||
$rgb_hex =~ s/^#//;
|
||||
my @rgb = unpack 'C*', pack 'H*', $rgb_hex;
|
||||
my $image = Wx::Image->new(16,16);
|
||||
$image->SetRGB(Wx::Rect->new(0,0,16,16), @rgb);
|
||||
$bitmap = Wx::Bitmap->new($image);
|
||||
}
|
||||
$bitmap = Wx::Bitmap->new($Slic3r::var->("spool.png"), wxBITMAP_TYPE_PNG);
|
||||
} elsif ($group eq 'print') {
|
||||
$bitmap = Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG);
|
||||
} elsif ($group eq 'printer') {
|
||||
@ -626,9 +618,76 @@ sub update_presets {
|
||||
$choice->SetSelection($idx);
|
||||
}
|
||||
}
|
||||
$choice_idx += 1;
|
||||
}
|
||||
|
||||
$self->{preset_choosers_default_suppressed}{$group} = $default_suppressed;
|
||||
$self->update_filament_colors_preview;
|
||||
}
|
||||
|
||||
# Update the color icon in front of each filament selection on the platter.
|
||||
# If the extruder has a preview color assigned, apply the extruder color to the active selection.
|
||||
# Always apply the filament color to the non-active selections.
|
||||
sub update_filament_colors_preview {
|
||||
my ($self, $extruder_idx) = shift;
|
||||
|
||||
my @choosers = @{$self->{preset_choosers}{filament}};
|
||||
|
||||
if (ref $extruder_idx) {
|
||||
# $extruder_idx is the chooser.
|
||||
foreach my $chooser (@choosers) {
|
||||
if ($extruder_idx == $chooser) {
|
||||
$extruder_idx = $chooser;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @extruder_colors = @{$self->{config}->extruder_colour};
|
||||
|
||||
my @extruder_list;
|
||||
if (defined $extruder_idx) {
|
||||
@extruder_list = ($extruder_idx);
|
||||
} else {
|
||||
# Collect extruder indices.
|
||||
@extruder_list = (0..$#extruder_colors);
|
||||
}
|
||||
|
||||
my $filament_tab = $self->GetFrame->{options_tabs}{filament};
|
||||
my $presets = $filament_tab->{presets};
|
||||
my $default_suppressed = $filament_tab->{default_suppressed};
|
||||
|
||||
foreach my $extruder_idx (@extruder_list) {
|
||||
my $chooser = $choosers[$extruder_idx];
|
||||
my $extruder_color = $self->{config}->extruder_colour->[$extruder_idx];
|
||||
my $preset_idx = 0;
|
||||
my $selection_idx = $chooser->GetSelection;
|
||||
foreach my $preset (@$presets) {
|
||||
my $bitmap;
|
||||
if ($preset->default) {
|
||||
next if $default_suppressed;
|
||||
} else {
|
||||
# Assign an extruder color to the selected item if the extruder color is defined.
|
||||
my $filament_rgb = $preset->config(['filament_colour'])->filament_colour->[0];
|
||||
my $extruder_rgb = ($preset_idx == $selection_idx && $extruder_color =~ m/^#[[:xdigit:]]{6}/) ? $extruder_color : $filament_rgb;
|
||||
$filament_rgb =~ s/^#//;
|
||||
$extruder_rgb =~ s/^#//;
|
||||
my $image = Wx::Image->new(24,16);
|
||||
if ($filament_rgb ne $extruder_rgb) {
|
||||
my @rgb = unpack 'C*', pack 'H*', $extruder_rgb;
|
||||
$image->SetRGB(Wx::Rect->new(0,0,16,16), @rgb);
|
||||
@rgb = unpack 'C*', pack 'H*', $filament_rgb;
|
||||
$image->SetRGB(Wx::Rect->new(16,0,8,16), @rgb);
|
||||
} else {
|
||||
my @rgb = unpack 'C*', pack 'H*', $filament_rgb;
|
||||
$image->SetRGB(Wx::Rect->new(0,0,24,16), @rgb);
|
||||
}
|
||||
$bitmap = Wx::Bitmap->new($image);
|
||||
}
|
||||
$chooser->SetItemBitmap($preset_idx, $bitmap) if $bitmap;
|
||||
$preset_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Return a vector of indices of filaments selected by the $self->{preset_choosers}{filament} combo boxes.
|
||||
@ -1675,6 +1734,8 @@ sub on_extruders_change {
|
||||
|
||||
# initialize new choice
|
||||
my $choice = Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [@presets], wxCB_READONLY);
|
||||
my $extruder_idx = scalar @$choices;
|
||||
EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down($extruder_idx, @_); } );
|
||||
push @$choices, $choice;
|
||||
|
||||
# copy icons from first choice
|
||||
@ -1756,6 +1817,8 @@ sub on_config_change {
|
||||
$self->{"btn_layer_editing"}->Enable;
|
||||
}
|
||||
}
|
||||
} elsif ($opt_key eq 'extruder_color') {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1793,6 +1856,33 @@ sub list_item_activated {
|
||||
$self->object_settings_dialog($obj_idx);
|
||||
}
|
||||
|
||||
# Called when clicked on the filament preset combo box.
|
||||
# When clicked on the icon, show the color picker.
|
||||
sub filament_color_box_lmouse_down
|
||||
{
|
||||
my ($self, $extruder_idx, $combobox, $event) = @_;
|
||||
my $pos = $event->GetLogicalPosition(Wx::ClientDC->new($combobox));
|
||||
my( $x, $y ) = ( $pos->x, $pos->y );
|
||||
if ($x > 24) {
|
||||
# Let the combo box process the mouse click.
|
||||
$event->Skip;
|
||||
} else {
|
||||
# Swallow the mouse click and open the color picker.
|
||||
my $data = Wx::ColourData->new;
|
||||
$data->SetChooseFull(1);
|
||||
my $dialog = Wx::ColourDialog->new($self->GetFrame, $data);
|
||||
if ($dialog->ShowModal == wxID_OK) {
|
||||
my $cfg = Slic3r::Config->new;
|
||||
my $colors = $self->GetFrame->config->get('extruder_colour');
|
||||
$colors->[$extruder_idx] = $dialog->GetColourData->GetColour->GetAsString(wxC2S_HTML_SYNTAX);
|
||||
$cfg->set('extruder_colour', $colors);
|
||||
$self->GetFrame->{options_tabs}{printer}->load_config($cfg);
|
||||
$self->update_filament_colors_preview($extruder_idx);
|
||||
}
|
||||
$dialog->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
sub object_cut_dialog {
|
||||
my $self = shift;
|
||||
my ($obj_idx) = @_;
|
||||
|
@ -8,13 +8,14 @@ use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE);
|
||||
use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN EVT_CHECKBOX);
|
||||
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 color_by_extruder));
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent, $print) = @_;
|
||||
my ($parent, $print, $config) = @_;
|
||||
|
||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition);
|
||||
$self->{config} = $config;
|
||||
|
||||
# init GUI elements
|
||||
my $canvas = Slic3r::GUI::3DScene->new($self);
|
||||
@ -53,7 +54,9 @@ sub new {
|
||||
$z_label_high->SetFont($Slic3r::GUI::small_font);
|
||||
|
||||
$self->single_layer(0);
|
||||
$self->color_by_extruder(0);
|
||||
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 $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
@ -67,6 +70,7 @@ sub new {
|
||||
$hsizer->Add($vsizer, 0, wxEXPAND, 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_color_by_extruder, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5);
|
||||
|
||||
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
$sizer->Add($canvas, 1, wxALL | wxEXPAND, 0);
|
||||
@ -107,6 +111,10 @@ sub new {
|
||||
$self->set_z_idx_high($slider_high->GetValue);
|
||||
}
|
||||
});
|
||||
EVT_CHECKBOX($self, $checkbox_color_by_extruder, sub {
|
||||
$self->color_by_extruder($checkbox_color_by_extruder->GetValue());
|
||||
$self->reload_print;
|
||||
});
|
||||
|
||||
$self->SetSizer($sizer);
|
||||
$self->SetMinSize($self->GetSize);
|
||||
@ -181,12 +189,26 @@ sub load_print {
|
||||
$self->slider_high->Show;
|
||||
$self->Layout;
|
||||
|
||||
# Collect colors per extruder.
|
||||
# Leave it empty, if the print should be colored by a feature.
|
||||
my @colors = ();
|
||||
if ($self->color_by_extruder) {
|
||||
my @extruder_colors = @{$self->{config}->extruder_colour};
|
||||
my @filament_colors = @{$self->{config}->filament_colour};
|
||||
for (my $i = 0; $i <= $#extruder_colors; $i += 1) {
|
||||
my $color = $extruder_colors[$i];
|
||||
$color = $filament_colors[$i] if ($color !~ m/^#[[:xdigit:]]{6}/);
|
||||
$color = '#FFFFFF' if ($color !~ m/^#[[:xdigit:]]{6}/);
|
||||
push @colors, $color;
|
||||
}
|
||||
}
|
||||
|
||||
if ($self->IsShown) {
|
||||
# load skirt and brim
|
||||
$self->canvas->load_print_toolpaths($self->print);
|
||||
$self->canvas->load_print_toolpaths($self->print, \@colors);
|
||||
|
||||
foreach my $object (@{$self->print->objects}) {
|
||||
$self->canvas->load_print_object_toolpaths($object);
|
||||
$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);
|
||||
|
@ -1164,7 +1164,7 @@ sub build {
|
||||
nozzle_diameter extruder_offset
|
||||
retract_length retract_lift retract_speed deretract_speed retract_before_wipe retract_restart_extra retract_before_travel retract_layer_change wipe
|
||||
retract_length_toolchange retract_restart_extra_toolchange
|
||||
printer_notes
|
||||
extruder_colour printer_notes
|
||||
));
|
||||
$self->{config}->set('printer_settings_id', '');
|
||||
|
||||
@ -1455,7 +1455,7 @@ sub _extruder_options {
|
||||
qw(nozzle_diameter min_layer_height max_layer_height extruder_offset
|
||||
retract_length retract_lift retract_lift_above retract_lift_below retract_speed deretract_speed
|
||||
retract_before_wipe retract_restart_extra retract_before_travel wipe
|
||||
retract_layer_change retract_length_toolchange retract_restart_extra_toolchange) }
|
||||
retract_layer_change retract_length_toolchange retract_restart_extra_toolchange extruder_colour) }
|
||||
|
||||
sub _build_extruder_pages {
|
||||
my $self = shift;
|
||||
@ -1514,6 +1514,10 @@ sub _build_extruder_pages {
|
||||
$optgroup->append_single_option_line($_, $extruder_idx)
|
||||
for qw(retract_length_toolchange retract_restart_extra_toolchange);
|
||||
}
|
||||
{
|
||||
my $optgroup = $page->new_optgroup('Preview');
|
||||
$optgroup->append_single_option_line('extruder_colour', $extruder_idx);
|
||||
}
|
||||
}
|
||||
|
||||
# remove extra pages
|
||||
@ -1765,6 +1769,7 @@ sub get_name {
|
||||
package Slic3r::GUI::Tab::Preset;
|
||||
use Moo;
|
||||
|
||||
# The preset represents a "default" set of properties.
|
||||
has 'default' => (is => 'ro', default => sub { 0 });
|
||||
has 'external' => (is => 'ro', default => sub { 0 });
|
||||
has 'name' => (is => 'rw', required => 1);
|
||||
|
@ -293,6 +293,9 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||
return layers_to_print;
|
||||
}
|
||||
|
||||
// Prepare for non-sequential printing of multiple objects: Support resp. object layers with nearly identical print_z
|
||||
// will be printed for all objects at once.
|
||||
// Return a list of <print_z, per object LayerToPrint> items.
|
||||
std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collect_layers_to_print(const Print &print)
|
||||
{
|
||||
struct OrderingItem {
|
||||
@ -304,11 +307,12 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
||||
std::vector<OrderingItem> ordering;
|
||||
for (size_t i = 0; i < print.objects.size(); ++ i) {
|
||||
per_object[i] = collect_layers_to_print(*print.objects[i]);
|
||||
const LayerToPrint &front = per_object[i].front();
|
||||
OrderingItem ordering_item;
|
||||
ordering_item.object_idx = i;
|
||||
ordering.reserve(ordering.size() + per_object[i].size());
|
||||
const LayerToPrint &front = per_object[i].front();
|
||||
for (const LayerToPrint <p : per_object[i]) {
|
||||
ordering_item.print_z = ltp.print_z();
|
||||
ordering_item.print_z = ltp.print_z();
|
||||
ordering_item.layer_idx = <p - &front;
|
||||
ordering.emplace_back(ordering_item);
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ Print::invalidate_state_by_config_options(const std::vector<t_config_option_key>
|
||||
|| *opt_key == "end_gcode"
|
||||
|| *opt_key == "extruder_clearance_height"
|
||||
|| *opt_key == "extruder_clearance_radius"
|
||||
|| *opt_key == "extruder_colour"
|
||||
|| *opt_key == "extruder_offset"
|
||||
|| *opt_key == "extrusion_axis"
|
||||
|| *opt_key == "extrusion_multiplier"
|
||||
|
@ -243,6 +243,19 @@ PrintConfigDef::PrintConfigDef()
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(20);
|
||||
|
||||
def = this->add("extruder_colour", coStrings);
|
||||
def->label = "Extruder Color";
|
||||
def->tooltip = "This is only used in the Slic3r interface as a visual help.";
|
||||
def->cli = "extruder-color=s@";
|
||||
def->gui_type = "color";
|
||||
{
|
||||
ConfigOptionStrings* opt = new ConfigOptionStrings();
|
||||
// Empty string means no color assigned yet.
|
||||
// opt->values.push_back("#FFFFFF");
|
||||
opt->values.push_back("");
|
||||
def->default_value = opt;
|
||||
}
|
||||
|
||||
def = this->add("extruder_offset", coPoints);
|
||||
def->label = "Extruder offset";
|
||||
def->tooltip = "If your firmware doesn't handle the extruder displacement you need the G-code to take it into account. This option lets you specify the displacement of each extruder with respect to the first one. It expects positive coordinates (they will be subtracted from the XY coordinate).";
|
||||
|
@ -413,7 +413,7 @@ public:
|
||||
// This object is mapped to Perl as Slic3r::Config::Print.
|
||||
class PrintConfig : public GCodeConfig
|
||||
{
|
||||
public:
|
||||
public:
|
||||
ConfigOptionBool avoid_crossing_perimeters;
|
||||
ConfigOptionPoints bed_shape;
|
||||
ConfigOptionInt bed_temperature;
|
||||
@ -427,6 +427,7 @@ class PrintConfig : public GCodeConfig
|
||||
ConfigOptionFloat duplicate_distance;
|
||||
ConfigOptionFloat extruder_clearance_height;
|
||||
ConfigOptionFloat extruder_clearance_radius;
|
||||
ConfigOptionStrings extruder_colour;
|
||||
ConfigOptionPoints extruder_offset;
|
||||
ConfigOptionBool fan_always_on;
|
||||
ConfigOptionInt fan_below_layer_time;
|
||||
@ -491,6 +492,7 @@ class PrintConfig : public GCodeConfig
|
||||
OPT_PTR(duplicate_distance);
|
||||
OPT_PTR(extruder_clearance_height);
|
||||
OPT_PTR(extruder_clearance_radius);
|
||||
OPT_PTR(extruder_colour);
|
||||
OPT_PTR(extruder_offset);
|
||||
OPT_PTR(fan_always_on);
|
||||
OPT_PTR(fan_below_layer_time);
|
||||
|
@ -710,12 +710,40 @@ void _3DScene::_glew_init()
|
||||
glewInit();
|
||||
}
|
||||
|
||||
inline int hex_digit_to_int(const char c)
|
||||
{
|
||||
return
|
||||
(c >= '0' && c <= '9') ? int(c - '0') :
|
||||
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
|
||||
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
||||
}
|
||||
|
||||
inline std::vector<float> parse_colors(const std::vector<std::string> &scolors)
|
||||
{
|
||||
std::vector<float> output(scolors.size() * 4, 1.f);
|
||||
for (size_t i = 0; i < scolors.size(); ++ i) {
|
||||
const std::string &scolor = scolors[i];
|
||||
const char *c = scolor.data() + 1;
|
||||
if (scolor.size() == 7 && scolor.front() == '#') {
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
int digit1 = hex_digit_to_int(*c ++);
|
||||
int digit2 = hex_digit_to_int(*c ++);
|
||||
if (digit1 == -1 || digit2 == -1)
|
||||
break;
|
||||
output[i * 4 + j] = float(digit1 * 16 + digit2) / 255.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Create 3D thick extrusion lines for a skirt and brim.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||
void _3DScene::_load_print_toolpaths(
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes,
|
||||
bool use_VBOs)
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors,
|
||||
bool use_VBOs)
|
||||
{
|
||||
if (! print->has_skirt() && print->config.brim_width.value == 0)
|
||||
return;
|
||||
@ -765,10 +793,13 @@ void _3DScene::_load_print_toolpaths(
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||
// one for perimeters, one for infill and one for supports.
|
||||
void _3DScene::_load_print_object_toolpaths(
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes,
|
||||
bool use_VBOs)
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors_str,
|
||||
bool use_VBOs)
|
||||
{
|
||||
std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
||||
|
||||
struct Ctxt
|
||||
{
|
||||
const Points *shifted_copies;
|
||||
@ -778,6 +809,7 @@ void _3DScene::_load_print_object_toolpaths(
|
||||
bool has_perimeters;
|
||||
bool has_infill;
|
||||
bool has_support;
|
||||
const std::vector<float>* tool_colors;
|
||||
|
||||
// Number of vertices (each vertex is 6x4=24 bytes long)
|
||||
static const size_t alloc_size_max () { return 131072; } // 3.15MB
|
||||
@ -788,6 +820,11 @@ void _3DScene::_load_print_object_toolpaths(
|
||||
static const float* color_perimeters () { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
||||
static const float* color_infill () { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
|
||||
static const float* color_support () { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
||||
|
||||
// For cloring by a tool, return a parsed color.
|
||||
bool color_by_tool() const { return tool_colors != nullptr; }
|
||||
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
||||
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
||||
} ctxt;
|
||||
|
||||
ctxt.shifted_copies = &print_object->_shifted_copies;
|
||||
@ -811,6 +848,7 @@ void _3DScene::_load_print_object_toolpaths(
|
||||
ctxt.has_perimeters = print_object->state.is_done(posPerimeters);
|
||||
ctxt.has_infill = print_object->state.is_done(posInfill);
|
||||
ctxt.has_support = print_object->state.is_done(posSupportMaterial);
|
||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
||||
|
||||
@ -829,15 +867,20 @@ void _3DScene::_load_print_object_toolpaths(
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
||||
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
||||
GLVolume* vols[3] = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
std::vector<GLVolume*> vols;
|
||||
if (ctxt.color_by_tool()) {
|
||||
for (size_t i = 0; i < ctxt.number_tools(); ++ i)
|
||||
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||
} else
|
||||
vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
||||
GLVolume &volume = *vols[i];
|
||||
volume.bounding_box = ctxt.bbox;
|
||||
volume.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||
}
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
const Layer *layer = ctxt.layers[idx_layer];
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
||||
GLVolume &vol = *vols[i];
|
||||
if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
|
||||
vol.print_zs.push_back(layer->print_z);
|
||||
@ -847,18 +890,45 @@ void _3DScene::_load_print_object_toolpaths(
|
||||
}
|
||||
for (const Point ©: *ctxt.shifted_copies) {
|
||||
for (const LayerRegion *layerm : layer->regions) {
|
||||
if (ctxt.has_perimeters)
|
||||
extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy, *vols[0]);
|
||||
if (ctxt.has_infill)
|
||||
extrusionentity_to_verts(layerm->fills, float(layer->print_z), copy, *vols[1]);
|
||||
if (ctxt.has_perimeters) {
|
||||
int volume_idx = ctxt.color_by_tool() ?
|
||||
std::max<int>(layerm->region()->config.perimeter_extruder.value - 1, 0) :
|
||||
0;
|
||||
extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy, *vols[volume_idx]);
|
||||
}
|
||||
if (ctxt.has_infill) {
|
||||
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||
// fill represents infill extrusions of a single island.
|
||||
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||
if (fill->entities.empty())
|
||||
// This shouldn't happen but first_point() would fail.
|
||||
continue;
|
||||
int volume_idx = ctxt.color_by_tool() ?
|
||||
std::max<int>(0,
|
||||
(is_solid_infill(fill->entities.front()->role()) ?
|
||||
layerm->region()->config.solid_infill_extruder :
|
||||
layerm->region()->config.infill_extruder) - 1) :
|
||||
1;
|
||||
extrusionentity_to_verts(*fill, float(layer->print_z), copy, *vols[volume_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctxt.has_support) {
|
||||
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
|
||||
if (support_layer)
|
||||
extrusionentity_to_verts(support_layer->support_fills, float(layer->print_z), copy, *vols[2]);
|
||||
if (support_layer) {
|
||||
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities) {
|
||||
int volume_idx = ctxt.color_by_tool() ?
|
||||
std::max<int>(0,
|
||||
((extrusion_entity->role() == erSupportMaterial) ?
|
||||
support_layer->object()->config.support_material_extruder :
|
||||
support_layer->object()->config.support_material_interface_extruder) - 1) :
|
||||
2;
|
||||
extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy, *vols[volume_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
||||
GLVolume &vol = *vols[i];
|
||||
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
||||
// Store the vertex arrays and restart their containers,
|
||||
@ -876,7 +946,7 @@ void _3DScene::_load_print_object_toolpaths(
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < 3; ++ i)
|
||||
for (size_t i = 0; i < vols.size(); ++ i)
|
||||
vols[i]->indexed_vertex_array.shrink_to_fit();
|
||||
});
|
||||
|
||||
|
@ -344,14 +344,16 @@ public:
|
||||
static void _glew_init();
|
||||
|
||||
static void _load_print_toolpaths(
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes,
|
||||
bool use_VBOs);
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors,
|
||||
bool use_VBOs);
|
||||
|
||||
static void _load_print_object_toolpaths(
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes,
|
||||
bool use_VBOs);
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes,
|
||||
const std::vector<std::string> &tool_colors,
|
||||
bool use_VBOs);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -118,19 +118,21 @@ _glew_init()
|
||||
_3DScene::_glew_init();
|
||||
|
||||
void
|
||||
_load_print_toolpaths(print, volumes, use_VBOs)
|
||||
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs)
|
||||
Print *print;
|
||||
GLVolumeCollection *volumes;
|
||||
std::vector<std::string> tool_colors;
|
||||
int use_VBOs;
|
||||
CODE:
|
||||
_3DScene::_load_print_toolpaths(print, volumes, use_VBOs != 0);
|
||||
_3DScene::_load_print_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
||||
|
||||
void
|
||||
_load_print_object_toolpaths(print_object, volumes, use_VBOs)
|
||||
_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs)
|
||||
PrintObject *print_object;
|
||||
GLVolumeCollection *volumes;
|
||||
std::vector<std::string> tool_colors;
|
||||
int use_VBOs;
|
||||
CODE:
|
||||
_3DScene::_load_print_object_toolpaths(print_object, volumes, use_VBOs != 0);
|
||||
_3DScene::_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs != 0);
|
||||
|
||||
%}
|
||||
|
Loading…
Reference in New Issue
Block a user