diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 776f80ec3..03a42ed02 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -205,6 +205,11 @@ sub _build_field { parent => $self->parent, option => $opt, ); + } elsif ($type eq 'point3'){ + $field = Slic3r::GUI::OptionsGroup::Field::Point3->new( + parent => $self->parent, + option => $opt, + ); } elsif ($type eq 'slider') { $field = Slic3r::GUI::OptionsGroup::Field::Slider->new( parent => $self->parent, diff --git a/lib/Slic3r/GUI/OptionsGroup/Field.pm b/lib/Slic3r/GUI/OptionsGroup/Field.pm index 65cea5f08..638612116 100644 --- a/lib/Slic3r/GUI/OptionsGroup/Field.pm +++ b/lib/Slic3r/GUI/OptionsGroup/Field.pm @@ -509,6 +509,87 @@ sub disable { $self->y_textctrl->Disable; } +package Slic3r::GUI::OptionsGroup::Field::Point3; +use Moo; +extends 'Slic3r::GUI::OptionsGroup::Field::wxSizer'; + +has 'x_textctrl' => (is => 'rw'); +has 'y_textctrl' => (is => 'rw'); +has 'z_textctrl' => (is => 'rw'); + +use Slic3r::Geometry qw(X Y Z); +use Wx qw(:misc :sizer); +use Wx::Event qw(EVT_TEXT); + +sub BUILD { + my ($self) = @_; + + my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); + $self->wxSizer($sizer); + + my $field_size = Wx::Size->new(40, -1); + + $self->x_textctrl(Wx::TextCtrl->new($self->parent, -1, $self->option->default->[X], wxDefaultPosition, $field_size)); + $self->y_textctrl(Wx::TextCtrl->new($self->parent, -1, $self->option->default->[Y], wxDefaultPosition, $field_size)); + $self->z_textctrl(Wx::TextCtrl->new($self->parent, -1, $self->option->default->[Z], wxDefaultPosition, $field_size)); + + my @items = ( + Wx::StaticText->new($self->parent, -1, "x:"), + $self->x_textctrl, + Wx::StaticText->new($self->parent, -1, " y:"), + $self->y_textctrl, + Wx::StaticText->new($self->parent, -1, " z:"), + $self->z_textctrl, + ); + $sizer->Add($_, 0, wxALIGN_CENTER_VERTICAL, 0) for @items; + + if ($self->option->tooltip) { + foreach my $item (@items) { + $item->SetToolTipString($self->option->tooltip) + if $item->can('SetToolTipString'); + } + } + + EVT_TEXT($self->parent, $_, sub { + $self->_on_change($self->option->opt_id); + }) for $self->x_textctrl, $self->y_textctrl, $self->z_textctrl; +} + +sub set_value { + my ($self, $value) = @_; + + $self->disable_change_event(1); + $self->x_textctrl->SetValue($value->[X]); + $self->y_textctrl->SetValue($value->[Y]); + $self->z_textctrl->SetValue($value->[Z]); + $self->disable_change_event(0); +} + +sub get_value { + my ($self) = @_; + + return [ + $self->x_textctrl->GetValue, + $self->y_textctrl->GetValue, + $self->z_textctrl->GetValue, + ]; +} + +sub enable { + my ($self) = @_; + + $self->x_textctrl->Enable; + $self->y_textctrl->Enable; + $self->z_textctrl->Enable; +} + +sub disable { + my ($self) = @_; + + $self->x_textctrl->Disable; + $self->y_textctrl->Disable; + $self->z_textctrl->Disable; +} package Slic3r::GUI::OptionsGroup::Field::Slider; use Moo; diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index 5269a4c11..9a4a71ac2 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -420,6 +420,12 @@ Pointf::vector_to(const Pointf &point) const return Vectorf(point.x - this->x, point.y - this->y); } +std::ostream& +operator<<(std::ostream &stm, const Pointf3 &pointf3) +{ + return stm << pointf3.x << "," << pointf3.y << "," << pointf3.z; +} + void Pointf3::scale(double factor) { diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 7fd05ff48..048e6c227 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -96,6 +96,7 @@ class Point3 : public Point public: coord_t z; explicit Point3(coord_t _x = 0, coord_t _y = 0, coord_t _z = 0): Point(_x, _y), z(_z) {}; + bool coincides_with(const Point3 &point3) const { return this->x == point3.x && this->y == point3.y && this->z == point3.z; } }; std::ostream& operator<<(std::ostream &stm, const Pointf &pointf); @@ -123,6 +124,8 @@ class Pointf Vectorf vector_to(const Pointf &point) const; }; +std::ostream& operator<<(std::ostream &stm, const Pointf3 &pointf3); + class Pointf3 : public Pointf { public: diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 0a194cbba..ebff92e0d 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -228,6 +228,9 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) } else if (def->type == coPoint) { ConfigOptionPoint* optv = dynamic_cast(opt); return from_SV_check(value, &optv->value); + } else if(def->type == coPoint3){ + ConfigOptionPoint3* optv = dynamic_cast(opt); + return from_SV_check(value, &optv->value); } else if (def->type == coPoints) { ConfigOptionPoints* optv = dynamic_cast(opt); std::vector values; @@ -507,6 +510,73 @@ bool from_SV_check(SV* point_sv, Pointf* point) } } +SV* to_SV_pureperl(const Point3* THIS) +{ + AV* av = newAV(); + av_fill(av, 2); + av_store(av, 0, newSViv(THIS->x)); + av_store(av, 1, newSViv(THIS->y)); + av_store(av, 1, newSViv(THIS->z)); + return newRV_noinc((SV*)av); +} + +void from_SV(SV* point3_sv, Point3* point) +{ + AV* point3_av = (AV*)SvRV(point3_sv); + // get a double from Perl and round it, otherwise + // it would get truncated + point->x = lrint(SvNV(*av_fetch(point3_av, 0, 0))); + point->y = lrint(SvNV(*av_fetch(point3_av, 1, 0))); + point->z = lrint(SvNV(*av_fetch(point3_av, 2, 0))); +} + +void from_SV_check(SV* point3_sv, Point3* point) +{ + if (sv_isobject(point3_sv) && (SvTYPE(SvRV(point3_sv)) == SVt_PVMG)) { + if (!sv_isa(point3_sv, perl_class_name(point)) && !sv_isa(point3_sv, perl_class_name_ref(point))) + CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point3_sv)))); + *point = *(Point3*)SvIV((SV*)SvRV( point3_sv )); + } else { + from_SV(point3_sv, point); + } +} + +SV* to_SV_pureperl(const Pointf3* point) +{ + AV* av = newAV(); + av_fill(av, 2); + av_store(av, 0, newSVnv(point->x)); + av_store(av, 1, newSVnv(point->y)); + av_store(av, 1, newSVnv(point->z)); + return newRV_noinc((SV*)av); +} + +bool from_SV(SV* point3_sv, Pointf3* point) +{ + AV* point3_av = (AV*)SvRV(point3_sv); + SV* sv_x = *av_fetch(point3_av, 0, 0); + SV* sv_y = *av_fetch(point3_av, 1, 0); + SV* sv_z = *av_fetch(point3_av, 2, 0); + if (!looks_like_number(sv_x) || !looks_like_number(sv_y) || !looks_like_number(sv_z) ) return false; + + point->x = SvNV(sv_x); + point->y = SvNV(sv_y); + point->z = SvNV(sv_z); + return true; +} + +bool from_SV_check(SV* point3_sv, Pointf3* point) +{ + if (sv_isobject(point3_sv) && (SvTYPE(SvRV(point3_sv)) == SVt_PVMG)) { + if (!sv_isa(point3_sv, perl_class_name(point)) && !sv_isa(point3_sv, perl_class_name_ref(point))) + CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point3_sv)))); + *point = *(Pointf3*)SvIV((SV*)SvRV( point3_sv )); + return true; + } else { + return from_SV(point3_sv, point); + } +} + void from_SV_check(SV* surface_sv, Surface* THIS) { if (!sv_isa(surface_sv, perl_class_name(THIS)) && !sv_isa(surface_sv, perl_class_name_ref(THIS))) diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index a5a3949d6..688f821ce 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -148,6 +148,10 @@ void from_SV_check(SV* point_sv, Point* point); SV* to_SV_pureperl(const Pointf* point); bool from_SV(SV* point_sv, Pointf* point); bool from_SV_check(SV* point_sv, Pointf* point); +void from_SV(SV* point_sv, Point3* point); +void from_SV_check(SV* point_sv, Point3* point); +bool from_SV(SV* point_sv, Pointf3* point); +bool from_SV_check(SV* point_sv, Pointf3* point); void from_SV_check(SV* surface_sv, Surface* THIS); SV* to_SV(TriangleMesh* THIS); SV* polynode_children_2_perl(const ClipperLib::PolyNode& node); diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index 75dc35405..2a9bd82c9 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -128,8 +128,10 @@ print_config_def() opt_type = "s"; } else if (optdef.type == coStrings) { opt_type = "s@"; - } else if (optdef.type == coPoint || optdef.type == coPoint3 || optdef.type == coPoints) { + } else if (optdef.type == coPoint || optdef.type == coPoints) { opt_type = "point"; + } else if (optdef.type == coPoint3 ){ + opt_type = "point3"; } else if (optdef.type == coBool || optdef.type == coBools) { opt_type = "bool"; } else if (optdef.type == coEnum) {