Slic3r GUI not starting, error when using --gui (on linux)

Implements https://github.com/prusa3d/Slic3r/issues/407
Shortcuts: Movement in 3D Space
Assignment of the camera shortcuts is clear from the menu accelerators.

Implements https://github.com/prusa3d/Slic3r/issues/406
Shortcuts: Rotate +/- 45 degrees
l/r keys rotate the object

Also changed the accelerators for adding / removing duplicates from
Ctrl++/- to plain +/-, from Ctrl-Del to plain Del,
and added an 's' key accelerator for uniform scaling.
This commit is contained in:
bubnikv 2017-07-21 16:29:40 +02:00
parent 969e3f4a80
commit 3b51f64411
4 changed files with 128 additions and 27 deletions

View File

@ -16,13 +16,13 @@ use strict;
use warnings; use warnings;
use Wx qw(:timer :bitmap :icon :dialog); use Wx qw(:timer :bitmap :icon :dialog);
use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_TIMER); use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER);
# must load OpenGL *before* Wx::GLCanvas # must load OpenGL *before* Wx::GLCanvas
use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants); use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants);
use base qw(Wx::GLCanvas Class::Accessor); use base qw(Wx::GLCanvas Class::Accessor);
use Math::Trig qw(asin tan); use Math::Trig qw(asin tan);
use List::Util qw(reduce min max first); use List::Util qw(reduce min max first);
use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan scale unscale scaled_epsilon); use Slic3r::Geometry qw(X Y normalize scale unscale scaled_epsilon);
use Slic3r::Geometry::Clipper qw(offset_ex intersection_pl JT_ROUND); use Slic3r::Geometry::Clipper qw(offset_ex intersection_pl JT_ROUND);
use Wx::GLCanvas qw(:all); use Wx::GLCanvas qw(:all);
use Slic3r::Geometry qw(PI); use Slic3r::Geometry qw(PI);
@ -168,6 +168,32 @@ sub new {
}); });
EVT_MOUSEWHEEL($self, \&mouse_wheel_event); EVT_MOUSEWHEEL($self, \&mouse_wheel_event);
EVT_MOUSE_EVENTS($self, \&mouse_event); EVT_MOUSE_EVENTS($self, \&mouse_event);
# EVT_KEY_DOWN($self, sub {
EVT_CHAR($self, sub {
my ($s, $event) = @_;
if ($event->HasModifiers) {
$event->Skip;
} else {
my $key = $event->GetKeyCode;
if ($key == ord('0')) {
$self->select_view('iso');
} elsif ($key == ord('1')) {
$self->select_view('top');
} elsif ($key == ord('2')) {
$self->select_view('bottom');
} elsif ($key == ord('3')) {
$self->select_view('front');
} elsif ($key == ord('4')) {
$self->select_view('rear');
} elsif ($key == ord('5')) {
$self->select_view('left');
} elsif ($key == ord('6')) {
$self->select_view('right');
} else {
$event->Skip;
}
}
});
$self->{layer_height_edit_timer_id} = &Wx::NewId(); $self->{layer_height_edit_timer_id} = &Wx::NewId();
$self->{layer_height_edit_timer} = Wx::Timer->new($self, $self->{layer_height_edit_timer_id}); $self->{layer_height_edit_timer} = Wx::Timer->new($self, $self->{layer_height_edit_timer_id});

View File

@ -7,7 +7,7 @@ use utf8;
use File::Basename qw(basename dirname); use File::Basename qw(basename dirname);
use List::Util qw(min); use List::Util qw(min);
use Slic3r::Geometry qw(X Y Z); use Slic3r::Geometry qw(X Y);
use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog
:font :icon wxTheApp); :font :icon wxTheApp);
use Wx::Event qw(EVT_CLOSE EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED); use Wx::Event qw(EVT_CLOSE EVT_MENU EVT_NOTEBOOK_PAGE_CHANGED);
@ -273,13 +273,16 @@ sub _init_menubar {
# View menu # View menu
if (!$self->{no_plater}) { if (!$self->{no_plater}) {
$self->{viewMenu} = Wx::Menu->new; $self->{viewMenu} = Wx::Menu->new;
$self->_append_menu_item($self->{viewMenu}, "Iso" , 'Iso View' , sub { $self->select_view('iso' ); }); # \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators,
$self->_append_menu_item($self->{viewMenu}, "Top" , 'Top View' , sub { $self->select_view('top' ); }); # as the simple numeric accelerators spoil all numeric data entry.
$self->_append_menu_item($self->{viewMenu}, "Bottom" , 'Bottom View' , sub { $self->select_view('bottom' ); }); # The camera control accelerators are captured by 3DScene Perl module instead.
$self->_append_menu_item($self->{viewMenu}, "Front" , 'Front View' , sub { $self->select_view('front' ); }); $self->_append_menu_item($self->{viewMenu}, "Iso\t\xA00" , 'Iso View' , sub { $self->select_view('iso' ); });
$self->_append_menu_item($self->{viewMenu}, "Rear" , 'Rear View' , sub { $self->select_view('rear' ); }); $self->_append_menu_item($self->{viewMenu}, "Top\t\xA01" , 'Top View' , sub { $self->select_view('top' ); });
$self->_append_menu_item($self->{viewMenu}, "Left" , 'Left View' , sub { $self->select_view('left' ); }); $self->_append_menu_item($self->{viewMenu}, "Bottom\t\xA02" , 'Bottom View' , sub { $self->select_view('bottom' ); });
$self->_append_menu_item($self->{viewMenu}, "Right" , 'Right View' , sub { $self->select_view('right' ); }); $self->_append_menu_item($self->{viewMenu}, "Front\t\xA03" , 'Front View' , sub { $self->select_view('front' ); });
$self->_append_menu_item($self->{viewMenu}, "Rear\t\xA04" , 'Rear View' , sub { $self->select_view('rear' ); });
$self->_append_menu_item($self->{viewMenu}, "Left\t\xA05" , 'Left View' , sub { $self->select_view('left' ); });
$self->_append_menu_item($self->{viewMenu}, "Right\t\xA06" , 'Right View' , sub { $self->select_view('right' ); });
} }
# Help menu # Help menu

View File

@ -7,7 +7,7 @@ use utf8;
use File::Basename qw(basename dirname); use File::Basename qw(basename dirname);
use List::Util qw(sum first max); use List::Util qw(sum first max);
use Slic3r::Geometry qw(X Y Z MIN MAX scale unscale deg2rad rad2deg); use Slic3r::Geometry qw(X Y Z scale unscale deg2rad rad2deg);
use LWP::UserAgent; use LWP::UserAgent;
use threads::shared qw(shared_clone); use threads::shared qw(shared_clone);
use Wx qw(:button :colour :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc use Wx qw(:button :colour :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc
@ -105,6 +105,12 @@ sub new {
$self->{canvas3D}->set_on_select_object($on_select_object); $self->{canvas3D}->set_on_select_object($on_select_object);
$self->{canvas3D}->set_on_double_click($on_double_click); $self->{canvas3D}->set_on_double_click($on_double_click);
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); }); $self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); });
$self->{canvas3D}->set_on_rotate_object_left(sub { $self->rotate(-45, Z, 'relative') });
$self->{canvas3D}->set_on_rotate_object_right(sub { $self->rotate( 45, Z, 'relative') });
$self->{canvas3D}->set_on_scale_object_uniformly(sub { $self->changescale(undef) });
$self->{canvas3D}->set_on_increase_objects(sub { $self->increase() });
$self->{canvas3D}->set_on_decrease_objects(sub { $self->decrease() });
$self->{canvas3D}->set_on_remove_object(sub { $self->remove() });
$self->{canvas3D}->set_on_instances_moved($on_instances_moved); $self->{canvas3D}->set_on_instances_moved($on_instances_moved);
$self->{canvas3D}->set_on_wipe_tower_moved(sub { $self->{canvas3D}->set_on_wipe_tower_moved(sub {
my ($new_pos_3f) = @_; my ($new_pos_3f) = @_;
@ -864,6 +870,7 @@ sub remove {
# if no object index is supplied, remove the selected one # if no object index is supplied, remove the selected one
if (! defined $obj_idx) { if (! defined $obj_idx) {
($obj_idx, undef) = $self->selected_object; ($obj_idx, undef) = $self->selected_object;
return if ! defined $obj_idx;
} }
splice @{$self->{objects}}, $obj_idx, 1; splice @{$self->{objects}}, $obj_idx, 1;
@ -1121,12 +1128,12 @@ sub changescale {
if ($tosize) { if ($tosize) {
my $cursize = max(@$object_size); my $cursize = max(@$object_size);
my $newsize = $self->_get_number_from_user('Enter the new max size for the selected object:', 'Scale', 'Invalid scaling value entered', $cursize, 1); my $newsize = $self->_get_number_from_user('Enter the new max size for the selected object:', 'Scale', 'Invalid scaling value entered', $cursize, 1);
return if $newsize eq ''; return if ! defined($newsize) || $newsize eq '';
$scale = $model_instance->scaling_factor * $newsize / $cursize * 100; $scale = $model_instance->scaling_factor * $newsize / $cursize * 100;
} else { } else {
# max scale factor should be above 2540 to allow importing files exported in inches # max scale factor should be above 2540 to allow importing files exported in inches
$scale = $self->_get_number_from_user('Enter the scale % for the selected object:', 'Scale', 'Invalid scaling value entered', $model_instance->scaling_factor*100, 1); $scale = $self->_get_number_from_user('Enter the scale % for the selected object:', 'Scale', 'Invalid scaling value entered', $model_instance->scaling_factor*100, 1);
return if $scale eq ''; return if ! defined($scale) || $scale eq '';
} }
$self->{list}->SetItem($obj_idx, 2, "$scale%"); $self->{list}->SetItem($obj_idx, 2, "$scale%");
@ -2060,23 +2067,23 @@ sub object_menu {
my $frame = $self->GetFrame; my $frame = $self->GetFrame;
my $menu = Wx::Menu->new; my $menu = Wx::Menu->new;
$frame->_append_menu_item($menu, "Delete\tCtrl+Del", 'Remove the selected object', sub { $frame->_append_menu_item($menu, "Delete\t\xA0Del", 'Remove the selected object', sub {
$self->remove; $self->remove;
}, undef, 'brick_delete.png'); }, undef, 'brick_delete.png');
$frame->_append_menu_item($menu, "Increase copies\tCtrl++", 'Place one more copy of the selected object', sub { $frame->_append_menu_item($menu, "Increase copies\t\xA0+", 'Place one more copy of the selected object', sub {
$self->increase; $self->increase;
}, undef, 'add.png'); }, undef, 'add.png');
$frame->_append_menu_item($menu, "Decrease copies\tCtrl+-", 'Remove one copy of the selected object', sub { $frame->_append_menu_item($menu, "Decrease copies\t\xA0-", 'Remove one copy of the selected object', sub {
$self->decrease; $self->decrease;
}, undef, 'delete.png'); }, undef, 'delete.png');
$frame->_append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub { $frame->_append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub {
$self->set_number_of_copies; $self->set_number_of_copies;
}, undef, 'textfield.png'); }, undef, 'textfield.png');
$menu->AppendSeparator(); $menu->AppendSeparator();
$frame->_append_menu_item($menu, "Rotate 45° clockwise", 'Rotate the selected object by 45° clockwise', sub { $frame->_append_menu_item($menu, "Rotate 45° clockwise\t\xA0l", 'Rotate the selected object by 45° clockwise', sub {
$self->rotate(-45, Z, 'relative'); $self->rotate(-45, Z, 'relative');
}, undef, 'arrow_rotate_clockwise.png'); }, undef, 'arrow_rotate_clockwise.png');
$frame->_append_menu_item($menu, "Rotate 45° counter-clockwise", 'Rotate the selected object by 45° counter-clockwise', sub { $frame->_append_menu_item($menu, "Rotate 45° counter-clockwise\t\xA0r", 'Rotate the selected object by 45° counter-clockwise', sub {
$self->rotate(+45, Z, 'relative'); $self->rotate(+45, Z, 'relative');
}, undef, 'arrow_rotate_anticlockwise.png'); }, undef, 'arrow_rotate_anticlockwise.png');
@ -2109,7 +2116,7 @@ sub object_menu {
my $scaleMenu = Wx::Menu->new; my $scaleMenu = Wx::Menu->new;
my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, "Scale", 'Scale the selected object along a single axis'); my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, "Scale", 'Scale the selected object along a single axis');
$frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png'); $frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png');
$frame->_append_menu_item($scaleMenu, "Uniformly…", 'Scale the selected object along the XYZ axes', sub { $frame->_append_menu_item($scaleMenu, "Uniformly…\t\xA0s", 'Scale the selected object along the XYZ axes', sub {
$self->changescale(undef); $self->changescale(undef);
}); });
$frame->_append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub { $frame->_append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub {
@ -2203,9 +2210,6 @@ sub OnDropFiles {
package Slic3r::GUI::Plater::Object; package Slic3r::GUI::Plater::Object;
use Moo; use Moo;
use List::Util qw(first);
use Slic3r::Geometry qw(X Y Z MIN MAX deg2rad);
has 'name' => (is => 'rw', required => 1); has 'name' => (is => 'rw', required => 1);
has 'thumbnail' => (is => 'rw'); # ExPolygon::Collection in scaled model units with no transforms has 'thumbnail' => (is => 'rw'); # ExPolygon::Collection in scaled model units with no transforms
has 'transformed_thumbnail' => (is => 'rw'); has 'transformed_thumbnail' => (is => 'rw');

View File

@ -4,12 +4,14 @@ use warnings;
use utf8; use utf8;
use List::Util qw(); use List::Util qw();
use Slic3r::Geometry qw(); use Wx qw(:misc :pen :brush :sizer :font :cursor :keycode wxTAB_TRAVERSAL);
use Slic3r::Geometry::Clipper qw(); use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR);
use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL);
use Wx::Event qw();
use base qw(Slic3r::GUI::3DScene Class::Accessor); use base qw(Slic3r::GUI::3DScene Class::Accessor);
__PACKAGE__->mk_accessors(qw(
on_rotate_object_left on_rotate_object_right on_scale_object_uniformly
on_remove_object on_increase_objects on_decrease_objects));
sub new { sub new {
my $class = shift; my $class = shift;
my ($parent, $objects, $model, $print, $config) = @_; my ($parent, $objects, $model, $print, $config) = @_;
@ -66,6 +68,42 @@ sub new {
if $wipe_tower_moved && $self->{on_wipe_tower_moved}; if $wipe_tower_moved && $self->{on_wipe_tower_moved};
}); });
EVT_KEY_DOWN($self, sub {
my ($s, $event) = @_;
if ($event->HasModifiers) {
$event->Skip;
} else {
my $key = $event->GetKeyCode;
if ($key == WXK_DELETE) {
$self->on_remove_object->() if $self->on_remove_object;
} else {
$event->Skip;
}
}
});
EVT_CHAR($self, sub {
my ($s, $event) = @_;
if ($event->HasModifiers) {
$event->Skip;
} else {
my $key = $event->GetKeyCode;
if ($key == ord('l')) {
$self->on_rotate_object_left->() if $self->on_rotate_object_left;
} elsif ($key == ord('r')) {
$self->on_rotate_object_right->() if $self->on_rotate_object_right;
} elsif ($key == ord('s')) {
$self->on_scale_object_uniformly->() if $self->on_scale_object_uniformly;
} elsif ($key == ord('+')) {
$self->on_increase_objects->() if $self->on_increase_objects;
} elsif ($key == ord('-')) {
$self->on_decrease_objects->() if $self->on_decrease_objects;
} else {
$event->Skip;
}
}
});
return $self; return $self;
} }
@ -84,6 +122,36 @@ sub set_on_right_click {
$self->on_right_click($cb); $self->on_right_click($cb);
} }
sub set_on_rotate_object_left {
my ($self, $cb) = @_;
$self->on_rotate_object_left($cb);
}
sub set_on_rotate_object_right {
my ($self, $cb) = @_;
$self->on_rotate_object_right($cb);
}
sub set_on_scale_object_uniformly {
my ($self, $cb) = @_;
$self->on_scale_object_uniformly($cb);
}
sub set_on_increase_objects {
my ($self, $cb) = @_;
$self->on_increase_objects($cb);
}
sub set_on_decrease_objects {
my ($self, $cb) = @_;
$self->on_decrease_objects($cb);
}
sub set_on_remove_object {
my ($self, $cb) = @_;
$self->on_remove_object($cb);
}
sub set_on_instances_moved { sub set_on_instances_moved {
my ($self, $cb) = @_; my ($self, $cb) = @_;
$self->{on_instances_moved} = $cb; $self->{on_instances_moved} = $cb;