diff --git a/xs/src/Config.cpp b/xs/src/Config.cpp index a0f8236f..28077df9 100644 --- a/xs/src/Config.cpp +++ b/xs/src/Config.cpp @@ -129,6 +129,8 @@ DynamicConfig::option(const t_config_option_key opt_key, bool create) { opt = new ConfigOptionPoint (); } else if (Options[opt_key].type == coBool) { opt = new ConfigOptionBool (); + } else if (Options[opt_key].type == coEnumGCodeFlavor) { + opt = new ConfigOptionEnumGCodeFlavor (); } else { throw "Unknown option type"; } diff --git a/xs/src/Config.hpp b/xs/src/Config.hpp index facdfa11..597ae183 100644 --- a/xs/src/Config.hpp +++ b/xs/src/Config.hpp @@ -6,7 +6,7 @@ #include #include #include -#include ; +#include #include #include #include "Point.hpp" @@ -162,33 +162,36 @@ enum GCodeFlavor { gcfRepRap, gcfTeacup, gcfMakerWare, gcfSailfish, gcfMach3, gcfNoExtrusion, }; -class ConfigOptionGCodeFlavor : public ConfigOption +template +class ConfigOptionEnum : public ConfigOption { public: - GCodeFlavor value; - ConfigOptionGCodeFlavor() : value(gcfRepRap) {}; + T value; - operator GCodeFlavor() const { return this->value; }; + operator T() const { return this->value; }; - std::string serialize() { - if (this->value == gfcRepRap) { return std::string("reprap"); } - else if (this->value == gcfTeacup) { return std::string("teacup"); } - else if (this->value == gcfMakerWare) { return std::string("makerware"); } - else if (this->value == gcfSailfish) { return std::string("sailfish"); } - else if (this->value == gcfMach3) { return std::string("mach3"); } - else if (this->value == gcfNoExtrusion) { return std::string("no-extrusion"); } - }; - - void deserialize(std::string str) { - if (str.compare("reprap") == 0) { this->value = gfcRepRap; } - else if (str.compare("teacup") == 0) { this->value = gcfTeacup; } - else if (str.compare("makerware") == 0) { this->value = gcfMakerWare; } - else if (str.compare("sailfish") == 0) { this->value = gcfSailfish; } - else if (str.compare("mach3") == 0) { this->value = gcfMach3; } - else if (str.compare("no-extrusion") == 0) { this->value = gcfNoExtrusion; } - }; + std::string serialize(); + void deserialize(std::string str); + static std::map get_enum_values(); }; +template +std::string ConfigOptionEnum::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) { + if (it->second == this->value) return it->first; + } + return ""; +}; + +template +void ConfigOptionEnum::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]; +}; +typedef ConfigOptionEnum ConfigOptionEnumGCodeFlavor; + enum ConfigOptionType { coFloat, coInt, @@ -196,7 +199,7 @@ enum ConfigOptionType { coFloatOrPercent, coPoint, coBool, - coGCodeFlavor, + coEnumGCodeFlavor, }; class ConfigOptionDef @@ -253,13 +256,14 @@ class StaticConfig : public ConfigBase class FullConfig : public StaticConfig { public: - ConfigOptionFloat layer_height; - ConfigOptionFloatOrPercent first_layer_height; - ConfigOptionInt perimeters; - ConfigOptionString extrusion_axis; - ConfigOptionPoint print_center; - ConfigOptionString notes; - ConfigOptionBool use_relative_e_distances; + ConfigOptionFloat layer_height; + ConfigOptionFloatOrPercent first_layer_height; + ConfigOptionInt perimeters; + ConfigOptionString extrusion_axis; + ConfigOptionPoint print_center; + ConfigOptionString notes; + ConfigOptionBool use_relative_e_distances; + ConfigOptionEnumGCodeFlavor gcode_flavor; ConfigOption* option(const t_config_option_key opt_key, bool create = false) { assert(!create); // can't create options in StaticConfig @@ -270,6 +274,7 @@ class FullConfig : public StaticConfig if (opt_key == "print_center") return &this->print_center; 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; return NULL; }; }; @@ -295,9 +300,24 @@ static t_optiondef_map _build_optiondef_map () { Options["use_relative_e_distances"].type = coBool; + Options["gcode_flavor"].type = coEnumGCodeFlavor; + return Options; } +// 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; +} + + static FullConfig _build_default_config () { FullConfig defconf; @@ -309,6 +329,7 @@ static FullConfig _build_default_config () { defconf.print_center.point = Pointf(100,100); defconf.notes.value = ""; defconf.use_relative_e_distances.value = false; + defconf.gcode_flavor.value = gcfRepRap; return defconf; } diff --git a/xs/t/15_config.t b/xs/t/15_config.t index 2006e89b..92c95919 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 => 18; +use Test::More tests => 20; { my $config = Slic3r::Config->new; @@ -44,6 +44,10 @@ use Test::More tests => 18; $config->set('use_relative_e_distances', 1); is $config->get('use_relative_e_distances'), 1, 'set/get bool'; is $config->serialize('use_relative_e_distances'), '1', 'serialize bool'; + + $config->set('gcode_flavor', 'teacup'); + is $config->get('gcode_flavor'), 'teacup', 'set/get enum'; + is $config->serialize('gcode_flavor'), 'teacup', 'serialize enum'; } __END__