ManualControlDialog.pm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. # A printer "Controller" -> "ManualControlDialog" subtab, opened per 3D printer connected?
  2. package Slic3r::GUI::Controller::ManualControlDialog;
  3. use strict;
  4. use warnings;
  5. use utf8;
  6. use Wx qw(:dialog :id :misc :sizer :choicebook :button :bitmap
  7. wxBORDER_NONE wxTAB_TRAVERSAL);
  8. use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
  9. use base qw(Wx::Dialog Class::Accessor);
  10. __PACKAGE__->mk_accessors(qw(sender config2 x_homed y_homed));
  11. sub new {
  12. my ($class, $parent, $config, $sender) = @_;
  13. my $self = $class->SUPER::new($parent, -1, "Manual Control", wxDefaultPosition,
  14. [500,380], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
  15. $self->sender($sender);
  16. $self->config2({
  17. xy_travel_speed => 130,
  18. z_travel_speed => 10,
  19. });
  20. my $bed_sizer = Wx::FlexGridSizer->new(2, 3, 1, 1);
  21. $bed_sizer->AddGrowableCol(1, 1);
  22. $bed_sizer->AddGrowableRow(0, 1);
  23. my $move_button = sub {
  24. my ($sizer, $label, $icon, $bold, $pos, $handler) = @_;
  25. my $btn = Wx::Button->new($self, -1, $label, wxDefaultPosition, wxDefaultSize,
  26. wxBU_LEFT | wxBU_EXACTFIT);
  27. $btn->SetFont($bold ? $Slic3r::GUI::small_bold_font : $Slic3r::GUI::small_font);
  28. $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("$icon.png"), wxBITMAP_TYPE_PNG));
  29. $btn->SetBitmapPosition($pos);
  30. EVT_BUTTON($self, $btn, $handler);
  31. $sizer->Add($btn, 1, wxEXPAND | wxALL, 0);
  32. };
  33. # Y buttons
  34. {
  35. my $sizer = Wx::BoxSizer->new(wxVERTICAL);
  36. for my $d (qw(+10 +1 +0.1)) {
  37. $move_button->($sizer, $d, 'arrow_up', 0, wxLEFT, sub { $self->rel_move('Y', $d) });
  38. }
  39. $move_button->($sizer, 'Y', 'house', 1, wxLEFT, sub { $self->home('Y') });
  40. for my $d (qw(-0.1 -1 -10)) {
  41. $move_button->($sizer, $d, 'arrow_down', 0, wxLEFT, sub { $self->rel_move('Y', $d) });
  42. };
  43. $bed_sizer->Add($sizer, 1, wxEXPAND, 0);
  44. }
  45. # Bed canvas
  46. {
  47. my $bed_shape = $config->bed_shape;
  48. $self->{canvas} = my $canvas = Slic3r::GUI::2DBed->new($self, $bed_shape);
  49. $canvas->interactive(1);
  50. $canvas->on_move(sub {
  51. my ($pos) = @_;
  52. if (!($self->x_homed && $self->y_homed)) {
  53. Slic3r::GUI::show_error($self, "Please home both X and Y before moving.");
  54. return ;
  55. }
  56. # delete any pending commands to get a smoother movement
  57. $self->sender->purge_queue(1);
  58. $self->abs_xy_move($pos);
  59. });
  60. $bed_sizer->Add($canvas, 0, wxEXPAND | wxRIGHT, 3);
  61. }
  62. # Z buttons
  63. {
  64. my $sizer = Wx::BoxSizer->new(wxVERTICAL);
  65. for my $d (qw(+10 +1 +0.1)) {
  66. $move_button->($sizer, $d, 'arrow_up', 0, wxLEFT, sub { $self->rel_move('Z', $d) });
  67. }
  68. $move_button->($sizer, 'Z', 'house', 1, wxLEFT, sub { $self->home('Z') });
  69. for my $d (qw(-0.1 -1 -10)) {
  70. $move_button->($sizer, $d, 'arrow_down', 0, wxLEFT, sub { $self->rel_move('Z', $d) });
  71. };
  72. $bed_sizer->Add($sizer, 1, wxEXPAND, 0);
  73. }
  74. # XYZ home button
  75. $move_button->($bed_sizer, 'XYZ', 'house', 1, wxTOP, sub { $self->home(undef) });
  76. # X buttons
  77. {
  78. my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
  79. for my $d (qw(-10 -1 -0.1)) {
  80. $move_button->($sizer, $d, 'arrow_left', 0, wxTOP, sub { $self->rel_move('X', $d) });
  81. }
  82. $move_button->($sizer, 'X', 'house', 1, wxTOP, sub { $self->home('X') });
  83. for my $d (qw(+0.1 +1 +10)) {
  84. $move_button->($sizer, $d, 'arrow_right', 0, wxTOP, sub { $self->rel_move('X', $d) });
  85. }
  86. $bed_sizer->Add($sizer, 1, wxEXPAND, 0);
  87. }
  88. my $optgroup = Slic3r::GUI::OptionsGroup->new(
  89. parent => $self,
  90. title => 'Settings',
  91. on_change => sub {
  92. my ($opt_id, $value) = @_;
  93. $self->config2->{$opt_id} = $value;
  94. },
  95. );
  96. {
  97. my $line = Slic3r::GUI::OptionsGroup::Line->new(
  98. label => 'Speed (mm/s)',
  99. );
  100. $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
  101. opt_id => 'xy_travel_speed',
  102. type => 'f',
  103. label => 'X/Y',
  104. tooltip => '',
  105. default => $self->config2->{xy_travel_speed},
  106. ));
  107. $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
  108. opt_id => 'z_travel_speed',
  109. type => 'f',
  110. label => 'Z',
  111. tooltip => '',
  112. default => $self->config2->{z_travel_speed},
  113. ));
  114. $optgroup->append_line($line);
  115. }
  116. my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
  117. $main_sizer->Add($bed_sizer, 1, wxEXPAND | wxALL, 10);
  118. $main_sizer->Add($optgroup->sizer, 0, wxEXPAND | wxALL, 10);
  119. #$main_sizer->Add($self->CreateButtonSizer(wxCLOSE), 0, wxEXPAND);
  120. #EVT_BUTTON($self, wxID_CLOSE, sub { $self->Close });
  121. $self->SetSizer($main_sizer);
  122. $self->SetMinSize($self->GetSize);
  123. #$main_sizer->SetSizeHints($self);
  124. $self->Layout;
  125. # needed to actually free memory
  126. EVT_CLOSE($self, sub {
  127. $self->EndModal(wxID_OK);
  128. $self->Destroy;
  129. });
  130. return $self;
  131. }
  132. sub abs_xy_move {
  133. my ($self, $pos) = @_;
  134. $self->sender->send("G90", 1); # set absolute positioning
  135. $self->sender->send(sprintf("G1 X%.1f Y%.1f F%d", @$pos, $self->config2->{xy_travel_speed}*60), 1);
  136. $self->{canvas}->set_pos($pos);
  137. }
  138. sub rel_move {
  139. my ($self, $axis, $distance) = @_;
  140. my $speed = ($axis eq 'Z') ? $self->config2->{z_travel_speed} : $self->config2->{xy_travel_speed};
  141. $self->sender->send("G91", 1); # set relative positioning
  142. $self->sender->send(sprintf("G1 %s%.1f F%d", $axis, $distance, $speed*60), 1);
  143. $self->sender->send("G90", 1); # set absolute positioning
  144. if (my $pos = $self->{canvas}->pos) {
  145. if ($axis eq 'X') {
  146. $pos->translate($distance, 0);
  147. } elsif ($axis eq 'Y') {
  148. $pos->translate(0, $distance);
  149. }
  150. $self->{canvas}->set_pos($pos);
  151. }
  152. }
  153. sub home {
  154. my ($self, $axis) = @_;
  155. $axis //= '';
  156. $self->sender->send(sprintf("G28 %s", $axis), 1);
  157. $self->{canvas}->set_pos(undef);
  158. $self->x_homed(1) if $axis eq 'X';
  159. $self->y_homed(1) if $axis eq 'Y';
  160. }
  161. 1;