mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-29 03:31:17 -06:00
Merge remote-tracking branch 'origin' into ys_printable_property
This commit is contained in:
commit
0520da3241
16 changed files with 2709 additions and 2039 deletions
|
|
@ -375,7 +375,7 @@ public:
|
|||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
}
|
||||
return false;
|
||||
return modified;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -579,11 +579,11 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
|||
}
|
||||
|
||||
if (print->config().remaining_times.value) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode" << log_memory_info();
|
||||
m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||
m_normal_time_estimator.reset();
|
||||
if (m_silent_time_estimator_enabled) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode" << log_memory_info();
|
||||
m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
|
||||
m_silent_time_estimator.reset();
|
||||
}
|
||||
|
|
@ -591,7 +591,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
|||
|
||||
// starts analyzer calculations
|
||||
if (m_enable_analyzer) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info();
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
||||
m_analyzer.reset();
|
||||
}
|
||||
|
|
@ -1838,7 +1838,8 @@ void GCode::process_layer(
|
|||
", time estimator memory: " <<
|
||||
format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) <<
|
||||
", analyzer memory: " <<
|
||||
format_memsize_MB(m_analyzer.memory_used());
|
||||
format_memsize_MB(m_analyzer.memory_used()) <<
|
||||
log_memory_info();
|
||||
}
|
||||
|
||||
void GCode::apply_print_config(const PrintConfig &print_config)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
unsigned int Model::s_auto_extruder_id = 1;
|
||||
|
||||
Model& Model::assign_copy(const Model &rhs)
|
||||
{
|
||||
this->copy_id(rhs);
|
||||
|
|
@ -485,9 +483,20 @@ bool Model::looks_like_multipart_object() const
|
|||
return false;
|
||||
}
|
||||
|
||||
// Generate next extruder ID string, in the range of (1, max_extruders).
|
||||
static inline std::string auto_extruder_id(unsigned int max_extruders, unsigned int &cntr)
|
||||
{
|
||||
char str_extruder[64];
|
||||
sprintf(str_extruder, "%ud", cntr + 1);
|
||||
if (++ cntr == max_extruders)
|
||||
cntr = 0;
|
||||
return str_extruder;
|
||||
}
|
||||
|
||||
void Model::convert_multipart_object(unsigned int max_extruders)
|
||||
{
|
||||
if (this->objects.empty())
|
||||
assert(this->objects.size() >= 2);
|
||||
if (this->objects.size() < 2)
|
||||
return;
|
||||
|
||||
ModelObject* object = new ModelObject(this);
|
||||
|
|
@ -495,58 +504,32 @@ void Model::convert_multipart_object(unsigned int max_extruders)
|
|||
object->name = this->objects.front()->name;
|
||||
//FIXME copy the config etc?
|
||||
|
||||
reset_auto_extruder_id();
|
||||
|
||||
bool is_single_object = (this->objects.size() == 1);
|
||||
|
||||
for (const ModelObject* o : this->objects)
|
||||
{
|
||||
for (const ModelVolume* v : o->volumes)
|
||||
{
|
||||
if (is_single_object)
|
||||
{
|
||||
// If there is only one object, just copy the volumes
|
||||
ModelVolume* new_v = object->add_volume(*v);
|
||||
if (new_v != nullptr)
|
||||
{
|
||||
new_v->name = o->name;
|
||||
new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders));
|
||||
new_v->translate(-o->origin_translation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there are more than one object, put all volumes together
|
||||
// Each object may contain any number of volumes and instances
|
||||
// The volumes transformations are relative to the object containing them...
|
||||
int counter = 1;
|
||||
for (const ModelInstance* i : o->instances)
|
||||
{
|
||||
ModelVolume* new_v = object->add_volume(*v);
|
||||
if (new_v != nullptr)
|
||||
{
|
||||
new_v->name = o->name + "_" + std::to_string(counter++);
|
||||
new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders));
|
||||
new_v->translate(-o->origin_translation);
|
||||
// ...so, transform everything to a common reference system (world)
|
||||
new_v->set_transformation(i->get_transformation() * v->get_transformation());
|
||||
}
|
||||
}
|
||||
unsigned int extruder_counter = 0;
|
||||
for (const ModelObject* o : this->objects)
|
||||
for (const ModelVolume* v : o->volumes) {
|
||||
// If there are more than one object, put all volumes together
|
||||
// Each object may contain any number of volumes and instances
|
||||
// The volumes transformations are relative to the object containing them...
|
||||
Geometry::Transformation trafo_volume = v->get_transformation();
|
||||
// Revert the centering operation.
|
||||
trafo_volume.set_offset(trafo_volume.get_offset() - o->origin_translation);
|
||||
int counter = 1;
|
||||
auto copy_volume = [o, max_extruders, &counter, &extruder_counter](ModelVolume *new_v) {
|
||||
assert(new_v != nullptr);
|
||||
new_v->name = o->name + "_" + std::to_string(counter++);
|
||||
new_v->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter));
|
||||
return new_v;
|
||||
};
|
||||
if (o->instances.empty()) {
|
||||
copy_volume(object->add_volume(*v))->set_transformation(trafo_volume);
|
||||
} else {
|
||||
for (const ModelInstance* i : o->instances)
|
||||
// ...so, transform everything to a common reference system (world)
|
||||
copy_volume(object->add_volume(*v))->set_transformation(i->get_transformation() * trafo_volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_single_object)
|
||||
{
|
||||
// If there is only one object, keep its instances
|
||||
for (const ModelInstance* i : this->objects.front()->instances)
|
||||
{
|
||||
object->add_instance(*i);
|
||||
}
|
||||
}
|
||||
else
|
||||
// If there are more than one object, create a single instance
|
||||
object->add_instance();
|
||||
// If there are more than one object, create a single instance
|
||||
object->add_instance();
|
||||
|
||||
this->clear_objects();
|
||||
this->objects.push_back(object);
|
||||
|
|
@ -571,32 +554,6 @@ void Model::adjust_min_z()
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int Model::get_auto_extruder_id(unsigned int max_extruders)
|
||||
{
|
||||
unsigned int id = s_auto_extruder_id;
|
||||
if (id > max_extruders) {
|
||||
// The current counter is invalid, likely due to switching the printer profiles
|
||||
// to a profile with a lower number of extruders.
|
||||
reset_auto_extruder_id();
|
||||
id = s_auto_extruder_id;
|
||||
} else if (++ s_auto_extruder_id > max_extruders) {
|
||||
reset_auto_extruder_id();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string Model::get_auto_extruder_id_as_string(unsigned int max_extruders)
|
||||
{
|
||||
char str_extruder[64];
|
||||
sprintf(str_extruder, "%ud", get_auto_extruder_id(max_extruders));
|
||||
return str_extruder;
|
||||
}
|
||||
|
||||
void Model::reset_auto_extruder_id()
|
||||
{
|
||||
s_auto_extruder_id = 1;
|
||||
}
|
||||
|
||||
// Propose a filename including path derived from the ModelObject's input path.
|
||||
// If object's name is filled in, use the object name, otherwise use the input name.
|
||||
std::string Model::propose_export_file_name_and_path() const
|
||||
|
|
@ -1662,7 +1619,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
|||
size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin();
|
||||
std::string name = this->name;
|
||||
|
||||
Model::reset_auto_extruder_id();
|
||||
unsigned int extruder_counter = 0;
|
||||
Vec3d offset = this->get_offset();
|
||||
|
||||
for (TriangleMesh *mesh : meshptrs) {
|
||||
|
|
@ -1681,7 +1638,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
|||
this->object->volumes[ivolume]->center_geometry_after_creation();
|
||||
this->object->volumes[ivolume]->translate(offset);
|
||||
this->object->volumes[ivolume]->name = name + "_" + std::to_string(idx + 1);
|
||||
this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string(max_extruders));
|
||||
this->object->volumes[ivolume]->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter));
|
||||
delete mesh;
|
||||
++ idx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -725,8 +725,6 @@ private:
|
|||
// all objects may share mutliple materials.
|
||||
class Model final : public ObjectBase
|
||||
{
|
||||
static unsigned int s_auto_extruder_id;
|
||||
|
||||
public:
|
||||
// Materials are owned by a model and referenced by objects through t_model_material_id.
|
||||
// Single material may be shared by multiple models.
|
||||
|
|
@ -795,14 +793,10 @@ public:
|
|||
|
||||
void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); }
|
||||
|
||||
static unsigned int get_auto_extruder_id(unsigned int max_extruders);
|
||||
static std::string get_auto_extruder_id_as_string(unsigned int max_extruders);
|
||||
static void reset_auto_extruder_id();
|
||||
|
||||
// Propose an output file name & path based on the first printable object's name and source input file's path.
|
||||
std::string propose_export_file_name_and_path() const;
|
||||
std::string propose_export_file_name_and_path() const;
|
||||
// Propose an output path, replace extension. The new_extension shall contain the initial dot.
|
||||
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
||||
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
||||
|
||||
private:
|
||||
explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); };
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ extern void trace(unsigned int level, const char *message);
|
|||
// Format memory allocated, separate thousands by comma.
|
||||
extern std::string format_memsize_MB(size_t n);
|
||||
// Return string to be added to the boost::log output to inform about the current process memory allocation.
|
||||
// The string is non-empty only if the loglevel >= info (3).
|
||||
extern std::string log_memory_info();
|
||||
// The string is non-empty if the loglevel >= info (3) or ignore_loglevel==true.
|
||||
// Latter is used to get the memory info from SysInfoDialog.
|
||||
extern std::string log_memory_info(bool ignore_loglevel = false);
|
||||
extern void disable_multi_threading();
|
||||
// Returns the size of physical memory (RAM) in bytes.
|
||||
extern size_t total_physical_memory();
|
||||
|
|
|
|||
|
|
@ -13,9 +13,13 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef BSD
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
|
|
@ -431,47 +435,82 @@ std::string format_memsize_MB(size_t n)
|
|||
return out + "MB";
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#ifndef PROCESS_MEMORY_COUNTERS_EX
|
||||
// MingW32 doesn't have this struct in psapi.h
|
||||
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
||||
DWORD cb;
|
||||
DWORD PageFaultCount;
|
||||
SIZE_T PeakWorkingSetSize;
|
||||
SIZE_T WorkingSetSize;
|
||||
SIZE_T QuotaPeakPagedPoolUsage;
|
||||
SIZE_T QuotaPagedPoolUsage;
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage;
|
||||
SIZE_T QuotaNonPagedPoolUsage;
|
||||
SIZE_T PagefileUsage;
|
||||
SIZE_T PeakPagefileUsage;
|
||||
SIZE_T PrivateUsage;
|
||||
} PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX;
|
||||
#endif /* PROCESS_MEMORY_COUNTERS_EX */
|
||||
|
||||
std::string log_memory_info()
|
||||
// Returns platform-specific string to be used as log output or parsed in SysInfoDialog.
|
||||
// The latter parses the string with (semi)colons as separators, it should look about as
|
||||
// "desc1: value1; desc2: value2" or similar (spaces should not matter).
|
||||
std::string log_memory_info(bool ignore_loglevel)
|
||||
{
|
||||
std::string out;
|
||||
if (logSeverity <= boost::log::trivial::info) {
|
||||
if (ignore_loglevel || logSeverity <= boost::log::trivial::info) {
|
||||
#ifdef WIN32
|
||||
#ifndef PROCESS_MEMORY_COUNTERS_EX
|
||||
// MingW32 doesn't have this struct in psapi.h
|
||||
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
||||
DWORD cb;
|
||||
DWORD PageFaultCount;
|
||||
SIZE_T PeakWorkingSetSize;
|
||||
SIZE_T WorkingSetSize;
|
||||
SIZE_T QuotaPeakPagedPoolUsage;
|
||||
SIZE_T QuotaPagedPoolUsage;
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage;
|
||||
SIZE_T QuotaNonPagedPoolUsage;
|
||||
SIZE_T PagefileUsage;
|
||||
SIZE_T PeakPagefileUsage;
|
||||
SIZE_T PrivateUsage;
|
||||
} PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX;
|
||||
#endif /* PROCESS_MEMORY_COUNTERS_EX */
|
||||
|
||||
|
||||
HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId());
|
||||
if (hProcess != nullptr) {
|
||||
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||
if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)))
|
||||
out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + " PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + " Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")";
|
||||
out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")";
|
||||
else
|
||||
out += " Used memory: N/A";
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
#elif defined(__linux__) or defined(__APPLE__)
|
||||
// Get current memory usage.
|
||||
#ifdef __APPLE__
|
||||
struct mach_task_basic_info info;
|
||||
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||
out += " Resident memory: ";
|
||||
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount ) == KERN_SUCCESS )
|
||||
out += format_memsize_MB((size_t)info.resident_size);
|
||||
else
|
||||
out += "N/A";
|
||||
#else // i.e. __linux__
|
||||
size_t tSize = 0, resident = 0, share = 0;
|
||||
std::ifstream buffer("/proc/self/statm");
|
||||
if (buffer && (buffer >> tSize >> resident >> share)) {
|
||||
size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE); // in case x86-64 is configured to use 2MB pages
|
||||
size_t rss = resident * page_size;
|
||||
out += " Resident memory: " + format_memsize_MB(rss);
|
||||
out += "; Shared memory: " + format_memsize_MB(share * page_size);
|
||||
out += "; Private memory: " + format_memsize_MB(rss - share * page_size);
|
||||
}
|
||||
else
|
||||
out += " Used memory: N/A";
|
||||
#endif
|
||||
// Now get peak memory usage.
|
||||
out += "; Peak memory usage: ";
|
||||
rusage memory_info;
|
||||
if (getrusage(RUSAGE_SELF, &memory_info) == 0)
|
||||
{
|
||||
size_t peak_mem_usage = (size_t)memory_info.ru_maxrss;
|
||||
#ifdef __linux__
|
||||
peak_mem_usage *= 1024;// getrusage returns the value in kB on linux
|
||||
#endif
|
||||
out += format_memsize_MB(peak_mem_usage);
|
||||
}
|
||||
else
|
||||
out += "N/A";
|
||||
#endif
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#else
|
||||
std::string log_memory_info()
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns the size of physical memory (RAM) in bytes.
|
||||
// http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
|
||||
size_t total_physical_memory()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue