mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 10:06:02 +08:00
DoubleSliderForLayers Improvements:
* Set "Show estimated print time on mouse moving" on true by default * Back ported Ruler * Fix for "Add" button * Show move line on ruler
This commit is contained in:
parent
102ff4a40e
commit
97d82a0d57
@ -218,6 +218,15 @@ void AppConfig::set_defaults()
|
|||||||
if (get("auth_login_dialog_confirmed").empty())
|
if (get("auth_login_dialog_confirmed").empty())
|
||||||
set("auth_login_dialog_confirmed", "0");
|
set("auth_login_dialog_confirmed", "0");
|
||||||
|
|
||||||
|
if (get("show_estimated_times_in_dbl_slider").empty())
|
||||||
|
set("show_estimated_times_in_dbl_slider", "1");
|
||||||
|
|
||||||
|
if (get("show_ruler_in_dbl_slider").empty())
|
||||||
|
set("show_ruler_in_dbl_slider", "0");
|
||||||
|
|
||||||
|
if (get("show_ruler_bg_in_dbl_slider").empty())
|
||||||
|
set("show_ruler_bg_in_dbl_slider", "1");
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (get("use_legacy_3DConnexion").empty())
|
if (get("use_legacy_3DConnexion").empty())
|
||||||
set("use_legacy_3DConnexion", "0");
|
set("use_legacy_3DConnexion", "0");
|
||||||
|
@ -262,6 +262,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/DoubleSliderForLayers.hpp
|
GUI/DoubleSliderForLayers.hpp
|
||||||
GUI/DoubleSliderForGcode.cpp
|
GUI/DoubleSliderForGcode.cpp
|
||||||
GUI/DoubleSliderForGcode.hpp
|
GUI/DoubleSliderForGcode.hpp
|
||||||
|
GUI/RulerForDoubleSlider.cpp
|
||||||
|
GUI/RulerForDoubleSlider.hpp
|
||||||
GUI/Notebook.cpp
|
GUI/Notebook.cpp
|
||||||
GUI/Notebook.hpp
|
GUI/Notebook.hpp
|
||||||
GUI/TopBar.cpp
|
GUI/TopBar.cpp
|
||||||
|
@ -27,7 +27,7 @@ using Slic3r::format;
|
|||||||
|
|
||||||
namespace DoubleSlider {
|
namespace DoubleSlider {
|
||||||
|
|
||||||
static const float VERTICAL_SLIDER_WIDTH = 105.0f;
|
//static const float VERTICAL_SLIDER_WIDTH = 105.0f;
|
||||||
|
|
||||||
DSForLayers::DSForLayers( int lowerValue,
|
DSForLayers::DSForLayers( int lowerValue,
|
||||||
int higherValue,
|
int higherValue,
|
||||||
@ -42,7 +42,10 @@ DSForLayers::DSForLayers( int lowerValue,
|
|||||||
Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false);
|
Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false);
|
||||||
m_ctrl.ShowLabelOnMouseMove(true);
|
m_ctrl.ShowLabelOnMouseMove(true);
|
||||||
|
|
||||||
m_ctrl.set_get_label_on_move_cb([this](int pos) { return m_show_estimated_times ? get_label(pos, ltEstimatedTime) : ""; });
|
m_ctrl.set_get_label_on_move_cb([this](int pos) {
|
||||||
|
m_pos_on_move = pos;
|
||||||
|
return m_show_estimated_times ? get_label(pos, ltEstimatedTime) : "";
|
||||||
|
});
|
||||||
m_ctrl.set_extra_draw_cb([this](const ImRect& draw_rc) {return draw_ticks(draw_rc); });
|
m_ctrl.set_extra_draw_cb([this](const ImRect& draw_rc) {return draw_ticks(draw_rc); });
|
||||||
|
|
||||||
m_ticks.set_values(&m_values);
|
m_ticks.set_values(&m_values);
|
||||||
@ -170,22 +173,25 @@ using namespace ImGui;
|
|||||||
|
|
||||||
void DSForLayers::draw_ticks(const ImRect& slideable_region)
|
void DSForLayers::draw_ticks(const ImRect& slideable_region)
|
||||||
{
|
{
|
||||||
//if(m_draw_mode != dmRegular)
|
if (m_show_ruler)
|
||||||
// return;
|
draw_ruler(slideable_region);
|
||||||
//if (m_ticks.empty() || m_mode == MultiExtruder)
|
|
||||||
// return;
|
|
||||||
if (m_ticks.empty() || m_draw_mode == dmSlaPrint)
|
if (m_ticks.empty() || m_draw_mode == dmSlaPrint)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// distance form center begin end
|
||||||
const ImVec2 tick_border = ImVec2(23.0f, 2.0f) * m_scale;
|
const ImVec2 tick_border = ImVec2(23.0f, 2.0f) * m_scale;
|
||||||
// distance form center begin end
|
|
||||||
const ImVec2 tick_size = ImVec2(19.0f, 11.0f) * m_scale;
|
|
||||||
const float tick_width = 1.0f * m_scale;
|
|
||||||
const float icon_side = m_imgui->GetTextureCustomRect(ImGui::PausePrint)->Height;
|
|
||||||
const float icon_offset = 0.5f * icon_side;;
|
|
||||||
|
|
||||||
const ImU32 tick_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_ORANGE_DARK);
|
const float inner_x = 11.f * m_scale;
|
||||||
const ImU32 tick_hovered_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_WINDOW_BACKGROUND);
|
const float outer_x = 19.f * m_scale;
|
||||||
|
const float x_center = slideable_region.GetCenter().x;
|
||||||
|
|
||||||
|
const float tick_width = float(int(1.0f * m_scale + 0.5f));
|
||||||
|
const float icon_side = m_imgui->GetTextureCustomRect(ImGui::PausePrint)->Height;
|
||||||
|
const float icon_offset = 0.5f * icon_side;;
|
||||||
|
|
||||||
|
const ImU32 tick_clr = ImGui::ColorConvertFloat4ToU32(m_show_ruler ? ImGuiPureWrap::COL_ORANGE_LIGHT : ImGuiPureWrap::COL_ORANGE_DARK);
|
||||||
|
const ImU32 tick_hovered_clr = ImGui::ColorConvertFloat4ToU32(m_show_ruler ? ImGuiPureWrap::COL_ORANGE_DARK : ImGuiPureWrap::COL_WINDOW_BACKGROUND);
|
||||||
|
|
||||||
auto get_tick_pos = [this, slideable_region](int tick) {
|
auto get_tick_pos = [this, slideable_region](int tick) {
|
||||||
return m_ctrl.GetPositionInRect(tick, slideable_region);
|
return m_ctrl.GetPositionInRect(tick, slideable_region);
|
||||||
@ -197,8 +203,8 @@ void DSForLayers::draw_ticks(const ImRect& slideable_region)
|
|||||||
float tick_pos = get_tick_pos(tick_it->tick);
|
float tick_pos = get_tick_pos(tick_it->tick);
|
||||||
|
|
||||||
//draw tick hover box when hovered
|
//draw tick hover box when hovered
|
||||||
ImRect tick_hover_box = ImRect(slideable_region.GetCenter().x - tick_border.x, tick_pos - tick_border.y,
|
ImRect tick_hover_box = ImRect(x_center - tick_border.x, tick_pos - tick_border.y,
|
||||||
slideable_region.GetCenter().x + tick_border.x, tick_pos + tick_border.y - tick_width);
|
x_center + tick_border.x, tick_pos + tick_border.y - tick_width);
|
||||||
|
|
||||||
if (ImGui::IsMouseHoveringRect(tick_hover_box.Min, tick_hover_box.Max)) {
|
if (ImGui::IsMouseHoveringRect(tick_hover_box.Min, tick_hover_box.Max)) {
|
||||||
ImGui::RenderFrame(tick_hover_box.Min, tick_hover_box.Max, tick_hovered_clr, false);
|
ImGui::RenderFrame(tick_hover_box.Min, tick_hover_box.Max, tick_hovered_clr, false);
|
||||||
@ -219,12 +225,12 @@ void DSForLayers::draw_ticks(const ImRect& slideable_region)
|
|||||||
float tick_pos = get_tick_pos(tick_it->tick);
|
float tick_pos = get_tick_pos(tick_it->tick);
|
||||||
|
|
||||||
//draw ticks
|
//draw ticks
|
||||||
ImRect tick_left = ImRect(slideable_region.GetCenter().x - tick_size.x, tick_pos - tick_width, slideable_region.GetCenter().x - tick_size.y, tick_pos);
|
ImRect tick_left = ImRect(x_center - outer_x, tick_pos - tick_width, x_center - inner_x, tick_pos);
|
||||||
ImRect tick_right = ImRect(slideable_region.GetCenter().x + tick_size.y, tick_pos - tick_width, slideable_region.GetCenter().x + tick_size.x, tick_pos);
|
ImRect tick_right = ImRect(x_center + inner_x, tick_pos - tick_width, x_center + outer_x, tick_pos);
|
||||||
ImGui::RenderFrame(tick_left.Min, tick_left.Max, tick_clr, false);
|
ImGui::RenderFrame(tick_left.Min, tick_left.Max, tick_clr, false);
|
||||||
ImGui::RenderFrame(tick_right.Min, tick_right.Max, tick_clr, false);
|
ImGui::RenderFrame(tick_right.Min, tick_right.Max, tick_clr, false);
|
||||||
|
|
||||||
ImVec2 icon_pos = ImVec2(tick_right.Max.x + 0.5f * icon_offset, tick_pos - icon_offset);
|
ImVec2 icon_pos = ImVec2(m_ctrl.GetCtrlPos().x + GetWidth(), tick_pos - icon_offset);
|
||||||
std::string btn_label = "tick " + std::to_string(tick_it->tick);
|
std::string btn_label = "tick " + std::to_string(tick_it->tick);
|
||||||
|
|
||||||
//draw tick icon-buttons
|
//draw tick icon-buttons
|
||||||
@ -257,6 +263,174 @@ void DSForLayers::draw_ticks(const ImRect& slideable_region)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DSForLayers::draw_ruler(const ImRect& slideable_region)
|
||||||
|
{
|
||||||
|
if (m_values.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const double step = double(slideable_region.GetHeight()) / (m_ctrl.GetMaxPos() - m_ctrl.GetMinPos());
|
||||||
|
|
||||||
|
if (!m_ruler.valid())
|
||||||
|
m_ruler.init(m_values, step);
|
||||||
|
|
||||||
|
const float inner_x = 11.f * m_scale;
|
||||||
|
const float long_outer_x = 17.f * m_scale;
|
||||||
|
const float short_outer_x = 14.f * m_scale;
|
||||||
|
const float tick_width = float(int(1.0f * m_scale +0.5f));
|
||||||
|
const float label_height = m_imgui->GetTextureCustomRect(ImGui::PausePrint)->Height;
|
||||||
|
|
||||||
|
const ImU32 tick_clr = IM_COL32(255, 255, 255, 255);
|
||||||
|
|
||||||
|
const float x_center = slideable_region.GetCenter().x;
|
||||||
|
|
||||||
|
double max_val = 0.;
|
||||||
|
for (const auto& val : m_ruler.max_values)
|
||||||
|
if (max_val < val)
|
||||||
|
max_val = val;
|
||||||
|
|
||||||
|
if (m_show_ruler_bg) {
|
||||||
|
// draw ruler BG
|
||||||
|
ImRect bg_rect = slideable_region;
|
||||||
|
bg_rect.Expand(ImVec2(0.f, long_outer_x));
|
||||||
|
bg_rect.Min.x -= tick_width;
|
||||||
|
bg_rect.Max.x = m_ctrl.GetCtrlPos().x + GetWidth();
|
||||||
|
bg_rect.Min.y = m_ctrl.GetCtrlPos().y + label_height;
|
||||||
|
bg_rect.Max.y = m_ctrl.GetCtrlPos().y + GetHeight() - label_height;
|
||||||
|
const ImU32 bg_color = ImGui::ColorConvertFloat4ToU32(ImVec4(0.13f, 0.13f, 0.13f, 0.5f));
|
||||||
|
|
||||||
|
ImGui::RenderFrame(bg_rect.Min, bg_rect.Max, bg_color, false, 2.f * m_ctrl.rounding());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get_tick_pos = [this, slideable_region](int tick) -> float {
|
||||||
|
return m_ctrl.GetPositionInRect(tick, slideable_region);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto draw_text = [max_val, x_center, label_height, long_outer_x, this](const int tick, const float tick_pos)
|
||||||
|
{
|
||||||
|
ImVec2 start = ImVec2(x_center + long_outer_x + 1, tick_pos - (0.5f * label_height));
|
||||||
|
std::string label = get_label(tick, ltHeight, max_val > 100.0 ? "%1$.1f" : "%1$.2f");
|
||||||
|
ImGui::RenderText(start, label.c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto draw_tick = [tick_clr, x_center, tick_width, inner_x](const float tick_pos, const float outer_x)
|
||||||
|
{
|
||||||
|
ImRect tick_right = ImRect(x_center + inner_x, tick_pos - tick_width, x_center + outer_x, tick_pos);
|
||||||
|
ImGui::RenderFrame(tick_right.Min, tick_right.Max, tick_clr, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto draw_short_ticks = [this, short_outer_x, draw_tick, get_tick_pos](double& current_tick, int max_tick)
|
||||||
|
{
|
||||||
|
if (m_ruler.short_step <= 0.0)
|
||||||
|
return;
|
||||||
|
while (current_tick < max_tick) {
|
||||||
|
float pos = get_tick_pos(lround(current_tick));
|
||||||
|
draw_tick(pos, short_outer_x);
|
||||||
|
current_tick += m_ruler.short_step;
|
||||||
|
if (current_tick > m_ctrl.GetMaxPos())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
double short_tick = NaNd;
|
||||||
|
int tick = 0;
|
||||||
|
double value = 0.0;
|
||||||
|
size_t sequence = 0;
|
||||||
|
int prev_y_pos = -1;
|
||||||
|
int values_size = (int)m_values.size();
|
||||||
|
|
||||||
|
if (m_ruler.long_step < 0) {
|
||||||
|
// sequential print when long_step wasn't detected because of a lot of printed objects
|
||||||
|
if (m_ruler.max_values.size() > 1) {
|
||||||
|
while (tick <= m_ctrl.GetMaxPos() && sequence < m_ruler.count()) {
|
||||||
|
// draw just ticks with max value
|
||||||
|
value = m_ruler.max_values[sequence];
|
||||||
|
short_tick = tick;
|
||||||
|
|
||||||
|
for (; tick < values_size; tick++) {
|
||||||
|
if (m_values[tick] == value)
|
||||||
|
break;
|
||||||
|
if (m_values[tick] > value) {
|
||||||
|
if (tick > 0)
|
||||||
|
tick--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tick > m_ctrl.GetMaxPos())
|
||||||
|
break;
|
||||||
|
|
||||||
|
float pos = get_tick_pos(tick);
|
||||||
|
draw_tick(pos, long_outer_x);
|
||||||
|
if (prev_y_pos < 0 || prev_y_pos - pos >= label_height) {
|
||||||
|
draw_text(tick, pos);
|
||||||
|
prev_y_pos = pos;
|
||||||
|
}
|
||||||
|
draw_short_ticks(short_tick, tick);
|
||||||
|
|
||||||
|
sequence++;
|
||||||
|
tick++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// very short object or some non-trivial ruler with non-regular step (see https://github.com/prusa3d/PrusaSlicer/issues/7263)
|
||||||
|
else {
|
||||||
|
if (step < 1) // step less then 1 px indicates very tall object with non-regular laayer step (probably in vase mode)
|
||||||
|
return;
|
||||||
|
for (size_t tick = 1; tick < m_values.size(); tick++) {
|
||||||
|
float pos = get_tick_pos(tick);
|
||||||
|
draw_tick(pos, long_outer_x);
|
||||||
|
draw_text(tick, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (tick <= m_ctrl.GetMaxPos()) {
|
||||||
|
value += m_ruler.long_step;
|
||||||
|
|
||||||
|
if (sequence < m_ruler.count() && value > m_ruler.max_values[sequence])
|
||||||
|
value = m_ruler.max_values[sequence];
|
||||||
|
|
||||||
|
short_tick = tick;
|
||||||
|
|
||||||
|
for (; tick < values_size; tick++) {
|
||||||
|
if (m_values[tick] == value)
|
||||||
|
break;
|
||||||
|
if (m_values[tick] > value) {
|
||||||
|
if (tick > 0)
|
||||||
|
tick--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tick > m_ctrl.GetMaxPos())
|
||||||
|
break;
|
||||||
|
|
||||||
|
float pos = get_tick_pos(tick);
|
||||||
|
draw_tick(pos, long_outer_x);
|
||||||
|
if (prev_y_pos < 0 || prev_y_pos - pos >= label_height) {
|
||||||
|
draw_text(tick, pos);
|
||||||
|
prev_y_pos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_short_ticks(short_tick, tick);
|
||||||
|
|
||||||
|
if (sequence < m_ruler.count() && value == m_ruler.max_values[sequence]) {
|
||||||
|
value = 0.0;
|
||||||
|
sequence++;
|
||||||
|
tick++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// short ticks from the last tick to the end
|
||||||
|
draw_short_ticks(short_tick, m_ctrl.GetMaxPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw mose move line
|
||||||
|
if (m_pos_on_move > 0) {
|
||||||
|
float line_pos = get_tick_pos(m_pos_on_move);
|
||||||
|
|
||||||
|
ImRect move_line = ImRect(x_center + 0.75f * inner_x, line_pos - tick_width, x_center + 1.5f * long_outer_x, line_pos);
|
||||||
|
ImGui::RenderFrame(move_line.Min, move_line.Max, ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_ORANGE_LIGHT), false);
|
||||||
|
m_pos_on_move = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static std::array<float, 4> decode_color_to_float_array(const std::string color)
|
static std::array<float, 4> decode_color_to_float_array(const std::string color)
|
||||||
{
|
{
|
||||||
auto hex_digit_to_int = [](const char c) {
|
auto hex_digit_to_int = [](const char c) {
|
||||||
@ -504,7 +678,7 @@ bool DSForLayers::render_multi_extruders_menu(bool switch_current_code/* = false
|
|||||||
void DSForLayers::render_color_picker()
|
void DSForLayers::render_color_picker()
|
||||||
{
|
{
|
||||||
ImGuiContext& context = *GImGui;
|
ImGuiContext& context = *GImGui;
|
||||||
const std::string title = _u8L("Select color for Color Change");
|
const std::string title = ("Select color for Color Change");
|
||||||
if (m_show_color_picker) {
|
if (m_show_color_picker) {
|
||||||
|
|
||||||
ImGuiPureWrap::set_next_window_pos(1200, 200, ImGuiCond_Always, 0.5f, 0.0f);
|
ImGuiPureWrap::set_next_window_pos(1200, 200, ImGuiCond_Always, 0.5f, 0.0f);
|
||||||
@ -534,12 +708,31 @@ void DSForLayers::render_cog_menu()
|
|||||||
}
|
}
|
||||||
if (ImGuiPureWrap::menu_item_with_icon(_u8L("Show estimated print time on hover").c_str(), "", icon_sz, 0, m_show_estimated_times)) {
|
if (ImGuiPureWrap::menu_item_with_icon(_u8L("Show estimated print time on hover").c_str(), "", icon_sz, 0, m_show_estimated_times)) {
|
||||||
m_show_estimated_times = !m_show_estimated_times;
|
m_show_estimated_times = !m_show_estimated_times;
|
||||||
|
if (m_cb_change_app_config)
|
||||||
|
m_cb_change_app_config("show_estimated_times_in_dbl_slider", m_show_estimated_times ? "1" : "0");
|
||||||
}
|
}
|
||||||
if (m_mode == MultiAsSingle && m_draw_mode == dmRegular &&
|
if (m_mode == MultiAsSingle && m_draw_mode == dmRegular &&
|
||||||
ImGuiPureWrap::menu_item_with_icon(_u8L("Set extruder sequence for the entire print").c_str(), "")) {
|
ImGuiPureWrap::menu_item_with_icon(_u8L("Set extruder sequence for the entire print").c_str(), "")) {
|
||||||
if (m_ticks.edit_extruder_sequence(m_ctrl.GetMaxPos(), m_mode))
|
if (m_ticks.edit_extruder_sequence(m_ctrl.GetMaxPos(), m_mode))
|
||||||
process_ticks_changed();
|
process_ticks_changed();
|
||||||
}
|
}
|
||||||
|
if (ImGuiPureWrap::begin_menu(_u8L("Ruler").c_str())) {
|
||||||
|
if (ImGuiPureWrap::menu_item_with_icon(_u8L("Show").c_str(), "", icon_sz, 0, m_show_ruler)) {
|
||||||
|
m_show_ruler = !m_show_ruler;
|
||||||
|
if (m_show_ruler)
|
||||||
|
m_imgui->set_requires_extra_frame();
|
||||||
|
if (m_cb_change_app_config)
|
||||||
|
m_cb_change_app_config("show_ruler_in_dbl_slider", m_show_ruler ? "1" : "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGuiPureWrap::menu_item_with_icon(_u8L("Show backgroung").c_str(), "", icon_sz, 0, m_show_ruler_bg)) {
|
||||||
|
m_show_ruler_bg = !m_show_ruler_bg;
|
||||||
|
if (m_cb_change_app_config)
|
||||||
|
m_cb_change_app_config("show_ruler_bg_in_dbl_slider", m_show_ruler_bg ? "1" : "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiPureWrap::end_menu();
|
||||||
|
}
|
||||||
if (can_edit()) {
|
if (can_edit()) {
|
||||||
if (ImGuiPureWrap::menu_item_with_icon(_u8L("Use default colors").c_str(), "", icon_sz, 0, m_ticks.used_default_colors())) {
|
if (ImGuiPureWrap::menu_item_with_icon(_u8L("Use default colors").c_str(), "", icon_sz, 0, m_ticks.used_default_colors())) {
|
||||||
UseDefaultColors(!m_ticks.used_default_colors());
|
UseDefaultColors(!m_ticks.used_default_colors());
|
||||||
@ -707,11 +900,15 @@ void DSForLayers::Render(const int canvas_width, const int canvas_height, float
|
|||||||
return;
|
return;
|
||||||
m_scale = extra_scale * 0.1f * m_em;
|
m_scale = extra_scale * 0.1f * m_em;
|
||||||
|
|
||||||
|
m_ruler.set_scale(m_scale);
|
||||||
|
|
||||||
const float action_btn_sz = m_imgui->GetTextureCustomRect(ImGui::DSRevert)->Height;
|
const float action_btn_sz = m_imgui->GetTextureCustomRect(ImGui::DSRevert)->Height;
|
||||||
const float tick_icon_side = m_imgui->GetTextureCustomRect(ImGui::PausePrint)->Height;
|
const float tick_icon_side = m_imgui->GetTextureCustomRect(ImGui::PausePrint)->Height;
|
||||||
|
|
||||||
ImVec2 pos;
|
ImVec2 pos;
|
||||||
|
|
||||||
|
const float VERTICAL_SLIDER_WIDTH = m_show_ruler ? 125.f : 105.0f;
|
||||||
|
|
||||||
pos.x = canvas_width - VERTICAL_SLIDER_WIDTH * m_scale - tick_icon_side;
|
pos.x = canvas_width - VERTICAL_SLIDER_WIDTH * m_scale - tick_icon_side;
|
||||||
pos.y = 1.5f * action_btn_sz + offset;
|
pos.y = 1.5f * action_btn_sz + offset;
|
||||||
if (m_allow_editing)
|
if (m_allow_editing)
|
||||||
@ -719,7 +916,7 @@ void DSForLayers::Render(const int canvas_width, const int canvas_height, float
|
|||||||
|
|
||||||
ImVec2 size = ImVec2(VERTICAL_SLIDER_WIDTH * m_scale, canvas_height - 4.f * action_btn_sz - offset);
|
ImVec2 size = ImVec2(VERTICAL_SLIDER_WIDTH * m_scale, canvas_height - 4.f * action_btn_sz - offset);
|
||||||
|
|
||||||
m_ctrl.Init(pos, size, m_scale);
|
m_ctrl.Init(pos, size, m_scale, m_show_ruler);
|
||||||
if (m_ctrl.render()) {
|
if (m_ctrl.render()) {
|
||||||
// request one more frame if value was changes with mouse wheel
|
// request one more frame if value was changes with mouse wheel
|
||||||
if (GImGui->IO.MouseWheel != 0.0f)
|
if (GImGui->IO.MouseWheel != 0.0f)
|
||||||
@ -770,6 +967,12 @@ void DSForLayers::Render(const int canvas_width, const int canvas_height, float
|
|||||||
render_color_picker();
|
render_color_picker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DSForLayers::force_ruler_update()
|
||||||
|
{
|
||||||
|
if (m_show_ruler)
|
||||||
|
m_ruler.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
bool DSForLayers::is_wipe_tower_layer(int tick) const
|
bool DSForLayers::is_wipe_tower_layer(int tick) const
|
||||||
{
|
{
|
||||||
if (!m_ticks.is_wipe_tower || tick >= (int)m_values.size())
|
if (!m_ticks.is_wipe_tower || tick >= (int)m_values.size())
|
||||||
@ -824,7 +1027,7 @@ static std::string short_and_splitted_time(const std::string& time)
|
|||||||
return get_s();
|
return get_s();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DSForLayers::get_label(int pos, LabelType label_type) const
|
std::string DSForLayers::get_label(int pos, LabelType label_type, const std::string& fmt/* = "%1$.2f"*/) const
|
||||||
{
|
{
|
||||||
const size_t value = pos;
|
const size_t value = pos;
|
||||||
|
|
||||||
@ -861,7 +1064,7 @@ std::string DSForLayers::get_label(int pos, LabelType label_type) const
|
|||||||
}
|
}
|
||||||
return value < m_layers_times.size() ? short_and_splitted_time(get_time_dhms(m_layers_times[value])) : "";
|
return value < m_layers_times.size() ? short_and_splitted_time(get_time_dhms(m_layers_times[value])) : "";
|
||||||
}
|
}
|
||||||
std::string str = format("%1$.2f", m_values[value]);
|
std::string str = format(fmt, m_values[value]);
|
||||||
if (label_type == ltHeight)
|
if (label_type == ltHeight)
|
||||||
return str;
|
return str;
|
||||||
if (label_type == ltHeightWithLayer) {
|
if (label_type == ltHeightWithLayer) {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define slic3r_GUI_DoubleSliderForLayers_hpp_
|
#define slic3r_GUI_DoubleSliderForLayers_hpp_
|
||||||
|
|
||||||
#include "ImGuiDoubleSlider.hpp"
|
#include "ImGuiDoubleSlider.hpp"
|
||||||
|
#include "RulerForDoubleSlider.hpp"
|
||||||
#include "TickCodesManager.hpp"
|
#include "TickCodesManager.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -72,6 +73,7 @@ public:
|
|||||||
void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder);
|
void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder);
|
||||||
|
|
||||||
void Render(const int canvas_width, const int canvas_height, float extra_scale = 1.f, float offset = 0.f) override;
|
void Render(const int canvas_width, const int canvas_height, float extra_scale = 1.f, float offset = 0.f) override;
|
||||||
|
void force_ruler_update();
|
||||||
|
|
||||||
// jump to selected layer
|
// jump to selected layer
|
||||||
void jump_to_value();
|
void jump_to_value();
|
||||||
@ -82,6 +84,8 @@ public:
|
|||||||
void UseDefaultColors(bool def_colors_on);
|
void UseDefaultColors(bool def_colors_on);
|
||||||
bool is_new_print(const std::string& print_obj_idxs);
|
bool is_new_print(const std::string& print_obj_idxs);
|
||||||
void set_imgui_wrapper(Slic3r::GUI::ImGuiWrapper* imgui) { m_imgui = imgui; }
|
void set_imgui_wrapper(Slic3r::GUI::ImGuiWrapper* imgui) { m_imgui = imgui; }
|
||||||
|
void show_estimated_times(bool show) { m_show_estimated_times = show; }
|
||||||
|
void show_ruler(bool show, bool show_bg) { m_show_ruler = show; m_show_ruler_bg = show_bg; }
|
||||||
|
|
||||||
// manipulation with slider from keyboard
|
// manipulation with slider from keyboard
|
||||||
|
|
||||||
@ -104,6 +108,9 @@ public:
|
|||||||
void set_callback_on_get_print (std::function<const Slic3r::Print& ()> cb)
|
void set_callback_on_get_print (std::function<const Slic3r::Print& ()> cb)
|
||||||
{ m_cb_get_print = cb; }
|
{ m_cb_get_print = cb; }
|
||||||
|
|
||||||
|
void set_callback_on_change_app_config (std::function<void(const std::string&, const std::string&)> cb)
|
||||||
|
{ m_cb_change_app_config = cb; }
|
||||||
|
|
||||||
void set_callback_on_empty_auto_color_change(std::function<void()> cb)
|
void set_callback_on_empty_auto_color_change(std::function<void()> cb)
|
||||||
{ m_ticks.set_callback_on_empty_auto_color_change(cb); }
|
{ m_ticks.set_callback_on_empty_auto_color_change(cb); }
|
||||||
|
|
||||||
@ -134,14 +141,18 @@ private:
|
|||||||
|
|
||||||
bool is_osx { false };
|
bool is_osx { false };
|
||||||
bool m_allow_editing { true };
|
bool m_allow_editing { true };
|
||||||
bool m_show_estimated_times { false };
|
bool m_show_estimated_times { true };
|
||||||
|
bool m_show_ruler { false };
|
||||||
|
bool m_show_ruler_bg { true };
|
||||||
bool m_show_cog_menu { false };
|
bool m_show_cog_menu { false };
|
||||||
bool m_show_edit_menu { false };
|
bool m_show_edit_menu { false };
|
||||||
|
int m_pos_on_move { -1 };
|
||||||
|
|
||||||
DrawMode m_draw_mode { dmRegular };
|
DrawMode m_draw_mode { dmRegular };
|
||||||
Mode m_mode { SingleExtruder };
|
Mode m_mode { SingleExtruder };
|
||||||
FocusedItem m_focus { fiNone };
|
FocusedItem m_focus { fiNone };
|
||||||
|
|
||||||
|
Ruler m_ruler;
|
||||||
TickCodeManager m_ticks;
|
TickCodeManager m_ticks;
|
||||||
Slic3r::GUI::ImGuiWrapper* m_imgui { nullptr };
|
Slic3r::GUI::ImGuiWrapper* m_imgui { nullptr };
|
||||||
|
|
||||||
@ -150,7 +161,7 @@ private:
|
|||||||
|
|
||||||
bool is_wipe_tower_layer(int tick) const;
|
bool is_wipe_tower_layer(int tick) const;
|
||||||
|
|
||||||
std::string get_label(int tick, LabelType label_type) const;
|
std::string get_label(int tick, LabelType label_type, const std::string& fmt = "%1$.2f") const;
|
||||||
|
|
||||||
std::string get_tooltip(int tick = -1);
|
std::string get_tooltip(int tick = -1);
|
||||||
|
|
||||||
@ -160,6 +171,7 @@ private:
|
|||||||
|
|
||||||
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
|
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
|
||||||
void draw_ticks(const ImRect& slideable_region);
|
void draw_ticks(const ImRect& slideable_region);
|
||||||
|
void draw_ruler(const ImRect& slideable_region);
|
||||||
void render_menu();
|
void render_menu();
|
||||||
void render_cog_menu();
|
void render_cog_menu();
|
||||||
void render_edit_menu();
|
void render_edit_menu();
|
||||||
@ -195,6 +207,7 @@ private:
|
|||||||
std::function<void()> m_cb_ticks_changed { nullptr };
|
std::function<void()> m_cb_ticks_changed { nullptr };
|
||||||
std::function<std::vector<std::string>()> m_cb_get_extruder_colors { nullptr };
|
std::function<std::vector<std::string>()> m_cb_get_extruder_colors { nullptr };
|
||||||
std::function<const Slic3r::Print&()> m_cb_get_print { nullptr };
|
std::function<const Slic3r::Print&()> m_cb_get_print { nullptr };
|
||||||
|
std::function<void(const std::string&, const std::string&)> m_cb_change_app_config { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // DoubleSlider;
|
} // DoubleSlider;
|
||||||
|
@ -6008,7 +6008,7 @@ bool GLCanvas3D::check_toolbar_icon_size(float init_scale, float& new_scale_to_s
|
|||||||
const float top_tb_width = m_main_toolbar.get_width() + m_undoredo_toolbar.get_width() + collapse_toolbar.get_width();
|
const float top_tb_width = m_main_toolbar.get_width() + m_undoredo_toolbar.get_width() + collapse_toolbar.get_width();
|
||||||
float items_cnt = float(m_main_toolbar.get_visible_items_cnt() + m_undoredo_toolbar.get_visible_items_cnt() + collapse_toolbar.get_visible_items_cnt());
|
float items_cnt = float(m_main_toolbar.get_visible_items_cnt() + m_undoredo_toolbar.get_visible_items_cnt() + collapse_toolbar.get_visible_items_cnt());
|
||||||
const float noitems_width = top_tb_width - float(size) * items_cnt; // width of separators and borders in top toolbars
|
const float noitems_width = top_tb_width - float(size) * items_cnt; // width of separators and borders in top toolbars
|
||||||
items_cnt += 1.6; // +1.6 means a place for some minimal margin between toolbars
|
items_cnt += 1.6f; // +1.6 means a place for some minimal margin between toolbars
|
||||||
|
|
||||||
// calculate scale needed for items in all top toolbars
|
// calculate scale needed for items in all top toolbars
|
||||||
// the std::max() is there because on some Linux dialects/virtual machines this code is called when the canvas has not been properly initialized yet,
|
// the std::max() is there because on some Linux dialects/virtual machines this code is called when the canvas has not been properly initialized yet,
|
||||||
|
@ -360,6 +360,7 @@ void Preview::hide_layers_slider()
|
|||||||
void Preview::on_size(wxSizeEvent& evt)
|
void Preview::on_size(wxSizeEvent& evt)
|
||||||
{
|
{
|
||||||
evt.Skip();
|
evt.Skip();
|
||||||
|
m_layers_slider->force_ruler_update();
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,12 +394,18 @@ void Preview::create_sliders()
|
|||||||
m_layers_slider = std::make_unique<DoubleSlider::DSForLayers>(0, 0, 0, 100, wxGetApp().is_editor());
|
m_layers_slider = std::make_unique<DoubleSlider::DSForLayers>(0, 0, 0, 100, wxGetApp().is_editor());
|
||||||
m_layers_slider->SetEmUnit(wxGetApp().em_unit());
|
m_layers_slider->SetEmUnit(wxGetApp().em_unit());
|
||||||
m_layers_slider->set_imgui_wrapper(wxGetApp().imgui());
|
m_layers_slider->set_imgui_wrapper(wxGetApp().imgui());
|
||||||
|
m_layers_slider->show_estimated_times(wxGetApp().app_config->get_bool("show_estimated_times_in_dbl_slider"));
|
||||||
|
m_layers_slider->show_ruler(wxGetApp().app_config->get_bool("show_ruler_in_dbl_slider"), wxGetApp().app_config->get_bool("show_ruler_bg_in_dbl_slider"));
|
||||||
|
|
||||||
m_layers_slider->SetDrawMode(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA,
|
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"));
|
wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects"));
|
||||||
|
|
||||||
m_layers_slider->set_callback_on_thumb_move( [this]() -> void { Preview::on_layers_slider_scroll_changed(); } );
|
m_layers_slider->set_callback_on_thumb_move( [this]() -> void { Preview::on_layers_slider_scroll_changed(); } );
|
||||||
|
|
||||||
|
m_layers_slider->set_callback_on_change_app_config([this](const std::string& key, const std::string& val) -> void {
|
||||||
|
wxGetApp().app_config->set(key, val);
|
||||||
|
});
|
||||||
|
|
||||||
if (wxGetApp().is_editor()) {
|
if (wxGetApp().is_editor()) {
|
||||||
m_layers_slider->set_callback_on_ticks_changed([this]() -> void {
|
m_layers_slider->set_callback_on_ticks_changed([this]() -> void {
|
||||||
Model& model = wxGetApp().plater()->model();
|
Model& model = wxGetApp().plater()->model();
|
||||||
@ -605,6 +612,7 @@ 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
|
//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_color_strings_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result));
|
m_layers_slider->SetExtruderColors(plater->get_extruder_color_strings_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result));
|
||||||
m_layers_slider->SetSliderValues(layers_z);
|
m_layers_slider->SetSliderValues(layers_z);
|
||||||
|
m_layers_slider->force_ruler_update();
|
||||||
assert(m_layers_slider->GetMinPos() == 0);
|
assert(m_layers_slider->GetMinPos() == 0);
|
||||||
|
|
||||||
m_layers_slider->Freeze();
|
m_layers_slider->Freeze();
|
||||||
|
@ -80,6 +80,43 @@ static bool behavior(ImGuiID id, const ImRect& region,
|
|||||||
return value_changed;
|
return value_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool lclicked_on_thumb(ImGuiID id, const ImRect& region,
|
||||||
|
const ImS32 v_min, const ImS32 v_max,
|
||||||
|
const ImRect& thumb, ImGuiSliderFlags flags = 0)
|
||||||
|
{
|
||||||
|
ImGuiContext& context = *GImGui;
|
||||||
|
|
||||||
|
if (context.ActiveId == id && context.ActiveIdSource == ImGuiInputSource_Mouse &&
|
||||||
|
context.IO.MouseReleased[0])
|
||||||
|
{
|
||||||
|
const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
|
||||||
|
|
||||||
|
ImS32 v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
|
||||||
|
const float region_usable_sz = (region.Max[axis] - region.Min[axis]);
|
||||||
|
const float region_usable_pos_min = region.Min[axis];
|
||||||
|
const float region_usable_pos_max = region.Max[axis];
|
||||||
|
|
||||||
|
const float mouse_abs_pos = context.IO.MousePos[axis];
|
||||||
|
float mouse_pos_ratio = (region_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - region_usable_pos_min) / region_usable_sz, 0.0f, 1.0f) : 0.0f;
|
||||||
|
if (axis == ImGuiAxis_Y)
|
||||||
|
mouse_pos_ratio = 1.0f - mouse_pos_ratio;
|
||||||
|
|
||||||
|
ImS32 v_new = v_min + (ImS32)(v_range * mouse_pos_ratio + 0.5f);
|
||||||
|
|
||||||
|
// Output thumb position so it can be displayed by the caller
|
||||||
|
const ImS32 v_clamped = (v_min < v_max) ? ImClamp(v_new, v_min, v_max) : ImClamp(v_new, v_max, v_min);
|
||||||
|
float thumb_pos_ratio = v_range != 0 ? ((float)(v_clamped - v_min) / (float)v_range) : 0.0f;
|
||||||
|
thumb_pos_ratio = axis == ImGuiAxis_Y ? 1.0f - thumb_pos_ratio : thumb_pos_ratio;
|
||||||
|
const float thumb_pos = region_usable_pos_min + (region_usable_pos_max - region_usable_pos_min) * thumb_pos_ratio;
|
||||||
|
|
||||||
|
ImVec2 new_thumb_center = axis == ImGuiAxis_Y ? ImVec2(thumb.GetCenter().x, thumb_pos) : ImVec2(thumb_pos, thumb.GetCenter().y);
|
||||||
|
if (thumb.Contains(new_thumb_center))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ImRect ImGuiControl::DrawOptions::groove(const ImVec2& pos, const ImVec2& size, bool is_horizontal) const
|
ImRect ImGuiControl::DrawOptions::groove(const ImVec2& pos, const ImVec2& size, bool is_horizontal) const
|
||||||
{
|
{
|
||||||
ImVec2 groove_start = is_horizontal ?
|
ImVec2 groove_start = is_horizontal ?
|
||||||
@ -262,6 +299,7 @@ bool ImGuiControl::IsLClickOnThumb()
|
|||||||
if (m_lclick_on_selected_thumb) {
|
if (m_lclick_on_selected_thumb) {
|
||||||
// discard left mouse click at list its value is checked to avoud reuse it on next frame
|
// discard left mouse click at list its value is checked to avoud reuse it on next frame
|
||||||
m_lclick_on_selected_thumb = false;
|
m_lclick_on_selected_thumb = false;
|
||||||
|
m_suppress_process_behavior = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -493,29 +531,55 @@ bool ImGuiControl::draw_slider( int* higher_pos, int* lower_pos,
|
|||||||
ImGui::ItemHoverable(m_regions.lower_thumb, id) && context.IO.MouseClicked[0])
|
ImGui::ItemHoverable(m_regions.lower_thumb, id) && context.IO.MouseClicked[0])
|
||||||
m_selection = ssLower;
|
m_selection = ssLower;
|
||||||
|
|
||||||
|
// detect left click on selected thumb
|
||||||
|
{
|
||||||
|
const ImRect& active_thumb = m_selection == ssHigher ? m_regions.higher_thumb : m_regions.lower_thumb;
|
||||||
|
if (ImGui::ItemHoverable(active_thumb, id) && context.IO.MouseClicked[0]) {
|
||||||
|
m_active_thumb = active_thumb;
|
||||||
|
m_suppress_process_behavior = true;
|
||||||
|
}
|
||||||
|
else if (ImGui::ItemHoverable(active_thumb, id) && context.IO.MouseReleased[0]) {
|
||||||
|
const ImRect& slideable_region = m_selection == ssHigher ? m_regions.higher_slideable_region : m_regions.lower_slideable_region;
|
||||||
|
if (lclicked_on_thumb(id, slideable_region, m_min_pos, m_max_pos, m_active_thumb, m_flags)) {
|
||||||
|
m_suppress_process_behavior = true;
|
||||||
|
m_lclick_on_selected_thumb = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// update thumb position
|
// update thumb position
|
||||||
bool pos_changed = false;
|
bool pos_changed = false;
|
||||||
if (m_selection == ssHigher) {
|
if (!m_suppress_process_behavior) {
|
||||||
pos_changed = behavior(id, m_regions.higher_slideable_region, m_min_pos, m_max_pos,
|
if (m_selection == ssHigher) {
|
||||||
higher_pos, &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) {
|
}
|
||||||
pos_changed = behavior(id, m_regions.lower_slideable_region, m_min_pos, m_max_pos,
|
else if (m_draw_lower_thumb && !m_combine_thumbs) {
|
||||||
lower_pos, &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 poss and correct them if needed
|
|
||||||
check_and_correct_thumbs(higher_pos, lower_pos);
|
|
||||||
|
|
||||||
|
// 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& 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;
|
const ImRect& active_thumb = m_selection == ssHigher ? m_regions.higher_thumb : m_regions.lower_thumb;
|
||||||
|
|
||||||
bool show_move_label = false;
|
bool show_move_label = false;
|
||||||
ImRect mouse_pos_rc = active_thumb;
|
ImRect mouse_pos_rc = active_thumb;
|
||||||
if (!pos_changed && ImGui::ItemHoverable(item_size, id) && !ImGui::IsMouseDragging(0)) {
|
|
||||||
behavior(id, slideable_region, m_min_pos, m_max_pos,
|
std::string move_label = "";
|
||||||
|
|
||||||
|
auto move_size = item_size;
|
||||||
|
move_size.Min.x += left_dummy_sz().x;
|
||||||
|
if (!pos_changed && ImGui::ItemHoverable(move_size, id) && !ImGui::IsMouseDragging(0)) {
|
||||||
|
auto sl_region = slideable_region;
|
||||||
|
if (!is_horizontal() && m_draw_opts.has_ruler)
|
||||||
|
sl_region.Max.x += m_draw_opts.dummy_sz().x;
|
||||||
|
behavior(id, sl_region, m_min_pos, m_max_pos,
|
||||||
&m_mouse_pos, &mouse_pos_rc, m_flags, true);
|
&m_mouse_pos, &mouse_pos_rc, m_flags, true);
|
||||||
show_move_label = true;
|
show_move_label = true;
|
||||||
|
move_label = get_label_on_move(m_mouse_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect right click on selected thumb
|
// detect right click on selected thumb
|
||||||
@ -525,16 +589,8 @@ bool ImGuiControl::draw_slider( int* higher_pos, int* lower_pos,
|
|||||||
context.IO.MouseClicked[0])
|
context.IO.MouseClicked[0])
|
||||||
m_rclick_on_selected_thumb = false;
|
m_rclick_on_selected_thumb = false;
|
||||||
|
|
||||||
// detect left click on selected thumb
|
if (m_suppress_process_behavior && ImGui::ItemHoverable(item_size, id) && ImGui::IsMouseDragging(0))
|
||||||
if (ImGui::ItemHoverable(active_thumb, id) && !pos_changed) {
|
m_suppress_process_behavior = false;
|
||||||
ImVec2 active_thumb_center = active_thumb.GetCenter();
|
|
||||||
if (context.IO.MouseClicked[0])
|
|
||||||
m_active_thumb_center_on_lcklick = active_thumb_center;
|
|
||||||
if (context.IO.MouseReleased[0] &&
|
|
||||||
(m_active_thumb_center_on_lcklick.y == active_thumb_center.y) &&
|
|
||||||
(m_active_thumb_center_on_lcklick.x == active_thumb_center.x) )
|
|
||||||
m_lclick_on_selected_thumb = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// render slider
|
// render slider
|
||||||
|
|
||||||
@ -565,8 +621,7 @@ bool ImGuiControl::draw_slider( int* higher_pos, int* lower_pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw label on mouse move
|
// draw label on mouse move
|
||||||
if (show_move_label)
|
draw_label(move_label, mouse_pos_rc, false, true);
|
||||||
draw_label(get_label_on_move(m_mouse_pos), mouse_pos_rc, false, true);
|
|
||||||
|
|
||||||
return pos_changed;
|
return pos_changed;
|
||||||
}
|
}
|
||||||
|
@ -62,10 +62,11 @@ public:
|
|||||||
void SetCtrlPos(ImVec2 pos) { m_pos = pos; }
|
void SetCtrlPos(ImVec2 pos) { m_pos = pos; }
|
||||||
void SetCtrlSize(ImVec2 size) { m_size = size; }
|
void SetCtrlSize(ImVec2 size) { m_size = size; }
|
||||||
void SetCtrlScale(float scale) { m_draw_opts.scale = scale; }
|
void SetCtrlScale(float scale) { m_draw_opts.scale = scale; }
|
||||||
void Init(const ImVec2& pos, const ImVec2& size, float scale) {
|
void Init(const ImVec2& pos, const ImVec2& size, float scale, bool has_ruler = false) {
|
||||||
m_pos = pos;
|
m_pos = pos;
|
||||||
m_size = size;
|
m_size = size;
|
||||||
m_draw_opts.scale = scale;
|
m_draw_opts.scale = scale;
|
||||||
|
m_draw_opts.has_ruler = has_ruler;
|
||||||
}
|
}
|
||||||
ImVec2 GetCtrlSize() { return m_size; }
|
ImVec2 GetCtrlSize() { return m_size; }
|
||||||
ImVec2 GetCtrlPos() { return m_pos; }
|
ImVec2 GetCtrlPos() { return m_pos; }
|
||||||
@ -90,6 +91,8 @@ public:
|
|||||||
bool render();
|
bool render();
|
||||||
|
|
||||||
std::string get_label(int pos) const;
|
std::string get_label(int pos) const;
|
||||||
|
float rounding() const { return m_draw_opts.rounding(); }
|
||||||
|
ImVec2 left_dummy_sz() const { return m_draw_opts.text_dummy_sz() + m_draw_opts.text_padding(); }
|
||||||
|
|
||||||
void set_get_label_on_move_cb(std::function<std::string(int)> cb) { m_cb_get_label_on_move = cb; }
|
void set_get_label_on_move_cb(std::function<std::string(int)> cb) { m_cb_get_label_on_move = cb; }
|
||||||
void set_get_label_cb(std::function<std::string(int)> cb) { m_cb_get_label = cb; }
|
void set_get_label_cb(std::function<std::string(int)> cb) { m_cb_get_label = cb; }
|
||||||
@ -100,12 +103,13 @@ private:
|
|||||||
|
|
||||||
struct DrawOptions {
|
struct DrawOptions {
|
||||||
float scale { 1.f }; // used for Retina on osx
|
float scale { 1.f }; // used for Retina on osx
|
||||||
|
bool has_ruler { false };
|
||||||
|
|
||||||
ImVec2 dummy_sz() const { return ImVec2(24.0f, 16.0f) * scale; }
|
ImVec2 dummy_sz() const { return ImVec2(has_ruler ? 48.0f : 24.0f, 16.0f) * scale; }
|
||||||
ImVec2 thumb_dummy_sz() const { return ImVec2(17.0f, 17.0f) * scale; }
|
ImVec2 thumb_dummy_sz() const { return ImVec2(17.0f, 17.0f) * scale; }
|
||||||
ImVec2 groove_sz() const { return ImVec2(4.0f, 4.0f) * scale; }
|
ImVec2 groove_sz() const { return ImVec2(4.0f, 4.0f) * scale; }
|
||||||
ImVec2 draggable_region_sz()const { return ImVec2(20.0f, 19.0f) * scale; }
|
ImVec2 draggable_region_sz()const { return ImVec2(20.0f, 19.0f) * scale; }
|
||||||
ImVec2 text_dummy_sz() const { return ImVec2(50.0f, 34.0f) * scale; }
|
ImVec2 text_dummy_sz() const { return ImVec2(60.0f, 34.0f) * scale; }
|
||||||
ImVec2 text_padding() const { return ImVec2( 5.0f, 2.0f) * scale; }
|
ImVec2 text_padding() const { return ImVec2( 5.0f, 2.0f) * scale; }
|
||||||
|
|
||||||
float thumb_radius() const { return 10.0f * scale; }
|
float thumb_radius() const { return 10.0f * scale; }
|
||||||
@ -140,7 +144,8 @@ private:
|
|||||||
|
|
||||||
bool m_rclick_on_selected_thumb{ false };
|
bool m_rclick_on_selected_thumb{ false };
|
||||||
bool m_lclick_on_selected_thumb{ false };
|
bool m_lclick_on_selected_thumb{ false };
|
||||||
ImVec2 m_active_thumb_center_on_lcklick;
|
bool m_suppress_process_behavior{ false };
|
||||||
|
ImRect m_active_thumb;
|
||||||
|
|
||||||
bool m_draw_lower_thumb{ true };
|
bool m_draw_lower_thumb{ true };
|
||||||
bool m_combine_thumbs { false };
|
bool m_combine_thumbs { false };
|
||||||
|
96
src/slic3r/GUI/RulerForDoubleSlider.cpp
Normal file
96
src/slic3r/GUI/RulerForDoubleSlider.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
///|/ 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 "RulerForDoubleSlider.hpp"
|
||||||
|
#include "libslic3r/CustomGCode.hpp"
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
using namespace CustomGCode;
|
||||||
|
|
||||||
|
namespace DoubleSlider {
|
||||||
|
|
||||||
|
static const double PIXELS_PER_SM_DEFAULT = 96./*DEFAULT_DPI*/ * 5. / 25.4;
|
||||||
|
|
||||||
|
void Ruler::init(const std::vector<double>& values, double scroll_step)
|
||||||
|
{
|
||||||
|
if (m_is_valid)
|
||||||
|
return;
|
||||||
|
max_values.clear();
|
||||||
|
max_values.reserve(std::count(values.begin(), values.end(), values.front()));
|
||||||
|
|
||||||
|
auto it = std::find(values.begin() + 1, values.end(), values.front());
|
||||||
|
while (it != values.end()) {
|
||||||
|
max_values.push_back(*(it - 1));
|
||||||
|
it = std::find(it + 1, values.end(), values.front());
|
||||||
|
}
|
||||||
|
max_values.push_back(*(it - 1));
|
||||||
|
|
||||||
|
m_is_valid = true;
|
||||||
|
update(values, scroll_step);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ruler::update(const std::vector<double>& values, double scroll_step)
|
||||||
|
{
|
||||||
|
if (!m_is_valid || values.empty() ||
|
||||||
|
// check if need to update ruler in respect to input values
|
||||||
|
(values.front() == m_min_val && values.back() == m_max_val && m_scroll_step == scroll_step && max_values.size() == m_max_values_cnt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_min_val = values.front();
|
||||||
|
m_max_val = values.back();
|
||||||
|
m_scroll_step = scroll_step;
|
||||||
|
m_max_values_cnt = max_values.size();
|
||||||
|
|
||||||
|
int pixels_per_sm = lround(m_scale * PIXELS_PER_SM_DEFAULT);
|
||||||
|
|
||||||
|
if (lround(scroll_step) > pixels_per_sm) {
|
||||||
|
long_step = -1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pow = -2;
|
||||||
|
int step = 0;
|
||||||
|
auto end_it = std::find(values.begin() + 1, values.end(), values.front());
|
||||||
|
|
||||||
|
while (pow < 3) {
|
||||||
|
for (int istep : {1, 2, 5}) {
|
||||||
|
double val = (double)istep * std::pow(10, pow);
|
||||||
|
auto val_it = std::lower_bound(values.begin(), end_it, val - epsilon());
|
||||||
|
|
||||||
|
if (val_it == values.end())
|
||||||
|
break;
|
||||||
|
int tick = val_it - values.begin();
|
||||||
|
|
||||||
|
// find next tick with istep
|
||||||
|
val *= 2;
|
||||||
|
val_it = std::lower_bound(values.begin(), end_it, val - epsilon());
|
||||||
|
// count of short ticks between ticks
|
||||||
|
int short_ticks_cnt = val_it == values.end() ? tick : val_it - values.begin() - tick;
|
||||||
|
|
||||||
|
if (lround(short_ticks_cnt * scroll_step) > pixels_per_sm) {
|
||||||
|
step = istep;
|
||||||
|
// there couldn't be more then 10 short ticks between ticks
|
||||||
|
short_step = 0.1 * short_ticks_cnt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (step > 0)
|
||||||
|
break;
|
||||||
|
pow++;
|
||||||
|
}
|
||||||
|
|
||||||
|
long_step = step == 0 ? -1.0 : (double)step * std::pow(10, pow);
|
||||||
|
if (long_step < 0)
|
||||||
|
short_step = long_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ruler::set_scale(double scale)
|
||||||
|
{
|
||||||
|
if (!is_approx(m_scale, scale))
|
||||||
|
m_scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // DoubleSlider
|
||||||
|
|
||||||
|
|
42
src/slic3r/GUI/RulerForDoubleSlider.hpp
Normal file
42
src/slic3r/GUI/RulerForDoubleSlider.hpp
Normal 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_RulerForDoubleSlider_hpp_
|
||||||
|
#define slic3r_GUI_RulerForDoubleSlider_hpp_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace DoubleSlider {
|
||||||
|
|
||||||
|
class Ruler
|
||||||
|
{
|
||||||
|
bool m_is_valid { false };
|
||||||
|
double m_scale { 1. };
|
||||||
|
double m_min_val;
|
||||||
|
double m_max_val;
|
||||||
|
double m_scroll_step;
|
||||||
|
size_t m_max_values_cnt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
double long_step;
|
||||||
|
double short_step;
|
||||||
|
std::vector<double> max_values;// max value for each object/instance in sequence print
|
||||||
|
// > 1 for sequential print
|
||||||
|
|
||||||
|
void init(const std::vector<double>& values, double scroll_step);
|
||||||
|
void update(const std::vector<double>& values, double scroll_step);
|
||||||
|
void set_scale(double scale);
|
||||||
|
void invalidate() { m_is_valid = false; }
|
||||||
|
bool is_ok() { return long_step > 0 && short_step > 0; }
|
||||||
|
size_t count() { return max_values.size(); }
|
||||||
|
bool valid() { return m_is_valid; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // DoubleSlider;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // slic3r_GUI_RulerForDoubleSlider_hpp_
|
Loading…
x
Reference in New Issue
Block a user