Fix copy of text

Fix store/load of volume type
Fix grayed out of Menu item
Change short curt from q to t
This commit is contained in:
Filip Sykala 2021-09-17 12:30:59 +02:00
parent a725b3f62b
commit 7f5c6b0513
10 changed files with 167 additions and 135 deletions

View File

@ -135,6 +135,7 @@ add_library(libslic3r STATIC
Model.hpp Model.hpp
ModelArrange.hpp ModelArrange.hpp
ModelArrange.cpp ModelArrange.cpp
ModelVolumeType.hpp
MultiMaterialSegmentation.cpp MultiMaterialSegmentation.cpp
MultiMaterialSegmentation.hpp MultiMaterialSegmentation.hpp
CustomGCode.cpp CustomGCode.cpp

View File

@ -14,6 +14,7 @@
#include "Arrange.hpp" #include "Arrange.hpp"
#include "CustomGCode.hpp" #include "CustomGCode.hpp"
#include "enum_bitmask.hpp" #include "enum_bitmask.hpp"
#include "ModelVolumeType.hpp"
#include "TextConfiguration.hpp" #include "TextConfiguration.hpp"
#include <map> #include <map>
@ -220,16 +221,6 @@ private:
friend class ModelObject; friend class ModelObject;
}; };
// Declared outside of ModelVolume, so it could be forward declared.
enum class ModelVolumeType : int {
INVALID = -1,
MODEL_PART = 0,
NEGATIVE_VOLUME,
PARAMETER_MODIFIER,
SUPPORT_BLOCKER,
SUPPORT_ENFORCER,
};
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower }; enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower };
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>; using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute); ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute);
@ -801,7 +792,8 @@ private:
ObjectBase(other), ObjectBase(other),
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull), name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
supported_facets(other.supported_facets), seam_facets(other.seam_facets), mmu_segmentation_facets(other.mmu_segmentation_facets) supported_facets(other.supported_facets), seam_facets(other.seam_facets),
mmu_segmentation_facets(other.mmu_segmentation_facets), text_configuration(other.text_configuration)
{ {
assert(this->id().valid()); assert(this->id().valid());
assert(this->config.id().valid()); assert(this->config.id().valid());
@ -821,7 +813,9 @@ private:
} }
// Providing a new mesh, therefore this volume will get a new unique ID assigned. // Providing a new mesh, therefore this volume will get a new unique ID assigned.
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) : ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
name(other.name), source(other.source), m_mesh(new TriangleMesh(std::move(mesh))), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation) name(other.name), source(other.source), m_mesh(new TriangleMesh(std::move(mesh))),
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
text_configuration(other.text_configuration)
{ {
assert(this->id().valid()); assert(this->id().valid());
assert(this->config.id().valid()); assert(this->config.id().valid());

View File

@ -0,0 +1,16 @@
#ifndef slic3r_ModelVolumeType_hpp_
#define slic3r_ModelVolumeType_hpp_
namespace Slic3r {
enum class ModelVolumeType : int {
INVALID = -1,
MODEL_PART = 0,
NEGATIVE_VOLUME,
PARAMETER_MODIFIER,
SUPPORT_BLOCKER,
SUPPORT_ENFORCER,
};
} // namespace Slic3r
#endif /* slic3r_ModelVolumeType_hpp_ */

View File

@ -56,9 +56,9 @@ struct TextConfiguration
// user modification of font // user modification of font
FontProp font_prop; FontProp font_prop;
std::string text; std::string text = "None";
TextConfiguration() = default; TextConfiguration() = default; // optional needs empty constructor
TextConfiguration(const FontItem & font_item, TextConfiguration(const FontItem & font_item,
const FontProp & font_prop, const FontProp & font_prop,
const std::string &text) const std::string &text)

View File

@ -2858,6 +2858,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{ {
if (!m_initialized || !_set_current()) if (!m_initialized || !_set_current())
return; return;
#if ENABLE_RETINA_GL #if ENABLE_RETINA_GL
const float scale = m_retina_helper->get_scale_factor(); const float scale = m_retina_helper->get_scale_factor();
@ -3281,6 +3282,18 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
mouse_up_cleanup(); mouse_up_cleanup();
} else if (evt.LeftDClick()) {
// open text editation
int vol_id = get_first_hover_volume_idx();
const auto & cid = m_volumes.volumes[vol_id]->composite_id;
const ModelObject *obj = m_model->objects[cid.object_id];
const ModelVolume *mv = obj->volumes[cid.volume_id];
if (mv->text_configuration.has_value()) {
// select volume and open emboss gizmo
deselect_all();
m_selection.add(vol_id);
m_gizmos.open_gizmo(GLGizmosManager::EType::Emboss);
}
} }
else if (evt.Moving()) { else if (evt.Moving()) {
m_mouse.position = pos.cast<double>(); m_mouse.position = pos.cast<double>();

View File

@ -469,12 +469,9 @@ wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType ty
auto add_text = [type](wxCommandEvent &) { auto add_text = [type](wxCommandEvent &) {
GLGizmosManager &mng = plater()->canvas3D()->get_gizmos_manager(); GLGizmosManager &mng = plater()->canvas3D()->get_gizmos_manager();
if (mng.open_gizmo(GLGizmosManager::Emboss)) { if (mng.get_current_type() == GLGizmosManager::Emboss ||
GLGizmoBase * base = mng.get_current(); mng.open_gizmo(GLGizmosManager::Emboss)) {
GLGizmoEmboss *emboss = dynamic_cast<GLGizmoEmboss *>(base); GLGizmoEmboss *emboss = dynamic_cast<GLGizmoEmboss *>(mng.get_current());
if (emboss == nullptr) {
int j = 42;
} else
emboss->set_volume_type(type); emboss->set_volume_type(type);
} }
}; };
@ -898,6 +895,26 @@ void MenuFactory::append_menu_items_mirror(wxMenu* menu)
[]() { return plater()->can_mirror(); }, m_parent); []() { return plater()->can_mirror(); }, m_parent);
} }
void MenuFactory::append_menu_item_edit_text(wxMenu *menu) {
wxString name = _L("Edit text");
wxString description = _L("Ability to change text, font, size, ...");
std::string icon = "";
append_menu_item(
menu, wxID_ANY, name, description,
[](wxCommandEvent &) {
plater()->canvas3D()->get_gizmos_manager().open_gizmo(GLGizmosManager::Emboss);
},
icon, nullptr,
[]() {
const auto& sel = plater()->get_selection();
if (sel.volumes_count() != 1) return false;
auto cid = sel.get_volume(*sel.get_volume_idxs().begin());
const ModelVolume *vol = plater()->canvas3D()->get_model()
->objects[cid->object_idx()]->volumes[cid->volume_idx()];
return vol->text_configuration.has_value();
}, m_parent);
}
MenuFactory::MenuFactory() MenuFactory::MenuFactory()
{ {
for (int i = 0; i < mtCount; i++) { for (int i = 0; i < mtCount; i++) {
@ -980,6 +997,7 @@ void MenuFactory::create_part_menu()
#ifdef __WXOSX__ #ifdef __WXOSX__
append_menu_items_osx(menu); append_menu_items_osx(menu);
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_edit_text(menu);
append_menu_item_delete(menu); append_menu_item_delete(menu);
append_menu_item_reload_from_disk(menu); append_menu_item_reload_from_disk(menu);
append_menu_item_replace_with_stl(menu); append_menu_item_replace_with_stl(menu);

View File

@ -103,6 +103,7 @@ private:
void append_menu_item_merge_to_multipart_object(wxMenu *menu); void append_menu_item_merge_to_multipart_object(wxMenu *menu);
// void append_menu_item_merge_to_single_object(wxMenu *menu); // void append_menu_item_merge_to_single_object(wxMenu *menu);
void append_menu_items_mirror(wxMenu *menu); void append_menu_items_mirror(wxMenu *menu);
void append_menu_item_edit_text(wxMenu *menu);
void append_menu_items_instance_manipulation(wxMenu *menu); void append_menu_items_instance_manipulation(wxMenu *menu);
void update_menu_items_instance_manipulation(MenuType type); void update_menu_items_instance_manipulation(MenuType type);
}; };

View File

@ -73,7 +73,7 @@ GLGizmoEmboss::~GLGizmoEmboss() {}
bool GLGizmoEmboss::on_init() bool GLGizmoEmboss::on_init()
{ {
//m_grabbers.emplace_back(); //m_grabbers.emplace_back();
m_shortcut_key = WXK_CONTROL_Q; m_shortcut_key = WXK_CONTROL_T;
return true; return true;
} }
@ -92,95 +92,9 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse; ImGuiWindowFlags_NoCollapse;
m_imgui->begin(on_get_name(), flag); m_imgui->begin(on_get_name(), flag);
draw_window();
if (!m_font.has_value()) {
ImGui::Text("Warning: No font is selected. Select correct one.");
}
draw_font_list(); m_imgui->end(); //
if (ImGui::Button(_L("choose font").c_str())) {
choose_font_by_dialog();
}
ImGui::SameLine();
if (ImGui::Button(_L("use system font").c_str())) {
wxSystemSettings ss;
wxFont f = ss.GetFont(wxSYS_DEFAULT_GUI_FONT);
size_t font_index = m_font_list.size();
FontItem fi = WxFontUtils::get_font_item(f);
m_font_list.emplace_back(fi);
bool loaded = load_font(font_index);
}
ImGui::SameLine();
draw_add_button();
if (ImGui::Button("add svg")) {
std::string filePath =
"C:/Users/filip/Downloads/fontawesome-free-5.15.4-web/"
"fontawesome-free-5.15.4-web/svgs/solid/bicycle.svg";
filePath = "C:/Users/filip/Downloads/circle.svg";
NSVGimage *image = nsvgParseFromFile(filePath.c_str(), "mm", 96.0f);
ExPolygons polys = NSVGUtils::to_ExPolygons(image);
for (auto &poly : polys) poly.scale(1e5);
SVG svg("converted.svg", BoundingBox(polys.front().contour.points));
svg.draw(polys);
nsvgDelete(image);
}
if (ImGui::InputFloat("Size[in mm]", &m_font_prop.size_in_mm)) {
if (m_font_prop.size_in_mm < 0.1) m_font_prop.size_in_mm = 10;
process();
}
if (ImGui::InputFloat("Emboss[in mm]", &m_font_prop.emboss)) process();
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness)) {
if (m_font.has_value()) m_font->cache.clear();
process();
}
if (ImGui::InputInt("CharGap[in font points]", &m_font_prop.char_gap)) process();
if (ImGui::InputInt("LineGap[in font points]", &m_font_prop.line_gap)) process();
//ImGui::InputFloat3("Origin", m_orientation.origin.data());
//if (ImGui::InputFloat3("Normal", m_normal.data())) m_normal.normalize();
//if (ImGui::InputFloat3("Up", m_up.data())) m_up.normalize();
ImVec2 input_size(-FLT_MIN, ImGui::GetTextLineHeight() * 6);
ImGuiInputTextFlags flags =
ImGuiInputTextFlags_::ImGuiInputTextFlags_AllowTabInput
| ImGuiInputTextFlags_::ImGuiInputTextFlags_AutoSelectAll
//| ImGuiInputTextFlags_::ImGuiInputTextFlags_CallbackResize
//|ImGuiInputTextFlags_::ImGuiInputTextFlags_CtrlEnterForNewLine
;
if (ImGui::InputTextMultiline("##Text", m_text.get(), m_text_size, input_size, flags)) {
process();
}
// change text size
int max_text_size = static_cast<int>(m_text_size);
if (ImGui::InputInt("max text size", &max_text_size, 8, 64)) {
set_max_text_size(static_cast<size_t>(max_text_size));
}
// draw 2d triangle in IMGUI
ImVec2 t0(25, 25);
ImVec2 t1(150, 5);
ImVec2 t2(10, 100);
ImU32 c = ImGui::ColorConvertFloat4ToU32(ImVec4(.0, .8, .2, 1.));
ImGui::GetOverlayDrawList()->AddTriangleFilled(t0, t1, t2, c);
// create text volume when reselect volumes
m_imgui->disabled_begin(!m_font.has_value());
if (m_volume == nullptr) {
if (ImGui::Button("Generate preview")) process();
}
m_imgui->disabled_end();
m_imgui->end();
} }
void GLGizmoEmboss::on_set_state() void GLGizmoEmboss::on_set_state()
@ -211,7 +125,7 @@ void GLGizmoEmboss::on_set_state()
} }
// Try set selected volume // Try set selected volume
if (!set_volume()) { if (!load_configuration(get_selected_volume())) {
// No volume with text selected, create new one // No volume with text selected, create new one
set_default_configuration(); set_default_configuration();
process(); process();
@ -314,6 +228,7 @@ bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action,
void GLGizmoEmboss::set_default_configuration() { void GLGizmoEmboss::set_default_configuration() {
set_text(_u8L("Embossed text")); set_text(_u8L("Embossed text"));
m_font_prop = FontProp(); m_font_prop = FontProp();
m_volume_type = ModelVolumeType::MODEL_PART;
// may be set default font? // may be set default font?
} }
@ -328,10 +243,9 @@ void GLGizmoEmboss::check_selection()
if (m_volume != nullptr) if (m_volume != nullptr)
ImGui::ClearActiveID(); ImGui::ClearActiveID();
// is selected volume embossed? // is select embossed volume?
if (vol!= nullptr && vol->text_configuration.has_value()) { if (load_configuration(vol)) {
m_volume = vol; // successfull load volume for editing
load_configuration(*vol->text_configuration);
return; return;
} }
@ -427,7 +341,7 @@ bool GLGizmoEmboss::process() {
// select new added volume // select new added volume
ModelObject *mo = m_volume->get_object(); ModelObject *mo = m_volume->get_object();
// Editing object volume change its name // Editing object volume change its name
if (mo->volumes.size() == 1) mo->name = volume_name; if (mo->volumes.size() == 1) mo->name = volume_name;
ObjectList *obj_list = app.obj_list(); ObjectList *obj_list = app.obj_list();
const ModelObjectPtrs &objs = *obj_list->objects(); const ModelObjectPtrs &objs = *obj_list->objects();
auto item = find(objs.begin(), objs.end(), mo); auto item = find(objs.begin(), objs.end(), mo);
@ -441,7 +355,7 @@ bool GLGizmoEmboss::process() {
return items.front(); return items.front();
}); });
if (m_volume_type == ModelVolumeType::MODEL_PART) if (m_volume->type() == ModelVolumeType::MODEL_PART)
// update printable state on canvas // update printable state on canvas
m_parent.update_instance_printable_state_for_object((size_t) object_idx); m_parent.update_instance_printable_state_for_object((size_t) object_idx);
@ -490,6 +404,89 @@ void GLGizmoEmboss::draw_add_button() {
} }
} }
void GLGizmoEmboss::draw_window()
{
if (!m_font.has_value()) {
ImGui::Text("Warning: No font is selected. Select correct one.");
}
draw_font_list();
if (ImGui::Button(_L("choose font").c_str())) { choose_font_by_dialog(); }
ImGui::SameLine();
if (ImGui::Button(_L("use system font").c_str())) {
wxSystemSettings ss;
wxFont f = ss.GetFont(wxSYS_DEFAULT_GUI_FONT);
size_t font_index = m_font_list.size();
FontItem fi = WxFontUtils::get_font_item(f);
m_font_list.emplace_back(fi);
bool loaded = load_font(font_index);
}
ImGui::SameLine();
draw_add_button();
if (ImGui::Button("add svg")) {
std::string filePath =
"C:/Users/filip/Downloads/fontawesome-free-5.15.4-web/"
"fontawesome-free-5.15.4-web/svgs/solid/bicycle.svg";
filePath = "C:/Users/filip/Downloads/circle.svg";
NSVGimage *image = nsvgParseFromFile(filePath.c_str(), "mm", 96.0f);
ExPolygons polys = NSVGUtils::to_ExPolygons(image);
for (auto &poly : polys) poly.scale(1e5);
SVG svg("converted.svg", BoundingBox(polys.front().contour.points));
svg.draw(polys);
nsvgDelete(image);
}
if (ImGui::InputFloat("Size[in mm]", &m_font_prop.size_in_mm)) {
if (m_font_prop.size_in_mm < 0.1) m_font_prop.size_in_mm = 10;
process();
}
if (ImGui::InputFloat("Emboss[in mm]", &m_font_prop.emboss)) process();
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness)) {
if (m_font.has_value()) m_font->cache.clear();
process();
}
if (ImGui::InputInt("CharGap[in font points]", &m_font_prop.char_gap))
process();
if (ImGui::InputInt("LineGap[in font points]", &m_font_prop.line_gap))
process();
// ImGui::InputFloat3("Origin", m_orientation.origin.data());
// if (ImGui::InputFloat3("Normal", m_normal.data())) m_normal.normalize();
// if (ImGui::InputFloat3("Up", m_up.data())) m_up.normalize();
ImVec2 input_size(-FLT_MIN, ImGui::GetTextLineHeight() * 6);
ImGuiInputTextFlags flags =
ImGuiInputTextFlags_::ImGuiInputTextFlags_AllowTabInput |
ImGuiInputTextFlags_::ImGuiInputTextFlags_AutoSelectAll
//| ImGuiInputTextFlags_::ImGuiInputTextFlags_CallbackResize
//|ImGuiInputTextFlags_::ImGuiInputTextFlags_CtrlEnterForNewLine
;
if (ImGui::InputTextMultiline("##Text", m_text.get(), m_text_size,
input_size, flags)) {
process();
}
// change text size
int max_text_size = static_cast<int>(m_text_size);
if (ImGui::InputInt("max text size", &max_text_size, 8, 64)) {
set_max_text_size(static_cast<size_t>(max_text_size));
}
// Option to create text volume when reselect volumes
m_imgui->disabled_begin(!m_font.has_value());
if (m_volume == nullptr) {
if (ImGui::Button("Generate preview")) process();
}
m_imgui->disabled_end();
}
void GLGizmoEmboss::draw_font_list() void GLGizmoEmboss::draw_font_list()
{ {
auto &current = m_font_list[m_font_selected]; auto &current = m_font_list[m_font_selected];
@ -623,28 +620,16 @@ void GLGizmoEmboss::add_fonts(const FontList &font_list) {
sort_fonts(); sort_fonts();
} }
bool GLGizmoEmboss::set_volume()
{
ModelVolume *vol = get_selected_volume();
// Is selected only one volume
if (vol == nullptr) return false;
// Is volume created by Emboss?
if (!vol->text_configuration.has_value()) return false;
// set selected volume
m_volume = vol;
load_configuration(*vol->text_configuration);
return true;
}
TextConfiguration GLGizmoEmboss::create_configuration() { TextConfiguration GLGizmoEmboss::create_configuration() {
std::string text((const char *) m_text.get()); std::string text((const char *) m_text.get());
return TextConfiguration(m_font_list[m_font_selected], m_font_prop, text); return TextConfiguration(m_font_list[m_font_selected], m_font_prop, text);
} }
bool GLGizmoEmboss::load_configuration(const TextConfiguration &configuration) bool GLGizmoEmboss::load_configuration(ModelVolume *volume)
{ {
if (volume == nullptr) return false;
if (!volume->text_configuration.has_value()) return false;
const TextConfiguration &configuration = *volume->text_configuration;
size_t index = m_font_list.size(); size_t index = m_font_list.size();
for (const auto &font_item : m_font_list) { for (const auto &font_item : m_font_list) {
if (font_item.type == configuration.font_item.type && if (font_item.type == configuration.font_item.type &&
@ -670,6 +655,8 @@ bool GLGizmoEmboss::load_configuration(const TextConfiguration &configuration)
m_font_prop = configuration.font_prop; m_font_prop = configuration.font_prop;
set_text(configuration.text); set_text(configuration.text);
m_volume_type = volume->type(); // not neccesary
m_volume = volume;
return true; return true;
} }

View File

@ -46,6 +46,7 @@ private:
// create volume from text - main functionality // create volume from text - main functionality
bool process(); bool process();
void close(); void close();
void draw_window();
void draw_font_list(); void draw_font_list();
void draw_add_button(); void draw_add_button();
bool load_font(); bool load_font();
@ -59,11 +60,9 @@ private:
void sort_fonts(); void sort_fonts();
void add_fonts(const FontList &font_list); void add_fonts(const FontList &font_list);
bool set_volume();
// Create object described how to make a Volume // Create object described how to make a Volume
TextConfiguration create_configuration(); TextConfiguration create_configuration();
bool load_configuration(const TextConfiguration& configuration); bool load_configuration(ModelVolume *volume);
std::string create_volume_name(); std::string create_volume_name();
@ -99,6 +98,8 @@ private:
// actual volume // actual volume
ModelVolume *m_volume; ModelVolume *m_volume;
// Only for new created volume
ModelVolumeType m_volume_type; ModelVolumeType m_volume_type;
bool m_is_initialized; bool m_is_initialized;

View File

@ -154,6 +154,7 @@ void KBShortcutsDialog::fill_shortcuts()
{ "L", L("Gizmo FDM paint-on supports") }, { "L", L("Gizmo FDM paint-on supports") },
{ "P", L("Gizmo FDM paint-on seam") }, { "P", L("Gizmo FDM paint-on seam") },
{ "N", L("Gizmo Multi Material painting") }, { "N", L("Gizmo Multi Material painting") },
{ "T", L("Gizmo Emboss Text / edit text")},
{ "Esc", L("Unselect gizmo or clear selection") }, { "Esc", L("Unselect gizmo or clear selection") },
{ "K", L("Change camera type (perspective, orthographic)") }, { "K", L("Change camera type (perspective, orthographic)") },
{ "B", L("Zoom to Bed") }, { "B", L("Zoom to Bed") },