mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-02 15:40:39 +08:00
Forward declaration of FaceNames data structure
This commit is contained in:
parent
b77f788c64
commit
aed764b089
@ -63,14 +63,13 @@ using namespace Slic3r::Emboss;
|
|||||||
using namespace Slic3r::GUI;
|
using namespace Slic3r::GUI;
|
||||||
using namespace Slic3r::GUI::Emboss;
|
using namespace Slic3r::GUI::Emboss;
|
||||||
|
|
||||||
namespace priv {
|
namespace {
|
||||||
template<typename T> struct Limit {
|
template<typename T> struct Limit {
|
||||||
// Limitation for view slider range in GUI
|
// Limitation for view slider range in GUI
|
||||||
MinMax<T> gui;
|
MinMax<T> gui;
|
||||||
// Real limits for setting exacts values
|
// Real limits for setting exacts values
|
||||||
MinMax<T> values;
|
MinMax<T> values;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variable keep limits for variables
|
// Variable keep limits for variables
|
||||||
static const struct Limits
|
static const struct Limits
|
||||||
{
|
{
|
||||||
@ -82,24 +81,11 @@ static const struct Limits
|
|||||||
MinMax<int> line_gap{-20000, 20000}; // in font points
|
MinMax<int> line_gap{-20000, 20000}; // in font points
|
||||||
// distance text object from surface
|
// distance text object from surface
|
||||||
MinMax<float> angle{-180.f, 180.f}; // in degrees
|
MinMax<float> angle{-180.f, 180.f}; // in degrees
|
||||||
|
|
||||||
|
// Distance of text volume from surface to be represented as distance surface
|
||||||
|
MinMax<double> calc_distance_sq{1e-4, 10.}; // in mm
|
||||||
} limits;
|
} limits;
|
||||||
|
|
||||||
} // namespace priv
|
|
||||||
using namespace priv;
|
|
||||||
|
|
||||||
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
|
||||||
: GLGizmoBase(parent, M_ICON_FILENAME, -2)
|
|
||||||
, m_style_manager(m_imgui->get_glyph_ranges(), create_default_styles)
|
|
||||||
, m_rotate_gizmo(parent, GLGizmoRotate::Axis::Z) // grab id = 2 (Z axis)
|
|
||||||
{
|
|
||||||
m_rotate_gizmo.set_group_id(0);
|
|
||||||
m_rotate_gizmo.set_force_local_coordinate(true);
|
|
||||||
// to use https://fontawesome.com/ (copy & paste) unicode symbols from web
|
|
||||||
// paste HEX unicode into notepad move cursor after unicode press [alt] + [x]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private namespace with helper function for create volume
|
|
||||||
namespace priv {
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prepare data for emboss
|
/// Prepare data for emboss
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -107,9 +93,17 @@ namespace priv {
|
|||||||
/// <param name="style_manager">Keep actual selected style</param>
|
/// <param name="style_manager">Keep actual selected style</param>
|
||||||
/// <param name="cancel">Cancel for previous job</param>
|
/// <param name="cancel">Cancel for previous job</param>
|
||||||
/// <returns>Base data for emboss text</returns>
|
/// <returns>Base data for emboss text</returns>
|
||||||
static std::unique_ptr<DataBase> create_emboss_data_base(
|
std::unique_ptr<DataBase> create_emboss_data_base(
|
||||||
const std::string &text, StyleManager &style_manager, std::shared_ptr<std::atomic<bool>> &cancel);
|
const std::string &text, StyleManager &style_manager, std::shared_ptr<std::atomic<bool>> &cancel);
|
||||||
|
|
||||||
|
CreateVolumeParams create_input(GLCanvas3D &canvas, const StyleManager::Style &style, RaycastManager &raycaster, ModelVolumeType volume_type);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move window for edit emboss text near to embossed object
|
||||||
|
/// NOTE: embossed object must be selected
|
||||||
|
/// </summary>
|
||||||
|
ImVec2 calc_fine_position(const Selection &selection, const ImVec2 &windows_size, const Size &canvas_size);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data for emboss job to create shape
|
/// Data for emboss job to create shape
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -150,16 +144,74 @@ enum class IconState : unsigned { activable = 0, hovered /*1*/, disabled /*2*/ }
|
|||||||
// selector for icon by enum
|
// selector for icon by enum
|
||||||
const IconManager::Icon &get_icon(const IconManager::VIcons& icons, IconType type, IconState state);
|
const IconManager::Icon &get_icon(const IconManager::VIcons& icons, IconType type, IconState state);
|
||||||
// short call of Slic3r::GUI::button
|
// short call of Slic3r::GUI::button
|
||||||
static bool draw_button(const IconManager::VIcons& icons, IconType type, bool disable = false);
|
bool draw_button(const IconManager::VIcons& icons, IconType type, bool disable = false);
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
CreateVolumeParams create_input(GLCanvas3D &canvas, const StyleManager::Style &style, RaycastManager& raycaster, ModelVolumeType volume_type)
|
struct GLGizmoEmboss::FaceName
|
||||||
{
|
{
|
||||||
auto gizmo = static_cast<unsigned char>(GLGizmosManager::Emboss);
|
wxString wx_name;
|
||||||
const GLVolume *gl_volume = get_first_hovered_gl_volume(canvas);
|
std::string name_truncated = "";
|
||||||
Plater *plater = wxGetApp().plater();
|
size_t texture_index = 0;
|
||||||
return CreateVolumeParams{canvas, plater->get_camera(), plater->build_volume(),
|
// State for generation of texture
|
||||||
plater->get_ui_job_worker(), volume_type, raycaster, gizmo, gl_volume, style.distance, style.angle};
|
// when start generate create share pointers
|
||||||
|
std::shared_ptr<std::atomic<bool>> cancel = nullptr;
|
||||||
|
// R/W only on main thread - finalize of job
|
||||||
|
std::shared_ptr<bool> is_created = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of forwarded struct
|
||||||
|
// Keep sorted list of loadable face names
|
||||||
|
struct GLGizmoEmboss::Facenames
|
||||||
|
{
|
||||||
|
// flag to keep need of enumeration fonts from OS
|
||||||
|
// false .. wants new enumeration check by Hash
|
||||||
|
// true .. already enumerated(During opened combo box)
|
||||||
|
bool is_init = false;
|
||||||
|
|
||||||
|
bool has_truncated_names = false;
|
||||||
|
|
||||||
|
// data of can_load() faces
|
||||||
|
std::vector<FaceName> faces = {};
|
||||||
|
// Sorter set of Non valid face names in OS
|
||||||
|
std::vector<wxString> bad = {};
|
||||||
|
|
||||||
|
// Configuration of font encoding
|
||||||
|
static const wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM;
|
||||||
|
|
||||||
|
// Identify if preview texture exists
|
||||||
|
GLuint texture_id = 0;
|
||||||
|
|
||||||
|
// protection for open too much font files together
|
||||||
|
// Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load
|
||||||
|
// /usr/share/icons/Yaru/48x48/status/image-missing.png: Error opening file /usr/share/icons/Yaru/48x48/status/image-missing.png: Too
|
||||||
|
// many open files (g-io-error-quark, 31) This variable must exist until no CreateFontImageJob is running
|
||||||
|
unsigned int count_opened_font_files = 0;
|
||||||
|
|
||||||
|
// Configuration for texture height
|
||||||
|
const int count_cached_textures = 32;
|
||||||
|
|
||||||
|
// index for new generated texture index(must be lower than count_cached_textures)
|
||||||
|
size_t texture_index = 0;
|
||||||
|
|
||||||
|
// hash created from enumerated font from OS
|
||||||
|
// check when new font was installed
|
||||||
|
size_t hash = 0;
|
||||||
|
|
||||||
|
// filtration pattern
|
||||||
|
std::string search = "";
|
||||||
|
std::vector<bool> hide; // result of filtration
|
||||||
|
};
|
||||||
|
|
||||||
|
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
||||||
|
: GLGizmoBase(parent, M_ICON_FILENAME, -2)
|
||||||
|
, m_style_manager(m_imgui->get_glyph_ranges(), create_default_styles)
|
||||||
|
, m_rotate_gizmo(parent, GLGizmoRotate::Axis::Z) // grab id = 2 (Z axis)
|
||||||
|
{
|
||||||
|
m_rotate_gizmo.set_group_id(0);
|
||||||
|
m_rotate_gizmo.set_force_local_coordinate(true);
|
||||||
|
// to use https://fontawesome.com/ (copy & paste) unicode symbols from web
|
||||||
|
// paste HEX unicode into notepad move cursor after unicode press [alt] + [x]
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
|
bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
|
||||||
@ -168,7 +220,7 @@ bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous
|
|||||||
set_default_text();
|
set_default_text();
|
||||||
|
|
||||||
// NOTE: change style manager - be carefull with order changes
|
// NOTE: change style manager - be carefull with order changes
|
||||||
DataBasePtr base = priv::create_emboss_data_base(m_text, m_style_manager, m_job_cancel);
|
DataBasePtr base = create_emboss_data_base(m_text, m_style_manager, m_job_cancel);
|
||||||
CreateVolumeParams input = create_input(m_parent, m_style_manager.get_style(), 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);
|
return start_create_volume(input, std::move(base), mouse_pos);
|
||||||
}
|
}
|
||||||
@ -180,7 +232,7 @@ bool GLGizmoEmboss::create_volume(ModelVolumeType volume_type)
|
|||||||
set_default_text();
|
set_default_text();
|
||||||
|
|
||||||
// NOTE: change style manager - be carefull with order changes
|
// NOTE: change style manager - be carefull with order changes
|
||||||
DataBasePtr base = priv::create_emboss_data_base(m_text, m_style_manager, m_job_cancel);
|
DataBasePtr base = create_emboss_data_base(m_text, m_style_manager, m_job_cancel);
|
||||||
CreateVolumeParams input = create_input(m_parent, m_style_manager.get_style(), 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));
|
return start_create_volume_without_position(input, std::move(base));
|
||||||
}
|
}
|
||||||
@ -196,7 +248,7 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
|
|||||||
if (!m_rotate_start_angle.has_value()) {
|
if (!m_rotate_start_angle.has_value()) {
|
||||||
// when m_rotate_start_angle is not set mean it is not Dragging
|
// when m_rotate_start_angle is not set mean it is not Dragging
|
||||||
// when angle_opt is not set than 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;
|
const std::optional<float> &angle_opt = m_style_manager.get_style().angle;
|
||||||
m_rotate_start_angle = angle_opt.value_or(0.f);
|
m_rotate_start_angle = angle_opt.value_or(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +270,7 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
|
|||||||
std::optional<float> angle_opt;
|
std::optional<float> angle_opt;
|
||||||
if (!is_approx(angle, 0.))
|
if (!is_approx(angle, 0.))
|
||||||
angle_opt = angle;
|
angle_opt = angle;
|
||||||
m_style_manager.get_font_prop().angle = angle_opt;
|
m_style_manager.get_style().angle = angle_opt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return used;
|
return used;
|
||||||
@ -230,8 +282,9 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
if (m_volume == nullptr)
|
if (m_volume == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::optional<double> up_limit;
|
std::optional<double> wanted_up_limit;
|
||||||
if (m_keep_up) up_limit = Slic3r::GUI::up_limit;
|
if (m_keep_up)
|
||||||
|
wanted_up_limit = up_limit;
|
||||||
const Camera &camera = wxGetApp().plater()->get_camera();
|
const Camera &camera = wxGetApp().plater()->get_camera();
|
||||||
bool was_dragging = m_surface_drag.has_value();
|
bool was_dragging = m_surface_drag.has_value();
|
||||||
bool res = on_mouse_surface_drag(mouse_event, camera, m_surface_drag, m_parent, m_raycast_manager, up_limit);
|
bool res = on_mouse_surface_drag(mouse_event, camera, m_surface_drag, m_parent, m_raycast_manager, up_limit);
|
||||||
@ -240,7 +293,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
// End with surface dragging?
|
// End with surface dragging?
|
||||||
if (was_dragging && !is_dragging) {
|
if (was_dragging && !is_dragging) {
|
||||||
// Update surface by new position
|
// Update surface by new position
|
||||||
if (m_volume->text_configuration->style.prop.use_surface)
|
if (m_volume->emboss_shape->projection.use_surface)
|
||||||
process();
|
process();
|
||||||
|
|
||||||
// Show correct value of height & depth inside of inputs
|
// Show correct value of height & depth inside of inputs
|
||||||
@ -305,15 +358,16 @@ std::string GLGizmoEmboss::on_get_name() const { return _u8L("Emboss"); }
|
|||||||
|
|
||||||
void GLGizmoEmboss::on_render() {
|
void GLGizmoEmboss::on_render() {
|
||||||
// no volume selected
|
// no volume selected
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
if (m_volume == nullptr ||
|
if (m_volume == nullptr ||
|
||||||
get_model_volume(m_volume_id, m_parent.get_selection().get_model()->objects) == nullptr)
|
get_model_volume(m_volume_id, selection.get_model()->objects) == nullptr)
|
||||||
return;
|
return;
|
||||||
Selection &selection = m_parent.get_selection();
|
|
||||||
if (selection.is_empty()) return;
|
if (selection.is_empty()) return;
|
||||||
|
|
||||||
// prevent get local coordinate system on multi volumes
|
// prevent get local coordinate system on multi volumes
|
||||||
if (!selection.is_single_volume_or_modifier() &&
|
if (!selection.is_single_volume_or_modifier() &&
|
||||||
!selection.is_single_volume_instance()) return;
|
!selection.is_single_volume_instance()) return;
|
||||||
|
|
||||||
bool is_surface_dragging = m_surface_drag.has_value();
|
bool is_surface_dragging = m_surface_drag.has_value();
|
||||||
bool is_parent_dragging = m_parent.is_mouse_dragging();
|
bool is_parent_dragging = m_parent.is_mouse_dragging();
|
||||||
// Do NOT render rotation grabbers when dragging object
|
// Do NOT render rotation grabbers when dragging object
|
||||||
@ -489,15 +543,6 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace priv {
|
|
||||||
/// <summary>
|
|
||||||
/// Move window for edit emboss text near to embossed object
|
|
||||||
/// NOTE: embossed object must be selected
|
|
||||||
/// </summary>
|
|
||||||
static ImVec2 calc_fine_position(const Selection &selection, const ImVec2 &windows_size, const Size &canvas_size);
|
|
||||||
|
|
||||||
} // namespace priv
|
|
||||||
|
|
||||||
void GLGizmoEmboss::on_set_state()
|
void GLGizmoEmboss::on_set_state()
|
||||||
{
|
{
|
||||||
// enable / disable bed from picking
|
// enable / disable bed from picking
|
||||||
@ -544,7 +589,7 @@ void GLGizmoEmboss::on_set_state()
|
|||||||
|
|
||||||
// change position of just opened emboss window
|
// change position of just opened emboss window
|
||||||
if (m_allow_open_near_volume) {
|
if (m_allow_open_near_volume) {
|
||||||
m_set_window_offset = priv::calc_fine_position(m_parent.get_selection(), get_minimal_window_size(), m_parent.get_canvas_size());
|
m_set_window_offset = calc_fine_position(m_parent.get_selection(), get_minimal_window_size(), m_parent.get_canvas_size());
|
||||||
} else {
|
} else {
|
||||||
if (m_gui_cfg.has_value())
|
if (m_gui_cfg.has_value())
|
||||||
m_set_window_offset = ImGuiWrapper::change_window_position(on_get_name().c_str(), false);
|
m_set_window_offset = ImGuiWrapper::change_window_position(on_get_name().c_str(), false);
|
||||||
@ -567,7 +612,6 @@ void GLGizmoEmboss::on_stop_dragging()
|
|||||||
{
|
{
|
||||||
m_rotate_gizmo.stop_dragging();
|
m_rotate_gizmo.stop_dragging();
|
||||||
|
|
||||||
// TODO: when start second rotatiton previous rotation rotate draggers
|
|
||||||
// This is fast fix for second try to rotate
|
// This is fast fix for second try to rotate
|
||||||
// When fixing, move grabber above text (not on side)
|
// When fixing, move grabber above text (not on side)
|
||||||
m_rotate_gizmo.set_angle(PI/2);
|
m_rotate_gizmo.set_angle(PI/2);
|
||||||
@ -585,8 +629,8 @@ void GLGizmoEmboss::on_stop_dragging()
|
|||||||
m_rotate_start_angle.reset();
|
m_rotate_start_angle.reset();
|
||||||
|
|
||||||
// recalculate for surface cut
|
// recalculate for surface cut
|
||||||
const FontProp &font_prop = m_style_manager.get_style().prop;
|
if (m_style_manager.get_style().projection.use_surface)
|
||||||
if (font_prop.use_surface) process();
|
process();
|
||||||
}
|
}
|
||||||
void GLGizmoEmboss::on_dragging(const UpdateData &data) { m_rotate_gizmo.dragging(data); }
|
void GLGizmoEmboss::on_dragging(const UpdateData &data) { m_rotate_gizmo.dragging(data); }
|
||||||
|
|
||||||
@ -606,10 +650,10 @@ GLGizmoEmboss::GuiCfg GLGizmoEmboss::create_gui_configuration()
|
|||||||
if (cfg.icon_width % 2 != 0) ++cfg.icon_width;
|
if (cfg.icon_width % 2 != 0) ++cfg.icon_width;
|
||||||
|
|
||||||
cfg.delete_pos_x = cfg.max_style_name_width + space;
|
cfg.delete_pos_x = cfg.max_style_name_width + space;
|
||||||
int count_line_of_text = 3;
|
const float count_line_of_text = 3.f;
|
||||||
cfg.text_size = ImVec2(-FLT_MIN, line_height_with_spacing * count_line_of_text);
|
cfg.text_size = ImVec2(-FLT_MIN, line_height_with_spacing * count_line_of_text);
|
||||||
ImVec2 letter_m_size = ImGui::CalcTextSize("M");
|
ImVec2 letter_m_size = ImGui::CalcTextSize("M");
|
||||||
int count_letter_M_in_input = 12;
|
const float count_letter_M_in_input = 12.f;
|
||||||
cfg.input_width = letter_m_size.x * count_letter_M_in_input;
|
cfg.input_width = letter_m_size.x * count_letter_M_in_input;
|
||||||
GuiCfg::Translations &tr = cfg.translations;
|
GuiCfg::Translations &tr = cfg.translations;
|
||||||
|
|
||||||
@ -679,9 +723,8 @@ GLGizmoEmboss::GuiCfg GLGizmoEmboss::create_gui_configuration()
|
|||||||
ImVec2(cfg.minimal_window_size_with_advance.x,
|
ImVec2(cfg.minimal_window_size_with_advance.x,
|
||||||
cfg.minimal_window_size_with_advance.y + input_height);
|
cfg.minimal_window_size_with_advance.y + input_height);
|
||||||
|
|
||||||
int max_style_image_width = cfg.max_style_name_width /2 -
|
int max_style_image_width = static_cast<int>(std::round(cfg.max_style_name_width/2 - 2 * style.FramePadding.x));
|
||||||
2 * style.FramePadding.x;
|
int max_style_image_height = static_cast<int>(std::round(1.5 * input_height));
|
||||||
int max_style_image_height = 1.5 * input_height;
|
|
||||||
cfg.max_style_image_size = Vec2i(max_style_image_width, max_style_image_height);
|
cfg.max_style_image_size = Vec2i(max_style_image_width, max_style_image_height);
|
||||||
cfg.face_name_size.y() = line_height_with_spacing;
|
cfg.face_name_size.y() = line_height_with_spacing;
|
||||||
return cfg;
|
return cfg;
|
||||||
@ -802,9 +845,25 @@ std::optional<float> calc_distance(const GLVolume &gl_volume, RaycastManager &ra
|
|||||||
Transform3d w = gl_volume.world_matrix();
|
Transform3d w = gl_volume.world_matrix();
|
||||||
Vec3d p = w.translation();
|
Vec3d p = w.translation();
|
||||||
const Vec3d& dir = get_z_base(w);
|
const Vec3d& dir = get_z_base(w);
|
||||||
auto hit_opt = raycaster.first_hit(p, dir, &condition);
|
auto hit_opt = raycaster.closest_hit(p, dir, &condition);
|
||||||
if (!hit_opt.has_value())
|
if (!hit_opt.has_value())
|
||||||
return {};
|
return {};
|
||||||
|
const RaycastManager::Hit &hit = *hit_opt;
|
||||||
|
|
||||||
|
// too small distance is calculated as zero distance
|
||||||
|
if (hit.squared_distance < limits.calc_distance_sq.min)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// check macimal distance
|
||||||
|
double max_squared_distance = std::max(std::pow(2 * volume->emboss_shape->projection.depth, 2), limits.calc_distance_sq.max);
|
||||||
|
if (hit.squared_distance > max_squared_distance)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// calculate sign
|
||||||
|
float sign = ((hit.position - p).dot(dir) > 0)? 1.f : -1.f;
|
||||||
|
|
||||||
|
// distiguish sign
|
||||||
|
return sign * static_cast<float>(sqrt(hit.squared_distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -848,25 +907,25 @@ void GLGizmoEmboss::set_volume_by_selection()
|
|||||||
// Could exist OS without getter on face_name,
|
// Could exist OS without getter on face_name,
|
||||||
// but it is able to restore font from descriptor
|
// but it is able to restore font from descriptor
|
||||||
// Soo default value must be TRUE
|
// Soo default value must be TRUE
|
||||||
bool is_font_installed = true;
|
bool is_font_installed = true;
|
||||||
wxString face_name;
|
wxString face_name;
|
||||||
const std::optional<std::string> &face_name_opt = style.prop.face_name;
|
if (const std::optional<std::string> &face_name_opt = style.prop.face_name;
|
||||||
if (face_name_opt.has_value()) {
|
face_name_opt.has_value()) {
|
||||||
face_name = wxString(face_name_opt->c_str());
|
face_name = wxString(face_name_opt->c_str());
|
||||||
|
|
||||||
// search in enumerated fonts
|
// search in enumerated fonts
|
||||||
// refresh list of installed font in the OS.
|
// refresh list of installed font in the OS.
|
||||||
init_face_names(m_face_names);
|
init_face_names(*m_face_names);
|
||||||
m_face_names.is_init = false;
|
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 &wx_name) { return fn.wx_name < wx_name; };
|
||||||
const std::vector<FaceName> &faces = m_face_names.faces;
|
const std::vector<FaceName> &faces = m_face_names->faces;
|
||||||
auto it = std::lower_bound(faces.begin(), faces.end(), face_name, cmp);
|
auto it = std::lower_bound(faces.begin(), faces.end(), face_name, cmp);
|
||||||
is_font_installed = it != faces.end() && it->wx_name == face_name;
|
is_font_installed = it != faces.end() && it->wx_name == face_name;
|
||||||
|
|
||||||
if (!is_font_installed) {
|
if (!is_font_installed) {
|
||||||
const std::vector<wxString> &bad = m_face_names.bad;
|
const std::vector<wxString> &bad = m_face_names->bad;
|
||||||
auto it_bad = std::lower_bound(bad.begin(), bad.end(), face_name);
|
auto it_bad = std::lower_bound(bad.begin(), bad.end(), face_name);
|
||||||
if (it_bad == bad.end() || *it_bad != face_name) {
|
if (it_bad == bad.end() || *it_bad != face_name) {
|
||||||
// check if wx allowed to set it up - another encoding of name
|
// check if wx allowed to set it up - another encoding of name
|
||||||
wxFontEnumerator::InvalidateCache();
|
wxFontEnumerator::InvalidateCache();
|
||||||
@ -894,7 +953,7 @@ void GLGizmoEmboss::set_volume_by_selection()
|
|||||||
is_exact_font = false;
|
is_exact_font = false;
|
||||||
// Try create similar wx font by FontFamily
|
// Try create similar wx font by FontFamily
|
||||||
wx_font = WxFontUtils::create_wxFont(style);
|
wx_font = WxFontUtils::create_wxFont(style);
|
||||||
if (is_font_installed)
|
if (is_font_installed && !face_name.empty())
|
||||||
is_exact_font = wx_font.SetFaceName(face_name);
|
is_exact_font = wx_font.SetFaceName(face_name);
|
||||||
|
|
||||||
// Have to use some wxFont
|
// Have to use some wxFont
|
||||||
@ -907,13 +966,13 @@ void GLGizmoEmboss::set_volume_by_selection()
|
|||||||
const auto &styles = m_style_manager.get_styles();
|
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; };
|
auto has_same_name = [&name = style.name](const StyleManager::Style &style_item) { return style_item.name == name; };
|
||||||
|
|
||||||
StyleManager::Style style_{style};
|
StyleManager::Style style_{style}; // copy
|
||||||
style_.projection = volume->emboss_shape->projection;
|
style_.projection = volume->emboss_shape->projection;
|
||||||
style_.angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
|
style_.angle = calc_up(gl_volume->world_matrix(), Slic3r::GUI::up_limit);
|
||||||
style_.distance = calc_distance(*gl_volume, m_raycast_manager, m_parent);
|
style_.distance = calc_distance(*gl_volume, m_raycast_manager, m_parent);
|
||||||
|
|
||||||
auto it = std::find_if(styles.begin(), styles.end(), has_same_name);
|
if (auto it = std::find_if(styles.begin(), styles.end(), has_same_name);
|
||||||
if (it == styles.end()) {
|
it == styles.end()) {
|
||||||
// style was not found
|
// style was not found
|
||||||
m_style_manager.load_style(style_, wx_font);
|
m_style_manager.load_style(style_, wx_font);
|
||||||
} else {
|
} else {
|
||||||
@ -1027,7 +1086,7 @@ bool GLGizmoEmboss::process()
|
|||||||
// exist loaded font file?
|
// exist loaded font file?
|
||||||
if (!m_style_manager.is_active_font()) return false;
|
if (!m_style_manager.is_active_font()) return false;
|
||||||
|
|
||||||
DataUpdate data{priv::create_emboss_data_base(m_text, m_style_manager, m_job_cancel), m_volume->id()};
|
DataUpdate data{create_emboss_data_base(m_text, m_style_manager, m_job_cancel), m_volume->id()};
|
||||||
|
|
||||||
std::unique_ptr<Job> job = nullptr;
|
std::unique_ptr<Job> job = nullptr;
|
||||||
|
|
||||||
@ -1516,7 +1575,7 @@ void GLGizmoEmboss::init_face_names(Facenames &face_names)
|
|||||||
void GLGizmoEmboss::init_font_name_texture() {
|
void GLGizmoEmboss::init_font_name_texture() {
|
||||||
Timer t("init_font_name_texture");
|
Timer t("init_font_name_texture");
|
||||||
// check if already exists
|
// check if already exists
|
||||||
GLuint &id = m_face_names.texture_id;
|
GLuint &id = m_face_names->texture_id;
|
||||||
if (id != 0) return;
|
if (id != 0) return;
|
||||||
// create texture for font
|
// create texture for font
|
||||||
GLenum target = GL_TEXTURE_2D;
|
GLenum target = GL_TEXTURE_2D;
|
||||||
@ -1525,7 +1584,7 @@ void GLGizmoEmboss::init_font_name_texture() {
|
|||||||
glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||||
glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||||
const Vec2i &size = m_gui_cfg->face_name_size;
|
const Vec2i &size = m_gui_cfg->face_name_size;
|
||||||
GLint w = size.x(), h = m_face_names.count_cached_textures * size.y();
|
GLint w = size.x(), h = m_face_names->count_cached_textures * size.y();
|
||||||
std::vector<unsigned char> data(4*w * h, {0});
|
std::vector<unsigned char> data(4*w * h, {0});
|
||||||
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
|
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
|
||||||
const GLint level = 0, internal_format = GL_RGBA, border = 0;
|
const GLint level = 0, internal_format = GL_RGBA, border = 0;
|
||||||
@ -1536,22 +1595,22 @@ void GLGizmoEmboss::init_font_name_texture() {
|
|||||||
glsafe(::glBindTexture(target, no_texture_id));
|
glsafe(::glBindTexture(target, no_texture_id));
|
||||||
|
|
||||||
// clear info about creation of texture - no one is initialized yet
|
// clear info about creation of texture - no one is initialized yet
|
||||||
for (FaceName &face : m_face_names.faces) {
|
for (FaceName &face : m_face_names->faces) {
|
||||||
face.cancel = nullptr;
|
face.cancel = nullptr;
|
||||||
face.is_created = nullptr;
|
face.is_created = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare filtration cache
|
// Prepare filtration cache
|
||||||
m_face_names.hide = std::vector<bool>(m_face_names.faces.size(), {false});
|
m_face_names->hide = std::vector<bool>(m_face_names->faces.size(), {false});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible)
|
void GLGizmoEmboss::draw_font_preview(FaceName &face, bool is_visible)
|
||||||
{
|
{
|
||||||
// Limit for opened font files at one moment
|
// Limit for opened font files at one moment
|
||||||
unsigned int &count_opened_fonts = m_face_names.count_opened_font_files;
|
unsigned int &count_opened_fonts = m_face_names->count_opened_font_files;
|
||||||
// Size of texture
|
// Size of texture
|
||||||
ImVec2 size(m_gui_cfg->face_name_size.x(), m_gui_cfg->face_name_size.y());
|
ImVec2 size(m_gui_cfg->face_name_size.x(), m_gui_cfg->face_name_size.y());
|
||||||
float count_cached_textures_f = static_cast<float>(m_face_names.count_cached_textures);
|
float count_cached_textures_f = static_cast<float>(m_face_names->count_cached_textures);
|
||||||
std::string state_text;
|
std::string state_text;
|
||||||
// uv0 and uv1 set to pixel 0,0 in texture
|
// uv0 and uv1 set to pixel 0,0 in texture
|
||||||
ImVec2 uv0(0.f, 0.f), uv1(1.f / size.x, 1.f / size.y / count_cached_textures_f);
|
ImVec2 uv0(0.f, 0.f), uv1(1.f / size.x, 1.f / size.y / count_cached_textures_f);
|
||||||
@ -1585,25 +1644,25 @@ void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible)
|
|||||||
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
|
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
|
||||||
const GLint level = 0;
|
const GLint level = 0;
|
||||||
// select next texture index
|
// select next texture index
|
||||||
size_t texture_index = (m_face_names.texture_index + 1) % m_face_names.count_cached_textures;
|
size_t texture_index = (m_face_names->texture_index + 1) % m_face_names->count_cached_textures;
|
||||||
|
|
||||||
// set previous cach as deleted
|
// set previous cach as deleted
|
||||||
for (FaceName &f : m_face_names.faces)
|
for (FaceName &f : m_face_names->faces)
|
||||||
if (f.texture_index == texture_index) {
|
if (f.texture_index == texture_index) {
|
||||||
if (f.cancel != nullptr) f.cancel->store(true);
|
if (f.cancel != nullptr) f.cancel->store(true);
|
||||||
f.is_created = nullptr;
|
f.is_created = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_face_names.texture_index = texture_index;
|
m_face_names->texture_index = texture_index;
|
||||||
face.texture_index = texture_index;
|
face.texture_index = texture_index;
|
||||||
|
|
||||||
// render text to texture
|
// render text to texture
|
||||||
FontImageData data{
|
FontImageData data{
|
||||||
m_text,
|
m_text,
|
||||||
face.wx_name,
|
face.wx_name,
|
||||||
m_face_names.encoding,
|
m_face_names->encoding,
|
||||||
m_face_names.texture_id,
|
m_face_names->texture_id,
|
||||||
m_face_names.texture_index,
|
m_face_names->texture_index,
|
||||||
m_gui_cfg->face_name_size,
|
m_gui_cfg->face_name_size,
|
||||||
gray_level,
|
gray_level,
|
||||||
format,
|
format,
|
||||||
@ -1623,11 +1682,11 @@ void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible)
|
|||||||
|
|
||||||
if (!state_text.empty()) {
|
if (!state_text.empty()) {
|
||||||
ImGui::SameLine(m_gui_cfg->face_name_texture_offset_x);
|
ImGui::SameLine(m_gui_cfg->face_name_texture_offset_x);
|
||||||
m_imgui->text(state_text);
|
ImGui::Text("%s", state_text.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine(m_gui_cfg->face_name_texture_offset_x);
|
ImGui::SameLine(m_gui_cfg->face_name_texture_offset_x);
|
||||||
ImTextureID tex_id = (void *) (intptr_t) m_face_names.texture_id;
|
ImTextureID tex_id = (void *) (intptr_t) m_face_names->texture_id;
|
||||||
ImGui::Image(tex_id, size, uv0, uv1);
|
ImGui::Image(tex_id, size, uv0, uv1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1635,7 +1694,7 @@ bool GLGizmoEmboss::select_facename(const wxString &facename)
|
|||||||
{
|
{
|
||||||
if (!wxFontEnumerator::IsValidFacename(facename)) return false;
|
if (!wxFontEnumerator::IsValidFacename(facename)) return false;
|
||||||
// Select font
|
// Select font
|
||||||
const wxFontEncoding &encoding = m_face_names.encoding;
|
const wxFontEncoding &encoding = m_face_names->encoding;
|
||||||
wxFont wx_font(wxFontInfo().FaceName(facename).Encoding(encoding));
|
wxFont wx_font(wxFontInfo().FaceName(facename).Encoding(encoding));
|
||||||
if (!wx_font.IsOk()) return false;
|
if (!wx_font.IsOk()) return false;
|
||||||
#ifdef USE_PIXEL_SIZE_IN_WX_FONT
|
#ifdef USE_PIXEL_SIZE_IN_WX_FONT
|
||||||
@ -1730,19 +1789,19 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
|
|
||||||
// Fix clearance of search input,
|
// Fix clearance of search input,
|
||||||
// Sometime happens that search text not disapear after font select
|
// Sometime happens that search text not disapear after font select
|
||||||
m_face_names.search.clear();
|
m_face_names->search.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::InputTextWithHint(input_id, selected, &m_face_names.search)) {
|
if (ImGui::InputTextWithHint(input_id, selected, &m_face_names->search)) {
|
||||||
// update filtration result
|
// update filtration result
|
||||||
m_face_names.hide = std::vector<bool>(m_face_names.faces.size(), {false});
|
m_face_names->hide = std::vector<bool>(m_face_names->faces.size(), {false});
|
||||||
|
|
||||||
// search to uppercase
|
// search to uppercase
|
||||||
std::string search = m_face_names.search; // copy
|
std::string search = m_face_names->search; // copy
|
||||||
std::transform(search.begin(), search.end(), search.begin(), ::toupper);
|
std::transform(search.begin(), search.end(), search.begin(), ::toupper);
|
||||||
|
|
||||||
for (FaceName &face : m_face_names.faces) {
|
for (FaceName &face : m_face_names->faces) {
|
||||||
size_t index = &face - &m_face_names.faces.front();
|
size_t index = &face - &m_face_names->faces.front();
|
||||||
|
|
||||||
// font name to uppercase
|
// font name to uppercase
|
||||||
std::string name(face.wx_name.ToUTF8().data());
|
std::string name(face.wx_name.ToUTF8().data());
|
||||||
@ -1750,7 +1809,7 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
|
|
||||||
// It should use C++ 20 feature https://en.cppreference.com/w/cpp/string/basic_string/starts_with
|
// It should use C++ 20 feature https://en.cppreference.com/w/cpp/string/basic_string/starts_with
|
||||||
bool start_with = boost::starts_with(name, search);
|
bool start_with = boost::starts_with(name, search);
|
||||||
m_face_names.hide[index] = !start_with;
|
m_face_names->hide[index] = !start_with;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!is_popup_open)
|
if (!is_popup_open)
|
||||||
@ -1769,23 +1828,23 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
if (ImGui::BeginPopup(popup_id, popup_flags))
|
if (ImGui::BeginPopup(popup_id, popup_flags))
|
||||||
{
|
{
|
||||||
bool set_selection_focus = false;
|
bool set_selection_focus = false;
|
||||||
if (!m_face_names.is_init) {
|
if (!m_face_names->is_init) {
|
||||||
init_face_names(m_face_names);
|
init_face_names(*m_face_names);
|
||||||
set_selection_focus = true;
|
set_selection_focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_face_names.has_truncated_names)
|
if (!m_face_names->has_truncated_names)
|
||||||
init_truncated_names(m_face_names, m_gui_cfg->face_name_max_width);
|
init_truncated_names(*m_face_names, m_gui_cfg->face_name_max_width);
|
||||||
|
|
||||||
if (m_face_names.texture_id == 0)
|
if (m_face_names->texture_id == 0)
|
||||||
init_font_name_texture();
|
init_font_name_texture();
|
||||||
|
|
||||||
for (FaceName &face : m_face_names.faces) {
|
for (FaceName &face : m_face_names->faces) {
|
||||||
const wxString &wx_face_name = face.wx_name;
|
const wxString &wx_face_name = face.wx_name;
|
||||||
size_t index = &face - &m_face_names.faces.front();
|
size_t index = &face - &m_face_names->faces.front();
|
||||||
|
|
||||||
// Filter for face names
|
// Filter for face names
|
||||||
if (m_face_names.hide[index])
|
if (m_face_names->hide[index])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ImGui::PushID(index);
|
ImGui::PushID(index);
|
||||||
@ -1815,33 +1874,33 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
} else if (m_face_names.is_init) {
|
} else if (m_face_names->is_init) {
|
||||||
// Just one after close combo box
|
// Just one after close combo box
|
||||||
// free texture and set id to zero
|
// free texture and set id to zero
|
||||||
m_face_names.is_init = false;
|
m_face_names->is_init = false;
|
||||||
m_face_names.hide.clear();
|
m_face_names->hide.clear();
|
||||||
// cancel all process for generation of texture
|
// cancel all process for generation of texture
|
||||||
for (FaceName &face : m_face_names.faces)
|
for (FaceName &face : m_face_names->faces)
|
||||||
if (face.cancel != nullptr)
|
if (face.cancel != nullptr)
|
||||||
face.cancel->store(true);
|
face.cancel->store(true);
|
||||||
glsafe(::glDeleteTextures(1, &m_face_names.texture_id));
|
glsafe(::glDeleteTextures(1, &m_face_names->texture_id));
|
||||||
m_face_names.texture_id = 0;
|
m_face_names->texture_id = 0;
|
||||||
|
|
||||||
// Remove value from search input
|
// Remove value from search input
|
||||||
ImGuiWrapper::left_inputs();
|
ImGuiWrapper::left_inputs();
|
||||||
m_face_names.search.clear();
|
m_face_names->search.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete unloadable face name when try to use
|
// delete unloadable face name when try to use
|
||||||
if (del_index.has_value()) {
|
if (del_index.has_value()) {
|
||||||
auto face = m_face_names.faces.begin() + (*del_index);
|
auto face = m_face_names->faces.begin() + (*del_index);
|
||||||
std::vector<wxString>& bad = m_face_names.bad;
|
std::vector<wxString>& bad = m_face_names->bad;
|
||||||
// sorted insert into bad fonts
|
// sorted insert into bad fonts
|
||||||
auto it = std::upper_bound(bad.begin(), bad.end(), face->wx_name);
|
auto it = std::upper_bound(bad.begin(), bad.end(), face->wx_name);
|
||||||
bad.insert(it, face->wx_name);
|
bad.insert(it, face->wx_name);
|
||||||
m_face_names.faces.erase(face);
|
m_face_names->faces.erase(face);
|
||||||
// update cached file
|
// update cached file
|
||||||
store(m_face_names);
|
store(*m_face_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ALLOW_ADD_FONT_BY_FILE
|
#ifdef ALLOW_ADD_FONT_BY_FILE
|
||||||
@ -1995,7 +2054,7 @@ void GLGizmoEmboss::draw_style_rename_button()
|
|||||||
bool can_rename = m_style_manager.exist_stored_style();
|
bool can_rename = m_style_manager.exist_stored_style();
|
||||||
std::string title = _u8L("Rename style");
|
std::string title = _u8L("Rename style");
|
||||||
const char * popup_id = title.c_str();
|
const char * popup_id = title.c_str();
|
||||||
if (priv::draw_button(m_icons, IconType::rename, !can_rename)) {
|
if (draw_button(m_icons, IconType::rename, !can_rename)) {
|
||||||
assert(m_style_manager.get_stored_style());
|
assert(m_style_manager.get_stored_style());
|
||||||
ImGui::OpenPopup(popup_id);
|
ImGui::OpenPopup(popup_id);
|
||||||
}
|
}
|
||||||
@ -2532,7 +2591,7 @@ bool GLGizmoEmboss::set_height() {
|
|||||||
float &value = m_style_manager.get_style().prop.size_in_mm;
|
float &value = m_style_manager.get_style().prop.size_in_mm;
|
||||||
|
|
||||||
// size can't be zero or negative
|
// size can't be zero or negative
|
||||||
apply(value, priv::limits.size_in_mm);
|
apply(value, limits.size_in_mm);
|
||||||
|
|
||||||
if (m_volume == nullptr || !m_volume->text_configuration.has_value()) {
|
if (m_volume == nullptr || !m_volume->text_configuration.has_value()) {
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -2573,7 +2632,7 @@ bool GLGizmoEmboss::set_depth()
|
|||||||
float &value = m_style_manager.get_style().prop.emboss;
|
float &value = m_style_manager.get_style().prop.emboss;
|
||||||
|
|
||||||
// size can't be zero or negative
|
// size can't be zero or negative
|
||||||
apply(value, priv::limits.emboss);
|
apply(value, limits.emboss);
|
||||||
|
|
||||||
// only different value need process
|
// only different value need process
|
||||||
return !is_approx(value, m_volume->text_configuration->style.prop.emboss);
|
return !is_approx(value, m_volume->text_configuration->style.prop.emboss);
|
||||||
@ -2725,7 +2784,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
min_char_gap, max_char_gap, units_fmt, _L("Distance 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
|
// Condition prevent recalculation when insertint out of limits value by imgui input
|
||||||
const std::optional<int> &volume_char_gap = m_volume->text_configuration->style.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) ||
|
if (!apply(current_prop.char_gap, limits.char_gap) ||
|
||||||
!volume_char_gap.has_value() || volume_char_gap != current_prop.char_gap) {
|
!volume_char_gap.has_value() || volume_char_gap != current_prop.char_gap) {
|
||||||
// char gap is stored inside of imgui font atlas
|
// char gap is stored inside of imgui font atlas
|
||||||
m_style_manager.clear_imgui_font();
|
m_style_manager.clear_imgui_font();
|
||||||
@ -2742,7 +2801,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
min_line_gap, max_line_gap, units_fmt, _L("Distance 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
|
// Condition prevent recalculation when insertint out of limits value by imgui input
|
||||||
const std::optional<int> &volume_line_gap = m_volume->text_configuration->style.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) ||
|
if (!apply(current_prop.line_gap, limits.line_gap) ||
|
||||||
!volume_line_gap.has_value() || volume_line_gap != current_prop.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
|
// line gap is planed to be stored inside of imgui font atlas
|
||||||
m_style_manager.clear_imgui_font();
|
m_style_manager.clear_imgui_font();
|
||||||
@ -2754,9 +2813,9 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
auto def_boldness = stored_style ?
|
auto def_boldness = stored_style ?
|
||||||
&stored_style->prop.boldness : nullptr;
|
&stored_style->prop.boldness : nullptr;
|
||||||
if (rev_slider(tr.boldness, current_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"))){
|
limits.boldness.gui.min, limits.boldness.gui.max, units_fmt, _L("Tiny / Wide glyphs"))){
|
||||||
const std::optional<float> &volume_boldness = m_volume->text_configuration->style.prop.boldness;
|
const std::optional<float> &volume_boldness = m_volume->text_configuration->style.prop.boldness;
|
||||||
if (!apply(current_prop.boldness, priv::limits.boldness.values) ||
|
if (!apply(current_prop.boldness, limits.boldness.values) ||
|
||||||
!volume_boldness.has_value() || volume_boldness != current_prop.boldness)
|
!volume_boldness.has_value() || volume_boldness != current_prop.boldness)
|
||||||
exist_change = true;
|
exist_change = true;
|
||||||
}
|
}
|
||||||
@ -2765,9 +2824,9 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
auto def_skew = stored_style ?
|
auto def_skew = stored_style ?
|
||||||
&stored_style->prop.skew : nullptr;
|
&stored_style->prop.skew : nullptr;
|
||||||
if (rev_slider(tr.skew_ration, current_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"))){
|
limits.skew.gui.min, limits.skew.gui.max, "%.2f", _L("Italic strength ratio"))){
|
||||||
const std::optional<float> &volume_skew = m_volume->text_configuration->style.prop.skew;
|
const std::optional<float> &volume_skew = m_volume->text_configuration->style.prop.skew;
|
||||||
if (!apply(current_prop.skew, priv::limits.skew.values) ||
|
if (!apply(current_prop.skew, limits.skew.values) ||
|
||||||
!volume_skew.has_value() ||volume_skew != current_prop.skew)
|
!volume_skew.has_value() ||volume_skew != current_prop.skew)
|
||||||
exist_change = true;
|
exist_change = true;
|
||||||
}
|
}
|
||||||
@ -2824,7 +2883,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
float* def_angle_deg = stored_style ?
|
float* def_angle_deg = stored_style ?
|
||||||
&def_angle_deg_val : nullptr;
|
&def_angle_deg_val : nullptr;
|
||||||
if (rev_slider(tr.rotation, angle_deg, def_angle_deg, _u8L("Undo rotation"),
|
if (rev_slider(tr.rotation, angle_deg, def_angle_deg, _u8L("Undo rotation"),
|
||||||
priv::limits.angle.min, priv::limits.angle.max, u8"%.2f °",
|
limits.angle.min, limits.angle.max, u8"%.2f °",
|
||||||
_L("Rotate text Clock-wise."))) {
|
_L("Rotate text Clock-wise."))) {
|
||||||
// convert back to radians and CCW
|
// convert back to radians and CCW
|
||||||
double angle_rad = -angle_deg * M_PI / 180.0;
|
double angle_rad = -angle_deg * M_PI / 180.0;
|
||||||
@ -3138,22 +3197,22 @@ void GLGizmoEmboss::init_icons()
|
|||||||
m_icons = m_icon_manager.init(filenames, size, type);
|
m_icons = m_icon_manager.init(filenames, size, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IconManager::Icon &priv::get_icon(const IconManager::VIcons& icons, IconType type, IconState state) { return *icons[(unsigned) type][(unsigned) state]; }
|
/////////////
|
||||||
bool priv::draw_button(const IconManager::VIcons &icons, IconType type, bool disable)
|
// private namespace implementation
|
||||||
{
|
///////////////
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const IconManager::Icon &get_icon(const IconManager::VIcons& icons, IconType type, IconState state) {
|
||||||
|
return *icons[(unsigned) type][(unsigned) state]; }
|
||||||
|
|
||||||
|
bool draw_button(const IconManager::VIcons &icons, IconType type, bool disable){
|
||||||
return Slic3r::GUI::button(
|
return Slic3r::GUI::button(
|
||||||
get_icon(icons, type, IconState::activable),
|
get_icon(icons, type, IconState::activable),
|
||||||
get_icon(icons, type, IconState::hovered),
|
get_icon(icons, type, IconState::hovered),
|
||||||
get_icon(icons, type, IconState::disabled),
|
get_icon(icons, type, IconState::disabled),
|
||||||
disable
|
disable);}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////
|
TextDataBase::TextDataBase(DataBase &&parent, const FontFileWithCache &font_file, TextConfiguration &&text_configuration)
|
||||||
// priv namespace implementation
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
priv::TextDataBase::TextDataBase(DataBase &&parent, const FontFileWithCache &font_file, TextConfiguration &&text_configuration)
|
|
||||||
: DataBase(std::move(parent)), font_file(font_file) /* copy */, text_configuration(std::move(text_configuration))
|
: DataBase(std::move(parent)), font_file(font_file) /* copy */, text_configuration(std::move(text_configuration))
|
||||||
{
|
{
|
||||||
assert(this->font_file.has_value());
|
assert(this->font_file.has_value());
|
||||||
@ -3168,7 +3227,7 @@ priv::TextDataBase::TextDataBase(DataBase &&parent, const FontFileWithCache &fon
|
|||||||
shape.scale = get_text_shape_scale(fp, ff);
|
shape.scale = get_text_shape_scale(fp, ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmbossShape &priv::TextDataBase::create_shape()
|
EmbossShape &TextDataBase::create_shape()
|
||||||
{
|
{
|
||||||
if (!shape.shapes.empty())
|
if (!shape.shapes.empty())
|
||||||
return shape;
|
return shape;
|
||||||
@ -3192,7 +3251,7 @@ EmbossShape &priv::TextDataBase::create_shape()
|
|||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv::TextDataBase::write(ModelVolume &volume) const
|
void TextDataBase::write(ModelVolume &volume) const
|
||||||
{
|
{
|
||||||
volume.text_configuration = text_configuration; // copy
|
volume.text_configuration = text_configuration; // copy
|
||||||
|
|
||||||
@ -3206,7 +3265,7 @@ void priv::TextDataBase::write(ModelVolume &volume) const
|
|||||||
DataBase::write(volume);
|
DataBase::write(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DataBase> priv::create_emboss_data_base(const std::string &text, StyleManager &style_manager, std::shared_ptr<std::atomic<bool>>& cancel)
|
std::unique_ptr<DataBase> create_emboss_data_base(const std::string &text, StyleManager &style_manager, std::shared_ptr<std::atomic<bool>>& cancel)
|
||||||
{
|
{
|
||||||
// create volume_name
|
// create volume_name
|
||||||
std::string volume_name = text; // copy
|
std::string volume_name = text; // copy
|
||||||
@ -3238,7 +3297,16 @@ std::unique_ptr<DataBase> priv::create_emboss_data_base(const std::string &text,
|
|||||||
return std::make_unique<TextDataBase>(std::move(base), font, std::move(tc));
|
return std::make_unique<TextDataBase>(std::move(base), font, std::move(tc));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 priv::calc_fine_position(const Selection &selection, const ImVec2 &windows_size, const Size &canvas_size)
|
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);
|
||||||
|
Plater *plater = wxGetApp().plater();
|
||||||
|
return CreateVolumeParams{canvas, plater->get_camera(), plater->build_volume(),
|
||||||
|
plater->get_ui_job_worker(), volume_type, raycaster, gizmo, gl_volume, style.distance, style.angle};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 calc_fine_position(const Selection &selection, const ImVec2 &windows_size, const Size &canvas_size)
|
||||||
{
|
{
|
||||||
const Selection::IndicesList indices = selection.get_volume_idxs();
|
const Selection::IndicesList indices = selection.get_volume_idxs();
|
||||||
// no selected volume
|
// no selected volume
|
||||||
@ -3257,5 +3325,7 @@ ImVec2 priv::calc_fine_position(const Selection &selection, const ImVec2 &window
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// any existing icon filename to not influence GUI
|
// any existing icon filename to not influence GUI
|
||||||
const std::string GLGizmoEmboss::M_ICON_FILENAME = "cut.svg";
|
const std::string GLGizmoEmboss::M_ICON_FILENAME = "cut.svg";
|
||||||
|
@ -222,58 +222,10 @@ private:
|
|||||||
// Keep information about stored styles and loaded actual style to compare with
|
// Keep information about stored styles and loaded actual style to compare with
|
||||||
Emboss::StyleManager m_style_manager;
|
Emboss::StyleManager m_style_manager;
|
||||||
|
|
||||||
struct FaceName{
|
// pImpl to hide implementation of FaceNames to .cpp file
|
||||||
wxString wx_name;
|
struct Facenames; // forward declaration
|
||||||
std::string name_truncated = "";
|
std::unique_ptr<Facenames> m_face_names;
|
||||||
size_t texture_index = 0;
|
|
||||||
// State for generation of texture
|
|
||||||
// when start generate create share pointers
|
|
||||||
std::shared_ptr<std::atomic<bool>> cancel = nullptr;
|
|
||||||
// R/W only on main thread - finalize of job
|
|
||||||
std::shared_ptr<bool> is_created = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep sorted list of loadable face names
|
|
||||||
struct Facenames
|
|
||||||
{
|
|
||||||
// flag to keep need of enumeration fonts from OS
|
|
||||||
// false .. wants new enumeration check by Hash
|
|
||||||
// true .. already enumerated(During opened combo box)
|
|
||||||
bool is_init = false;
|
|
||||||
|
|
||||||
bool has_truncated_names = false;
|
|
||||||
|
|
||||||
// data of can_load() faces
|
|
||||||
std::vector<FaceName> faces = {};
|
|
||||||
// Sorter set of Non valid face names in OS
|
|
||||||
std::vector<wxString> bad = {};
|
|
||||||
|
|
||||||
// Configuration of font encoding
|
|
||||||
static const wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM;
|
|
||||||
|
|
||||||
// Identify if preview texture exists
|
|
||||||
GLuint texture_id = 0;
|
|
||||||
|
|
||||||
// protection for open too much font files together
|
|
||||||
// Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Yaru/48x48/status/image-missing.png: Error opening file /usr/share/icons/Yaru/48x48/status/image-missing.png: Too many open files (g-io-error-quark, 31)
|
|
||||||
// This variable must exist until no CreateFontImageJob is running
|
|
||||||
unsigned int count_opened_font_files = 0;
|
|
||||||
|
|
||||||
// Configuration for texture height
|
|
||||||
const int count_cached_textures = 32;
|
|
||||||
|
|
||||||
// index for new generated texture index(must be lower than count_cached_textures)
|
|
||||||
size_t texture_index = 0;
|
|
||||||
|
|
||||||
// hash created from enumerated font from OS
|
|
||||||
// check when new font was installed
|
|
||||||
size_t hash = 0;
|
|
||||||
|
|
||||||
// filtration pattern
|
|
||||||
std::string search = "";
|
|
||||||
std::vector<bool> hide; // result of filtration
|
|
||||||
};
|
|
||||||
Facenames m_face_names;
|
|
||||||
static bool store(const Facenames &facenames);
|
static bool store(const Facenames &facenames);
|
||||||
static bool load(Facenames &facenames);
|
static bool load(Facenames &facenames);
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ void make_unique_name(const StyleManager::Styles &styles, std::string &name);
|
|||||||
|
|
||||||
void StyleManager::init(AppConfig *app_config)
|
void StyleManager::init(AppConfig *app_config)
|
||||||
{
|
{
|
||||||
|
assert(app_config != nullptr);
|
||||||
m_app_config = app_config;
|
m_app_config = app_config;
|
||||||
m_styles = ::load_styles(*app_config);
|
m_styles = ::load_styles(*app_config);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user