Another step towards C++ presets.

This commit is contained in:
bubnikv 2017-10-25 12:53:31 +02:00
parent 7308017ee8
commit ee645007f2
27 changed files with 1161 additions and 907 deletions

View file

@ -7,7 +7,8 @@ namespace Slic3r {
template <class PointClass>
BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &points)
{
if (points.empty()) CONFESS("Empty point set supplied to BoundingBoxBase constructor");
if (points.empty())
CONFESS("Empty point set supplied to BoundingBoxBase constructor");
typename std::vector<PointClass>::const_iterator it = points.begin();
this->min.x = this->max.x = it->x;
this->min.y = this->max.y = it->y;
@ -26,7 +27,8 @@ template <class PointClass>
BoundingBox3Base<PointClass>::BoundingBox3Base(const std::vector<PointClass> &points)
: BoundingBoxBase<PointClass>(points)
{
if (points.empty()) CONFESS("Empty point set supplied to BoundingBox3Base constructor");
if (points.empty())
CONFESS("Empty point set supplied to BoundingBox3Base constructor");
typename std::vector<PointClass>::const_iterator it = points.begin();
this->min.z = this->max.z = it->z;
for (++it; it != points.end(); ++it) {
@ -39,9 +41,10 @@ template BoundingBox3Base<Pointf3>::BoundingBox3Base(const std::vector<Pointf3>
BoundingBox::BoundingBox(const Lines &lines)
{
Points points;
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) {
points.push_back(line->a);
points.push_back(line->b);
points.reserve(lines.size());
for (const Line &line : lines) {
points.emplace_back(line.a);
points.emplace_back(line.b);
}
*this = BoundingBox(points);
}
@ -190,9 +193,9 @@ BoundingBox3Base<PointClass>::size() const
}
template Pointf3 BoundingBox3Base<Pointf3>::size() const;
template <class PointClass> double
BoundingBoxBase<PointClass>::radius() const
template <class PointClass> double BoundingBoxBase<PointClass>::radius() const
{
assert(this->defined);
double x = this->max.x - this->min.x;
double y = this->max.y - this->min.y;
return 0.5 * sqrt(x*x+y*y);
@ -200,8 +203,7 @@ BoundingBoxBase<PointClass>::radius() const
template double BoundingBoxBase<Point>::radius() const;
template double BoundingBoxBase<Pointf>::radius() const;
template <class PointClass> double
BoundingBox3Base<PointClass>::radius() const
template <class PointClass> double BoundingBox3Base<PointClass>::radius() const
{
double x = this->max.x - this->min.x;
double y = this->max.y - this->min.y;

View file

@ -27,35 +27,36 @@ extern bool unescape_strings_cstyle(const std::string &str, std::vector<
// Type of a configuration value.
enum ConfigOptionType {
coNone,
coVectorType = 0x4000,
coNone = 0,
// single float
coFloat,
coFloat = 1,
// vector of floats
coFloats,
coFloats = coFloat + coVectorType,
// single int
coInt,
coInt = 2,
// vector of ints
coInts,
coInts = coInt + coVectorType,
// single string
coString,
coString = 3,
// vector of strings
coStrings,
coStrings = coString + coVectorType,
// percent value. Currently only used for infill.
coPercent,
coPercent = 4,
// percents value. Currently used for retract before wipe only.
coPercents,
coPercents = coPercent + coVectorType,
// a fraction or an absolute value
coFloatOrPercent,
coFloatOrPercent = 5,
// single 2d point. Currently not used.
coPoint,
coPoint = 6,
// vector of 2d points. Currently used for the definition of the print bed and for the extruder offsets.
coPoints,
coPoints = coPoint + coVectorType,
// single boolean value
coBool,
coBool = 7,
// vector of boolean values
coBools,
coBools = coBool + coVectorType,
// a generic enum
coEnum,
coEnum = 8,
};
// A generic value of a configuration option.
@ -75,6 +76,8 @@ public:
virtual void setInt(int /* val */) { throw std::runtime_error("Calling ConfigOption::setInt on a non-int ConfigOption"); }
virtual bool operator==(const ConfigOption &rhs) const = 0;
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; }
bool is_vector() const { return ! this->is_scalar(); }
};
// Value of a single valued option (bool, int, float, string, point, enum)
@ -110,6 +113,18 @@ class ConfigOptionVectorBase : public ConfigOption {
public:
// Currently used only to initialize the PlaceholderParser.
virtual std::vector<std::string> vserialize() const = 0;
// Set from a vector of ConfigOptions.
// If the rhs ConfigOption is scalar, then its value is used,
// otherwise for each of rhs, the first value of a vector is used.
// This function is useful to collect values for multiple extrder / filament settings.
virtual void set(const std::vector<const ConfigOption*> &rhs) = 0;
// Set a single vector item from either a scalar option or the first value of a vector option.vector of ConfigOptions.
// This function is useful to split values from multiple extrder / filament settings into separate configurations.
virtual void set_at(const ConfigOption *rhs, size_t i, size_t j) = 0;
protected:
// Used to verify type compatibility when assigning to / from a scalar ConfigOption.
ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); }
};
// Value of a vector valued option (bools, ints, floats, strings, points), template
@ -125,13 +140,57 @@ public:
throw std::runtime_error("ConfigOptionVector: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionVector<T>*>(rhs));
this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values;
};
}
// Set from a vector of ConfigOptions.
// If the rhs ConfigOption is scalar, then its value is used,
// otherwise for each of rhs, the first value of a vector is used.
// This function is useful to collect values for multiple extrder / filament settings.
void set(const std::vector<const ConfigOption*> &rhs) override
{
this->values.clear();
this->values.reserve(rhs.size());
for (const ConfigOption *opt : rhs) {
if (opt->type() == this->type()) {
auto other = static_cast<const ConfigOptionVector<T>*>(opt);
if (other->values.empty())
throw std::runtime_error("ConfigOptionVector::set(): Assigning from an empty vector");
this->values.emplace_back(other->values.front());
} else if (opt->type() == this->scalar_type())
this->values.emplace_back(static_cast<const ConfigOptionSingle<T>*>(opt)->value);
else
throw std::runtime_error("ConfigOptionVector::set():: Assigning an incompatible type");
}
}
// Set a single vector item from either a scalar option or the first value of a vector option.vector of ConfigOptions.
// This function is useful to split values from multiple extrder / filament settings into separate configurations.
void set_at(const ConfigOption *rhs, size_t i, size_t j) override
{
// It is expected that the vector value has at least one value, which is the default, if not overwritten.
assert(! this->values.empty());
if (this->values.size() <= i) {
// Resize this vector, fill in the new vector fields with the copy of the first field.
T v = this->values.front();
this->values.resize(i + 1, v);
}
if (rhs->type() == this->type()) {
// Assign the first value of the rhs vector.
auto other = static_cast<const ConfigOptionVector<T>*>(rhs);
if (other->values.empty())
throw std::runtime_error("ConfigOptionVector::set_at(): Assigning from an empty vector");
this->values[i] = other->get_at(j);
} else if (rhs->type() == this->scalar_type())
this->values[i] = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
else
throw std::runtime_error("ConfigOptionVector::set_at(): Assigning an incompatible type");
}
T& get_at(size_t i)
{
assert(! this->values.empty());
return (i < this->values.size()) ? this->values[i] : this->values.front();
};
}
const T& get_at(size_t i) const { return const_cast<ConfigOptionVector<T>*>(this)->get_at(i); }

View file

@ -1208,6 +1208,8 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
// perform a safety offset to merge very close facets (TODO: find test case for this)
double safety_offset = scale_(0.0499);
//FIXME see https://github.com/prusa3d/Slic3r/issues/520
// double safety_offset = scale_(0.0001);
ExPolygons ex_slices = offset2_ex(p_slices, +safety_offset, -safety_offset);
#ifdef SLIC3R_TRIANGLEMESH_DEBUG

View file

@ -8,11 +8,21 @@ extern void trace(unsigned int level, const char *message);
// Set a path with GUI resource files.
void set_var_dir(const std::string &path);
// Return a path to the GUI resource files.
// Return a full path to the GUI resource files.
const std::string& var_dir();
// Return a resource path for a file_name.
// Return a full resource path for a file_name.
std::string var(const std::string &file_name);
// Set a path with preset files.
void set_data_dir(const std::string &path);
// Return a full path to the GUI resource files.
const std::string& data_dir();
// Return a full path to a configuration file given its file name..
std::string config_path(const std::string &file_name);
// Return a full path to a configuration file given the section and name.
// The suffix ".ini" will be added if it is missing in the name.
std::string config_path(const std::string &section, const std::string &name);
extern std::string encode_path(const char *src);
extern std::string decode_path(const char *src);
extern std::string normalize_utf8_nfc(const char *src);

View file

@ -6,8 +6,8 @@
#include <boost/locale.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/nowide/integration/filesystem.hpp>
#include <boost/nowide/convert.hpp>
@ -87,6 +87,31 @@ std::string var(const std::string &file_name)
return file.string();
}
static std::string g_data_dir;
void set_data_dir(const std::string &dir)
{
g_data_dir = dir;
}
const std::string& data_dir()
{
return g_data_dir;
}
std::string config_path(const std::string &file_name)
{
auto file = boost::filesystem::canonical(boost::filesystem::path(g_data_dir) / file_name).make_preferred();
return file.string();
}
std::string config_path(const std::string &section, const std::string &name)
{
auto file_name = boost::algorithm::iends_with(name, ".ini") ? name : name + ".ini";
auto file = boost::filesystem::canonical(boost::filesystem::path(g_data_dir) / file_name).make_preferred();
return file.string();
}
} // namespace Slic3r
#ifdef SLIC3R_HAS_BROKEN_CROAK

View file

@ -13,8 +13,7 @@ namespace Slic3r { namespace GUI {
IOPMAssertionID assertionID;
#endif
void
disable_screensaver()
void disable_screensaver()
{
#if __APPLE__
CFStringRef reasonForActivity = CFSTR("Slic3r");
@ -26,8 +25,7 @@ disable_screensaver()
#endif
}
void
enable_screensaver()
void enable_screensaver()
{
#if __APPLE__
IOReturn success = IOPMAssertionRelease(assertionID);
@ -36,8 +34,7 @@ enable_screensaver()
#endif
}
bool
debugged()
bool debugged()
{
#ifdef _WIN32
return IsDebuggerPresent();
@ -46,8 +43,7 @@ debugged()
#endif /* _WIN32 */
}
void
break_to_debugger()
void break_to_debugger()
{
#ifdef _WIN32
if (IsDebuggerPresent())

View file

@ -4,9 +4,17 @@
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/nowide/cenv.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <wx/image.h>
#include <wx/choice.h>
#include <wx/bmpcbox.h>
#include "../../libslic3r/Utils.hpp"
#if 0
#define DEBUG
#define _DEBUG
@ -17,6 +25,42 @@
namespace Slic3r {
static std::string g_suffix_modified = " (modified)";
// Load keys from a config file or a G-code.
// Throw exceptions with reasonable messages if something goes wrong.
static void load_config_file(DynamicPrintConfig &config, const std::string &path)
{
try {
if (boost::algorithm::iends_with(path, ".gcode") || boost::algorithm::iends_with(path, ".g"))
config.load_from_gcode(path);
else
config.load(path);
} catch (const std::ifstream::failure&) {
throw std::runtime_error(std::string("The selected preset does not exist anymore: ") + path);
} catch (const std::runtime_error&) {
throw std::runtime_error(std::string("Failed loading the preset file: ") + path);
}
// Update new extruder fields at the printer profile.
auto keys = config.keys();
const auto &defaults = FullPrintConfig::defaults();
if (std::find(keys.begin(), keys.end(), "nozzle_diameter") != keys.end()) {
// Loaded the Printer settings. Verify, that all extruder dependent values have enough values.
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter"));
size_t num_extruders = nozzle_diameter->values.size();
auto *deretract_speed = dynamic_cast<ConfigOptionFloats*>(config.option("deretract_speed"));
deretract_speed->values.resize(num_extruders, deretract_speed->values.empty() ?
defaults.deretract_speed.values.front() : deretract_speed->values.front());
auto *extruder_colour = dynamic_cast<ConfigOptionStrings*>(config.option("extruder_colour"));
extruder_colour->values.resize(num_extruders, extruder_colour->values.empty() ?
defaults.extruder_colour.values.front() : extruder_colour->values.front());
auto *retract_before_wipe = dynamic_cast<ConfigOptionPercents*>(config.option("retract_before_wipe"));
retract_before_wipe->values.resize(num_extruders, retract_before_wipe->values.empty() ?
defaults.retract_before_wipe.values.front() : retract_before_wipe->values.front());
}
}
// Load a config file, return a C++ class Slic3r::DynamicPrintConfig with $keys initialized from the config file.
// In case of a "default" config item, return the default values.
DynamicPrintConfig& Preset::load(const std::vector<std::string> &keys)
@ -24,40 +68,24 @@ DynamicPrintConfig& Preset::load(const std::vector<std::string> &keys)
// Set the configuration from the defaults.
Slic3r::FullPrintConfig defaults;
this->config.apply_only(defaults, keys.empty() ? defaults.keys() : keys);
if (! this->is_default) {
if (! this->is_default)
// Load the preset file, apply preset values on top of defaults.
try {
if (boost::algorithm::iends_with(this->file, ".gcode") || boost::algorithm::iends_with(this->file, ".g"))
this->config.load_from_gcode(this->file);
else
this->config.load(this->file);
} catch (const std::ifstream::failure&) {
throw std::runtime_error(std::string("The selected preset does not exist anymore: ") + this->file);
} catch (const std::runtime_error&) {
throw std::runtime_error(std::string("Failed loading the preset file: ") + this->file);
}
if (this->type == TYPE_PRINTER && std::find(keys.begin(), keys.end(), "nozzle_diameter") != keys.end()) {
// Loaded the Printer settings. Verify, that all extruder dependent values have enough values.
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(this->config.option("nozzle_diameter"));
size_t num_extruders = nozzle_diameter->values.size();
auto *deretract_speed = dynamic_cast<ConfigOptionFloats*>(this->config.option("deretract_speed"));
deretract_speed->values.resize(num_extruders, deretract_speed->values.empty() ?
defaults.deretract_speed.values.front() : deretract_speed->values.front());
auto *extruder_colour = dynamic_cast<ConfigOptionStrings*>(this->config.option("extruder_colour"));
extruder_colour->values.resize(num_extruders, extruder_colour->values.empty() ?
defaults.extruder_colour.values.front() : extruder_colour->values.front());
auto *retract_before_wipe = dynamic_cast<ConfigOptionPercents*>(this->config.option("retract_before_wipe"));
retract_before_wipe->values.resize(num_extruders, retract_before_wipe->values.empty() ?
defaults.retract_before_wipe.values.front() : retract_before_wipe->values.front());
}
}
load_config_file(this->config, this->file);
this->loaded = true;
return this->config;
}
void Preset::save()
{
this->config.save(this->file);
}
// Return a label of this preset, consisting of a name and a "(modified)" suffix, if this preset is dirty.
std::string Preset::label() const
{
return this->name + (this->is_dirty ? g_suffix_modified : "");
}
bool Preset::enable_compatible(const std::string &active_printer)
{
auto *compatible_printers = dynamic_cast<const ConfigOptionStrings*>(this->config.optptr("compatible_printers"));
@ -69,11 +97,20 @@ bool Preset::enable_compatible(const std::string &active_printer)
PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::string> &keys) :
m_type(type),
m_edited_preset(type, "", false)
m_edited_preset(type, "", false),
m_idx_selected(0),
m_bitmap_main_frame(new wxBitmap)
{
// Insert just the default preset.
m_presets.emplace_back(Preset(type, "- default -", true));
m_presets.front().load(keys);
m_edited_preset.config.apply(m_presets.front().config);
}
PresetCollection::~PresetCollection()
{
delete m_bitmap_main_frame;
m_bitmap_main_frame = nullptr;
}
// Load all presets found in dir_path.
@ -96,6 +133,58 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
}
}
std::sort(m_presets.begin() + 1, m_presets.end(), [](const Preset &p1, const Preset &p2){ return p1.name < p2.name; });
}
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
// and select it, losing previous modifications.
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select)
{
Preset key(m_type, name);
auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key);
if (it != m_presets.end() && it->name == name) {
// The preset with the same name was found.
it->is_dirty = false;
} else {
it = m_presets.emplace(it, Preset(m_type, name, false));
}
Preset &preset = *it;
preset.file = path;
preset.config = this->default_preset().config;
preset.loaded = true;
this->get_selected_preset().is_dirty = false;
if (select)
this->select_preset_by_name(name, true);
return preset;
}
bool PresetCollection::load_bitmap_default(const std::string &file_name)
{
return m_bitmap_main_frame->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
}
// Return a preset by its name. If the preset is active, a temporary copy is returned.
// If a preset is not found by its name, null is returned.
Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found)
{
Preset key(m_type, name, false);
auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key,
[](const Preset &p1, const Preset &p2) { return p1.name < p2.name; } );
// Ensure that a temporary copy is returned if the preset found is currently selected.
return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin()) :
first_visible_if_not_found ? &this->first_visible() : nullptr;
}
// Return index of the first visible preset. Certainly at least the '- default -' preset shall be visible.
size_t PresetCollection::first_visible_idx() const
{
size_t idx = 0;
for (; idx < this->m_presets.size(); ++ idx)
if (m_presets[idx].is_visible)
break;
if (idx == this->m_presets.size())
idx = 0;
return idx;
}
void PresetCollection::set_default_suppressed(bool default_suppressed)
@ -117,7 +206,13 @@ void PresetCollection::enable_disable_compatible_to_printer(const std::string &a
m_presets.front().is_visible = true;
}
static std::string g_suffix_modified = " (modified)";
// Save the preset under a new name. If the name is different from the old one,
// a new preset is stored into the list of presets.
// All presets are marked as not modified and the new preset is activated.
//void PresetCollection::save_current_preset(const std::string &new_name);
// Delete the current preset, activate the first visible preset.
//void PresetCollection::delete_current_preset();
// Update the wxChoice UI component from this list of presets.
// Hide the
@ -175,6 +270,113 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
}
}
void PresetCollection::update_platter_ui(wxChoice *ui)
{
if (ui == nullptr)
return;
size_t n_visible = this->num_visible();
size_t n_choice = size_t(ui->GetCount());
if (std::abs(int(n_visible) - int(n_choice)) <= 1) {
// The number of items differs by at most one, update the choice.
} else {
// Otherwise fill in the list from scratch.
}
std::string name_selected = dynamic_cast<wxItemContainerImmutable*>(ui)->GetStringSelection().ToUTF8().data();
if (boost::algorithm::iends_with(name_selected, g_suffix_modified))
// Remove the g_suffix_modified.
name_selected.erase(name_selected.end() - g_suffix_modified.size(), name_selected.end());
ui->Clear();
for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) {
const Preset &preset = this->m_presets[i];
const wxBitmap *bmp = (i == 0 || preset.is_visible) ? m_bitmap_compatible : m_bitmap_incompatible;
ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), (void*)&preset);
if (name_selected == preset.name)
ui->SetSelection(ui->GetCount() - 1);
}
}
// Update a dirty floag of the current preset, update the labels of the UI component accordingly.
// Return true if the dirty flag changed.
bool PresetCollection::update_dirty_ui(wxItemContainer *ui)
{
// 1) Update the dirty flag of the current preset.
bool was_dirty = this->get_selected_preset().is_dirty;
bool is_dirty = current_is_dirty();
this->get_selected_preset().is_dirty = is_dirty;
// 2) Update the labels.
for (unsigned int ui_id = 0; ui_id < ui->GetCount(); ++ ui_id) {
std::string old_label = ui->GetString(ui_id).utf8_str().data();
std::string preset_name = boost::algorithm::ends_with(old_label, g_suffix_modified) ?
old_label.substr(0, g_suffix_modified.size()) :
old_label;
const Preset *preset = this->find_preset(preset_name, false);
assert(preset != nullptr);
std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name;
if (old_label != new_label)
ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str()));
}
return was_dirty != is_dirty;
}
bool PresetCollection::update_dirty_ui(wxChoice *ui)
{
return update_dirty_ui(dynamic_cast<wxItemContainer*>(ui));
}
Preset& PresetCollection::select_preset(size_t idx)
{
if (idx >= m_presets.size())
idx = first_visible_idx();
m_idx_selected = idx;
m_edited_preset = m_presets[idx];
return m_presets[idx];
}
bool PresetCollection::select_preset_by_name(const std::string &name, bool force)
{
// 1) Try to find the preset by its name.
Preset key(m_type, name, false);
auto it = std::lower_bound(m_presets.begin(), m_presets.end(), key,
[](const Preset &p1, const Preset &p2) { return p1.name < p2.name; } );
size_t idx = 0;
if (it != m_presets.end() && it->name == key.name)
// Preset found by its name.
idx = it - m_presets.begin();
else {
// Find the first visible preset.
for (size_t i = 0; i < m_presets.size(); ++ i)
if (m_presets[i].is_visible) {
idx = i;
break;
}
// If the first visible preset was not found, return the 0th element, which is the default preset.
}
// 2) Select the new preset.
if (m_idx_selected != idx || force) {
this->select_preset(idx);
return true;
}
return false;
}
bool PresetCollection::select_by_name_ui(char *name, wxItemContainer *ui)
{
this->select_preset_by_name(name, true);
//FIXME this is not finished yet.
//this->update_platter_ui(wxChoice *ui)
return true;
}
bool PresetCollection::select_by_name_ui(char *name, wxChoice *ui)
{
return this->select_by_name_ui(name, dynamic_cast<wxItemContainer*>(ui));
}
PresetBundle::PresetBundle() :
prints(Preset::TYPE_PRINT, print_options()),
filaments(Preset::TYPE_FILAMENT, filament_options()),
@ -182,6 +384,8 @@ PresetBundle::PresetBundle() :
m_bitmapCompatible(new wxBitmap),
m_bitmapIncompatible(new wxBitmap)
{
::wxInitAllImageHandlers();
// Create the ID config keys, as they are not part of the Static print config classes.
this->prints.preset(0).config.opt_string("print_settings_id", true);
this->filaments.preset(0).config.opt_string("filament_settings_id", true);
@ -189,6 +393,13 @@ PresetBundle::PresetBundle() :
// Create the "compatible printers" keys, as they are not part of the Static print config classes.
this->filaments.preset(0).config.optptr("compatible_printers", true);
this->prints.preset(0).config.optptr("compatible_printers", true);
this->prints .load_bitmap_default("cog.png");
this->filaments.load_bitmap_default("spool.png");
this->printers .load_bitmap_default("printer_empty.png");
// FIXME select some icons indicating compatibility.
this->load_compatible_bitmaps("cog.png", "cog.png");
}
PresetBundle::~PresetBundle()
@ -205,15 +416,17 @@ PresetBundle::~PresetBundle()
void PresetBundle::load_presets(const std::string &dir_path)
{
this->prints.load_presets(dir_path, "print");
this->prints.load_presets(dir_path, "filament");
this->prints.load_presets(dir_path, "printer");
this->prints .load_presets(dir_path, "print");
this->filaments.load_presets(dir_path, "filament");
this->printers .load_presets(dir_path, "printer");
}
bool PresetBundle::load_bitmaps(const std::string &path_bitmap_compatible, const std::string &path_bitmap_incompatible)
bool PresetBundle::load_compatible_bitmaps(const std::string &path_bitmap_compatible, const std::string &path_bitmap_incompatible)
{
bool loaded_compatible = m_bitmapCompatible ->LoadFile(wxString::FromUTF8(path_bitmap_compatible.c_str()));
bool loaded_incompatible = m_bitmapIncompatible->LoadFile(wxString::FromUTF8(path_bitmap_incompatible.c_str()));
bool loaded_compatible = m_bitmapCompatible ->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_compatible).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_incompatible = m_bitmapIncompatible->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_incompatible).c_str()), wxBITMAP_TYPE_PNG);
if (loaded_compatible) {
prints .set_bitmap_compatible(m_bitmapCompatible);
filaments.set_bitmap_compatible(m_bitmapCompatible);
@ -227,6 +440,269 @@ bool PresetBundle::load_bitmaps(const std::string &path_bitmap_compatible, const
return loaded_compatible && loaded_incompatible;
}
DynamicPrintConfig PresetBundle::full_config() const
{
DynamicPrintConfig out;
out.apply(FullPrintConfig());
out.apply(this->prints.get_edited_preset().config);
out.apply(this->printers.get_edited_preset().config);
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(out.option("nozzle_diameter"));
size_t num_extruders = nozzle_diameter->values.size();
if (num_extruders <= 1) {
out.apply(this->filaments.get_edited_preset().config);
} else {
// Retrieve filament presets and build a single config object for them.
// First collect the filament configurations based on the user selection of this->filament_presets.
std::vector<const DynamicPrintConfig*> filament_configs;
for (const std::string &filament_preset_name : this->filament_presets)
filament_configs.emplace_back(&this->filaments.find_preset(filament_preset_name, true)->config);
while (filament_configs.size() < num_extruders)
filament_configs.emplace_back(&this->filaments.first_visible().config);
// Option values to set a ConfigOptionVector from.
std::vector<const ConfigOption*> filament_opts(num_extruders, nullptr);
// loop through options and apply them to the resulting config.
for (const t_config_option_key &key : this->filaments.default_preset().config.keys()) {
// Get a destination option.
ConfigOption *opt_dst = out.option(key, false);
if (opt_dst->is_scalar()) {
// Get an option, do not create if it does not exist.
const ConfigOption *opt_src = filament_configs.front()->option(key);
if (opt_src != nullptr)
opt_dst->set(opt_src);
} else {
// Setting a vector value from all filament_configs.
for (size_t i = 0; i < filament_opts.size(); ++ i)
filament_opts[i] = filament_configs[i]->option(key);
static_cast<ConfigOptionVectorBase*>(opt_dst)->set(filament_opts);
}
}
}
static const char *keys[] = { "perimeter", "infill", "solid_infill", "support_material", "support_material_interface" };
for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++ i) {
std::string key = std::string(keys[i]) + "_extruder";
auto *opt = dynamic_cast<ConfigOptionInt*>(out.option(key, false));
assert(opt != nullptr);
opt->value = std::min<int>(opt->value, std::min<int>(0, int(num_extruders) - 1));
}
return out;
}
// Load an external config file containing the print, filament and printer presets.
// Instead of a config file, a G-code may be loaded containing the full set of parameters.
// In the future the configuration will likely be read from an AMF file as well.
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
void PresetBundle::load_config_file(const std::string &path)
{
// 1) Initialize a config from full defaults.
DynamicPrintConfig config;
config.apply(FullPrintConfig());
// 2) Try to load the config file.
// Throw exceptions with reasonable messages if something goes wrong.
Slic3r::load_config_file(config, path);
// 3) Create a name from the file name.
// Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles.
std::string name = boost::filesystem::path(path).filename().string();
// 3) If the loading succeeded, split and load the config into print / filament / printer settings.
// First load the print and printer presets.
for (size_t i_group = 0; i_group < 2; ++ i_group) {
PresetCollection &presets = (i_group == 0) ? this->prints : this->printers;
presets.load_preset(path, name, config).is_external = true;
}
// Now load the filaments. If there are multiple filament presets, split them and load them.
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter"));
auto *filament_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("filament_diameter"));
size_t num_extruders = std::min(nozzle_diameter->values.size(), filament_diameter->values.size());
if (num_extruders <= 1) {
this->filaments.load_preset(path, name, config).is_external = true;
this->filament_presets.clear();
this->filament_presets.emplace_back(name);
} else {
// Split the filament presets, load each of them separately.
std::vector<DynamicPrintConfig> configs(num_extruders, this->filaments.default_preset().config);
// loop through options and scatter them into configs.
for (const t_config_option_key &key : this->filaments.default_preset().config.keys()) {
const ConfigOption *other_opt = config.option(key, false);
if (other_opt == nullptr)
continue;
if (other_opt->is_scalar()) {
for (size_t i = 0; i < configs.size(); ++ i)
configs[i].option(key, false)->set(other_opt);
} else {
for (size_t i = 0; i < configs.size(); ++ i)
static_cast<ConfigOptionVectorBase*>(configs[i].option(key, false))->set_at(other_opt, 0, i);
}
}
// Load the configs into this->filaments and make them active.
filament_presets.clear();
for (size_t i = 0; i < configs.size(); ++ i) {
char suffix[64];
if (i == 0)
suffix[0] = 0;
else
sprintf(suffix, " (%d)", i);
// Load all filament presets, but only select the first one in the preset dialog.
this->filaments.load_preset(path, name + suffix, configs[i], i == 0).is_external = true;
filament_presets.emplace_back(name + suffix);
}
}
}
std::string PresetCollection::name() const
{
switch (this->type()) {
case Preset::TYPE_PRINT: return "print";
case Preset::TYPE_FILAMENT: return "filament";
case Preset::TYPE_PRINTER: return "printer";
default: return "invalid";
}
}
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
// Load settings into the provided settings instance.
void PresetBundle::load_configbundle(const std::string &path, const DynamicPrintConfig &settings)
{
// 1) Read the complete config file into the boost::property_tree.
namespace pt = boost::property_tree;
pt::ptree tree;
boost::nowide::ifstream ifs(path);
pt::read_ini(ifs, tree);
// 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
std::vector<std::string> loaded_prints;
std::vector<std::string> loaded_filaments;
std::vector<std::string> loaded_printers;
std::string active_print;
std::vector<std::string> active_filaments;
std::string active_printer;
for (const auto &section : tree) {
PresetCollection *presets = nullptr;
std::vector<std::string> *loaded = nullptr;
std::string preset_name;
if (boost::starts_with(section.first, "print:")) {
presets = &prints;
loaded = &loaded_prints;
preset_name = section.first.substr(6);
} else if (boost::starts_with(section.first, "filament:")) {
presets = &filaments;
loaded = &loaded_filaments;
preset_name = section.first.substr(9);
} else if (boost::starts_with(section.first, "printer:")) {
presets = &printers;
loaded = &loaded_printers;
preset_name = section.first.substr(8);
} else if (section.first == "presets") {
// Load the names of the active presets.
for (auto &kvp : section.second) {
if (kvp.first == "print") {
active_print = kvp.second.data();
} else if (boost::starts_with(kvp.first, "filament")) {
int idx = 0;
if (kvp.first == "filament" || sscanf(kvp.first.c_str(), "filament_%d", &idx) == 1) {
if (int(active_filaments.size()) <= idx)
active_filaments.resize(idx + 1, std::string());
active_filaments[idx] = kvp.second.data();
}
} else if (kvp.first == "printer") {
active_printer = kvp.second.data();
}
}
} else if (section.first == "settings") {
// Load the settings.
for (auto &kvp : section.second) {
if (kvp.first == "autocenter") {
}
}
} else
// Ignore an unknown section.
continue;
if (presets != nullptr) {
// Load the print, filament or printer preset.
DynamicPrintConfig config(presets->default_preset().config);
for (auto &kvp : section.second)
config.set_deserialize(kvp.first, kvp.second.data());
// Load the preset into the list of presets, save it to disk.
presets->load_preset(Slic3r::config_path(presets->name(), preset_name), preset_name, config, false).save();
}
}
// 3) Activate the presets.
if (! active_print.empty())
prints.select_preset_by_name(active_print, true);
if (! active_printer.empty())
printers.select_preset_by_name(active_printer, true);
// Activate the first filament preset.
if (! active_filaments.empty() && ! active_filaments.front().empty())
filaments.select_preset_by_name(active_filaments.front(), true);
// Verify and select the filament presets.
auto *nozzle_diameter = static_cast<const ConfigOptionFloats*>(printers.get_selected_preset().config.option("nozzle_diameter"));
size_t num_extruders = nozzle_diameter->values.size();
if (this->filament_presets.size() < num_extruders)
this->filament_presets.resize(num_extruders, filaments.get_selected_preset().name);
for (size_t i = 0; i < num_extruders; ++ i)
this->filament_presets[i] = (i < active_filaments.size()) ?
filaments.find_preset(active_filaments[i], true)->name :
filaments.first_visible().name;
}
void PresetBundle::export_configbundle(const std::string &path, const DynamicPrintConfig &settings)
{
boost::nowide::ofstream c;
c.open(path, std::ios::out | std::ios::trunc);
// Put a comment at the first line including the time stamp and Slic3r version.
{
std::time_t now;
time(&now);
char buf[sizeof "0000-00-00 00:00:00"];
strftime(buf, sizeof(buf), "%F %T", gmtime(&now));
c << "# generated by Slic3r " << SLIC3R_VERSION << " on " << buf << std::endl;
}
// Export the print, filament and printer profiles.
for (size_t i_group = 0; i_group < 3; ++ i_group) {
const PresetCollection &presets = (i_group == 0) ? this->prints : (i_group == 1) ? this->filaments : this->printers;
for (const Preset &preset : presets()) {
if (preset.is_default || preset.is_external)
// Only export the common presets, not external files or the default preset.
continue;
c << "[" << presets.name() << ":" << preset.name << "]" << std::endl;
for (const std::string &opt_key : preset.config.keys())
c << opt_key << " = " << preset.config.serialize(opt_key) << std::endl;
}
}
// Export the names of the active presets.
c << "[presets]" << std::endl;
c << "print = " << this->prints.get_selected_preset().name << std::endl;
c << "printer = " << this->printers.get_selected_preset().name << std::endl;
for (size_t i = 0; i < this->filament_presets.size(); ++ i) {
char suffix[64];
if (i > 0)
sprintf(suffix, "_%d", i);
else
suffix[0] = 0;
c << "filament" << suffix << " = " << this->filament_presets[i] << std::endl;
}
// Export the following setting values from the provided setting repository.
static const char *settings_keys[] = { "autocenter" };
c << "[presets]" << std::endl;
c << "print = " << this->prints.get_selected_preset().name << std::endl;
for (size_t i = 0; i < sizeof(settings_keys) / sizeof(settings_keys[0]); ++ i)
c << settings_keys[i] << " = " << settings.serialize(settings_keys[i]) << std::endl;
c.close();
}
static inline int hex_digit_to_int(const char c)
{
return
@ -261,12 +737,12 @@ void PresetBundle::update_platter_filament_ui_colors(wxBitmapComboBox *ui, unsig
extruder_color.clear();
for (unsigned int ui_id = 0; ui_id < ui->GetCount(); ++ ui_id) {
if (! ui->HasClientUntypedData())
continue;
std::string preset_name = ui->GetString(ui_id).utf8_str().data();
size_t filament_preset_id = size_t(ui->GetClientData(ui_id));
const Preset &filament_preset = filaments.preset(filament_preset_id);
const Preset *filament_preset = filaments.find_preset(preset_name, false);
assert(filament_preset != nullptr);
// Assign an extruder color to the selected item if the extruder color is defined.
std::string filament_rgb = filament_preset.config.opt_string("filament_colour", 0);
std::string filament_rgb = filament_preset->config.opt_string("filament_colour", 0);
std::string extruder_rgb = (int(ui_id) == ui->GetSelection() && ! extruder_color.empty()) ? extruder_color : filament_rgb;
wxBitmap *bitmap = nullptr;
if (filament_rgb == extruder_rgb) {
@ -362,4 +838,11 @@ const std::vector<std::string>& PresetBundle::printer_options()
return s_opts;
}
void PresetBundle::set_default_suppressed(bool default_suppressed)
{
prints.set_default_suppressed(default_suppressed);
filaments.set_default_suppressed(default_suppressed);
printers.set_default_suppressed(default_suppressed);
}
} // namespace Slic3r

View file

@ -1,11 +1,15 @@
#ifndef slic3r_Preset_hpp_
#define slic3r_Preset_hpp_
#include <deque>
#include "../../libslic3r/libslic3r.h"
#include "../../libslic3r/PrintConfig.hpp"
class wxBitmap;
class wxChoice;
class wxBitmapComboBox;
class wxItemContainer;
namespace Slic3r {
@ -53,10 +57,21 @@ public:
// Throws std::runtime_error in case the file cannot be read.
DynamicPrintConfig& load(const std::vector<std::string> &keys);
void save();
// Return a label of this preset, consisting of a name and a "(modified)" suffix, if this preset is dirty.
std::string label() const;
// Set the is_dirty flag if the provided config is different from the active one.
void set_dirty(const DynamicPrintConfig &config) { this->is_dirty = ! this->config.diff(config).empty(); }
void set_dirty(bool dirty = true) { this->is_dirty = dirty; }
void reset_dirty() { this->is_dirty = false; }
// Mark this preset as visible if it is compatible with active_printer.
bool enable_compatible(const std::string &active_printer);
// Sort lexicographically by a preset name. The preset name shall be unique across a single PresetCollection.
bool operator<(const Preset &other) const { return this->name < other.name; }
};
// Collections of presets of the same type (one of the Print, Filament or Printer type).
@ -65,17 +80,29 @@ class PresetCollection
public:
// Initialize the PresetCollection with the "- default -" preset.
PresetCollection(Preset::Type type, const std::vector<std::string> &keys);
~PresetCollection();
Preset::Type type() const { return m_type; }
std::string name() const;
const std::deque<Preset>& operator()() const { return m_presets; }
// Load ini files of the particular type from the provided directory path.
void load_presets(const std::string &dir_path, const std::string &subdir);
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
// and select it, losing previous modifications.
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true);
// Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame.
bool load_bitmap_default(const std::string &file_name);
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items.
void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; }
void set_bitmap_incompatible(const wxBitmap *bmp) { m_bitmap_incompatible = bmp; }
// Enable / disable the "- default -" preset.
void set_default_suppressed(bool default_suppressed);
bool is_default_suppressed() const { return m_default_suppressed; }
bool is_default_suppressed() const { return m_default_suppressed || m_presets.size() <= 1; }
// Select a preset. If an invalid index is provided, the first visible preset is selected.
Preset& select_preset(size_t idx);
@ -87,33 +114,86 @@ public:
const Preset& get_edited_preset() const { return m_edited_preset; }
// Return a preset possibly with modifications.
const Preset& default_preset() const { return m_presets.front(); }
// Return a preset by an index. If the preset is active, a temporary copy is returned.
Preset& preset(size_t idx) { return (int(idx) == m_idx_selected) ? m_edited_preset : m_presets[idx]; }
const Preset& preset(size_t idx) const { return const_cast<PresetCollection*>(this)->preset(idx); }
// Return a preset by its name. If the preset is active, a temporary copy is returned.
// If a preset is not found by its name, null is returned.
Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false);
const Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false) const
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found); }
size_t first_visible_idx() const;
// Return index of the first visible preset. Certainly at least the '- default -' preset shall be visible.
// Return the first visible preset. Certainly at least the '- default -' preset shall be visible.
Preset& first_visible() { return this->preset(this->first_visible_idx()); }
const Preset& first_visible() const { return this->preset(this->first_visible_idx()); }
// Return number of presets including the "- default -" preset.
size_t size() const { return this->m_presets.size(); }
// For Print / Filament presets, disable those, which are not compatible with the printer.
void enable_disable_compatible_to_printer(const std::string &active_printer);
size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); }
void delete_preset(const size_t idx);
// Compare the content of get_selected_preset() with get_edited_preset() configs, return true if they differ.
bool current_is_dirty() { return ! this->current_dirty_options().empty(); }
// Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ.
std::vector<std::string> current_dirty_options() { return this->get_selected_preset().config.diff(this->get_edited_preset().config); }
// Save the preset under a new name. If the name is different from the old one,
// a new preset is stored into the list of presets.
// All presets are marked as not modified and the new preset is activated.
void save_current_preset(const std::string &new_name);
// Delete the current preset, activate the first visible preset.
void delete_current_preset();
// Update the choice UI from the list of presets.
void update_editor_ui(wxBitmapComboBox *ui);
void update_platter_ui(wxChoice *ui);
void update_platter_ui(wxBitmapComboBox *ui);
// Update a dirty floag of the current preset, update the labels of the UI component accordingly.
// Return true if the dirty flag changed.
bool update_dirty_ui(wxItemContainer *ui);
bool update_dirty_ui(wxChoice *ui);
// Select a profile by its name. Return true if the selection changed.
// Without force, the selection is only updated if the index changes.
// With force, the changes are reverted if the new index is the same as the old index.
bool select_preset_by_name(const std::string &name, bool force);
// Select a profile by its name, update selection at the UI component.
// Return true if the selection changed.
bool select_by_name_ui(char *name, wxItemContainer *ui);
bool select_by_name_ui(char *name, wxChoice *ui);
private:
PresetCollection();
PresetCollection(const PresetCollection &other);
PresetCollection& operator=(const PresetCollection &other);
// Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER.
Preset::Type m_type;
// List of presets, starting with the "- default -" preset.
std::vector<Preset> m_presets;
// Use deque to force the container to allocate an object per each entry,
// so that the addresses of the presets don't change during resizing of the container.
std::deque<Preset> m_presets;
// Initially this preset contains a copy of the selected preset. Later on, this copy may be modified by the user.
Preset m_edited_preset;
// Selected preset.
int m_idx_selected;
// Is the "- default -" preset suppressed?
bool m_default_suppressed = true;
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items.
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items of a Platter.
// These bitmaps are not owned by PresetCollection, but by a PresetBundle.
const wxBitmap *m_bitmap_compatible = nullptr;
const wxBitmap *m_bitmap_incompatible = nullptr;
// Marks placed at the wxBitmapComboBox of a MainFrame.
// These bitmaps are owned by PresetCollection.
wxBitmap *m_bitmap_main_frame;
};
// Bundle of Print + Filament + Printer presets.
@ -123,14 +203,32 @@ public:
PresetBundle();
~PresetBundle();
bool load_bitmaps(const std::string &path_bitmap_compatible, const std::string &path_bitmap_incompatible);
// Load ini files of all types (print, filament, printer) from the provided directory path.
void load_presets(const std::string &dir_path);
PresetCollection prints;
PresetCollection filaments;
PresetCollection printers;
PresetCollection prints;
PresetCollection filaments;
PresetCollection printers;
// Filament preset names for a multi-extruder or multi-material print.
// extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size()
std::vector<std::string> filament_presets;
DynamicPrintConfig full_config() const;
// Load an external config file containing the print, filament and printer presets.
// Instead of a config file, a G-code may be loaded containing the full set of parameters.
// In the future the configuration will likely be read from an AMF file as well.
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
void load_config_file(const std::string &path);
// Load a config bundle file, into presets and store the loaded presets into separate files
// of the local configuration directory.
// Load settings into the provided settings instance.
// Activate the presets stored in the
void load_configbundle(const std::string &path, const DynamicPrintConfig &settings);
// Export a config bundle file containing all the presets and the names of the active presets.
void export_configbundle(const std::string &path, const DynamicPrintConfig &settings);
// Update the colors preview at the platter extruder combo box.
void update_platter_filament_ui_colors(wxBitmapComboBox *ui, unsigned int idx_extruder, unsigned int idx_filament);
@ -139,7 +237,12 @@ public:
static const std::vector<std::string>& filament_options();
static const std::vector<std::string>& printer_options();
// Enable / disable the "- default -" preset.
void set_default_suppressed(bool default_suppressed);
private:
bool load_compatible_bitmaps(const std::string &path_bitmap_compatible, const std::string &path_bitmap_incompatible);
// Indicator, that the preset is compatible with the selected printer.
wxBitmap *m_bitmapCompatible;
// Indicator, that the preset is NOT compatible with the selected printer.

View file

@ -8,17 +8,18 @@
%name{Slic3r::GUI::Preset} class Preset {
// owned by PresetCollection, no constructor/destructor
bool is_default() %code%{ RETVAL = THIS->is_default; %};
bool is_external() %code%{ RETVAL = THIS->is_external; %};
bool is_visible() %code%{ RETVAL = THIS->is_visible; %};
bool is_dirty() %code%{ RETVAL = THIS->is_dirty; %};
bool default() %code%{ RETVAL = THIS->is_default; %};
bool external() %code%{ RETVAL = THIS->is_external; %};
bool visible() %code%{ RETVAL = THIS->is_visible; %};
bool dirty() %code%{ RETVAL = THIS->is_dirty; %};
const char* name() %code%{ RETVAL = THIS->name.c_str(); %};
const char* file() %code%{ RETVAL = THIS->file.c_str(); %};
const char* name() %code%{ RETVAL = THIS->name.c_str(); %};
const char* file() %code%{ RETVAL = THIS->file.c_str(); %};
bool loaded() %code%{ RETVAL = THIS->loaded; %};
bool loaded() %code%{ RETVAL = THIS->loaded; %};
Ref<DynamicPrintConfig> config() %code%{ RETVAL = &THIS->config; %};
Ref<DynamicPrintConfig> config_ref() %code%{ RETVAL = &THIS->config; %};
Clone<DynamicPrintConfig> config() %code%{ RETVAL = &THIS->config; %};
};
%name{Slic3r::GUI::PresetCollection} class PresetCollection {
@ -27,6 +28,29 @@
Ref<Preset> default_preset() %code%{ RETVAL = &THIS->default_preset(); %};
size_t size() const;
size_t num_visible() const;
Ref<Preset> get_selected_preset() %code%{ RETVAL = &THIS->get_selected_preset(); %};
Ref<Preset> get_current_preset() %code%{ RETVAL = &THIS->get_edited_preset(); %};
std::string get_current_preset_name() %code%{ RETVAL = THIS->get_selected_preset().name; %};
Ref<Preset> get_edited_preset() %code%{ RETVAL = &THIS->get_edited_preset(); %};
void set_default_suppressed(bool default_suppressed);
Ref<Preset> find_preset(char *name, bool first_visible_if_not_found = false) %code%{ RETVAL = THIS->find_preset(name, first_visible_if_not_found); %};
bool current_is_dirty();
std::vector<std::string> current_dirty_options();
void update_platter_ui(SV *ui)
%code%{ wxChoice* cb = (wxChoice*)wxPli_sv_2_object( aTHX_ ui, "Wx::Choice" );
THIS->update_platter_ui(cb); %};
bool update_dirty_ui(SV *ui)
%code%{ RETVAL = THIS->update_dirty_ui((wxChoice*)wxPli_sv_2_object(aTHX_ ui, "Wx::Choice")); %};
bool select_preset_by_name(char *name) %code%{ RETVAL = THIS->select_preset_by_name(name, true); %};
bool select_by_name_ui(char *name, SV *ui)
%code%{ RETVAL = THIS->select_by_name_ui(name, (wxChoice*)wxPli_sv_2_object(aTHX_ ui, "Wx::Choice")); %};
%{
SV*
@ -43,6 +67,19 @@ PresetCollection::arrayref()
OUTPUT:
RETVAL
SV*
PresetCollection::presets_hash()
CODE:
HV* hv = newHV();
for (size_t i = 1; i < THIS->size(); ++ i) {
const Slic3r::Preset &preset = THIS->preset(i);
if (! preset.is_default && ! preset.is_external)
(void)hv_store(hv, preset.name.c_str(), - int(preset.name.size()), newSVpvn_utf8(preset.file.c_str(), preset.file.size(), true), 0);
}
RETVAL = (SV*)newRV_noinc((SV*)hv);
OUTPUT:
RETVAL
%}
};
@ -51,10 +88,12 @@ PresetCollection::arrayref()
PresetBundle();
~PresetBundle();
void load_bitmaps(std::string path_bitmap_compatible, std::string path_bitmap_incompatible);
void load_presets(std::string dir_path);
void set_default_suppressed(bool default_suppressed);
Ref<PresetCollection> prints() %code%{ RETVAL = &THIS->prints; %};
Ref<PresetCollection> filaments() %code%{ RETVAL = &THIS->filaments; %};
Ref<PresetCollection> printers() %code%{ RETVAL = &THIS->printers; %};
Ref<PresetCollection> print() %code%{ RETVAL = &THIS->prints; %};
Ref<PresetCollection> filament() %code%{ RETVAL = &THIS->filaments; %};
Ref<PresetCollection> printer() %code%{ RETVAL = &THIS->printers; %};
Clone<DynamicPrintConfig> full_config() %code%{ RETVAL = THIS->full_config(); %};
};

View file

@ -67,6 +67,25 @@ var(file_name)
RETVAL = Slic3r::var(file_name);
OUTPUT: RETVAL
void
set_data_dir(dir)
char *dir;
CODE:
Slic3r::set_data_dir(dir);
char*
data_dir()
CODE:
RETVAL = const_cast<char*>(Slic3r::data_dir().c_str());
OUTPUT: RETVAL
std::string
config_path(file_name)
const char *file_name;
CODE:
RETVAL = Slic3r::config_path(file_name);
OUTPUT: RETVAL
std::string
encode_path(src)
const char *src;