Reader.pm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # Helper module to parse and interpret a G-code file,
  2. # invoking a callback for each move extracted from the G-code.
  3. # Currently used by the automatic tests only.
  4. package Slic3r::GCode::Reader;
  5. use Moo;
  6. has 'config' => (is => 'ro', default => sub { Slic3r::Config::GCode->new });
  7. has 'X' => (is => 'rw', default => sub {0});
  8. has 'Y' => (is => 'rw', default => sub {0});
  9. has 'Z' => (is => 'rw', default => sub {0});
  10. has 'E' => (is => 'rw', default => sub {0});
  11. has 'F' => (is => 'rw', default => sub {0});
  12. has '_extrusion_axis' => (is => 'rw', default => sub {"E"});
  13. our $Verbose = 0;
  14. my @AXES = qw(X Y Z E);
  15. sub apply_print_config {
  16. my ($self, $print_config) = @_;
  17. $self->config->apply_static($print_config);
  18. $self->_extrusion_axis($self->config->get_extrusion_axis);
  19. }
  20. sub clone {
  21. my $self = shift;
  22. return (ref $self)->new(
  23. map { $_ => $self->$_ } (@AXES, 'F', '_extrusion_axis', 'config'),
  24. );
  25. }
  26. sub parse {
  27. my $self = shift;
  28. my ($gcode, $cb) = @_;
  29. foreach my $raw_line (split /\R+/, $gcode) {
  30. print "$raw_line\n" if $Verbose || $ENV{SLIC3R_TESTS_GCODE};
  31. my $line = $raw_line;
  32. $line =~ s/\s*;(.*)//; # strip comment
  33. my %info = (comment => $1, raw => $raw_line);
  34. # parse command
  35. my ($command, @args) = split /\s+/, $line;
  36. $command //= '';
  37. my %args = map { /([A-Z])(.*)/; ($1 => $2) } @args;
  38. # convert extrusion axis
  39. if (exists $args{ $self->_extrusion_axis }) {
  40. $args{E} = $args{ $self->_extrusion_axis };
  41. }
  42. # check motion
  43. if ($command =~ /^G[01]$/) {
  44. foreach my $axis (@AXES) {
  45. if (exists $args{$axis}) {
  46. $self->$axis(0) if $axis eq 'E' && $self->config->use_relative_e_distances;
  47. $info{"dist_$axis"} = $args{$axis} - $self->$axis;
  48. $info{"new_$axis"} = $args{$axis};
  49. } else {
  50. $info{"dist_$axis"} = 0;
  51. $info{"new_$axis"} = $self->$axis;
  52. }
  53. }
  54. $info{dist_XY} = sqrt(($info{dist_X}**2) + ($info{dist_Y}**2));
  55. if (exists $args{E}) {
  56. if ($info{dist_E} > 0) {
  57. $info{extruding} = 1;
  58. } elsif ($info{dist_E} < 0) {
  59. $info{retracting} = 1
  60. }
  61. } else {
  62. $info{travel} = 1;
  63. }
  64. }
  65. # run callback
  66. $cb->($self, $command, \%args, \%info);
  67. # update coordinates
  68. if ($command =~ /^(?:G[01]|G92)$/) {
  69. for my $axis (@AXES, 'F') {
  70. $self->$axis($args{$axis}) if exists $args{$axis};
  71. }
  72. }
  73. # TODO: update temperatures
  74. }
  75. }
  76. 1;