From fd3d673a1ebf72b923f394e5788e1fdefe8a370c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 12:18:46 +0200 Subject: [PATCH 01/66] Tech ENABLE_PREVIEW_LAYER_TIME - Implementation of coloring toolpaths by layer time (Similar to pull request #3904) --- src/libslic3r/Technologies.hpp | 9 +++ src/libslic3r/Utils.hpp | 3 +- src/slic3r/GUI/GCodeViewer.cpp | 103 ++++++++++++++++++++++++++++----- src/slic3r/GUI/GCodeViewer.hpp | 38 ++++++++---- src/slic3r/GUI/GUI_Preview.cpp | 3 + 5 files changed, 127 insertions(+), 29 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6132430f1a..fd7609e770 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,4 +57,13 @@ #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) +//==================== +// 2.4.0.alpha2 techs +//==================== +#define ENABLE_2_4_0_ALPHA2 1 + +// Enable coloring of toolpaths in preview by layer time +#define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_4_0_ALPHA2) + + #endif // _prusaslicer_technologies_h_ diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index a01e63166b..d4f53013f8 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -343,7 +344,7 @@ inline std::string get_time_dhms(float time_in_secs) else if (minutes > 0) ::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs); else - ::sprintf(buffer, "%ds", (int)time_in_secs); + ::sprintf(buffer, "%ds", (int)std::round(time_in_secs)); return buffer; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 656a674066..d909f8ac23 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -730,6 +730,18 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: } } +#if ENABLE_PREVIEW_LAYER_TIME + for (size_t i = 0; i < gcode_result.print_statistics.modes.size(); ++i) { + m_layers_times[i] = gcode_result.print_statistics.modes[i].layers_times; + } + + for (size_t i = 0; i < m_layers_times.size(); ++i) { + for (float time : m_layers_times[i]) { + m_extrusions.ranges.layer_time[i].update_from(time); + } + } +#endif // ENABLE_PREVIEW_LAYER_TIME + #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.refresh_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -771,6 +783,11 @@ void GCodeViewer::reset() m_layers_z_range = { 0, 0 }; m_roles = std::vector(); m_print_statistics.reset(); +#if ENABLE_PREVIEW_LAYER_TIME + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + m_layers_times[i] = std::vector(); + } +#endif // ENABLE_PREVIEW_LAYER_TIME #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER m_custom_gcode_per_print_z = std::vector(); #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER @@ -1965,7 +1982,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) m_layers.append(z, { last_travel_s_id, i }); else - m_layers.get_endpoints().back().last = i; + m_layers.get_ranges().back().last = i; // extruder ids m_extruder_ids.emplace_back(move.extruder_id); // roles @@ -1974,7 +1991,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } else if (move.type == EMoveType::Travel) { if (i - last_travel_s_id > 1 && !m_layers.empty()) - m_layers.get_endpoints().back().last = i; + m_layers.get_ranges().back().last = i; last_travel_s_id = i; } @@ -2082,6 +2099,24 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; } case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; } case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; } +#if ENABLE_PREVIEW_LAYER_TIME + case EViewType::LayerTime: { + const Path::Sub_Path& sub_path = path.sub_paths.front(); + double z = static_cast(sub_path.first.position.z()); + const std::vector& zs = m_layers.get_zs(); + const std::vector& ranges = m_layers.get_ranges(); + size_t time_mode_id = static_cast(m_time_estimate_mode); + for (size_t i = 0; i < zs.size(); ++i) { + if (std::abs(zs[i] - z) < EPSILON) { + if (ranges[i].contains(sub_path.first.s_id)) { + color = m_extrusions.ranges.layer_time[time_mode_id].get_color_at(m_layers_times[time_mode_id][i]); + break; + } + } + } + break; + } +#endif // ENABLE_PREVIEW_LAYER_TIME case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; } case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; } case EViewType::ColorPrint: { @@ -2106,7 +2141,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool auto is_in_layers_range = [this](const Path& path, size_t min_id, size_t max_id) { auto in_layers_range = [this, min_id, max_id](size_t id) { - return m_layers.get_endpoints_at(min_id).first <= id && id <= m_layers.get_endpoints_at(max_id).last; + return m_layers.get_range_at(min_id).first <= id && id <= m_layers.get_range_at(max_id).last; }; return in_layers_range(path.sub_paths.front().first.s_id) || in_layers_range(path.sub_paths.back().last.s_id); @@ -2131,8 +2166,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool path.sub_paths.back().last = buffer.paths[last].sub_paths.back().last; } - const size_t min_s_id = m_layers.get_endpoints_at(min_id).first; - const size_t max_s_id = m_layers.get_endpoints_at(max_id).last; + const size_t min_s_id = m_layers.get_range_at(min_id).first; + const size_t max_s_id = m_layers.get_range_at(max_id).last; return (min_s_id <= path.sub_paths.front().first.s_id && path.sub_paths.front().first.s_id <= max_s_id) || (min_s_id <= path.sub_paths.back().last.s_id && path.sub_paths.back().last.s_id <= max_s_id); @@ -2167,14 +2202,14 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { for (size_t id : buffer.model.instances.s_ids) { - if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) + if (id < m_layers.get_range_at(m_layers_z_range[0]).first || m_layers.get_range_at(m_layers_z_range[1]).last < id) continue; global_endpoints.first = std::min(global_endpoints.first, id); global_endpoints.last = std::max(global_endpoints.last, id); if (top_layer_only) { - if (id < m_layers.get_endpoints_at(m_layers_z_range[1]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) + if (id < m_layers.get_range_at(m_layers_z_range[1]).first || m_layers.get_range_at(m_layers_z_range[1]).last < id) continue; top_layer_endpoints.first = std::min(top_layer_endpoints.first, id); @@ -2847,8 +2882,13 @@ void GCodeViewer::render_legend(float& legend_height) }; const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast(m_time_estimate_mode)]; +#if ENABLE_PREVIEW_LAYER_TIME + bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || m_view_type == EViewType::LayerTime || + (m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty())); +#else bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || (m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty())); +#endif // ENABLE_PREVIEW_LAYER_TIME const float icon_size = ImGui::GetTextLineHeight(); const float percent_bar_size = 2.0f * ImGui::GetTextLineHeight(); @@ -2971,6 +3011,7 @@ void GCodeViewer::render_legend(float& legend_height) // single item use case append_range_item(0, range.min, decimals); else if (range.count == 2) { + // two items use case append_range_item(static_cast(Range_Colors.size()) - 1, range.max, decimals); append_range_item(0, range.min, decimals); } @@ -2982,6 +3023,29 @@ void GCodeViewer::render_legend(float& legend_height) } }; +#if ENABLE_PREVIEW_LAYER_TIME + auto append_time_range = [append_item](const Extrusions::Range& range) { + auto append_range_item = [append_item](int i, float value) { + append_item(EItemType::Rect, Range_Colors[i], get_time_dhms(value)); + }; + + if (range.count == 1) + // single item use case + append_range_item(0, range.min); + else if (range.count == 2) { + // two items use case + append_range_item(static_cast(Range_Colors.size()) - 1, range.max); + append_range_item(0, range.min); + } + else { + const float step_size = range.step_size(); + for (int i = static_cast(Range_Colors.size()) - 1; i >= 0; --i) { + append_range_item(i, range.min + static_cast(i) * step_size); + } + } + }; +#endif // ENABLE_PREVIEW_LAYER_TIME + auto append_headers = [&imgui](const std::array& texts, const std::array& offsets) { size_t i = 0; for (; i < offsets.size(); i++) { @@ -3163,8 +3227,10 @@ void GCodeViewer::render_legend(float& legend_height) case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } - case EViewType::Tool: - { +#if ENABLE_PREVIEW_LAYER_TIME + case EViewType::LayerTime: { imgui.title(_u8L("Layer time")); break; } +#endif // ENABLE_PREVIEW_LAYER_TIME + case EViewType::Tool: { append_headers({ _u8L("Tool"), _u8L("Used filament") }, offsets); break; } @@ -3186,7 +3252,7 @@ void GCodeViewer::render_legend(float& legend_height) visible, times[i], percents[i], max_percent, offsets, used_filaments_m[i], used_filaments_g[i], [this, role, visible]() { m_extrusions.role_visibility_flags = visible ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role); // update buffers' render paths - refresh_render_paths(false, false); + refresh_render_paths(); wxGetApp().plater()->update_preview_moves_slider(); wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); wxGetApp().plater()->update_preview_bottom_toolbar(); @@ -3201,8 +3267,10 @@ void GCodeViewer::render_legend(float& legend_height) case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; } case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; } case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; } - case EViewType::Tool: - { +#if ENABLE_PREVIEW_LAYER_TIME + case EViewType::LayerTime: { append_time_range(m_extrusions.ranges.layer_time[static_cast(m_time_estimate_mode)]); break; } +#endif // ENABLE_PREVIEW_LAYER_TIME + case EViewType::Tool: { // shows only extruders actually used size_t i = 0; for (unsigned char extruder_id : m_extruder_ids) { @@ -3212,8 +3280,7 @@ void GCodeViewer::render_legend(float& legend_height) } break; } - case EViewType::ColorPrint: - { + case EViewType::ColorPrint: { #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER const std::vector& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z; #else @@ -3626,7 +3693,7 @@ void GCodeViewer::render_legend(float& legend_height) if (can_show_mode_button(m_time_estimate_mode)) { switch (m_time_estimate_mode) { - case PrintEstimatedStatistics::ETimeMode::Normal: { time_title += " [" + _u8L("Normal mode") + "]"; break; } + case PrintEstimatedStatistics::ETimeMode::Normal: { time_title += " [" + _u8L("Normal mode") + "]"; break; } case PrintEstimatedStatistics::ETimeMode::Stealth: { time_title += " [" + _u8L("Stealth mode") + "]"; break; } default: { assert(false); break; } } @@ -3657,6 +3724,10 @@ void GCodeViewer::render_legend(float& legend_height) if (can_show_mode_button(mode)) { if (imgui.button(label)) { m_time_estimate_mode = mode; +#if ENABLE_PREVIEW_LAYER_TIME + if (m_view_type == EViewType::LayerTime) + refresh_render_paths(); +#endif // ENABLE_PREVIEW_LAYER_TIME wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); } @@ -3803,7 +3874,7 @@ void GCodeViewer::log_memory_used(const std::string& label, int64_t additional) } } int64_t layers_size = SLIC3R_STDVEC_MEMSIZE(m_layers.get_zs(), double); - layers_size += SLIC3R_STDVEC_MEMSIZE(m_layers.get_endpoints(), Layers::Endpoints); + layers_size += SLIC3R_STDVEC_MEMSIZE(m_layers.get_ranges(), Layers::Range); BOOST_LOG_TRIVIAL(trace) << label << "(" << format_memsize_MB(additional + paths_size + render_paths_size + layers_size) << ");" << log_memory_info(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 429175fe68..73bdb0ac0e 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -417,6 +417,10 @@ class GCodeViewer Range volumetric_rate; // Color mapping by extrusion temperature. Range temperature; +#if ENABLE_PREVIEW_LAYER_TIME + // Color mapping by layer time. + std::array(PrintEstimatedStatistics::ETimeMode::Count)> layer_time; +#endif // ENABLE_PREVIEW_LAYER_TIME void reset() { height.reset(); @@ -425,6 +429,11 @@ class GCodeViewer fan_speed.reset(); volumetric_rate.reset(); temperature.reset(); +#if ENABLE_PREVIEW_LAYER_TIME + for (auto& range : layer_time) { + range.reset(); + } +#endif // ENABLE_PREVIEW_LAYER_TIME } }; @@ -444,43 +453,42 @@ class GCodeViewer class Layers { public: - struct Endpoints + struct Range { size_t first{ 0 }; size_t last{ 0 }; - bool operator == (const Endpoints& other) const { - return first == other.first && last == other.last; - } + bool operator == (const Range& other) const { return first == other.first && last == other.last; } + bool contains(size_t id) const { return first <= id && id <= last; } }; private: std::vector m_zs; - std::vector m_endpoints; + std::vector m_ranges; public: - void append(double z, Endpoints endpoints) { + void append(double z, const Range& range) { m_zs.emplace_back(z); - m_endpoints.emplace_back(endpoints); + m_ranges.emplace_back(range); } void reset() { m_zs = std::vector(); - m_endpoints = std::vector(); + m_ranges = std::vector(); } size_t size() const { return m_zs.size(); } bool empty() const { return m_zs.empty(); } const std::vector& get_zs() const { return m_zs; } - const std::vector& get_endpoints() const { return m_endpoints; } - std::vector& get_endpoints() { return m_endpoints; } + const std::vector& get_ranges() const { return m_ranges; } + std::vector& get_ranges() { return m_ranges; } double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; } - Endpoints get_endpoints_at(unsigned int id) const { return (id < m_endpoints.size()) ? m_endpoints[id] : Endpoints(); } + Range get_range_at(unsigned int id) const { return (id < m_ranges.size()) ? m_ranges[id] : Range(); } bool operator != (const Layers& other) const { if (m_zs != other.m_zs) return true; - if (!(m_endpoints == other.m_endpoints)) + if (!(m_ranges == other.m_ranges)) return true; return false; @@ -692,6 +700,9 @@ public: FanSpeed, Temperature, VolumetricRate, +#if ENABLE_PREVIEW_LAYER_TIME + LayerTime, +#endif // ENABLE_PREVIEW_LAYER_TIME Tool, ColorPrint, Count @@ -727,6 +738,9 @@ private: std::array m_detected_point_sizes = { 0.0f, 0.0f }; GCodeProcessor::Result::SettingsIds m_settings_ids; std::array m_sequential_range_caps; +#if ENABLE_PREVIEW_LAYER_TIME + std::array, static_cast(PrintEstimatedStatistics::ETimeMode::Count)> m_layers_times; +#endif // ENABLE_PREVIEW_LAYER_TIME #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER std::vector m_custom_gcode_per_print_z; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 8c10fb1576..231fa92067 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -225,6 +225,9 @@ bool Preview::init(wxWindow* parent, Model* model) m_choice_view_type->Append(_L("Fan speed")); m_choice_view_type->Append(_L("Temperature")); m_choice_view_type->Append(_L("Volumetric flow rate")); +#if ENABLE_PREVIEW_LAYER_TIME + m_choice_view_type->Append(_L("Layer time")); +#endif // ENABLE_PREVIEW_LAYER_TIME m_choice_view_type->Append(_L("Tool")); m_choice_view_type->Append(_L("Color Print")); m_choice_view_type->SetSelection(0); From 8f36002ebeb743b71b042f0b55ba56dd46956cd0 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 14:59:22 +0200 Subject: [PATCH 02/66] Tech ENABLE_PREVIEW_LAYER_TIME - Show '< 1s' in place of '0s' in preview legend --- src/slic3r/GUI/GCodeViewer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 3d7d754274..2c5ef72a00 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3026,7 +3026,10 @@ void GCodeViewer::render_legend(float& legend_height) #if ENABLE_PREVIEW_LAYER_TIME auto append_time_range = [append_item](const Extrusions::Range& range) { auto append_range_item = [append_item](int i, float value) { - append_item(EItemType::Rect, Range_Colors[i], get_time_dhms(value)); + std::string str_value = get_time_dhms(value); + if (str_value == "0s") + str_value = "< 1s"; + append_item(EItemType::Rect, Range_Colors[i], str_value); }; if (range.count == 1) From f30fffa0bc0d5c4a978d94d2293185bb8e932a31 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 13 Sep 2021 10:05:06 +0200 Subject: [PATCH 03/66] ENABLE_PREVIEW_LAYER_TIME -> Linear and logarithmic layer time visualization --- src/slic3r/GUI/GCodeViewer.cpp | 89 ++++++++++++++++++++++++---------- src/slic3r/GUI/GCodeViewer.hpp | 16 +++++- src/slic3r/GUI/GUI_Preview.cpp | 3 +- 3 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 966dd60aed..b1483dcdc6 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -179,11 +179,38 @@ void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsi move.volumetric_rate(), move.extruder_id, move.cp_color_id, { { endpoint, endpoint } } }); } +#if ENABLE_PREVIEW_LAYER_TIME +float GCodeViewer::Extrusions::Range::step_size(EType type) const +{ + switch (type) + { + default: + case EType::Linear: { return (max > min) ? (max - min) / (static_cast(Range_Colors.size()) - 1.0f) : 0.0f; } + case EType::Logarithmic: { return (max > min && min > 0.0f) ? ::log(max / min) / (static_cast(Range_Colors.size()) - 1.0f) : 0.0f; } + } +} + +GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value, EType type) const +#else GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) const +#endif // ENABLE_PREVIEW_LAYER_TIME { // Input value scaled to the colors range +#if ENABLE_PREVIEW_LAYER_TIME + float global_t = 0.0f; + const float step = step_size(type); + if (step > 0.0f) { + switch (type) + { + default: + case EType::Linear: { global_t = (value > min) ? (value - min) / step : 0.0f; break; } + case EType::Logarithmic: { global_t = (value > min && min > 0.0f) ? ::log(value / min) / step : 0.0f; break; } + } + } +#else const float step = step_size(); const float global_t = (step != 0.0f) ? std::max(0.0f, value - min) / step : 0.0f; // lower limit of 0.0f +#endif // ENABLE_PREVIEW_LAYER_TIME const size_t color_max_idx = Range_Colors.size() - 1; @@ -2196,7 +2223,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; } case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; } #if ENABLE_PREVIEW_LAYER_TIME - case EViewType::LayerTime: { + case EViewType::LayerTimeLinear: + case EViewType::LayerTimeLogarithmic: { const Path::Sub_Path& sub_path = path.sub_paths.front(); double z = static_cast(sub_path.first.position.z()); const std::vector& zs = m_layers.get_zs(); @@ -2205,7 +2233,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool for (size_t i = 0; i < zs.size(); ++i) { if (std::abs(zs[i] - z) < EPSILON) { if (ranges[i].contains(sub_path.first.s_id)) { - color = m_extrusions.ranges.layer_time[time_mode_id].get_color_at(m_layers_times[time_mode_id][i]); + color = m_extrusions.ranges.layer_time[time_mode_id].get_color_at(m_layers_times[time_mode_id][i], + (m_view_type == EViewType::LayerTimeLinear) ? Extrusions::Range::EType::Linear : Extrusions::Range::EType::Logarithmic); break; } } @@ -3073,7 +3102,8 @@ void GCodeViewer::render_legend(float& legend_height) const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast(m_time_estimate_mode)]; #if ENABLE_PREVIEW_LAYER_TIME - bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || m_view_type == EViewType::LayerTime || + bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || + m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic || (m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty())); #else bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || @@ -3216,7 +3246,7 @@ void GCodeViewer::render_legend(float& legend_height) }; #if ENABLE_PREVIEW_LAYER_TIME - auto append_time_range = [append_item](const Extrusions::Range& range) { + auto append_time_range = [append_item](const Extrusions::Range& range, Extrusions::Range::EType type) { auto append_range_item = [append_item](int i, float value) { std::string str_value = get_time_dhms(value); if (str_value == "0s") @@ -3233,9 +3263,16 @@ void GCodeViewer::render_legend(float& legend_height) append_range_item(0, range.min); } else { - const float step_size = range.step_size(); + float step_size = range.step_size(type); for (int i = static_cast(Range_Colors.size()) - 1; i >= 0; --i) { - append_range_item(i, range.min + static_cast(i) * step_size); + float value = 0.0f; + switch (type) + { + default: + case Extrusions::Range::EType::Linear: { value = range.min + static_cast(i) * step_size; break; } + case Extrusions::Range::EType::Logarithmic: { value = ::exp(::log(range.min) + static_cast(i) * step_size); break; } + } + append_range_item(i, value); } } }; @@ -3416,20 +3453,21 @@ void GCodeViewer::render_legend(float& legend_height) append_headers({ _u8L("Feature type"), _u8L("Time"), _u8L("Percentage"), _u8L("Used filament") }, offsets); break; } - case EViewType::Height: { imgui.title(_u8L("Height (mm)")); break; } - case EViewType::Width: { imgui.title(_u8L("Width (mm)")); break; } - case EViewType::Feedrate: { imgui.title(_u8L("Speed (mm/s)")); break; } - case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } - case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } - case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } + case EViewType::Height: { imgui.title(_u8L("Height (mm)")); break; } + case EViewType::Width: { imgui.title(_u8L("Width (mm)")); break; } + case EViewType::Feedrate: { imgui.title(_u8L("Speed (mm/s)")); break; } + case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } + case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } + case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } #if ENABLE_PREVIEW_LAYER_TIME - case EViewType::LayerTime: { imgui.title(_u8L("Layer time")); break; } + case EViewType::LayerTimeLinear: { imgui.title(_u8L("Layer time (linear)")); break; } + case EViewType::LayerTimeLogarithmic: { imgui.title(_u8L("Layer time (logarithmic)")); break; } #endif // ENABLE_PREVIEW_LAYER_TIME - case EViewType::Tool: { + case EViewType::Tool: { append_headers({ _u8L("Tool"), _u8L("Used filament") }, offsets); break; } - case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; } + case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; } default: { break; } } @@ -3456,16 +3494,17 @@ void GCodeViewer::render_legend(float& legend_height) } break; } - case EViewType::Height: { append_range(m_extrusions.ranges.height, 3); break; } - case EViewType::Width: { append_range(m_extrusions.ranges.width, 3); break; } - case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 1); break; } - case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; } - case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; } - case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; } + case EViewType::Height: { append_range(m_extrusions.ranges.height, 3); break; } + case EViewType::Width: { append_range(m_extrusions.ranges.width, 3); break; } + case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 1); break; } + case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; } + case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; } + case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; } #if ENABLE_PREVIEW_LAYER_TIME - case EViewType::LayerTime: { append_time_range(m_extrusions.ranges.layer_time[static_cast(m_time_estimate_mode)]); break; } + case EViewType::LayerTimeLinear: { append_time_range(m_extrusions.ranges.layer_time[static_cast(m_time_estimate_mode)], Extrusions::Range::EType::Linear); break; } + case EViewType::LayerTimeLogarithmic: { append_time_range(m_extrusions.ranges.layer_time[static_cast(m_time_estimate_mode)], Extrusions::Range::EType::Logarithmic); break; } #endif // ENABLE_PREVIEW_LAYER_TIME - case EViewType::Tool: { + case EViewType::Tool: { // shows only extruders actually used size_t i = 0; for (unsigned char extruder_id : m_extruder_ids) { @@ -3475,7 +3514,7 @@ void GCodeViewer::render_legend(float& legend_height) } break; } - case EViewType::ColorPrint: { + case EViewType::ColorPrint: { #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER const std::vector& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z; #else @@ -3924,7 +3963,7 @@ void GCodeViewer::render_legend(float& legend_height) if (imgui.button(label)) { m_time_estimate_mode = mode; #if ENABLE_PREVIEW_LAYER_TIME - if (m_view_type == EViewType::LayerTime) + if (m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic) refresh_render_paths(); #endif // ENABLE_PREVIEW_LAYER_TIME wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index fe88cc5391..28f009c7a6 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -429,6 +429,14 @@ class GCodeViewer { struct Range { +#if ENABLE_PREVIEW_LAYER_TIME + enum class EType : unsigned char + { + Linear, + Logarithmic + }; +#endif // ENABLE_PREVIEW_LAYER_TIME + float min; float max; unsigned int count; @@ -443,8 +451,13 @@ class GCodeViewer } void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; } +#if ENABLE_PREVIEW_LAYER_TIME + float step_size(EType type = EType::Linear) const; + Color get_color_at(float value, EType type = EType::Linear) const; +#else float step_size() const { return (max - min) / (static_cast(Range_Colors.size()) - 1.0f); } Color get_color_at(float value) const; +#endif // ENABLE_PREVIEW_LAYER_TIME }; struct Ranges @@ -756,7 +769,8 @@ public: Temperature, VolumetricRate, #if ENABLE_PREVIEW_LAYER_TIME - LayerTime, + LayerTimeLinear, + LayerTimeLogarithmic, #endif // ENABLE_PREVIEW_LAYER_TIME Tool, ColorPrint, diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 231fa92067..f6a96cf0d6 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -226,7 +226,8 @@ bool Preview::init(wxWindow* parent, Model* model) m_choice_view_type->Append(_L("Temperature")); m_choice_view_type->Append(_L("Volumetric flow rate")); #if ENABLE_PREVIEW_LAYER_TIME - m_choice_view_type->Append(_L("Layer time")); + m_choice_view_type->Append(_L("Layer time (linear)")); + m_choice_view_type->Append(_L("Layer time (logarithmic)")); #endif // ENABLE_PREVIEW_LAYER_TIME m_choice_view_type->Append(_L("Tool")); m_choice_view_type->Append(_L("Color Print")); From 7f89a42be6d3c40b7fb5824e8abfe5c13992d6f2 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 14 Sep 2021 08:15:47 +0200 Subject: [PATCH 04/66] Tech ENABLE_PREVIEW_LAYOUT - 1st installment: move view type combo from bottom toolbar to legend --- src/libslic3r/Technologies.hpp | 2 ++ src/slic3r/GUI/GCodeViewer.cpp | 32 ++++++++++++++++++++++++++++++++ src/slic3r/GUI/GUI_Preview.cpp | 26 ++++++++++++++++++++++++++ src/slic3r/GUI/GUI_Preview.hpp | 6 ++++++ src/slic3r/GUI/ImGuiWrapper.cpp | 10 ++++++++-- 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index ac92ecd108..dfd03fbedf 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -66,6 +66,8 @@ #define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) // Enable fixing the z position of color change, pause print and custom gcode markers in preview #define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER && ENABLE_2_4_0_ALPHA2) +// Enable changes in preview layout +#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_4_0_ALPHA2) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 9b7d8ec47c..d60935978d 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3344,6 +3344,31 @@ void GCodeViewer::render_legend(float& legend_height) offsets = calculate_offsets(labels, times, { "Extruder NNN", longest_used_filament_string }, icon_size); } +#if ENABLE_PREVIEW_LAYOUT + // selection section + bool selection_changed = false; + int view_type = static_cast(get_view_type()); + int old_view_type = view_type; + if (imgui.combo("", { _u8L("Feature type"), + _u8L("Height (mm)"), + _u8L("Width (mm)"), + _u8L("Speed (mm/s)"), + _u8L("Fan speed (%)"), + _u8L("Temperature (°C)"), + _u8L("Volumetric flow rate (mm³/s)"), + _u8L("Tool"), + _u8L("Color Print") }, view_type)) { + set_view_type(static_cast(view_type)); + wxGetApp().plater()->refresh_print(); + selection_changed = old_view_type != view_type; + } + + // extrusion paths section -> title + if (m_view_type == EViewType::FeatureType) + append_headers({ _u8L(""), _u8L("Time"), _u8L("Percentage"), _u8L("Used filament") }, offsets); + else + ImGui::Separator(); +#else // extrusion paths section -> title switch (m_view_type) { @@ -3366,7 +3391,11 @@ void GCodeViewer::render_legend(float& legend_height) case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; } default: { break; } } +#endif // ENABLE_PREVIEW_LAYOUT +#if ENABLE_PREVIEW_LAYOUT + if (!selection_changed) { +#endif // ENABLE_PREVIEW_LAYOUT // extrusion paths section -> items switch (m_view_type) { @@ -3481,6 +3510,9 @@ void GCodeViewer::render_legend(float& legend_height) } default: { break; } } +#if ENABLE_PREVIEW_LAYOUT + } +#endif // ENABLE_PREVIEW_LAYOUT // partial estimated printing time section if (m_view_type == EViewType::ColorPrint) { diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index f8a10bb8e9..3375702e38 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -207,6 +207,7 @@ bool Preview::init(wxWindow* parent, Model* model) m_layers_slider_sizer = create_layers_slider_sizer(); wxGetApp().UpdateDarkUI(m_bottom_toolbar_panel = new wxPanel(this)); +#if !ENABLE_PREVIEW_LAYOUT m_label_view_type = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("View")); #ifdef _WIN32 wxGetApp().UpdateDarkUI(m_choice_view_type = new BitmapComboBox(m_bottom_toolbar_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY)); @@ -223,6 +224,7 @@ bool Preview::init(wxWindow* parent, Model* model) m_choice_view_type->Append(_L("Tool")); m_choice_view_type->Append(_L("Color Print")); m_choice_view_type->SetSelection(0); +#endif // !ENABLE_PREVIEW_LAYOUT m_label_show = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("Show")); @@ -231,6 +233,7 @@ bool Preview::init(wxWindow* parent, Model* model) #else long combo_style = wxCB_READONLY; #endif +#if !ENABLE_PREVIEW_LAYOUT m_combochecklist_features = new wxComboCtrl(); m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, combo_style); std::string feature_items = GUI::into_u8( @@ -251,6 +254,7 @@ bool Preview::init(wxWindow* parent, Model* model) _L("Custom") + "|1" ); Slic3r::GUI::create_combochecklist(m_combochecklist_features, GUI::into_u8(_L("Feature types")), feature_items); +#endif // !ENABLE_PREVIEW_LAYOUT m_combochecklist_options = new wxComboCtrl(); m_combochecklist_options->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Options"), wxDefaultPosition, wxDefaultSize, combo_style); @@ -280,16 +284,20 @@ bool Preview::init(wxWindow* parent, Model* model) m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView); wxBoxSizer* bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL); +#if !ENABLE_PREVIEW_LAYOUT bottom_toolbar_sizer->AddSpacer(5); bottom_toolbar_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5); bottom_toolbar_sizer->Add(m_choice_view_type, 0, wxALIGN_CENTER_VERTICAL, 0); +#endif // !ENABLE_PREVIEW_LAYOUT bottom_toolbar_sizer->AddSpacer(5); bottom_toolbar_sizer->Add(m_label_show, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5); bottom_toolbar_sizer->Add(m_combochecklist_options, 0, wxALIGN_CENTER_VERTICAL, 0); +#if !ENABLE_PREVIEW_LAYOUT // change the following number if editing the layout of the bottom toolbar sizer. It is used into update_bottom_toolbar() m_combochecklist_features_pos = 6; bottom_toolbar_sizer->Add(m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5); bottom_toolbar_sizer->Hide(m_combochecklist_features); +#endif // !ENABLE_PREVIEW_LAYOUT bottom_toolbar_sizer->AddSpacer(5); bottom_toolbar_sizer->Add(m_moves_slider, 1, wxALL | wxEXPAND, 0); m_bottom_toolbar_panel->SetSizer(bottom_toolbar_sizer); @@ -395,10 +403,12 @@ void Preview::refresh_print() void Preview::msw_rescale() { +#if !ENABLE_PREVIEW_LAYOUT #ifdef _WIN32 m_choice_view_type->Rescale(); m_choice_view_type->SetMinSize(m_choice_view_type->GetSize()); #endif +#endif // !ENABLE_PREVIEW_LAYOUT // rescale slider if (m_layers_slider != nullptr) m_layers_slider->msw_rescale(); if (m_moves_slider != nullptr) m_moves_slider->msw_rescale(); @@ -416,9 +426,11 @@ void Preview::sys_color_changed() wxWindowUpdateLocker noUpdates(this); wxGetApp().UpdateAllStaticTextDarkUI(m_bottom_toolbar_panel); +#if !ENABLE_PREVIEW_LAYOUT wxGetApp().UpdateDarkUI(m_choice_view_type); wxGetApp().UpdateDarkUI(m_combochecklist_features); wxGetApp().UpdateDarkUI(static_cast(m_combochecklist_features->GetPopupControl())); +#endif // !ENABLE_PREVIEW_LAYOUT wxGetApp().UpdateDarkUI(m_combochecklist_options); wxGetApp().UpdateDarkUI(static_cast(m_combochecklist_options->GetPopupControl())); #endif @@ -445,8 +457,10 @@ void Preview::edit_layers_slider(wxKeyEvent& evt) void Preview::bind_event_handlers() { this->Bind(wxEVT_SIZE, &Preview::on_size, this); +#if !ENABLE_PREVIEW_LAYOUT m_choice_view_type->Bind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this); m_combochecklist_features->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this); +#endif // !ENABLE_PREVIEW_LAYOUT m_combochecklist_options->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this); m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); } @@ -454,8 +468,10 @@ void Preview::bind_event_handlers() void Preview::unbind_event_handlers() { this->Unbind(wxEVT_SIZE, &Preview::on_size, this); +#if !ENABLE_PREVIEW_LAYOUT m_choice_view_type->Unbind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this); m_combochecklist_features->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this); +#endif // !ENABLE_PREVIEW_LAYOUT m_combochecklist_options->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this); m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); } @@ -477,6 +493,7 @@ void Preview::on_size(wxSizeEvent& evt) Refresh(); } +#if !ENABLE_PREVIEW_LAYOUT void Preview::on_choice_view_type(wxCommandEvent& evt) { int selection = m_choice_view_type->GetCurrentSelection(); @@ -493,6 +510,7 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt) m_canvas->set_toolpath_role_visibility_flags(flags); refresh_print(); } +#endif // !ENABLE_PREVIEW_LAYOUT void Preview::on_combochecklist_options(wxCommandEvent& evt) { @@ -508,9 +526,12 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt) void Preview::update_bottom_toolbar() { +#if !ENABLE_PREVIEW_LAYOUT combochecklist_set_flags(m_combochecklist_features, m_canvas->get_toolpath_role_visibility_flags()); +#endif // !ENABLE_PREVIEW_LAYOUT combochecklist_set_flags(m_combochecklist_options, m_canvas->get_gcode_options_visibility_flags()); +#if !ENABLE_PREVIEW_LAYOUT // updates visibility of features combobox if (m_bottom_toolbar_panel->IsShown()) { wxSizer* sizer = m_bottom_toolbar_panel->GetSizer(); @@ -533,6 +554,7 @@ void Preview::update_bottom_toolbar() } } } +#endif // !ENABLE_PREVIEW_LAYOUT } wxBoxSizer* Preview::create_layers_slider_sizer() @@ -975,6 +997,9 @@ void Preview::load_print_as_fff(bool keep_z_range) _L("Color Print") : (number_extruders > 1) ? _L("Tool") : _L("Feature type"); +#if ENABLE_PREVIEW_LAYOUT + GCodeViewer::EViewType view_type = m_canvas->get_gcode_view_type(); +#else int type = m_choice_view_type->FindString(choice); if (m_choice_view_type->GetSelection() != type) { if (0 <= type && type < static_cast(GCodeViewer::EViewType::Count)) { @@ -986,6 +1011,7 @@ void Preview::load_print_as_fff(bool keep_z_range) } } } +#endif // ENABLE_PREVIEW_LAYOUT } #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 97ced0a1e0..91d126e344 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -80,15 +80,19 @@ class Preview : public wxPanel wxBoxSizer* m_left_sizer { nullptr }; wxBoxSizer* m_layers_slider_sizer { nullptr }; wxPanel* m_bottom_toolbar_panel { nullptr }; +#if !ENABLE_PREVIEW_LAYOUT wxStaticText* m_label_view_type { nullptr }; #ifdef _WIN32 BitmapComboBox* m_choice_view_type { nullptr }; #else wxComboBox* m_choice_view_type { nullptr }; #endif +#endif // !ENABLE_PREVIEW_LAYOUT wxStaticText* m_label_show { nullptr }; +#if !ENABLE_PREVIEW_LAYOUT wxComboCtrl* m_combochecklist_features { nullptr }; size_t m_combochecklist_features_pos { 0 }; +#endif // !ENABLE_PREVIEW_LAYOUT wxComboCtrl* m_combochecklist_options { nullptr }; DynamicPrintConfig* m_config; @@ -167,8 +171,10 @@ private: void unbind_event_handlers(); void on_size(wxSizeEvent& evt); +#if !ENABLE_PREVIEW_LAYOUT void on_choice_view_type(wxCommandEvent& evt); void on_combochecklist_features(wxCommandEvent& evt); +#endif // !ENABLE_PREVIEW_LAYOUT void on_combochecklist_options(wxCommandEvent& evt); // Create/Update/Reset double slider on 3dPreview diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index fa9845c5d7..7bdfb15c71 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -444,8 +444,14 @@ bool ImGuiWrapper::slider_float(const wxString& label, float* v, float v_min, fl bool ImGuiWrapper::combo(const wxString& label, const std::vector& options, int& selection) { // this is to force the label to the left of the widget: - text(label); - ImGui::SameLine(); +#if ENABLE_PREVIEW_LAYOUT + if (!label.empty()) { +#endif // ENABLE_PREVIEW_LAYOUT + text(label); + ImGui::SameLine(); +#if ENABLE_PREVIEW_LAYOUT + } +#endif // ENABLE_PREVIEW_LAYOUT int selection_out = selection; bool res = false; From cddfc8b690ad87d40320d9ea557ed8244543ffd8 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 14 Sep 2021 10:32:17 +0200 Subject: [PATCH 05/66] Tech ENABLE_PREVIEW_LAYOUT - A few fixes in the new legend layout --- src/slic3r/GUI/GCodeViewer.cpp | 33 +++++++++++++++++++-------------- src/slic3r/GUI/GUI_Preview.cpp | 16 ++++++++++++---- src/slic3r/GUI/GUI_Preview.hpp | 4 ++++ src/slic3r/GUI/Plater.cpp | 6 ++++++ src/slic3r/GUI/Plater.hpp | 4 ++++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index d60935978d..ac47494598 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3346,21 +3346,26 @@ void GCodeViewer::render_legend(float& legend_height) #if ENABLE_PREVIEW_LAYOUT // selection section - bool selection_changed = false; - int view_type = static_cast(get_view_type()); - int old_view_type = view_type; - if (imgui.combo("", { _u8L("Feature type"), - _u8L("Height (mm)"), - _u8L("Width (mm)"), - _u8L("Speed (mm/s)"), - _u8L("Fan speed (%)"), - _u8L("Temperature (°C)"), - _u8L("Volumetric flow rate (mm³/s)"), - _u8L("Tool"), - _u8L("Color Print") }, view_type)) { + bool view_type_changed = false; + int old_view_type = static_cast(get_view_type()); + int view_type = old_view_type; + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::PushItemWidth(ImGui::GetWindowWidth() - style.ItemSpacing.x - 2.0f * style.FramePadding.x); + imgui.combo("", { _u8L("Feature type"), + _u8L("Height (mm)"), + _u8L("Width (mm)"), + _u8L("Speed (mm/s)"), + _u8L("Fan speed (%)"), + _u8L("Temperature (°C)"), + _u8L("Volumetric flow rate (mm³/s)"), + _u8L("Tool"), + _u8L("Color Print") }, view_type); + + if (old_view_type != view_type) { set_view_type(static_cast(view_type)); + wxGetApp().plater()->set_keep_current_preview_type(true); wxGetApp().plater()->refresh_print(); - selection_changed = old_view_type != view_type; + view_type_changed = true; } // extrusion paths section -> title @@ -3394,7 +3399,7 @@ void GCodeViewer::render_legend(float& legend_height) #endif // ENABLE_PREVIEW_LAYOUT #if ENABLE_PREVIEW_LAYOUT - if (!selection_changed) { + if (!view_type_changed) { #endif // ENABLE_PREVIEW_LAYOUT // extrusion paths section -> items switch (m_view_type) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 3375702e38..65bcf212d9 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -993,13 +993,21 @@ void Preview::load_print_as_fff(bool keep_z_range) std::vector gcodes = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_canvas->get_custom_gcode_per_print_z(); +#if ENABLE_PREVIEW_LAYOUT + const GCodeViewer::EViewType choice = !gcodes.empty() ? + GCodeViewer::EViewType::ColorPrint : + (number_extruders > 1) ? GCodeViewer::EViewType::Tool : GCodeViewer::EViewType::FeatureType; + if (choice != gcode_view_type) { + m_canvas->set_gcode_view_preview_type(choice); + if (wxGetApp().is_gcode_viewer()) { + m_keep_current_preview_type = true; + refresh_print(); + } + } +#else const wxString choice = !gcodes.empty() ? _L("Color Print") : (number_extruders > 1) ? _L("Tool") : _L("Feature type"); - -#if ENABLE_PREVIEW_LAYOUT - GCodeViewer::EViewType view_type = m_canvas->get_gcode_view_type(); -#else int type = m_choice_view_type->FindString(choice); if (m_choice_view_type->GetSelection() != type) { if (0 <= type && type < static_cast(GCodeViewer::EViewType::Count)) { diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 91d126e344..bf3db0915e 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -164,6 +164,10 @@ public: void move_moves_slider(wxKeyEvent& evt); void hide_layers_slider(); +#if ENABLE_PREVIEW_LAYOUT + void set_keep_current_preview_type(bool value) { m_keep_current_preview_type = value; } +#endif // ENABLE_PREVIEW_LAYOUT + private: bool init(wxWindow* parent, Model* model); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7d344c389b..6506cb2c1b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6606,6 +6606,12 @@ bool Plater::is_render_statistic_dialog_visible() const return p->show_render_statistic_dialog; } +#if ENABLE_PREVIEW_LAYOUT +void Plater::set_keep_current_preview_type(bool value) +{ + p->preview->set_keep_current_preview_type(value); +} +#endif // ENABLE_PREVIEW_LAYOUT Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name) : TakeSnapshot(plater, from_u8(snapshot_name)) {} diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 4a98797e5d..dffb2451f3 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -403,6 +403,10 @@ public: void toggle_render_statistic_dialog(); bool is_render_statistic_dialog_visible() const; +#if ENABLE_PREVIEW_LAYOUT + void set_keep_current_preview_type(bool value); +#endif // ENABLE_PREVIEW_LAYOUT + // Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu. bool PopupMenu(wxMenu *menu, const wxPoint& pos = wxDefaultPosition); bool PopupMenu(wxMenu *menu, int x, int y) { return this->PopupMenu(menu, wxPoint(x, y)); } From 3f1c845089155333d9fb7feb544c769aafabdb81 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 20 Sep 2021 12:05:35 +0200 Subject: [PATCH 06/66] Tech ENABLE_PREVIEW_LAYOUT - Darker background for the new combo into legend --- src/slic3r/GUI/GCodeViewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index ac47494598..742a114597 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3351,6 +3351,8 @@ void GCodeViewer::render_legend(float& legend_height) int view_type = old_view_type; ImGuiStyle& style = ImGui::GetStyle(); ImGui::PushItemWidth(ImGui::GetWindowWidth() - style.ItemSpacing.x - 2.0f * style.FramePadding.x); + ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0.1f, 0.1f, 0.1f, 0.8f }); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, { 0.2f, 0.2f, 0.2f, 0.8f }); imgui.combo("", { _u8L("Feature type"), _u8L("Height (mm)"), _u8L("Width (mm)"), @@ -3360,6 +3362,7 @@ void GCodeViewer::render_legend(float& legend_height) _u8L("Volumetric flow rate (mm³/s)"), _u8L("Tool"), _u8L("Color Print") }, view_type); + ImGui::PopStyleColor(2); if (old_view_type != view_type) { set_view_type(static_cast(view_type)); From e12cf58c913017ceab660b6f4ef9ba8c6f6dc19d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 24 Sep 2021 09:22:50 +0200 Subject: [PATCH 07/66] Tech ENABLE_PREVIEW_LAYOUT - Replace options combo in bottom toolbar with toolbar in legend --- src/slic3r/GUI/GCodeViewer.cpp | 118 +++++++++++++++++++++++++++++++- src/slic3r/GUI/GLCanvas3D.cpp | 2 + src/slic3r/GUI/GUI_Preview.cpp | 29 ++++---- src/slic3r/GUI/GUI_Preview.hpp | 14 ++-- src/slic3r/GUI/ImGuiWrapper.cpp | 36 ++++++++++ src/slic3r/GUI/ImGuiWrapper.hpp | 8 ++- src/slic3r/GUI/Plater.cpp | 6 ++ src/slic3r/GUI/Plater.hpp | 2 + 8 files changed, 191 insertions(+), 24 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 1ae39ef68f..b901ca01ef 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -959,7 +959,9 @@ unsigned int GCodeViewer::get_options_visibility_flags() const flags = set_flag(flags, static_cast(Preview::OptionType::CustomGCodes), is_toolpath_move_type_visible(EMoveType::Custom_GCode)); flags = set_flag(flags, static_cast(Preview::OptionType::Shells), m_shells.visible); flags = set_flag(flags, static_cast(Preview::OptionType::ToolMarker), m_sequential_view.marker.is_visible()); +#if !ENABLE_PREVIEW_LAYOUT flags = set_flag(flags, static_cast(Preview::OptionType::Legend), is_legend_enabled()); +#endif // !ENABLE_PREVIEW_LAYOUT return flags; } @@ -980,7 +982,9 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags) set_toolpath_move_type_visible(EMoveType::Custom_GCode, is_flag_set(static_cast(Preview::OptionType::CustomGCodes))); m_shells.visible = is_flag_set(static_cast(Preview::OptionType::Shells)); m_sequential_view.marker.set_visible(is_flag_set(static_cast(Preview::OptionType::ToolMarker))); +#if !ENABLE_PREVIEW_LAYOUT enable_legend(is_flag_set(static_cast(Preview::OptionType::Legend))); +#endif // !ENABLE_PREVIEW_LAYOUT } void GCodeViewer::set_layers_z_range(const std::array& layers_z_range) @@ -3575,7 +3579,9 @@ void GCodeViewer::render_legend(float& legend_height) refresh_render_paths(false, false); wxGetApp().plater()->update_preview_moves_slider(); wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); +#if !ENABLE_PREVIEW_LAYOUT wxGetApp().plater()->update_preview_bottom_toolbar(); +#endif // !ENABLE_PREVIEW_LAYOUT } ); } @@ -3846,6 +3852,7 @@ void GCodeViewer::render_legend(float& legend_height) } } +#if !ENABLE_PREVIEW_LAYOUT // travel paths section if (m_buffers[buffer_id(EMoveType::Travel)].visible) { switch (m_view_type) @@ -3930,6 +3937,7 @@ void GCodeViewer::render_legend(float& legend_height) add_option(EMoveType::Pause_Print, EOptionsColors::PausePrints, _u8L("Print pauses")); add_option(EMoveType::Custom_GCode, EOptionsColors::CustomGCodes, _u8L("Custom G-codes")); } +#endif // !ENABLE_PREVIEW_LAYOUT // settings section bool has_settings = false; @@ -4050,17 +4058,123 @@ void GCodeViewer::render_legend(float& legend_height) switch (m_time_estimate_mode) { case PrintEstimatedStatistics::ETimeMode::Normal: { - show_mode_button(_L("Show stealth mode"), PrintEstimatedStatistics::ETimeMode::Stealth); + show_mode_button(_u8L("Show stealth mode"), PrintEstimatedStatistics::ETimeMode::Stealth); break; } case PrintEstimatedStatistics::ETimeMode::Stealth: { - show_mode_button(_L("Show normal mode"), PrintEstimatedStatistics::ETimeMode::Normal); + show_mode_button(_u8L("Show normal mode"), PrintEstimatedStatistics::ETimeMode::Normal); break; } default : { assert(false); break; } } } +#if ENABLE_PREVIEW_LAYOUT + // toolbar section + auto toggle_button = [this, &imgui, icon_size](Preview::OptionType type, const std::string& name, + std::function draw_callback) { + auto is_flag_set = [](unsigned int flags, unsigned int flag) { + return (flags & (1 << flag)) != 0; + }; + + auto set_flag = [](unsigned int flags, unsigned int flag, bool active) { + return active ? (flags | (1 << flag)) : (flags & ~(1 << flag)); + }; + + unsigned int flags = get_options_visibility_flags(); + unsigned int flag = static_cast(type); + bool active = is_flag_set(flags, flag); + + if (imgui.draw_radio_button(name, 1.5f * icon_size, active, draw_callback)) { + unsigned int new_flags = set_flag(flags, flag, !active); + set_options_visibility_from_flags(new_flags); + + wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(); + wxGetApp().plater()->update_preview_moves_slider(); + } + + if (ImGui::IsItemHovered()) { + ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND); + ImGui::BeginTooltip(); + imgui.text(name); + ImGui::EndTooltip(); + ImGui::PopStyleColor(); + } + }; + + auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { + const float margin = 3.0f; + const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); + window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); + }; + auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { + const float margin = 3.0f; + window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); + }; + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + toggle_button(Preview::OptionType::Travel, _u8L("Travel"), [line_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + line_icon(window, pos, size, Travel_Colors[0]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::Wipe, _u8L("Wipe"), [line_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + line_icon(window, pos, size, Wipe_Color); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::Retractions, _u8L("Retractions"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Retractions)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::Unretractions, _u8L("Deretractions"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Unretractions)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::Seams, _u8L("Seams"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Seams)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::ToolChanges, _u8L("Tool changes"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::ToolChanges)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::ColorChanges, _u8L("Color changes"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::ColorChanges)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::PausePrints, _u8L("Print pauses"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::PausePrints)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::CustomGCodes, _u8L("Custom G-codes"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::CustomGCodes)]); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [](ImGuiWindow& window, const ImVec2& pos, float size) { + const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f }); + const float margin = 3.0f; + const float proj = 0.25f * size; + window.DrawList->AddRect({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin - proj, pos.y + margin + proj }, color); + window.DrawList->AddLine({ pos.x + margin, pos.y + margin + proj }, { pos.x + margin + proj, pos.y + margin }, color); + window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + margin + proj }, { pos.x + size - margin, pos.y + margin }, color); + window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + size - margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color); + window.DrawList->AddLine({ pos.x + margin + proj, pos.y + margin }, { pos.x + size - margin, pos.y + margin }, color); + window.DrawList->AddLine({ pos.x + size - margin, pos.y + margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color); + }); + ImGui::SameLine(); + toggle_button(Preview::OptionType::ToolMarker, _u8L("Tool marker"), [](ImGuiWindow& window, const ImVec2& pos, float size) { + const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.8f }); + const float margin = 3.0f; + const ImVec2 p1(0.5f * (pos.x + pos.x + size), pos.y + size - margin); + const ImVec2 p2 = ImVec2(p1.x + 0.25f * size, p1.y - 0.25f * size); + const ImVec2 p3 = ImVec2(p1.x - 0.25f * size, p1.y - 0.25f * size); + window.DrawList->AddTriangleFilled(p1, p2, p3, color); + const float mid_x = 0.5f * (pos.x + pos.x + size); + window.DrawList->AddRectFilled({ mid_x - 0.09375f * size, p1.y - 0.25f * size }, { mid_x + 0.09375f * size, pos.y + margin }, color); + }); +#endif // ENABLE_PREVIEW_LAYOUT + legend_height = ImGui::GetCurrentWindow()->Size.y; imgui.end(); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e2aa6fb7b8..45d1900808 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2410,7 +2410,9 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) if (!m_main_toolbar.is_enabled()) { m_gcode_viewer.enable_legend(!m_gcode_viewer.is_legend_enabled()); m_dirty = true; +#if !ENABLE_PREVIEW_LAYOUT wxGetApp().plater()->update_preview_bottom_toolbar(); +#endif // !ENABLE_PREVIEW_LAYOUT } break; } diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 99dea09a88..9f6159cb40 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -224,7 +224,6 @@ bool Preview::init(wxWindow* parent, Model* model) m_choice_view_type->Append(_L("Tool")); m_choice_view_type->Append(_L("Color Print")); m_choice_view_type->SetSelection(0); -#endif // !ENABLE_PREVIEW_LAYOUT m_label_show = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("Show")); @@ -233,7 +232,7 @@ bool Preview::init(wxWindow* parent, Model* model) #else long combo_style = wxCB_READONLY; #endif -#if !ENABLE_PREVIEW_LAYOUT + m_combochecklist_features = new wxComboCtrl(); m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, combo_style); std::string feature_items = GUI::into_u8( @@ -254,7 +253,6 @@ bool Preview::init(wxWindow* parent, Model* model) _L("Custom") + "|1" ); Slic3r::GUI::create_combochecklist(m_combochecklist_features, GUI::into_u8(_L("Feature types")), feature_items); -#endif // !ENABLE_PREVIEW_LAYOUT m_combochecklist_options = new wxComboCtrl(); m_combochecklist_options->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Options"), wxDefaultPosition, wxDefaultSize, combo_style); @@ -273,6 +271,7 @@ bool Preview::init(wxWindow* parent, Model* model) get_option_type_string(OptionType::Legend) + "|1" ); Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items); +#endif // !ENABLE_PREVIEW_LAYOUT m_left_sizer = new wxBoxSizer(wxVERTICAL); m_left_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0); @@ -288,17 +287,15 @@ bool Preview::init(wxWindow* parent, Model* model) bottom_toolbar_sizer->AddSpacer(5); bottom_toolbar_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5); bottom_toolbar_sizer->Add(m_choice_view_type, 0, wxALIGN_CENTER_VERTICAL, 0); -#endif // !ENABLE_PREVIEW_LAYOUT bottom_toolbar_sizer->AddSpacer(5); bottom_toolbar_sizer->Add(m_label_show, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5); bottom_toolbar_sizer->Add(m_combochecklist_options, 0, wxALIGN_CENTER_VERTICAL, 0); -#if !ENABLE_PREVIEW_LAYOUT // change the following number if editing the layout of the bottom toolbar sizer. It is used into update_bottom_toolbar() m_combochecklist_features_pos = 6; bottom_toolbar_sizer->Add(m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5); bottom_toolbar_sizer->Hide(m_combochecklist_features); -#endif // !ENABLE_PREVIEW_LAYOUT bottom_toolbar_sizer->AddSpacer(5); +#endif // !ENABLE_PREVIEW_LAYOUT bottom_toolbar_sizer->Add(m_moves_slider, 1, wxALL | wxEXPAND, 0); m_bottom_toolbar_panel->SetSizer(bottom_toolbar_sizer); @@ -360,7 +357,9 @@ void Preview::load_print(bool keep_z_range) else if (tech == ptSLA) load_print_as_sla(); +#if !ENABLE_PREVIEW_LAYOUT update_bottom_toolbar(); +#endif // !ENABLE_PREVIEW_LAYOUT Layout(); } @@ -430,9 +429,9 @@ void Preview::sys_color_changed() wxGetApp().UpdateDarkUI(m_choice_view_type); wxGetApp().UpdateDarkUI(m_combochecklist_features); wxGetApp().UpdateDarkUI(static_cast(m_combochecklist_features->GetPopupControl())); -#endif // !ENABLE_PREVIEW_LAYOUT wxGetApp().UpdateDarkUI(m_combochecklist_options); wxGetApp().UpdateDarkUI(static_cast(m_combochecklist_options->GetPopupControl())); +#endif // !ENABLE_PREVIEW_LAYOUT #endif if (m_layers_slider != nullptr) @@ -456,23 +455,23 @@ void Preview::edit_layers_slider(wxKeyEvent& evt) void Preview::bind_event_handlers() { - this->Bind(wxEVT_SIZE, &Preview::on_size, this); + Bind(wxEVT_SIZE, &Preview::on_size, this); #if !ENABLE_PREVIEW_LAYOUT m_choice_view_type->Bind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this); m_combochecklist_features->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this); -#endif // !ENABLE_PREVIEW_LAYOUT m_combochecklist_options->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this); +#endif // !ENABLE_PREVIEW_LAYOUT m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); } void Preview::unbind_event_handlers() { - this->Unbind(wxEVT_SIZE, &Preview::on_size, this); + Unbind(wxEVT_SIZE, &Preview::on_size, this); #if !ENABLE_PREVIEW_LAYOUT m_choice_view_type->Unbind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this); m_combochecklist_features->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this); -#endif // !ENABLE_PREVIEW_LAYOUT m_combochecklist_options->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this); +#endif // !ENABLE_PREVIEW_LAYOUT m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); } @@ -510,7 +509,6 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt) m_canvas->set_toolpath_role_visibility_flags(flags); refresh_print(); } -#endif // !ENABLE_PREVIEW_LAYOUT void Preview::on_combochecklist_options(wxCommandEvent& evt) { @@ -526,12 +524,9 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt) void Preview::update_bottom_toolbar() { -#if !ENABLE_PREVIEW_LAYOUT combochecklist_set_flags(m_combochecklist_features, m_canvas->get_toolpath_role_visibility_flags()); -#endif // !ENABLE_PREVIEW_LAYOUT combochecklist_set_flags(m_combochecklist_options, m_canvas->get_gcode_options_visibility_flags()); -#if !ENABLE_PREVIEW_LAYOUT // updates visibility of features combobox if (m_bottom_toolbar_panel->IsShown()) { wxSizer* sizer = m_bottom_toolbar_panel->GetSizer(); @@ -554,8 +549,8 @@ void Preview::update_bottom_toolbar() } } } -#endif // !ENABLE_PREVIEW_LAYOUT } +#endif // !ENABLE_PREVIEW_LAYOUT wxBoxSizer* Preview::create_layers_slider_sizer() { @@ -1077,6 +1072,7 @@ void Preview::on_moves_slider_scroll_changed(wxCommandEvent& event) m_canvas->render(); } +#if !ENABLE_PREVIEW_LAYOUT wxString Preview::get_option_type_string(OptionType type) const { switch (type) @@ -1096,6 +1092,7 @@ wxString Preview::get_option_type_string(OptionType type) const default: { return ""; } } } +#endif // !ENABLE_PREVIEW_LAYOUT } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index bf3db0915e..fe63b44a72 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -87,13 +87,11 @@ class Preview : public wxPanel #else wxComboBox* m_choice_view_type { nullptr }; #endif -#endif // !ENABLE_PREVIEW_LAYOUT - wxStaticText* m_label_show { nullptr }; -#if !ENABLE_PREVIEW_LAYOUT + wxStaticText* m_label_show{ nullptr }; wxComboCtrl* m_combochecklist_features { nullptr }; size_t m_combochecklist_features_pos { 0 }; -#endif // !ENABLE_PREVIEW_LAYOUT wxComboCtrl* m_combochecklist_options { nullptr }; +#endif // !ENABLE_PREVIEW_LAYOUT DynamicPrintConfig* m_config; BackgroundSlicingProcess* m_process; @@ -130,7 +128,9 @@ public: CustomGCodes, Shells, ToolMarker, +#if !ENABLE_PREVIEW_LAYOUT Legend +#endif // !ENABLE_PREVIEW_LAYOUT }; Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, @@ -158,7 +158,9 @@ public: bool is_loaded() const { return m_loaded; } +#if !ENABLE_PREVIEW_LAYOUT void update_bottom_toolbar(); +#endif // !ENABLE_PREVIEW_LAYOUT void update_moves_slider(); void enable_moves_slider(bool enable); void move_moves_slider(wxKeyEvent& evt); @@ -178,8 +180,8 @@ private: #if !ENABLE_PREVIEW_LAYOUT void on_choice_view_type(wxCommandEvent& evt); void on_combochecklist_features(wxCommandEvent& evt); -#endif // !ENABLE_PREVIEW_LAYOUT void on_combochecklist_options(wxCommandEvent& evt); +#endif // !ENABLE_PREVIEW_LAYOUT // Create/Update/Reset double slider on 3dPreview wxBoxSizer* create_layers_slider_sizer(); @@ -196,7 +198,9 @@ private: void on_layers_slider_scroll_changed(wxCommandEvent& event); void on_moves_slider_scroll_changed(wxCommandEvent& event); +#if !ENABLE_PREVIEW_LAYOUT wxString get_option_type_string(OptionType type) const; +#endif // !ENABLE_PREVIEW_LAYOUT }; } // namespace GUI diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 7bdfb15c71..e514a4f796 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -349,6 +349,42 @@ bool ImGuiWrapper::radio_button(const wxString &label, bool active) return ImGui::RadioButton(label_utf8.c_str(), active); } +#if ENABLE_PREVIEW_LAYOUT +bool ImGuiWrapper::draw_radio_button(const std::string& name, float size, bool active, + std::function draw_callback) +{ + ImGuiWindow& window = *ImGui::GetCurrentWindow(); + if (window.SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window.GetID(name.c_str()); + + const ImVec2 pos = window.DC.CursorPos; + const ImRect total_bb(pos, pos + ImVec2(size, size + style.FramePadding.y * 2.0f)); + ImGui::ItemSize(total_bb, style.FramePadding.y); + if (!ImGui::ItemAdd(total_bb, id)) + return false; + + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); + if (pressed) + ImGui::MarkItemEdited(id); + + if (hovered) + window.DrawList->AddRect({ pos.x - 1.0f, pos.y - 1.0f }, { pos.x + size + 1.0f, pos.y + size + 1.0f }, ImGui::GetColorU32(ImGuiCol_CheckMark)); + + if (active) + window.DrawList->AddRect(pos, { pos.x + size, pos.y + size }, ImGui::GetColorU32(ImGuiCol_CheckMark)); + + draw_callback(window, pos, size); + + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window.DC.LastItemStatusFlags); + return pressed; +} +#endif // ENABLE_PREVIEW_LAYOUT + bool ImGuiWrapper::image_button() { return false; diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 441d26ccc6..73fe59ad13 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -16,6 +16,9 @@ class wxString; class wxMouseEvent; class wxKeyEvent; +#if ENABLE_PREVIEW_LAYOUT +struct IMGUI_API ImGuiWindow; +#endif // ENABLE_PREVIEW_LAYOUT namespace Slic3r { namespace GUI { @@ -68,7 +71,10 @@ public: bool button(const wxString &label); bool button(const wxString& label, float width, float height); bool radio_button(const wxString &label, bool active); - bool image_button(); +#if ENABLE_PREVIEW_LAYOUT + bool draw_radio_button(const std::string& name, float size, bool active, std::function draw_callback); +#endif // ENABLE_PREVIEW_LAYOUT + bool image_button(); bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f"); bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f"); bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f"); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8b110e1819..106b4a87de 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1632,7 +1632,9 @@ struct Plater::priv bool init_view_toolbar(); bool init_collapse_toolbar(); +#if !ENABLE_PREVIEW_LAYOUT void update_preview_bottom_toolbar(); +#endif // !ENABLE_PREVIEW_LAYOUT void update_preview_moves_slider(); void enable_preview_moves_slider(bool enable); @@ -4400,10 +4402,12 @@ bool Plater::priv::init_collapse_toolbar() return true; } +#if !ENABLE_PREVIEW_LAYOUT void Plater::priv::update_preview_bottom_toolbar() { preview->update_bottom_toolbar(); } +#endif // !ENABLE_PREVIEW_LAYOUT void Plater::priv::update_preview_moves_slider() { @@ -6637,10 +6641,12 @@ GLToolbar& Plater::get_collapse_toolbar() return p->collapse_toolbar; } +#if !ENABLE_PREVIEW_LAYOUT void Plater::update_preview_bottom_toolbar() { p->update_preview_bottom_toolbar(); } +#endif // !ENABLE_PREVIEW_LAYOUT void Plater::update_preview_moves_slider() { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 564caac968..f48025ba84 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -345,7 +345,9 @@ public: const GLToolbar& get_collapse_toolbar() const; GLToolbar& get_collapse_toolbar(); +#if !ENABLE_PREVIEW_LAYOUT void update_preview_bottom_toolbar(); +#endif // !ENABLE_PREVIEW_LAYOUT void update_preview_moves_slider(); void enable_preview_moves_slider(bool enable); From 57a0b23a0756246c481f8500944ac482bc4b32ed Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 24 Sep 2021 11:57:29 +0200 Subject: [PATCH 08/66] Tech ENABLE_PREVIEW_LAYOUT - Avoid resetting the preview's horizontal slider when toggling options --- src/slic3r/GUI/GCodeViewer.cpp | 8 +++++++- src/slic3r/GUI/GCodeViewer.hpp | 6 ++++++ src/slic3r/GUI/GLCanvas3D.cpp | 9 +++++++++ src/slic3r/GUI/GLCanvas3D.hpp | 4 ++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index b901ca01ef..2e8bbfc9c6 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -712,14 +712,20 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: #endif // ENABLE_GCODE_VIEWER_STATISTICS // update buffers' render paths +#if ENABLE_PREVIEW_LAYOUT + refresh_render_paths(false, false); +#else refresh_render_paths(); +#endif // ENABLE_PREVIEW_LAYOUT log_memory_used("Refreshed G-code extrusion paths, "); } +#if !ENABLE_PREVIEW_LAYOUT void GCodeViewer::refresh_render_paths() { refresh_render_paths(false, false); } +#endif // !ENABLE_PREVIEW_LAYOUT void GCodeViewer::update_shells_color_by_extruder(const DynamicPrintConfig* config) { @@ -4089,7 +4095,7 @@ void GCodeViewer::render_legend(float& legend_height) unsigned int new_flags = set_flag(flags, flag, !active); set_options_visibility_from_flags(new_flags); - wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(); + wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(true, true); wxGetApp().plater()->update_preview_moves_slider(); } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 6c164f5e8f..15b8d453c6 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -812,7 +812,11 @@ public: void load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized); // recalculate ranges in dependence of what is visible and sets tool/print colors void refresh(const GCodeProcessor::Result& gcode_result, const std::vector& str_tool_colors); +#if ENABLE_PREVIEW_LAYOUT + void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const; +#else void refresh_render_paths(); +#endif // ENABLE_PREVIEW_LAYOUT void update_shells_color_by_extruder(const DynamicPrintConfig* config); void reset(); @@ -857,7 +861,9 @@ public: private: void load_toolpaths(const GCodeProcessor::Result& gcode_result); void load_shells(const Print& print, bool initialized); +#if !ENABLE_PREVIEW_LAYOUT void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const; +#endif // !ENABLE_PREVIEW_LAYOUT void render_toolpaths(); void render_shells(); void render_legend(float& legend_height); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 45d1900808..5ebf57c6ce 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2100,12 +2100,21 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessor::Result& gcode_result, request_extra_frame(); } +#if ENABLE_PREVIEW_LAYOUT +void GLCanvas3D::refresh_gcode_preview_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) +{ + m_gcode_viewer.refresh_render_paths(keep_sequential_current_first, keep_sequential_current_last); + set_as_dirty(); + request_extra_frame(); +} +#else void GLCanvas3D::refresh_gcode_preview_render_paths() { m_gcode_viewer.refresh_render_paths(); set_as_dirty(); request_extra_frame(); } +#endif // ENABLE_PREVIEW_LAYOUT void GLCanvas3D::load_sla_preview() { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index e03c4a71db..ad9398ae65 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -721,7 +721,11 @@ public: void reload_scene(bool refresh_immediately, bool force_full_scene_refresh = false); void load_gcode_preview(const GCodeProcessor::Result& gcode_result, const std::vector& str_tool_colors); +#if ENABLE_PREVIEW_LAYOUT + void refresh_gcode_preview_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last); +#else void refresh_gcode_preview_render_paths(); +#endif // ENABLE_PREVIEW_LAYOUT void set_gcode_view_preview_type(GCodeViewer::EViewType type) { return m_gcode_viewer.set_view_type(type); } GCodeViewer::EViewType get_gcode_view_preview_type() const { return m_gcode_viewer.get_view_type(); } void load_sla_preview(); From d458de601b51aa06886507d88b4d26ff469885dd Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 24 Sep 2021 12:33:26 +0200 Subject: [PATCH 09/66] Tech ENABLE_PREVIEW_LAYOUT - Fixed legend layout for tool view --- src/slic3r/GUI/GCodeViewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 2e8bbfc9c6..b65d401f73 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3538,6 +3538,8 @@ void GCodeViewer::render_legend(float& legend_height) // extrusion paths section -> title if (m_view_type == EViewType::FeatureType) append_headers({ _u8L(""), _u8L("Time"), _u8L("Percentage"), _u8L("Used filament") }, offsets); + else if (m_view_type == EViewType::Tool) + append_headers({ _u8L(""), _u8L("Used filament"), _u8L(""), _u8L("") }, offsets); else ImGui::Separator(); #else @@ -4121,6 +4123,7 @@ void GCodeViewer::render_legend(float& legend_height) ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); + ImGui::Spacing(); toggle_button(Preview::OptionType::Travel, _u8L("Travel"), [line_icon](ImGuiWindow& window, const ImVec2& pos, float size) { line_icon(window, pos, size, Travel_Colors[0]); }); From 1a95169466614af21707f4928097af2d49f86403 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 29 Sep 2021 11:56:55 +0200 Subject: [PATCH 10/66] Tech ENABLE_PREVIEW_LAYOUT - Fixed legend width when moving the application to another monitor --- src/slic3r/GUI/GCodeViewer.cpp | 14 ++++++++++++-- src/slic3r/GUI/GCodeViewer.hpp | 17 +++++++++++++++++ src/slic3r/GUI/GLCanvas3D.cpp | 3 +++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index b65d401f73..0ab4f80d6a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -758,6 +758,9 @@ void GCodeViewer::reset() #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.reset_all(); #endif // ENABLE_GCODE_VIEWER_STATISTICS +#if ENABLE_PREVIEW_LAYOUT + m_legend_resizer.reset(); +#endif // ENABLE_PREVIEW_LAYOUT } void GCodeViewer::render() @@ -3513,8 +3516,11 @@ void GCodeViewer::render_legend(float& legend_height) bool view_type_changed = false; int old_view_type = static_cast(get_view_type()); int view_type = old_view_type; - ImGuiStyle& style = ImGui::GetStyle(); - ImGui::PushItemWidth(ImGui::GetWindowWidth() - style.ItemSpacing.x - 2.0f * style.FramePadding.x); + + ImGui::SetNextItemWidth(m_legend_resizer.dirty ? 0.0f : -1.0f); + if (m_legend_resizer.last_width > ImGui::GetWindowWidth()) + m_legend_resizer.dirty = false; + ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0.1f, 0.1f, 0.1f, 0.8f }); ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, { 0.2f, 0.2f, 0.2f, 0.8f }); imgui.combo("", { _u8L("Feature type"), @@ -4182,6 +4188,10 @@ void GCodeViewer::render_legend(float& legend_height) const float mid_x = 0.5f * (pos.x + pos.x + size); window.DrawList->AddRectFilled({ mid_x - 0.09375f * size, p1.y - 0.25f * size }, { mid_x + 0.09375f * size, pos.y + margin }, color); }); + + m_legend_resizer.last_width = ImGui::GetCurrentWindow()->DC.CursorPosPrevLine.x + ImGui::GetStyle().WindowPadding.x; + if (m_legend_resizer.last_width < ImGui::GetWindowWidth()) + m_legend_resizer.dirty = true; #endif // ENABLE_PREVIEW_LAYOUT legend_height = ImGui::GetCurrentWindow()->Size.y; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 15b8d453c6..b002826d14 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -793,6 +793,19 @@ private: Shells m_shells; EViewType m_view_type{ EViewType::FeatureType }; bool m_legend_enabled{ true }; +#if ENABLE_PREVIEW_LAYOUT + struct LegendResizer + { + bool dirty{ true }; + float last_width{ 0.0f }; + + void reset() { + dirty = true; + last_width = 0.0f; + } + }; + LegendResizer m_legend_resizer; +#endif // ENABLE_PREVIEW_LAYOUT PrintEstimatedStatistics m_print_statistics; PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal }; #if ENABLE_GCODE_VIEWER_STATISTICS @@ -858,6 +871,10 @@ public: std::vector& get_custom_gcode_per_print_z() { return m_custom_gcode_per_print_z; } size_t get_extruders_count() { return m_extruders_count; } +#if ENABLE_PREVIEW_LAYOUT + void invalidate_legend() { m_legend_resizer.reset(); } +#endif // ENABLE_PREVIEW_LAYOUT + private: void load_toolpaths(const GCodeProcessor::Result& gcode_result); void load_shells(const Print& print, bool initialized); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5ebf57c6ce..57d338600d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3741,6 +3741,9 @@ void GLCanvas3D::set_cursor(ECursorType type) void GLCanvas3D::msw_rescale() { +#if ENABLE_PREVIEW_LAYOUT + m_gcode_viewer.invalidate_legend(); +#endif // ENABLE_PREVIEW_LAYOUT } void GLCanvas3D::update_tooltip_for_settings_item_in_main_toolbar() From c963c3c80105f71b9a001e8c066cd7df9c14cadf Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 29 Sep 2021 12:35:53 +0200 Subject: [PATCH 11/66] Follow-up of 1a95169466614af21707f4928097af2d49f86403 - Fixed legend resizer --- src/slic3r/GUI/GCodeViewer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 0ab4f80d6a..8897ffddf7 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3517,8 +3517,9 @@ void GCodeViewer::render_legend(float& legend_height) int old_view_type = static_cast(get_view_type()); int view_type = old_view_type; - ImGui::SetNextItemWidth(m_legend_resizer.dirty ? 0.0f : -1.0f); - if (m_legend_resizer.last_width > ImGui::GetWindowWidth()) + if (!m_legend_resizer.dirty) + ImGui::SetNextItemWidth(-1.0f); + if (m_legend_resizer.last_width >= ImGui::GetWindowWidth()) m_legend_resizer.dirty = false; ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0.1f, 0.1f, 0.1f, 0.8f }); From e088a9fc363562ff233076aa0405b6fe73d39f1d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 29 Sep 2021 13:30:18 +0200 Subject: [PATCH 12/66] Tech ENABLE_PREVIEW_LAYOUT - View type combo popup has now adaptive height --- src/slic3r/GUI/GCodeViewer.cpp | 4 ++-- src/slic3r/GUI/ImGuiWrapper.cpp | 4 ++-- src/slic3r/GUI/ImGuiWrapper.hpp | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 8897ffddf7..5ec802c5e5 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3532,9 +3532,9 @@ void GCodeViewer::render_legend(float& legend_height) _u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), _u8L("Tool"), - _u8L("Color Print") }, view_type); + _u8L("Color Print") }, view_type, ImGuiComboFlags_HeightLargest); ImGui::PopStyleColor(2); - + if (old_view_type != view_type) { set_view_type(static_cast(view_type)); wxGetApp().plater()->set_keep_current_preview_type(true); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index e514a4f796..e2bd87a2a0 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -477,7 +477,7 @@ bool ImGuiWrapper::slider_float(const wxString& label, float* v, float v_min, fl return this->slider_float(label_utf8.c_str(), v, v_min, v_max, format, power, clamp); } -bool ImGuiWrapper::combo(const wxString& label, const std::vector& options, int& selection) +bool ImGuiWrapper::combo(const wxString& label, const std::vector& options, int& selection, ImGuiComboFlags flags) { // this is to force the label to the left of the widget: #if ENABLE_PREVIEW_LAYOUT @@ -493,7 +493,7 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector& bool res = false; const char *selection_str = selection < int(options.size()) && selection >= 0 ? options[selection].c_str() : ""; - if (ImGui::BeginCombo("", selection_str)) { + if (ImGui::BeginCombo("", selection_str, flags)) { for (int i = 0; i < (int)options.size(); i++) { if (ImGui::Selectable(options[i].c_str(), i == selection)) { selection_out = i; diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 73fe59ad13..8d464a202e 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -91,7 +91,8 @@ public: bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true); bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true); - bool combo(const wxString& label, const std::vector& options, int& selection); // Use -1 to not mark any option as selected + // Use selection = -1 to not mark any option as selected + bool combo(const wxString& label, const std::vector& options, int& selection, ImGuiComboFlags flags = 0); bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel); void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str, Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel, bool is_localized); From b4423aa9542ff24acb06a0cf42793584020795a8 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 30 Sep 2021 08:35:36 +0200 Subject: [PATCH 13/66] Fixes required after merge with branch et_layer_time_preview --- src/libslic3r/Technologies.hpp | 4 ++-- src/slic3r/GUI/GCodeViewer.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index d89b995125..ee64ebab41 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -62,8 +62,6 @@ #define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2) // Enable fixing the synchronization of seams with the horizontal slider in preview #define ENABLE_FIX_SEAMS_SYNCH (1 && ENABLE_2_4_0_ALPHA2) -// Enable changes in preview layout -#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_4_0_ALPHA2) //==================== @@ -73,6 +71,8 @@ // Enable fixing loading of gcode files generated with SuperSlicer in GCodeViewer #define ENABLE_FIX_SUPERSLICER_GCODE_IMPORT (1 && ENABLE_2_4_0_ALPHA3) +// Enable changes in preview layout +#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_4_0_ALPHA3) // Enable coloring of toolpaths in preview by layer time #define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_4_0_ALPHA3) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index aa9d321105..a97a2ab35b 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3683,6 +3683,10 @@ void GCodeViewer::render_legend(float& legend_height) _u8L("Fan speed (%)"), _u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), +#if ENABLE_PREVIEW_LAYER_TIME + _u8L("Layer time (linear)"), + _u8L("Layer time (logarithmic)"), +#endif // ENABLE_PREVIEW_LAYER_TIME _u8L("Tool"), _u8L("Color Print") }, view_type, ImGuiComboFlags_HeightLargest); ImGui::PopStyleColor(2); @@ -3746,7 +3750,7 @@ void GCodeViewer::render_legend(float& legend_height) visible, times[i], percents[i], max_percent, offsets, used_filaments_m[i], used_filaments_g[i], [this, role, visible]() { m_extrusions.role_visibility_flags = visible ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role); // update buffers' render paths - refresh_render_paths(); + refresh_render_paths(false, false); wxGetApp().plater()->update_preview_moves_slider(); wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); #if !ENABLE_PREVIEW_LAYOUT @@ -4225,7 +4229,7 @@ void GCodeViewer::render_legend(float& legend_height) m_time_estimate_mode = mode; #if ENABLE_PREVIEW_LAYER_TIME if (m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic) - refresh_render_paths(); + refresh_render_paths(false, false); #endif // ENABLE_PREVIEW_LAYER_TIME wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); From cd05e8f6cb4c0cf6d421eb820bea936369722ec3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 5 Oct 2021 14:13:35 +0200 Subject: [PATCH 14/66] Tech ENABLE_PREVIEW_LAYOUT - Other fixes related to legend size when moving the application to another monitor --- src/slic3r/GUI/GCodeViewer.cpp | 17 +++++++++-------- src/slic3r/GUI/GCodeViewer.hpp | 7 +------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index a97a2ab35b..51dc892f8b 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3671,8 +3671,6 @@ void GCodeViewer::render_legend(float& legend_height) if (!m_legend_resizer.dirty) ImGui::SetNextItemWidth(-1.0f); - if (m_legend_resizer.last_width >= ImGui::GetWindowWidth()) - m_legend_resizer.dirty = false; ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0.1f, 0.1f, 0.1f, 0.8f }); ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, { 0.2f, 0.2f, 0.2f, 0.8f }); @@ -3789,7 +3787,7 @@ void GCodeViewer::render_legend(float& legend_height) total_items += color_print_ranges(i, custom_gcode_per_print_z).size(); } - const bool need_scrollable = static_cast(total_items) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height; + const bool need_scrollable = static_cast(total_items) * icon_size + (static_cast(total_items) - 1.0f) * ImGui::GetStyle().ItemSpacing.y > child_height; // add scrollable region, if needed if (need_scrollable) @@ -3999,7 +3997,7 @@ void GCodeViewer::render_legend(float& legend_height) ImGui::Spacing(); append_headers({ _u8L("Event"), _u8L("Remaining time"), _u8L("Duration"), _u8L("Used filament") }, offsets); - const bool need_scrollable = static_cast(partial_times.size()) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height; + const bool need_scrollable = static_cast(partial_times.size()) * icon_size + (static_cast(partial_times.size()) - 1.0f) * ImGui::GetStyle().ItemSpacing.y > child_height; if (need_scrollable) // add scrollable region ImGui::BeginChild("events", { -1.0f, child_height }, false); @@ -4356,12 +4354,15 @@ void GCodeViewer::render_legend(float& legend_height) window.DrawList->AddRectFilled({ mid_x - 0.09375f * size, p1.y - 0.25f * size }, { mid_x + 0.09375f * size, pos.y + margin }, color); }); - m_legend_resizer.last_width = ImGui::GetCurrentWindow()->DC.CursorPosPrevLine.x + ImGui::GetStyle().WindowPadding.x; - if (m_legend_resizer.last_width < ImGui::GetWindowWidth()) - m_legend_resizer.dirty = true; + bool size_dirty = !ImGui::GetCurrentWindow()->ScrollbarY && ImGui::CalcWindowNextAutoFitSize(ImGui::GetCurrentWindow()).x != ImGui::GetWindowWidth(); + if (m_legend_resizer.dirty || size_dirty != m_legend_resizer.dirty) { + wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); + wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); + } + m_legend_resizer.dirty = size_dirty; #endif // ENABLE_PREVIEW_LAYOUT - legend_height = ImGui::GetCurrentWindow()->Size.y; + legend_height = ImGui::GetWindowHeight(); imgui.end(); ImGui::PopStyleVar(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index e8c036e333..e1753576ad 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -822,12 +822,7 @@ private: struct LegendResizer { bool dirty{ true }; - float last_width{ 0.0f }; - - void reset() { - dirty = true; - last_width = 0.0f; - } + void reset() { dirty = true; } }; LegendResizer m_legend_resizer; #endif // ENABLE_PREVIEW_LAYOUT From c18280016ab6a1f1227d782a527a7a59df0d8d5d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 5 Oct 2021 14:27:12 +0200 Subject: [PATCH 15/66] Tech ENABLE_PREVIEW_LAYOUT - Follow-up of 9a24b08e2890481f25941ba5e9a8a59fcb315d63 - Port of the into fix the tech --- src/slic3r/GUI/GUI_Preview.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 4d84454eb6..1e738aa7c5 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -980,10 +980,9 @@ void Preview::load_print_as_fff(bool keep_z_range) (number_extruders > 1) ? GCodeViewer::EViewType::Tool : GCodeViewer::EViewType::FeatureType; if (choice != gcode_view_type) { m_canvas->set_gcode_view_preview_type(choice); - if (wxGetApp().is_gcode_viewer()) { + if (wxGetApp().is_gcode_viewer()) m_keep_current_preview_type = true; - refresh_print(); - } + refresh_print(); } #else const wxString choice = !gcodes.empty() ? From e02a25cf1e6ed07ef8b30259a875b907d205110f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 5 Oct 2021 15:28:43 +0200 Subject: [PATCH 16/66] Follow-up of 57a0b23a0756246c481f8500944ac482bc4b32ed - Tech ENABLE_PREVIEW_LAYOUT - Fixed logic to avoid resetting the preview's horizontal slider when toggling options --- src/slic3r/GUI/GCodeViewer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 5a17ae7f35..9c0550495d 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4276,7 +4276,9 @@ void GCodeViewer::render_legend(float& legend_height) unsigned int new_flags = set_flag(flags, flag, !active); set_options_visibility_from_flags(new_flags); - wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(true, true); + bool keep_first = m_sequential_view.current.first != m_sequential_view.global.first; + bool keep_last = m_sequential_view.current.last != m_sequential_view.global.last; + wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(keep_first, keep_last); wxGetApp().plater()->update_preview_moves_slider(); } From 077abe117a24fa8e3bf03590702afa368cf31573 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 6 Oct 2021 15:49:25 +0200 Subject: [PATCH 17/66] Port of 2afdc66dfb84f512a3f72b0a18ceb51873d779c5 and dbad87fb42343a8c9eaf51897bfe316a82c344d7 into tech ENABLE_PREVIEW_LAYOUT --- src/slic3r/GUI/GCodeViewer.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 9c0550495d..9086a86060 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4276,9 +4276,15 @@ void GCodeViewer::render_legend(float& legend_height) unsigned int new_flags = set_flag(flags, flag, !active); set_options_visibility_from_flags(new_flags); - bool keep_first = m_sequential_view.current.first != m_sequential_view.global.first; - bool keep_last = m_sequential_view.current.last != m_sequential_view.global.last; - wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(keep_first, keep_last); + const unsigned int diff_flags = flags ^ new_flags; + if (m_view_type == GCodeViewer::EViewType::Feedrate && + (diff_flags & (1 << static_cast(Preview::OptionType::Travel))) != 0) + wxGetApp().plater()->refresh_print(); + else { + bool keep_first = m_sequential_view.current.first != m_sequential_view.global.first; + bool keep_last = m_sequential_view.current.last != m_sequential_view.global.last; + wxGetApp().plater()->get_current_canvas3D()->refresh_gcode_preview_render_paths(keep_first, keep_last); + } wxGetApp().plater()->update_preview_moves_slider(); } From 86636a906cc7977b0b2861d0045cfbde3b9018d9 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 6 Oct 2021 15:55:14 +0200 Subject: [PATCH 18/66] Small refactoring --- src/slic3r/GUI/GCodeViewer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 9086a86060..d76d4bed4d 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4277,9 +4277,8 @@ void GCodeViewer::render_legend(float& legend_height) set_options_visibility_from_flags(new_flags); const unsigned int diff_flags = flags ^ new_flags; - if (m_view_type == GCodeViewer::EViewType::Feedrate && - (diff_flags & (1 << static_cast(Preview::OptionType::Travel))) != 0) - wxGetApp().plater()->refresh_print(); + if (m_view_type == GCodeViewer::EViewType::Feedrate && is_flag_set(diff_flags, static_cast(Preview::OptionType::Travel))) + wxGetApp().plater()->refresh_print(); else { bool keep_first = m_sequential_view.current.first != m_sequential_view.global.first; bool keep_last = m_sequential_view.current.last != m_sequential_view.global.last; From eee8d97f497fcfaa69763cfa316d070c430f07e9 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 7 Oct 2021 14:07:33 +0200 Subject: [PATCH 19/66] Tech ENABLE_TRAVEL_TIME - Show estimated time for travel moves in legend when they are visible --- src/libslic3r/GCode/GCodeProcessor.cpp | 26 ++++++++++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 13 +++++++++ src/libslic3r/Technologies.hpp | 13 +++++++-- src/slic3r/GUI/GCodeViewer.cpp | 37 +++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 9c90535c4e..4b38d15358 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -189,6 +189,9 @@ void GCodeProcessor::TimeMachine::reset() max_travel_acceleration = 0.0f; extrude_factor_override_percentage = 1.0f; time = 0.0f; +#if ENABLE_TRAVEL_TIME + travel_time = 0.0f; +#endif // ENABLE_TRAVEL_TIME stop_times = std::vector(); curr.reset(); prev.reset(); @@ -303,9 +306,17 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks) const TimeBlock& block = blocks[i]; float block_time = block.time(); time += block_time; +#if ENABLE_TRAVEL_TIME + if (block.move_type == EMoveType::Travel) + travel_time += block_time; + else + roles_time[static_cast(block.role)] += block_time; +#endif // ENABLE_TRAVEL_TIME gcode_time.cache += block_time; moves_time[static_cast(block.move_type)] += block_time; +#if !ENABLE_TRAVEL_TIME roles_time[static_cast(block.role)] += block_time; +#endif // !ENABLE_TRAVEL_TIME if (block.layer_id > 0) { if (block.layer_id >= layers_time.size()) { size_t curr_size = layers_time.size(); @@ -1327,6 +1338,18 @@ std::string GCodeProcessor::get_time_dhm(PrintEstimatedStatistics::ETimeMode mod return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast(mode)].time)) : std::string("N/A"); } +#if ENABLE_TRAVEL_TIME +float GCodeProcessor::get_travel_time(PrintEstimatedStatistics::ETimeMode mode) const +{ + return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast(mode)].travel_time : 0.0f; +} + +std::string GCodeProcessor::get_travel_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const +{ + return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast(mode)].travel_time)) : std::string("N/A"); +} +#endif // ENABLE_TRAVEL_TIME + std::vector>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const { std::vector>> ret; @@ -3332,6 +3355,9 @@ void GCodeProcessor::update_estimated_times_stats() auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) { PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast(mode)]; data.time = get_time(mode); +#if ENABLE_TRAVEL_TIME + data.travel_time = get_travel_time(mode); +#endif // ENABLE_TRAVEL_TIME data.custom_gcode_times = get_custom_gcode_times(mode, true); data.moves_times = get_moves_time(mode); data.roles_times = get_roles_time(mode); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index fce8882333..a4e6f4d2fa 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -44,6 +44,9 @@ namespace Slic3r { struct Mode { float time; +#if ENABLE_TRAVEL_TIME + float travel_time; +#endif // ENABLE_TRAVEL_TIME std::vector>> custom_gcode_times; std::vector> moves_times; std::vector> roles_times; @@ -51,6 +54,9 @@ namespace Slic3r { void reset() { time = 0.0f; +#if ENABLE_TRAVEL_TIME + travel_time = 0.0f; +#endif // ENABLE_TRAVEL_TIME custom_gcode_times.clear(); moves_times.clear(); roles_times.clear(); @@ -250,6 +256,9 @@ namespace Slic3r { float max_travel_acceleration; // mm/s^2 float extrude_factor_override_percentage; float time; // s +#if ENABLE_TRAVEL_TIME + float travel_time; // s +#endif // ENABLE_TRAVEL_TIME struct StopTime { unsigned int g1_line_id; @@ -593,6 +602,10 @@ namespace Slic3r { float get_time(PrintEstimatedStatistics::ETimeMode mode) const; std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const; +#if ENABLE_TRAVEL_TIME + float get_travel_time(PrintEstimatedStatistics::ETimeMode mode) const; + std::string get_travel_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const; +#endif // ENABLE_TRAVEL_TIME std::vector>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const; std::vector> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index ee64ebab41..7f78f5d1b8 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -71,10 +71,19 @@ // Enable fixing loading of gcode files generated with SuperSlicer in GCodeViewer #define ENABLE_FIX_SUPERSLICER_GCODE_IMPORT (1 && ENABLE_2_4_0_ALPHA3) + + +//==================== +// 2.4.0.alpha4 techs +//==================== +#define ENABLE_2_4_0_ALPHA4 1 + // Enable changes in preview layout -#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_4_0_ALPHA3) +#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_4_0_ALPHA4) // Enable coloring of toolpaths in preview by layer time -#define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_4_0_ALPHA3) +#define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_4_0_ALPHA4) +// Enable showing time estimate for travel moves in legend +#define ENABLE_TRAVEL_TIME (1 && ENABLE_2_4_0_ALPHA4) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index d76d4bed4d..32f73ddd8b 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3433,7 +3433,25 @@ void GCodeViewer::render_legend(float& legend_height) } else { imgui.text(label); +#if ENABLE_TRAVEL_TIME + if (!time.empty()) { + ImGui::SameLine(offsets[0]); + imgui.text(time); + ImGui::SameLine(offsets[1]); + pos = ImGui::GetCursorScreenPos(); + const float width = std::max(1.0f, percent_bar_size * percent / max_percent); + draw_list->AddRectFilled({ pos.x, pos.y + 2.0f }, { pos.x + width, pos.y + icon_size - 2.0f }, + ImGui::GetColorU32(ImGuiWrapper::COL_ORANGE_LIGHT)); + ImGui::Dummy({ percent_bar_size, icon_size }); + ImGui::SameLine(); + char buf[64]; + ::sprintf(buf, "%.1f%%", 100.0f * percent); + ImGui::TextUnformatted((percent > 0.0f) ? buf : ""); + } + else if (used_filament_m > 0.0) { +#else if (used_filament_m > 0.0) { +#endif // ENABLE_TRAVEL_TIME char buf[64]; ImGui::SameLine(offsets[0]); ::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", used_filament_m); @@ -3600,7 +3618,7 @@ void GCodeViewer::render_legend(float& legend_height) std::vector percents; std::vector used_filaments_m; std::vector used_filaments_g; - float max_percent = 0.0f; + float max_time_percent = 0.0f; if (m_view_type == EViewType::FeatureType) { // calculate offsets to align time/percentage data @@ -3611,7 +3629,7 @@ void GCodeViewer::render_legend(float& legend_height) auto [time, percent] = role_time_and_percent(role); times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : ""); percents.push_back(percent); - max_percent = std::max(max_percent, percent); + max_time_percent = std::max(max_time_percent, percent); auto [used_filament_m, used_filament_g] = used_filament_per_role(role); used_filaments_m.push_back(used_filament_m); used_filaments_g.push_back(used_filament_g); @@ -3747,13 +3765,17 @@ void GCodeViewer::render_legend(float& legend_height) { case EViewType::FeatureType: { +#if ENABLE_TRAVEL_TIME + max_time_percent = std::max(max_time_percent, time_mode.travel_time / time_mode.time); +#endif // ENABLE_TRAVEL_TIME + for (size_t i = 0; i < m_roles.size(); ++i) { ExtrusionRole role = m_roles[i]; if (role >= erCount) continue; const bool visible = is_visible(role); append_item(EItemType::Rect, Extrusion_Role_Colors[static_cast(role)], labels[i], - visible, times[i], percents[i], max_percent, offsets, used_filaments_m[i], used_filaments_g[i], [this, role, visible]() { + visible, times[i], percents[i], max_time_percent, offsets, used_filaments_m[i], used_filaments_g[i], [this, role, visible]() { m_extrusions.role_visibility_flags = visible ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role); // update buffers' render paths refresh_render_paths(false, false); @@ -3765,6 +3787,13 @@ void GCodeViewer::render_legend(float& legend_height) } ); } + +#if ENABLE_TRAVEL_TIME + if (m_buffers[buffer_id(EMoveType::Travel)].visible) + append_item(EItemType::Line, Travel_Colors[0], _u8L("Travel"), true, short_time(get_time_dhms(time_mode.travel_time)), + time_mode.travel_time / time_mode.time, max_time_percent, offsets, 0.0f, 0.0f); +#endif // ENABLE_TRAVEL_TIME + break; } case EViewType::Height: { append_range(m_extrusions.ranges.height, 3); break; } @@ -3783,7 +3812,7 @@ void GCodeViewer::render_legend(float& legend_height) for (unsigned char extruder_id : m_extruder_ids) { append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1), true, "", 0.0f, 0.0f, offsets, used_filaments_m[i], used_filaments_g[i]); - i++; + ++i; } break; } From 0d922b04af5e4df8f0a7c044d5f05ef4e1975990 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 14 Oct 2021 11:30:27 +0200 Subject: [PATCH 20/66] Tech ENABLE_PREVIEW_LAYOUT - Added menu item View/Show legend --- src/slic3r/GUI/GLCanvas3D.cpp | 12 +++++++----- src/slic3r/GUI/GLCanvas3D.hpp | 5 +++++ src/slic3r/GUI/KBShortcutsDialog.cpp | 2 +- src/slic3r/GUI/MainFrame.cpp | 11 +++++++++++ src/slic3r/GUI/Plater.cpp | 10 ++++++++++ src/slic3r/GUI/Plater.hpp | 5 +++++ 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ca31645c1e..8dc750d40e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2422,14 +2422,16 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'i': { _update_camera_zoom(1.0); break; } case 'K': case 'k': { wxGetApp().plater()->get_camera().select_next_type(); m_dirty = true; break; } - case 'L': - case 'l': { - if (!m_main_toolbar.is_enabled()) { + case 'L': + case 'l': { + if (!m_main_toolbar.is_enabled()) { +#if ENABLE_PREVIEW_LAYOUT + show_legend(!is_legend_shown()); +#else m_gcode_viewer.enable_legend(!m_gcode_viewer.is_legend_enabled()); m_dirty = true; -#if !ENABLE_PREVIEW_LAYOUT wxGetApp().plater()->update_preview_bottom_toolbar(); -#endif // !ENABLE_PREVIEW_LAYOUT +#endif // ENABLE_PREVIEW_LAYOUT } break; } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 10df84b35e..0987823376 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -820,6 +820,11 @@ public: bool are_labels_shown() const { return m_labels.is_shown(); } void show_labels(bool show) { m_labels.show(show); } +#if ENABLE_PREVIEW_LAYOUT + bool is_legend_shown() const { return m_gcode_viewer.is_legend_enabled(); } + void show_legend(bool show) { m_gcode_viewer.enable_legend(show); m_dirty = true; } +#endif // ENABLE_PREVIEW_LAYOUT + bool is_using_slope() const { return m_slope.is_used(); } void use_slope(bool use) { m_slope.use(use); } void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); } diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index d16161f890..992b0be137 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -223,7 +223,7 @@ void KBShortcutsDialog::fill_shortcuts() { "A", L("Horizontal slider - Move active thumb Left") }, { "D", L("Horizontal slider - Move active thumb Right") }, { "X", L("On/Off one layer mode of the vertical slider") }, - { "L", L("Show/Hide Legend and Estimated printing time") }, + { "L", L("Show/Hide legend") }, { "C", L("Show/Hide G-code window") }, }; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 799c4e7933..9f80874ac2 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1433,6 +1433,11 @@ void MainFrame::init_menubar_as_editor() append_menu_check_item(viewMenu, wxID_ANY, _L("Show &labels") + sep + "E", _L("Show object/instance labels in 3D scene"), [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); +#if ENABLE_PREVIEW_LAYOUT + append_menu_check_item(viewMenu, wxID_ANY, _L("Show legen&d") + sep + "L", _L("Show legend in preview"), + [this](wxCommandEvent&) { m_plater->show_legend(!m_plater->is_legend_shown()); }, this, + [this]() { return m_plater->is_preview_shown(); }, [this]() { return m_plater->is_legend_shown(); }, this); +#endif // ENABLE_PREVIEW_LAYOUT append_menu_check_item(viewMenu, wxID_ANY, _L("&Collapse sidebar") + sep + "Shift+" + sep_space + "Tab", _L("Collapse sidebar"), [this](wxCommandEvent&) { m_plater->collapse_sidebar(!m_plater->is_sidebar_collapsed()); }, this, []() { return true; }, [this]() { return m_plater->is_sidebar_collapsed(); }, this); @@ -1550,6 +1555,12 @@ void MainFrame::init_menubar_as_gcodeviewer() if (m_plater != nullptr) { viewMenu = new wxMenu(); add_common_view_menu_items(viewMenu, this, std::bind(&MainFrame::can_change_view, this)); +#if ENABLE_PREVIEW_LAYOUT + viewMenu->AppendSeparator(); + append_menu_check_item(viewMenu, wxID_ANY, _L("Show legen&d") + sep + "L", _L("Show legend"), + [this](wxCommandEvent&) { m_plater->show_legend(!m_plater->is_legend_shown()); }, this, + [this]() { return m_plater->is_preview_shown(); }, [this]() { return m_plater->is_legend_shown(); }, this); +#endif // ENABLE_PREVIEW_LAYOUT } // helpmenu diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 52a84206b5..9aa3999663 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1667,6 +1667,11 @@ struct Plater::priv bool are_view3D_labels_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->are_labels_shown(); } void show_view3D_labels(bool show) { if (current_panel == view3D) view3D->get_canvas3d()->show_labels(show); } +#if ENABLE_PREVIEW_LAYOUT + bool is_legend_shown() const { return (current_panel == preview) && preview->get_canvas3d()->is_legend_shown(); } + void show_legend(bool show) { if (current_panel == preview) preview->get_canvas3d()->show_legend(show); } +#endif // ENABLE_PREVIEW_LAYOUT + bool is_sidebar_collapsed() const { return sidebar->is_collapsed(); } void collapse_sidebar(bool collapse); @@ -5410,6 +5415,11 @@ bool Plater::is_view3D_shown() const { return p->is_view3D_shown(); } bool Plater::are_view3D_labels_shown() const { return p->are_view3D_labels_shown(); } void Plater::show_view3D_labels(bool show) { p->show_view3D_labels(show); } +#if ENABLE_PREVIEW_LAYOUT +bool Plater::is_legend_shown() const { return p->is_legend_shown(); } +void Plater::show_legend(bool show) { p->show_legend(show); } +#endif // ENABLE_PREVIEW_LAYOUT + bool Plater::is_sidebar_collapsed() const { return p->is_sidebar_collapsed(); } void Plater::collapse_sidebar(bool show) { p->collapse_sidebar(show); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index a595ab44ee..2370e09c87 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -187,6 +187,11 @@ public: bool are_view3D_labels_shown() const; void show_view3D_labels(bool show); +#if ENABLE_PREVIEW_LAYOUT + bool is_legend_shown() const; + void show_legend(bool show); +#endif // ENABLE_PREVIEW_LAYOUT + bool is_sidebar_collapsed() const; void collapse_sidebar(bool show); From 3b17cde53ff3928041ee706656e7b3b1f33b9f0a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 19 Oct 2021 13:36:20 +0200 Subject: [PATCH 21/66] Tech ENABLE_PREVIEW_LAYOUT - Collassable legend --- src/slic3r/GUI/GCodeViewer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 4af575e193..8aa5b0bffe 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3369,7 +3369,11 @@ void GCodeViewer::render_legend(float& legend_height) const float max_height = 0.75f * static_cast(cnv_size.get_height()); const float child_height = 0.3333f * max_height; ImGui::SetNextWindowSizeConstraints({ 0.0f, 0.0f }, { -1.0f, max_height }); +#if ENABLE_PREVIEW_LAYOUT + imgui.begin(std::string("Legend"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove); +#else imgui.begin(std::string("Legend"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove); +#endif // ENABLE_PREVIEW_LAYOUT enum class EItemType : unsigned char { From a326c5b32024492497545bcb2f3a70dc446c08c7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 12 Nov 2021 14:04:37 +0100 Subject: [PATCH 22/66] Tech ENABLE_LEGEND_TOOLBAR_ICONS - Toolbar items in legend using svn icons --- resources/icons/legend_colorchanges.svg | 157 +++++++++++++++++++++++ resources/icons/legend_customgcodes.svg | 71 +++++++++++ resources/icons/legend_deretract.svg | 107 ++++++++++++++++ resources/icons/legend_pauseprints.svg | 76 +++++++++++ resources/icons/legend_retract.svg | 110 ++++++++++++++++ resources/icons/legend_seams.svg | 45 +++++++ resources/icons/legend_shells.svg | 77 +++++++++++ resources/icons/legend_toolchanges.svg | 102 +++++++++++++++ resources/icons/legend_toolmarker.svg | 76 +++++++++++ resources/icons/legend_travel.svg | 163 ++++++++++++++++++++++++ resources/icons/legend_wipe.svg | 48 +++++++ src/imgui/imconfig.h | 11 ++ src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/GCodeViewer.cpp | 69 +++++++++- src/slic3r/GUI/ImGuiWrapper.cpp | 38 +++++- src/slic3r/GUI/ImGuiWrapper.hpp | 7 + 16 files changed, 1157 insertions(+), 2 deletions(-) create mode 100644 resources/icons/legend_colorchanges.svg create mode 100644 resources/icons/legend_customgcodes.svg create mode 100644 resources/icons/legend_deretract.svg create mode 100644 resources/icons/legend_pauseprints.svg create mode 100644 resources/icons/legend_retract.svg create mode 100644 resources/icons/legend_seams.svg create mode 100644 resources/icons/legend_shells.svg create mode 100644 resources/icons/legend_toolchanges.svg create mode 100644 resources/icons/legend_toolmarker.svg create mode 100644 resources/icons/legend_travel.svg create mode 100644 resources/icons/legend_wipe.svg diff --git a/resources/icons/legend_colorchanges.svg b/resources/icons/legend_colorchanges.svg new file mode 100644 index 0000000000..cb95ef4676 --- /dev/null +++ b/resources/icons/legend_colorchanges.svg @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/legend_customgcodes.svg b/resources/icons/legend_customgcodes.svg new file mode 100644 index 0000000000..f363b39fdc --- /dev/null +++ b/resources/icons/legend_customgcodes.svg @@ -0,0 +1,71 @@ + + diff --git a/resources/icons/legend_deretract.svg b/resources/icons/legend_deretract.svg new file mode 100644 index 0000000000..4b636df9de --- /dev/null +++ b/resources/icons/legend_deretract.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/legend_pauseprints.svg b/resources/icons/legend_pauseprints.svg new file mode 100644 index 0000000000..954bc00e97 --- /dev/null +++ b/resources/icons/legend_pauseprints.svg @@ -0,0 +1,76 @@ + + diff --git a/resources/icons/legend_retract.svg b/resources/icons/legend_retract.svg new file mode 100644 index 0000000000..494e2f7286 --- /dev/null +++ b/resources/icons/legend_retract.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/legend_seams.svg b/resources/icons/legend_seams.svg new file mode 100644 index 0000000000..724414119d --- /dev/null +++ b/resources/icons/legend_seams.svg @@ -0,0 +1,45 @@ + + + + + + + diff --git a/resources/icons/legend_shells.svg b/resources/icons/legend_shells.svg new file mode 100644 index 0000000000..b0a93effb2 --- /dev/null +++ b/resources/icons/legend_shells.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/icons/legend_toolchanges.svg b/resources/icons/legend_toolchanges.svg new file mode 100644 index 0000000000..e6c195b110 --- /dev/null +++ b/resources/icons/legend_toolchanges.svg @@ -0,0 +1,102 @@ + + diff --git a/resources/icons/legend_toolmarker.svg b/resources/icons/legend_toolmarker.svg new file mode 100644 index 0000000000..be0c80bbb7 --- /dev/null +++ b/resources/icons/legend_toolmarker.svg @@ -0,0 +1,76 @@ + + diff --git a/resources/icons/legend_travel.svg b/resources/icons/legend_travel.svg new file mode 100644 index 0000000000..553e90a743 --- /dev/null +++ b/resources/icons/legend_travel.svg @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/legend_wipe.svg b/resources/icons/legend_wipe.svg new file mode 100644 index 0000000000..9dbc9a6556 --- /dev/null +++ b/resources/icons/legend_wipe.svg @@ -0,0 +1,48 @@ + + + + + Svg Vector Icons : http://www.onlinewebfonts.com/icon + + diff --git a/src/imgui/imconfig.h b/src/imgui/imconfig.h index e95ae3adfa..4f82a1f4c3 100644 --- a/src/imgui/imconfig.h +++ b/src/imgui/imconfig.h @@ -155,6 +155,17 @@ namespace ImGui const wchar_t ClippyMarker = 0x2602; const wchar_t InfoMarker = 0x2603; const wchar_t SliderFloatEditBtnIcon = 0x2604; + const wchar_t LegendTravel = 0x2605; + const wchar_t LegendWipe = 0x2606; + const wchar_t LegendRetract = 0x2607; + const wchar_t LegendDeretract = 0x2608; + const wchar_t LegendSeams = 0x2609; + const wchar_t LegendToolChanges = 0x2610; + const wchar_t LegendColorChanges = 0x2611; + const wchar_t LegendPausePrints = 0x2612; + const wchar_t LegendCustomGCodes = 0x2613; + const wchar_t LegendShells = 0x2614; + const wchar_t LegendToolMarker = 0x2615; // void MyFunction(const char* name, const MyMatrix44& v); } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index c628ae9647..dfaba9c71e 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -96,6 +96,8 @@ #define ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT (1 && ENABLE_2_4_0_BETA2) // Enable changes in preview layout #define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_4_0_BETA2) +// Enable drawing the items in legend toolbar using icons +#define ENABLE_LEGEND_TOOLBAR_ICONS (1 && ENABLE_PREVIEW_LAYOUT) // Enable coloring of toolpaths in preview by layer time #define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_4_0_BETA2) // Enable showing time estimate for travel moves in legend diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 0170191af3..0bbc7e8a0c 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4407,47 +4407,108 @@ void GCodeViewer::render_legend(float& legend_height) const float margin = 3.0f; window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); }; +#if ENABLE_LEGEND_TOOLBAR_ICONS + auto image_icon = [&imgui](ImGuiWindow& window, const ImVec2& pos, float size, const wchar_t& icon_id) { + ImGuiIO& io = ImGui::GetIO(); + const ImTextureID tex_id = io.Fonts->TexID; + const float tex_w = static_cast(io.Fonts->TexWidth); + const float tex_h = static_cast(io.Fonts->TexHeight); + const ImFontAtlas::CustomRect* const rect = imgui.GetTextureCustomRect(icon_id); + const ImVec2 uv0 = { static_cast(rect->X) / tex_w, static_cast(rect->Y) / tex_h }; + const ImVec2 uv1 = { static_cast(rect->X + rect->Width) / tex_w, static_cast(rect->Y + rect->Height) / tex_h }; + window.DrawList->AddImage(tex_id, pos, { pos.x + size, pos.y + size }, uv0, uv1, ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f })); + }; +#endif // ENABLE_LEGEND_TOOLBAR_ICONS ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); ImGui::Spacing(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::Travel, _u8L("Travel"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendTravel); +#else toggle_button(Preview::OptionType::Travel, _u8L("Travel"), [line_icon](ImGuiWindow& window, const ImVec2& pos, float size) { line_icon(window, pos, size, Travel_Colors[0]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::Wipe, _u8L("Wipe"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendWipe); +#else toggle_button(Preview::OptionType::Wipe, _u8L("Wipe"), [line_icon](ImGuiWindow& window, const ImVec2& pos, float size) { line_icon(window, pos, size, Wipe_Color); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::Retractions, _u8L("Retractions"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendRetract); +#else toggle_button(Preview::OptionType::Retractions, _u8L("Retractions"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { - circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Retractions)]); + circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Retractions)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::Unretractions, _u8L("Deretractions"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendDeretract); +#else toggle_button(Preview::OptionType::Unretractions, _u8L("Deretractions"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Unretractions)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::Seams, _u8L("Seams"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendSeams); +#else toggle_button(Preview::OptionType::Seams, _u8L("Seams"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::Seams)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::ToolChanges, _u8L("Tool changes"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendToolChanges); +#else toggle_button(Preview::OptionType::ToolChanges, _u8L("Tool changes"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::ToolChanges)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::ColorChanges, _u8L("Color changes"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendColorChanges); +#else toggle_button(Preview::OptionType::ColorChanges, _u8L("Color changes"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::ColorChanges)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::PausePrints, _u8L("Print pauses"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendPausePrints); +#else toggle_button(Preview::OptionType::PausePrints, _u8L("Print pauses"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::PausePrints)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::CustomGCodes, _u8L("Custom G-codes"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendCustomGCodes); +#else toggle_button(Preview::OptionType::CustomGCodes, _u8L("Custom G-codes"), [circle_icon](ImGuiWindow& window, const ImVec2& pos, float size) { circle_icon(window, pos, size, Options_Colors[static_cast(EOptionsColors::CustomGCodes)]); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendShells); +#else toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [](ImGuiWindow& window, const ImVec2& pos, float size) { const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f }); const float margin = 3.0f; @@ -4458,8 +4519,13 @@ void GCodeViewer::render_legend(float& legend_height) window.DrawList->AddLine({ pos.x + size - margin - proj, pos.y + size - margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color); window.DrawList->AddLine({ pos.x + margin + proj, pos.y + margin }, { pos.x + size - margin, pos.y + margin }, color); window.DrawList->AddLine({ pos.x + size - margin, pos.y + margin }, { pos.x + size - margin, pos.y + size - margin - proj }, color); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); ImGui::SameLine(); +#if ENABLE_LEGEND_TOOLBAR_ICONS + toggle_button(Preview::OptionType::ToolMarker, _u8L("Tool marker"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) { + image_icon(window, pos, size, ImGui::LegendToolMarker); +#else toggle_button(Preview::OptionType::ToolMarker, _u8L("Tool marker"), [](ImGuiWindow& window, const ImVec2& pos, float size) { const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.8f }); const float margin = 3.0f; @@ -4469,6 +4535,7 @@ void GCodeViewer::render_legend(float& legend_height) window.DrawList->AddTriangleFilled(p1, p2, p3, color); const float mid_x = 0.5f * (pos.x + pos.x + size); window.DrawList->AddRectFilled({ mid_x - 0.09375f * size, p1.y - 0.25f * size }, { mid_x + 0.09375f * size, pos.y + margin }, color); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }); bool size_dirty = !ImGui::GetCurrentWindow()->ScrollbarY && ImGui::CalcWindowNextAutoFitSize(ImGui::GetCurrentWindow()).x != ImGui::GetWindowWidth(); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 92401f0acd..058d8ef20c 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -53,8 +53,21 @@ static const std::map font_icons = { {ImGui::PreferencesButton , "notification_preferences" }, {ImGui::PreferencesHoverButton , "notification_preferences_hover"}, #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT - {ImGui::SliderFloatEditBtnIcon, "edit_button" }, + {ImGui::SliderFloatEditBtnIcon , "edit_button" }, #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT +#if ENABLE_LEGEND_TOOLBAR_ICONS + {ImGui::LegendTravel , "legend_travel" }, + {ImGui::LegendWipe , "legend_wipe" }, + {ImGui::LegendRetract , "legend_retract" }, + {ImGui::LegendDeretract , "legend_deretract" }, + {ImGui::LegendSeams , "legend_seams" }, + {ImGui::LegendToolChanges , "legend_toolchanges" }, + {ImGui::LegendColorChanges , "legend_colorchanges" }, + {ImGui::LegendPausePrints , "legend_pauseprints" }, + {ImGui::LegendCustomGCodes , "legend_customgcodes" }, + {ImGui::LegendShells , "legend_shells" }, + {ImGui::LegendToolMarker , "legend_toolmarker" }, +#endif // ENABLE_LEGEND_TOOLBAR_ICONS }; static const std::map font_icons_large = { {ImGui::CloseNotifButton , "notification_close" }, @@ -1052,6 +1065,14 @@ bool ImGuiWrapper::want_any_input() const return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput; } +#if ENABLE_LEGEND_TOOLBAR_ICONS +ImFontAtlasCustomRect* ImGuiWrapper::GetTextureCustomRect(const wchar_t& tex_id) +{ + auto item = m_custom_glyph_rects_ids.find(tex_id); + return (item != m_custom_glyph_rects_ids.end()) ? ImGui::GetIO().Fonts->GetCustomRectByIndex(m_custom_glyph_rects_ids[tex_id]) : nullptr; +} +#endif // ENABLE_LEGEND_TOOLBAR_ICONS + #ifdef __APPLE__ static const ImWchar ranges_keyboard_shortcuts[] = { @@ -1140,12 +1161,27 @@ void ImGuiWrapper::init_font(bool compress) int rect_id = io.Fonts->CustomRects.Size; // id of the rectangle added next // add rectangles for the icons to the font atlas +#if ENABLE_LEGEND_TOOLBAR_ICONS + for (auto& icon : font_icons) { + m_custom_glyph_rects_ids[icon.first] = + io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz, icon_sz, 3.0 * font_scale + icon_sz); + } + for (auto& icon : font_icons_large) { + m_custom_glyph_rects_ids[icon.first] = + io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 2, icon_sz * 2, 3.0 * font_scale + icon_sz * 2); + } + for (auto& icon : font_icons_extra_large) { + m_custom_glyph_rects_ids[icon.first] = + io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4); +} +#else for (auto& icon : font_icons) io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz, icon_sz, 3.0 * font_scale + icon_sz); for (auto& icon : font_icons_large) io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 2, icon_sz * 2, 3.0 * font_scale + icon_sz * 2); for (auto& icon : font_icons_extra_large) io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS // Build texture atlas unsigned char* pixels; diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 8c17ca183d..102a1537f7 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -39,6 +39,9 @@ class ImGuiWrapper #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT bool m_requires_extra_frame{ false }; #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT +#if ENABLE_LEGEND_TOOLBAR_ICONS + std::map m_custom_glyph_rects_ids; +#endif // ENABLE_LEGEND_TOOLBAR_ICONS std::string m_clipboard_text; public: @@ -132,6 +135,10 @@ public: void reset_requires_extra_frame() { m_requires_extra_frame = false; } #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT +#if ENABLE_LEGEND_TOOLBAR_ICONS + ImFontAtlasCustomRect* GetTextureCustomRect(const wchar_t& tex_id); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS + static const ImVec4 COL_GREY_DARK; static const ImVec4 COL_GREY_LIGHT; static const ImVec4 COL_ORANGE_DARK; From 6d89b22a5a37f38e3daa3eeaee262e963d0503db Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 15 Nov 2021 08:45:13 +0100 Subject: [PATCH 23/66] Tech ENABLE_LEGEND_TOOLBAR_ICONS - New icons for legend toolbar --- resources/icons/legend_toolchanges.svg | 122 ++++--------------------- resources/icons/legend_wipe.svg | 60 +++--------- 2 files changed, 34 insertions(+), 148 deletions(-) diff --git a/resources/icons/legend_toolchanges.svg b/resources/icons/legend_toolchanges.svg index e6c195b110..b6ed4c8a66 100644 --- a/resources/icons/legend_toolchanges.svg +++ b/resources/icons/legend_toolchanges.svg @@ -1,102 +1,20 @@ - - + + + + + + + + + + + + + + diff --git a/resources/icons/legend_wipe.svg b/resources/icons/legend_wipe.svg index 9dbc9a6556..decfcd6011 100644 --- a/resources/icons/legend_wipe.svg +++ b/resources/icons/legend_wipe.svg @@ -1,48 +1,16 @@ - - + + + + + + + + + + - - Svg Vector Icons : http://www.onlinewebfonts.com/icon - From b9c99ab27b2c1926c78f052ede313c5e2a522733 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 23 Nov 2021 08:32:55 +0100 Subject: [PATCH 24/66] New icon for legend toolbar --- resources/icons/legend_toolmarker.svg | 79 +-------------------------- 1 file changed, 3 insertions(+), 76 deletions(-) diff --git a/resources/icons/legend_toolmarker.svg b/resources/icons/legend_toolmarker.svg index be0c80bbb7..3cd5cf8d96 100644 --- a/resources/icons/legend_toolmarker.svg +++ b/resources/icons/legend_toolmarker.svg @@ -1,76 +1,3 @@ - - + + + From 78615546452dba0d5b25e9e9cef58871d36eb6e6 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 23 Nov 2021 10:59:52 +0100 Subject: [PATCH 25/66] New icons for legend toolbar --- resources/icons/legend_customgcodes.svg | 80 +++---------------------- resources/icons/legend_toolchanges.svg | 28 +++------ 2 files changed, 18 insertions(+), 90 deletions(-) diff --git a/resources/icons/legend_customgcodes.svg b/resources/icons/legend_customgcodes.svg index f363b39fdc..96e0be69e3 100644 --- a/resources/icons/legend_customgcodes.svg +++ b/resources/icons/legend_customgcodes.svg @@ -1,71 +1,9 @@ - - + + + + + + + + + diff --git a/resources/icons/legend_toolchanges.svg b/resources/icons/legend_toolchanges.svg index b6ed4c8a66..85b6218a9b 100644 --- a/resources/icons/legend_toolchanges.svg +++ b/resources/icons/legend_toolchanges.svg @@ -1,20 +1,10 @@ - - - - - - - - - - - - - + + + + + + + + + From 046f9d238062d69384aa5d58e33ea7692184af78 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 25 Nov 2021 09:46:52 +0100 Subject: [PATCH 26/66] ConfigWizard: Improved detection of the preferred printer technology when new printers are added --- src/slic3r/GUI/ConfigWizard.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 85268fca15..f674abd0c0 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -2522,23 +2522,33 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese { wxString header, caption = _L("Configuration is edited in ConfigWizard"); const auto enabled_vendors = appconfig_new.vendors(); + const auto enabled_vendors_old = app_config->vendors(); bool suppress_sla_printer = model_has_multi_part_objects(wxGetApp().model()); PrinterTechnology preferred_pt = ptAny; - auto get_preferred_printer_technology = [enabled_vendors, suppress_sla_printer](const std::string& bundle_name, const Bundle& bundle) { + auto get_preferred_printer_technology = [enabled_vendors, enabled_vendors_old, suppress_sla_printer](const std::string& bundle_name, const Bundle& bundle) { const auto config = enabled_vendors.find(bundle_name); PrinterTechnology pt = ptAny; if (config != enabled_vendors.end()) { for (const auto& model : bundle.vendor_profile->models) { if (const auto model_it = config->second.find(model.id); model_it != config->second.end() && model_it->second.size() > 0) { - if (pt == ptAny) - pt = model.technology; - // if preferred printer model has SLA printer technology it's important to check the model for multypart state - if (pt == ptSLA && suppress_sla_printer) - continue; - else + pt = model.technology; + const auto config_old = enabled_vendors_old.find(bundle_name); + if (config_old == enabled_vendors_old.end() || config_old->second.find(model.id) == config_old->second.end()) { + // if preferred printer model has SLA printer technology it's important to check the model for multi-part state + if (pt == ptSLA && suppress_sla_printer) + continue; return pt; + } + + if (const auto model_it_old = config_old->second.find(model.id); + model_it_old == config_old->second.end() || model_it_old->second != model_it->second) { + // if preferred printer model has SLA printer technology it's important to check the model for multi-part state + if (pt == ptSLA && suppress_sla_printer) + continue; + return pt; + } } } } @@ -2645,7 +2655,6 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese std::string preferred_model; std::string preferred_variant; - const auto enabled_vendors_old = app_config->vendors(); auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old, preferred_pt](const std::string& bundle_name, const Bundle& bundle, std::string& variant) { const auto config = enabled_vendors.find(bundle_name); if (config == enabled_vendors.end()) From 8bc442cd328ae41641d93a03244d4d2c84aac4d7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 29 Nov 2021 11:46:28 +0100 Subject: [PATCH 27/66] Tech ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT - 2nd click on edit button exits editing state in slider --- resources/icons/edit_button_pressed.svg | 91 ++++++++++++++++++++ src/imgui/imconfig.h | 23 +++--- src/slic3r/GUI/ImGuiWrapper.cpp | 105 ++++++++++++++++++------ src/slic3r/GUI/ImGuiWrapper.hpp | 3 +- 4 files changed, 186 insertions(+), 36 deletions(-) create mode 100644 resources/icons/edit_button_pressed.svg diff --git a/resources/icons/edit_button_pressed.svg b/resources/icons/edit_button_pressed.svg new file mode 100644 index 0000000000..6e4058d10f --- /dev/null +++ b/resources/icons/edit_button_pressed.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/imgui/imconfig.h b/src/imgui/imconfig.h index 27f5242a83..db0e54e60d 100644 --- a/src/imgui/imconfig.h +++ b/src/imgui/imconfig.h @@ -155,17 +155,18 @@ namespace ImGui const wchar_t ClippyMarker = 0x2602; const wchar_t InfoMarker = 0x2603; const wchar_t SliderFloatEditBtnIcon = 0x2604; - const wchar_t LegendTravel = 0x2605; - const wchar_t LegendWipe = 0x2606; - const wchar_t LegendRetract = 0x2607; - const wchar_t LegendDeretract = 0x2608; - const wchar_t LegendSeams = 0x2609; - const wchar_t LegendToolChanges = 0x2610; - const wchar_t LegendColorChanges = 0x2611; - const wchar_t LegendPausePrints = 0x2612; - const wchar_t LegendCustomGCodes = 0x2613; - const wchar_t LegendShells = 0x2614; - const wchar_t LegendToolMarker = 0x2615; + const wchar_t SliderFloatEditBtnPressedIcon = 0x2605; + const wchar_t LegendTravel = 0x2606; + const wchar_t LegendWipe = 0x2607; + const wchar_t LegendRetract = 0x2608; + const wchar_t LegendDeretract = 0x2609; + const wchar_t LegendSeams = 0x2610; + const wchar_t LegendToolChanges = 0x2611; + const wchar_t LegendColorChanges = 0x2612; + const wchar_t LegendPausePrints = 0x2613; + const wchar_t LegendCustomGCodes = 0x2614; + const wchar_t LegendShells = 0x2615; + const wchar_t LegendToolMarker = 0x2616; // void MyFunction(const char* name, const MyMatrix44& v); } diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index b4b37de839..00218af960 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -51,23 +51,24 @@ static const std::map font_icons = { {ImGui::MinimalizeHoverButton , "notification_minimalize_hover" }, {ImGui::RightArrowButton , "notification_right" }, {ImGui::RightArrowHoverButton , "notification_right_hover" }, - {ImGui::PreferencesButton , "notification_preferences" }, - {ImGui::PreferencesHoverButton , "notification_preferences_hover"}, + {ImGui::PreferencesButton , "notification_preferences" }, + {ImGui::PreferencesHoverButton, "notification_preferences_hover"}, #if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT - {ImGui::SliderFloatEditBtnIcon , "edit_button" }, + {ImGui::SliderFloatEditBtnIcon, "edit_button" }, + {ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" }, #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT #if ENABLE_LEGEND_TOOLBAR_ICONS - {ImGui::LegendTravel , "legend_travel" }, - {ImGui::LegendWipe , "legend_wipe" }, - {ImGui::LegendRetract , "legend_retract" }, - {ImGui::LegendDeretract , "legend_deretract" }, - {ImGui::LegendSeams , "legend_seams" }, - {ImGui::LegendToolChanges , "legend_toolchanges" }, - {ImGui::LegendColorChanges , "legend_colorchanges" }, - {ImGui::LegendPausePrints , "legend_pauseprints" }, - {ImGui::LegendCustomGCodes , "legend_customgcodes" }, - {ImGui::LegendShells , "legend_shells" }, - {ImGui::LegendToolMarker , "legend_toolmarker" }, + {ImGui::LegendTravel , "legend_travel" }, + {ImGui::LegendWipe , "legend_wipe" }, + {ImGui::LegendRetract , "legend_retract" }, + {ImGui::LegendDeretract , "legend_deretract" }, + {ImGui::LegendSeams , "legend_seams" }, + {ImGui::LegendToolChanges , "legend_toolchanges" }, + {ImGui::LegendColorChanges , "legend_colorchanges" }, + {ImGui::LegendPausePrints , "legend_pauseprints" }, + {ImGui::LegendCustomGCodes , "legend_customgcodes" }, + {ImGui::LegendShells , "legend_shells" }, + {ImGui::LegendToolMarker , "legend_toolmarker" }, #endif // ENABLE_LEGEND_TOOLBAR_ICONS }; static const std::map font_icons_large = { @@ -423,11 +424,6 @@ bool ImGuiWrapper::draw_radio_button(const std::string& name, float size, bool a } #endif // ENABLE_PREVIEW_LAYOUT -bool ImGuiWrapper::image_button() -{ - return false; -} - bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format) { return ImGui::InputDouble(label.c_str(), const_cast(&value), 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal); @@ -551,6 +547,9 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float ImGui::SameLine(); } + // the current slider edit state needs to be detected here before calling SliderFloat() + bool slider_editing = ImGui::GetCurrentWindow()->GetID(str_label.c_str()) == ImGui::GetActiveID(); + bool ret = ImGui::SliderFloat(str_label.c_str(), v, v_min, v_max, format, power); if (!tooltip.empty() && ImGui::IsItemHovered()) this->tooltip(into_u8(tooltip).c_str(), max_tooltip_width); @@ -562,15 +561,31 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float const ImGuiStyle& style = ImGui::GetStyle(); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 1, style.ItemSpacing.y }); ImGui::SameLine(); - std::wstring btn_name = ImGui::SliderFloatEditBtnIcon + boost::nowide::widen(str_label); + ImGuiIO& io = ImGui::GetIO(); + assert(io.Fonts->TexWidth > 0 && io.Fonts->TexHeight > 0); + float inv_tex_w = 1.0f / float(io.Fonts->TexWidth); + float inv_tex_h = 1.0f / float(io.Fonts->TexHeight); + + const ImFontAtlasCustomRect* const rect = GetTextureCustomRect(slider_editing ? ImGui::SliderFloatEditBtnPressedIcon : ImGui::SliderFloatEditBtnIcon); + const ImVec2 size = { float(rect->Width), float(rect->Height) }; + const ImVec2 uv0 = ImVec2(float(rect->X) * inv_tex_w, float(rect->Y) * inv_tex_h); + const ImVec2 uv1 = ImVec2(float(rect->X + rect->Width) * inv_tex_w, float(rect->Y + rect->Height) * inv_tex_h); + ImGui::PushStyleColor(ImGuiCol_Button, { 0.25f, 0.25f, 0.25f, 0.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.5f, 0.5f, 0.5f, 1.0f }); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.5f, 0.5f, 0.5f, 1.0f }); - if (ImGui::Button(into_u8(btn_name).c_str())) { - ImGui::SetKeyboardFocusHere(-1); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.4f, 0.4f, 0.4f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.4f, 0.4f, 0.4f, 1.0f }); + + const ImTextureID tex_id = io.Fonts->TexID; + if (image_button(tex_id, size, uv0, uv1, -1, ImVec4(0.0, 0.0, 0.0, 0.0), ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags_PressedOnClick)) { + if (!slider_editing) + ImGui::SetKeyboardFocusHere(-1); + else + ImGui::ClearActiveID(); this->set_requires_extra_frame(); } + ImGui::PopStyleColor(3); + if (ImGui::IsItemHovered()) this->tooltip(into_u8(_L("Edit")).c_str(), max_tooltip_width); @@ -590,6 +605,48 @@ bool ImGuiWrapper::slider_float(const wxString& label, float* v, float v_min, fl auto label_utf8 = into_u8(label); return this->slider_float(label_utf8.c_str(), v, v_min, v_max, format, power, clamp, tooltip, show_edit_btn); } + +static bool image_button_ex(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->SkipItems) + return false; + + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2); + ImGui::ItemSize(bb); + if (!ImGui::ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, flags); + + // Render + const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + ImGui::RenderNavHighlight(bb, id); + ImGui::RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding)); + if (bg_col.w > 0.0f) + window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, ImGui::GetColorU32(bg_col)); + window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, ImGui::GetColorU32(tint_col)); + + return pressed; +} + +bool ImGuiWrapper::image_button(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (window->SkipItems) + return false; + + // Default to using texture ID as ID. User can still push string/integer prefixes. + ImGui::PushID((void*)(intptr_t)user_texture_id); + const ImGuiID id = window->GetID("#image"); + ImGui::PopID(); + + const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : g.Style.FramePadding; + return image_button_ex(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col, flags); +} #else bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float v_max, const char* format/* = "%.3f"*/, float power/* = 1.0f*/, bool clamp /*= true*/) { diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index a4e25415c3..a1ecc6712f 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -86,7 +86,6 @@ public: #if ENABLE_PREVIEW_LAYOUT bool draw_radio_button(const std::string& name, float size, bool active, std::function draw_callback); #endif // ENABLE_PREVIEW_LAYOUT - bool image_button(); bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f"); bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f"); bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f"); @@ -109,6 +108,8 @@ public: bool slider_float(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true); bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true); bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true); + + bool image_button(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0.0, 0.0), const ImVec2& uv1 = ImVec2(1.0, 1.0), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0.0, 0.0, 0.0, 0.0), const ImVec4& tint_col = ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags flags = 0); #else bool slider_float(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true); bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true); From 5218570348b2c733abb9842467b06eeae5be650a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 29 Nov 2021 12:46:27 +0100 Subject: [PATCH 28/66] Follow-up of 8bc442cd328ae41641d93a03244d4d2c84aac4d7 - Commented out unused code and fixed build when tech ENABLE_LEGEND_TOOLBAR_ICONS is disabled --- src/slic3r/GUI/GCodeViewer.cpp | 28 +++++++++++++++++++--------- src/slic3r/GUI/ImGuiWrapper.cpp | 11 +++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index baad791071..ea4b72cf17 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4380,16 +4380,16 @@ void GCodeViewer::render_legend(float& legend_height) } }; - auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { - const float margin = 3.0f; - const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); - window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); - }; - auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { - const float margin = 3.0f; - window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); - }; #if ENABLE_LEGEND_TOOLBAR_ICONS +// auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { +// const float margin = 3.0f; +// const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); +// window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); +// }; +// auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { +// const float margin = 3.0f; +// window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); +// }; auto image_icon = [&imgui](ImGuiWindow& window, const ImVec2& pos, float size, const wchar_t& icon_id) { ImGuiIO& io = ImGui::GetIO(); const ImTextureID tex_id = io.Fonts->TexID; @@ -4400,6 +4400,16 @@ void GCodeViewer::render_legend(float& legend_height) const ImVec2 uv1 = { static_cast(rect->X + rect->Width) / tex_w, static_cast(rect->Y + rect->Height) / tex_h }; window.DrawList->AddImage(tex_id, pos, { pos.x + size, pos.y + size }, uv0, uv1, ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f })); }; +#else + auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { + const float margin = 3.0f; + const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size)); + window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); + }; + auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) { + const float margin = 3.0f; + window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); + }; #endif // ENABLE_LEGEND_TOOLBAR_ICONS ImGui::Spacing(); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 7d7282511f..48186cde91 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -561,6 +561,8 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float if (show_edit_btn) { ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 1, style.ItemSpacing.y }); ImGui::SameLine(); + +#if ENABLE_LEGEND_TOOLBAR_ICONS ImGuiIO& io = ImGui::GetIO(); assert(io.Fonts->TexWidth > 0 && io.Fonts->TexHeight > 0); float inv_tex_w = 1.0f / float(io.Fonts->TexWidth); @@ -570,11 +572,13 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float const ImVec2 size = { float(rect->Width), float(rect->Height) }; const ImVec2 uv0 = ImVec2(float(rect->X) * inv_tex_w, float(rect->Y) * inv_tex_h); const ImVec2 uv1 = ImVec2(float(rect->X + rect->Width) * inv_tex_w, float(rect->Y + rect->Height) * inv_tex_h); +#endif // ENABLE_LEGEND_TOOLBAR_ICONS ImGui::PushStyleColor(ImGuiCol_Button, { 0.25f, 0.25f, 0.25f, 0.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.4f, 0.4f, 0.4f, 1.0f }); ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.4f, 0.4f, 0.4f, 1.0f }); +#if ENABLE_LEGEND_TOOLBAR_ICONS const ImTextureID tex_id = io.Fonts->TexID; if (image_button(tex_id, size, uv0, uv1, -1, ImVec4(0.0, 0.0, 0.0, 0.0), ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags_PressedOnClick)) { if (!slider_editing) @@ -583,6 +587,13 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float ImGui::ClearActiveID(); this->set_requires_extra_frame(); } +#else + std::wstring btn_name = ImGui::SliderFloatEditBtnIcon + boost::nowide::widen(str_label); + if (ImGui::Button(into_u8(btn_name).c_str())) { + ImGui::SetKeyboardFocusHere(-1); + this->set_requires_extra_frame(); + } +#endif // ENABLE_LEGEND_TOOLBAR_ICONS ImGui::PopStyleColor(3); From 7ec7d5181a22601b273f5d332d35b2d180b74af5 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 8 Dec 2021 17:30:27 +0100 Subject: [PATCH 29/66] Updated tooltip on 'synchronize supports with object layers' --- src/libslic3r/PrintConfig.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 11e741ec61..b22d3b2409 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2751,7 +2751,8 @@ void PrintConfigDef::init_fff_params() def->label = L("Synchronize with object layers"); def->category = L("Support material"); def->tooltip = L("Synchronize support layers with the object print layers. This is useful " - "with multi-material printers, where the extruder switch is expensive."); + "with multi-material printers, where the extruder switch is expensive. " + "This option is only available when top contact Z distance is set to zero."); def->mode = comExpert; def->set_default_value(new ConfigOptionBool(false)); From 0d6f2df268add2d0e4d6cc44d3d4def6f321ce64 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 9 Dec 2021 09:00:58 +0100 Subject: [PATCH 30/66] Tech ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT - Fixed missing tooltips passed as parameter to ImGuiWrapper::slider_float --- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 691a867063..440e81356d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -549,9 +549,13 @@ RENDER_AGAIN: m_imgui->text(m_desc.at("offset")); ImGui::SameLine(settings_sliders_left, m_imgui->get_item_spacing().x); ImGui::PushItemWidth(window_width - settings_sliders_left); +#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT + m_imgui->slider_float("##offset", &offset, offset_min, offset_max, "%.1f mm", 1.0f, true, _L(opts[0].second->tooltip)); +#else m_imgui->slider_float("##offset", &offset, offset_min, offset_max, "%.1f mm"); if (m_imgui->get_last_slider_status().hovered) m_imgui->tooltip((_utf8(opts[0].second->tooltip)).c_str(), max_tooltip_width); +#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT bool slider_clicked = m_imgui->get_last_slider_status().clicked; // someone clicked the slider bool slider_edited =m_imgui->get_last_slider_status().edited; // someone is dragging the slider @@ -561,9 +565,13 @@ RENDER_AGAIN: ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("quality")); ImGui::SameLine(settings_sliders_left, m_imgui->get_item_spacing().x); +#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT + m_imgui->slider_float("##quality", &quality, quality_min, quality_max, "%.1f", 1.0f, true, _L(opts[1].second->tooltip)); +#else m_imgui->slider_float("##quality", &quality, quality_min, quality_max, "%.1f"); if (m_imgui->get_last_slider_status().hovered) m_imgui->tooltip((_utf8(opts[1].second->tooltip)).c_str(), max_tooltip_width); +#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT slider_clicked |= m_imgui->get_last_slider_status().clicked; slider_edited |= m_imgui->get_last_slider_status().edited; @@ -574,9 +582,13 @@ RENDER_AGAIN: ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("closing_distance")); ImGui::SameLine(settings_sliders_left, m_imgui->get_item_spacing().x); +#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT + m_imgui->slider_float("##closing_distance", &closing_d, closing_d_min, closing_d_max, "%.1f mm", 1.0f, true, _L(opts[2].second->tooltip)); +#else m_imgui->slider_float("##closing_distance", &closing_d, closing_d_min, closing_d_max, "%.1f mm"); if (m_imgui->get_last_slider_status().hovered) m_imgui->tooltip((_utf8(opts[2].second->tooltip)).c_str(), max_tooltip_width); +#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT slider_clicked |= m_imgui->get_last_slider_status().clicked; slider_edited |= m_imgui->get_last_slider_status().edited; From e3d5cd445c7ad74ceaa4e3872ec512a64cb074b8 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 10 Dec 2021 11:28:12 +0100 Subject: [PATCH 31/66] Gizmos refactoring - Removed GLModels defined into GLGizmoBase, and mostly unused, to avoid wasting GPU memory. Use a shared GLModel for Gizmos inheriting from GLGizmoPainterBase. Initialization of GLModels moved from constructor to render methods --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 9 ++------ src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 4 ---- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 10 +++++---- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 3 ++- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 8 ++++--- src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 19 +++++++++++++---- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 5 +++-- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 22 ++++---------------- src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 6 +++--- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 7 +++++++ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 4 ++++ 12 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 393be1a4e8..97ab7094c7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -50,13 +50,12 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const void GLGizmoBase::Grabber::render(float size, const std::array& render_color, bool picking) const { - if (! cube_initialized) { + if (!cube.is_initialized()) { // This cannot be done in constructor, OpenGL is not yet // initialized at that point (on Linux at least). indexed_triangle_set mesh = its_make_cube(1., 1., 1.); its_translate(mesh, Vec3f(-0.5, -0.5, -0.5)); const_cast(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); - const_cast(cube_initialized) = true; } float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); @@ -90,15 +89,11 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u m_base_color = DEFAULT_BASE_COLOR; m_drag_color = DEFAULT_DRAG_COLOR; m_highlight_color = DEFAULT_HIGHLIGHT_COLOR; - m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24)); - m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.)); - m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.)); } void GLGizmoBase::set_hover_id(int id) { - if (m_grabbers.empty() || (id < (int)m_grabbers.size())) - { + if (m_grabbers.empty() || id < (int)m_grabbers.size()) { m_hover_id = id; on_set_hover_id(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 66ca4fca27..1e2cd93fbb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -66,7 +66,6 @@ protected: void render(float size, const std::array& render_color, bool picking) const; GLModel cube; - bool cube_initialized = false; }; public: @@ -105,9 +104,6 @@ protected: bool m_first_input_window_render; mutable std::string m_tooltip; CommonGizmosDataPool* m_c; - GLModel m_cone; - GLModel m_cylinder; - GLModel m_sphere; public: GLGizmoBase(GLCanvas3D& parent, diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 440e81356d..a001d5a81c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -20,7 +20,6 @@ namespace GUI { GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) { - m_vbo_cylinder.init_from(its_make_cylinder(1., 1.)); } @@ -63,6 +62,9 @@ void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&) void GLGizmoHollow::on_render() { + if (!m_cylinder.is_initialized()) + m_cylinder.init_from(its_make_cylinder(1.0, 1.0)); + const Selection& selection = m_parent.get_selection(); const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info(); @@ -148,11 +150,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons } } - const_cast(&m_vbo_cylinder)->set_color(-1, render_color); + const_cast(&m_cylinder)->set_color(-1, render_color); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. glsafe(::glPushMatrix()); - glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2))); + glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z())); glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); if (vol->is_left_handed()) @@ -166,7 +168,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons glsafe(::glPushMatrix()); glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); - m_vbo_cylinder.render(); + m_cylinder.render(); glsafe(::glPopMatrix()); if (vol->is_left_handed()) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 2cf08de2a0..bc144c2973 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -48,7 +48,8 @@ private: ObjectID m_old_mo_id = -1; - GLModel m_vbo_cylinder; + GLModel m_cylinder; + float m_new_hole_radius = 2.f; // Size of a new hole. float m_new_hole_height = 6.f; mutable std::vector m_selected; // which holes are currently selected diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index e73a85647e..d16f0ff2d7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -20,7 +20,6 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam , m_starting_box_center(Vec3d::Zero()) , m_starting_box_bottom_center(Vec3d::Zero()) { - m_vbo_cone.init_from(its_make_cone(1., 1., 2*PI/36)); } std::string GLGizmoMove3D::get_tooltip() const @@ -89,6 +88,9 @@ void GLGizmoMove3D::on_update(const UpdateData& data) void GLGizmoMove3D::on_render() { + if (!m_cone.is_initialized()) + m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0)); + const Selection& selection = m_parent.get_selection(); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); @@ -205,7 +207,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box if (shader == nullptr) return; - const_cast(&m_vbo_cone)->set_color(-1, color); + const_cast(&m_cone)->set_color(-1, color); if (!picking) { shader->start_using(); shader->set_uniform("emission_factor", 0.1f); @@ -220,7 +222,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box glsafe(::glTranslated(0.0, 0.0, 2.0 * size)); glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size)); - m_vbo_cone.render(); + m_cone.render(); glsafe(::glPopMatrix()); if (! picking) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index baa2df7391..2d331bfb5c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -19,7 +19,7 @@ class GLGizmoMove3D : public GLGizmoBase Vec3d m_starting_box_center; Vec3d m_starting_box_bottom_center; - GLModel m_vbo_cone; + GLModel m_cone; public: GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 8b866c7c99..260e46563b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -18,13 +18,17 @@ namespace Slic3r::GUI { + std::shared_ptr GLGizmoPainterBase::s_sphere = nullptr; GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) { - // Make sphere and save it into a vertex buffer. - m_vbo_sphere.load_its_flat_shading(its_make_sphere(1., (2*M_PI)/24.)); - m_vbo_sphere.finalize_geometry(true); +} + +GLGizmoPainterBase::~GLGizmoPainterBase() +{ + if (s_sphere != nullptr && s_sphere->has_VBOs()) + s_sphere->release_geometry(); } void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection) @@ -184,6 +188,12 @@ void GLGizmoPainterBase::render_cursor_circle() const void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const { + if (s_sphere == nullptr) { + s_sphere = std::make_shared(); + s_sphere->load_its_flat_shading(its_make_sphere(1.0, double(PI) / 12.0)); + s_sphere->finalize_geometry(true); + } + const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse(); const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed(); @@ -204,7 +214,8 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const render_color = this->get_cursor_sphere_right_button_color(); glsafe(::glColor4fv(render_color.data())); - m_vbo_sphere.render(); + assert(s_sphere != nullptr); + s_sphere->render(); if (is_left_handed) glFrontFace(GL_CCW); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 97ac8e4e98..ea6760a17a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -12,6 +12,7 @@ #include #include +#include namespace Slic3r::GUI { @@ -112,7 +113,7 @@ private: void on_render_for_picking() override {} public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - ~GLGizmoPainterBase() override = default; + virtual ~GLGizmoPainterBase() override; virtual void set_painter_gizmo_data(const Selection& selection); virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); @@ -202,7 +203,7 @@ private: const Camera& camera, const std::vector& trafo_matrices) const; - GLIndexedVertexArray m_vbo_sphere; + static std::shared_ptr s_sphere; bool m_internal_stack_active = false; bool m_schedule_update = false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 61fe6e7095..a234a19ff9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -39,20 +39,6 @@ GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) { } -GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other) - : GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id) - , m_axis(other.m_axis) - , m_angle(other.m_angle) - , m_center(other.m_center) - , m_radius(other.m_radius) - , m_snap_coarse_in_radius(other.m_snap_coarse_in_radius) - , m_snap_coarse_out_radius(other.m_snap_coarse_out_radius) - , m_snap_fine_in_radius(other.m_snap_fine_in_radius) - , m_snap_fine_out_radius(other.m_snap_fine_out_radius) -{ -} - - void GLGizmoRotate::set_angle(double angle) { if (std::abs(angle - 2.0 * (double)PI) < EPSILON) @@ -130,6 +116,9 @@ void GLGizmoRotate::on_render() if (!m_grabbers[0].enabled) return; + if (!m_cone.is_initialized()) + m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0)); + const Selection& selection = m_parent.get_selection(); const BoundingBoxf3& box = selection.get_bounding_box(); @@ -433,11 +422,8 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) + , m_gizmos({ GLGizmoRotate(parent, GLGizmoRotate::X), GLGizmoRotate(parent, GLGizmoRotate::Y), GLGizmoRotate(parent, GLGizmoRotate::Z) }) { - m_gizmos.emplace_back(parent, GLGizmoRotate::X); - m_gizmos.emplace_back(parent, GLGizmoRotate::Y); - m_gizmos.emplace_back(parent, GLGizmoRotate::Z); - for (unsigned int i = 0; i < 3; ++i) { m_gizmos[i].set_group_id(i); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 3245c4dbe8..af1ecf548e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -4,7 +4,6 @@ #include "GLGizmoBase.hpp" #include "../Jobs/RotoptimizeJob.hpp" - namespace Slic3r { namespace GUI { @@ -40,9 +39,10 @@ private: mutable float m_snap_fine_in_radius; mutable float m_snap_fine_out_radius; + GLModel m_cone; + public: GLGizmoRotate(GLCanvas3D& parent, Axis axis); - GLGizmoRotate(const GLGizmoRotate& other); virtual ~GLGizmoRotate() = default; double get_angle() const { return m_angle; } @@ -74,7 +74,7 @@ private: class GLGizmoRotate3D : public GLGizmoBase { - std::vector m_gizmos; + std::array m_gizmos; public: GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 29e1fd2f30..51551281a4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -77,6 +77,13 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S void GLGizmoSlaSupports::on_render() { + if (!m_cone.is_initialized()) + m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0)); + if (!m_sphere.is_initialized()) + m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0)); + if (!m_cylinder.is_initialized()) + m_cylinder.init_from(its_make_cylinder(1.0, 1.0, double(PI) / 12.0)); + ModelObject* mo = m_c->selection_info()->model_object(); const Selection& selection = m_parent.get_selection(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 35e6a73089..92d085f378 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -91,6 +91,10 @@ private: std::vector m_normal_cache; // to restore after discarding changes or undo/redo ObjectID m_old_mo_id; + GLModel m_cone; + GLModel m_cylinder; + GLModel m_sphere; + // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. std::map m_desc; From 1376c9cffdb23351d35270ef5673ea98789dcaaf Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 10 Dec 2021 15:11:17 +0100 Subject: [PATCH 32/66] Updated deps-windows.cmake and Boost.cmake to be able to build dependencies using Visual Studio 2022 --- deps/Boost/Boost.cmake | 3 +++ deps/deps-windows.cmake | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/deps/Boost/Boost.cmake b/deps/Boost/Boost.cmake index ae2bd96466..ec8bab799c 100644 --- a/deps/Boost/Boost.cmake +++ b/deps/Boost/Boost.cmake @@ -28,6 +28,9 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") elseif (MSVC_VERSION LESS 1930) # 1920-1929 = VS 16.0 (v142 toolset) set(_boost_toolset "msvc-14.2") + elseif (MSVC_VERSION LESS 1940) + # 1930-1939 = VS 17.0 (v143 toolset) + set(_boost_toolset "msvc-14.3") else () message(FATAL_ERROR "Unsupported MSVC version") endif () diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index 7288cfe6fa..aba6fcab49 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -15,6 +15,10 @@ elseif (MSVC_VERSION LESS 1930) # 1920-1929 = VS 16.0 (v142 toolset) set(DEP_VS_VER "16") set(DEP_BOOST_TOOLSET "msvc-14.2") +elseif (MSVC_VERSION LESS 1940) +# 1930-1939 = VS 17.0 (v143 toolset) + set(DEP_VS_VER "17") + set(DEP_BOOST_TOOLSET "msvc-14.3") else () message(FATAL_ERROR "Unsupported MSVC version") endif () From 6204d107eef946f42fdac8dcc4e2d38e700aac49 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 10 Dec 2021 15:41:35 +0100 Subject: [PATCH 33/66] Added missing include --- src/slic3r/GUI/fts_fuzzy_match.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/fts_fuzzy_match.h b/src/slic3r/GUI/fts_fuzzy_match.h index 379fd9c74e..29dd348356 100644 --- a/src/slic3r/GUI/fts_fuzzy_match.h +++ b/src/slic3r/GUI/fts_fuzzy_match.h @@ -33,6 +33,7 @@ #include // uint8_t #include // ::tolower, ::toupper +#include // std::towlower, std::towupper #include // memcpy #include From 296041da38273fbf0053d6e338bf5a2bb51d030d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 14 Dec 2021 10:21:31 +0100 Subject: [PATCH 34/66] #7464 - Fixed 'Export as .stl' scaling not applied on scaled object instances --- src/slic3r/GUI/Plater.cpp | 62 ++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b3ec464256..89d74f7bb5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5707,23 +5707,26 @@ void Plater::export_stl(bool extended, bool selection_only) return; // Following lambda generates a combined mesh for export with normals pointing outwards. - auto mesh_to_export = [](const ModelObject* mo, bool instances) -> TriangleMesh { + auto mesh_to_export = [](const ModelObject& mo, int instance_id) { TriangleMesh mesh; - for (const ModelVolume *v : mo->volumes) + for (const ModelVolume* v : mo.volumes) if (v->is_model_part()) { TriangleMesh vol_mesh(v->mesh()); vol_mesh.transform(v->get_matrix(), true); mesh.merge(vol_mesh); } - if (instances) { + if (instance_id == -1) { TriangleMesh vols_mesh(mesh); mesh = TriangleMesh(); - for (const ModelInstance *i : mo->instances) { + for (const ModelInstance* i : mo.instances) { TriangleMesh m = vols_mesh; m.transform(i->get_matrix(), true); mesh.merge(m); } } + else if (0 <= instance_id && instance_id < mo.instances.size()) + mesh.transform(mo.instances[instance_id]->get_matrix(), true); + return mesh; }; @@ -5732,14 +5735,8 @@ void Plater::export_stl(bool extended, bool selection_only) if (selection_only) { const ModelObject* model_object = p->model.objects[obj_idx]; if (selection.get_mode() == Selection::Instance) - { - if (selection.is_single_full_object()) - mesh = mesh_to_export(model_object, true); - else - mesh = mesh_to_export(model_object, false); - } - else - { + mesh = selection.is_single_full_object() ? mesh_to_export(*model_object, -1) : mesh_to_export(*model_object, selection.get_instance_idx()); + else { const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); mesh = model_object->volumes[volume->volume_idx()]->mesh(); mesh.transform(volume->get_volume_transformation().get_matrix(), true); @@ -5747,69 +5744,62 @@ void Plater::export_stl(bool extended, bool selection_only) } } else { - for (const ModelObject *o : p->model.objects) - mesh.merge(mesh_to_export(o, true)); + for (const ModelObject* o : p->model.objects) { + mesh.merge(mesh_to_export(*o, -1)); + } } } - else - { + else { // This is SLA mode, all objects have only one volume. // However, we must have a look at the backend to load // hollowed mesh and/or supports const PrintObjects& objects = p->sla_print.objects(); - for (const SLAPrintObject* object : objects) - { + for (const SLAPrintObject* object : objects) { const ModelObject* model_object = object->model_object(); if (selection_only) { if (model_object->id() != p->model.objects[obj_idx]->id()) continue; } - Transform3d mesh_trafo_inv = object->trafo().inverse(); - bool is_left_handed = object->is_left_handed(); + const Transform3d mesh_trafo_inv = object->trafo().inverse(); + const bool is_left_handed = object->is_left_handed(); TriangleMesh pad_mesh; - bool has_pad_mesh = extended && object->has_mesh(slaposPad); - if (has_pad_mesh) - { + const bool has_pad_mesh = extended && object->has_mesh(slaposPad); + if (has_pad_mesh) { pad_mesh = object->get_mesh(slaposPad); pad_mesh.transform(mesh_trafo_inv); } TriangleMesh supports_mesh; - bool has_supports_mesh = extended && object->has_mesh(slaposSupportTree); - if (has_supports_mesh) - { + const bool has_supports_mesh = extended && object->has_mesh(slaposSupportTree); + if (has_supports_mesh) { supports_mesh = object->get_mesh(slaposSupportTree); supports_mesh.transform(mesh_trafo_inv); } const std::vector& obj_instances = object->instances(); - for (const SLAPrintObject::Instance& obj_instance : obj_instances) - { + for (const SLAPrintObject::Instance& obj_instance : obj_instances) { auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(), [&obj_instance](const ModelInstance *mi) { return mi->id() == obj_instance.instance_id; }); assert(it != model_object->instances.end()); - if (it != model_object->instances.end()) - { - bool one_inst_only = selection_only && ! selection.is_single_full_object(); + if (it != model_object->instances.end()) { + const bool one_inst_only = selection_only && ! selection.is_single_full_object(); - int instance_idx = it - model_object->instances.begin(); + const int instance_idx = it - model_object->instances.begin(); const Transform3d& inst_transform = one_inst_only ? Transform3d::Identity() : object->model_object()->instances[instance_idx]->get_transformation().get_matrix(); TriangleMesh inst_mesh; - if (has_pad_mesh) - { + if (has_pad_mesh) { TriangleMesh inst_pad_mesh = pad_mesh; inst_pad_mesh.transform(inst_transform, is_left_handed); inst_mesh.merge(inst_pad_mesh); } - if (has_supports_mesh) - { + if (has_supports_mesh) { TriangleMesh inst_supports_mesh = supports_mesh; inst_supports_mesh.transform(inst_transform, is_left_handed); inst_mesh.merge(inst_supports_mesh); From 9e88eb09b51f95e676486ed072153393a6c9d1aa Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Wed, 15 Dec 2021 14:22:27 +0100 Subject: [PATCH 35/66] add VS filter by subdir --- src/libslic3r/CMakeLists.txt | 10 +++++++++- src/slic3r/CMakeLists.txt | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index deaa0b9241..97d1d5ce5c 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -14,7 +14,7 @@ if (TARGET OpenVDB::openvdb) set(OpenVDBUtils_SOURCES OpenVDBUtils.cpp OpenVDBUtils.hpp) endif() -add_library(libslic3r STATIC +set(SLIC3R_SOURCES pchheader.cpp pchheader.hpp BoundingBox.cpp @@ -291,6 +291,14 @@ add_library(libslic3r STATIC SLA/ReprojectPointsOnMesh.hpp ) +add_library(libslic3r STATIC ${SLIC3R_SOURCES}) + +foreach(_source IN ITEMS ${SLIC3R_SOURCES}) + get_filename_component(_source_path "${_source}" PATH) + string(REPLACE "/" "\\" _group_path "${_source_path}") + source_group("${_group_path}" FILES "${_source}") +endforeach() + if (SLIC3R_STATIC) set(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE) endif () diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 34cc980513..211a2c2e7a 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -258,6 +258,12 @@ endif () add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES}) +foreach(_source IN ITEMS ${SLIC3R_GUI_SOURCES}) + get_filename_component(_source_path "${_source}" PATH) + string(REPLACE "/" "\\" _group_path "${_source_path}") + source_group("${_group_path}" FILES "${_source}") +endforeach() + encoding_check(libslic3r_gui) target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES}) From c30f5823f5b86e486abab9e84dabbd8e89e7c4f1 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 15 Dec 2021 14:55:21 +0100 Subject: [PATCH 36/66] Refactoring of GLShaderProgram::set_uniform() methods --- src/slic3r/GUI/GCodeViewer.cpp | 6 +- src/slic3r/GUI/GLShader.cpp | 140 +++++++++++---------------------- src/slic3r/GUI/GLShader.hpp | 49 ++++++++---- 3 files changed, 81 insertions(+), 114 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 6b9ba5da9a..42dd0954b1 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2661,7 +2661,7 @@ void GCodeViewer::render_toolpaths() // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. assert(! path.sizes.empty()); assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); + shader.set_uniform(uniform_color, path.color); glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_points_calls_count; @@ -2685,7 +2685,7 @@ void GCodeViewer::render_toolpaths() // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. assert(! path.sizes.empty()); assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); + shader.set_uniform(uniform_color, path.color); glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_lines_calls_count; @@ -2703,7 +2703,7 @@ void GCodeViewer::render_toolpaths() // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. assert(! path.sizes.empty()); assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); + shader.set_uniform(uniform_color, path.color); glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_triangles_calls_count; diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index 9c1e936525..4c36efdd92 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -206,154 +206,104 @@ void GLShaderProgram::stop_using() const glsafe(::glUseProgram(0)); } -bool GLShaderProgram::set_uniform(const char* name, int value) const +void GLShaderProgram::set_uniform(int id, int value) const { - int id = get_uniform_location(name); - if (id >= 0) { - glsafe(::glUniform1i(id, static_cast(value))); - return true; - } - return false; + if (id >= 0) + glsafe(::glUniform1i(id, value)); } -bool GLShaderProgram::set_uniform(const char* name, bool value) const +void GLShaderProgram::set_uniform(int id, bool value) const { - return set_uniform(name, value ? 1 : 0); + set_uniform(id, value ? 1 : 0); } -bool GLShaderProgram::set_uniform(const char* name, float value) const +void GLShaderProgram::set_uniform(int id, float value) const { - int id = get_uniform_location(name); - if (id >= 0) { - glsafe(::glUniform1f(id, static_cast(value))); - return true; - } - return false; + if (id >= 0) + glsafe(::glUniform1f(id, value)); } -bool GLShaderProgram::set_uniform(const char* name, double value) const +void GLShaderProgram::set_uniform(int id, double value) const { - return set_uniform(name, static_cast(value)); + set_uniform(id, static_cast(value)); } -bool GLShaderProgram::set_uniform(const char* name, const std::array& value) const +void GLShaderProgram::set_uniform(int id, const std::array& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform2iv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const std::array& value) const +void GLShaderProgram::set_uniform(int id, const std::array& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform3iv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const std::array& value) const +void GLShaderProgram::set_uniform(int id, const std::array& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform4iv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const std::array& value) const +void GLShaderProgram::set_uniform(int id, const std::array& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform2fv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const std::array& value) const +void GLShaderProgram::set_uniform(int id, const std::array& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform3fv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const std::array& value) const +void GLShaderProgram::set_uniform(int id, const std::array& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform4fv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const float* value, size_t size) const +void GLShaderProgram::set_uniform(int id, const float* value, size_t size) const { - if (size == 1) - return set_uniform(name, value[0]); - else if (size < 5) { - int id = get_uniform_location(name); - if (id >= 0) { - if (size == 2) - glsafe(::glUniform2fv(id, 1, static_cast(value))); - else if (size == 3) - glsafe(::glUniform3fv(id, 1, static_cast(value))); - else - glsafe(::glUniform4fv(id, 1, static_cast(value))); - - return true; - } - } - return false; -} - -bool GLShaderProgram::set_uniform(const char* name, const Transform3f& value) const -{ - int id = get_uniform_location(name); if (id >= 0) { + if (size == 1) + set_uniform(id, value[0]); + else if (size == 2) + glsafe(::glUniform2fv(id, 1, static_cast(value))); + else if (size == 3) + glsafe(::glUniform3fv(id, 1, static_cast(value))); + else if (size == 4) + glsafe(::glUniform4fv(id, 1, static_cast(value))); + } +} + +void GLShaderProgram::set_uniform(int id, const Transform3f& value) const +{ + if (id >= 0) glsafe(::glUniformMatrix4fv(id, 1, GL_FALSE, static_cast(value.matrix().data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const Transform3d& value) const +void GLShaderProgram::set_uniform(int id, const Transform3d& value) const { - return set_uniform(name, value.cast()); + set_uniform(id, value.cast()); } -bool GLShaderProgram::set_uniform(const char* name, const Matrix3f& value) const +void GLShaderProgram::set_uniform(int id, const Matrix3f& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniformMatrix3fv(id, 1, GL_FALSE, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const Vec3f& value) const +void GLShaderProgram::set_uniform(int id, const Vec3f& value) const { - int id = get_uniform_location(name); - if (id >= 0) { + if (id >= 0) glsafe(::glUniform3fv(id, 1, static_cast(value.data()))); - return true; - } - return false; } -bool GLShaderProgram::set_uniform(const char* name, const Vec3d& value) const +void GLShaderProgram::set_uniform(int id, const Vec3d& value) const { - return set_uniform(name, static_cast(value.cast())); + set_uniform(id, static_cast(value.cast())); } int GLShaderProgram::get_attrib_location(const char* name) const diff --git a/src/slic3r/GUI/GLShader.hpp b/src/slic3r/GUI/GLShader.hpp index d7b92000df..46e46b4f08 100644 --- a/src/slic3r/GUI/GLShader.hpp +++ b/src/slic3r/GUI/GLShader.hpp @@ -44,22 +44,39 @@ public: void start_using() const; void stop_using() const; - bool set_uniform(const char* name, int value) const; - bool set_uniform(const char* name, bool value) const; - bool set_uniform(const char* name, float value) const; - bool set_uniform(const char* name, double value) const; - bool set_uniform(const char* name, const std::array& value) const; - bool set_uniform(const char* name, const std::array& value) const; - bool set_uniform(const char* name, const std::array& value) const; - bool set_uniform(const char* name, const std::array& value) const; - bool set_uniform(const char* name, const std::array& value) const; - bool set_uniform(const char* name, const std::array& value) const; - bool set_uniform(const char* name, const float* value, size_t size) const; - bool set_uniform(const char* name, const Transform3f& value) const; - bool set_uniform(const char* name, const Transform3d& value) const; - bool set_uniform(const char* name, const Matrix3f& value) const; - bool set_uniform(const char* name, const Vec3f& value) const; - bool set_uniform(const char* name, const Vec3d& value) const; + void set_uniform(const char* name, int value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, bool value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, float value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, double value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const float* value, size_t size) const { set_uniform(get_uniform_location(name), value, size); } + void set_uniform(const char* name, const Transform3f& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const Transform3d& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const Matrix3f& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const Vec3f& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const Vec3d& value) const { set_uniform(get_uniform_location(name), value); } + + void set_uniform(int id, int value) const; + void set_uniform(int id, bool value) const; + void set_uniform(int id, float value) const; + void set_uniform(int id, double value) const; + void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const float* value, size_t size) const; + void set_uniform(int id, const Transform3f& value) const; + void set_uniform(int id, const Transform3d& value) const; + void set_uniform(int id, const Matrix3f& value) const; + void set_uniform(int id, const Vec3f& value) const; + void set_uniform(int id, const Vec3d& value) const; // returns -1 if not found int get_attrib_location(const char* name) const; From cd4094743e57d0d9f3947068c48deae4c03b354b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Dec 2021 10:45:35 +0100 Subject: [PATCH 37/66] Tech ENABLE_COLOR_CLASSES - 1st installment -> Introduction of classes ColorRGB and ColorRGBA to unify color data definition and manipulation --- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/Color.cpp | 402 ++++++++++++++++++ src/libslic3r/Color.hpp | 174 ++++++++ src/libslic3r/Technologies.hpp | 9 + src/slic3r/GUI/3DBed.cpp | 27 ++ src/slic3r/GUI/3DScene.cpp | 117 ++++- src/slic3r/GUI/3DScene.hpp | 43 +- src/slic3r/GUI/AboutDialog.cpp | 19 +- src/slic3r/GUI/BitmapCache.cpp | 2 + src/slic3r/GUI/BitmapCache.hpp | 13 +- src/slic3r/GUI/ConfigSnapshotDialog.cpp | 7 + src/slic3r/GUI/ConfigWizard.cpp | 9 + src/slic3r/GUI/DoubleSlider.cpp | 56 ++- src/slic3r/GUI/DoubleSlider.hpp | 4 + src/slic3r/GUI/DoubleSlider_Utils.hpp | 12 +- src/slic3r/GUI/Field.cpp | 6 +- src/slic3r/GUI/GCodeViewer.cpp | 198 ++++++++- src/slic3r/GUI/GCodeViewer.hpp | 46 ++ src/slic3r/GUI/GLCanvas3D.cpp | 103 ++++- src/slic3r/GUI/GLCanvas3D.hpp | 2 + src/slic3r/GUI/GLModel.cpp | 18 + src/slic3r/GUI/GLModel.hpp | 15 + src/slic3r/GUI/GLShader.cpp | 15 + src/slic3r/GUI/GLShader.hpp | 13 + src/slic3r/GUI/GUI_App.cpp | 11 + src/slic3r/GUI/GUI_Utils.hpp | 2 + src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 32 +- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 35 ++ src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 13 + src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 2 + src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 12 + src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 22 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 70 ++- .../GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 20 + src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 14 + src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 28 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 9 + src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 18 + src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 32 ++ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 8 + src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 5 + src/slic3r/GUI/ImGuiWrapper.cpp | 46 +- src/slic3r/GUI/ImGuiWrapper.hpp | 16 +- src/slic3r/GUI/MsgDialog.cpp | 8 + src/slic3r/GUI/PresetComboBoxes.cpp | 27 +- src/slic3r/GUI/Selection.cpp | 33 +- src/slic3r/GUI/SendSystemInfoDialog.cpp | 9 +- src/slic3r/GUI/SysInfoDialog.cpp | 8 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 12 + src/slic3r/GUI/WipeTowerDialog.cpp | 10 + src/slic3r/GUI/wxExtensions.cpp | 14 + tests/libslic3r/CMakeLists.txt | 1 + tests/libslic3r/test_color.cpp | 41 ++ 53 files changed, 1810 insertions(+), 60 deletions(-) create mode 100644 src/libslic3r/Color.cpp create mode 100644 src/libslic3r/Color.hpp create mode 100644 tests/libslic3r/test_color.cpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index deaa0b9241..f398c3ba76 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -29,6 +29,8 @@ add_library(libslic3r STATIC clipper.hpp ClipperUtils.cpp ClipperUtils.hpp + Color.cpp + Color.hpp Config.cpp Config.hpp EdgeGrid.cpp diff --git a/src/libslic3r/Color.cpp b/src/libslic3r/Color.cpp new file mode 100644 index 0000000000..d0437b6816 --- /dev/null +++ b/src/libslic3r/Color.cpp @@ -0,0 +1,402 @@ +#include "libslic3r.h" +#include "Color.hpp" + +#include + +#if ENABLE_COLOR_CLASSES +static const float INV_255 = 1.0f / 255.0f; + +namespace Slic3r { + +// Conversion from RGB to HSV color space +// The input RGB values are in the range [0, 1] +// The output HSV values are in the ranges h = [0, 360], and s, v = [0, 1] +static void RGBtoHSV(float r, float g, float b, float& h, float& s, float& v) +{ + assert(0.0f <= r && r <= 1.0f); + assert(0.0f <= g && g <= 1.0f); + assert(0.0f <= b && b <= 1.0f); + + const float max_comp = std::max(std::max(r, g), b); + const float min_comp = std::min(std::min(r, g), b); + const float delta = max_comp - min_comp; + + if (delta > 0.0f) { + if (max_comp == r) + h = 60.0f * (std::fmod(((g - b) / delta), 6.0f)); + else if (max_comp == g) + h = 60.0f * (((b - r) / delta) + 2.0f); + else if (max_comp == b) + h = 60.0f * (((r - g) / delta) + 4.0f); + + s = (max_comp > 0.0f) ? delta / max_comp : 0.0f; + } + else { + h = 0.0f; + s = 0.0f; + } + v = max_comp; + + while (h < 0.0f) { h += 360.0f; } + while (h > 360.0f) { h -= 360.0f; } + + assert(0.0f <= s && s <= 1.0f); + assert(0.0f <= v && v <= 1.0f); + assert(0.0f <= h && h <= 360.0f); +} + +// Conversion from HSV to RGB color space +// The input HSV values are in the ranges h = [0, 360], and s, v = [0, 1] +// The output RGB values are in the range [0, 1] +static void HSVtoRGB(float h, float s, float v, float& r, float& g, float& b) +{ + assert(0.0f <= s && s <= 1.0f); + assert(0.0f <= v && v <= 1.0f); + assert(0.0f <= h && h <= 360.0f); + + const float chroma = v * s; + const float h_prime = std::fmod(h / 60.0f, 6.0f); + const float x = chroma * (1.0f - std::abs(std::fmod(h_prime, 2.0f) - 1.0f)); + const float m = v - chroma; + + if (0.0f <= h_prime && h_prime < 1.0f) { + r = chroma; + g = x; + b = 0.0f; + } + else if (1.0f <= h_prime && h_prime < 2.0f) { + r = x; + g = chroma; + b = 0.0f; + } + else if (2.0f <= h_prime && h_prime < 3.0f) { + r = 0.0f; + g = chroma; + b = x; + } + else if (3.0f <= h_prime && h_prime < 4.0f) { + r = 0.0f; + g = x; + b = chroma; + } + else if (4.0f <= h_prime && h_prime < 5.0f) { + r = x; + g = 0.0f; + b = chroma; + } + else if (5.0f <= h_prime && h_prime < 6.0f) { + r = chroma; + g = 0.0f; + b = x; + } + else { + r = 0.0f; + g = 0.0f; + b = 0.0f; + } + + r += m; + g += m; + b += m; + + assert(0.0f <= r && r <= 1.0f); + assert(0.0f <= g && g <= 1.0f); + assert(0.0f <= b && b <= 1.0f); +} + +class Randomizer +{ + std::random_device m_rd; + +public: + float random_float(float min, float max) { + std::mt19937 rand_generator(m_rd()); + std::uniform_real_distribution distrib(min, max); + return distrib(rand_generator); + } +}; + +ColorRGB::ColorRGB(float r, float g, float b) +: m_data({ std::clamp(r, 0.0f, 1.0f), std::clamp(g, 0.0f, 1.0f), std::clamp(b, 0.0f, 1.0f) }) +{ +} + +ColorRGB::ColorRGB(unsigned char r, unsigned char g, unsigned char b) +: m_data({ std::clamp(r * INV_255, 0.0f, 1.0f), std::clamp(g * INV_255, 0.0f, 1.0f), std::clamp(b * INV_255, 0.0f, 1.0f) }) +{ +} + +bool ColorRGB::operator < (const ColorRGB& other) const +{ + for (size_t i = 0; i < 3; ++i) { + if (m_data[i] < other.m_data[i]) + return true; + } + + return false; +} + +bool ColorRGB::operator > (const ColorRGB& other) const +{ + for (size_t i = 0; i < 3; ++i) { + if (m_data[i] > other.m_data[i]) + return true; + } + + return false; +} + +ColorRGB ColorRGB::operator + (const ColorRGB& other) const +{ + ColorRGB ret; + for (size_t i = 0; i < 3; ++i) { + ret.m_data[i] = std::clamp(m_data[i] + other.m_data[i], 0.0f, 1.0f); + } + return ret; +} + +ColorRGB ColorRGB::operator * (float value) const +{ + assert(value >= 0.0f); + ColorRGB ret; + for (size_t i = 0; i < 3; ++i) { + ret.m_data[i] = std::clamp(value * m_data[i], 0.0f, 1.0f); + } + return ret; +} + +ColorRGBA::ColorRGBA(float r, float g, float b, float a) +: m_data({ std::clamp(r, 0.0f, 1.0f), std::clamp(g, 0.0f, 1.0f), std::clamp(b, 0.0f, 1.0f), std::clamp(a, 0.0f, 1.0f) }) +{ +} + +ColorRGBA::ColorRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +: m_data({ std::clamp(r * INV_255, 0.0f, 1.0f), std::clamp(g * INV_255, 0.0f, 1.0f), std::clamp(b * INV_255, 0.0f, 1.0f), std::clamp(a * INV_255, 0.0f, 1.0f) }) +{ +} + +bool ColorRGBA::operator < (const ColorRGBA& other) const +{ + for (size_t i = 0; i < 3; ++i) { + if (m_data[i] < other.m_data[i]) + return true; + } + + return false; +} + +bool ColorRGBA::operator > (const ColorRGBA& other) const +{ + for (size_t i = 0; i < 3; ++i) { + if (m_data[i] > other.m_data[i]) + return true; + } + + return false; +} + +ColorRGBA ColorRGBA::operator + (const ColorRGBA& other) const +{ + ColorRGBA ret; + for (size_t i = 0; i < 3; ++i) { + ret.m_data[i] = std::clamp(m_data[i] + other.m_data[i], 0.0f, 1.0f); + } + return ret; +} + +ColorRGBA ColorRGBA::operator * (float value) const +{ + assert(value >= 0.0f); + ColorRGBA ret; + for (size_t i = 0; i < 3; ++i) { + ret.m_data[i] = std::clamp(value * m_data[i], 0.0f, 1.0f); + } + ret.m_data[3] = this->m_data[3]; + return ret; +} + +ColorRGB operator * (float value, const ColorRGB& other) { return other * value; } +ColorRGBA operator * (float value, const ColorRGBA& other) { return other * value; } + +ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t) +{ + assert(0.0f <= t && t <= 1.0f); + return (1.0f - t) * a + t * b; +} + +ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t) +{ + assert(0.0f <= t && t <= 1.0f); + return (1.0f - t) * a + t * b; +} + +ColorRGB complementary(const ColorRGB& color) +{ + return { 1.0f - color.r(), 1.0f - color.g(), 1.0f - color.b() }; +} + +ColorRGBA complementary(const ColorRGBA& color) +{ + return { 1.0f - color.r(), 1.0f - color.g(), 1.0f - color.b(), color.a() }; +} + +ColorRGB saturate(const ColorRGB& color, float factor) +{ + float h, s, v; + RGBtoHSV(color.r(), color.g(), color.b(), h, s, v); + s = std::clamp(s * factor, 0.0f, 1.0f); + float r, g, b; + HSVtoRGB(h, s, v, r, g, b); + return { r, g, b }; +} + +ColorRGBA saturate(const ColorRGBA& color, float factor) +{ + return to_rgba(saturate(to_rgb(color), factor), color.a()); +} + +ColorRGB opposite(const ColorRGB& color) +{ + float h, s, v; + RGBtoHSV(color.r(), color.g(), color.b(), h, s, v); + + h += 65.0f; // 65 instead 60 to avoid circle values + if (h > 360.0f) + h -= 360.0f; + + Randomizer rnd; + s = rnd.random_float(0.65f, 1.0f); + v = rnd.random_float(0.65f, 1.0f); + + float r, g, b; + HSVtoRGB(h, s, v, r, g, b); + return { r, g, b }; +} + +ColorRGB opposite(const ColorRGB& a, const ColorRGB& b) +{ + float ha, sa, va; + RGBtoHSV(a.r(), a.g(), a.b(), ha, sa, va); + float hb, sb, vb; + RGBtoHSV(b.r(), b.g(), b.b(), hb, sb, vb); + + float delta_h = std::abs(ha - hb); + float start_h = (delta_h > 180.0f) ? std::min(ha, hb) : std::max(ha, hb); + + start_h += 5.0f; // to avoid circle change of colors for 120 deg + if (delta_h < 180.0f) + delta_h = 360.0f - delta_h; + + Randomizer rnd; + float out_h = start_h + 0.5f * delta_h; + if (out_h > 360.0f) + out_h -= 360.0f; + float out_s = rnd.random_float(0.65f, 1.0f); + float out_v = rnd.random_float(0.65f, 1.0f); + + float out_r, out_g, out_b; + HSVtoRGB(out_h, out_s, out_v, out_r, out_g, out_b); + return { out_r, out_g, out_b }; +} + +bool can_decode_color(const std::string& color) { return color.size() == 7 && color.front() == '#'; } + +bool decode_color(const std::string& color_in, ColorRGB& color_out) +{ + auto hex_digit_to_int = [](const char c) { + return + (c >= '0' && c <= '9') ? int(c - '0') : + (c >= 'A' && c <= 'F') ? int(c - 'A') + 10 : + (c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1; + }; + + color_out = ColorRGB::BLACK(); + if (can_decode_color(color_in)) { + const char* c = color_in.data() + 1; + for (unsigned int i = 0; i < 3; ++i) { + const int digit1 = hex_digit_to_int(*c++); + const int digit2 = hex_digit_to_int(*c++); + if (digit1 != -1 && digit2 != -1) + color_out.set(i, float(digit1 * 16 + digit2) * INV_255); + } + } + else + return false; + + assert(0.0f <= color_out.r() && color_out.r() <= 1.0f); + assert(0.0f <= color_out.g() && color_out.g() <= 1.0f); + assert(0.0f <= color_out.b() && color_out.b() <= 1.0f); + return true; +} + +bool decode_color(const std::string& color_in, ColorRGBA& color_out) +{ + ColorRGB rgb; + if (!decode_color(color_in, rgb)) + return false; + + color_out = to_rgba(rgb, color_out.a()); + return true; +} + +bool decode_colors(const std::vector& colors_in, std::vector& colors_out) +{ + colors_out = std::vector(colors_in.size(), ColorRGB::BLACK()); + for (size_t i = 0; i < colors_in.size(); ++i) { + if (!decode_color(colors_in[i], colors_out[i])) + return false; + } + return true; +} + +bool decode_colors(const std::vector& colors_in, std::vector& colors_out) +{ + colors_out = std::vector(colors_in.size(), ColorRGBA::BLACK()); + for (size_t i = 0; i < colors_in.size(); ++i) { + if (!decode_color(colors_in[i], colors_out[i])) + return false; + } + return true; +} + +std::string encode_color(const ColorRGB& color) +{ + char buffer[64]; + ::sprintf(buffer, "#%02X%02X%02X", color.r_uchar(), color.g_uchar(), color.b_uchar()); + return std::string(buffer); +} + +std::string encode_color(const ColorRGBA& color) { return encode_color(to_rgb(color)); } + +ColorRGB to_rgb(const ColorRGBA& other_rgba) { return { other_rgba.r(), other_rgba.g(), other_rgba.b() }; } +ColorRGBA to_rgba(const ColorRGB& other_rgb) { return { other_rgb.r(), other_rgb.g(), other_rgb.b(), 1.0f }; } +ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha) { return { other_rgb.r(), other_rgb.g(), other_rgb.b(), alpha }; } + +ColorRGBA picking_decode(unsigned int id) +{ + return { + float((id >> 0) & 0xff) * INV_255, // red + float((id >> 8) & 0xff) * INV_255, // green + float((id >> 16) & 0xff) * INV_255, // blue + float(picking_checksum_alpha_channel(id & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff)) * INV_255 // checksum for validating against unwanted alpha blending and multi sampling + }; +} + +unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b) { return r + (g << 8) + (b << 16); } + +unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue) +{ + // 8 bit hash for the color + unsigned char b = ((((37 * red) + green) & 0x0ff) * 37 + blue) & 0x0ff; + // Increase enthropy by a bit reversal + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + // Flip every second bit to increase the enthropy even more. + b ^= 0x55; + return b; +} + +} // namespace Slic3r + +#endif // ENABLE_COLOR_CLASSES diff --git a/src/libslic3r/Color.hpp b/src/libslic3r/Color.hpp new file mode 100644 index 0000000000..7ad10fec57 --- /dev/null +++ b/src/libslic3r/Color.hpp @@ -0,0 +1,174 @@ +#ifndef slic3r_Color_hpp_ +#define slic3r_Color_hpp_ + +#if ENABLE_COLOR_CLASSES + +#include +#include + +namespace Slic3r { + +class ColorRGB +{ + std::array m_data{1.0f, 1.0f, 1.0f}; + +public: + ColorRGB() = default; + ColorRGB(float r, float g, float b); + ColorRGB(unsigned char r, unsigned char g, unsigned char b); + ColorRGB(const ColorRGB& other) = default; + + ColorRGB& operator = (const ColorRGB& other) { m_data = other.m_data; return *this; } + + bool operator == (const ColorRGB& other) const { return m_data == other.m_data; } + bool operator != (const ColorRGB& other) const { return !operator==(other); } + bool operator < (const ColorRGB& other) const; + bool operator > (const ColorRGB& other) const; + + ColorRGB operator + (const ColorRGB& other) const; + ColorRGB operator * (float value) const; + + const float* const data() const { return m_data.data(); } + + float r() const { return m_data[0]; } + float g() const { return m_data[1]; } + float b() const { return m_data[2]; } + + void r(float r) { m_data[0] = std::clamp(r, 0.0f, 1.0f); } + void g(float g) { m_data[1] = std::clamp(g, 0.0f, 1.0f); } + void b(float b) { m_data[2] = std::clamp(b, 0.0f, 1.0f); } + + void set(unsigned int comp, float value) { + assert(0 <= comp && comp <= 2); + m_data[comp] = std::clamp(value, 0.0f, 1.0f); + } + + unsigned char r_uchar() const { return unsigned char(m_data[0] * 255.0f); } + unsigned char g_uchar() const { return unsigned char(m_data[1] * 255.0f); } + unsigned char b_uchar() const { return unsigned char(m_data[2] * 255.0f); } + + static const ColorRGB BLACK() { return { 0.0f, 0.0f, 0.0f }; } + static const ColorRGB BLUE() { return { 0.0f, 0.0f, 1.0f }; } + static const ColorRGB BLUEISH() { return { 0.5f, 0.5f, 1.0f }; } + static const ColorRGB DARK_GRAY() { return { 0.25f, 0.25f, 0.25f }; } + static const ColorRGB DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f }; } + static const ColorRGB GRAY() { return { 0.5f, 0.5f, 0.5f }; } + static const ColorRGB GREEN() { return { 0.0f, 1.0f, 0.0f }; } + static const ColorRGB GREENISH() { return { 0.5f, 1.0f, 0.5f }; } + static const ColorRGB LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f }; } + static const ColorRGB ORANGE() { return { 0.92f, 0.50f, 0.26f }; } + static const ColorRGB RED() { return { 1.0f, 0.0f, 0.0f }; } + static const ColorRGB REDISH() { return { 1.0f, 0.5f, 0.5f }; } + static const ColorRGB YELLOW() { return { 1.0f, 1.0f, 0.0f }; } + static const ColorRGB WHITE() { return { 1.0f, 1.0f, 1.0f }; } + + static const ColorRGB X() { return { 0.75f, 0.0f, 0.0f }; } + static const ColorRGB Y() { return { 0.0f, 0.75f, 0.0f }; } + static const ColorRGB Z() { return { 0.0f, 0.0f, 0.75f }; } +}; + +class ColorRGBA +{ + std::array m_data{ 1.0f, 1.0f, 1.0f, 1.0f }; + +public: + ColorRGBA() = default; + ColorRGBA(float r, float g, float b, float a); + ColorRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a); + ColorRGBA(const ColorRGBA& other) = default; + + ColorRGBA& operator = (const ColorRGBA& other) { m_data = other.m_data; return *this; } + + bool operator == (const ColorRGBA& other) const { return m_data == other.m_data; } + bool operator != (const ColorRGBA& other) const { return !operator==(other); } + bool operator < (const ColorRGBA& other) const; + bool operator > (const ColorRGBA& other) const; + + ColorRGBA operator + (const ColorRGBA& other) const; + ColorRGBA operator * (float value) const; + + const float* const data() const { return m_data.data(); } + + float r() const { return m_data[0]; } + float g() const { return m_data[1]; } + float b() const { return m_data[2]; } + float a() const { return m_data[3]; } + + void r(float r) { m_data[0] = std::clamp(r, 0.0f, 1.0f); } + void g(float g) { m_data[1] = std::clamp(g, 0.0f, 1.0f); } + void b(float b) { m_data[2] = std::clamp(b, 0.0f, 1.0f); } + void a(float a) { m_data[3] = std::clamp(a, 0.0f, 1.0f); } + + void set(unsigned int comp, float value) { + assert(0 <= comp && comp <= 3); + m_data[comp] = std::clamp(value, 0.0f, 1.0f); + } + + unsigned char r_uchar() const { return unsigned char(m_data[0] * 255.0f); } + unsigned char g_uchar() const { return unsigned char(m_data[1] * 255.0f); } + unsigned char b_uchar() const { return unsigned char(m_data[2] * 255.0f); } + unsigned char a_uchar() const { return unsigned char(m_data[3] * 255.0f); } + + bool is_transparent() const { return m_data[3] < 1.0f; } + + static const ColorRGBA BLACK() { return { 0.0f, 0.0f, 0.0f, 1.0f }; } + static const ColorRGBA BLUE() { return { 0.0f, 0.0f, 1.0f, 1.0f }; } + static const ColorRGBA BLUEISH() { return { 0.5f, 0.5f, 1.0f, 1.0f }; } + static const ColorRGBA DARK_GRAY() { return { 0.25f, 0.25f, 0.25f, 1.0f }; } + static const ColorRGBA DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f, 1.0f }; } + static const ColorRGBA GRAY() { return { 0.5f, 0.5f, 0.5f, 1.0f }; } + static const ColorRGBA GREEN() { return { 0.0f, 1.0f, 0.0f, 1.0f }; } + static const ColorRGBA GREENISH() { return { 0.5f, 1.0f, 0.5f, 1.0f }; } + static const ColorRGBA LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f, 1.0f }; } + static const ColorRGBA ORANGE() { return { 0.923f, 0.504f, 0.264f, 1.0f }; } + static const ColorRGBA RED() { return { 1.0f, 0.0f, 0.0f, 1.0f }; } + static const ColorRGBA REDISH() { return { 1.0f, 0.5f, 0.5f, 1.0f }; } + static const ColorRGBA YELLOW() { return { 1.0f, 1.0f, 0.0f, 1.0f }; } + static const ColorRGBA WHITE() { return { 1.0f, 1.0f, 1.0f, 1.0f }; } + + static const ColorRGBA X() { return { 0.75f, 0.0f, 0.0f, 1.0f }; } + static const ColorRGBA Y() { return { 0.0f, 0.75f, 0.0f, 1.0f }; } + static const ColorRGBA Z() { return { 0.0f, 0.0f, 0.75f, 1.0f }; } +}; + +extern ColorRGB operator * (float value, const ColorRGB& other); +extern ColorRGBA operator * (float value, const ColorRGBA& other); + +extern ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t); +extern ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t); + +extern ColorRGB complementary(const ColorRGB& color); +extern ColorRGBA complementary(const ColorRGBA& color); + +extern ColorRGB saturate(const ColorRGB& color, float factor); +extern ColorRGBA saturate(const ColorRGBA& color, float factor); + +extern ColorRGB opposite(const ColorRGB& color); +extern ColorRGB opposite(const ColorRGB& a, const ColorRGB& b); + +extern bool can_decode_color(const std::string& color); + +extern bool decode_color(const std::string& color_in, ColorRGB& color_out); +extern bool decode_color(const std::string& color_in, ColorRGBA& color_out); + +extern bool decode_colors(const std::vector& colors_in, std::vector& colors_out); +extern bool decode_colors(const std::vector& colors_in, std::vector& colors_out); + +extern std::string encode_color(const ColorRGB& color); +extern std::string encode_color(const ColorRGBA& color); + +extern ColorRGB to_rgb(const ColorRGBA& other_rgba); +extern ColorRGBA to_rgba(const ColorRGB& other_rgb); +extern ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha); + +extern ColorRGBA picking_decode(unsigned int id); +extern unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b); +// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components +// were not interpolated by alpha blending or multi sampling. +extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue); + +} // namespace Slic3r + +#endif // ENABLE_COLOR_CLASSES + +#endif /* slic3r_Color_hpp_ */ diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index ef975461e2..0c2728bd3f 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -58,4 +58,13 @@ #define ENABLE_ENHANCED_PRINT_VOLUME_FIT (1 && ENABLE_2_4_0_BETA2) +//==================== +// 2.5.0.alpha1 techs +//==================== +#define ENABLE_2_5_0_ALPHA1 1 + +// Enable Color classes definition as unified point for colors manipulation +#define ENABLE_COLOR_CLASSES (1 && ENABLE_2_5_0_ALPHA1) + + #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index bd5ca9f521..ef99aeec0d 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -19,8 +19,15 @@ #include static const float GROUND_Z = -0.02f; +#if ENABLE_COLOR_CLASSES +static const Slic3r::ColorRGBA DEFAULT_MODEL_COLOR = Slic3r::ColorRGBA::DARK_GRAY(); +static const Slic3r::ColorRGBA PICKING_MODEL_COLOR = Slic3r::ColorRGBA::BLACK(); +static const Slic3r::ColorRGBA DEFAULT_SOLID_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f }; +static const Slic3r::ColorRGBA DEFAULT_TRANSPARENT_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 0.6f }; +#else static const std::array DEFAULT_MODEL_COLOR = { 0.235f, 0.235f, 0.235f, 1.0f }; static const std::array PICKING_MODEL_COLOR = { 0.0f, 0.0f, 0.0f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES namespace Slic3r { namespace GUI { @@ -121,15 +128,27 @@ void Bed3D::Axes::render() const shader->set_uniform("emission_factor", 0.0f); // x axis +#if ENABLE_COLOR_CLASSES + const_cast(&m_arrow)->set_color(-1, ColorRGBA::X()); +#else const_cast(&m_arrow)->set_color(-1, { 0.75f, 0.0f, 0.0f, 1.0f }); +#endif // ENABLE_COLOR_CLASSES render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast()); // y axis +#if ENABLE_COLOR_CLASSES + const_cast(&m_arrow)->set_color(-1, ColorRGBA::Y()); +#else const_cast(&m_arrow)->set_color(-1, { 0.0f, 0.75f, 0.0f, 1.0f }); +#endif // ENABLE_COLOR_CLASSES render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast()); // z axis +#if ENABLE_COLOR_CLASSES + const_cast(&m_arrow)->set_color(-1, ColorRGBA::Z()); +#else const_cast(&m_arrow)->set_color(-1, { 0.0f, 0.0f, 0.75f, 1.0f }); +#endif // ENABLE_COLOR_CLASSES render_axis(Geometry::assemble_transform(m_origin).cast()); shader->stop_using(); @@ -540,7 +559,11 @@ void Bed3D::render_default(bool bottom, bool picking) const if (!has_model && !bottom) { // draw background glsafe(::glDepthMask(GL_FALSE)); +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(picking ? PICKING_MODEL_COLOR.data() : DEFAULT_MODEL_COLOR.data())); +#else + glsafe(::glColor4fv(picking ? PICKING_MODEL_COLOR.data() : DEFAULT_MODEL_COLOR.data())); +#endif // ENABLE_COLOR_CLASSES glsafe(::glNormal3d(0.0f, 0.0f, 1.0f)); glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_vertices_data())); glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)triangles_vcount)); @@ -550,10 +573,14 @@ void Bed3D::render_default(bool bottom, bool picking) const if (!picking) { // draw grid glsafe(::glLineWidth(1.5f * m_scale_factor)); +#if ENABLE_COLOR_CLASSES + glsafe(::glColor4fv(has_model && !bottom ? DEFAULT_SOLID_GRID_COLOR.data() : DEFAULT_TRANSPARENT_GRID_COLOR.data())); +#else if (has_model && !bottom) glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 1.0f)); else glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.6f)); +#endif // ENABLE_COLOR_CLASSES glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data())); glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)m_gridlines.get_vertices_count())); } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 94b1f31569..d6391ac9ed 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -344,6 +344,23 @@ void GLVolume::SinkingContours::update() m_model.reset(); } +#if ENABLE_COLOR_CLASSES +const ColorRGBA GLVolume::SELECTED_COLOR = ColorRGBA::GREEN(); +const ColorRGBA GLVolume::HOVER_SELECT_COLOR = { 0.4f, 0.9f, 0.1f, 1.0f }; +const ColorRGBA GLVolume::HOVER_DESELECT_COLOR = { 1.0f, 0.75f, 0.75f, 1.0f }; +const ColorRGBA GLVolume::OUTSIDE_COLOR = { 0.0f, 0.38f, 0.8f, 1.0f }; +const ColorRGBA GLVolume::SELECTED_OUTSIDE_COLOR = { 0.19f, 0.58f, 1.0f, 1.0f }; +const ColorRGBA GLVolume::DISABLED_COLOR = ColorRGBA::DARK_GRAY(); +const ColorRGBA GLVolume::SLA_SUPPORT_COLOR = ColorRGBA::LIGHT_GRAY(); +const ColorRGBA GLVolume::SLA_PAD_COLOR = { 0.0f, 0.2f, 0.0f, 1.0f }; +const ColorRGBA GLVolume::NEUTRAL_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f }; +const std::array GLVolume::MODEL_COLOR = { { + ColorRGBA::YELLOW(), + { 1.0f, 0.5f, 0.5f, 1.0f }, + { 0.5f, 1.0f, 0.5f, 1.0f }, + { 0.5f, 0.5f, 1.0f, 1.0f } +} }; +#else const std::array GLVolume::SELECTED_COLOR = { 0.0f, 1.0f, 0.0f, 1.0f }; const std::array GLVolume::HOVER_SELECT_COLOR = { 0.4f, 0.9f, 0.1f, 1.0f }; const std::array GLVolume::HOVER_DESELECT_COLOR = { 1.0f, 0.75f, 0.75f, 1.0f }; @@ -359,6 +376,7 @@ const std::array, 4> GLVolume::MODEL_COLOR = { { { 0.5f, 1.0f, 0.5f, 1.f }, { 0.5f, 0.5f, 1.0f, 1.f } } }; +#endif // ENABLE_COLOR_CLASSES GLVolume::GLVolume(float r, float g, float b, float a) : m_sla_shift_z(0.0) @@ -388,6 +406,7 @@ GLVolume::GLVolume(float r, float g, float b, float a) set_render_color(color); } +#if !ENABLE_COLOR_CLASSES void GLVolume::set_color(const std::array& rgba) { color = rgba; @@ -402,6 +421,7 @@ void GLVolume::set_render_color(const std::array& rgba) { render_color = rgba; } +#endif // !ENABLE_COLOR_CLASSES void GLVolume::set_render_color() { @@ -433,15 +453,46 @@ void GLVolume::set_render_color() } if (!printable) { +#if ENABLE_COLOR_CLASSES + render_color = saturate(render_color, 0.25f); +#else render_color[0] /= 4; render_color[1] /= 4; render_color[2] /= 4; +#endif // ENABLE_COLOR_CLASSES } if (force_transparent) +#if ENABLE_COLOR_CLASSES + render_color.a(color.a()); +#else render_color[3] = color[3]; +#endif // ENABLE_COLOR_CLASSES } +#if ENABLE_COLOR_CLASSES +ColorRGBA color_from_model_volume(const ModelVolume& model_volume) +{ + ColorRGBA color; + if (model_volume.is_negative_volume()) + color = { 0.2f, 0.2f, 0.2f, 1.0f }; + else if (model_volume.is_modifier()) +#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT + color = { 1.0, 1.0f, 0.2f, 1.0f }; +#else + color[0] = { 0.2f, 1.0f, 0.2f, 1.0f }; +#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT + else if (model_volume.is_support_blocker()) + color = { 1.0f, 0.2f, 0.2f, 1.0f }; + else if (model_volume.is_support_enforcer()) + color = { 0.2f, 0.2f, 1.0f, 1.0f }; + + if (!model_volume.is_model_part()) + color.a(0.5f); + + return color; +} +#else std::array color_from_model_volume(const ModelVolume& model_volume) { std::array color; @@ -474,6 +525,7 @@ std::array color_from_model_volume(const ModelVolume& model_volume) color[3] = model_volume.is_model_part() ? 1.f : 0.5f; return color; } +#endif // ENABLE_COLOR_CLASSES Transform3d GLVolume::world_matrix() const { @@ -631,8 +683,13 @@ int GLVolumeCollection::load_object_volume( const int extruder_id = model_volume->extruder_id(); const ModelInstance *instance = model_object->instances[instance_idx]; const TriangleMesh &mesh = model_volume->mesh(); +#if ENABLE_COLOR_CLASSES + ColorRGBA color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4]; + color.a(model_volume->is_model_part() ? 1.0f : 0.5f); +#else std::array color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4]; color[3] = model_volume->is_model_part() ? 1.f : 0.5f; +#endif // ENABLE_COLOR_CLASSES this->volumes.emplace_back(new GLVolume(color)); GLVolume& v = *this->volumes.back(); v.set_color(color_from_model_volume(*model_volume)); @@ -713,13 +770,22 @@ int GLVolumeCollection::load_wipe_tower_preview( height = 0.1f; TriangleMesh mesh; +#if ENABLE_COLOR_CLASSES + ColorRGBA color = ColorRGBA::DARK_YELLOW(); +#else std::array color = { 0.5f, 0.5f, 0.0f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES // In case we don't know precise dimensions of the wipe tower yet, we'll draw // the box with different color with one side jagged: if (size_unknown) { +#if ENABLE_COLOR_CLASSES + color.r(0.9f); + color.g(0.6f); +#else color[0] = 0.9f; color[1] = 0.6f; +#endif // ENABLE_COLOR_CLASSES // Too narrow tower would interfere with the teeth. The estimate is not precise anyway. depth = std::max(depth, 10.f); @@ -775,14 +841,22 @@ int GLVolumeCollection::load_wipe_tower_preview( return int(volumes.size() - 1); } +#if ENABLE_COLOR_CLASSES +GLVolume* GLVolumeCollection::new_toolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats) +#else GLVolume* GLVolumeCollection::new_toolpath_volume(const std::array& rgba, size_t reserve_vbo_floats) +#endif // ENABLE_COLOR_CLASSES { GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats); out->is_extrusion_path = true; return out; } +#if ENABLE_COLOR_CLASSES +GLVolume* GLVolumeCollection::new_nontoolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats) +#else GLVolume* GLVolumeCollection::new_nontoolpath_volume(const std::array& rgba, size_t reserve_vbo_floats) +#endif // ENABLE_COLOR_CLASSES { GLVolume *out = new GLVolume(rgba); out->is_extrusion_path = false; @@ -799,7 +873,11 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i) { GLVolume* volume = volumes[i]; +#if ENABLE_COLOR_CLASSES + bool is_transparent = volume->render_color.is_transparent(); +#else bool is_transparent = (volume->render_color[3] < 1.0f); +#endif // ENABLE_COLOR_CLASSES if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) || (type == GLVolumeCollection::ERenderType::Transparent && is_transparent) || type == GLVolumeCollection::ERenderType::All) && @@ -991,6 +1069,10 @@ void GLVolumeCollection::reset_outside_state() void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* config) { +#if ENABLE_COLOR_CLASSES + using ColorItem = std::pair; + std::vector colors; +#else static const float inv_255 = 1.0f / 255.0f; struct Color @@ -1018,19 +1100,24 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con unsigned char rgb[3]; std::vector colors; +#endif // ENABLE_COLOR_CLASSES - if (static_cast(config->opt_int("printer_technology")) == ptSLA) - { + if (static_cast(config->opt_int("printer_technology")) == ptSLA) { const std::string& txt_color = config->opt_string("material_colour").empty() ? print_config_def.get("material_colour")->get_default_value()->value : config->opt_string("material_colour"); +#if ENABLE_COLOR_CLASSES + ColorRGBA rgba; + if (decode_color(txt_color, rgba)) + colors.push_back({ txt_color, rgba }); +#else if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb)) { colors.resize(1); colors[0].set(txt_color, rgb); } +#endif // ENABLE_COLOR_CLASSES } - else - { + else { const ConfigOptionStrings* extruders_opt = dynamic_cast(config->option("extruder_colour")); if (extruders_opt == nullptr) return; @@ -1039,12 +1126,23 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con if (filamemts_opt == nullptr) return; - unsigned int colors_count = std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size()); + size_t colors_count = std::max(extruders_opt->values.size(), filamemts_opt->values.size()); if (colors_count == 0) return; colors.resize(colors_count); for (unsigned int i = 0; i < colors_count; ++i) { +#if ENABLE_COLOR_CLASSES + const std::string& ext_color = config->opt_string("extruder_colour", i); + ColorRGBA rgba; + if (decode_color(ext_color, rgba)) + colors[i] = { ext_color, rgba }; + else { + const std::string& fil_color = config->opt_string("filament_colour", i); + if (decode_color(fil_color, rgba)) + colors[i] = { fil_color, rgba }; + } +#else const std::string& txt_color = config->opt_string("extruder_colour", i); if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb)) colors[i].set(txt_color, rgb); @@ -1053,23 +1151,30 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb)) colors[i].set(txt_color, rgb); } +#endif // ENABLE_COLOR_CLASSES } } for (GLVolume* volume : volumes) { - if (volume == nullptr || volume->is_modifier || volume->is_wipe_tower || (volume->volume_idx() < 0)) + if (volume == nullptr || volume->is_modifier || volume->is_wipe_tower || volume->volume_idx() < 0) continue; int extruder_id = volume->extruder_id - 1; if (extruder_id < 0 || (int)colors.size() <= extruder_id) extruder_id = 0; +#if ENABLE_COLOR_CLASSES + const ColorItem& color = colors[extruder_id]; + if (!color.first.empty()) + volume->color = color.second; +#else const Color& color = colors[extruder_id]; if (!color.text.empty()) { for (int i = 0; i < 3; ++i) { volume->color[i] = (float)color.rgb[i] * inv_255; } } +#endif // ENABLE_COLOR_CLASSES } } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 6d82e3bb7c..843ad256e4 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -7,6 +7,9 @@ #include "libslic3r/TriangleMesh.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Geometry.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GLModel.hpp" @@ -43,7 +46,11 @@ class ModelVolume; enum ModelInstanceEPrintVolumeState : unsigned char; // Return appropriate color based on the ModelVolume. +#if ENABLE_COLOR_CLASSES +extern ColorRGBA color_from_model_volume(const ModelVolume& model_volume); +#else std::array color_from_model_volume(const ModelVolume& model_volume); +#endif // ENABLE_COLOR_CLASSES // A container for interleaved arrays of 3D vertices and normals, // possibly indexed by triangles and / or quads. @@ -248,6 +255,18 @@ private: class GLVolume { public: +#if ENABLE_COLOR_CLASSES + static const ColorRGBA SELECTED_COLOR; + static const ColorRGBA HOVER_SELECT_COLOR; + static const ColorRGBA HOVER_DESELECT_COLOR; + static const ColorRGBA OUTSIDE_COLOR; + static const ColorRGBA SELECTED_OUTSIDE_COLOR; + static const ColorRGBA DISABLED_COLOR; + static const ColorRGBA SLA_SUPPORT_COLOR; + static const ColorRGBA SLA_PAD_COLOR; + static const ColorRGBA NEUTRAL_COLOR; + static const std::array MODEL_COLOR; +#else static const std::array SELECTED_COLOR; static const std::array HOVER_SELECT_COLOR; static const std::array HOVER_DESELECT_COLOR; @@ -258,6 +277,7 @@ public: static const std::array SLA_PAD_COLOR; static const std::array NEUTRAL_COLOR; static const std::array, 4> MODEL_COLOR; +#endif // ENABLE_COLOR_CLASSES enum EHoverState : unsigned char { @@ -267,8 +287,12 @@ public: HS_Deselect }; - GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f); + GLVolume(float r = 1.0f, float g = 1.0f, float b = 1.0f, float a = 1.0f); +#if ENABLE_COLOR_CLASSES + GLVolume(const ColorRGBA& color) : GLVolume(color.r(), color.g(), color.b(), color.a()) {} +#else GLVolume(const std::array& rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {} +#endif // ENABLE_COLOR_CLASSES private: Geometry::Transformation m_instance_transformation; @@ -304,10 +328,17 @@ private: SinkingContours m_sinking_contours; public: +#if ENABLE_COLOR_CLASSES + // Color of the triangles / quads held by this volume. + ColorRGBA color; + // Color used to render this volume. + ColorRGBA render_color; +#else // Color of the triangles / quads held by this volume. std::array color; // Color used to render this volume. std::array render_color; +#endif // ENABLE_COLOR_CLASSES struct CompositeID { CompositeID(int object_id, int volume_id, int instance_id) : object_id(object_id), volume_id(volume_id), instance_id(instance_id) {} @@ -393,9 +424,14 @@ public: return out; } +#if ENABLE_COLOR_CLASSES + void set_color(const ColorRGBA& rgba) { color = rgba; } + void set_render_color(const ColorRGBA& rgba) { render_color = rgba; } +#else void set_color(const std::array& rgba); void set_render_color(float r, float g, float b, float a); void set_render_color(const std::array& rgba); +#endif // ENABLE_COLOR_CLASSES // Sets render color in dependence of current state void set_render_color(); // set color according to model volume @@ -595,8 +631,13 @@ public: int load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized); +#if ENABLE_COLOR_CLASSES + GLVolume* new_toolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats = 0); + GLVolume* new_nontoolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats = 0); +#else GLVolume* new_toolpath_volume(const std::array& rgba, size_t reserve_vbo_floats = 0); GLVolume* new_nontoolpath_volume(const std::array& rgba, size_t reserve_vbo_floats = 0); +#endif // ENABLE_COLOR_CLASSES // Render the volumes by OpenGL. void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function filter_func = std::function()) const; diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index 05f301186a..17c99708f4 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -2,6 +2,9 @@ #include "I18N.hpp" #include "libslic3r/Utils.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GUI.hpp" #include "GUI_App.hpp" #include "MainFrame.hpp" @@ -133,12 +136,17 @@ wxString CopyrightsDialog::get_html_text() wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); const auto text_clr = wxGetApp().get_label_clr_default();// wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); +#if ENABLE_COLOR_CLASSES + const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); + const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); +#else const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); +#endif // ENABLE_COLOR_CLASSES - const wxString copyright_str = _(L("Copyright")) + "© "; + const wxString copyright_str = _L("Copyright") + "© "; // TRN "Slic3r _is licensed under the_ License" - const wxString header_str = _(L("License agreements of all following programs (libraries) are part of application license agreement")); + const wxString header_str = _L("License agreements of all following programs (libraries) are part of application license agreement"); wxString text = wxString::Format( "" @@ -257,8 +265,13 @@ AboutDialog::AboutDialog() m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit())); wxFont font = get_default_font(this); const auto text_clr = wxGetApp().get_label_clr_default();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); - auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); +#if ENABLE_COLOR_CLASSES + const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); + const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); +#else + auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); +#endif // ENABLE_COLOR_CLASSES const int fs = font.GetPointSize()-1; int size[] = {fs,fs,fs,fs,fs,fs,fs}; diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp index 39ba849d33..00516575be 100644 --- a/src/slic3r/GUI/BitmapCache.cpp +++ b/src/slic3r/GUI/BitmapCache.cpp @@ -395,6 +395,7 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi return wxImage_to_wxBitmap_with_alpha(std::move(image), scale); } +#if !ENABLE_COLOR_CLASSES bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out) { rgb_out[0] = rgb_out[1] = rgb_out[2] = 0; @@ -410,6 +411,7 @@ bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out) } return true; } +#endif // !ENABLE_COLOR_CLASSES } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/BitmapCache.hpp b/src/slic3r/GUI/BitmapCache.hpp index 4d1d383c41..e2f5b6d313 100644 --- a/src/slic3r/GUI/BitmapCache.hpp +++ b/src/slic3r/GUI/BitmapCache.hpp @@ -9,9 +9,14 @@ #include #endif +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES + struct NSVGimage; -namespace Slic3r { namespace GUI { +namespace Slic3r { +namespace GUI { class BitmapCache { @@ -43,10 +48,16 @@ public: wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false, const bool dark_mode = false, const std::string& new_color = ""); wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false); +#if ENABLE_COLOR_CLASSES + wxBitmap mksolid(size_t width, size_t height, const ColorRGB& rgb, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb.r_uchar(), rgb.g_uchar(), rgb.b_uchar(), wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); } +#else wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3], bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); } +#endif // ENABLE_COLOR_CLASSES wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); } +#if !ENABLE_COLOR_CLASSES static bool parse_color(const std::string& scolor, unsigned char* rgb_out); +#endif // !ENABLE_COLOR_CLASSES private: std::map m_map; diff --git a/src/slic3r/GUI/ConfigSnapshotDialog.cpp b/src/slic3r/GUI/ConfigSnapshotDialog.cpp index 7d2029e22c..f194a2ade8 100644 --- a/src/slic3r/GUI/ConfigSnapshotDialog.cpp +++ b/src/slic3r/GUI/ConfigSnapshotDialog.cpp @@ -5,6 +5,9 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/Time.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GUI_App.hpp" #include "MainFrame.hpp" #include "wxExtensions.hpp" @@ -31,8 +34,12 @@ static wxString format_reason(const Config::Snapshot::Reason reason) static std::string get_color(wxColour colour) { +#if ENABLE_COLOR_CLASSES + return encode_color(ColorRGB(colour.Red(), colour.Green(), colour.Blue())); +#else wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue()); return clr_str.ToStdString(); +#endif // ENABLE_COLOR_CLASSES }; diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 842c690de2..bb102f48fb 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -36,6 +36,9 @@ #include "libslic3r/Config.hpp" #include "libslic3r/libslic3r.h" #include "libslic3r/Model.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_Utils.hpp" @@ -746,9 +749,15 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector* are not compatible with some installed printers."), materials->technology == T_FFF ? _L("Filaments") : _L("SLA materials")); wxString text; if (all_printers) { diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 3d914d5b66..12dc022dda 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -2557,36 +2557,68 @@ bool Control::check_ticks_changed_event(Type type) std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder) { +#if ENABLE_COLOR_CLASSES + auto opposite_one_color = [](const std::string& color) { + ColorRGB rgb; + decode_color(color, rgb); + return encode_color(opposite(rgb)); + }; + auto opposite_two_colors = [](const std::string& a, const std::string& b) { + ColorRGB rgb1; decode_color(a, rgb1); + ColorRGB rgb2; decode_color(b, rgb2); + return encode_color(opposite(rgb1, rgb2)); + }; +#endif // ENABLE_COLOR_CLASSES + if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) { #if 1 if (ticks.empty()) +#if ENABLE_COLOR_CLASSES + return opposite_one_color((*m_colors)[0]); +#else return color_generator.get_opposite_color((*m_colors)[0]); - +#endif // ENABLE_COLOR_CLASSES + auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick); - if (before_tick_it == ticks.end()) - { + if (before_tick_it == ticks.end()) { while (before_tick_it != ticks.begin()) if (--before_tick_it; before_tick_it->type == ColorChange) break; if (before_tick_it->type == ColorChange) +#if ENABLE_COLOR_CLASSES + return opposite_one_color(before_tick_it->color); + + return opposite_one_color((*m_colors)[0]); +#else return color_generator.get_opposite_color(before_tick_it->color); + return color_generator.get_opposite_color((*m_colors)[0]); +#endif // ENABLE_COLOR_CLASSES } - if (before_tick_it == ticks.begin()) - { + if (before_tick_it == ticks.begin()) { const std::string& frst_color = (*m_colors)[0]; if (before_tick_it->type == ColorChange) +#if ENABLE_COLOR_CLASSES + return opposite_two_colors(frst_color, before_tick_it->color); +#else return color_generator.get_opposite_color(frst_color, before_tick_it->color); +#endif // ENABLE_COLOR_CLASSES auto next_tick_it = before_tick_it; while (next_tick_it != ticks.end()) if (++next_tick_it; next_tick_it->type == ColorChange) break; if (next_tick_it->type == ColorChange) +#if ENABLE_COLOR_CLASSES + return opposite_two_colors(frst_color, next_tick_it->color); + + return opposite_one_color(frst_color); +#else return color_generator.get_opposite_color(frst_color, next_tick_it->color); return color_generator.get_opposite_color(frst_color); +#endif // ENABLE_COLOR_CLASSES } std::string frst_color = ""; @@ -2607,13 +2639,27 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int if (before_tick_it->type == ColorChange) { if (frst_color.empty()) +#if ENABLE_COLOR_CLASSES + return opposite_one_color(before_tick_it->color); + + return opposite_two_colors(before_tick_it->color, frst_color); +#else return color_generator.get_opposite_color(before_tick_it->color); + return color_generator.get_opposite_color(before_tick_it->color, frst_color); +#endif // ENABLE_COLOR_CLASSES } if (frst_color.empty()) +#if ENABLE_COLOR_CLASSES + return opposite_one_color((*m_colors)[0]); + + return opposite_two_colors((*m_colors)[0], frst_color); +#else return color_generator.get_opposite_color((*m_colors)[0]); + return color_generator.get_opposite_color((*m_colors)[0], frst_color); +#endif // ENABLE_COLOR_CLASSES #else const std::vector& colors = ColorPrintColors::get(); if (ticks.empty()) diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index 23275cf2ad..6783cd7e72 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -3,7 +3,9 @@ #include "libslic3r/CustomGCode.hpp" #include "wxExtensions.hpp" +#if !ENABLE_COLOR_CLASSES #include "DoubleSlider_Utils.hpp" +#endif // !ENABLE_COLOR_CLASSES #include #include @@ -119,7 +121,9 @@ class TickCodeInfo // int m_default_color_idx = 0; std::vector* m_colors {nullptr}; +#if !ENABLE_COLOR_CLASSES ColorGenerator color_generator; +#endif // !ENABLE_COLOR_CLASSES std::string get_color_for_tick(TickCode tick, Type type, const int extruder); diff --git a/src/slic3r/GUI/DoubleSlider_Utils.hpp b/src/slic3r/GUI/DoubleSlider_Utils.hpp index b5955f2fc4..83a9dae0bd 100644 --- a/src/slic3r/GUI/DoubleSlider_Utils.hpp +++ b/src/slic3r/GUI/DoubleSlider_Utils.hpp @@ -1,6 +1,11 @@ +#ifndef slic3r_GUI_DoubleSlider_Utils_hpp_ +#define slic3r_GUI_DoubleSlider_Utils_hpp_ + #include #include +#if !ENABLE_COLOR_CLASSES + #include "wx/colour.h" class ColorGenerator @@ -158,7 +163,6 @@ public: hsv_clr.h += 65; // 65 instead 60 to avoid circle values hsv_clr.s = rand_val(); hsv_clr.v = rand_val(); - rgb rgb_opp_color = hsv2rgb(hsv_clr); wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255)); @@ -188,4 +192,8 @@ public: return opp_color; } -}; \ No newline at end of file +}; + +#endif // !ENABLE_COLOR_CLASSES + +#endif // slic3r_GUI_DoubleSlider_Utils_hpp_ diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 5ec622b872..005cef8ecd 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1390,8 +1390,12 @@ boost::any& ColourPicker::get_value() if (colour == wxTransparentColour) m_value = std::string(""); else { - auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue()); +#if ENABLE_COLOR_CLASSES + m_value = encode_color(ColorRGB(colour.Red(), colour.Green(), colour.Blue())); +#else + auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue()); m_value = clr_str.ToStdString(); +#endif // ENABLE_COLOR_CLASSES } return m_value; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 42dd0954b1..590ef341ac 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -47,6 +47,7 @@ static EMoveType buffer_type(unsigned char id) { return static_cast(static_cast(EMoveType::Retract) + id); } +#if !ENABLE_COLOR_CLASSES static std::array decode_color(const std::string& color) { static const float INV_255 = 1.0f / 255.0f; @@ -72,6 +73,7 @@ static std::vector> decode_colors(const std::vector(static_cast(global_t), 0, color_max_idx); const size_t color_high_idx = std::clamp(color_low_idx + 1, 0, color_max_idx); +#if ENABLE_COLOR_CLASSES + // Interpolate between the low and high colors to find exactly which color the input value should get + return lerp(Range_Colors[color_low_idx], Range_Colors[color_high_idx], global_t - static_cast(color_low_idx)); +#else // Compute how far the value is between the low and high colors so that they can be interpolated const float local_t = std::clamp(global_t - static_cast(color_low_idx), 0.0f, 1.0f); @@ -197,6 +207,7 @@ GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) con ret[i] = lerp(Range_Colors[color_low_idx][i], Range_Colors[color_high_idx][i], local_t); } return ret; +#endif // ENABLE_COLOR_CLASSES } GCodeViewer::SequentialRangeCap::~SequentialRangeCap() { @@ -346,11 +357,11 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u return ret; }; - static const ImVec4 LINE_NUMBER_COLOR = ImGuiWrapper::COL_ORANGE_LIGHT; + static const ImVec4 LINE_NUMBER_COLOR = ImGuiWrapper::COL_ORANGE_LIGHT; static const ImVec4 SELECTION_RECT_COLOR = ImGuiWrapper::COL_ORANGE_DARK; - static const ImVec4 COMMAND_COLOR = { 0.8f, 0.8f, 0.0f, 1.0f }; - static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f }; - static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f }; + static const ImVec4 COMMAND_COLOR = { 0.8f, 0.8f, 0.0f, 1.0f }; + static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f }; + static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f }; if (!m_visible || m_filename.empty() || m_lines_ends.empty() || curr_line_id == 0) return; @@ -475,7 +486,11 @@ void GCodeViewer::SequentialView::render(float legend_height) const gcode_window.render(legend_height, bottom, static_cast(gcode_ids[current.last])); } +#if ENABLE_COLOR_CLASSES +const std::vector GCodeViewer::Extrusion_Role_Colors{ { +#else const std::vector GCodeViewer::Extrusion_Role_Colors {{ +#endif // ENABLE_COLOR_CLASSES { 0.90f, 0.70f, 0.70f, 1.0f }, // erNone { 1.00f, 0.90f, 0.30f, 1.0f }, // erPerimeter { 1.00f, 0.49f, 0.22f, 1.0f }, // erExternalPerimeter @@ -494,7 +509,11 @@ const std::vector GCodeViewer::Extrusion_Role_Colors {{ { 0.00f, 0.00f, 0.00f, 1.0f } // erMixed }}; +#if ENABLE_COLOR_CLASSES +const std::vector GCodeViewer::Options_Colors{ { +#else const std::vector GCodeViewer::Options_Colors {{ +#endif // ENABLE_COLOR_CLASSES { 0.803f, 0.135f, 0.839f, 1.0f }, // Retractions { 0.287f, 0.679f, 0.810f, 1.0f }, // Unretractions { 0.900f, 0.900f, 0.900f, 1.0f }, // Seams @@ -504,7 +523,11 @@ const std::vector GCodeViewer::Options_Colors {{ { 0.886f, 0.825f, 0.262f, 1.0f } // CustomGCodes }}; +#if ENABLE_COLOR_CLASSES +const std::vector GCodeViewer::Travel_Colors{ { +#else const std::vector GCodeViewer::Travel_Colors {{ +#endif // ENABLE_COLOR_CLASSES { 0.219f, 0.282f, 0.609f, 1.0f }, // Move { 0.112f, 0.422f, 0.103f, 1.0f }, // Extrude { 0.505f, 0.064f, 0.028f, 1.0f } // Retract @@ -512,7 +535,11 @@ const std::vector GCodeViewer::Travel_Colors {{ #if 1 // Normal ranges +#if ENABLE_COLOR_CLASSES +const std::vector GCodeViewer::Range_Colors{ { +#else const std::vector GCodeViewer::Range_Colors {{ +#endif // ENABLE_COLOR_CLASSES { 0.043f, 0.173f, 0.478f, 1.0f }, // bluish { 0.075f, 0.349f, 0.522f, 1.0f }, { 0.110f, 0.533f, 0.569f, 1.0f }, @@ -527,7 +554,11 @@ const std::vector GCodeViewer::Range_Colors {{ }}; #else // Detailed ranges +#if ENABLE_COLOR_CLASSES +const std::vector GCodeViewer::Range_Colors{ { +#else const std::vector GCodeViewer::Range_Colors{ { +#endif // ENABLE_COLOR_CLASSES { 0.043f, 0.173f, 0.478f, 1.0f }, // bluish { 0.5f * (0.043f + 0.075f), 0.5f * (0.173f + 0.349f), 0.5f * (0.478f + 0.522f), 1.0f }, { 0.075f, 0.349f, 0.522f, 1.0f }, @@ -552,8 +583,13 @@ const std::vector GCodeViewer::Range_Colors{ { } }; #endif +#if ENABLE_COLOR_CLASSES +const ColorRGBA GCodeViewer::Wipe_Color = ColorRGBA::YELLOW(); +const ColorRGBA GCodeViewer::Neutral_Color = ColorRGBA::DARK_GRAY(); +#else const GCodeViewer::Color GCodeViewer::Wipe_Color = { 1.0f, 1.0f, 0.0f, 1.0f }; const GCodeViewer::Color GCodeViewer::Neutral_Color = { 0.25f, 0.25f, 0.25f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES GCodeViewer::GCodeViewer() { @@ -724,14 +760,31 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v if (m_view_type == EViewType::Tool && !gcode_result.extruder_colors.empty()) // update tool colors from config stored in the gcode +#if ENABLE_COLOR_CLASSES + decode_colors(gcode_result.extruder_colors, m_tool_colors); +#else m_tool_colors = decode_colors(gcode_result.extruder_colors); +#endif // ENABLE_COLOR_CLASSES else // update tool colors +#if ENABLE_COLOR_CLASSES + decode_colors(str_tool_colors, m_tool_colors); +#else m_tool_colors = decode_colors(str_tool_colors); +#endif // ENABLE_COLOR_CLASSES + +#if ENABLE_COLOR_CLASSES + ColorRGBA default_color; + decode_color("#FF8000", default_color); +#endif // ENABLE_COLOR_CLASSES // ensure there are enough colors defined while (m_tool_colors.size() < std::max(size_t(1), gcode_result.extruders_count)) +#if ENABLE_COLOR_CLASSES + m_tool_colors.push_back(default_color); +#else m_tool_colors.push_back(decode_color("#FF8000")); +#endif // ENABLE_COLOR_CLASSES // update ranges for coloring / legend m_extrusions.reset_ranges(); @@ -795,7 +848,11 @@ void GCodeViewer::reset() m_paths_bounding_box = BoundingBoxf3(); m_max_bounding_box = BoundingBoxf3(); m_max_print_height = 0.0f; +#if ENABLE_COLOR_CLASSES + m_tool_colors = std::vector(); +#else m_tool_colors = std::vector(); +#endif // ENABLE_COLOR_CLASSES m_extruders_count = 0; m_extruder_ids = std::vector(); m_filament_diameters = std::vector(); @@ -973,7 +1030,11 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const return; // collect color information to generate materials +#if ENABLE_COLOR_CLASSES + std::vector colors; +#else std::vector colors; +#endif // ENABLE_COLOR_CLASSES for (const RenderPath& path : t_buffer.render_paths) { colors.push_back(path.color); } @@ -995,12 +1056,21 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const fprintf(fp, "# Generated by %s-%s based on Slic3r\n", SLIC3R_APP_NAME, SLIC3R_VERSION); unsigned int colors_count = 1; +#if ENABLE_COLOR_CLASSES + for (const ColorRGBA& color : colors) { + fprintf(fp, "\nnewmtl material_%d\n", colors_count++); + fprintf(fp, "Ka 1 1 1\n"); + fprintf(fp, "Kd %g %g %g\n", color.r(), color.g(), color.b()); + fprintf(fp, "Ks 0 0 0\n"); + } +#else for (const Color& color : colors) { fprintf(fp, "\nnewmtl material_%d\n", colors_count++); fprintf(fp, "Ka 1 1 1\n"); fprintf(fp, "Kd %g %g %g\n", color[0], color[1], color[2]); fprintf(fp, "Ks 0 0 0\n"); } +#endif // ENABLE_COLOR_CLASSES fclose(fp); @@ -1059,7 +1129,11 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const } size_t i = 0; +#if ENABLE_COLOR_CLASSES + for (const ColorRGBA& color : colors) { +#else for (const Color& color : colors) { +#endif // ENABLE_COLOR_CLASSES // save material triangles to file fprintf(fp, "\nusemtl material_%zu\n", i + 1); fprintf(fp, "# triangles material %zu\n", i + 1); @@ -2111,7 +2185,11 @@ void GCodeViewer::load_shells(const Print& print, bool initialized) for (GLVolume* volume : m_shells.volumes.volumes) { volume->zoom_to_volumes = false; +#if ENABLE_COLOR_CLASSES + volume->color.a(0.25f); +#else volume->color[3] = 0.25f; +#endif // ENABLE_COLOR_CLASSES volume->force_native_color = true; volume->set_render_color(); } @@ -2124,7 +2202,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #endif // ENABLE_GCODE_VIEWER_STATISTICS auto extrusion_color = [this](const Path& path) { +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else Color color; +#endif // ENABLE_COLOR_CLASSES switch (m_view_type) { case EViewType::FeatureType: { color = Extrusion_Role_Colors[static_cast(path.role)]; break; } @@ -2137,13 +2219,21 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; } case EViewType::ColorPrint: { if (path.cp_color_id >= static_cast(m_tool_colors.size())) +#if ENABLE_COLOR_CLASSES + color = ColorRGBA::GRAY(); +#else color = { 0.5f, 0.5f, 0.5f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES else color = m_tool_colors[path.cp_color_id]; break; } +#if ENABLE_COLOR_CLASSES + default: { color = ColorRGBA::WHITE(); break; } +#else default: { color = { 1.0f, 1.0f, 1.0f, 1.0f }; break; } +#endif // ENABLE_COLOR_CLASSES } return color; @@ -2342,7 +2432,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (m_sequential_view.current.last < sub_path.first.s_id || sub_path.last.s_id < m_sequential_view.current.first) continue; +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else Color color; +#endif // ENABLE_COLOR_CLASSES switch (path.type) { case EMoveType::Tool_change: @@ -2984,7 +3078,11 @@ void GCodeViewer::render_legend(float& legend_height) bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; +#if ENABLE_COLOR_CLASSES + auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const ColorRGBA& color, const std::string& label, +#else auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, +#endif // ENABLE_COLOR_CLASSES bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array& offsets = { 0.0f, 0.0f, 0.0f, 0.0f }, double used_filament_m = 0.0, double used_filament_g = 0.0, std::function callback = nullptr) { @@ -2997,21 +3095,37 @@ void GCodeViewer::render_legend(float& legend_height) default: case EItemType::Rect: { draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f }, +#if ENABLE_COLOR_CLASSES + ImGuiWrapper::to_ImU32(color)); +#else ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f })); +#endif // ENABLE_COLOR_CLASSES break; } case EItemType::Circle: { ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); +#if ENABLE_COLOR_CLASSES + draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGuiWrapper::to_ImU32(color), 16); +#else draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); +#endif // ENABLE_COLOR_CLASSES break; } case EItemType::Hexagon: { ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); +#if ENABLE_COLOR_CLASSES + draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGuiWrapper::to_ImU32(color), 6); +#else draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 6); +#endif // ENABLE_COLOR_CLASSES break; } case EItemType::Line: { +#if ENABLE_COLOR_CLASSES + draw_list->AddLine({ pos.x + 1, pos.y + icon_size - 1 }, { pos.x + icon_size - 1, pos.y + 1 }, ImGuiWrapper::to_ImU32(color), 3.0f); +#else draw_list->AddLine({ pos.x + 1, pos.y + icon_size - 1 }, { pos.x + icon_size - 1, pos.y + 1 }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f); +#endif // ENABLE_COLOR_CLASSES break; } } @@ -3134,7 +3248,11 @@ void GCodeViewer::render_legend(float& legend_height) }; auto color_print_ranges = [this](unsigned char extruder_id, const std::vector& custom_gcode_per_print_z) { +#if ENABLE_COLOR_CLASSES + std::vector>> ret; +#else std::vector>> ret; +#endif // ENABLE_COLOR_CLASSES ret.reserve(custom_gcode_per_print_z.size()); for (const auto& item : custom_gcode_per_print_z) { @@ -3154,7 +3272,15 @@ void GCodeViewer::render_legend(float& legend_height) // to avoid duplicate values, check adding values if (ret.empty() || !(ret.back().second.first == previous_z && ret.back().second.second == current_z)) +#if ENABLE_COLOR_CLASSES + { + ColorRGBA color; + decode_color(item.color, color); + ret.push_back({ color, { previous_z, current_z } }); + } +#else ret.push_back({ decode_color(item.color), { previous_z, current_z } }); +#endif // ENABLE_COLOR_CLASSES } return ret; @@ -3349,7 +3475,11 @@ void GCodeViewer::render_legend(float& legend_height) if (need_scrollable) ImGui::BeginChild("color_prints", { -1.0f, child_height }, false); if (m_extruders_count == 1) { // single extruder use case +#if ENABLE_COLOR_CLASSES + const std::vector>> cp_values = color_print_ranges(0, custom_gcode_per_print_z); +#else const std::vector>> cp_values = color_print_ranges(0, custom_gcode_per_print_z); +#endif // ENABLE_COLOR_CLASSES const int items_cnt = static_cast(cp_values.size()); if (items_cnt == 0) { // There are no color changes, but there are some pause print or custom Gcode append_item(EItemType::Rect, m_tool_colors.front(), _u8L("Default color")); @@ -3372,11 +3502,15 @@ void GCodeViewer::render_legend(float& legend_height) else { // multi extruder use case // shows only extruders actually used for (unsigned char i : m_extruder_ids) { +#if ENABLE_COLOR_CLASSES + const std::vector>> cp_values = color_print_ranges(i, custom_gcode_per_print_z); +#else const std::vector>> cp_values = color_print_ranges(i, custom_gcode_per_print_z); +#endif // ENABLE_COLOR_CLASSES const int items_cnt = static_cast(cp_values.size()); - if (items_cnt == 0) { // There are no color changes, but there are some pause print or custom Gcode + if (items_cnt == 0) + // There are no color changes, but there are some pause print or custom Gcode append_item(EItemType::Rect, m_tool_colors[i], _u8L("Extruder") + " " + std::to_string(i + 1) + " " + _u8L("default color")); - } else { for (int j = items_cnt; j >= 0; --j) { // create label for color change item @@ -3422,10 +3556,15 @@ void GCodeViewer::render_legend(float& legend_height) }; EType type; int extruder_id; +#if ENABLE_COLOR_CLASSES + ColorRGBA color1; + ColorRGBA color2; +#else Color color1; Color color2; +#endif // ENABLE_COLOR_CLASSES Times times; - std::pair used_filament {0.0f, 0.0f}; + std::pair used_filament{ 0.0f, 0.0f }; }; using PartialTimes = std::vector; @@ -3434,7 +3573,11 @@ void GCodeViewer::render_legend(float& legend_height) std::vector custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z; int extruders_count = wxGetApp().extruders_edited_cnt(); +#if ENABLE_COLOR_CLASSES + std::vector last_color(extruders_count); +#else std::vector last_color(extruders_count); +#endif // ENABLE_COLOR_CLASSES for (int i = 0; i < extruders_count; ++i) { last_color[i] = m_tool_colors[i]; } @@ -3446,8 +3589,13 @@ void GCodeViewer::render_legend(float& legend_height) case CustomGCode::PausePrint: { auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; }); if (it != custom_gcode_per_print_z.end()) { +#if ENABLE_COLOR_CLASSES + items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], ColorRGBA::BLACK(), time_rec.second }); + items.push_back({ PartialTime::EType::Pause, it->extruder, ColorRGBA::BLACK(), ColorRGBA::BLACK(), time_rec.second }); +#else items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], Color(), time_rec.second }); items.push_back({ PartialTime::EType::Pause, it->extruder, Color(), Color(), time_rec.second }); +#endif // ENABLE_COLOR_CLASSES custom_gcode_per_print_z.erase(it); } break; @@ -3455,14 +3603,26 @@ void GCodeViewer::render_legend(float& legend_height) case CustomGCode::ColorChange: { auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; }); if (it != custom_gcode_per_print_z.end()) { +#if ENABLE_COLOR_CLASSES + items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], ColorRGBA::BLACK(), time_rec.second, get_used_filament_from_volume(used_filaments[color_change_idx++], it->extruder - 1) }); + ColorRGBA color; + decode_color(it->color, color); + items.push_back({ PartialTime::EType::ColorChange, it->extruder, last_color[it->extruder - 1], color, time_rec.second }); + last_color[it->extruder - 1] = color; +#else items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], Color(), time_rec.second, get_used_filament_from_volume(used_filaments[color_change_idx++], it->extruder-1) }); items.push_back({ PartialTime::EType::ColorChange, it->extruder, last_color[it->extruder - 1], decode_color(it->color), time_rec.second }); last_color[it->extruder - 1] = decode_color(it->color); +#endif // ENABLE_COLOR_CLASSES last_extruder_id = it->extruder; custom_gcode_per_print_z.erase(it); } else +#if ENABLE_COLOR_CLASSES + items.push_back({ PartialTime::EType::Print, last_extruder_id, last_color[last_extruder_id - 1], ColorRGBA::BLACK(), time_rec.second, get_used_filament_from_volume(used_filaments[color_change_idx++], last_extruder_id - 1) }); +#else items.push_back({ PartialTime::EType::Print, last_extruder_id, last_color[last_extruder_id - 1], Color(), time_rec.second, get_used_filament_from_volume(used_filaments[color_change_idx++], last_extruder_id -1) }); +#endif // ENABLE_COLOR_CLASSES break; } @@ -3473,7 +3633,11 @@ void GCodeViewer::render_legend(float& legend_height) return items; }; +#if ENABLE_COLOR_CLASSES + auto append_color_change = [&imgui](const ColorRGBA& color1, const ColorRGBA& color2, const std::array& offsets, const Times& times) { +#else auto append_color_change = [&imgui](const Color& color1, const Color& color2, const std::array& offsets, const Times& times) { +#endif // ENABLE_COLOR_CLASSES imgui.text(_u8L("Color change")); ImGui::SameLine(); @@ -3483,16 +3647,28 @@ void GCodeViewer::render_legend(float& legend_height) pos.x -= 0.5f * ImGui::GetStyle().ItemSpacing.x; draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f }, +#if ENABLE_COLOR_CLASSES + ImGuiWrapper::to_ImU32(color1)); +#else ImGui::GetColorU32({ color1[0], color1[1], color1[2], 1.0f })); +#endif // ENABLE_COLOR_CLASSES pos.x += icon_size; draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f }, +#if ENABLE_COLOR_CLASSES + ImGuiWrapper::to_ImU32(color2)); +#else ImGui::GetColorU32({ color2[0], color2[1], color2[2], 1.0f })); +#endif // ENABLE_COLOR_CLASSES ImGui::SameLine(offsets[0]); imgui.text(short_time(get_time_dhms(times.second - times.first))); }; +#if ENABLE_COLOR_CLASSES + auto append_print = [&imgui, imperial_units](const ColorRGBA& color, const std::array& offsets, const Times& times, std::pair used_filament) { +#else auto append_print = [&imgui, imperial_units](const Color& color, const std::array& offsets, const Times& times, std::pair used_filament) { +#endif // ENABLE_COLOR_CLASSES imgui.text(_u8L("Print")); ImGui::SameLine(); @@ -3502,7 +3678,11 @@ void GCodeViewer::render_legend(float& legend_height) pos.x -= 0.5f * ImGui::GetStyle().ItemSpacing.x; draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f }, +#if ENABLE_COLOR_CLASSES + ImGuiWrapper::to_ImU32(color)); +#else ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f })); +#endif // ENABLE_COLOR_CLASSES ImGui::SameLine(offsets[0]); imgui.text(short_time(get_time_dhms(times.second))); @@ -3924,7 +4104,11 @@ void GCodeViewer::log_memory_used(const std::string& label, int64_t additional) } } +#if ENABLE_COLOR_CLASSES +ColorRGBA GCodeViewer::option_color(EMoveType move_type) const +#else GCodeViewer::Color GCodeViewer::option_color(EMoveType move_type) const +#endif // ENABLE_COLOR_CLASSES { switch (move_type) { diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index c56e88c880..1a8c8838cf 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -22,7 +22,9 @@ namespace GUI { class GCodeViewer { using IBufferType = unsigned short; +#if !ENABLE_COLOR_CLASSES using Color = std::array; +#endif // !ENABLE_COLOR_CLASSES using VertexBuffer = std::vector; using MultiVertexBuffer = std::vector; using IndexBuffer = std::vector; @@ -31,12 +33,21 @@ class GCodeViewer using InstanceIdBuffer = std::vector; using InstancesOffsets = std::vector; +#if ENABLE_COLOR_CLASSES + static const std::vector Extrusion_Role_Colors; + static const std::vector Options_Colors; + static const std::vector Travel_Colors; + static const std::vector Range_Colors; + static const ColorRGBA Wipe_Color; + static const ColorRGBA Neutral_Color; +#else static const std::vector Extrusion_Role_Colors; static const std::vector Options_Colors; static const std::vector Travel_Colors; static const std::vector Range_Colors; static const Color Wipe_Color; static const Color Neutral_Color; +#endif // ENABLE_COLOR_CLASSES enum class EOptionsColors : unsigned char { @@ -121,7 +132,11 @@ class GCodeViewer // vbo id unsigned int vbo{ 0 }; // Color to apply to the instances +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else Color color; +#endif // ENABLE_COLOR_CLASSES }; std::vector ranges; @@ -243,7 +258,11 @@ class GCodeViewer // Index of the parent tbuffer unsigned char tbuffer_id; // Render path property +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else Color color; +#endif // ENABLE_COLOR_CLASSES // Index of the buffer in TBuffer::indices unsigned int ibuffer_id; // Render path content @@ -263,12 +282,19 @@ class GCodeViewer bool operator() (const RenderPath &l, const RenderPath &r) const { if (l.tbuffer_id < r.tbuffer_id) return true; +#if ENABLE_COLOR_CLASSES + if (l.color < r.color) + return true; + else if (l.color > r.color) + return false; +#else for (int i = 0; i < 3; ++i) { if (l.color[i] < r.color[i]) return true; else if (l.color[i] > r.color[i]) return false; } +#endif // ENABLE_COLOR_CLASSES return l.ibuffer_id < r.ibuffer_id; } }; @@ -299,7 +325,11 @@ class GCodeViewer struct Model { GLModel model; +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else Color color; +#endif // ENABLE_COLOR_CLASSES InstanceVBuffer instances; GLModel::InitializationData data; @@ -399,7 +429,11 @@ class GCodeViewer void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; } float step_size() const { return (max - min) / (static_cast(Range_Colors.size()) - 1.0f); } +#if ENABLE_COLOR_CLASSES + ColorRGBA get_color_at(float value) const; +#else Color get_color_at(float value) const; +#endif // ENABLE_COLOR_CLASSES }; struct Ranges @@ -493,7 +527,11 @@ class GCodeViewer TBuffer* buffer{ nullptr }; unsigned int ibo{ 0 }; unsigned int vbo{ 0 }; +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else Color color; +#endif // ENABLE_COLOR_CLASSES ~SequentialRangeCap(); bool is_renderable() const { return buffer != nullptr; } @@ -697,7 +735,11 @@ private: // bounding box of toolpaths + marker tools BoundingBoxf3 m_max_bounding_box; float m_max_print_height{ 0.0f }; +#if ENABLE_COLOR_CLASSES + std::vector m_tool_colors; +#else std::vector m_tool_colors; +#endif // ENABLE_COLOR_CLASSES Layers m_layers; std::array m_layers_z_range; std::vector m_roles; @@ -792,7 +834,11 @@ private: } bool is_visible(const Path& path) const { return is_visible(path.role); } void log_memory_used(const std::string& label, int64_t additional = 0) const; +#if ENABLE_COLOR_CLASSES + ColorRGBA option_color(EMoveType move_type) const; +#else Color option_color(EMoveType move_type) const; +#endif // ENABLE_COLOR_CLASSES }; } // namespace GUI diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 622f5b3e27..73936f431f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -72,11 +72,18 @@ static constexpr const float TRACKBALLSIZE = 0.8f; +#if ENABLE_COLOR_CLASSES +static const Slic3r::ColorRGB DEFAULT_BG_DARK_COLOR = { 0.478f, 0.478f, 0.478f }; +static const Slic3r::ColorRGB DEFAULT_BG_LIGHT_COLOR = { 0.753f, 0.753f, 0.753f }; +static const Slic3r::ColorRGB ERROR_BG_DARK_COLOR = { 0.478f, 0.192f, 0.039f }; +static const Slic3r::ColorRGB ERROR_BG_LIGHT_COLOR = { 0.753f, 0.192f, 0.039f }; +#else static constexpr const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f }; static constexpr const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f }; static constexpr const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f }; static constexpr const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f }; //static constexpr const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; +#endif // ENABLE_COLOR_CLASSES // Number of floats static constexpr const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB @@ -859,8 +866,13 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons void GLCanvas3D::SequentialPrintClearance::render() { +#if ENABLE_COLOR_CLASSES + const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f }; + const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; +#else std::array FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f }; std::array NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; +#endif // ENABLE_COLOR_CLASSES GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) @@ -4119,8 +4131,10 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const return ret; }; +#if !ENABLE_COLOR_CLASSES static const std::array orange = { 0.923f, 0.504f, 0.264f, 1.0f }; static const std::array gray = { 0.64f, 0.64f, 0.64f, 1.0f }; +#endif // !ENABLE_COLOR_CLASSES GLVolumePtrs visible_volumes; @@ -4176,7 +4190,11 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const shader->set_uniform("emission_factor", 0.0f); for (GLVolume* vol : visible_volumes) { +#if ENABLE_COLOR_CLASSES + shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? (current_printer_technology() == ptSLA ? vol->color : ColorRGBA::ORANGE()) : ColorRGBA::GRAY()); +#else shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? (current_printer_technology() == ptSLA ? vol->color : orange) : gray); +#endif // ENABLE_COLOR_CLASSES // the volume may have been deactivated by an active gizmo bool is_active = vol->is_active; vol->is_active = true; @@ -4907,19 +4925,34 @@ void GLCanvas3D::_picking_pass() int volume_id = -1; int gizmo_id = -1; +#if ENABLE_COLOR_CLASSES + std::array color = { 0, 0, 0, 0 }; +#else GLubyte color[4] = { 0, 0, 0, 0 }; +#endif // ENABLE_COLOR_CLASSES const Size& cnv_size = get_canvas_size(); bool inside = 0 <= m_mouse.position(0) && m_mouse.position(0) < cnv_size.get_width() && 0 <= m_mouse.position(1) && m_mouse.position(1) < cnv_size.get_height(); if (inside) { +#if ENABLE_COLOR_CLASSES + glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position.y() - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color.data())); +#else glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color)); +#endif // ENABLE_COLOR_CLASSES if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) { // Only non-interpolated colors are valid, those have their lowest three bits zeroed. // we reserve color = (0,0,0) for occluders (as the printbed) // volumes' id are shifted by 1 // see: _render_volumes_for_picking() +#if ENABLE_COLOR_CLASSES + unsigned int id = picking_encode(color[0], color[1], color[2]); + volume_id = id - 1; + // gizmos' id are instead properly encoded by the color + gizmo_id = id; +#else volume_id = color[0] + (color[1] << 8) + (color[2] << 16) - 1; // gizmos' id are instead properly encoded by the color gizmo_id = color[0] + (color[1] << 8) + (color[2] << 16); +#endif // ENABLE_COLOR_CLASSES } } if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) { @@ -5035,18 +5068,26 @@ void GLCanvas3D::_render_background() const glsafe(::glDisable(GL_DEPTH_TEST)); ::glBegin(GL_QUADS); +#if ENABLE_COLOR_CLASSES + ::glColor3fv(use_error_color ? ERROR_BG_DARK_COLOR.data(): DEFAULT_BG_DARK_COLOR.data()); +#else if (use_error_color) ::glColor3fv(ERROR_BG_DARK_COLOR); else ::glColor3fv(DEFAULT_BG_DARK_COLOR); +#endif // ENABLE_COLOR_CLASSES ::glVertex2f(-1.0f, -1.0f); ::glVertex2f(1.0f, -1.0f); +#if ENABLE_COLOR_CLASSES + ::glColor3fv(use_error_color ? ERROR_BG_LIGHT_COLOR.data() : DEFAULT_BG_LIGHT_COLOR.data()); +#else if (use_error_color) ::glColor3fv(ERROR_BG_LIGHT_COLOR); else ::glColor3fv(DEFAULT_BG_LIGHT_COLOR); +#endif // ENABLE_COLOR_CLASSES ::glVertex2f(1.0f, 1.0f); ::glVertex2f(-1.0f, 1.0f); @@ -5346,13 +5387,18 @@ void GLCanvas3D::_render_volumes_for_picking() const // Object picking mode. Render the object with a color encoding the object index. // we reserve color = (0,0,0) for occluders (as the printbed) // so we shift volumes' id by 1 to get the proper color +#if ENABLE_COLOR_CLASSES + const unsigned int id = 1 + volume.second.first; + glsafe(::glColor4fv(picking_decode(id).data())); +#else unsigned int id = 1 + volume.second.first; unsigned int r = (id & (0x000000FF << 0)) << 0; unsigned int g = (id & (0x000000FF << 8)) >> 8; unsigned int b = (id & (0x000000FF << 16)) >> 16; unsigned int a = picking_checksum_alpha_channel(r, g, b); glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); - volume.first->render(); +#endif // ENABLE_COLOR_CLASSES + volume.first->render(); } } @@ -5771,7 +5817,11 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume) if (!print->has_skirt() && !print->has_brim()) return; +#if ENABLE_COLOR_CLASSES + const ColorRGBA color = ColorRGBA::GREENISH(); +#else const std::array color = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish +#endif // ENABLE_COLOR_CLASSES // number of skirt layers size_t total_layer_count = 0; @@ -5818,7 +5868,12 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume) void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const BuildVolume& build_volume, const std::vector& str_tool_colors, const std::vector& color_print_values) { +#if ENABLE_COLOR_CLASSES + std::vector tool_colors; + decode_colors(str_tool_colors, tool_colors); +#else std::vector> tool_colors = _parse_colors(str_tool_colors); +#endif // ENABLE_COLOR_CLASSES struct Ctxt { @@ -5827,20 +5882,35 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c bool has_perimeters; bool has_infill; bool has_support; +#if ENABLE_COLOR_CLASSES + const std::vector* tool_colors; +#else const std::vector>* tool_colors; +#endif // ENABLE_COLOR_CLASSES bool is_single_material_print; int extruders_cnt; const std::vector* color_print_values; +#if ENABLE_COLOR_CLASSES + static ColorRGBA color_perimeters() { return ColorRGBA::YELLOW(); } + static ColorRGBA color_infill() { return ColorRGBA::REDISH(); } + static ColorRGBA color_support() { return ColorRGBA::GREENISH(); } + static ColorRGBA color_pause_or_custom_code() { return ColorRGBA::GRAY(); } +#else static const std::array& color_perimeters() { static std::array color = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow static const std::array& color_infill() { static std::array color = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish static const std::array& color_support() { static std::array color = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish static const std::array& color_pause_or_custom_code() { static std::array color = { 0.5f, 0.5f, 0.5f, 1.f }; return color; } // gray +#endif // ENABLE_COLOR_CLASSES // For cloring by a tool, return a parsed color. bool color_by_tool() const { return tool_colors != nullptr; } size_t number_tools() const { return color_by_tool() ? tool_colors->size() : 0; } +#if ENABLE_COLOR_CLASSES + const ColorRGBA& color_tool(size_t tool) const { return (*tool_colors)[tool]; } +#else const std::array& color_tool(size_t tool) const { return (*tool_colors)[tool]; } +#endif // ENABLE_COLOR_CLASSES // For coloring by a color_print(M600), return a parsed color. bool color_by_color_print() const { return color_print_values!=nullptr; } @@ -5980,7 +6050,11 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c //FIXME Improve the heuristics for a grain size. size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1)); tbb::spin_mutex new_volume_mutex; +#if ENABLE_COLOR_CLASSES + auto new_volume = [this, &new_volume_mutex](const ColorRGBA& color) { +#else auto new_volume = [this, &new_volume_mutex](const std::array& color) { +#endif // ENABLE_COLOR_CLASSES // Allocate the volume before locking. GLVolume *volume = new GLVolume(color); volume->is_extrusion_path = true; @@ -6121,21 +6195,38 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con if (!print->is_step_done(psWipeTower)) return; +#if ENABLE_COLOR_CLASSES + std::vector tool_colors; + decode_colors(str_tool_colors, tool_colors); +#else std::vector> tool_colors = _parse_colors(str_tool_colors); +#endif // ENABLE_COLOR_CLASSES struct Ctxt { const Print *print; +#if ENABLE_COLOR_CLASSES + const std::vector* tool_colors; +#else const std::vector>* tool_colors; +#endif // ENABLE_COLOR_CLASSES Vec2f wipe_tower_pos; float wipe_tower_angle; +#if ENABLE_COLOR_CLASSES + static ColorRGBA color_support() { return ColorRGBA::GREENISH(); } +#else static const std::array& color_support() { static std::array color = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish +#endif // ENABLE_COLOR_CLASSES // For cloring by a tool, return a parsed color. bool color_by_tool() const { return tool_colors != nullptr; } size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() : 0; } +#if ENABLE_COLOR_CLASSES + const ColorRGBA& color_tool(size_t tool) const { return (*tool_colors)[tool]; } +#else const std::array& color_tool(size_t tool) const { return (*tool_colors)[tool]; } +#endif // ENABLE_COLOR_CLASSES int volume_idx(int tool, int feature) const { return this->color_by_tool() ? std::min(this->number_tools() - 1, std::max(tool, 0)) : feature; } @@ -6167,7 +6258,11 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1); size_t grain_size = std::max(n_items / 128, size_t(1)); tbb::spin_mutex new_volume_mutex; +#if ENABLE_COLOR_CLASSES + auto new_volume = [this, &new_volume_mutex](const ColorRGBA& color) { +#else auto new_volume = [this, &new_volume_mutex](const std::array& color) { +#endif // ENABLE_COLOR_CLASSES auto *volume = new GLVolume(color); volume->is_extrusion_path = true; tbb::spin_mutex::scoped_lock lock; @@ -6286,7 +6381,11 @@ void GLCanvas3D::_load_sla_shells() return; auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance, +#if ENABLE_COLOR_CLASSES + const TriangleMesh& mesh, const ColorRGBA& color, bool outside_printer_detection_enabled) { +#else const TriangleMesh& mesh, const std::array& color, bool outside_printer_detection_enabled) { +#endif // ENABLE_COLOR_CLASSES m_volumes.volumes.emplace_back(new GLVolume(color)); GLVolume& v = *m_volumes.volumes.back(); #if ENABLE_SMOOTH_NORMALS @@ -6348,6 +6447,7 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) _set_warning_notification(warning, show); } +#if !ENABLE_COLOR_CLASSES std::vector> GLCanvas3D::_parse_colors(const std::vector& colors) { static const float INV_255 = 1.0f / 255.0f; @@ -6369,6 +6469,7 @@ std::vector> GLCanvas3D::_parse_colors(const std::vector> _parse_colors(const std::vector& colors); +#endif // !ENABLE_COLOR_CLASSES }; } // namespace GUI diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 422b654080..f18cb0a237 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -165,6 +165,15 @@ bool GLModel::init_from_file(const std::string& filename) return true; } +#if ENABLE_COLOR_CLASSES +void GLModel::set_color(int entity_id, const ColorRGBA& color) +{ + for (size_t i = 0; i < m_render_data.size(); ++i) { + if (entity_id == -1 || static_cast(i) == entity_id) + m_render_data[i].color = color; + } +} +#else void GLModel::set_color(int entity_id, const std::array& color) { for (size_t i = 0; i < m_render_data.size(); ++i) { @@ -172,6 +181,7 @@ void GLModel::set_color(int entity_id, const std::array& color) m_render_data[i].color = color; } } +#endif // ENABLE_COLOR_CLASSES void GLModel::reset() { @@ -216,7 +226,11 @@ void GLModel::render() const if (shader != nullptr) shader->set_uniform("uniform_color", data.color); else +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(data.color.data())); +#else + glsafe(::glColor4fv(data.color.data())); +#endif // ENABLE_COLOR_CLASSES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id)); glsafe(::glDrawElements(mode, static_cast(data.indices_count), GL_UNSIGNED_INT, (const void*)0)); @@ -276,7 +290,11 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance if (shader != nullptr) shader->set_uniform("uniform_color", data.color); else +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(data.color.data())); +#else + glsafe(::glColor4fv(data.color.data())); +#endif // ENABLE_COLOR_CLASSES glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); if (position_id != -1) { diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index d47c56fd93..8bb60ba795 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -3,6 +3,9 @@ #include "libslic3r/Point.hpp" #include "libslic3r/BoundingBox.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include #include @@ -33,7 +36,11 @@ namespace GUI { unsigned int vbo_id{ 0 }; unsigned int ibo_id{ 0 }; size_t indices_count{ 0 }; +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else std::array color{ 1.0f, 1.0f, 1.0f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES }; struct InitializationData @@ -44,7 +51,11 @@ namespace GUI { std::vector positions; std::vector normals; std::vector indices; +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else std::array color{ 1.0f, 1.0f, 1.0f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES }; std::vector entities; @@ -74,7 +85,11 @@ namespace GUI { bool init_from_file(const std::string& filename); // if entity_id == -1 set the color of all entities +#if ENABLE_COLOR_CLASSES + void set_color(int entity_id, const ColorRGBA& color); +#else void set_color(int entity_id, const std::array& color); +#endif // ENABLE_COLOR_CLASSES void reset(); void render() const; diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index 4c36efdd92..42dcbeca0d 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -4,6 +4,9 @@ #include "3DScene.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/format.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include #include @@ -306,6 +309,18 @@ void GLShaderProgram::set_uniform(int id, const Vec3d& value) const set_uniform(id, static_cast(value.cast())); } +#if ENABLE_COLOR_CLASSES +void GLShaderProgram::set_uniform(int id, const ColorRGB& value) const +{ + set_uniform(id, value.data(), 3); +} + +void GLShaderProgram::set_uniform(int id, const ColorRGBA& value) const +{ + set_uniform(id, value.data(), 4); +} +#endif // ENABLE_COLOR_CLASSES + int GLShaderProgram::get_attrib_location(const char* name) const { assert(m_id > 0); diff --git a/src/slic3r/GUI/GLShader.hpp b/src/slic3r/GUI/GLShader.hpp index 46e46b4f08..0a41461e28 100644 --- a/src/slic3r/GUI/GLShader.hpp +++ b/src/slic3r/GUI/GLShader.hpp @@ -9,6 +9,11 @@ namespace Slic3r { +#if ENABLE_COLOR_CLASSES +class ColorRGB; +class ColorRGBA; +#endif // ENABLE_COLOR_CLASSES + class GLShaderProgram { public: @@ -60,6 +65,10 @@ public: void set_uniform(const char* name, const Matrix3f& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Vec3f& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Vec3d& value) const { set_uniform(get_uniform_location(name), value); } +#if ENABLE_COLOR_CLASSES + void set_uniform(const char* name, const ColorRGB& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const ColorRGBA& value) const { set_uniform(get_uniform_location(name), value); } +#endif // ENABLE_COLOR_CLASSES void set_uniform(int id, int value) const; void set_uniform(int id, bool value) const; @@ -77,6 +86,10 @@ public: void set_uniform(int id, const Matrix3f& value) const; void set_uniform(int id, const Vec3f& value) const; void set_uniform(int id, const Vec3d& value) const; +#if ENABLE_COLOR_CLASSES + void set_uniform(int id, const ColorRGB& value) const; + void set_uniform(int id, const ColorRGBA& value) const; +#endif // ENABLE_COLOR_CLASSES // returns -1 if not found int get_attrib_location(const char* name) const; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 0436ab1e6a..131b9df2a3 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -44,6 +44,9 @@ #include "libslic3r/Model.hpp" #include "libslic3r/I18N.hpp" #include "libslic3r/PresetBundle.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GUI.hpp" #include "GUI_Utils.hpp" @@ -1520,8 +1523,12 @@ void GUI_App::set_label_clr_modified(const wxColour& clr) if (m_color_label_modified == clr) return; m_color_label_modified = clr; +#if ENABLE_COLOR_CLASSES + const std::string str = encode_color(ColorRGB(clr.Red(), clr.Green(), clr.Blue())); +#else auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); std::string str = clr_str.ToStdString(); +#endif // ENABLE_COLOR_CLASSES app_config->set("label_clr_modified", str); app_config->save(); } @@ -1531,8 +1538,12 @@ void GUI_App::set_label_clr_sys(const wxColour& clr) if (m_color_label_sys == clr) return; m_color_label_sys = clr; +#if ENABLE_COLOR_CLASSES + const std::string str = encode_color(ColorRGB(clr.Red(), clr.Green(), clr.Blue())); +#else auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); std::string str = clr_str.ToStdString(); +#endif // ENABLE_COLOR_CLASSES app_config->set("label_clr_sys", str); app_config->save(); } diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index a5ba218b52..4b4bc2396a 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -406,6 +406,7 @@ public: std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics); +#if !ENABLE_COLOR_CLASSES inline int hex_digit_to_int(const char c) { return @@ -413,6 +414,7 @@ inline int hex_digit_to_int(const char c) (c >= 'A' && c <= 'F') ? int(c - 'A') + 10 : (c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1; } +#endif // !ENABLE_COLOR_CLASSES class TaskTimer { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 97ab7094c7..3d697942ce 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -25,6 +25,11 @@ GLGizmoBase::Grabber::Grabber() void GLGizmoBase::Grabber::render(bool hover, float size) const { +#if ENABLE_COLOR_CLASSES + ColorRGBA render_color = color; + if (hover) + render_color = complementary(render_color); +#else std::array render_color; if (hover) { render_color[0] = (1.0f - color[0]); @@ -34,6 +39,7 @@ void GLGizmoBase::Grabber::render(bool hover, float size) const } else render_color = color; +#endif // ENABLE_COLOR_CLASSES render(size, render_color, false); } @@ -48,7 +54,11 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const return get_half_size(size) * DraggingScaleFactor; } +#if ENABLE_COLOR_CLASSES +void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) const +#else void GLGizmoBase::Grabber::render(float size, const std::array& render_color, bool picking) const +#endif // ENABLE_COLOR_CLASSES { if (!cube.is_initialized()) { // This cannot be done in constructor, OpenGL is not yet @@ -99,10 +109,12 @@ void GLGizmoBase::set_hover_id(int id) } } +#if !ENABLE_COLOR_CLASSES void GLGizmoBase::set_highlight_color(const std::array& color) { m_highlight_color = color; } +#endif // !ENABLE_COLOR_CLASSES void GLGizmoBase::enable_grabber(unsigned int id) { @@ -157,15 +169,21 @@ bool GLGizmoBase::update_items_state() return res; }; +#if ENABLE_COLOR_CLASSES +ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const +{ +#else std::array GLGizmoBase::picking_color_component(unsigned int id) const { static const float INV_255 = 1.0f / 255.0f; - +#endif // ENABLE_COLOR_CLASSES id = BASE_ID - id; - if (m_group_id > -1) id -= m_group_id; +#if ENABLE_COLOR_CLASSES + return picking_decode(id); +#else // color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass() return std::array { float((id >> 0) & 0xff) * INV_255, // red @@ -173,6 +191,7 @@ std::array GLGizmoBase::picking_color_component(unsigned int id) const float((id >> 16) & 0xff) * INV_255, // blue float(picking_checksum_alpha_channel(id & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff))* INV_255 // checksum for validating against unwanted alpha blending and multi sampling }; +#endif // ENABLE_COLOR_CLASSES } void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const @@ -200,8 +219,12 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) { +#if ENABLE_COLOR_CLASSES + m_grabbers[i].color = picking_color_component(i); +#else std::array color = picking_color_component(i); m_grabbers[i].color = color; +#endif // ENABLE_COLOR_CLASSES m_grabbers[i].render_for_picking(mean_size); } } @@ -238,8 +261,7 @@ std::string GLGizmoBase::get_name(bool include_shortcut) const return out; } - - +#if !ENABLE_COLOR_CLASSES // Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components // were not interpolated by alpha blending or multi sampling. unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue) @@ -254,7 +276,7 @@ unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char gr b ^= 0x55; return b; } - +#endif // !ENABLE_COLOR_CLASSES } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 1e2cd93fbb..ef0a91b3e8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -2,6 +2,9 @@ #define slic3r_GLGizmoBase_hpp_ #include "libslic3r/Point.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/GLModel.hpp" @@ -18,6 +21,13 @@ class ModelObject; namespace GUI { +#if ENABLE_COLOR_CLASSES + static const ColorRGBA DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f }; + static const ColorRGBA DEFAULT_DRAG_COLOR = ColorRGBA::WHITE(); + static const ColorRGBA DEFAULT_HIGHLIGHT_COLOR = ColorRGBA::ORANGE(); + static const std::array AXES_COLOR = {{ ColorRGBA::X(), ColorRGBA::Y(), ColorRGBA::Z() }}; + static const ColorRGBA CONSTRAINED_COLOR = ColorRGBA::GRAY(); +#else static const std::array DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f }; static const std::array DEFAULT_DRAG_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f }; static const std::array DEFAULT_HIGHLIGHT_COLOR = { 1.0f, 0.38f, 0.0f, 1.0f }; @@ -27,6 +37,7 @@ static const std::array, 3> AXES_COLOR = {{ { 0.0f, 0.0f, 0.75f, 1.0f } }}; static const std::array CONSTRAINED_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES class ImGuiWrapper; class GLCanvas3D; @@ -50,7 +61,11 @@ protected: Vec3d center; Vec3d angles; +#if ENABLE_COLOR_CLASSES + ColorRGBA color; +#else std::array color; +#endif // ENABLE_COLOR_CLASSES bool enabled; bool dragging; @@ -63,7 +78,11 @@ protected: float get_dragging_half_size(float size) const; private: +#if ENABLE_COLOR_CLASSES + void render(float size, const ColorRGBA& render_color, bool picking) const; +#else void render(float size, const std::array& render_color, bool picking) const; +#endif // ENABLE_COLOR_CLASSES GLModel cube; }; @@ -96,9 +115,15 @@ protected: unsigned int m_sprite_id; int m_hover_id; bool m_dragging; +#if ENABLE_COLOR_CLASSES + ColorRGBA m_base_color; + ColorRGBA m_drag_color; + ColorRGBA m_highlight_color; +#else std::array m_base_color; std::array m_drag_color; std::array m_highlight_color; +#endif // ENABLE_COLOR_CLASSES mutable std::vector m_grabbers; ImGuiWrapper* m_imgui; bool m_first_input_window_render; @@ -142,7 +167,11 @@ public: int get_hover_id() const { return m_hover_id; } void set_hover_id(int id); +#if ENABLE_COLOR_CLASSES + void set_highlight_color(const ColorRGBA& color) { m_highlight_color = color; } +#else void set_highlight_color(const std::array& color); +#endif // ENABLE_COLOR_CLASSES void enable_grabber(unsigned int id); void disable_grabber(unsigned int id); @@ -184,7 +213,11 @@ protected: // Returns the picking color for the given id, based on the BASE_ID constant // No check is made for clashing with other picking color (i.e. GLVolumes) +#if ENABLE_COLOR_CLASSES + ColorRGBA picking_color_component(unsigned int id) const; +#else std::array picking_color_component(unsigned int id) const; +#endif // ENABLE_COLOR_CLASSES void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(float size) const; void render_grabbers_for_picking(const BoundingBoxf3& box) const; @@ -199,9 +232,11 @@ private: bool m_dirty; }; +#if !ENABLE_COLOR_CLASSES // Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components // were not interpolated by alpha blending or multi sampling. extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue); +#endif // !ENABLE_COLOR_CLASSES } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index d2c32d488a..3b5cc29080 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -23,7 +23,12 @@ namespace GUI { const double GLGizmoCut::Offset = 10.0; const double GLGizmoCut::Margin = 20.0; +#if ENABLE_COLOR_CLASSES +static const ColorRGBA GRABBER_COLOR = ColorRGBA::ORANGE(); +static const ColorRGBA PLANE_COLOR = { 0.8f, 0.8f, 0.8f, 0.5f }; +#else const std::array GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0, 1.0 }; +#endif // ENABLE_COLOR_CLASSES GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) @@ -103,7 +108,11 @@ void GLGizmoCut::on_render() // Draw the cutting plane ::glBegin(GL_QUADS); +#if ENABLE_COLOR_CLASSES + ::glColor4fv(PLANE_COLOR.data()); +#else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); +#endif // ENABLE_COLOR_CLASSES ::glVertex3f(min_x, min_y, plane_center.z()); ::glVertex3f(max_x, min_y, plane_center.z()); ::glVertex3f(max_x, max_y, plane_center.z()); @@ -134,7 +143,11 @@ void GLGizmoCut::on_render() shader->start_using(); shader->set_uniform("emission_factor", 0.1f); +#if ENABLE_COLOR_CLASSES + m_grabbers[0].color = GRABBER_COLOR; +#else m_grabbers[0].color = GrabberColor; +#endif // ENABLE_COLOR_CLASSES m_grabbers[0].render(m_hover_id == 0, (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0)); shader->stop_using(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 4007f89d47..fde5d71b93 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -13,7 +13,9 @@ class GLGizmoCut : public GLGizmoBase { static const double Offset; static const double Margin; +#if !ENABLE_COLOR_CLASSES static const std::array GrabberColor; +#endif // !ENABLE_COLOR_CLASSES double m_cut_z{ 0.0 }; double m_max_z{ 0.0 }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 9034d78d87..e3eea101c4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -13,6 +13,10 @@ namespace Slic3r { namespace GUI { +#if ENABLE_COLOR_CLASSES +static const Slic3r::ColorRGBA DEFAULT_PLANE_COLOR = { 0.9f, 0.9f, 0.9f, 0.5f }; +static const Slic3r::ColorRGBA DEFAULT_HOVER_PLANE_COLOR = { 0.9f, 0.9f, 0.9f, 0.75f }; +#endif // ENABLE_COLOR_CLASSES GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) @@ -74,10 +78,14 @@ void GLGizmoFlatten::on_render() if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { +#if ENABLE_COLOR_CLASSES + glsafe(::glColor4fv(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR.data() : DEFAULT_PLANE_COLOR.data())); +#else if (i == m_hover_id) glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.75f)); else glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.5f)); +#endif // ENABLE_COLOR_CLASSES if (m_planes[i].vbo.has_VBOs()) m_planes[i].vbo.render(); @@ -104,7 +112,11 @@ void GLGizmoFlatten::on_render_for_picking() if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(picking_color_component(i).data())); +#else + glsafe(::glColor4fv(picking_color_component(i).data())); +#endif // ENABLE_COLOR_CLASSES m_planes[i].vbo.render(); } glsafe(::glPopMatrix()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index a001d5a81c..5c151e0ad3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -116,7 +116,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift())); glsafe(::glMultMatrixd(instance_matrix.data())); +#if ENABLE_COLOR_CLASSES + ColorRGBA render_color; +#else std::array render_color; +#endif // ENABLE_COLOR_CLASSES const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; size_t cache_size = drain_holes.size(); @@ -129,24 +133,30 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons // First decide about the color of the point. if (picking) { +#if ENABLE_COLOR_CLASSES + render_color = picking_color_component(i); +#else std::array color = picking_color_component(i); render_color = color; +#endif // ENABLE_COLOR_CLASSES } else { - if (size_t(m_hover_id) == i) { - render_color = {0.f, 1.f, 1.f, 1.f}; - } + if (size_t(m_hover_id) == i) + render_color = {0.0f, 1.0f, 1.0f, 1.0f}; else if (m_c->hollowed_mesh() && i < m_c->hollowed_mesh()->get_drainholes().size() && m_c->hollowed_mesh()->get_drainholes()[i].failed) { - render_color = {1.f, 0.f, 0.f, .5f}; + render_color = {1.0f, 0.0f, 0.0f, 0.5f}; } - else { // neigher hover nor picking - + else { // neither hover nor picking +#if ENABLE_COLOR_CLASSES + render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); +#else render_color[0] = point_selected ? 1.0f : 1.f; render_color[1] = point_selected ? 0.3f : 1.f; render_color[2] = point_selected ? 0.3f : 1.f; render_color[3] = 0.5f; +#endif // ENABLE_COLOR_CLASSES } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 285089357f..a315d0e977 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -56,10 +56,20 @@ bool GLGizmoMmuSegmentation::on_is_activable() const return GLGizmoPainterBase::on_is_activable() && wxGetApp().extruders_edited_cnt() > 1; } +#if ENABLE_COLOR_CLASSES +static std::vector get_extruders_colors() +{ +#else static std::vector> get_extruders_colors() { unsigned char rgb_color[3] = {}; - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); +#endif // ENABLE_COLOR_CLASSES + std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); +#if ENABLE_COLOR_CLASSES + std::vector ret; + decode_colors(colors, ret); + return ret; +#else std::vector> colors_out(colors.size()); for (const std::string &color : colors) { Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); @@ -68,6 +78,7 @@ static std::vector> get_extruders_colors() } return colors_out; +#endif // ENABLE_COLOR_CLASSES } static std::vector get_extruders_names() @@ -212,17 +223,26 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const } } +#if ENABLE_COLOR_CLASSES +static void render_extruders_combo(const std::string& label, + const std::vector& extruders, + const std::vector& extruders_colors, + size_t& selection_idx) +#else static void render_extruders_combo(const std::string &label, const std::vector &extruders, const std::vector> &extruders_colors, size_t &selection_idx) +#endif // ENABLE_COLOR_CLASSES { assert(!extruders_colors.empty()); assert(extruders_colors.size() == extruders_colors.size()); +#if !ENABLE_COLOR_CLASSES auto convert_to_imu32 = [](const std::array &color) -> ImU32 { return IM_COL32(uint8_t(color[0] * 255.f), uint8_t(color[1] * 255.f), uint8_t(color[2] * 255.f), uint8_t(color[3] * 255.f)); }; +#endif // !ENABLE_COLOR_CLASSES size_t selection_out = selection_idx; // It is necessary to use BeginGroup(). Otherwise, when using SameLine() is called, then other items will be drawn inside the combobox. @@ -239,7 +259,11 @@ static void render_extruders_combo(const std::string &labe ImGui::SameLine(); ImGuiStyle &style = ImGui::GetStyle(); float height = ImGui::GetTextLineHeight(); +#if ENABLE_COLOR_CLASSES + ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), ImGuiWrapper::to_ImU32(extruders_colors[extruder_idx])); +#else ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), convert_to_imu32(extruders_colors[extruder_idx])); +#endif // ENABLE_COLOR_CLASSES ImGui::GetWindowDrawList()->AddRect(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), IM_COL32_BLACK); ImGui::SetCursorScreenPos(ImVec2(start_position.x + height + height / 2 + style.FramePadding.x, start_position.y)); @@ -257,7 +281,11 @@ static void render_extruders_combo(const std::string &labe ImVec2 p = ImGui::GetCursorScreenPos(); float height = ImGui::GetTextLineHeight(); +#if ENABLE_COLOR_CLASSES + ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height), ImGuiWrapper::to_ImU32(extruders_colors[selection_idx])); +#else ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height), convert_to_imu32(extruders_colors[selection_idx])); +#endif // ENABLE_COLOR_CLASSES ImGui::GetWindowDrawList()->AddRect(p, ImVec2(p.x + height + height / 2, p.y + height), IM_COL32_BLACK); ImGui::SetCursorScreenPos(ImVec2(p.x + height + height / 2 + style.FramePadding.x, p.y)); @@ -343,10 +371,17 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott render_extruders_combo("##first_color_combo", m_original_extruders_names, m_original_extruders_colors, m_first_selected_extruder_idx); ImGui::SameLine(); +#if ENABLE_COLOR_CLASSES + const ColorRGBA& select_first_color = m_modified_extruders_colors[m_first_selected_extruder_idx]; + ImVec4 first_color = ImGuiWrapper::to_ImVec4(select_first_color); + if (ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) + m_modified_extruders_colors[m_first_selected_extruder_idx] = ImGuiWrapper::from_ImVec4(first_color); +#else const std::array &select_first_color = m_modified_extruders_colors[m_first_selected_extruder_idx]; - ImVec4 first_color = ImVec4(select_first_color[0], select_first_color[1], select_first_color[2], select_first_color[3]); - if(ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) - m_modified_extruders_colors[m_first_selected_extruder_idx] = {first_color.x, first_color.y, first_color.z, first_color.w}; + ImVec4 first_color = ImVec4(select_first_color[0], select_first_color[1], select_first_color[2], select_first_color[3]); + if (ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) + m_modified_extruders_colors[m_first_selected_extruder_idx] = { first_color.x, first_color.y, first_color.z, first_color.w }; +#endif // ENABLE_COLOR_CLASSES ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("second_color")); @@ -355,10 +390,17 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott render_extruders_combo("##second_color_combo", m_original_extruders_names, m_original_extruders_colors, m_second_selected_extruder_idx); ImGui::SameLine(); +#if ENABLE_COLOR_CLASSES + const ColorRGBA& select_second_color = m_modified_extruders_colors[m_second_selected_extruder_idx]; + ImVec4 second_color = ImGuiWrapper::to_ImVec4(select_second_color); + if (ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) + m_modified_extruders_colors[m_second_selected_extruder_idx] = ImGuiWrapper::from_ImVec4(second_color); +#else const std::array &select_second_color = m_modified_extruders_colors[m_second_selected_extruder_idx]; ImVec4 second_color = ImVec4(select_second_color[0], select_second_color[1], select_second_color[2], select_second_color[3]); - if(ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) - m_modified_extruders_colors[m_second_selected_extruder_idx] = {second_color.x, second_color.y, second_color.z, second_color.w}; + if (ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) + m_modified_extruders_colors[m_second_selected_extruder_idx] = { second_color.x, second_color.y, second_color.z, second_color.w }; +#endif // ENABLE_COLOR_CLASSES const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; @@ -595,6 +637,21 @@ PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const return PainterGizmoType::MMU_SEGMENTATION; } +#if ENABLE_COLOR_CLASSES +ColorRGBA GLGizmoMmuSegmentation::get_cursor_sphere_left_button_color() const +{ + ColorRGBA color = m_modified_extruders_colors[m_first_selected_extruder_idx]; + color.a(0.25f); + return color; +} + +ColorRGBA GLGizmoMmuSegmentation::get_cursor_sphere_right_button_color() const +{ + ColorRGBA color = m_modified_extruders_colors[m_second_selected_extruder_idx]; + color.a(0.25f); + return color; +} +#else std::array GLGizmoMmuSegmentation::get_cursor_sphere_left_button_color() const { const std::array &color = m_modified_extruders_colors[m_first_selected_extruder_idx]; @@ -606,6 +663,7 @@ std::array GLGizmoMmuSegmentation::get_cursor_sphere_right_button_colo const std::array &color = m_modified_extruders_colors[m_second_selected_extruder_idx]; return {color[0], color[1], color[2], 0.25f}; } +#endif // ENABLE_COLOR_CLASSES void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 577db8ed5a..cde33d99cc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -62,8 +62,13 @@ public: class TriangleSelectorMmGui : public TriangleSelectorGUI { public: // Plus 1 in the initialization of m_gizmo_scene is because the first position is allocated for non-painted triangles, and the indices above colors.size() are allocated for seed fill. +#if ENABLE_COLOR_CLASSES + TriangleSelectorMmGui(const TriangleMesh& mesh, const std::vector& colors, const ColorRGBA& default_volume_color) + : TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color), m_gizmo_scene(2 * (colors.size() + 1)) {} +#else explicit TriangleSelectorMmGui(const TriangleMesh &mesh, const std::vector> &colors, const std::array &default_volume_color) : TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color), m_gizmo_scene(2 * (colors.size() + 1)) {} +#endif // ENABLE_COLOR_CLASSES ~TriangleSelectorMmGui() override = default; // Render current selection. Transformation matrices are supposed @@ -73,8 +78,13 @@ public: private: void update_render_data(); +#if ENABLE_COLOR_CLASSES + const std::vector& m_colors; + const ColorRGBA m_default_volume_color; +#else const std::vector> &m_colors; const std::array m_default_volume_color; +#endif // ENABLE_COLOR_CLASSES GLMmSegmentationGizmo3DScene m_gizmo_scene; }; @@ -100,8 +110,13 @@ public: const float get_cursor_radius_min() const override { return CursorRadiusMin; } protected: +#if ENABLE_COLOR_CLASSES + ColorRGBA get_cursor_sphere_left_button_color() const override; + ColorRGBA get_cursor_sphere_right_button_color() const override; +#else std::array get_cursor_sphere_left_button_color() const override; std::array get_cursor_sphere_right_button_color() const override; +#endif // ENABLE_COLOR_CLASSES EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx + 1); } EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx + 1); } @@ -121,8 +136,13 @@ protected: size_t m_first_selected_extruder_idx = 0; size_t m_second_selected_extruder_idx = 1; std::vector m_original_extruders_names; +#if ENABLE_COLOR_CLASSES + std::vector m_original_extruders_colors; + std::vector m_modified_extruders_colors; +#else std::vector> m_original_extruders_colors; std::vector> m_modified_extruders_colors; +#endif // ENABLE_COLOR_CLASSES std::vector m_original_volumes_extruder_idxs; static const constexpr float CursorRadiusMin = 0.1f; // cannot be zero diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index d16f0ff2d7..c36d448cdf 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -117,7 +117,11 @@ void GLGizmoMove3D::on_render() // draw axes for (unsigned int i = 0; i < 3; ++i) { if (m_grabbers[i].enabled) { +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(AXES_COLOR[i].data())); +#else + glsafe(::glColor4fv(AXES_COLOR[i].data())); +#endif // ENABLE_COLOR_CLASSES ::glBegin(GL_LINES); ::glVertex3dv(center.data()); ::glVertex3dv(m_grabbers[i].center.data()); @@ -134,7 +138,11 @@ void GLGizmoMove3D::on_render() } else { // draw axis +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data())); +#else + glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data())); +#endif // ENABLE_COLOR_CLASSES ::glBegin(GL_LINES); ::glVertex3dv(center.data()); ::glVertex3dv(m_grabbers[m_hover_id].center.data()); @@ -195,6 +203,11 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size); +#if ENABLE_COLOR_CLASSES + ColorRGBA color = m_grabbers[axis].color; + if (!picking && m_hover_id != -1) + color = complementary(color); +#else std::array color = m_grabbers[axis].color; if (!picking && m_hover_id != -1) { color[0] = 1.0f - color[0]; @@ -202,6 +215,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box color[2] = 1.0f - color[2]; color[3] = color[3]; } +#endif // ENABLE_COLOR_CLASSES GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index fa59d76464..bfb2d6fefa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -207,12 +207,20 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const if (is_left_handed) glFrontFace(GL_CW); +#if ENABLE_COLOR_CLASSES + ColorRGBA render_color = { 0.0f, 0.0f, 0.0f, 0.25f }; +#else std::array render_color = {0.f, 0.f, 0.f, 0.25f}; +#endif // ENABLE_COLOR_CLASSES if (m_button_down == Button::Left) render_color = this->get_cursor_sphere_left_button_color(); else if (m_button_down == Button::Right) render_color = this->get_cursor_sphere_right_button_color(); +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(render_color.data())); +#else + glsafe(::glColor4fv(render_color.data())); +#endif // ENABLE_COLOR_CLASSES assert(s_sphere != nullptr); s_sphere->render(); @@ -709,15 +717,27 @@ TriangleSelector::ClippingPlane GLGizmoPainterBase::get_clipping_plane_in_volume return TriangleSelector::ClippingPlane({float(normal_transformed.x()), float(normal_transformed.y()), float(normal_transformed.z()), offset_transformed}); } +#if ENABLE_COLOR_CLASSES +ColorRGBA TriangleSelectorGUI::get_seed_fill_color(const ColorRGBA& base_color) +{ + return saturate(base_color, 0.75f); +} +#else std::array TriangleSelectorGUI::get_seed_fill_color(const std::array &base_color) { - return {base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f}; + return { base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f }; } +#endif // ENABLE_COLOR_CLASSES void TriangleSelectorGUI::render(ImGuiWrapper* imgui) { +#if ENABLE_COLOR_CLASSES + static const ColorRGBA enforcers_color = { 0.47f, 0.47f, 1.0f, 1.0f }; + static const ColorRGBA blockers_color = { 1.0f, 0.44f, 0.44f, 1.0f }; +#else static constexpr std::array enforcers_color{0.47f, 0.47f, 1.f, 1.f}; static constexpr std::array blockers_color{1.f, 0.44f, 0.44f, 1.f}; +#endif // ENABLE_COLOR_CLASSES if (m_update_render_data) { update_render_data(); @@ -741,9 +761,15 @@ 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(); +#if ENABLE_COLOR_CLASSES + const ColorRGBA& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : + color_idx == 2 ? blockers_color : + GLVolume::NEUTRAL_COLOR); +#else const std::array &color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : color_idx == 2 ? blockers_color : GLVolume::NEUTRAL_COLOR); +#endif // ENABLE_COLOR_CLASSES shader->set_uniform("uniform_color", color); iva.render(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index ea6760a17a..2822ec2928 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -86,7 +86,11 @@ public: protected: bool m_update_render_data = false; +#if ENABLE_COLOR_CLASSES + static ColorRGBA get_seed_fill_color(const ColorRGBA& base_color); +#else static std::array get_seed_fill_color(const std::array &base_color); +#endif // ENABLE_COLOR_CLASSES private: void update_render_data(); @@ -135,8 +139,13 @@ protected: virtual void update_model_object() const = 0; virtual void update_from_model_object() = 0; +#if ENABLE_COLOR_CLASSES + virtual ColorRGBA get_cursor_sphere_left_button_color() const { return { 0.0f, 0.0f, 1.0f, 0.25f }; } + virtual ColorRGBA get_cursor_sphere_right_button_color() const { return { 1.0f, 0.0f, 0.0f, 0.25f }; } +#else virtual std::array get_cursor_sphere_left_button_color() const { return {0.f, 0.f, 1.f, 0.25f}; } virtual std::array get_cursor_sphere_right_button_color() const { return {1.f, 0.f, 0.f, 0.25f}; } +#endif // ENABLE_COLOR_CLASSES virtual EnforcerBlockerType get_left_button_state_type() const { return EnforcerBlockerType::ENFORCER; } virtual EnforcerBlockerType get_right_button_state_type() const { return EnforcerBlockerType::BLOCKER; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index a234a19ff9..bfad56c592 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -137,7 +137,11 @@ void GLGizmoRotate::on_render() transform_to_local(selection); glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data())); +#else + glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data())); +#endif // ENABLE_COLOR_CLASSES render_circle(); @@ -147,7 +151,11 @@ void GLGizmoRotate::on_render() render_reference_radius(); } +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_highlight_color.data())); +#else + glsafe(::glColor4fv(m_highlight_color.data())); +#endif // ENABLE_COLOR_CLASSES if (m_hover_id != -1) render_angle(); @@ -298,7 +306,11 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); m_grabbers[0].angles(2) = m_angle; +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data())); +#else + glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data())); +#endif // ENABLE_COLOR_CLASSES ::glBegin(GL_LINES); ::glVertex3f(0.0f, 0.0f, 0.0f); @@ -314,12 +326,18 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0); double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size); +#if ENABLE_COLOR_CLASSES + ColorRGBA color = m_grabbers[0].color; + if (!picking && m_hover_id != -1) + color = complementary(color); +#else std::array color = m_grabbers[0].color; if (!picking && m_hover_id != -1) { color[0] = 1.0f - color[0]; color[1] = 1.0f - color[1]; color[2] = 1.0f - color[2]; } +#endif // ENABLE_COLOR_CLASSES GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index b97507166b..44d0f7dc54 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -209,18 +209,34 @@ void GLGizmoScale3D::on_render() if (m_hover_id == -1) { // draw connections if (m_grabbers[0].enabled && m_grabbers[1].enabled) { +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_grabbers[0].color.data())); +#else + glsafe(::glColor4fv(m_grabbers[0].color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(0, 1); } if (m_grabbers[2].enabled && m_grabbers[3].enabled) { +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_grabbers[2].color.data())); +#else + glsafe(::glColor4fv(m_grabbers[2].color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(2, 3); } if (m_grabbers[4].enabled && m_grabbers[5].enabled) { +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_grabbers[4].color.data())); +#else + glsafe(::glColor4fv(m_grabbers[4].color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(4, 5); } +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_base_color.data())); +#else + glsafe(::glColor4fv(m_base_color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(6, 7); render_grabbers_connection(7, 8); render_grabbers_connection(8, 9); @@ -230,7 +246,11 @@ void GLGizmoScale3D::on_render() } else if (m_hover_id == 0 || m_hover_id == 1) { // draw connection +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_grabbers[0].color.data())); +#else + glsafe(::glColor4fv(m_grabbers[0].color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(0, 1); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); @@ -245,7 +265,11 @@ void GLGizmoScale3D::on_render() } else if (m_hover_id == 2 || m_hover_id == 3) { // draw connection +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_grabbers[2].color.data())); +#else + glsafe(::glColor4fv(m_grabbers[2].color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(2, 3); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); @@ -260,7 +284,11 @@ void GLGizmoScale3D::on_render() } else if (m_hover_id == 4 || m_hover_id == 5) { // draw connection +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_grabbers[4].color.data())); +#else + glsafe(::glColor4fv(m_grabbers[4].color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(4, 5); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); @@ -275,7 +303,11 @@ void GLGizmoScale3D::on_render() } else if (m_hover_id >= 6) { // draw connection +#if ENABLE_COLOR_CLASSES glsafe(::glColor4fv(m_drag_color.data())); +#else + glsafe(::glColor4fv(m_drag_color.data())); +#endif // ENABLE_COLOR_CLASSES render_grabbers_connection(6, 7); render_grabbers_connection(7, 8); render_grabbers_connection(8, 9); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 51551281a4..16f3bd729e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -144,7 +144,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glTranslated(0.0, 0.0, z_shift)); glsafe(::glMultMatrixd(instance_matrix.data())); +#if ENABLE_COLOR_CLASSES + ColorRGBA render_color; +#else std::array render_color; +#endif // ENABLE_COLOR_CLASSES for (size_t i = 0; i < cache_size; ++i) { const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i]; const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false; @@ -226,10 +230,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) // Now render the drain holes: if (has_holes && ! picking) { +#if ENABLE_COLOR_CLASSES + render_color = { 0.7f, 0.7f, 0.7f, 0.7f }; +#else render_color[0] = 0.7f; render_color[1] = 0.7f; render_color[2] = 0.7f; render_color[3] = 0.7f; +#endif // ENABLE_COLOR_CLASSES const_cast(&m_cylinder)->set_color(-1, render_color); if (shader) shader->set_uniform("emission_factor", 0.5f); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index d2a7e0d73e..405d3bc1e4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -216,8 +216,13 @@ void InstancesHider::render_cut() const if (mv->is_model_part()) glsafe(::glColor3f(0.8f, 0.3f, 0.0f)); else { +#if ENABLE_COLOR_CLASSES + const ColorRGBA color = color_from_model_volume(*mv); + glsafe(::glColor4fv(color.data())); +#else const std::array& c = color_from_model_volume(*mv); glsafe(::glColor4f(c[0], c[1], c[2], c[3])); +#endif // ENABLE_COLOR_CLASSES } glsafe(::glPushAttrib(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST)); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index a01e2ed697..7722d6a46b 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -27,6 +27,9 @@ #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "3DScene.hpp" #include "GUI.hpp" #include "I18N.hpp" @@ -82,14 +85,25 @@ static const std::map font_icons_extra_large = { }; -const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f }; +#if ENABLE_COLOR_CLASSES +const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.33f, 0.33f, 0.33f, 1.0f }; const ImVec4 ImGuiWrapper::COL_GREY_LIGHT = { 0.4f, 0.4f, 0.4f, 1.0f }; -const ImVec4 ImGuiWrapper::COL_ORANGE_DARK = { 0.757f, 0.404f, 0.216f, 1.0f }; -const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT = { 1.0f, 0.49f, 0.216f, 1.0f }; -const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.133f, 0.133f, 0.133f, 0.8f }; +const ImVec4 ImGuiWrapper::COL_ORANGE_DARK = { 0.67f, 0.36f, 0.19f, 1.0f }; +const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT = to_ImVec4(ColorRGBA::ORANGE()); +const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.13f, 0.13f, 0.13f, 0.8f }; const ImVec4 ImGuiWrapper::COL_BUTTON_BACKGROUND = COL_ORANGE_DARK; const ImVec4 ImGuiWrapper::COL_BUTTON_HOVERED = COL_ORANGE_LIGHT; -const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = ImGuiWrapper::COL_BUTTON_HOVERED; +const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = COL_BUTTON_HOVERED; +#else +const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f }; +const ImVec4 ImGuiWrapper::COL_GREY_LIGHT = { 0.4f, 0.4f, 0.4f, 1.0f }; +const ImVec4 ImGuiWrapper::COL_ORANGE_DARK = { 0.757f, 0.404f, 0.216f, 1.0f }; +const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT = { 1.0f, 0.49f, 0.216f, 1.0f }; +const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.133f, 0.133f, 0.133f, 0.8f }; +const ImVec4 ImGuiWrapper::COL_BUTTON_BACKGROUND = COL_ORANGE_DARK; +const ImVec4 ImGuiWrapper::COL_BUTTON_HOVERED = COL_ORANGE_LIGHT; +const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = ImGuiWrapper::COL_BUTTON_HOVERED; +#endif // ENABLE_COLOR_CLASSES ImGuiWrapper::ImGuiWrapper() { @@ -1035,6 +1049,28 @@ bool ImGuiWrapper::want_any_input() const return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput; } +#if ENABLE_COLOR_CLASSES +ImU32 ImGuiWrapper::to_ImU32(const ColorRGBA& color) +{ + return ImGui::GetColorU32({ color.r(), color.g(), color.b(), color.a() }); +} + +ImVec4 ImGuiWrapper::to_ImVec4(const ColorRGBA& color) +{ + return { color.r(), color.g(), color.b(), color.a() }; +} + +ColorRGBA ImGuiWrapper::from_ImU32(const ImU32& color) +{ + return from_ImVec4(ImGui::ColorConvertU32ToFloat4(color)); +} + +ColorRGBA ImGuiWrapper::from_ImVec4(const ImVec4& color) +{ + return { color.x, color.y, color.z, color.w }; +} +#endif // ENABLE_COLOR_CLASSES + #ifdef __APPLE__ static const ImWchar ranges_keyboard_shortcuts[] = { diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 255c4171bf..a9b3c4c496 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -10,9 +10,14 @@ #include "libslic3r/Point.hpp" -namespace Slic3r {namespace Search { +namespace Slic3r { +#if ENABLE_COLOR_CLASSES +class ColorRGBA; +#endif // ENABLE_COLOR_CLASSES +namespace Search { struct OptionViewParameters; -}} +} // namespace Search +} // namespace Slic3r class wxString; class wxMouseEvent; @@ -134,6 +139,13 @@ public: void reset_requires_extra_frame() { m_requires_extra_frame = false; } #endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT +#if ENABLE_COLOR_CLASSES + static ImU32 to_ImU32(const ColorRGBA& color); + static ImVec4 to_ImVec4(const ColorRGBA& color); + static ColorRGBA from_ImU32(const ImU32& color); + static ColorRGBA from_ImVec4(const ImVec4& color); +#endif // ENABLE_COLOR_CLASSES + static const ImVec4 COL_GREY_DARK; static const ImVec4 COL_GREY_LIGHT; static const ImVec4 COL_ORANGE_DARK; diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index a70a9b1728..9ec6114e9b 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -14,6 +14,9 @@ #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GUI.hpp" #include "I18N.hpp" #include "ConfigWizard.hpp" @@ -137,8 +140,13 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); #endif wxColour bgr_clr = parent->GetBackgroundColour(); //wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); +#if ENABLE_COLOR_CLASSES + auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); + auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); +#else auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); +#endif // ENABLE_COLOR_CLASSES const int font_size = font.GetPointSize(); int size[] = { font_size, font_size, font_size, font_size, font_size, font_size, font_size }; html->SetFonts(font.GetFaceName(), monospace.GetFaceName(), size); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 2b53883be0..bbf7a66cc6 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -24,6 +24,9 @@ #include "libslic3r/libslic3r.h" #include "libslic3r/PrintConfig.hpp" #include "libslic3r/PresetBundle.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "GUI.hpp" #include "GUI_App.hpp" @@ -441,15 +444,26 @@ wxBitmap* PresetComboBox::get_bmp( std::string bitmap_key, bool wide_icons, con // Paint a red flag for incompatible presets. bmps.emplace_back(is_compatible ? bitmap_cache().mkclear(norm_icon_width, icon_height) : m_bitmapIncompatible.bmp()); - if (m_type == Preset::TYPE_FILAMENT && !filament_rgb.empty()) - { + if (m_type == Preset::TYPE_FILAMENT && !filament_rgb.empty()) { +#if ENABLE_COLOR_CLASSES + // Paint the color bars. + ColorRGB color; + decode_color(filament_rgb, color); + bmps.emplace_back(bitmap_cache().mksolid(is_single_bar ? wide_icon_width : norm_icon_width, icon_height, color, false, 1, dark_mode)); +#else unsigned char rgb[3]; // Paint the color bars. bitmap_cache().parse_color(filament_rgb, rgb); bmps.emplace_back(bitmap_cache().mksolid(is_single_bar ? wide_icon_width : norm_icon_width, icon_height, rgb, false, 1, dark_mode)); +#endif // ENABLE_COLOR_CLASSES if (!is_single_bar) { +#if ENABLE_COLOR_CLASSES + decode_color(extruder_rgb, color); + bmps.emplace_back(bitmap_cache().mksolid(thin_icon_width, icon_height, color, false, 1, dark_mode)); +#else bitmap_cache().parse_color(extruder_rgb, rgb); bmps.emplace_back(bitmap_cache().mksolid(thin_icon_width, icon_height, rgb, false, 1, dark_mode)); +#endif // ENABLE_COLOR_CLASSES } // Paint a lock at the system presets. bmps.emplace_back(bitmap_cache().mkclear(space_icon_width, icon_height)); @@ -767,11 +781,16 @@ void PlaterPresetComboBox::update() const Preset* selected_filament_preset = nullptr; std::string extruder_color; - if (m_type == Preset::TYPE_FILAMENT) - { + if (m_type == Preset::TYPE_FILAMENT) { +#if !ENABLE_COLOR_CLASSES unsigned char rgb[3]; +#endif // !ENABLE_COLOR_CLASSES extruder_color = m_preset_bundle->printers.get_edited_preset().config.opt_string("extruder_colour", (unsigned int)m_extruder_idx); +#if ENABLE_COLOR_CLASSES + if (!can_decode_color(extruder_color)) +#else if (!bitmap_cache().parse_color(extruder_color, rgb)) +#endif // ENABLE_COLOR_CLASSES // Extruder color is not defined. extruder_color.clear(); selected_filament_preset = m_collection->find_preset(m_preset_bundle->filament_presets[m_extruder_idx]); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 406617d5ab..3133ad9fc2 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -24,7 +24,13 @@ #include #include +#if ENABLE_COLOR_CLASSES +static const Slic3r::ColorRGBA UNIFORM_SCALE_COLOR = Slic3r::ColorRGBA::ORANGE(); +static const Slic3r::ColorRGBA SOLID_PLANE_COLOR = Slic3r::ColorRGBA::ORANGE(); +static const Slic3r::ColorRGBA TRANSPARENT_PLANE_COLOR = { 0.8f, 0.8f, 0.8f, 0.5f }; +#else static const std::array UNIFORM_SCALE_COLOR = { 0.923f, 0.504f, 0.264f, 1.0f }; +#endif // ENABLE_COLOR_CLASSES namespace Slic3r { namespace GUI { @@ -453,11 +459,15 @@ void Selection::clear() for (unsigned int i : m_list) { GLVolume& volume = *(*m_volumes)[i]; volume.selected = false; - bool transparent = volume.color[3] < 1.0f; - if (transparent) +#if ENABLE_COLOR_CLASSES + bool is_transparent = volume.color.is_transparent(); +#else + bool is_transparent = volume.color[3] < 1.0f; +#endif // ENABLE_COLOR_CLASSES + if (is_transparent) volume.force_transparent = true; volume.set_render_color(); - if (transparent) + if (is_transparent) volume.force_transparent = false; } #else @@ -1919,10 +1929,17 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons glsafe(::glEnd()); } +#if ENABLE_COLOR_CLASSES +static ColorRGBA get_color(Axis axis) +{ + return AXES_COLOR[axis]; +}; +#else static std::array get_color(Axis axis) { return { AXES_COLOR[axis][0], AXES_COLOR[axis][1], AXES_COLOR[axis][2], AXES_COLOR[axis][3] }; }; +#endif // ENABLE_COLOR_CLASSES void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const { @@ -2052,10 +2069,15 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); ::glBegin(GL_QUADS); +#if ENABLE_COLOR_CLASSES + ::glColor4fv((camera_on_top && type == 1) || (!camera_on_top && type == 2) ? + SOLID_PLANE_COLOR.data() : TRANSPARENT_PLANE_COLOR.data()); +#else if ((camera_on_top && type == 1) || (!camera_on_top && type == 2)) ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); +#endif // ENABLE_COLOR_CLASSES ::glVertex3f(min_x, min_y, z1); ::glVertex3f(max_x, min_y, z1); ::glVertex3f(max_x, max_y, z1); @@ -2063,10 +2085,15 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glEnd()); ::glBegin(GL_QUADS); +#if ENABLE_COLOR_CLASSES + ::glColor4fv((camera_on_top && type == 2) || (!camera_on_top && type == 1) ? + SOLID_PLANE_COLOR.data() : TRANSPARENT_PLANE_COLOR.data()); +#else if ((camera_on_top && type == 2) || (!camera_on_top && type == 1)) ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); +#endif // ENABLE_COLOR_CLASSES ::glVertex3f(min_x, min_y, z2); ::glVertex3f(max_x, min_y, z2); ::glVertex3f(max_x, max_y, z2); diff --git a/src/slic3r/GUI/SendSystemInfoDialog.cpp b/src/slic3r/GUI/SendSystemInfoDialog.cpp index 0bfb343b84..0c61888f4b 100644 --- a/src/slic3r/GUI/SendSystemInfoDialog.cpp +++ b/src/slic3r/GUI/SendSystemInfoDialog.cpp @@ -4,6 +4,9 @@ #include "libslic3r/BlacklistedLibraryCheck.hpp" #include "libslic3r/Platform.hpp" #include "libslic3r/Utils.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "slic3r/GUI/format.hpp" #include "slic3r/Utils/Http.hpp" @@ -571,9 +574,13 @@ SendSystemInfoDialog::SendSystemInfoDialog(wxWindow* parent) wxColour bgr_clr = wxGetApp().get_window_default_clr(); SetBackgroundColour(bgr_clr); const auto text_clr = wxGetApp().get_label_clr_default(); +#if ENABLE_COLOR_CLASSES + auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); + auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); +#else auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); - +#endif // ENABLE_COLOR_CLASSES auto *topSizer = new wxBoxSizer(wxVERTICAL); auto *vsizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index 1a8542438c..13d45759ec 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -15,6 +15,9 @@ #include "MainFrame.hpp" #include "wxExtensions.hpp" #include "../libslic3r/BlacklistedLibraryCheck.hpp" +#if ENABLE_COLOR_CLASSES +#include "../libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "format.hpp" #ifdef _WIN32 @@ -114,8 +117,13 @@ SysInfoDialog::SysInfoDialog() // main_info_text wxFont font = get_default_font(this); const auto text_clr = wxGetApp().get_label_clr_default();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); +#if ENABLE_COLOR_CLASSES + auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue())); + auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); +#else auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); +#endif // ENABLE_COLOR_CLASSES const int fs = font.GetPointSize() - 1; int size[] = { static_cast(fs*1.5), static_cast(fs*1.4), static_cast(fs*1.3), fs, fs, fs, fs }; diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 38440b16ab..b1cfb09e7f 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -11,6 +11,9 @@ #include "libslic3r/PrintConfig.hpp" #include "libslic3r/PresetBundle.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES #include "format.hpp" #include "GUI_App.hpp" #include "Plater.hpp" @@ -58,8 +61,12 @@ static std::string get_icon_name(Preset::Type type, PrinterTechnology pt) { static std::string def_text_color() { wxColour def_colour = wxGetApp().get_label_clr_default();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); +#if ENABLE_COLOR_CLASSES + return encode_color(ColorRGB(def_colour.Red(), def_colour.Green(), def_colour.Blue())); +#else auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), def_colour.Red(), def_colour.Green(), def_colour.Blue()); return clr_str.ToStdString(); +#endif // ENABLE_COLOR_CLASSES } static std::string grey = "#808080"; static std::string orange = "#ed6b21"; @@ -124,8 +131,13 @@ wxBitmap ModelNode::get_bitmap(const wxString& color) const int icon_height = lround(1.6 * em); BitmapCache bmp_cache; +#if ENABLE_COLOR_CLASSES + ColorRGB rgb; + decode_color(into_u8(color), rgb); +#else unsigned char rgb[3]; BitmapCache::parse_color(into_u8(color), rgb); +#endif // ENABLE_COLOR_CLASSES // there is no need to scale created solid bitmap #ifndef __linux__ return bmp_cache.mksolid(icon_width, icon_height, rgb, true); diff --git a/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp index 71b87322f0..e984738dbc 100644 --- a/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/src/slic3r/GUI/WipeTowerDialog.cpp @@ -7,6 +7,10 @@ #include "GUI_App.hpp" #include "MsgDialog.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES + #include int scale(const int val) { return val * Slic3r::GUI::wxGetApp().em_unit(); } @@ -226,9 +230,15 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con m_number_of_extruders = (int)(sqrt(matrix.size())+0.001); for (const std::string& color : extruder_colours) { +#if ENABLE_COLOR_CLASSES + Slic3r::ColorRGB rgb; + Slic3r::decode_color(color, rgb); + m_colours.push_back(wxColor(rgb.r_uchar(), rgb.g_uchar(), rgb.b_uchar())); +#else unsigned char rgb[3]; Slic3r::GUI::BitmapCache::parse_color(color, rgb); m_colours.push_back(wxColor(rgb[0], rgb[1], rgb[2])); +#endif // ENABLE_COLOR_CLASSES } // Create two switched panels with their own sizers diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 01a553a81a..9712a41b30 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -17,6 +17,10 @@ #include "../Utils/MacDarkMode.hpp" #include "BitmapComboBox.hpp" +#if ENABLE_COLOR_CLASSES +#include "libslic3r/Color.hpp" +#endif // ENABLE_COLOR_CLASSES + #ifndef __linux__ // msw_menuitem_bitmaps is used for MSW and OSX static std::map msw_menuitem_bitmaps; @@ -471,7 +475,9 @@ std::vector get_extruder_color_icons(bool thin_icon/* = false*/) if (colors.empty()) return bmps; +#if !ENABLE_COLOR_CLASSES unsigned char rgb[3]; +#endif // !ENABLE_COLOR_CLASSES /* It's supposed that standard size of an icon is 36px*16px for 100% scaled display. * So set sizes for solid_colored icons used for filament preset @@ -489,10 +495,18 @@ std::vector get_extruder_color_icons(bool thin_icon/* = false*/) wxBitmap* bitmap = bmp_cache.find(bitmap_key); if (bitmap == nullptr) { +#if ENABLE_COLOR_CLASSES + // Paint the color icon. + Slic3r::ColorRGB rgb; + Slic3r::decode_color(color, rgb); + // there is no neede to scale created solid bitmap + bitmap = bmp_cache.insert(bitmap_key, bmp_cache.mksolid(icon_width, icon_height, rgb, true, 1, dark_mode)); +#else // Paint the color icon. Slic3r::GUI::BitmapCache::parse_color(color, rgb); // there is no neede to scale created solid bitmap bitmap = bmp_cache.insert(bitmap_key, bmp_cache.mksolid(icon_width, icon_height, rgb, true, 1, dark_mode)); +#endif // ENABLE_COLOR_CLASSES } bmps.emplace_back(bitmap); } diff --git a/tests/libslic3r/CMakeLists.txt b/tests/libslic3r/CMakeLists.txt index 6475570c10..69470aad1c 100644 --- a/tests/libslic3r/CMakeLists.txt +++ b/tests/libslic3r/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(${_TEST_NAME}_tests test_aabbindirect.cpp test_clipper_offset.cpp test_clipper_utils.cpp + test_color.cpp test_config.cpp test_elephant_foot_compensation.cpp test_geometry.cpp diff --git a/tests/libslic3r/test_color.cpp b/tests/libslic3r/test_color.cpp new file mode 100644 index 0000000000..f139917e0a --- /dev/null +++ b/tests/libslic3r/test_color.cpp @@ -0,0 +1,41 @@ +#include +#include "libslic3r/libslic3r.h" + +#if ENABLE_COLOR_CLASSES + +#include "libslic3r/Color.hpp" + +using namespace Slic3r; + +SCENARIO("Color encoding/decoding cycle", "[Color]") { + GIVEN("Color") { + const ColorRGB src_rgb(unsigned char(255), unsigned char(127), unsigned char(63)); + WHEN("apply encode/decode cycle") { + const std::string encoded = encode_color(src_rgb); + ColorRGB res_rgb; + decode_color(encoded, res_rgb); + const bool ret = res_rgb.r_uchar() == src_rgb.r_uchar() && res_rgb.g_uchar() == src_rgb.g_uchar() && res_rgb.b_uchar() == src_rgb.b_uchar(); + THEN("result matches source") { + REQUIRE(ret); + } + } + } +} + +SCENARIO("Color picking encoding/decoding cycle", "[Color]") { + GIVEN("Picking color") { + const ColorRGB src_rgb(unsigned char(255), unsigned char(127), unsigned char(63)); + WHEN("apply encode/decode cycle") { + const unsigned int encoded = picking_encode(src_rgb.r_uchar(), src_rgb.g_uchar(), src_rgb.b_uchar()); + const ColorRGBA res_rgba = picking_decode(encoded); + const bool ret = res_rgba.r_uchar() == src_rgb.r_uchar() && res_rgba.g_uchar() == src_rgb.g_uchar() && res_rgba.b_uchar() == src_rgb.b_uchar(); + THEN("result matches source") { + REQUIRE(ret); + } + } + } +} + +#endif // ENABLE_COLOR_CLASSES + + From e77f89cf5de7cd15637985c7a64e1732eeb4fd63 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Dec 2021 11:07:10 +0100 Subject: [PATCH 38/66] Fixed build on non-Windows OSs --- src/libslic3r/Color.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Color.hpp b/src/libslic3r/Color.hpp index 7ad10fec57..6f39a26fc1 100644 --- a/src/libslic3r/Color.hpp +++ b/src/libslic3r/Color.hpp @@ -43,9 +43,9 @@ public: m_data[comp] = std::clamp(value, 0.0f, 1.0f); } - unsigned char r_uchar() const { return unsigned char(m_data[0] * 255.0f); } - unsigned char g_uchar() const { return unsigned char(m_data[1] * 255.0f); } - unsigned char b_uchar() const { return unsigned char(m_data[2] * 255.0f); } + unsigned char r_uchar() const { return static_cast(m_data[0] * 255.0f); } + unsigned char g_uchar() const { return static_cast(m_data[1] * 255.0f); } + unsigned char b_uchar() const { return static_cast(m_data[2] * 255.0f); } static const ColorRGB BLACK() { return { 0.0f, 0.0f, 0.0f }; } static const ColorRGB BLUE() { return { 0.0f, 0.0f, 1.0f }; } @@ -104,10 +104,10 @@ public: m_data[comp] = std::clamp(value, 0.0f, 1.0f); } - unsigned char r_uchar() const { return unsigned char(m_data[0] * 255.0f); } - unsigned char g_uchar() const { return unsigned char(m_data[1] * 255.0f); } - unsigned char b_uchar() const { return unsigned char(m_data[2] * 255.0f); } - unsigned char a_uchar() const { return unsigned char(m_data[3] * 255.0f); } + unsigned char r_uchar() const { return static_cast(m_data[0] * 255.0f); } + unsigned char g_uchar() const { return static_cast(m_data[1] * 255.0f); } + unsigned char b_uchar() const { return static_cast(m_data[2] * 255.0f); } + unsigned char a_uchar() const { return static_cast(m_data[3] * 255.0f); } bool is_transparent() const { return m_data[3] < 1.0f; } From c44fd433073064567eb7bbb56650b0f35fe2b883 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Dec 2021 11:12:46 +0100 Subject: [PATCH 39/66] Fixed warning --- src/slic3r/GUI/Plater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 89d74f7bb5..70ce5c2ffb 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5724,7 +5724,7 @@ void Plater::export_stl(bool extended, bool selection_only) mesh.merge(m); } } - else if (0 <= instance_id && instance_id < mo.instances.size()) + else if (0 <= instance_id && instance_id < int(mo.instances.size())) mesh.transform(mo.instances[instance_id]->get_matrix(), true); return mesh; From ab99a7865f92d33485a4eebc6487634e28dbaf31 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Dec 2021 11:31:35 +0100 Subject: [PATCH 40/66] Fixed build of test_color.cpp on non-Windows OSs --- src/slic3r/GUI/GLCanvas3D.cpp | 2 ++ tests/libslic3r/test_color.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 94edc797dc..df5efeb485 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5377,7 +5377,9 @@ void GLCanvas3D::_render_overlays() void GLCanvas3D::_render_volumes_for_picking() const { +#if !ENABLE_COLOR_CLASSES static const GLfloat INV_255 = 1.0f / 255.0f; +#endif // !ENABLE_COLOR_CLASSES // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); diff --git a/tests/libslic3r/test_color.cpp b/tests/libslic3r/test_color.cpp index f139917e0a..dcfb8526d6 100644 --- a/tests/libslic3r/test_color.cpp +++ b/tests/libslic3r/test_color.cpp @@ -9,7 +9,7 @@ using namespace Slic3r; SCENARIO("Color encoding/decoding cycle", "[Color]") { GIVEN("Color") { - const ColorRGB src_rgb(unsigned char(255), unsigned char(127), unsigned char(63)); + const ColorRGB src_rgb(static_cast(255), static_cast(127), static_cast(63)); WHEN("apply encode/decode cycle") { const std::string encoded = encode_color(src_rgb); ColorRGB res_rgb; @@ -24,7 +24,7 @@ SCENARIO("Color encoding/decoding cycle", "[Color]") { SCENARIO("Color picking encoding/decoding cycle", "[Color]") { GIVEN("Picking color") { - const ColorRGB src_rgb(unsigned char(255), unsigned char(127), unsigned char(63)); + const ColorRGB src_rgb(static_cast(255), static_cast(127), static_cast(63)); WHEN("apply encode/decode cycle") { const unsigned int encoded = picking_encode(src_rgb.r_uchar(), src_rgb.g_uchar(), src_rgb.b_uchar()); const ColorRGBA res_rgba = picking_decode(encoded); From 9596b2d8b434dcdcd6986658bb33183dcd483d7a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Dec 2021 11:45:26 +0100 Subject: [PATCH 41/66] Fixed warning --- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 5c151e0ad3..a65952fbfb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -556,7 +556,6 @@ RENDER_AGAIN: } m_imgui->disabled_begin(! m_enable_hollowing); - float max_tooltip_width = ImGui::GetFontSize() * 20.0f; ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("offset")); ImGui::SameLine(settings_sliders_left, m_imgui->get_item_spacing().x); From f2aeca3a716d8d3d4233be321cddcf463c1bf21f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 22 Dec 2021 14:38:23 +0100 Subject: [PATCH 42/66] Options from the "Preferences" dialog added to the Search Some code refactoring: * use GUI_App::open_preferences() on all places where it's needed * Preferences Dialog is an attribute of a ManeFrame class and created just ones during the MainFrame creation now. * Created class Highlighter. Use it in Preferences and Tab --- resources/data/hints.ini | 6 +- src/libslic3r/Preset.hpp | 2 + src/slic3r/GUI/GLCanvas3D.cpp | 5 +- src/slic3r/GUI/GUI_App.cpp | 82 ++-- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/HintNotification.cpp | 6 +- src/slic3r/GUI/MainFrame.cpp | 3 + src/slic3r/GUI/MainFrame.hpp | 2 + src/slic3r/GUI/OptionsGroup.hpp | 8 + src/slic3r/GUI/Plater.cpp | 8 +- src/slic3r/GUI/Preferences.cpp | 627 +++++++++++++--------------- src/slic3r/GUI/Preferences.hpp | 28 +- src/slic3r/GUI/Search.cpp | 49 ++- src/slic3r/GUI/Search.hpp | 6 +- src/slic3r/GUI/Tab.cpp | 49 --- src/slic3r/GUI/Tab.hpp | 15 +- src/slic3r/GUI/wxExtensions.cpp | 74 ++++ src/slic3r/GUI/wxExtensions.hpp | 28 ++ 18 files changed, 520 insertions(+), 480 deletions(-) diff --git a/resources/data/hints.ini b/resources/data/hints.ini index b90976c1a7..ccb248bc37 100644 --- a/resources/data/hints.ini +++ b/resources/data/hints.ini @@ -34,7 +34,7 @@ # # Open preferences (might add item to highlight) # hypertext_type = preferences -# hypertext_preferences_page = 2 (values 0-2 according to prefernces tab to be opened) +# hypertext_preferences_page = name of the prefernces tab # hypertext_preferences_item = show_collapse_button (name of variable saved in prusaslicer.ini connected to the setting in preferences) # # Open gallery (no aditional var) @@ -97,7 +97,7 @@ documentation_link = https://help.prusa3d.com/en/article/reload-from-disk_120427 [hint:Hiding sidebar] text = Hiding sidebar\nDid you know that you can hide the right sidebar using the shortcut Shift+Tab? You can also enable the icon for this from thePreferences. hypertext_type = preferences -hypertext_preferences_page = 2 +hypertext_preferences_page = GUI hypertext_preferences_item = show_collapse_button [hint:Perspective camera] @@ -214,7 +214,7 @@ disabled_tags = SLA [hint:Settings in non-modal window] text = Settings in non-modal window\nDid you know that you can open the Settings in a new non-modal window? This means you can have settings open on one screen and the G-code Preview on the other. Go to thePreferencesand select Settings in non-modal window. hypertext_type = preferences -hypertext_preferences_page = 2 +hypertext_preferences_page = GUI hypertext_preferences_item = dlg_settings_layout_mode [hint:Adaptive infills] diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 6764b197d1..dd6a2e03cc 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -116,6 +116,8 @@ public: // This type is here to support PresetConfigSubstitutions for physical printers, however it does not belong to the Preset class, // PhysicalPrinter class is used instead. TYPE_PHYSICAL_PRINTER, + // This type is here to support search through the Preferences + TYPE_PREFERENCES, }; Type type = TYPE_INVALID; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a3b54a8417..b6739da3d7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4010,8 +4010,11 @@ bool GLCanvas3D::_render_search_list(float pos_x) action_taken = true; else sidebar.jump_to_option(selected);*/ - if (selected != 9999) + if (selected != 9999) { + imgui->end(); // end imgui before the jump to option sidebar.jump_to_option(selected); + return true; + } action_taken = true; } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index cf14fc7351..afd9ab0c3d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1735,6 +1735,7 @@ void GUI_App::update_ui_from_settings() m_force_colors_update = false; mainframe->force_color_changed(); mainframe->diff_dialog.force_color_changed(); + mainframe->preferences_dialog->force_color_changed(); mainframe->printhost_queue_dlg()->force_color_changed(); #ifdef _MSW_DARK_MODE update_scrolls(mainframe); @@ -2255,40 +2256,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) break; case ConfigMenuPreferences: { - bool app_layout_changed = false; - { - // the dialog needs to be destroyed before the call to recreate_GUI() - // or sometimes the application crashes into wxDialogBase() destructor - // so we put it into an inner scope - PreferencesDialog dlg(mainframe); - dlg.ShowModal(); - app_layout_changed = dlg.settings_layout_changed(); - if (dlg.seq_top_layer_only_changed()) - this->plater_->refresh_print(); - - if (dlg.recreate_GUI()) { - recreate_GUI(_L("Restart application") + dots); - return; - } -#ifdef _WIN32 - if (is_editor()) { - if (app_config->get("associate_3mf") == "1") - associate_3mf_files(); - if (app_config->get("associate_stl") == "1") - associate_stl_files(); - } - else { - if (app_config->get("associate_gcode") == "1") - associate_gcode_files(); - } -#endif // _WIN32 - } - if (app_layout_changed) { - // hide full main_sizer for mainFrame - mainframe->GetSizer()->Show(false); - mainframe->update_layout(); - mainframe->select_tab(size_t(0)); - } + open_preferences(); break; } case ConfigMenuLanguage: @@ -2336,36 +2304,34 @@ void GUI_App::add_config_menu(wxMenuBar *menu) menu->Append(local_menu, _L("&Configuration")); } -void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_option) +void GUI_App::open_preferences(const std::string& highlight_option /*= std::string()*/, const std::string& tab_name/*= std::string()*/) { - bool app_layout_changed = false; - { - // the dialog needs to be destroyed before the call to recreate_GUI() - // or sometimes the application crashes into wxDialogBase() destructor - // so we put it into an inner scope - PreferencesDialog dlg(mainframe, open_on_tab, highlight_option); - dlg.ShowModal(); - app_layout_changed = dlg.settings_layout_changed(); + mainframe->preferences_dialog->show(highlight_option, tab_name); + + if (mainframe->preferences_dialog->recreate_GUI()) + recreate_GUI(_L("Restart application") + dots); + #if ENABLE_GCODE_LINES_ID_IN_H_SLIDER - if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed()) + if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed()) #else - if (dlg.seq_top_layer_only_changed()) + if (mainframe->preferences_dialog->seq_top_layer_only_changed()) #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER - this->plater_->refresh_print(); + this->plater_->refresh_print(); + #ifdef _WIN32 - if (is_editor()) { - if (app_config->get("associate_3mf") == "1") - associate_3mf_files(); - if (app_config->get("associate_stl") == "1") - associate_stl_files(); - } - else { - if (app_config->get("associate_gcode") == "1") - associate_gcode_files(); - } -#endif // _WIN32 + if (is_editor()) { + if (app_config->get("associate_3mf") == "1") + associate_3mf_files(); + if (app_config->get("associate_stl") == "1") + associate_stl_files(); } - if (app_layout_changed) { + else { + if (app_config->get("associate_gcode") == "1") + associate_gcode_files(); + } +#endif // _WIN32 + + if (mainframe->preferences_dialog->settings_layout_changed()) { // hide full main_sizer for mainFrame mainframe->GetSizer()->Show(false); mainframe->update_layout(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 9c65bc024f..eddaf4a97c 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -264,7 +264,7 @@ public: wxString current_language_code_safe() const; bool is_localized() const { return m_wxLocale->GetLocale() != "English"; } - void open_preferences(size_t open_on_tab = 0, const std::string& highlight_option = std::string()); + void open_preferences(const std::string& highlight_option = std::string(), const std::string& tab_name = std::string()); virtual bool OnExceptionInMainLoop() override; // Calls wxLaunchDefaultBrowser if user confirms in dialog. diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index fc61ab62d8..55bcc90a9e 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -417,9 +417,9 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) m_loaded_hints.emplace_back(hint_data); // open preferences } else if(dict["hypertext_type"] == "preferences") { - int page = static_cast(std::atoi(dict["hypertext_preferences_page"].c_str())); + std::string page = dict["hypertext_preferences_page"]; std::string item = dict["hypertext_preferences_item"]; - HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, [page, item]() { wxGetApp().open_preferences(page, item); } }; + HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, [page, item]() { wxGetApp().open_preferences(item, page); } }; m_loaded_hints.emplace_back(hint_data); } else if (dict["hypertext_type"] == "plater") { std::string item = dict["hypertext_plater_item"]; @@ -924,7 +924,7 @@ void NotificationManager::HintNotification::render_preferences_button(ImGuiWrapp } if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) { - wxGetApp().open_preferences(2, "show_hints"); + wxGetApp().open_preferences("show_hints", "GUI"); } ImGui::PopStyleColor(5); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1e589e4324..a88509527b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -47,6 +47,7 @@ #include "GUI_ObjectList.hpp" #include "GalleryDialog.hpp" #include "NotificationManager.hpp" +#include "Preferences.hpp" #ifdef _WIN32 #include @@ -272,6 +273,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S if (m_plater != nullptr) { m_plater->get_collapse_toolbar().set_enabled(wxGetApp().app_config->get("show_collapse_button") == "1"); m_plater->show_action_buttons(true); + + preferences_dialog = new PreferencesDialog(this); } } diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 951ed70a1d..f385ee8f85 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -32,6 +32,7 @@ class Tab; class PrintHostQueueDialog; class Plater; class MainFrame; +class PreferencesDialog; enum QuickSlice { @@ -203,6 +204,7 @@ public: DiffPresetDialog diff_dialog; wxWindow* m_plater_page{ nullptr }; // wxProgressDialog* m_progress_dialog { nullptr }; + PreferencesDialog* preferences_dialog { nullptr }; PrintHostQueueDialog* m_printhost_queue_dlg; // std::shared_ptr m_statusbar; diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 67c3fbdbde..29d8baaa63 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -74,6 +74,12 @@ public: label(_(label)), label_tooltip(_(tooltip)) {} Line() : m_is_separator(true) {} + Line(const std::string& opt_key, const wxString& label, const wxString& tooltip) : + label(_(label)), label_tooltip(_(tooltip)) + { + m_options.push_back(Option({ opt_key, coNone }, opt_key)); + } + bool is_separator() const { return m_is_separator; } const std::vector& get_extra_widgets() const {return m_extra_widgets;} @@ -180,6 +186,8 @@ public: // if we have to set the same control alignment for different option groups, // we have to set same max contrtol width to all of them void set_max_win_width(int max_win_width); + void set_use_custom_ctrl(bool use_custom_ctrl) { m_use_custom_ctrl = use_custom_ctrl; } + const std::map& get_optioms_map() { return m_options; } bool is_activated() { return sizer != nullptr; } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 89d74f7bb5..461eb02e27 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1185,10 +1185,10 @@ void Sidebar::jump_to_option(const std::string& opt_key, Preset::Type type, cons void Sidebar::jump_to_option(size_t selected) { const Search::Option& opt = p->searcher.get_option(selected); - wxGetApp().get_tab(opt.type)->activate_option(opt.opt_key(), boost::nowide::narrow(opt.category)); - - // Switch to the Settings NotePad -// wxGetApp().mainframe->select_tab(); + if (opt.type == Preset::TYPE_PREFERENCES) + wxGetApp().open_preferences(opt.opt_key(), boost::nowide::narrow(opt.group)); + else + wxGetApp().get_tab(opt.type)->activate_option(opt.opt_key(), boost::nowide::narrow(opt.category)); } ObjectManipulation* Sidebar::obj_manipul() diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index ff89d90ad8..9e4753e12e 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -42,22 +42,40 @@ namespace Slic3r { namespace GUI { -PreferencesDialog::PreferencesDialog(wxWindow* parent, int selected_tab, const std::string& highlight_opt_key) : +PreferencesDialog::PreferencesDialog(wxWindow* parent) : DPIDialog(parent, wxID_ANY, _L("Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) { #ifdef __WXOSX__ isOSX = true; #endif - build(selected_tab); + build(); + + m_highlighter.set_timer_owner(this, 0); + this->Bind(wxEVT_TIMER, [this](wxTimerEvent&) { + m_highlighter.blink(); + }); +} + +void PreferencesDialog::show(const std::string& highlight_opt_key /*= std::string()*/, const std::string& tab_name/*= std::string()*/) +{ + int selected_tab = 0; + for (selected_tab; selected_tab < tabs->GetPageCount(); selected_tab++) + if (tabs->GetPageText(selected_tab) == _(tab_name)) + break; + if (selected_tab < tabs->GetPageCount()) + tabs->SetSelection(selected_tab); + if (!highlight_opt_key.empty()) init_highlighter(highlight_opt_key); + + this->ShowModal(); } static std::shared_ptrcreate_options_tab(const wxString& title, wxBookCtrlBase* tabs) { wxPanel* tab = new wxPanel(tabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); - tabs->AddPage(tab, title); + tabs->AddPage(tab, _(title)); tab->SetFont(wxGetApp().normal_font()); wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); @@ -66,6 +84,7 @@ static std::shared_ptrcreate_options_tab(const wxString& tit std::shared_ptr optgroup = std::make_shared(tab); optgroup->label_width = 40; + optgroup->set_config_category_and_type(title, int(Preset::TYPE_PREFERENCES)); return optgroup; } @@ -75,9 +94,67 @@ static void activate_options_tab(std::shared_ptr optgroup) optgroup->update_visibility(comSimple); wxBoxSizer* sizer = static_cast(static_cast(optgroup->parent())->GetSizer()); sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); + + // apply sercher + wxGetApp().sidebar().get_searcher().append_preferences_options(optgroup->get_lines()); } -void PreferencesDialog::build(size_t selected_tab) +static void append_bool_option( std::shared_ptr optgroup, + const std::string& opt_key, + const std::string& label, + const std::string& tooltip, + bool def_val, + ConfigOptionMode mode = comSimple) +{ + ConfigOptionDef def = {opt_key, coBool}; + def.label = label; + def.tooltip = tooltip; + def.mode = mode; + def.set_default_value(new ConfigOptionBool{ def_val }); + Option option(def, opt_key); + optgroup->append_single_option_line(option); + + // fill data to the Search Dialog + wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences")); +} + +static void append_enum_option( std::shared_ptr optgroup, + const std::string& opt_key, + const std::string& label, + const std::string& tooltip, + const ConfigOption* def_val, + const t_config_enum_values *enum_keys_map, + std::initializer_list enum_values, + std::initializer_list enum_labels, + ConfigOptionMode mode = comSimple) +{ + ConfigOptionDef def = {opt_key, coEnum }; + def.label = label; + def.tooltip = tooltip; + def.mode = mode; + def.enum_keys_map = enum_keys_map; + def.enum_values = std::vector(enum_values); + def.enum_labels = std::vector(enum_labels); + + def.set_default_value(def_val); + Option option(def, opt_key); + optgroup->append_single_option_line(option); + + // fill data to the Search Dialog + wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences")); +} + +static void append_preferences_option_to_searcer(std::shared_ptr optgroup, + const std::string& opt_key, + const wxString& label) +{ + // fill data to the Search Dialog + wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences")); + // apply sercher + wxGetApp().sidebar().get_searcher().append_preferences_option(Line(opt_key, label, "")); +} + +void PreferencesDialog::build() { #ifdef _WIN32 wxGetApp().UpdateDarkUI(this); @@ -90,20 +167,14 @@ void PreferencesDialog::build(size_t selected_tab) auto app_config = get_app_config(); #ifdef _MSW_DARK_MODE - wxBookCtrlBase* tabs; -// if (wxGetApp().dark_mode()) - tabs = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNB_DEFAULT); -/* else { - tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNB_DEFAULT); - tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - }*/ + tabs = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME | wxNB_DEFAULT); #else - wxNotebook* tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL |wxNB_NOPAGETHEME | wxNB_DEFAULT ); + tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL |wxNB_NOPAGETHEME | wxNB_DEFAULT ); tabs->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif // Add "General" tab - m_optgroup_general = create_options_tab(_L("General"), tabs); + m_optgroup_general = create_options_tab(L("General"), tabs); m_optgroup_general->m_on_change = [this](t_config_option_key opt_key, boost::any value) { if (opt_key == "default_action_on_close_application" || opt_key == "default_action_on_select_preset" || opt_key == "default_action_on_new_project") m_values[opt_key] = boost::any_cast(value) ? "none" : "discard"; @@ -113,215 +184,167 @@ void PreferencesDialog::build(size_t selected_tab) bool is_editor = wxGetApp().is_editor(); - ConfigOptionDef def; - Option option(def, ""); if (is_editor) { - def.label = L("Remember output directory"); - def.type = coBool; - def.tooltip = L("If this is enabled, Slic3r will prompt the last output directory " - "instead of the one containing the input files."); - def.set_default_value(new ConfigOptionBool{ app_config->has("remember_output_path") ? app_config->get("remember_output_path") == "1" : true }); - option = Option(def, "remember_output_path"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "remember_output_path", + L("Remember output directory"), + L("If this is enabled, Slic3r will prompt the last output directory instead of the one containing the input files."), + app_config->has("remember_output_path") ? app_config->get("remember_output_path") == "1" : true); - def.label = L("Auto-center parts"); - def.type = coBool; - def.tooltip = L("If this is enabled, Slic3r will auto-center objects " - "around the print bed center."); - def.set_default_value(new ConfigOptionBool{ app_config->get("autocenter") == "1" }); - option = Option(def, "autocenter"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "autocenter", + L("Auto-center parts"), + L("If this is enabled, Slic3r will auto-center objects around the print bed center."), + app_config->get("autocenter") == "1"); - def.label = L("Background processing"); - def.type = coBool; - def.tooltip = L("If this is enabled, Slic3r will pre-process objects as soon " - "as they\'re loaded in order to save time when exporting G-code."); - def.set_default_value(new ConfigOptionBool{ app_config->get("background_processing") == "1" }); - option = Option(def, "background_processing"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "background_processing", + L("Background processing"), + L("If this is enabled, Slic3r will pre-process objects as soon " + "as they\'re loaded in order to save time when exporting G-code."), + app_config->get("background_processing") == "1"); m_optgroup_general->append_separator(); // Please keep in sync with ConfigWizard - def.label = L("Export sources full pathnames to 3mf and amf"); - def.type = coBool; - def.tooltip = L("If enabled, allows the Reload from disk command to automatically find and load the files when invoked."); - def.set_default_value(new ConfigOptionBool(app_config->get("export_sources_full_pathnames") == "1")); - option = Option(def, "export_sources_full_pathnames"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "export_sources_full_pathnames", + L("Export sources full pathnames to 3mf and amf"), + L("If enabled, allows the Reload from disk command to automatically find and load the files when invoked."), + app_config->get("export_sources_full_pathnames") == "1"); #ifdef _WIN32 // Please keep in sync with ConfigWizard - def.label = L("Associate .3mf files to PrusaSlicer"); - def.type = coBool; - def.tooltip = L("If enabled, sets PrusaSlicer as default application to open .3mf files."); - def.set_default_value(new ConfigOptionBool(app_config->get("associate_3mf") == "1")); - option = Option(def, "associate_3mf"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "associate_3mf", + L("Associate .3mf files to PrusaSlicer"), + L("If enabled, sets PrusaSlicer as default application to open .3mf files."), + app_config->get("associate_3mf") == "1"); - def.label = L("Associate .stl files to PrusaSlicer"); - def.type = coBool; - def.tooltip = L("If enabled, sets PrusaSlicer as default application to open .stl files."); - def.set_default_value(new ConfigOptionBool(app_config->get("associate_stl") == "1")); - option = Option(def, "associate_stl"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "associate_stl", + L("Associate .stl files to PrusaSlicer"), + L("If enabled, sets PrusaSlicer as default application to open .stl files."), + app_config->get("associate_stl") == "1"); #endif // _WIN32 m_optgroup_general->append_separator(); // Please keep in sync with ConfigWizard - def.label = L("Update built-in Presets automatically"); - def.type = coBool; - def.tooltip = L("If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded into a separate temporary location. When a new preset version becomes available it is offered at application startup."); - def.set_default_value(new ConfigOptionBool(app_config->get("preset_update") == "1")); - option = Option(def, "preset_update"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "preset_update", + L("Update built-in Presets automatically"), + L("If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded " + "into a separate temporary location. When a new preset version becomes available it is offered at application startup."), + app_config->get("preset_update") == "1"); - def.label = L("Suppress \" - default - \" presets"); - def.type = coBool; - def.tooltip = L("Suppress \" - default - \" presets in the Print / Filament / Printer " - "selections once there are any other valid presets available."); - def.set_default_value(new ConfigOptionBool{ app_config->get("no_defaults") == "1" }); - option = Option(def, "no_defaults"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "no_defaults", + L("Suppress \" - default - \" presets"), + L("Suppress \" - default - \" presets in the Print / Filament / Printer selections once there are any other valid presets available."), + app_config->get("no_defaults") == "1"); - def.label = L("Show incompatible print and filament presets"); - def.type = coBool; - def.tooltip = L("When checked, the print and filament presets are shown in the preset editor " - "even if they are marked as incompatible with the active printer"); - def.set_default_value(new ConfigOptionBool{ app_config->get("show_incompatible_presets") == "1" }); - option = Option(def, "show_incompatible_presets"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "show_incompatible_presets", + L("Show incompatible print and filament presets"), + L("When checked, the print and filament presets are shown in the preset editor " + "even if they are marked as incompatible with the active printer"), + app_config->get("show_incompatible_presets") == "1"); m_optgroup_general->append_separator(); - def.label = L("Show drop project dialog"); - def.type = coBool; - def.tooltip = L("When checked, whenever dragging and dropping a project file on the application, shows a dialog asking to select the action to take on the file to load."); - def.set_default_value(new ConfigOptionBool{ app_config->get("show_drop_project_dialog") == "1" }); - option = Option(def, "show_drop_project_dialog"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "show_drop_project_dialog", + L("Show drop project dialog"), + L("When checked, whenever dragging and dropping a project file on the application, shows a dialog asking to select the action to take on the file to load."), + app_config->get("show_drop_project_dialog") == "1"); + append_bool_option(m_optgroup_general, "single_instance", #if __APPLE__ - def.label = L("Allow just a single PrusaSlicer instance"); - def.type = coBool; - def.tooltip = L("On OSX there is always only one instance of app running by default. However it is allowed to run multiple instances of same app from the command line. In such case this settings will allow only one instance."); + L("Allow just a single PrusaSlicer instance"), + L("On OSX there is always only one instance of app running by default. However it is allowed to run multiple instances " + "of same app from the command line. In such case this settings will allow only one instance."), #else - def.label = L("Allow just a single PrusaSlicer instance"); - def.type = coBool; - def.tooltip = L("If this is enabled, when starting PrusaSlicer and another instance of the same PrusaSlicer is already running, that instance will be reactivated instead."); + L("Allow just a single PrusaSlicer instance"), + L("If this is enabled, when starting PrusaSlicer and another instance of the same PrusaSlicer is already running, that instance will be reactivated instead."), #endif - def.set_default_value(new ConfigOptionBool{ app_config->has("single_instance") ? app_config->get("single_instance") == "1" : false }); - option = Option(def, "single_instance"); - m_optgroup_general->append_single_option_line(option); + app_config->has("single_instance") ? app_config->get("single_instance") == "1" : false ); m_optgroup_general->append_separator(); - def.label = L("Ask to save unsaved changes when closing the application or when loading a new project"); - def.type = coBool; - def.tooltip = L("Always ask for unsaved changes, when: \n" + append_bool_option(m_optgroup_general, "default_action_on_close_application", + L("Ask to save unsaved changes when closing the application or when loading a new project"), + L("Always ask for unsaved changes, when: \n" "- Closing PrusaSlicer while some presets are modified,\n" - "- Loading a new project while some presets are modified"); - def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_close_application") == "none" }); - option = Option(def, "default_action_on_close_application"); - m_optgroup_general->append_single_option_line(option); + "- Loading a new project while some presets are modified"), + app_config->get("default_action_on_close_application") == "none"); - def.label = L("Ask for unsaved changes when selecting new preset"); - def.type = coBool; - def.tooltip = L("Always ask for unsaved changes when selecting new preset or resetting a preset"); - def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_select_preset") == "none" }); - option = Option(def, "default_action_on_select_preset"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "default_action_on_select_preset", + L("Ask for unsaved changes when selecting new preset"), + L("Always ask for unsaved changes when selecting new preset or resetting a preset"), + app_config->get("default_action_on_select_preset") == "none"); - def.label = L("Ask for unsaved changes when creating new project"); - def.type = coBool; - def.tooltip = L("Always ask for unsaved changes when creating new project"); - def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_new_project") == "none" }); - option = Option(def, "default_action_on_new_project"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "default_action_on_new_project", + L("Ask for unsaved changes when creating new project"), + L("Always ask for unsaved changes when creating new project"), + app_config->get("default_action_on_new_project") == "none"); } #ifdef _WIN32 else { - def.label = L("Associate .gcode files to PrusaSlicer G-code Viewer"); - def.type = coBool; - def.tooltip = L("If enabled, sets PrusaSlicer G-code Viewer as default application to open .gcode files."); - def.set_default_value(new ConfigOptionBool(app_config->get("associate_gcode") == "1")); - option = Option(def, "associate_gcode"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "associate_gcode", + L("Associate .gcode files to PrusaSlicer G-code Viewer"), + L("If enabled, sets PrusaSlicer G-code Viewer as default application to open .gcode files."), + app_config->get("associate_gcode") == "1"); } #endif // _WIN32 #if __APPLE__ - def.label = L("Use Retina resolution for the 3D scene"); - def.type = coBool; - def.tooltip = L("If enabled, the 3D scene will be rendered in Retina resolution. " - "If you are experiencing 3D performance problems, disabling this option may help."); - def.set_default_value(new ConfigOptionBool{ app_config->get("use_retina_opengl") == "1" }); - option = Option (def, "use_retina_opengl"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "use_retina_opengl", + L("Use Retina resolution for the 3D scene"), + L("If enabled, the 3D scene will be rendered in Retina resolution. " + "If you are experiencing 3D performance problems, disabling this option may help."), + app_config->get("use_retina_opengl") == "1"); #endif m_optgroup_general->append_separator(); // Show/Hide splash screen - def.label = L("Show splash screen"); - def.type = coBool; - def.tooltip = L("Show splash screen"); - def.set_default_value(new ConfigOptionBool{ app_config->get("show_splash_screen") == "1" }); - option = Option(def, "show_splash_screen"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "show_splash_screen", + L("Show splash screen"), + L("Show splash screen"), + app_config->get("show_splash_screen") == "1"); // Clear Undo / Redo stack on new project - def.label = L("Clear Undo / Redo stack on new project"); - def.type = coBool; - def.tooltip = L("Clear Undo / Redo stack on new project or when an existing project is loaded."); - def.set_default_value(new ConfigOptionBool{ app_config->get("clear_undo_redo_stack_on_new_project") == "1" }); - option = Option(def, "clear_undo_redo_stack_on_new_project"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "clear_undo_redo_stack_on_new_project", + L("Clear Undo / Redo stack on new project"), + L("Clear Undo / Redo stack on new project or when an existing project is loaded."), + app_config->get("clear_undo_redo_stack_on_new_project") == "1"); #if defined(_WIN32) || defined(__APPLE__) - def.label = L("Enable support for legacy 3DConnexion devices"); - def.type = coBool; - def.tooltip = L("If enabled, the legacy 3DConnexion devices settings dialog is available by pressing CTRL+M"); - def.set_default_value(new ConfigOptionBool{ app_config->get("use_legacy_3DConnexion") == "1" }); - option = Option(def, "use_legacy_3DConnexion"); - m_optgroup_general->append_single_option_line(option); + append_bool_option(m_optgroup_general, "use_legacy_3DConnexion", + L("Enable support for legacy 3DConnexion devices"), + L("If enabled, the legacy 3DConnexion devices settings dialog is available by pressing CTRL+M"), + app_config->get("use_legacy_3DConnexion") == "1"); #endif // _WIN32 || __APPLE__ activate_options_tab(m_optgroup_general); // Add "Camera" tab - m_optgroup_camera = create_options_tab(_L("Camera"), tabs); + m_optgroup_camera = create_options_tab(L("Camera"), tabs); m_optgroup_camera->m_on_change = [this](t_config_option_key opt_key, boost::any value) { m_values[opt_key] = boost::any_cast(value) ? "1" : "0"; }; - def.label = L("Use perspective camera"); - def.type = coBool; - def.tooltip = L("If enabled, use perspective camera. If not enabled, use orthographic camera."); - def.set_default_value(new ConfigOptionBool{ app_config->get("use_perspective_camera") == "1" }); - option = Option(def, "use_perspective_camera"); - m_optgroup_camera->append_single_option_line(option); + append_bool_option(m_optgroup_camera, "use_perspective_camera", + L("Use perspective camera"), + L("If enabled, use perspective camera. If not enabled, use orthographic camera."), + app_config->get("use_perspective_camera") == "1"); - def.label = L("Use free camera"); - def.type = coBool; - def.tooltip = L("If enabled, use free camera. If not enabled, use constrained camera."); - def.set_default_value(new ConfigOptionBool(app_config->get("use_free_camera") == "1")); - option = Option(def, "use_free_camera"); - m_optgroup_camera->append_single_option_line(option); + append_bool_option(m_optgroup_camera, "use_free_camera", + L("Use free camera"), + L("If enabled, use free camera. If not enabled, use constrained camera."), + app_config->get("use_free_camera") == "1"); - def.label = L("Reverse direction of zoom with mouse wheel"); - def.type = coBool; - def.tooltip = L("If enabled, reverses the direction of zoom with mouse wheel"); - def.set_default_value(new ConfigOptionBool(app_config->get("reverse_mouse_wheel_zoom") == "1")); - option = Option(def, "reverse_mouse_wheel_zoom"); - m_optgroup_camera->append_single_option_line(option); + append_bool_option(m_optgroup_camera, "reverse_mouse_wheel_zoom", + L("Reverse direction of zoom with mouse wheel"), + L("If enabled, reverses the direction of zoom with mouse wheel"), + app_config->get("reverse_mouse_wheel_zoom") == "1"); activate_options_tab(m_optgroup_camera); // Add "GUI" tab - m_optgroup_gui = create_options_tab(_L("GUI"), tabs); - m_optgroup_gui->m_on_change = [this, tabs](t_config_option_key opt_key, boost::any value) { + m_optgroup_gui = create_options_tab(L("GUI"), tabs); + m_optgroup_gui->m_on_change = [this](t_config_option_key opt_key, boost::any value) { if (opt_key == "suppress_hyperlinks") m_values[opt_key] = boost::any_cast(value) ? "1" : ""; else if (opt_key == "notify_release") { @@ -343,165 +366,123 @@ void PreferencesDialog::build(size_t selected_tab) } }; - def.label = L("Sequential slider applied only to top layer"); - def.type = coBool; - def.tooltip = L("If enabled, changes made using the sequential slider, in preview, apply only to gcode top layer. " - "If disabled, changes made using the sequential slider, in preview, apply to the whole gcode."); - def.set_default_value(new ConfigOptionBool{ app_config->get("seq_top_layer_only") == "1" }); - option = Option(def, "seq_top_layer_only"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "seq_top_layer_only", + L("Sequential slider applied only to top layer"), + L("If enabled, changes made using the sequential slider, in preview, apply only to gcode top layer." + "If disabled, changes made using the sequential slider, in preview, apply to the whole gcode."), + app_config->get("seq_top_layer_only") == "1"); if (is_editor) { - def.label = L("Show sidebar collapse/expand button"); - def.type = coBool; - def.tooltip = L("If enabled, the button for the collapse sidebar will be appeared in top right corner of the 3D Scene"); - def.set_default_value(new ConfigOptionBool{ app_config->get("show_collapse_button") == "1" }); - option = Option(def, "show_collapse_button"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "show_collapse_button", + L("Show sidebar collapse/expand button"), + L("If enabled, the button for the collapse sidebar will be appeared in top right corner of the 3D Scene"), + app_config->get("show_collapse_button") == "1"); - def.label = L("Suppress to open hyperlink in browser"); - def.type = coBool; - def.tooltip = L("If enabled, the descriptions of configuration parameters in settings tabs wouldn't work as hyperlinks. " - "If disabled, the descriptions of configuration parameters in settings tabs will work as hyperlinks."); - def.set_default_value(new ConfigOptionBool{ app_config->get("suppress_hyperlinks") == "1" }); - option = Option(def, "suppress_hyperlinks"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "suppress_hyperlinks", + L("Suppress to open hyperlink in browser"), + L("If enabled, the descriptions of configuration parameters in settings tabs wouldn't work as hyperlinks. " + "If disabled, the descriptions of configuration parameters in settings tabs will work as hyperlinks."), + app_config->get("suppress_hyperlinks") == "1"); - def.label = L("Use colors for axes values in Manipulation panel"); - def.type = coBool; - def.tooltip = L("If enabled, the axes names and axes values will be colorized according to the axes colors. " - "If disabled, old UI will be used."); - def.set_default_value(new ConfigOptionBool{ app_config->get("color_mapinulation_panel") == "1" }); - option = Option(def, "color_mapinulation_panel"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "color_mapinulation_panel", + L("Use colors for axes values in Manipulation panel"), + L("If enabled, the axes names and axes values will be colorized according to the axes colors. " + "If disabled, old UI will be used."), + app_config->get("color_mapinulation_panel") == "1"); - def.label = L("Order object volumes by types"); - def.type = coBool; - def.tooltip = L("If enabled, volumes will be always ordered inside the object. Correct order is Model Part, Negative Volume, Modifier, Support Blocker and Support Enforcer. " - "If disabled, you can reorder Model Parts, Negative Volumes and Modifiers. But one of the model parts have to be on the first place."); - def.set_default_value(new ConfigOptionBool{ app_config->get("order_volumes") == "1" }); - option = Option(def, "order_volumes"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "order_volumes", + L("Order object volumes by types"), + L("If enabled, volumes will be always ordered inside the object. Correct order is Model Part, Negative Volume, Modifier, Support Blocker and Support Enforcer. " + "If disabled, you can reorder Model Parts, Negative Volumes and Modifiers. But one of the model parts have to be on the first place."), + app_config->get("order_volumes") == "1"); #ifdef _MSW_DARK_MODE - def.label = L("Set settings tabs as menu items (experimental)"); - def.type = coBool; - def.tooltip = L("If enabled, Settings Tabs will be placed as menu items. " - "If disabled, old UI will be used."); - def.set_default_value(new ConfigOptionBool{ app_config->get("tabs_as_menu") == "1" }); - option = Option(def, "tabs_as_menu"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "tabs_as_menu", + L("Set settings tabs as menu items (experimental)"), + L("If enabled, Settings Tabs will be placed as menu items. If disabled, old UI will be used."), + app_config->get("tabs_as_menu") == "1"); #endif m_optgroup_gui->append_separator(); - def.label = L("Show \"Tip of the day\" notification after start"); - def.type = coBool; - def.tooltip = L("If enabled, useful hints are displayed at startup."); - def.set_default_value(new ConfigOptionBool{ app_config->get("show_hints") == "1" }); - option = Option(def, "show_hints"); - m_optgroup_gui->append_single_option_line(option); + append_bool_option(m_optgroup_gui, "show_hints", + L("Show \"Tip of the day\" notification after start"), + L("If enabled, useful hints are displayed at startup."), + app_config->get("show_hints") == "1"); - ConfigOptionDef def_enum; - def_enum.label = L("Notify about new releases"); - def_enum.type = coEnum; - def_enum.tooltip = L("You will be notified about new release after startup acordingly: All = Regular release and alpha / beta releases. Release only = regular release."); - def_enum.enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def_enum.enum_values.push_back("all"); - def_enum.enum_values.push_back("release"); - def_enum.enum_values.push_back("none"); - def_enum.enum_labels.push_back(L("All")); - def_enum.enum_labels.push_back(L("Release only")); - def_enum.enum_labels.push_back(L("None")); - def_enum.mode = comSimple; - def_enum.set_default_value(new ConfigOptionEnum(static_cast(s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release"))))); - option = Option(def_enum, "notify_release"); - m_optgroup_gui->append_single_option_line(option); + append_enum_option(m_optgroup_gui, "notify_release", + L("Notify about new releases"), + L("You will be notified about new release after startup acordingly: All = Regular release and alpha / beta releases. Release only = regular release."), + new ConfigOptionEnum(static_cast(s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release")))), + &ConfigOptionEnum::get_enum_values(), + {"all", "release", "none"}, + {L("All"), L("Release only"), L("None")}); m_optgroup_gui->append_separator(); - def.label = L("Use custom size for toolbar icons"); - def.type = coBool; - def.tooltip = L("If enabled, you can change size of toolbar icons manually."); - def.set_default_value(new ConfigOptionBool{ app_config->get("use_custom_toolbar_size") == "1" }); - option = Option(def, "use_custom_toolbar_size"); - m_optgroup_gui->append_single_option_line(option); - + append_bool_option(m_optgroup_gui, "use_custom_toolbar_size", + L("Use custom size for toolbar icons"), + L("If enabled, you can change size of toolbar icons manually."), + app_config->get("use_custom_toolbar_size") == "1"); } activate_options_tab(m_optgroup_gui); - // set Field for notify_release to its value to activate the object - if (is_editor) { - boost::any val = s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release")); - m_optgroup_gui->get_field("notify_release")->set_value(val, false); - } if (is_editor) { + // set Field for notify_release to its value to activate the object + boost::any val = s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release")); + m_optgroup_gui->get_field("notify_release")->set_value(val, false); + create_icon_size_slider(); m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1"); create_settings_mode_widget(); create_settings_text_color_widget(); - } #if ENABLE_ENVIRONMENT_MAP - if (is_editor) { // Add "Render" tab - m_optgroup_render = create_options_tab(_L("Render"), tabs); + m_optgroup_render = create_options_tab(L("Render"), tabs); m_optgroup_render->m_on_change = [this](t_config_option_key opt_key, boost::any value) { m_values[opt_key] = boost::any_cast(value) ? "1" : "0"; }; - def.label = L("Use environment map"); - def.type = coBool; - def.tooltip = L("If enabled, renders object using the environment map."); - def.set_default_value(new ConfigOptionBool{ app_config->get("use_environment_map") == "1" }); - option = Option(def, "use_environment_map"); - m_optgroup_render->append_single_option_line(option); + append_bool_option(m_optgroup_render, "use_environment_map", + L("Use environment map"), + L("If enabled, renders object using the environment map."), + app_config->get("use_environment_map") == "1"); activate_options_tab(m_optgroup_render); - } #endif // ENABLE_ENVIRONMENT_MAP #ifdef _WIN32 - // Add "Dark Mode" tab - { // Add "Dark Mode" tab m_optgroup_dark_mode = create_options_tab(_L("Dark mode (experimental)"), tabs); m_optgroup_dark_mode->m_on_change = [this](t_config_option_key opt_key, boost::any value) { m_values[opt_key] = boost::any_cast(value) ? "1" : "0"; }; - def.label = L("Enable dark mode"); - def.type = coBool; - def.tooltip = L("If enabled, UI will use Dark mode colors. " - "If disabled, old UI will be used."); - def.set_default_value(new ConfigOptionBool{ app_config->get("dark_color_mode") == "1" }); - option = Option(def, "dark_color_mode"); - m_optgroup_dark_mode->append_single_option_line(option); + append_bool_option(m_optgroup_dark_mode, "dark_color_mode", + L("Enable dark mode"), + L("If enabled, UI will use Dark mode colors. If disabled, old UI will be used."), + app_config->get("dark_color_mode") == "1"); if (wxPlatformInfo::Get().GetOSMajorVersion() >= 10) // Use system menu just for Window newer then Windows 10 // Use menu with ownerdrawn items by default on systems older then Windows 10 { - def.label = L("Use system menu for application"); - def.type = coBool; - def.tooltip = L("If enabled, application will use the standard Windows system menu,\n" - "but on some combination of display scales it can looks ugly. If disabled, old UI will be used."); - def.set_default_value(new ConfigOptionBool{ app_config->get("sys_menu_enabled") == "1" }); - option = Option(def, "sys_menu_enabled"); - m_optgroup_dark_mode->append_single_option_line(option); + append_bool_option(m_optgroup_dark_mode, "sys_menu_enabled", + L("Use system menu for application"), + L("If enabled, application will use the standart Windows system menu,\n" + "but on some combination od display scales it can look ugly. If disabled, old UI will be used."), + app_config->get("sys_menu_enabled") == "1"); } activate_options_tab(m_optgroup_dark_mode); - } #endif //_WIN32 + } // update alignment of the controls for all tabs update_ctrls_alignment(); - if (selected_tab < tabs->GetPageCount()) - tabs->SetSelection(selected_tab); - auto sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(tabs, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5); @@ -526,7 +507,10 @@ std::vector PreferencesDialog::optgroups() #ifdef _WIN32 , m_optgroup_dark_mode.get() #endif // _WIN32 - }) +#if ENABLE_ENVIRONMENT_MAP + , m_optgroup_render.get() +#endif // ENABLE_ENVIRONMENT_MAP + }) if (opt) out.emplace_back(opt); return out; @@ -546,9 +530,6 @@ void PreferencesDialog::update_ctrls_alignment() void PreferencesDialog::accept(wxEvent&) { -// if (m_values.find("no_defaults") != m_values.end() -// warning_catcher(this, wxString::Format(_L("You need to restart %s to make the changes effective."), SLIC3R_APP_NAME)); - std::vector options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled" }; for (const std::string& option : options_to_recreate_GUI) { @@ -627,16 +608,29 @@ void PreferencesDialog::accept(wxEvent&) wxGetApp().update_ui_from_settings(); } -void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect) +void PreferencesDialog::msw_rescale() { for (ConfigOptionsGroup* og : this->optgroups()) og->msw_rescale(); +#ifdef _WIN32 + m_optgroup_dark_mode->msw_rescale(); +#endif //_WIN32 +#if ENABLE_ENVIRONMENT_MAP + m_optgroup_render->msw_rescale(); +#endif // ENABLE_ENVIRONMENT_MAP msw_buttons_rescale(this, em_unit(), { wxID_OK, wxID_CANCEL }); layout(); } +void PreferencesDialog::on_sys_color_changed() +{ +#ifdef _WIN32 + wxGetApp().UpdateDlgDarkUI(this); +#endif +} + void PreferencesDialog::layout() { const int em = em_unit(); @@ -732,7 +726,8 @@ void PreferencesDialog::create_settings_mode_widget() wxWindow* parent = m_optgroup_gui->parent(); wxGetApp().UpdateDarkUI(parent); - wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _L("Layout Options")); + wxString title = L("Layout Options"); + wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title)); wxGetApp().UpdateDarkUI(stb); if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); stb->SetFont(wxGetApp().normal_font()); @@ -766,36 +761,58 @@ void PreferencesDialog::create_settings_mode_widget() id++; } + std::string opt_key = "settings_layout_mode"; + m_blinkers[opt_key] = new BlinkingBitmap(this); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_blinkers[opt_key], 0, wxALIGN_CENTER_VERTICAL); sizer->Add(stb_sizer, 1, wxALIGN_CENTER_VERTICAL); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); + + append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title); } void PreferencesDialog::create_settings_text_color_widget() { wxWindow* parent = m_optgroup_gui->parent(); - wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _L("Text colors")); + wxString title = L("Text colors"); + wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title)); wxGetApp().UpdateDarkUI(stb); if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); - wxSizer* sizer = new wxStaticBoxSizer(stb, wxVERTICAL); - ButtonsDescription::FillSizerWithTextColorDescriptions(sizer, parent, &m_sys_colour, &m_mod_colour); + std::string opt_key = "text_colors"; + m_blinkers[opt_key] = new BlinkingBitmap(this); + + wxSizer* stb_sizer = new wxStaticBoxSizer(stb, wxVERTICAL); + ButtonsDescription::FillSizerWithTextColorDescriptions(stb_sizer, parent, &m_sys_colour, &m_mod_colour); + + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_blinkers[opt_key], 0, wxALIGN_CENTER_VERTICAL); + sizer->Add(stb_sizer, 1, wxALIGN_CENTER_VERTICAL); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); + + append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title); } void PreferencesDialog::init_highlighter(const t_config_option_key& opt_key) { - m_highlighter.set_timer_owner(this, 0); - this->Bind(wxEVT_TIMER, [this](wxTimerEvent&) - { - m_highlighter.blink(); - }); + if (m_blinkers.find(opt_key) != m_blinkers.end()) + if (BlinkingBitmap* blinker = m_blinkers.at(opt_key); blinker) { + m_highlighter.init(blinker); + return; + } - std::pair ctrl = { nullptr, nullptr }; - for (ConfigOptionsGroup* opt_group : this->optgroups()) { - ctrl = opt_group->get_custom_ctrl_with_blinking_ptr(opt_key, -1); + for (auto opt_group : { m_optgroup_general, m_optgroup_camera, m_optgroup_gui +#ifdef _WIN32 + , m_optgroup_dark_mode +#endif // _WIN32 +#if ENABLE_ENVIRONMENT_MAP + , m_optgroup_render +#endif // ENABLE_ENVIRONMENT_MAP + }) { + std::pair ctrl = opt_group->get_custom_ctrl_with_blinking_ptr(opt_key, -1); if (ctrl.first && ctrl.second) { m_highlighter.init(ctrl); break; @@ -803,53 +820,5 @@ void PreferencesDialog::init_highlighter(const t_config_option_key& opt_key) } } -void PreferencesDialog::PreferencesHighlighter::set_timer_owner(wxEvtHandler* owner, int timerid/* = wxID_ANY*/) -{ - m_timer.SetOwner(owner, timerid); -} - -void PreferencesDialog::PreferencesHighlighter::init(std::pair params) -{ - if (m_timer.IsRunning()) - invalidate(); - if (!params.first || !params.second) - return; - - m_timer.Start(300, false); - - m_custom_ctrl = params.first; - m_show_blink_ptr = params.second; - - *m_show_blink_ptr = true; - m_custom_ctrl->Refresh(); -} - -void PreferencesDialog::PreferencesHighlighter::invalidate() -{ - m_timer.Stop(); - - if (m_custom_ctrl && m_show_blink_ptr) { - *m_show_blink_ptr = false; - m_custom_ctrl->Refresh(); - m_show_blink_ptr = nullptr; - m_custom_ctrl = nullptr; - } - - m_blink_counter = 0; -} - -void PreferencesDialog::PreferencesHighlighter::blink() -{ - if (m_custom_ctrl && m_show_blink_ptr) { - *m_show_blink_ptr = !*m_show_blink_ptr; - m_custom_ctrl->Refresh(); - } - else - return; - - if ((++m_blink_counter) == 11) - invalidate(); -} - } // GUI } // Slic3r diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 6c80121950..ef13ee5990 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -3,6 +3,7 @@ #include "GUI.hpp" #include "GUI_Utils.hpp" +#include "wxExtensions.hpp" #include #include @@ -10,6 +11,7 @@ #include class wxColourPickerCtrl; +class wxBookCtrlBase; namespace Slic3r { @@ -39,24 +41,29 @@ class PreferencesDialog : public DPIDialog wxSizer* m_icon_size_sizer; wxColourPickerCtrl* m_sys_colour {nullptr}; wxColourPickerCtrl* m_mod_colour {nullptr}; + wxBookCtrlBase* tabs {nullptr}; + bool isOSX {false}; bool m_settings_layout_changed {false}; bool m_seq_top_layer_only_changed{ false }; bool m_recreate_GUI{false}; public: - explicit PreferencesDialog(wxWindow* parent, int selected_tab = 0, const std::string& highlight_opt_key = std::string()); + explicit PreferencesDialog(wxWindow* paren); ~PreferencesDialog() = default; bool settings_layout_changed() const { return m_settings_layout_changed; } bool seq_top_layer_only_changed() const { return m_seq_top_layer_only_changed; } bool recreate_GUI() const { return m_recreate_GUI; } - void build(size_t selected_tab = 0); + void build(); void update_ctrls_alignment(); void accept(wxEvent&); + void show(const std::string& highlight_option = std::string(), const std::string& tab_name = std::string()); protected: - void on_dpi_changed(const wxRect &suggested_rect) override; + void msw_rescale(); + void on_dpi_changed(const wxRect& suggested_rect) override { msw_rescale(); } + void on_sys_color_changed() override; void layout(); void create_icon_size_slider(); void create_settings_mode_widget(); @@ -64,20 +71,9 @@ protected: void init_highlighter(const t_config_option_key& opt_key); std::vector optgroups(); - struct PreferencesHighlighter - { - void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY); - void init(std::pair); - void blink(); - void invalidate(); + Highlighter m_highlighter; - private: - OG_CustomCtrl* m_custom_ctrl{ nullptr }; - bool* m_show_blink_ptr{ nullptr }; - int m_blink_counter{ 0 }; - wxTimer m_timer; - } - m_highlighter; + std::map m_blinkers; }; } // GUI diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index add5dc0024..bdb2e55bf9 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -43,6 +43,8 @@ static char marker_by_type(Preset::Type type, PrinterTechnology pt) return ImGui::MaterialIconMarker; case Preset::TYPE_PRINTER: return pt == ptSLA ? ImGui::PrinterSlaIconMarker : ImGui::PrinterIconMarker; + case Preset::TYPE_PREFERENCES: + return ImGui::PreferencesButton; default: return ' '; } @@ -302,6 +304,9 @@ void OptionsSearcher::init(std::vector input_values) options.clear(); for (auto i : input_values) append_options(i.config, i.type, i.mode); + + options.insert(options.end(), preferences_options.begin(), preferences_options.end()); + sort_options(); search(search_line, true); @@ -323,6 +328,47 @@ void OptionsSearcher::apply(DynamicPrintConfig* config, Preset::Type type, Confi search(search_line, true); } +void OptionsSearcher::append_preferences_option(const GUI::Line& opt_line) +{ + Preset::Type type = Preset::TYPE_PREFERENCES; + wxString label = opt_line.label; + if (label.IsEmpty()) + return; + + std::string key = get_key(opt_line.get_options().front().opt_id, type); + const GroupAndCategory& gc = groups_and_categories[key]; + if (gc.group.IsEmpty() || gc.category.IsEmpty()) + return; + + preferences_options.emplace_back(Search::Option{ boost::nowide::widen(key), type, + label.ToStdWstring(), _(label).ToStdWstring(), + gc.group.ToStdWstring(), _(gc.group).ToStdWstring(), + gc.category.ToStdWstring(), _(gc.category).ToStdWstring() }); +} + +void OptionsSearcher::append_preferences_options(const std::vector& opt_lines) +{ + //Preset::Type type = Preset::TYPE_PREFERENCES; + for (const GUI::Line& line : opt_lines) { + if (line.is_separator()) + continue; + append_preferences_option(line); + //wxString label = line.label; + //if (label.IsEmpty()) + // continue; + + //std::string key = get_key(line.get_options().front().opt_id, type); + //const GroupAndCategory& gc = groups_and_categories[key]; + //if (gc.group.IsEmpty() || gc.category.IsEmpty()) + // continue; + // + //preferences_options.emplace_back(Search::Option{ boost::nowide::widen(key), type, + // label.ToStdWstring(), _(label).ToStdWstring(), + // gc.group.ToStdWstring(), _(gc.group).ToStdWstring(), + // gc.category.ToStdWstring(), _(gc.category).ToStdWstring() }); + } +} + const Option& OptionsSearcher::get_option(size_t pos_in_filter) const { assert(pos_in_filter != size_t(-1) && found[pos_in_filter].option_idx != size_t(-1)); @@ -429,6 +475,7 @@ static const std::map icon_idxs = { {ImGui::PrinterSlaIconMarker, 2}, {ImGui::FilamentIconMarker , 3}, {ImGui::MaterialIconMarker , 4}, + {ImGui::PreferencesButton , 5}, }; SearchDialog::SearchDialog(OptionsSearcher* searcher) @@ -717,7 +764,7 @@ void SearchDialog::on_sys_color_changed() SearchListModel::SearchListModel(wxWindow* parent) : wxDataViewVirtualListModel(0) { int icon_id = 0; - for (const std::string& icon : { "cog", "printer", "sla_printer", "spool", "resin" }) + for (const std::string& icon : { "cog", "printer", "sla_printer", "spool", "resin", "notification_preferences" }) m_icon[icon_id++] = ScalableBitmap(parent, icon); } diff --git a/src/slic3r/GUI/Search.hpp b/src/slic3r/GUI/Search.hpp index d5add92629..47385e879a 100644 --- a/src/slic3r/GUI/Search.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -17,6 +17,7 @@ #include "GUI_Utils.hpp" #include "wxExtensions.hpp" +#include "OptionsGroup.hpp" #include "libslic3r/Preset.hpp" @@ -85,6 +86,7 @@ class OptionsSearcher PrinterTechnology printer_technology; std::vector