diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index d47cdf99fb..9ff913a1e4 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -717,7 +717,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co if (model.id() != m_model.id()) { // Kill everything, initialize from scratch. // Stop background processing. - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(this->invalidate_all_steps()); for (PrintObject *object : m_objects) { model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); @@ -749,7 +749,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co } else { // Reorder the objects, add new objects. // First stop background processing before shuffling or deleting the PrintObjects in the object list. - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(this->invalidate_step(psGCodeExport)); // Second create a new list of objects. std::vector model_objects_old(std::move(m_model.objects)); @@ -859,7 +859,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co model_object.assign_copy(model_object_new); } else if (support_blockers_differ || support_enforcers_differ) { // First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list. - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(false); // Invalidate just the supports step. auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); @@ -960,7 +960,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co } } if (m_objects != print_objects_new) { - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(this->invalidate_all_steps()); m_objects = print_objects_new; // Delete the PrintObjects marked as Unknown or Deleted. @@ -1867,7 +1867,7 @@ std::string Print::output_filename() const DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders(); return this->PrintBase::output_filename(m_config.output_filename_format.value, "gcode", &config); } - +/* // Shorten the dhms time by removing the seconds, rounding the dhm to full minutes // and removing spaces. static std::string short_time(const std::string &time) @@ -1907,7 +1907,7 @@ static std::string short_time(const std::string &time) ::sprintf(buffer, "%ds", seconds); return buffer; } - +*/ DynamicConfig PrintStatistics::config() const { DynamicConfig config; diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index e70edd20d7..e01b678a53 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -326,7 +326,7 @@ protected: tbb::mutex& state_mutex() const { return m_state_mutex; } std::function cancel_callback() { return m_cancel_callback; } - void call_cancell_callback() { m_cancel_callback(); } + void call_cancel_callback() { m_cancel_callback(); } // If the background processing stop was requested, throw CanceledException. // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index c01a1f6aad..745223906f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2435,6 +2435,32 @@ void PrintConfigDef::init_sla_params() def->enum_labels.push_back(L("Portrait")); def->default_value = new ConfigOptionEnum(sladoPortrait); + def = this->add("fast_tilt_time", coFloat); + def->label = L("Fast"); + def->full_label = L("Fast tilt"); + def->tooltip = L("Time of the fast tilt"); + def->sidetext = L("s"); + def->min = 0; + def->mode = comExpert; + def->default_value = new ConfigOptionFloat(5.); + + def = this->add("slow_tilt_time", coFloat); + def->label = L("Slow"); + def->full_label = L("Slow tilt"); + def->tooltip = L("Time of the slow tilt"); + def->sidetext = L("s"); + def->min = 0; + def->mode = comExpert; + def->default_value = new ConfigOptionFloat(8.); + + def = this->add("area_fill", coFloat); + def->label = L("Area fill"); + def->tooltip = L("The percentage of the bed area. \nIf the print area exceeds the specified value, \nthen a slow tilt will be used, otherwise - a fast tilt"); + def->sidetext = L("%"); + def->min = 0; + def->mode = comExpert; + def->default_value = new ConfigOptionFloat(50.); + def = this->add("printer_correction", coFloats); def->full_label = L("Printer scaling correction"); def->tooltip = L("Printer scaling correction"); @@ -2450,6 +2476,14 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->default_value = new ConfigOptionFloat(0.3); + def = this->add("faded_layers", coInt); + def->label = L("Faded layers"); + def->tooltip = L("Number of the layers needed for the exposure time fade from initial exposure time to the exposure time"); + def->min = 3; + def->max = 20; + def->mode = comExpert; + def->default_value = new ConfigOptionInt(10); + def = this->add("exposure_time", coFloat); def->label = L("Exposure time"); def->tooltip = L("Exposure time"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index c6c9175156..221eac220f 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -958,6 +958,9 @@ class SLAPrintObjectConfig : public StaticPrintConfig public: ConfigOptionFloat layer_height; + //Number of the layers needed for the exposure time fade [3;20] + ConfigOptionInt faded_layers /*= 10*/; + // Enabling or disabling support creation ConfigOptionBool supports_enable; @@ -1027,6 +1030,7 @@ protected: void initialize(StaticCacheBase &cache, const char *base_ptr) { OPT_PTR(layer_height); + OPT_PTR(faded_layers); OPT_PTR(supports_enable); OPT_PTR(support_head_front_diameter); OPT_PTR(support_head_penetration); @@ -1083,6 +1087,9 @@ public: ConfigOptionInt display_pixels_y; ConfigOptionEnum display_orientation; ConfigOptionFloats printer_correction; + ConfigOptionFloat fast_tilt_time; + ConfigOptionFloat slow_tilt_time; + ConfigOptionFloat area_fill; protected: void initialize(StaticCacheBase &cache, const char *base_ptr) { @@ -1095,6 +1102,9 @@ protected: OPT_PTR(display_pixels_y); OPT_PTR(display_orientation); OPT_PTR(printer_correction); + OPT_PTR(fast_tilt_time); + OPT_PTR(slow_tilt_time); + OPT_PTR(area_fill); } }; diff --git a/src/libslic3r/PrintExport.hpp b/src/libslic3r/PrintExport.hpp index 5cfb552176..e196cde5f2 100644 --- a/src/libslic3r/PrintExport.hpp +++ b/src/libslic3r/PrintExport.hpp @@ -14,6 +14,17 @@ namespace Slic3r { +// Used for addressing parameters of FilePrinter::set_statistics() +enum ePrintStatistics +{ + psUsedMaterial = 0, + psNumFade, + psNumSlow, + psNumFast, + + psCnt +}; + enum class FilePrinterFormat { SLA_PNGZIP, SVG @@ -118,32 +129,45 @@ template<> class FilePrinter double m_layer_height = .0; Raster::Origin m_o = Raster::Origin::TOP_LEFT; + double m_used_material = 0.0; + int m_cnt_fade_layers = 0; + int m_cnt_slow_layers = 0; + int m_cnt_fast_layers = 0; + std::string createIniContent(const std::string& projectname) { - double layer_height = m_layer_height; +// double layer_height = m_layer_height; using std::string; using std::to_string; auto expt_str = to_string(m_exp_time_s); auto expt_first_str = to_string(m_exp_time_first_s); - auto stepnum_str = to_string(static_cast(800*layer_height)); - auto layerh_str = to_string(layer_height); +// auto stepnum_str = to_string(static_cast(800*layer_height)); + auto layerh_str = to_string(m_layer_height); + + const std::string cnt_fade_layers = to_string(m_cnt_fade_layers); + const std::string cnt_slow_layers = to_string(m_cnt_slow_layers); + const std::string cnt_fast_layers = to_string(m_cnt_fast_layers); + const std::string used_material = to_string(m_used_material); return string( "action = print\n" "jobDir = ") + projectname + "\n" + "expTime = " + expt_str + "\n" "expTimeFirst = " + expt_first_str + "\n" - "stepNum = " + stepnum_str + "\n" - "wifiOn = 1\n" - "tiltSlow = 60\n" - "tiltFast = 15\n" - "numFade = 10\n" - "startdelay = 0\n" +// "stepNum = " + stepnum_str + "\n" +// "wifiOn = 1\n" +// "tiltSlow = 60\n" +// "tiltFast = 15\n" + "numFade = " + cnt_fade_layers + "\n" +// "startdelay = 0\n" "layerHeight = " + layerh_str + "\n" "noteInfo = " - "expTime="+expt_str+"+resinType=generic+layerHeight=" - +layerh_str+"+printer=DWARF3\n"; + "expTime = "+expt_str+" + resinType = generic+layerHeight = " + +layerh_str+" + printer = DWARF3\n" + "usedMaterial = " + used_material + "\n" + "numSlow = " + cnt_slow_layers + "\n" + "numFast = " + cnt_fast_layers + "\n"; } public: @@ -277,6 +301,17 @@ public: out.close(); m_layers_rst[i].first.reset(); } + + void set_statistics(const std::vector statistics) + { + if (statistics.size() != psCnt) + return; + + m_used_material = statistics[psUsedMaterial]; + m_cnt_fade_layers = int(statistics[psNumFade]); + m_cnt_slow_layers = int(statistics[psNumSlow]); + m_cnt_fast_layers = int(statistics[psNumFast]); + } }; } diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 2134376126..01f35149d2 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -2,12 +2,14 @@ #include "SLA/SLASupportTree.hpp" #include "SLA/SLABasePool.hpp" #include "SLA/SLAAutoSupports.hpp" +#include "ClipperUtils.hpp" #include "MTUtils.hpp" #include #include #include +#include #include //#include //#include "tbb/mutex.h" @@ -182,7 +184,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf if (model.id() != m_model.id()) { // Kill everything, initialize from scratch. // Stop background processing. - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(this->invalidate_all_steps()); for (SLAPrintObject *object : m_objects) { model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); @@ -211,7 +213,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf } else { // Reorder the objects, add new objects. // First stop background processing before shuffling or deleting the PrintObjects in the object list. - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(this->invalidate_step(slapsRasterize)); // Second create a new list of objects. std::vector model_objects_old(std::move(m_model.objects)); @@ -380,7 +382,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf } if (m_objects != print_objects_new) { - this->call_cancell_callback(); + this->call_cancel_callback(); update_apply_status(this->invalidate_all_steps()); m_objects = print_objects_new; // Delete the PrintObjects marked as Unknown or Deleted. @@ -436,7 +438,7 @@ void SLAPrint::set_task(const TaskParams ¶ms) } } if (!running) - this->cancel_callback(); + this->call_cancel_callback(); // Now the background process is either stopped, or it is inside one of the print object steps to be calculated anyway. if (params.single_model_instance_only) { @@ -476,6 +478,15 @@ void SLAPrint::finalize() m_stepmask[istep] = true; } +// Generate a recommended output file name based on the format template, default extension, and template parameters +// (timestamps, object placeholders derived from the model, current placeholder prameters and print statistics. +// Use the final print statistics if available, or just keep the print statistics placeholders if not available yet (before the output is finalized). +std::string SLAPrint::output_filename() const +{ + DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders(); + return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "zip", &config); +} + namespace { // Compile the argument for support creation from the static print config. sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { @@ -959,6 +970,15 @@ void SLAPrint::process() // Print all the layers in parallel tbb::parallel_for(0, lvlcnt, lvlfn); + + // Fill statistics + this->fill_statistics(); + // Set statistics values to the printer + m_printer->set_statistics({(m_print_statistics.objects_used_material + m_print_statistics.support_used_material)/1000, + 10.0, + double(m_print_statistics.slow_layers_count), + double(m_print_statistics.fast_layers_count) + }); }; using slaposFn = std::function; @@ -1069,7 +1089,10 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector steps; @@ -1102,6 +1125,166 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector& instances) { + const size_t inst_cnt = instances.size(); + + size_t polygon_cnt = 0; + for (const ExPolygon& polygon : input_polygons) + polygon_cnt += polygon.holes.size() + 1; + + Polygons polygons; + polygons.reserve(polygon_cnt * inst_cnt); + for (const ExPolygon& polygon : input_polygons) { + for (size_t i = 0; i < inst_cnt; ++i) + { + ExPolygon tmp = polygon; + tmp.rotate(Geometry::rad2deg(instances[i].rotation)); + tmp.translate(instances[i].shift.x(), instances[i].shift.y()); + polygons_append(polygons, to_polygons(std::move(tmp))); + } + } + return polygons; + }; + + double supports_volume = 0.0; + double models_volume = 0.0; + + double estim_time = 0.0; + + size_t slow_layers = 0; + size_t fast_layers = 0; + + // find highest object + // Which is a better bet? To compare by max_z or by number of layers in the index? + double max_z = 0.; + size_t max_layers_cnt = 0; + size_t highest_obj_idx = 0; + for (SLAPrintObject *&po : m_objects) { + const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index(); + if (! slice_index.empty()) { + double z = (-- slice_index.end())->first; + size_t cnt = slice_index.size(); + //if (z > max_z) { + if (cnt > max_layers_cnt) { + max_layers_cnt = cnt; + max_z = z; + highest_obj_idx = &po - &m_objects.front(); + } + } + } + + const SLAPrintObject * highest_obj = m_objects[highest_obj_idx]; + const SLAPrintObject::SliceIndex& highest_obj_slice_index = highest_obj->get_slice_index(); + + const double delta_fade_time = (init_exp_time - exp_time) / (fade_layers_cnt + 1); + double fade_layer_time = init_exp_time; + + int sliced_layer_cnt = 0; + for (const auto& layer : highest_obj_slice_index) + { + const double l_height = (layer.first == highest_obj_slice_index.begin()->first) ? init_layer_height : layer_height; + + // Calculation of the consumed material + + Polygons model_polygons; + Polygons supports_polygons; + + for (SLAPrintObject * po : m_objects) + { + const SLAPrintObject::SliceRecord *record = nullptr; + { + const SLAPrintObject::SliceIndex& index = po->get_slice_index(); + auto key = layer.first; + const SLAPrintObject::SliceIndex::const_iterator it_key = index.lower_bound(key - float(EPSILON)); + if (it_key == index.end() || it_key->first > key + EPSILON) + continue; + record = &it_key->second; + } + + if (record->model_slices_idx != SLAPrintObject::SliceRecord::NONE) + append(model_polygons, get_all_polygons(po->get_model_slices()[record->model_slices_idx], po->instances())); + + if (record->support_slices_idx != SLAPrintObject::SliceRecord::NONE) + append(supports_polygons, get_all_polygons(po->get_support_slices()[record->support_slices_idx], po->instances())); + } + + model_polygons = union_(model_polygons); + double layer_model_area = 0; + for (const Polygon& polygon : model_polygons) + layer_model_area += polygon.area(); + + if (layer_model_area != 0) + models_volume += layer_model_area * l_height; + + if (!supports_polygons.empty() && !model_polygons.empty()) + supports_polygons = diff(supports_polygons, model_polygons); + double layer_support_area = 0; + for (const Polygon& polygon : supports_polygons) + layer_support_area += polygon.area(); + + if (layer_support_area != 0) + supports_volume += layer_support_area * l_height; + + // Calculation of the slow and fast layers to the future controlling those values on FW + + const bool is_fast_layer = (layer_model_area + layer_support_area) <= display_area*area_fill; + const double tilt_time = is_fast_layer ? fast_tilt : slow_tilt; + if (is_fast_layer) + fast_layers++; + else + slow_layers++; + + + // Calculation of the printing time + + if (sliced_layer_cnt < 3) + estim_time += init_exp_time; + else if (fade_layer_time > exp_time) + { + fade_layer_time -= delta_fade_time; + estim_time += fade_layer_time; + } + else + estim_time += exp_time; + + estim_time += tilt_time; + + sliced_layer_cnt++; + } + + m_print_statistics.support_used_material = supports_volume * SCALING_FACTOR * SCALING_FACTOR; + m_print_statistics.objects_used_material = models_volume * SCALING_FACTOR * SCALING_FACTOR; + + // Estimated printing time + // A layers count o the highest object + if (max_layers_cnt == 0) + m_print_statistics.estimated_print_time = "N/A"; + else + m_print_statistics.estimated_print_time = get_time_dhms(float(estim_time)); + + m_print_statistics.fast_layers_count = fast_layers; + m_print_statistics.slow_layers_count = slow_layers; +} + // Returns true if an object step is done on all objects and there's at least one object. bool SLAPrint::is_step_done(SLAPrintObjectStep step) const { @@ -1339,4 +1522,43 @@ std::vector SLAPrintObject::transformed_support_points() cons return ret; } +DynamicConfig SLAPrintStatistics::config() const +{ + DynamicConfig config; + const std::string print_time = Slic3r::short_time(this->estimated_print_time); + config.set_key_value("print_time", new ConfigOptionString(print_time)); + config.set_key_value("objects_used_material", new ConfigOptionFloat(this->objects_used_material)); + config.set_key_value("support_used_material", new ConfigOptionFloat(this->support_used_material)); + config.set_key_value("total_cost", new ConfigOptionFloat(this->total_cost)); + config.set_key_value("total_weight", new ConfigOptionFloat(this->total_weight)); + return config; +} + +DynamicConfig SLAPrintStatistics::placeholders() +{ + DynamicConfig config; + for (const std::string &key : { + "print_time", "total_cost", "total_weight", + "objects_used_material", "support_used_material" }) + config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}")); + return config; +} + +std::string SLAPrintStatistics::finalize_output_path(const std::string &path_in) const +{ + std::string final_path; + try { + boost::filesystem::path path(path_in); + DynamicConfig cfg = this->config(); + PlaceholderParser pp; + std::string new_stem = pp.process(path.stem().string(), 0, &cfg); + final_path = (path.parent_path() / (new_stem + path.extension().string())).string(); + } + catch (const std::exception &ex) { + BOOST_LOG_TRIVIAL(error) << "Failed to apply the print statistics to the export file name: " << ex.what(); + final_path = path_in; + } + return final_path; +} + } // namespace Slic3r diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 68a0d34aac..4ac17f7b5c 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -2,7 +2,6 @@ #define slic3r_SLAPrint_hpp_ #include - #include "PrintBase.hpp" #include "PrintExport.hpp" #include "Point.hpp" @@ -172,6 +171,35 @@ using PrintObjects = std::vector; class TriangleMesh; +struct SLAPrintStatistics +{ + SLAPrintStatistics() { clear(); } + std::string estimated_print_time; + double objects_used_material; + double support_used_material; + size_t slow_layers_count; + size_t fast_layers_count; + double total_cost; + double total_weight; + + // Config with the filled in print statistics. + DynamicConfig config() const; + // Config with the statistics keys populated with placeholder strings. + static DynamicConfig placeholders(); + // Replace the print statistics placeholders in the path. + std::string finalize_output_path(const std::string &path_in) const; + + void clear() { + estimated_print_time.clear(); + objects_used_material = 0.; + support_used_material = 0.; + slow_layers_count = 0; + fast_layers_count = 0; + total_cost = 0.; + total_weight = 0.; + } +}; + /** * @brief This class is the high level FSM for the SLA printing process. * @@ -208,8 +236,9 @@ public: } const PrintObjects& objects() const { return m_objects; } - std::string output_filename() const override - { return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "zip"); } + std::string output_filename() const override; + + const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } private: using SLAPrinter = FilePrinter; @@ -218,6 +247,8 @@ private: // Invalidate steps based on a set of parameters changed. bool invalidate_state_by_config_options(const std::vector &opt_keys); + void fill_statistics(); + SLAPrintConfig m_print_config; SLAPrinterConfig m_printer_config; SLAMaterialConfig m_material_config; @@ -249,6 +280,9 @@ private: // The printer itself SLAPrinterPtr m_printer; + // Estimated print time, material consumed. + SLAPrintStatistics m_print_statistics; + friend SLAPrintObject; }; diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 046745e6f5..c13df45462 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -206,6 +206,69 @@ public: void reset() { closure = Closure(); } }; +// Shorten the dhms time by removing the seconds, rounding the dhm to full minutes +// and removing spaces. +static std::string short_time(const std::string &time) +{ + // Parse the dhms time format. + int days = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + if (time.find('d') != std::string::npos) + ::sscanf(time.c_str(), "%dd %dh %dm %ds", &days, &hours, &minutes, &seconds); + else if (time.find('h') != std::string::npos) + ::sscanf(time.c_str(), "%dh %dm %ds", &hours, &minutes, &seconds); + else if (time.find('m') != std::string::npos) + ::sscanf(time.c_str(), "%dm %ds", &minutes, &seconds); + else if (time.find('s') != std::string::npos) + ::sscanf(time.c_str(), "%ds", &seconds); + // Round to full minutes. + if (days + hours + minutes > 0 && seconds >= 30) { + if (++minutes == 60) { + minutes = 0; + if (++hours == 24) { + hours = 0; + ++days; + } + } + } + // Format the dhm time. + char buffer[64]; + if (days > 0) + ::sprintf(buffer, "%dd%dh%dm", days, hours, minutes); + else if (hours > 0) + ::sprintf(buffer, "%dh%dm", hours, minutes); + else if (minutes > 0) + ::sprintf(buffer, "%dm", minutes); + else + ::sprintf(buffer, "%ds", seconds); + return buffer; +} + +// Returns the given time is seconds in format DDd HHh MMm SSs +static std::string get_time_dhms(float time_in_secs) +{ + int days = (int)(time_in_secs / 86400.0f); + time_in_secs -= (float)days * 86400.0f; + int hours = (int)(time_in_secs / 3600.0f); + time_in_secs -= (float)hours * 3600.0f; + int minutes = (int)(time_in_secs / 60.0f); + time_in_secs -= (float)minutes * 60.0f; + + char buffer[64]; + if (days > 0) + ::sprintf(buffer, "%dd %dh %dm %ds", days, hours, minutes, (int)time_in_secs); + else if (hours > 0) + ::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)time_in_secs); + else if (minutes > 0) + ::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs); + else + ::sprintf(buffer, "%ds", (int)time_in_secs); + + return buffer; +} + } // namespace Slic3r #if WIN32 diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 2df1f0bc99..90e2cbc9c7 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -13,6 +13,7 @@ #include "libslic3r/Utils.hpp" #include "avrdude/avrdude-slic3r.hpp" #include "GUI.hpp" +#include "GUI_App.hpp" #include "I18N.hpp" #include "MsgDialog.hpp" #include "../Utils/HexFile.hpp" @@ -36,7 +37,6 @@ #include #include #include -#include "GUI_App.hpp" namespace fs = boost::filesystem; @@ -693,11 +693,16 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : enum { DIALOG_MARGIN = 15, SPACING = 10, - MIN_WIDTH = 600, - MIN_HEIGHT = 200, - MIN_HEIGHT_EXPANDED = 500, + MIN_WIDTH = 50, + MIN_HEIGHT = 18, + MIN_HEIGHT_EXPANDED = 40, }; + const int em = GUI::wxGetApp().em_unit(); + int min_width = MIN_WIDTH * em; + int min_height = MIN_HEIGHT * em; + int min_height_expanded = MIN_HEIGHT_EXPANDED * em; + wxFont status_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); status_font.MakeBold(); wxFont mono_font(wxFontInfo().Family(wxFONTFAMILY_TELETYPE)); @@ -769,10 +774,10 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : auto *topsizer = new wxBoxSizer(wxVERTICAL); topsizer->Add(panel, 1, wxEXPAND | wxALL, DIALOG_MARGIN); - SetMinSize(wxSize(MIN_WIDTH, MIN_HEIGHT)); + SetMinSize(wxSize(min_width, min_height)); SetSizerAndFit(topsizer); const auto size = GetSize(); - SetSize(std::max(size.GetWidth(), static_cast(MIN_WIDTH)), std::max(size.GetHeight(), static_cast(MIN_HEIGHT))); + SetSize(std::max(size.GetWidth(), static_cast(min_width)), std::max(size.GetHeight(), static_cast(min_height))); Layout(); SetEscapeId(wxID_CLOSE); // To close the dialog using "Esc" button @@ -786,13 +791,13 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) : } }); - p->spoiler->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, [this](wxCollapsiblePaneEvent &evt) { + p->spoiler->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, [=](wxCollapsiblePaneEvent &evt) { if (evt.GetCollapsed()) { - this->SetMinSize(wxSize(MIN_WIDTH, MIN_HEIGHT)); + this->SetMinSize(wxSize(min_width, min_height)); const auto new_height = this->GetSize().GetHeight() - this->p->txt_stdout->GetSize().GetHeight(); this->SetSize(this->GetSize().GetWidth(), new_height); } else { - this->SetMinSize(wxSize(MIN_WIDTH, MIN_HEIGHT_EXPANDED)); + this->SetMinSize(wxSize(min_width, min_height_expanded)); } this->Layout(); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f187e50994..d48b6ea616 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3279,8 +3279,8 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c wxMemoryDC mask_memDC; // calculate scaling -// const float scale = canvas.get_canvas_size().get_scale_factor(); - const float scale = wxGetApp().em_unit()*0.1; // get scale from em_unit() value, because of get_scale_factor() return 1 + const float scale_gl = canvas.get_canvas_size().get_scale_factor(); + const float scale = scale_gl * wxGetApp().em_unit()*0.1; // get scale from em_unit() value, because of get_scale_factor() return 1 const int scaled_square = std::floor((float)Px_Square * scale); const int scaled_title_offset = Px_Title_Offset * scale; const int scaled_text_offset = Px_Text_Offset * scale; @@ -3288,7 +3288,7 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c const int scaled_border = Px_Border * scale; // select default font - const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)/*.Scale(scale)*/; // font is no need to scale now + const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl); memDC.SetFont(font); mask_memDC.SetFont(font); @@ -3486,6 +3486,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) @@ -3516,6 +3517,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) , m_multisample_allowed(false) , m_regenerate_volumes(true) , m_moving(false) + , m_tab_down(false) , m_color_by("volume") , m_reload_delayed(false) , m_render_sla_auxiliaries(true) @@ -4673,6 +4675,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) void GLCanvas3D::on_key(wxKeyEvent& evt) { + const int keyCode = evt.GetKeyCode(); + #if ENABLE_IMGUI auto imgui = wxGetApp().imgui(); if (imgui->update_key_data(evt)) { @@ -4680,14 +4684,25 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) } else #endif // ENABLE_IMGUI if (evt.GetEventType() == wxEVT_KEY_UP) { - const int keyCode = evt.GetKeyCode(); - - // shift has been just released - SLA gizmo might want to close rectangular selection. - if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp)) + if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) { + // Enable switching between 3D and Preview with Tab + // m_canvas->HandleAsNavigationKey(evt); // XXX: Doesn't work in some cases / on Linux + post_event(SimpleEvent(EVT_GLCANVAS_TAB)); + } else if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp)) { + // shift has been just released - SLA gizmo might want to close rectangular selection. m_dirty = true; + } + } else if (evt.GetEventType() == wxEVT_KEY_DOWN) { + m_tab_down = keyCode == WXK_TAB && !evt.HasAnyModifiers(); } - evt.Skip(); // Needed to have EVT_CHAR generated as well + if (keyCode != WXK_TAB + && keyCode != WXK_LEFT + && keyCode != WXK_UP + && keyCode != WXK_RIGHT + && keyCode != WXK_DOWN) { + evt.Skip(); // Needed to have EVT_CHAR generated as well + } } void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index dbd068724e..bcae0f9afe 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -115,6 +115,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); // this describes events being passed from GLCanvas3D to SlaSupport gizmo enum class SLAGizmoEventType { @@ -837,6 +838,7 @@ private: bool m_multisample_allowed; bool m_regenerate_volumes; bool m_moving; + bool m_tab_down; bool m_render_sla_auxiliaries; std::string m_color_by; diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 7a7f08518d..086dbfdb16 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1790,7 +1790,7 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G update_mesh(); // If there are no points, let's ask the backend if it calculated some. - if (m_editing_mode_cache.empty() && m_parent.sla_print()->is_step_done(slaposSupportPoints)) + if (m_editing_mode_cache.empty()) get_data_from_backend(); if (m_model_object != m_old_model_object) @@ -2169,7 +2169,7 @@ void GLGizmoSlaSupports::delete_selected_points() m_unsaved_changes = true; } // This should trigger the support generation - // wxGetApp().plater()->reslice(); + // wxGetApp().plater()->reslice_SLA_supports(*m_model_object); } select_point(NoPoints); @@ -2283,7 +2283,9 @@ RENDER_AGAIN: if (apply_changes) { editing_mode_apply_changes(); force_refresh = true; - m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + // Recalculate support structures once the editing mode is left. + // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + wxGetApp().plater()->reslice_SLA_supports(*m_model_object); } ImGui::SameLine(); bool discard_changes = m_imgui->button(_(L("Discard changes"))); @@ -2316,7 +2318,7 @@ RENDER_AGAIN: if (m_model_object->sla_support_points.empty() || dlg.ShowModal() == wxID_YES) { m_model_object->sla_support_points.clear(); m_editing_mode_cache.clear(); - wxGetApp().plater()->reslice(); + wxGetApp().plater()->reslice_SLA_supports(*m_model_object); } #endif } @@ -2335,7 +2337,7 @@ RENDER_AGAIN: m_model_object->sla_support_points.clear(); m_editing_mode_cache.clear(); - wxGetApp().plater()->reslice(); + wxGetApp().plater()->reslice_SLA_supports(*m_model_object); } ImGui::SameLine(); if (m_imgui->button(_(L("Cancel")))) { @@ -2496,7 +2498,7 @@ void GLGizmoSlaSupports::editing_mode_reload_cache() void GLGizmoSlaSupports::get_data_from_backend() { for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { - if (po->model_object()->id() == m_model_object->id()) { + if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) { const std::vector& points = po->get_support_points(); auto mat = po->trafo().inverse().cast(); for (unsigned int i=0; iappend_single_option_line(Option(def, "object_name")); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 5fcea479c0..25872fc1f7 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -52,7 +52,7 @@ View3D::~View3D() bool View3D::init(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) { - if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)) + if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */)) return false; m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(this); @@ -227,7 +227,7 @@ bool Preview::init(wxWindow* parent, DynamicPrintConfig* config, BackgroundSlici if ((config == nullptr) || (process == nullptr) || (gcode_preview_data == nullptr)) return false; - if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)) + if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */)) return false; m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(this); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 0ec0050e6d..0e437ef6d9 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -138,11 +138,8 @@ bool ImGuiWrapper::update_key_data(wxKeyEvent &evt) io.KeyAlt = evt.AltDown(); io.KeySuper = evt.MetaDown(); - // XXX: Unfortunatelly this seems broken due to some interference with wxWidgets, - // we have to return true always (perform re-render). - // new_frame(); - // return want_keyboard() || want_text_input(); - return true; + new_frame(); + return want_keyboard() || want_text_input(); } } diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index a5af6afe25..09bb89e4f7 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -32,8 +32,8 @@ struct MsgDialog : wxDialog protected: enum { - CONTENT_WIDTH = 50,//500, - CONTENT_MAX_HEIGHT = 60,//600, + CONTENT_WIDTH = 50, + CONTENT_MAX_HEIGHT = 60, BORDER = 30, VERT_SPACING = 15, HORIZ_SPACING = 5, diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index ad949cbf54..3b66799858 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -99,6 +99,11 @@ public: wxStaticText *info_facets; wxStaticText *info_materials; wxStaticText *info_manifold; + + wxStaticText *label_volume; + wxStaticText *label_materials; + std::vector sla_hidden_items; + bool showing_manifold_warning_icon; void show_sizer(bool show); }; @@ -120,15 +125,16 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : (*info_label)->SetFont(wxGetApp().small_font()); grid_sizer->Add(text, 0); grid_sizer->Add(*info_label, 0); + return text; }; init_info_label(&info_size, _(L("Size"))); - init_info_label(&info_volume, _(L("Volume"))); + label_volume = init_info_label(&info_volume, _(L("Volume"))); init_info_label(&info_facets, _(L("Facets"))); - init_info_label(&info_materials, _(L("Materials"))); + label_materials = init_info_label(&info_materials, _(L("Materials"))); Add(grid_sizer, 0, wxEXPAND); - auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold"))); + auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold")) + ":"); info_manifold_text->SetFont(wxGetApp().small_font()); info_manifold = new wxStaticText(parent, wxID_ANY, ""); info_manifold->SetFont(wxGetApp().small_font()); @@ -139,6 +145,8 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : sizer_manifold->Add(manifold_warning_icon, 0, wxLEFT, 2); sizer_manifold->Add(info_manifold, 0, wxLEFT, 2); Add(sizer_manifold, 0, wxEXPAND | wxTOP, 4); + + sla_hidden_items = { label_volume, info_volume, label_materials, info_materials }; } void ObjectInfo::show_sizer(bool show) @@ -153,6 +161,7 @@ enum SlisedInfoIdx siFilament_m, siFilament_mm3, siFilament_g, + siMateril_unit, siCost, siEstimatedTime, siWTNumbetOfToolchanges, @@ -193,6 +202,7 @@ SlicedInfo::SlicedInfo(wxWindow *parent) : init_info_label(_(L("Used Filament (m)"))); init_info_label(_(L("Used Filament (mm³)"))); init_info_label(_(L("Used Filament (g)"))); + init_info_label(_(L("Used Material (unit)"))); init_info_label(_(L("Cost"))); init_info_label(_(L("Estimated printing time"))); init_info_label(_(L("Number of tool changes"))); @@ -828,6 +838,11 @@ void Sidebar::show_info_sizer() } p->object_info->show_sizer(true); + + if (p->plater->printer_technology() == ptSLA) { + for (auto item: p->object_info->sla_hidden_items) + item->Show(false); + } } void Sidebar::show_sliced_info_sizer(const bool show) @@ -836,53 +851,83 @@ void Sidebar::show_sliced_info_sizer(const bool show) p->sliced_info->Show(show); if (show) { - const PrintStatistics& ps = p->plater->fff_print().print_statistics(); - const bool is_wipe_tower = ps.total_wipe_tower_filament > 0; + if (p->plater->printer_technology() == ptSLA) + { + const SLAPrintStatistics& ps = p->plater->sla_print().print_statistics(); + wxString new_label = _(L("Used Material (ml)")) + " :"; + const bool is_supports = ps.support_used_material > 0.0; + if (is_supports) + new_label += wxString::Format("\n - %s\n - %s", _(L("object(s)")), _(L("supports and pad"))); - wxString new_label = _(L("Used Filament (m)")); - if (is_wipe_tower) - new_label += wxString::Format(" :\n - %s\n - %s", _(L("objects")), _(L("wipe tower"))); + wxString info_text = is_supports ? + wxString::Format("%.2f \n%.2f \n%.2f", (ps.objects_used_material + ps.support_used_material) / 1000, + ps.objects_used_material / 1000, + ps.support_used_material / 1000) : + wxString::Format("%.2f", (ps.objects_used_material + ps.support_used_material) / 1000); + p->sliced_info->SetTextAndShow(siMateril_unit, info_text, new_label); - wxString info_text = is_wipe_tower ? - wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / 1000, - (ps.total_used_filament - ps.total_wipe_tower_filament) / 1000, - ps.total_wipe_tower_filament / 1000) : - wxString::Format("%.2f", ps.total_used_filament / 1000); - p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label); + p->sliced_info->SetTextAndShow(siCost, "N/A"/*wxString::Format("%.2f", ps.total_cost)*/); + p->sliced_info->SetTextAndShow(siEstimatedTime, ps.estimated_print_time, _(L("Estimated printing time")) + " :"); - p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume)); - p->sliced_info->SetTextAndShow(siFilament_g, wxString::Format("%.2f", ps.total_weight)); - - - new_label = _(L("Cost")); - if (is_wipe_tower) - new_label += wxString::Format(" :\n - %s\n - %s", _(L("objects")), _(L("wipe tower"))); - - info_text = is_wipe_tower ? - wxString::Format("%.2f \n%.2f \n%.2f", ps.total_cost, - (ps.total_cost - ps.total_wipe_tower_cost), - ps.total_wipe_tower_cost) : - wxString::Format("%.2f", ps.total_cost); - p->sliced_info->SetTextAndShow(siCost, info_text, new_label); - - if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A") - p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A"); - else { - new_label = _(L("Estimated printing time")) +" :"; - info_text = ""; - if (ps.estimated_normal_print_time != "N/A") { - new_label += wxString::Format("\n - %s", _(L("normal mode"))); - info_text += wxString::Format("\n%s", ps.estimated_normal_print_time); - } - if (ps.estimated_silent_print_time != "N/A") { - new_label += wxString::Format("\n - %s", _(L("silent mode"))); - info_text += wxString::Format("\n%s", ps.estimated_silent_print_time); - } - p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label); + // Hide non-SLA sliced info parameters + p->sliced_info->SetTextAndShow(siFilament_m, "N/A"); + p->sliced_info->SetTextAndShow(siFilament_mm3, "N/A"); + p->sliced_info->SetTextAndShow(siFilament_g, "N/A"); + p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, "N/A"); } + else + { + const PrintStatistics& ps = p->plater->fff_print().print_statistics(); + const bool is_wipe_tower = ps.total_wipe_tower_filament > 0; - // if there is a wipe tower, insert number of toolchanges info into the array: - p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", p->plater->fff_print().wipe_tower_data().number_of_toolchanges) : "N/A"); + wxString new_label = _(L("Used Filament (m)")); + if (is_wipe_tower) + new_label += wxString::Format(" :\n - %s\n - %s", _(L("objects")), _(L("wipe tower"))); + + wxString info_text = is_wipe_tower ? + wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / 1000, + (ps.total_used_filament - ps.total_wipe_tower_filament) / 1000, + ps.total_wipe_tower_filament / 1000) : + wxString::Format("%.2f", ps.total_used_filament / 1000); + p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label); + + p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume)); + p->sliced_info->SetTextAndShow(siFilament_g, wxString::Format("%.2f", ps.total_weight)); + + + new_label = _(L("Cost")); + if (is_wipe_tower) + new_label += wxString::Format(" :\n - %s\n - %s", _(L("objects")), _(L("wipe tower"))); + + info_text = is_wipe_tower ? + wxString::Format("%.2f \n%.2f \n%.2f", ps.total_cost, + (ps.total_cost - ps.total_wipe_tower_cost), + ps.total_wipe_tower_cost) : + wxString::Format("%.2f", ps.total_cost); + p->sliced_info->SetTextAndShow(siCost, info_text, new_label); + + if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A") + p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A"); + else { + new_label = _(L("Estimated printing time")) +" :"; + info_text = ""; + if (ps.estimated_normal_print_time != "N/A") { + new_label += wxString::Format("\n - %s", _(L("normal mode"))); + info_text += wxString::Format("\n%s", ps.estimated_normal_print_time); + } + if (ps.estimated_silent_print_time != "N/A") { + new_label += wxString::Format("\n - %s", _(L("silent mode"))); + info_text += wxString::Format("\n%s", ps.estimated_silent_print_time); + } + p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label); + } + + // if there is a wipe tower, insert number of toolchanges info into the array: + p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", p->plater->fff_print().wipe_tower_data().number_of_toolchanges) : "N/A"); + + // Hide non-FFF sliced info parameters + p->sliced_info->SetTextAndShow(siMateril_unit, "N/A"); + } } Layout(); @@ -1154,9 +1199,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D = new View3D(q, &model, config, &background_process); preview = new Preview(q, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); }); - // Let the Tab key switch between the 3D view and the layer preview. - view3D->Bind(wxEVT_NAVIGATION_KEY, [this](wxNavigationKeyEvent &evt) { if (evt.IsFromTab()) this->select_next_view_3D(); }); - preview->Bind(wxEVT_NAVIGATION_KEY, [this](wxNavigationKeyEvent &evt) { if (evt.IsFromTab()) this->select_next_view_3D(); }); view3D->set_bed(&bed); preview->set_bed(&bed); @@ -1206,6 +1248,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event &evt) { this->sidebar->enable_buttons(evt.data); }); view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this); view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this); + view3D_canvas->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); }); // 3DScene/Toolbar: view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); }); @@ -1223,6 +1266,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); }); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [this](SimpleEvent&) { set_bed_shape(config->option("bed_shape")->values); }); + preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); }); view3D_canvas->Bind(EVT_GLCANVAS_INIT, [this](SimpleEvent&) { init_view_toolbar(); }); @@ -2043,8 +2087,9 @@ unsigned int Plater::priv::update_background_process(bool force_validation) //background_process.is_export_scheduled() - byl zavolan "Export G-code", background processing ma jmeno export souboru //background_process.is_upload_scheduled() - byl zavolan "Send to OctoPrint", jeste nebylo doslajsovano (pak se preda upload fronte a background process zapomene) //background_process.empty() - prazdna plocha - // pokud (invalidated != Print::APPLY_STATUS_UNCHANGED) a ! background_process.empty() -> je neco ke slajsovani (povol tlacitko) - // pokud (return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0 -> doslo k chybe (gray out "Slice now") + // pokud (return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0 -> doslo k chybe (gray out "Slice now") mozna "Invalid data"??? + // jinak background_process.running() -> Zobraz "Slicing ..." + // jinak pokud ! background_process.empty() && ! background_process.finished() -> je neco ke slajsovani (povol tlacitko) "Slice Now" return return_state; } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index ab6d3275ae..b8623eeac3 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -444,6 +444,7 @@ const std::vector& Preset::sla_print_options() if (s_opts.empty()) { s_opts = { "layer_height", + "faded_layers", "supports_enable", "support_head_front_diameter", "support_head_penetration", @@ -500,6 +501,7 @@ const std::vector& Preset::sla_printer_options() "bed_shape", "max_print_height", "display_width", "display_height", "display_pixels_x", "display_pixels_y", "display_orientation", + "fast_tilt_time", "slow_tilt_time", "area_fill", "printer_correction", "print_host", "printhost_apikey", "printhost_cafile", "printer_notes", diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index 6dfa11889d..0d70027c07 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -38,7 +38,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path) #endif auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _(L("Use forward slashes ( / ) as a directory separator if needed."))); - label_dir_hint->Wrap(CONTENT_WIDTH); + label_dir_hint->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(txt_filename, 0, wxEXPAND); content_sizer->Add(label_dir_hint); @@ -135,10 +135,11 @@ PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent) , on_error_evt(this, EVT_PRINTHOST_ERROR, &PrintHostQueueDialog::on_error, this) , on_cancel_evt(this, EVT_PRINTHOST_CANCEL, &PrintHostQueueDialog::on_cancel, this) { - enum { HEIGHT = 800, WIDTH = 400, SPACING = 5 }; + enum { HEIGHT = 60, WIDTH = 30, SPACING = 5 }; - SetSize(wxSize(HEIGHT, WIDTH)); - SetSize(GetMinSize()); + const auto em = GetTextExtent("m").x; + + SetSize(wxSize(HEIGHT * em, WIDTH * em)); auto *topsizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index dc82d1a39e..839e7b74df 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1977,6 +1977,13 @@ void TabPrinter::build_sla() optgroup->append_line(line); optgroup->append_single_option_line("display_orientation"); + optgroup = page->new_optgroup(_(L("Tilt"))); + line = { _(L("Tilt time")), "" }; + line.append_option(optgroup->get_option("fast_tilt_time")); + line.append_option(optgroup->get_option("slow_tilt_time")); + optgroup->append_line(line); + optgroup->append_single_option_line("area_fill"); + optgroup = page->new_optgroup(_(L("Corrections"))); line = Line{ m_config->def()->get("printer_correction")->full_label, "" }; std::vector axes{ "X", "Y", "Z" }; @@ -3210,6 +3217,7 @@ void TabSLAPrint::build() auto optgroup = page->new_optgroup(_(L("Layers"))); optgroup->append_single_option_line("layer_height"); + optgroup->append_single_option_line("faded_layers"); page = add_options_page(_(L("Supports")), "building.png"); optgroup = page->new_optgroup(_(L("Supports"))); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 135420edb9..430caaf0e1 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -204,7 +204,7 @@ protected: void set_type(); int m_em_unit; - std::set m_dirty_options = {}; + std::set m_dirty_options; public: PresetBundle* m_preset_bundle; diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 346a9e231b..c4b78eb1a8 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -12,6 +12,7 @@ #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" #include "GUI.hpp" +#include "GUI_App.hpp" #include "I18N.hpp" #include "ConfigWizard.hpp" @@ -34,7 +35,8 @@ MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_on auto *text = new wxStaticText(this, wxID_ANY, _(L("To download, follow the link below."))); const auto link_width = link->GetSize().GetWidth(); - text->Wrap(CONTENT_WIDTH > link_width ? CONTENT_WIDTH : link_width); + const int content_width = CONTENT_WIDTH * wxGetApp().em_unit(); + text->Wrap(content_width > link_width ? content_width : link_width); content_sizer->Add(text); content_sizer->AddSpacer(VERT_SPACING); @@ -75,7 +77,7 @@ MsgUpdateConfig::MsgUpdateConfig(const std::unordered_mapWrap(CONTENT_WIDTH); + text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(text); content_sizer->AddSpacer(VERT_SPACING); @@ -115,16 +117,16 @@ MsgDataIncompatible::MsgDataIncompatible(const std::unordered_mapWrap(CONTENT_WIDTH); + text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(text); auto *text2 = new wxStaticText(this, wxID_ANY, wxString::Format(_(L("This Slic3r PE version: %s")), SLIC3R_VERSION)); - text2->Wrap(CONTENT_WIDTH); + text2->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(text2); content_sizer->AddSpacer(VERT_SPACING); auto *text3 = new wxStaticText(this, wxID_ANY, _(L("Incompatible bundles:"))); - text3->Wrap(CONTENT_WIDTH); + text3->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(text3); content_sizer->AddSpacer(VERT_SPACING); @@ -175,7 +177,7 @@ MsgDataLegacy::MsgDataLegacy() : )), ConfigWizard::name() )); - text->Wrap(CONTENT_WIDTH); + text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); content_sizer->Add(text); content_sizer->AddSpacer(VERT_SPACING);