Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_preview_layout

This commit is contained in:
enricoturri1966 2021-10-07 14:13:05 +02:00
commit 6b4014433f
19 changed files with 534 additions and 283 deletions

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
<circle fill="#FFFFFF" cx="512" cy="512" r="512"/>
<path fill="#333333" d="M308.97,650.05c0.72,0.89,1.44,1.77,2.17,2.65c0.47,0.57,0.94,1.13,1.42,1.69
c5.82,6.94,11.97,13.7,18.49,20.22l435.89-435.89c-21.69-21.69-45.83-39.46-71.5-53.33c-0.46-0.25-0.93-0.51-1.39-0.75
c-1.31-0.7-2.63-1.39-3.96-2.07c-0.58-0.3-1.16-0.59-1.73-0.88c-1.34-0.68-2.69-1.36-4.04-2.02c0,0,0,0,0,0l0,0
c-23.73-11.59-48.64-19.95-74.07-25.08l0,0c0,0,0,0,0,0c-4.86-0.98-9.74-1.84-14.63-2.59c0,0,0,0-0.01,0
c-2.44-0.37-4.89-0.71-7.34-1.03c0,0-0.01,0-0.01,0c-2.45-0.31-4.91-0.6-7.37-0.85l0,0l0,0c-8.26-0.85-16.54-1.39-24.83-1.58
c-1.96-0.04-3.92-0.06-5.87-0.07c-0.4,0-0.79-0.01-1.19-0.01c-0.3,0-0.61,0.01-0.91,0.01c-1.78,0.01-3.57,0.03-5.35,0.06
c-0.96,0.02-1.92,0.05-2.88,0.08c-1.03,0.03-2.05,0.07-3.08,0.11c-1.84,0.07-3.67,0.16-5.5,0.27c-0.56,0.03-1.12,0.07-1.68,0.1
c-15.09,0.95-30.12,2.99-44.97,6.15l0,0c0,0,0,0,0,0c-2.2,0.47-4.39,0.96-6.58,1.48c-0.14,0.03-0.28,0.06-0.42,0.1
c-2.11,0.5-4.22,1.03-6.33,1.57c-0.2,0.05-0.4,0.1-0.61,0.16c-2.07,0.54-4.14,1.11-6.2,1.7c-0.22,0.06-0.44,0.12-0.67,0.19
c-2.06,0.59-4.12,1.21-6.17,1.84c-0.21,0.06-0.42,0.13-0.63,0.19c-2.07,0.65-4.14,1.31-6.2,2c-0.18,0.06-0.35,0.12-0.53,0.18
c-2.09,0.71-4.18,1.43-6.26,2.18c-0.13,0.05-0.26,0.1-0.4,0.14c-2.12,0.77-4.24,1.56-6.35,2.38c-0.07,0.03-0.14,0.06-0.22,0.08
c-2.17,0.84-4.33,1.71-6.48,2.6c0,0,0,0,0,0l0,0c-33.3,13.84-64.67,33.76-92.4,59.79h0c0,0,0,0,0,0c-0.94,0.88-1.87,1.77-2.8,2.66
c-1.46,1.4-2.91,2.81-4.35,4.24c-1.43,1.43-2.84,2.88-4.23,4.34c-25.08,26.07-44.67,55.46-58.78,86.73v0c0,0,0,0,0,0
c-2.06,4.57-4.01,9.17-5.83,13.82c-0.18,0.45-0.36,0.91-0.53,1.36c-0.54,1.4-1.08,2.8-1.61,4.21c0,0,0,0,0,0l0,0
c-15.88,42.78-21.94,88.37-18.19,133.3c0,0,0,0,0,0l0,0c1.15,13.7,3.19,27.35,6.16,40.83c0.4,1.81,0.82,3.61,1.25,5.42
c0.19,0.79,0.38,1.57,0.57,2.36c0.41,1.64,0.83,3.28,1.26,4.92c0.27,1.03,0.55,2.05,0.84,3.07c0.23,0.82,0.46,1.64,0.7,2.46
c0.56,1.95,1.13,3.89,1.73,5.83c0.12,0.39,0.24,0.78,0.36,1.17c0.79,2.54,1.61,5.07,2.47,7.59c0,0,0,0,0,0l0,0
c10.76,31.64,26.79,61.88,48.12,89.34C306.53,647,307.74,648.53,308.97,650.05z M346.52,261.4l26.16,17.44v51.62l-26.16,17.44
l-26.16,17.44l-26.16-17.44l-9.53-6.35c13.53-31.12,32.34-59.34,56-84.05L346.52,261.4z M549.89,168.46l9.76,6.51v51.62
l-26.16,17.44l-26.16,17.44l-46.15-30.77l-6.17-4.11v-42.45c30.19-10.41,61.74-15.69,93.99-15.69
C549.29,168.44,549.59,168.45,549.89,168.46z M641.98,330.46v-51.62l26.16-17.44l26.16-17.44l23.46,15.64l-72.83,72.83
L641.98,330.46z M509.79,467.58l-2.46,1.64L455,434.34v-51.62l10.98-7.32l41.34-27.56l26.16,17.44l26.16,17.44v35L509.79,467.58z
M330.35,642.09v-51.62l26.16-17.44l26.16-17.44l23.46,15.64l-72.83,72.83L330.35,642.09z M418.84,555.65l-26.16-17.44v-51.62
l26.16-17.44L445,451.71l26.16,17.44l22.23,14.82l-72.83,72.83L418.84,555.65z M621.98,330.46l-26.16,17.44l-26.16,17.44
l-52.32-34.88v-51.62l52.32-34.88l26.16,17.44l26.16,17.44V330.46z M624.65,352.72l-45,45v-15l26.16-17.44L624.65,352.72z
M445,243.96l26.16,17.44l26.16,17.44v51.62l-26.16,17.44L445,365.34l-26.16-17.44l-26.16-17.44v-51.62l26.16-17.44L445,243.96z
M408.84,365.27L435,382.72v51.62l-52.32,34.88l-26.16-17.44l-26.16-17.44v-51.62l26.16-17.44l26.16-17.44L408.84,365.27z
M346.52,469.15l26.16,17.44v51.62l-26.16,17.44l-26.16,17.44l-26.16-17.44l-20.57-13.72c-2.12-6.87-3.99-13.8-5.59-20.79v-34.56
l26.16-17.44l26.16-17.44L346.52,469.15z M310.35,590.47v27.94c-9.53-14.02-17.77-28.84-24.69-44.4L310.35,590.47z M732.19,245.18
l-27.89-18.59v-12.8c11.86,7.6,23.16,16.08,33.87,25.42L732.19,245.18z M657.46,189.55c9.2,3.73,18.15,7.91,26.85,12.53v24.51
l-26.16,17.44l-26.16,17.44l-26.16-17.44l-26.16-17.44v-51.62l6.25-4.17C610.43,173.93,634.38,180.19,657.46,189.55z M435,191.87
v34.72l-26.16,17.44l-26.16,17.44l-26.16-17.44l-1.21-0.81C378.99,221.68,405.73,204.45,435,191.87z M284.19,365.27l26.16,17.44
v51.62l-49.37,32.92c-0.13-3.52-0.21-7.05-0.21-10.59c0-32.99,5.52-65.24,16.41-96.07L284.19,365.27z"/>
<path fill="#ED6B21" d="M759.84,687.31c0.31-0.74,0.63-1.49,0.94-2.23c0.51-1.24,1.01-2.48,1.51-3.72c0.3-0.75,0.59-1.5,0.88-2.26
c15.37-39.59,22.26-81.7,20.67-123.56c-0.02-0.42-0.03-0.85-0.05-1.28c-0.08-1.87-0.18-3.74-0.29-5.61
c-0.01-0.19-0.02-0.38-0.03-0.57c-0.12-1.99-0.27-3.98-0.43-5.96c0,0,0,0,0,0l0,0c-1.24-15.16-3.59-30.24-7.06-45.12l0,0
c0,0,0,0,0,0c-0.58-2.49-1.19-4.98-1.84-7.46c0,0,0,0,0,0c-0.64-2.47-1.31-4.92-2.01-7.38c-0.01-0.02-0.01-0.05-0.02-0.07
c-0.7-2.43-1.43-4.86-2.18-7.28c-0.01-0.04-0.02-0.07-0.03-0.11c-0.77-2.44-1.56-4.87-2.39-7.3c0,0,0,0,0,0l0,0
c-10.8-31.61-26.88-61.81-48.25-89.23c-1.1-1.41-2.22-2.81-3.35-4.21c-0.8-0.99-1.61-1.98-2.43-2.96c-0.44-0.53-0.88-1.05-1.32-1.57
c-5.77-6.88-11.87-13.57-18.34-20.04l-5.16,5.16l0,0l-14.42,14.42l0,0L590.4,452.8l-3.42,3.42l0,0l-60.3,60.3l0,0l-20,20l0,0
l-2.64,2.64l0,0l-30.11,30.11l-96.89,96.89l0,0l-10.84,10.84l-76.42,76.42h0l-13.83,13.83l-18.03,18.03
c18.94,18.94,39.73,34.89,61.78,47.87c1.78,1.05,3.56,2.07,5.36,3.08c0.86,0.48,1.72,0.95,2.58,1.42c1.13,0.62,2.26,1.24,3.4,1.84
c0.89,0.47,1.78,0.95,2.67,1.41c1.25,0.65,2.5,1.28,3.75,1.91c28.95,14.55,59.72,24.25,91.1,29.1c0,0,0,0,0,0
c2.44,0.38,4.88,0.72,7.32,1.04c0,0,0.01,0,0.01,0c2.45,0.32,4.89,0.61,7.34,0.87c0,0,0,0,0,0l0,0c8.87,0.94,17.78,1.5,26.69,1.67
c1.44,0.03,2.87,0.04,4.31,0.05c0.54,0,1.08,0.02,1.62,0.02c0.41,0,0.83-0.01,1.24-0.01c1.49-0.01,2.97-0.02,4.46-0.05
c1.11-0.02,2.23-0.05,3.34-0.08c0.66-0.02,1.31-0.05,1.97-0.07c2.2-0.08,4.4-0.18,6.59-0.3c0.26-0.02,0.52-0.03,0.79-0.05
c15.01-0.89,29.97-2.88,44.75-5.95l0,0c0,0,0,0,0,0c2.3-0.48,4.61-0.99,6.9-1.52c0.04-0.01,0.08-0.02,0.12-0.03
c2.26-0.53,4.52-1.08,6.77-1.66c0.08-0.02,0.15-0.04,0.23-0.06c2.22-0.57,4.43-1.17,6.64-1.79c0.11-0.03,0.21-0.06,0.32-0.09
c2.18-0.62,4.36-1.26,6.54-1.93c0.13-0.04,0.25-0.08,0.38-0.12c2.16-0.67,4.31-1.35,6.46-2.07c0.13-0.04,0.26-0.09,0.39-0.13
c2.15-0.72,4.29-1.46,6.42-2.22c0.12-0.04,0.24-0.09,0.35-0.13c2.15-0.78,4.3-1.57,6.44-2.4c0.08-0.03,0.15-0.06,0.23-0.09
c37.07-14.33,71.92-36.1,102.27-65.29c1.46-1.39,2.91-2.8,4.34-4.23c1.43-1.43,2.84-2.89,4.24-4.35c0.9-0.94,1.8-1.88,2.69-2.83l0,0
l0,0C726.34,750.82,746.03,720.02,759.84,687.31z M739.81,658.73l-26.16-17.44v-51.62l26.16-17.44l24.04-16.03
c0.14,3.71,0.23,7.42,0.23,11.14c0,33.15-5.58,65.56-16.57,96.52L739.81,658.73z M474.09,855.53l-9.75-6.5v-51.62l26.16-17.44
l26.16-17.44l26.16,17.44L569,797.41v42.74c-29.93,10.21-61.19,15.4-93.13,15.4C475.27,855.56,474.68,855.54,474.09,855.53z
M516.69,554.79l26.14,17.43L569,589.66v51.62l-26.16,17.44l-26.16,17.44l-26.16-17.44l-26.16-17.44v-34.15L516.69,554.79z
M579,658.66l26.16,17.44l26.16,17.44v51.62l-26.16,17.44L579,780.04l-26.16-17.44l-26.16-17.44v-51.62l26.16-17.44L579,658.66z
M402.02,693.54l26.16-17.44l26.16-17.44l26.16,17.44l26.16,17.44v51.62l-26.16,17.44l-26.16,17.44l-26.16-17.44l-26.16-17.44
V693.54z M401.91,669.58l42.44-42.44v14.15l-26.16,17.44L401.91,669.58z M589,797.41l26.16-17.44l26.16-17.44l26.16,17.44l1.71,1.14
c-23.82,21.6-50.73,38.83-80.2,51.38V797.41z M615.16,658.73L589,641.28v-51.62l26.16-17.44l26.16-17.44l26.16,17.44l26.16,17.44
v51.62l-26.16,17.44l-26.16,17.44L615.16,658.73z M677.48,554.85l-26.16-17.44v-51.62l26.16-17.44l26.16-17.44l26.16,17.44
l21.65,14.43c1.66,5.43,3.18,10.89,4.51,16.4v38.23l-26.16,17.44l-26.16,17.44L677.48,554.85z M739.55,450.8l-25.9-17.27v-29.18
C723.7,418.98,732.35,434.49,739.55,450.8z M693.65,381.91v51.62l-26.16,17.44l-26.16,17.44l-22.95-15.3l72.83-72.83L693.65,381.91z
M605.16,468.35l26.16,17.44v51.62l-26.16,17.44L579,572.29l-26.16-17.44l-21.72-14.48l72.83-72.83L605.16,468.35z M379.58,691.91
l2.44,1.63v51.62l-26.16,17.44l-26.16,17.44l-22.95-15.3L379.58,691.91z M292.32,779.16l27.38,18.25v12.26
c-11.55-7.46-22.56-15.75-33.01-24.87L292.32,779.16z M339.7,821.46v-24.04l26.16-17.44l26.16-17.44l26.16,17.44l26.16,17.44v51.62
l-6.11,4.07c-24.28-3.16-47.99-9.39-70.84-18.65C357.9,830.6,348.66,826.26,339.7,821.46z M677.48,762.6l-26.16-17.44v-51.62
l26.16-17.44l26.16-17.44l26.16,17.44l10.18,6.79c-13.58,31.09-32.43,59.28-56.14,83.96L677.48,762.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -85,9 +85,6 @@ void AppConfig::set_defaults()
if (get("associate_stl").empty()) if (get("associate_stl").empty())
set("associate_stl", "0"); set("associate_stl", "0");
if (get("dark_color_mode").empty())
set("dark_color_mode", "0");
if (get("tabs_as_menu").empty()) if (get("tabs_as_menu").empty())
set("tabs_as_menu", "0"); set("tabs_as_menu", "0");
#endif // _WIN32 #endif // _WIN32
@ -179,6 +176,9 @@ void AppConfig::set_defaults()
#ifdef _WIN32 #ifdef _WIN32
if (get("use_legacy_3DConnexion").empty()) if (get("use_legacy_3DConnexion").empty())
set("use_legacy_3DConnexion", "0"); set("use_legacy_3DConnexion", "0");
if (get("dark_color_mode").empty())
set("dark_color_mode", "0");
#endif // _WIN32 #endif // _WIN32
// Remove legacy window positions/sizes // Remove legacy window positions/sizes

View File

@ -1214,7 +1214,7 @@ static void cut_segmented_layers(const std::vector<ExPolygons>
const std::function<void()> &throw_on_cancel_callback) const std::function<void()> &throw_on_cancel_callback)
{ {
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin";
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),[&](const tbb::blocked_range<size_t>& range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),[&segmented_regions, &input_expolygons, &cut_width, &throw_on_cancel_callback](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
throw_on_cancel_callback(); throw_on_cancel_callback();
std::vector<std::pair<ExPolygon, size_t>> segmented_regions_cuts; std::vector<std::pair<ExPolygon, size_t>> segmented_regions_cuts;
@ -1366,7 +1366,8 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
return out; return out;
}; };
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers, granularity), [&](const tbb::blocked_range<size_t> &range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers, granularity), [&granularity, &num_layers, &num_extruders, &layer_color_stat, &top_raw, &triangles_by_color_top,
&throw_on_cancel_callback, &input_expolygons, &bottom_raw, &triangles_by_color_bottom](const tbb::blocked_range<size_t> &range) {
size_t group_idx = range.begin() / granularity; size_t group_idx = range.begin() / granularity;
size_t layer_idx_offset = (group_idx & 1) * num_layers; size_t layer_idx_offset = (group_idx & 1) * num_layers;
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
@ -1417,7 +1418,7 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
std::vector<std::vector<ExPolygons>> triangles_by_color_merged(num_extruders); std::vector<std::vector<ExPolygons>> triangles_by_color_merged(num_extruders);
triangles_by_color_merged.assign(num_extruders, std::vector<ExPolygons>(num_layers)); triangles_by_color_merged.assign(num_extruders, std::vector<ExPolygons>(num_layers));
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&](const tbb::blocked_range<size_t> &range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&triangles_by_color_merged, &triangles_by_color_bottom, &triangles_by_color_top, &num_layers, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
throw_on_cancel_callback(); throw_on_cancel_callback();
for (size_t color_idx = 0; color_idx < triangles_by_color_merged.size(); ++color_idx) { for (size_t color_idx = 0; color_idx < triangles_by_color_merged.size(); ++color_idx) {
@ -1446,7 +1447,7 @@ static std::vector<std::vector<std::pair<ExPolygon, size_t>>> merge_segmented_la
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged(segmented_regions.size()); std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions_merged(segmented_regions.size());
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin";
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()), [&](const tbb::blocked_range<size_t> &range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()), [&segmented_regions, &top_and_bottom_layers, &segmented_regions_merged, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
for (const std::pair<ExPolygon, size_t> &colored_expoly : segmented_regions[layer_idx]) { for (const std::pair<ExPolygon, size_t> &colored_expoly : segmented_regions[layer_idx]) {
throw_on_cancel_callback(); throw_on_cancel_callback();
@ -1526,6 +1527,20 @@ void export_processed_input_expolygons_to_svg(const std::string &path, const Lay
} }
#endif // MMU_SEGMENTATION_DEBUG_INPUT #endif // MMU_SEGMENTATION_DEBUG_INPUT
// Check if all ColoredLine representing a single layer uses the same color.
static bool has_layer_only_one_color(const std::vector<std::vector<ColoredLine>> &colored_polygons)
{
assert(!colored_polygons.empty());
assert(!colored_polygons.front().empty());
int first_line_color = colored_polygons.front().front().color;
for (const std::vector<ColoredLine> &colored_polygon : colored_polygons)
for (const ColoredLine &colored_line : colored_polygon)
if (first_line_color != colored_line.color)
return false;
return true;
}
std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback) std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{ {
std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions(print_object.layers().size()); std::vector<std::vector<std::pair<ExPolygon, size_t>>> segmented_regions(print_object.layers().size());
@ -1539,7 +1554,7 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
// Merge all regions and remove small holes // Merge all regions and remove small holes
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin";
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size()), [&](const tbb::blocked_range<size_t> &range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size()), [&layers, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
throw_on_cancel_callback(); throw_on_cancel_callback();
ExPolygons ex_polygons; ExPolygons ex_polygons;
@ -1649,16 +1664,16 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
edge_grids[layer_idx].visit_cells_intersecting_line(line_start, line_end, visitor); edge_grids[layer_idx].visit_cells_intersecting_line(line_start, line_end, visitor);
} }
} }
}); }); // end of parallel_for
} }
}); }); // end of parallel_for
} }
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - end"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - end";
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - painted layers count: " BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - painted layers count: "
<< std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector<PaintedLine> &pl) { return !pl.empty(); }); << std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector<PaintedLine> &pl) { return !pl.empty(); });
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin"; BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin";
tbb::parallel_for(tbb::blocked_range<size_t>(0, print_object.layers().size()), [&](const tbb::blocked_range<size_t> &range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, print_object.layers().size()), [&edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
throw_on_cancel_callback(); throw_on_cancel_callback();
auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) { auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) {
@ -1677,20 +1692,28 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
if (!painted_lines_single.empty()) { if (!painted_lines_single.empty()) {
std::vector<std::vector<ColoredLine>> color_poly = colorize_polygons(edge_grids[layer_idx].contours(), painted_lines_single); std::vector<std::vector<ColoredLine>> color_poly = colorize_polygons(edge_grids[layer_idx].contours(), painted_lines_single);
MMU_Graph graph = build_graph(layer_idx, color_poly); assert(!color_poly.empty());
remove_multiple_edges_in_vertices(graph, color_poly); assert(!color_poly.front().empty());
graph.remove_nodes_with_one_arc(); if (has_layer_only_one_color(color_poly)) {
// If the whole layer is painted using the same color, it is not needed to construct a Voronoi diagram for the segmentation of this layer.
for (const ExPolygon &ex_polygon : input_expolygons[layer_idx])
segmented_regions[layer_idx].emplace_back(ex_polygon, size_t(color_poly.front().front().color));
} else {
MMU_Graph graph = build_graph(layer_idx, color_poly);
remove_multiple_edges_in_vertices(graph, color_poly);
graph.remove_nodes_with_one_arc();
#ifdef MMU_SEGMENTATION_DEBUG_GRAPH #ifdef MMU_SEGMENTATION_DEBUG_GRAPH
{ {
static int iRun = 0; static int iRun = 0;
export_graph_to_svg(debug_out_path("mm-graph-final-%d-%d.svg", layer_idx, iRun++), graph, input_expolygons[layer_idx]); export_graph_to_svg(debug_out_path("mm-graph-final-%d-%d.svg", layer_idx, iRun++), graph, input_expolygons[layer_idx]);
} }
#endif // MMU_SEGMENTATION_DEBUG_GRAPH #endif // MMU_SEGMENTATION_DEBUG_GRAPH
std::vector<std::pair<Polygon, size_t>> segmentation = extract_colored_segments(graph); std::vector<std::pair<Polygon, size_t>> segmentation = extract_colored_segments(graph);
for (std::pair<Polygon, size_t> &region : segmentation) for (std::pair<Polygon, size_t> &region : segmentation)
segmented_regions[layer_idx].emplace_back(std::move(region)); segmented_regions[layer_idx].emplace_back(std::move(region));
}
#ifdef MMU_SEGMENTATION_DEBUG_REGIONS #ifdef MMU_SEGMENTATION_DEBUG_REGIONS
{ {

View File

@ -220,7 +220,7 @@ AboutDialog::AboutDialog()
main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20); main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
// logo // logo
m_logo_bitmap = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_192px.png" : "PrusaSlicer-gcodeviewer_192px.png", 192); m_logo_bitmap = ScalableBitmap(this, wxGetApp().logo_name(), 192);
m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp()); m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp());
hsizer->Add(m_logo, 1, wxALIGN_CENTER_VERTICAL); hsizer->Add(m_logo, 1, wxALIGN_CENTER_VERTICAL);

View File

@ -193,7 +193,7 @@ public:
// load bitmap for logo // load bitmap for logo
BitmapCache bmp_cache; BitmapCache bmp_cache;
int logo_size = lround(width * 0.25); int logo_size = lround(width * 0.25);
wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().is_editor() ? "prusa_slicer_logo" : "add_gcode", logo_size, logo_size); wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().logo_name(), logo_size, logo_size);
wxCoord margin = int(m_scale * 20); wxCoord margin = int(m_scale * 20);
@ -883,7 +883,7 @@ bool GUI_App::on_init_inner()
} }
// create splash screen with updated bmp // create splash screen with updated bmp
scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("prusa_slicer_logo", nullptr, 400), scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("PrusaSlicer", nullptr, 400),
wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 4000, splashscreen_pos); wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 4000, splashscreen_pos);
#ifndef __linux__ #ifndef __linux__
wxYield(); wxYield();

View File

@ -166,6 +166,7 @@ public:
bool is_editor() const { return m_app_mode == EAppMode::Editor; } bool is_editor() const { return m_app_mode == EAppMode::Editor; }
bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; } bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
bool is_recreating_gui() const { return m_is_recreating_gui; } bool is_recreating_gui() const { return m_is_recreating_gui; }
std::string logo_name() const { return is_editor() ? "PrusaSlicer" : "PrusaSlicer-gcodeviewer"; }
// To be called after the GUI is fully built up. // To be called after the GUI is fully built up.
// Process command line parameters cached in this->init_params, // Process command line parameters cached in this->init_params,

View File

@ -4123,8 +4123,7 @@ void ObjectList::fix_through_netfabb()
Plater::TakeSnapshot snapshot(plater, _L("Fix through NetFabb")); Plater::TakeSnapshot snapshot(plater, _L("Fix through NetFabb"));
// Open a progress dialog. // Open a progress dialog.
wxProgressDialog progress_dlg(_L("Fixing through NetFabb"), "", 100, wxProgressDialog progress_dlg(_L("Fixing through NetFabb"), "", 100, plater,
nullptr, // ! parent of the wxProgressDialog should be nullptr to avoid flickering during the model fixing
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
int model_idx{ 0 }; int model_idx{ 0 };
if (vol_idxs.empty()) { if (vol_idxs.empty()) {

View File

@ -51,10 +51,17 @@ bool GLGizmoFdmSupports::on_init()
m_desc["remove_all"] = _L("Remove all selection"); m_desc["remove_all"] = _L("Remove all selection");
m_desc["circle"] = _L("Circle"); m_desc["circle"] = _L("Circle");
m_desc["sphere"] = _L("Sphere"); m_desc["sphere"] = _L("Sphere");
m_desc["pointer"] = _L("Triangles");
m_desc["highlight_by_angle"] = _L("Highlight by angle"); m_desc["highlight_by_angle"] = _L("Highlight by angle");
m_desc["enforce_button"] = _L("Enforce"); m_desc["enforce_button"] = _L("Enforce");
m_desc["cancel"] = _L("Cancel"); m_desc["cancel"] = _L("Cancel");
m_desc["tool_type"] = _L("Tool type") + ": ";
m_desc["tool_brush"] = _L("Brush");
m_desc["tool_smart_fill"] = _L("Smart fill");
m_desc["smart_fill_angle"] = _L("Smart fill angle");
return true; return true;
} }
@ -82,42 +89,48 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
if (! m_c->selection_info()->model_object()) if (! m_c->selection_info()->model_object())
return; return;
const float approx_height = m_imgui->scaled(17.0f); const float approx_height = m_imgui->scaled(20.5f);
y = std::min(y, bottom_limit - approx_height); y = std::min(y, bottom_limit - approx_height);
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x,
m_imgui->calc_text_size(m_desc.at("reset_direction")).x) m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
+ m_imgui->scaled(1.5f); const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); const float autoset_slider_left = m_imgui->calc_text_size(m_desc.at("highlight_by_angle")).x + m_imgui->scaled(1.f);
const float autoset_slider_left = m_imgui->calc_text_size(m_desc.at("highlight_by_angle")).x + m_imgui->scaled(1.f); const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.f);
const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f);
const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f);
+ m_imgui->scaled(2.5f); const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f);
const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x const float cursor_type_radio_pointer = m_imgui->calc_text_size(m_desc["pointer"]).x + m_imgui->scaled(2.5f);
+ m_imgui->scaled(2.5f);
const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
const float button_enforce_width = m_imgui->calc_text_size(m_desc.at("enforce_button")).x; const float button_enforce_width = m_imgui->calc_text_size(m_desc.at("enforce_button")).x;
const float button_cancel_width = m_imgui->calc_text_size(m_desc.at("cancel")).x; const float button_cancel_width = m_imgui->calc_text_size(m_desc.at("cancel")).x;
const float buttons_width = std::max(button_enforce_width, button_cancel_width) + m_imgui->scaled(0.5f); const float buttons_width = std::max(button_enforce_width, button_cancel_width) + m_imgui->scaled(0.5f);
const float minimal_slider_width = m_imgui->scaled(4.f); const float minimal_slider_width = m_imgui->scaled(4.f);
const float tool_type_radio_left = m_imgui->calc_text_size(m_desc["tool_type"]).x + m_imgui->scaled(1.f);
const float tool_type_radio_brush = m_imgui->calc_text_size(m_desc["tool_brush"]).x + m_imgui->scaled(2.5f);
const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f);
float caption_max = 0.f; float caption_max = 0.f;
float total_text_max = 0.f; float total_text_max = 0.f;
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) { for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) {
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
} }
caption_max += m_imgui->scaled(1.f); total_text_max += caption_max + m_imgui->scaled(1.f);
total_text_max += m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f);
float window_width = minimal_slider_width + std::max(autoset_slider_left, std::max(cursor_slider_left, clipping_slider_left)); float sliders_width = std::max(std::max(autoset_slider_left, smart_fill_slider_left), std::max(cursor_slider_left, clipping_slider_left));
float window_width = minimal_slider_width + sliders_width;
window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_width); window_width = std::max(window_width, button_width);
window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); window_width = std::max(window_width, cursor_type_radio_circle + cursor_type_radio_sphere + cursor_type_radio_pointer);
window_width = std::max(window_width, tool_type_radio_left + tool_type_radio_brush + tool_type_radio_smart_fill);
window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f)); window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f));
auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
@ -129,7 +142,6 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"})
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
m_imgui->text("");
ImGui::Separator(); ImGui::Separator();
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -138,9 +150,9 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
std::string format_str = std::string("%.f") + I18N::translate_utf8("°", std::string format_str = std::string("%.f") + I18N::translate_utf8("°",
"Degree sign to use in the respective slider in FDM supports gizmo," "Degree sign to use in the respective slider in FDM supports gizmo,"
"placed after the number with no whitespace in between."); "placed after the number with no whitespace in between.");
ImGui::SameLine(autoset_slider_left); ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - autoset_slider_left); ImGui::PushItemWidth(window_width - sliders_width);
if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) { if (m_imgui->slider_float("##angle_threshold_deg", &m_angle_threshold_deg, 0.f, 90.f, format_str.data())) {
m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg); m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg);
if (! m_parent.is_using_slope()) { if (! m_parent.is_using_slope()) {
m_parent.use_slope(true); m_parent.use_slope(true);
@ -163,79 +175,136 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
} }
m_imgui->disabled_end(); m_imgui->disabled_end();
ImGui::Separator();
if (m_imgui->button(m_desc.at("remove_all"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"),
UndoRedo::SnapshotType::GizmoAction);
ModelObject* mo = m_c->selection_info()->model_object();
int idx = -1;
for (ModelVolume* mv : mo->volumes) {
if (mv->is_model_part()) {
++idx;
m_triangle_selectors[idx]->reset();
m_triangle_selectors[idx]->request_update_render_data();
}
}
update_model_object();
m_parent.set_as_dirty();
}
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
ImGui::AlignTextToFramePadding(); ImGui::Separator();
m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(cursor_slider_left);
ImGui::PushItemWidth(window_width - cursor_slider_left);
m_imgui->slider_float(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_type")); m_imgui->text(m_desc["tool_type"]);
ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f));
ImGui::PushItemWidth(cursor_type_radio_width1);
bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; float tool_type_offset = tool_type_radio_left + (window_width - tool_type_radio_left - tool_type_radio_brush - tool_type_radio_smart_fill + m_imgui->scaled(0.5f)) / 2.f;
if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) ImGui::SameLine(tool_type_offset);
sphere_sel = true; ImGui::PushItemWidth(tool_type_radio_brush);
if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == ToolType::BRUSH))
m_tool_type = ToolType::BRUSH;
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width); ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data()); ImGui::TextUnformatted(_L("Paints facets according to the chosen painting brush.").ToUTF8().data());
ImGui::PopTextWrapPos(); ImGui::PopTextWrapPos();
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); ImGui::SameLine(tool_type_offset + tool_type_radio_brush);
ImGui::PushItemWidth(cursor_type_radio_width2); ImGui::PushItemWidth(tool_type_radio_smart_fill);
if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == ToolType::SMART_FILL))
if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) m_tool_type = ToolType::SMART_FILL;
sphere_sel = false;
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width); ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data()); ImGui::TextUnformatted(_L("Paints neighboring facets whose relative angle is less or equal to set angle.").ToUTF8().data());
ImGui::PopTextWrapPos(); ImGui::PopTextWrapPos();
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
m_cursor_type = sphere_sel ImGui::Separator();
? TriangleSelector::CursorType::SPHERE
: TriangleSelector::CursorType::CIRCLE;
if (m_tool_type == ToolType::BRUSH) {
m_imgui->text(m_desc.at("cursor_type"));
ImGui::NewLine();
float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(1.5f)) / 2.f;
ImGui::SameLine(cursor_type_offset);
ImGui::PushItemWidth(cursor_type_radio_sphere);
if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE))
m_cursor_type = TriangleSelector::CursorType::SPHERE;
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Paints all facets inside, regardless of their orientation.").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere);
ImGui::PushItemWidth(cursor_type_radio_circle);
if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE))
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Ignores facets facing away from the camera.").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle);
ImGui::PushItemWidth(cursor_type_radio_pointer);
if (m_imgui->radio_button(m_desc["pointer"], m_cursor_type == TriangleSelector::CursorType::POINTER))
m_cursor_type = TriangleSelector::CursorType::POINTER;
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Paints only one facet.").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
m_imgui->disabled_begin(m_cursor_type != TriangleSelector::CursorType::SPHERE && m_cursor_type != TriangleSelector::CursorType::CIRCLE);
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
m_imgui->checkbox(_L("Split triangles"), m_triangle_splitting_enabled);
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Split bigger facets into smaller ones while the object is painted.").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
m_imgui->disabled_end();
} else {
assert(m_tool_type == ToolType::SMART_FILL);
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc["smart_fill_angle"] + ":");
std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in MMU gizmo,"
"placed after the number with no whitespace in between.");
ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width);
if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data()))
for (auto &triangle_selector : m_triangle_selectors) {
triangle_selector->seed_fill_unselect_all_triangles();
triangle_selector->request_update_render_data();
}
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width);
ImGui::TextUnformatted(_L("Alt + Mouse wheel").ToUTF8().data());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
ImGui::Separator(); ImGui::Separator();
if (m_c->object_clipper()->get_position() == 0.f) { if (m_c->object_clipper()->get_position() == 0.f) {
@ -250,10 +319,10 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
} }
} }
ImGui::SameLine(clipping_slider_left); ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - clipping_slider_left); ImGui::PushItemWidth(window_width - sliders_width);
auto clp_dist = float(m_c->object_clipper()->get_position()); auto clp_dist = float(m_c->object_clipper()->get_position());
if (m_imgui->slider_float(" ", &clp_dist, 0.f, 1.f, "%.2f")) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
@ -263,6 +332,23 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::PopTextWrapPos(); ImGui::PopTextWrapPos();
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::Separator();
if (m_imgui->button(m_desc.at("remove_all"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), UndoRedo::SnapshotType::GizmoAction);
ModelObject *mo = m_c->selection_info()->model_object();
int idx = -1;
for (ModelVolume *mv : mo->volumes)
if (mv->is_model_part()) {
++idx;
m_triangle_selectors[idx]->reset();
m_triangle_selectors[idx]->request_update_render_data();
}
update_model_object();
m_parent.set_as_dirty();
}
m_imgui->end(); m_imgui->end();
} }
@ -291,7 +377,7 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
// Now calculate dot product of vert_direction and facets' normals. // Now calculate dot product of vert_direction and facets' normals.
int idx = 0; int idx = 0;
const indexed_triangle_set &its = mv->mesh().its; const indexed_triangle_set &its = mv->mesh().its;
for (stl_triangle_vertex_indices face : its.indices) { for (const stl_triangle_vertex_indices &face : its.indices) {
if (its_face_normal(its, face).dot(down) > dot_limit) { if (its_face_normal(its, face).dot(down) > dot_limit) {
m_triangle_selectors[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER); m_triangle_selectors[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER);
m_triangle_selectors.back()->request_update_render_data(); m_triangle_selectors.back()->request_update_render_data();

View File

@ -42,7 +42,6 @@ void GLGizmoMmuSegmentation::on_shutdown()
std::string GLGizmoMmuSegmentation::on_get_name() const std::string GLGizmoMmuSegmentation::on_get_name() const
{ {
// FIXME Lukas H.: Discuss and change shortcut
return _u8L("Multimaterial painting"); return _u8L("Multimaterial painting");
} }
@ -107,7 +106,6 @@ void GLGizmoMmuSegmentation::init_extruders_data()
bool GLGizmoMmuSegmentation::on_init() bool GLGizmoMmuSegmentation::on_init()
{ {
// FIXME Lukas H.: Discuss and change shortcut
m_shortcut_key = WXK_CONTROL_N; m_shortcut_key = WXK_CONTROL_N;
m_desc["reset_direction"] = _L("Reset direction"); m_desc["reset_direction"] = _L("Reset direction");
@ -123,7 +121,7 @@ bool GLGizmoMmuSegmentation::on_init()
m_desc["remove_all"] = _L("Remove all painted areas"); m_desc["remove_all"] = _L("Remove all painted areas");
m_desc["circle"] = _L("Circle"); m_desc["circle"] = _L("Circle");
m_desc["sphere"] = _L("Sphere"); m_desc["sphere"] = _L("Sphere");
m_desc["pointer"] = _L("Pointer"); m_desc["pointer"] = _L("Triangles");
m_desc["tool_type"] = _L("Tool type"); m_desc["tool_type"] = _L("Tool type");
m_desc["tool_brush"] = _L("Brush"); m_desc["tool_brush"] = _L("Brush");
@ -236,7 +234,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
if (!m_c->selection_info()->model_object()) if (!m_c->selection_info()->model_object())
return; return;
const float approx_height = m_imgui->scaled(25.0f); const float approx_height = m_imgui->scaled(22.0f);
y = std::min(y, bottom_limit - approx_height); y = std::min(y, bottom_limit - approx_height);
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
@ -264,13 +262,13 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f); const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f);
float caption_max = 0.f; float caption_max = 0.f;
float total_text_max = 0.; float total_text_max = 0.f;
for (const auto &t : std::array<std::string, 3>{"first_color", "second_color", "remove"}) { for (const auto &t : std::array<std::string, 3>{"first_color", "second_color", "remove"}) {
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
} }
caption_max += m_imgui->scaled(1.f); total_text_max += caption_max + m_imgui->scaled(1.f);
total_text_max += m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f);
float sliders_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left)); float sliders_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left));
float window_width = minimal_slider_width + sliders_width; float window_width = minimal_slider_width + sliders_width;
@ -289,7 +287,6 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
for (const auto &t : std::array<std::string, 3>{"first_color", "second_color", "remove"}) for (const auto &t : std::array<std::string, 3>{"first_color", "second_color", "remove"})
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
m_imgui->text("");
ImGui::Separator(); ImGui::Separator();
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -321,15 +318,13 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::Separator(); ImGui::Separator();
m_imgui->text(m_desc.at("tool_type")); m_imgui->text(m_desc.at("tool_type"));
float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_smart_fill + m_imgui->scaled(2.f)) / 2.f;
ImGui::NewLine(); ImGui::NewLine();
ImGui::SameLine(tool_type_offset + m_imgui->scaled(0.f)); float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_smart_fill + m_imgui->scaled(1.5f)) / 2.f;
ImGui::SameLine(tool_type_offset);
ImGui::PushItemWidth(tool_type_radio_brush); ImGui::PushItemWidth(tool_type_radio_brush);
if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == GLGizmoMmuSegmentation::ToolType::BRUSH)) { if (m_imgui->radio_button(m_desc["tool_brush"], m_tool_type == ToolType::BRUSH)) {
m_tool_type = GLGizmoMmuSegmentation::ToolType::BRUSH; m_tool_type = ToolType::BRUSH;
for (auto &triangle_selector : m_triangle_selectors) { for (auto &triangle_selector : m_triangle_selectors) {
triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->seed_fill_unselect_all_triangles();
triangle_selector->request_update_render_data(); triangle_selector->request_update_render_data();
@ -344,10 +339,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(tool_type_offset + tool_type_radio_brush + m_imgui->scaled(0.f)); ImGui::SameLine(tool_type_offset + tool_type_radio_brush);
ImGui::PushItemWidth(tool_type_radio_smart_fill); ImGui::PushItemWidth(tool_type_radio_smart_fill);
if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::SMART_FILL)) { if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == ToolType::SMART_FILL)) {
m_tool_type = GLGizmoMmuSegmentation::ToolType::SMART_FILL; m_tool_type = ToolType::SMART_FILL;
for (auto &triangle_selector : m_triangle_selectors) { for (auto &triangle_selector : m_triangle_selectors) {
triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->seed_fill_unselect_all_triangles();
triangle_selector->request_update_render_data(); triangle_selector->request_update_render_data();
@ -362,10 +357,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(tool_type_offset + tool_type_radio_brush + tool_type_radio_smart_fill + m_imgui->scaled(0.f)); ImGui::SameLine(tool_type_offset + tool_type_radio_brush + tool_type_radio_smart_fill);
ImGui::PushItemWidth(tool_type_radio_bucket_fill); ImGui::PushItemWidth(tool_type_radio_bucket_fill);
if (m_imgui->radio_button(m_desc["tool_bucket_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::BUCKET_FILL)) { if (m_imgui->radio_button(m_desc["tool_bucket_fill"], m_tool_type == ToolType::BUCKET_FILL)) {
m_tool_type = GLGizmoMmuSegmentation::ToolType::BUCKET_FILL; m_tool_type = ToolType::BUCKET_FILL;
for (auto &triangle_selector : m_triangle_selectors) { for (auto &triangle_selector : m_triangle_selectors) {
triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->seed_fill_unselect_all_triangles();
triangle_selector->request_update_render_data(); triangle_selector->request_update_render_data();
@ -386,8 +381,8 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
m_imgui->text(m_desc.at("cursor_type")); m_imgui->text(m_desc.at("cursor_type"));
ImGui::NewLine(); ImGui::NewLine();
float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(2.f)) / 2.f; float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(1.5f)) / 2.f;
ImGui::SameLine(cursor_type_offset + m_imgui->scaled(0.f)); ImGui::SameLine(cursor_type_offset);
ImGui::PushItemWidth(cursor_type_radio_sphere); ImGui::PushItemWidth(cursor_type_radio_sphere);
if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE)) if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE))
m_cursor_type = TriangleSelector::CursorType::SPHERE; m_cursor_type = TriangleSelector::CursorType::SPHERE;
@ -400,7 +395,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(cursor_type_offset +cursor_type_radio_sphere + m_imgui->scaled(0.f)); ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere);
ImGui::PushItemWidth(cursor_type_radio_circle); ImGui::PushItemWidth(cursor_type_radio_circle);
if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE)) if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE))
@ -414,7 +409,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle + m_imgui->scaled(0.f)); ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle);
ImGui::PushItemWidth(cursor_type_radio_pointer); ImGui::PushItemWidth(cursor_type_radio_pointer);
if (m_imgui->radio_button(m_desc["pointer"], m_cursor_type == TriangleSelector::CursorType::POINTER)) if (m_imgui->radio_button(m_desc["pointer"], m_cursor_type == TriangleSelector::CursorType::POINTER))
@ -434,7 +429,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
m_imgui->text(m_desc.at("cursor_size")); m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(sliders_width); ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width); ImGui::PushItemWidth(window_width - sliders_width);
m_imgui->slider_float(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width); ImGui::PushTextWrapPos(max_tooltip_width);
@ -492,8 +487,9 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::SameLine(sliders_width); ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - sliders_width); ImGui::PushItemWidth(window_width - sliders_width);
auto clp_dist = float(m_c->object_clipper()->get_position()); auto clp_dist = float(m_c->object_clipper()->get_position());
if (m_imgui->slider_float(" ", &clp_dist, 0.f, 1.f, "%.2f")) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width); ImGui::PushTextWrapPos(max_tooltip_width);
@ -596,11 +592,6 @@ std::array<float, 4> GLGizmoMmuSegmentation::get_cursor_sphere_right_button_colo
return {color[0], color[1], color[2], 0.25f}; return {color[0], color[1], color[2], 0.25f};
} }
static std::array<float, 4> get_seed_fill_color(const std::array<float, 4> &base_color)
{
return {base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f};
}
void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
{ {
if (m_update_render_data) if (m_update_render_data)
@ -616,14 +607,14 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx) for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx)
if (m_gizmo_scene.has_VBOs(color_idx)) { if (m_gizmo_scene.has_VBOs(color_idx)) {
if (color_idx > m_colors.size()) // Seed fill VBO if (color_idx > m_colors.size()) // Seed fill VBO
shader->set_uniform("uniform_color", get_seed_fill_color(color_idx == (m_colors.size() + 1) ? m_default_volume_color : m_colors[color_idx - (m_colors.size() + 1) - 1])); shader->set_uniform("uniform_color", TriangleSelectorGUI::get_seed_fill_color(color_idx == (m_colors.size() + 1) ? m_default_volume_color : m_colors[color_idx - (m_colors.size() + 1) - 1]));
else // Normal VBO else // Normal VBO
shader->set_uniform("uniform_color", color_idx == 0 ? m_default_volume_color : m_colors[color_idx - 1]); shader->set_uniform("uniform_color", color_idx == 0 ? m_default_volume_color : m_colors[color_idx - 1]);
m_gizmo_scene.render(color_idx); m_gizmo_scene.render(color_idx);
} }
if (m_gizmo_scene.has_contour_VBO()) { if (m_paint_contour.has_VBO()) {
ScopeGuard guard_gouraud([shader]() { shader->start_using(); }); ScopeGuard guard_gouraud([shader]() { shader->start_using(); });
shader->stop_using(); shader->stop_using();
@ -631,7 +622,7 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
contour_shader->start_using(); contour_shader->start_using();
glsafe(::glDepthFunc(GL_LEQUAL)); glsafe(::glDepthFunc(GL_LEQUAL));
m_gizmo_scene.render_contour(); m_paint_contour.render();
glsafe(::glDepthFunc(GL_LESS)); glsafe(::glDepthFunc(GL_LESS));
contour_shader->stop_using(); contour_shader->stop_using();
@ -670,23 +661,24 @@ void TriangleSelectorMmGui::update_render_data()
m_gizmo_scene.finalize_triangle_indices(); m_gizmo_scene.finalize_triangle_indices();
m_paint_contour.release_geometry();
std::vector<Vec2i> contour_edges = this->get_seed_fill_contour(); std::vector<Vec2i> contour_edges = this->get_seed_fill_contour();
m_gizmo_scene.contour_vertices.reserve(contour_edges.size() * 6); m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6);
for (const Vec2i &edge : contour_edges) { for (const Vec2i &edge : contour_edges) {
m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(0)].v.x()); m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.x());
m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(0)].v.y()); m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.y());
m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(0)].v.z()); m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.z());
m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(1)].v.x()); m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.x());
m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(1)].v.y()); m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.y());
m_gizmo_scene.contour_vertices.emplace_back(m_vertices[edge(1)].v.z()); m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.z());
} }
m_gizmo_scene.contour_indices.assign(m_gizmo_scene.contour_vertices.size() / 3, 0); m_paint_contour.contour_indices.assign(m_paint_contour.contour_vertices.size() / 3, 0);
std::iota(m_gizmo_scene.contour_indices.begin(), m_gizmo_scene.contour_indices.end(), 0); std::iota(m_paint_contour.contour_indices.begin(), m_paint_contour.contour_indices.end(), 0);
m_gizmo_scene.contour_indices_size = m_gizmo_scene.contour_indices.size(); m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size();
m_gizmo_scene.finalize_contour(); m_paint_contour.finalize_geometry();
} }
wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const
@ -710,14 +702,6 @@ void GLMmSegmentationGizmo3DScene::release_geometry() {
glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id));
triangle_indices_VBO_id = 0; triangle_indices_VBO_id = 0;
} }
if (this->contour_vertices_VBO_id) {
glsafe(::glDeleteBuffers(1, &this->contour_vertices_VBO_id));
this->contour_vertices_VBO_id = 0;
}
if (this->contour_indices_VBO_id) {
glsafe(::glDeleteBuffers(1, &this->contour_indices_VBO_id));
this->contour_indices_VBO_id = 0;
}
this->clear(); this->clear();
} }
@ -745,29 +729,6 @@ void GLMmSegmentationGizmo3DScene::render(size_t triangle_indices_idx) const
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
} }
void GLMmSegmentationGizmo3DScene::render_contour() const
{
assert(this->contour_vertices_VBO_id != 0);
assert(this->contour_indices_VBO_id != 0);
glsafe(::glLineWidth(4.0f));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->contour_vertices_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
if (this->contour_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->contour_indices_VBO_id));
glsafe(::glDrawElements(GL_LINES, GLsizei(this->contour_indices_size), GL_UNSIGNED_INT, nullptr));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
void GLMmSegmentationGizmo3DScene::finalize_vertices() void GLMmSegmentationGizmo3DScene::finalize_vertices()
{ {
assert(this->vertices_VBO_id == 0); assert(this->vertices_VBO_id == 0);
@ -795,26 +756,4 @@ void GLMmSegmentationGizmo3DScene::finalize_triangle_indices()
} }
} }
void GLMmSegmentationGizmo3DScene::finalize_contour()
{
assert(this->contour_vertices_VBO_id == 0);
assert(this->contour_indices_VBO_id == 0);
if (!this->contour_vertices.empty()) {
glsafe(::glGenBuffers(1, &this->contour_vertices_VBO_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->contour_vertices_VBO_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_vertices.size() * sizeof(float), this->contour_vertices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
this->contour_vertices.clear();
}
if (!this->contour_indices.empty()) {
glsafe(::glGenBuffers(1, &this->contour_indices_VBO_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->contour_indices_VBO_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_indices.size() * sizeof(unsigned int), this->contour_indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
this->contour_indices.clear();
}
}
} // namespace Slic3r } // namespace Slic3r

View File

@ -25,8 +25,6 @@ public:
return this->triangle_indices_VBO_ids[triangle_indices_idx] != 0; return this->triangle_indices_VBO_ids[triangle_indices_idx] != 0;
} }
[[nodiscard]] inline bool has_contour_VBO() const { return this->contour_indices_VBO_id != 0; }
// Release the geometry data, release OpenGL VBOs. // Release the geometry data, release OpenGL VBOs.
void release_geometry(); void release_geometry();
// Finalize the initialization of the geometry, upload the geometry to OpenGL VBO objects // Finalize the initialization of the geometry, upload the geometry to OpenGL VBO objects
@ -35,9 +33,6 @@ public:
// Finalize the initialization of the indices, upload the indices to OpenGL VBO objects // Finalize the initialization of the indices, upload the indices to OpenGL VBO objects
// and possibly releasing it if it has been loaded into the VBOs. // and possibly releasing it if it has been loaded into the VBOs.
void finalize_triangle_indices(); void finalize_triangle_indices();
// Finalize the initialization of the contour geometry and the indices, upload both to OpenGL VBO objects
// and possibly releasing it if it has been loaded into the VBOs.
void finalize_contour();
void clear() void clear()
{ {
@ -47,34 +42,21 @@ public:
for (size_t &triangle_indices_size : this->triangle_indices_sizes) for (size_t &triangle_indices_size : this->triangle_indices_sizes)
triangle_indices_size = 0; triangle_indices_size = 0;
this->contour_vertices.clear();
this->contour_indices.clear();
this->contour_indices_size = 0;
} }
void render(size_t triangle_indices_idx) const; void render(size_t triangle_indices_idx) const;
void render_contour() const;
std::vector<float> vertices; std::vector<float> vertices;
std::vector<std::vector<int>> triangle_indices; std::vector<std::vector<int>> triangle_indices;
std::vector<float> contour_vertices;
std::vector<int> contour_indices;
// When the triangle indices are loaded into the graphics card as Vertex Buffer Objects, // When the triangle indices are loaded into the graphics card as Vertex Buffer Objects,
// the above mentioned std::vectors are cleared and the following variables keep their original length. // the above mentioned std::vectors are cleared and the following variables keep their original length.
std::vector<size_t> triangle_indices_sizes; std::vector<size_t> triangle_indices_sizes;
size_t contour_indices_size{0};
// IDs of the Vertex Array Objects, into which the geometry has been loaded. // IDs of the Vertex Array Objects, into which the geometry has been loaded.
// Zero if the VBOs are not sent to GPU yet. // Zero if the VBOs are not sent to GPU yet.
unsigned int vertices_VBO_id{0}; unsigned int vertices_VBO_id{0};
std::vector<unsigned int> triangle_indices_VBO_ids; std::vector<unsigned int> triangle_indices_VBO_ids;
unsigned int contour_vertices_VBO_id{0};
unsigned int contour_indices_VBO_id{0};
}; };
class TriangleSelectorMmGui : public TriangleSelectorGUI { class TriangleSelectorMmGui : public TriangleSelectorGUI {

View File

@ -541,7 +541,10 @@ void GLGizmoPainterBase::on_load(cereal::BinaryInputArchive&)
m_schedule_update = true; m_schedule_update = true;
} }
std::array<float, 4> TriangleSelectorGUI::get_seed_fill_color(const std::array<float, 4> &base_color)
{
return {base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f};
}
void TriangleSelectorGUI::render(ImGuiWrapper* imgui) void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
{ {
@ -566,6 +569,29 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
} }
} }
for (auto &iva : m_iva_seed_fills)
if (iva.has_VBOs()) {
size_t color_idx = &iva - &m_iva_seed_fills.front();
const std::array<float, 4> &color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color :
color_idx == 2 ? blockers_color :
GLVolume::NEUTRAL_COLOR);
shader->set_uniform("uniform_color", color);
iva.render();
}
if (m_paint_contour.has_VBO()) {
ScopeGuard guard_gouraud([shader]() { shader->start_using(); });
shader->stop_using();
auto *contour_shader = wxGetApp().get_shader("mm_contour");
contour_shader->start_using();
glsafe(::glDepthFunc(GL_GEQUAL));
m_paint_contour.render();
glsafe(::glDepthFunc(GL_LESS));
contour_shader->stop_using();
}
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
if (imgui) if (imgui)
@ -575,22 +601,29 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
#endif #endif
} }
void TriangleSelectorGUI::update_render_data() void TriangleSelectorGUI::update_render_data()
{ {
int enf_cnt = 0; int enf_cnt = 0;
int blc_cnt = 0; int blc_cnt = 0;
std::vector<int> seed_fill_cnt(m_iva_seed_fills.size(), 0);
for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) for (auto *iva : {&m_iva_enforcers, &m_iva_blockers})
iva->release_geometry(); iva->release_geometry();
for (auto &iva : m_iva_seed_fills)
iva.release_geometry();
for (const Triangle &tr : m_triangles) { for (const Triangle &tr : m_triangles) {
if (!tr.valid() || tr.is_split() || tr.get_state() == EnforcerBlockerType::NONE) if (!tr.valid() || tr.is_split() || (tr.get_state() == EnforcerBlockerType::NONE && !tr.is_selected_by_seed_fill()))
continue; continue;
GLIndexedVertexArray &iva = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers; int tr_state = int(tr.get_state());
int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; GLIndexedVertexArray &iva = tr.is_selected_by_seed_fill() ? m_iva_seed_fills[tr_state] :
tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers :
m_iva_blockers;
int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] :
tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt :
blc_cnt;
const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v; const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v;
const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v; const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v;
const Vec3f &v2 = m_vertices[tr.verts_idxs[2]].v; const Vec3f &v2 = m_vertices[tr.verts_idxs[2]].v;
@ -606,9 +639,87 @@ void TriangleSelectorGUI::update_render_data()
for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) for (auto *iva : {&m_iva_enforcers, &m_iva_blockers})
iva->finalize_geometry(true); iva->finalize_geometry(true);
for (auto &iva : m_iva_seed_fills)
iva.finalize_geometry(true);
m_paint_contour.release_geometry();
std::vector<Vec2i> contour_edges = this->get_seed_fill_contour();
m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6);
for (const Vec2i &edge : contour_edges) {
m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.x());
m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.y());
m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.z());
m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.x());
m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.y());
m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.z());
}
m_paint_contour.contour_indices.assign(m_paint_contour.contour_vertices.size() / 3, 0);
std::iota(m_paint_contour.contour_indices.begin(), m_paint_contour.contour_indices.end(), 0);
m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size();
m_paint_contour.finalize_geometry();
} }
void GLPaintContour::render() const
{
assert(this->m_contour_VBO_id != 0);
assert(this->m_contour_EBO_id != 0);
glsafe(::glLineWidth(4.0f));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
if (this->contour_indices_size > 0) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->m_contour_EBO_id));
glsafe(::glDrawElements(GL_LINES, GLsizei(this->contour_indices_size), GL_UNSIGNED_INT, nullptr));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
void GLPaintContour::finalize_geometry()
{
assert(this->m_contour_VBO_id == 0);
assert(this->m_contour_EBO_id == 0);
if (!this->contour_vertices.empty()) {
glsafe(::glGenBuffers(1, &this->m_contour_VBO_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_vertices.size() * sizeof(float), this->contour_vertices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
this->contour_vertices.clear();
}
if (!this->contour_indices.empty()) {
glsafe(::glGenBuffers(1, &this->m_contour_EBO_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_EBO_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_indices.size() * sizeof(unsigned int), this->contour_indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
this->contour_indices.clear();
}
}
void GLPaintContour::release_geometry()
{
if (this->m_contour_VBO_id) {
glsafe(::glDeleteBuffers(1, &this->m_contour_VBO_id));
this->m_contour_VBO_id = 0;
}
if (this->m_contour_EBO_id) {
glsafe(::glDeleteBuffers(1, &this->m_contour_EBO_id));
this->m_contour_EBO_id = 0;
}
this->clear();
}
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)

View File

@ -10,6 +10,7 @@
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include <cereal/types/vector.hpp> #include <cereal/types/vector.hpp>
#include <GL/glew.h>
@ -26,6 +27,41 @@ enum class PainterGizmoType {
MMU_SEGMENTATION MMU_SEGMENTATION
}; };
class GLPaintContour
{
public:
GLPaintContour() = default;
void render() const;
inline bool has_VBO() const { return this->m_contour_EBO_id != 0; }
// Release the geometry data, release OpenGL VBOs.
void release_geometry();
// Finalize the initialization of the contour geometry and the indices, upload both to OpenGL VBO objects
// and possibly releasing it if it has been loaded into the VBOs.
void finalize_geometry();
void clear()
{
this->contour_vertices.clear();
this->contour_indices.clear();
this->contour_indices_size = 0;
}
std::vector<float> contour_vertices;
std::vector<int> contour_indices;
// When the triangle indices are loaded into the graphics card as Vertex Buffer Objects,
// the above mentioned std::vectors are cleared and the following variables keep their original length.
size_t contour_indices_size{0};
// IDs of the Vertex Array Objects, into which the geometry has been loaded.
// Zero if the VBOs are not sent to GPU yet.
GLuint m_contour_VBO_id{0};
GLuint m_contour_EBO_id{0};
};
class TriangleSelectorGUI : public TriangleSelector { class TriangleSelectorGUI : public TriangleSelector {
public: public:
@ -49,12 +85,18 @@ public:
protected: protected:
bool m_update_render_data = false; bool m_update_render_data = false;
static std::array<float, 4> get_seed_fill_color(const std::array<float, 4> &base_color);
private: private:
void update_render_data(); void update_render_data();
GLIndexedVertexArray m_iva_enforcers; GLIndexedVertexArray m_iva_enforcers;
GLIndexedVertexArray m_iva_blockers; GLIndexedVertexArray m_iva_blockers;
std::array<GLIndexedVertexArray, 3> m_iva_seed_fills;
std::array<GLIndexedVertexArray, 3> m_varrays; std::array<GLIndexedVertexArray, 3> m_varrays;
protected:
GLPaintContour m_paint_contour;
}; };
class GLGizmoTransparentRender class GLGizmoTransparentRender

View File

@ -77,7 +77,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
if (! m_c->selection_info()->model_object()) if (! m_c->selection_info()->model_object())
return; return;
const float approx_height = m_imgui->scaled(14.0f); const float approx_height = m_imgui->scaled(12.5f);
y = std::min(y, bottom_limit - approx_height); y = std::min(y, bottom_limit - approx_height);
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
@ -87,27 +87,28 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
m_imgui->calc_text_size(m_desc.at("reset_direction")).x) m_imgui->calc_text_size(m_desc.at("reset_direction")).x)
+ m_imgui->scaled(1.5f); + m_imgui->scaled(1.5f);
const float cursor_size_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); const float cursor_size_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc.at("cursor_type")).x + m_imgui->scaled(1.f);
const float cursor_type_radio_width1 = m_imgui->calc_text_size(m_desc["circle"]).x const float cursor_type_radio_left = m_imgui->calc_text_size(m_desc["cursor_type"]).x + m_imgui->scaled(1.f);
+ m_imgui->scaled(2.5f); const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f);
const float cursor_type_radio_width2 = m_imgui->calc_text_size(m_desc["sphere"]).x const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f);
+ m_imgui->scaled(2.5f);
const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
const float minimal_slider_width = m_imgui->scaled(4.f); const float minimal_slider_width = m_imgui->scaled(4.f);
float caption_max = 0.f; float caption_max = 0.f;
float total_text_max = 0.f; float total_text_max = 0.f;
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) { for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) {
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
} }
caption_max += m_imgui->scaled(1.f); total_text_max += caption_max + m_imgui->scaled(1.f);
total_text_max += m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f);
float window_width = minimal_slider_width + std::max(cursor_size_slider_left, clipping_slider_left); float sliders_width = std::max(cursor_size_slider_left, clipping_slider_left);
float window_width = minimal_slider_width + sliders_width;
window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, total_text_max);
window_width = std::max(window_width, button_width); window_width = std::max(window_width, button_width);
window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_width1 + cursor_type_radio_width2); window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_sphere + cursor_type_radio_circle);
auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) { auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f); static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
@ -119,32 +120,15 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"})
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
m_imgui->text(""); ImGui::Separator();
if (m_imgui->button(m_desc.at("remove_all"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"),
UndoRedo::SnapshotType::GizmoAction);
ModelObject* mo = m_c->selection_info()->model_object();
int idx = -1;
for (ModelVolume* mv : mo->volumes) {
if (mv->is_model_part()) {
++idx;
m_triangle_selectors[idx]->reset();
m_triangle_selectors[idx]->request_update_render_data();
}
}
update_model_object();
m_parent.set_as_dirty();
}
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_size")); m_imgui->text(m_desc.at("cursor_size"));
ImGui::SameLine(cursor_size_slider_left); ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - cursor_size_slider_left); ImGui::PushItemWidth(window_width - sliders_width);
m_imgui->slider_float(" ", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f"); m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::PushTextWrapPos(max_tooltip_width); ImGui::PushTextWrapPos(max_tooltip_width);
@ -155,12 +139,12 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_type")); m_imgui->text(m_desc.at("cursor_type"));
ImGui::SameLine(cursor_type_radio_left + m_imgui->scaled(0.f));
ImGui::PushItemWidth(cursor_type_radio_width1);
bool sphere_sel = m_cursor_type == TriangleSelector::CursorType::SPHERE; float cursor_type_offset = cursor_type_radio_left + (window_width - cursor_type_radio_left - cursor_type_radio_sphere - cursor_type_radio_circle + m_imgui->scaled(0.5f)) / 2.f;
if (m_imgui->radio_button(m_desc["sphere"], sphere_sel)) ImGui::SameLine(cursor_type_offset);
sphere_sel = true; ImGui::PushItemWidth(cursor_type_radio_sphere);
if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE))
m_cursor_type = TriangleSelector::CursorType::SPHERE;
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
@ -170,11 +154,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::SameLine(cursor_type_radio_left + cursor_type_radio_width2 + m_imgui->scaled(0.f)); ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere);
ImGui::PushItemWidth(cursor_type_radio_width2); ImGui::PushItemWidth(cursor_type_radio_circle);
if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE))
if (m_imgui->radio_button(m_desc["circle"], ! sphere_sel)) m_cursor_type = TriangleSelector::CursorType::CIRCLE;
sphere_sel = false;
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
@ -184,12 +167,6 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
m_cursor_type = sphere_sel
? TriangleSelector::CursorType::SPHERE
: TriangleSelector::CursorType::CIRCLE;
ImGui::Separator(); ImGui::Separator();
if (m_c->object_clipper()->get_position() == 0.f) { if (m_c->object_clipper()->get_position() == 0.f) {
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -203,10 +180,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
} }
} }
ImGui::SameLine(clipping_slider_left); ImGui::SameLine(sliders_width);
ImGui::PushItemWidth(window_width - clipping_slider_left); ImGui::PushItemWidth(window_width - sliders_width);
auto clp_dist = float(m_c->object_clipper()->get_position()); auto clp_dist = float(m_c->object_clipper()->get_position());
if (m_imgui->slider_float(" ", &clp_dist, 0.f, 1.f, "%.2f")) if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true); m_c->object_clipper()->set_position(clp_dist, true);
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
@ -217,6 +194,22 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ImGui::Separator();
if (m_imgui->button(m_desc.at("remove_all"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), UndoRedo::SnapshotType::GizmoAction);
ModelObject *mo = m_c->selection_info()->model_object();
int idx = -1;
for (ModelVolume *mv : mo->volumes)
if (mv->is_model_part()) {
++idx;
m_triangle_selectors[idx]->reset();
m_triangle_selectors[idx]->request_update_render_data();
}
update_model_object();
m_parent.set_as_dirty();
}
m_imgui->end(); m_imgui->end();
} }

View File

@ -548,7 +548,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
// mouse anywhere // mouse anywhere
if (evt.Moving()) { if (evt.Moving()) {
m_tooltip = update_hover_state(mouse_pos); m_tooltip = update_hover_state(mouse_pos);
if (m_current == MmuSegmentation) if (m_current == MmuSegmentation || m_current == FdmSupports)
gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown()); gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown());
} else if (evt.LeftUp()) { } else if (evt.LeftUp()) {
if (m_mouse_capture.left) { if (m_mouse_capture.left) {

View File

@ -270,7 +270,7 @@ wxPanel* KBShortcutsDialog::create_header(wxWindow* parent, const wxFont& bold_f
sizer->AddStretchSpacer(); sizer->AddStretchSpacer();
// logo // logo
m_logo_bmp = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_32px.png" : "PrusaSlicer-gcodeviewer_32px.png", 32); m_logo_bmp = ScalableBitmap(this, wxGetApp().logo_name(), 32);
m_header_bitmap = new wxStaticBitmap(panel, wxID_ANY, m_logo_bmp.bmp()); m_header_bitmap = new wxStaticBitmap(panel, wxID_ANY, m_logo_bmp.bmp());
sizer->Add(m_header_bitmap, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); sizer->Add(m_header_bitmap, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);

View File

@ -343,6 +343,7 @@ void PreferencesDialog::build(size_t selected_tab)
m_optgroup_gui->append_single_option_line(option); m_optgroup_gui->append_single_option_line(option);
#ifdef _MSW_DARK_MODE #ifdef _MSW_DARK_MODE
}
def.label = L("Use Dark color mode (experimental)"); def.label = L("Use Dark color mode (experimental)");
def.type = coBool; def.type = coBool;
def.tooltip = L("If enabled, UI will use Dark mode colors. " def.tooltip = L("If enabled, UI will use Dark mode colors. "
@ -351,6 +352,7 @@ void PreferencesDialog::build(size_t selected_tab)
option = Option(def, "dark_color_mode"); option = Option(def, "dark_color_mode");
m_optgroup_gui->append_single_option_line(option); m_optgroup_gui->append_single_option_line(option);
if (is_editor) {
def.label = L("Set settings tabs as menu items (experimental)"); def.label = L("Set settings tabs as menu items (experimental)");
def.type = coBool; def.type = coBool;
def.tooltip = L("If enabled, Settings Tabs will be placed as menu items. " def.tooltip = L("If enabled, Settings Tabs will be placed as menu items. "

View File

@ -94,7 +94,7 @@ SysInfoDialog::SysInfoDialog()
main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10); main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10);
// logo // logo
m_logo_bmp = ScalableBitmap(this, wxGetApp().is_editor() ? "PrusaSlicer_192px.png" : "PrusaSlicer-gcodeviewer_192px.png", 192); m_logo_bmp = ScalableBitmap(this, wxGetApp().logo_name(), 192);
m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bmp.bmp()); m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bmp.bmp());
hsizer->Add(m_logo, 0, wxALIGN_CENTER_VERTICAL); hsizer->Add(m_logo, 0, wxALIGN_CENTER_VERTICAL);

View File

@ -421,7 +421,7 @@ bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxPro
} }
}); });
while (! finished) { while (! finished) {
condition.wait_for(lock, std::chrono::milliseconds(500), [&progress]{ return progress.updated; }); condition.wait_for(lock, std::chrono::milliseconds(250), [&progress]{ return progress.updated; });
// decrease progress.percent value to avoid closing of the progress dialog // decrease progress.percent value to avoid closing of the progress dialog
if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message))) if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message)))
canceled = true; canceled = true;