New config field extruder_color for preview of extruder assignment.

This commit is contained in:
bubnikv 2017-05-24 15:20:20 +02:00
parent 2713aa1772
commit 7d64c465c0
13 changed files with 284 additions and 64 deletions

View File

@ -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 {

View File

@ -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';

View File

@ -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);
}

View File

@ -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) = @_;

View File

@ -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);

View File

@ -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);

View File

@ -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 &ltp : per_object[i]) {
ordering_item.print_z = ltp.print_z();
ordering_item.print_z = ltp.print_z();
ordering_item.layer_idx = &ltp - &front;
ordering.emplace_back(ordering_item);
}

View File

@ -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"

View File

@ -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).";

View File

@ -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);

View File

@ -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 &copy: *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();
});

View File

@ -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);
};
}

View File

@ -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);
%}