mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-13 17:51:47 +08:00
Add icons(refresh and burn) to svg emboss
Add NSVG image to shape
This commit is contained in:
parent
ed10fefba8
commit
d530831e35
4
resources/icons/burn.svg
Normal file
4
resources/icons/burn.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
|
||||||
|
<path fill="#808080" d="M 10.324265,12.637091 C 9.7126185,11.801826 9.4455652,11.319769 9.3860031,10.943437 9.3387131,10.644653 9.2775165,10.67725 9.032793,11.131535 8.8565876,11.45863 8.806364,11.904627 8.9008009,12.303679 8.330577,11.894019 7.6015175,10.031363 7.7096999,9.1284851 5.381808,10.598103 4.7271155,13.939753 5,16 2.9751051,14.608227 1.2851951,13.046842 1.3078808,10.57598 1.3305665,8.1051179 3.8432395,6.4490194 3.8697024,4.1713523 3.8727624,3.3745518 3.8421277,3.3793755 4.5118024,4.0701844 5.3014406,5.073513 5.8791344,5.964439 5.6521467,7.0731381 6.1486239,6.623741 6.3341015,5.940722 6.5401623,5.4070849 6.8689362,3.4222537 6.7021829,1.5642078 6,0 c 2.5998224,0.67409817 4.550997,3.5888298 4.623306,5.6887828 l 9.3e-4,0.4921817 C 11.260843,5.1624272 11.966175,4.3725405 13,4 12.774748,6.4272659 14.752236,8.539235 14.683585,10.819702 14.614934,13.100169 13.178608,15.41894 11,16 11.750123,14.792953 10.874074,13.393198 10.324265,12.637091 Z" />
|
||||||
|
<path fill="#ed6b21" d="M 9.032793,11.131535 C 8.8565876,11.45863 8.806364,11.904627 8.9008009,12.303679 8.2684185,12.02479 7.7175594,10.368983 7.6751289,9.4545414 7.7066738,9.2878597 7.7222018,9.1411316 7.7097002,9.1284851 8.5239771,6.6708553 5.893441,7.0819045 6.5401623,5.4070849 6.8689362,3.4222537 6.7021829,1.5642078 6,0 c 2.5998224,0.67409817 4.550997,3.5888298 4.623306,5.6887828 l 9.3e-4,0.4921817 c -0.04706,1.5271028 -0.04706,2.5643146 -1.591443,4.9505705 z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
4
resources/icons/refresh.svg
Normal file
4
resources/icons/refresh.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
|
||||||
|
<path fill="#ed6b21" d="m 0.80996126,4.2067338 c 0,0 1.45662384,-2.2486082 3.76076774,-3.45466511 2.3041438,-1.2060569 5.1439072,-0.85800021 7.005512,0.31082271 1.861604,1.1704417 2.488671,2.1563326 2.488671,2.1563326 l 1.603592,-0.9146606 c 0,0 0.331496,-0.1651245 0.331496,0.2185472 v 5.7388883 c 0,0 0,0.5115624 -0.387017,0.3286302 C 15.288019,8.4368366 11.764034,6.4326776 10.655236,5.801319 10.046132,5.5293491 10.581752,5.309183 10.581752,5.309183 l 1.548071,-0.8855209 c 0,0 -0.883446,-1.1056871 -2.1751379,-1.6917175 C 8.5715456,2.0147859 7.2765874,1.9289859 5.6909576,2.5279672 4.6572773,2.9181146 3.4390694,3.9185752 2.5621557,5.3966019 Z" />
|
||||||
|
<path fill="#808080" d="m 15.19004,11.792751 c 0,0 -1.456624,2.248608 -3.760768,3.454665 C 9.125128,16.453472 6.2853646,16.107035 4.4237602,14.936593 2.5621557,13.766151 1.935089,12.78026 1.935089,12.78026 l -1.60359274,0.913042 c 0,0 -0.3314962496,0.165125 -0.3314962496,-0.218547 V 7.7342477 c 0,0 0,-0.5115623 0.3870177796,-0.3286303 0.32496429,0.1537925 3.84894891,2.1579516 4.95774671,2.7893106 0.609104,0.271969 0.073485,0.492136 0.073485,0.492136 l -1.5480712,0.88552 c 0,0 0.8834456,1.105688 2.1751379,1.691718 1.3831395,0.720396 2.6780976,0.806196 4.2637278,0.207215 1.033681,-0.390147 2.251888,-1.390608 3.128802,-2.868635 z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <memory> // unique_ptr
|
||||||
#include <cereal/cereal.hpp>
|
#include <cereal/cereal.hpp>
|
||||||
#include <cereal/types/string.hpp>
|
#include <cereal/types/string.hpp>
|
||||||
#include <cereal/types/vector.hpp>
|
#include <cereal/types/vector.hpp>
|
||||||
@ -11,6 +12,7 @@
|
|||||||
#include "Point.hpp" // Transform3d
|
#include "Point.hpp" // Transform3d
|
||||||
#include "ExPolygon.hpp"
|
#include "ExPolygon.hpp"
|
||||||
#include "ExPolygonSerialize.hpp"
|
#include "ExPolygonSerialize.hpp"
|
||||||
|
#include "nanosvg/nanosvg.h" // NSVGimage
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -83,19 +85,31 @@ struct EmbossShape
|
|||||||
// Stored_Transform3d * fix_3mf_tr = Transform3d_before_store_to_3mf
|
// Stored_Transform3d * fix_3mf_tr = Transform3d_before_store_to_3mf
|
||||||
std::optional<Slic3r::Transform3d> fix_3mf_tr;
|
std::optional<Slic3r::Transform3d> fix_3mf_tr;
|
||||||
|
|
||||||
// file(.svg) path to source of shape
|
struct SvgFile {
|
||||||
// When empty can't reload from disk
|
// File(.svg) path on local computer
|
||||||
std::string svg_file_path;
|
// When empty can't reload from disk
|
||||||
|
std::string path;
|
||||||
|
|
||||||
|
// File path into .3mf(.zip)
|
||||||
|
// When empty svg is not stored into .3mf file yet.
|
||||||
|
// and will create dialog to delete private data on save.
|
||||||
|
std::string path_in_3mf;
|
||||||
|
|
||||||
|
// Loaded svg file data.
|
||||||
|
// !!! It is not serialized on undo/redo stack
|
||||||
|
std::shared_ptr<NSVGimage> image;
|
||||||
|
};
|
||||||
|
SvgFile svg_file;
|
||||||
|
|
||||||
// undo / redo stack recovery
|
// undo / redo stack recovery
|
||||||
template<class Archive> void save(Archive &ar) const
|
template<class Archive> void save(Archive &ar) const
|
||||||
{
|
{
|
||||||
ar(shapes_with_ids, scale, projection, svg_file_path);
|
ar(shapes_with_ids, scale, projection, svg_file.path, svg_file.path_in_3mf);
|
||||||
cereal::save(ar, fix_3mf_tr);
|
cereal::save(ar, fix_3mf_tr);
|
||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar)
|
template<class Archive> void load(Archive &ar)
|
||||||
{
|
{
|
||||||
ar(shapes_with_ids, scale, projection, svg_file_path);
|
ar(shapes_with_ids, scale, projection, svg_file.path, svg_file.path_in_3mf);
|
||||||
cereal::load(ar, fix_3mf_tr);
|
cereal::load(ar, fix_3mf_tr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3691,7 +3691,7 @@ std::string to_string(const ExPolygonsWithIds &shapes)
|
|||||||
|
|
||||||
void to_xml(std::stringstream &stream, const EmbossShape &es, const ModelVolume &volume) {
|
void to_xml(std::stringstream &stream, const EmbossShape &es, const ModelVolume &volume) {
|
||||||
stream << " <" << SHAPE_TAG << " ";
|
stream << " <" << SHAPE_TAG << " ";
|
||||||
stream << SVG_FILE_PATH_ATTR << "=\"" << xml_escape_double_quotes_attribute_value(es.svg_file_path) << "\" ";
|
stream << SVG_FILE_PATH_ATTR << "=\"" << xml_escape_double_quotes_attribute_value(es.svg_file.path) << "\" ";
|
||||||
stream << SHAPE_SCALE_ATTR << "=\"" << es.scale << "\" ";
|
stream << SHAPE_SCALE_ATTR << "=\"" << es.scale << "\" ";
|
||||||
|
|
||||||
std::string expolygons_str = to_string(es.shapes_with_ids); // cereal serialize expolygons
|
std::string expolygons_str = to_string(es.shapes_with_ids); // cereal serialize expolygons
|
||||||
|
@ -23,10 +23,10 @@ Point::coord_type to_coor(float val, float scale) { return static_cast<Point::co
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
Polygons to_polygons(NSVGimage *image, float tessTol, int max_level, float scale, bool is_y_negative)
|
Polygons to_polygons(const NSVGimage &image, float tessTol, int max_level, float scale, bool is_y_negative)
|
||||||
{
|
{
|
||||||
Polygons polygons;
|
Polygons polygons;
|
||||||
for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
|
for (NSVGshape *shape = image.shapes; shape != NULL; shape = shape->next) {
|
||||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE))
|
if (!(shape->flags & NSVG_FLAGS_VISIBLE))
|
||||||
continue;
|
continue;
|
||||||
if (shape->fill.type == NSVG_PAINT_NONE)
|
if (shape->fill.type == NSVG_PAINT_NONE)
|
||||||
@ -64,10 +64,16 @@ Polygons to_polygons(NSVGimage *image, float tessTol, int max_level, float scale
|
|||||||
return polygons;
|
return polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons to_expolygons(NSVGimage *image, float tessTol, int max_level, float scale, bool is_y_negative){
|
ExPolygons to_expolygons(const NSVGimage &image, float tessTol, int max_level, float scale, bool is_y_negative){
|
||||||
return union_ex(to_polygons(image, tessTol, max_level, scale, is_y_negative));
|
return union_ex(to_polygons(image, tessTol, max_level, scale, is_y_negative));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSVGimage_ptr nsvgParseFromFile(const std::string &filename, const char *units, float dpi)
|
||||||
|
{
|
||||||
|
NSVGimage *image = ::nsvgParseFromFile(filename.c_str(), units, dpi);
|
||||||
|
return {image, ::nsvgDelete};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef slic3r_NSVGUtils_hpp_
|
#ifndef slic3r_NSVGUtils_hpp_
|
||||||
#define slic3r_NSVGUtils_hpp_
|
#define slic3r_NSVGUtils_hpp_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include "Polygon.hpp"
|
#include "Polygon.hpp"
|
||||||
#include "ExPolygon.hpp"
|
#include "ExPolygon.hpp"
|
||||||
#include "nanosvg/nanosvg.h" // load SVG file
|
#include "nanosvg/nanosvg.h" // load SVG file
|
||||||
@ -19,8 +21,11 @@ namespace Slic3r {
|
|||||||
/// NOTE: Every point coor from image(float) is multiplied by scale and rounded to integer</param>
|
/// NOTE: Every point coor from image(float) is multiplied by scale and rounded to integer</param>
|
||||||
/// <param name="is_y_negative">Flag is y negative, when true than y coor is multiplied by -1</param>
|
/// <param name="is_y_negative">Flag is y negative, when true than y coor is multiplied by -1</param>
|
||||||
/// <returns>Polygons extracted from svg</returns>
|
/// <returns>Polygons extracted from svg</returns>
|
||||||
Polygons to_polygons(NSVGimage *image, float tessTol = 10., int max_level = 10, float scale = 1.f, bool is_y_negative = true);
|
Polygons to_polygons(const NSVGimage &image, float tessTol = 10., int max_level = 10, float scale = 1.f, bool is_y_negative = true);
|
||||||
ExPolygons to_expolygons(NSVGimage *image, float tessTol = 10., int max_level = 10, float scale = 1.f, bool is_y_negative = true);
|
ExPolygons to_expolygons(const NSVGimage &image, float tessTol = 10., int max_level = 10, float scale = 1.f, bool is_y_negative = true);
|
||||||
|
|
||||||
|
using NSVGimage_ptr = std::unique_ptr<NSVGimage, void (*)(NSVGimage*)>;
|
||||||
|
NSVGimage_ptr nsvgParseFromFile(const std::string& filename, const char *units = "mm", float dpi = 96.0f);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
#endif // slic3r_NSVGUtils_hpp_
|
#endif // slic3r_NSVGUtils_hpp_
|
||||||
|
@ -68,7 +68,7 @@ std::string choose_svg_file();
|
|||||||
/// Let user to choose file with (S)calable (V)ector (G)raphics - SVG.
|
/// Let user to choose file with (S)calable (V)ector (G)raphics - SVG.
|
||||||
/// Than let select contour
|
/// Than let select contour
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filepath">SVG file path</param>
|
/// <param name="filepath">SVG file path, when empty promt user to select one</param>
|
||||||
/// <returns>EmbossShape to create</returns>
|
/// <returns>EmbossShape to create</returns>
|
||||||
EmbossShape select_shape(std::string_view filepath = "");
|
EmbossShape select_shape(std::string_view filepath = "");
|
||||||
|
|
||||||
@ -80,14 +80,6 @@ EmbossShape select_shape(std::string_view filepath = "");
|
|||||||
/// <returns>Base data for emboss SVG</returns>
|
/// <returns>Base data for emboss SVG</returns>
|
||||||
DataBasePtr create_emboss_data_base(std::shared_ptr<std::atomic<bool>> &cancel, std::string_view filepath = "");
|
DataBasePtr create_emboss_data_base(std::shared_ptr<std::atomic<bool>> &cancel, std::string_view filepath = "");
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create symbol '?' as default shape
|
|
||||||
/// without source file
|
|
||||||
/// with size 2cm
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Default shape to emboss</returns>
|
|
||||||
ExPolygons default_shape();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Separate file name from file path.
|
/// Separate file name from file path.
|
||||||
/// String after last delimiter and before last point
|
/// String after last delimiter and before last point
|
||||||
@ -115,6 +107,12 @@ CreateVolumeParams create_input(GLCanvas3D &canvas, RaycastManager &raycaster, M
|
|||||||
enum class IconType : unsigned {
|
enum class IconType : unsigned {
|
||||||
reset_value,
|
reset_value,
|
||||||
reset_value_hover,
|
reset_value_hover,
|
||||||
|
refresh,
|
||||||
|
refresh_hover,
|
||||||
|
change_file,
|
||||||
|
change_file_hover,
|
||||||
|
bake,
|
||||||
|
bake_hover,
|
||||||
lock,
|
lock,
|
||||||
lock_hover,
|
lock_hover,
|
||||||
unlock,
|
unlock,
|
||||||
@ -126,6 +124,8 @@ enum class IconType : unsigned {
|
|||||||
// automatic calc of icon's count
|
// automatic calc of icon's count
|
||||||
_count
|
_count
|
||||||
};
|
};
|
||||||
|
// Do not forgot add loading of file in funtion:
|
||||||
|
// IconManager::Icons init_icons(
|
||||||
|
|
||||||
const IconManager::Icon &get_icon(const IconManager::Icons &icons, IconType type) {
|
const IconManager::Icon &get_icon(const IconManager::Icons &icons, IconType type) {
|
||||||
return *icons[static_cast<unsigned>(type)]; }
|
return *icons[static_cast<unsigned>(type)]; }
|
||||||
@ -140,7 +140,7 @@ struct GuiCfg
|
|||||||
float main_toolbar_height;
|
float main_toolbar_height;
|
||||||
|
|
||||||
// Define bigger size(width or height)
|
// Define bigger size(width or height)
|
||||||
unsigned texture_max_size_px = 64;
|
unsigned texture_max_size_px = 256;
|
||||||
|
|
||||||
// Zero means it is calculated in init function
|
// Zero means it is calculated in init function
|
||||||
ImVec2 minimal_window_size = ImVec2(0, 0);
|
ImVec2 minimal_window_size = ImVec2(0, 0);
|
||||||
@ -385,6 +385,12 @@ IconManager::Icons init_icons(IconManager &mng, const GuiCfg &cfg)
|
|||||||
IconManager::InitTypes init_types{
|
IconManager::InitTypes init_types{
|
||||||
{"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
|
||||||
|
{"refresh.svg", size, IconManager::RasterType::white_only_data}, // refresh
|
||||||
|
{"refresh.svg", size, IconManager::RasterType::color}, // refresh_hovered
|
||||||
|
{"open.svg", size, IconManager::RasterType::white_only_data}, // changhe_file
|
||||||
|
{"open.svg", size, IconManager::RasterType::color}, // changhe_file_hovered
|
||||||
|
{"burn.svg", size, IconManager::RasterType::white_only_data}, // bake_file
|
||||||
|
{"burn.svg", size, IconManager::RasterType::color}, // bake_hovered
|
||||||
{"lock_closed.svg", size, IconManager::RasterType::white_only_data}, // lock
|
{"lock_closed.svg", size, IconManager::RasterType::white_only_data}, // lock
|
||||||
{"lock_open_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
|
||||||
@ -554,7 +560,7 @@ bool init_texture(Texture &texture, const ModelVolume &mv, unsigned max_size_px)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const EmbossShape &es = *mv.emboss_shape;
|
const EmbossShape &es = *mv.emboss_shape;
|
||||||
const std::string &filepath = es.svg_file_path;
|
const std::string &filepath = es.svg_file.path;
|
||||||
if (filepath.empty())
|
if (filepath.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -566,7 +572,7 @@ bool init_texture(Texture &texture, const ModelVolume &mv, unsigned max_size_px)
|
|||||||
ScopeGuard sg_image([image]() { nsvgDelete(image); });
|
ScopeGuard sg_image([image]() { nsvgDelete(image); });
|
||||||
|
|
||||||
// NOTE: Can not use es.shape --> it is aligned and one need offset in svg
|
// NOTE: Can not use es.shape --> it is aligned and one need offset in svg
|
||||||
ExPolygons shape = to_expolygons(image);
|
ExPolygons shape = to_expolygons(*image);
|
||||||
if (shape.empty())
|
if (shape.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -793,14 +799,10 @@ bool GLGizmoSVG::draw_preview(){
|
|||||||
|
|
||||||
if (m_filename_preview.empty()){
|
if (m_filename_preview.empty()){
|
||||||
// create filename preview
|
// create filename preview
|
||||||
m_filename_preview = get_file_name(m_volume->emboss_shape->svg_file_path);
|
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);
|
m_filename_preview = ImGuiWrapper::trunc(m_filename_preview, m_gui_cfg->input_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::BeginGroup();
|
|
||||||
ScopeGuard sg_group([]() { ImGui::EndGroup(); });
|
|
||||||
|
|
||||||
// Remove space between filename and gray suffix ".svg"
|
// Remove space between filename and gray suffix ".svg"
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
||||||
|
|
||||||
@ -812,19 +814,19 @@ bool GLGizmoSVG::draw_preview(){
|
|||||||
|
|
||||||
is_hovered |= ImGui::IsItemHovered();
|
is_hovered |= ImGui::IsItemHovered();
|
||||||
if (is_hovered) {
|
if (is_hovered) {
|
||||||
std::string tooltip = GUI::format(_L("SVG file path is \"%1%\" "), m_volume->emboss_shape->svg_file_path);
|
std::string tooltip = GUI::format(_L("SVG file path is \"%1%\" "), m_volume->emboss_shape->svg_file.path);
|
||||||
ImGui::SetTooltip("%s", tooltip.c_str());
|
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::refresh), get_icon(m_icons, IconType::refresh_hover))) {
|
||||||
if (!boost::filesystem::exists(m_volume_shape.svg_file_path)) {
|
if (!boost::filesystem::exists(m_volume_shape.svg_file.path)) {
|
||||||
m_volume_shape.svg_file_path.clear();
|
m_volume_shape.svg_file.path.clear();
|
||||||
} else {
|
} else {
|
||||||
m_volume_shape.shapes_with_ids = select_shape(m_volume_shape.svg_file_path).shapes_with_ids;
|
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);
|
init_texture(m_texture, *m_volume, m_gui_cfg->texture_max_size_px);
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
@ -832,19 +834,22 @@ bool GLGizmoSVG::draw_preview(){
|
|||||||
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())) {
|
ImGui::SameLine();
|
||||||
|
if (clickable(get_icon(m_icons, IconType::change_file), get_icon(m_icons, IconType::change_file_hover))) {
|
||||||
m_volume_shape.shapes_with_ids = select_shape().shapes_with_ids;
|
m_volume_shape.shapes_with_ids = select_shape().shapes_with_ids;
|
||||||
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);
|
||||||
process();
|
process();
|
||||||
|
} else if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("%s", _u8L("Change to another .svg file").c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button(_u8L("Bake").c_str())) {
|
if (clickable(get_icon(m_icons, IconType::bake), get_icon(m_icons, IconType::bake_hover))) {
|
||||||
m_volume->emboss_shape.reset();
|
m_volume->emboss_shape.reset();
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
} else if (ImGui::IsItemHovered()) {
|
} else if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("%s", _u8L("Remove connection to source file to take care about copyright").c_str());
|
ImGui::SetTooltip("%s", _u8L("Bake to uneditable part and save copyright of svg").c_str());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1221,7 +1226,7 @@ std::string get_file_name(const std::string &file_path)
|
|||||||
|
|
||||||
std::string volume_name(const EmbossShape &shape)
|
std::string volume_name(const EmbossShape &shape)
|
||||||
{
|
{
|
||||||
std::string file_name = get_file_name(shape.svg_file_path);
|
std::string file_name = get_file_name(shape.svg_file.path);
|
||||||
if (!file_name.empty())
|
if (!file_name.empty())
|
||||||
return file_name;
|
return file_name;
|
||||||
return "SVG shape";
|
return "SVG shape";
|
||||||
@ -1244,7 +1249,7 @@ GuiCfg create_gui_configuration() {
|
|||||||
|
|
||||||
float space = line_height_with_spacing - line_height;
|
float space = line_height_with_spacing - line_height;
|
||||||
|
|
||||||
cfg.icon_width = std::floor(line_height/8)*8;
|
cfg.icon_width = std::max(std::round(line_height/8)*8, 8.f);
|
||||||
|
|
||||||
GuiCfg::Translations &tr = cfg.translations;
|
GuiCfg::Translations &tr = cfg.translations;
|
||||||
|
|
||||||
@ -1271,7 +1276,7 @@ GuiCfg create_gui_configuration() {
|
|||||||
ImVec2 letter_m_size = ImGui::CalcTextSize("M");
|
ImVec2 letter_m_size = ImGui::CalcTextSize("M");
|
||||||
const float count_letter_M_in_input = 12.f;
|
const float count_letter_M_in_input = 12.f;
|
||||||
cfg.input_width = letter_m_size.x * count_letter_M_in_input;
|
cfg.input_width = letter_m_size.x * count_letter_M_in_input;
|
||||||
|
cfg.texture_max_size_px = std::round((cfg.input_width + cfg.input_offset + cfg.icon_width +space)/8) * 8;
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1299,8 +1304,19 @@ std::string choose_svg_file()
|
|||||||
if (input_files.size() != 1)
|
if (input_files.size() != 1)
|
||||||
BOOST_LOG_TRIVIAL(warning) << "SVG file dialog result contain multiple files but only first is used.";
|
BOOST_LOG_TRIVIAL(warning) << "SVG file dialog result contain multiple files but only first is used.";
|
||||||
|
|
||||||
auto &input_file = input_files.front();
|
auto &input_file = input_files.front();
|
||||||
std::string path = std::string(input_file.c_str());
|
std::string path = std::string(input_file.c_str());
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists(path)) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "SVG file dialog return invalid path.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::algorithm::iends_with(path, ".svg")) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "SVG file dialog return path without '.svg' tail";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1309,32 +1325,6 @@ void translate(ExPolygons &expolys, const Point &p) {
|
|||||||
expoly.translate(p);
|
expoly.translate(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSVGimage *parse_from_file(const char *filepath){
|
|
||||||
const char *unit_mm{"mm"};
|
|
||||||
// common used DPI is 96 or 72
|
|
||||||
float dpi = 96.0f;
|
|
||||||
return nsvgParseFromFile(filepath, unit_mm, dpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExPolygons default_shape()
|
|
||||||
{
|
|
||||||
std::string file = Slic3r::resources_dir() + "/icons/question.svg";
|
|
||||||
assert(boost::filesystem::exists(file));
|
|
||||||
NSVGimage *image = parse_from_file(file.c_str());
|
|
||||||
assert(image != nullptr);
|
|
||||||
|
|
||||||
// tesselation tolerance
|
|
||||||
float tol = 1e-2f;
|
|
||||||
int max_level = 10;
|
|
||||||
float scale = static_cast<float>(2. / DEFAULT_SCALE);
|
|
||||||
bool is_y_negative = true;
|
|
||||||
ExPolygons shape = to_expolygons(image, tol, max_level, scale, is_y_negative);
|
|
||||||
assert(!shape.empty());
|
|
||||||
|
|
||||||
nsvgDelete(image);
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmbossShape select_shape(std::string_view filepath)
|
EmbossShape select_shape(std::string_view filepath)
|
||||||
{
|
{
|
||||||
EmbossShape shape;
|
EmbossShape shape;
|
||||||
@ -1342,32 +1332,42 @@ EmbossShape select_shape(std::string_view filepath)
|
|||||||
shape.projection.use_surface = false;
|
shape.projection.use_surface = false;
|
||||||
|
|
||||||
if (filepath.empty()) {
|
if (filepath.empty()) {
|
||||||
shape.svg_file_path = choose_svg_file();
|
// When empty open file dialog
|
||||||
if (shape.svg_file_path.empty())
|
shape.svg_file.path = choose_svg_file();
|
||||||
return {};
|
if (shape.svg_file.path.empty())
|
||||||
|
return {}; // file was not selected
|
||||||
} else {
|
} else {
|
||||||
shape.svg_file_path = filepath; // copy
|
shape.svg_file.path = filepath; // copy
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists(shape.svg_file.path)) {
|
||||||
|
show_error(nullptr, GUI::format(_u8L("File(%1%) does NOT exists."), shape.svg_file.path));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!boost::filesystem::exists(shape.svg_file_path) ||
|
if (!boost::algorithm::iends_with(shape.svg_file.path, ".svg")){
|
||||||
!boost::algorithm::iends_with(shape.svg_file_path, ".svg"))
|
show_error(nullptr, GUI::format(_u8L("File has to end with \".svg\" but you select: %1%"), shape.svg_file.path));
|
||||||
return {};
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
NSVGimage *image = parse_from_file(shape.svg_file_path.c_str());
|
shape.svg_file.image = nsvgParseFromFile(shape.svg_file.path);
|
||||||
if (image == nullptr) return {};
|
if (shape.svg_file.image.get() == nullptr) {
|
||||||
ScopeGuard sg([image]() { nsvgDelete(image); });
|
show_error(nullptr, GUI::format(_u8L("Nano SVG parser can't load from file(%1%)."), shape.svg_file.path));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
shape.scale = DEFAULT_SCALE; // loaded in mm
|
shape.scale = DEFAULT_SCALE; // loaded in mm
|
||||||
|
|
||||||
constexpr float tesselation_tolerance = 1e-2f;
|
constexpr float tesselation_tolerance = 1e-2f;
|
||||||
int max_level = 10;
|
int max_level = 10;
|
||||||
float scale = static_cast<float>(1 / shape.scale);
|
float scale = static_cast<float>(1 / shape.scale);
|
||||||
bool is_y_negative = true;
|
bool is_y_negative = true;
|
||||||
ExPolygons expoly = to_expolygons(image, tesselation_tolerance, max_level, scale, is_y_negative);
|
ExPolygons expoly = to_expolygons(*shape.svg_file.image, tesselation_tolerance, max_level, scale, is_y_negative);
|
||||||
|
|
||||||
// Must contain some shapes !!!
|
// Must contain some shapes !!!
|
||||||
if (expoly.empty())
|
if (expoly.empty()) {
|
||||||
expoly = default_shape();
|
show_error(nullptr, GUI::format(_u8L("SVG file(%1%) do NOT contain path to be able embossed."), shape.svg_file.path));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// SVG is used as centered
|
// SVG is used as centered
|
||||||
// Do not disturb user by settings of pivot position
|
// Do not disturb user by settings of pivot position
|
||||||
|
@ -244,7 +244,7 @@ void scale(Polygons &polygons, double multiplicator) {
|
|||||||
Polygons load_polygons(const std::string &svg_file) {
|
Polygons load_polygons(const std::string &svg_file) {
|
||||||
std::string file_path = TEST_DATA_DIR PATH_SEPARATOR + svg_file;
|
std::string file_path = TEST_DATA_DIR PATH_SEPARATOR + svg_file;
|
||||||
NSVGimage *image = nsvgParseFromFile(file_path.c_str(), "px", 96.0f);
|
NSVGimage *image = nsvgParseFromFile(file_path.c_str(), "px", 96.0f);
|
||||||
Polygons polygons = to_polygons(image);
|
Polygons polygons = to_polygons(*image);
|
||||||
nsvgDelete(image);
|
nsvgDelete(image);
|
||||||
return polygons;
|
return polygons;
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ TEST_CASE("Heal of points close to line", "[Emboss]")
|
|||||||
std::string file_name = "points_close_to_line.svg";
|
std::string file_name = "points_close_to_line.svg";
|
||||||
std::string file_path = TEST_DATA_DIR PATH_SEPARATOR + file_name;
|
std::string file_path = TEST_DATA_DIR PATH_SEPARATOR + file_name;
|
||||||
NSVGimage *image = nsvgParseFromFile(file_path.c_str(), "px", 96.0f);
|
NSVGimage *image = nsvgParseFromFile(file_path.c_str(), "px", 96.0f);
|
||||||
Polygons polygons = to_polygons(image);
|
Polygons polygons = to_polygons(*image);
|
||||||
nsvgDelete(image);
|
nsvgDelete(image);
|
||||||
REQUIRE(polygons.size() == 1);
|
REQUIRE(polygons.size() == 1);
|
||||||
Polygon polygon = polygons.front();
|
Polygon polygon = polygons.front();
|
||||||
@ -536,7 +536,7 @@ TEST_CASE("UndoRedo EmbossShape serialization", "[Emboss]")
|
|||||||
emboss.projection.depth = 5.;
|
emboss.projection.depth = 5.;
|
||||||
emboss.projection.use_surface = true;
|
emboss.projection.use_surface = true;
|
||||||
emboss.fix_3mf_tr = Transform3d::Identity();
|
emboss.fix_3mf_tr = Transform3d::Identity();
|
||||||
emboss.svg_file_path = "Everything starts somewhere, though many physicists disagree.\
|
emboss.svg_file.path = "Everything starts somewhere, though many physicists disagree.\
|
||||||
But people have always been dimly aware of the problem with the start of things.\
|
But people have always been dimly aware of the problem with the start of things.\
|
||||||
They wonder how the snowplough driver gets to work,\
|
They wonder how the snowplough driver gets to work,\
|
||||||
or how the makers of dictionaries look up the spelling of words.";
|
or how the makers of dictionaries look up the spelling of words.";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user