mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 00:56:00 +08:00
Partialy calculated distance on the fly.
This commit is contained in:
parent
1b34b1970c
commit
e0a4ac0313
@ -144,6 +144,21 @@ Pointf3s transform(const Pointf3s& points, const Transform3d& t);
|
||||
/// <returns>Is positive determinant</returns>
|
||||
inline bool has_reflection(const Transform3d &transform) { return transform.matrix().determinant() < 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Getter on base of transformation matrix
|
||||
/// </summary>
|
||||
/// <param name="index">column index</param>
|
||||
/// <param name="transform">source transformation</param>
|
||||
/// <returns>Base of transformation matrix</returns>
|
||||
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<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N, 1>;
|
||||
|
||||
class Point : public Vec2crd
|
||||
|
@ -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<unsigned char>(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<float> &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 {
|
||||
|
||||
/// <summary>
|
||||
/// Throow ray by embossing params to object and find surface point
|
||||
/// </summary>
|
||||
/// <param name="gl_volume">Define embossed volume</param>
|
||||
/// <param name="raycaster">Way to cast rays to object</param>
|
||||
/// <param name="canvas">Contain model</param>
|
||||
/// <returns>Calculated distance from surface</returns>
|
||||
std::optional<float> 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<size_t> 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<TextConfiguration>& tc_opt = volume->text_configuration;
|
||||
if (!tc_opt.has_value())
|
||||
const std::optional<TextConfiguration> &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<std::string> face_name_opt = style.prop.face_name;
|
||||
bool is_font_installed = true;
|
||||
wxString face_name;
|
||||
const std::optional<std::string> &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<FaceName> &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<wxString> &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<wxString> &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<float> &f_angle_opt = from.angle;
|
||||
const std::optional<float> &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<float> &f_move_opt = from.distance;
|
||||
const std::optional<float> &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<std::pair<size_t,size_t>> swap_indexes;
|
||||
const std::vector<StyleManager::Item> &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<StyleManager::StyleImage> &img = item.image;
|
||||
float select_height = static_cast<float>(m_gui_cfg->max_style_image_size.y());
|
||||
ImVec2 select_size(0.f, select_height); // 0,0 --> calculate in draw
|
||||
const std::optional<StyleManager::StyleImage> &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<int> &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<int> &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<float> &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<float> &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<float> &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<float> &distance = current_style.distance;
|
||||
float prev_distance = distance.value_or(.0f);
|
||||
float min_distance = static_cast<float>(-2 * current_style.projection.depth);
|
||||
float max_distance = static_cast<float>(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<float> &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<float>(-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<wxFont> 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<float>(shape.projection.depth); // copy
|
||||
|
||||
DataBase::write(volume);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace Slic3r::GUI {
|
||||
class GLGizmoEmboss : public GLGizmoBase
|
||||
{
|
||||
public:
|
||||
GLGizmoEmboss(GLCanvas3D& parent);
|
||||
explicit GLGizmoEmboss(GLCanvas3D& parent);
|
||||
|
||||
/// <summary>
|
||||
/// 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<SurfaceDrag> 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
|
||||
|
@ -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())
|
||||
|
@ -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<EmbossShape> &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);
|
||||
|
@ -37,8 +37,8 @@ class DataBase
|
||||
public:
|
||||
DataBase(const std::string& volume_name, std::shared_ptr<std::atomic<bool>> cancel) : volume_name(volume_name), cancel(std::move(cancel)) {}
|
||||
DataBase(const std::string& volume_name, std::shared_ptr<std::atomic<bool>> 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;
|
||||
|
||||
/// <summary>
|
||||
|
@ -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<size_t>(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<size_t> 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<double>();
|
||||
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<float> 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);
|
||||
|
@ -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<EmbossStyles()> 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<size_t>::max())
|
||||
StyleManager::StyleManager(const ImWchar *language_glyph_range, const std::function<EmbossStyles()>& 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
|
||||
/// </summary>
|
||||
namespace {
|
||||
void store_style_index(AppConfig &cfg, unsigned index);
|
||||
void store_style_index(AppConfig &cfg, size_t index);
|
||||
::std::optional<size_t> 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<size_t> 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<size_t>::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<FontFile> 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<wxFont> 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::Item> &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::StyleImages>();
|
||||
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<wxFont> wx_font_opt = WxFontUtils::load_wxFont(style.path);
|
||||
if (!wx_font_opt.has_value()) continue;
|
||||
std::unique_ptr<FontFile> 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<FontFile>
|
||||
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<float> &
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<EmbossStyle> load_style(const Section &app_cfg_section)
|
||||
std::optional<StyleManager::Style> 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<size_t> 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<EmbossStyle> style_opt = load_style(cfg.get_section(section_name));
|
||||
if (style_opt.has_value())
|
||||
std::optional<StyleManager::Style> 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
|
||||
|
@ -24,11 +24,10 @@ namespace Slic3r::GUI::Emboss {
|
||||
class StyleManager
|
||||
{
|
||||
friend class CreateFontStyleImagesJob; // access to StyleImagesData
|
||||
|
||||
public:
|
||||
/// <param name="language_glyph_range">Character to load for imgui when initialize imgui font</param>
|
||||
/// <param name="create_default_styles">Function to create default styles</param>
|
||||
StyleManager(const ImWchar *language_glyph_range, std::function<EmbossStyles()> create_default_styles);
|
||||
StyleManager(const ImWchar *language_glyph_range, const std::function<EmbossStyles()>& create_default_styles);
|
||||
|
||||
/// <summary>
|
||||
/// Release imgui font and style images from GPU
|
||||
@ -59,11 +58,11 @@ public:
|
||||
void add_style(const std::string& name);
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <param name="i1">First index to m_style_items</param>
|
||||
/// <param name="i2">Second index to m_style_items</param>
|
||||
/// <param name="i1">First index to m_styles</param>
|
||||
/// <param name="i2">Second index to m_styles</param>
|
||||
void swap(size_t i1, size_t i2);
|
||||
|
||||
/// <summary>
|
||||
@ -73,7 +72,7 @@ public:
|
||||
void discard_style_changes();
|
||||
|
||||
/// <summary>
|
||||
/// Remove style from m_style_items.
|
||||
/// Remove style from m_styles.
|
||||
/// Fix selected font index when index is under m_font_selected
|
||||
/// </summary>
|
||||
/// <param name="index">Index of style to be removed</param>
|
||||
@ -94,13 +93,14 @@ public:
|
||||
/// Change active font
|
||||
/// When font not loaded roll back activ font
|
||||
/// </summary>
|
||||
/// <param name="font_index">New font index(from m_style_items range)</param>
|
||||
/// <param name="font_index">New font index(from m_styles range)</param>
|
||||
/// <returns>True on succes. False on fail load font</returns>
|
||||
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:
|
||||
/// <returns></returns>
|
||||
bool is_font_changed() const;
|
||||
|
||||
bool is_unique_style_name(const std::string &name) const;
|
||||
|
||||
/// <summary>
|
||||
/// Setter on wx_font when changed
|
||||
/// </summary>
|
||||
@ -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<Item> &get_styles() const;
|
||||
const std::vector<Style> &get_styles() const;
|
||||
|
||||
/// <summary>
|
||||
/// Describe image in GPU to show settings of style
|
||||
/// </summary>
|
||||
struct StyleImage
|
||||
{
|
||||
void* texture_id = 0; // GLuint
|
||||
void* texture_id = nullptr; // GLuint
|
||||
BoundingBox bounding_box;
|
||||
ImVec2 tex_size;
|
||||
ImVec2 uv0;
|
||||
ImVec2 uv1;
|
||||
Point offset = Point(0, 0);
|
||||
StyleImage() = default;
|
||||
Point offset = Point(0, 0);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// All connected with one style
|
||||
/// keep temporary data and caches for style
|
||||
/// </summary>
|
||||
struct Item
|
||||
struct Style : public EmbossStyle
|
||||
{
|
||||
// parent Text style
|
||||
EmbossStyle style;
|
||||
|
||||
// Define how to emboss shape
|
||||
EmbossProjection projection;
|
||||
|
||||
@ -208,9 +205,12 @@ public:
|
||||
// When not set value is zero and is not stored
|
||||
std::optional<float> angle; // [in radians] form -Pi to Pi
|
||||
|
||||
bool operator==(const Item &other) const
|
||||
bool operator==(const Style &other) const
|
||||
{
|
||||
return style == other.style && projection == other.projection && distance == other.distance && angle == other.angle;
|
||||
return EmbossStyle::operator==(other) &&
|
||||
projection == other.projection &&
|
||||
distance == other.distance &&
|
||||
angle == other.angle;
|
||||
}
|
||||
|
||||
// cache for view font name with maximal width in imgui
|
||||
@ -219,6 +219,7 @@ public:
|
||||
// visualization of style
|
||||
std::optional<StyleImage> image;
|
||||
};
|
||||
using Styles = std::vector<Style>;
|
||||
|
||||
// check if exist selected font style in manager
|
||||
bool is_active_font();
|
||||
@ -230,7 +231,10 @@ public:
|
||||
static float get_imgui_font_size(const FontProp &prop, const Slic3r::Emboss::FontFile &file, double scale);
|
||||
|
||||
private:
|
||||
// function to create default style list
|
||||
std::function<EmbossStyles()> m_create_default_styles;
|
||||
// keep language dependent glyph range
|
||||
const ImWchar *m_imgui_init_glyph_range;
|
||||
|
||||
/// <summary>
|
||||
/// Cache data from style to reduce amount of:
|
||||
@ -256,22 +260,20 @@ private:
|
||||
std::string truncated_name;
|
||||
|
||||
// actual used font item
|
||||
EmbossStyle style = {};
|
||||
Style style = {};
|
||||
|
||||
// cache for stored wx font to not create every frame
|
||||
wxFont stored_wx_font = {};
|
||||
|
||||
// index into m_style_items
|
||||
// index into m_styles
|
||||
size_t style_index = std::numeric_limits<size_t>::max();
|
||||
|
||||
} m_style_cache;
|
||||
|
||||
void make_unique_name(std::string &name);
|
||||
|
||||
// Privat member
|
||||
std::vector<Item> m_style_items;
|
||||
AppConfig *m_app_config;
|
||||
size_t m_last_style_index;
|
||||
Styles m_styles;
|
||||
AppConfig *m_app_config = nullptr;
|
||||
size_t m_last_style_index = std::numeric_limits<size_t>::max();
|
||||
|
||||
/// <summary>
|
||||
/// Keep data needed to create Font Style Images in Job
|
||||
@ -310,12 +312,8 @@ private:
|
||||
// pixel per milimeter (scaled DPI)
|
||||
double ppm;
|
||||
};
|
||||
std::shared_ptr<StyleImagesData::StyleImages> m_temp_style_images;
|
||||
bool m_exist_style_images;
|
||||
|
||||
// store all font GLImages
|
||||
//ImFontAtlas m_imgui_font_atlas;
|
||||
const ImWchar *m_imgui_init_glyph_range;
|
||||
std::shared_ptr<StyleImagesData::StyleImages> m_temp_style_images = nullptr;
|
||||
bool m_exist_style_images = false;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -108,7 +108,7 @@ std::unique_ptr<Emboss::FontFile> WxFontUtils::create_font_file(const wxFont &fo
|
||||
#endif
|
||||
}
|
||||
|
||||
EmbossStyle::Type WxFontUtils::get_actual_type()
|
||||
EmbossStyle::Type WxFontUtils::get_current_type()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return EmbossStyle::Type::wx_win_font_descr;
|
||||
@ -125,7 +125,7 @@ EmbossStyle WxFontUtils::create_emboss_style(const wxFont &font, const std::stri
|
||||
{
|
||||
std::string name_item = name.empty()? get_human_readable_name(font) : name;
|
||||
std::string fontDesc = store_wxFont(font);
|
||||
EmbossStyle::Type type = get_actual_type();
|
||||
EmbossStyle::Type type = get_current_type();
|
||||
|
||||
// synchronize font property with actual font
|
||||
FontProp font_prop;
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
// os specific load of wxFont
|
||||
static std::unique_ptr<Slic3r::Emboss::FontFile> create_font_file(const wxFont &font);
|
||||
|
||||
static EmbossStyle::Type get_actual_type();
|
||||
static EmbossStyle::Type get_current_type();
|
||||
static EmbossStyle create_emboss_style(const wxFont &font, const std::string& name = "");
|
||||
|
||||
static std::string get_human_readable_name(const wxFont &font);
|
||||
|
Loading…
x
Reference in New Issue
Block a user