mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-23 22:54:08 -06:00
Merge branch 'master' of https://github.com/Prusa3d/PrusaSlicer
This commit is contained in:
commit
7e1d2daf78
18 changed files with 240 additions and 119 deletions
|
@ -1,4 +1,5 @@
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
|
#include "I18N.hpp"
|
||||||
#include "GCode.hpp"
|
#include "GCode.hpp"
|
||||||
#include "ExtrusionEntity.hpp"
|
#include "ExtrusionEntity.hpp"
|
||||||
#include "EdgeGrid.hpp"
|
#include "EdgeGrid.hpp"
|
||||||
|
@ -36,6 +37,11 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
//! macro used to mark string used at localization,
|
||||||
|
//! return same string
|
||||||
|
#define L(s) (s)
|
||||||
|
#define _(s) Slic3r::I18N::translate(s)
|
||||||
|
|
||||||
// Only add a newline in case the current G-code does not end with a newline.
|
// Only add a newline in case the current G-code does not end with a newline.
|
||||||
static inline void check_add_eol(std::string &gcode)
|
static inline void check_add_eol(std::string &gcode)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +411,8 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id,
|
||||||
assert(m_layer_idx >= 0 && size_t(m_layer_idx) <= m_tool_changes.size());
|
assert(m_layer_idx >= 0 && size_t(m_layer_idx) <= m_tool_changes.size());
|
||||||
if (! m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
if (! m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||||
if (m_layer_idx < (int)m_tool_changes.size()) {
|
if (m_layer_idx < (int)m_tool_changes.size()) {
|
||||||
assert(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size());
|
if (! (size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||||
|
throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer.");
|
||||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id);
|
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id);
|
||||||
}
|
}
|
||||||
m_brim_done = true;
|
m_brim_done = true;
|
||||||
|
@ -448,6 +455,17 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||||
-- idx_object_layer;
|
-- idx_object_layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let's make sure that the last layer is not empty, so we don't build on top of it.
|
||||||
|
if (! layers_to_print.empty()
|
||||||
|
&& ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|
||||||
|
|| (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions()))
|
||||||
|
&& (! layers_to_print.back().object_layer || ! layers_to_print.back().object_layer->has_extrusions())
|
||||||
|
&& (! layers_to_print.back().support_layer || ! layers_to_print.back().support_layer->has_extrusions()))
|
||||||
|
throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" +
|
||||||
|
_(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) +
|
||||||
|
std::to_string(layers_to_print.back().print_z()));
|
||||||
|
|
||||||
layers_to_print.emplace_back(layer_to_print);
|
layers_to_print.emplace_back(layer_to_print);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,9 +1156,9 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
print.m_print_statistics.clear();
|
print.m_print_statistics.clear();
|
||||||
print.m_print_statistics.estimated_normal_print_time = m_normal_time_estimator.get_time_dhms();
|
print.m_print_statistics.estimated_normal_print_time = m_normal_time_estimator.get_time_dhms();
|
||||||
print.m_print_statistics.estimated_silent_print_time = m_silent_time_estimator_enabled ? m_silent_time_estimator.get_time_dhms() : "N/A";
|
print.m_print_statistics.estimated_silent_print_time = m_silent_time_estimator_enabled ? m_silent_time_estimator.get_time_dhms() : "N/A";
|
||||||
print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms();
|
print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms(true);
|
||||||
if (m_silent_time_estimator_enabled)
|
if (m_silent_time_estimator_enabled)
|
||||||
print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms();
|
print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms(true);
|
||||||
|
|
||||||
std::vector<Extruder> extruders = m_writer.extruders();
|
std::vector<Extruder> extruders = m_writer.extruders();
|
||||||
if (! extruders.empty()) {
|
if (! extruders.empty()) {
|
||||||
|
|
|
@ -78,8 +78,13 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
||||||
zs.emplace_back(layer->print_z);
|
zs.emplace_back(layer->print_z);
|
||||||
for (auto layer : object->support_layers())
|
for (auto layer : object->support_layers())
|
||||||
zs.emplace_back(layer->print_z);
|
zs.emplace_back(layer->print_z);
|
||||||
if (! object->layers().empty())
|
|
||||||
object_bottom_z = object->layers().front()->print_z - object->layers().front()->height;
|
// Find first object layer that is not empty and save its print_z
|
||||||
|
for (const Layer* layer : object->layers())
|
||||||
|
if (layer->has_extrusions()) {
|
||||||
|
object_bottom_z = layer->print_z - layer->height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->initialize_layers(zs);
|
this->initialize_layers(zs);
|
||||||
}
|
}
|
||||||
|
@ -324,6 +329,7 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
||||||
m_layer_tools[j].has_wipe_tower = true;
|
m_layer_tools[j].has_wipe_tower = true;
|
||||||
} else {
|
} else {
|
||||||
LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new);
|
LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new);
|
||||||
|
//LayerTools <_prev = m_layer_tools[j];
|
||||||
LayerTools <_next = m_layer_tools[j + 1];
|
LayerTools <_next = m_layer_tools[j + 1];
|
||||||
assert(! m_layer_tools[j - 1].extruders.empty() && ! lt_next.extruders.empty());
|
assert(! m_layer_tools[j - 1].extruders.empty() && ! lt_next.extruders.empty());
|
||||||
// FIXME: Following assert tripped when running combine_infill.t. I decided to comment it out for now.
|
// FIXME: Following assert tripped when running combine_infill.t. I decided to comment it out for now.
|
||||||
|
|
|
@ -694,22 +694,39 @@ namespace Slic3r {
|
||||||
return m_color_times;
|
return m_color_times;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms() const
|
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
|
float total_time = 0.0f;
|
||||||
for (float t : m_color_times)
|
for (float t : m_color_times)
|
||||||
{
|
{
|
||||||
ret.push_back(_get_time_dhms(t));
|
std::string time = _get_time_dhms(t);
|
||||||
|
if (include_remaining)
|
||||||
|
{
|
||||||
|
time += " (";
|
||||||
|
time += _get_time_dhms(m_time - total_time);
|
||||||
|
time += ")";
|
||||||
|
}
|
||||||
|
total_time += t;
|
||||||
|
ret.push_back(time);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_minutes() const
|
std::vector<std::string> GCodeTimeEstimator::get_color_times_minutes(bool include_remaining) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
|
float total_time = 0.0f;
|
||||||
for (float t : m_color_times)
|
for (float t : m_color_times)
|
||||||
{
|
{
|
||||||
ret.push_back(_get_time_minutes(t));
|
std::string time = _get_time_minutes(t);
|
||||||
|
if (include_remaining)
|
||||||
|
{
|
||||||
|
time += " (";
|
||||||
|
time += _get_time_minutes(m_time - total_time);
|
||||||
|
time += ")";
|
||||||
|
}
|
||||||
|
total_time += t;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,14 +346,16 @@ namespace Slic3r {
|
||||||
// Returns the estimated time, in minutes (integer)
|
// Returns the estimated time, in minutes (integer)
|
||||||
std::string get_time_minutes() const;
|
std::string get_time_minutes() const;
|
||||||
|
|
||||||
// Returns the estimated time, in seconds, for each color
|
// Returns the estimated time, in seconds, for each color
|
||||||
std::vector<float> get_color_times() const;
|
std::vector<float> get_color_times() const;
|
||||||
|
|
||||||
// Returns the estimated time, in format DDd HHh MMm SSs, for each color
|
// Returns the estimated time, in format DDd HHh MMm SSs, for each color
|
||||||
std::vector<std::string> get_color_times_dhms() const;
|
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
|
||||||
|
std::vector<std::string> get_color_times_dhms(bool include_remaining) const;
|
||||||
|
|
||||||
// Returns the estimated time, in minutes (integer), for each color
|
// Returns the estimated time, in minutes (integer), for each color
|
||||||
std::vector<std::string> get_color_times_minutes() const;
|
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
|
||||||
|
std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
|
||||||
|
|
||||||
// Return an estimate of the memory consumed by the time estimator.
|
// Return an estimate of the memory consumed by the time estimator.
|
||||||
size_t memory_used() const;
|
size_t memory_used() const;
|
||||||
|
|
|
@ -1723,7 +1723,7 @@ void Print::_make_wipe_tower()
|
||||||
break;
|
break;
|
||||||
lt.has_support = true;
|
lt.has_support = true;
|
||||||
// Insert the new support layer.
|
// Insert the new support layer.
|
||||||
double height = lt.print_z - m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z;
|
double height = lt.print_z - (i == 0 ? 0. : m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z);
|
||||||
//FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway.
|
//FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway.
|
||||||
it_layer = m_objects.front()->insert_support_layer(it_layer, -1, height, lt.print_z, lt.print_z - 0.5 * height);
|
it_layer = m_objects.front()->insert_support_layer(it_layer, -1, height, lt.print_z, lt.print_z - 0.5 * height);
|
||||||
++ it_layer;
|
++ it_layer;
|
||||||
|
|
|
@ -422,6 +422,7 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern";
|
def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern";
|
||||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||||
def->enum_values = def_top_fill_pattern->enum_values;
|
def->enum_values = def_top_fill_pattern->enum_values;
|
||||||
|
def->enum_labels = def_top_fill_pattern->enum_labels;
|
||||||
def->aliases = def_top_fill_pattern->aliases;
|
def->aliases = def_top_fill_pattern->aliases;
|
||||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,13 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#ifdef BSD
|
#ifdef BSD
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/log/core.hpp>
|
#include <boost/log/core.hpp>
|
||||||
|
@ -432,7 +436,6 @@ std::string format_memsize_MB(size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
#ifndef PROCESS_MEMORY_COUNTERS_EX
|
#ifndef PROCESS_MEMORY_COUNTERS_EX
|
||||||
// MingW32 doesn't have this struct in psapi.h
|
// MingW32 doesn't have this struct in psapi.h
|
||||||
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
||||||
|
@ -464,12 +467,51 @@ std::string log_memory_info()
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
#elif defined(__linux__) or defined(__APPLE__)
|
||||||
|
std::string log_memory_info()
|
||||||
|
{
|
||||||
|
std::string out = " Unable to get current memory usage.";
|
||||||
|
|
||||||
|
// Get current memory usage.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
struct mach_task_basic_info info;
|
||||||
|
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||||
|
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount ) == KERN_SUCCESS )
|
||||||
|
out = " Memory usage: resident: " + format_memsize_MB((size_t)info.resident_size);
|
||||||
|
#else // i.e. __linux__
|
||||||
|
|
||||||
|
size_t tSize = 0, resident = 0, share = 0;
|
||||||
|
std::ifstream buffer("/proc/self/statm");
|
||||||
|
if (buffer) {
|
||||||
|
if ((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 = " Memory usage: resident: " + format_memsize_MB(rss);
|
||||||
|
out += " shared: " + format_memsize_MB(share * page_size);
|
||||||
|
out += " private: " + format_memsize_MB(rss - share * page_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Now get peak memory usage.
|
||||||
|
rusage memory_info;
|
||||||
|
if (getrusage(RUSAGE_SELF, &memory_info) != 0)
|
||||||
|
out += " Could not get peak memory usage.";
|
||||||
|
else {
|
||||||
|
size_t peak_mem_usage = (size_t)memory_info.ru_maxrss;
|
||||||
|
#ifdef __linux
|
||||||
|
peak_mem_usage *= 1024L;// getrusage returns the value in kB on linux
|
||||||
|
#endif
|
||||||
|
out += " Peak Memory Usage: " + format_memsize_MB(peak_mem_usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
std::string log_memory_info()
|
std::string log_memory_info()
|
||||||
{
|
{
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Returns the size of physical memory (RAM) in bytes.
|
// Returns the size of physical memory (RAM) in bytes.
|
||||||
|
|
|
@ -22,10 +22,10 @@ namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
const double Camera::DefaultDistance = 1000.0;
|
const double Camera::DefaultDistance = 1000.0;
|
||||||
double Camera::FrustrumMinZSize = 50.0;
|
double Camera::FrustrumMinZRange = 50.0;
|
||||||
|
double Camera::FrustrumMinNearZ = 100.0;
|
||||||
double Camera::FrustrumZMargin = 10.0;
|
double Camera::FrustrumZMargin = 10.0;
|
||||||
double Camera::FovMinDeg = 0.5;
|
double Camera::MaxFovDeg = 60.0;
|
||||||
double Camera::FovMaxDeg = 75.0;
|
|
||||||
|
|
||||||
Camera::Camera()
|
Camera::Camera()
|
||||||
: phi(45.0f)
|
: phi(45.0f)
|
||||||
|
@ -186,7 +186,8 @@ void Camera::apply_view_matrix() const
|
||||||
|
|
||||||
void Camera::apply_projection(const BoundingBoxf3& box) const
|
void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
m_distance = DefaultDistance;
|
set_distance(DefaultDistance);
|
||||||
|
|
||||||
double w = 0.0;
|
double w = 0.0;
|
||||||
double h = 0.0;
|
double h = 0.0;
|
||||||
|
|
||||||
|
@ -194,15 +195,14 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
||||||
|
|
||||||
w = (double)m_viewport[2];
|
w = 0.5 * (double)m_viewport[2];
|
||||||
h = (double)m_viewport[3];
|
h = 0.5 * (double)m_viewport[3];
|
||||||
|
|
||||||
double two_zoom = 2.0 * m_zoom;
|
if (m_zoom != 0.0)
|
||||||
if (two_zoom != 0.0)
|
|
||||||
{
|
{
|
||||||
double inv_two_zoom = 1.0 / two_zoom;
|
double inv_zoom = 1.0 / m_zoom;
|
||||||
w *= inv_two_zoom;
|
w *= inv_zoom;
|
||||||
h *= inv_two_zoom;
|
h *= inv_zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
|
@ -226,21 +226,16 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
|
|
||||||
if (m_type == Perspective)
|
if (m_type == Perspective)
|
||||||
{
|
{
|
||||||
double fov_rad = 2.0 * std::atan(h / m_frustrum_zs.first);
|
double fov_deg = Geometry::rad2deg(2.0 * std::atan(h / m_frustrum_zs.first));
|
||||||
double fov_deg = Geometry::rad2deg(fov_rad);
|
|
||||||
|
|
||||||
// adjust camera distance to keep fov in a limited range
|
// adjust camera distance to keep fov in a limited range
|
||||||
if (fov_deg > FovMaxDeg + 0.001)
|
if (fov_deg > MaxFovDeg)
|
||||||
{
|
{
|
||||||
double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMaxDeg));
|
double delta_z = h / ::tan(0.5 * Geometry::deg2rad(MaxFovDeg)) - m_frustrum_zs.first;
|
||||||
m_distance += (new_near_z - m_frustrum_zs.first);
|
if (delta_z > 0.001)
|
||||||
apply_view_matrix();
|
set_distance(m_distance + delta_z);
|
||||||
}
|
else
|
||||||
else if (fov_deg < FovMinDeg - 0.001)
|
break;
|
||||||
{
|
|
||||||
double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMinDeg));
|
|
||||||
m_distance += (new_near_z - m_frustrum_zs.first);
|
|
||||||
apply_view_matrix();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -328,42 +323,50 @@ void Camera::debug_render() const
|
||||||
|
|
||||||
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
|
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
std::pair<double, double> ret = std::make_pair(DBL_MAX, -DBL_MAX);
|
std::pair<double, double> ret;
|
||||||
|
|
||||||
Vec3d bb_min = box.min;
|
while (true)
|
||||||
Vec3d bb_max = box.max;
|
|
||||||
|
|
||||||
// box vertices in world space
|
|
||||||
std::vector<Vec3d> vertices;
|
|
||||||
vertices.reserve(8);
|
|
||||||
vertices.push_back(bb_min);
|
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2));
|
|
||||||
vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2));
|
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2));
|
|
||||||
vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2));
|
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2));
|
|
||||||
vertices.push_back(bb_max);
|
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2));
|
|
||||||
|
|
||||||
// set the Z range in eye coordinates (negative Zs are in front of the camera)
|
|
||||||
for (const Vec3d& v : vertices)
|
|
||||||
{
|
{
|
||||||
double z = -(m_view_matrix * v)(2);
|
ret = std::make_pair(DBL_MAX, -DBL_MAX);
|
||||||
ret.first = std::min(ret.first, z);
|
|
||||||
ret.second = std::max(ret.second, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply margin
|
// box vertices in world space
|
||||||
ret.first -= FrustrumZMargin;
|
std::vector<Vec3d> vertices;
|
||||||
ret.second += FrustrumZMargin;
|
vertices.reserve(8);
|
||||||
|
vertices.push_back(box.min);
|
||||||
|
vertices.emplace_back(box.max(0), box.min(1), box.min(2));
|
||||||
|
vertices.emplace_back(box.max(0), box.max(1), box.min(2));
|
||||||
|
vertices.emplace_back(box.min(0), box.max(1), box.min(2));
|
||||||
|
vertices.emplace_back(box.min(0), box.min(1), box.max(2));
|
||||||
|
vertices.emplace_back(box.max(0), box.min(1), box.max(2));
|
||||||
|
vertices.push_back(box.max);
|
||||||
|
vertices.emplace_back(box.min(0), box.max(1), box.max(2));
|
||||||
|
|
||||||
// ensure min size
|
// set the Z range in eye coordinates (negative Zs are in front of the camera)
|
||||||
if (ret.second - ret.first < FrustrumMinZSize)
|
for (const Vec3d& v : vertices)
|
||||||
{
|
{
|
||||||
double mid_z = 0.5 * (ret.first + ret.second);
|
double z = -(m_view_matrix * v)(2);
|
||||||
double half_size = 0.5 * FrustrumMinZSize;
|
ret.first = std::min(ret.first, z);
|
||||||
ret.first = mid_z - half_size;
|
ret.second = std::max(ret.second, z);
|
||||||
ret.second = mid_z + half_size;
|
}
|
||||||
|
|
||||||
|
// apply margin
|
||||||
|
ret.first -= FrustrumZMargin;
|
||||||
|
ret.second += FrustrumZMargin;
|
||||||
|
|
||||||
|
// ensure min size
|
||||||
|
if (ret.second - ret.first < FrustrumMinZRange)
|
||||||
|
{
|
||||||
|
double mid_z = 0.5 * (ret.first + ret.second);
|
||||||
|
double half_size = 0.5 * FrustrumMinZRange;
|
||||||
|
ret.first = mid_z - half_size;
|
||||||
|
ret.second = mid_z + half_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret.first >= FrustrumMinNearZ)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ensure min Near Z
|
||||||
|
set_distance(m_distance + FrustrumMinNearZ - ret.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -385,21 +388,19 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||||
Vec3d up = get_dir_up();
|
Vec3d up = get_dir_up();
|
||||||
Vec3d forward = get_dir_forward();
|
Vec3d forward = get_dir_forward();
|
||||||
|
|
||||||
Vec3d bb_min = box.min;
|
|
||||||
Vec3d bb_max = box.max;
|
|
||||||
Vec3d bb_center = box.center();
|
Vec3d bb_center = box.center();
|
||||||
|
|
||||||
// box vertices in world space
|
// box vertices in world space
|
||||||
std::vector<Vec3d> vertices;
|
std::vector<Vec3d> vertices;
|
||||||
vertices.reserve(8);
|
vertices.reserve(8);
|
||||||
vertices.push_back(bb_min);
|
vertices.push_back(box.min);
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2));
|
vertices.emplace_back(box.max(0), box.min(1), box.min(2));
|
||||||
vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2));
|
vertices.emplace_back(box.max(0), box.max(1), box.min(2));
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2));
|
vertices.emplace_back(box.min(0), box.max(1), box.min(2));
|
||||||
vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2));
|
vertices.emplace_back(box.min(0), box.min(1), box.max(2));
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2));
|
vertices.emplace_back(box.max(0), box.min(1), box.max(2));
|
||||||
vertices.push_back(bb_max);
|
vertices.push_back(box.max);
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2));
|
vertices.emplace_back(box.min(0), box.max(1), box.max(2));
|
||||||
|
|
||||||
double max_x = 0.0;
|
double max_x = 0.0;
|
||||||
double max_y = 0.0;
|
double max_y = 0.0;
|
||||||
|
@ -430,6 +431,12 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||||
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::set_distance(double distance) const
|
||||||
|
{
|
||||||
|
m_distance = distance;
|
||||||
|
apply_view_matrix();
|
||||||
|
}
|
||||||
|
|
||||||
} // GUI
|
} // GUI
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ namespace GUI {
|
||||||
struct Camera
|
struct Camera
|
||||||
{
|
{
|
||||||
static const double DefaultDistance;
|
static const double DefaultDistance;
|
||||||
static double FrustrumMinZSize;
|
static double FrustrumMinZRange;
|
||||||
|
static double FrustrumMinNearZ;
|
||||||
static double FrustrumZMargin;
|
static double FrustrumZMargin;
|
||||||
static double FovMinDeg;
|
static double MaxFovDeg;
|
||||||
static double FovMaxDeg;
|
|
||||||
|
|
||||||
enum EType : unsigned char
|
enum EType : unsigned char
|
||||||
{
|
{
|
||||||
|
@ -101,6 +101,7 @@ private:
|
||||||
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
||||||
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
||||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
||||||
|
void set_distance(double distance) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // GUI
|
} // GUI
|
||||||
|
|
|
@ -354,7 +354,7 @@ bool FirmwareDialog::priv::check_model_id()
|
||||||
// Therefore, regretably, so far the check cannot be used and we just return true here.
|
// Therefore, regretably, so far the check cannot be used and we just return true here.
|
||||||
// TODO: Rewrite Serial using more platform-native code.
|
// TODO: Rewrite Serial using more platform-native code.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// if (hex_file.model_id.empty()) {
|
// if (hex_file.model_id.empty()) {
|
||||||
// // No data to check against, assume it's ok
|
// // No data to check against, assume it's ok
|
||||||
// return true;
|
// return true;
|
||||||
|
|
|
@ -1528,7 +1528,7 @@ void GLCanvas3D::render()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_camera.apply_view_matrix();
|
m_camera.apply_view_matrix();
|
||||||
m_camera.apply_projection(_max_bounding_box(true));
|
m_camera.apply_projection(_max_bounding_box(true, true));
|
||||||
|
|
||||||
GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f };
|
GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f };
|
||||||
glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam));
|
glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam));
|
||||||
|
@ -3272,7 +3272,7 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
||||||
void GLCanvas3D::set_camera_zoom(double zoom)
|
void GLCanvas3D::set_camera_zoom(double zoom)
|
||||||
{
|
{
|
||||||
const Size& cnv_size = get_canvas_size();
|
const Size& cnv_size = get_canvas_size();
|
||||||
m_camera.set_zoom(zoom, _max_bounding_box(false), cnv_size.get_width(), cnv_size.get_height());
|
m_camera.set_zoom(zoom, _max_bounding_box(false, false), cnv_size.get_width(), cnv_size.get_height());
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3698,9 +3698,20 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_bed_model) const
|
BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_bed_model) const
|
||||||
{
|
{
|
||||||
BoundingBoxf3 bb = volumes_bounding_box();
|
BoundingBoxf3 bb = volumes_bounding_box();
|
||||||
|
|
||||||
|
// The following is a workaround for gizmos not being taken in account when calculating the tight camera frustrum
|
||||||
|
// A better solution would ask the gizmo manager for the bounding box of the current active gizmo, if any
|
||||||
|
if (include_gizmos && m_gizmos.is_running())
|
||||||
|
{
|
||||||
|
BoundingBoxf3 sel_bb = m_selection.get_bounding_box();
|
||||||
|
Vec3d sel_bb_center = sel_bb.center();
|
||||||
|
Vec3d extend_by = sel_bb.max_size() * Vec3d::Ones();
|
||||||
|
bb.merge(BoundingBoxf3(sel_bb_center - extend_by, sel_bb_center + extend_by));
|
||||||
|
}
|
||||||
|
|
||||||
bb.merge(m_bed.get_bounding_box(include_bed_model));
|
bb.merge(m_bed.get_bounding_box(include_bed_model));
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,7 +652,7 @@ private:
|
||||||
bool _set_current();
|
bool _set_current();
|
||||||
void _resize(unsigned int w, unsigned int h);
|
void _resize(unsigned int w, unsigned int h);
|
||||||
|
|
||||||
BoundingBoxf3 _max_bounding_box(bool include_bed_model) const;
|
BoundingBoxf3 _max_bounding_box(bool include_gizmos, bool include_bed_model) const;
|
||||||
|
|
||||||
void _zoom_to_box(const BoundingBoxf3& box);
|
void _zoom_to_box(const BoundingBoxf3& box);
|
||||||
|
|
||||||
|
|
|
@ -1755,7 +1755,19 @@ void ObjectList::del_subobject_item(wxDataViewItem& item)
|
||||||
if (type & itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0)
|
if (type & itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0)
|
||||||
m_objects_model->DeleteWarningIcon(m_objects_model->GetParent(item));
|
m_objects_model->DeleteWarningIcon(m_objects_model->GetParent(item));
|
||||||
|
|
||||||
|
// If last two Instances of object is selected, show the message about impossible action
|
||||||
|
bool show_msg = false;
|
||||||
|
if (type & itInstance) {
|
||||||
|
wxDataViewItemArray instances;
|
||||||
|
m_objects_model->GetChildren(m_objects_model->GetParent(item), instances);
|
||||||
|
if (instances.Count() == 2 && IsSelected(instances[0]) && IsSelected(instances[1]))
|
||||||
|
show_msg = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_objects_model->Delete(item);
|
m_objects_model->Delete(item);
|
||||||
|
|
||||||
|
if (show_msg)
|
||||||
|
Slic3r::GUI::show_error(nullptr, _(L("From Object List You can't delete the last intance from object.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item)
|
void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item)
|
||||||
|
@ -1838,7 +1850,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
|
||||||
if (vol->is_model_part())
|
if (vol->is_model_part())
|
||||||
++solid_cnt;
|
++solid_cnt;
|
||||||
if (volume->is_model_part() && solid_cnt == 1) {
|
if (volume->is_model_part() && solid_cnt == 1) {
|
||||||
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from object.")));
|
Slic3r::GUI::show_error(nullptr, _(L("From Object List You can't delete the last solid part from object.")));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1857,7 +1869,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
|
||||||
}
|
}
|
||||||
else if (type == itInstance) {
|
else if (type == itInstance) {
|
||||||
if (object->instances.size() == 1) {
|
if (object->instances.size() == 1) {
|
||||||
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object.")));
|
Slic3r::GUI::show_error(nullptr, _(L("From Object List You can't delete the last intance from object.")));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2404,6 +2416,8 @@ void ObjectList::remove()
|
||||||
|
|
||||||
for (auto& item : sels)
|
for (auto& item : sels)
|
||||||
{
|
{
|
||||||
|
if (m_objects_model->InvalidItem(item)) // item can be deleted for this moment (like last 2 Instances or Volumes)
|
||||||
|
continue;
|
||||||
if (m_objects_model->GetParent(item) == wxDataViewItem(0))
|
if (m_objects_model->GetParent(item) == wxDataViewItem(0))
|
||||||
delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1);
|
delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1);
|
||||||
else {
|
else {
|
||||||
|
@ -3150,33 +3164,6 @@ void ObjectList::last_volume_is_deleted(const int obj_idx)
|
||||||
volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #lm_FIXME_delete_after_testing
|
|
||||||
void ObjectList::update_settings_items()
|
|
||||||
{
|
|
||||||
m_prevent_canvas_selection_update = true;
|
|
||||||
wxDataViewItemArray sel;
|
|
||||||
GetSelections(sel); // stash selection
|
|
||||||
|
|
||||||
wxDataViewItemArray items;
|
|
||||||
m_objects_model->GetChildren(wxDataViewItem(0), items);
|
|
||||||
|
|
||||||
for (auto& item : items) {
|
|
||||||
const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item);
|
|
||||||
select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item));
|
|
||||||
|
|
||||||
// If settings item was deleted from the list,
|
|
||||||
// it's need to be deleted from selection array, if it was there
|
|
||||||
if (settings_item != m_objects_model->GetSettingsItem(item) &&
|
|
||||||
sel.Index(settings_item) != wxNOT_FOUND) {
|
|
||||||
sel.Remove(settings_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore selection:
|
|
||||||
SetSelections(sel);
|
|
||||||
m_prevent_canvas_selection_update = false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
void ObjectList::update_and_show_object_settings_item()
|
void ObjectList::update_and_show_object_settings_item()
|
||||||
{
|
{
|
||||||
const wxDataViewItem item = GetSelection();
|
const wxDataViewItem item = GetSelection();
|
||||||
|
|
|
@ -1175,10 +1175,10 @@ void Sidebar::show_sliced_info_sizer(const bool show)
|
||||||
if (ps.estimated_silent_print_time != "N/A") {
|
if (ps.estimated_silent_print_time != "N/A") {
|
||||||
new_label += wxString::Format("\n - %s", _(L("stealth mode")));
|
new_label += wxString::Format("\n - %s", _(L("stealth mode")));
|
||||||
info_text += wxString::Format("\n%s", ps.estimated_silent_print_time);
|
info_text += wxString::Format("\n%s", ps.estimated_silent_print_time);
|
||||||
for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i)
|
for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
new_label += wxString::Format("\n - %s%d", _(L("Color ")), i + 1);
|
new_label += wxString::Format("\n - %s%d", _(L("Color ")), i + 1);
|
||||||
info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]);
|
info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
|
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
|
||||||
|
|
|
@ -1325,6 +1325,18 @@ int ObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ObjectDataViewModel::InvalidItem(const wxDataViewItem& item)
|
||||||
|
{
|
||||||
|
if (!item)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
|
||||||
|
if (!node || node->invalid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
wxString ObjectDataViewModel::GetName(const wxDataViewItem &item) const
|
wxString ObjectDataViewModel::GetName(const wxDataViewItem &item) const
|
||||||
{
|
{
|
||||||
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
|
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
|
||||||
|
|
|
@ -355,6 +355,7 @@ public:
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool valid();
|
bool valid();
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
bool invalid() const { return m_idx < -1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ObjectDataViewModel;
|
friend class ObjectDataViewModel;
|
||||||
|
@ -417,6 +418,7 @@ public:
|
||||||
void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
|
void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
|
||||||
int GetRowByItem(const wxDataViewItem& item) const;
|
int GetRowByItem(const wxDataViewItem& item) const;
|
||||||
bool IsEmpty() { return m_objects.empty(); }
|
bool IsEmpty() { return m_objects.empty(); }
|
||||||
|
bool InvalidItem(const wxDataViewItem& item);
|
||||||
|
|
||||||
// helper method for wxLog
|
// helper method for wxLog
|
||||||
|
|
||||||
|
|
|
@ -353,6 +353,8 @@ void Serial::set_baud_rate(unsigned baud_rate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
void Serial::set_DTR(bool on)
|
void Serial::set_DTR(bool on)
|
||||||
{
|
{
|
||||||
auto handle = native_handle();
|
auto handle = native_handle();
|
||||||
|
@ -495,6 +497,7 @@ std::string Serial::printer_format_line(const std::string &line, unsigned line_n
|
||||||
|
|
||||||
return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str();
|
return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
|
|
@ -46,6 +46,17 @@ public:
|
||||||
~Serial();
|
~Serial();
|
||||||
|
|
||||||
void set_baud_rate(unsigned baud_rate);
|
void set_baud_rate(unsigned baud_rate);
|
||||||
|
|
||||||
|
// The Serial implementation is currently in disarray and therefore commented out.
|
||||||
|
// The boost implementation seems to have several problems, such as lack of support
|
||||||
|
// for custom baud rates, few weird implementation bugs and a history of API breakages.
|
||||||
|
// It's questionable whether it solves more problems than causes. Probably not.
|
||||||
|
// TODO: Custom implementation not based on asio.
|
||||||
|
//
|
||||||
|
// As of now, this class is only kept for the purpose of rebooting AVR109,
|
||||||
|
// see FirmwareDialog::priv::avr109_reboot()
|
||||||
|
|
||||||
|
/*
|
||||||
void set_DTR(bool on);
|
void set_DTR(bool on);
|
||||||
|
|
||||||
// Resets the line number both internally as well as with the firmware using M110
|
// Resets the line number both internally as well as with the firmware using M110
|
||||||
|
@ -68,7 +79,7 @@ public:
|
||||||
|
|
||||||
// Same as above, but with internally-managed line number
|
// Same as above, but with internally-managed line number
|
||||||
size_t printer_write_line(const std::string &line);
|
size_t printer_write_line(const std::string &line);
|
||||||
|
|
||||||
// Toggles DTR to reset the printer
|
// Toggles DTR to reset the printer
|
||||||
void printer_reset();
|
void printer_reset();
|
||||||
|
|
||||||
|
@ -76,6 +87,7 @@ public:
|
||||||
static std::string printer_format_line(const std::string &line, unsigned line_num);
|
static std::string printer_format_line(const std::string &line, unsigned line_num);
|
||||||
private:
|
private:
|
||||||
unsigned m_line_num = 0;
|
unsigned m_line_num = 0;
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue