diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp
index d1e5eb0d8f..50b6071cf9 100644
--- a/src/libslic3r/Emboss.cpp
+++ b/src/libslic3r/Emboss.cpp
@@ -20,9 +20,6 @@
#include "libslic3r/Line.hpp"
using namespace Slic3r;
-
-double Emboss::SHAPE_SCALE = 0.001;//SCALING_FACTOR;
-
// do not expose out of this file stbtt_ data types
namespace priv{
diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp
index abe0c125ff..e188d3fe6e 100644
--- a/src/libslic3r/Emboss.hpp
+++ b/src/libslic3r/Emboss.hpp
@@ -16,23 +16,21 @@ namespace Slic3r {
/// class with only static function add ability to engraved OR raised
/// text OR polygons onto model surface
///
-class Emboss
-{
-public:
- Emboss() = delete;
-
+namespace Emboss
+{
// every glyph's shape point is divided by SHAPE_SCALE - increase precission of fixed point value
- static double SHAPE_SCALE;
+ // stored in fonts (to be able represents curve by sequence of lines)
+ static constexpr double SHAPE_SCALE = 0.001; // SCALING_FACTOR promile is fine enough
///
/// Collect fonts registred inside OS
///
/// OS registred TTF font files(full path) with names
- static EmbossStyles get_font_list();
+ EmbossStyles get_font_list();
#ifdef _WIN32
- static EmbossStyles get_font_list_by_register();
- static EmbossStyles get_font_list_by_enumeration();
- static EmbossStyles get_font_list_by_folder();
+ EmbossStyles get_font_list_by_register();
+ EmbossStyles get_font_list_by_enumeration();
+ EmbossStyles get_font_list_by_folder();
#endif
///
@@ -40,7 +38,7 @@ public:
///
/// Unique identificator for font
/// File path to font when found
- static std::optional get_font_path(const std::wstring &font_face_name);
+ std::optional get_font_path(const std::wstring &font_face_name);
// description of one letter
struct Glyph
@@ -126,14 +124,14 @@ public:
///
/// Location of .ttf or .ttc font file
/// Font object when loaded.
- static std::unique_ptr create_font_file(const char *file_path);
+ std::unique_ptr create_font_file(const char *file_path);
// data = raw file data
- static std::unique_ptr create_font_file(std::unique_ptr> data);
+ std::unique_ptr create_font_file(std::unique_ptr> data);
#ifdef _WIN32
// fix for unknown pointer HFONT
using HFONT = void*;
- static void * can_load(HFONT hfont);
- static std::unique_ptr create_font_file(HFONT hfont);
+ void * can_load(HFONT hfont);
+ std::unique_ptr create_font_file(HFONT hfont);
#endif // _WIN32
///
@@ -144,7 +142,7 @@ public:
/// One character defined by unicode codepoint
/// Precision of lettter outline curve in conversion to lines
/// inner polygon cw(outer ccw)
- static std::optional letter2glyph(const FontFile &font, unsigned int font_index, int letter, float flatness);
+ std::optional letter2glyph(const FontFile &font, unsigned int font_index, int letter, float flatness);
///
/// Convert text into polygons
@@ -154,14 +152,14 @@ public:
/// User defined property of the font
/// Way to interupt processing
/// Inner polygon cw(outer ccw)
- static ExPolygons text2shapes(FontFileWithCache &font, const char *text, const FontProp &font_prop, std::function was_canceled = nullptr);
+ ExPolygons text2shapes(FontFileWithCache &font, const char *text, const FontProp &font_prop, std::function was_canceled = nullptr);
///
/// Fix intersections and self intersections in polygons glyph shape
///
/// Input shape to heal
/// Healed shapes
- static ExPolygons heal_shape(const Polygons &shape);
+ ExPolygons heal_shape(const Polygons &shape);
///
/// NOTE: call Slic3r::union_ex before this call
@@ -175,7 +173,7 @@ public:
/// Heal could create another issue,
/// After healing it is checked again until shape is good or maximal count of iteration
/// True when shapes is good otherwise False
- static bool heal_shape(ExPolygons &shape, unsigned max_iteration = 10);
+ bool heal_shape(ExPolygons &shape, unsigned max_iteration = 10);
///
/// Divide line segments in place near to point
@@ -186,7 +184,7 @@ public:
/// Expolygon to edit
/// (epsilon)Euclidean distance from point to line which divide line
/// True when some division was made otherwise false
- static bool divide_segments_for_close_point(ExPolygons &expolygons, double distance);
+ bool divide_segments_for_close_point(ExPolygons &expolygons, double distance);
///
/// Use data from font property to modify transformation
@@ -194,7 +192,7 @@ public:
/// Z-move as surface distance(FontProp::distance)
/// Z-rotation as angle to Y axis(FontProp::angle)
/// In / Out transformation to modify by property
- static void apply_transformation(const FontProp &font_prop, Transform3d &transformation);
+ void apply_transformation(const FontProp &font_prop, Transform3d &transformation);
///
/// Read information from naming table of font file
@@ -203,7 +201,7 @@ public:
/// Selector of font
/// Index of font in collection
/// True when the font description contains italic/obligue otherwise False
- static bool is_italic(const FontFile &font, unsigned int font_index);
+ bool is_italic(const FontFile &font, unsigned int font_index);
///
/// Create unique character set from string with filtered from text with only character from font
@@ -213,7 +211,7 @@ public:
/// Define font in collection
/// True when text contain glyph unknown in font
/// Unique set of character from text contained in font
- static std::string create_range_text(const std::string &text, const FontFile &font, unsigned int font_index, bool* exist_unknown = nullptr);
+ std::string create_range_text(const std::string &text, const FontFile &font, unsigned int font_index, bool* exist_unknown = nullptr);
///
/// Calculate scale for glyph shape convert from shape points to mm
@@ -221,7 +219,7 @@ public:
/// Property of font
/// Font data
/// Conversion to mm
- static double get_shape_scale(const FontProp &fp, const FontFile &ff);
+ double get_shape_scale(const FontProp &fp, const FontFile &ff);
///
/// Project spatial point
@@ -274,7 +272,7 @@ public:
/// text or image
/// Define transformation from 2d to 3d(orientation, position, scale, ...)
/// Projected shape into space
- static indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProjection& projection);
+ indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProjection& projection);
///
/// Create transformation for emboss text object to lay on surface point
@@ -283,7 +281,7 @@ public:
/// Normal of surface point
/// Is compared with normal.z to suggest up direction
/// Transformation onto surface point
- static Transform3d create_transformation_onto_surface(
+ Transform3d create_transformation_onto_surface(
const Vec3f &position, const Vec3f &normal, float up_limit = 0.9f);
class ProjectZ : public IProjection
@@ -345,7 +343,7 @@ public:
Vec3d project(const Vec3d &point) const override;
std::optional unproject(const Vec3d &p, double * depth = nullptr) const override;
};
-};
+} // namespace Emboss
} // namespace Slic3r
#endif // slic3r_Emboss_hpp_
diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp
index 94b846a5db..d514171f17 100644
--- a/src/libslic3r/Model.hpp
+++ b/src/libslic3r/Model.hpp
@@ -936,23 +936,8 @@ private:
// 1 -> is splittable
mutable int m_is_splittable{ -1 };
- ModelVolume(ModelObject *object, const TriangleMesh &mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART) : m_mesh(new TriangleMesh(mesh)), m_type(type), object(object)
- {
- assert(this->id().valid());
- assert(this->config.id().valid());
- assert(this->supported_facets.id().valid());
- assert(this->seam_facets.id().valid());
- assert(this->mmu_segmentation_facets.id().valid());
- assert(this->id() != this->config.id());
- assert(this->id() != this->supported_facets.id());
- assert(this->id() != this->seam_facets.id());
- assert(this->id() != this->mmu_segmentation_facets.id());
- if (mesh.facets_count() > 1)
- calculate_convex_hull();
- }
- ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
- m_mesh(new TriangleMesh(std::move(mesh))), m_convex_hull(new TriangleMesh(std::move(convex_hull))), m_type(type), object(object) {
- assert(this->id().valid());
+ inline bool check() {
+ assert(this->id().valid());
assert(this->config.id().valid());
assert(this->supported_facets.id().valid());
assert(this->seam_facets.id().valid());
@@ -961,6 +946,24 @@ private:
assert(this->id() != this->supported_facets.id());
assert(this->id() != this->seam_facets.id());
assert(this->id() != this->mmu_segmentation_facets.id());
+ return true;
+ }
+
+ ModelVolume(ModelObject *object, const TriangleMesh &mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
+ m_mesh(new TriangleMesh(mesh)), m_type(type), object(object)
+ {
+ assert(check());
+ if (m_mesh->facets_count() > 1) calculate_convex_hull();
+ }
+ ModelVolume(ModelObject *object, TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART)
+ : m_mesh(new TriangleMesh(std::move(mesh))), m_type(type), object(object)
+ {
+ assert(check());
+ if (m_mesh->facets_count() > 1) calculate_convex_hull();
+ }
+ ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
+ m_mesh(new TriangleMesh(std::move(mesh))), m_convex_hull(new TriangleMesh(std::move(convex_hull))), m_type(type), object(object) {
+ assert(check());
}
// Copying an existing volume, therefore this volume will get a copy of the ID assigned.
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
index 04dc15266a..5c3b5ca771 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
@@ -57,7 +57,9 @@
#endif // ALLOW_DEBUG_MODE
using namespace Slic3r;
+using namespace Slic3r::Emboss;
using namespace Slic3r::GUI;
+using namespace Slic3r::GUI::Emboss;
// anonymous namespace for unique names
namespace {
@@ -165,6 +167,18 @@ void GLGizmoEmboss::set_fine_position()
ImGuiWrapper::draw(rect);
}
+namespace priv {
+
+///
+/// Prepare data for emboss
+///
+/// Text to emboss
+/// Keep actual selected style
+/// Base data for emboss text
+static DataBase create_emboss_data_base(const std::string &text, StyleManager &style_manager);
+
+} // namespace priv
+
void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
{
assert(volume_type == ModelVolumeType::MODEL_PART ||
@@ -188,11 +202,17 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous
Plater* plater = wxGetApp().plater();
const Camera &camera = plater->get_camera();
const Pointfs &bed_shape = plater->build_volume().bed_shape();
- EmbossDataCreateObject data{create_emboss_data_base(),
- screen_coor,
- camera,
- bed_shape};
- auto job = std::make_unique(std::move(data));
+ // TODO: Fix double creation of base data (first is inside function start_volume_creation)
+ DataBase emboss_data = priv::create_emboss_data_base(m_text, m_style_manager);
+ FontProp& prop = emboss_data.text_configuration.style.prop;
+
+ // can't create new object with using surface
+ if (prop.use_surface) prop.use_surface = false;
+ // can't create new object with distance from surface
+ if (prop.distance.has_value()) prop.distance.reset();
+
+ DataCreateObject data{std::move(emboss_data), screen_coor, camera, bed_shape};
+ auto job = std::make_unique(std::move(data));
Worker &worker = plater->get_ui_job_worker();
queue_job(worker, std::move(job));
}
@@ -369,9 +389,9 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
// Calculate temporary position
Transform3d object_trmat = m_raycast_manager.get_transformation(hit->tr_key);
- Transform3d trmat = Emboss::create_transformation_onto_surface(hit->position, hit->normal);
+ Transform3d trmat = create_transformation_onto_surface(hit->position, hit->normal);
const FontProp& font_prop = tc.style.prop;
- Emboss::apply_transformation(font_prop, trmat);
+ apply_transformation(font_prop, trmat);
// fix baked transformation from .3mf store process
if (tc.fix_3mf_tr.has_value())
@@ -807,8 +827,7 @@ EmbossStyles GLGizmoEmboss::create_default_styles()
void GLGizmoEmboss::set_default_text(){ m_text = _u8L("Embossed text"); }
-bool GLGizmoEmboss::start_volume_creation(ModelVolumeType volume_type,
- const Vec2d &screen_coor)
+bool GLGizmoEmboss::start_volume_creation(ModelVolumeType volume_type, const Vec2d &screen_coor)
{
Plater* plater = wxGetApp().plater();
@@ -848,18 +867,33 @@ bool GLGizmoEmboss::start_volume_creation(ModelVolumeType volume_type,
GLVolume *gl_volume = volumes[hovered_id];
Transform3d hit_instance_trmat = gl_volume->get_instance_transformation().get_matrix();
- // create volume
- EmbossDataCreateVolume data{create_emboss_data_base(),
- volume_type,
- screen_coor,
- object_idx_signed,
- camera,
- *hit,
- hit_object_trmat,
- hit_instance_trmat};
+ DataBase emboss_data = priv::create_emboss_data_base(m_text, m_style_manager);
+ // Create result volume transformation
+ Transform3d surface_trmat = create_transformation_onto_surface(hit->position, hit->normal);
+ const FontProp& font_prop = emboss_data.text_configuration.style.prop;
+ apply_transformation(font_prop, surface_trmat);
+ Transform3d volume_trmat = hit_instance_trmat.inverse() * hit_object_trmat * surface_trmat;
+
+ std::unique_ptr job;
+ if (!emboss_data.text_configuration.style.prop.use_surface) {
+ // create volume
+ DataCreateVolume data{std::move(emboss_data), volume_type, object_idx_signed, volume_trmat};
+ job = std::make_unique(std::move(data));
+ } else {
+ // Model to cut surface from.
+ SurfaceVolumeData::ModelSources sources = create_sources(obj->volumes);
+ if (sources.empty()) return false;
+
+ bool is_outside = volume_type == ModelVolumeType::MODEL_PART;
+ // check that there is not unexpected volume type
+ assert(is_outside ||
+ volume_type == ModelVolumeType::NEGATIVE_VOLUME ||
+ volume_type == ModelVolumeType::PARAMETER_MODIFIER);
+ CreateSurfaceVolumeData surface_data{std::move(emboss_data), volume_trmat, is_outside, std::move(sources), volume_type, object_idx_signed};
+ job = std::make_unique(std::move(surface_data));
+ }
Worker &worker = plater->get_ui_job_worker();
- auto job = std::make_unique(std::move(data));
queue_job(worker, std::move(job));
return true;
}
@@ -957,7 +991,7 @@ bool GLGizmoEmboss::process()
m_update_job_cancel->store(true);
// create new shared ptr to cancel new job
m_update_job_cancel = std::make_shared >(false);
- EmbossDataUpdate data{create_emboss_data_base(), m_volume->id(), m_update_job_cancel};
+ DataUpdate data{priv::create_emboss_data_base(m_text, m_style_manager), m_volume->id(), m_update_job_cancel};
std::unique_ptr job = nullptr;
@@ -965,7 +999,7 @@ bool GLGizmoEmboss::process()
const TextConfiguration &tc = data.text_configuration;
if (tc.style.prop.use_surface) {
// Model to cut surface from.
- UseSurfaceData::ModelSources sources = UseSurfaceData::create_sources(m_volume);
+ SurfaceVolumeData::ModelSources sources = create_volume_sources(m_volume);
if (sources.empty()) return false;
Transform3d text_tr = m_volume->get_matrix();
@@ -977,11 +1011,10 @@ bool GLGizmoEmboss::process()
// check that there is not unexpected volume type
assert(is_outside || m_volume->is_negative_volume() ||
m_volume->is_modifier());
- UseSurfaceData surface_data{std::move(data), text_tr, is_outside,
- std::move(sources)};
- job = std::make_unique(std::move(surface_data));
+ UpdateSurfaceVolumeData surface_data{std::move(data), text_tr, is_outside, std::move(sources)};
+ job = std::make_unique(std::move(surface_data));
} else {
- job = std::make_unique(std::move(data));
+ job = std::make_unique(std::move(data));
}
//*
@@ -1024,7 +1057,7 @@ void GLGizmoEmboss::close()
void GLGizmoEmboss::discard_and_close() {
if (!m_unmodified_volume.has_value()) return;
m_volume->set_transformation(m_unmodified_volume->tr);
- EmbossUpdateJob::update_volume(m_volume, std::move(m_unmodified_volume->tm), m_unmodified_volume->tc, m_unmodified_volume->name);
+ UpdateJob::update_volume(m_volume, std::move(m_unmodified_volume->tm), m_unmodified_volume->tc, m_unmodified_volume->name);
close();
//auto plater = wxGetApp().plater();
@@ -1139,18 +1172,18 @@ void GLGizmoEmboss::draw_window()
void GLGizmoEmboss::draw_text_input()
{
- auto create_range_text = [&mng = m_style_manager, &text = m_text, &exist_unknown = m_text_contain_unknown_glyph]() {
+ auto create_range_text_prep = [&mng = m_style_manager, &text = m_text, &exist_unknown = m_text_contain_unknown_glyph]() {
auto& ff = mng.get_font_file_with_cache();
assert(ff.has_value());
const auto &cn = mng.get_font_prop().collection_number;
unsigned int font_index = (cn.has_value()) ? *cn : 0;
- return Emboss::create_range_text(text, *ff.font_file, font_index, &exist_unknown);
+ return create_range_text(text, *ff.font_file, font_index, &exist_unknown);
};
ImFont *imgui_font = m_style_manager.get_imgui_font();
if (imgui_font == nullptr) {
// try create new imgui font
- m_style_manager.create_imgui_font(create_range_text());
+ m_style_manager.create_imgui_font(create_range_text_prep());
imgui_font = m_style_manager.get_imgui_font();
}
bool exist_font =
@@ -1190,10 +1223,10 @@ void GLGizmoEmboss::draw_text_input()
if (prop.line_gap.has_value())
append_warning(_u8L("Line gap"), _u8L("Unsupported visualization of gap between lines inside text input."));
auto &ff = m_style_manager.get_font_file_with_cache();
- float imgui_size = EmbossStyleManager::get_imgui_font_size(prop, *ff.font_file);
- if (imgui_size > EmbossStyleManager::max_imgui_font_size)
+ float imgui_size = StyleManager::get_imgui_font_size(prop, *ff.font_file);
+ if (imgui_size > StyleManager::max_imgui_font_size)
append_warning(_u8L("To tall"), _u8L("Diminished font height inside text input."));
- if (imgui_size < EmbossStyleManager::min_imgui_font_size)
+ if (imgui_size < StyleManager::min_imgui_font_size)
append_warning(_u8L("To small"), _u8L("Enlarged font height inside text input."));
if (!who.empty()) warning = GUI::format(_L("%1% is NOT shown."), who);
}
@@ -1217,7 +1250,7 @@ void GLGizmoEmboss::draw_text_input()
const ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_AutoSelectAll;
if (ImGui::InputTextMultiline("##Text", &m_text, text_size, flags)) {
process();
- range_text = create_range_text();
+ range_text = create_range_text_prep();
}
if (exist_font) ImGui::PopFont();
@@ -1571,7 +1604,7 @@ void GLGizmoEmboss::draw_font_list()
// When is unknown font is inside .3mf only font selection is allowed
// Stop Imgui disable + Guard again start disabling
ScopeGuard unknown_font_sc;
- if (m_is_unknown_font) {
+ if (m_is_unknown_font) {
m_imgui->disabled_end();
unknown_font_sc = ScopeGuard([&]() {
m_imgui->disabled_begin(true);
@@ -1963,7 +1996,7 @@ void GLGizmoEmboss::draw_delete_style_button() {
void GLGizmoEmboss::draw_revert_all_styles_button() {
if (draw_button(IconType::revert_all)) {
- m_style_manager = EmbossStyleManager(m_imgui->get_glyph_ranges());
+ m_style_manager = StyleManager(m_imgui->get_glyph_ranges());
m_style_manager.init(nullptr, create_default_styles());
assert(m_style_manager.get_font_file_with_cache().has_value());
process();
@@ -2029,7 +2062,7 @@ void GLGizmoEmboss::draw_style_list() {
m_style_manager.init_style_images(m_gui_cfg->max_style_image_size, m_text);
m_style_manager.init_trunc_names(max_style_name_width);
std::optional> swap_indexes;
- const std::vector &styles = m_style_manager.get_styles();
+ const std::vector &styles = m_style_manager.get_styles();
for (const auto &item : styles) {
size_t index = &item - &styles.front();
const EmbossStyle &style = item.style;
@@ -2038,7 +2071,7 @@ void GLGizmoEmboss::draw_style_list() {
bool is_selected = (index == m_style_manager.get_style_index());
ImVec2 select_size(0,m_gui_cfg->max_style_image_size.y()); // 0,0 --> calculate in draw
- const std::optional &img = item.image;
+ const std::optional &img = item.image;
// allow click delete button
ImGuiSelectableFlags_ flags = ImGuiSelectableFlags_AllowItemOverlap;
if (ImGui::Selectable(item.truncated_name.c_str(), is_selected, flags, select_size)) {
@@ -2918,9 +2951,9 @@ bool GLGizmoEmboss::choose_svg_file()
for (const auto &p : polys) bb.merge(p.contour.points);
const FontProp &fp = m_style_manager.get_style().prop;
float scale = fp.size_in_mm / std::max(bb.max.x(), bb.max.y());
- auto project = std::make_unique(
- std::make_unique(fp.emboss / scale), scale);
- indexed_triangle_set its = Emboss::polygons2model(polys, *project);
+ auto project = std::make_unique(
+ std::make_unique(fp.emboss / scale), scale);
+ indexed_triangle_set its = polygons2model(polys, *project);
return false;
// test store:
// for (auto &poly : polys) poly.scale(1e5);
@@ -2929,41 +2962,38 @@ bool GLGizmoEmboss::choose_svg_file()
//return add_volume(name, its);
}
-EmbossDataBase GLGizmoEmboss::create_emboss_data_base() {
+DataBase priv::create_emboss_data_base(const std::string &text, StyleManager& style_manager)
+{
auto create_volume_name = [&]() {
- bool contain_enter = m_text.find('\n') != std::string::npos;
+ bool contain_enter = text.find('\n') != std::string::npos;
std::string text_fixed;
if (contain_enter) {
// change enters to space
- text_fixed = m_text; // copy
- std::replace(text_fixed.begin(), text_fixed.end(), '\n', ' ');
+ text_fixed = text; // copy
+ std::replace(text_fixed.begin(), text_fixed.end(), '\n', ' ');
}
- return _u8L("Text") + " - " + ((contain_enter) ? text_fixed : m_text);
+ return _u8L("Text") + " - " + ((contain_enter) ? text_fixed : text);
};
-
+
auto create_configuration = [&]() -> TextConfiguration {
- if (!m_style_manager.is_activ_font()) {
- std::string default_text_for_emboss = _u8L("Embossed text");
- EmbossStyle es = m_style_manager.get_style();
+ if (!style_manager.is_activ_font()) {
+ std::string default_text_for_emboss = _u8L("Embossed text");
+ EmbossStyle es = style_manager.get_style();
TextConfiguration tc{es, default_text_for_emboss};
// TODO: investigate how to initialize
return tc;
}
- EmbossStyle &es = m_style_manager.get_style();
+ EmbossStyle &es = style_manager.get_style();
// actualize font path - during changes in gui it could be corrupted
// volume must store valid path
- assert(m_style_manager.get_wx_font().has_value());
- assert(es.path.compare(WxFontUtils::store_wxFont(*m_style_manager.get_wx_font())) == 0);
- //style.path = WxFontUtils::store_wxFont(*m_style_manager.get_wx_font());
- return TextConfiguration{es, m_text};
- };
-
- return EmbossDataBase{
- m_style_manager.get_font_file_with_cache(),
- create_configuration(),
- create_volume_name()
+ assert(style_manager.get_wx_font().has_value());
+ assert(es.path.compare(WxFontUtils::store_wxFont(*style_manager.get_wx_font())) == 0);
+ // style.path = WxFontUtils::store_wxFont(*m_style_manager.get_wx_font());
+ return TextConfiguration{es, text};
};
+
+ return Slic3r::GUI::Emboss::DataBase{style_manager.get_font_file_with_cache(), create_configuration(), create_volume_name()};
}
bool GLGizmoEmboss::load_configuration(ModelVolume *volume)
@@ -2974,7 +3004,7 @@ bool GLGizmoEmboss::load_configuration(ModelVolume *volume)
const TextConfiguration &tc = *tc_opt;
const EmbossStyle &style = tc.style;
- auto has_same_name = [&style](const EmbossStyleManager::Item &style_item) -> bool {
+ auto has_same_name = [&style](const StyleManager::Item &style_item) -> bool {
const EmbossStyle &es = style_item.style;
return es.name == style.name;
};
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
index e1a5c5b050..9df7722e60 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
@@ -34,8 +34,6 @@ namespace Slic3r{
namespace Slic3r::GUI {
class MeshRaycaster;
-struct EmbossDataBase;
-
class GLGizmoEmboss : public GLGizmoBase
{
public:
@@ -157,8 +155,6 @@ private:
bool choose_true_type_file();
bool choose_svg_file();
- // prepare base data for emboss text
- EmbossDataBase create_emboss_data_base();
bool load_configuration(ModelVolume *volume);
// When open text loaded from .3mf it could be written with unknown font
@@ -225,7 +221,7 @@ private:
std::optional m_set_window_offset;
bool m_is_advanced_edit_style = false;
- EmbossStyleManager m_style_manager;
+ Emboss::StyleManager m_style_manager;
struct FaceName{
wxString wx_name;
diff --git a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp
index 6da3695fed..d1a671330a 100644
--- a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp
+++ b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp
@@ -15,11 +15,13 @@
#include "slic3r/GUI/GLCanvas3D.hpp"
using namespace Slic3r;
+using namespace Slic3r::Emboss;
using namespace Slic3r::GUI;
+using namespace Slic3r::GUI::Emboss;
CreateFontStyleImagesJob::CreateFontStyleImagesJob(
- EmbossStyleManager::StyleImagesData &&input)
+ StyleManager::StyleImagesData &&input)
: m_input(std::move(input))
{
assert(m_input.result != nullptr);
@@ -34,15 +36,15 @@ void CreateFontStyleImagesJob::process(Ctl &ctl)
// create shapes and calc size (bounding boxes)
std::vector name_shapes(m_input.styles.size());
std::vector scales(m_input.styles.size());
- images = std::vector(m_input.styles.size());
+ images = std::vector(m_input.styles.size());
for (auto &item : m_input.styles) {
size_t index = &item - &m_input.styles.front();
ExPolygons &shapes = name_shapes[index];
- shapes = Emboss::text2shapes(item.font, m_input.text.c_str(), item.prop);
+ shapes = text2shapes(item.font, m_input.text.c_str(), item.prop);
// create image description
- EmbossStyleManager::StyleImage &image = images[index];
+ StyleManager::StyleImage &image = images[index];
BoundingBox &bounding_box = image.bounding_box;
for (ExPolygon &shape : shapes)
bounding_box.merge(BoundingBox(shape.contour.points));
@@ -56,7 +58,7 @@ void CreateFontStyleImagesJob::process(Ctl &ctl)
const auto &cn = item.prop.collection_number;
unsigned int font_index = (cn.has_value()) ? *cn : 0;
double unit_per_em = item.font.font_file->infos[font_index].unit_per_em;
- double scale = item.prop.size_in_mm / unit_per_em * Emboss::SHAPE_SCALE * ppm;
+ double scale = item.prop.size_in_mm / unit_per_em * SHAPE_SCALE * ppm;
scales[index] = scale;
//double scale = font_prop.size_in_mm * SCALING_FACTOR;
@@ -77,14 +79,14 @@ void CreateFontStyleImagesJob::process(Ctl &ctl)
// arrange bounding boxes
int offset_y = 0;
width = 0;
- for (EmbossStyleManager::StyleImage &image : images) {
+ for (StyleManager::StyleImage &image : images) {
image.offset.y() = offset_y;
offset_y += image.tex_size.y+1;
if (width < image.tex_size.x)
width = image.tex_size.x;
}
height = offset_y;
- for (EmbossStyleManager::StyleImage &image : images) {
+ for (StyleManager::StyleImage &image : images) {
const Point &o = image.offset;
const ImVec2 &s = image.tex_size;
image.uv0 = ImVec2(o.x() / (double) width,
@@ -97,7 +99,7 @@ void CreateFontStyleImagesJob::process(Ctl &ctl)
pixels = std::vector(4*width * height, {255});
// upload sub textures
- for (EmbossStyleManager::StyleImage &image : images) {
+ for (StyleManager::StyleImage &image : images) {
sla::Resolution resolution(image.tex_size.x, image.tex_size.y);
size_t index = &image - &images.front();
double pixel_dim = SCALING_FACTOR / scales[index];
@@ -146,7 +148,7 @@ void CreateFontStyleImagesJob::finalize(bool canceled, std::exception_ptr &)
// set up texture id
void *texture_id = (void *) (intptr_t) tex_id;
- for (EmbossStyleManager::StyleImage &image : images)
+ for (StyleManager::StyleImage &image : images)
image.texture_id = texture_id;
// move to result
diff --git a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp
index 453f14586f..c220f2ee01 100644
--- a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp
+++ b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp
@@ -7,7 +7,7 @@
#include "slic3r/Utils/EmbossStyleManager.hpp"
#include "Job.hpp"
-namespace Slic3r::GUI {
+namespace Slic3r::GUI::Emboss {
///
/// Create texture with name of styles written by its style
@@ -15,7 +15,7 @@ namespace Slic3r::GUI {
///
class CreateFontStyleImagesJob : public Job
{
- EmbossStyleManager::StyleImagesData m_input;
+ StyleManager::StyleImagesData m_input;
// Output data
// texture size
@@ -23,10 +23,10 @@ class CreateFontStyleImagesJob : public Job
// texture data
std::vector pixels;
// descriptors of sub textures
- std::vector images;
+ std::vector images;
public:
- CreateFontStyleImagesJob(EmbossStyleManager::StyleImagesData &&input);
+ CreateFontStyleImagesJob(StyleManager::StyleImagesData &&input);
void process(Ctl &ctl) override;
void finalize(bool canceled, std::exception_ptr &) override;
};
diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp
index 7112ceb474..f49e8499bd 100644
--- a/src/slic3r/GUI/Jobs/EmbossJob.cpp
+++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp
@@ -19,7 +19,9 @@
#include "slic3r/Utils/UndoRedo.hpp"
using namespace Slic3r;
-using namespace GUI;
+using namespace Slic3r::Emboss;
+using namespace Slic3r::GUI;
+using namespace Slic3r::GUI::Emboss;
// private namespace
namespace priv{
@@ -31,11 +33,12 @@ constexpr float safe_extension = 1.0f;
///
///
///
-bool check(const EmbossDataBase &input, bool check_fontfile = true);
-bool check(const EmbossDataCreateVolume &input, bool is_main_thread = false);
-bool check(const EmbossDataCreateObject &input);
-bool check(const EmbossDataUpdate &input, bool is_main_thread = false);
-bool check(const UseSurfaceData &input, bool is_main_thread = false);
+bool check(const DataBase &input, bool check_fontfile = true, bool use_surface = false);
+bool check(const DataCreateVolume &input, bool is_main_thread = false);
+bool check(const DataCreateObject &input);
+bool check(const DataUpdate &input, bool is_main_thread = false, bool use_surface = false);
+bool check(const CreateSurfaceVolumeData &input, bool is_main_thread = false);
+bool check(const UpdateSurfaceVolumeData &input, bool is_main_thread = false);
//
/// Try to create mesh from text
@@ -46,14 +49,8 @@ bool check(const UseSurfaceData &input, bool is_main_thread = false);
/// NOTE: Cache glyphs is changed
/// To check if process was canceled
/// Triangle mesh model
-template
-static TriangleMesh try_create_mesh(const EmbossDataBase &input,
- Emboss::FontFileWithCache &font,
- Fnc was_canceled);
-template
-static TriangleMesh create_mesh(EmbossDataBase &input,
- Fnc was_canceled,
- Job::Ctl &ctl);
+template static TriangleMesh try_create_mesh(const DataBase &input, FontFileWithCache &font, Fnc was_canceled);
+template static TriangleMesh create_mesh(DataBase &input, Fnc was_canceled, Job::Ctl &ctl);
///
/// Create default mesh for embossed text
@@ -66,7 +63,18 @@ static TriangleMesh create_default_mesh();
///
/// New mesh data
/// Text configuration, ...
-static void update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data);
+static void update_volume(TriangleMesh &&mesh, const DataUpdate &data);
+
+///
+/// Add new volume to object
+///
+/// triangles of new volume
+/// Object where to add volume
+/// Type of new volume
+/// Transformation of volume inside of object
+/// Text configuration and New VolumeName
+static void create_volume(TriangleMesh &&mesh, const size_t object_idx,
+ const ModelVolumeType type, const Transform3d trmat, const DataBase &data);
///
/// Select Volume from objects
@@ -74,8 +82,7 @@ static void update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data);
/// All objects in scene
/// Identifier of volume in object
/// Pointer to volume when exist otherwise nullptr
-static ModelVolume *get_volume(ModelObjectPtrs &objects,
- const ObjectID &volume_id);
+static ModelVolume *get_volume(ModelObjectPtrs &objects, const ObjectID &volume_id);
///
/// Create projection for cut surface from mesh
@@ -84,10 +91,7 @@ static ModelVolume *get_volume(ModelObjectPtrs &objects,
/// Convert shape to milimeters
/// Bounding box 3d of model volume for projection ranges
/// Orthogonal cut_projection
-static Emboss::OrthoProject create_projection_for_cut(
- Transform3d tr,
- double shape_scale,
- const std::pair &z_range);
+static OrthoProject create_projection_for_cut(Transform3d tr, double shape_scale, const std::pair &z_range);
///
/// Create tranformation for emboss Cutted surface
@@ -97,41 +101,43 @@ static Emboss::OrthoProject create_projection_for_cut(
/// Text voliume transformation inside object
/// Cutted surface from model
/// Projection
-static Emboss::OrthoProject3d create_emboss_projection(
- bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut);
+static OrthoProject3d create_emboss_projection(bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut);
+
+///
+/// Cut surface into triangle mesh
+///
+/// (can't be const - cache of font)
+/// SurfaceVolume data
+/// Check to interupt execution
+/// Extruded object from cuted surace
+static TriangleMesh cut_surface(/*const*/ DataBase &input1, const SurfaceVolumeData &input2, std::function was_canceled);
static void create_message(const std::string &message); // only in finalize
static bool process(std::exception_ptr &eptr);
-class EmbossJobException : public std::runtime_error
-{ public: EmbossJobException(const char* message):runtime_error(message){}};
+class JobException : public std::runtime_error {
+public: JobException(const char* message):runtime_error(message){}};
}// namespace priv
/////////////////
/// Create Volume
-EmbossCreateVolumeJob::EmbossCreateVolumeJob(EmbossDataCreateVolume &&input)
+CreateVolumeJob::CreateVolumeJob(DataCreateVolume &&input)
: m_input(std::move(input))
{
assert(priv::check(m_input, true));
}
-void EmbossCreateVolumeJob::process(Ctl &ctl) {
+void CreateVolumeJob::process(Ctl &ctl) {
if (!priv::check(m_input)) throw std::runtime_error("Bad input data for EmbossCreateVolumeJob.");
auto was_canceled = [&ctl]()->bool { return ctl.was_canceled(); };
m_result = priv::create_mesh(m_input, was_canceled, ctl);
- if (was_canceled()) return;
-
- // Create new volume inside of object
- const FontProp &font_prop = m_input.text_configuration.style.prop;
- Transform3d surface_trmat = Emboss::create_transformation_onto_surface(
- m_input.hit.position, m_input.hit.normal);
- Emboss::apply_transformation(font_prop, surface_trmat);
- m_transformation = m_input.hit_instance_tr.inverse() *
- m_input.hit_object_tr * surface_trmat;
+ // center result
+ Vec3f c = m_result.bounding_box().center().cast();
+ if (!c.isApprox(Vec3f::Zero())) m_result.translate(-c);
}
-void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
+void CreateVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
// doesn't care about exception when process was canceled by user
if (canceled) {
eptr = nullptr;
@@ -141,74 +147,19 @@ void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
if (m_result.its.empty())
return priv::create_message(_u8L("Can't create empty volume."));
- GUI_App &app = wxGetApp();
- Plater *plater = app.plater();
- ObjectList *obj_list = app.obj_list();
- GLCanvas3D *canvas = plater->canvas3D();
- ModelObjectPtrs &objects = plater->model().objects;
-
- // create volume in object
- size_t object_idx = m_input.object_idx;
-
- // Parent object for text volume was propably removed.
- // Assumption: User know what he does, so text volume is no more needed.
- if (objects.size() <= object_idx)
- return;
-
- plater->take_snapshot(_L("Add Emboss text Volume"));
-
- ModelObject *obj = objects[object_idx];
- ModelVolumeType type = m_input.volume_type;
-
- ModelVolume *volume = obj->add_volume(std::move(m_result), type);
-
- // set a default extruder value, since user can't add it manually
- volume->config.set_key_value("extruder", new ConfigOptionInt(0));
-
- // do not allow model reload from disk
- volume->source.is_from_builtin_objects = true;
-
- volume->name = m_input.volume_name;
- volume->text_configuration = std::move(m_input.text_configuration);
- volume->set_transformation(m_transformation);
-
- // update volume name in object list
- // updata selection after new volume added
- // change name of volume in right panel
- // select only actual volume
- // when new volume is created change selection to this volume
- auto add_to_selection = [volume](const ModelVolume *vol) {
- return vol == volume;
- };
- wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(
- m_input.object_idx, add_to_selection);
- if (!sel.IsEmpty()) obj_list->select_item(sel.front());
-
- // update printable state on canvas
- if (type == ModelVolumeType::MODEL_PART)
- canvas->update_instance_printable_state_for_object(object_idx);
-
- obj_list->selection_changed();
-
- // Now is valid text volume selected open emboss gizmo
- GLGizmosManager &manager = canvas->get_gizmos_manager();
- if (manager.get_current_type() != GLGizmosManager::Emboss)
- manager.open_gizmo(GLGizmosManager::Emboss);
-
- // redraw scene
- canvas->reload_scene(true);
+ priv::create_volume(std::move(m_result), m_input.object_idx, m_input.volume_type, m_input.trmat, m_input);
}
/////////////////
/// Create Object
-EmbossCreateObjectJob::EmbossCreateObjectJob(EmbossDataCreateObject &&input)
+CreateObjectJob::CreateObjectJob(DataCreateObject &&input)
: m_input(std::move(input))
{
assert(priv::check(m_input));
}
-void EmbossCreateObjectJob::process(Ctl &ctl)
+void CreateObjectJob::process(Ctl &ctl)
{
if (!priv::check(m_input))
throw std::runtime_error("Bad input data for EmbossCreateObjectJob.");
@@ -240,7 +191,7 @@ void EmbossCreateObjectJob::process(Ctl &ctl)
m_transformation = Transform3d(tt);
}
-void EmbossCreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
+void CreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
{
// doesn't care about exception when process was canceled by user
if (canceled) {
@@ -279,13 +230,13 @@ void EmbossCreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
/////////////////
/// Update Volume
-EmbossUpdateJob::EmbossUpdateJob(EmbossDataUpdate&& input)
+UpdateJob::UpdateJob(DataUpdate&& input)
: m_input(std::move(input))
{
assert(priv::check(m_input, true));
}
-void EmbossUpdateJob::process(Ctl &ctl)
+void UpdateJob::process(Ctl &ctl)
{
if (!priv::check(m_input))
throw std::runtime_error("Bad input data for EmbossUpdateJob.");
@@ -297,16 +248,14 @@ void EmbossUpdateJob::process(Ctl &ctl)
m_result = priv::try_create_mesh(m_input, m_input.font_file, was_canceled);
if (was_canceled()) return;
if (m_result.its.empty())
- throw priv::EmbossJobException(
- _u8L("Created text volume is empty. Change text or "
- "font.").c_str());
+ throw priv::JobException(_u8L("Created text volume is empty. Change text or font.").c_str());
// center triangle mesh
Vec3d shift = m_result.bounding_box().center();
m_result.translate(-shift.cast());
}
-void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &eptr)
+void UpdateJob::finalize(bool canceled, std::exception_ptr &eptr)
{
// doesn't care about exception when process was canceled by user
if (canceled || m_input.cancel->load()) {
@@ -317,19 +266,14 @@ void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &eptr)
priv::update_volume(std::move(m_result), m_input);
}
-UseSurfaceData::ModelSources UseSurfaceData::create_sources(
- const ModelVolume *text_volume)
-{
- if (text_volume == nullptr) return {};
- if (!text_volume->text_configuration.has_value()) return {};
- const ModelVolumePtrs &volumes = text_volume->get_object()->volumes;
- // no other volume in object
- if (volumes.size() <= 1) return {};
+namespace Slic3r::GUI::Emboss {
- ModelSources result;
+SurfaceVolumeData::ModelSources create_sources(const ModelVolumePtrs &volumes, std::optional text_volume_id)
+{
+ SurfaceVolumeData::ModelSources result;
result.reserve(volumes.size() - 1);
for (const ModelVolume *v : volumes) {
- if (v->id() == text_volume->id()) continue;
+ if (text_volume_id.has_value() && v->id().id == *text_volume_id) continue;
// skip modifiers and negative volumes, ...
if (!v->is_model_part()) continue;
const TriangleMesh &tm = v->mesh();
@@ -340,15 +284,60 @@ UseSurfaceData::ModelSources UseSurfaceData::create_sources(
return result;
}
+SurfaceVolumeData::ModelSources create_volume_sources(const ModelVolume *text_volume)
+{
+ if (text_volume == nullptr) return {};
+ if (!text_volume->text_configuration.has_value()) return {};
+ const ModelVolumePtrs &volumes = text_volume->get_object()->volumes;
+ // no other volume in object
+ if (volumes.size() <= 1) return {};
+ return create_sources(volumes, text_volume->id().id);
+}
+
+} // namespace Slic3r::GUI::Emboss
+
/////////////////
-/// Cut Surface
-UseSurfaceJob::UseSurfaceJob(UseSurfaceData &&input)
+/// Create Surface volume
+CreateSurfaceVolumeJob::CreateSurfaceVolumeJob(CreateSurfaceVolumeData &&input)
: m_input(std::move(input))
{
assert(priv::check(m_input, true));
}
-void UseSurfaceJob::process(Ctl &ctl) {
+void CreateSurfaceVolumeJob::process(Ctl &ctl) {
+ if (!priv::check(m_input))
+ throw std::runtime_error("Bad input data for CreateSurfaceVolumeJob.");
+ // check cancelation of process
+ auto was_canceled = [&ctl]() -> bool { return ctl.was_canceled(); };
+ m_result = priv::cut_surface(m_input, m_input, was_canceled);
+}
+
+void CreateSurfaceVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
+ // doesn't care about exception when process was canceled by user
+ if (canceled) return;
+ if (priv::process(eptr)) return;
+
+ // TODO: Find better way to Not center volume data when add !!!
+ TriangleMesh mesh = m_result; // Part1: copy
+
+ priv::create_volume(std::move(m_result), m_input.object_idx,
+ m_input.volume_type, m_input.text_tr, m_input);
+
+ // Part2: update volume data
+ //auto vol = wxGetApp().plater()->model().objects[m_input.object_idx]->volumes.back();
+ //UpdateJob::update_volume(vol, std::move(mesh), m_input.text_configuration, m_input.volume_name);
+}
+
+/////////////////
+/// Cut Surface
+UpdateSurfaceVolumeJob::UpdateSurfaceVolumeJob(UpdateSurfaceVolumeData &&input)
+ : m_input(std::move(input))
+{
+ assert(priv::check(m_input, true));
+}
+
+void UpdateSurfaceVolumeJob::process(Ctl &ctl)
+{
if (!priv::check(m_input))
throw std::runtime_error("Bad input data for UseSurfaceJob.");
@@ -357,107 +346,25 @@ void UseSurfaceJob::process(Ctl &ctl) {
if (cancel->load()) return true;
return ctl.was_canceled();
};
-
- const TextConfiguration &tc = m_input.text_configuration;
- const char *text = tc.text.c_str();
- const FontProp &fp = tc.style.prop;
- ExPolygons shapes = Emboss::text2shapes(m_input.font_file, text, fp, was_canceled);
- if (shapes.empty() || shapes.front().contour.empty())
- throw priv::EmbossJobException(
- _u8L("Font doesn't have any shape for given text.").c_str());
-
- if (was_canceled()) return;
-
- // Define alignment of text - left, right, center, top bottom, ....
- BoundingBox bb = get_extents(shapes);
- Point projection_center = bb.center();
- for (ExPolygon &shape : shapes) shape.translate(-projection_center);
- bb.translate(-projection_center);
-
- const Emboss::FontFile &ff = *m_input.font_file.font_file;
- double shape_scale = Emboss::get_shape_scale(fp, ff);
-
- size_t biggest_count = 0;
- const UseSurfaceData::ModelSource *biggest = nullptr;
- std::vector s_to_itss(m_input.sources.size(), std::numeric_limits::max());
- std::vector itss;
- itss.reserve(m_input.sources.size());
- for (const UseSurfaceData::ModelSource &s : m_input.sources) {
- Transform3d mesh_tr_inv = s.tr.inverse();
- Transform3d cut_projection_tr = mesh_tr_inv * m_input.text_tr;
- std::pair z_range{0., 1.};
- Emboss::OrthoProject cut_projection =
- priv::create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
- // copy only part of source model
- indexed_triangle_set its = its_cut_AoI(s.mesh->its, bb, cut_projection);
- if (its.indices.empty()) continue;
- if (biggest_count < its.vertices.size()) {
- biggest_count = its.vertices.size();
- biggest = &s;
- }
- s_to_itss[&s - &m_input.sources.front()] = itss.size();
- itss.emplace_back(std::move(its));
- }
- if (itss.empty())
- throw priv::EmbossJobException(_u8L("There is no volume in projection direction.").c_str());
-
- Transform3d tr_inv = biggest->tr.inverse();
- size_t itss_index = s_to_itss[biggest - &m_input.sources.front()];
- BoundingBoxf3 mesh_bb = bounding_box(itss[itss_index]);
- for (const UseSurfaceData::ModelSource &s : m_input.sources) {
- if (&s == biggest) continue;
- size_t itss_index = s_to_itss[&s - &m_input.sources.front()];
- if (itss_index == std::numeric_limits::max()) continue;
- Transform3d tr = s.tr * tr_inv;
- indexed_triangle_set &its = itss[itss_index];
- its_transform(its, tr);
- BoundingBoxf3 bb = bounding_box(its);
- mesh_bb.merge(bb);
- }
-
- Transform3d mesh_tr_inv = tr_inv;
- Transform3d cut_projection_tr = mesh_tr_inv * m_input.text_tr;
- Transform3d emboss_tr = cut_projection_tr.inverse();
- BoundingBoxf3 mesh_bb_tr = mesh_bb.transformed(emboss_tr);
- std::pair z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
- Emboss::OrthoProject cut_projection = priv::create_projection_for_cut(
- cut_projection_tr, shape_scale, z_range);
- float projection_ratio = (-z_range.first + priv::safe_extension) /
- (z_range.second - z_range.first + 2 * priv::safe_extension);
-
- // Use CGAL to cut surface from triangle mesh
- SurfaceCut cut = cut_surface(shapes, itss, cut_projection, projection_ratio);
- if (cut.empty())
- throw priv::EmbossJobException(
- _u8L("There is no valid surface for text projection.").c_str());
- if (was_canceled()) return;
-
- // !! Projection needs to transform cut
- Emboss::OrthoProject3d projection = priv::create_emboss_projection(
- m_input.is_outside, fp.emboss, emboss_tr, cut);
-
- indexed_triangle_set new_its = cut2model(cut, projection);
- assert(!new_its.empty());
-
- if (was_canceled()) return;
- //its_write_obj(new_its, "C:/data/temp/projected.obj"); // only debug
- m_result = TriangleMesh(std::move(new_its));
+ m_result = priv::cut_surface(m_input, m_input, was_canceled);
}
-void UseSurfaceJob::finalize(bool canceled, std::exception_ptr &eptr)
+void UpdateSurfaceVolumeJob::finalize(bool canceled, std::exception_ptr &eptr)
{
// doesn't care about exception when process was canceled by user
- if (canceled || m_input.cancel->load()) {
+ if (m_input.cancel->load()) {
eptr = nullptr;
return;
}
+ if (canceled) return;
if (priv::process(eptr)) return;
priv::update_volume(std::move(m_result), m_input);
}
////////////////////////////
/// private namespace implementation
-bool priv::check(const EmbossDataBase &input, bool check_fontfile){
+bool priv::check(const DataBase &input, bool check_fontfile, bool use_surface)
+{
bool res = true;
if (check_fontfile) {
assert(input.font_file.has_value());
@@ -469,26 +376,24 @@ bool priv::check(const EmbossDataBase &input, bool check_fontfile){
res &= !input.text_configuration.text.empty();
assert(!input.volume_name.empty());
res &= !input.volume_name.empty();
+ assert(input.text_configuration.style.prop.use_surface == use_surface);
+ res &= input.text_configuration.style.prop.use_surface == use_surface;
return res;
}
-bool priv::check(const EmbossDataCreateVolume &input, bool is_main_thread) {
+bool priv::check(const DataCreateVolume &input, bool is_main_thread) {
bool check_fontfile = false;
- bool res = check((EmbossDataBase) input, check_fontfile);
+ bool res = check((DataBase) input, check_fontfile);
assert(input.volume_type != ModelVolumeType::INVALID);
res &= input.volume_type != ModelVolumeType::INVALID;
assert(input.object_idx >= 0);
res &= input.object_idx >= 0;
if (is_main_thread)
- assert((size_t)input.object_idx < wxGetApp().model().objects.size());
- assert(input.screen_coor.x() >= 0.);
- res &= input.screen_coor.x() >= 0.;
- assert(input.screen_coor.y() >= 0.);
- res &= input.screen_coor.y() >= 0.;
+ assert((size_t)input.object_idx < wxGetApp().model().objects.size());
return res;
}
-bool priv::check(const EmbossDataCreateObject &input) {
+bool priv::check(const DataCreateObject &input) {
bool check_fontfile = false;
- bool res = check((EmbossDataBase) input, check_fontfile);
+ bool res = check((DataBase) input, check_fontfile);
assert(input.screen_coor.x() >= 0.);
res &= input.screen_coor.x() >= 0.;
assert(input.screen_coor.y() >= 0.);
@@ -497,8 +402,9 @@ bool priv::check(const EmbossDataCreateObject &input) {
res &= input.bed_shape.size() >= 3;
return res;
}
-bool priv::check(const EmbossDataUpdate &input, bool is_main_thread){
- bool res = check((EmbossDataBase) input);
+bool priv::check(const DataUpdate &input, bool is_main_thread, bool use_surface){
+ bool check_fontfile = true;
+ bool res = check((DataBase) input, check_fontfile, use_surface);
assert(input.volume_id.id >= 0);
res &= input.volume_id.id >= 0;
if (is_main_thread)
@@ -509,15 +415,24 @@ bool priv::check(const EmbossDataUpdate &input, bool is_main_thread){
assert(!input.cancel->load());
return res;
}
-bool priv::check(const UseSurfaceData &input, bool is_main_thread){
- bool res = check((EmbossDataUpdate) input, is_main_thread);
+bool priv::check(const CreateSurfaceVolumeData &input, bool is_main_thread)
+{
+ bool use_surface = true;
+ bool res = check((DataBase)input, is_main_thread, use_surface);
+ assert(!input.sources.empty());
+ res &= !input.sources.empty();
+ return res;
+}
+bool priv::check(const UpdateSurfaceVolumeData &input, bool is_main_thread){
+ bool use_surface = true;
+ bool res = check((DataUpdate)input, is_main_thread, use_surface);
assert(!input.sources.empty());
res &= !input.sources.empty();
return res;
}
template
-TriangleMesh priv::try_create_mesh(const EmbossDataBase &input, Emboss::FontFileWithCache &font, Fnc was_canceled)
+TriangleMesh priv::try_create_mesh(const DataBase &input, FontFileWithCache &font, Fnc was_canceled)
{
const TextConfiguration &tc = input.text_configuration;
const char *text = tc.text.c_str();
@@ -526,7 +441,7 @@ TriangleMesh priv::try_create_mesh(const EmbossDataBase &input, Emboss::FontFile
assert(font.has_value());
if (!font.has_value()) return {};
- ExPolygons shapes = Emboss::text2shapes(font, text, prop, was_canceled);
+ ExPolygons shapes = text2shapes(font, text, prop, was_canceled);
if (shapes.empty()) return {};
if (was_canceled()) return {};
@@ -536,14 +451,14 @@ TriangleMesh priv::try_create_mesh(const EmbossDataBase &input, Emboss::FontFile
int unit_per_em = font.font_file->infos[font_index].unit_per_em;
float scale = prop.size_in_mm / unit_per_em;
float depth = prop.emboss / scale;
- auto projectZ = std::make_unique(depth);
- Emboss::ProjectScale project(std::move(projectZ), scale);
+ auto projectZ = std::make_unique(depth);
+ ProjectScale project(std::move(projectZ), scale);
if (was_canceled()) return {};
- return TriangleMesh(Emboss::polygons2model(shapes, project));
+ return TriangleMesh(polygons2model(shapes, project));
}
template
-TriangleMesh priv::create_mesh(EmbossDataBase &input, Fnc was_canceled, Job::Ctl& ctl)
+TriangleMesh priv::create_mesh(DataBase &input, Fnc was_canceled, Job::Ctl& ctl)
{
// It is neccessary to create some shape
// Emboss text window is opened by creation new emboss text object
@@ -579,10 +494,10 @@ TriangleMesh priv::create_default_mesh()
return triangle_mesh;
}
-void EmbossUpdateJob::update_volume(ModelVolume *volume,
- TriangleMesh &&mesh,
- const TextConfiguration &text_configuration,
- const std::string &volume_name)
+void UpdateJob::update_volume(ModelVolume *volume,
+ TriangleMesh &&mesh,
+ const TextConfiguration &text_configuration,
+ const std::string &volume_name)
{
// check inputs
bool is_valid_input =
@@ -626,7 +541,7 @@ void EmbossUpdateJob::update_volume(ModelVolume *volume,
canvas->reload_scene(refresh_immediately);
}
-void priv::update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data)
+void priv::update_volume(TriangleMesh &&mesh, const DataUpdate &data)
{
// for sure that some object will be created
if (mesh.its.empty())
@@ -652,7 +567,72 @@ void priv::update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data)
if (tc.has_value() && tc->fix_3mf_tr.has_value())
volume->set_transformation(volume->get_matrix() * tc->fix_3mf_tr->inverse());
- EmbossUpdateJob::update_volume(volume, std::move(mesh), data.text_configuration, data.volume_name);
+ UpdateJob::update_volume(volume, std::move(mesh), data.text_configuration, data.volume_name);
+}
+
+void priv::create_volume(
+ TriangleMesh &&mesh, const size_t object_idx,
+ const ModelVolumeType type, const Transform3d trmat, const DataBase &data)
+{
+ GUI_App &app = wxGetApp();
+ Plater *plater = app.plater();
+ ObjectList *obj_list = app.obj_list();
+ GLCanvas3D *canvas = plater->canvas3D();
+ ModelObjectPtrs &objects = plater->model().objects;
+
+ // Parent object for text volume was propably removed.
+ // Assumption: User know what he does, so text volume is no more needed.
+ if (objects.size() <= object_idx)
+ return priv::create_message(_u8L("Bad object index to create volume."));
+
+ if (mesh.its.empty())
+ return priv::create_message(_u8L("Can't create empty volume."));
+
+ plater->take_snapshot(_L("Add Emboss text Volume"));
+
+ ModelObject *obj = objects[object_idx];
+
+ // NOTE: be carefull add volume also center mesh !!!
+ // So first add simple shape(convex hull is also calculated)
+ ModelVolume *volume = obj->add_volume(make_cube(1., 1., 1.), type);
+
+ // TODO: Refactor to create better way to not set cube at begining
+ // Revert mesh centering by set mesh after add cube
+ volume->set_mesh(std::move(mesh));
+ volume->calculate_convex_hull();
+
+
+ // set a default extruder value, since user can't add it manually
+ volume->config.set_key_value("extruder", new ConfigOptionInt(0));
+
+ // do not allow model reload from disk
+ volume->source.is_from_builtin_objects = true;
+
+ volume->name = data.volume_name; // copy
+ volume->text_configuration = data.text_configuration; // copy
+ volume->set_transformation(trmat);
+
+ // update volume name in object list
+ // updata selection after new volume added
+ // change name of volume in right panel
+ // select only actual volume
+ // when new volume is created change selection to this volume
+ auto add_to_selection = [volume](const ModelVolume *vol) { return vol == volume; };
+ wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(object_idx, add_to_selection);
+ if (!sel.IsEmpty()) obj_list->select_item(sel.front());
+
+ // update printable state on canvas
+ if (type == ModelVolumeType::MODEL_PART) canvas->update_instance_printable_state_for_object(object_idx);
+
+ obj_list->selection_changed();
+
+ // Now is valid text volume selected open emboss gizmo
+ GLGizmosManager &manager = canvas->get_gizmos_manager();
+ if (manager.get_current_type() != GLGizmosManager::Emboss)
+ manager.open_gizmo(GLGizmosManager::Emboss);
+
+ // redraw scene
+ canvas->reload_scene(true);
}
ModelVolume *priv::get_volume(ModelObjectPtrs &objects,
@@ -664,7 +644,7 @@ ModelVolume *priv::get_volume(ModelObjectPtrs &objects,
return nullptr;
};
-Emboss::OrthoProject priv::create_projection_for_cut(
+OrthoProject priv::create_projection_for_cut(
Transform3d tr,
double shape_scale,
const std::pair &z_range)
@@ -686,10 +666,10 @@ Emboss::OrthoProject priv::create_projection_for_cut(
// Projection is in direction from far plane
tr.translate(Vec3d(0., 0., min_z));
tr.scale(shape_scale);
- return Emboss::OrthoProject(tr, project_direction);
+ return OrthoProject(tr, project_direction);
}
-Emboss::OrthoProject3d priv::create_emboss_projection(
+OrthoProject3d priv::create_emboss_projection(
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
{
// Offset of clossed side to model
@@ -699,14 +679,98 @@ Emboss::OrthoProject3d priv::create_emboss_projection(
back_move = -((is_outside) ? surface_offset : emboss);
its_transform(cut, tr.pretranslate(Vec3d(0., 0., front_move)));
Vec3d from_front_to_back(0., 0., back_move - front_move);
- return Emboss::OrthoProject3d(from_front_to_back);
+ return OrthoProject3d(from_front_to_back);
+}
+
+// input can't be const - cache of font
+TriangleMesh priv::cut_surface(DataBase& input1, const SurfaceVolumeData& input2, std::function was_canceled)
+{
+ const TextConfiguration &tc = input1.text_configuration;
+ const char *text = tc.text.c_str();
+ const FontProp &fp = tc.style.prop;
+
+ ExPolygons shapes = text2shapes(input1.font_file, text, fp, was_canceled);
+ if (shapes.empty() || shapes.front().contour.empty())
+ throw JobException(_u8L("Font doesn't have any shape for given text.").c_str());
+
+ if (was_canceled()) return {};
+
+ // Define alignment of text - left, right, center, top bottom, ....
+ BoundingBox bb = get_extents(shapes);
+ Point projection_center = bb.center();
+ for (ExPolygon &shape : shapes) shape.translate(-projection_center);
+ bb.translate(-projection_center);
+
+ const FontFile &ff = *input1.font_file.font_file;
+ double shape_scale = get_shape_scale(fp, ff);
+
+ const SurfaceVolumeData::ModelSources &sources = input2.sources;
+ const SurfaceVolumeData::ModelSource *biggest = nullptr;
+
+ size_t biggest_count = 0;
+ // convert index from (s)ources to (i)ndexed (t)riangle (s)ets
+ std::vector s_to_itss(sources.size(), std::numeric_limits::max());
+ std::vector itss;
+ itss.reserve(sources.size());
+ for (const SurfaceVolumeData::ModelSource &s : sources) {
+ Transform3d mesh_tr_inv = s.tr.inverse();
+ Transform3d cut_projection_tr = mesh_tr_inv * input2.text_tr;
+ std::pair z_range{0., 1.};
+ OrthoProject cut_projection = create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
+ // copy only part of source model
+ indexed_triangle_set its = its_cut_AoI(s.mesh->its, bb, cut_projection);
+ if (its.indices.empty()) continue;
+ if (biggest_count < its.vertices.size()) {
+ biggest_count = its.vertices.size();
+ biggest = &s;
+ }
+ s_to_itss[&s - &sources.front()] = itss.size();
+ itss.emplace_back(std::move(its));
+ }
+ if (itss.empty()) throw JobException(_u8L("There is no volume in projection direction.").c_str());
+
+ Transform3d tr_inv = biggest->tr.inverse();
+ size_t itss_index = s_to_itss[biggest - &sources.front()];
+ BoundingBoxf3 mesh_bb = bounding_box(itss[itss_index]);
+ for (const SurfaceVolumeData::ModelSource &s : sources) {
+ if (&s == biggest) continue;
+ size_t itss_index = s_to_itss[&s - &sources.front()];
+ if (itss_index == std::numeric_limits::max()) continue;
+ Transform3d tr = s.tr * tr_inv;
+ indexed_triangle_set &its = itss[itss_index];
+ its_transform(its, tr);
+ BoundingBoxf3 bb = bounding_box(its);
+ mesh_bb.merge(bb);
+ }
+
+ // tr_inv = transformation of mesh inverted
+ Transform3d cut_projection_tr = tr_inv * input2.text_tr;
+ Transform3d emboss_tr = cut_projection_tr.inverse();
+ BoundingBoxf3 mesh_bb_tr = mesh_bb.transformed(emboss_tr);
+ std::pair z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
+ OrthoProject cut_projection = create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
+ float projection_ratio = (-z_range.first + safe_extension) / (z_range.second - z_range.first + 2 * safe_extension);
+
+ // Use CGAL to cut surface from triangle mesh
+ SurfaceCut cut = cut_surface(shapes, itss, cut_projection, projection_ratio);
+ if (cut.empty()) throw JobException(_u8L("There is no valid surface for text projection.").c_str());
+ if (was_canceled()) return {};
+
+ // !! Projection needs to transform cut
+ OrthoProject3d projection = create_emboss_projection(input2.is_outside, fp.emboss, emboss_tr, cut);
+
+ indexed_triangle_set new_its = cut2model(cut, projection);
+ assert(!new_its.empty());
+
+ if (was_canceled()) return {};
+ return TriangleMesh(std::move(new_its));
}
bool priv::process(std::exception_ptr &eptr) {
if (!eptr) return false;
try {
std::rethrow_exception(eptr);
- } catch (priv::EmbossJobException &e) {
+ } catch (priv::JobException &e) {
create_message(e.what());
eptr = nullptr;
}
diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp
index bd347812fa..cf64044bf0 100644
--- a/src/slic3r/GUI/Jobs/EmbossJob.hpp
+++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp
@@ -15,15 +15,15 @@ class ModelVolume;
class TriangleMesh;
}
-namespace Slic3r::GUI {
+namespace Slic3r::GUI::Emboss {
///
/// Base data holder for embossing
///
-struct EmbossDataBase
+struct DataBase
{
// Keep pointer on Data of font (glyph shapes)
- Emboss::FontFileWithCache font_file;
+ Slic3r::Emboss::FontFileWithCache font_file;
// font item is not used for create object
TextConfiguration text_configuration;
// new volume name created from text
@@ -35,24 +35,16 @@ struct EmbossDataBase
/// Volume is created on the surface of existing volume in object.
/// NOTE: EmbossDataBase::font_file doesn't have to be valid !!!
///
-struct EmbossDataCreateVolume : public EmbossDataBase
+struct DataCreateVolume : public DataBase
{
// define embossed volume type
ModelVolumeType volume_type;
- // define position on screen where to create object
- Vec2d screen_coor;
-
// parent ModelObject index where to create volume
int object_idx;
- // projection property
- Camera camera;
-
- // used to find point on surface where to create new object
- RaycastManager::SurfacePoint hit;
- Transform3d hit_object_tr;
- Transform3d hit_instance_tr;
+ // new created volume transformation
+ Transform3d trmat;
};
///
@@ -60,14 +52,13 @@ struct EmbossDataCreateVolume : public EmbossDataBase
/// Should not be stopped
/// NOTE: EmbossDataBase::font_file doesn't have to be valid !!!
///
-class EmbossCreateVolumeJob : public Job
+class CreateVolumeJob : public Job
{
- EmbossDataCreateVolume m_input;
- TriangleMesh m_result;
- Transform3d m_transformation;
+ DataCreateVolume m_input;
+ TriangleMesh m_result;
public:
- EmbossCreateVolumeJob(EmbossDataCreateVolume&& input);
+ CreateVolumeJob(DataCreateVolume&& input);
void process(Ctl &ctl) override;
void finalize(bool canceled, std::exception_ptr &eptr) override;
};
@@ -77,7 +68,7 @@ public:
/// Object is placed on bed under screen coor
/// OR to center of scene when it is out of bed shape
///
-struct EmbossDataCreateObject : public EmbossDataBase
+struct DataCreateObject : public DataBase
{
// define position on screen where to create object
Vec2d screen_coor;
@@ -93,13 +84,13 @@ struct EmbossDataCreateObject : public EmbossDataBase
/// Create new TextObject on the platter
/// Should not be stopped
///
-class EmbossCreateObjectJob : public Job
+class CreateObjectJob : public Job
{
- EmbossDataCreateObject m_input;
- TriangleMesh m_result;
- Transform3d m_transformation;
+ DataCreateObject m_input;
+ TriangleMesh m_result;
+ Transform3d m_transformation;
public:
- EmbossCreateObjectJob(EmbossDataCreateObject&& input);
+ CreateObjectJob(DataCreateObject&& input);
void process(Ctl &ctl) override;
void finalize(bool canceled, std::exception_ptr &eptr) override;
};
@@ -107,7 +98,7 @@ public:
///
/// Hold neccessary data to update embossed text object in job
///
-struct EmbossDataUpdate : public EmbossDataBase
+struct DataUpdate : public DataBase
{
// unique identifier of volume to change
ObjectID volume_id;
@@ -121,14 +112,14 @@ struct EmbossDataUpdate : public EmbossDataBase
/// Update text shape in existing text volume
/// Predict that there is only one runnig(not canceled) instance of it
///
-class EmbossUpdateJob : public Job
+class UpdateJob : public Job
{
- EmbossDataUpdate m_input;
- TriangleMesh m_result;
+ DataUpdate m_input;
+ TriangleMesh m_result;
public:
// move params to private variable
- EmbossUpdateJob(EmbossDataUpdate &&input);
+ UpdateJob(DataUpdate &&input);
///
/// Create new embossed volume by m_input data and store to m_result
@@ -158,10 +149,7 @@ public:
const std::string &volume_name);
};
-///
-/// Hold neccessary data to update embossed text object in job
-///
-struct UseSurfaceData : public EmbossDataUpdate
+struct SurfaceVolumeData
{
// Transformation of text volume inside of object
Transform3d text_tr;
@@ -180,26 +168,66 @@ struct UseSurfaceData : public EmbossDataUpdate
};
using ModelSources = std::vector;
ModelSources sources;
-
- ///
- /// Copied triangles from object to be able create mesh for cut surface from
- ///
- /// Define text in object
- /// Source data for cut surface from
- static ModelSources create_sources(const ModelVolume *text_volume);
};
+///
+/// Hold neccessary data to create(cut) volume from surface object in job
+///
+struct CreateSurfaceVolumeData : public DataBase, public SurfaceVolumeData{
+ // define embossed volume type
+ ModelVolumeType volume_type;
+
+ // parent ModelObject index where to create volume
+ int object_idx;
+};
+
+///
+/// Cut surface from object and create cutted volume
+/// Should not be stopped
+///
+class CreateSurfaceVolumeJob : public Job
+{
+ CreateSurfaceVolumeData m_input;
+ TriangleMesh m_result;
+
+public:
+ CreateSurfaceVolumeJob(CreateSurfaceVolumeData &&input);
+ void process(Ctl &ctl) override;
+ void finalize(bool canceled, std::exception_ptr &eptr) override;
+};
+
+///
+/// Hold neccessary data to update embossed text object in job
+///
+struct UpdateSurfaceVolumeData : public DataUpdate, public SurfaceVolumeData{};
+
+///
+/// Copied triangles from object to be able create mesh for cut surface from
+///
+/// Source object volumes for cut surface from
+/// Source volume id
+/// Source data for cut surface from
+SurfaceVolumeData::ModelSources create_sources(const ModelVolumePtrs &volumes, std::optional text_volume_id = {});
+
+///
+/// Copied triangles from object to be able create mesh for cut surface from
+///
+/// Define text in object
+/// Source data for cut surface from
+SurfaceVolumeData::ModelSources create_volume_sources(const ModelVolume *text_volume);
+
+
///
/// Update text volume to use surface from object
///
-class UseSurfaceJob : public Job
+class UpdateSurfaceVolumeJob : public Job
{
- UseSurfaceData m_input;
+ UpdateSurfaceVolumeData m_input;
TriangleMesh m_result;
public:
// move params to private variable
- UseSurfaceJob(UseSurfaceData &&input);
+ UpdateSurfaceVolumeJob(UpdateSurfaceVolumeData &&input);
void process(Ctl &ctl) override;
void finalize(bool canceled, std::exception_ptr &eptr) override;
};
diff --git a/src/slic3r/Utils/EmbossStyleManager.cpp b/src/slic3r/Utils/EmbossStyleManager.cpp
index 3fff460361..060d936d85 100644
--- a/src/slic3r/Utils/EmbossStyleManager.cpp
+++ b/src/slic3r/Utils/EmbossStyleManager.cpp
@@ -12,9 +12,10 @@
#include "slic3r/Utils/EmbossStylesSerializable.hpp"
using namespace Slic3r;
-using namespace Slic3r::GUI;
+using namespace Slic3r::Emboss;
+using namespace Slic3r::GUI::Emboss;
-EmbossStyleManager::EmbossStyleManager(const ImWchar *language_glyph_range)
+StyleManager::StyleManager(const ImWchar *language_glyph_range)
: m_imgui_init_glyph_range(language_glyph_range)
, m_exist_style_images(false)
, m_temp_style_images(nullptr)
@@ -22,12 +23,12 @@ EmbossStyleManager::EmbossStyleManager(const ImWchar *language_glyph_range)
, m_last_style_index(std::numeric_limits::max())
{}
-EmbossStyleManager::~EmbossStyleManager() {
+StyleManager::~StyleManager() {
clear_imgui_font();
free_style_images();
}
-void EmbossStyleManager::init(AppConfig *app_config, const EmbossStyles &default_styles)
+void StyleManager::init(AppConfig *app_config, const EmbossStyles &default_styles)
{
m_app_config = app_config;
EmbossStyles styles = (app_config != nullptr) ?
@@ -67,7 +68,7 @@ void EmbossStyleManager::init(AppConfig *app_config, const EmbossStyles &default
}
}
-bool EmbossStyleManager::store_styles_to_app_config(bool use_modification,
+bool StyleManager::store_styles_to_app_config(bool use_modification,
bool store_activ_index)
{
assert(m_app_config != nullptr);
@@ -102,7 +103,7 @@ bool EmbossStyleManager::store_styles_to_app_config(bool use_modification,
return true;
}
-void EmbossStyleManager::add_style(const std::string &name) {
+void StyleManager::add_style(const std::string &name) {
EmbossStyle& style = m_style_cache.style;
style.name = name;
make_unique_name(style.name);
@@ -112,7 +113,7 @@ void EmbossStyleManager::add_style(const std::string &name) {
m_style_items.push_back({style});
}
-void EmbossStyleManager::swap(size_t i1, size_t i2) {
+void StyleManager::swap(size_t i1, size_t i2) {
if (i1 >= m_style_items.size() ||
i2 >= m_style_items.size()) return;
std::swap(m_style_items[i1], m_style_items[i2]);
@@ -125,7 +126,7 @@ void EmbossStyleManager::swap(size_t i1, size_t i2) {
}
}
-void EmbossStyleManager::discard_style_changes() {
+void StyleManager::discard_style_changes() {
if (exist_stored_style()) {
if (load_style(m_style_cache.style_index))
return; // correct reload style
@@ -138,7 +139,7 @@ void EmbossStyleManager::discard_style_changes() {
load_first_valid_font();
}
-void EmbossStyleManager::erase(size_t index) {
+void StyleManager::erase(size_t index) {
if (index >= m_style_items.size()) return;
// fix selected index
@@ -151,7 +152,7 @@ void EmbossStyleManager::erase(size_t index) {
m_style_items.erase(m_style_items.begin() + index);
}
-void EmbossStyleManager::rename(const std::string& name) {
+void StyleManager::rename(const std::string& name) {
m_style_cache.style.name = name;
m_style_cache.truncated_name.clear();
if (exist_stored_style()) {
@@ -161,7 +162,7 @@ void EmbossStyleManager::rename(const std::string& name) {
}
}
-bool EmbossStyleManager::load_style(size_t style_index)
+bool StyleManager::load_style(size_t style_index)
{
if (style_index >= m_style_items.size()) return false;
if (!load_style(m_style_items[style_index].style)) return false;
@@ -171,14 +172,14 @@ bool EmbossStyleManager::load_style(size_t style_index)
return true;
}
-bool EmbossStyleManager::load_style(const EmbossStyle &style) {
+bool StyleManager::load_style(const EmbossStyle &style) {
if (style.type == EmbossStyle::Type::file_path) {
- std::unique_ptr font_ptr =
- Emboss::create_font_file(style.path.c_str());
+ std::unique_ptr font_ptr =
+ create_font_file(style.path.c_str());
if (font_ptr == nullptr) return false;
m_style_cache.wx_font = {};
m_style_cache.font_file =
- Emboss::FontFileWithCache(std::move(font_ptr));
+ FontFileWithCache(std::move(font_ptr));
m_style_cache.style = style; // copy
m_style_cache.style_index = std::numeric_limits::max();
m_style_cache.stored_wx_font = {};
@@ -190,7 +191,7 @@ bool EmbossStyleManager::load_style(const EmbossStyle &style) {
return load_style(style, *wx_font_opt);
}
-bool EmbossStyleManager::load_style(const EmbossStyle &style, const wxFont &font)
+bool StyleManager::load_style(const EmbossStyle &style, const wxFont &font)
{
if (!set_wx_font(font)) return false;
m_style_cache.style = style; // copy
@@ -200,9 +201,9 @@ bool EmbossStyleManager::load_style(const EmbossStyle &style, const wxFont &font
return true;
}
-bool EmbossStyleManager::is_activ_font() { return m_style_cache.font_file.has_value(); }
+bool StyleManager::is_activ_font() { return m_style_cache.font_file.has_value(); }
-bool EmbossStyleManager::load_first_valid_font() {
+bool StyleManager::load_first_valid_font() {
while (!m_style_items.empty()) {
if (load_style(0)) return true;
// can't load so erase it from list
@@ -211,22 +212,22 @@ bool EmbossStyleManager::load_first_valid_font() {
return false;
}
-const EmbossStyle* EmbossStyleManager::get_stored_style() const
+const EmbossStyle* StyleManager::get_stored_style() const
{
if (m_style_cache.style_index >= m_style_items.size()) return nullptr;
return &m_style_items[m_style_cache.style_index].style;
}
-void EmbossStyleManager::clear_glyphs_cache()
+void StyleManager::clear_glyphs_cache()
{
- Emboss::FontFileWithCache &ff = m_style_cache.font_file;
+ FontFileWithCache &ff = m_style_cache.font_file;
if (!ff.has_value()) return;
- ff.cache = std::make_shared();
+ ff.cache = std::make_shared();
}
-void EmbossStyleManager::clear_imgui_font() { m_style_cache.atlas.Clear(); }
+void StyleManager::clear_imgui_font() { m_style_cache.atlas.Clear(); }
-ImFont *EmbossStyleManager::get_imgui_font()
+ImFont *StyleManager::get_imgui_font()
{
if (!is_activ_font()) return nullptr;
@@ -242,16 +243,16 @@ ImFont *EmbossStyleManager::get_imgui_font()
return font;
}
-const std::vector &EmbossStyleManager::get_styles() const{ return m_style_items; }
+const std::vector &StyleManager::get_styles() const{ return m_style_items; }
-ImFont* EmbossStyleManager::extend_imgui_font_range(size_t index, const std::string& text)
+ImFont* StyleManager::extend_imgui_font_range(size_t index, const std::string& text)
{
// TODO: start using merge mode
// ImFontConfig::MergeMode = true;
return create_imgui_font(text);
}
-void EmbossStyleManager::make_unique_name(std::string &name)
+void StyleManager::make_unique_name(std::string &name)
{
auto is_unique = [&](const std::string &name) -> bool {
for (const Item &it : m_style_items)
@@ -283,7 +284,7 @@ void EmbossStyleManager::make_unique_name(std::string &name)
name = new_name;
}
-void EmbossStyleManager::init_trunc_names(float max_width) {
+void StyleManager::init_trunc_names(float max_width) {
for (auto &s : m_style_items)
if (s.truncated_name.empty()) {
std::string name = s.style.name;
@@ -298,7 +299,7 @@ void EmbossStyleManager::init_trunc_names(float max_width) {
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
-void EmbossStyleManager::init_style_images(const Vec2i &max_size,
+void StyleManager::init_style_images(const Vec2i &max_size,
const std::string &text)
{
// check already initialized
@@ -311,7 +312,7 @@ void EmbossStyleManager::init_style_images(const Vec2i &max_size,
assert(m_temp_style_images->images.size() ==
m_temp_style_images->styles.size());
// copy images into styles
- for (EmbossStyleManager::StyleImage &image : m_temp_style_images->images){
+ for (StyleManager::StyleImage &image : m_temp_style_images->images){
size_t index = &image - &m_temp_style_images->images.front();
StyleImagesData::Item &style = m_temp_style_images->styles[index];
@@ -340,11 +341,11 @@ void EmbossStyleManager::init_style_images(const Vec2i &max_size,
const EmbossStyle &style = item.style;
std::optional wx_font_opt = WxFontUtils::load_wxFont(style.path);
if (!wx_font_opt.has_value()) continue;
- std::unique_ptr font_file =
+ std::unique_ptr font_file =
WxFontUtils::create_font_file(*wx_font_opt);
if (font_file == nullptr) continue;
styles.push_back({
- Emboss::FontFileWithCache(std::move(font_file)),
+ FontFileWithCache(std::move(font_file)),
style.name,
style.prop
});
@@ -354,7 +355,7 @@ void EmbossStyleManager::init_style_images(const Vec2i &max_size,
queue_job(worker, std::make_unique(std::move(data)));
}
-void EmbossStyleManager::free_style_images() {
+void StyleManager::free_style_images() {
if (!m_exist_style_images) return;
GLuint tex_id = 0;
for (Item &it : m_style_items) {
@@ -367,10 +368,10 @@ void EmbossStyleManager::free_style_images() {
m_exist_style_images = false;
}
-float EmbossStyleManager::min_imgui_font_size = 18.f;
-float EmbossStyleManager::max_imgui_font_size = 60.f;
-float EmbossStyleManager::get_imgui_font_size(const FontProp &prop,
- const Emboss::FontFile &file)
+float StyleManager::min_imgui_font_size = 18.f;
+float StyleManager::max_imgui_font_size = 60.f;
+float StyleManager::get_imgui_font_size(const FontProp &prop,
+ const FontFile &file)
{
const auto &cn = prop.collection_number;
unsigned int font_index = (cn.has_value()) ? *cn : 0;
@@ -384,12 +385,12 @@ float EmbossStyleManager::get_imgui_font_size(const FontProp &prop,
return c1 * std::abs(prop.size_in_mm) / 0.3528f;
}
-ImFont *EmbossStyleManager::create_imgui_font(const std::string &text)
+ImFont *StyleManager::create_imgui_font(const std::string &text)
{
// inspiration inside of ImGuiWrapper::init_font
auto& ff = m_style_cache.font_file;
if (!ff.has_value()) return nullptr;
- const Emboss::FontFile &font_file = *ff.font_file;
+ const FontFile &font_file = *ff.font_file;
ImFontGlyphRangesBuilder builder;
builder.AddRanges(m_imgui_init_glyph_range);
@@ -464,18 +465,18 @@ ImFont *EmbossStyleManager::create_imgui_font(const std::string &text)
return font;
}
-bool EmbossStyleManager::set_wx_font(const wxFont &wx_font) {
- std::unique_ptr font_file =
+bool StyleManager::set_wx_font(const wxFont &wx_font) {
+ std::unique_ptr font_file =
WxFontUtils::create_font_file(wx_font);
return set_wx_font(wx_font, std::move(font_file));
}
-bool EmbossStyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr font_file)
+bool StyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr font_file)
{
if (font_file == nullptr) return false;
m_style_cache.wx_font = wx_font; // copy
m_style_cache.font_file =
- Emboss::FontFileWithCache(std::move(font_file));
+ FontFileWithCache(std::move(font_file));
EmbossStyle &style = m_style_cache.style;
style.type = WxFontUtils::get_actual_type();
diff --git a/src/slic3r/Utils/EmbossStyleManager.hpp b/src/slic3r/Utils/EmbossStyleManager.hpp
index 0012bcd3cf..af915d1449 100644
--- a/src/slic3r/Utils/EmbossStyleManager.hpp
+++ b/src/slic3r/Utils/EmbossStyleManager.hpp
@@ -11,24 +11,24 @@
class wxFont;
-namespace Slic3r::GUI {
+namespace Slic3r::GUI::Emboss {
///
/// Manage Emboss text styles
/// Cache actual state of style
/// + imgui font
/// + wx font
///
-class EmbossStyleManager
+class StyleManager
{
friend class CreateFontStyleImagesJob; // access to StyleImagesData
public:
- EmbossStyleManager(const ImWchar *language_glyph_range);
+ StyleManager(const ImWchar *language_glyph_range);
///
/// Release imgui font and style images from GPU
///
- ~EmbossStyleManager();
+ ~StyleManager();
///
/// Load font style list from config
@@ -111,7 +111,7 @@ public:
FontProp &get_font_prop() { return get_style().prop; }
const std::optional &get_wx_font() const { return m_style_cache.wx_font; }
const std::optional &get_stored_wx_font() const { return m_style_cache.stored_wx_font; }
- Emboss::FontFileWithCache &get_font_file_with_cache() { return m_style_cache.font_file; }
+ Slic3r::Emboss::FontFileWithCache &get_font_file_with_cache() { return m_style_cache.font_file; }
bool has_collections() const { return m_style_cache.font_file.font_file != nullptr &&
m_style_cache.font_file.font_file->infos.size() > 1; }
@@ -132,7 +132,7 @@ public:
/// Must be source of font file
/// font file created by WxFontUtils::create_font_file(wx_font)
/// True on success otherwise false
- bool set_wx_font(const wxFont &wx_font, std::unique_ptr font_file );
+ bool set_wx_font(const wxFont &wx_font, std::unique_ptr font_file);
// Getter on acitve font pointer for imgui
// Initialize imgui font(generate texture) when doesn't exist yet.
@@ -191,7 +191,7 @@ public:
// Value out of limits is crop
static float min_imgui_font_size;
static float max_imgui_font_size;
- static float get_imgui_font_size(const FontProp& prop, const Emboss::FontFile& file);
+ static float get_imgui_font_size(const FontProp &prop, const Slic3r::Emboss::FontFile &file);
private:
// erase font when not possible to load
@@ -207,7 +207,7 @@ private:
struct StyleCache
{
// share font file data with emboss job thread
- Emboss::FontFileWithCache font_file = {};
+ Slic3r::Emboss::FontFileWithCache font_file = {};
// must live same as imgui_font inside of atlas
ImVector ranges = {};
@@ -251,7 +251,7 @@ private:
{
struct Item
{
- Emboss::FontFileWithCache font;
+ Slic3r::Emboss::FontFileWithCache font;
std::string text;
FontProp prop;
};
diff --git a/src/slic3r/Utils/WxFontUtils.hpp b/src/slic3r/Utils/WxFontUtils.hpp
index d047740b1f..9732d2dc91 100644
--- a/src/slic3r/Utils/WxFontUtils.hpp
+++ b/src/slic3r/Utils/WxFontUtils.hpp
@@ -51,7 +51,7 @@ public:
/// wx descriptor of font
/// file described in wx font
/// New created font fileon success otherwise nullptr
- static std::unique_ptr set_italic(wxFont &font, const Emboss::FontFile& prev_font_file);
+ static std::unique_ptr set_italic(wxFont &font, const Slic3r::Emboss::FontFile &prev_font_file);
///
/// Set boldness into wx font
@@ -61,7 +61,7 @@ public:
/// wx descriptor of font
/// file described in wx font
/// New created font fileon success otherwise nullptr
- static std::unique_ptr set_bold(wxFont &font, const Emboss::FontFile& font_file);
+ static std::unique_ptr set_bold(wxFont &font, const Slic3r::Emboss::FontFile &font_file);
// convert wxFont types to string and vice versa
static const boost::bimap type_to_family;