Skip to content

Commit

Permalink
Add Field graph type
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Jun 26, 2024
1 parent e5c4369 commit 982409c
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 71 deletions.
2 changes: 1 addition & 1 deletion resources/ui_layout/default/extruder.ui
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ group:Offsets (for multi-extruder printers)
setting:idx:extruder_offset
setting:idx:extruder_temperature_offset
setting:idx:extruder_fan_offset
extruder_extrusion_multiplier_speed
setting:idx:extruder_extrusion_multiplier_speed
group:Retraction
setting:idx:retract_length
setting:idx:retract_lift
Expand Down
19 changes: 19 additions & 0 deletions src/libslic3r/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,22 @@ namespace Slic3r {
}
};

struct GraphSettings
{
std::string title;
std::string description;
std::string y_label;
std::string x_label;
std::string null_label;
double min_x, max_x, step_x;
double min_y, max_y, step_y;
std::string label_min_x;
std::string label_max_x;
std::string label_min_y;
std::string label_max_y;
std::vector<GraphData::GraphType> allowed_types;
GraphData reset_vals;
};
}

namespace std {
Expand Down Expand Up @@ -2715,6 +2731,9 @@ class ConfigOptionDef
// For enums (when type == coEnum). Maps enum_values to enums.
// Initialized by ConfigOptionEnum<xxx>::get_enum_values()
const t_config_enum_values *enum_keys_map = nullptr;

// Initialized by ConfigOptionEnum<xxx>::get_enum_values()
std::shared_ptr<GraphSettings> graph_settings;

// for scripted gui widgets
// true if it's not a real option but a simplified/composite one that use angelscript for interaction.
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/LocalesUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ std::string to_string_nozero(double value, int32_t max_precision) {
double intpart;
if (modf(value, &intpart) == 0.0) {
//shortcut for int
return std::to_string(intpart);
return std::to_string(int64_t(intpart));
} else {
std::stringstream ss;
//first, get the int part, to see how many digit it takes
Expand Down
21 changes: 19 additions & 2 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,9 +1724,26 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("This string is edited by a Dialog and contains extusion multiplier for different speeds.");
def->mode = comExpert | comSuSi;
def->is_vector_extruder = true;
def->set_default_value((new ConfigOptionGraphs( GraphData(0,10,
def->set_default_value(new ConfigOptionGraphs( GraphData(0,10, GraphData::GraphType::LINEAR,
{{10,1.},{20,1.},{30,1.},{40,1.},{60,1.},{80,1.},{120,1.},{160,1.},{240,1.},{320,1.},{480,1.},{640,1.},{960,1.},{1280,1.}}
)))->set_enabled(false));
)));
def->graph_settings = std::make_shared<GraphSettings>();
def->graph_settings->title = L("Extrusion multiplier per extrusion speed");
def->graph_settings->description = L("Choose the extrusion multipler value for multiple speeds.\nYou can add/remove points with a right clic.");
def->graph_settings->x_label = L("Print speed (mm/s)");
def->graph_settings->y_label = L("Extrusion multiplier");
def->graph_settings->null_label = L("No compensation");
def->graph_settings->label_min_x = L("Graph min speed");
def->graph_settings->label_max_x = L("Graph max speed");
def->graph_settings->label_min_y = L("Minimum flow");
def->graph_settings->label_max_y = L("Maximum flow");
def->graph_settings->min_x = 10;
def->graph_settings->max_x = 2000;
def->graph_settings->step_x = 1.;
def->graph_settings->min_y = 0.1;
def->graph_settings->max_y = 2;
def->graph_settings->step_y = 0.1;
def->graph_settings->allowed_types = {GraphData::GraphType::LINEAR, GraphData::GraphType::SQUARE};

def = this->add("extruder_offset", coPoints);
def->label = L("Extruder offset");
Expand Down
114 changes: 114 additions & 0 deletions src/slic3r/GUI/Field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "BitmapComboBox.hpp"
#include "format.hpp"
#include "GraphDialog.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "I18N.hpp"
Expand Down Expand Up @@ -2098,6 +2099,119 @@ void ColourPicker::sys_color_changed()
#endif
}


void GraphButton::BUILD()
{
auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord);
if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit);
if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit);

assert(m_opt.type == coGraph || m_opt.type == coGraphs);
if (m_opt.type == coGraphs)
current_value = m_opt.get_default_value<ConfigOptionGraphs>()->get_at(m_opt_idx);
if (m_opt.type == coGraph)
current_value = m_opt.get_default_value<ConfigOptionGraph>()->value;

wxButton* bt_widget = new wxButton(m_parent, wxID_ANY, _L("Edit graph"), wxDefaultPosition, size);
if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double)bt_widget->GetSize().GetHeight() / m_em_unit;
bt_widget->SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (!wxOSX) bt_widget->SetBackgroundStyle(wxBG_STYLE_PAINT);

wxGetApp().UpdateDarkUI(bt_widget);

// recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(bt_widget);

//window->Bind(wxEVT_COLOURPICKER_CHANGED, ([this](wxCommandEvent e) { on_change_field(); }), window->GetId());

bt_widget->Bind(wxEVT_BUTTON, ([this](wxCommandEvent &e) {
GraphSettings settings;
assert(m_opt.graph_settings);
if (m_opt.graph_settings) {
settings = *m_opt.graph_settings;
} else {
settings.title = m_opt.full_label.empty() ? m_opt.label : m_opt.full_label;
settings.description = m_opt.tooltip;
settings.x_label = "";
settings.y_label = "";
settings.null_label = L("No values");
settings.label_min_x = L("Minimum x");
settings.label_max_x = L("Maximum x");
settings.label_min_y = L("Minimum y");
settings.label_max_y = L("Maximum y");
settings.min_x = 0;
settings.max_x = 1000;
settings.step_x = 0.1;
settings.min_y = 0;
settings.max_y = 1000;
settings.step_y = 0.1;
settings.allowed_types = {GraphData::GraphType::LINEAR, GraphData::GraphType::SPLINE, GraphData::GraphType::SQUARE};
}
if (this->m_opt.type == coGraphs)
settings.reset_vals = m_opt.get_default_value<ConfigOptionGraphs>()->get_at(m_opt_idx);
if (this->m_opt.type == coGraph)
settings.reset_vals = m_opt.get_default_value<ConfigOptionGraph>()->value;
GraphDialog dlg(this->window, current_value, settings);
if (dlg.ShowModal() == wxID_OK) {
m_value = current_value = dlg.get_data();
this->on_change_field();
}
}));
this->set_tooltip(current_value.serialize());
}

void GraphButton::set_any_value(const boost::any &value, bool change_event)
{
// can be ConfigOptionDef::GUIType::color
m_disable_change_event = !change_event;
if (this->m_opt.type == coGraphs && m_opt_idx >= 0) {
assert(false); // shouldn't happen. or need to be tested
std::vector<GraphData> graphs = boost::any_cast<std::vector<GraphData>>(value);
assert(!graphs.empty());
if (!graphs.empty()) {
assert(m_opt_idx <graphs.size());
m_value = current_value = graphs[m_opt_idx <graphs.size() ? m_opt_idx : 0];
}
} else if (this->m_opt.type == coGraph || this->m_opt.type == coGraphs) {
m_value = current_value = boost::any_cast<GraphData>(value);
}
m_disable_change_event = false;
}

boost::any& GraphButton::get_value()
{
m_value = current_value;
return m_value;
}

void GraphButton::msw_rescale()
{
Field::msw_rescale();

wxButton* field = dynamic_cast<wxButton*>(window);
auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord);
if (m_opt.height >= 0)
size.SetHeight(m_opt.height * m_em_unit);
else if (parent_is_custom_ctrl && opt_height > 0)
size.SetHeight(lround(opt_height * m_em_unit));
if (m_opt.width >= 0) size.SetWidth(m_opt.width * m_em_unit);
if (parent_is_custom_ctrl)
field->SetSize(size);
else
field->SetMinSize(size);

}

void GraphButton::sys_color_changed()
{
#ifdef _WIN32
if (wxWindow* win = this->getWindow())
if (wxButton* bt = dynamic_cast<wxButton*>(win))
wxGetApp().UpdateDarkUI(bt);
#endif
}

void PointCtrl::BUILD()
{
auto temp = new wxBoxSizer(wxHORIZONTAL);
Expand Down
21 changes: 21 additions & 0 deletions src/slic3r/GUI/Field.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,27 @@ class ColourPicker : public Field {
wxWindow* getWindow() override { return window; }
};

class GraphButton : public Field {
using Field::Field;
GraphData current_value;
public:
GraphButton(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
GraphButton(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
~GraphButton() {}

wxWindow* window{ nullptr };
void BUILD() override;

void set_any_value(const boost::any &value, bool change_event = false) override;
boost::any& get_value() override;
void msw_rescale() override;
void sys_color_changed() override;

void enable() override { dynamic_cast<wxButton*>(window)->Enable(); }
void disable() override{ dynamic_cast<wxButton*>(window)->Disable(); }
wxWindow* getWindow() override { return window; }
};

class PointCtrl : public Field {
using Field::Field;
public:
Expand Down
11 changes: 11 additions & 0 deletions src/slic3r/GUI/GUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,17 @@ static void add_config_substitutions(const ConfigSubstitutions& conf_substitutio
if (! new_val.empty())
new_val.erase(new_val.begin() + new_val.size() - 2, new_val.end());
break;
case coGraph:
if (auto opt = dynamic_cast<const ConfigOptionGraph *>(conf_substitution.new_value.get())) {
new_val = opt->value.serialize();
} else assert(false);
break;
case coGraphs:
if (auto opts = dynamic_cast<const ConfigOptionGraphs *>(conf_substitution.new_value.get())) {
for (const GraphData &graph : opts->get_values())
new_val += graph.serialize() + ", ";
} else assert(false);
break;
default:
assert(false);
}
Expand Down
18 changes: 1 addition & 17 deletions src/slic3r/GUI/GraphDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,11 @@
#include <wx/checkbox.h>
#include <wx/msgdlg.h>

#include "libslic3r/Config.hpp" // for GraphSettings
#include "RammingChart.hpp"

namespace Slic3r { namespace GUI {

struct GraphSettings
{
std::string title;
std::string description;
std::string y_label;
std::string x_label;
std::string null_label;
double min_x, max_x, step_x;
double min_y, max_y, step_y;
std::string label_min_x;
std::string label_max_x;
std::string label_min_y;
std::string label_max_y;
std::vector<GraphData::GraphType> allowed_types;
GraphData reset_vals;
};

class GraphPanel : public wxPanel
{
public:
Expand Down
26 changes: 15 additions & 11 deletions src/slic3r/GUI/OptionsGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const t_field& OptionsGroup::build_field(const Option& opt) {
return build_field(opt.opt_id, opt.opt);
}
const t_field& OptionsGroup::build_field(const t_config_option_key& id) {
const ConfigOptionDef& opt = m_options.at(id).opt;
const ConfigOptionDef& opt = m_options.at(id).opt;
return build_field(id, opt);
}

Expand Down Expand Up @@ -54,11 +54,11 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
case coFloatOrPercent:
case coFloat:
case coFloats:
case coPercent:
case coPercent:
case coPercents:
case coFloatsOrPercents:
case coString:
case coStrings:
case coString:
case coStrings:
m_fields.emplace(id, TextCtrl::Create<TextCtrl>(this->ctrl_parent(), opt, id));
break;
case coBools:
Expand All @@ -67,28 +67,32 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
m_fields.emplace(id, TextCtrl::Create<TextCtrl>(this->ctrl_parent(), opt, id));
break;
}
case coBool:
case coBool:
m_fields.emplace(id, CheckBox::Create<CheckBox>(this->ctrl_parent(), opt, id));
break;
break;
case coInts:
if (id.find('#') == std::string::npos) {
// string field with vector serialization
m_fields.emplace(id, TextCtrl::Create<TextCtrl>(this->ctrl_parent(), opt, id));
break;
}
case coInt:
case coInt:
m_fields.emplace(id, SpinCtrl::Create<SpinCtrl>(this->ctrl_parent(), opt, id));
break;
break;
case coEnum:
m_fields.emplace(id, Choice::Create<Choice>(this->ctrl_parent(), opt, id));
break;
break;
case coPoint:
case coPoints:
m_fields.emplace(id, PointCtrl::Create<PointCtrl>(this->ctrl_parent(), opt, id));
break;
break;
case coGraph:
case coGraphs:
m_fields.emplace(id, GraphButton::Create<GraphButton>(this->ctrl_parent(), opt, id));
break;
case coNone: assert(false); break;
default:
throw Slic3r::LogicError("This control doesn't exist till now"); break;
throw Slic3r::LogicError("This control doesn't exist till now"); break;
}
}
// Grab a reference to fields for convenience
Expand Down
39 changes: 0 additions & 39 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2566,45 +2566,6 @@ std::vector<Slic3r::GUI::PageShp> Tab::create_pages(std::string setting_type_nam
return sizer;
};
current_group->append_line(thisline);
} else if (boost::starts_with(full_line, "extruder_extrusion_multiplier_speed")) {
// don't forget the idx_page as it's on the extruder page.
Line thisline = current_group->create_single_option_line("extruder_extrusion_multiplier_speed", "", idx_page);
thisline.widget = [this, idx_page](wxWindow *parent) {
auto dialog_btn = new wxButton(parent, wxID_ANY, _L("Extrusion multiplier per speed") + dots,
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
wxGetApp().UpdateDarkUI(dialog_btn);
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(dialog_btn);
dialog_btn->Bind(wxEVT_BUTTON, ([this, idx_page](wxCommandEvent &e) {
GraphSettings settings;
settings.title = L("Extrusion multiplier per extrusion speed");
settings.description = L("Choose the extrusion multipler value for multiple speeds.\nYou can add/remove points with a right clic.");
settings.x_label = L("Print speed (mm/s)");
settings.y_label = L("Extrusion multiplier");
settings.null_label = L("No compensation");
settings.label_min_x = L("Graph min speed");
settings.label_max_x = L("Graph max speed");
settings.label_min_y = L("Minimum flow");
settings.label_max_y = L("Maximum flow");
settings.min_x = 10;
settings.max_x = 2000;
settings.step_x = 1.;
settings.min_y = 0.1;
settings.max_y = 2;
settings.step_y = 0.1;
settings.allowed_types = {GraphData::GraphType::LINEAR, GraphData::GraphType::SQUARE};
settings.reset_vals = static_cast<const ConfigOptionGraphs*>(m_config_base->def()->get("extruder_extrusion_multiplier_speed")->default_value.get())->get_at(idx_page);
GraphDialog dlg(this, (m_config_base->option<ConfigOptionGraphs>("extruder_extrusion_multiplier_speed"))->get_at(idx_page), settings);
if (dlg.ShowModal() == wxID_OK) {
//(m_config_base->option<ConfigOptionStrings>("extruder_extrusion_multiplier_speed"))->get_at(0) = dlg.get_parameters();
m_config_base->option("extruder_extrusion_multiplier_speed")->set_enabled(!dlg.is_disabled(), idx_page);
load_key_value("extruder_extrusion_multiplier_speed", dlg.get_data(), false, idx_page);
}
}));
return sizer;
};
current_group->append_line(thisline);
} else if (full_line == "bed_shape") {
TabPrinter *tab = nullptr;
if ((tab = dynamic_cast<TabPrinter *>(this)) == nullptr)
Expand Down

0 comments on commit 982409c

Please sign in to comment.