diff --git a/xs/MANIFEST b/xs/MANIFEST index 754b9f025e..3233e85501 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -37,6 +37,8 @@ src/Polyline.cpp src/Polyline.hpp src/PolylineCollection.cpp src/PolylineCollection.hpp +src/PrintConfig.cpp +src/PrintConfig.hpp src/ppport.h src/Surface.cpp src/Surface.hpp diff --git a/xs/src/Config.cpp b/xs/src/Config.cpp index 5b98a268c6..be816670cd 100644 --- a/xs/src/Config.cpp +++ b/xs/src/Config.cpp @@ -2,16 +2,6 @@ namespace Slic3r { -t_optiondef_map Options = _build_optiondef_map(); -FullConfig DefaultConfig = _build_default_config(); - -ConfigOptionDef* -get_config_option_def(const t_config_option_key opt_key) { - t_optiondef_map::iterator it = Options.find(opt_key); - if (it == Options.end()) return NULL; - return &it->second; -} - void ConfigBase::apply(ConfigBase &other, bool ignore_nonexistent) { // get list of option keys to apply @@ -43,8 +33,8 @@ ConfigBase::set_deserialize(const t_config_option_key opt_key, std::string str) float ConfigBase::get_abs_value(const t_config_option_key opt_key) { // get option definition - ConfigOptionDef* def = get_config_option_def(opt_key); - assert(def != NULL); + assert(this->def->count(opt_key) != 0); + ConfigOptionDef* def = &(*this->def)[opt_key]; assert(def->type == coFloatOrPercent); // get stored option value @@ -171,32 +161,34 @@ DynamicConfig::~DynamicConfig () { ConfigOption* DynamicConfig::option(const t_config_option_key opt_key, bool create) { - t_options_map::iterator it = this->options.find(opt_key); - if (it == this->options.end()) { + if (this->options.count(opt_key) == 0) { if (create) { + ConfigOptionDef* optdef = &(*this->def)[opt_key]; ConfigOption* opt; - if (Options[opt_key].type == coFloat) { + if (optdef->type == coFloat) { opt = new ConfigOptionFloat (); - } else if (Options[opt_key].type == coFloats) { + } else if (optdef->type == coFloats) { opt = new ConfigOptionFloats (); - } else if (Options[opt_key].type == coInt) { + } else if (optdef->type == coInt) { opt = new ConfigOptionInt (); - } else if (Options[opt_key].type == coInts) { + } else if (optdef->type == coInts) { opt = new ConfigOptionInts (); - } else if (Options[opt_key].type == coString) { + } else if (optdef->type == coString) { opt = new ConfigOptionString (); - } else if (Options[opt_key].type == coFloatOrPercent) { + } else if (optdef->type == coFloatOrPercent) { opt = new ConfigOptionFloatOrPercent (); - } else if (Options[opt_key].type == coPoint) { + } else if (optdef->type == coPoint) { opt = new ConfigOptionPoint (); - } else if (Options[opt_key].type == coPoints) { + } else if (optdef->type == coPoints) { opt = new ConfigOptionPoints (); - } else if (Options[opt_key].type == coBool) { + } else if (optdef->type == coBool) { opt = new ConfigOptionBool (); - } else if (Options[opt_key].type == coBools) { + } else if (optdef->type == coBools) { opt = new ConfigOptionBools (); - } else if (Options[opt_key].type == coEnumGCodeFlavor) { - opt = new ConfigOptionEnumGCodeFlavor (); + } else if (optdef->type == coEnum) { + ConfigOptionEnumGeneric* optv = new ConfigOptionEnumGeneric (); + optv->keys_map = &optdef->enum_keys_map; + opt = static_cast(optv); } else { throw "Unknown option type"; } @@ -206,7 +198,7 @@ DynamicConfig::option(const t_config_option_key opt_key, bool create) { return NULL; } } - return it->second; + return this->options[opt_key]; } void @@ -217,13 +209,12 @@ DynamicConfig::keys(t_config_option_keys *keys) { bool DynamicConfig::has(const t_config_option_key opt_key) const { - t_options_map::const_iterator it = this->options.find(opt_key); - return (it != this->options.end()); + return (this->options.count(opt_key) != 0); } void StaticConfig::keys(t_config_option_keys *keys) { - for (t_optiondef_map::const_iterator it = Options.begin(); it != Options.end(); ++it) { + for (t_optiondef_map::const_iterator it = this->def->begin(); it != this->def->end(); ++it) { ConfigOption* opt = this->option(it->first); if (opt != NULL) keys->push_back(it->first); } diff --git a/xs/src/Config.hpp b/xs/src/Config.hpp index f53682d431..1374347d2e 100644 --- a/xs/src/Config.hpp +++ b/xs/src/Config.hpp @@ -258,6 +258,8 @@ class ConfigOptionBools : public ConfigOption }; }; +typedef std::map t_config_enum_values; + template class ConfigOptionEnum : public ConfigOption { @@ -267,41 +269,45 @@ class ConfigOptionEnum : public ConfigOption operator T() const { return this->value; }; std::string serialize() { - typename std::map enum_keys_map = ConfigOptionEnum::get_enum_values(); - for (typename std::map::iterator it = enum_keys_map.begin(); it != enum_keys_map.end(); ++it) { + t_config_enum_values enum_keys_map = ConfigOptionEnum::get_enum_values(); + for (t_config_enum_values::iterator it = enum_keys_map.begin(); it != enum_keys_map.end(); ++it) { + if (it->second == static_cast(this->value)) return it->first; + } + return ""; + }; + + void deserialize(std::string str) { + t_config_enum_values enum_keys_map = ConfigOptionEnum::get_enum_values(); + assert(enum_keys_map.count(str) > 0); + this->value = static_cast(enum_keys_map[str]); + }; + + static t_config_enum_values get_enum_values(); +}; + +/* We use this one in DynamicConfig objects, otherwise it's better to use + the specialized ConfigOptionEnum containers. */ +class ConfigOptionEnumGeneric : public ConfigOption +{ + public: + int value; + t_config_enum_values* keys_map; + + operator int() const { return this->value; }; + + std::string serialize() { + for (t_config_enum_values::iterator it = this->keys_map->begin(); it != this->keys_map->end(); ++it) { if (it->second == this->value) return it->first; } return ""; }; void deserialize(std::string str) { - typename std::map enum_keys_map = ConfigOptionEnum::get_enum_values(); - assert(enum_keys_map.count(str) > 0); - this->value = enum_keys_map[str]; + assert(this->keys_map->count(str) != 0); + this->value = (*this->keys_map)[str]; }; - - static std::map get_enum_values(); }; - - -enum GCodeFlavor { - gcfRepRap, gcfTeacup, gcfMakerWare, gcfSailfish, gcfMach3, gcfNoExtrusion, -}; -typedef ConfigOptionEnum ConfigOptionEnumGCodeFlavor; - -// we declare this as inline to keep it in this file along with all other option definitions -template<> inline std::map ConfigOptionEnum::get_enum_values() { - std::map keys_map; - keys_map["reprap"] = gcfRepRap; - keys_map["teacup"] = gcfTeacup; - keys_map["makerware"] = gcfMakerWare; - keys_map["sailfish"] = gcfSailfish; - keys_map["mach3"] = gcfMach3; - keys_map["no-extrusion"] = gcfNoExtrusion; - return keys_map; -} - enum ConfigOptionType { coFloat, coFloats, @@ -313,7 +319,7 @@ enum ConfigOptionType { coPoints, coBool, coBools, - coEnumGCodeFlavor, + coEnum, }; class ConfigOptionDef @@ -323,6 +329,7 @@ class ConfigOptionDef std::string label; std::string tooltip; std::string ratio_over; + t_config_enum_values enum_keys_map; }; typedef std::map t_optiondef_map; @@ -332,6 +339,9 @@ ConfigOptionDef* get_config_option_def(const t_config_option_key opt_key); class ConfigBase { public: + t_optiondef_map* def; + + ConfigBase() : def(NULL) {}; virtual ConfigOption* option(const t_config_option_key opt_key, bool create = false) = 0; virtual void keys(t_config_option_keys *keys) = 0; void apply(ConfigBase &other, bool ignore_nonexistent = false); @@ -348,7 +358,7 @@ class ConfigBase class DynamicConfig : public ConfigBase { public: - DynamicConfig() {}; + DynamicConfig(){}; ~DynamicConfig(); ConfigOption* option(const t_config_option_key opt_key, bool create = false); void keys(t_config_option_keys *keys); @@ -367,95 +377,6 @@ class StaticConfig : public ConfigBase void keys(t_config_option_keys *keys); }; -class FullConfig : public StaticConfig -{ - public: - ConfigOptionFloat layer_height; - ConfigOptionFloatOrPercent first_layer_height; - ConfigOptionInt perimeters; - ConfigOptionString extrusion_axis; - ConfigOptionPoint print_center; - ConfigOptionPoints extruder_offset; - ConfigOptionString notes; - ConfigOptionBool use_relative_e_distances; - ConfigOptionEnumGCodeFlavor gcode_flavor; - ConfigOptionFloats nozzle_diameter; - ConfigOptionInts temperature; - ConfigOptionBools wipe; - - ConfigOption* option(const t_config_option_key opt_key, bool create = false) { - assert(!create); // can't create options in StaticConfig - if (opt_key == "layer_height") return &this->layer_height; - if (opt_key == "first_layer_height") return &this->first_layer_height; - if (opt_key == "perimeters") return &this->perimeters; - if (opt_key == "extrusion_axis") return &this->extrusion_axis; - if (opt_key == "print_center") return &this->print_center; - if (opt_key == "extruder_offset") return &this->extruder_offset; - if (opt_key == "notes") return &this->notes; - if (opt_key == "use_relative_e_distances") return &this->use_relative_e_distances; - if (opt_key == "gcode_flavor") return &this->gcode_flavor; - if (opt_key == "nozzle_diameter") return &this->nozzle_diameter; - if (opt_key == "temperature") return &this->temperature; - if (opt_key == "wipe") return &this->wipe; - return NULL; - }; -}; - -static t_optiondef_map _build_optiondef_map () { - t_optiondef_map Options; - Options["layer_height"].type = coFloat; - Options["layer_height"].label = "Layer height"; - Options["layer_height"].tooltip = "This setting controls the height (and thus the total number) of the slices/layers. Thinner layers give better accuracy but take more time to print."; - - Options["first_layer_height"].type = coFloatOrPercent; - Options["first_layer_height"].ratio_over = "layer_height"; - - Options["perimeters"].type = coInt; - Options["perimeters"].label = "Perimeters (minimum)"; - Options["perimeters"].tooltip = "This option sets the number of perimeters to generate for each layer. Note that Slic3r may increase this number automatically when it detects sloping surfaces which benefit from a higher number of perimeters if the Extra Perimeters option is enabled."; - - Options["extrusion_axis"].type = coString; - - Options["print_center"].type = coPoint; - - Options["extruder_offset"].type = coPoints; - - Options["notes"].type = coString; - - Options["use_relative_e_distances"].type = coBool; - - Options["gcode_flavor"].type = coEnumGCodeFlavor; - - Options["nozzle_diameter"].type = coFloats; - - Options["temperature"].type = coInts; - - Options["wipe"].type = coBools; - - return Options; -} - - -static FullConfig _build_default_config () { - FullConfig defconf; - - defconf.layer_height.value = 0.4; - defconf.first_layer_height.value = 0.35; - defconf.first_layer_height.percent = false; - defconf.perimeters.value = 3; - defconf.extrusion_axis.value = "E"; - defconf.print_center.point = Pointf(100,100); - defconf.extruder_offset.points.push_back(Pointf(0,0)); - defconf.notes.value = ""; - defconf.use_relative_e_distances.value = false; - defconf.gcode_flavor.value = gcfRepRap; - defconf.nozzle_diameter.values.push_back(0.5); - defconf.temperature.values.push_back(200); - defconf.wipe.values.push_back(true); - - return defconf; -} - } #endif diff --git a/xs/src/PrintConfig.cpp b/xs/src/PrintConfig.cpp new file mode 100644 index 0000000000..76cc9ef496 --- /dev/null +++ b/xs/src/PrintConfig.cpp @@ -0,0 +1,7 @@ +#include "PrintConfig.hpp" + +namespace Slic3r { + +t_optiondef_map PrintConfig::PrintConfigDef = PrintConfig::build_def(); + +} diff --git a/xs/src/PrintConfig.hpp b/xs/src/PrintConfig.hpp new file mode 100644 index 0000000000..c2d86dac57 --- /dev/null +++ b/xs/src/PrintConfig.hpp @@ -0,0 +1,123 @@ +#ifndef slic3r_PrintConfig_hpp_ +#define slic3r_PrintConfig_hpp_ + +#include "Config.hpp" + +namespace Slic3r { + +enum GCodeFlavor { + gcfRepRap, gcfTeacup, gcfMakerWare, gcfSailfish, gcfMach3, gcfNoExtrusion, +}; + +template<> inline t_config_enum_values ConfigOptionEnum::get_enum_values() { + t_config_enum_values keys_map; + keys_map["reprap"] = gcfRepRap; + keys_map["teacup"] = gcfTeacup; + keys_map["makerware"] = gcfMakerWare; + keys_map["sailfish"] = gcfSailfish; + keys_map["mach3"] = gcfMach3; + keys_map["no-extrusion"] = gcfNoExtrusion; + return keys_map; +} + +class PrintConfig : public StaticConfig +{ + public: + static t_optiondef_map PrintConfigDef; + + ConfigOptionFloat layer_height; + ConfigOptionFloatOrPercent first_layer_height; + ConfigOptionInt perimeters; + ConfigOptionString extrusion_axis; + ConfigOptionPoint print_center; + ConfigOptionPoints extruder_offset; + ConfigOptionString notes; + ConfigOptionBool use_relative_e_distances; + ConfigOptionEnum gcode_flavor; + ConfigOptionFloats nozzle_diameter; + ConfigOptionInts temperature; + ConfigOptionBools wipe; + + PrintConfig() { + this->def = &PrintConfig::PrintConfigDef; + + this->layer_height.value = 0.4; + this->first_layer_height.value = 0.35; + this->first_layer_height.percent = false; + this->perimeters.value = 3; + this->extrusion_axis.value = "E"; + this->print_center.point = Pointf(100,100); + this->extruder_offset.points.push_back(Pointf(0,0)); + this->notes.value = ""; + this->use_relative_e_distances.value = false; + this->gcode_flavor.value = gcfRepRap; + this->nozzle_diameter.values.push_back(0.5); + this->temperature.values.push_back(200); + this->wipe.values.push_back(true); + }; + + ConfigOption* option(const t_config_option_key opt_key, bool create = false) { + assert(!create); // can't create options in StaticConfig + if (opt_key == "layer_height") return &this->layer_height; + if (opt_key == "first_layer_height") return &this->first_layer_height; + if (opt_key == "perimeters") return &this->perimeters; + if (opt_key == "extrusion_axis") return &this->extrusion_axis; + if (opt_key == "print_center") return &this->print_center; + if (opt_key == "extruder_offset") return &this->extruder_offset; + if (opt_key == "notes") return &this->notes; + if (opt_key == "use_relative_e_distances") return &this->use_relative_e_distances; + if (opt_key == "gcode_flavor") return &this->gcode_flavor; + if (opt_key == "nozzle_diameter") return &this->nozzle_diameter; + if (opt_key == "temperature") return &this->temperature; + if (opt_key == "wipe") return &this->wipe; + return NULL; + }; + + static t_optiondef_map build_def () { + t_optiondef_map Options; + Options["layer_height"].type = coFloat; + Options["layer_height"].label = "Layer height"; + Options["layer_height"].tooltip = "This setting controls the height (and thus the total number) of the slices/layers. Thinner layers give better accuracy but take more time to print."; + + Options["first_layer_height"].type = coFloatOrPercent; + Options["first_layer_height"].ratio_over = "layer_height"; + + Options["perimeters"].type = coInt; + Options["perimeters"].label = "Perimeters (minimum)"; + Options["perimeters"].tooltip = "This option sets the number of perimeters to generate for each layer. Note that Slic3r may increase this number automatically when it detects sloping surfaces which benefit from a higher number of perimeters if the Extra Perimeters option is enabled."; + + Options["extrusion_axis"].type = coString; + + Options["print_center"].type = coPoint; + + Options["extruder_offset"].type = coPoints; + + Options["notes"].type = coString; + + Options["use_relative_e_distances"].type = coBool; + + Options["gcode_flavor"].type = coEnum; + Options["gcode_flavor"].enum_keys_map = ConfigOptionEnum::get_enum_values(); + + Options["nozzle_diameter"].type = coFloats; + + Options["temperature"].type = coInts; + + Options["wipe"].type = coBools; + + return Options; + }; +}; + +class DynamicPrintConfig : public DynamicConfig +{ + public: + DynamicPrintConfig() { + this->def = &PrintConfig::PrintConfigDef; + }; + +}; + +} + +#endif diff --git a/xs/t/15_config.t b/xs/t/15_config.t index bafd869b81..2a5b4d4978 100644 --- a/xs/t/15_config.t +++ b/xs/t/15_config.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 32; +use Test::More tests => 33; { my $config = Slic3r::Config->new; @@ -48,6 +48,8 @@ use Test::More tests => 32; $config->set('gcode_flavor', 'teacup'); is $config->get('gcode_flavor'), 'teacup', 'set/get enum'; is $config->serialize('gcode_flavor'), 'teacup', 'serialize enum'; + $config->set_deserialize('gcode_flavor', 'mach3'); + is $config->get('gcode_flavor'), 'mach3', 'deserialize enum'; $config->set('extruder_offset', [[10,20],[30,45]]); is_deeply $config->get('extruder_offset'), [[10,20],[30,45]], 'set/get points'; diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index b0e4595309..f4608a784c 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -2,12 +2,12 @@ %{ #include -#include "Config.hpp" +#include "PrintConfig.hpp" %} -%name{Slic3r::Config} class DynamicConfig { - DynamicConfig(); - ~DynamicConfig(); +%name{Slic3r::Config} class DynamicPrintConfig { + DynamicPrintConfig(); + ~DynamicPrintConfig(); SV* get(t_config_option_key opt_key); void set(t_config_option_key opt_key, SV* value); void set_deserialize(t_config_option_key opt_key, std::string str); diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 7543ce82d5..bd7abe0437 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -1,7 +1,7 @@ std::vector T_STD_VECTOR_INT t_config_option_key T_STD_STRING -DynamicConfig* O_OBJECT +DynamicPrintConfig* O_OBJECT ZTable* O_OBJECT TriangleMesh* O_OBJECT Point* O_OBJECT diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index a4e26fcc1d..5ff11b6af3 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -7,7 +7,7 @@ %typemap{SV*}; %typemap{AV*}; %typemap{Point*}; -%typemap{DynamicConfig*}; +%typemap{DynamicPrintConfig*}; %typemap{ExPolygon*}; %typemap{ExPolygonCollection*}; %typemap{Line*};