mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-30 06:22:03 +08:00
Validate CLI config options against min/max
This commit is contained in:
parent
bb29661a90
commit
a1464a737e
@ -718,12 +718,12 @@ void Plater::remove(int obj_idx, bool dont_push) {
|
||||
Slic3r::Log::info(LogChannel, "Assigned obj_ref");
|
||||
try {
|
||||
this->model->delete_object(obj_ref->identifier);
|
||||
} catch (InvalidObjectException& ex) {
|
||||
} catch (out_of_range &ex) {
|
||||
Slic3r::Log::error(LogChannel, LOG_WSTRING("Failed to delete object " << obj_ref->identifier << " from Model."));
|
||||
}
|
||||
try {
|
||||
this->print->delete_object(obj_ref->identifier);
|
||||
} catch (InvalidObjectException& ex) {
|
||||
} catch (out_of_range &ex) {
|
||||
Slic3r::Log::error(LogChannel, LOG_WSTRING("Failed to delete object " << obj_ref->identifier << " from Print."));
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,14 @@ int CLI::run(int argc, char **argv) {
|
||||
// create a static (full) print config to be used in our logic
|
||||
this->full_print_config.apply(this->print_config);
|
||||
|
||||
// validate config
|
||||
try {
|
||||
this->full_print_config.validate();
|
||||
} catch (InvalidOptionException &e) {
|
||||
boost::nowide::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// read input file(s) if any
|
||||
for (auto const &file : input_files) {
|
||||
Model model;
|
||||
@ -271,6 +279,7 @@ int CLI::run(int argc, char **argv) {
|
||||
print.status_cb = [](int ln, const std::string& msg) {
|
||||
boost::nowide::cout << msg << std::endl;
|
||||
};
|
||||
print.apply_config(this->print_config);
|
||||
print.center = !this->config.has("center")
|
||||
&& !this->config.has("align_xy")
|
||||
&& !this->config.getBool("dont_arrange");
|
||||
@ -282,7 +291,12 @@ int CLI::run(int argc, char **argv) {
|
||||
std::chrono::time_point<clock_> t0{ clock_::now() };
|
||||
|
||||
const std::string outfile = this->output_filepath(model, IO::Gcode);
|
||||
print.export_gcode(outfile);
|
||||
try {
|
||||
print.export_gcode(outfile);
|
||||
} catch (InvalidPrintException &e) {
|
||||
boost::nowide::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
boost::nowide::cout << "G-code exported to " << outfile << std::endl;
|
||||
|
||||
// output some statistics
|
||||
|
@ -265,7 +265,7 @@ ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &opt_
|
||||
ConfigOption* my_opt = this->option(opt_key, true);
|
||||
if (opt_key.size() == 0) continue;
|
||||
if (my_opt == NULL) {
|
||||
if (ignore_nonexistent == false) throw UnknownOptionException();
|
||||
if (ignore_nonexistent == false) throw UnknownOptionException(opt_key);
|
||||
continue;
|
||||
}
|
||||
if (default_nonexistent && !other.has(opt_key)) {
|
||||
@ -328,7 +328,7 @@ ConfigBase::set_deserialize(t_config_option_key opt_key, std::string str, bool a
|
||||
if (optdef != NULL) break;
|
||||
}
|
||||
if (optdef == NULL)
|
||||
throw UnknownOptionException();
|
||||
throw UnknownOptionException(opt_key);
|
||||
}
|
||||
|
||||
if (!optdef->shortcut.empty()) {
|
||||
@ -472,6 +472,35 @@ ConfigBase::save(const std::string &file) const
|
||||
c.close();
|
||||
}
|
||||
|
||||
void
|
||||
ConfigBase::validate() const
|
||||
{
|
||||
for (auto &opt_key : this->keys()) {
|
||||
// get option definition
|
||||
const ConfigOptionDef* def = this->def->get(opt_key);
|
||||
assert(def != nullptr);
|
||||
|
||||
if (def->type == coInt) {
|
||||
auto &value = this->opt<ConfigOptionInt>(opt_key)->value;
|
||||
if (value < def->min || value > def->max)
|
||||
throw InvalidOptionException(opt_key);
|
||||
} else if (def->type == coFloat) {
|
||||
auto &value = this->opt<ConfigOptionFloat>(opt_key)->value;
|
||||
if (value < def->min || value > def->max)
|
||||
throw InvalidOptionException(opt_key);
|
||||
} else if (def->type == coInts) {
|
||||
for (auto &value : this->opt<ConfigOptionInts>(opt_key)->values)
|
||||
if (value < def->min || value > def->max)
|
||||
throw InvalidOptionException(opt_key);
|
||||
} else if (def->type == coFloats) {
|
||||
for (auto &value : this->opt<ConfigOptionFloats>(opt_key)->values)
|
||||
if (value < def->min || value > def->max)
|
||||
throw InvalidOptionException(opt_key);
|
||||
}
|
||||
// TODO: validate coFloatOrPercent (semantics of min/max are ambiguous for it)
|
||||
}
|
||||
}
|
||||
|
||||
DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
|
||||
{
|
||||
this->swap(other);
|
||||
|
@ -732,6 +732,7 @@ class ConfigBase
|
||||
void setenv_();
|
||||
void load(const std::string &file);
|
||||
void save(const std::string &file) const;
|
||||
void validate() const;
|
||||
};
|
||||
|
||||
/// Configuration store with dynamic number of configuration values.
|
||||
@ -775,7 +776,25 @@ class StaticConfig : public virtual ConfigBase
|
||||
};
|
||||
|
||||
/// Specialization of std::exception to indicate that an unknown config option has been encountered.
|
||||
class UnknownOptionException : public std::exception {};
|
||||
class ConfigOptionException : public std::exception {
|
||||
public:
|
||||
t_config_option_key opt_key;
|
||||
ConfigOptionException(t_config_option_key _opt_key)
|
||||
: opt_key(_opt_key) {};
|
||||
};
|
||||
class UnknownOptionException : public ConfigOptionException {
|
||||
using ConfigOptionException::ConfigOptionException;
|
||||
};
|
||||
class InvalidOptionException : public ConfigOptionException {
|
||||
using ConfigOptionException::ConfigOptionException;
|
||||
|
||||
public:
|
||||
virtual const char* what() const noexcept {
|
||||
std::string s("Invalid value for option: ");
|
||||
s += this->opt_key;
|
||||
return s.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ Print::delete_object(size_t idx)
|
||||
{
|
||||
PrintObjectPtrs::iterator i = this->objects.begin() + idx;
|
||||
if (i >= this->objects.end())
|
||||
throw InvalidObjectException();
|
||||
throw std::out_of_range("Object not found");
|
||||
|
||||
// before deleting object, invalidate all of its steps in order to
|
||||
// invalidate all of the dependent ones in Print
|
||||
@ -858,7 +858,7 @@ bool Print::has_skirt() const
|
||||
|| this->has_infinite_skirt();
|
||||
}
|
||||
|
||||
std::string
|
||||
void
|
||||
Print::validate() const
|
||||
{
|
||||
if (this->config.complete_objects) {
|
||||
@ -896,7 +896,7 @@ Print::validate() const
|
||||
Polygon p = convex_hull;
|
||||
p.translate(*copy);
|
||||
if (!intersection(a, p).empty())
|
||||
return "Some objects are too close; your extruder will collide with them.";
|
||||
throw InvalidPrintException{"Some objects are too close; your extruder will collide with them."};
|
||||
|
||||
a = union_(a, p);
|
||||
}
|
||||
@ -915,7 +915,7 @@ Print::validate() const
|
||||
// it will be printed as last one so its height doesn't matter
|
||||
object_height.pop_back();
|
||||
if (!object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value))
|
||||
return "Some objects are too tall and cannot be printed without extruder collisions.";
|
||||
throw InvalidPrintException{"Some objects are too tall and cannot be printed without extruder collisions."};
|
||||
}
|
||||
} // end if (this->config.complete_objects)
|
||||
|
||||
@ -923,15 +923,13 @@ Print::validate() const
|
||||
size_t total_copies_count = 0;
|
||||
FOREACH_OBJECT(this, i_object) total_copies_count += (*i_object)->copies().size();
|
||||
if (total_copies_count > 1 && !this->config.complete_objects.getBool())
|
||||
return "The Spiral Vase option can only be used when printing a single object.";
|
||||
throw InvalidPrintException{"The Spiral Vase option can only be used when printing a single object."};
|
||||
if (this->regions.size() > 1)
|
||||
return "The Spiral Vase option can only be used when printing single material objects.";
|
||||
throw InvalidPrintException{"The Spiral Vase option can only be used when printing single material objects."};
|
||||
}
|
||||
|
||||
if (this->extruders().empty())
|
||||
return "The supplied settings will cause an empty print.";
|
||||
|
||||
return std::string();
|
||||
throw InvalidPrintException{"The supplied settings will cause an empty print."};
|
||||
}
|
||||
|
||||
// the bounding box of objects placed in copies position
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <boost/thread.hpp>
|
||||
#include "BoundingBox.hpp"
|
||||
#include "Flow.hpp"
|
||||
@ -19,13 +21,11 @@
|
||||
#include "LayerHeightSpline.hpp"
|
||||
#include "SupportMaterial.hpp"
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class InvalidObjectException : public std::exception {};
|
||||
class InvalidPrintException : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
class Print;
|
||||
class PrintObject;
|
||||
@ -292,8 +292,8 @@ class Print
|
||||
bool apply_config(DynamicPrintConfig config);
|
||||
bool has_infinite_skirt() const;
|
||||
bool has_skirt() const;
|
||||
// Returns an empty string if valid, otherwise returns an error message.
|
||||
std::string validate() const;
|
||||
// Throws exceptions if print is not valid.
|
||||
void validate() const;
|
||||
BoundingBox bounding_box() const;
|
||||
BoundingBox total_bounding_box() const;
|
||||
double skirt_first_layer_height() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user