mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-26 06:34:32 +08:00
GUI for emboss SVG
This commit is contained in:
parent
3a6c85ef58
commit
1c44fcab9e
@ -365,9 +365,9 @@ IconManager::Icons init_icons(IconManager &mng, const GuiCfg &cfg)
|
|||||||
{"undo.svg", size, IconManager::RasterType::white_only_data}, // undo
|
{"undo.svg", size, IconManager::RasterType::white_only_data}, // undo
|
||||||
{"undo.svg", size, IconManager::RasterType::color}, // undo_hovered
|
{"undo.svg", size, IconManager::RasterType::color}, // undo_hovered
|
||||||
{"lock_closed.svg", size, IconManager::RasterType::white_only_data}, // lock,
|
{"lock_closed.svg", size, IconManager::RasterType::white_only_data}, // lock,
|
||||||
{"lock_closed_f.svg",size, IconManager::RasterType::white_only_data}, // lock_hovered,
|
{"lock_open_f.svg", size, IconManager::RasterType::white_only_data}, // lock_hovered
|
||||||
{"lock_open.svg", size, IconManager::RasterType::white_only_data}, // unlock,
|
{"lock_open.svg", size, IconManager::RasterType::white_only_data}, // unlock,
|
||||||
{"lock_open_f.svg", size, IconManager::RasterType::white_only_data} // unlock_hovered
|
{"lock_closed_f.svg",size, IconManager::RasterType::white_only_data} // unlock_hovered,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(init_types.size() == static_cast<size_t>(IconType::_count));
|
assert(init_types.size() == static_cast<size_t>(IconType::_count));
|
||||||
@ -624,6 +624,8 @@ void GLGizmoSVG::set_volume_by_selection()
|
|||||||
m_job_cancel = nullptr;
|
m_job_cancel = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_volume(); // clear cached data
|
||||||
|
|
||||||
m_volume = volume;
|
m_volume = volume;
|
||||||
m_volume_id = volume->id();
|
m_volume_id = volume->id();
|
||||||
m_volume_shape = *volume->emboss_shape; // copy
|
m_volume_shape = *volume->emboss_shape; // copy
|
||||||
@ -644,9 +646,12 @@ void GLGizmoSVG::reset_volume()
|
|||||||
m_volume = nullptr;
|
m_volume = nullptr;
|
||||||
m_volume_id.id = 0;
|
m_volume_id.id = 0;
|
||||||
m_volume_shape.shapes_with_ids.clear();
|
m_volume_shape.shapes_with_ids.clear();
|
||||||
|
m_filename_preview.clear();
|
||||||
|
|
||||||
if (m_texture.id != 0)
|
if (m_texture.id != 0) {
|
||||||
glsafe(::glDeleteTextures(1, &m_texture.id));
|
glsafe(::glDeleteTextures(1, &m_texture.id));
|
||||||
|
m_texture.id = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSVG::calculate_scale() {
|
void GLGizmoSVG::calculate_scale() {
|
||||||
@ -697,6 +702,7 @@ bool GLGizmoSVG::process()
|
|||||||
|
|
||||||
void GLGizmoSVG::close()
|
void GLGizmoSVG::close()
|
||||||
{
|
{
|
||||||
|
reset_volume();
|
||||||
// close gizmo == open it again
|
// close gizmo == open it again
|
||||||
auto& mng = m_parent.get_gizmos_manager();
|
auto& mng = m_parent.get_gizmos_manager();
|
||||||
if (mng.get_current_type() == GLGizmosManager::Svg)
|
if (mng.get_current_type() == GLGizmosManager::Svg)
|
||||||
@ -732,37 +738,71 @@ void GLGizmoSVG::draw_window()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSVG::draw_preview(){
|
void GLGizmoSVG::draw_preview(){
|
||||||
|
assert(m_volume->emboss_shape.has_value());
|
||||||
|
if (!m_volume->emboss_shape.has_value()) {
|
||||||
|
ImGui::Text("No embossed file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_volume->emboss_shape.has_value())
|
// init texture when not initialized yet.
|
||||||
ImGui::Text("SVG file path is %s", m_volume->emboss_shape->svg_file_path.c_str());
|
// drag&drop is out of rendering scope so texture must be created on this place
|
||||||
|
|
||||||
if (m_texture.id == 0)
|
if (m_texture.id == 0)
|
||||||
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
||||||
|
|
||||||
if (m_texture.id != 0) {
|
if (m_texture.id != 0) {
|
||||||
ImTextureID id = (void *) static_cast<intptr_t>(m_texture.id);
|
ImTextureID id = (void *) static_cast<intptr_t>(m_texture.id);
|
||||||
ImVec2 s(m_texture.width, m_texture.height);
|
ImVec2 s(m_texture.width, m_texture.height);
|
||||||
ImGui::Image(id, s);
|
ImGui::Image(id, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_filename_preview.empty()){
|
||||||
|
// create filename preview
|
||||||
|
m_filename_preview = get_file_name(m_volume->emboss_shape->svg_file_path);
|
||||||
|
m_filename_preview = ImGuiWrapper::trunc(m_filename_preview, m_gui_cfg->input_width);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("change file")) {
|
ImGui::BeginGroup();
|
||||||
m_volume_shape.shapes_with_ids = select_shape().shapes_with_ids;
|
|
||||||
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
// Remove space between filename and gray suffix ".svg"
|
||||||
process();
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
||||||
}
|
|
||||||
|
ImGui::Text("%s", m_filename_preview.c_str());
|
||||||
|
bool is_hovered = ImGui::IsItemHovered();
|
||||||
|
ImGui::SameLine();
|
||||||
|
m_imgui->text_colored(ImGuiWrapper::COL_GREY_LIGHT, ".svg");
|
||||||
|
ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing
|
||||||
|
|
||||||
|
is_hovered |= ImGui::IsItemHovered();
|
||||||
|
if (is_hovered) {
|
||||||
|
std::string tooltip = GUI::format(_L("SVG file path is \"%1%\" "), m_volume->emboss_shape->svg_file_path);
|
||||||
|
ImGui::SetTooltip("%s", tooltip.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Re-Load button
|
// Re-Load button
|
||||||
bool can_reload = !m_volume_shape.svg_file_path.empty();
|
bool can_reload = !m_volume_shape.svg_file_path.empty();
|
||||||
if (can_reload) {
|
if (can_reload) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (clickable(get_icon(m_icons, IconType::reset_value), get_icon(m_icons, IconType::reset_value_hover))) {
|
if (clickable(get_icon(m_icons, IconType::reset_value), get_icon(m_icons, IconType::reset_value_hover))) {
|
||||||
m_volume_shape.shapes_with_ids = select_shape(m_volume_shape.svg_file_path).shapes_with_ids;
|
if (!boost::filesystem::exists(m_volume_shape.svg_file_path)) {
|
||||||
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
m_volume_shape.svg_file_path.clear();
|
||||||
process();
|
} else {
|
||||||
|
m_volume_shape.shapes_with_ids = select_shape(m_volume_shape.svg_file_path).shapes_with_ids;
|
||||||
|
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
||||||
|
process();
|
||||||
|
}
|
||||||
} else if (ImGui::IsItemHovered())
|
} else if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip("%s", _u8L("Re-load SVG file from disk.").c_str());
|
ImGui::SetTooltip("%s", _u8L("Re-load SVG file from disk.").c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button(_u8L("Change file").c_str())) {
|
||||||
|
m_volume_shape.shapes_with_ids = select_shape().shapes_with_ids;
|
||||||
|
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSVG::draw_depth()
|
void GLGizmoSVG::draw_depth()
|
||||||
@ -794,46 +834,78 @@ void GLGizmoSVG::draw_size()
|
|||||||
ImGuiWrapper::text(m_gui_cfg->translations.size);
|
ImGuiWrapper::text(m_gui_cfg->translations.size);
|
||||||
|
|
||||||
bool use_inch = wxGetApp().app_config->get_bool("use_inches");
|
bool use_inch = wxGetApp().app_config->get_bool("use_inches");
|
||||||
float space = m_gui_cfg->icon_width / 2;
|
|
||||||
float input_width = m_gui_cfg->input_width / 2 - space / 2;
|
|
||||||
float second_offset = m_gui_cfg->input_offset + input_width + space;
|
|
||||||
|
|
||||||
ImGui::SameLine(m_gui_cfg->input_offset);
|
|
||||||
ImGui::SetNextItemWidth(input_width);
|
|
||||||
|
|
||||||
// TODO: cache it
|
// TODO: cache it
|
||||||
BoundingBox bb = get_extents(m_volume_shape.shapes_with_ids);
|
BoundingBox bb = get_extents(m_volume_shape.shapes_with_ids);
|
||||||
Point size = bb.size();
|
Point size = bb.size();
|
||||||
|
|
||||||
const char *size_format = (use_inch) ? "%.2f in" : "%.1f mm";
|
|
||||||
double step = -1.0;
|
|
||||||
double fast_step = -1.0;
|
|
||||||
double width = size.x() * m_volume_shape.scale;
|
double width = size.x() * m_volume_shape.scale;
|
||||||
if (use_inch) width *= ObjectManipulation::mm_to_in;
|
if (use_inch) width *= ObjectManipulation::mm_to_in;
|
||||||
|
|
||||||
ImGuiInputTextFlags flags = 0;
|
|
||||||
|
|
||||||
if (ImGui::InputDouble("##width", &width, step, fast_step, size_format, flags)) {
|
|
||||||
if (use_inch) width *= ObjectManipulation::in_to_mm;
|
|
||||||
m_volume_shape.scale = width / size.x();
|
|
||||||
process();
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered())
|
|
||||||
ImGui::SetTooltip("%s", _u8L("Width of SVG.").c_str());
|
|
||||||
|
|
||||||
ImGui::SameLine(second_offset);
|
|
||||||
ImGui::SetNextItemWidth(input_width);
|
|
||||||
|
|
||||||
double height = size.y() * m_volume_shape.scale;
|
double height = size.y() * m_volume_shape.scale;
|
||||||
if (use_inch) height *= ObjectManipulation::mm_to_in;
|
if (use_inch) height *= ObjectManipulation::mm_to_in;
|
||||||
if (ImGui::InputDouble("##height", &height, step, fast_step, size_format, flags)) {
|
|
||||||
if (use_inch) height *= ObjectManipulation::in_to_mm;
|
|
||||||
m_volume_shape.scale = height / size.y();
|
|
||||||
process();
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered())
|
|
||||||
ImGui::SetTooltip("%s", _u8L("Height of SVG.").c_str());
|
|
||||||
|
|
||||||
|
if (m_keep_ratio) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::setprecision(2) << width << " x " << height << " " << (use_inch ? "in" : "mm");
|
||||||
|
|
||||||
|
ImGui::SameLine(m_gui_cfg->input_offset);
|
||||||
|
ImGui::SetNextItemWidth(m_gui_cfg->input_width);
|
||||||
|
|
||||||
|
float width_f = width;
|
||||||
|
if (m_imgui->slider_float("##width_size_slider", &width_f, 5.f, 100.f, ss.str().c_str())) {
|
||||||
|
if (use_inch)
|
||||||
|
width_f *= ObjectManipulation::in_to_mm;
|
||||||
|
m_volume_shape.scale = width_f / size.x();
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGuiInputTextFlags flags = 0;
|
||||||
|
|
||||||
|
float space = m_gui_cfg->icon_width / 2;
|
||||||
|
float input_width = m_gui_cfg->input_width / 2 - space / 2;
|
||||||
|
float second_offset = m_gui_cfg->input_offset + input_width + space;
|
||||||
|
|
||||||
|
const char *size_format = (use_inch) ? "%.2f in" : "%.1f mm";
|
||||||
|
double step = -1.0;
|
||||||
|
double fast_step = -1.0;
|
||||||
|
|
||||||
|
ImGui::SameLine(m_gui_cfg->input_offset);
|
||||||
|
ImGui::SetNextItemWidth(input_width);
|
||||||
|
if (ImGui::InputDouble("##width", &width, step, fast_step, size_format, flags)) {
|
||||||
|
if (use_inch)
|
||||||
|
width *= ObjectManipulation::in_to_mm;
|
||||||
|
m_volume_shape.scale = width / size.x();
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("%s", _u8L("Width of SVG.").c_str());
|
||||||
|
|
||||||
|
ImGui::SameLine(second_offset);
|
||||||
|
ImGui::SetNextItemWidth(input_width);
|
||||||
|
if (ImGui::InputDouble("##height", &height, step, fast_step, size_format, flags)) {
|
||||||
|
if (use_inch)
|
||||||
|
height *= ObjectManipulation::in_to_mm;
|
||||||
|
m_volume_shape.scale = height / size.y();
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("%s", _u8L("Height of SVG.").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock on ratio m_keep_ratio
|
||||||
|
ImGui::SameLine(m_gui_cfg->lock_offset);
|
||||||
|
const IconManager::Icon &icon = get_icon(m_icons, m_keep_ratio ? IconType::lock : IconType::unlock);
|
||||||
|
const IconManager::Icon &icon_hover = get_icon(m_icons, m_keep_ratio ? IconType::lock_hover : IconType::unlock_hover);
|
||||||
|
if (button(icon, icon_hover, icon))
|
||||||
|
m_keep_ratio = !m_keep_ratio;
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("%s", (m_keep_ratio ?
|
||||||
|
_u8L("Free set of width and height value."):
|
||||||
|
_u8L("Keep same ratio of width to height.")
|
||||||
|
).c_str());
|
||||||
|
|
||||||
|
|
||||||
|
// reset button
|
||||||
bool can_reset = !is_approx(m_volume_shape.scale, DEFAULT_SCALE);
|
bool can_reset = !is_approx(m_volume_shape.scale, DEFAULT_SCALE);
|
||||||
if (can_reset) {
|
if (can_reset) {
|
||||||
if (reset_button(m_icons)) {
|
if (reset_button(m_icons)) {
|
||||||
@ -1186,16 +1258,21 @@ EmbossShape select_shape(std::string_view filepath)
|
|||||||
|
|
||||||
if (filepath.empty()) {
|
if (filepath.empty()) {
|
||||||
shape.svg_file_path = choose_svg_file();
|
shape.svg_file_path = choose_svg_file();
|
||||||
if (shape.svg_file_path.empty())
|
if (shape.svg_file_path.empty())
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
shape.svg_file_path = filepath; // copy
|
shape.svg_file_path = filepath; // copy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists(shape.svg_file_path) ||
|
||||||
|
!boost::algorithm::iends_with(shape.svg_file_path, ".svg"))
|
||||||
|
return {};
|
||||||
|
|
||||||
const char *unit_mm{"mm"};
|
const char *unit_mm{"mm"};
|
||||||
// common used DPI is 96 or 72
|
// common used DPI is 96 or 72
|
||||||
float dpi = 96.0f;
|
float dpi = 96.0f;
|
||||||
NSVGimage *image = nsvgParseFromFile(shape.svg_file_path.c_str(), unit_mm, dpi);
|
NSVGimage *image = nsvgParseFromFile(shape.svg_file_path.c_str(), unit_mm, dpi);
|
||||||
|
if (image == nullptr) return {};
|
||||||
ScopeGuard sg([image]() { nsvgDelete(image); });
|
ScopeGuard sg([image]() { nsvgDelete(image); });
|
||||||
|
|
||||||
shape.scale = DEFAULT_SCALE; // loaded in mm
|
shape.scale = DEFAULT_SCALE; // loaded in mm
|
||||||
|
@ -157,6 +157,7 @@ private:
|
|||||||
// When true keep up vector otherwise relative rotation
|
// When true keep up vector otherwise relative rotation
|
||||||
bool m_keep_up = true;
|
bool m_keep_up = true;
|
||||||
|
|
||||||
|
|
||||||
bool m_keep_ratio = true;
|
bool m_keep_ratio = true;
|
||||||
|
|
||||||
// setted only when wanted to use - not all the time
|
// setted only when wanted to use - not all the time
|
||||||
@ -171,9 +172,10 @@ private:
|
|||||||
void calculate_scale();
|
void calculate_scale();
|
||||||
|
|
||||||
// keep SVG data rendered on GPU
|
// keep SVG data rendered on GPU
|
||||||
|
|
||||||
Texture m_texture;
|
Texture m_texture;
|
||||||
|
|
||||||
|
std::string m_filename_preview;
|
||||||
|
|
||||||
IconManager m_icon_manager;
|
IconManager m_icon_manager;
|
||||||
IconManager::Icons m_icons;
|
IconManager::Icons m_icons;
|
||||||
|
|
||||||
|
@ -344,6 +344,7 @@ void priv::draw_transparent_icon(const IconManager::Icon &icon)
|
|||||||
draw(icon_px);
|
draw(icon_px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "imgui/imgui_internal.h" //ImGuiWindow
|
||||||
namespace Slic3r::GUI {
|
namespace Slic3r::GUI {
|
||||||
|
|
||||||
void draw(const IconManager::Icon &icon, const ImVec2 &size, const ImVec4 &tint_col, const ImVec4 &border_col)
|
void draw(const IconManager::Icon &icon, const ImVec2 &size, const ImVec4 &tint_col, const ImVec4 &border_col)
|
||||||
@ -364,7 +365,10 @@ void draw(const IconManager::Icon &icon, const ImVec2 &size, const ImVec4 &tint_
|
|||||||
bool clickable(const IconManager::Icon &icon, const IconManager::Icon &icon_hover)
|
bool clickable(const IconManager::Icon &icon, const IconManager::Icon &icon_hover)
|
||||||
{
|
{
|
||||||
// check of hover
|
// check of hover
|
||||||
float cursor_x = ImGui::GetCursorPosX();
|
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||||
|
float cursor_x = ImGui::GetCursorPosX()
|
||||||
|
- window->DC.GroupOffset.x
|
||||||
|
- window->DC.ColumnsOffset.x;
|
||||||
priv::draw_transparent_icon(icon);
|
priv::draw_transparent_icon(icon);
|
||||||
ImGui::SameLine(cursor_x);
|
ImGui::SameLine(cursor_x);
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user