Merge branch 'bedshape'
This commit is contained in:
commit
7cc0bce97d
20 changed files with 497 additions and 130 deletions
|
@ -9,7 +9,7 @@ use List::Util qw(first max);
|
||||||
our @Ignore = qw(duplicate_x duplicate_y multiply_x multiply_y support_material_tool acceleration
|
our @Ignore = qw(duplicate_x duplicate_y multiply_x multiply_y support_material_tool acceleration
|
||||||
adjust_overhang_flow standby_temperature scale rotate duplicate duplicate_grid
|
adjust_overhang_flow standby_temperature scale rotate duplicate duplicate_grid
|
||||||
rotate scale duplicate_grid start_perimeters_at_concave_points start_perimeters_at_non_overhang
|
rotate scale duplicate_grid start_perimeters_at_concave_points start_perimeters_at_non_overhang
|
||||||
randomize_start seal_position);
|
randomize_start seal_position bed_size);
|
||||||
|
|
||||||
our $Options = print_config_def();
|
our $Options = print_config_def();
|
||||||
|
|
||||||
|
@ -124,7 +124,6 @@ sub _handle_legacy {
|
||||||
my ($opt_key, $value) = @_;
|
my ($opt_key, $value) = @_;
|
||||||
|
|
||||||
# handle legacy options
|
# handle legacy options
|
||||||
return () if first { $_ eq $opt_key } @Ignore;
|
|
||||||
if ($opt_key =~ /^(extrusion_width|bottom_layer_speed|first_layer_height)_ratio$/) {
|
if ($opt_key =~ /^(extrusion_width|bottom_layer_speed|first_layer_height)_ratio$/) {
|
||||||
$opt_key = $1;
|
$opt_key = $1;
|
||||||
$opt_key =~ s/^bottom_layer_speed$/first_layer_speed/;
|
$opt_key =~ s/^bottom_layer_speed$/first_layer_speed/;
|
||||||
|
@ -145,6 +144,12 @@ sub _handle_legacy {
|
||||||
$opt_key = 'seam_position';
|
$opt_key = 'seam_position';
|
||||||
$value = 'random';
|
$value = 'random';
|
||||||
}
|
}
|
||||||
|
if ($opt_key eq 'bed_size' && $value) {
|
||||||
|
$opt_key = 'bed_shape';
|
||||||
|
my ($x, $y) = split /,/, $value;
|
||||||
|
$value = "0x0,${x}x0,${x}x${y},0x${y}";
|
||||||
|
}
|
||||||
|
return () if first { $_ eq $opt_key } @Ignore;
|
||||||
|
|
||||||
# For historical reasons, the world's full of configs having these very low values;
|
# For historical reasons, the world's full of configs having these very low values;
|
||||||
# to avoid unexpected behavior we need to ignore them. Banning these two hard-coded
|
# to avoid unexpected behavior we need to ignore them. Banning these two hard-coded
|
||||||
|
@ -297,11 +302,6 @@ sub validate {
|
||||||
die "Invalid value for --infill-every-layers\n"
|
die "Invalid value for --infill-every-layers\n"
|
||||||
if $self->infill_every_layers !~ /^\d+$/ || $self->infill_every_layers < 1;
|
if $self->infill_every_layers !~ /^\d+$/ || $self->infill_every_layers < 1;
|
||||||
|
|
||||||
# --bed-size
|
|
||||||
die "Invalid value for --bed-size\n"
|
|
||||||
if !ref $self->bed_size
|
|
||||||
&& (!$self->bed_size || $self->bed_size !~ /^\d+,\d+$/);
|
|
||||||
|
|
||||||
# --skirt-height
|
# --skirt-height
|
||||||
die "Invalid value for --skirt-height\n"
|
die "Invalid value for --skirt-height\n"
|
||||||
if $self->skirt_height < -1; # -1 means as tall as the object
|
if $self->skirt_height < -1; # -1 means as tall as the object
|
||||||
|
|
|
@ -6,6 +6,7 @@ use utf8;
|
||||||
use File::Basename qw(basename);
|
use File::Basename qw(basename);
|
||||||
use FindBin;
|
use FindBin;
|
||||||
use Slic3r::GUI::AboutDialog;
|
use Slic3r::GUI::AboutDialog;
|
||||||
|
use Slic3r::GUI::BedShapeDialog;
|
||||||
use Slic3r::GUI::ConfigWizard;
|
use Slic3r::GUI::ConfigWizard;
|
||||||
use Slic3r::GUI::MainFrame;
|
use Slic3r::GUI::MainFrame;
|
||||||
use Slic3r::GUI::Notifier;
|
use Slic3r::GUI::Notifier;
|
||||||
|
@ -111,6 +112,11 @@ sub OnInit {
|
||||||
. "your support material settings to the factory defaults and start from "
|
. "your support material settings to the factory defaults and start from "
|
||||||
. "those. Enjoy and provide feedback!", "Support Material");
|
. "those. Enjoy and provide feedback!", "Support Material");
|
||||||
}
|
}
|
||||||
|
if (!defined $last_version || $last_version =~ /^(?:0|1\.[01])\./) {
|
||||||
|
show_info($self->{mainframe}, "Hello! In this version a new Bed Shape option was "
|
||||||
|
. "added. If the bed placement in the plater preview screen looks wrong, go "
|
||||||
|
. "to Print Settings and click the \"Set\" button next to \"Bed Shape\".", "Bed Shape");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$self->{mainframe}->config_wizard if $run_wizard;
|
$self->{mainframe}->config_wizard if $run_wizard;
|
||||||
|
|
||||||
|
|
200
lib/Slic3r/GUI/BedShapeDialog.pm
Normal file
200
lib/Slic3r/GUI/BedShapeDialog.pm
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
package Slic3r::GUI::BedShapeDialog;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use List::Util qw(min max);
|
||||||
|
use Slic3r::Geometry qw(PI X Y unscale);
|
||||||
|
use Wx qw(:dialog :id :misc :sizer :choicebook wxTAB_TRAVERSAL);
|
||||||
|
use Wx::Event qw(EVT_CLOSE EVT_BUTTON EVT_CHOICE);
|
||||||
|
use base 'Wx::Dialog';
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my ($parent, $default) = @_;
|
||||||
|
my $self = $class->SUPER::new($parent, -1, "Bed Shape", wxDefaultPosition, [350,700], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||||
|
|
||||||
|
$self->{panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $default);
|
||||||
|
|
||||||
|
my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
|
$main_sizer->Add($panel, 1, wxEXPAND);
|
||||||
|
$main_sizer->Add($self->CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND);
|
||||||
|
|
||||||
|
$self->SetSizer($main_sizer);
|
||||||
|
$self->SetMinSize($self->GetSize);
|
||||||
|
$main_sizer->SetSizeHints($self);
|
||||||
|
|
||||||
|
# needed to actually free memory
|
||||||
|
EVT_CLOSE($self, sub {
|
||||||
|
$self->EndModal(wxID_OK);
|
||||||
|
$self->Destroy;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GetValue {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->{panel}->GetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
package Slic3r::GUI::BedShapePanel;
|
||||||
|
|
||||||
|
use List::Util qw(min max);
|
||||||
|
use Slic3r::Geometry qw(PI X Y unscale);
|
||||||
|
use Wx qw(:dialog :id :misc :sizer :choicebook wxTAB_TRAVERSAL);
|
||||||
|
use Wx::Event qw(EVT_CLOSE EVT_BUTTON EVT_CHOICE);
|
||||||
|
use base 'Wx::Panel';
|
||||||
|
|
||||||
|
use constant SHAPE_RECTANGULAR => 0;
|
||||||
|
use constant SHAPE_CIRCULAR => 1;
|
||||||
|
use constant SHAPE_CUSTOM => 2;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my ($parent, $default) = @_;
|
||||||
|
my $self = $class->SUPER::new($parent, -1);
|
||||||
|
|
||||||
|
$self->on_change(undef);
|
||||||
|
|
||||||
|
my $box = Wx::StaticBox->new($self, -1, "Shape");
|
||||||
|
my $sbsizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
|
||||||
|
|
||||||
|
# shape options
|
||||||
|
$self->{shape_options_book} = Wx::Choicebook->new($self, -1, wxDefaultPosition, [300,-1], wxCHB_TOP);
|
||||||
|
$sbsizer->Add($self->{shape_options_book});
|
||||||
|
|
||||||
|
$self->{optgroups} = [];
|
||||||
|
$self->_init_shape_options_page('Rectangular', [
|
||||||
|
{
|
||||||
|
opt_key => 'rect_size',
|
||||||
|
type => 'point',
|
||||||
|
label => 'Size',
|
||||||
|
tooltip => 'Size in X and Y of the rectangular plate.',
|
||||||
|
default => [200,200],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
opt_key => 'rect_origin',
|
||||||
|
type => 'select',
|
||||||
|
label => 'Origin',
|
||||||
|
tooltip => 'Position of the 0,0 point.',
|
||||||
|
labels => ['Front left corner','Center'],
|
||||||
|
values => ['corner','center'],
|
||||||
|
default => 'corner',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
# right pane with preview canvas
|
||||||
|
my $canvas;
|
||||||
|
|
||||||
|
# main sizer
|
||||||
|
my $top_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
$top_sizer->Add($sbsizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
||||||
|
$top_sizer->Add($canvas, 1, wxEXPAND | wxALL, 0) if $canvas;
|
||||||
|
|
||||||
|
$self->SetSizerAndFit($top_sizer);
|
||||||
|
|
||||||
|
$self->_set_shape($default);
|
||||||
|
$self->_update_preview;
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub on_change {
|
||||||
|
my ($self, $cb) = @_;
|
||||||
|
$self->{on_change} = $cb // sub {};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _set_shape {
|
||||||
|
my ($self, $points) = @_;
|
||||||
|
|
||||||
|
$self->{bed_shape} = $points;
|
||||||
|
|
||||||
|
# is this a rectangle?
|
||||||
|
if (@$points == 4) {
|
||||||
|
my $polygon = Slic3r::Polygon->new_scale(@$points);
|
||||||
|
my $lines = $polygon->lines;
|
||||||
|
if ($lines->[0]->parallel_to_line($lines->[2]) && $lines->[1]->parallel_to_line($lines->[3])) {
|
||||||
|
# okay, it's a rectangle
|
||||||
|
# let's check whether origin is at a known point
|
||||||
|
my $x_min = min(map $_->[X], @$points);
|
||||||
|
my $x_max = max(map $_->[X], @$points);
|
||||||
|
my $y_min = min(map $_->[Y], @$points);
|
||||||
|
my $y_max = max(map $_->[Y], @$points);
|
||||||
|
my $origin;
|
||||||
|
if ($x_min == 0 && $y_min == 0) {
|
||||||
|
$origin = 'corner';
|
||||||
|
} elsif (($x_min + $x_max)/2 == 0 && ($y_min + $y_max)/2 == 0) {
|
||||||
|
$origin = 'center';
|
||||||
|
}
|
||||||
|
if (defined $origin) {
|
||||||
|
$self->{shape_options_book}->SetSelection(SHAPE_RECTANGULAR);
|
||||||
|
my $optgroup = $self->{optgroups}[SHAPE_RECTANGULAR];
|
||||||
|
$optgroup->set_value('rect_size', [ $x_max-$x_min, $y_max-$y_min ]);
|
||||||
|
$optgroup->set_value('rect_origin', $origin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{shape_options_book}->SetSelection(SHAPE_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _update_shape {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $page_idx = $self->{shape_options_book}->GetSelection;
|
||||||
|
if ($page_idx == SHAPE_RECTANGULAR) {
|
||||||
|
return if grep !defined($self->{"_$_"}), qw(rect_size rect_origin); # not loaded yet
|
||||||
|
my ($x, $y) = @{$self->{_rect_size}};
|
||||||
|
my ($x0, $y0) = (0,0);
|
||||||
|
my ($x1, $y1) = ($x,$y);
|
||||||
|
if ($self->{_rect_origin} eq 'center') {
|
||||||
|
$x0 -= $x/2;
|
||||||
|
$x1 -= $x/2;
|
||||||
|
$y0 -= $y/2;
|
||||||
|
$y1 -= $y/2;
|
||||||
|
}
|
||||||
|
$self->{bed_shape} = [
|
||||||
|
[$x0,$y0],
|
||||||
|
[$x1,$y0],
|
||||||
|
[$x1,$y1],
|
||||||
|
[$x0,$y1],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->{on_change}->();
|
||||||
|
$self->_update_preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _update_preview {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _init_shape_options_page {
|
||||||
|
my ($self, $title, $options) = @_;
|
||||||
|
|
||||||
|
my $panel = Wx::Panel->new($self->{shape_options_book});
|
||||||
|
push @{$self->{optgroups}}, my $optgroup = Slic3r::GUI::OptionsGroup->new(
|
||||||
|
parent => $panel,
|
||||||
|
title => 'Settings',
|
||||||
|
options => $options,
|
||||||
|
on_change => sub {
|
||||||
|
my ($opt_key, $value) = @_;
|
||||||
|
$self->{"_$opt_key"} = $value;
|
||||||
|
$self->_update_shape;
|
||||||
|
},
|
||||||
|
label_width => 100,
|
||||||
|
);
|
||||||
|
$panel->SetSizerAndFit($optgroup->sizer);
|
||||||
|
$self->{shape_options_book}->AddPage($panel, $title);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GetValue {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->{bed_shape};
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
|
@ -5,6 +5,7 @@ use utf8;
|
||||||
|
|
||||||
use Wx;
|
use Wx;
|
||||||
use base 'Wx::Wizard';
|
use base 'Wx::Wizard';
|
||||||
|
use Slic3r::Geometry qw(unscale);
|
||||||
|
|
||||||
# adhere to various human interface guidelines
|
# adhere to various human interface guidelines
|
||||||
our $wizard = 'Wizard';
|
our $wizard = 'Wizard';
|
||||||
|
@ -52,9 +53,13 @@ sub run {
|
||||||
# it would be cleaner to have these defined inside each page class,
|
# it would be cleaner to have these defined inside each page class,
|
||||||
# in some event getting called before leaving the page
|
# in some event getting called before leaving the page
|
||||||
{
|
{
|
||||||
# set print_center to centre of bed_size
|
# set print_center to center of bed_shape
|
||||||
my $bed_size = $self->{config}->bed_size;
|
{
|
||||||
$self->{config}->set('print_center', [$bed_size->[0]/2, $bed_size->[1]/2]);
|
my $bed_shape = $self->{config}->bed_shape;
|
||||||
|
my $polygon = Slic3r::Polygon->new_scale(@$bed_shape);
|
||||||
|
my $center = $polygon->centroid;
|
||||||
|
$self->{config}->set('print_center', [ map unscale($_), @$center ]);
|
||||||
|
}
|
||||||
|
|
||||||
# set first_layer_height + layer_height based on nozzle_diameter
|
# set first_layer_height + layer_height based on nozzle_diameter
|
||||||
my $nozzle = $self->{config}->nozzle_diameter;
|
my $nozzle = $self->{config}->nozzle_diameter;
|
||||||
|
@ -204,19 +209,24 @@ sub append_option {
|
||||||
# populate repository with the factory default
|
# populate repository with the factory default
|
||||||
my $opt_key = $full_key;
|
my $opt_key = $full_key;
|
||||||
$opt_key =~ s/#.+//;
|
$opt_key =~ s/#.+//;
|
||||||
$self->GetParent->{config}->apply(Slic3r::Config->new_from_defaults($opt_key));
|
$self->config->apply(Slic3r::Config->new_from_defaults($opt_key));
|
||||||
|
|
||||||
# draw the control
|
# draw the control
|
||||||
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
|
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
|
||||||
parent => $self,
|
parent => $self,
|
||||||
title => '',
|
title => '',
|
||||||
config => $self->GetParent->{config},
|
config => $self->config,
|
||||||
options => [$full_key],
|
options => [$full_key],
|
||||||
full_labels => 1,
|
full_labels => 1,
|
||||||
);
|
);
|
||||||
$self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
$self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub append_panel {
|
||||||
|
my ($self, $panel) = @_;
|
||||||
|
$self->{vsizer}->Add($panel, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
||||||
|
}
|
||||||
|
|
||||||
sub set_previous_page {
|
sub set_previous_page {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($previous_page) = @_;
|
my ($previous_page) = @_;
|
||||||
|
@ -253,6 +263,11 @@ sub build_index {
|
||||||
$self->{index}->append_title($page->get_short_title) while ($page = $page->GetNext);
|
$self->{index}->append_title($page->get_short_title) while ($page = $page->GetNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub config {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->GetParent->{config};
|
||||||
|
}
|
||||||
|
|
||||||
package Slic3r::GUI::ConfigWizard::Page::Welcome;
|
package Slic3r::GUI::ConfigWizard::Page::Welcome;
|
||||||
use base 'Slic3r::GUI::ConfigWizard::Page';
|
use base 'Slic3r::GUI::ConfigWizard::Page';
|
||||||
|
|
||||||
|
@ -290,9 +305,14 @@ sub new {
|
||||||
my ($parent) = @_;
|
my ($parent) = @_;
|
||||||
my $self = $class->SUPER::new($parent, 'Bed Size');
|
my $self = $class->SUPER::new($parent, 'Bed Size');
|
||||||
|
|
||||||
$self->append_text('Enter the size of your printers bed, then click Next.');
|
$self->append_text('Set the shape of your printer\'s bed, then click Next.');
|
||||||
$self->append_option('bed_size');
|
|
||||||
|
|
||||||
|
$self->config->apply(Slic3r::Config->new_from_defaults('bed_shape'));
|
||||||
|
$self->{bed_shape_panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $self->config->bed_shape);
|
||||||
|
$self->{bed_shape_panel}->on_change(sub {
|
||||||
|
$self->config->set('bed_shape', $self->{bed_shape_panel}->GetValue);
|
||||||
|
});
|
||||||
|
$self->append_panel($self->{bed_shape_panel});
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +324,7 @@ sub new {
|
||||||
my ($parent) = @_;
|
my ($parent) = @_;
|
||||||
my $self = $class->SUPER::new($parent, 'Nozzle Diameter');
|
my $self = $class->SUPER::new($parent, 'Nozzle Diameter');
|
||||||
|
|
||||||
$self->append_text('Enter the diameter of your printers hot end nozzle, then click Next.');
|
$self->append_text('Enter the diameter of your printer\'s hot end nozzle, then click Next.');
|
||||||
$self->append_option('nozzle_diameter#0');
|
$self->append_option('nozzle_diameter#0');
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
|
|
|
@ -48,6 +48,7 @@ has 'options' => (is => 'ro', required => 1, trigger => 1);
|
||||||
has 'lines' => (is => 'lazy');
|
has 'lines' => (is => 'lazy');
|
||||||
has 'on_change' => (is => 'ro', default => sub { sub {} });
|
has 'on_change' => (is => 'ro', default => sub { sub {} });
|
||||||
has 'no_labels' => (is => 'ro', default => sub { 0 });
|
has 'no_labels' => (is => 'ro', default => sub { 0 });
|
||||||
|
has 'staticbox' => (is => 'ro', default => sub { 1 });
|
||||||
has 'label_width' => (is => 'ro', default => sub { 180 });
|
has 'label_width' => (is => 'ro', default => sub { 180 });
|
||||||
has 'extra_column' => (is => 'ro');
|
has 'extra_column' => (is => 'ro');
|
||||||
has 'label_font' => (is => 'ro');
|
has 'label_font' => (is => 'ro');
|
||||||
|
@ -63,9 +64,11 @@ sub _trigger_options {}
|
||||||
sub BUILD {
|
sub BUILD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
{
|
if ($self->staticbox) {
|
||||||
my $box = Wx::StaticBox->new($self->parent, -1, $self->title);
|
my $box = Wx::StaticBox->new($self->parent, -1, $self->title);
|
||||||
$self->sizer(Wx::StaticBoxSizer->new($box, wxVERTICAL));
|
$self->sizer(Wx::StaticBoxSizer->new($box, wxVERTICAL));
|
||||||
|
} else {
|
||||||
|
$self->sizer(Wx::BoxSizer->new(wxVERTICAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
my $num_columns = $self->extra_column ? 3 : 2;
|
my $num_columns = $self->extra_column ? 3 : 2;
|
||||||
|
@ -77,11 +80,18 @@ sub BUILD {
|
||||||
$self->sizer->Add($grid_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 5);
|
$self->sizer->Add($grid_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 5);
|
||||||
|
|
||||||
foreach my $line (@{$self->lines}) {
|
foreach my $line (@{$self->lines}) {
|
||||||
|
# build default callbacks in case we don't call _build_line() below
|
||||||
|
foreach my $opt_key (@{$line->{options}}) {
|
||||||
|
my $opt = first { $_->{opt_key} eq $opt_key } @{$self->options};
|
||||||
|
$self->_setters->{$opt_key} //= sub {};
|
||||||
|
$self->_triggers->{$opt_key} = $opt->{on_change} || sub { return 1 };
|
||||||
|
}
|
||||||
|
|
||||||
if ($line->{sizer}) {
|
if ($line->{sizer}) {
|
||||||
$self->sizer->Add($line->{sizer}, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
|
$self->sizer->Add($line->{sizer}, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
|
||||||
} elsif ($line->{widget}) {
|
} elsif ($line->{widget} && $line->{full_width}) {
|
||||||
my $window = $line->{widget}->GetWindow($self->parent);
|
my $sizer = $line->{widget}->($self->parent);
|
||||||
$self->sizer->Add($window, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
|
$self->sizer->Add($sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
|
||||||
} else {
|
} else {
|
||||||
$self->_build_line($line, $grid_sizer);
|
$self->_build_line($line, $grid_sizer);
|
||||||
}
|
}
|
||||||
|
@ -140,10 +150,10 @@ sub _build_line {
|
||||||
my @field_labels = ();
|
my @field_labels = ();
|
||||||
foreach my $opt_key (@{$line->{options}}) {
|
foreach my $opt_key (@{$line->{options}}) {
|
||||||
my $opt = first { $_->{opt_key} eq $opt_key } @{$self->options};
|
my $opt = first { $_->{opt_key} eq $opt_key } @{$self->options};
|
||||||
push @fields, $self->_build_field($opt);
|
push @fields, $self->_build_field($opt) unless $line->{widget};
|
||||||
push @field_labels, $opt->{label};
|
push @field_labels, $opt->{label};
|
||||||
}
|
}
|
||||||
if (@fields > 1 || $line->{sidetext}) {
|
if (@fields > 1 || $line->{widget} || $line->{sidetext}) {
|
||||||
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
for my $i (0 .. $#fields) {
|
for my $i (0 .. $#fields) {
|
||||||
if (@fields > 1 && $field_labels[$i]) {
|
if (@fields > 1 && $field_labels[$i]) {
|
||||||
|
@ -153,7 +163,10 @@ sub _build_line {
|
||||||
}
|
}
|
||||||
$sizer->Add($fields[$i], 0, wxALIGN_CENTER_VERTICAL, 0);
|
$sizer->Add($fields[$i], 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||||
}
|
}
|
||||||
if ($line->{sidetext}) {
|
if ($line->{widget}) {
|
||||||
|
my $widget_sizer = $line->{widget}->($self->parent);
|
||||||
|
$sizer->Add($widget_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
|
||||||
|
} elsif ($line->{sidetext}) {
|
||||||
my $sidetext = Wx::StaticText->new($self->parent, -1, $line->{sidetext}, wxDefaultPosition, wxDefaultSize);
|
my $sidetext = Wx::StaticText->new($self->parent, -1, $line->{sidetext}, wxDefaultPosition, wxDefaultSize);
|
||||||
$sidetext->SetFont($self->sidetext_font);
|
$sidetext->SetFont($self->sidetext_font);
|
||||||
$sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4);
|
$sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4);
|
||||||
|
@ -169,7 +182,6 @@ sub _build_field {
|
||||||
my ($opt) = @_;
|
my ($opt) = @_;
|
||||||
|
|
||||||
my $opt_key = $opt->{opt_key};
|
my $opt_key = $opt->{opt_key};
|
||||||
$self->_triggers->{$opt_key} = $opt->{on_change} || sub { return 1 };
|
|
||||||
|
|
||||||
my $on_kill_focus = sub {
|
my $on_kill_focus = sub {
|
||||||
my ($s, $event) = @_;
|
my ($s, $event) = @_;
|
||||||
|
@ -363,6 +375,7 @@ has '+ignore_on_change_return' => (is => 'ro', default => sub { 0 });
|
||||||
sub _trigger_options {
|
sub _trigger_options {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
$self->SUPER::_trigger_options;
|
||||||
@{$self->options} = map {
|
@{$self->options} = map {
|
||||||
my $opt = $_;
|
my $opt = $_;
|
||||||
if (ref $opt ne 'HASH') {
|
if (ref $opt ne 'HASH') {
|
||||||
|
@ -408,10 +421,17 @@ sub set_value {
|
||||||
if ($key eq $opt_key) {
|
if ($key eq $opt_key) {
|
||||||
$self->config->set($key, $value);
|
$self->config->set($key, $value);
|
||||||
$self->SUPER::set_value($full_key, $self->_get_config($key, $index));
|
$self->SUPER::set_value($full_key, $self->_get_config($key, $index));
|
||||||
$changed = 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $changed;
|
|
||||||
|
# if we're here, we know this option but we found no setter, so we just propagate it
|
||||||
|
if ($self->config->has($opt_key)) {
|
||||||
|
$self->config->set($opt_key, $value);
|
||||||
|
$self->SUPER::set_value($opt_key, $value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub on_kill_focus {
|
sub on_kill_focus {
|
||||||
|
@ -479,26 +499,24 @@ sub _config_methods {
|
||||||
}
|
}
|
||||||
|
|
||||||
package Slic3r::GUI::OptionsGroup::StaticTextLine;
|
package Slic3r::GUI::OptionsGroup::StaticTextLine;
|
||||||
use Moo;
|
|
||||||
use Wx qw(:misc :systemsettings);
|
use Wx qw(:misc :systemsettings);
|
||||||
|
use base 'Wx::StaticText';
|
||||||
|
|
||||||
sub GetWindow {
|
sub new {
|
||||||
my $self = shift;
|
my ($class, $parent) = @_;
|
||||||
my ($parent) = @_;
|
|
||||||
|
|
||||||
$self->{statictext} = Wx::StaticText->new($parent, -1, "foo", wxDefaultPosition, wxDefaultSize);
|
my $self = $class->SUPER::new($parent, -1, "", wxDefaultPosition, wxDefaultSize);
|
||||||
my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||||
$self->{statictext}->SetFont($font);
|
$self->SetFont($font);
|
||||||
return $self->{statictext};
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub SetText {
|
sub SetText {
|
||||||
my $self = shift;
|
my ($self, $value) = @_;
|
||||||
my ($value) = @_;
|
|
||||||
|
|
||||||
$self->{statictext}->SetLabel($value);
|
$self->SetLabel($value);
|
||||||
$self->{statictext}->Wrap(400);
|
$self->Wrap(400);
|
||||||
$self->{statictext}->GetParent->Layout;
|
$self->GetParent->Layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -38,7 +38,6 @@ our $ERROR_EVENT : shared = Wx::NewEventType;
|
||||||
our $EXPORT_COMPLETED_EVENT : shared = Wx::NewEventType;
|
our $EXPORT_COMPLETED_EVENT : shared = Wx::NewEventType;
|
||||||
our $PROCESS_COMPLETED_EVENT : shared = Wx::NewEventType;
|
our $PROCESS_COMPLETED_EVENT : shared = Wx::NewEventType;
|
||||||
|
|
||||||
use constant CANVAS_SIZE => [335,335];
|
|
||||||
use constant FILAMENT_CHOOSERS_SPACING => 3;
|
use constant FILAMENT_CHOOSERS_SPACING => 3;
|
||||||
use constant PROCESS_DELAY => 0.5 * 1000; # milliseconds
|
use constant PROCESS_DELAY => 0.5 * 1000; # milliseconds
|
||||||
|
|
||||||
|
@ -51,7 +50,7 @@ sub new {
|
||||||
my ($parent) = @_;
|
my ($parent) = @_;
|
||||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||||
$self->{config} = Slic3r::Config->new_from_defaults(qw(
|
$self->{config} = Slic3r::Config->new_from_defaults(qw(
|
||||||
bed_size print_center complete_objects extruder_clearance_radius skirts skirt_distance
|
bed_shape print_center complete_objects extruder_clearance_radius skirts skirt_distance
|
||||||
));
|
));
|
||||||
$self->{model} = Slic3r::Model->new;
|
$self->{model} = Slic3r::Model->new;
|
||||||
$self->{print} = Slic3r::Print->new;
|
$self->{print} = Slic3r::Print->new;
|
||||||
|
@ -69,7 +68,7 @@ sub new {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$self->{canvas} = Slic3r::GUI::Plater::2D->new($self, CANVAS_SIZE, $self->{objects}, $self->{model}, $self->{config});
|
$self->{canvas} = Slic3r::GUI::Plater::2D->new($self, [335,335], $self->{objects}, $self->{model}, $self->{config});
|
||||||
$self->{canvas}->on_select_object(sub {
|
$self->{canvas}->on_select_object(sub {
|
||||||
my ($obj_idx) = @_;
|
my ($obj_idx) = @_;
|
||||||
$self->select_object($obj_idx);
|
$self->select_object($obj_idx);
|
||||||
|
@ -133,7 +132,7 @@ sub new {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, wxDefaultSize, wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS);
|
$self->{list} = Wx::ListView->new($self, -1, wxDefaultPosition, [250,-1], wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS);
|
||||||
$self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 145);
|
$self->{list}->InsertColumn(0, "Name", wxLIST_FORMAT_LEFT, 145);
|
||||||
$self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 45);
|
$self->{list}->InsertColumn(1, "Copies", wxLIST_FORMAT_CENTER, 45);
|
||||||
$self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
|
$self->{list}->InsertColumn(2, "Scale", wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
|
||||||
|
@ -285,6 +284,7 @@ sub new {
|
||||||
{
|
{
|
||||||
my $box = Wx::StaticBox->new($self, -1, "Info");
|
my $box = Wx::StaticBox->new($self, -1, "Info");
|
||||||
$object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
|
$object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
|
||||||
|
$object_info_sizer->SetMinSize([350,-1]);
|
||||||
my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5);
|
my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5);
|
||||||
$grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
$grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
||||||
$grid_sizer->AddGrowableCol(1, 1);
|
$grid_sizer->AddGrowableCol(1, 1);
|
||||||
|
@ -300,14 +300,14 @@ sub new {
|
||||||
);
|
);
|
||||||
while (my $field = shift @info) {
|
while (my $field = shift @info) {
|
||||||
my $label = shift @info;
|
my $label = shift @info;
|
||||||
my $text = Wx::StaticText->new($self, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
my $text = Wx::StaticText->new($box, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||||
$text->SetFont($Slic3r::GUI::small_font);
|
$text->SetFont($Slic3r::GUI::small_font);
|
||||||
$grid_sizer->Add($text, 0);
|
$grid_sizer->Add($text, 0);
|
||||||
|
|
||||||
$self->{"object_info_$field"} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
$self->{"object_info_$field"} = Wx::StaticText->new($box, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||||
$self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font);
|
$self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font);
|
||||||
if ($field eq 'manifold') {
|
if ($field eq 'manifold') {
|
||||||
$self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new("$Slic3r::var/error.png", wxBITMAP_TYPE_PNG));
|
$self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($box, -1, Wx::Bitmap->new("$Slic3r::var/error.png", wxBITMAP_TYPE_PNG));
|
||||||
$self->{object_info_manifold_warning_icon}->Hide;
|
$self->{object_info_manifold_warning_icon}->Hide;
|
||||||
|
|
||||||
my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
@ -334,8 +334,8 @@ sub new {
|
||||||
$right_sizer->Add($object_info_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
$right_sizer->Add($object_info_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||||
|
|
||||||
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
$hsizer->Add($self->{canvas}, 0, wxTOP, 1);
|
$hsizer->Add($self->{canvas}, 1, wxEXPAND | wxTOP, 1);
|
||||||
$hsizer->Add($right_sizer, 1, wxEXPAND | wxBOTTOM, 0);
|
$hsizer->Add($right_sizer, 0, wxEXPAND | wxBOTTOM, 0);
|
||||||
|
|
||||||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
$sizer->Add($self->{htoolbar}, 0, wxEXPAND, 0) if $self->{htoolbar};
|
$sizer->Add($self->{htoolbar}, 0, wxEXPAND, 0) if $self->{htoolbar};
|
||||||
|
@ -677,12 +677,7 @@ sub changescale {
|
||||||
sub arrange {
|
sub arrange {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
# get the bounding box of the model area shown in the viewport
|
my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($self->{config}->bed_shape);
|
||||||
my $bb = Slic3r::Geometry::BoundingBox->new_from_points([
|
|
||||||
Slic3r::Point->new(@{ $self->{canvas}->point_to_model_units([0,0]) }),
|
|
||||||
Slic3r::Point->new(@{ $self->{canvas}->point_to_model_units(CANVAS_SIZE) }),
|
|
||||||
]);
|
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
$self->{model}->arrange_objects($self->GetFrame->config->min_object_distance, $bb);
|
$self->{model}->arrange_objects($self->GetFrame->config->min_object_distance, $bb);
|
||||||
};
|
};
|
||||||
|
@ -758,7 +753,8 @@ sub split_object {
|
||||||
|
|
||||||
sub schedule_background_process {
|
sub schedule_background_process {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
$self->{apply_config_timer}->Start(PROCESS_DELAY, 1); # 1 = one shot
|
$self->{apply_config_timer}->Start(PROCESS_DELAY, 1) # 1 = one shot
|
||||||
|
if defined $self->{apply_config_timer};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub async_apply_config {
|
sub async_apply_config {
|
||||||
|
@ -841,7 +837,7 @@ sub start_background_process {
|
||||||
sub stop_background_process {
|
sub stop_background_process {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
$self->{apply_config_timer}->Stop;
|
$self->{apply_config_timer}->Stop if defined $self->{apply_config_timer};
|
||||||
$self->statusbar->SetCancelCallback(undef);
|
$self->statusbar->SetCancelCallback(undef);
|
||||||
$self->statusbar->StopBusy;
|
$self->statusbar->StopBusy;
|
||||||
$self->statusbar->SetStatusText("");
|
$self->statusbar->SetStatusText("");
|
||||||
|
@ -1147,7 +1143,7 @@ sub on_config_change {
|
||||||
$self->Layout;
|
$self->Layout;
|
||||||
} elsif ($self->{config}->has($opt_key)) {
|
} elsif ($self->{config}->has($opt_key)) {
|
||||||
$self->{config}->set($opt_key, $value);
|
$self->{config}->set($opt_key, $value);
|
||||||
if ($opt_key eq 'bed_size') {
|
if ($opt_key eq 'bed_shape') {
|
||||||
$self->{canvas}->update_bed_size;
|
$self->{canvas}->update_bed_size;
|
||||||
$self->update;
|
$self->update;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use utf8;
|
use utf8;
|
||||||
|
|
||||||
use List::Util qw(max first);
|
use List::Util qw(min max first);
|
||||||
use Slic3r::Geometry qw(X Y scale unscale convex_hull);
|
use Slic3r::Geometry qw(X Y scale unscale convex_hull);
|
||||||
use Slic3r::Geometry::Clipper qw(offset JT_ROUND);
|
use Slic3r::Geometry::Clipper qw(offset JT_ROUND);
|
||||||
use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL);
|
use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL);
|
||||||
use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT);
|
use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT EVT_SIZE);
|
||||||
use base 'Wx::Panel';
|
use base 'Wx::Panel';
|
||||||
|
|
||||||
use constant CANVAS_TEXT => join('-', +(localtime)[3,4]) eq '13-8'
|
use constant CANVAS_TEXT => join('-', +(localtime)[3,4]) eq '13-8'
|
||||||
|
@ -40,6 +40,9 @@ sub new {
|
||||||
|
|
||||||
EVT_PAINT($self, \&repaint);
|
EVT_PAINT($self, \&repaint);
|
||||||
EVT_MOUSE_EVENTS($self, \&mouse_event);
|
EVT_MOUSE_EVENTS($self, \&mouse_event);
|
||||||
|
EVT_SIZE($self, sub {
|
||||||
|
$self->update_bed_size;
|
||||||
|
});
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
@ -71,25 +74,27 @@ sub repaint {
|
||||||
my $size = $self->GetSize;
|
my $size = $self->GetSize;
|
||||||
my @size = ($size->GetWidth, $size->GetHeight);
|
my @size = ($size->GetWidth, $size->GetHeight);
|
||||||
|
|
||||||
# draw grid
|
# draw bed
|
||||||
$dc->SetPen($self->{grid_pen});
|
{
|
||||||
my $step = 10 * $self->{scaling_factor};
|
$dc->SetPen($self->{print_center_pen});
|
||||||
for (my $x = $step; $x <= $size[X]; $x += $step) {
|
$dc->SetBrush($self->{transparent_brush});
|
||||||
$dc->DrawLine($x, 0, $x, $size[Y]);
|
$dc->DrawPolygon($self->scaled_points_to_pixel($self->{bed_polygon}, 1), 0, 0);
|
||||||
}
|
|
||||||
for (my $y = $step; $y <= $size[Y]; $y += $step) {
|
|
||||||
$dc->DrawLine(0, $y, $size[X], $y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# draw grid
|
||||||
|
$dc->SetPen($self->{grid_pen});
|
||||||
|
$dc->DrawLine(map @$_, @$_) for @{$self->{grid}};
|
||||||
|
|
||||||
# draw print center
|
# draw print center
|
||||||
if (@{$self->{objects}}) {
|
if (@{$self->{objects}} && $Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||||
|
my $center = $self->unscaled_point_to_pixel($self->{config}->print_center);
|
||||||
$dc->SetPen($self->{print_center_pen});
|
$dc->SetPen($self->{print_center_pen});
|
||||||
$dc->DrawLine($size[X]/2, 0, $size[X]/2, $size[Y]);
|
$dc->DrawLine($center->[X], 0, $center->[X], $size[Y]);
|
||||||
$dc->DrawLine(0, $size[Y]/2, $size[X], $size[Y]/2);
|
$dc->DrawLine(0, $center->[Y], $size[X], $center->[Y]);
|
||||||
$dc->SetTextForeground(Wx::Colour->new(0,0,0));
|
$dc->SetTextForeground(Wx::Colour->new(0,0,0));
|
||||||
$dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL));
|
$dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL));
|
||||||
$dc->DrawLabel("X = " . $self->{config}->print_center->[X], Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
|
$dc->DrawLabel("X = " . $self->{config}->print_center->[X], Wx::Rect->new(0, 0, $center->[X]*2, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
|
||||||
$dc->DrawRotatedText("Y = " . $self->{config}->print_center->[Y], 0, $size[Y]/2+15, 90);
|
$dc->DrawRotatedText("Y = " . $self->{config}->print_center->[Y], 0, $center->[Y]+15, 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
# draw frame
|
# draw frame
|
||||||
|
@ -131,7 +136,7 @@ sub repaint {
|
||||||
}
|
}
|
||||||
foreach my $expolygon (@$thumbnail) {
|
foreach my $expolygon (@$thumbnail) {
|
||||||
foreach my $points (@{$expolygon->pp}) {
|
foreach my $points (@{$expolygon->pp}) {
|
||||||
$dc->DrawPolygon($self->points_to_pixel($points, 1), 0, 0);
|
$dc->DrawPolygon($self->scaled_points_to_pixel($points, 1), 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +156,7 @@ sub repaint {
|
||||||
my ($clearance) = @{offset([$thumbnail->convex_hull], (scale($self->{config}->extruder_clearance_radius) / 2), 1, JT_ROUND, scale(0.1))};
|
my ($clearance) = @{offset([$thumbnail->convex_hull], (scale($self->{config}->extruder_clearance_radius) / 2), 1, JT_ROUND, scale(0.1))};
|
||||||
$dc->SetPen($self->{clearance_pen});
|
$dc->SetPen($self->{clearance_pen});
|
||||||
$dc->SetBrush($self->{transparent_brush});
|
$dc->SetBrush($self->{transparent_brush});
|
||||||
$dc->DrawPolygon($self->points_to_pixel($clearance, 1), 0, 0);
|
$dc->DrawPolygon($self->scaled_points_to_pixel($clearance, 1), 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +168,7 @@ sub repaint {
|
||||||
my ($convex_hull) = @{offset([convex_hull(\@points)], scale($self->{config}->skirt_distance), 1, JT_ROUND, scale(0.1))};
|
my ($convex_hull) = @{offset([convex_hull(\@points)], scale($self->{config}->skirt_distance), 1, JT_ROUND, scale(0.1))};
|
||||||
$dc->SetPen($self->{skirt_pen});
|
$dc->SetPen($self->{skirt_pen});
|
||||||
$dc->SetBrush($self->{transparent_brush});
|
$dc->SetBrush($self->{transparent_brush});
|
||||||
$dc->DrawPolygon($self->points_to_pixel($convex_hull, 1), 0, 0);
|
$dc->DrawPolygon($self->scaled_points_to_pixel($convex_hull, 1), 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,16 +178,15 @@ sub repaint {
|
||||||
sub mouse_event {
|
sub mouse_event {
|
||||||
my ($self, $event) = @_;
|
my ($self, $event) = @_;
|
||||||
|
|
||||||
my $point = $event->GetPosition;
|
my $pos = $event->GetPosition;
|
||||||
my $pos = $self->point_to_model_units([ $point->x, $point->y ]); #]]
|
my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]]
|
||||||
$pos = Slic3r::Point->new_scale(@$pos);
|
|
||||||
if ($event->ButtonDown) {
|
if ($event->ButtonDown) {
|
||||||
$self->{on_select_object}->(undef);
|
$self->{on_select_object}->(undef);
|
||||||
OBJECTS: for my $obj_idx (0 .. $#{$self->{objects}}) {
|
OBJECTS: for my $obj_idx (0 .. $#{$self->{objects}}) {
|
||||||
my $object = $self->{objects}->[$obj_idx];
|
my $object = $self->{objects}->[$obj_idx];
|
||||||
for my $instance_idx (0 .. $#{ $object->instance_thumbnails }) {
|
for my $instance_idx (0 .. $#{ $object->instance_thumbnails }) {
|
||||||
my $thumbnail = $object->instance_thumbnails->[$instance_idx];
|
my $thumbnail = $object->instance_thumbnails->[$instance_idx];
|
||||||
if (defined first { $_->contour->contains_point($pos) } @$thumbnail) {
|
if (defined first { $_->contour->contains_point($point) } @$thumbnail) {
|
||||||
$self->{on_select_object}->($obj_idx);
|
$self->{on_select_object}->($obj_idx);
|
||||||
|
|
||||||
if ($event->LeftDown) {
|
if ($event->LeftDown) {
|
||||||
|
@ -190,12 +194,12 @@ sub mouse_event {
|
||||||
my $instance = $self->{model}->objects->[$obj_idx]->instances->[$instance_idx];
|
my $instance = $self->{model}->objects->[$obj_idx]->instances->[$instance_idx];
|
||||||
my $instance_origin = [ map scale($_), @{$instance->offset} ];
|
my $instance_origin = [ map scale($_), @{$instance->offset} ];
|
||||||
$self->{drag_start_pos} = [ # displacement between the click and the instance origin in scaled model units
|
$self->{drag_start_pos} = [ # displacement between the click and the instance origin in scaled model units
|
||||||
$pos->x - $instance_origin->[X],
|
$point->x - $instance_origin->[X],
|
||||||
$pos->y - $instance_origin->[Y], #-
|
$point->y - $instance_origin->[Y], #-
|
||||||
];
|
];
|
||||||
$self->{drag_object} = [ $obj_idx, $instance_idx ];
|
$self->{drag_object} = [ $obj_idx, $instance_idx ];
|
||||||
} elsif ($event->RightDown) {
|
} elsif ($event->RightDown) {
|
||||||
$self->{on_right_click}->($point);
|
$self->{on_right_click}->($pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
last OBJECTS;
|
last OBJECTS;
|
||||||
|
@ -217,14 +221,14 @@ sub mouse_event {
|
||||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||||
$model_object->instances->[$instance_idx]->set_offset(
|
$model_object->instances->[$instance_idx]->set_offset(
|
||||||
Slic3r::Pointf->new(
|
Slic3r::Pointf->new(
|
||||||
unscale($pos->[X] - $self->{drag_start_pos}[X]),
|
unscale($point->[X] - $self->{drag_start_pos}[X]),
|
||||||
unscale($pos->[Y] - $self->{drag_start_pos}[Y]),
|
unscale($point->[Y] - $self->{drag_start_pos}[Y]),
|
||||||
));
|
));
|
||||||
$model_object->update_bounding_box;
|
$model_object->update_bounding_box;
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
} elsif ($event->Moving) {
|
} elsif ($event->Moving) {
|
||||||
my $cursor = wxSTANDARD_CURSOR;
|
my $cursor = wxSTANDARD_CURSOR;
|
||||||
if (defined first { $_->contour->contains_point($pos) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) {
|
if (defined first { $_->contour->contains_point($point) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) {
|
||||||
$cursor = Wx::Cursor->new(wxCURSOR_HAND);
|
$cursor = Wx::Cursor->new(wxCURSOR_HAND);
|
||||||
}
|
}
|
||||||
$self->SetCursor($cursor);
|
$self->SetCursor($cursor);
|
||||||
|
@ -234,13 +238,37 @@ sub mouse_event {
|
||||||
sub update_bed_size {
|
sub update_bed_size {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
# supposing the preview canvas is square, calculate the scaling factor
|
|
||||||
# to constrain print bed area inside preview
|
|
||||||
# when the canvas is not rendered yet, its GetSize() method returns 0,0
|
# when the canvas is not rendered yet, its GetSize() method returns 0,0
|
||||||
|
my $canvas_size = $self->GetSize;
|
||||||
|
my ($canvas_w, $canvas_h) = ($canvas_size->GetWidth, $canvas_size->GetHeight);
|
||||||
|
return if $canvas_w == 0;
|
||||||
|
|
||||||
|
# get bed shape polygon
|
||||||
|
$self->{bed_polygon} = my $polygon = Slic3r::Polygon->new_scale(@{$self->{config}->bed_shape});
|
||||||
|
my $bb = $polygon->bounding_box;
|
||||||
|
my $size = $bb->size;
|
||||||
|
|
||||||
|
# calculate the scaling factor needed for constraining print bed area inside preview
|
||||||
# scaling_factor is expressed in pixel / mm
|
# scaling_factor is expressed in pixel / mm
|
||||||
my $width = $self->GetSize->GetWidth;
|
$self->{scaling_factor} = min($canvas_w / unscale($size->x), $canvas_h / unscale($size->y)); #)
|
||||||
$self->{scaling_factor} = $width / max(@{ $self->{config}->bed_size })
|
|
||||||
if $width != 0;
|
# calculate the displacement needed to center bed
|
||||||
|
$self->{bed_origin} = [
|
||||||
|
$self->GetSize->GetWidth/2 - (unscale($bb->x_max + $bb->x_min)/2 * $self->{scaling_factor}),
|
||||||
|
$canvas_h - ($self->GetSize->GetHeight/2 - (unscale($bb->y_max + $bb->y_min)/2 * $self->{scaling_factor})),
|
||||||
|
];
|
||||||
|
|
||||||
|
# cache bed contours and grid
|
||||||
|
{
|
||||||
|
my $step = scale 10; # 1cm grid
|
||||||
|
$self->{grid} = my $grid = []; # arrayref of lines
|
||||||
|
for (my $x = $bb->x_min + $step; $x < $bb->x_max; $x += $step) {
|
||||||
|
push @$grid, $self->scaled_points_to_pixel([[$x, $bb->y_min], [$x, $bb->y_max]], 1);
|
||||||
|
}
|
||||||
|
for (my $y = $bb->y_min + $step; $y < $bb->y_max; $y += $step) {
|
||||||
|
push @$grid, $self->scaled_points_to_pixel([[$bb->x_min, $y], [$bb->x_max, $y]], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub clean_instance_thumbnails {
|
sub clean_instance_thumbnails {
|
||||||
|
@ -251,35 +279,25 @@ sub clean_instance_thumbnails {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# coordinates of the model origin (0,0) in pixels
|
# convert a model coordinate into a pixel coordinate
|
||||||
sub model_origin_to_pixel {
|
sub unscaled_point_to_pixel {
|
||||||
my ($self) = @_;
|
|
||||||
|
|
||||||
return [
|
|
||||||
$self->GetSize->GetWidth/2 - ($self->{config}->print_center->[X] * $self->{scaling_factor}),
|
|
||||||
$self->GetSize->GetHeight/2 - ($self->{config}->print_center->[Y] * $self->{scaling_factor}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
# convert a model coordinate into a pixel coordinate, assuming preview has square shape
|
|
||||||
sub point_to_pixel {
|
|
||||||
my ($self, $point) = @_;
|
my ($self, $point) = @_;
|
||||||
|
|
||||||
my $canvas_height = $self->GetSize->GetHeight;
|
my $canvas_height = $self->GetSize->GetHeight;
|
||||||
my $zero = $self->model_origin_to_pixel;
|
my $zero = $self->{bed_origin};
|
||||||
return [
|
return [
|
||||||
$point->[X] * $self->{scaling_factor} + $zero->[X],
|
$point->[X] * $self->{scaling_factor} + $zero->[X],
|
||||||
$canvas_height - ($point->[Y] * $self->{scaling_factor} + $zero->[Y]),
|
$canvas_height - $point->[Y] * $self->{scaling_factor} + ($zero->[Y] - $canvas_height),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub points_to_pixel {
|
sub scaled_points_to_pixel {
|
||||||
my ($self, $points, $unscale) = @_;
|
my ($self, $points, $unscale) = @_;
|
||||||
|
|
||||||
my $result = [];
|
my $result = [];
|
||||||
foreach my $point (@$points) {
|
foreach my $point (@$points) {
|
||||||
$point = [ map unscale($_), @$point ] if $unscale;
|
$point = [ map unscale($_), @$point ] if $unscale;
|
||||||
push @$result, $self->point_to_pixel($point);
|
push @$result, $self->unscaled_point_to_pixel($point);
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
@ -287,12 +305,11 @@ sub points_to_pixel {
|
||||||
sub point_to_model_units {
|
sub point_to_model_units {
|
||||||
my ($self, $point) = @_;
|
my ($self, $point) = @_;
|
||||||
|
|
||||||
my $canvas_height = $self->GetSize->GetHeight;
|
my $zero = $self->{bed_origin};
|
||||||
my $zero = $self->model_origin_to_pixel;
|
return Slic3r::Point->new(
|
||||||
return [
|
scale ($point->[X] - $zero->[X]) / $self->{scaling_factor},
|
||||||
($point->[X] - $zero->[X]) / $self->{scaling_factor},
|
scale ($zero->[Y] - $point->[Y]) / $self->{scaling_factor},
|
||||||
(($canvas_height - $point->[Y] - $zero->[Y]) / $self->{scaling_factor}),
|
);
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -599,7 +599,11 @@ sub build {
|
||||||
Slic3r::GUI::OptionsGroup->single_option_line('cooling'),
|
Slic3r::GUI::OptionsGroup->single_option_line('cooling'),
|
||||||
{
|
{
|
||||||
label => '',
|
label => '',
|
||||||
widget => ($self->{description_line} = Slic3r::GUI::OptionsGroup::StaticTextLine->new),
|
full_width => 1,
|
||||||
|
widget => sub {
|
||||||
|
my ($parent) = @_;
|
||||||
|
return $self->{description_line} = Slic3r::GUI::OptionsGroup::StaticTextLine->new($parent);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -662,6 +666,8 @@ sub on_value_change {
|
||||||
|
|
||||||
package Slic3r::GUI::Tab::Printer;
|
package Slic3r::GUI::Tab::Printer;
|
||||||
use base 'Slic3r::GUI::Tab';
|
use base 'Slic3r::GUI::Tab';
|
||||||
|
use Wx qw(:sizer :button :bitmap :misc :id);
|
||||||
|
use Wx::Event qw(EVT_BUTTON);
|
||||||
|
|
||||||
sub name { 'printer' }
|
sub name { 'printer' }
|
||||||
sub title { 'Printer Settings' }
|
sub title { 'Printer Settings' }
|
||||||
|
@ -671,10 +677,43 @@ sub build {
|
||||||
|
|
||||||
$self->{extruders_count} = 1;
|
$self->{extruders_count} = 1;
|
||||||
|
|
||||||
|
my $bed_shape_widget = sub {
|
||||||
|
my ($parent) = @_;
|
||||||
|
|
||||||
|
my $btn = Wx::Button->new($parent, -1, "Set…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||||
|
$btn->SetFont($Slic3r::GUI::small_font);
|
||||||
|
if ($Slic3r::GUI::have_button_icons) {
|
||||||
|
$btn->SetBitmap(Wx::Bitmap->new("$Slic3r::var/cog.png", wxBITMAP_TYPE_PNG));
|
||||||
|
}
|
||||||
|
|
||||||
|
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
$sizer->Add($btn);
|
||||||
|
|
||||||
|
EVT_BUTTON($self, $btn, sub {
|
||||||
|
my $dlg = Slic3r::GUI::BedShapeDialog->new($self, $self->{config}->bed_shape);
|
||||||
|
if ($dlg->ShowModal == wxID_OK) {
|
||||||
|
my $value = $dlg->GetValue;
|
||||||
|
$self->{config}->set('bed_shape', $value);
|
||||||
|
$self->on_value_change('bed_shape', $value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return $sizer;
|
||||||
|
};
|
||||||
|
|
||||||
$self->add_options_page('General', 'printer_empty.png', optgroups => [
|
$self->add_options_page('General', 'printer_empty.png', optgroups => [
|
||||||
{
|
{
|
||||||
title => 'Size and coordinates',
|
title => 'Size and coordinates',
|
||||||
options => [qw(bed_size print_center z_offset)],
|
options => [qw(bed_shape print_center z_offset)],
|
||||||
|
lines => [
|
||||||
|
{
|
||||||
|
label => 'Bed shape',
|
||||||
|
widget => $bed_shape_widget,
|
||||||
|
options => ['bed_shape'],
|
||||||
|
},
|
||||||
|
Slic3r::GUI::OptionsGroup->single_option_line('print_center'),
|
||||||
|
Slic3r::GUI::OptionsGroup->single_option_line('z_offset'),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title => 'Firmware',
|
title => 'Firmware',
|
||||||
|
|
|
@ -146,6 +146,7 @@ sub duplicate {
|
||||||
sub _arrange {
|
sub _arrange {
|
||||||
my ($self, $sizes, $distance, $bb) = @_;
|
my ($self, $sizes, $distance, $bb) = @_;
|
||||||
|
|
||||||
|
# we supply unscaled data to arrange()
|
||||||
return Slic3r::Geometry::arrange(
|
return Slic3r::Geometry::arrange(
|
||||||
scalar(@$sizes), # number of parts
|
scalar(@$sizes), # number of parts
|
||||||
max(map $_->x, @$sizes), # cell width
|
max(map $_->x, @$sizes), # cell width
|
||||||
|
|
|
@ -18,6 +18,7 @@ BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &poin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 <class PointClass>
|
template <class PointClass>
|
||||||
BoundingBox3Base<PointClass>::BoundingBox3Base(const std::vector<PointClass> &points)
|
BoundingBox3Base<PointClass>::BoundingBox3Base(const std::vector<PointClass> &points)
|
||||||
|
@ -65,6 +66,7 @@ BoundingBoxBase<PointClass>::scale(double factor)
|
||||||
this->max.scale(factor);
|
this->max.scale(factor);
|
||||||
}
|
}
|
||||||
template void BoundingBoxBase<Point>::scale(double factor);
|
template void BoundingBoxBase<Point>::scale(double factor);
|
||||||
|
template void BoundingBoxBase<Pointf>::scale(double factor);
|
||||||
template void BoundingBoxBase<Pointf3>::scale(double factor);
|
template void BoundingBoxBase<Pointf3>::scale(double factor);
|
||||||
|
|
||||||
template <class PointClass> void
|
template <class PointClass> void
|
||||||
|
@ -76,6 +78,7 @@ BoundingBoxBase<PointClass>::merge(const PointClass &point)
|
||||||
this->max.y = std::max(point.y, this->max.y);
|
this->max.y = std::max(point.y, this->max.y);
|
||||||
}
|
}
|
||||||
template void BoundingBoxBase<Point>::merge(const Point &point);
|
template void BoundingBoxBase<Point>::merge(const Point &point);
|
||||||
|
template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
|
||||||
|
|
||||||
template <class PointClass> void
|
template <class PointClass> void
|
||||||
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
||||||
|
@ -86,6 +89,7 @@ BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
||||||
this->max.y = std::max(bb.max.y, this->max.y);
|
this->max.y = std::max(bb.max.y, this->max.y);
|
||||||
}
|
}
|
||||||
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
|
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
|
||||||
|
template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
|
||||||
|
|
||||||
template <class PointClass> void
|
template <class PointClass> void
|
||||||
BoundingBox3Base<PointClass>::merge(const PointClass &point)
|
BoundingBox3Base<PointClass>::merge(const PointClass &point)
|
||||||
|
@ -111,6 +115,7 @@ BoundingBoxBase<PointClass>::size() const
|
||||||
return PointClass(this->max.x - this->min.x, this->max.y - this->min.y);
|
return PointClass(this->max.x - this->min.x, this->max.y - this->min.y);
|
||||||
}
|
}
|
||||||
template Point BoundingBoxBase<Point>::size() const;
|
template Point BoundingBoxBase<Point>::size() const;
|
||||||
|
template Pointf BoundingBoxBase<Pointf>::size() const;
|
||||||
|
|
||||||
template <class PointClass> PointClass
|
template <class PointClass> PointClass
|
||||||
BoundingBox3Base<PointClass>::size() const
|
BoundingBox3Base<PointClass>::size() const
|
||||||
|
@ -126,6 +131,7 @@ BoundingBoxBase<PointClass>::translate(coordf_t x, coordf_t y)
|
||||||
this->max.translate(x, y);
|
this->max.translate(x, y);
|
||||||
}
|
}
|
||||||
template void BoundingBoxBase<Point>::translate(coordf_t x, coordf_t y);
|
template void BoundingBoxBase<Point>::translate(coordf_t x, coordf_t y);
|
||||||
|
template void BoundingBoxBase<Pointf>::translate(coordf_t x, coordf_t y);
|
||||||
|
|
||||||
template <class PointClass> void
|
template <class PointClass> void
|
||||||
BoundingBox3Base<PointClass>::translate(coordf_t x, coordf_t y, coordf_t z)
|
BoundingBox3Base<PointClass>::translate(coordf_t x, coordf_t y, coordf_t z)
|
||||||
|
@ -144,6 +150,7 @@ BoundingBoxBase<PointClass>::center() const
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
template Point BoundingBoxBase<Point>::center() const;
|
template Point BoundingBoxBase<Point>::center() const;
|
||||||
|
template Pointf BoundingBoxBase<Pointf>::center() const;
|
||||||
|
|
||||||
template <class PointClass> PointClass
|
template <class PointClass> PointClass
|
||||||
BoundingBox3Base<PointClass>::center() const
|
BoundingBox3Base<PointClass>::center() const
|
||||||
|
|
|
@ -53,10 +53,15 @@ class BoundingBox : public BoundingBoxBase<Point>
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
class BoundingBoxf : public BoundingBoxBase<Pointf> {};
|
|
||||||
class BoundingBox3 : public BoundingBox3Base<Point3> {};
|
class BoundingBox3 : public BoundingBox3Base<Point3> {};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class BoundingBoxf : public BoundingBoxBase<Pointf> {
|
||||||
|
public:
|
||||||
|
BoundingBoxf() {};
|
||||||
|
BoundingBoxf(const std::vector<Pointf> &points) : BoundingBoxBase<Pointf>(points) {};
|
||||||
|
};
|
||||||
|
|
||||||
class BoundingBoxf3 : public BoundingBox3Base<Pointf3> {
|
class BoundingBoxf3 : public BoundingBox3Base<Pointf3> {
|
||||||
public:
|
public:
|
||||||
BoundingBoxf3() {};
|
BoundingBoxf3() {};
|
||||||
|
|
|
@ -293,6 +293,18 @@ Pointf::from_SV(SV* point_sv)
|
||||||
this->y = SvNV(sv_y);
|
this->y = SvNV(sv_y);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pointf::from_SV_check(SV* point_sv)
|
||||||
|
{
|
||||||
|
if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
|
||||||
|
if (!sv_isa(point_sv, perl_class_name(this)) && !sv_isa(point_sv, perl_class_name_ref(this)))
|
||||||
|
CONFESS("Not a valid %s object (got %s)", perl_class_name(this), HvNAME(SvSTASH(SvRV(point_sv))));
|
||||||
|
*this = *(Pointf*)SvIV((SV*)SvRV( point_sv ));
|
||||||
|
} else {
|
||||||
|
this->from_SV(point_sv);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -74,6 +74,7 @@ class Pointf
|
||||||
|
|
||||||
#ifdef SLIC3RXS
|
#ifdef SLIC3RXS
|
||||||
bool from_SV(SV* point_sv);
|
bool from_SV(SV* point_sv);
|
||||||
|
void from_SV_check(SV* point_sv);
|
||||||
SV* to_SV_pureperl() const;
|
SV* to_SV_pureperl() const;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -427,7 +427,7 @@ Print::invalidate_state_by_config_options(const std::vector<t_config_option_key>
|
||||||
} else if (*opt_key == "nozzle_diameter") {
|
} else if (*opt_key == "nozzle_diameter") {
|
||||||
steps.insert(psInitExtruders);
|
steps.insert(psInitExtruders);
|
||||||
} else if (*opt_key == "avoid_crossing_perimeters"
|
} else if (*opt_key == "avoid_crossing_perimeters"
|
||||||
|| *opt_key == "bed_size"
|
|| *opt_key == "bed_shape"
|
||||||
|| *opt_key == "bed_temperature"
|
|| *opt_key == "bed_temperature"
|
||||||
|| *opt_key == "bridge_acceleration"
|
|| *opt_key == "bridge_acceleration"
|
||||||
|| *opt_key == "bridge_fan_speed"
|
|| *opt_key == "bridge_fan_speed"
|
||||||
|
|
|
@ -11,11 +11,8 @@ PrintConfigDef::build_def() {
|
||||||
Options["avoid_crossing_perimeters"].tooltip = "Optimize travel moves in order to minimize the crossing of perimeters. This is mostly useful with Bowden extruders which suffer from oozing. This feature slows down both the print and the G-code generation.";
|
Options["avoid_crossing_perimeters"].tooltip = "Optimize travel moves in order to minimize the crossing of perimeters. This is mostly useful with Bowden extruders which suffer from oozing. This feature slows down both the print and the G-code generation.";
|
||||||
Options["avoid_crossing_perimeters"].cli = "avoid-crossing-perimeters!";
|
Options["avoid_crossing_perimeters"].cli = "avoid-crossing-perimeters!";
|
||||||
|
|
||||||
Options["bed_size"].type = coPoint;
|
Options["bed_shape"].type = coPoints;
|
||||||
Options["bed_size"].label = "Bed size";
|
Options["bed_shape"].label = "Bed shape";
|
||||||
Options["bed_size"].tooltip = "Size of your bed. This is used to adjust the preview in the plater and for auto-arranging parts in it.";
|
|
||||||
Options["bed_size"].sidetext = "mm";
|
|
||||||
Options["bed_size"].cli = "bed-size=s";
|
|
||||||
|
|
||||||
Options["bed_temperature"].type = coInt;
|
Options["bed_temperature"].type = coInt;
|
||||||
Options["bed_temperature"].label = "Other layers";
|
Options["bed_temperature"].label = "Other layers";
|
||||||
|
|
|
@ -307,7 +307,7 @@ class PrintConfig : public virtual StaticPrintConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConfigOptionBool avoid_crossing_perimeters;
|
ConfigOptionBool avoid_crossing_perimeters;
|
||||||
ConfigOptionPoint bed_size;
|
ConfigOptionPoints bed_shape;
|
||||||
ConfigOptionInt bed_temperature;
|
ConfigOptionInt bed_temperature;
|
||||||
ConfigOptionFloat bridge_acceleration;
|
ConfigOptionFloat bridge_acceleration;
|
||||||
ConfigOptionInt bridge_fan_speed;
|
ConfigOptionInt bridge_fan_speed;
|
||||||
|
@ -378,7 +378,10 @@ class PrintConfig : public virtual StaticPrintConfig
|
||||||
|
|
||||||
PrintConfig() : StaticPrintConfig() {
|
PrintConfig() : StaticPrintConfig() {
|
||||||
this->avoid_crossing_perimeters.value = false;
|
this->avoid_crossing_perimeters.value = false;
|
||||||
this->bed_size.point = Pointf(200,200);
|
this->bed_shape.values.push_back(Pointf(0,0));
|
||||||
|
this->bed_shape.values.push_back(Pointf(200,0));
|
||||||
|
this->bed_shape.values.push_back(Pointf(200,200));
|
||||||
|
this->bed_shape.values.push_back(Pointf(0,200));
|
||||||
this->bed_temperature.value = 0;
|
this->bed_temperature.value = 0;
|
||||||
this->bridge_acceleration.value = 0;
|
this->bridge_acceleration.value = 0;
|
||||||
this->bridge_fan_speed.value = 100;
|
this->bridge_fan_speed.value = 100;
|
||||||
|
@ -466,7 +469,7 @@ class PrintConfig : public virtual StaticPrintConfig
|
||||||
|
|
||||||
ConfigOption* option(const t_config_option_key opt_key, bool create = false) {
|
ConfigOption* option(const t_config_option_key opt_key, bool create = false) {
|
||||||
if (opt_key == "avoid_crossing_perimeters") return &this->avoid_crossing_perimeters;
|
if (opt_key == "avoid_crossing_perimeters") return &this->avoid_crossing_perimeters;
|
||||||
if (opt_key == "bed_size") return &this->bed_size;
|
if (opt_key == "bed_shape") return &this->bed_shape;
|
||||||
if (opt_key == "bed_temperature") return &this->bed_temperature;
|
if (opt_key == "bed_temperature") return &this->bed_temperature;
|
||||||
if (opt_key == "bridge_acceleration") return &this->bridge_acceleration;
|
if (opt_key == "bridge_acceleration") return &this->bridge_acceleration;
|
||||||
if (opt_key == "bridge_fan_speed") return &this->bridge_fan_speed;
|
if (opt_key == "bridge_fan_speed") return &this->bridge_fan_speed;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use Slic3r::XS;
|
use Slic3r::XS;
|
||||||
use Test::More tests => 34;
|
use Test::More tests => 39;
|
||||||
|
|
||||||
use constant PI => 4 * atan2(1, 1);
|
use constant PI => 4 * atan2(1, 1);
|
||||||
use constant EPSILON => 1E-4;
|
use constant EPSILON => 1E-4;
|
||||||
|
@ -40,10 +40,17 @@ isa_ok $line->[0], 'Slic3r::Point::Ref', 'line point is blessed';
|
||||||
], 'translate';
|
], 'translate';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ok +Slic3r::Line->new([0,0],[200,0])->parallel_to_line(Slic3r::Line->new([200,200],[0,200])), 'parallel_to';
|
||||||
|
}
|
||||||
|
|
||||||
foreach my $base_angle (0, PI/4, PI/2, PI) {
|
foreach my $base_angle (0, PI/4, PI/2, PI) {
|
||||||
my $line = Slic3r::Line->new([0,0], [100,0]);
|
my $line = Slic3r::Line->new([0,0], [100,0]);
|
||||||
$line->rotate($base_angle, [0,0]);
|
$line->rotate($base_angle, [0,0]);
|
||||||
ok $line->parallel_to_line($line->clone), 'line is parallel to self';
|
my $clone = $line->clone;
|
||||||
|
ok $line->parallel_to_line($clone), 'line is parallel to self';
|
||||||
|
$clone->reverse;
|
||||||
|
ok $line->parallel_to_line($clone), 'line is parallel to self + PI';
|
||||||
ok $line->parallel_to($line->direction), 'line is parallel to its direction';
|
ok $line->parallel_to($line->direction), 'line is parallel to its direction';
|
||||||
ok $line->parallel_to($line->direction + PI), 'line is parallel to its direction + PI';
|
ok $line->parallel_to($line->direction + PI), 'line is parallel to its direction + PI';
|
||||||
ok $line->parallel_to($line->direction - PI), 'line is parallel to its direction - PI';
|
ok $line->parallel_to($line->direction - PI), 'line is parallel to its direction - PI';
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
Clone<Point> center();
|
Clone<Point> center();
|
||||||
Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
|
Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
|
||||||
Clone<Point> max_point() %code{% RETVAL = THIS->max; %};
|
Clone<Point> max_point() %code{% RETVAL = THIS->max; %};
|
||||||
double x_min() %code{% RETVAL = THIS->min.x; %};
|
long x_min() %code{% RETVAL = THIS->min.x; %};
|
||||||
double x_max() %code{% RETVAL = THIS->max.x; %};
|
long x_max() %code{% RETVAL = THIS->max.x; %};
|
||||||
double y_min() %code{% RETVAL = THIS->min.y; %};
|
long y_min() %code{% RETVAL = THIS->min.y; %};
|
||||||
double y_max() %code{% RETVAL = THIS->max.y; %};
|
long y_max() %code{% RETVAL = THIS->max.y; %};
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
@ -39,6 +39,37 @@ new_from_points(CLASS, points)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
%name{Slic3r::Geometry::BoundingBoxf} class BoundingBoxf {
|
||||||
|
~BoundingBoxf();
|
||||||
|
Clone<BoundingBoxf> clone()
|
||||||
|
%code{% RETVAL = THIS; %};
|
||||||
|
void merge(BoundingBoxf* bb) %code{% THIS->merge(*bb); %};
|
||||||
|
void merge_point(Pointf* point) %code{% THIS->merge(*point); %};
|
||||||
|
void scale(double factor);
|
||||||
|
void translate(double x, double y);
|
||||||
|
Clone<Pointf> size();
|
||||||
|
Clone<Pointf> center();
|
||||||
|
Clone<Pointf> min_point() %code{% RETVAL = THIS->min; %};
|
||||||
|
Clone<Pointf> max_point() %code{% RETVAL = THIS->max; %};
|
||||||
|
double x_min() %code{% RETVAL = THIS->min.x; %};
|
||||||
|
double x_max() %code{% RETVAL = THIS->max.x; %};
|
||||||
|
double y_min() %code{% RETVAL = THIS->min.y; %};
|
||||||
|
double y_max() %code{% RETVAL = THIS->max.y; %};
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
|
BoundingBoxf*
|
||||||
|
new_from_points(CLASS, points)
|
||||||
|
char* CLASS
|
||||||
|
Pointfs points
|
||||||
|
CODE:
|
||||||
|
RETVAL = new BoundingBoxf(points);
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
%name{Slic3r::Geometry::BoundingBoxf3} class BoundingBoxf3 {
|
%name{Slic3r::Geometry::BoundingBoxf3} class BoundingBoxf3 {
|
||||||
~BoundingBoxf3();
|
~BoundingBoxf3();
|
||||||
Clone<BoundingBoxf3> clone()
|
Clone<BoundingBoxf3> clone()
|
||||||
|
|
|
@ -12,6 +12,10 @@ BoundingBox* O_OBJECT_SLIC3R
|
||||||
Ref<BoundingBox> O_OBJECT_SLIC3R_T
|
Ref<BoundingBox> O_OBJECT_SLIC3R_T
|
||||||
Clone<BoundingBox> O_OBJECT_SLIC3R_T
|
Clone<BoundingBox> O_OBJECT_SLIC3R_T
|
||||||
|
|
||||||
|
BoundingBoxf* O_OBJECT_SLIC3R
|
||||||
|
Ref<BoundingBoxf> O_OBJECT_SLIC3R_T
|
||||||
|
Clone<BoundingBoxf> O_OBJECT_SLIC3R_T
|
||||||
|
|
||||||
BoundingBoxf3* O_OBJECT_SLIC3R
|
BoundingBoxf3* O_OBJECT_SLIC3R
|
||||||
Ref<BoundingBoxf3> O_OBJECT_SLIC3R_T
|
Ref<BoundingBoxf3> O_OBJECT_SLIC3R_T
|
||||||
Clone<BoundingBoxf3> O_OBJECT_SLIC3R_T
|
Clone<BoundingBoxf3> O_OBJECT_SLIC3R_T
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
%typemap{BoundingBox*};
|
%typemap{BoundingBox*};
|
||||||
%typemap{Ref<BoundingBox>}{simple};
|
%typemap{Ref<BoundingBox>}{simple};
|
||||||
%typemap{Clone<BoundingBox>}{simple};
|
%typemap{Clone<BoundingBox>}{simple};
|
||||||
|
%typemap{BoundingBoxf*};
|
||||||
|
%typemap{Ref<BoundingBoxf>}{simple};
|
||||||
|
%typemap{Clone<BoundingBoxf>}{simple};
|
||||||
%typemap{BoundingBoxf3*};
|
%typemap{BoundingBoxf3*};
|
||||||
%typemap{Ref<BoundingBoxf3>}{simple};
|
%typemap{Ref<BoundingBoxf3>}{simple};
|
||||||
%typemap{Clone<BoundingBoxf3>}{simple};
|
%typemap{Clone<BoundingBoxf3>}{simple};
|
||||||
|
|
Loading…
Reference in a new issue