mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -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 "I18N.hpp" | ||||
| #include "GCode.hpp" | ||||
| #include "ExtrusionEntity.hpp" | ||||
| #include "EdgeGrid.hpp" | ||||
|  | @ -36,6 +37,11 @@ | |||
| 
 | ||||
| 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.
 | ||||
| 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()); | ||||
|     if (! m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) { | ||||
| 		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); | ||||
| 		} | ||||
|         m_brim_done = true; | ||||
|  | @ -448,6 +455,17 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec | |||
|                 -- 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); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1138,9 +1156,9 @@ void GCode::_do_export(Print &print, FILE *file) | |||
|     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_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) | ||||
|         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(); | ||||
|     if (! extruders.empty()) { | ||||
|  |  | |||
|  | @ -78,8 +78,13 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool | |||
|                 zs.emplace_back(layer->print_z); | ||||
|             for (auto layer : object->support_layers()) | ||||
|                 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); | ||||
|     } | ||||
|  | @ -324,6 +329,7 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ | |||
| 						m_layer_tools[j].has_wipe_tower = true; | ||||
| 					} else { | ||||
| 						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]; | ||||
|                         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.
 | ||||
|  |  | |||
|  | @ -694,22 +694,39 @@ namespace Slic3r { | |||
|         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; | ||||
|         float total_time = 0.0f; | ||||
|         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; | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
|         float total_time = 0.0f; | ||||
|         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; | ||||
|     } | ||||
|  |  | |||
|  | @ -346,14 +346,16 @@ namespace Slic3r { | |||
|         // Returns the estimated time, in minutes (integer)
 | ||||
|         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; | ||||
| 
 | ||||
|         // 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
 | ||||
|         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.
 | ||||
|         size_t memory_used() const; | ||||
|  |  | |||
|  | @ -1723,7 +1723,7 @@ void Print::_make_wipe_tower() | |||
|                     break; | ||||
|                 lt.has_support = true; | ||||
|                 // 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.
 | ||||
|                 it_layer = m_objects.front()->insert_support_layer(it_layer, -1, height, lt.print_z, lt.print_z - 0.5 * height); | ||||
|                 ++ it_layer; | ||||
|  |  | |||
|  | @ -422,6 +422,7 @@ void PrintConfigDef::init_fff_params() | |||
|     def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern"; | ||||
|     def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_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->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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> | ||||
|  | @ -432,7 +436,6 @@ std::string format_memsize_MB(size_t n) | |||
| } | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| 
 | ||||
| #ifndef PROCESS_MEMORY_COUNTERS_EX | ||||
|     // MingW32 doesn't have this struct in psapi.h
 | ||||
|     typedef struct _PROCESS_MEMORY_COUNTERS_EX { | ||||
|  | @ -464,12 +467,51 @@ std::string log_memory_info() | |||
|     } | ||||
|     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 | ||||
| std::string log_memory_info() | ||||
| { | ||||
|     return std::string(); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // Returns the size of physical memory (RAM) in bytes.
 | ||||
|  |  | |||
|  | @ -22,10 +22,10 @@ namespace Slic3r { | |||
| namespace GUI { | ||||
| 
 | ||||
| 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::FovMinDeg = 0.5; | ||||
| double Camera::FovMaxDeg = 75.0; | ||||
| double Camera::MaxFovDeg = 60.0; | ||||
| 
 | ||||
| Camera::Camera() | ||||
|     : phi(45.0f) | ||||
|  | @ -186,7 +186,8 @@ void Camera::apply_view_matrix() const | |||
| 
 | ||||
| void Camera::apply_projection(const BoundingBoxf3& box) const | ||||
| { | ||||
|     m_distance = DefaultDistance; | ||||
|     set_distance(DefaultDistance); | ||||
| 
 | ||||
|     double w = 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); | ||||
| 
 | ||||
|         w = (double)m_viewport[2]; | ||||
|         h = (double)m_viewport[3]; | ||||
|         w = 0.5 * (double)m_viewport[2]; | ||||
|         h = 0.5 * (double)m_viewport[3]; | ||||
| 
 | ||||
|         double two_zoom = 2.0 * m_zoom; | ||||
|         if (two_zoom != 0.0) | ||||
|         if (m_zoom != 0.0) | ||||
|         { | ||||
|             double inv_two_zoom = 1.0 / two_zoom; | ||||
|             w *= inv_two_zoom; | ||||
|             h *= inv_two_zoom; | ||||
|             double inv_zoom = 1.0 / m_zoom; | ||||
|             w *= inv_zoom; | ||||
|             h *= inv_zoom; | ||||
|         } | ||||
| 
 | ||||
|         switch (m_type) | ||||
|  | @ -226,21 +226,16 @@ void Camera::apply_projection(const BoundingBoxf3& box) const | |||
| 
 | ||||
|         if (m_type == Perspective) | ||||
|         { | ||||
|             double fov_rad = 2.0 * std::atan(h / m_frustrum_zs.first); | ||||
|             double fov_deg = Geometry::rad2deg(fov_rad); | ||||
|             double fov_deg = Geometry::rad2deg(2.0 * std::atan(h / m_frustrum_zs.first)); | ||||
| 
 | ||||
|             // 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)); | ||||
|                 m_distance += (new_near_z - m_frustrum_zs.first); | ||||
|                 apply_view_matrix(); | ||||
|             } | ||||
|             else if (fov_deg < FovMinDeg - 0.001) | ||||
|             { | ||||
|                 double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMinDeg)); | ||||
|                 m_distance += (new_near_z - m_frustrum_zs.first); | ||||
|                 apply_view_matrix(); | ||||
|                 double delta_z = h / ::tan(0.5 * Geometry::deg2rad(MaxFovDeg)) - m_frustrum_zs.first; | ||||
|                 if (delta_z > 0.001) | ||||
|                     set_distance(m_distance + delta_z); | ||||
|                 else | ||||
|                     break; | ||||
|             } | ||||
|             else | ||||
|                 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> ret = std::make_pair(DBL_MAX, -DBL_MAX); | ||||
|     std::pair<double, double> ret; | ||||
| 
 | ||||
|     Vec3d bb_min = box.min; | ||||
|     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) | ||||
|     while (true) | ||||
|     { | ||||
|         double z = -(m_view_matrix * v)(2); | ||||
|         ret.first = std::min(ret.first, z); | ||||
|         ret.second = std::max(ret.second, z); | ||||
|     } | ||||
|         ret = std::make_pair(DBL_MAX, -DBL_MAX); | ||||
| 
 | ||||
|     // apply margin
 | ||||
|     ret.first -= FrustrumZMargin; | ||||
|     ret.second += FrustrumZMargin; | ||||
|         // box vertices in world space
 | ||||
|         std::vector<Vec3d> vertices; | ||||
|         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
 | ||||
|     if (ret.second - ret.first < FrustrumMinZSize) | ||||
|     { | ||||
|         double mid_z = 0.5 * (ret.first + ret.second); | ||||
|         double half_size = 0.5 * FrustrumMinZSize; | ||||
|         ret.first = mid_z - half_size; | ||||
|         ret.second = mid_z + half_size; | ||||
|         // 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.first = std::min(ret.first, z); | ||||
|             ret.second = std::max(ret.second, z); | ||||
|         } | ||||
| 
 | ||||
|         // 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; | ||||
|  | @ -385,21 +388,19 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca | |||
|     Vec3d up = get_dir_up(); | ||||
|     Vec3d forward = get_dir_forward(); | ||||
| 
 | ||||
|     Vec3d bb_min = box.min; | ||||
|     Vec3d bb_max = box.max; | ||||
|     Vec3d bb_center = box.center(); | ||||
| 
 | ||||
|     // 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)); | ||||
|     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)); | ||||
| 
 | ||||
|     double max_x = 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)); | ||||
| } | ||||
| 
 | ||||
| void Camera::set_distance(double distance) const | ||||
| { | ||||
|     m_distance = distance; | ||||
|     apply_view_matrix(); | ||||
| } | ||||
| 
 | ||||
| } // GUI
 | ||||
| } // Slic3r
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,10 +10,10 @@ namespace GUI { | |||
| struct Camera | ||||
| { | ||||
|     static const double DefaultDistance; | ||||
|     static double FrustrumMinZSize; | ||||
|     static double FrustrumMinZRange; | ||||
|     static double FrustrumMinNearZ; | ||||
|     static double FrustrumZMargin; | ||||
|     static double FovMinDeg; | ||||
|     static double FovMaxDeg; | ||||
|     static double MaxFovDeg; | ||||
| 
 | ||||
|     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
 | ||||
|     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; | ||||
|     void set_distance(double distance) const; | ||||
| }; | ||||
| 
 | ||||
| } // GUI
 | ||||
|  |  | |||
|  | @ -1528,7 +1528,7 @@ void GLCanvas3D::render() | |||
|     } | ||||
| 
 | ||||
|     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 }; | ||||
|     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) | ||||
| { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
|  | @ -3698,9 +3698,20 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) | |||
|     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(); | ||||
| 
 | ||||
|     // 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)); | ||||
|     return bb; | ||||
| } | ||||
|  |  | |||
|  | @ -652,7 +652,7 @@ private: | |||
|     bool _set_current(); | ||||
|     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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1755,7 +1755,19 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) | |||
|     if (type & itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0) | ||||
|         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); | ||||
| 
 | ||||
|     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) | ||||
|  | @ -1838,7 +1850,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con | |||
|             if (vol->is_model_part()) | ||||
|                 ++solid_cnt; | ||||
|         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; | ||||
|         } | ||||
| 
 | ||||
|  | @ -1857,7 +1869,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con | |||
|     } | ||||
|     else if (type == itInstance) { | ||||
|         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; | ||||
|         } | ||||
| 
 | ||||
|  | @ -2404,6 +2416,8 @@ void ObjectList::remove() | |||
| 
 | ||||
|     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)) | ||||
|             delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1); | ||||
|         else { | ||||
|  | @ -3150,33 +3164,6 @@ void ObjectList::last_volume_is_deleted(const int obj_idx) | |||
|     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() | ||||
| { | ||||
|     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") { | ||||
|                     new_label += wxString::Format("\n    - %s", _(L("stealth mode"))); | ||||
|                     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); | ||||
|                         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); | ||||
|  |  | |||
|  | @ -1325,6 +1325,18 @@ int ObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const | |||
|     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 | ||||
| { | ||||
| 	ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); | ||||
|  |  | |||
|  | @ -355,6 +355,7 @@ public: | |||
| #ifndef NDEBUG | ||||
| 	bool 		valid(); | ||||
| #endif /* NDEBUG */ | ||||
|     bool        invalid() const { return m_idx < -1; } | ||||
| 
 | ||||
| private: | ||||
|     friend class ObjectDataViewModel; | ||||
|  | @ -417,6 +418,7 @@ public: | |||
|     void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); | ||||
|     int  GetRowByItem(const wxDataViewItem& item) const; | ||||
|     bool IsEmpty() { return m_objects.empty(); } | ||||
|     bool InvalidItem(const wxDataViewItem& item); | ||||
| 
 | ||||
| 	// helper method for wxLog
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -353,6 +353,8 @@ void Serial::set_baud_rate(unsigned baud_rate) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| void Serial::set_DTR(bool on) | ||||
| { | ||||
| 	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(); | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| } // namespace Utils
 | ||||
|  |  | |||
|  | @ -46,6 +46,17 @@ public: | |||
| 	~Serial(); | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	// Resets the line number both internally as well as with the firmware using M110
 | ||||
|  | @ -76,6 +87,7 @@ public: | |||
| 	static std::string printer_format_line(const std::string &line, unsigned line_num); | ||||
| private: | ||||
| 	unsigned m_line_num = 0; | ||||
| */ | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv