diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp
index d97f1b32d0..a46422022b 100644
--- a/src/libslic3r/Point.hpp
+++ b/src/libslic3r/Point.hpp
@@ -144,6 +144,21 @@ Pointf3s transform(const Pointf3s& points, const Transform3d& t);
/// Is positive determinant
inline bool has_reflection(const Transform3d &transform) { return transform.matrix().determinant() < 0; }
+///
+/// Getter on base of transformation matrix
+///
+/// column index
+/// source transformation
+/// Base of transformation matrix
+inline const Vec3d &get_base(unsigned index, const Transform3d &transform) { return transform.linear().col(index); }
+inline const Vec3d &get_base(unsigned index, const Transform3d::LinearPart &transform) { return transform.col(index); }
+inline const Vec3d& get_x_base(const Transform3d &transform) { return get_base(0, transform); }
+inline const Vec3d& get_y_base(const Transform3d &transform) { return get_base(1, transform); }
+inline const Vec3d& get_z_base(const Transform3d &transform) { return get_base(2, transform); }
+inline const Vec3d &get_x_base(const Transform3d::LinearPart &transform) { return get_base(0, transform); }
+inline const Vec3d &get_y_base(const Transform3d::LinearPart &transform) { return get_base(1, transform); }
+inline const Vec3d &get_z_base(const Transform3d::LinearPart &transform) { return get_base(2, transform); }
+
template using Vec = Eigen::Matrix;
class Point : public Vec2crd
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
index 75fe6cbfc5..f00ae83aed 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
@@ -154,14 +154,13 @@ const IconManager::Icon &get_icon(const IconManager::VIcons& icons, IconType typ
static bool draw_button(const IconManager::VIcons& icons, IconType type, bool disable = false);
} // namespace priv
-CreateVolumeParams create_input(GLCanvas3D &canvas, StyleManager &styler, RaycastManager& raycaster, ModelVolumeType volume_type)
+CreateVolumeParams create_input(GLCanvas3D &canvas, const StyleManager::Style &style, RaycastManager& raycaster, ModelVolumeType volume_type)
{
auto gizmo = static_cast(GLGizmosManager::Emboss);
const GLVolume *gl_volume = get_first_hovered_gl_volume(canvas);
- const FontProp &fp = styler.get_style().prop;
Plater *plater = wxGetApp().plater();
return CreateVolumeParams{canvas, plater->get_camera(), plater->build_volume(),
- plater->get_ui_job_worker(), volume_type, raycaster, gizmo, gl_volume, fp.distance, fp.angle};
+ plater->get_ui_job_worker(), volume_type, raycaster, gizmo, gl_volume, style.distance, style.angle};
}
bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
@@ -171,7 +170,7 @@ bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous
// NOTE: change style manager - be carefull with order changes
DataBasePtr base = priv::create_emboss_data_base(m_text, m_style_manager, m_job_cancel);
- CreateVolumeParams input = create_input(m_parent, m_style_manager, m_raycast_manager, volume_type);
+ CreateVolumeParams input = create_input(m_parent, m_style_manager.get_style(), m_raycast_manager, volume_type);
return start_create_volume(input, std::move(base), mouse_pos);
}
@@ -183,7 +182,7 @@ bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type)
// NOTE: change style manager - be carefull with order changes
DataBasePtr base = priv::create_emboss_data_base(m_text, m_style_manager, m_job_cancel);
- CreateVolumeParams input = create_input(m_parent, m_style_manager, m_raycast_manager, volume_type);
+ CreateVolumeParams input = create_input(m_parent, m_style_manager.get_style(), m_raycast_manager, volume_type);
return start_create_volume_without_position(input, std::move(base));
}
@@ -197,9 +196,9 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
if (mouse_event.Dragging()) {
if (!m_rotate_start_angle.has_value()) {
// when m_rotate_start_angle is not set mean it is not Dragging
- // when angle_opt is not set mean angle is Zero
+ // when angle_opt is not set than angle is Zero
const std::optional &angle_opt = m_style_manager.get_font_prop().angle;
- m_rotate_start_angle = angle_opt.has_value() ? *angle_opt : 0.f;
+ m_rotate_start_angle = angle_opt.value_or(0.f);
}
double angle = m_rotate_gizmo.get_angle();
@@ -269,7 +268,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
if (gl_volume == nullptr || !m_style_manager.is_active_font())
return res;
- m_style_manager.get_style().prop.angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
+ m_style_manager.get_style().angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
}
}
return res;
@@ -576,7 +575,7 @@ void GLGizmoEmboss::on_stop_dragging()
assert(m_style_manager.is_active_font());
assert(gl_volume != nullptr);
if (m_style_manager.is_active_font() && gl_volume != nullptr)
- m_style_manager.get_font_prop().angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
+ m_style_manager.get_style().angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
m_rotate_start_angle.reset();
@@ -754,15 +753,66 @@ EmbossStyles GLGizmoEmboss::create_default_styles()
void GLGizmoEmboss::set_default_text(){ m_text = _u8L("Embossed text"); }
+namespace {
+
+///
+/// Throow ray by embossing params to object and find surface point
+///
+/// Define embossed volume
+/// Way to cast rays to object
+/// Contain model
+/// Calculated distance from surface
+std::optional calc_distance(const GLVolume &gl_volume, RaycastManager &raycaster, GLCanvas3D& canvas)
+{
+ const ModelObject *object = get_model_object(gl_volume, canvas.get_model()->objects);
+ assert(object != nullptr);
+ if (object == nullptr)
+ return {};
+
+ const ModelInstance *instance = get_model_instance(gl_volume, *object);
+ const ModelVolume *volume = get_model_volume(gl_volume, *object);
+ assert(instance != nullptr && volume != nullptr);
+ if (object == nullptr || instance == nullptr || volume == nullptr)
+ return {};
+
+ if (volume->is_the_only_one_part())
+ return {};
+
+ const ModelVolumePtrs &volumes = object->volumes;
+ std::vector allowed_volumes_id;
+ allowed_volumes_id.reserve(volumes.size() - 1);
+ for (const ModelVolume *v : volumes) {
+ // skip actual selected object
+ if (v->id() == volume->id())
+ continue;
+ // collect hit only from object parts not modifiers neither negative
+ if (!v->is_model_part())
+ continue;
+ allowed_volumes_id.emplace_back(v->id().id);
+ }
+ RaycastManager::AllowVolumes condition(std::move(allowed_volumes_id));
+ RaycastManager::Meshes meshes = create_meshes(canvas, condition);
+ raycaster.actualize(*instance, &condition, &meshes);
+
+ Transform3d w = gl_volume.world_matrix();
+ Vec3d p = w.translation();
+ const Vec3d& dir = get_z_base(w);
+ auto hit_opt = raycaster.first_hit(p, dir, &condition);
+ if (!hit_opt.has_value())
+ return {};
+}
+
+} // namespace
+
void GLGizmoEmboss::set_volume_by_selection()
{
const Selection &selection = m_parent.get_selection();
- const GLVolume *gl_volume = get_selected_gl_volume(selection);
+ const GLVolume *gl_volume = get_selected_gl_volume(selection);
if (gl_volume == nullptr)
return reset_volume();
const ModelObjectPtrs &objects = selection.get_model()->objects;
- ModelVolume *volume =get_model_volume(*gl_volume, objects);
+ ModelVolume *volume = get_model_volume(*gl_volume, objects);
if (volume == nullptr)
return reset_volume();
@@ -774,24 +824,28 @@ void GLGizmoEmboss::set_volume_by_selection()
remove_notification_not_valid_font();
// Do not use focused input value when switch volume(it must swith value)
- if (m_volume != nullptr &&
- m_volume != volume) // when update volume it changed id BUT not pointer
+ if (m_volume != nullptr && m_volume != volume) // when update volume it changed id BUT not pointer
ImGuiWrapper::left_inputs();
// Is selected volume text volume?
- const std::optional& tc_opt = volume->text_configuration;
- if (!tc_opt.has_value())
+ const std::optional &tc_opt = volume->text_configuration;
+ if (!tc_opt.has_value())
return reset_volume();
+ // Emboss shape must be setted
+ assert(volume->emboss_shape.has_value());
+ if (!volume->emboss_shape.has_value())
+ return;
+
const TextConfiguration &tc = *tc_opt;
const EmbossStyle &style = tc.style;
// Could exist OS without getter on face_name,
// but it is able to restore font from descriptor
// Soo default value must be TRUE
- bool is_font_installed = true;
- wxString face_name;
- std::optional face_name_opt = style.prop.face_name;
+ bool is_font_installed = true;
+ wxString face_name;
+ const std::optional &face_name_opt = style.prop.face_name;
if (face_name_opt.has_value()) {
face_name = wxString(face_name_opt->c_str());
@@ -800,21 +854,20 @@ void GLGizmoEmboss::set_volume_by_selection()
init_face_names(m_face_names);
m_face_names.is_init = false;
- auto cmp = [](const FaceName &fn, const wxString& face_name)->bool { return fn.wx_name < face_name; };
+ auto cmp = [](const FaceName &fn, const wxString &face_name) -> bool { return fn.wx_name < face_name; };
const std::vector &faces = m_face_names.faces;
auto it = std::lower_bound(faces.begin(), faces.end(), face_name, cmp);
is_font_installed = it != faces.end() && it->wx_name == face_name;
if (!is_font_installed) {
- const std::vector &bad = m_face_names.bad;
- auto it_bad = std::lower_bound(bad.begin(), bad.end(), face_name);
- if (it_bad == bad.end() || *it_bad != face_name){
+ const std::vector &bad = m_face_names.bad;
+ auto it_bad = std::lower_bound(bad.begin(), bad.end(), face_name);
+ if (it_bad == bad.end() || *it_bad != face_name) {
// check if wx allowed to set it up - another encoding of name
wxFontEnumerator::InvalidateCache();
- wxFont wx_font_; // temporary structure
- if (wx_font_.SetFaceName(face_name) &&
- WxFontUtils::create_font_file(wx_font_) != nullptr // can load TTF file?
- ) {
+ wxFont wx_font_; // temporary structure
+ if (wx_font_.SetFaceName(face_name) && WxFontUtils::create_font_file(wx_font_) != nullptr // can load TTF file?
+ ) {
is_font_installed = true;
// QUESTION: add this name to allowed faces?
// Could create twin of font face name
@@ -826,8 +879,8 @@ void GLGizmoEmboss::set_volume_by_selection()
wxFont wx_font;
// load wxFont from same OS when font name is installed
- if (style.type == WxFontUtils::get_actual_type() && is_font_installed)
- wx_font = WxFontUtils::load_wxFont(style.path);
+ if (style.type == WxFontUtils::get_current_type() && is_font_installed)
+ wx_font = WxFontUtils::load_wxFont(style.path);
// Flag that is selected same font
bool is_exact_font = true;
@@ -837,7 +890,7 @@ void GLGizmoEmboss::set_volume_by_selection()
// Try create similar wx font by FontFamily
wx_font = WxFontUtils::create_wxFont(style);
if (is_font_installed)
- is_exact_font = wx_font.SetFaceName(face_name);
+ is_exact_font = wx_font.SetFaceName(face_name);
// Have to use some wxFont
if (!wx_font.IsOk())
@@ -846,25 +899,28 @@ void GLGizmoEmboss::set_volume_by_selection()
assert(wx_font.IsOk());
// Load style to style manager
- const auto& styles = m_style_manager.get_styles();
- auto has_same_name = [&style](const StyleManager::Item &style_item) -> bool {
- const EmbossStyle &es = style_item.style;
- return es.name == style.name;
- };
+ const auto &styles = m_style_manager.get_styles();
+ auto has_same_name = [&name = style.name](const StyleManager::Style &style_item) { return style_item.name == name; };
+
+ StyleManager::Style style_{style};
+ style_.projection = volume->emboss_shape->projection;
+ style_.angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
+ style_.distance = calc_distance(*gl_volume, m_raycast_manager, m_parent);
+
auto it = std::find_if(styles.begin(), styles.end(), has_same_name);
if (it == styles.end()) {
// style was not found
- m_style_manager.load_style(style, wx_font);
+ m_style_manager.load_style(style_, wx_font);
} else {
// style name is in styles list
size_t style_index = it - styles.begin();
if (!m_style_manager.load_style(style_index)) {
// can`t load stored style
m_style_manager.erase(style_index);
- m_style_manager.load_style(style, wx_font);
+ m_style_manager.load_style(style_, wx_font);
} else {
// stored style is loaded, now set modification of style
- m_style_manager.get_style() = style;
+ m_style_manager.get_style() = style_;
m_style_manager.set_wx_font(wx_font);
}
}
@@ -890,11 +946,6 @@ void GLGizmoEmboss::set_volume_by_selection()
m_volume = volume;
m_volume_id = volume->id();
- // Calculate current angle of up vector
- assert(m_style_manager.is_active_font());
- if (m_style_manager.is_active_font())
- m_style_manager.get_font_prop().angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
-
// calculate scale for height and depth inside of scaled object instance
calculate_scale();
}
@@ -1858,14 +1909,10 @@ void GLGizmoEmboss::draw_style_rename_popup() {
const std::string &old_name = m_style_manager.get_stored_style()->name;
std::string text_in_popup = GUI::format(_L("Rename style(%1%) for embossing text: "), old_name);
ImGui::Text("%s", text_in_popup.c_str());
-
- bool is_unique = true;
- for (const auto &item : m_style_manager.get_styles()) {
- const EmbossStyle &style = item.style;
- if (&style == &m_style_manager.get_style())
- continue; // could be same as original name
- if (style.name == new_name) is_unique = false;
- }
+
+ bool is_unique = (new_name == old_name) || // could be same as before rename
+ m_style_manager.is_unique_style_name(new_name);
+
bool allow_change = false;
if (new_name.empty()) {
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_DARK, _u8L("Name can't be empty."));
@@ -1946,11 +1993,7 @@ void GLGizmoEmboss::draw_style_save_as_popup() {
// use name inside of volume configuration as temporary new name
std::string &new_name = m_volume->text_configuration->style.name;
-
- bool is_unique = true;
- for (const auto &item : m_style_manager.get_styles())
- if (item.style.name == new_name) is_unique = false;
-
+ bool is_unique = m_style_manager.is_unique_style_name(new_name);
bool allow_change = false;
if (new_name.empty()) {
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_DARK, _u8L("Name can't be empty."));
@@ -1988,7 +2031,7 @@ void GLGizmoEmboss::draw_style_add_button()
bool only_add_style = !m_style_manager.exist_stored_style();
bool can_add = true;
if (only_add_style &&
- m_volume->text_configuration->style.type != WxFontUtils::get_actual_type())
+ m_volume->text_configuration->style.type != WxFontUtils::get_current_type())
can_add = false;
std::string title = _u8L("Save as new style");
@@ -2080,46 +2123,46 @@ void GLGizmoEmboss::draw_delete_style_button() {
}
}
-// FIX IT: it should not change volume position before successfull change
-void GLGizmoEmboss::fix_transformation(const FontProp &from,
- const FontProp &to)
-{
+namespace {
+// FIX IT: It should not change volume position before successfull change volume by process
+void fix_transformation(const StyleManager::Style &from, const StyleManager::Style &to, GLCanvas3D &canvas) {
// fix Z rotation when exists difference in styles
const std::optional &f_angle_opt = from.angle;
const std::optional &t_angle_opt = to.angle;
if (!is_approx(f_angle_opt, t_angle_opt)) {
// fix rotation
- float f_angle = f_angle_opt.has_value() ? *f_angle_opt : .0f;
- float t_angle = t_angle_opt.has_value() ? *t_angle_opt : .0f;
- do_local_z_rotate(m_parent, t_angle - f_angle);
+ float f_angle = f_angle_opt.value_or(.0f);
+ float t_angle = t_angle_opt.value_or(.0f);
+ do_local_z_rotate(canvas, t_angle - f_angle);
}
// fix distance (Z move) when exists difference in styles
const std::optional &f_move_opt = from.distance;
const std::optional &t_move_opt = to.distance;
if (!is_approx(f_move_opt, t_move_opt)) {
- float f_move = f_move_opt.has_value() ? *f_move_opt : .0f;
- float t_move = t_move_opt.has_value() ? *t_move_opt : .0f;
- do_local_z_move(m_parent, t_move - f_move);
+ float f_move = f_move_opt.value_or(.0f);
+ float t_move = t_move_opt.value_or(.0f);
+ do_local_z_move(canvas, t_move - f_move);
}
}
+} // namesapce
void GLGizmoEmboss::draw_style_list() {
if (!m_style_manager.is_active_font()) return;
- const EmbossStyle *stored_style = nullptr;
+ const StyleManager::Style *stored_style = nullptr;
bool is_stored = m_style_manager.exist_stored_style();
if (is_stored)
stored_style = m_style_manager.get_stored_style();
- const EmbossStyle &actual_style = m_style_manager.get_style();
- bool is_changed = (stored_style)? !(*stored_style == actual_style) : true;
+ const StyleManager::Style ¤t_style = m_style_manager.get_style();
+ bool is_changed = (stored_style)? !(*stored_style == current_style) : true;
bool is_modified = is_stored && is_changed;
const float &max_style_name_width = m_gui_cfg->max_style_name_width;
std::string &trunc_name = m_style_manager.get_truncated_name();
if (trunc_name.empty()) {
// generate trunc name
- std::string current_name = actual_style.name;
+ std::string current_name = current_style.name;
ImGuiWrapper::escape_double_hash(current_name);
trunc_name = ImGuiWrapper::trunc(current_name, max_style_name_width);
}
@@ -2140,19 +2183,19 @@ 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();
- for (const auto &item : styles) {
- size_t index = &item - &styles.front();
- const EmbossStyle &style = item.style;
+ const StyleManager::Styles &styles = m_style_manager.get_styles();
+ for (const StyleManager::Style &style : styles) {
+ size_t index = &style - &styles.front();
const std::string &actual_style_name = style.name;
ImGui::PushID(actual_style_name.c_str());
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;
+ float select_height = static_cast(m_gui_cfg->max_style_image_size.y());
+ ImVec2 select_size(0.f, select_height); // 0,0 --> calculate in draw
+ const std::optional &img = style.image;
// allow click delete button
ImGuiSelectableFlags_ flags = ImGuiSelectableFlags_AllowItemOverlap;
- if (ImGui::Selectable(item.truncated_name.c_str(), is_selected, flags, select_size)) {
+ if (ImGui::Selectable(style.truncated_name.c_str(), is_selected, flags, select_size)) {
selected_style_index = index;
} else if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", actual_style_name.c_str());
@@ -2184,10 +2227,10 @@ void GLGizmoEmboss::draw_style_list() {
// do not keep in memory style images when no combo box open
m_style_manager.free_style_images();
if (ImGui::IsItemHovered()) {
- std::string style_name = add_text_modify(actual_style.name);
+ std::string style_name = add_text_modify(current_style.name);
std::string tooltip = is_modified?
- GUI::format(_L("Modified style \"%1%\""), actual_style.name):
- GUI::format(_L("Current style is \"%1%\""), actual_style.name);
+ GUI::format(_L("Modified style \"%1%\""), current_style.name):
+ GUI::format(_L("Current style is \"%1%\""), current_style.name);
ImGui::SetTooltip(" %s", tooltip.c_str());
}
}
@@ -2195,7 +2238,7 @@ void GLGizmoEmboss::draw_style_list() {
// Check whether user wants lose actual style modification
if (selected_style_index.has_value() && is_modified) {
wxString title = _L("Style modification will be lost.");
- const EmbossStyle &style = m_style_manager.get_styles()[*selected_style_index].style;
+ const EmbossStyle &style = m_style_manager.get_styles()[*selected_style_index];
wxString message = GUI::format_wxstr(_L("Changing style to '%1%' will discard current style modification.\n\n Would you like to continue anyway?"), style.name);
MessageDialog not_loaded_style_message(nullptr, message, title, wxICON_WARNING | wxYES|wxNO);
if (not_loaded_style_message.ShowModal() != wxID_YES)
@@ -2204,12 +2247,12 @@ void GLGizmoEmboss::draw_style_list() {
// selected style from combo box
if (selected_style_index.has_value()) {
- const EmbossStyle &style = m_style_manager.get_styles()[*selected_style_index].style;
+ const StyleManager::Style &style = m_style_manager.get_styles()[*selected_style_index];
// create copy to be able do fix transformation only when successfully load style
- FontProp act_prop = actual_style.prop; // copy
- FontProp new_prop = style.prop; // copy
+ StyleManager::Style cur_s = current_style; // copy
+ StyleManager::Style new_s = style; // copy
if (m_style_manager.load_style(*selected_style_index)) {
- fix_transformation(act_prop, new_prop);
+ ::fix_transformation(cur_s, new_s, m_parent);
process();
} else {
wxString title = _L("Not valid style.");
@@ -2667,11 +2710,10 @@ void GLGizmoEmboss::draw_advanced()
return;
}
- FontProp &font_prop = m_style_manager.get_style().prop;
- const auto &cn = m_style_manager.get_font_prop().collection_number;
- unsigned int font_index = (cn.has_value()) ? *cn : 0;
- const auto &font_info = ff.font_file->infos[font_index];
-
+ StyleManager::Style ¤t_style = m_style_manager.get_style();
+ FontProp ¤t_prop = current_style.prop;
+
+ const FontFile::Info &font_info = ff.font_file->infos[current_prop.collection_number.value_or(0)];
#ifdef SHOW_FONT_FILE_PROPERTY
ImGui::SameLine();
int cache_size = ff.has_value()? (int)ff.cache->size() : 0;
@@ -2682,8 +2724,8 @@ void GLGizmoEmboss::draw_advanced()
", unitPerEm=" + std::to_string(font_info.unit_per_em) +
", cache(" + std::to_string(cache_size) + " glyphs)";
if (font_file->infos.size() > 1) {
- unsigned int collection = font_prop.collection_number.has_value() ?
- *font_prop.collection_number : 0;
+ unsigned int collection = current_prop.collection_number.has_value() ?
+ *current_prop.collection_number : 0;
ff_property += ", collect=" + std::to_string(collection+1) + "/" + std::to_string(font_file->infos.size());
}
m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, ff_property);
@@ -2692,26 +2734,22 @@ void GLGizmoEmboss::draw_advanced()
bool exist_change = false;
auto &tr = m_gui_cfg->translations;
- const EmbossStyle *stored_style = nullptr;
+ const StyleManager::Style *stored_style = nullptr;
if (m_style_manager.exist_stored_style())
stored_style = m_style_manager.get_stored_style();
- bool can_use_surface = (m_volume==nullptr)? false :
- (font_prop.use_surface)? true : // already used surface must have option to uncheck
- (m_volume->get_object()->volumes.size() > 1);
+ bool can_use_surface = (m_volume == nullptr)? false :
+ (m_volume->emboss_shape->projection.use_surface)? true : // already used surface must have option to uncheck
+ !m_volume->is_the_only_one_part();
m_imgui->disabled_begin(!can_use_surface);
const bool *def_use_surface = stored_style ?
- &stored_style->prop.use_surface : nullptr;
- if (rev_checkbox(tr.use_surface, font_prop.use_surface, def_use_surface,
+ &stored_style->projection.use_surface : nullptr;
+ bool &use_surface = current_style.projection.use_surface;
+ if (rev_checkbox(tr.use_surface, use_surface, def_use_surface,
_u8L("Revert using of model surface."))) {
- if (font_prop.use_surface) {
+ if (use_surface)
// when using surface distance is not used
- font_prop.distance.reset();
-
- // there should be minimal embossing depth
- if (font_prop.emboss < 0.1)
- font_prop.emboss = 1;
- }
+ current_style.distance.reset();
process();
}
m_imgui->disabled_end(); // !can_use_surface
@@ -2724,13 +2762,14 @@ void GLGizmoEmboss::draw_advanced()
&stored_style->prop.char_gap : nullptr;
int half_ascent = font_info.ascent / 2;
- int min_char_gap = -half_ascent, max_char_gap = half_ascent;
- if (rev_slider(tr.char_gap, font_prop.char_gap, def_char_gap, _u8L("Revert gap between letters"),
+ int min_char_gap = -half_ascent;
+ int max_char_gap = half_ascent;
+ if (rev_slider(tr.char_gap, current_prop.char_gap, def_char_gap, _u8L("Revert gap between letters"),
min_char_gap, max_char_gap, units_fmt, _L("Distance between letters"))){
// Condition prevent recalculation when insertint out of limits value by imgui input
- if (!apply(font_prop.char_gap, priv::limits.char_gap) ||
- !m_volume->text_configuration->style.prop.char_gap.has_value() ||
- m_volume->text_configuration->style.prop.char_gap != font_prop.char_gap) {
+ const std::optional &volume_char_gap = m_volume->text_configuration->style.prop.char_gap;
+ if (!apply(current_prop.char_gap, priv::limits.char_gap) ||
+ !volume_char_gap.has_value() || volume_char_gap != current_prop.char_gap) {
// char gap is stored inside of imgui font atlas
m_style_manager.clear_imgui_font();
exist_change = true;
@@ -2740,13 +2779,14 @@ void GLGizmoEmboss::draw_advanced()
// input gap between lines
auto def_line_gap = stored_style ?
&stored_style->prop.line_gap : nullptr;
- int min_line_gap = -half_ascent, max_line_gap = half_ascent;
- if (rev_slider(tr.line_gap, font_prop.line_gap, def_line_gap, _u8L("Revert gap between lines"),
+ int min_line_gap = -half_ascent;
+ int max_line_gap = half_ascent;
+ if (rev_slider(tr.line_gap, current_prop.line_gap, def_line_gap, _u8L("Revert gap between lines"),
min_line_gap, max_line_gap, units_fmt, _L("Distance between lines"))){
// Condition prevent recalculation when insertint out of limits value by imgui input
- if (!apply(font_prop.line_gap, priv::limits.line_gap) ||
- !m_volume->text_configuration->style.prop.line_gap.has_value() ||
- m_volume->text_configuration->style.prop.line_gap != font_prop.line_gap) {
+ const std::optional &volume_line_gap = m_volume->text_configuration->style.prop.line_gap;
+ if (!apply(current_prop.line_gap, priv::limits.line_gap) ||
+ !volume_line_gap.has_value() || volume_line_gap != current_prop.line_gap) {
// line gap is planed to be stored inside of imgui font atlas
m_style_manager.clear_imgui_font();
exist_change = true;
@@ -2756,37 +2796,34 @@ void GLGizmoEmboss::draw_advanced()
// input boldness
auto def_boldness = stored_style ?
&stored_style->prop.boldness : nullptr;
- if (rev_slider(tr.boldness, font_prop.boldness, def_boldness, _u8L("Undo boldness"),
+ if (rev_slider(tr.boldness, current_prop.boldness, def_boldness, _u8L("Undo boldness"),
priv::limits.boldness.gui.min, priv::limits.boldness.gui.max, units_fmt, _L("Tiny / Wide glyphs"))){
- if (!apply(font_prop.boldness, priv::limits.boldness.values) ||
- !m_volume->text_configuration->style.prop.boldness.has_value() ||
- m_volume->text_configuration->style.prop.boldness != font_prop.boldness)
+ const std::optional &volume_boldness = m_volume->text_configuration->style.prop.boldness;
+ if (!apply(current_prop.boldness, priv::limits.boldness.values) ||
+ !volume_boldness.has_value() || volume_boldness != current_prop.boldness)
exist_change = true;
}
// input italic
auto def_skew = stored_style ?
&stored_style->prop.skew : nullptr;
- if (rev_slider(tr.skew_ration, font_prop.skew, def_skew, _u8L("Undo letter's skew"),
+ if (rev_slider(tr.skew_ration, current_prop.skew, def_skew, _u8L("Undo letter's skew"),
priv::limits.skew.gui.min, priv::limits.skew.gui.max, "%.2f", _L("Italic strength ratio"))){
- if (!apply(font_prop.skew, priv::limits.skew.values) ||
- !m_volume->text_configuration->style.prop.skew.has_value() ||
- m_volume->text_configuration->style.prop.skew != font_prop.skew)
+ const std::optional &volume_skew = m_volume->text_configuration->style.prop.skew;
+ if (!apply(current_prop.skew, priv::limits.skew.values) ||
+ !volume_skew.has_value() ||volume_skew != current_prop.skew)
exist_change = true;
}
// input surface distance
- bool allowe_surface_distance =
- !m_volume->text_configuration->style.prop.use_surface &&
- !m_volume->is_the_only_one_part();
- std::optional &distance = font_prop.distance;
- float prev_distance = distance.has_value() ? *distance : .0f,
- min_distance = -2 * font_prop.emboss,
- max_distance = 2 * font_prop.emboss;
+ bool allowe_surface_distance = !use_surface && !m_volume->is_the_only_one_part();
+ std::optional &distance = current_style.distance;
+ float prev_distance = distance.value_or(.0f);
+ float min_distance = static_cast(-2 * current_style.projection.depth);
+ float max_distance = static_cast(2 * current_style.projection.depth);
auto def_distance = stored_style ?
- &stored_style->prop.distance : nullptr;
- m_imgui->disabled_begin(!allowe_surface_distance);
-
+ &stored_style->distance : nullptr;
+ m_imgui->disabled_begin(!allowe_surface_distance);
bool use_inch = wxGetApp().app_config->get_bool("use_inches");
const std::string undo_move_tooltip = _u8L("Undo translation");
const wxString move_tooltip = _L("Distance of the center of text from model surface");
@@ -2803,9 +2840,9 @@ void GLGizmoEmboss::draw_advanced()
max_distance *= ObjectManipulation::mm_to_in;
if (rev_slider(tr.from_surface, distance_inch, def_distance, undo_move_tooltip, min_distance, max_distance, "%.3f in", move_tooltip)) {
if (distance_inch.has_value()) {
- font_prop.distance = *distance_inch * ObjectManipulation::in_to_mm;
+ distance = *distance_inch * ObjectManipulation::in_to_mm;
} else {
- font_prop.distance.reset();
+ distance.reset();
}
is_moved = true;
}
@@ -2814,23 +2851,19 @@ void GLGizmoEmboss::draw_advanced()
min_distance, max_distance, "%.2f mm", move_tooltip)) is_moved = true;
}
- if (is_moved){
- m_volume->text_configuration->style.prop.distance = font_prop.distance;
- float act_distance = font_prop.distance.has_value() ? *font_prop.distance : .0f;
- do_local_z_move(m_parent, act_distance - prev_distance);
- }
- m_imgui->disabled_end();
+ if (is_moved)
+ do_local_z_move(m_parent, distance.value_or(.0f) - prev_distance);
+ m_imgui->disabled_end(); // allowe_surface_distance
// slider for Clock-wise angle in degress
// stored angle is optional CCW and in radians
// Convert stored value to degress
// minus create clock-wise roation from CCW
- const std::optional &angle_opt = m_style_manager.get_font_prop().angle;
- float angle = angle_opt.has_value() ? *angle_opt: 0.f;
+ float angle = current_style.angle.value_or(0.f);
float angle_deg = static_cast(-angle * 180 / M_PI);
float def_angle_deg_val =
- (!stored_style || !stored_style->prop.angle.has_value()) ?
- 0.f : (*stored_style->prop.angle * -180 / M_PI);
+ (!stored_style || !stored_style->angle.has_value()) ?
+ 0.f : (*stored_style->angle * -180 / M_PI);
float* def_angle_deg = stored_style ?
&def_angle_deg_val : nullptr;
if (rev_slider(tr.rotation, angle_deg, def_angle_deg, _u8L("Undo rotation"),
@@ -2848,21 +2881,16 @@ void GLGizmoEmboss::draw_advanced()
assert(gl_volume != nullptr);
assert(m_style_manager.is_active_font());
if (m_style_manager.is_active_font() && gl_volume != nullptr)
- m_style_manager.get_font_prop().angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
+ m_style_manager.get_style().angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
// recalculate for surface cut
- if (font_prop.use_surface)
+ if (use_surface)
process();
}
ImGui::Text("%s", tr.keep_up.c_str());
ImGui::SameLine(m_gui_cfg->advanced_input_offset);
- if (ImGui::Checkbox("##keep_up", &m_keep_up)) {
- if (m_keep_up) {
- // copy angle to volume
- m_volume->text_configuration->style.prop.angle = font_prop.angle;
- }
- }
+ ImGui::Checkbox("##keep_up", &m_keep_up);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", _u8L("Keep text orientation during surface dragging.\nNot stable between horizontal and vertical alignment.").c_str());
@@ -2871,15 +2899,15 @@ void GLGizmoEmboss::draw_advanced()
ImGui::Text("%s", tr.collection.c_str());
ImGui::SameLine(m_gui_cfg->advanced_input_offset);
ImGui::SetNextItemWidth(m_gui_cfg->input_width);
- unsigned int selected = font_prop.collection_number.has_value() ?
- *font_prop.collection_number : 0;
+ unsigned int selected = current_prop.collection_number.has_value() ?
+ *current_prop.collection_number : 0;
if (ImGui::BeginCombo("## Font collection", std::to_string(selected).c_str())) {
for (unsigned int i = 0; i < ff.font_file->infos.size(); ++i) {
ImGui::PushID(1 << (10 + i));
bool is_selected = (i == selected);
if (ImGui::Selectable(std::to_string(i).c_str(), is_selected)) {
- if (i == 0) font_prop.collection_number.reset();
- else font_prop.collection_number = i;
+ if (i == 0) current_prop.collection_number.reset();
+ else current_prop.collection_number = i;
exist_change = true;
}
ImGui::PopID();
@@ -2897,25 +2925,24 @@ void GLGizmoEmboss::draw_advanced()
if (ImGui::Button(_u8L("Set text to face camera").c_str())) {
assert(get_selected_volume(m_parent.get_selection()) == m_volume);
- const Camera &cam = wxGetApp().plater()->get_camera();
- bool use_surface = m_style_manager.get_style().prop.use_surface;
+ const Camera &cam = wxGetApp().plater()->get_camera();
if (face_selected_volume_to_camera(cam, m_parent) && use_surface)
process();
} else if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", _u8L("Use camera direction for text orientation").c_str());
}
#ifdef ALLOW_DEBUG_MODE
- ImGui::Text("family = %s", (font_prop.family.has_value() ?
- font_prop.family->c_str() :
+ ImGui::Text("family = %s", (current_prop.family.has_value() ?
+ current_prop.family->c_str() :
" --- "));
- ImGui::Text("face name = %s", (font_prop.face_name.has_value() ?
- font_prop.face_name->c_str() :
+ ImGui::Text("face name = %s", (current_prop.face_name.has_value() ?
+ current_prop.face_name->c_str() :
" --- "));
ImGui::Text("style = %s",
- (font_prop.style.has_value() ? font_prop.style->c_str() :
+ (current_prop.style.has_value() ? current_prop.style->c_str() :
" --- "));
- ImGui::Text("weight = %s", (font_prop.weight.has_value() ?
- font_prop.weight->c_str() :
+ ImGui::Text("weight = %s", (current_prop.weight.has_value() ?
+ current_prop.weight->c_str() :
" --- "));
std::string descriptor = style.path;
@@ -2961,7 +2988,7 @@ bool GLGizmoEmboss::choose_font_by_wxdialog()
data.RestrictSelection(wxFONTRESTRICT_SCALABLE);
// set previous selected font
EmbossStyle &selected_style = m_style_manager.get_style();
- if (selected_style.type == WxFontUtils::get_actual_type()) {
+ if (selected_style.type == WxFontUtils::get_current_type()) {
std::optional selected_font = WxFontUtils::load_wxFont(
selected_style.path);
if (selected_font.has_value()) data.SetInitialFont(*selected_font);
@@ -3179,9 +3206,9 @@ priv::TextDataBase::TextDataBase(DataBase &&parent, const FontFileWithCache &fon
// partialy fill shape from text configuration
const FontProp &fp = this->text_configuration.style.prop;
- shape.depth = fp.emboss;
- shape.use_surface = fp.use_surface;
- shape.distance = fp.distance;
+ EmbossProjection &p = shape.projection;
+ p.depth = fp.emboss;
+ p.use_surface = fp.use_surface;
const FontFile &ff = *this->font_file.font_file;
shape.scale = get_text_shape_scale(fp, ff);
@@ -3219,8 +3246,8 @@ void priv::TextDataBase::write(ModelVolume &volume) const
volume.text_configuration->style.prop.angle.reset();
// only temporary solution
- volume.text_configuration->style.prop.use_surface = shape.use_surface;
- volume.text_configuration->style.prop.distance = shape.distance;
+ volume.text_configuration->style.prop.use_surface = shape.projection.use_surface; // copy
+ volume.text_configuration->style.prop.emboss = static_cast(shape.projection.depth); // copy
DataBase::write(volume);
}
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
index 3422039fa2..8f48628fb6 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
@@ -32,7 +32,7 @@ namespace Slic3r::GUI {
class GLGizmoEmboss : public GLGizmoBase
{
public:
- GLGizmoEmboss(GLCanvas3D& parent);
+ explicit GLGizmoEmboss(GLCanvas3D& parent);
///
/// Create new embossed text volume by type on position of mouse
@@ -51,8 +51,8 @@ protected:
bool on_init() override;
std::string on_get_name() const override;
void on_render() override;
- virtual void on_register_raycasters_for_picking() override;
- virtual void on_unregister_raycasters_for_picking() override;
+ void on_register_raycasters_for_picking() override;
+ void on_unregister_raycasters_for_picking() override;
void on_render_input_window(float x, float y, float bottom_limit) override;
bool on_is_activable() const override { return true; }
bool on_is_selectable() const override { return false; }
@@ -90,7 +90,6 @@ private:
void draw_window();
void draw_text_input();
void draw_model_type();
- void fix_transformation(const FontProp &from, const FontProp &to);
void draw_style_list();
void draw_delete_style_button();
void draw_style_rename_popup();
@@ -308,8 +307,8 @@ private:
// Keep data about dragging only during drag&drop
std::optional m_surface_drag;
- // TODO: it should be accessible by other gizmo too.
- // May be move to plater?
+ // Keep old scene triangle data in AABB trees,
+ // all the time it need actualize before use.
RaycastManager m_raycast_manager;
// For text on scaled objects
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp
index 8c56912b5f..54ff00cbdf 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp
@@ -398,7 +398,7 @@ void GLGizmoSVG::on_stop_dragging()
// recalculate for surface cut
if (m_volume != nullptr &&
m_volume->emboss_shape.has_value() &&
- m_volume->emboss_shape->use_surface)
+ m_volume->emboss_shape->projection.use_surface)
process();
}
void GLGizmoSVG::on_dragging(const UpdateData &data) { m_rotate_gizmo.dragging(data); }
@@ -710,9 +710,8 @@ ExPolygons priv::default_shape() {
EmbossShape priv::select_shape() {
EmbossShape shape;
- shape.depth = 10.;
- shape.distance = 0;
- shape.use_surface = false;
+ shape.projection.depth = 10.;
+ shape.projection.use_surface = false;
shape.svg_file_path = choose_svg_file();
if (shape.svg_file_path.empty())
diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp
index c1671db2d7..15f9296374 100644
--- a/src/slic3r/GUI/Jobs/EmbossJob.cpp
+++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp
@@ -825,10 +825,10 @@ void update_volume(TriangleMesh &&mesh, const DataUpdate &data, const Transform3
volume->set_transformation(*tr);
} else {
// apply fix matrix made by store to .3mf
- const auto &tc = volume->text_configuration;
- assert(tc.has_value());
- if (tc.has_value() && tc->fix_3mf_tr.has_value())
- volume->set_transformation(volume->get_matrix() * tc->fix_3mf_tr->inverse());
+ const std::optional &emboss_shape = volume->emboss_shape;
+ assert(emboss_shape.has_value());
+ if (emboss_shape.has_value() && emboss_shape->fix_3mf_tr.has_value())
+ volume->set_transformation(volume->get_matrix() * emboss_shape->fix_3mf_tr->inverse());
}
UpdateJob::update_volume(volume, std::move(mesh), *data.base);
diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp
index 173eec399e..7a3a39b7b7 100644
--- a/src/slic3r/GUI/Jobs/EmbossJob.hpp
+++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp
@@ -37,8 +37,8 @@ class DataBase
public:
DataBase(const std::string& volume_name, std::shared_ptr> cancel) : volume_name(volume_name), cancel(std::move(cancel)) {}
DataBase(const std::string& volume_name, std::shared_ptr> cancel, EmbossShape&& shape)
- : volume_name(volume_name), cancel(std::move(cancel)), shape(std::move(shape))
- {}
+ : volume_name(volume_name), cancel(std::move(cancel)), shape(std::move(shape)){}
+ DataBase(DataBase &&) = default;
virtual ~DataBase() = default;
///
diff --git a/src/slic3r/GUI/SurfaceDrag.cpp b/src/slic3r/GUI/SurfaceDrag.cpp
index b80e1fb894..a65acd452a 100644
--- a/src/slic3r/GUI/SurfaceDrag.cpp
+++ b/src/slic3r/GUI/SurfaceDrag.cpp
@@ -93,25 +93,28 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
// detect start text dragging
if (mouse_event.LeftDown()) {
// selected volume
- GLVolume *gl_volume = get_selected_gl_volume(canvas);
- if (gl_volume == nullptr)
+ GLVolume *gl_volume_ptr = get_selected_gl_volume(canvas);
+ if (gl_volume_ptr == nullptr)
return false;
+ const GLVolume &gl_volume = *gl_volume_ptr;
// is selected volume closest hovered?
- const GLVolumePtrs &gl_volumes = canvas.get_volumes().volumes;
- int hovered_idx = canvas.get_first_hover_volume_idx();
- if (hovered_idx < 0 ||
- hovered_idx >= gl_volumes.size() ||
- gl_volumes[hovered_idx] != gl_volume)
+ const GLVolumePtrs &gl_volumes = canvas.get_volumes().volumes;
+ if (int hovered_idx = canvas.get_first_hover_volume_idx();
+ hovered_idx < 0)
+ return false;
+ else if (auto hovered_idx_ = static_cast(hovered_idx);
+ hovered_idx_ >= gl_volumes.size() ||
+ gl_volumes[hovered_idx_] != gl_volume_ptr)
return false;
- const ModelObject *object = get_model_object(*gl_volume, canvas.get_model()->objects);
+ const ModelObject *object = get_model_object(gl_volume, canvas.get_model()->objects);
assert(object != nullptr);
if (object == nullptr)
return false;
- const ModelInstance *instance = get_model_instance(*gl_volume, *object);
- const ModelVolume *volume = get_model_volume(*gl_volume, *object);
+ const ModelInstance *instance = get_model_instance(gl_volume, *object);
+ const ModelVolume *volume = get_model_volume(gl_volume, *object);
assert(instance != nullptr && volume != nullptr);
if (object == nullptr || instance == nullptr || volume == nullptr)
return false;
@@ -124,7 +127,7 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
std::vector allowed_volumes_id;
if (volumes.size() > 1) {
allowed_volumes_id.reserve(volumes.size() - 1);
- for (auto &v : volumes) {
+ for (const ModelVolume *v : volumes) {
// skip actual selected object
if (v->id() == volume->id())
continue;
@@ -146,7 +149,7 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
Vec2d mouse_pos = mouse_coord.cast();
Vec2d mouse_offset = calc_screen_offset_to_volume_center(mouse_pos, *volume, camera);
- Transform3d volume_tr = gl_volume->get_volume_transformation().get_matrix();
+ Transform3d volume_tr = gl_volume.get_volume_transformation().get_matrix();
if (volume->text_configuration.has_value()) {
const TextConfiguration &tc = *volume->text_configuration;
@@ -161,7 +164,7 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
std::optional start_angle;
if (up_limit.has_value())
start_angle = Emboss::calc_up(world_tr, *up_limit);
- surface_drag = SurfaceDrag{mouse_offset, world_tr, instance_tr_inv, gl_volume, condition, start_angle};
+ surface_drag = SurfaceDrag{mouse_offset, world_tr, instance_tr_inv, gl_volume_ptr, condition, start_angle};
// disable moving with object by mouse
canvas.enable_moving(false);
diff --git a/src/slic3r/Utils/EmbossStyleManager.cpp b/src/slic3r/Utils/EmbossStyleManager.cpp
index 32e003c6d7..af9013301b 100644
--- a/src/slic3r/Utils/EmbossStyleManager.cpp
+++ b/src/slic3r/Utils/EmbossStyleManager.cpp
@@ -14,13 +14,9 @@ using namespace Slic3r;
using namespace Slic3r::Emboss;
using namespace Slic3r::GUI::Emboss;
-StyleManager::StyleManager(const ImWchar *language_glyph_range, std::function create_default_styles)
- : m_imgui_init_glyph_range(language_glyph_range)
- , m_create_default_styles(create_default_styles)
- , m_exist_style_images(false)
- , m_temp_style_images(nullptr)
- , m_app_config(nullptr)
- , m_last_style_index(std::numeric_limits::max())
+StyleManager::StyleManager(const ImWchar *language_glyph_range, const std::function& create_default_styles)
+ : m_create_default_styles(create_default_styles)
+ , m_imgui_init_glyph_range(language_glyph_range)
{}
StyleManager::~StyleManager() {
@@ -32,24 +28,26 @@ StyleManager::~StyleManager() {
/// For store/load emboss style to/from AppConfig
///
namespace {
-void store_style_index(AppConfig &cfg, unsigned index);
+void store_style_index(AppConfig &cfg, size_t index);
::std::optional load_style_index(const AppConfig &cfg);
-EmbossStyles load_styles(const AppConfig &cfg);
-void store_styles(AppConfig &cfg, const EmbossStyles &styles);
+StyleManager::Styles load_styles(const AppConfig &cfg);
+void store_styles(AppConfig &cfg, const StyleManager::Styles &styles);
+void make_unique_name(const StyleManager::Styles &styles, std::string &name);
} // namespace
void StyleManager::init(AppConfig *app_config)
{
m_app_config = app_config;
- EmbossStyles styles = (app_config != nullptr) ?
- ::load_styles(*app_config) :
- EmbossStyles{};
- if (styles.empty())
- styles = m_create_default_styles();
- for (EmbossStyle &style : styles) {
- make_unique_name(style.name);
- m_style_items.push_back({style});
+ m_styles = ::load_styles(*app_config);
+
+ if (m_styles.empty()) {
+ // No styles loaded from ini file so use default
+ EmbossStyles styles = m_create_default_styles();
+ for (EmbossStyle &style : styles) {
+ ::make_unique_name(m_styles, style.name);
+ m_styles.push_back({style});
+ }
}
std::optional active_index_opt = (app_config != nullptr) ?
@@ -58,14 +56,14 @@ void StyleManager::init(AppConfig *app_config)
size_t active_index = 0;
if (active_index_opt.has_value()) active_index = *active_index_opt;
- if (active_index >= m_style_items.size()) active_index = 0;
+ if (active_index >= m_styles.size()) active_index = 0;
// find valid font item
if (load_style(active_index))
return; // style is loaded
// Try to fix that style can't be loaded
- m_style_items.erase(m_style_items.begin() + active_index);
+ m_styles.erase(m_styles.begin() + active_index);
load_valid_style();
}
@@ -77,14 +75,14 @@ bool StyleManager::store_styles_to_app_config(bool use_modification, bool store_
if (use_modification) {
if (exist_stored_style()) {
// update stored item
- m_style_items[m_style_cache.style_index].style = m_style_cache.style;
+ m_styles[m_style_cache.style_index] = m_style_cache.style;
} else {
// add new into stored list
EmbossStyle &style = m_style_cache.style;
- make_unique_name(style.name);
+ ::make_unique_name(m_styles, style.name);
m_style_cache.truncated_name.clear();
- m_style_cache.style_index = m_style_items.size();
- m_style_items.push_back({style});
+ m_style_cache.style_index = m_styles.size();
+ m_styles.push_back({style});
}
m_style_cache.stored_wx_font = m_style_cache.wx_font;
}
@@ -97,27 +95,24 @@ bool StyleManager::store_styles_to_app_config(bool use_modification, bool store_
store_style_index(*m_app_config, style_index);
}
- EmbossStyles styles;
- styles.reserve(m_style_items.size());
- for (const Item &item : m_style_items) styles.push_back(item.style);
- store_styles(*m_app_config, styles);
+ store_styles(*m_app_config, m_styles);
return true;
}
void StyleManager::add_style(const std::string &name) {
EmbossStyle& style = m_style_cache.style;
style.name = name;
- make_unique_name(style.name);
- m_style_cache.style_index = m_style_items.size();
+ ::make_unique_name(m_styles, style.name);
+ m_style_cache.style_index = m_styles.size();
m_style_cache.stored_wx_font = m_style_cache.wx_font;
m_style_cache.truncated_name.clear();
- m_style_items.push_back({style});
+ m_styles.push_back({style});
}
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]);
+ if (i1 >= m_styles.size() ||
+ i2 >= m_styles.size()) return;
+ std::swap(m_styles[i1], m_styles[i2]);
// fix selected index
if (!exist_stored_style()) return;
if (m_style_cache.style_index == i1) {
@@ -141,7 +136,7 @@ void StyleManager::discard_style_changes() {
}
void StyleManager::erase(size_t index) {
- if (index >= m_style_items.size()) return;
+ if (index >= m_styles.size()) return;
// fix selected index
if (exist_stored_style()) {
@@ -150,15 +145,15 @@ void StyleManager::erase(size_t index) {
else if (index == i) i = std::numeric_limits::max();
}
- m_style_items.erase(m_style_items.begin() + index);
+ m_styles.erase(m_styles.begin() + index);
}
void StyleManager::rename(const std::string& name) {
m_style_cache.style.name = name;
m_style_cache.truncated_name.clear();
if (exist_stored_style()) {
- Item &it = m_style_items[m_style_cache.style_index];
- it.style.name = name;
+ Style &it = m_styles[m_style_cache.style_index];
+ it.name = name;
it.truncated_name.clear();
}
}
@@ -166,28 +161,28 @@ void StyleManager::rename(const std::string& name) {
void StyleManager::load_valid_style()
{
// iterate over all known styles
- while (!m_style_items.empty()) {
+ while (!m_styles.empty()) {
if (load_style(0))
return;
// can't load so erase it from list
- m_style_items.erase(m_style_items.begin());
+ m_styles.erase(m_styles.begin());
}
// no one style is loadable
// set up default font list
EmbossStyles def_style = m_create_default_styles();
for (EmbossStyle &style : def_style) {
- make_unique_name(style.name);
- m_style_items.push_back({std::move(style)});
+ ::make_unique_name(m_styles, style.name);
+ m_styles.push_back({std::move(style)});
}
// iterate over default styles
// There have to be option to use build in font
- while (!m_style_items.empty()) {
+ while (!m_styles.empty()) {
if (load_style(0))
return;
// can't load so erase it from list
- m_style_items.erase(m_style_items.begin());
+ m_styles.erase(m_styles.begin());
}
// This OS doesn't have TTF as default font,
@@ -197,15 +192,15 @@ void StyleManager::load_valid_style()
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;
+ if (style_index >= m_styles.size()) return false;
+ if (!load_style(m_styles[style_index])) return false;
m_style_cache.style_index = style_index;
m_style_cache.stored_wx_font = m_style_cache.wx_font; // copy
m_last_style_index = style_index;
return true;
}
-bool StyleManager::load_style(const EmbossStyle &style) {
+bool StyleManager::load_style(const Style &style) {
if (style.type == EmbossStyle::Type::file_path) {
std::unique_ptr font_ptr =
create_font_file(style.path.c_str());
@@ -218,13 +213,13 @@ bool StyleManager::load_style(const EmbossStyle &style) {
m_style_cache.stored_wx_font = {};
return true;
}
- if (style.type != WxFontUtils::get_actual_type()) return false;
+ if (style.type != WxFontUtils::get_current_type()) return false;
std::optional wx_font_opt = WxFontUtils::load_wxFont(style.path);
if (!wx_font_opt.has_value()) return false;
return load_style(style, *wx_font_opt);
}
-bool StyleManager::load_style(const EmbossStyle &style, const wxFont &font)
+bool StyleManager::load_style(const Style &style, const wxFont &font)
{
m_style_cache.style = style; // copy
@@ -275,12 +270,19 @@ bool StyleManager::is_font_changed() const
return is_bold != is_stored_bold;
}
+bool StyleManager::is_unique_style_name(const std::string &name) const {
+ for (const StyleManager::Style &style : m_styles)
+ if (style.name == name)
+ return false;
+ return true;
+}
+
bool StyleManager::is_active_font() { return m_style_cache.font_file.has_value(); }
-const EmbossStyle* StyleManager::get_stored_style() const
+const StyleManager::Style *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;
+ if (m_style_cache.style_index >= m_styles.size()) return nullptr;
+ return &m_styles[m_style_cache.style_index];
}
void StyleManager::clear_glyphs_cache()
@@ -308,44 +310,11 @@ ImFont *StyleManager::get_imgui_font()
return font;
}
-const std::vector &StyleManager::get_styles() const{ return m_style_items; }
-
-void StyleManager::make_unique_name(std::string &name)
-{
- auto is_unique = [&](const std::string &name) -> bool {
- for (const Item &it : m_style_items)
- if (it.style.name == name) return false;
- return true;
- };
-
- // Style name can't be empty so default name is set
- if (name.empty()) name = "Text style";
-
- // When name is already unique, nothing need to be changed
- if (is_unique(name)) return;
-
- // when there is previous version of style name only find number
- const char *prefix = " (";
- const char suffix = ')';
- auto pos = name.find_last_of(prefix);
- if (name.c_str()[name.size() - 1] == suffix &&
- pos != std::string::npos) {
- // short name by ord number
- name = name.substr(0, pos);
- }
-
- int order = 1; // start with value 2 to represents same font name
- std::string new_name;
- do {
- new_name = name + prefix + std::to_string(++order) + suffix;
- } while (!is_unique(new_name));
- name = new_name;
-}
-
+const StyleManager::Styles &StyleManager::get_styles() const{ return m_styles; }
void StyleManager::init_trunc_names(float max_width) {
- for (auto &s : m_style_items)
+ for (auto &s : m_styles)
if (s.truncated_name.empty()) {
- std::string name = s.style.name;
+ std::string name = s.name;
ImGuiWrapper::escape_double_hash(name);
s.truncated_name = ImGuiWrapper::trunc(name, max_width);
}
@@ -378,9 +347,9 @@ void StyleManager::init_style_images(const Vec2i &max_size,
StyleImagesData::Item &style = m_temp_style_images->styles[index];
// find style in font list and copy to it
- for (auto &it : m_style_items) {
- if (it.style.name != style.text ||
- !(it.style.prop == style.prop))
+ for (auto &it : m_styles) {
+ if (it.name != style.text ||
+ !(it.prop == style.prop))
continue;
it.image = image;
break;
@@ -397,9 +366,8 @@ void StyleManager::init_style_images(const Vec2i &max_size,
// create job for init images
m_temp_style_images = std::make_shared();
StyleImagesData::Items styles;
- styles.reserve(m_style_items.size());
- for (const Item &item : m_style_items) {
- const EmbossStyle &style = item.style;
+ styles.reserve(m_styles.size());
+ for (const Style &style : m_styles) {
std::optional wx_font_opt = WxFontUtils::load_wxFont(style.path);
if (!wx_font_opt.has_value()) continue;
std::unique_ptr font_file =
@@ -426,7 +394,7 @@ void StyleManager::init_style_images(const Vec2i &max_size,
void StyleManager::free_style_images() {
if (!m_exist_style_images) return;
GLuint tex_id = 0;
- for (Item &it : m_style_items) {
+ for (Style &it : m_styles) {
if (tex_id == 0 && it.image.has_value())
tex_id = (GLuint)(intptr_t) it.image->texture_id;
it.image.reset();
@@ -546,7 +514,7 @@ bool StyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr
FontFileWithCache(std::move(font_file));
EmbossStyle &style = m_style_cache.style;
- style.type = WxFontUtils::get_actual_type();
+ style.type = WxFontUtils::get_current_type();
// update string path
style.path = WxFontUtils::store_wxFont(wx_font);
WxFontUtils::update_property(style.prop, wx_font);
@@ -664,51 +632,55 @@ bool read(const Section §ion, const std::string &key, std::optional &
return true;
}
-std::optional load_style(const Section &app_cfg_section)
+std::optional load_style(const Section &app_cfg_section)
{
auto path_it = app_cfg_section.find(APP_CONFIG_FONT_DESCRIPTOR);
if (path_it == app_cfg_section.end())
return {};
- const std::string &path = path_it->second;
-
- auto name_it = app_cfg_section.find(APP_CONFIG_FONT_NAME);
+
+ StyleManager::Style s;
+ EmbossProjection& ep = s.projection;
+ FontProp& fp = s.prop;
+
+ s.path = path_it->second;
+ s.type = WxFontUtils::get_current_type();
+ auto name_it = app_cfg_section.find(APP_CONFIG_FONT_NAME);
const std::string default_name = "font_name";
- const std::string &name = (name_it == app_cfg_section.end()) ? default_name : name_it->second;
+ s.name = (name_it == app_cfg_section.end()) ? default_name : name_it->second;
- FontProp fp;
+ float depth;
read(app_cfg_section, APP_CONFIG_FONT_LINE_HEIGHT, fp.size_in_mm);
- read(app_cfg_section, APP_CONFIG_FONT_DEPTH, fp.emboss);
- read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, fp.use_surface);
+ read(app_cfg_section, APP_CONFIG_FONT_DEPTH, depth);ep.depth = depth;
+ read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, ep.use_surface);
read(app_cfg_section, APP_CONFIG_FONT_BOLDNESS, fp.boldness);
read(app_cfg_section, APP_CONFIG_FONT_SKEW, fp.skew);
- read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, fp.distance);
- read(app_cfg_section, APP_CONFIG_FONT_ANGLE, fp.angle);
+ read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, s.distance);
+ read(app_cfg_section, APP_CONFIG_FONT_ANGLE, s.angle);
read(app_cfg_section, APP_CONFIG_FONT_COLLECTION, fp.collection_number);
read(app_cfg_section, APP_CONFIG_FONT_CHAR_GAP, fp.char_gap);
read(app_cfg_section, APP_CONFIG_FONT_LINE_GAP, fp.line_gap);
-
- EmbossStyle::Type type = WxFontUtils::get_actual_type();
- return EmbossStyle{name, path, type, fp};
+ return s;
}
-void store_style(AppConfig &cfg, const EmbossStyle &fi, unsigned index)
+void store_style(AppConfig &cfg, const StyleManager::Style &s, unsigned index)
{
+ const EmbossProjection &ep = s.projection;
Section data;
- data[APP_CONFIG_FONT_NAME] = fi.name;
- data[APP_CONFIG_FONT_DESCRIPTOR] = fi.path;
- const FontProp &fp = fi.prop;
+ data[APP_CONFIG_FONT_NAME] = s.name;
+ data[APP_CONFIG_FONT_DESCRIPTOR] = s.path;
+ const FontProp &fp = s.prop;
data[APP_CONFIG_FONT_LINE_HEIGHT] = std::to_string(fp.size_in_mm);
- data[APP_CONFIG_FONT_DEPTH] = std::to_string(fp.emboss);
- if (fp.use_surface)
+ data[APP_CONFIG_FONT_DEPTH] = std::to_string(ep.depth);
+ if (ep.use_surface)
data[APP_CONFIG_FONT_USE_SURFACE] = "true";
if (fp.boldness.has_value())
data[APP_CONFIG_FONT_BOLDNESS] = std::to_string(*fp.boldness);
if (fp.skew.has_value())
data[APP_CONFIG_FONT_SKEW] = std::to_string(*fp.skew);
- if (fp.distance.has_value())
- data[APP_CONFIG_FONT_DISTANCE] = std::to_string(*fp.distance);
- if (fp.angle.has_value())
- data[APP_CONFIG_FONT_ANGLE] = std::to_string(*fp.angle);
+ if (s.distance.has_value())
+ data[APP_CONFIG_FONT_DISTANCE] = std::to_string(*s.distance);
+ if (s.angle.has_value())
+ data[APP_CONFIG_FONT_ANGLE] = std::to_string(*s.angle);
if (fp.collection_number.has_value())
data[APP_CONFIG_FONT_COLLECTION] = std::to_string(*fp.collection_number);
if (fp.char_gap.has_value())
@@ -718,7 +690,7 @@ void store_style(AppConfig &cfg, const EmbossStyle &fi, unsigned index)
cfg.set_section(create_section_name(index), std::move(data));
}
-void store_style_index(AppConfig &cfg, unsigned index)
+void store_style_index(AppConfig &cfg, size_t index)
{
// store actual font index
// active font first index is +1 to correspond with section name
@@ -742,29 +714,34 @@ std::optional load_style_index(const AppConfig &cfg)
return active_font - 1;
}
-EmbossStyles load_styles(const AppConfig &cfg)
+::StyleManager::Styles load_styles(const AppConfig &cfg)
{
- EmbossStyles result;
+ StyleManager::Styles result;
// human readable index inside of config starts from 1 !!
unsigned index = 1;
std::string section_name = create_section_name(index);
while (cfg.has_section(section_name)) {
- std::optional style_opt = load_style(cfg.get_section(section_name));
- if (style_opt.has_value())
+ std::optional style_opt = load_style(cfg.get_section(section_name));
+ if (style_opt.has_value()) {
+ make_unique_name(result, style_opt->name);
result.emplace_back(*style_opt);
+ }
+
section_name = create_section_name(++index);
}
return result;
}
-void store_styles(AppConfig &cfg, const EmbossStyles &styles)
+void store_styles(AppConfig &cfg, const StyleManager::Styles &styles)
{
+ EmbossStyle::Type current_type = WxFontUtils::get_current_type();
// store styles
unsigned index = 1;
- for (const EmbossStyle &style : styles) {
+ for (const StyleManager::Style &style : styles) {
// skip file paths + fonts from other OS(loaded from .3mf)
- assert(style.type == WxFontUtils::get_actual_type());
- // if (style_opt.type != WxFontUtils::get_actual_type()) continue;
+ assert(style.type == current_type);
+ if (style.type != current_type)
+ continue;
store_style(cfg, style, index);
++index;
}
@@ -778,4 +755,36 @@ void store_styles(AppConfig &cfg, const EmbossStyles &styles)
}
}
+void make_unique_name(const StyleManager::Styles& styles, std::string &name)
+{
+ auto is_unique = [&styles](const std::string &name){
+ for (const StyleManager::Style &it : styles)
+ if (it.name == name) return false;
+ return true;
+ };
+
+ // Style name can't be empty so default name is set
+ if (name.empty()) name = "Text style";
+
+ // When name is already unique, nothing need to be changed
+ if (is_unique(name)) return;
+
+ // when there is previous version of style name only find number
+ const char *prefix = " (";
+ const char suffix = ')';
+ auto pos = name.find_last_of(prefix);
+ if (name.c_str()[name.size() - 1] == suffix &&
+ pos != std::string::npos) {
+ // short name by ord number
+ name = name.substr(0, pos);
+ }
+
+ int order = 1; // start with value 2 to represents same font name
+ std::string new_name;
+ do {
+ new_name = name + prefix + std::to_string(++order) + suffix;
+ } while (!is_unique(new_name));
+ name = new_name;
+}
+
} // namespace
diff --git a/src/slic3r/Utils/EmbossStyleManager.hpp b/src/slic3r/Utils/EmbossStyleManager.hpp
index 5bab7adce5..492d3f51c4 100644
--- a/src/slic3r/Utils/EmbossStyleManager.hpp
+++ b/src/slic3r/Utils/EmbossStyleManager.hpp
@@ -24,11 +24,10 @@ namespace Slic3r::GUI::Emboss {
class StyleManager
{
friend class CreateFontStyleImagesJob; // access to StyleImagesData
-
public:
/// Character to load for imgui when initialize imgui font
/// Function to create default styles
- StyleManager(const ImWchar *language_glyph_range, std::function create_default_styles);
+ StyleManager(const ImWchar *language_glyph_range, const std::function& create_default_styles);
///
/// Release imgui font and style images from GPU
@@ -59,11 +58,11 @@ public:
void add_style(const std::string& name);
///
- /// Change order of style item in m_style_items.
+ /// Change order of style item in m_styles.
/// Fix selected font index when (i1 || i2) == m_font_selected
///
- /// First index to m_style_items
- /// Second index to m_style_items
+ /// First index to m_styles
+ /// Second index to m_styles
void swap(size_t i1, size_t i2);
///
@@ -73,7 +72,7 @@ public:
void discard_style_changes();
///
- /// Remove style from m_style_items.
+ /// Remove style from m_styles.
/// Fix selected font index when index is under m_font_selected
///
/// Index of style to be removed
@@ -94,13 +93,14 @@ public:
/// Change active font
/// When font not loaded roll back activ font
///
- /// New font index(from m_style_items range)
+ /// New font index(from m_styles range)
/// True on succes. False on fail load font
bool load_style(size_t font_index);
// load font style not stored in list
- bool load_style(const EmbossStyle &style);
+ struct Style;
+ bool load_style(const Style &style);
// fastering load font on index by wxFont, ignore type and descriptor
- bool load_style(const EmbossStyle &style, const wxFont &font);
+ bool load_style(const Style &style, const wxFont &font);
// clear actual selected glyphs cache
void clear_glyphs_cache();
@@ -109,10 +109,10 @@ public:
void clear_imgui_font();
// getters for private data
- const EmbossStyle *get_stored_style() const;
+ const Style *get_stored_style() const;
- const EmbossStyle &get_style() const { return m_style_cache.style; }
- EmbossStyle &get_style() { return m_style_cache.style; }
+ const Style &get_style() const { return m_style_cache.style; }
+ Style &get_style() { return m_style_cache.style; }
size_t get_style_index() const { return m_style_cache.style_index; }
std::string &get_truncated_name() { return m_style_cache.truncated_name; }
const ImFontAtlas &get_atlas() const { return m_style_cache.atlas; }
@@ -133,6 +133,8 @@ public:
///
bool is_font_changed() const;
+ bool is_unique_style_name(const std::string &name) const;
+
///
/// Setter on wx_font when changed
///
@@ -167,33 +169,28 @@ public:
void init_style_images(const Vec2i& max_size, const std::string &text);
void free_style_images();
- struct Item;
// access to all managed font styles
- const std::vector- &get_styles() const;
+ const std::vector