mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-08 11:49:08 +08:00
Fixed conflicts after merge with master
This commit is contained in:
commit
eb0b3aea09
@ -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<ModelObject*> 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;
|
||||
|
@ -326,7 +326,7 @@ protected:
|
||||
|
||||
tbb::mutex& state_mutex() const { return m_state_mutex; }
|
||||
std::function<void()> 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.
|
||||
|
@ -2435,6 +2435,32 @@ void PrintConfigDef::init_sla_params()
|
||||
def->enum_labels.push_back(L("Portrait"));
|
||||
def->default_value = new ConfigOptionEnum<SLADisplayOrientation>(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");
|
||||
|
@ -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<SLADisplayOrientation> 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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<FilePrinterFormat::SLA_PNGZIP>
|
||||
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<unsigned>(800*layer_height));
|
||||
auto layerh_str = to_string(layer_height);
|
||||
// auto stepnum_str = to_string(static_cast<unsigned>(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<double> 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]);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2,12 +2,14 @@
|
||||
#include "SLA/SLASupportTree.hpp"
|
||||
#include "SLA/SLABasePool.hpp"
|
||||
#include "SLA/SLAAutoSupports.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <numeric>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
//#include <tbb/spin_mutex.h>//#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<ModelObject*> 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<unsigned, decltype(lvlfn)>(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<void(SLAPrintObject&)>;
|
||||
@ -1069,7 +1089,10 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
||||
"bed_shape",
|
||||
"max_print_height",
|
||||
"printer_technology",
|
||||
"output_filename_format"
|
||||
"output_filename_format",
|
||||
"fast_tilt_time",
|
||||
"slow_tilt_time",
|
||||
"area_fill"
|
||||
};
|
||||
|
||||
std::vector<SLAPrintStep> steps;
|
||||
@ -1102,6 +1125,166 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
void SLAPrint::fill_statistics()
|
||||
{
|
||||
const double init_layer_height = m_material_config.initial_layer_height.getFloat();
|
||||
const double layer_height = m_default_object_config.layer_height.getFloat();
|
||||
|
||||
const double area_fill = m_printer_config.area_fill.getFloat()*0.01;// 0.5 (50%);
|
||||
const double fast_tilt = m_printer_config.fast_tilt_time.getFloat();// 5.0;
|
||||
const double slow_tilt = m_printer_config.slow_tilt_time.getFloat();// 8.0;
|
||||
|
||||
const double init_exp_time = m_material_config.initial_exposure_time.getFloat();
|
||||
const double exp_time = m_material_config.exposure_time.getFloat();
|
||||
|
||||
const int fade_layers_cnt = m_default_object_config.faded_layers.getInt();// 10 // [3;20]
|
||||
|
||||
const double width = m_printer_config.display_width.getFloat() / SCALING_FACTOR;
|
||||
const double height = m_printer_config.display_height.getFloat() / SCALING_FACTOR;
|
||||
const double display_area = width*height;
|
||||
|
||||
// get polygons for all instances in the object
|
||||
auto get_all_polygons = [](const ExPolygons& input_polygons, const std::vector<SLAPrintObject::Instance>& 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<sla::SupportPoint> 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
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define slic3r_SLAPrint_hpp_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "PrintBase.hpp"
|
||||
#include "PrintExport.hpp"
|
||||
#include "Point.hpp"
|
||||
@ -172,6 +171,35 @@ using PrintObjects = std::vector<SLAPrintObject*>;
|
||||
|
||||
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<FilePrinterFormat::SLA_PNGZIP>;
|
||||
@ -218,6 +247,8 @@ private:
|
||||
// Invalidate steps based on a set of parameters changed.
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <wx/collpane.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/filefn.h>
|
||||
#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<int>(MIN_WIDTH)), std::max(size.GetHeight(), static_cast<int>(MIN_HEIGHT)));
|
||||
SetSize(std::max(size.GetWidth(), static_cast<int>(min_width)), std::max(size.GetHeight(), static_cast<int>(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();
|
||||
|
@ -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<bool>);
|
||||
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)
|
||||
|
@ -115,6 +115,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
|
||||
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;
|
||||
|
@ -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<sla::SupportPoint>& points = po->get_support_points();
|
||||
auto mat = po->trafo().inverse().cast<float>();
|
||||
for (unsigned int i=0; i<points.size();++i)
|
||||
|
@ -78,6 +78,7 @@ IMPLEMENT_APP(GUI_App)
|
||||
|
||||
GUI_App::GUI_App()
|
||||
: wxApp()
|
||||
, m_em_unit(10)
|
||||
#if ENABLE_IMGUI
|
||||
, m_imgui(new ImGuiWrapper())
|
||||
#endif // ENABLE_IMGUI
|
||||
|
@ -44,7 +44,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
def.label = L("Name");
|
||||
def.gui_type = "legend";
|
||||
def.tooltip = L("Object name");
|
||||
def.width = 200;
|
||||
def.width = 21 * wxGetApp().em_unit();
|
||||
def.default_value = new ConfigOptionString{ " " };
|
||||
m_og->append_single_option_line(Option(def, "object_name"));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -99,6 +99,11 @@ public:
|
||||
wxStaticText *info_facets;
|
||||
wxStaticText *info_materials;
|
||||
wxStaticText *info_manifold;
|
||||
|
||||
wxStaticText *label_volume;
|
||||
wxStaticText *label_materials;
|
||||
std::vector<wxStaticText *> 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<bool> &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<ConfigOptionPoints>("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;
|
||||
}
|
||||
|
@ -444,6 +444,7 @@ const std::vector<std::string>& 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<std::string>& 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",
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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<std::string> 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")));
|
||||
|
@ -204,7 +204,7 @@ protected:
|
||||
void set_type();
|
||||
|
||||
int m_em_unit;
|
||||
std::set<std::string> m_dirty_options = {};
|
||||
std::set<std::string> m_dirty_options;
|
||||
|
||||
public:
|
||||
PresetBundle* m_preset_bundle;
|
||||
|
@ -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_map<std::string, std::stri
|
||||
"should there be a problem with the new version.\n\n"
|
||||
"Updated configuration bundles:"
|
||||
)));
|
||||
text->Wrap(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_map<std::string, w
|
||||
"You may either exit Slic3r and try again with a newer version, or you may re-run the initial configuration. "
|
||||
"Doing so will create a backup snapshot of the existing configuration before installing files compatible with this Slic3r.\n"
|
||||
)));
|
||||
text->Wrap(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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user