mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 23:46:24 -06:00
Various Emboss improvements from PS (#4039)
* Fix: invalid distance from surface when load from 3mf Cherry-picked from prusa3d/PrusaSlicer@e1d9393e51 Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> * Apply rotation angle given by style for new text object Turn off feature 'use_surface' for new text object Cherry-picked from prusa3d/PrusaSlicer@1cb156c815 Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> * Store/Load align and per_glyph in Slicer.ini for text style Cherry-picked from prusa3d/PrusaSlicer@fe16f5bdd1 Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> * Store undo/redo snap after stop input-sliding Cherry-picked from prusa3d/PrusaSlicer@fb4e4710e7 Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> * Initialize SvgFile object in optional different way. Cherry-picked from prusa3d/PrusaSlicer@0ff255eadc Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> * SPE-2103 Make snap-shot to undo/redo stack only on release slider Connected with attributes: Text/advanced(char gap, line gap, boldness, skew ratio) SVG(size) Also change range for Boldness. VRT font-Ascent. (different font may have different slider value range) Fix line gap (it was denied when per glyph was false) Cherry-picked from prusa3d/PrusaSlicer@ee3546b186 Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> --------- Co-authored-by: YFilip Sykala - NTB T15p <Filip.Sykala@Prusa3D.cz> Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
291cfe1d4a
commit
2d140f92ff
10 changed files with 217 additions and 72 deletions
|
@ -105,6 +105,7 @@ struct EmbossShape
|
||||||
// Note: image is only cache it is not neccessary to store
|
// Note: image is only cache it is not neccessary to store
|
||||||
|
|
||||||
// Store file data as plain string
|
// Store file data as plain string
|
||||||
|
// For Embossed text file_data are nullptr
|
||||||
ar(path, path_in_3mf, (file_data != nullptr) ? *file_data : std::string(""));
|
ar(path, path_in_3mf, (file_data != nullptr) ? *file_data : std::string(""));
|
||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar) {
|
template<class Archive> void load(Archive &ar) {
|
||||||
|
|
|
@ -81,6 +81,14 @@ using namespace Slic3r::GUI;
|
||||||
using namespace Slic3r::GUI::Emboss;
|
using namespace Slic3r::GUI::Emboss;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
// TRN - Title in Undo/Redo stack after rotate with text around emboss axe
|
||||||
|
const std::string rotation_snapshot_name = L("Text rotate");
|
||||||
|
// NOTE: Translation is made in "m_parent.do_rotate()"
|
||||||
|
|
||||||
|
// TRN - Title in Undo/Redo stack after move with text along emboss axe - From surface
|
||||||
|
const std::string move_snapshot_name = L("Text move");
|
||||||
|
// NOTE: Translation is made in "m_parent.do_translate()"
|
||||||
|
|
||||||
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;
|
||||||
|
@ -92,7 +100,7 @@ static const struct Limits
|
||||||
{
|
{
|
||||||
MinMax<double> emboss{0.01, 1e4}; // in mm
|
MinMax<double> emboss{0.01, 1e4}; // in mm
|
||||||
MinMax<float> size_in_mm{0.1f, 1000.f}; // in mm
|
MinMax<float> size_in_mm{0.1f, 1000.f}; // in mm
|
||||||
Limit<float> boldness{{-200.f, 200.f}, {-2e4f, 2e4f}}; // in font points
|
Limit<float> boldness{{-.5f, .5f}, {-5e5f, 5e5f}}; // in font points
|
||||||
Limit<float> skew{{-1.f, 1.f}, {-100.f, 100.f}}; // ration without unit
|
Limit<float> skew{{-1.f, 1.f}, {-100.f, 100.f}}; // ration without unit
|
||||||
MinMax<int> char_gap{-20000, 20000}; // in font points
|
MinMax<int> char_gap{-20000, 20000}; // in font points
|
||||||
MinMax<int> line_gap{-20000, 20000}; // in font points
|
MinMax<int> line_gap{-20000, 20000}; // in font points
|
||||||
|
@ -377,7 +385,7 @@ bool GLGizmoEmboss::re_emboss(const ModelVolume &text_volume, std::shared_ptr<st
|
||||||
TextLinesModel text_lines;
|
TextLinesModel text_lines;
|
||||||
const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection();
|
const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
DataBasePtr base = create_emboss_data_base(tc.text, style_manager, text_lines, selection, text_volume.type(), job_cancel);
|
DataBasePtr base = create_emboss_data_base(tc.text, style_manager, text_lines, selection, text_volume.type(), job_cancel);
|
||||||
DataUpdate data{std::move(base), text_volume.id()};
|
DataUpdate data{std::move(base), text_volume.id(), false};
|
||||||
|
|
||||||
RaycastManager raycast_manager; // Nothing is cached now, so It need to create raycasters
|
RaycastManager raycast_manager; // Nothing is cached now, so It need to create raycasters
|
||||||
return start_update_volume(std::move(data), text_volume, selection, raycast_manager);
|
return start_update_volume(std::move(data), text_volume, selection, raycast_manager);
|
||||||
|
@ -965,7 +973,7 @@ void GLGizmoEmboss::on_stop_dragging()
|
||||||
m_rotate_gizmo.set_angle(PI/2);
|
m_rotate_gizmo.set_angle(PI/2);
|
||||||
|
|
||||||
// apply rotation
|
// apply rotation
|
||||||
m_parent.do_rotate(L("Text-Rotate"));
|
m_parent.do_rotate(rotation_snapshot_name);
|
||||||
m_rotate_start_angle.reset();
|
m_rotate_start_angle.reset();
|
||||||
volume_transformation_changed();
|
volume_transformation_changed();
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1295,7 @@ namespace {
|
||||||
bool is_text_empty(std::string_view text) { return text.empty() || text.find_first_not_of(" \n\t\r") == std::string::npos; }
|
bool is_text_empty(std::string_view text) { return text.empty() || text.find_first_not_of(" \n\t\r") == std::string::npos; }
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool GLGizmoEmboss::process()
|
bool GLGizmoEmboss::process(bool make_snapshot)
|
||||||
{
|
{
|
||||||
// no volume is selected -> selection from right panel
|
// no volume is selected -> selection from right panel
|
||||||
assert(m_volume != nullptr);
|
assert(m_volume != nullptr);
|
||||||
|
@ -1301,7 +1309,7 @@ bool GLGizmoEmboss::process()
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
DataBasePtr base = create_emboss_data_base(m_text, m_style_manager, m_text_lines, selection, m_volume->type(), m_job_cancel);
|
DataBasePtr base = create_emboss_data_base(m_text, m_style_manager, m_text_lines, selection, m_volume->type(), m_job_cancel);
|
||||||
DataUpdate data{std::move(base), m_volume->id()};
|
DataUpdate data{std::move(base), m_volume->id(), make_snapshot};
|
||||||
|
|
||||||
// check valid count of text lines
|
// check valid count of text lines
|
||||||
assert(data.base->text_lines.empty() || data.base->text_lines.size() == get_count_lines(m_text));
|
assert(data.base->text_lines.empty() || data.base->text_lines.size() == get_count_lines(m_text));
|
||||||
|
@ -2129,7 +2137,9 @@ void fix_transformation(const StyleManager::Style &from, const StyleManager::Sty
|
||||||
// fix rotation
|
// fix rotation
|
||||||
float f_angle = f_angle_opt.value_or(.0f);
|
float f_angle = f_angle_opt.value_or(.0f);
|
||||||
float t_angle = t_angle_opt.value_or(.0f);
|
float t_angle = t_angle_opt.value_or(.0f);
|
||||||
do_local_z_rotate(canvas, t_angle - f_angle);
|
do_local_z_rotate(canvas.get_selection(), t_angle - f_angle);
|
||||||
|
std::string no_snapshot;
|
||||||
|
canvas.do_rotate(no_snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix distance (Z move) when exists difference in styles
|
// fix distance (Z move) when exists difference in styles
|
||||||
|
@ -2138,7 +2148,9 @@ void fix_transformation(const StyleManager::Style &from, const StyleManager::Sty
|
||||||
if (!is_approx(f_move_opt, t_move_opt)) {
|
if (!is_approx(f_move_opt, t_move_opt)) {
|
||||||
float f_move = f_move_opt.value_or(.0f);
|
float f_move = f_move_opt.value_or(.0f);
|
||||||
float t_move = t_move_opt.value_or(.0f);
|
float t_move = t_move_opt.value_or(.0f);
|
||||||
do_local_z_move(canvas, t_move - f_move);
|
do_local_z_move(canvas.get_selection(), t_move - f_move);
|
||||||
|
std::string no_snapshot;
|
||||||
|
canvas.do_move(no_snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namesapce
|
} // namesapce
|
||||||
|
@ -2408,6 +2420,10 @@ bool GLGizmoEmboss::revertible(const std::string &name,
|
||||||
ImGui::SameLine(undo_offset); // change cursor postion
|
ImGui::SameLine(undo_offset); // change cursor postion
|
||||||
if (draw_button(m_icons, IconType::undo)) {
|
if (draw_button(m_icons, IconType::undo)) {
|
||||||
value = *default_value;
|
value = *default_value;
|
||||||
|
|
||||||
|
// !! Fix to detect change of value after revert of float-slider
|
||||||
|
m_imgui->get_last_slider_status().deactivated_after_edit = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (ImGui::IsItemHovered())
|
} else if (ImGui::IsItemHovered())
|
||||||
m_imgui->tooltip(undo_tooltip, m_gui_cfg->max_tooltip_width);
|
m_imgui->tooltip(undo_tooltip, m_gui_cfg->max_tooltip_width);
|
||||||
|
@ -2645,7 +2661,6 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, ff_property);
|
m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, ff_property);
|
||||||
#endif // SHOW_FONT_FILE_PROPERTY
|
#endif // SHOW_FONT_FILE_PROPERTY
|
||||||
|
|
||||||
bool exist_change = false;
|
|
||||||
auto &tr = m_gui_cfg->translations;
|
auto &tr = m_gui_cfg->translations;
|
||||||
|
|
||||||
const StyleManager::Style *stored_style = nullptr;
|
const StyleManager::Style *stored_style = nullptr;
|
||||||
|
@ -2737,6 +2752,7 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
auto def_char_gap = stored_style ?
|
auto def_char_gap = stored_style ?
|
||||||
&stored_style->prop.char_gap : nullptr;
|
&stored_style->prop.char_gap : nullptr;
|
||||||
|
|
||||||
|
bool exist_change = false;
|
||||||
int half_ascent = font_info.ascent / 2;
|
int half_ascent = font_info.ascent / 2;
|
||||||
int min_char_gap = -half_ascent;
|
int min_char_gap = -half_ascent;
|
||||||
int max_char_gap = half_ascent;
|
int max_char_gap = half_ascent;
|
||||||
|
@ -2752,13 +2768,16 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
exist_change = true;
|
exist_change = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool last_change = false;
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit)
|
||||||
|
last_change = true;
|
||||||
|
|
||||||
// input gap between lines
|
// input gap between lines
|
||||||
bool is_multiline = m_text_lines.get_lines().size() > 1;
|
bool is_multiline = get_count_lines(m_volume->text_configuration->text) > 1; // TODO: cache count lines
|
||||||
m_imgui->disabled_begin(!is_multiline);
|
m_imgui->disabled_begin(!is_multiline);
|
||||||
auto def_line_gap = stored_style ?
|
auto def_line_gap = stored_style ?
|
||||||
&stored_style->prop.line_gap : nullptr;
|
&stored_style->prop.line_gap : nullptr;
|
||||||
int min_line_gap = -half_ascent;
|
int min_line_gap = -half_ascent;
|
||||||
int max_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"),
|
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"))){
|
min_line_gap, max_line_gap, units_fmt, _L("Distance between lines"))){
|
||||||
|
@ -2773,18 +2792,24 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
exist_change = true;
|
exist_change = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit)
|
||||||
|
last_change = true;
|
||||||
m_imgui->disabled_end(); // !is_multiline
|
m_imgui->disabled_end(); // !is_multiline
|
||||||
|
|
||||||
// input boldness
|
// input boldness
|
||||||
auto def_boldness = stored_style ?
|
auto def_boldness = stored_style ?
|
||||||
&stored_style->prop.boldness : nullptr;
|
&stored_style->prop.boldness : nullptr;
|
||||||
|
int min_boldness = static_cast<int>(font_info.ascent * limits.boldness.gui.min);
|
||||||
|
int max_boldness = static_cast<int>(font_info.ascent * limits.boldness.gui.max);
|
||||||
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"),
|
||||||
limits.boldness.gui.min, limits.boldness.gui.max, units_fmt, _L("Tiny / Wide glyphs"))){
|
min_boldness, max_boldness, 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, 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;
|
||||||
}
|
}
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit)
|
||||||
|
last_change = true;
|
||||||
|
|
||||||
// input italic
|
// input italic
|
||||||
auto def_skew = stored_style ?
|
auto def_skew = stored_style ?
|
||||||
|
@ -2796,6 +2821,8 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
!volume_skew.has_value() ||volume_skew != current_prop.skew)
|
!volume_skew.has_value() ||volume_skew != current_prop.skew)
|
||||||
exist_change = true;
|
exist_change = true;
|
||||||
}
|
}
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit)
|
||||||
|
last_change = true;
|
||||||
|
|
||||||
// input surface distance
|
// input surface distance
|
||||||
bool allowe_surface_distance = !use_surface && !m_volume->is_the_only_one_part();
|
bool allowe_surface_distance = !use_surface && !m_volume->is_the_only_one_part();
|
||||||
|
@ -2835,11 +2862,19 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
|
|
||||||
if (is_moved){
|
if (is_moved){
|
||||||
if (font_prop.per_glyph){
|
if (font_prop.per_glyph){
|
||||||
process();
|
process(false);
|
||||||
} else {
|
} else {
|
||||||
do_local_z_move(m_parent, distance.value_or(.0f) - prev_distance);
|
do_local_z_move(m_parent.get_selection(), distance.value_or(.0f) - prev_distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply move to model(backend)
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit) {
|
||||||
|
m_parent.do_move(move_snapshot_name);
|
||||||
|
if (font_prop.per_glyph)
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
|
||||||
m_imgui->disabled_end(); // allowe_surface_distance
|
m_imgui->disabled_end(); // allowe_surface_distance
|
||||||
|
|
||||||
// slider for Clock-wise angle in degress
|
// slider for Clock-wise angle in degress
|
||||||
|
@ -2861,7 +2896,7 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
Geometry::to_range_pi_pi(angle_rad);
|
Geometry::to_range_pi_pi(angle_rad);
|
||||||
|
|
||||||
double diff_angle = angle_rad - angle;
|
double diff_angle = angle_rad - angle;
|
||||||
do_local_z_rotate(m_parent, diff_angle);
|
do_local_z_rotate(m_parent.get_selection(), diff_angle);
|
||||||
|
|
||||||
// calc angle after rotation
|
// calc angle after rotation
|
||||||
const Selection &selection = m_parent.get_selection();
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
@ -2876,6 +2911,15 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
|
|
||||||
// recalculate for surface cut
|
// recalculate for surface cut
|
||||||
if (use_surface || font_prop.per_glyph)
|
if (use_surface || font_prop.per_glyph)
|
||||||
|
process(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply rotation on model (backend)
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit) {
|
||||||
|
m_parent.do_rotate(rotation_snapshot_name);
|
||||||
|
|
||||||
|
// recalculate for surface cut
|
||||||
|
if (use_surface || font_prop.per_glyph)
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2912,6 +2956,7 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
if (i == 0) current_prop.collection_number.reset();
|
if (i == 0) current_prop.collection_number.reset();
|
||||||
else current_prop.collection_number = i;
|
else current_prop.collection_number = i;
|
||||||
exist_change = true;
|
exist_change = true;
|
||||||
|
last_change = true;
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
@ -2924,13 +2969,13 @@ void GLGizmoEmboss::draw_advanced()
|
||||||
m_imgui->tooltip(tooltip, m_gui_cfg->max_tooltip_width);
|
m_imgui->tooltip(tooltip, m_gui_cfg->max_tooltip_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exist_change) {
|
if (exist_change || last_change) {
|
||||||
m_style_manager.clear_glyphs_cache();
|
m_style_manager.clear_glyphs_cache();
|
||||||
if (m_style_manager.get_font_prop().per_glyph)
|
if (font_prop.per_glyph)
|
||||||
reinit_text_lines();
|
reinit_text_lines();
|
||||||
else
|
else
|
||||||
m_text_lines.reset();
|
m_text_lines.reset();
|
||||||
process();
|
process(last_change);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button(_u8L("Set text to face camera").c_str())) {
|
if (ImGui::Button(_u8L("Set text to face camera").c_str())) {
|
||||||
|
|
|
@ -114,7 +114,7 @@ private:
|
||||||
void reset_volume();
|
void reset_volume();
|
||||||
|
|
||||||
// create volume from text - main functionality
|
// create volume from text - main functionality
|
||||||
bool process();
|
bool process(bool make_snapshot = true);
|
||||||
void close();
|
void close();
|
||||||
void draw_window();
|
void draw_window();
|
||||||
void draw_text_input();
|
void draw_text_input();
|
||||||
|
|
|
@ -55,6 +55,14 @@ GLGizmoSVG::GLGizmoSVG(GLCanvas3D &parent)
|
||||||
// Private functions to create emboss volume
|
// Private functions to create emboss volume
|
||||||
namespace{
|
namespace{
|
||||||
|
|
||||||
|
// TRN - Title in Undo/Redo stack after rotate with SVG around emboss axe
|
||||||
|
const std::string rotation_snapshot_name = L("SVG rotate");
|
||||||
|
// NOTE: Translation is made in "m_parent.do_rotate()"
|
||||||
|
|
||||||
|
// TRN - Title in Undo/Redo stack after move with SVG along emboss axe - From surface
|
||||||
|
const std::string move_snapshot_name = L("SVG move");
|
||||||
|
// NOTE: Translation is made in "m_parent.do_translate()"
|
||||||
|
|
||||||
// Variable keep limits for variables
|
// Variable keep limits for variables
|
||||||
const struct Limits
|
const struct Limits
|
||||||
{
|
{
|
||||||
|
@ -537,7 +545,7 @@ void GLGizmoSVG::on_stop_dragging()
|
||||||
|
|
||||||
// apply rotation
|
// apply rotation
|
||||||
// TRN This is an item label in the undo-redo stack.
|
// TRN This is an item label in the undo-redo stack.
|
||||||
m_parent.do_rotate(L("SVG-Rotate"));
|
m_parent.do_rotate(rotation_snapshot_name);
|
||||||
m_rotate_start_angle.reset();
|
m_rotate_start_angle.reset();
|
||||||
volume_transformation_changed();
|
volume_transformation_changed();
|
||||||
|
|
||||||
|
@ -1264,8 +1272,7 @@ void GLGizmoSVG::calculate_scale() {
|
||||||
float GLGizmoSVG::get_scale_for_tolerance(){
|
float GLGizmoSVG::get_scale_for_tolerance(){
|
||||||
return std::max(m_scale_width.value_or(1.f), m_scale_height.value_or(1.f)); }
|
return std::max(m_scale_width.value_or(1.f), m_scale_height.value_or(1.f)); }
|
||||||
|
|
||||||
bool GLGizmoSVG::process()
|
bool GLGizmoSVG::process(bool make_snapshot) {
|
||||||
{
|
|
||||||
// no volume is selected -> selection from right panel
|
// no volume is selected -> selection from right panel
|
||||||
assert(m_volume != nullptr);
|
assert(m_volume != nullptr);
|
||||||
if (m_volume == nullptr)
|
if (m_volume == nullptr)
|
||||||
|
@ -1286,7 +1293,7 @@ bool GLGizmoSVG::process()
|
||||||
EmbossShape shape = m_volume_shape; // copy
|
EmbossShape shape = m_volume_shape; // copy
|
||||||
auto base = std::make_unique<DataBase>(m_volume->name, m_job_cancel, std::move(shape));
|
auto base = std::make_unique<DataBase>(m_volume->name, m_job_cancel, std::move(shape));
|
||||||
base->is_outside = m_volume->type() == ModelVolumeType::MODEL_PART;
|
base->is_outside = m_volume->type() == ModelVolumeType::MODEL_PART;
|
||||||
DataUpdate data{std::move(base), m_volume_id};
|
DataUpdate data{std::move(base), m_volume_id, make_snapshot};
|
||||||
return start_update_volume(std::move(data), *m_volume, m_parent.get_selection(), m_raycast_manager);
|
return start_update_volume(std::move(data), *m_volume, m_parent.get_selection(), m_raycast_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1492,8 +1499,9 @@ void GLGizmoSVG::draw_filename(){
|
||||||
std::string new_path = choose_svg_file();
|
std::string new_path = choose_svg_file();
|
||||||
if (!new_path.empty()) {
|
if (!new_path.empty()) {
|
||||||
file_changed = true;
|
file_changed = true;
|
||||||
m_volume_shape.svg_file = {}; // clear data
|
EmbossShape::SvgFile svg_file_new;
|
||||||
m_volume_shape.svg_file->path = new_path;
|
svg_file_new.path = new_path;
|
||||||
|
m_volume_shape.svg_file = svg_file_new; // clear data
|
||||||
}
|
}
|
||||||
} else if (ImGui::IsItemHovered()) {
|
} else if (ImGui::IsItemHovered()) {
|
||||||
tooltip = _u8L("Change to another .svg file");
|
tooltip = _u8L("Change to another .svg file");
|
||||||
|
@ -1689,6 +1697,8 @@ void GLGizmoSVG::draw_size()
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<Vec3d> new_relative_scale;
|
std::optional<Vec3d> new_relative_scale;
|
||||||
|
bool make_snap = false;
|
||||||
|
|
||||||
if (m_keep_ratio) {
|
if (m_keep_ratio) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::setprecision(2) << std::fixed << width << " x " << height << " " << (use_inch ? "in" : "mm");
|
ss << std::setprecision(2) << std::fixed << width << " x " << height << " " << (use_inch ? "in" : "mm");
|
||||||
|
@ -1707,6 +1717,8 @@ void GLGizmoSVG::draw_size()
|
||||||
new_relative_scale = Vec3d(width_ratio, width_ratio, 1.);
|
new_relative_scale = Vec3d(width_ratio, width_ratio, 1.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m_imgui->get_last_slider_status().deactivated_after_edit)
|
||||||
|
make_snap = true; // only last change of slider make snap
|
||||||
} else {
|
} else {
|
||||||
ImGuiInputTextFlags flags = 0;
|
ImGuiInputTextFlags flags = 0;
|
||||||
|
|
||||||
|
@ -1726,6 +1738,7 @@ void GLGizmoSVG::draw_size()
|
||||||
if (is_valid_scale_ratio(width_ratio)) {
|
if (is_valid_scale_ratio(width_ratio)) {
|
||||||
m_scale_width = m_scale_width.value_or(1.f) * width_ratio;
|
m_scale_width = m_scale_width.value_or(1.f) * width_ratio;
|
||||||
new_relative_scale = Vec3d(width_ratio, 1., 1.);
|
new_relative_scale = Vec3d(width_ratio, 1., 1.);
|
||||||
|
make_snap = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
|
@ -1739,6 +1752,7 @@ void GLGizmoSVG::draw_size()
|
||||||
if (is_valid_scale_ratio(height_ratio)) {
|
if (is_valid_scale_ratio(height_ratio)) {
|
||||||
m_scale_height = m_scale_height.value_or(1.f) * height_ratio;
|
m_scale_height = m_scale_height.value_or(1.f) * height_ratio;
|
||||||
new_relative_scale = Vec3d(1., height_ratio, 1.);
|
new_relative_scale = Vec3d(1., height_ratio, 1.);
|
||||||
|
make_snap = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
|
@ -1760,6 +1774,7 @@ void GLGizmoSVG::draw_size()
|
||||||
if (can_reset) {
|
if (can_reset) {
|
||||||
if (reset_button(m_icons)) {
|
if (reset_button(m_icons)) {
|
||||||
new_relative_scale = Vec3d(1./m_scale_width.value_or(1.f), 1./m_scale_height.value_or(1.f), 1.);
|
new_relative_scale = Vec3d(1./m_scale_width.value_or(1.f), 1./m_scale_height.value_or(1.f), 1.);
|
||||||
|
make_snap = true;
|
||||||
} else if (ImGui::IsItemHovered())
|
} else if (ImGui::IsItemHovered())
|
||||||
m_imgui->tooltip(_u8L("Reset scale"), m_gui_cfg->max_tooltip_width);
|
m_imgui->tooltip(_u8L("Reset scale"), m_gui_cfg->max_tooltip_width);
|
||||||
}
|
}
|
||||||
|
@ -1773,20 +1788,25 @@ void GLGizmoSVG::draw_size()
|
||||||
};
|
};
|
||||||
selection_transform(selection, selection_scale_fnc);
|
selection_transform(selection, selection_scale_fnc);
|
||||||
|
|
||||||
m_parent.do_scale(L("Resize"));
|
std::string snap_name; // Empty mean do not store on undo/redo stack
|
||||||
|
m_parent.do_scale(snap_name);
|
||||||
wxGetApp().obj_manipul()->set_dirty();
|
wxGetApp().obj_manipul()->set_dirty();
|
||||||
// should be the almost same
|
// should be the almost same
|
||||||
calculate_scale();
|
calculate_scale();
|
||||||
|
|
||||||
NSVGimage *img = m_volume_shape.svg_file->image.get();
|
const NSVGimage *img = m_volume_shape.svg_file->image.get();
|
||||||
assert(img != NULL);
|
assert(img != NULL);
|
||||||
if (img != NULL){
|
if (img != NULL){
|
||||||
NSVGLineParams params{get_tesselation_tolerance(get_scale_for_tolerance())};
|
NSVGLineParams params{get_tesselation_tolerance(get_scale_for_tolerance())};
|
||||||
m_volume_shape.shapes_with_ids = create_shape_with_ids(*img, params);
|
m_volume_shape.shapes_with_ids = create_shape_with_ids(*img, params);
|
||||||
m_volume_shape.final_shape = {}; // reset cache for final shape
|
m_volume_shape.final_shape = {}; // reset cache for final shape
|
||||||
process();
|
if (!make_snap) // Be carefull: Last change may be without change of scale
|
||||||
|
process(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (make_snap)
|
||||||
|
process(); // make undo/redo snap-shot
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSVG::draw_use_surface()
|
void GLGizmoSVG::draw_use_surface()
|
||||||
|
@ -1842,18 +1862,20 @@ void GLGizmoSVG::draw_distance()
|
||||||
if (m_imgui->slider_optional_float("##distance", m_distance, min_distance, max_distance, "%.2f mm", 1.f, false, move_tooltip))
|
if (m_imgui->slider_optional_float("##distance", m_distance, min_distance, max_distance, "%.2f mm", 1.f, false, move_tooltip))
|
||||||
is_moved = true;
|
is_moved = true;
|
||||||
}
|
}
|
||||||
|
bool is_stop_sliding = m_imgui->get_last_slider_status().deactivated_after_edit;
|
||||||
bool can_reset = m_distance.has_value();
|
bool is_reseted = false;
|
||||||
if (can_reset) {
|
if (m_distance.has_value()) {
|
||||||
if (reset_button(m_icons)) {
|
if (reset_button(m_icons)) {
|
||||||
m_distance.reset();
|
m_distance.reset();
|
||||||
is_moved = true;
|
is_reseted = true;
|
||||||
} else if (ImGui::IsItemHovered())
|
} else if (ImGui::IsItemHovered())
|
||||||
m_imgui->tooltip(_u8L("Reset distance"), m_gui_cfg->max_tooltip_width);
|
m_imgui->tooltip(_u8L("Reset distance"), m_gui_cfg->max_tooltip_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_moved)
|
if (is_moved || is_reseted)
|
||||||
do_local_z_move(m_parent, m_distance.value_or(.0f) - prev_distance);
|
do_local_z_move(m_parent.get_selection(), m_distance.value_or(.0f) - prev_distance);
|
||||||
|
if (is_stop_sliding || is_reseted)
|
||||||
|
m_parent.do_move(move_snapshot_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSVG::draw_rotation()
|
void GLGizmoSVG::draw_rotation()
|
||||||
|
@ -1876,7 +1898,7 @@ void GLGizmoSVG::draw_rotation()
|
||||||
|
|
||||||
double diff_angle = angle_rad - angle;
|
double diff_angle = angle_rad - angle;
|
||||||
|
|
||||||
do_local_z_rotate(m_parent, diff_angle);
|
do_local_z_rotate(m_parent.get_selection(), diff_angle);
|
||||||
|
|
||||||
// calc angle after rotation
|
// calc angle after rotation
|
||||||
m_angle = calc_angle(m_parent.get_selection());
|
m_angle = calc_angle(m_parent.get_selection());
|
||||||
|
@ -1885,20 +1907,28 @@ void GLGizmoSVG::draw_rotation()
|
||||||
if (m_volume->emboss_shape->projection.use_surface)
|
if (m_volume->emboss_shape->projection.use_surface)
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
|
bool is_stop_sliding = m_imgui->get_last_slider_status().deactivated_after_edit;
|
||||||
|
|
||||||
// Reset button
|
// Reset button
|
||||||
|
bool is_reseted = false;
|
||||||
if (m_angle.has_value()) {
|
if (m_angle.has_value()) {
|
||||||
if (reset_button(m_icons)) {
|
if (reset_button(m_icons)) {
|
||||||
do_local_z_rotate(m_parent, -(*m_angle));
|
do_local_z_rotate(m_parent.get_selection(), -(*m_angle));
|
||||||
m_angle.reset();
|
m_angle.reset();
|
||||||
|
|
||||||
// recalculate for surface cut
|
// recalculate for surface cut
|
||||||
if (m_volume->emboss_shape->projection.use_surface)
|
if (m_volume->emboss_shape->projection.use_surface)
|
||||||
process();
|
process();
|
||||||
|
|
||||||
|
is_reseted = true;
|
||||||
} else if (ImGui::IsItemHovered())
|
} else if (ImGui::IsItemHovered())
|
||||||
m_imgui->tooltip(_u8L("Reset rotation"), m_gui_cfg->max_tooltip_width);
|
m_imgui->tooltip(_u8L("Reset rotation"), m_gui_cfg->max_tooltip_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply rotation on model (backend)
|
||||||
|
if (is_stop_sliding || is_reseted)
|
||||||
|
m_parent.do_rotate(rotation_snapshot_name);
|
||||||
|
|
||||||
// Keep up - lock button icon
|
// Keep up - lock button icon
|
||||||
if (!m_volume->is_the_only_one_part()) {
|
if (!m_volume->is_the_only_one_part()) {
|
||||||
ImGui::SameLine(m_gui_cfg->lock_offset);
|
ImGui::SameLine(m_gui_cfg->lock_offset);
|
||||||
|
|
|
@ -112,7 +112,7 @@ private:
|
||||||
void reset_volume();
|
void reset_volume();
|
||||||
|
|
||||||
// create volume from text - main functionality
|
// create volume from text - main functionality
|
||||||
bool process();
|
bool process(bool make_snapshot = true);
|
||||||
void close();
|
void close();
|
||||||
void draw_window();
|
void draw_window();
|
||||||
void draw_preview();
|
void draw_preview();
|
||||||
|
|
|
@ -102,6 +102,9 @@ struct DataCreateObject
|
||||||
|
|
||||||
// Define which gizmo open on the success
|
// Define which gizmo open on the success
|
||||||
GLGizmosManager::EType gizmo;
|
GLGizmosManager::EType gizmo;
|
||||||
|
|
||||||
|
// additionl rotation around Z axe, given by style settings
|
||||||
|
std::optional<float> angle = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -330,6 +333,12 @@ void CreateObjectJob::process(Ctl &ctl)
|
||||||
offset -= m_result.center();
|
offset -= m_result.center();
|
||||||
Transform3d::TranslationType tt(offset.x(), offset.y(), offset.z());
|
Transform3d::TranslationType tt(offset.x(), offset.y(), offset.z());
|
||||||
m_transformation = Transform3d(tt);
|
m_transformation = Transform3d(tt);
|
||||||
|
|
||||||
|
// rotate around Z by style settings
|
||||||
|
if (m_input.angle.has_value()) {
|
||||||
|
std::optional<float> distance; // new object ignore surface distance from style settings
|
||||||
|
apply_transformation(m_input.angle, distance, m_transformation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
|
void CreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
|
@ -1023,10 +1032,13 @@ void update_volume(TriangleMesh &&mesh, const DataUpdate &data, const Transform3
|
||||||
assert(plater->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Emboss ||
|
assert(plater->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Emboss ||
|
||||||
plater->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Svg);
|
plater->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Svg);
|
||||||
|
|
||||||
// TRN: This is the name of the action appearing in undo/redo stack.
|
if (data.make_snapshot) {
|
||||||
std::string snap_name = _u8L("Text/SVG attribute change");
|
// TRN: This is the title of the action appearing in undo/redo stack.
|
||||||
Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
|
// It is same for Text and SVG.
|
||||||
|
std::string snap_name = _u8L("Emboss attribute change");
|
||||||
|
Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
|
||||||
|
}
|
||||||
|
|
||||||
ModelVolume *volume = get_model_volume(data.volume_id, plater->model().objects);
|
ModelVolume *volume = get_model_volume(data.volume_id, plater->model().objects);
|
||||||
|
|
||||||
// could appear when user delete edited volume
|
// could appear when user delete edited volume
|
||||||
|
@ -1486,8 +1498,14 @@ bool start_create_object_job(const CreateVolumeParams &input, DataBasePtr emboss
|
||||||
{
|
{
|
||||||
const Pointfs &bed_shape = input.build_volume.printable_area();
|
const Pointfs &bed_shape = input.build_volume.printable_area();
|
||||||
auto gizmo_type = static_cast<GLGizmosManager::EType>(input.gizmo);
|
auto gizmo_type = static_cast<GLGizmosManager::EType>(input.gizmo);
|
||||||
DataCreateObject data{std::move(emboss_data), coor, input.camera, bed_shape, gizmo_type};
|
DataCreateObject data{std::move(emboss_data), coor, input.camera, bed_shape, gizmo_type, input.angle};
|
||||||
auto job = std::make_unique<CreateObjectJob>(std::move(data));
|
|
||||||
|
// Fix: adding text on print bed with style containing use_surface
|
||||||
|
if (data.base->shape.projection.use_surface)
|
||||||
|
// Til the print bed is flat using surface for Object is useless
|
||||||
|
data.base->shape.projection.use_surface = false;
|
||||||
|
|
||||||
|
auto job = std::make_unique<CreateObjectJob>(std::move(data));
|
||||||
return queue_job(input.worker, std::move(job));
|
return queue_job(input.worker, std::move(job));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,9 @@ struct DataUpdate
|
||||||
|
|
||||||
// unique identifier of volume to change
|
// unique identifier of volume to change
|
||||||
ObjectID volume_id;
|
ObjectID volume_id;
|
||||||
|
|
||||||
|
// Used for prevent flooding Undo/Redo stack on slider.
|
||||||
|
bool make_snapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -198,15 +198,20 @@ std::optional<float> calc_distance(const GLVolume &gl_volume, RaycastManager &ra
|
||||||
if (volume->is_the_only_one_part())
|
if (volume->is_the_only_one_part())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
if (!volume->emboss_shape.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
RaycastManager::AllowVolumes condition = create_condition(object->volumes, volume->id());
|
RaycastManager::AllowVolumes condition = create_condition(object->volumes, volume->id());
|
||||||
RaycastManager::Meshes meshes = create_meshes(canvas, condition);
|
RaycastManager::Meshes meshes = create_meshes(canvas, condition);
|
||||||
raycaster.actualize(*instance, &condition, &meshes);
|
raycaster.actualize(*instance, &condition, &meshes);
|
||||||
return calc_distance(gl_volume, raycaster, &condition);
|
return calc_distance(gl_volume, raycaster, &condition, volume->emboss_shape->fix_3mf_tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<float> calc_distance(const GLVolume &gl_volume, const RaycastManager &raycaster, const RaycastManager::ISkip *condition)
|
std::optional<float> calc_distance(const GLVolume &gl_volume, const RaycastManager &raycaster,
|
||||||
{
|
const RaycastManager::ISkip *condition, const std::optional<Slic3r::Transform3d>& fix) {
|
||||||
Transform3d w = gl_volume.world_matrix();
|
Transform3d w = gl_volume.world_matrix();
|
||||||
|
if (fix.has_value())
|
||||||
|
w = w * fix->inverse();
|
||||||
Vec3d p = w.translation();
|
Vec3d p = w.translation();
|
||||||
Vec3d dir = -get_z_base(w);
|
Vec3d dir = -get_z_base(w);
|
||||||
auto hit_opt = raycaster.closest_hit(p, dir, condition);
|
auto hit_opt = raycaster.closest_hit(p, dir, condition);
|
||||||
|
@ -322,11 +327,11 @@ bool face_selected_volume_to_camera(const Camera &camera, GLCanvas3D &canvas, co
|
||||||
return false;
|
return false;
|
||||||
ModelObject &object = *object_ptr;
|
ModelObject &object = *object_ptr;
|
||||||
|
|
||||||
ModelInstance *instance_ptr = get_model_instance(gl_volume, object);
|
const ModelInstance *instance_ptr = get_model_instance(gl_volume, object);
|
||||||
assert(instance_ptr != nullptr);
|
assert(instance_ptr != nullptr);
|
||||||
if (instance_ptr == nullptr)
|
if (instance_ptr == nullptr)
|
||||||
return false;
|
return false;
|
||||||
ModelInstance &instance = *instance_ptr;
|
const ModelInstance &instance = *instance_ptr;
|
||||||
|
|
||||||
ModelVolume *volume_ptr = get_model_volume(gl_volume, object);
|
ModelVolume *volume_ptr = get_model_volume(gl_volume, object);
|
||||||
assert(volume_ptr != nullptr);
|
assert(volume_ptr != nullptr);
|
||||||
|
@ -385,10 +390,7 @@ bool face_selected_volume_to_camera(const Camera &camera, GLCanvas3D &canvas, co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_local_z_rotate(GLCanvas3D &canvas, double relative_angle)
|
void do_local_z_rotate(Selection &selection, double relative_angle) {
|
||||||
{
|
|
||||||
Selection &selection = canvas.get_selection();
|
|
||||||
|
|
||||||
assert(!selection.is_empty());
|
assert(!selection.is_empty());
|
||||||
if(selection.is_empty()) return;
|
if(selection.is_empty()) return;
|
||||||
|
|
||||||
|
@ -418,17 +420,9 @@ void do_local_z_rotate(GLCanvas3D &canvas, double relative_angle)
|
||||||
selection.rotate(Vec3d(0., 0., relative_angle), get_drag_transformation_type(selection));
|
selection.rotate(Vec3d(0., 0., relative_angle), get_drag_transformation_type(selection));
|
||||||
};
|
};
|
||||||
selection_transform(selection, selection_rotate_fnc);
|
selection_transform(selection, selection_rotate_fnc);
|
||||||
|
|
||||||
std::string snapshot_name; // empty meand no store undo / redo
|
|
||||||
// NOTE: it use L instead of _L macro because prefix _ is appended
|
|
||||||
// inside function do_move
|
|
||||||
// snapshot_name = L("Set text rotation");
|
|
||||||
canvas.do_rotate(snapshot_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_local_z_move(GLCanvas3D &canvas, double relative_move) {
|
void do_local_z_move(Selection &selection, double relative_move) {
|
||||||
|
|
||||||
Selection &selection = canvas.get_selection();
|
|
||||||
assert(!selection.is_empty());
|
assert(!selection.is_empty());
|
||||||
if (selection.is_empty()) return;
|
if (selection.is_empty()) return;
|
||||||
|
|
||||||
|
@ -438,12 +432,6 @@ void do_local_z_move(GLCanvas3D &canvas, double relative_move) {
|
||||||
selection.translate(translate, TransformationType::Local);
|
selection.translate(translate, TransformationType::Local);
|
||||||
};
|
};
|
||||||
selection_transform(selection, selection_translate_fnc);
|
selection_transform(selection, selection_translate_fnc);
|
||||||
|
|
||||||
std::string snapshot_name; // empty mean no store undo / redo
|
|
||||||
// NOTE: it use L instead of _L macro because prefix _ is appended inside
|
|
||||||
// function do_move
|
|
||||||
// snapshot_name = L("Set surface distance");
|
|
||||||
canvas.do_move(snapshot_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformationType get_drag_transformation_type(const Selection &selection)
|
TransformationType get_drag_transformation_type(const Selection &selection)
|
||||||
|
@ -589,7 +577,7 @@ bool start_dragging(const Vec2d &mouse_pos,
|
||||||
|
|
||||||
std::optional<float> start_distance;
|
std::optional<float> start_distance;
|
||||||
if (!volume->emboss_shape->projection.use_surface)
|
if (!volume->emboss_shape->projection.use_surface)
|
||||||
start_distance = calc_distance(gl_volume, raycast_manager, &condition);
|
start_distance = calc_distance(gl_volume, raycast_manager, &condition, volume->emboss_shape->fix_3mf_tr);
|
||||||
surface_drag = SurfaceDrag{mouse_offset, world_tr, instance_tr_inv,
|
surface_drag = SurfaceDrag{mouse_offset, world_tr, instance_tr_inv,
|
||||||
gl_volume_ptr, condition, start_angle,
|
gl_volume_ptr, condition, start_angle,
|
||||||
start_distance, true, mouse_offset_without_sla_shift};
|
start_distance, true, mouse_offset_without_sla_shift};
|
||||||
|
|
|
@ -89,7 +89,8 @@ std::optional<Vec3d> calc_surface_offset(const Selection &selection, RaycastMana
|
||||||
/// <param name="canvas">Contain model</param>
|
/// <param name="canvas">Contain model</param>
|
||||||
/// <returns>Calculated distance from surface</returns>
|
/// <returns>Calculated distance from surface</returns>
|
||||||
std::optional<float> calc_distance(const GLVolume &gl_volume, RaycastManager &raycaster, GLCanvas3D &canvas);
|
std::optional<float> calc_distance(const GLVolume &gl_volume, RaycastManager &raycaster, GLCanvas3D &canvas);
|
||||||
std::optional<float> calc_distance(const GLVolume &gl_volume, const RaycastManager &raycaster, const RaycastManager::ISkip *condition);
|
std::optional<float> calc_distance(const GLVolume &gl_volume, const RaycastManager &raycaster,
|
||||||
|
const RaycastManager::ISkip *condition, const std::optional<Slic3r::Transform3d>& fix);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculate up vector angle
|
/// Calculate up vector angle
|
||||||
|
@ -136,16 +137,16 @@ bool face_selected_volume_to_camera(const Camera &camera, GLCanvas3D &canvas, co
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotation around z Axis(emboss direction)
|
/// Rotation around z Axis(emboss direction)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="canvas">Selected volume for rotation</param>
|
/// <param name="selection">Selected volume for rotation</param>
|
||||||
/// <param name="relative_angle">Relative angle to rotate around emboss direction</param>
|
/// <param name="relative_angle">Relative angle to rotate around emboss direction</param>
|
||||||
void do_local_z_rotate(GLCanvas3D &canvas, double relative_angle);
|
void do_local_z_rotate(Selection &selection, double relative_angle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Translation along local z Axis (emboss direction)
|
/// Translation along local z Axis (emboss direction)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="canvas">Selected volume for translate</param>
|
/// <param name="selection">Selected volume for translate</param>
|
||||||
/// <param name="relative_move">Relative move along emboss direction</param>
|
/// <param name="relative_move">Relative move along emboss direction</param>
|
||||||
void do_local_z_move(GLCanvas3D &canvas, double relative_move);
|
void do_local_z_move(Selection &selection, double relative_move);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Distiguish between object and volume
|
/// Distiguish between object and volume
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
|
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
|
||||||
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
|
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
|
||||||
|
|
||||||
|
#include <boost/assign.hpp>
|
||||||
|
#include <boost/bimap.hpp>
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::Emboss;
|
using namespace Slic3r::Emboss;
|
||||||
using namespace Slic3r::GUI::Emboss;
|
using namespace Slic3r::GUI::Emboss;
|
||||||
|
@ -38,6 +41,20 @@ void store_style_index(AppConfig &cfg, size_t index);
|
||||||
StyleManager::Styles load_styles(const AppConfig &cfg);
|
StyleManager::Styles load_styles(const AppConfig &cfg);
|
||||||
void store_styles(AppConfig &cfg, const StyleManager::Styles &styles);
|
void store_styles(AppConfig &cfg, const StyleManager::Styles &styles);
|
||||||
void make_unique_name(const StyleManager::Styles &styles, std::string &name);
|
void make_unique_name(const StyleManager::Styles &styles, std::string &name);
|
||||||
|
|
||||||
|
// Enum map to string and vice versa
|
||||||
|
using HorizontalAlignToName = boost::bimap<FontProp::HorizontalAlign, std::string_view>;
|
||||||
|
const HorizontalAlignToName horizontal_align_to_name =
|
||||||
|
boost::assign::list_of<HorizontalAlignToName::relation>
|
||||||
|
(FontProp::HorizontalAlign::left, "left")
|
||||||
|
(FontProp::HorizontalAlign::center, "center")
|
||||||
|
(FontProp::HorizontalAlign::right, "right");
|
||||||
|
using VerticalAlignToName = boost::bimap<FontProp::VerticalAlign, std::string_view>;
|
||||||
|
const VerticalAlignToName vertical_align_to_name =
|
||||||
|
boost::assign::list_of<VerticalAlignToName::relation>
|
||||||
|
(FontProp::VerticalAlign::top, "top")
|
||||||
|
(FontProp::VerticalAlign::center, "middle")
|
||||||
|
(FontProp::VerticalAlign::bottom, "bottom");
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void StyleManager::init(AppConfig *app_config)
|
void StyleManager::init(AppConfig *app_config)
|
||||||
|
@ -535,6 +552,9 @@ const std::string APP_CONFIG_FONT_DESCRIPTOR = "descriptor";
|
||||||
const std::string APP_CONFIG_FONT_LINE_HEIGHT = "line_height";
|
const std::string APP_CONFIG_FONT_LINE_HEIGHT = "line_height";
|
||||||
const std::string APP_CONFIG_FONT_DEPTH = "depth";
|
const std::string APP_CONFIG_FONT_DEPTH = "depth";
|
||||||
const std::string APP_CONFIG_FONT_USE_SURFACE = "use_surface";
|
const std::string APP_CONFIG_FONT_USE_SURFACE = "use_surface";
|
||||||
|
const std::string APP_CONFIG_PER_GLYPH = "per_glyph";
|
||||||
|
const std::string APP_CONFIG_VERTICAL_ALIGN = "vertical_align";
|
||||||
|
const std::string APP_CONFIG_HORIZONTAL_ALIGN = "horizontal_align";
|
||||||
const std::string APP_CONFIG_FONT_BOLDNESS = "boldness";
|
const std::string APP_CONFIG_FONT_BOLDNESS = "boldness";
|
||||||
const std::string APP_CONFIG_FONT_SKEW = "skew";
|
const std::string APP_CONFIG_FONT_SKEW = "skew";
|
||||||
const std::string APP_CONFIG_FONT_DISTANCE = "distance";
|
const std::string APP_CONFIG_FONT_DISTANCE = "distance";
|
||||||
|
@ -561,6 +581,36 @@ bool read(const Section §ion, const std::string &key, bool &value)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool read(const Section §ion, const std::string &key, Slic3r::FontProp::HorizontalAlign &value) {
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const std::string &data = item->second;
|
||||||
|
if (data.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& map = horizontal_align_to_name.right;
|
||||||
|
auto it = map.find(data);
|
||||||
|
value = (it != map.end()) ? it->second : Slic3r::FontProp::HorizontalAlign::center;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read(const Section §ion, const std::string &key, Slic3r::FontProp::VerticalAlign &value) {
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const std::string &data = item->second;
|
||||||
|
if (data.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto &map = vertical_align_to_name.right;
|
||||||
|
auto it = map.find(data);
|
||||||
|
value = (it != map.end()) ? it->second : Slic3r::FontProp::VerticalAlign::center;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool read(const Section §ion, const std::string &key, float &value)
|
bool read(const Section §ion, const std::string &key, float &value)
|
||||||
{
|
{
|
||||||
auto item = section.find(key);
|
auto item = section.find(key);
|
||||||
|
@ -650,6 +700,9 @@ std::optional<StyleManager::Style> load_style(const Section &app_cfg_section)
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_DEPTH, depth);
|
read(app_cfg_section, APP_CONFIG_FONT_DEPTH, depth);
|
||||||
ep.depth = depth;
|
ep.depth = depth;
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, ep.use_surface);
|
read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, ep.use_surface);
|
||||||
|
read(app_cfg_section, APP_CONFIG_PER_GLYPH, fp.per_glyph);
|
||||||
|
read(app_cfg_section, APP_CONFIG_HORIZONTAL_ALIGN, fp.align.first);
|
||||||
|
read(app_cfg_section, APP_CONFIG_VERTICAL_ALIGN, fp.align.second);
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_BOLDNESS, fp.boldness);
|
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_SKEW, fp.skew);
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, s.distance);
|
read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, s.distance);
|
||||||
|
@ -671,6 +724,12 @@ void store_style(AppConfig &cfg, const StyleManager::Style &s, unsigned index)
|
||||||
data[APP_CONFIG_FONT_DEPTH] = std::to_string(ep.depth);
|
data[APP_CONFIG_FONT_DEPTH] = std::to_string(ep.depth);
|
||||||
if (ep.use_surface)
|
if (ep.use_surface)
|
||||||
data[APP_CONFIG_FONT_USE_SURFACE] = "true";
|
data[APP_CONFIG_FONT_USE_SURFACE] = "true";
|
||||||
|
if (fp.per_glyph)
|
||||||
|
data[APP_CONFIG_PER_GLYPH] = "true";
|
||||||
|
if (fp.align.first != FontProp::HorizontalAlign::center)
|
||||||
|
data[APP_CONFIG_HORIZONTAL_ALIGN] = horizontal_align_to_name.left.find(fp.align.first)->second;
|
||||||
|
if (fp.align.second != FontProp::VerticalAlign::center)
|
||||||
|
data[APP_CONFIG_VERTICAL_ALIGN] = vertical_align_to_name.left.find(fp.align.second)->second;
|
||||||
if (fp.boldness.has_value())
|
if (fp.boldness.has_value())
|
||||||
data[APP_CONFIG_FONT_BOLDNESS] = std::to_string(*fp.boldness);
|
data[APP_CONFIG_FONT_BOLDNESS] = std::to_string(*fp.boldness);
|
||||||
if (fp.skew.has_value())
|
if (fp.skew.has_value())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue