Merge with bibnikv.
Added some functions to TabIface. Added BedShapeDialog & Bed2D classes. Added new_scale to Polygon. In class Field: Point renamed to PointCtrl and added set_value for PointCtrl, extended get_value for Choice.
This commit is contained in:
parent
a1705c093b
commit
f0b035059a
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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<Pointf> 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; }
|
||||
|
||||
|
167
xs/src/slic3r/GUI/2DBed.cpp
Normal file
167
xs/src/slic3r/GUI/2DBed.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
#include "2DBed.hpp";
|
||||
|
||||
#include <wx/dcbuffer.h>
|
||||
#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
|
40
xs/src/slic3r/GUI/2DBed.hpp
Normal file
40
xs/src/slic3r/GUI/2DBed.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include <wx/wx.h>
|
||||
#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<Pointf> m_bed_shape;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
314
xs/src/slic3r/GUI/BedShapeDialog.cpp
Normal file
314
xs/src/slic3r/GUI/BedShapeDialog.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
#include "BedShapeDialog.hpp"
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/wx.h>
|
||||
#include "Polygon.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include <wx/numformatter.h>
|
||||
|
||||
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<ConfigOptionsGroup>(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<double> 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
|
50
xs/src/slic3r/GUI/BedShapeDialog.hpp
Normal file
50
xs/src/slic3r/GUI/BedShapeDialog.hpp
Normal file
@ -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 <wx/dialog.h>
|
||||
#include <wx/choicebk.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
|
||||
class BedShapePanel : public wxPanel
|
||||
{
|
||||
wxChoicebook* m_shape_options_book;
|
||||
Bed_2D* m_canvas;
|
||||
|
||||
std::vector <ConfigOptionsGroupShp> 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
|
@ -404,8 +404,19 @@ boost::any Choice::get_value()
|
||||
else
|
||||
{
|
||||
int ret_enum = static_cast<wxComboBox*>(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<InfillPattern>::get_enum_values();
|
||||
int value = map_names.at(key);
|
||||
|
||||
ret_val = static_cast<InfillPattern>(value);
|
||||
}
|
||||
else
|
||||
ret_val = static_cast<InfillPattern>(0);
|
||||
}
|
||||
if (m_opt_id.compare("fill_pattern") == 0)
|
||||
ret_val = static_cast<InfillPattern>(ret_enum);
|
||||
else if (m_opt_id.compare("gcode_flavor") == 0)
|
||||
ret_val = static_cast<GCodeFlavor>(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<ConfigOptionPoints*>(value)->values.at(0);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
try{
|
||||
pt = boost::any_cast<Pointf>(value);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
int i=0;
|
||||
}
|
||||
}
|
||||
set_value(pt);
|
||||
}
|
||||
|
||||
boost::any PointCtrl::get_value()
|
||||
{
|
||||
Pointf ret_point;
|
||||
double val;
|
||||
|
@ -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<class T>
|
||||
@ -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<wxColourPickerCtrl*>(sizer)->SetColour(boost::any_cast<std::string>(value));
|
||||
}
|
||||
void set_value(boost::any value);
|
||||
boost::any get_value() override;
|
||||
|
||||
void enable() override {
|
||||
|
@ -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<ConfigOptionStrings>(opt_key)->values.resize(0);
|
||||
for (auto el : boost::any_cast<std::vector<std::string>>(value))
|
||||
config.option<ConfigOptionStrings>(opt_key)->values.push_back(el);
|
||||
config.option<ConfigOptionStrings>(opt_key)->values.resize(0);
|
||||
for (auto el : boost::any_cast<std::vector<std::string>>(value))
|
||||
config.option<ConfigOptionStrings>(opt_key)->values.push_back(el);
|
||||
}
|
||||
else{
|
||||
ConfigOptionStrings* vec_new = new ConfigOptionStrings{ boost::any_cast<std::string>(value) };
|
||||
config.option<ConfigOptionStrings>(opt_key)->set_at(vec_new, 0, 0);
|
||||
ConfigOptionStrings* vec_new = new ConfigOptionStrings{ boost::any_cast<std::string>(value) };
|
||||
config.option<ConfigOptionStrings>(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();
|
||||
|
@ -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<Choice>(m_parent, opt, id)));
|
||||
break;
|
||||
case coPoints:
|
||||
m_fields.emplace(id, STDMOVE(Point::Create<Point>(m_parent, opt, id)));
|
||||
m_fields.emplace(id, STDMOVE(PointCtrl::Create<PointCtrl>(m_parent, opt, id)));
|
||||
break;
|
||||
case coNone: break;
|
||||
default:
|
||||
|
@ -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<t_config_option_key, Option> 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};
|
||||
|
@ -1,4 +1,9 @@
|
||||
#include "../../libslic3r/GCodeSender.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PresetHints.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/scrolwin.h>
|
||||
@ -11,10 +16,6 @@
|
||||
#include <wx/imaglist.h>
|
||||
#include <wx/settings.h>
|
||||
|
||||
#include "Tab.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PresetHints.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
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<const wxComboBox*>(m_presets_choice)->GetStringSelection());
|
||||
select_preset(static_cast<const wxComboBox*>(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<size_t>(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<std::string> 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<ConfigOptionPoints>("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();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#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<const wxComboBox*>(m_presets_choice)->GetStringSelection()); }
|
||||
void OnComboBox(wxCommandEvent& event) {
|
||||
select_preset(static_cast<const wxComboBox*>(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<std::string> get_dependent_tabs() {
|
||||
return m_reload_dependent_tabs; }
|
||||
|
||||
void on_value_change(std::string opt_key, boost::any value);
|
||||
|
||||
|
@ -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<std::string> TabIface::get_dependent_tabs() { return m_tab->get_dependent_tabs(); }
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
@ -1,16 +1,30 @@
|
||||
#include <vector>
|
||||
|
||||
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<std::string> TabIface::get_dependent_tabs();
|
||||
|
||||
protected:
|
||||
GUI::Tab *m_tab;
|
||||
};
|
||||
|
@ -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<DynamicPrintConfig> get_config();
|
||||
Ref<PresetCollection> get_presets();
|
||||
std::vector<std::string> get_dependent_tabs();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user