mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-23 03:34:27 +08:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
00ec9cc4ed
@ -514,8 +514,10 @@ elseif (SLIC3R_FHS)
|
|||||||
set(SLIC3R_FHS_RESOURCES "${CMAKE_INSTALL_FULL_DATAROOTDIR}/PrusaSlicer")
|
set(SLIC3R_FHS_RESOURCES "${CMAKE_INSTALL_FULL_DATAROOTDIR}/PrusaSlicer")
|
||||||
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${SLIC3R_FHS_RESOURCES}")
|
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${SLIC3R_FHS_RESOURCES}")
|
||||||
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${SLIC3R_FHS_RESOURCES}/applications)
|
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${SLIC3R_FHS_RESOURCES}/applications)
|
||||||
|
install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${SLIC3R_FHS_RESOURCES}/applications)
|
||||||
else ()
|
else ()
|
||||||
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
|
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
|
||||||
|
install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
|
||||||
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
|
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
11
deps/CGAL/CGAL.cmake
vendored
11
deps/CGAL/CGAL.cmake
vendored
@ -15,6 +15,17 @@ include(GNUInstallDirs)
|
|||||||
# If this file is not present, it will not consider the stored absolute path
|
# If this file is not present, it will not consider the stored absolute path
|
||||||
ExternalProject_Add_Step(dep_CGAL dep_CGAL_relocation_fix
|
ExternalProject_Add_Step(dep_CGAL dep_CGAL_relocation_fix
|
||||||
DEPENDEES install
|
DEPENDEES install
|
||||||
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E remove CGALConfig-installation-dirs.cmake
|
COMMAND ${CMAKE_COMMAND} -E remove CGALConfig-installation-dirs.cmake
|
||||||
WORKING_DIRECTORY "${DESTDIR}/usr/local/${CMAKE_INSTALL_LIBDIR}/cmake/CGAL"
|
WORKING_DIRECTORY "${DESTDIR}/usr/local/${CMAKE_INSTALL_LIBDIR}/cmake/CGAL"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Again, for whatever reason, CGAL thinks that its version is not relevant if
|
||||||
|
# configured as a header only library. Fixing it by placing a cmake version file
|
||||||
|
# besides the installed config file.
|
||||||
|
ExternalProject_Add_Step(dep_CGAL dep_CGAL_version_fix
|
||||||
|
DEPENDEES install
|
||||||
|
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy cgal/CGALConfigVersion.cmake "${DESTDIR}/usr/local/${CMAKE_INSTALL_LIBDIR}/cmake/CGAL/CGALConfigVersion.cmake"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
|
||||||
|
)
|
||||||
|
37
deps/CGAL/cgal/CGALConfigVersion.cmake
vendored
Normal file
37
deps/CGAL/cgal/CGALConfigVersion.cmake
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# This is a basic version file for the Config-mode of find_package().
|
||||||
|
# It is used by write_basic_package_version_file() as input file for configure_file()
|
||||||
|
# to create a version-file which can be installed along a config.cmake file.
|
||||||
|
#
|
||||||
|
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
|
||||||
|
# the requested version string are exactly the same and it sets
|
||||||
|
# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
|
||||||
|
# The variable CVF_VERSION must be set before calling configure_file().
|
||||||
|
|
||||||
|
set(PACKAGE_VERSION "5.0.0")
|
||||||
|
|
||||||
|
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# if the installed project requested no architecture check, don't perform the check
|
||||||
|
if("FALSE")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
|
||||||
|
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
|
||||||
|
math(EXPR installedBits "8 * 8")
|
||||||
|
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
|
||||||
|
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
||||||
|
endif()
|
12
resources/data/flatpak/com.prusa3d.PrusaSlicer.desktop
Executable file
12
resources/data/flatpak/com.prusa3d.PrusaSlicer.desktop
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=PrusaSlicer
|
||||||
|
GenericName=3D Printing Software
|
||||||
|
Icon=com.prusa3d.PrusaSlicer
|
||||||
|
Exec=prusa-slicer %F
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
MimeType=model/stl;model/x-wavefront-obj;model/3mf;model/x-geomview-off;application/x-amf;
|
||||||
|
Categories=Graphics;3DGraphics;Engineering;
|
||||||
|
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
|
||||||
|
StartupNotify=false
|
||||||
|
StartupWMClass=prusa-slicer
|
62
resources/data/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml
Executable file
62
resources/data/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop">
|
||||||
|
<id>com.prusa3d.PrusaSlicer</id>
|
||||||
|
<launchable type="desktop-id">com.prusa3d.PrusaSlicer.desktop</launchable>
|
||||||
|
<provides>
|
||||||
|
<id>prusa-slicer.desktop</id>
|
||||||
|
</provides>
|
||||||
|
<name>PrusaSlicer</name>
|
||||||
|
<summary>Powerful 3D printing slicer optimized for Prusa printers</summary>
|
||||||
|
<metadata_license>0BSD</metadata_license>
|
||||||
|
<project_license>AGPL-3.0-only</project_license>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
PrusaSlicer takes 3D models (STL, OBJ, AMF) and converts them into G-code
|
||||||
|
instructions for FFF printers or PNG layers for mSLA 3D printers. It's
|
||||||
|
compatible with any modern printer based on the RepRap toolchain, including all
|
||||||
|
those based on the Marlin, Prusa, Sprinter and Repetier firmware. It also works
|
||||||
|
with Mach3, LinuxCNC and Machinekit controllers.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
PrusaSlicer is based on Slic3r by Alessandro Ranelucci and the RepRap community.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
What are some of PrusaSlicer's main features?
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>multi-platform (Linux/Mac/Win) and packaged as standalone-app with no dependencies required</li>
|
||||||
|
<li>complete command-line interface to use it with no GUI</li>
|
||||||
|
<li>multi-material (multiple extruders) object printing</li>
|
||||||
|
<li>multiple G-code flavors supported (RepRap, Makerbot, Mach3, Machinekit etc.)</li>
|
||||||
|
<li>ability to plate multiple objects having distinct print settings</li>
|
||||||
|
<li>multithread processing</li>
|
||||||
|
<li>STL auto-repair (tolerance for broken models)</li>
|
||||||
|
<li>wide automated unit testing</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">https://www.prusa3d.com/prusaslicer/</url>
|
||||||
|
<url type="help">https://help.prusa3d.com</url>
|
||||||
|
<url type="bugtracker">https://github.com/prusa3d/PrusaSlicer/issues</url>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image>https://user-images.githubusercontent.com/590307/78981854-24d07580-7b21-11ea-9441-77923534a659.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image>https://user-images.githubusercontent.com/590307/78981860-2863fc80-7b21-11ea-8c2d-8ff79ced2578.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image>https://user-images.githubusercontent.com/590307/78981862-28fc9300-7b21-11ea-9b0d-d03e16b709d3.png</image>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<content_rating type="oars-1.1" />
|
||||||
|
<releases>
|
||||||
|
<release version="2.2.0" date="2020-03-21">
|
||||||
|
<description>
|
||||||
|
<p>This is final release of PrusaSlicer 2.2.0 introducing SLA hollowing and hole drilling, support for 3rd party printer vendors, 3Dconnexion support,
|
||||||
|
automatic variable layer height, macOS dark mode support, greatly improved ColorPrint feature and much, much more.
|
||||||
|
Several bugs found in the previous release candidate are fixed in this final release. See the respective change logs of the previous releases for all the
|
||||||
|
new features, improvements and bugfixes in the 2.2.0 series.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
</component>
|
@ -205,6 +205,20 @@ std::string AppConfig::load()
|
|||||||
m_legacy_datadir = ini_ver < Semver(1, 40, 0);
|
m_legacy_datadir = ini_ver < Semver(1, 40, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Legacy conversion
|
||||||
|
if (m_mode == EAppMode::Editor) {
|
||||||
|
// Convert [extras] "physical_printer" to [presets] "physical_printer",
|
||||||
|
// remove the [extras] section if it becomes empty.
|
||||||
|
if (auto it_section = m_storage.find("extras"); it_section != m_storage.end()) {
|
||||||
|
if (auto it_physical_printer = it_section->second.find("physical_printer"); it_physical_printer != it_section->second.end()) {
|
||||||
|
m_storage["presets"]["physical_printer"] = it_physical_printer->second;
|
||||||
|
it_section->second.erase(it_physical_printer);
|
||||||
|
}
|
||||||
|
if (it_section->second.empty())
|
||||||
|
m_storage.erase(it_section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Override missing or keys with their defaults.
|
// Override missing or keys with their defaults.
|
||||||
this->set_defaults();
|
this->set_defaults();
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
@ -428,6 +442,7 @@ void AppConfig::reset_selections()
|
|||||||
it->second.erase("sla_print");
|
it->second.erase("sla_print");
|
||||||
it->second.erase("sla_material");
|
it->second.erase("sla_material");
|
||||||
it->second.erase("printer");
|
it->second.erase("printer");
|
||||||
|
it->second.erase("physical_printer");
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,20 +142,20 @@ public:
|
|||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
// Returns true if the user's data directory comes from before Slic3r 1.40.0 (no updating)
|
// Returns true if the user's data directory comes from before Slic3r 1.40.0 (no updating)
|
||||||
bool legacy_datadir() const { return m_legacy_datadir; }
|
bool legacy_datadir() const { return m_legacy_datadir; }
|
||||||
void set_legacy_datadir(bool value) { m_legacy_datadir = value; }
|
void set_legacy_datadir(bool value) { m_legacy_datadir = value; }
|
||||||
|
|
||||||
// Get the Slic3r version check url.
|
// Get the Slic3r version check url.
|
||||||
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
|
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
|
||||||
std::string version_check_url() const;
|
std::string version_check_url() const;
|
||||||
|
|
||||||
// Returns the original Slic3r version found in the ini file before it was overwritten
|
// Returns the original Slic3r version found in the ini file before it was overwritten
|
||||||
// by the current version
|
// by the current version
|
||||||
Semver orig_version() const { return m_orig_version; }
|
Semver orig_version() const { return m_orig_version; }
|
||||||
|
|
||||||
// Does the config file exist?
|
// Does the config file exist?
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
bool exists();
|
bool exists();
|
||||||
#else
|
#else
|
||||||
static bool exists();
|
static bool exists();
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
|
@ -154,7 +154,9 @@ struct SegmentIntersection
|
|||||||
// Vertical link, up.
|
// Vertical link, up.
|
||||||
Up,
|
Up,
|
||||||
// Vertical link, down.
|
// Vertical link, down.
|
||||||
Down
|
Down,
|
||||||
|
// Phony intersection point has no link.
|
||||||
|
Phony,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class LinkQuality : uint8_t {
|
enum class LinkQuality : uint8_t {
|
||||||
@ -353,6 +355,25 @@ struct SegmentedIntersectionLine
|
|||||||
std::vector<SegmentIntersection> intersections;
|
std::vector<SegmentIntersection> intersections;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static SegmentIntersection phony_outer_intersection(SegmentIntersection::SegmentIntersectionType type, coord_t pos)
|
||||||
|
{
|
||||||
|
assert(type == SegmentIntersection::OUTER_LOW || type == SegmentIntersection::OUTER_HIGH);
|
||||||
|
SegmentIntersection out;
|
||||||
|
// Invalid contour & segment.
|
||||||
|
out.iContour = std::numeric_limits<size_t>::max();
|
||||||
|
out.iSegment = std::numeric_limits<size_t>::max();
|
||||||
|
out.pos_p = pos;
|
||||||
|
out.type = type;
|
||||||
|
// Invalid prev / next.
|
||||||
|
out.prev_on_contour = -1;
|
||||||
|
out.next_on_contour = -1;
|
||||||
|
out.prev_on_contour_type = SegmentIntersection::LinkType::Phony;
|
||||||
|
out.next_on_contour_type = SegmentIntersection::LinkType::Phony;
|
||||||
|
out.prev_on_contour_quality = SegmentIntersection::LinkQuality::Invalid;
|
||||||
|
out.next_on_contour_quality = SegmentIntersection::LinkQuality::Invalid;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// A container maintaining an expolygon with its inner offsetted polygon.
|
// A container maintaining an expolygon with its inner offsetted polygon.
|
||||||
// The purpose of the inner offsetted polygon is to provide segments to connect the infill lines.
|
// The purpose of the inner offsetted polygon is to provide segments to connect the infill lines.
|
||||||
struct ExPolygonWithOffset
|
struct ExPolygonWithOffset
|
||||||
@ -889,6 +910,60 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
|
|||||||
return segs;
|
return segs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
bool validate_segment_intersection_connectivity(const std::vector<SegmentedIntersectionLine> &segs)
|
||||||
|
{
|
||||||
|
// Validate the connectivity.
|
||||||
|
for (size_t i_vline = 0; i_vline + 1 < segs.size(); ++ i_vline) {
|
||||||
|
const SegmentedIntersectionLine &il_left = segs[i_vline];
|
||||||
|
const SegmentedIntersectionLine &il_right = segs[i_vline + 1];
|
||||||
|
for (const SegmentIntersection &it : il_left.intersections) {
|
||||||
|
if (it.has_right_horizontal()) {
|
||||||
|
const SegmentIntersection &it_right = il_right.intersections[it.right_horizontal()];
|
||||||
|
// For a right link there is a symmetric left link.
|
||||||
|
assert(it.iContour == it_right.iContour);
|
||||||
|
assert(it.type == it_right.type);
|
||||||
|
assert(it_right.has_left_horizontal());
|
||||||
|
assert(it_right.left_horizontal() == int(&it - il_left.intersections.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const SegmentIntersection &it : il_right.intersections) {
|
||||||
|
if (it.has_left_horizontal()) {
|
||||||
|
const SegmentIntersection &it_left = il_left.intersections[it.left_horizontal()];
|
||||||
|
// For a right link there is a symmetric left link.
|
||||||
|
assert(it.iContour == it_left.iContour);
|
||||||
|
assert(it.type == it_left.type);
|
||||||
|
assert(it_left.has_right_horizontal());
|
||||||
|
assert(it_left.right_horizontal() == int(&it - il_right.intersections.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i_vline = 0; i_vline < segs.size(); ++ i_vline) {
|
||||||
|
const SegmentedIntersectionLine &il = segs[i_vline];
|
||||||
|
for (const SegmentIntersection &it : il.intersections) {
|
||||||
|
auto i_it = int(&it - il.intersections.data());
|
||||||
|
if (it.has_left_vertical_up()) {
|
||||||
|
assert(il.intersections[it.left_vertical_up()].left_vertical_down() == i_it);
|
||||||
|
assert(il.intersections[it.left_vertical_up()].prev_on_contour_quality == it.prev_on_contour_quality);
|
||||||
|
}
|
||||||
|
if (it.has_left_vertical_down()) {
|
||||||
|
assert(il.intersections[it.left_vertical_down()].left_vertical_up() == i_it);
|
||||||
|
assert(il.intersections[it.left_vertical_down()].prev_on_contour_quality == it.prev_on_contour_quality);
|
||||||
|
}
|
||||||
|
if (it.has_right_vertical_up()) {
|
||||||
|
assert(il.intersections[it.right_vertical_up()].right_vertical_down() == i_it);
|
||||||
|
assert(il.intersections[it.right_vertical_up()].next_on_contour_quality == it.next_on_contour_quality);
|
||||||
|
}
|
||||||
|
if (it.has_right_vertical_down()) {
|
||||||
|
assert(il.intersections[it.right_vertical_down()].right_vertical_up() == i_it);
|
||||||
|
assert(il.intersections[it.right_vertical_down()].next_on_contour_quality == it.next_on_contour_quality);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
// Connect each contour / vertical line intersection point with another two contour / vertical line intersection points.
|
// Connect each contour / vertical line intersection point with another two contour / vertical line intersection points.
|
||||||
// (fill in SegmentIntersection::{prev_on_contour, prev_on_contour_vertical, next_on_contour, next_on_contour_vertical}.
|
// (fill in SegmentIntersection::{prev_on_contour, prev_on_contour_vertical, next_on_contour, next_on_contour_vertical}.
|
||||||
// These contour points are either on the same vertical line, or on the vertical line left / right to the current one.
|
// These contour points are either on the same vertical line, or on the vertical line left / right to the current one.
|
||||||
@ -1055,55 +1130,104 @@ static void connect_segment_intersections_by_contours(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
assert(validate_segment_intersection_connectivity(segs));
|
||||||
// Validate the connectivity.
|
}
|
||||||
for (size_t i_vline = 0; i_vline + 1 < segs.size(); ++ i_vline) {
|
|
||||||
const SegmentedIntersectionLine &il_left = segs[i_vline];
|
static void pinch_contours_insert_phony_outer_intersections(std::vector<SegmentedIntersectionLine> &segs)
|
||||||
const SegmentedIntersectionLine &il_right = segs[i_vline + 1];
|
{
|
||||||
for (const SegmentIntersection &it : il_left.intersections) {
|
// Keep the vector outside the loops, so they will not be reallocated.
|
||||||
if (it.has_right_horizontal()) {
|
// Where to insert new outer points.
|
||||||
const SegmentIntersection &it_right = il_right.intersections[it.right_horizontal()];
|
std::vector<size_t> insert_after;
|
||||||
// For a right link there is a symmetric left link.
|
// Mapping of indices of current intersection line after inserting new outer points.
|
||||||
assert(it.iContour == it_right.iContour);
|
std::vector<int32_t> map;
|
||||||
assert(it.type == it_right.type);
|
std::vector<SegmentIntersection> temp_intersections;
|
||||||
assert(it_right.has_left_horizontal());
|
|
||||||
assert(it_right.left_horizontal() == int(&it - il_left.intersections.data()));
|
for (size_t i_vline = 1; i_vline < segs.size(); ++ i_vline) {
|
||||||
|
SegmentedIntersectionLine &il = segs[i_vline];
|
||||||
|
assert(il.intersections.empty() || il.intersections.size() >= 2);
|
||||||
|
if (! il.intersections.empty()) {
|
||||||
|
assert(il.intersections.front().type == SegmentIntersection::OUTER_LOW);
|
||||||
|
assert(il.intersections.back().type == SegmentIntersection::OUTER_HIGH);
|
||||||
|
auto end = il.intersections.end() - 1;
|
||||||
|
insert_after.clear();
|
||||||
|
for (auto it = il.intersections.begin() + 1; it != end;) {
|
||||||
|
if (it->type == SegmentIntersection::OUTER_HIGH) {
|
||||||
|
++ it;
|
||||||
|
assert(it->type == SegmentIntersection::OUTER_LOW);
|
||||||
|
++ it;
|
||||||
|
} else {
|
||||||
|
auto lo = it;
|
||||||
|
assert(lo->type == SegmentIntersection::INNER_LOW);
|
||||||
|
auto hi = ++ it;
|
||||||
|
assert(hi->type == SegmentIntersection::INNER_HIGH);
|
||||||
|
auto lo2 = ++ it;
|
||||||
|
if (lo2->type == SegmentIntersection::INNER_LOW) {
|
||||||
|
// INNER_HIGH followed by INNER_LOW. The outer contour may have squeezed the inner contour into two separate loops.
|
||||||
|
// In that case one shall insert a phony OUTER_HIGH / OUTER_LOW pair.
|
||||||
|
int up = hi->vertical_up();
|
||||||
|
int dn = lo2->vertical_down();
|
||||||
|
#ifndef _NDEBUG
|
||||||
|
assert(up == -1 || up > 0);
|
||||||
|
assert(dn == -1 || dn >= 0);
|
||||||
|
assert((up == -1 && dn == -1) || (dn + 1 == up));
|
||||||
|
#endif // _NDEBUG
|
||||||
|
bool pinched = dn + 1 != up;
|
||||||
|
if (pinched) {
|
||||||
|
// hi is not connected with its inner contour to lo2.
|
||||||
|
// Insert a phony OUTER_HIGH / OUTER_LOW pair.
|
||||||
|
#if 0
|
||||||
|
static int pinch_idx = 0;
|
||||||
|
printf("Pinched %d\n", pinch_idx++);
|
||||||
|
#endif
|
||||||
|
insert_after.emplace_back(hi - il.intersections.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (const SegmentIntersection &it : il_right.intersections) {
|
if (! insert_after.empty()) {
|
||||||
if (it.has_left_horizontal()) {
|
// Insert phony OUTER_HIGH / OUTER_LOW pairs, adjust indices pointing to intersection points on this contour.
|
||||||
const SegmentIntersection &it_left = il_left.intersections[it.left_horizontal()];
|
map.clear();
|
||||||
// For a right link there is a symmetric left link.
|
{
|
||||||
assert(it.iContour == it_left.iContour);
|
size_t i = 0;
|
||||||
assert(it.type == it_left.type);
|
temp_intersections.clear();
|
||||||
assert(it_left.has_right_horizontal());
|
for (size_t idx_inset_after : insert_after) {
|
||||||
assert(it_left.right_horizontal() == int(&it - il_right.intersections.data()));
|
for (; i <= idx_inset_after; ++ i) {
|
||||||
|
map.emplace_back(temp_intersections.size());
|
||||||
|
temp_intersections.emplace_back(il.intersections[i]);
|
||||||
|
}
|
||||||
|
coord_t pos = (temp_intersections.back().pos() + il.intersections[i].pos()) / 2;
|
||||||
|
temp_intersections.emplace_back(phony_outer_intersection(SegmentIntersection::OUTER_HIGH, pos));
|
||||||
|
temp_intersections.emplace_back(phony_outer_intersection(SegmentIntersection::OUTER_LOW, pos));
|
||||||
|
}
|
||||||
|
for (; i < il.intersections.size(); ++ i) {
|
||||||
|
map.emplace_back(temp_intersections.size());
|
||||||
|
temp_intersections.emplace_back(il.intersections[i]);
|
||||||
|
}
|
||||||
|
temp_intersections.swap(il.intersections);
|
||||||
|
}
|
||||||
|
// Reindex references on current intersection line.
|
||||||
|
for (SegmentIntersection &ip : il.intersections) {
|
||||||
|
if (ip.has_left_vertical())
|
||||||
|
ip.prev_on_contour = map[ip.prev_on_contour];
|
||||||
|
if (ip.has_right_vertical())
|
||||||
|
ip.next_on_contour = map[ip.next_on_contour];
|
||||||
|
}
|
||||||
|
// Reindex references on previous intersection line.
|
||||||
|
for (SegmentIntersection &ip : segs[i_vline - 1].intersections)
|
||||||
|
if (ip.has_right_horizontal())
|
||||||
|
ip.next_on_contour = map[ip.next_on_contour];
|
||||||
|
if (i_vline < segs.size()) {
|
||||||
|
// Reindex references on next intersection line.
|
||||||
|
for (SegmentIntersection &ip : segs[i_vline + 1].intersections)
|
||||||
|
if (ip.has_left_horizontal())
|
||||||
|
ip.prev_on_contour = map[ip.prev_on_contour];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i_vline = 0; i_vline < segs.size(); ++ i_vline) {
|
|
||||||
const SegmentedIntersectionLine &il = segs[i_vline];
|
assert(validate_segment_intersection_connectivity(segs));
|
||||||
for (const SegmentIntersection &it : il.intersections) {
|
|
||||||
auto i_it = int(&it - il.intersections.data());
|
|
||||||
if (it.has_left_vertical_up()) {
|
|
||||||
assert(il.intersections[it.left_vertical_up()].left_vertical_down() == i_it);
|
|
||||||
assert(il.intersections[it.left_vertical_up()].prev_on_contour_quality == it.prev_on_contour_quality);
|
|
||||||
}
|
|
||||||
if (it.has_left_vertical_down()) {
|
|
||||||
assert(il.intersections[it.left_vertical_down()].left_vertical_up() == i_it);
|
|
||||||
assert(il.intersections[it.left_vertical_down()].prev_on_contour_quality == it.prev_on_contour_quality);
|
|
||||||
}
|
|
||||||
if (it.has_right_vertical_up()) {
|
|
||||||
assert(il.intersections[it.right_vertical_up()].right_vertical_down() == i_it);
|
|
||||||
assert(il.intersections[it.right_vertical_up()].next_on_contour_quality == it.next_on_contour_quality);
|
|
||||||
}
|
|
||||||
if (it.has_right_vertical_down()) {
|
|
||||||
assert(il.intersections[it.right_vertical_down()].right_vertical_up() == i_it);
|
|
||||||
assert(il.intersections[it.right_vertical_down()].next_on_contour_quality == it.next_on_contour_quality);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* NDEBUG */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the last INNER_HIGH intersection starting with INNER_LOW, that is followed by OUTER_HIGH intersection.
|
// Find the last INNER_HIGH intersection starting with INNER_LOW, that is followed by OUTER_HIGH intersection.
|
||||||
@ -1431,7 +1555,7 @@ struct AntPath
|
|||||||
|
|
||||||
struct MonotonicRegionLink
|
struct MonotonicRegionLink
|
||||||
{
|
{
|
||||||
MonotonicRegion *region;
|
MonotonicRegion *region;
|
||||||
bool flipped;
|
bool flipped;
|
||||||
// Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region
|
// Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region
|
||||||
// is applied as defined.
|
// is applied as defined.
|
||||||
@ -2058,7 +2182,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
|
|||||||
// After how many rounds without an improvement to exit?
|
// After how many rounds without an improvement to exit?
|
||||||
constexpr int num_rounds_no_change_exit = 8;
|
constexpr int num_rounds_no_change_exit = 8;
|
||||||
// With how many ants each of the run will be performed?
|
// With how many ants each of the run will be performed?
|
||||||
const int num_ants = std::min<int>(regions.size(), 10);
|
const int num_ants = std::min(int(regions.size()), 10);
|
||||||
// Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found.
|
// Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found.
|
||||||
float pheromone_initial_deposit = 0.5f;
|
float pheromone_initial_deposit = 0.5f;
|
||||||
// Evaporation rate of pheromones.
|
// Evaporation rate of pheromones.
|
||||||
@ -2136,7 +2260,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set an initial pheromone value to 10% of the greedy path's value.
|
// Set an initial pheromone value to 10% of the greedy path's value.
|
||||||
pheromone_initial_deposit = 0.1 / total_length;
|
pheromone_initial_deposit = 0.1f / total_length;
|
||||||
path_matrix.update_inital_pheromone(pheromone_initial_deposit);
|
path_matrix.update_inital_pheromone(pheromone_initial_deposit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2334,9 +2458,21 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
|
|||||||
// Handle nearly zero length edges.
|
// Handle nearly zero length edges.
|
||||||
if (polyline->points.size() <= 1 ||
|
if (polyline->points.size() <= 1 ||
|
||||||
(polyline->points.size() == 2 &&
|
(polyline->points.size() == 2 &&
|
||||||
std::abs(polyline->points.front()(0) - polyline->points.back()(0)) < SCALED_EPSILON &&
|
std::abs(polyline->points.front().x() - polyline->points.back().x()) < SCALED_EPSILON &&
|
||||||
std::abs(polyline->points.front()(1) - polyline->points.back()(1)) < SCALED_EPSILON))
|
std::abs(polyline->points.front().y() - polyline->points.back().y()) < SCALED_EPSILON))
|
||||||
polylines_out.pop_back();
|
polylines_out.pop_back();
|
||||||
|
else if (polylines_out.size() >= 2) {
|
||||||
|
assert(polyline->points.size() >= 2);
|
||||||
|
// Merge the two last polylines. An extrusion may have been split by an introduction of phony outer points on intersection lines
|
||||||
|
// to cope with pinching of inner offset contours.
|
||||||
|
Polyline &pl_prev = polylines_out[polylines_out.size() - 2];
|
||||||
|
if (std::abs(polyline->points.front().x() - pl_prev.points.back().x()) < SCALED_EPSILON &&
|
||||||
|
std::abs(polyline->points.front().y() - pl_prev.points.back().y()) < SCALED_EPSILON) {
|
||||||
|
pl_prev.points.back() = (pl_prev.points.back() + polyline->points.front()) / 2;
|
||||||
|
pl_prev.points.insert(pl_prev.points.end(), polyline->points.begin() + 1, polyline->points.end());
|
||||||
|
polylines_out.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
polyline = nullptr;
|
polyline = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2489,7 +2625,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||||||
surface->expolygon,
|
surface->expolygon,
|
||||||
- rotate_vector.first,
|
- rotate_vector.first,
|
||||||
float(scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)),
|
float(scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)),
|
||||||
float(scale_(this->overlap - 0.5 * this->spacing)));
|
float(scale_(this->overlap - 0.5f * this->spacing)));
|
||||||
if (poly_with_offset.n_contours_inner == 0) {
|
if (poly_with_offset.n_contours_inner == 0) {
|
||||||
// Not a single infill line fits.
|
// Not a single infill line fits.
|
||||||
//FIXME maybe one shall trigger the gap fill here?
|
//FIXME maybe one shall trigger the gap fill here?
|
||||||
@ -2561,6 +2697,10 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
|
|||||||
//FIXME this is a hack to get the monotonic infill rolling. We likely want a smarter switch, likely based on user decison.
|
//FIXME this is a hack to get the monotonic infill rolling. We likely want a smarter switch, likely based on user decison.
|
||||||
bool monotonic_infill = params.monotonic; // || params.density > 0.99;
|
bool monotonic_infill = params.monotonic; // || params.density > 0.99;
|
||||||
if (monotonic_infill) {
|
if (monotonic_infill) {
|
||||||
|
// Sometimes the outer contour pinches the inner contour from both sides along a single vertical line.
|
||||||
|
// This situation is not handled correctly by generate_montonous_regions().
|
||||||
|
// Insert phony OUTER_HIGH / OUTER_LOW pairs at the position where the contour is pinched.
|
||||||
|
pinch_contours_insert_phony_outer_intersections(segs);
|
||||||
std::vector<MonotonicRegion> regions = generate_montonous_regions(segs);
|
std::vector<MonotonicRegion> regions = generate_montonous_regions(segs);
|
||||||
connect_monotonic_regions(regions, poly_with_offset, segs);
|
connect_monotonic_regions(regions, poly_with_offset, segs);
|
||||||
if (! regions.empty()) {
|
if (! regions.empty()) {
|
||||||
|
@ -458,7 +458,7 @@ void PresetBundle::load_selections(AppConfig &config, const std::string &preferr
|
|||||||
this->update_multi_material_filament_presets();
|
this->update_multi_material_filament_presets();
|
||||||
|
|
||||||
// Parse the initial physical printer name.
|
// Parse the initial physical printer name.
|
||||||
std::string initial_physical_printer_name = remove_ini_suffix(config.get("extras", "physical_printer"));
|
std::string initial_physical_printer_name = remove_ini_suffix(config.get("presets", "physical_printer"));
|
||||||
|
|
||||||
// Activate physical printer from the config
|
// Activate physical printer from the config
|
||||||
if (!initial_physical_printer_name.empty())
|
if (!initial_physical_printer_name.empty())
|
||||||
@ -482,8 +482,7 @@ void PresetBundle::export_selections(AppConfig &config)
|
|||||||
config.set("presets", "sla_print", sla_prints.get_selected_preset_name());
|
config.set("presets", "sla_print", sla_prints.get_selected_preset_name());
|
||||||
config.set("presets", "sla_material", sla_materials.get_selected_preset_name());
|
config.set("presets", "sla_material", sla_materials.get_selected_preset_name());
|
||||||
config.set("presets", "printer", printers.get_selected_preset_name());
|
config.set("presets", "printer", printers.get_selected_preset_name());
|
||||||
|
config.set("presets", "physical_printer", physical_printers.get_selected_full_printer_name());
|
||||||
config.set("extras", "physical_printer", physical_printers.get_selected_full_printer_name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicPrintConfig PresetBundle::full_config() const
|
DynamicPrintConfig PresetBundle::full_config() const
|
||||||
|
9
src/platform/unix/PrusaGcodeviewer.desktop
Normal file
9
src/platform/unix/PrusaGcodeviewer.desktop
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Prusa GCode viewer
|
||||||
|
Exec=prusa-slicer --gcodeviewer %F
|
||||||
|
Icon=PrusaSlicer # TODO: change when the new icon is ready
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
MimeType=text/x.gcode;
|
||||||
|
Categories=Graphics;3DGraphics;
|
||||||
|
Keywords=3D;Printing;Slicer;
|
@ -1,9 +1,12 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=PrusaSlicer
|
Name=PrusaSlicer
|
||||||
Exec=prusa-slicer %F
|
GenericName=3D Printing Software
|
||||||
Icon=PrusaSlicer
|
Icon=PrusaSlicer
|
||||||
|
Exec=prusa-slicer %F
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;
|
MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;
|
||||||
Categories=Graphics;3DGraphics;
|
Categories=Graphics;3DGraphics;Engineering;
|
||||||
Keywords=3D;Printing;Slicer;
|
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
|
||||||
|
StartupNotify=false
|
||||||
|
StartupWMClass=prusa-slicer
|
@ -31,8 +31,11 @@ void Snapshot::clear()
|
|||||||
this->comment.clear();
|
this->comment.clear();
|
||||||
this->reason = SNAPSHOT_UNKNOWN;
|
this->reason = SNAPSHOT_UNKNOWN;
|
||||||
this->print.clear();
|
this->print.clear();
|
||||||
|
this->sla_print.clear();
|
||||||
this->filaments.clear();
|
this->filaments.clear();
|
||||||
|
this->sla_material.clear();
|
||||||
this->printer.clear();
|
this->printer.clear();
|
||||||
|
this->physical_printer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Snapshot::load_ini(const std::string &path)
|
void Snapshot::load_ini(const std::string &path)
|
||||||
@ -94,6 +97,8 @@ void Snapshot::load_ini(const std::string &path)
|
|||||||
for (auto &kvp : section.second) {
|
for (auto &kvp : section.second) {
|
||||||
if (kvp.first == "print") {
|
if (kvp.first == "print") {
|
||||||
this->print = kvp.second.data();
|
this->print = kvp.second.data();
|
||||||
|
} else if (kvp.first == "sla_print") {
|
||||||
|
this->sla_print = kvp.second.data();
|
||||||
} else if (boost::starts_with(kvp.first, "filament")) {
|
} else if (boost::starts_with(kvp.first, "filament")) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
if (kvp.first == "filament" || sscanf(kvp.first.c_str(), "filament_%d", &idx) == 1) {
|
if (kvp.first == "filament" || sscanf(kvp.first.c_str(), "filament_%d", &idx) == 1) {
|
||||||
@ -101,8 +106,12 @@ void Snapshot::load_ini(const std::string &path)
|
|||||||
this->filaments.resize(idx + 1, std::string());
|
this->filaments.resize(idx + 1, std::string());
|
||||||
this->filaments[idx] = kvp.second.data();
|
this->filaments[idx] = kvp.second.data();
|
||||||
}
|
}
|
||||||
|
} else if (kvp.first == "sla_material") {
|
||||||
|
this->sla_material = kvp.second.data();
|
||||||
} else if (kvp.first == "printer") {
|
} else if (kvp.first == "printer") {
|
||||||
this->printer = kvp.second.data();
|
this->printer = kvp.second.data();
|
||||||
|
} else if (kvp.first == "physical_printer") {
|
||||||
|
this->physical_printer = kvp.second.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (boost::starts_with(section.first, group_name_vendor) && section.first.size() > group_name_vendor.size()) {
|
} else if (boost::starts_with(section.first, group_name_vendor) && section.first.size() > group_name_vendor.size()) {
|
||||||
@ -172,10 +181,13 @@ void Snapshot::save_ini(const std::string &path)
|
|||||||
// Export the active presets at the time of the snapshot.
|
// Export the active presets at the time of the snapshot.
|
||||||
c << std::endl << "[presets]" << std::endl;
|
c << std::endl << "[presets]" << std::endl;
|
||||||
c << "print = " << this->print << std::endl;
|
c << "print = " << this->print << std::endl;
|
||||||
|
c << "sla_print = " << this->sla_print << std::endl;
|
||||||
c << "filament = " << this->filaments.front() << std::endl;
|
c << "filament = " << this->filaments.front() << std::endl;
|
||||||
for (size_t i = 1; i < this->filaments.size(); ++ i)
|
for (size_t i = 1; i < this->filaments.size(); ++ i)
|
||||||
c << "filament_" << std::to_string(i) << " = " << this->filaments[i] << std::endl;
|
c << "filament_" << std::to_string(i) << " = " << this->filaments[i] << std::endl;
|
||||||
|
c << "sla_material = " << this->sla_material << std::endl;
|
||||||
c << "printer = " << this->printer << std::endl;
|
c << "printer = " << this->printer << std::endl;
|
||||||
|
c << "physical_printer = " << this->physical_printer << std::endl;
|
||||||
|
|
||||||
// Export the vendor configs.
|
// Export the vendor configs.
|
||||||
for (const VendorConfig &vc : this->vendor_configs) {
|
for (const VendorConfig &vc : this->vendor_configs) {
|
||||||
@ -199,14 +211,17 @@ void Snapshot::export_selections(AppConfig &config) const
|
|||||||
{
|
{
|
||||||
assert(filaments.size() >= 1);
|
assert(filaments.size() >= 1);
|
||||||
config.clear_section("presets");
|
config.clear_section("presets");
|
||||||
config.set("presets", "print", print);
|
config.set("presets", "print", print);
|
||||||
config.set("presets", "filament", filaments.front());
|
config.set("presets", "sla_print", sla_print);
|
||||||
|
config.set("presets", "filament", filaments.front());
|
||||||
for (unsigned i = 1; i < filaments.size(); ++i) {
|
for (unsigned i = 1; i < filaments.size(); ++i) {
|
||||||
char name[64];
|
char name[64];
|
||||||
sprintf(name, "filament_%u", i);
|
sprintf(name, "filament_%u", i);
|
||||||
config.set("presets", name, filaments[i]);
|
config.set("presets", name, filaments[i]);
|
||||||
}
|
}
|
||||||
config.set("presets", "printer", printer);
|
config.set("presets", "sla_material", sla_material);
|
||||||
|
config.set("presets", "printer", printer);
|
||||||
|
config.set("presets", "physical_printer", physical_printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Snapshot::export_vendor_configs(AppConfig &config) const
|
void Snapshot::export_vendor_configs(AppConfig &config) const
|
||||||
@ -217,8 +232,10 @@ void Snapshot::export_vendor_configs(AppConfig &config) const
|
|||||||
config.set_vendors(std::move(vendors));
|
config.set_vendors(std::move(vendors));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform a deep compare of the active print / filament / printer / vendor directories.
|
static constexpr auto snapshot_subdirs = { "print", "sla_print", "filament", "sla_material", "printer", "physical_printer", "vendor" };
|
||||||
// Return true if the content of the current print / filament / printer / vendor directories
|
|
||||||
|
// Perform a deep compare of the active print / sla_print / filament / sla_material / printer / physical_printer / vendor directories.
|
||||||
|
// Return true if the content of the current print / sla_print / filament / sla_material / printer / physical_printer / vendor directories
|
||||||
// matches the state stored in this snapshot.
|
// matches the state stored in this snapshot.
|
||||||
bool Snapshot::equal_to_active(const AppConfig &app_config) const
|
bool Snapshot::equal_to_active(const AppConfig &app_config) const
|
||||||
{
|
{
|
||||||
@ -243,7 +260,7 @@ bool Snapshot::equal_to_active(const AppConfig &app_config) const
|
|||||||
// 2) Check, whether this snapshot references the same set of ini files as the current state.
|
// 2) Check, whether this snapshot references the same set of ini files as the current state.
|
||||||
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
|
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
|
||||||
boost::filesystem::path snapshot_dir = boost::filesystem::path(Slic3r::data_dir()) / SLIC3R_SNAPSHOTS_DIR / this->id;
|
boost::filesystem::path snapshot_dir = boost::filesystem::path(Slic3r::data_dir()) / SLIC3R_SNAPSHOTS_DIR / this->id;
|
||||||
for (const char *subdir : { "print", "filament", "printer", "vendor" }) {
|
for (const char *subdir : snapshot_subdirs) {
|
||||||
boost::filesystem::path path1 = data_dir / subdir;
|
boost::filesystem::path path1 = data_dir / subdir;
|
||||||
boost::filesystem::path path2 = snapshot_dir / subdir;
|
boost::filesystem::path path2 = snapshot_dir / subdir;
|
||||||
std::vector<std::string> files1, files2;
|
std::vector<std::string> files1, files2;
|
||||||
@ -369,9 +386,12 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot:
|
|||||||
snapshot.comment = comment;
|
snapshot.comment = comment;
|
||||||
snapshot.reason = reason;
|
snapshot.reason = reason;
|
||||||
// Active presets at the time of the snapshot.
|
// Active presets at the time of the snapshot.
|
||||||
snapshot.print = app_config.get("presets", "print");
|
snapshot.print = app_config.get("presets", "print");
|
||||||
|
snapshot.sla_print = app_config.get("presets", "sla_print");
|
||||||
snapshot.filaments.emplace_back(app_config.get("presets", "filament"));
|
snapshot.filaments.emplace_back(app_config.get("presets", "filament"));
|
||||||
snapshot.printer = app_config.get("presets", "printer");
|
snapshot.sla_material = app_config.get("presets", "sla_material");
|
||||||
|
snapshot.printer = app_config.get("presets", "printer");
|
||||||
|
snapshot.physical_printer = app_config.get("presets", "physical_printer");
|
||||||
for (unsigned i = 1; i < 1000; ++ i) {
|
for (unsigned i = 1; i < 1000; ++ i) {
|
||||||
char name[64];
|
char name[64];
|
||||||
sprintf(name, "filament_%u", i);
|
sprintf(name, "filament_%u", i);
|
||||||
@ -414,7 +434,7 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot:
|
|||||||
boost::filesystem::create_directory(snapshot_dir);
|
boost::filesystem::create_directory(snapshot_dir);
|
||||||
|
|
||||||
// Backup the presets.
|
// Backup the presets.
|
||||||
for (const char *subdir : { "print", "filament", "printer", "vendor" })
|
for (const char *subdir : snapshot_subdirs)
|
||||||
copy_config_dir_single_level(data_dir / subdir, snapshot_dir / subdir);
|
copy_config_dir_single_level(data_dir / subdir, snapshot_dir / subdir);
|
||||||
snapshot.save_ini((snapshot_dir / "snapshot.ini").string());
|
snapshot.save_ini((snapshot_dir / "snapshot.ini").string());
|
||||||
assert(m_snapshots.empty() || m_snapshots.back().time_captured <= snapshot.time_captured);
|
assert(m_snapshots.empty() || m_snapshots.back().time_captured <= snapshot.time_captured);
|
||||||
@ -438,11 +458,11 @@ void SnapshotDB::restore_snapshot(const Snapshot &snapshot, AppConfig &app_confi
|
|||||||
boost::filesystem::path snapshot_db_dir = SnapshotDB::create_db_dir();
|
boost::filesystem::path snapshot_db_dir = SnapshotDB::create_db_dir();
|
||||||
boost::filesystem::path snapshot_dir = snapshot_db_dir / snapshot.id;
|
boost::filesystem::path snapshot_dir = snapshot_db_dir / snapshot.id;
|
||||||
// Remove existing ini files and restore the ini files from the snapshot.
|
// Remove existing ini files and restore the ini files from the snapshot.
|
||||||
for (const char *subdir : { "print", "filament", "printer", "vendor" }) {
|
for (const char *subdir : snapshot_subdirs) {
|
||||||
delete_existing_ini_files(data_dir / subdir);
|
delete_existing_ini_files(data_dir / subdir);
|
||||||
copy_config_dir_single_level(snapshot_dir / subdir, data_dir / subdir);
|
copy_config_dir_single_level(snapshot_dir / subdir, data_dir / subdir);
|
||||||
}
|
}
|
||||||
// Update AppConfig with the selections of the print / filament / printer profiles
|
// Update AppConfig with the selections of the print / sla_print / filament / sla_material / printer profiles
|
||||||
// and about the installed printer types and variants.
|
// and about the installed printer types and variants.
|
||||||
snapshot.export_selections(app_config);
|
snapshot.export_selections(app_config);
|
||||||
snapshot.export_vendor_configs(app_config);
|
snapshot.export_vendor_configs(app_config);
|
||||||
|
@ -23,8 +23,11 @@ namespace Config {
|
|||||||
// Slic3r.ini
|
// Slic3r.ini
|
||||||
// vendor/
|
// vendor/
|
||||||
// print/
|
// print/
|
||||||
|
// sla_print/
|
||||||
// filament/
|
// filament/
|
||||||
|
// sla_material
|
||||||
// printer/
|
// printer/
|
||||||
|
// physical_printer/
|
||||||
class Snapshot
|
class Snapshot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -42,12 +45,12 @@ public:
|
|||||||
void load_ini(const std::string &path);
|
void load_ini(const std::string &path);
|
||||||
void save_ini(const std::string &path);
|
void save_ini(const std::string &path);
|
||||||
|
|
||||||
// Export the print / filament / printer selections to be activated into the AppConfig.
|
// Export the print / sla_print / filament / sla_material / printer selections to be activated into the AppConfig.
|
||||||
void export_selections(AppConfig &config) const;
|
void export_selections(AppConfig &config) const;
|
||||||
void export_vendor_configs(AppConfig &config) const;
|
void export_vendor_configs(AppConfig &config) const;
|
||||||
|
|
||||||
// Perform a deep compare of the active print / filament / printer / vendor directories.
|
// Perform a deep compare of the active print / sla_print / filament / sla_material / printer / physical_printer / vendor directories.
|
||||||
// Return true if the content of the current print / filament / printer / vendor directories
|
// Return true if the content of the current print / sla_print / filament / sla_material / printer / physical_printer / vendor directories
|
||||||
// matches the state stored in this snapshot.
|
// matches the state stored in this snapshot.
|
||||||
bool equal_to_active(const AppConfig &app_config) const;
|
bool equal_to_active(const AppConfig &app_config) const;
|
||||||
|
|
||||||
@ -65,8 +68,11 @@ public:
|
|||||||
|
|
||||||
// Active presets at the time of the snapshot.
|
// Active presets at the time of the snapshot.
|
||||||
std::string print;
|
std::string print;
|
||||||
|
std::string sla_print;
|
||||||
std::vector<std::string> filaments;
|
std::vector<std::string> filaments;
|
||||||
|
std::string sla_material;
|
||||||
std::string printer;
|
std::string printer;
|
||||||
|
std::string physical_printer;
|
||||||
|
|
||||||
// Annotation of the vendor configuration stored in the snapshot.
|
// Annotation of the vendor configuration stored in the snapshot.
|
||||||
// This information is displayed to the user and used to decide compatibility
|
// This information is displayed to the user and used to decide compatibility
|
||||||
@ -97,7 +103,7 @@ public:
|
|||||||
size_t load_db();
|
size_t load_db();
|
||||||
void update_slic3r_versions(std::vector<Index> &index_db);
|
void update_slic3r_versions(std::vector<Index> &index_db);
|
||||||
|
|
||||||
// Create a snapshot directory, copy the vendor config bundles, user print/filament/printer profiles,
|
// Create a snapshot directory, copy the vendor config bundles, user print / sla_print / filament / sla_material / printer / physical_printer profiles,
|
||||||
// create an index.
|
// create an index.
|
||||||
const Snapshot& take_snapshot(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment = "");
|
const Snapshot& take_snapshot(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment = "");
|
||||||
const Snapshot& restore_snapshot(const std::string &id, AppConfig &app_config);
|
const Snapshot& restore_snapshot(const std::string &id, AppConfig &app_config);
|
||||||
|
@ -48,9 +48,17 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve
|
|||||||
text += "</b></font><br>";
|
text += "</b></font><br>";
|
||||||
// End of row header.
|
// End of row header.
|
||||||
text += _(L("PrusaSlicer version")) + ": " + snapshot.slic3r_version_captured.to_string() + "<br>";
|
text += _(L("PrusaSlicer version")) + ": " + snapshot.slic3r_version_captured.to_string() + "<br>";
|
||||||
text += _(L("print")) + ": " + snapshot.print + "<br>";
|
bool has_fff = ! snapshot.print.empty() || ! snapshot.filaments.empty();
|
||||||
text += _(L("filaments")) + ": " + snapshot.filaments.front() + "<br>";
|
bool has_sla = ! snapshot.sla_print.empty() || ! snapshot.sla_material.empty();
|
||||||
text += _(L("printer")) + ": " + snapshot.printer + "<br>";
|
if (has_fff || ! has_sla) {
|
||||||
|
text += _(L("print")) + ": " + snapshot.print + "<br>";
|
||||||
|
text += _(L("filaments")) + ": " + snapshot.filaments.front() + "<br>";
|
||||||
|
}
|
||||||
|
if (has_sla) {
|
||||||
|
text += _(L("SLA print")) + ": " + snapshot.sla_print + "<br>";
|
||||||
|
text += _(L("SLA material")) + ": " + snapshot.sla_material + "<br>";
|
||||||
|
}
|
||||||
|
text += _(L("printer")) + ": " + (snapshot.physical_printer.empty() ? snapshot.printer : snapshot.physical_printer) + "<br>";
|
||||||
|
|
||||||
bool compatible = true;
|
bool compatible = true;
|
||||||
for (const Config::Snapshot::VendorConfig &vc : snapshot.vendor_configs) {
|
for (const Config::Snapshot::VendorConfig &vc : snapshot.vendor_configs) {
|
||||||
|
@ -12,9 +12,7 @@
|
|||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "ExtruderSequenceDialog.hpp"
|
#include "ExtruderSequenceDialog.hpp"
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
#if ENABLE_GCODE_VIEWER
|
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
|
||||||
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
@ -477,8 +475,10 @@ void Control::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_
|
|||||||
{
|
{
|
||||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||||
|
|
||||||
|
#if ENABLE_GCODE_VIEWER
|
||||||
if (!m_enable_action_icon)
|
if (!m_enable_action_icon)
|
||||||
return;
|
return;
|
||||||
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
// suppress add tick on first layer
|
// suppress add tick on first layer
|
||||||
if (tick == 0)
|
if (tick == 0)
|
||||||
|
@ -717,6 +717,7 @@ void GUI_App::init_app_config()
|
|||||||
std::string error = app_config->load();
|
std::string error = app_config->load();
|
||||||
if (!error.empty()) {
|
if (!error.empty()) {
|
||||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||||
|
#if ENABLE_GCODE_VIEWER
|
||||||
if (is_editor()) {
|
if (is_editor()) {
|
||||||
throw Slic3r::RuntimeError(
|
throw Slic3r::RuntimeError(
|
||||||
_u8L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
_u8L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||||
@ -724,11 +725,14 @@ void GUI_App::init_app_config()
|
|||||||
"\n\n" + app_config->config_path() + "\n\n" + error);
|
"\n\n" + app_config->config_path() + "\n\n" + error);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
throw Slic3r::RuntimeError(
|
throw Slic3r::RuntimeError(
|
||||||
_u8L("Error parsing PrusaGCodeViewer config file, it is probably corrupted. "
|
_u8L("Error parsing PrusaGCodeViewer config file, it is probably corrupted. "
|
||||||
"Try to manually delete the file to recover from the error.") +
|
"Try to manually delete the file to recover from the error.") +
|
||||||
"\n\n" + app_config->config_path() + "\n\n" + error);
|
"\n\n" + app_config->config_path() + "\n\n" + error);
|
||||||
|
#if ENABLE_GCODE_VIEWER
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <boost/bind/placeholders.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <wx/glcanvas.h>
|
#include <wx/glcanvas.h>
|
||||||
@ -639,7 +641,7 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
|
|||||||
void NotificationManager::push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp)
|
void NotificationManager::push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(basic_notifications.begin(), basic_notifications.end(),
|
auto it = std::find_if(basic_notifications.begin(), basic_notifications.end(),
|
||||||
boost::bind(&NotificationData::type, _1) == type);
|
boost::bind(&NotificationData::type, boost::placeholders::_1) == type);
|
||||||
assert(it != basic_notifications.end());
|
assert(it != basic_notifications.end());
|
||||||
if (it != basic_notifications.end())
|
if (it != basic_notifications.end())
|
||||||
push_notification_data( *it, canvas, timestamp);
|
push_notification_data( *it, canvas, timestamp);
|
||||||
@ -825,7 +827,7 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
|||||||
it = m_pop_notifications.erase(it);
|
it = m_pop_notifications.erase(it);
|
||||||
} else {
|
} else {
|
||||||
(*it)->set_paused(m_hovered);
|
(*it)->set_paused(m_hovered);
|
||||||
PopNotification::RenderResult res = (*it)->render(canvas, last_x, m_move_from_overlay, overlay_width);
|
PopNotification::RenderResult res = (*it)->render(canvas, last_x, m_move_from_overlay && !m_in_preview, overlay_width);
|
||||||
if (res != PopNotification::RenderResult::Finished) {
|
if (res != PopNotification::RenderResult::Finished) {
|
||||||
last_x = (*it)->get_top() + GAP_WIDTH;
|
last_x = (*it)->get_top() + GAP_WIDTH;
|
||||||
current_height = std::max(current_height, (*it)->get_current_top());
|
current_height = std::max(current_height, (*it)->get_current_top());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user