ImguiDoubleSlider: WIP: Slider Manager is moved to ImGuiDoubleSlider and some values and methods are renamed

+ "DoubleSlider: file is split to DoubleSliderForGcode and DoubleSliderForLayers in separate files
 + Suppress to add/delete ticks on update layers_slider from canvas when an application is a GCodeViewer
 + epsilon() is moved from DoubleSlider name space to CustomGCode
This commit is contained in:
YuSanka 2024-03-25 14:49:30 +01:00 committed by Lukas Matena
parent 56a3740fe4
commit 6b83f135c9
13 changed files with 637 additions and 601 deletions

View File

@ -30,7 +30,7 @@ src/slic3r/GUI/ConfigManipulation.cpp
src/slic3r/GUI/ConfigSnapshotDialog.cpp
src/slic3r/GUI/ConfigWizard.cpp
src/slic3r/GUI/DesktopIntegrationDialog.cpp
src/slic3r/GUI/DoubleSlider.cpp
src/slic3r/GUI/DoubleSliderForLayers.cpp
src/slic3r/GUI/Downloader.cpp
src/slic3r/GUI/DownloaderFileGet.cpp
src/slic3r/GUI/EditGCodeDialog.cpp

View File

@ -14,6 +14,11 @@ class DynamicPrintConfig;
namespace CustomGCode {
/* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values.
* So, let use same value as a permissible error for layer height.
*/
constexpr double epsilon() { return 0.0011; }
enum Type
{
ColorChange,

View File

@ -252,10 +252,12 @@ set(SLIC3R_GUI_SOURCES
GUI/ProgressStatusBar.cpp
GUI/Mouse3DController.cpp
GUI/Mouse3DController.hpp
GUI/DoubleSlider.cpp
GUI/DoubleSlider.hpp
GUI/ImGuiDoubleSlider.cpp
GUI/ImGuiDoubleSlider.hpp
GUI/DoubleSliderForLayers.cpp
GUI/DoubleSliderForLayers.hpp
GUI/DoubleSliderForGcode.cpp
GUI/DoubleSliderForGcode.hpp
GUI/Notebook.cpp
GUI/Notebook.hpp
GUI/TopBar.cpp

View File

@ -0,0 +1,33 @@
///|/ Copyright (c) Prusa Research 2020 - 2023 Oleksandra Iushchenko @YuSanka, Vojtěch Bubník @bubnikv, Tomáš Mészáros @tamasmeszaros, Lukáš Matěna @lukasmatena, Enrico Turri @enricoturri1966
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "DoubleSliderForGcode.hpp"
namespace Slic3r {
namespace DoubleSlider {
static const float LEFT_MARGIN = 13.0f + 100.0f; // avoid thumbnail toolbar
static const float HORIZONTAL_SLIDER_HEIGHT = 90.0f;
void DSForGcode::Render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/)
{
if (!m_ctrl.IsShown())
return;
m_scale = extra_scale * 0.1f * m_em;
ImVec2 pos = ImVec2{std::max(LEFT_MARGIN, 0.2f * canvas_width), canvas_height - HORIZONTAL_SLIDER_HEIGHT * m_scale};
ImVec2 size = ImVec2(canvas_width - 2 * pos.x, HORIZONTAL_SLIDER_HEIGHT * m_scale);
m_ctrl.Init(pos, size, m_scale);
if (m_ctrl.render())
process_thumb_move();
}
} // DoubleSlider
} // Slic3r

View File

@ -0,0 +1,42 @@
///|/ Copyright (c) Prusa Research 2020 - 2022 Vojtěch Bubník @bubnikv, Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, Lukáš Matěna @lukasmatena
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_GUI_DoubleSliderForGcode_hpp_
#define slic3r_GUI_DoubleSliderForGcode_hpp_
#include "ImGuiDoubleSlider.hpp"
namespace Slic3r {
namespace DoubleSlider {
class DSForGcode : public Manager<unsigned int>
{
public:
DSForGcode() : Manager<unsigned int>() {}
DSForGcode( int lowerPos,
int higherPos,
int minPos,
int maxPos)
{
Init(lowerPos, higherPos, minPos, maxPos, "moves_slider", true);
}
~DSForGcode() {}
void Render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override;
void set_render_as_disabled(bool value) { m_render_as_disabled = value; }
bool is_rendering_as_disabled() const { return m_render_as_disabled; }
private:
bool m_render_as_disabled{ false };
};
} // DoubleSlider;
} // Slic3r
#endif // slic3r_GUI_DoubleSliderForGcode_hpp_

View File

@ -2,8 +2,9 @@
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "DoubleSliderForLayers.hpp"
#include "libslic3r/libslic3r.h"
#include "DoubleSlider.hpp"
#include "libslic3r/GCode.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
@ -14,8 +15,6 @@
#include "libslic3r/AppConfig.hpp"
#include "GUI_Utils.hpp"
#include "MsgDialog.hpp"
#include "Tab.hpp"
#include "GUI_ObjectList.hpp"
#include <wx/dialog.h>
#include <wx/menu.h>
@ -24,7 +23,7 @@
#include <cmath>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include "Field.hpp"
#include "format.hpp"
#include "NotificationManager.hpp"
@ -44,9 +43,7 @@ namespace DoubleSlider {
constexpr double min_delta_area = scale_(scale_(25)); // equal to 25 mm2
constexpr double miscalculation = scale_(scale_(1)); // equal to 1 mm2
static const float LEFT_MARGIN = 13.0f + 100.0f; // avoid thumbnail toolbar
static const float HORIZONTAL_SLIDER_WIDTH = 90.0f;
static const float VERTICAL_SLIDER_HEIGHT = 105.0f;
static const float VERTICAL_SLIDER_WIDTH = 105.0f;
bool equivalent_areas(const double& bottom_area, const double& top_area)
{
@ -55,7 +52,7 @@ bool equivalent_areas(const double& bottom_area, const double& top_area)
static std::string gcode(Type type)
{
const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config();
const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config(); // ! ys_FIXME
switch (type) {
case ColorChange: return config.color_change_gcode;
case PausePrint: return config.pause_print_gcode;
@ -64,7 +61,26 @@ static std::string gcode(Type type)
}
}
int DSManagerForLayers::get_tick_from_value(double value, bool force_lower_bound/* = false*/)
DSForLayers::DSForLayers( int lowerValue,
int higherValue,
int minValue,
int maxValue,
bool allow_editing) :
m_allow_editing(allow_editing)
{
#ifdef __WXOSX__
is_osx = true;
#endif //__WXOSX__
Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false);
m_ctrl.set_get_label_on_move_cb([this](int pos) { return m_show_estimated_times ? into_u8(get_label(pos, ltEstimatedTime)) : ""; });
m_ctrl.set_extra_draw_cb([this](const ImRect& draw_rc) {return draw_ticks(draw_rc); });
m_ticks.set_pause_print_msg(_u8L("Place bearings in slots and resume printing"));
m_ticks.set_extruder_colors(&m_extruder_colors);
}
int DSForLayers::get_tick_from_value(double value, bool force_lower_bound/* = false*/)
{
std::vector<double>::iterator it;
if (m_is_wipe_tower && !force_lower_bound)
@ -78,7 +94,7 @@ int DSManagerForLayers::get_tick_from_value(double value, bool force_lower_bound
return int(it - m_values.begin());
}
Info DSManagerForLayers::GetTicksValues() const
Info DSForLayers::GetTicksValues() const
{
Info custom_gcode_per_print_z;
std::vector<CustomGCode::Item>& values = custom_gcode_per_print_z.gcodes;
@ -91,13 +107,12 @@ Info DSManagerForLayers::GetTicksValues() const
values.emplace_back(CustomGCode::Item{ m_values[tick.tick], tick.type, tick.extruder, tick.color, tick.extra });
}
if (m_force_mode_apply)
custom_gcode_per_print_z.mode = m_mode;
custom_gcode_per_print_z.mode = m_mode;
return custom_gcode_per_print_z;
}
void DSManagerForLayers::SetTicksValues(const Info& custom_gcode_per_print_z)
void DSForLayers::SetTicksValues(const Info& custom_gcode_per_print_z)
{
if (m_values.empty()) {
m_ticks.mode = m_mode;
@ -116,18 +131,18 @@ void DSManagerForLayers::SetTicksValues(const Info& custom_gcode_per_print_z)
if (!was_empty && m_ticks.empty())
// Switch to the "Feature type"/"Tool" from the very beginning of a new object slicing after deleting of the old one
post_ticks_changed_event();
process_ticks_changed();
// init extruder sequence in respect to the extruders count
if (m_ticks.empty())
m_extruders_sequence.init(m_extruder_colors.size());
update_callbacks();
update_draw_scroll_line_cb();
if (custom_gcode_per_print_z.mode && !custom_gcode_per_print_z.gcodes.empty())
m_ticks.mode = custom_gcode_per_print_z.mode;
}
void DSManagerForLayers::SetLayersTimes(const std::vector<float>& layers_times, float total_time)
void DSForLayers::SetLayersTimes(const std::vector<float>& layers_times, float total_time)
{
m_layers_times.clear();
if (layers_times.empty())
@ -153,7 +168,7 @@ void DSManagerForLayers::SetLayersTimes(const std::vector<float>& layers_times,
}
}
void DSManagerForLayers::SetLayersTimes(const std::vector<double>& layers_times)
void DSForLayers::SetLayersTimes(const std::vector<double>& layers_times)
{
m_is_wipe_tower = false;
m_layers_times = layers_times;
@ -161,16 +176,16 @@ void DSManagerForLayers::SetLayersTimes(const std::vector<double>& layers_times)
m_layers_times[i] += m_layers_times[i - 1];
}
void DSManagerForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print)
void DSForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print)
{
m_draw_mode = is_sla_print ? dmSlaPrint :
is_sequential_print ? dmSequentialFffPrint :
dmRegular;
update_callbacks();
update_draw_scroll_line_cb();
}
void DSManagerForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder)
void DSForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder)
{
m_mode = !is_one_extruder_printed_model ? MultiExtruder :
only_extruder < 0 ? SingleExtruder :
@ -185,12 +200,12 @@ void DSManagerForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_print
m_is_wipe_tower = m_mode != SingleExtruder;
}
void DSManagerForLayers::SetExtruderColors( const std::vector<std::string>& extruder_colors)
void DSForLayers::SetExtruderColors( const std::vector<std::string>& extruder_colors)
{
m_extruder_colors = extruder_colors;
}
bool DSManagerForLayers::IsNewPrint(const std::string& idxs)
bool DSForLayers::IsNewPrint(const std::string& idxs)
{
if (idxs == "sla" || idxs == m_print_obj_idxs)
return false;
@ -199,17 +214,17 @@ bool DSManagerForLayers::IsNewPrint(const std::string& idxs)
return true;
}
void DSManagerForLayers::update_callbacks()
void DSForLayers::update_draw_scroll_line_cb()
{
if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint)
imgui_ctrl.set_draw_scroll_line_cb(nullptr);
if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint || m_draw_mode == dmSlaPrint)
m_ctrl.set_draw_scroll_line_cb(nullptr);
else
imgui_ctrl.set_draw_scroll_line_cb([this](const ImRect& scroll_line, const ImRect& slideable_region) { draw_colored_band(scroll_line, slideable_region); });
m_ctrl.set_draw_scroll_line_cb([this](const ImRect& scroll_line, const ImRect& slideable_region) { draw_colored_band(scroll_line, slideable_region); });
}
using namespace ImGui;
void DSManagerForLayers::draw_ticks(const ImRect& slideable_region)
void DSForLayers::draw_ticks(const ImRect& slideable_region)
{
//if(m_draw_mode != dmRegular)
// return;
@ -231,7 +246,7 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region)
const ImU32 tick_hovered_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_WINDOW_BACKGROUND);
auto get_tick_pos = [this, slideable_region](int tick) {
return imgui_ctrl.GetPositionFromValue(tick, slideable_region);
return m_ctrl.GetPositionInRect(tick, slideable_region);
};
std::set<TickCode>::const_iterator tick_it = m_ticks.ticks.begin();
@ -250,7 +265,7 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region)
++tick_it;
}
auto active_tick_it = m_ticks.ticks.find(TickCode{ imgui_ctrl.GetActiveValue() });
auto active_tick_it = m_ticks.ticks.find(TickCode{ m_ctrl.GetActivePos() });
tick_it = m_ticks.ticks.begin();
while (tick_it != m_ticks.ticks.end())
@ -270,10 +285,10 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region)
bool activate_this_tick = false;
if (tick_it == active_tick_it && m_allow_editing) {
// delete tick
if (render_button(ImGui::RemoveTick, ImGui::RemoveTickHovered, btn_label, icon_pos, imgui_ctrl.IsActiveHigherThumb() ? fiHigherThumb : fiLowerThumb, tick_it->tick)) {
if (render_button(ImGui::RemoveTick, ImGui::RemoveTickHovered, btn_label, icon_pos, m_ctrl.IsActiveHigherThumb() ? fiHigherThumb : fiLowerThumb, tick_it->tick)) {
Type type = tick_it->type;
m_ticks.ticks.erase(tick_it);
post_ticks_changed_event(type);
process_ticks_changed();
break;
}
}
@ -289,7 +304,7 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region)
activate_this_tick = render_button(ImGui::EditGCode, ImGui::EditGCodeHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick);
if (activate_this_tick) {
imgui_ctrl.IsActiveHigherThumb() ? SetHigherValue(tick_it->tick) : SetLowerValue(tick_it->tick);
m_ctrl.IsActiveHigherThumb() ? SetHigherPos(tick_it->tick) : SetLowerPos(tick_it->tick);
break;
}
@ -318,7 +333,7 @@ static std::array<float, 4> decode_color_to_float_array(const std::string color)
return ret;
}
void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideable_region)
void DSForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideable_region)
{
if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint)
return;
@ -352,7 +367,7 @@ void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& s
while (tick_it != m_ticks.ticks.end())
{
//get position from tick
tick_pos = imgui_ctrl.GetPositionFromValue(tick_it->tick, slideable_region);
tick_pos = m_ctrl.GetPositionInRect(tick_it->tick, slideable_region);
ImRect band_rect = ImRect(ImVec2(main_band.Min.x, std::min(tick_pos, main_band.Min.y)),
ImVec2(main_band.Max.x, std::min(tick_pos, main_band.Max.y)));
@ -380,7 +395,7 @@ void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& s
}
}
void DSManagerForLayers::render_menu()
void DSForLayers::render_menu()
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 10.0f) * m_scale);
ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f * m_scale);
@ -391,14 +406,14 @@ void DSManagerForLayers::render_menu()
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
int extruder_num = colors.size();
if (imgui_ctrl.is_rclick_on_thumb()) {
if (m_ctrl.IsRClickOnThumb()) {
ImGui::OpenPopup("slider_menu_popup");
}
ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_ChildRounding, 4.0f * m_scale);
if (ImGui::BeginPopup("slider_menu_popup")) {
if ((!imgui_ctrl.IsActiveHigherThumb() && GetLowerValueD() == 0.0) ||
(imgui_ctrl.IsActiveHigherThumb() && GetHigherValueD() == 0.0))
if ((!m_ctrl.IsActiveHigherThumb() && GetLowerValue() == 0.0) ||
(m_ctrl.IsActiveHigherThumb() && GetHigherValue() == 0.0))
{
menu_item_with_icon(_u8L("Add Pause").c_str(), "", ImVec2(0, 0), 0, false, false);
}
@ -442,7 +457,7 @@ void DSManagerForLayers::render_menu()
ImGui::PopStyleVar(3);
}
bool DSManagerForLayers::render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick /*= -1*/)
bool DSForLayers::render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick /*= -1*/)
{
float scale = (float)wxGetApp().em_unit() / 10.0f;
@ -468,7 +483,7 @@ bool DSManagerForLayers::render_button(const wchar_t btn_icon, const wchar_t btn
ImGuiContext& g = *GImGui;
m_focus = focus;
std::string tooltip = m_allow_editing ? into_u8(get_tooltip(tick)) : "";
std::string tooltip = m_allow_editing ? get_tooltip(tick) : "";
ImGui::SetCursorPos(ImVec2(0, 0));
const bool ret = m_imgui->image_button(g.HoveredWindow == g.CurrentWindow ? btn_icon_hovered : btn_icon, tooltip, false);
@ -480,25 +495,11 @@ bool DSManagerForLayers::render_button(const wchar_t btn_icon, const wchar_t btn
return ret;
}
void DSManagerForGcode::imgui_render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/)
void DSForLayers::Render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/)
{
if (!imgui_ctrl.IsShown())
if (!m_ctrl.IsShown())
return;
m_scale = extra_scale * 0.1f * wxGetApp().em_unit();
ImVec2 pos = ImVec2{std::max(LEFT_MARGIN, 0.2f * canvas_width), canvas_height - HORIZONTAL_SLIDER_WIDTH * m_scale};
ImVec2 size = ImVec2(canvas_width - 2 * pos.x, HORIZONTAL_SLIDER_WIDTH * m_scale);
imgui_ctrl.Init(pos, size, m_scale);
if (imgui_ctrl.render())
process_thumb_move();
}
void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/)
{
if (!imgui_ctrl.IsShown())
return;
m_scale = extra_scale * 0.1f * wxGetApp().em_unit();
m_scale = extra_scale * 0.1f * m_em;
const float action_btn_sz = wxGetApp().imgui()->GetTextureCustomRect(ImGui::DSRevert)->Height;
const float tick_icon_side = wxGetApp().imgui()->GetTextureCustomRect(ImGui::PausePrint)->Height;
@ -506,15 +507,15 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h
ImVec2 pos;
ImVec2 size;
pos.x = canvas_width - VERTICAL_SLIDER_HEIGHT * m_scale - tick_icon_side;
pos.x = canvas_width - VERTICAL_SLIDER_WIDTH * m_scale - tick_icon_side;
pos.y = 1.f * action_btn_sz;
if (m_allow_editing)
pos.y += 2.f;
size = ImVec2(VERTICAL_SLIDER_HEIGHT * m_scale, canvas_height - 4.f * action_btn_sz);
imgui_ctrl.ShowLabelOnMouseMove(true);
size = ImVec2(VERTICAL_SLIDER_WIDTH * m_scale, canvas_height - 4.f * action_btn_sz);
m_ctrl.ShowLabelOnMouseMove(true);
imgui_ctrl.Init(pos, size, m_scale);
if (imgui_ctrl.render()) {
m_ctrl.Init(pos, size, m_scale);
if (m_ctrl.render()) {
// request one more frame if value was changes with mouse wheel
if (GImGui->IO.MouseWheel != 0.0f)
wxGetApp().imgui()->set_requires_extra_frame();
@ -523,7 +524,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h
// draw action buttons
const float groove_center_x = imgui_ctrl.GetGrooveRect().GetCenter().x;
const float groove_center_x = m_ctrl.GetGrooveRect().GetCenter().x;
ImVec2 btn_pos = ImVec2(groove_center_x - 0.5f * action_btn_sz, pos.y - 0.25f * action_btn_sz);
@ -532,7 +533,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h
discard_all_thicks();
btn_pos.y += 0.1f * action_btn_sz + size.y;
const bool is_one_layer = imgui_ctrl.IsCombineThumbs();
const bool is_one_layer = m_ctrl.IsCombineThumbs();
if (render_button(is_one_layer ? ImGui::Lock : ImGui::Unlock, is_one_layer ? ImGui::LockHovered : ImGui::UnlockHovered, "one_layer", btn_pos, fiOneLayerIcon))
ChangeOneLayerLock();
@ -540,7 +541,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h
if (render_button(ImGui::DSSettings, ImGui::DSSettingsHovered, "settings", btn_pos, fiCogIcon))
show_cog_icon_context_menu();
if (m_draw_mode == dmSequentialFffPrint && imgui_ctrl.is_rclick_on_thumb()) {
if (m_draw_mode == dmSequentialFffPrint && m_ctrl.IsRClickOnThumb()) {
std::string tooltip = _u8L("The sequential print is on.\n"
"It's impossible to apply any custom G-code for objects printing sequentually.");
ImGuiPureWrap::tooltip(tooltip, ImGui::GetFontSize() * 20.0f);
@ -549,7 +550,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h
render_menu();
}
bool DSManagerForLayers::is_wipe_tower_layer(int tick) const
bool DSForLayers::is_wipe_tower_layer(int tick) const
{
if (!m_is_wipe_tower || tick >= (int)m_values.size())
return false;
@ -603,7 +604,7 @@ static std::string short_and_splitted_time(const std::string& time)
return get_s();
}
std::string DSManagerForLayers::get_label(int pos, LabelType label_type/* = ltHeightWithLayer*/) const
std::string DSForLayers::get_label(int pos, LabelType label_type/* = ltHeightWithLayer*/) const
{
const size_t value = pos;
@ -651,7 +652,7 @@ std::string DSManagerForLayers::get_label(int pos, LabelType label_type/* = ltHe
return "";
}
std::string DSManagerForLayers::get_color_for_tool_change_tick(std::set<TickCode>::const_iterator it) const
std::string DSForLayers::get_color_for_tool_change_tick(std::set<TickCode>::const_iterator it) const
{
const int current_extruder = it->extruder == 0 ? std::max<int>(m_only_extruder, 1) : it->extruder;
@ -665,7 +666,7 @@ std::string DSManagerForLayers::get_color_for_tool_change_tick(std::set<TickCode
return m_extruder_colors[current_extruder-1]; // return a color for a specific extruder from the colors list
}
std::string DSManagerForLayers::get_color_for_color_change_tick(std::set<TickCode>::const_iterator it) const
std::string DSForLayers::get_color_for_color_change_tick(std::set<TickCode>::const_iterator it) const
{
const int def_extruder = std::max<int>(1, m_only_extruder);
auto it_n = it;
@ -687,48 +688,48 @@ std::string DSManagerForLayers::get_color_for_color_change_tick(std::set<TickCod
return "";
}
void DSManagerForLayers::ChangeOneLayerLock()
void DSForLayers::ChangeOneLayerLock()
{
imgui_ctrl.CombineThumbs(!imgui_ctrl.IsCombineThumbs());
m_ctrl.CombineThumbs(!m_ctrl.IsCombineThumbs());
process_thumb_move();
}
wxString DSManagerForLayers::get_tooltip(int tick/*=-1*/)
std::string DSForLayers::get_tooltip(int tick/*=-1*/)
{
if (m_focus == fiNone)
return "";
if (m_focus == fiOneLayerIcon)
return _L("One layer mode");
return _u8L("One layer mode");
if (m_focus == fiRevertIcon)
return _L("Discard all custom changes");
return _u8L("Discard all custom changes");
if (m_focus == fiCogIcon)
{
return m_mode == MultiAsSingle ?
GUI::from_u8((boost::format(_u8L("Jump to height %s\n"
"Set ruler mode\n"
"or Set extruder sequence for the entire print")) % "(Shift + G)").str()) :
GUI::from_u8((boost::format(_u8L("Jump to height %s\n"
"or Set ruler mode")) % "(Shift + G)").str());
(boost::format(_u8L("Jump to height %s\n"
"Set ruler mode\n"
"or Set extruder sequence for the entire print")) % "(Shift + G)").str() :
(boost::format(_u8L("Jump to height %s\n"
"or Set ruler mode")) % "(Shift + G)").str();
}
if (m_focus == fiColorBand)
return m_mode != SingleExtruder ? "" :
_L("Edit current color - Right click the colored slider segment");
_u8L("Edit current color - Right click the colored slider segment");
if (m_focus == fiSmartWipeTower)
return _L("This is wipe tower layer");
return _u8L("This is wipe tower layer");
if (m_draw_mode == dmSlaPrint)
return ""; // no drawn ticks and no tooltips for them in SlaPrinting mode
wxString tooltip;
std::string tooltip;
const auto tick_code_it = m_ticks.ticks.find(TickCode{tick});
if (tick_code_it == m_ticks.ticks.end() && m_focus == fiActionIcon) // tick doesn't exist
{
if (m_draw_mode == dmSequentialFffPrint)
return (_L("The sequential print is on.\n"
return (_u8L("The sequential print is on.\n"
"It's impossible to apply any custom G-code for objects printing sequentually.") + "\n");
// Show mode as a first string of tooltop
tooltip = " " + _L("Print mode") + ": ";
tooltip = " " + _u8L("Print mode") + ": ";
tooltip += (m_mode == SingleExtruder ? SingleExtruderMode :
m_mode == MultiAsSingle ? MultiAsSingleMode :
MultiExtruderMode );
@ -742,28 +743,28 @@ wxString DSManagerForLayers::get_tooltip(int tick/*=-1*/)
// Show list of actions with new tick
tooltip += ( m_mode == MultiAsSingle ?
_L("Add extruder change - Left click") :
_u8L("Add extruder change - Left click") :
m_mode == SingleExtruder ?
_L("Add color change - Left click for predefined color or "
_u8L("Add color change - Left click for predefined color or "
"Shift + Left click for custom color selection") :
_L("Add color change - Left click") ) + " " +
_L("or press \"+\" key") + "\n" + (
_u8L("Add color change - Left click") ) + " " +
_u8L("or press \"+\" key") + "\n" + (
is_osx ?
_L("Add another code - Ctrl + Left click") :
_L("Add another code - Right click") );
_u8L("Add another code - Ctrl + Left click") :
_u8L("Add another code - Right click") );
}
if (tick_code_it != m_ticks.ticks.end()) // tick exists
{
if (m_draw_mode == dmSequentialFffPrint)
return _L("The sequential print is on.\n"
return _u8L("The sequential print is on.\n"
"It's impossible to apply any custom G-code for objects printing sequentually.\n"
"This code won't be processed during G-code generation.");
// Show custom Gcode as a first string of tooltop
std::string space = " ";
tooltip = space;
auto format_gcode = [space](std::string gcode) {
auto format_gcode = [space](std::string gcode) -> std::string {
// when the tooltip is too long, it starts to flicker, see: https://github.com/prusa3d/PrusaSlicer/issues/7368
// so we limit the number of lines shown
std::vector<std::string> lines;
@ -782,50 +783,50 @@ wxString DSManagerForLayers::get_tooltip(int tick/*=-1*/)
tooltip +=
tick_code_it->type == ColorChange ?
(m_mode == SingleExtruder ?
format_wxstr(_L("Color change (\"%1%\")"), gcode(ColorChange)) :
format_wxstr(_L("Color change (\"%1%\") for Extruder %2%"), gcode(ColorChange), tick_code_it->extruder)) :
GUI::format(_L("Color change (\"%1%\")"), gcode(ColorChange)) :
GUI::format(_L("Color change (\"%1%\") for Extruder %2%"), gcode(ColorChange), tick_code_it->extruder)) :
tick_code_it->type == PausePrint ?
format_wxstr(_L("Pause print (\"%1%\")"), gcode(PausePrint)) :
GUI::format(_L("Pause print (\"%1%\")"), gcode(PausePrint)) :
tick_code_it->type == Template ?
format_wxstr(_L("Custom template (\"%1%\")"), gcode(Template)) :
GUI::format(_L("Custom template (\"%1%\")"), gcode(Template)) :
tick_code_it->type == ToolChange ?
format_wxstr(_L("Extruder (tool) is changed to Extruder \"%1%\""), tick_code_it->extruder) :
from_u8(format_gcode(tick_code_it->extra));// tick_code_it->type == Custom
GUI::format(_L("Extruder (tool) is changed to Extruder \"%1%\""), tick_code_it->extruder) :
format_gcode(tick_code_it->extra);// tick_code_it->type == Custom
// If tick is marked as a conflict (exclamation icon),
// we should to explain why
ConflictType conflict = m_ticks.is_conflict_tick(*tick_code_it, m_mode, m_only_extruder, m_values[tick]);
if (conflict != ctNone)
tooltip += "\n\n" + _L("Note") + "! ";
tooltip += "\n\n" + _u8L("Note") + "! ";
if (conflict == ctModeConflict)
tooltip += _L("G-code associated to this tick mark is in a conflict with print mode.\n"
tooltip += _u8L("G-code associated to this tick mark is in a conflict with print mode.\n"
"Editing it will cause changes of Slider data.");
else if (conflict == ctMeaninglessColorChange)
tooltip += _L("There is a color change for extruder that won't be used till the end of print job.\n"
tooltip += _u8L("There is a color change for extruder that won't be used till the end of print job.\n"
"This code won't be processed during G-code generation.");
else if (conflict == ctMeaninglessToolChange)
tooltip += _L("There is an extruder change set to the same extruder.\n"
tooltip += _u8L("There is an extruder change set to the same extruder.\n"
"This code won't be processed during G-code generation.");
else if (conflict == ctRedundant)
tooltip += _L("There is a color change for extruder that has not been used before.\n"
tooltip += _u8L("There is a color change for extruder that has not been used before.\n"
"Check your settings to avoid redundant color changes.");
// Show list of actions with existing tick
if (m_focus == fiActionIcon)
tooltip += "\n\n" + _L("Delete tick mark - Left click or press \"-\" key") + "\n" + (
tooltip += "\n\n" + _u8L("Delete tick mark - Left click or press \"-\" key") + "\n" + (
is_osx ?
_L("Edit tick mark - Ctrl + Left click") :
_L("Edit tick mark - Right click") );
_u8L("Edit tick mark - Ctrl + Left click") :
_u8L("Edit tick mark - Right click") );
}
return tooltip;
return tooltip;
}
void DSManagerForLayers::append_change_extruder_menu_item(wxMenu* menu, bool switch_current_code/* = false*/)
void DSForLayers::append_change_extruder_menu_item(wxMenu* menu, bool switch_current_code/* = false*/)
{
const int extruders_cnt = GUI::wxGetApp().extruders_edited_cnt();
if (extruders_cnt > 1) {
std::array<int, 2> active_extruders = get_active_extruders_for_tick(imgui_ctrl.GetActiveValue());
std::array<int, 2> active_extruders = get_active_extruders_for_tick(m_ctrl.GetActivePos());
std::vector<wxBitmapBundle*> icons = get_extruder_color_icons(true);
@ -848,15 +849,15 @@ void DSManagerForLayers::append_change_extruder_menu_item(wxMenu* menu, bool swi
append_submenu(menu, change_extruder_menu, wxID_ANY, change_extruder_menu_name, _L("Use another extruder"),
active_extruders[1] > 0 ? "edit_uni" : "change_extruder",
[this]() {return m_mode == MultiAsSingle && !GUI::wxGetApp().obj_list()->has_paint_on_segmentation(); }, GUI::wxGetApp().plater());
[this]() {return m_mode == MultiAsSingle /*&& !GUI::wxGetApp().obj_list()->has_paint_on_segmentation()*/; }, GUI::wxGetApp().plater()); // !ysFIXME has_paint_on_segmentation
}
}
void DSManagerForLayers::append_add_color_change_menu_item(wxMenu* menu, bool switch_current_code/* = false*/)
void DSForLayers::append_add_color_change_menu_item(wxMenu* menu, bool switch_current_code/* = false*/)
{
const int extruders_cnt = GUI::wxGetApp().extruders_edited_cnt();
if (extruders_cnt > 1) {
int tick = imgui_ctrl.GetActiveValue();
int tick = m_ctrl.GetActivePos();
std::set<int> used_extruders_for_tick = m_ticks.get_used_extruders_for_tick(tick, m_only_extruder, m_values[tick]);
wxMenu* add_color_change_menu = new wxMenu();
@ -880,7 +881,7 @@ void DSManagerForLayers::append_add_color_change_menu_item(wxMenu* menu, bool sw
}
}
void DSManagerForLayers::UseDefaultColors(bool def_colors_on)
void DSForLayers::UseDefaultColors(bool def_colors_on)
{
m_ticks.set_default_colors(def_colors_on);
}
@ -889,7 +890,7 @@ void DSManagerForLayers::UseDefaultColors(bool def_colors_on)
// Means one current extruder for not existing tick OR
// 2 extruders - for existing tick (extruder before ToolChange and extruder of current existing tick)
// Use those values to disable selection of active extruders
std::array<int, 2> DSManagerForLayers::get_active_extruders_for_tick(int tick) const
std::array<int, 2> DSForLayers::get_active_extruders_for_tick(int tick) const
{
int default_initial_extruder = m_mode == MultiAsSingle ? std::max<int>(1, m_only_extruder) : 1;
std::array<int, 2> extruders = { default_initial_extruder, -1 };
@ -912,73 +913,14 @@ std::array<int, 2> DSManagerForLayers::get_active_extruders_for_tick(int tick) c
return extruders;
}
// Get used extruders for tick.
// Means all extruders(tools) which will be used during printing from current tick to the end
std::set<int> TickCodeInfo::get_used_extruders_for_tick(int tick, int only_extruder, double print_z, Mode force_mode/* = Undef*/) const
{
Mode e_mode = !force_mode ? mode : force_mode;
if (e_mode == MultiExtruder) {
// #ys_FIXME: get tool ordering from _correct_ place
const ToolOrdering& tool_ordering = GUI::wxGetApp().plater()->fff_print().get_tool_ordering();
if (tool_ordering.empty())
return {};
std::set<int> used_extruders;
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), print_z, [](const LayerTools &lhs, double rhs){ return lhs.print_z < rhs; });
for (; it_layer_tools != tool_ordering.end(); ++it_layer_tools) {
const std::vector<unsigned>& extruders = it_layer_tools->extruders;
for (const auto& extruder : extruders)
used_extruders.emplace(extruder+1);
}
return used_extruders;
}
const int default_initial_extruder = e_mode == MultiAsSingle ? std::max(only_extruder, 1) : 1;
if (ticks.empty() || e_mode == SingleExtruder)
return {default_initial_extruder};
std::set<int> used_extruders;
auto it_start = ticks.lower_bound(TickCode{tick});
auto it = it_start;
if (it == ticks.begin() && it->type == ToolChange &&
tick != it->tick ) // In case of switch of ToolChange to ColorChange, when tick exists,
// we shouldn't change color for extruder, which will be deleted
{
used_extruders.emplace(it->extruder);
if (tick < it->tick)
used_extruders.emplace(default_initial_extruder);
}
while (it != ticks.begin()) {
--it;
if (it->type == ToolChange && tick != it->tick) {
used_extruders.emplace(it->extruder);
break;
}
}
if (it == ticks.begin() && used_extruders.empty())
used_extruders.emplace(default_initial_extruder);
for (it = it_start; it != ticks.end(); ++it)
if (it->type == ToolChange && tick != it->tick)
used_extruders.emplace(it->extruder);
return used_extruders;
}
void DSManagerForLayers::show_cog_icon_context_menu()
void DSForLayers::show_cog_icon_context_menu()
{
wxMenu menu;
append_menu_item(&menu, wxID_ANY, _L("Jump to height") + " (Shift+G)", "",
[this](wxCommandEvent&) { jump_to_value(); }, "", & menu);
if (m_allow_editing)
append_menu_check_item(&menu, wxID_ANY, _L("Use default colors"), _L("Use default colors on color change"),
[this](wxCommandEvent&) {
UseDefaultColors(!m_ticks.used_default_colors()); }, &menu,
@ -1025,7 +967,7 @@ bool check_color_change(const PrintObject* object, size_t frst_layer_id, size_t
return detected;
}
void DSManagerForLayers::auto_color_change()
void DSForLayers::auto_color_change()
{
if (!m_ticks.empty()) {
wxString msg_text = _L("This action will cause deletion of all ticks on vertical slider.") + "\n\n" +
@ -1072,9 +1014,9 @@ void DSManagerForLayers::auto_color_change()
if (m_ticks.empty())
GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::EmptyAutoColorChange);
update_callbacks();
update_draw_scroll_line_cb();
post_ticks_changed_event();
process_ticks_changed();
}
static std::string get_new_color(const std::string& color)
@ -1149,7 +1091,7 @@ static std::string get_custom_code(const std::string& code_in, double height)
return "";
value = into_u8(dlg.GetValue());
valid = GUI::Tab::validate_custom_gcode("Custom G-code", value);
valid = true;// GUI::Tab::validate_custom_gcode("Custom G-code", value); // !ysFIXME validate_custom_gcode
} while (!valid);
return value;
}
@ -1170,11 +1112,12 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height)
return into_u8(dlg.GetValue());
}
// draw with imgui
static double get_value_to_jump(double active_value, double min_z, double max_z, DrawMode mode)
{
wxString msg_text = _L("Enter the height you want to jump to") + ":";
wxString msg_header = _L("Jump to height");
wxString msg_in = GUI::double_to_string(active_value);
wxString msg_in = "";// GUI::double_to_string(active_value);
// get custom gcode
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, msg_in, wxTextEntryDialogStyle);
@ -1187,9 +1130,9 @@ static double get_value_to_jump(double active_value, double min_z, double max_z,
return dlg.GetValue().ToDouble(&value) ? value : -1.0;
}
void DSManagerForLayers::add_code_as_tick(Type type, int selected_extruder/* = -1*/)
void DSForLayers::add_code_as_tick(Type type, int selected_extruder/* = -1*/)
{
const int tick = imgui_ctrl.GetActiveValue();
const int tick = m_ctrl.GetActivePos();
if ( !check_ticks_changed_event(type) )
return;
@ -1216,14 +1159,17 @@ void DSManagerForLayers::add_code_as_tick(Type type, int selected_extruder/* = -
return;
if (was_ticks != m_ticks.empty())
update_callbacks();
update_draw_scroll_line_cb();
post_ticks_changed_event(type);
process_ticks_changed();
}
void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/)
void DSForLayers::add_current_tick()
{
const int tick = imgui_ctrl.GetActiveValue();
if (!m_allow_editing)
return;
const int tick = m_ctrl.GetActivePos();
auto it = m_ticks.ticks.find(TickCode{ tick });
if (it != m_ticks.ticks.end() || // this tick is already exist
@ -1232,8 +1178,9 @@ void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/)
if (m_mode == SingleExtruder)
add_code_as_tick(ColorChange);
/*
else
render_menu();
/*
{
wxMenu menu;
@ -1263,43 +1210,42 @@ void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/)
*/
}
void DSManagerForLayers::delete_current_tick()
void DSForLayers::delete_current_tick()
{
auto it = m_ticks.ticks.find(TickCode{ imgui_ctrl.GetActiveValue()});
auto it = m_ticks.ticks.find(TickCode{ m_ctrl.GetActivePos()});
if (it == m_ticks.ticks.end() ||
!check_ticks_changed_event(it->type))
return;
Type type = it->type;
m_ticks.ticks.erase(it);
post_ticks_changed_event(type);
process_ticks_changed();
}
void DSManagerForLayers::edit_tick(int tick/* = -1*/)
void DSForLayers::edit_tick(int tick/* = -1*/)
{
if (tick < 0)
tick = imgui_ctrl.GetActiveValue();
tick = m_ctrl.GetActivePos();
const std::set<TickCode>::iterator it = m_ticks.ticks.find(TickCode{ tick });
if (it == m_ticks.ticks.end() ||
!check_ticks_changed_event(it->type))
return;
Type type = it->type;
if (m_ticks.edit_tick(it, m_values[it->tick]))
post_ticks_changed_event(type);
process_ticks_changed();
}
// discard all custom changes on DoubleSlider
void DSManagerForLayers::discard_all_thicks()
void DSForLayers::discard_all_thicks()
{
m_ticks.ticks.clear();
imgui_ctrl.ResetValues();
update_callbacks();
post_ticks_changed_event();
m_ctrl.ResetPositions();
update_draw_scroll_line_cb();
process_ticks_changed();
}
void DSManagerForLayers::edit_extruder_sequence()
void DSForLayers::edit_extruder_sequence()
{
if (!check_ticks_changed_event(ToolChange))
return;
@ -1323,7 +1269,7 @@ void DSManagerForLayers::edit_extruder_sequence()
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> distrib(0, extr_cnt-1);
while (tick <= imgui_ctrl.GetMaxValue())
while (tick <= m_ctrl.GetMaxPos())
{
bool color_repetition = false;
if (m_extruders_sequence.random_sequence) {
@ -1357,31 +1303,25 @@ void DSManagerForLayers::edit_extruder_sequence()
tick += m_extruders_sequence.interval_by_layers;
}
post_ticks_changed_event(ToolChange);
process_ticks_changed();
}
void DSManagerForLayers::jump_to_value()
void DSForLayers::jump_to_value()
{
double value = get_value_to_jump(m_values[imgui_ctrl.GetActiveValue()],
m_values[imgui_ctrl.GetMinValue()], m_values[imgui_ctrl.GetMaxValue()], m_draw_mode);
double value = get_value_to_jump(m_values[m_ctrl.GetActivePos()],
m_values[m_ctrl.GetMinPos()], m_values[m_ctrl.GetMaxPos()], m_draw_mode);
if (value < 0.0)
return;
int tick_value = get_tick_from_value(value);
if (imgui_ctrl.IsActiveHigherThumb())
SetHigherValue(tick_value);
if (m_ctrl.IsActiveHigherThumb())
SetHigherPos(tick_value);
else
SetLowerValue(tick_value);
SetLowerPos(tick_value);
}
void DSManagerForLayers::post_ticks_changed_event(Type type /*= Custom*/)
{
// m_force_mode_apply = type != ToolChange; // It looks like this condition is no needed now. Leave it for the testing
process_ticks_changed();
}
bool DSManagerForLayers::check_ticks_changed_event(Type type)
bool DSForLayers::check_ticks_changed_event(Type type)
{
if ( m_ticks.mode == m_mode ||
(type != ColorChange && type != ToolChange) ||
@ -1406,7 +1346,7 @@ bool DSManagerForLayers::check_ticks_changed_event(Type type)
GUI::MessageDialog msg(nullptr, message, _L("Notice"), wxYES_NO);
if (msg.ShowModal() == wxID_YES) {
m_ticks.erase_all_ticks_with_code(ColorChange);
post_ticks_changed_event(ColorChange);
process_ticks_changed();
}
return false;
}
@ -1427,11 +1367,11 @@ bool DSManagerForLayers::check_ticks_changed_event(Type type)
const int answer = msg.ShowModal();
if (answer == wxID_YES) {
m_ticks.erase_all_ticks_with_code(ToolChange);
post_ticks_changed_event(ToolChange);
process_ticks_changed();
}
else if (m_mode == SingleExtruder && answer == wxID_NO) {
m_ticks.switch_code(ToolChange, ColorChange);
post_ticks_changed_event(ColorChange);
process_ticks_changed();
}
return false;
}
@ -1439,23 +1379,67 @@ bool DSManagerForLayers::check_ticks_changed_event(Type type)
return true;
}
DSManagerForLayers::DSManagerForLayers( int lowerValue,
int higherValue,
int minValue,
int maxValue,
bool allow_editing/* = true*/) :
m_allow_editing(allow_editing)
// Get used extruders for tick.
// Means all extruders(tools) which will be used during printing from current tick to the end
std::set<int> TickCodeInfo::get_used_extruders_for_tick(int tick, int only_extruder, double print_z, Mode force_mode/* = Undef*/) const
{
#ifdef __WXOSX__
is_osx = true;
#endif //__WXOSX__
Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false);
Mode e_mode = !force_mode ? mode : force_mode;
imgui_ctrl.set_get_label_on_move_cb([this](int pos) { return m_show_estimated_times ? into_u8(get_label(pos, ltEstimatedTime)) : ""; });
imgui_ctrl.set_extra_draw_cb([this](const ImRect& draw_rc) {return draw_ticks(draw_rc); });
if (e_mode == MultiExtruder) {
// #ys_FIXME: get tool ordering from _correct_ place
const ToolOrdering& tool_ordering = GUI::wxGetApp().plater()->fff_print().get_tool_ordering();
m_ticks.set_pause_print_msg(_u8L("Place bearings in slots and resume printing"));
m_ticks.set_extruder_colors(&m_extruder_colors);
if (tool_ordering.empty())
return {};
std::set<int> used_extruders;
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), print_z, [](const LayerTools& lhs, double rhs) { return lhs.print_z < rhs; });
for (; it_layer_tools != tool_ordering.end(); ++it_layer_tools) {
const std::vector<unsigned>& extruders = it_layer_tools->extruders;
for (const auto& extruder : extruders)
used_extruders.emplace(extruder + 1);
}
return used_extruders;
}
const int default_initial_extruder = e_mode == MultiAsSingle ? std::max(only_extruder, 1) : 1;
if (ticks.empty() || e_mode == SingleExtruder)
return { default_initial_extruder };
std::set<int> used_extruders;
auto it_start = ticks.lower_bound(TickCode{ tick });
auto it = it_start;
if (it == ticks.begin() && it->type == ToolChange &&
tick != it->tick) // In case of switch of ToolChange to ColorChange, when tick exists,
// we shouldn't change color for extruder, which will be deleted
{
used_extruders.emplace(it->extruder);
if (tick < it->tick)
used_extruders.emplace(default_initial_extruder);
}
while (it != ticks.begin()) {
--it;
if (it->type == ToolChange && tick != it->tick) {
used_extruders.emplace(it->extruder);
break;
}
}
if (it == ticks.begin() && used_extruders.empty())
used_extruders.emplace(default_initial_extruder);
for (it = it_start; it != ticks.end(); ++it)
if (it->type == ToolChange && tick != it->tick)
used_extruders.emplace(it->extruder);
return used_extruders;
}
std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder)

View File

@ -2,8 +2,8 @@
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_GUI_DoubleSlider_hpp_
#define slic3r_GUI_DoubleSlider_hpp_
#ifndef slic3r_GUI_DoubleSliderForLayers_hpp_
#define slic3r_GUI_DoubleSliderForLayers_hpp_
#include "libslic3r/CustomGCode.hpp"
#include "ImGuiDoubleSlider.hpp"
@ -23,11 +23,6 @@ namespace DoubleSlider {
using namespace GUI;
/* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values.
* So, let use same value as a permissible error for layer height.
*/
constexpr double epsilon() { return 0.0011; }
// return true when areas are mostly equivalent
bool equivalent_areas(const double& bottom_area, const double& top_area);
@ -60,20 +55,6 @@ enum ConflictType
ctRedundant
};
enum MouseAction
{
maNone,
maAddMenu, // show "Add" context menu for NOTexist active tick
maEditMenu, // show "Edit" context menu for exist active tick
maCogIconMenu, // show context for "cog" icon
maForceColorEdit, // force color editing from colored band
maAddTick, // force tick adding
maDeleteTick, // force tick deleting
maCogIconClick, // LeftMouseClick on "cog" icon
maOneLayerIconClick, // LeftMouseClick on "one_layer" icon
maRevertIconClick, // LeftMouseClick on "revert" icon
};
enum DrawMode
{
dmRegular,
@ -192,148 +173,17 @@ struct ExtrudersSequence
}
};
template<typename ValType>
class DSManager_t
class DSForLayers : public Manager<double>
{
public:
void Init( int lowerValue,
DSForLayers() : Manager<double>() {}
DSForLayers(int lowerValue,
int higherValue,
int minValue,
int maxValue,
const std::string& name,
bool is_horizontal)
{
imgui_ctrl = ImGuiControl( lowerValue, higherValue,
minValue, maxValue,
is_horizontal ? 0 : ImGuiSliderFlags_Vertical,
name, !is_horizontal);
imgui_ctrl.set_get_label_cb([this](int pos) {return get_label(pos); });
};
DSManager_t() {}
DSManager_t(int lowerValue,
int higherValue,
int minValue,
int maxValue,
const std::string& name,
bool is_horizontal)
{
Init (lowerValue, higherValue, minValue, maxValue, name, is_horizontal);
}
~DSManager_t() {}
int GetMinValue() const { return imgui_ctrl.GetMinValue(); }
int GetMaxValue() const { return imgui_ctrl.GetMaxValue(); }
int GetLowerValue() const { return imgui_ctrl.GetLowerValue(); }
int GetHigherValue()const { return imgui_ctrl.GetHigherValue(); }
ValType GetMinValueD() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetMinValue()]; }
ValType GetMaxValueD() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetMaxValue()]; }
ValType GetLowerValueD() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetLowerValue()];}
ValType GetHigherValueD() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetHigherValue()]; }
// Set low and high slider position. If the span is non-empty, disable the "one layer" mode.
void SetLowerValue(const int lower_val) {
imgui_ctrl.SetLowerValue(lower_val);
process_thumb_move();
}
void SetHigherValue(const int higher_val) {
imgui_ctrl.SetHigherValue(higher_val);
process_thumb_move();
}
void SetSelectionSpan(const int lower_val, const int higher_val) {
imgui_ctrl.SetSelectionSpan(lower_val, higher_val);
process_thumb_move();
}
void SetMaxValue(const int max_value) {
imgui_ctrl.SetMaxValue(max_value);
process_thumb_move();
}
void SetSliderValues(const std::vector<ValType>& values) { m_values = values; }
// values used to show thumb labels
void SetSliderAlternateValues(const std::vector<ValType>& values) { m_alternate_values = values; }
bool is_lower_at_min() const { return imgui_ctrl.is_lower_at_min(); }
bool is_higher_at_max() const { return imgui_ctrl.is_higher_at_max(); }
void Show(bool show = true) { imgui_ctrl.Show(show); }
void Hide() { Show(false); }
virtual void imgui_render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) = 0;
void set_callback_on_thumb_move(std::function<void()> cb) { m_cb_thumb_move = cb; };
void move_current_thumb(const int delta)
{
imgui_ctrl.MoveActiveThumb(delta);
process_thumb_move();
}
protected:
std::vector<ValType> m_values;
std::vector<ValType> m_alternate_values;
GUI::ImGuiControl imgui_ctrl;
float m_scale{ 1.f };
std::string get_label(int pos) const {
if (m_values.empty())
return GUI::format("%1%", pos);
if (pos >= m_values.size())
return "ErrVal";
return GUI::format("%1%", static_cast<ValType>(m_alternate_values.empty() ? m_values[pos] : m_alternate_values[pos]));
}
void process_thumb_move() {
if (m_cb_thumb_move)
m_cb_thumb_move();
}
private:
std::function<void()> m_cb_thumb_move{ nullptr };
};
class DSManagerForGcode : public DSManager_t<unsigned int>
{
public:
DSManagerForGcode() : DSManager_t<unsigned int>() {}
DSManagerForGcode( int lowerValue,
int higherValue,
int minValue,
int maxValue)
{
Init(lowerValue, higherValue, minValue, maxValue, "moves_slider", true);
}
~DSManagerForGcode() {}
void imgui_render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override;
void set_render_as_disabled(bool value) { m_render_as_disabled = value; }
bool is_rendering_as_disabled() const { return m_render_as_disabled; }
private:
bool m_render_as_disabled{ false };
};
class DSManagerForLayers : public DSManager_t<double>
{
public:
DSManagerForLayers() : DSManager_t<double>() {}
DSManagerForLayers( int lowerValue,
int higherValue,
int minValue,
int maxValue,
bool allow_editing = true);
~DSManagerForLayers() {}
bool allow_editing);
~DSForLayers() {}
void ChangeOneLayerLock();
@ -349,35 +199,38 @@ public:
void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder);
void SetExtruderColors(const std::vector<std::string>& extruder_colors);
void UseDefaultColors(bool def_colors_on);
void add_code_as_tick(Type type, int selected_extruder = -1);
// add default action for tick, when press "+"
void add_current_tick(bool call_from_keyboard = false);
// delete current tick, when press "-"
void delete_current_tick();
void edit_tick(int tick = -1);
void discard_all_thicks();
void edit_extruder_sequence();
void enable_action_icon(bool enable) { m_enable_action_icon = enable; }
void show_cog_icon_context_menu();
void auto_color_change();
void jump_to_value();
void set_callback_on_ticks_changed(std::function<void()> cb) { m_cb_ticks_changed = cb; };
void imgui_render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override;
void UseDefaultColors(bool def_colors_on);
bool IsNewPrint(const std::string& print_obj_idxs);
void Render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override;
void set_callback_on_ticks_changed(std::function<void()> cb) { m_cb_ticks_changed = cb; };
// manipulation with slider from keyboard
// add default action for tick, when press "+"
void add_current_tick();
// delete current tick, when press "-"
void delete_current_tick();
// process adding of auto color change
void auto_color_change();
// jump to selected layer
void jump_to_value();
private:
void add_code_as_tick(Type type, int selected_extruder = -1);
void edit_tick(int tick = -1);
void discard_all_thicks();
void edit_extruder_sequence();
void show_cog_icon_context_menu();
bool is_wipe_tower_layer(int tick) const;
std::string get_label(int tick, LabelType label_type = ltHeightWithLayer) const;
std::string get_label(int tick, LabelType label_type = ltHeightWithLayer) const;
int get_tick_from_value(double value, bool force_lower_bound = false);
wxString get_tooltip(int tick = -1);
std::string get_tooltip(int tick = -1);
std::string get_color_for_tool_change_tick(std::set<TickCode>::const_iterator it) const;
std::string get_color_for_color_change_tick(std::set<TickCode>::const_iterator it) const;
@ -393,48 +246,44 @@ private:
// Use those values to disable selection of active extruders
std::array<int, 2> get_active_extruders_for_tick(int tick) const;
void post_ticks_changed_event(Type type = Custom);
bool check_ticks_changed_event(Type type);
void append_change_extruder_menu_item(wxMenu*, bool switch_current_code = false);
void append_add_color_change_menu_item(wxMenu*, bool switch_current_code = false);
void append_change_extruder_menu_item(wxMenu*, bool switch_current_code = false); // ysFIXME !
void append_add_color_change_menu_item(wxMenu*, bool switch_current_code = false); // ysFIXME !
bool is_osx{ false };
bool m_allow_editing{ true };
bool is_osx { false };
bool m_allow_editing { true };
bool m_is_wipe_tower { false }; //This flag indicates that there is multiple extruder print with wipe tower
bool m_show_estimated_times { false };
bool m_force_mode_apply = true;
bool m_enable_action_icon = true;
bool m_is_wipe_tower = false; //This flag indicates that there is multiple extruder print with wipe tower
DrawMode m_draw_mode { dmRegular };
Mode m_mode { SingleExtruder };
FocusedItem m_focus { fiNone };
DrawMode m_draw_mode { dmRegular };
Mode m_mode = SingleExtruder;
int m_only_extruder = -1;
MouseAction m_mouse = maNone;
FocusedItem m_focus = fiNone;
bool m_show_estimated_times{ false };
TickCodeInfo m_ticks;
std::vector<double> m_layers_times;
std::vector<double> m_layers_values;
std::vector<std::string> m_extruder_colors;
ExtrudersSequence m_extruders_sequence;
std::function<void()> m_cb_ticks_changed{ nullptr };
int m_only_extruder { -1 };
std::string m_print_obj_idxs;
// ImGuiDS
std::vector<double> m_layers_times;
std::vector<double> m_layers_values;
std::vector<std::string> m_extruder_colors;
TickCodeInfo m_ticks;
ExtrudersSequence m_extruders_sequence;
std::function<void()> m_cb_ticks_changed{ nullptr };
bool m_can_change_color{ true };
// functions for extend rendering of m_ctrl
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
void draw_ticks(const ImRect& slideable_region);
void render_menu();
bool render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick = -1);
void update_callbacks();
void update_draw_scroll_line_cb();
};
} // DoubleSlider;
@ -443,4 +292,4 @@ private:
#endif // slic3r_GUI_DoubleSlider_hpp_
#endif // slic3r_GUI_DoubleSliderForLayers_hpp_

View File

@ -6,7 +6,7 @@
#define slic3r_GUI_ExtruderSequenceDialog_hpp_
#include "GUI_Utils.hpp"
#include "DoubleSlider.hpp"
#include "DoubleSliderForLayers.hpp"
#include "wxExtensions.hpp"
class wxTextCtrl;

View File

@ -14,6 +14,7 @@
#include "libslic3r/Utils.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/CustomGCode.hpp"
#include "slic3r/GUI/format.hpp"
@ -24,7 +25,6 @@
#include "I18N.hpp"
#include "GUI_Utils.hpp"
#include "GUI.hpp"
#include "DoubleSlider.hpp"
#include "GLCanvas3D.hpp"
#include "GLToolbar.hpp"
#include "GUI_Preview.hpp"
@ -2120,12 +2120,12 @@ void GCodeViewer::render_legend(float& legend_height)
if (extruder_id + 1 != static_cast<unsigned char>(item.extruder))
continue;
if (item.type != ColorChange)
if (item.type != CustomGCode::ColorChange)
continue;
const std::vector<float> zs = m_viewer.get_layers_zs();
auto lower_b = std::lower_bound(zs.begin(), zs.end(),
static_cast<float>(item.print_z - Slic3r::DoubleSlider::epsilon()));
static_cast<float>(item.print_z - Slic3r::CustomGCode::epsilon()));
if (lower_b == zs.end())
continue;

View File

@ -19,7 +19,8 @@
#include "OpenGLManager.hpp"
#include "GLCanvas3D.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "DoubleSlider.hpp"
#include "DoubleSliderForGcode.hpp"
#include "DoubleSliderForLayers.hpp"
#include "Plater.hpp"
#include "MainFrame.hpp"
#include "format.hpp"
@ -197,8 +198,8 @@ Preview::Preview(
void Preview::set_layers_slider_values_range(int bottom, int top)
{
m_layers_slider->SetHigherValue(std::min(top, m_layers_slider->GetMaxValue()));
m_layers_slider->SetLowerValue(std::max(bottom, m_layers_slider->GetMinValue()));
m_layers_slider->SetHigherPos(std::min(top, m_layers_slider->GetMaxPos()));
m_layers_slider->SetLowerPos(std::max(bottom, m_layers_slider->GetMinPos()));
}
bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
@ -314,6 +315,8 @@ void Preview::reload_print()
void Preview::msw_rescale()
{
m_layers_slider->SetEmUnit(wxGetApp().em_unit());
m_moves_slider->SetEmUnit(wxGetApp().em_unit());
// rescale warning legend on the canvas
get_canvas3d()->msw_rescale();
@ -328,9 +331,9 @@ void Preview::render_sliders(GLCanvas3D& canvas, float extra_scale/* = 0.1f*/)
const int canvas_height = cnv_size.get_height();
if (m_layers_slider)
m_layers_slider->imgui_render(canvas_width, canvas_height, extra_scale);
m_layers_slider->Render(canvas_width, canvas_height, extra_scale);
if (m_moves_slider)
m_moves_slider->imgui_render(canvas_width, canvas_height, extra_scale);
m_moves_slider->Render(canvas_width, canvas_height, extra_scale);
}
void Preview::bind_event_handlers()
@ -358,13 +361,12 @@ void Preview::create_sliders()
{
// Layers Slider
m_layers_slider = new DoubleSlider::DSManagerForLayers(0, 0, 0, 100, wxGetApp().is_editor());
m_layers_slider = new DoubleSlider::DSForLayers(0, 0, 0, 100, wxGetApp().is_editor());
m_layers_slider->SetEmUnit(wxGetApp().em_unit());
m_layers_slider->SetDrawMode(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA,
wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects"));
m_layers_slider->enable_action_icon(wxGetApp().is_editor());
m_layers_slider->set_callback_on_thumb_move( [this]() -> void { Preview::on_layers_slider_scroll_changed(); } );
m_layers_slider->set_callback_on_ticks_changed( [this]() -> void {
@ -378,7 +380,8 @@ void Preview::create_sliders()
// Move Gcode Slider
m_moves_slider = new DoubleSlider::DSManagerForGcode(0, 0, 0, 100);
m_moves_slider = new DoubleSlider::DSForGcode(0, 0, 0, 100);
m_moves_slider->SetEmUnit(wxGetApp().em_unit());
m_moves_slider->set_callback_on_thumb_move([this]() ->void { Preview::on_moves_slider_scroll_changed(); });
@ -423,7 +426,7 @@ void Preview::check_layers_slider_values(std::vector<CustomGCode::Item>& ticks_f
ticks_from_model.erase(std::remove_if(ticks_from_model.begin(), ticks_from_model.end(),
[layers_z](CustomGCode::Item val)
{
auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val.print_z - DoubleSlider::epsilon());
auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val.print_z - CustomGCode::epsilon());
return it == layers_z.end();
}),
ticks_from_model.end());
@ -434,17 +437,17 @@ void Preview::check_layers_slider_values(std::vector<CustomGCode::Item>& ticks_f
void Preview::update_layers_slider(const std::vector<double>& layers_z, bool keep_z_range)
{
// Save the initial slider span.
double z_low = m_layers_slider->GetLowerValueD();
double z_high = m_layers_slider->GetHigherValueD();
bool was_empty = m_layers_slider->GetMaxValue() == 0;
double z_low = m_layers_slider->GetLowerValue();
double z_high = m_layers_slider->GetHigherValue();
bool was_empty = m_layers_slider->GetMaxPos() == 0;
bool force_sliders_full_range = was_empty;
if (!keep_z_range) {
bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_layers_slider->GetMaxValueD()) > DoubleSlider::epsilon()/*1e-6*/;
bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_layers_slider->GetMaxValue()) > CustomGCode::epsilon()/*1e-6*/;
force_sliders_full_range |= span_changed;
}
bool snap_to_min = force_sliders_full_range || m_layers_slider->is_lower_at_min();
bool snap_to_max = force_sliders_full_range || m_layers_slider->is_higher_at_max();
bool snap_to_min = force_sliders_full_range || m_layers_slider->IsLowerAtMin();
bool snap_to_max = force_sliders_full_range || m_layers_slider->IsHigherAtMax();
// Detect and set manipulation mode for double slider
update_layers_slider_mode();
@ -462,19 +465,19 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
//first of all update extruder colors to avoid crash, when we are switching printer preset from MM to SM
m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result));
m_layers_slider->SetSliderValues(layers_z);
assert(m_layers_slider->GetMinValue() == 0);
m_layers_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1);
assert(m_layers_slider->GetMinPos() == 0);
m_layers_slider->SetMaxPos(layers_z.empty() ? 0 : layers_z.size() - 1);
int idx_low = 0;
int idx_high = m_layers_slider->GetMaxValue();
int idx_high = m_layers_slider->GetMaxPos();
if (!layers_z.empty()) {
if (!snap_to_min) {
int idx_new = find_close_layer_idx(layers_z, z_low, DoubleSlider::epsilon()/*1e-6*/);
int idx_new = find_close_layer_idx(layers_z, z_low, CustomGCode::epsilon()/*1e-6*/);
if (idx_new != -1)
idx_low = idx_new;
}
if (!snap_to_max) {
int idx_new = find_close_layer_idx(layers_z, z_high, DoubleSlider::epsilon()/*1e-6*/);
int idx_new = find_close_layer_idx(layers_z, z_high, CustomGCode::epsilon()/*1e-6*/);
if (idx_new != -1)
idx_high = idx_new;
}
@ -625,17 +628,19 @@ void Preview::update_layers_slider_mode()
void Preview::reset_layers_slider()
{
m_layers_slider->SetHigherValue(0);
m_layers_slider->SetLowerValue(0);
m_layers_slider->SetHigherPos(0);
m_layers_slider->SetLowerPos(0);
}
void Preview::update_sliders_from_canvas(wxKeyEvent& event)
{
const auto key = event.GetKeyCode();
if (key == WXK_NUMPAD_ADD || key == '+')
m_layers_slider->add_current_tick(true);
else if (key == WXK_NUMPAD_SUBTRACT || key == WXK_DELETE || key == WXK_BACK || key == '-')
const bool can_edit = wxGetApp().is_editor();
if (can_edit && (key == WXK_NUMPAD_ADD || key == '+'))
m_layers_slider->add_current_tick();
else if (can_edit && (key == WXK_NUMPAD_SUBTRACT || key == WXK_DELETE || key == WXK_BACK || key == '-'))
m_layers_slider->delete_current_tick();
else if (key == 'G' || key == 'g')
m_layers_slider->jump_to_value();
@ -662,12 +667,12 @@ void Preview::update_sliders_from_canvas(wxKeyEvent& event)
}
else if (key == 'S' || key == 'W') {
const int new_pos = key == 'W' ? m_layers_slider->GetHigherValue() + 1 : m_layers_slider->GetHigherValue() - 1;
m_layers_slider->SetHigherValue(new_pos);
const int new_pos = key == 'W' ? m_layers_slider->GetHigherPos() + 1 : m_layers_slider->GetHigherPos() - 1;
m_layers_slider->SetHigherPos(new_pos);
}
else if (key == 'A' || key == 'D') {
const int new_pos = key == 'D' ? m_moves_slider->GetHigherValue() + 1 : m_moves_slider->GetHigherValue() - 1;
m_moves_slider->SetHigherValue(new_pos);
const int new_pos = key == 'D' ? m_moves_slider->GetHigherPos() + 1 : m_moves_slider->GetHigherPos() - 1;
m_moves_slider->SetHigherPos(new_pos);
}
else if (key == 'X')
m_layers_slider->ChangeOneLayerLock();
@ -726,8 +731,10 @@ void Preview::update_moves_slider(std::optional<int> visible_range_min, std::opt
m_moves_slider->SetSliderValues(values);
m_moves_slider->SetSliderAlternateValues(alternate_values);
m_moves_slider->SetMaxValue(static_cast<int>(values.size()) - 1);
m_moves_slider->SetMaxPos(static_cast<int>(values.size()) - 1);
m_moves_slider->SetSelectionSpan(span_min_id, span_max_id);
m_moves_slider->ShowLowerThumb(get_app_config()->get("seq_top_layer_only") == "0");
}
void Preview::enable_moves_slider(bool enable)
@ -888,13 +895,13 @@ void Preview::on_layers_slider_scroll_changed()
if (IsShown()) {
PrinterTechnology tech = m_process->current_printer_technology();
if (tech == ptFFF) {
m_canvas->set_volumes_z_range({ m_layers_slider->GetLowerValueD(), m_layers_slider->GetHigherValueD() });
m_canvas->set_toolpaths_z_range({ static_cast<unsigned int>(m_layers_slider->GetLowerValue()), static_cast<unsigned int>(m_layers_slider->GetHigherValue()) });
m_canvas->set_volumes_z_range({ m_layers_slider->GetLowerValue(), m_layers_slider->GetHigherValue() });
m_canvas->set_toolpaths_z_range({ static_cast<unsigned int>(m_layers_slider->GetLowerPos()), static_cast<unsigned int>(m_layers_slider->GetHigherPos()) });
m_canvas->set_as_dirty();
}
else if (tech == ptSLA) {
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValueD()));
m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValueD()));
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValue()));
m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValue()));
m_canvas->render();
}
}
@ -902,7 +909,7 @@ void Preview::on_layers_slider_scroll_changed()
void Preview::on_moves_slider_scroll_changed()
{
m_canvas->update_gcode_sequential_view_current(static_cast<unsigned int>(m_moves_slider->GetLowerValueD() - 1.0), static_cast<unsigned int>(m_moves_slider->GetHigherValueD() - 1.0));
m_canvas->update_gcode_sequential_view_current(static_cast<unsigned int>(m_moves_slider->GetLowerValue() - 1), static_cast<unsigned int>(m_moves_slider->GetHigherValue() - 1));
m_canvas->set_as_dirty();
m_canvas->request_extra_frame();
}

View File

@ -28,8 +28,8 @@ class BackgroundSlicingProcess;
class Model;
namespace DoubleSlider {
class DSManagerForGcode;
class DSManagerForLayers;
class DSForGcode;
class DSForLayers;
};
namespace GUI {
@ -96,8 +96,8 @@ class Preview : public wxPanel
bool m_loaded { false };
DoubleSlider::DSManagerForLayers* m_layers_slider{ nullptr };
DoubleSlider::DSManagerForGcode* m_moves_slider { nullptr };
DoubleSlider::DSForLayers* m_layers_slider{ nullptr };
DoubleSlider::DSForGcode* m_moves_slider { nullptr };
public:
enum class OptionType : unsigned int

View File

@ -6,7 +6,9 @@
#include "ImGuiDoubleSlider.hpp"
namespace Slic3r {
namespace GUI {
namespace DoubleSlider {
using namespace GUI;
const ImU32 tooltip_bg_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_GREY_LIGHT);
const ImU32 thumb_bg_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_ORANGE_LIGHT);
@ -125,46 +127,47 @@ ImGuiControl::ImGuiControl( int lowerValue,
bool use_lower_thumb) :
m_selection(ssUndef),
m_name(name),
m_lower_value(lowerValue),
m_higher_value (higherValue),
m_min_value(minValue),
m_max_value(maxValue),
m_lower_pos(lowerValue),
m_higher_pos (higherValue),
m_min_pos(minValue),
m_max_pos(maxValue),
m_flags(flags),
m_draw_lower_thumb(use_lower_thumb)
{
}
int ImGuiControl::GetActiveValue() const
int ImGuiControl::GetActivePos() const
{
return m_selection == ssLower ? m_lower_value :
m_selection == ssHigher ? m_higher_value : -1;
return m_selection == ssLower ? m_lower_pos :
m_selection == ssHigher ? m_higher_pos : -1;
}
void ImGuiControl::SetLowerValue(const int lower_val)
void ImGuiControl::SetLowerPos(const int lower_pos)
{
m_selection = ssLower;
m_lower_value = lower_val;
correct_lower_value();
m_lower_pos = lower_pos;
correct_lower_pos();
}
void ImGuiControl::SetHigherValue(const int higher_val)
void ImGuiControl::SetHigherPos(const int higher_pos)
{
m_selection = ssHigher;
m_higher_value = higher_val;
correct_higher_value();
m_higher_pos = higher_pos;
correct_higher_pos();
}
void ImGuiControl::SetSelectionSpan(const int lower_val, const int higher_val)
void ImGuiControl::SetSelectionSpan(const int lower_pos, const int higher_pos)
{
m_lower_value = std::max(lower_val, m_min_value);
m_higher_value = std::max(std::min(higher_val, m_max_value), m_lower_value);
if (m_lower_value < m_higher_value)
m_lower_pos = std::max(lower_pos, m_min_pos);
m_higher_pos = std::max(std::min(higher_pos, m_max_pos), m_lower_pos);
if (m_lower_pos < m_higher_pos)
m_combine_thumbs = false;
}
void ImGuiControl::SetMaxValue(const int max_value)
void ImGuiControl::SetMaxPos(const int max_pos)
{
m_max_value = max_value;
m_max_pos = max_pos;
correct_higher_pos();
}
void ImGuiControl::MoveActiveThumb(int delta)
@ -173,36 +176,36 @@ void ImGuiControl::MoveActiveThumb(int delta)
m_selection = ssHigher;
if (m_selection == ssLower) {
m_lower_value -= delta;
correct_lower_value();
m_lower_pos -= delta;
correct_lower_pos();
}
else if (m_selection == ssHigher) {
m_higher_value -= delta;
correct_higher_value();
m_higher_pos -= delta;
correct_higher_pos();
}
}
void ImGuiControl::correct_lower_value()
void ImGuiControl::correct_lower_pos()
{
if (m_lower_value < m_min_value)
m_lower_value = m_min_value;
else if (m_lower_value > m_max_value)
m_lower_value = m_max_value;
if (m_lower_pos < m_min_pos)
m_lower_pos = m_min_pos;
else if (m_lower_pos > m_max_pos)
m_lower_pos = m_max_pos;
if ((m_lower_value >= m_higher_value && m_lower_value <= m_max_value) || m_combine_thumbs) {
m_higher_value = m_lower_value;
if ((m_lower_pos >= m_higher_pos && m_lower_pos <= m_max_pos) || m_combine_thumbs) {
m_higher_pos = m_lower_pos;
}
}
void ImGuiControl::correct_higher_value()
void ImGuiControl::correct_higher_pos()
{
if (m_higher_value > m_max_value)
m_higher_value = m_max_value;
else if (m_higher_value < m_min_value)
m_higher_value = m_min_value;
if (m_higher_pos > m_max_pos)
m_higher_pos = m_max_pos;
else if (m_higher_pos < m_min_pos)
m_higher_pos = m_min_pos;
if ((m_higher_value <= m_lower_value && m_higher_value >= m_min_value) || m_combine_thumbs) {
m_lower_value = m_higher_value;
if ((m_higher_pos <= m_lower_pos && m_higher_pos >= m_min_pos) || m_combine_thumbs) {
m_lower_pos = m_higher_pos;
}
}
@ -211,17 +214,17 @@ void ImGuiControl::CombineThumbs(bool combine)
m_combine_thumbs = combine;
if (combine) {
m_selection = ssHigher;
correct_higher_value();
correct_higher_pos();
}
else
ResetValues();
ResetPositions();
}
void ImGuiControl::ResetValues()
void ImGuiControl::ResetPositions()
{
SetLowerValue(m_min_value);
SetHigherValue(m_max_value);
m_selection == ssLower ? correct_lower_value() : correct_higher_value();
SetLowerPos(m_min_pos);
SetHigherPos(m_max_pos);
m_selection == ssLower ? correct_lower_pos() : correct_higher_pos();
}
std::string ImGuiControl::get_label(int pos) const
@ -229,18 +232,18 @@ std::string ImGuiControl::get_label(int pos) const
if (m_cb_get_label)
return m_cb_get_label(pos);
if (pos >= m_max_value || pos < m_min_value)
if (pos >= m_max_pos || pos < m_min_pos)
return "ErrVal";
return std::to_string(pos);
}
float ImGuiControl::GetPositionFromValue(int value, const ImRect& rect) const
float ImGuiControl::GetPositionInRect(int pos, const ImRect& rect) const
{
int v_min = m_min_value;
int v_max = m_max_value;
int v_min = m_min_pos;
int v_max = m_max_pos;
float pos_ratio = (v_max - v_min) != 0 ? ((float)(value - v_min) / (float)(v_max - v_min)) : 0.0f;
float pos_ratio = (v_max - v_min) != 0 ? ((float)(pos - v_min) / (float)(v_max - v_min)) : 0.0f;
float thumb_pos;
if (is_horizontal()) {
thumb_pos = rect.Min.x + (rect.Max.x - rect.Min.x) * pos_ratio;
@ -324,7 +327,7 @@ void ImGuiControl::draw_thumb(const ImVec2& center, bool mark/* = false*/)
}
}
void ImGuiControl::apply_regions(int higher_value, int lower_value, const ImRect& draggable_region)
void ImGuiControl::apply_regions(int higher_pos, int lower_pos, const ImRect& draggable_region)
{
ImVec2 mid = draggable_region.GetCenter();
float thumb_radius = m_draw_opts.thumb_radius();
@ -338,18 +341,18 @@ void ImGuiControl::apply_regions(int higher_value, int lower_value, const ImRect
ImRect(draggable_region.Min + ImVec2(0, thumb_radius), draggable_region.Max);
// initialize the thumbs.
float higher_thumb_pos = GetPositionFromValue(higher_value, m_regions.higher_slideable_region);
float higher_thumb_pos = GetPositionInRect(higher_pos, m_regions.higher_slideable_region);
m_regions.higher_thumb = is_horizontal() ?
ImRect(higher_thumb_pos - thumb_radius, mid.y - thumb_radius, higher_thumb_pos + thumb_radius, mid.y + thumb_radius) :
ImRect(mid.x - thumb_radius, higher_thumb_pos - thumb_radius, mid.x + thumb_radius, higher_thumb_pos + thumb_radius);
float lower_thumb_pos = GetPositionFromValue(lower_value, m_regions.lower_slideable_region);
float lower_thumb_pos = GetPositionInRect(lower_pos, m_regions.lower_slideable_region);
m_regions.lower_thumb = is_horizontal() ?
ImRect(lower_thumb_pos - thumb_radius, mid.y - thumb_radius, lower_thumb_pos + thumb_radius, mid.y + thumb_radius) :
ImRect(mid.x - thumb_radius, lower_thumb_pos - thumb_radius, mid.x + thumb_radius, lower_thumb_pos + thumb_radius);
}
void ImGuiControl::check_and_correct_thumbs(int* higher_value, int* lower_value)
void ImGuiControl::check_and_correct_thumbs(int* higher_pos, int* lower_pos)
{
if (!m_draw_lower_thumb || m_combine_thumbs)
return;
@ -366,12 +369,12 @@ void ImGuiControl::check_and_correct_thumbs(int* higher_value, int* lower_value)
if (m_selection == ssHigher) {
m_regions.lower_thumb = m_regions.higher_thumb;
m_regions.higher_thumb.TranslateX(thumb_radius);
*lower_value = *higher_value;
*lower_pos = *higher_pos;
}
else {
m_regions.higher_thumb = m_regions.lower_thumb;
m_regions.lower_thumb.TranslateX(-thumb_radius);
*higher_value = *lower_value;
*higher_pos = *lower_pos;
}
}
}
@ -380,18 +383,18 @@ void ImGuiControl::check_and_correct_thumbs(int* higher_value, int* lower_value)
if (m_selection == ssHigher) {
m_regions.lower_thumb = m_regions.higher_thumb;
m_regions.lower_thumb.TranslateY(thumb_radius);
*lower_value = *higher_value;
*lower_pos = *higher_pos;
}
else {
m_regions.higher_thumb = m_regions.lower_thumb;
m_regions.lower_thumb.TranslateY(-thumb_radius);
*higher_value = *lower_value;
*higher_pos = *lower_pos;
}
}
}
}
bool ImGuiControl::draw_slider( int* higher_value, int* lower_value,
bool ImGuiControl::draw_slider( int* higher_pos, int* lower_pos,
std::string& higher_label, std::string& lower_label,
const ImVec2& pos, const ImVec2& size, float scale)
{
@ -418,7 +421,7 @@ bool ImGuiControl::draw_slider( int* higher_value, int* lower_value,
}
// set slideable regions and thumbs.
apply_regions(*higher_value, *lower_value, draggable_region);
apply_regions(*higher_pos, *lower_pos, draggable_region);
// select and mark higher thumb by default
if (m_selection == ssUndef)
@ -433,28 +436,28 @@ bool ImGuiControl::draw_slider( int* higher_value, int* lower_value,
ImGui::ItemHoverable(m_regions.lower_thumb, id) && context.IO.MouseClicked[0])
m_selection = ssLower;
// update thumb position and value
bool value_changed = false;
// update thumb position
bool pos_changed = false;
if (m_selection == ssHigher) {
value_changed = behavior(id, m_regions.higher_slideable_region, m_min_value, m_max_value,
higher_value, &m_regions.higher_thumb, m_flags);
pos_changed = behavior(id, m_regions.higher_slideable_region, m_min_pos, m_max_pos,
higher_pos, &m_regions.higher_thumb, m_flags);
}
else if (m_draw_lower_thumb && !m_combine_thumbs) {
value_changed = behavior(id, m_regions.lower_slideable_region, m_min_value, m_max_value,
lower_value, &m_regions.lower_thumb, m_flags);
pos_changed = behavior(id, m_regions.lower_slideable_region, m_min_pos, m_max_pos,
lower_pos, &m_regions.lower_thumb, m_flags);
}
// check thumbs values and correct them if needed
check_and_correct_thumbs(higher_value, lower_value);
// check thumbs poss and correct them if needed
check_and_correct_thumbs(higher_pos, lower_pos);
const ImRect& slideable_region = m_selection == ssHigher ? m_regions.higher_slideable_region : m_regions.lower_slideable_region;
const ImRect& active_thumb = m_selection == ssHigher ? m_regions.higher_thumb : m_regions.lower_thumb;
bool show_move_label = false;
ImRect mouse_pos_rc = active_thumb;
if (!value_changed && ImGui::ItemHoverable(item_size, id) && !ImGui::IsMouseDragging(0)) {
behavior(id, slideable_region, m_min_value, m_max_value,
&m_mouse_pos_value, &mouse_pos_rc, m_flags, true);
if (!pos_changed && ImGui::ItemHoverable(item_size, id) && !ImGui::IsMouseDragging(0)) {
behavior(id, slideable_region, m_min_pos, m_max_pos,
&m_mouse_pos, &mouse_pos_rc, m_flags, true);
show_move_label = true;
}
@ -491,9 +494,9 @@ bool ImGuiControl::draw_slider( int* higher_value, int* lower_value,
// draw label on mouse move
if (show_move_label)
draw_label(get_label_on_move(m_mouse_pos_value), mouse_pos_rc);
draw_label(get_label_on_move(m_mouse_pos), mouse_pos_rc);
return value_changed;
return pos_changed;
}
bool ImGuiControl::render()
@ -519,21 +522,21 @@ bool ImGuiControl::render()
float scale = 1.f;
int higher_value = m_higher_value;
int lower_value = m_lower_value;
std::string higher_label = get_label(m_higher_value);
std::string lower_label = get_label(m_lower_value);
int temp_higher_value = m_higher_value;
int temp_lower_value = m_lower_value;
int higher_pos = m_higher_pos;
int lower_pos = m_lower_pos;
std::string higher_label = get_label(m_higher_pos);
std::string lower_label = get_label(m_lower_pos);
int temp_higher_pos = m_higher_pos;
int temp_lower_pos = m_lower_pos;
if (draw_slider(&higher_value, &lower_value, higher_label, lower_label, m_pos, m_size, scale)) {
if (temp_higher_value != higher_value) {
m_higher_value = higher_value;
if (draw_slider(&higher_pos, &lower_pos, higher_label, lower_label, m_pos, m_size, scale)) {
if (temp_higher_pos != higher_pos) {
m_higher_pos = higher_pos;
if (m_combine_thumbs)
m_lower_value = m_higher_value;
m_lower_pos = m_higher_pos;
}
if (temp_lower_value != lower_value)
m_lower_value = lower_value;
if (temp_lower_pos != lower_pos)
m_lower_pos = lower_pos;
result = true;
}

View File

@ -24,7 +24,7 @@ std::string to_string_with_precision(const T a_value, const int n = 2)
}
namespace Slic3r {
namespace GUI {
namespace DoubleSlider {
enum SelectedSlider {
ssUndef,
@ -45,25 +45,24 @@ public:
ImGuiControl() {}
~ImGuiControl() {}
int GetMinValue() const { return m_min_value; }
int GetMaxValue() const { return m_max_value; }
int GetLowerValue() const { return m_lower_value; }
int GetHigherValue() const { return m_higher_value; }
int GetActiveValue() const;
float GetPositionFromValue(int value, const ImRect& rect) const;
int GetMinPos() const { return m_min_pos; }
int GetMaxPos() const { return m_max_pos; }
int GetLowerPos() const { return m_lower_pos; }
int GetHigherPos() const { return m_higher_pos; }
int GetActivePos() const;
// Set low and high slider position. If the span is non-empty, disable the "one layer" mode.
void SetLowerValue (const int lower_val);
void SetHigherValue(const int higher_val);
void SetSelectionSpan(const int lower_val, const int higher_val);
void SetLowerPos (const int lower_pos);
void SetHigherPos(const int higher_pos);
void SetSelectionSpan(const int lower_pos, const int higher_pos);
void SetMaxValue(const int max_value);
void SetMaxPos(const int max_pos);
void CombineThumbs(bool combine);
void ResetValues();
void ResetPositions();
void SetPos(ImVec2 pos) { m_pos = pos; }
void SetSize(ImVec2 size) { m_size = size; }
void SetScale(float scale) { m_draw_opts.scale = scale; }
void SetCtrlPos(ImVec2 pos) { m_pos = pos; }
void SetCtrlSize(ImVec2 size) { m_size = size; }
void SetCtrlScale(float scale) { m_draw_opts.scale = scale; }
void Init(const ImVec2& pos, const ImVec2& size, float scale) {
m_pos = pos;
m_size = size;
@ -76,16 +75,15 @@ public:
bool IsCombineThumbs() const { return m_combine_thumbs; }
bool IsActiveHigherThumb() const { return m_selection == ssHigher; }
void MoveActiveThumb(int delta);
void ShowLowerThumb(bool show) { m_draw_lower_thumb = show; }
void ShowLabelOnMouseMove(bool show = true) { m_show_move_label = show; }
ImRect GetGrooveRect() const { return m_draw_opts.groove(m_pos, m_size, is_horizontal()); }
float GetPositionInRect(int pos, const ImRect& rect) const;
bool IsRClickOnThumb() const { return m_rclick_on_selected_thumb; }
bool is_horizontal() const { return !(m_flags & ImGuiSliderFlags_Vertical); }
bool is_lower_at_min() const { return m_lower_value == m_min_value; }
bool is_higher_at_max() const { return m_higher_value == m_max_value; }
bool is_full_span() const { return this->is_lower_at_min() && this->is_higher_at_max(); }
bool is_rclick_on_thumb() const { return m_rclick_on_selected_thumb; }
bool render();
std::string get_label(int pos) const;
@ -130,11 +128,12 @@ private:
ImGuiSliderFlags m_flags{ ImGuiSliderFlags_None };
bool m_is_shown{ true };
int m_min_value;
int m_max_value;
int m_lower_value;
int m_higher_value;
int m_mouse_pos_value;
int m_min_pos;
int m_max_pos;
int m_lower_pos;
int m_higher_pos;
// slider's position of the mouse cursor
int m_mouse_pos;
bool m_rclick_on_selected_thumb{ false };
@ -150,24 +149,136 @@ private:
std::function<void(const ImRect&, const ImRect&)> m_cb_draw_scroll_line { nullptr };
std::function<void(const ImRect&)> m_cb_extra_draw { nullptr };
void correct_lower_value();
void correct_higher_value();
void correct_lower_pos();
void correct_higher_pos();
std::string get_label_on_move(int pos) const { return m_cb_get_label_on_move ? m_cb_get_label_on_move(pos) : get_label(pos); }
void apply_regions(int higher_value, int lower_value, const ImRect& draggable_region);
void check_and_correct_thumbs(int* higher_value, int* lower_value);
void apply_regions(int higher_pos, int lower_pos, const ImRect& draggable_region);
void check_and_correct_thumbs(int* higher_pos, int* lower_pos);
void draw_scroll_line(const ImRect& scroll_line, const ImRect& slideable_region);
void draw_background(const ImRect& slideable_region);
void draw_label(std::string label, const ImRect& thumb);
void draw_thumb(const ImVec2& center, bool mark = false);
bool draw_slider(int* higher_value, int* lower_value,
bool draw_slider(int* higher_pos, int* lower_pos,
std::string& higher_label, std::string& lower_label,
const ImVec2& pos, const ImVec2& size, float scale = 1.0f);
};
} // GUI
// VatType = a typ of values, related to the each position in slider
template<typename ValType>
class Manager
{
public:
void Init( int lowerPos,
int higherPos,
int minPos,
int maxPos,
const std::string& name,
bool is_horizontal)
{
m_ctrl = ImGuiControl( lowerPos, higherPos,
minPos, maxPos,
is_horizontal ? 0 : ImGuiSliderFlags_Vertical,
name, !is_horizontal);
m_ctrl.set_get_label_cb([this](int pos) {return get_label(pos); });
};
Manager() {}
Manager(int lowerPos,
int higherPos,
int minPos,
int maxPos,
const std::string& name,
bool is_horizontal)
{
Init (lowerPos, higherPos, minPos, maxPos, name, is_horizontal);
}
~Manager() {}
int GetMinPos() const { return m_ctrl.GetMinPos(); }
int GetMaxPos() const { return m_ctrl.GetMaxPos(); }
int GetLowerPos() const { return m_ctrl.GetLowerPos(); }
int GetHigherPos()const { return m_ctrl.GetHigherPos(); }
ValType GetMinValue() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetMinPos()]; }
ValType GetMaxValue() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetMaxPos()]; }
ValType GetLowerValue() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetLowerPos()];}
ValType GetHigherValue() { return m_values.empty() ? static_cast<ValType>(0) : m_values[GetHigherPos()]; }
// Set low and high slider position. If the span is non-empty, disable the "one layer" mode.
void SetLowerPos(const int lower_pos) {
m_ctrl.SetLowerPos(lower_pos);
process_thumb_move();
}
void SetHigherPos(const int higher_pos) {
m_ctrl.SetHigherPos(higher_pos);
process_thumb_move();
}
void SetSelectionSpan(const int lower_pos, const int higher_pos) {
m_ctrl.SetSelectionSpan(lower_pos, higher_pos);
process_thumb_move();
}
void SetMaxPos(const int max_pos) {
m_ctrl.SetMaxPos(max_pos);
process_thumb_move();
}
void SetSliderValues(const std::vector<ValType>& values) { m_values = values; }
// values used to show thumb labels
void SetSliderAlternateValues(const std::vector<ValType>& values) { m_alternate_values = values; }
bool IsLowerAtMin() const { return m_ctrl.GetLowerPos() == m_ctrl.GetMinPos(); }
bool IsHigherAtMax() const { return m_ctrl.GetHigherPos() == m_ctrl.GetMaxPos(); }
void Show(bool show = true) { m_ctrl.Show(show); }
void Hide() { m_ctrl.Show(false); }
void SetEmUnit(int em_unit) { m_em = em_unit; }
void ShowLowerThumb(bool show) { m_ctrl.ShowLowerThumb(show); }
virtual void Render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) = 0;
void set_callback_on_thumb_move(std::function<void()> cb) { m_cb_thumb_move = cb; };
void move_current_thumb(const int delta)
{
m_ctrl.MoveActiveThumb(delta);
process_thumb_move();
}
protected:
std::vector<ValType> m_values;
std::vector<ValType> m_alternate_values;
ImGuiControl m_ctrl;
int m_em{ 10 };
float m_scale{ 1.f };
std::string get_label(int pos) const {
if (m_values.empty())
return std::to_string(pos);
if (pos >= m_values.size())
return "ErrVal";
return to_string_with_precision(static_cast<ValType>(m_alternate_values.empty() ? m_values[pos] : m_alternate_values[pos]));
}
void process_thumb_move() {
if (m_cb_thumb_move)
m_cb_thumb_move();
}
private:
std::function<void()> m_cb_thumb_move{ nullptr };
};
} // GUI
} // Slic3r