diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 0d8ed634c..d983b9be8 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -161,24 +161,60 @@ sub _init_tabpanel { # The following event is emited by the C++ Tab implementation on config value change. EVT_COMMAND($self, -1, $VALUE_CHANGE_EVENT, sub { my ($self, $event) = @_; - print "VALUE_CHANGE_EVENT: ", $event->GetString, "\n"; + my $str = $event->GetString; + my ($opt_key, $title) = ($str =~ /(.*) (.*)/); + #print "VALUE_CHANGE_EVENT: ", $opt_key, "\n"; + my $tab = Slic3r::GUI::get_preset_tab($title); + my $config = $tab->get_config; + if ($self->{plater}) { + $self->{plater}->on_config_change($config); # propagate config change events to the plater + if ($opt_key eq 'extruders_count'){ + my $value = $event->GetInt(); + $self->{plater}->on_extruders_change($value); + } + } + # don't save while loading for the first time + $self->config->save($Slic3r::GUI::autosave) if $Slic3r::GUI::autosave && $self->{loaded}; }); # The following event is emited by the C++ Tab implementation on preset selection, # or when the preset's "modified" status changes. EVT_COMMAND($self, -1, $PRESETS_CHANGED_EVENT, sub { my ($self, $event) = @_; - print "PRESETS_CHANGED_EVENT: ", $event->GetString, "\n"; + my $title = $event->GetString; + my $tab_name = lc($title); + #print "PRESETS_CHANGED_EVENT: ", $tab_name , "\n"; + + my $tab = Slic3r::GUI::get_preset_tab($title); + if ($self->{plater}) { + # Update preset combo boxes (Print settings, Filament, Printer) from their respective tabs. + my $presets = $tab->get_presets; + my $reload_dependent_tabs = $tab->get_dependent_tabs; + $self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets); + if ($tab_name eq 'printer') { + # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. + for my $tab_name_other (qw(print filament)) { + # If the printer tells us that the print or filament preset has been switched or invalidated, + # refresh the print or filament tab page. Otherwise just refresh the combo box. + my $update_action = ($reload_dependent_tabs && (first { $_ eq $tab_name_other } (@{$reload_dependent_tabs}))) + ? 'load_current_preset' : 'update_tab_ui'; + $self->{options_tabs2}{$tab_name_other}->$update_action; + } + # Update the controller printers. + $self->{controller}->update_presets($presets) if $self->{controller}; + } + $self->{plater}->on_config_change($tab->get_config); + } }); Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, wxTheApp->{app_config}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT); $self->{options_tabs2}{print} = Slic3r::GUI::get_preset_tab("Print"); $self->{options_tabs2}{filament} = Slic3r::GUI::get_preset_tab("Filament"); $self->{options_tabs2}{printer} = Slic3r::GUI::get_preset_tab("Printer"); -# $self->{options_tabs2}{print}->rebuild_page_tree(); if ($self->{plater}) { $self->{plater}->on_select_preset(sub { my ($group, $name) = @_; $self->{options_tabs}{$group}->select_preset($name); + $self->{options_tabs2}{$group}->select_preset($name);#! }); # load initial config my $full_config = wxTheApp->{preset_bundle}->full_config; @@ -573,6 +609,7 @@ sub load_config_file { # Dont proceed further if the config file cannot be loaded. return if Slic3r::GUI::catch_error($self); $_->load_current_preset for (values %{$self->{options_tabs}}); + $_->load_current_preset for (values %{$self->{options_tabs2}});#! wxTheApp->{app_config}->update_config_dir(dirname($file)); $last_config = $file; } @@ -624,6 +661,11 @@ sub load_configbundle { foreach my $tab (values %{$self->{options_tabs}}) { $tab->load_current_preset; } + + #! Load the currently selected preset into the GUI, update the preset selection box. + foreach my $tab (values %{$self->{options_tabs2}}) { + $tab->load_current_preset; + } my $message = sprintf "%d presets successfully imported.", $presets_imported; Slic3r::GUI::show_info($self, $message); @@ -632,8 +674,9 @@ sub load_configbundle { # Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset. # Also update the platter with the new presets. sub load_config { - my ($self, $config) = @_; + my ($self, $config) = @_; $_->load_config($config) foreach values %{$self->{options_tabs}}; + $_->load_config($config) foreach values %{$self->{options_tabs2}};#! $self->{plater}->on_config_change($config) if $self->{plater}; } @@ -672,6 +715,11 @@ sub config_wizard { foreach my $tab (values %{$self->{options_tabs}}) { $tab->load_current_preset; } + + #! Load the currently selected preset into the GUI, update the preset selection box. + foreach my $tab (values %{$self->{options_tabs2}}) { + $tab->load_current_preset; + } } } @@ -684,6 +732,9 @@ sub check_unsaved_changes { foreach my $tab (values %{$self->{options_tabs}}) { push @dirty, $tab->title if $tab->{presets}->current_is_dirty; } + foreach my $tab (values %{$self->{options_tabs2}}) { #! + push @dirty, $tab->title if $tab->current_preset_is_dirty; + } if (@dirty) { my $titles = join ', ', @dirty; @@ -734,6 +785,9 @@ sub update_ui_from_settings { for my $tab_name (qw(print filament printer)) { $self->{options_tabs}{$tab_name}->update_ui_from_settings; } + for my $tab_name (qw(print filament printer)) { + $self->{options_tabs2}{$tab_name}->update_ui_from_settings;#! + } } 1; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 10d65475c..af341a8e1 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -113,6 +113,7 @@ sub new { $cfg->set('wipe_tower_x', $new_pos_3f->x); $cfg->set('wipe_tower_y', $new_pos_3f->y); $self->GetFrame->{options_tabs}{print}->load_config($cfg); + $self->GetFrame->{options_tabs2}{print}->load_config($cfg);#! }); $self->{canvas3D}->set_on_model_update(sub { if (wxTheApp->{app_config}->get("background_processing")) { @@ -1747,6 +1748,7 @@ sub filament_color_box_lmouse_down $colors->[$extruder_idx] = $dialog->GetColourData->GetColour->GetAsString(wxC2S_HTML_SYNTAX); $cfg->set('extruder_colour', $colors); $self->GetFrame->{options_tabs}{printer}->load_config($cfg); + $self->GetFrame->{options_tabs2}{printer}->load_config($cfg);#! wxTheApp->{preset_bundle}->update_platter_filament_ui($extruder_idx, $combobox); } $dialog->Destroy(); diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 04635cd2b..994c50dc0 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -185,6 +185,10 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/Field.hpp ${LIBDIR}/slic3r/GUI/OptionsGroup.cpp ${LIBDIR}/slic3r/GUI/OptionsGroup.hpp + ${LIBDIR}/slic3r/GUI/BedShapeDialog.cpp + ${LIBDIR}/slic3r/GUI/BedShapeDialog.hpp + ${LIBDIR}/slic3r/GUI/2DBed.cpp + ${LIBDIR}/slic3r/GUI/2DBed.hpp ) add_library(admesh STATIC diff --git a/xs/src/libslic3r/Polygon.hpp b/xs/src/libslic3r/Polygon.hpp index f36abc185..1a02d78b7 100644 --- a/xs/src/libslic3r/Polygon.hpp +++ b/xs/src/libslic3r/Polygon.hpp @@ -24,6 +24,12 @@ public: explicit Polygon(const Points &points): MultiPoint(points) {} Polygon(const Polygon &other) : MultiPoint(other.points) {} Polygon(Polygon &&other) : MultiPoint(std::move(other.points)) {} + static Polygon new_scale(std::vector points) { + Points int_points; + for (auto pt : points) + int_points.push_back(Point::new_scale(pt.x, pt.y)); + return Polygon(int_points); + } Polygon& operator=(const Polygon &other) { points = other.points; return *this; } Polygon& operator=(Polygon &&other) { points = std::move(other.points); return *this; } diff --git a/xs/src/slic3r/GUI/2DBed.cpp b/xs/src/slic3r/GUI/2DBed.cpp new file mode 100644 index 000000000..f89514d03 --- /dev/null +++ b/xs/src/slic3r/GUI/2DBed.cpp @@ -0,0 +1,167 @@ +#include "2DBed.hpp"; + +#include +#include "BoundingBox.hpp" +#include "Geometry.hpp" + +namespace Slic3r { +namespace GUI { + +void Bed_2D::repaint() +{ +// auto dc = new wxAutoBufferedPaintDC(this); + wxClientDC dc(this); + auto cw = GetSize().GetWidth(); + auto ch = GetSize().GetHeight(); + // when canvas is not rendered yet, size is 0, 0 + if (cw == 0) return ; + + if (m_user_drawn_background) { + // On all systems the AutoBufferedPaintDC() achieves double buffering. + // On MacOS the background is erased, on Windows the background is not erased + // and on Linux / GTK the background is erased to gray color. + // Fill DC with the background on Windows & Linux / GTK. + auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); //GetSystemColour + dc.SetPen(/**new wxPen(color, 1, wxPENSTYLE_SOLID)*/*new wxPen(*new wxColour(0, 0, 0), 1, wxSOLID)); + dc.SetBrush(*new wxBrush(color, wxBRUSHSTYLE_SOLID)); + auto rect = GetUpdateRegion().GetBox(); + dc.DrawRectangle(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); + } + + // turn cw and ch from sizes to max coordinates +/* cw--; + ch--; + + auto cbb = BoundingBoxf(Pointf(0, 0),Pointf(cw, ch)); + // leave space for origin point + cbb.min.translate(4, 0); // cbb.set_x_min(cbb.min.x + 4); + cbb.max.translate(-4, -4); // cbb.set_x_max(cbb.max.x - 4);cbb.set_y_max(cbb.max.y - 4); + + // leave space for origin label + cbb.max.translate(0, -13); // $cbb->set_y_max($cbb->y_max - 13); + + // read new size + cw = cbb.size().x; + ch = cbb.size().y; + + auto ccenter = cbb.center(); + + // get bounding box of bed shape in G - code coordinates + auto bed_shape = m_bed_shape; + auto bed_polygon = Polygon::new_scale(m_bed_shape); + auto bb = BoundingBoxf(m_bed_shape); + bb.merge(Pointf(0, 0)); // origin needs to be in the visible area + auto bw = bb.size().x; + auto bh = bb.size().y; + auto bcenter = bb.center(); + + // calculate the scaling factor for fitting bed shape in canvas area + auto sfactor = std::min(cw/bw, ch/bh); + auto shift = Pointf( + ccenter.x - bcenter.x * sfactor, + ccenter.y - bcenter.y * sfactor + ); + m_scale_factor = sfactor; + m_shift = Pointf(shift.x + cbb.min.x, + shift.y - (cbb.max.y - GetSize().GetHeight())); + + // draw bed fill +// { + dc->SetPen(*new wxPen(*new wxColour(0, 0, 0), 1, wxSOLID)); + dc->SetBrush(*new wxBrush(*new wxColour(255, 255, 255), wxSOLID)); + wxPointList pt_list; + for (auto pt: m_bed_shape) + { + Point pt_pix = to_pixels(pt); + pt_list.push_back(new wxPoint(pt_pix.x, pt_pix.y)); + } + dc->DrawPolygon(&pt_list, 0, 0); +// } +*/ + // draw grid +// { +// auto step = 10; // 1cm grid +// Polylines polylines; +// for (auto x = bb.min.x - (bb.min.x % step) + step; x < bb.max.x; x += step) { +// // push @polylines, Slic3r::Polyline->new_scale([$x, $bb->y_min], [$x, $bb->y_max]); +// } +// for (auto y = bb.min.y - (bb.min.y % step) + step; y < bb.max.y; y += step) { +// // push @polylines, Slic3r::Polyline->new_scale([$bb->x_min, $y], [$bb->x_max, $y]); +// } +// // @polylines = @{intersection_pl(\@polylines, [$bed_polygon])}; +// +// dc->SetPen(*new wxPen(*new wxColour(230, 230, 230), 1, wxSOLID)); +// // for (auto pl: polylines) +// // dc->DrawLine(map @{$self->to_pixels([map unscale($_), @$_])}, @$_[0, -1]); +// } +// +// // draw bed contour +// { +// dc->SetPen(*new wxPen(*new wxColour(0, 0, 0), 1, wxSOLID)); +// dc->SetBrush(*new wxBrush(*new wxColour(255, 255, 255), wxTRANSPARENT)); +// // dc->DrawPolygon([map $self->to_pixels($_), @$bed_shape], 0, 0); +// } + +// auto origin_px = to_pixels(Pointf(0, 0)); +// +// // draw axes +// { +// auto axes_len = 50; +// auto arrow_len = 6; +// auto arrow_angle = Geometry::deg2rad(45); +// dc->SetPen(*new wxPen(*new wxColour(255, 0, 0), 2, wxSOLID)); // red +// auto x_end = Pointf(origin_px.x + axes_len, origin_px.y); +// dc->DrawLine(wxPoint(origin_px), wxPoint(x_end)); +// foreach my $angle(-$arrow_angle, +$arrow_angle) { +// auto end = x_end.clone; +// end->translate(-arrow_len, 0); +// end->rotate(angle, x_end); +// dc->DrawLine(x_end, end); +// } +// +// dc->SetPen(*new wxPen(*new wxColour(0, 255, 0), 2, wxSOLID)); // green +// auto y_end = Pointf(origin_px.x, origin_px.y - axes_len); +// dc->DrawLine(origin_px, y_end); +// foreach my $angle(-$arrow_angle, +$arrow_angle) { +// auto end = y_end->clone; +// end->translate(0, +arrow_len); +// end->rotate(angle, y_end); +// dc->DrawLine(y_end, end); +// } +// } +// +// // draw origin +// { +// dc->SetPen(*new wxPen(*new wxColour(0, 0, 0), 1, wxSOLID)); +// dc->SetBrush(*new wxBrush(*new wxColour(0, 0, 0), wxSOLID)); +// dc->DrawCircle(origin_px.x, origin_px.y, 3); +// +// dc->SetTextForeground(*new wxColour(0, 0, 0)); +// dc->SetFont(*new wxFont(10, wxDEFAULT, wxNORMAL, wxNORMAL)); +// dc->DrawText("(0,0)", origin_px.x + 1, origin_px.y + 2); +// } +// +// // draw current position +// if (m_pos) { +// auto pos_px = to_pixels(m_pos); +// dc->SetPen(*new wxPen(*new wxColour(200, 0, 0), 2, wxSOLID)); +// dc->SetBrush(*new wxBrush(*new wxColour(200, 0, 0), wxTRANSPARENT)); +// dc->DrawCircle(pos_px, 5); +// +// dc->DrawLine(pos_px.x - 15, pos_px.y, pos_px.x + 15, pos_px.y); +// dc->DrawLine(pos_px.x, pos_px.y - 15, pos_px.x, pos_px.y + 15); +// } + + m_painted = true; +} + +// convert G - code coordinates into pixels +Point Bed_2D::to_pixels(Pointf point){ + auto p = Pointf(point); + p.scale(m_scale_factor); + p.translate(m_shift); + return Point(p.x, GetSize().GetHeight() - p.y); +} + +} // GUI +} // Slic3r \ No newline at end of file diff --git a/xs/src/slic3r/GUI/2DBed.hpp b/xs/src/slic3r/GUI/2DBed.hpp new file mode 100644 index 000000000..942edd8d3 --- /dev/null +++ b/xs/src/slic3r/GUI/2DBed.hpp @@ -0,0 +1,40 @@ +#include +#include "Config.hpp" + +namespace Slic3r { +namespace GUI { + +class Bed_2D : public wxPanel +{ + bool m_user_drawn_background = false; + + bool m_painted = false; + double m_scale_factor; + Pointf m_shift; + Point m_pos; + + Point to_pixels(Pointf point); + void repaint(); +public: + Bed_2D(wxWindow* parent) + { + Create(parent, wxID_ANY, wxDefaultPosition, wxSize(250, -1), wxTAB_TRAVERSAL); +// m_user_drawn_background = $^O ne 'darwin'; + m_user_drawn_background = true; + Bind(wxEVT_PAINT, ([this](wxPaintEvent e) + { + repaint(); + })); +// EVT_ERASE_BACKGROUND($self, sub{}) if $self->{user_drawn_background}; +// Bind(wxEVT_MOUSE_EVENTS, ([this](wxCommandEvent){/*mouse_event()*/; })); + Bind(wxEVT_SIZE, ([this](wxSizeEvent){Refresh(); })); + } + ~Bed_2D(){} + + std::vector m_bed_shape; + +}; + + +} // GUI +} // Slic3r diff --git a/xs/src/slic3r/GUI/BedShapeDialog.cpp b/xs/src/slic3r/GUI/BedShapeDialog.cpp new file mode 100644 index 000000000..e05702918 --- /dev/null +++ b/xs/src/slic3r/GUI/BedShapeDialog.cpp @@ -0,0 +1,314 @@ +#include "BedShapeDialog.hpp" + +#include +#include +#include +#include "Polygon.hpp" +#include "BoundingBox.hpp" +#include + +namespace Slic3r { +namespace GUI { + +void BedShapeDialog::build_dialog(ConfigOptionPoints* default_pt) +{ + m_panel = new BedShapePanel(this); + m_panel->build_panel(default_pt); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(m_panel, 1, wxEXPAND); + main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, /*wxEXPAND*/wxALIGN_CENTER_HORIZONTAL | wxBOTTOM/*ALL*/, 10); + + SetSizer(main_sizer); + SetMinSize(GetSize()); + main_sizer->SetSizeHints(this); + + // needed to actually free memory + this->Bind(wxEVT_CLOSE_WINDOW, ([this](wxCloseEvent e){ + EndModal(wxID_OK); + Destroy(); + })); +} + +void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) +{ +// on_change(nullptr); + + auto box = new wxStaticBox(this, wxID_ANY, "Shape"); + auto sbsizer = new wxStaticBoxSizer(box, wxVERTICAL); + + // shape options + m_shape_options_book = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxSize(300, -1), wxCHB_TOP); + sbsizer->Add(m_shape_options_book); + + auto optgroup = init_shape_options_page("Rectangular"); + ConfigOptionDef def; + def.type = coPoints; + def.default_value = new ConfigOptionPoints{ Pointf(200, 200) }; + def.label = "Size"; + def.tooltip = "Size in X and Y of the rectangular plate."; + Option option(def, "rect_size"); + optgroup->append_single_option_line(option); + + def.type = coPoints; + def.default_value = new ConfigOptionPoints{ Pointf(0, 0) }; + def.label = "Origin"; + def.tooltip = "Distance of the 0,0 G-code coordinate from the front left corner of the rectangle."; + option = Option(def, "rect_origin"); + optgroup->append_single_option_line(option); + + optgroup = init_shape_options_page("Circular"); + def.type = coFloat; + def.default_value = new ConfigOptionFloat(200); + def.sidetext = "mm"; + def.label = "Diameter"; + def.tooltip = "Diameter of the print bed. It is assumed that origin (0,0) is located in the center."; + option = Option(def, "diameter"); + optgroup->append_single_option_line(option); + + optgroup = init_shape_options_page("Custom"); + Line line{ "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + auto btn = new wxButton(parent, wxID_ANY, "Load shape from STL...", wxDefaultPosition, wxDefaultSize); + + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) + { + load_stl(); + })); + + return sizer; + }; + optgroup->append_line(line); + + Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e) + { + update_shape(); + })); + + // right pane with preview canvas + m_canvas = new Bed_2D(this); + m_canvas->m_bed_shape = default_pt->values; + + // main sizer + auto top_sizer = new wxBoxSizer(wxHORIZONTAL); + top_sizer->Add(sbsizer, 0, wxEXPAND | wxLeft | wxTOP | wxBOTTOM, 10); + if (m_canvas) + top_sizer->Add(m_canvas, 1, wxEXPAND | wxALL, 10) ; + + SetSizerAndFit(top_sizer); + + set_shape(default_pt); + update_preview(); +} + +#define SHAPE_RECTANGULAR 0 +#define SHAPE_CIRCULAR 1 +#define SHAPE_CUSTOM 2 + +// Called from the constructor. +// Create a panel for a rectangular / circular / custom bed shape. +ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(std::string title){ + + auto panel = new wxPanel(m_shape_options_book); + ConfigOptionsGroupShp optgroup; + optgroup = std::make_shared(panel, "Settings"); + + optgroup->label_width = 100; + optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ + update_shape(); + }; + + m_optgroups.push_back(optgroup); + panel->SetSizerAndFit(optgroup->sizer); + m_shape_options_book->AddPage(panel, title); + + return optgroup; +} + +// Called from the constructor. +// Set the initial bed shape from a list of points. +// Deduce the bed shape type(rect, circle, custom) +// This routine shall be smart enough if the user messes up +// with the list of points in the ini file directly. +void BedShapePanel::set_shape(ConfigOptionPoints* points) +{ + auto polygon = Polygon::new_scale(points->values); + + // is this a rectangle ? + if (points->size() == 4) { + auto lines = polygon.lines(); + if (lines[0].parallel_to(lines[2]) && lines[1].parallel_to(lines[3])) { + // okay, it's a rectangle + // find origin + // the || 0 hack prevents "-0" which might confuse the user + int x_min, x_max, y_min, y_max; + x_max = x_min = points->values[0].x; + y_max = y_min = points->values[0].y; + for (auto pt : points->values){ + if (x_min > pt.x) x_min = pt.x; + if (x_max < pt.x) x_max = pt.x; + if (y_min > pt.y) y_min = pt.y; + if (y_max < pt.y) y_max = pt.y; + } + if (x_min < 0) x_min = 0; + if (x_max < 0) x_max = 0; + if (y_min < 0) y_min = 0; + if (y_max < 0) y_max = 0; +// auto x_min = min(map $_->[X], @$points) || 0; +// auto x_max = max(map $_->[X], @$points) || 0; +// auto y_min = min(map $_->[Y], @$points) || 0; +// auto y_max = max(map $_->[Y], @$points) || 0; +// auto origin = [-x_min, -y_min]; + auto origin = new ConfigOptionPoints{ Pointf(-x_min, -y_min) }; + + m_shape_options_book->SetSelection(SHAPE_RECTANGULAR); + auto optgroup = m_optgroups[SHAPE_RECTANGULAR]; + optgroup->set_value("rect_size", new ConfigOptionPoints{ Pointf(x_max - x_min, y_max - y_min) });//[x_max - x_min, y_max - y_min]); + optgroup->set_value("rect_origin", origin); + update_shape(); + return; + } + } + + // is this a circle ? + { + // Analyze the array of points.Do they reside on a circle ? +// auto polygon;// = Slic3r::Polygon->new_scale(@$points); + auto center = polygon.bounding_box().center();// ->bounding_box->center; +// auto /*@*/vertex_distances;// = map $center->distance_to($_), @$polygon; +// auto avg_dist = sum(/*@*/vertex_distances) / /*@*/vertex_distances; + std::vector vertex_distances;// = map $center->distance_to($_), @$polygon; + double avg_dist = 0; + for (auto pt: polygon.points) + { + double distance = center.distance_to(pt); + vertex_distances.push_back(distance); + avg_dist += distance; + } + + bool defined_value = true; + for (auto el: vertex_distances) + { + if (abs(el - avg_dist) > 10 * SCALED_EPSILON/*scaled_epsilon*/) + defined_value = false; + break; + } + if (defined_value/*!defined first{ abs($_ - $avg_dist) > 10 * scaled_epsilon } @vertex_distances*/) { + // all vertices are equidistant to center + m_shape_options_book->SetSelection(SHAPE_CIRCULAR); + auto optgroup = m_optgroups[SHAPE_CIRCULAR]; + boost::any ret = wxNumberFormatter::ToString(unscale(avg_dist * 2), 0); + optgroup->set_value("diameter", ret /*sprintf("%.0f", unscale(avg_dist * 2))*/); + update_shape(); + return; + } + } + + if (points->size() < 3) { + // Invalid polygon.Revert to default bed dimensions. + m_shape_options_book->SetSelection(SHAPE_RECTANGULAR); + auto optgroup = m_optgroups[SHAPE_RECTANGULAR]; + optgroup->set_value("rect_size", new ConfigOptionPoints{ Pointf(200, 200) }); + optgroup->set_value("rect_origin", new ConfigOptionPoints{ Pointf(0, 0) }); + update_shape(); + return; + } + + // This is a custom bed shape, use the polygon provided. + m_shape_options_book->SetSelection(SHAPE_CUSTOM); + // Copy the polygon to the canvas, make a copy of the array. + m_canvas->m_bed_shape = points->values; + update_shape(); +} + +void BedShapePanel::update_preview() +{ + if (m_canvas) m_canvas->Refresh(); + Refresh(); +} + +// Update the bed shape from the dialog fields. +void BedShapePanel::update_shape() +{ + auto page_idx = m_shape_options_book->GetSelection(); + if (page_idx == SHAPE_RECTANGULAR) { + auto rect_size = m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_size"); + auto rect_origin = m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_origin"); +/* auto x = rect_size->x; + auto y = rect_size->y; + // empty strings or '-' or other things +// if (!looks_like_number(x) || !looks_like_number(y)) return; + if ((!x || !y) || x == 0 || y == 0) return; +// my($x0, $y0) = (0, 0); +// my($x1, $y1) = ($x, $y); +// { +// my($dx, $dy) = @$rect_origin; +// return if !looks_like_number($dx) || !looks_like_number($dy); # empty strings or '-' or other things +// $x0 -= $dx; +// $x1 -= $dx; +// $y0 -= $dy; +// $y1 -= $dy; +// } +// m_canvas->bed_shape([ +// [$x0, $y0], +// [$x1, $y0], +// [$x1, $y1], +// [$x0, $y1], +// ]); + } + else if(page_idx == SHAPE_CIRCULAR) { +// auto diameter = m_optgroups[SHAPE_CIRCULAR]->get_value("diameter"); +// if (!diameter || diameter == 0) return ; +// r = diameter / 2; +// twopi = 2 * PI; +// edges = 60; +// polygon = Slic3r::Polygon->new_scale( +// map[$r * cos $_, $r * sin $_], +// map{ $twopi / $edges*$_ } 1..$edges +// ); +// m_canvas->bed_shape([ +// map[unscale($_->x), unscale($_->y)], @$polygon #)) +// ]); +*/ } + +// $self->{on_change}->(); + update_preview(); +} + +// Loads an stl file, projects it to the XY plane and calculates a polygon. +void BedShapePanel::load_stl() +{ + auto dialog = new wxFileDialog(this, "Choose a file to import bed shape from (STL/OBJ/AMF/PRUSA):", "", "", + wxFileSelectorDefaultWildcardStr/* &Slic3r::GUI::MODEL_WILDCARD*/, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (dialog->ShowModal() != wxID_OK) { + dialog->Destroy(); + return; + } + wxArrayString input_file; + dialog->GetPaths(input_file); + dialog->Destroy(); + +// auto model = Slic3r::Model->read_from_file(input_file); +// auto mesh = model->mesh; +// auto expolygons = mesh->horizontal_projection; +// +// if (expolygons.size() == 0) { +// show_error(this, "The selected file contains no geometry."); +// return; +// } +// if (expolygons.size() > 1) { +// show_error(this, "The selected file contains several disjoint areas. This is not supported."); +// return; +// } +// +// auto polygon = expolygons[0]->contour; +// m_canvas->bed_shape([map[unscale($_->x), unscale($_->y)], @$polygon]); + update_preview(); +} + +} // GUI +} // Slic3r diff --git a/xs/src/slic3r/GUI/BedShapeDialog.hpp b/xs/src/slic3r/GUI/BedShapeDialog.hpp new file mode 100644 index 000000000..b4849cbba --- /dev/null +++ b/xs/src/slic3r/GUI/BedShapeDialog.hpp @@ -0,0 +1,50 @@ +// The bed shape dialog. +// The dialog opens from Print Settins tab->Bed Shape : Set... + +#include "OptionsGroup.hpp" +#include "2DBed.hpp" + + +#include +#include + +namespace Slic3r { +namespace GUI { + +using ConfigOptionsGroupShp = std::shared_ptr; +class BedShapePanel : public wxPanel +{ + wxChoicebook* m_shape_options_book; + Bed_2D* m_canvas; + + std::vector m_optgroups; + +public: + BedShapePanel(wxWindow* parent) : wxPanel(parent, wxID_ANY){} + ~BedShapePanel(){} + + void build_panel(ConfigOptionPoints* default_pt); + + // Returns the resulting bed shape polygon. This value will be stored to the ini file. + int GetValue() { return 1/*m_canvas->bed_shape*/; } + ConfigOptionsGroupShp init_shape_options_page(std::string title); + void set_shape(ConfigOptionPoints* points); + void update_preview(); + void update_shape(); + void load_stl(); +}; + +class BedShapeDialog : public wxDialog +{ + BedShapePanel* m_panel; +public: + BedShapeDialog(wxWindow* parent) : wxDialog(parent, wxID_ANY, "Bed Shape", + wxDefaultPosition, wxSize(350, 700), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER){} + ~BedShapeDialog(){} + + void build_dialog(ConfigOptionPoints* default_pt); + int GetValue() { return m_panel->GetValue(); } +}; + +} // GUI +} // Slic3r diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index fd4c5f8c9..e4b81116e 100644 --- a/xs/src/slic3r/GUI/Field.cpp +++ b/xs/src/slic3r/GUI/Field.cpp @@ -404,8 +404,19 @@ boost::any Choice::get_value() else { int ret_enum = static_cast(window)->GetSelection(); - if (m_opt_id.compare("external_fill_pattern") == 0 || - m_opt_id.compare("fill_pattern") == 0) + if (m_opt_id.compare("external_fill_pattern") == 0) + { + if (!m_opt.enum_values.empty()){ + std::string key = m_opt.enum_values[ret_enum]; + t_config_enum_values map_names = ConfigOptionEnum::get_enum_values(); + int value = map_names.at(key); + + ret_val = static_cast(value); + } + else + ret_val = static_cast(0); + } + if (m_opt_id.compare("fill_pattern") == 0) ret_val = static_cast(ret_enum); else if (m_opt_id.compare("gcode_flavor") == 0) ret_val = static_cast(ret_enum); @@ -436,7 +447,7 @@ void ColourPicker::BUILD() } -void Point::BUILD() +void PointCtrl::BUILD() { auto size = wxSize(wxDefaultSize); if (m_opt.height >= 0) size.SetHeight(m_opt.height); @@ -456,9 +467,9 @@ void Point::BUILD() x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size); y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size); - temp->Add(new wxStaticText(m_parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); + temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : ")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); temp->Add(x_textctrl); - temp->Add(new wxStaticText(m_parent, wxID_ANY, " y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); + temp->Add(new wxStaticText(m_parent, wxID_ANY, " y : ")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); temp->Add(y_textctrl); x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); @@ -474,7 +485,7 @@ void Point::BUILD() } } -void Point::set_value(const Pointf value) +void PointCtrl::set_value(const Pointf value) { m_disable_change_event = true; @@ -486,7 +497,27 @@ void Point::set_value(const Pointf value) m_disable_change_event = false; } -boost::any Point::get_value() +void PointCtrl::set_value(boost::any value) +{ + Pointf pt; + try + { + pt = boost::any_cast(value)->values.at(0); + } + catch (const std::exception &e) + { + try{ + pt = boost::any_cast(value); + } + catch (const std::exception &e) + { + int i=0; + } + } + set_value(pt); +} + +boost::any PointCtrl::get_value() { Pointf ret_point; double val; diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp index ca2e7a57a..6e46a45f0 100644 --- a/xs/src/slic3r/GUI/Field.hpp +++ b/xs/src/slic3r/GUI/Field.hpp @@ -80,7 +80,7 @@ public: virtual wxWindow* getWindow() { return nullptr; } bool is_matched(std::string string, std::string pattern); - boost::any get_value_by_opt_type(wxString str, ConfigOptionType type); + boost::any get_value_by_opt_type(wxString str, ConfigOptionType type); /// Factory method for generating new derived classes. template @@ -226,11 +226,11 @@ public: void set_tooltip(const wxString& tip) override {}; //! Redundant }; -class Point : public Field { +class PointCtrl : public Field { using Field::Field; public: - Point(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} - Point(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} + PointCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} + PointCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} wxSizer* sizer{ nullptr }; wxTextCtrl* x_textctrl; @@ -239,9 +239,7 @@ public: void BUILD() override; void set_value(const Pointf value); - void set_value(boost::any value) { -// dynamic_cast(sizer)->SetColour(boost::any_cast(value)); - } + void set_value(boost::any value); boost::any get_value() override; void enable() override { diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 2503bbb5b..439033ce7 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -246,13 +246,13 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b break; case coStrings:{ if (opt_key.compare("compatible_printers") == 0){ - config.option(opt_key)->values.resize(0); - for (auto el : boost::any_cast>(value)) - config.option(opt_key)->values.push_back(el); + config.option(opt_key)->values.resize(0); + for (auto el : boost::any_cast>(value)) + config.option(opt_key)->values.push_back(el); } else{ - ConfigOptionStrings* vec_new = new ConfigOptionStrings{ boost::any_cast(value) }; - config.option(opt_key)->set_at(vec_new, 0, 0); + ConfigOptionStrings* vec_new = new ConfigOptionStrings{ boost::any_cast(value) }; + config.option(opt_key)->set_at(vec_new, 0, 0); } } break; @@ -302,39 +302,6 @@ void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_con panel->m_no_controller = app_config->get("no_controller").empty(); panel->m_show_btn_incompatible_presets = app_config->get("show_incompatible_presets").empty(); panel->create_preset_tab(preset_bundle); - // Callback to be executed after any of the configuration fields(Perl class Slic3r::GUI::OptionsGroup::Field) change their value. -// panel->m_on_value_change = [/*this*/](std::string opt_key, boost::any value){ - //! plater & loaded - variables of MainFrame -// if (plater) { -// plater->on_config_change(m_config); //# propagate config change events to the plater -// if (opt_key.compare("extruders_count") plater->on_extruders_change(value); -// } - // don't save while loading for the first time -// if (loaded && Slic3r::GUI::autosave) m_config->save(Slic3r::GUI::autosave) ; -// }; - - // Install a callback for the tab to update the platter and print controller presets, when - // a preset changes at Slic3r::GUI::Tab. -// panel->m_on_presets_changed = [](){ -// if ($self->{plater}) { -// # Update preset combo boxes(Print settings, Filament, Printer) from their respective tabs. -// $self->{plater}->update_presets($tab_name, @_); -// if ($tab_name eq 'printer') { -// # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. -// my($presets, $reload_dependent_tabs) = @_; -// for my $tab_name_other(qw(print filament)) { -// # If the printer tells us that the print or filament preset has been switched or invalidated, -// # refresh the print or filament tab page.Otherwise just refresh the combo box. -// my $update_action = ($reload_dependent_tabs && (first{ $_ eq $tab_name_other } (@{$reload_dependent_tabs}))) -// ? 'load_current_preset' : 'update_tab_ui'; -// $self->{options_tabs}{$tab_name_other}->$update_action; -// } -// # Update the controller printers. -// $self->{controller}->update_presets(@_) if $self->{controller}; -// } -// $self->{plater}->on_config_change($tab->{presets}->get_current_preset->config); -// } -// }; // Load the currently selected preset into the GUI, update the preset selection box. panel->load_current_preset(); diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index bf1cd8eb4..014dfe41d 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -52,7 +52,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); break; case coPoints: - m_fields.emplace(id, STDMOVE(Point::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(PointCtrl::Create(m_parent, opt, id))); break; case coNone: break; default: diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp index 66d521f7c..0aaee59e3 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.hpp +++ b/xs/src/slic3r/GUI/OptionsGroup.hpp @@ -98,8 +98,8 @@ public: inline void enable() { for (auto& field : m_fields) field.second->enable(); } inline void disable() { for (auto& field : m_fields) field.second->disable(); } - OptionsGroup(wxWindow* _parent, std::string title, const ConfigDef& configs) : - m_optiondefs(configs.options), m_parent(_parent), title(wxString(title)) { + OptionsGroup(wxWindow* _parent, std::string title) : + m_parent(_parent), title(wxString(title)) { sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); auto num_columns = 1U; if (label_width != 0) num_columns++; @@ -112,7 +112,6 @@ public: } protected: - const t_optiondef_map& m_optiondefs; //#WHY std::map m_options; wxWindow* m_parent {nullptr}; @@ -136,8 +135,8 @@ protected: class ConfigOptionsGroup: public OptionsGroup { public: - ConfigOptionsGroup(wxWindow* parent, std::string title, DynamicPrintConfig* _config) : - OptionsGroup(parent, title, *_config->def()), m_config(_config) {} + ConfigOptionsGroup(wxWindow* parent, std::string title, DynamicPrintConfig* _config = nullptr) : + OptionsGroup(parent, title), m_config(_config) {} /// reference to libslic3r config, non-owning pointer (?). DynamicPrintConfig* m_config {nullptr}; diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 9d3e23474..f06dcbd10 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -1,4 +1,9 @@ #include "../../libslic3r/GCodeSender.hpp" +#include "Tab.hpp" +#include "PresetBundle.hpp" +#include "PresetHints.hpp" +#include "../../libslic3r/Utils.hpp" + #include #include #include @@ -11,10 +16,6 @@ #include #include -#include "Tab.hpp" -#include "PresetBundle.hpp" -#include "PresetHints.hpp" -#include "../../libslic3r/Utils.hpp" #include namespace Slic3r { @@ -86,7 +87,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) m_treectrl->Bind(wxEVT_COMBOBOX, &Tab::OnComboBox, this); m_presets_choice->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e){ - select_preset(static_cast(m_presets_choice)->GetStringSelection()); + select_preset(static_cast(m_presets_choice)->GetStringSelection().ToStdString()); })); m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e){ save_preset(); })); @@ -273,15 +274,20 @@ extern wxFrame *g_wxMainFrame; void Tab::on_value_change(std::string opt_key, boost::any value) { -// if (m_on_value_change != nullptr) -// m_on_value_change(opt_key, value); if (m_event_value_change > 0) { wxCommandEvent event(m_event_value_change); - event.SetString(opt_key); + std::string str_out = opt_key + " " + m_title; + event.SetString(str_out); + if (opt_key == "extruders_count") + { + int val = boost::any_cast(value); + event.SetInt(val); + } + g_wxMainFrame->ProcessWindowEvent(event); } update(); -}; +} // Call a callback to update the selection of presets on the platter: // To update the content of the selection boxes, @@ -290,11 +296,9 @@ void Tab::on_value_change(std::string opt_key, boost::any value) // to uddate number of "filament" selection boxes when the number of extruders change. void Tab::on_presets_changed(/*std::vector reload_dependent_tabs*/) { -// if (m_on_presets_changed != nullptr) -// m_on_presets_changed(/*m_presets, reload_dependent_tabs*/); if (m_event_presets_changed > 0) { wxCommandEvent event(m_event_presets_changed); - //event.SetString(opt_key); + event.SetString(m_title); g_wxMainFrame->ProcessWindowEvent(event); } } @@ -919,6 +923,11 @@ wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticTex return sizer; } +bool Tab::current_preset_is_dirty() +{ + return m_presets->current_is_dirty(); +} + void TabPrinter::build() { m_presets = &m_preset_bundle->printers; @@ -932,7 +941,7 @@ void TabPrinter::build() auto optgroup = page->new_optgroup("Size and coordinates"); Line line = { "Bed shape", "" }; - line.widget = [](wxWindow* parent){ + line.widget = [this](wxWindow* parent){ auto btn = new wxButton(parent, wxID_ANY, "Set\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); // btn->SetFont(Slic3r::GUI::small_font); @@ -941,11 +950,13 @@ void TabPrinter::build() auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, ([](wxCommandEvent e) + btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { - // auto dlg = new BedShapeDialog->new($self, $self->{config}->bed_shape); - // if (dlg->ShowModal == wxID_OK) - ;// load_key_value_("bed_shape", dlg->GetValue); + auto dlg = new BedShapeDialog(this); + dlg->build_dialog(m_config->option("bed_shape")); + if (dlg->ShowModal() == wxID_OK) +// load_key_value("bed_shape", dlg->GetValue()); + ; })); return sizer; @@ -1336,10 +1347,10 @@ void Tab::load_current_preset() // and we don't want them to be called after this update_dirty() as they would mark the // preset dirty again // (not sure this is true anymore now that update_dirty is idempotent) - wxTheApp->CallAfter([this]{ +// wxTheApp->CallAfter([this]{ update_tab_ui(); on_presets_changed(); - }); +// }); } //Regerenerate content of the page tree. @@ -1372,9 +1383,9 @@ void Tab::rebuild_page_tree() // Called by the UI combo box when the user switches profiles. // Select a preset by a name.If !defined(name), then the default preset is selected. // If the current profile is modified, user is asked to save the changes. -void Tab::select_preset(wxString preset_name) +void Tab::select_preset(std::string preset_name /*= ""*/) { - std::string name = preset_name.ToStdString(); + std::string name = preset_name/*.ToStdString()*/; auto force = false; auto presets = m_presets; // If no name is provided, select the "-- default --" preset. @@ -1407,12 +1418,12 @@ void Tab::select_preset(wxString preset_name) if (!canceled) { if (!print_preset_compatible) { // The preset will be switched to a different, compatible preset, or the '-- default --'. - m_reload_dependent_tabs.push_back("Print"); + m_reload_dependent_tabs.push_back("print"); if (print_preset_dirty) print_presets->discard_current_changes(); } if (!filament_preset_compatible) { // The preset will be switched to a different, compatible preset, or the '-- default --'. - m_reload_dependent_tabs.push_back("Filament"); + m_reload_dependent_tabs.push_back("filament"); if (filament_preset_dirty) filament_presets->discard_current_changes(); } } diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index 14c84af08..38856b9ba 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -26,7 +26,7 @@ #include #include -#include "OptionsGroup.hpp" +#include "BedShapeDialog.hpp" //!enum { ID_TAB_TREE = wxID_HIGHEST + 1 }; @@ -128,7 +128,7 @@ public: void create_preset_tab(PresetBundle *preset_bundle); void load_current_preset(); void rebuild_page_tree(); - void select_preset(wxString preset_name = ""); + void select_preset(std::string preset_name = ""); bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, std::string new_printer_name = ""); wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); @@ -137,7 +137,8 @@ public: void OnTreeSelChange(wxTreeEvent& event); void OnKeyDown(wxKeyEvent& event); - void OnComboBox(wxCommandEvent& event) { select_preset(static_cast(m_presets_choice)->GetStringSelection()); } + void OnComboBox(wxCommandEvent& event) { + select_preset(static_cast(m_presets_choice)->GetStringSelection().ToStdString()); } void save_preset(std::string name = ""); void delete_preset(); void toggle_show_hide_incompatible(); @@ -157,6 +158,11 @@ public: Field* get_field(t_config_option_key opt_key, int opt_index = -1) const; bool set_value(t_config_option_key opt_key, boost::any value); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); + bool current_preset_is_dirty(); + DynamicPrintConfig* get_config() { return m_config; } + PresetCollection* get_presets() { return m_presets; } + std::vector get_dependent_tabs() { + return m_reload_dependent_tabs; } void on_value_change(std::string opt_key, boost::any value); diff --git a/xs/src/slic3r/GUI/TabIface.cpp b/xs/src/slic3r/GUI/TabIface.cpp index 141fdbe64..3d311f43f 100644 --- a/xs/src/slic3r/GUI/TabIface.cpp +++ b/xs/src/slic3r/GUI/TabIface.cpp @@ -3,7 +3,15 @@ namespace Slic3r { -void TabIface::load_current_preset() { m_tab->load_current_preset(); } -void TabIface::rebuild_page_tree() { m_tab->rebuild_page_tree(); } +void TabIface::load_current_preset() { m_tab->load_current_preset(); } +void TabIface::update_tab_ui() { m_tab->update_tab_ui(); } +void TabIface::update_ui_from_settings() { m_tab->update_ui_from_settings();} +void TabIface::select_preset(char* name) { m_tab->select_preset(name);} +char* TabIface::title() { return (char*)m_tab->title().ToStdString()/*ToUTF8()*/.data();} +void TabIface::load_config(DynamicPrintConfig* config) { m_tab->load_config(*config);} +bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_dirty();} +DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config();} +PresetCollection* TabIface::get_presets() { return m_tab->get_presets(); } +std::vector TabIface::get_dependent_tabs() { return m_tab->get_dependent_tabs(); } }; // namespace Slic3r diff --git a/xs/src/slic3r/GUI/TabIface.hpp b/xs/src/slic3r/GUI/TabIface.hpp index a77cb7255..12ceb93c0 100644 --- a/xs/src/slic3r/GUI/TabIface.hpp +++ b/xs/src/slic3r/GUI/TabIface.hpp @@ -1,16 +1,30 @@ +#include + namespace Slic3r { + class DynamicPrintConfig; + class PresetCollection; namespace GUI { class Tab; -}; +} class TabIface { public: TabIface() : m_tab(nullptr) {} TabIface(GUI::Tab *tab) : m_tab(tab) {} // TabIface(const TabIface &rhs) : m_tab(rhs.m_tab) {} - void load_current_preset(); - void rebuild_page_tree(); + + void load_current_preset(); + void update_tab_ui(); + void update_ui_from_settings(); + void select_preset(char* name); + char* title(); + void load_config(DynamicPrintConfig* config); + bool current_preset_is_dirty(); + DynamicPrintConfig* get_config(); + PresetCollection* TabIface::get_presets(); + std::vector TabIface::get_dependent_tabs(); + protected: GUI::Tab *m_tab; }; diff --git a/xs/xsp/GUI_Tab.xsp b/xs/xsp/GUI_Tab.xsp index a557e0f19..d71dfa3d9 100644 --- a/xs/xsp/GUI_Tab.xsp +++ b/xs/xsp/GUI_Tab.xsp @@ -8,6 +8,14 @@ %name{Slic3r::GUI::Tab2} class TabIface { TabIface(); ~TabIface(); - void load_current_preset(); - void rebuild_page_tree(); + void load_current_preset(); + void update_tab_ui(); + void update_ui_from_settings(); + void select_preset(char* name); + void load_config(DynamicPrintConfig* config); + bool current_preset_is_dirty(); + char* title(); + Ref get_config(); + Ref get_presets(); + std::vector get_dependent_tabs(); };