Add svg file loading for emboss
This commit is contained in:
parent
9b0a17939e
commit
b0ed881bd4
3 changed files with 117 additions and 84 deletions
src
|
@ -524,6 +524,7 @@ ExPolygons Emboss::text2shapes(Font & font,
|
|||
expolygons_append(result, polygons);
|
||||
}
|
||||
return union_ex(result);
|
||||
// TODO: simplify after union! Do NOT create 2 close vertices (may cause problem in triangulation)
|
||||
}
|
||||
|
||||
indexed_triangle_set Emboss::polygons2model(const ExPolygons &shape2d,
|
||||
|
|
|
@ -218,7 +218,8 @@ ModelVolume *GLGizmoEmboss::get_selected_volume(const Selection &selection,
|
|||
}
|
||||
|
||||
// create_text_volume()
|
||||
bool GLGizmoEmboss::process() {
|
||||
bool GLGizmoEmboss::process()
|
||||
{
|
||||
if (!m_font.has_value()) return false;
|
||||
|
||||
ExPolygons shapes = Emboss::text2shapes(*m_font, m_text.c_str(), m_font_prop);
|
||||
|
@ -228,35 +229,39 @@ bool GLGizmoEmboss::process() {
|
|||
auto project = std::make_unique<Emboss::ProjectScale>(
|
||||
std::make_unique<Emboss::ProjectZ>(m_font_prop.emboss / scale), scale);
|
||||
indexed_triangle_set its = Emboss::polygons2model(shapes, *project);
|
||||
if (its.indices.empty()) return false;
|
||||
return add_volume(create_volume_name(), its);
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::add_volume(const std::string &name, indexed_triangle_set &its)
|
||||
{
|
||||
if (its.indices.empty()) return false;
|
||||
// add object
|
||||
TriangleMesh tm(std::move(its));
|
||||
tm.repair();
|
||||
|
||||
//tm.WriteOBJFile("text_preview.obj");
|
||||
|
||||
GUI_App &app = wxGetApp();
|
||||
Plater * plater = app.plater();
|
||||
std::string volume_name = create_volume_name();
|
||||
plater->take_snapshot(_L("Add") + " " + volume_name);
|
||||
// tm.WriteOBJFile("text_preview.obj");
|
||||
|
||||
GUI_App & app = wxGetApp();
|
||||
Plater * plater = app.plater();
|
||||
plater->take_snapshot(_L("Add") + " " + name);
|
||||
if (m_volume == nullptr) {
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
if (selection.is_empty()) {
|
||||
// create new object
|
||||
app.obj_list()->load_mesh_object(tm, volume_name);
|
||||
app.mainframe->update_title();
|
||||
app.obj_list()->load_mesh_object(tm, name);
|
||||
app.mainframe->update_title();
|
||||
// get new created volume
|
||||
m_volume = app.obj_list()->objects()->back()->volumes.front();
|
||||
m_volume->text_configuration = create_configuration();
|
||||
|
||||
// load mesh cause close gizmo, soo I open it again
|
||||
m_parent.get_gizmos_manager().open_gizmo(GLGizmosManager::EType::Emboss);
|
||||
m_parent.get_gizmos_manager().open_gizmo(
|
||||
GLGizmosManager::EType::Emboss);
|
||||
return true;
|
||||
} else {
|
||||
Model &model = plater->model();
|
||||
int object_idx = selection.get_object_idx();
|
||||
ModelObject *obj = model.objects[object_idx];
|
||||
Model & model = plater->model();
|
||||
int object_idx = selection.get_object_idx();
|
||||
ModelObject *obj = model.objects[object_idx];
|
||||
m_volume = obj->add_volume(std::move(tm), m_volume_type);
|
||||
}
|
||||
} else {
|
||||
|
@ -268,7 +273,7 @@ bool GLGizmoEmboss::process() {
|
|||
m_volume->calculate_convex_hull();
|
||||
m_volume->get_object()->invalidate_bounding_box();
|
||||
}
|
||||
m_volume->name = volume_name;
|
||||
m_volume->name = name;
|
||||
|
||||
// set a default extruder value, since user can't add it manually
|
||||
m_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||
|
@ -277,23 +282,26 @@ bool GLGizmoEmboss::process() {
|
|||
// select new added volume
|
||||
ModelObject *mo = m_volume->get_object();
|
||||
// Editing object volume change its name
|
||||
if (mo->volumes.size() == 1) mo->name = volume_name;
|
||||
ObjectList *obj_list = app.obj_list();
|
||||
const ModelObjectPtrs &objs = *obj_list->objects();
|
||||
auto item = find(objs.begin(), objs.end(), mo);
|
||||
if (mo->volumes.size() == 1) mo->name = name;
|
||||
ObjectList * obj_list = app.obj_list();
|
||||
const ModelObjectPtrs &objs = *obj_list->objects();
|
||||
auto item = find(objs.begin(), objs.end(), mo);
|
||||
assert(item != objs.end());
|
||||
int object_idx = item - objs.begin();
|
||||
int object_idx = item - objs.begin();
|
||||
ModelVolume *new_volume = m_volume; // copy pointer for lambda
|
||||
obj_list->select_item([new_volume, object_idx, obj_list]() {
|
||||
wxDataViewItemArray items = obj_list->reorder_volumes_and_get_selection(
|
||||
object_idx, [new_volume](const ModelVolume *volume) { return volume == new_volume; });
|
||||
object_idx, [new_volume](const ModelVolume *volume) {
|
||||
return volume == new_volume;
|
||||
});
|
||||
if (items.IsEmpty()) return wxDataViewItem();
|
||||
return items.front();
|
||||
});
|
||||
|
||||
if (m_volume->type() == ModelVolumeType::MODEL_PART)
|
||||
// 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);
|
||||
|
||||
obj_list->selection_changed();
|
||||
m_parent.reload_scene(true);
|
||||
|
@ -305,40 +313,6 @@ void GLGizmoEmboss::close() {
|
|||
m_parent.get_gizmos_manager().open_gizmo(GLGizmosManager::Emboss);
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_add_button() {
|
||||
if (ImGui::Button(_u8L("Add").c_str())) {
|
||||
wxArrayString input_files;
|
||||
wxString fontDir = wxEmptyString;
|
||||
wxString selectedFile = wxEmptyString;
|
||||
wxFileDialog dialog(
|
||||
nullptr, _L("Choose one or more files (TTF, TTC):"),
|
||||
fontDir, selectedFile,
|
||||
file_wildcards(FT_FONTS),
|
||||
wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
|
||||
if (input_files.IsEmpty()) return;
|
||||
|
||||
FontList font_list;
|
||||
font_list.reserve(input_files.size());
|
||||
for (auto &input_file : input_files) {
|
||||
std::string path = std::string(input_file.c_str());
|
||||
size_t pos = path.find_last_of('\\');
|
||||
size_t pos2 = path.find_last_of('.');
|
||||
std::string name = path.substr(pos + 1, pos2 - pos-1);
|
||||
font_list.emplace_back(name, path);
|
||||
}
|
||||
// set last added font as active
|
||||
m_font_selected = m_font_list.size() + font_list.size() - 1;
|
||||
add_fonts(font_list);
|
||||
load_font();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("add file with font(.ttf, .ttc)");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_window()
|
||||
{
|
||||
if (!m_font.has_value()) {
|
||||
|
@ -347,35 +321,27 @@ void GLGizmoEmboss::draw_window()
|
|||
|
||||
draw_font_list();
|
||||
|
||||
if (ImGui::Button(_L("choose font").c_str())) { choose_font_by_dialog(); }
|
||||
if (ImGui::Button(_L("choose font").c_str())) choose_font_by_wxdialog();
|
||||
|
||||
//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();
|
||||
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);
|
||||
if (ImGui::Button(_L("Add").c_str())) choose_true_type_file();
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(_L("add file with font(.ttf, .ttc)").c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
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::Button("add svg")) choose_svg_file();
|
||||
|
||||
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;
|
||||
|
@ -481,7 +447,7 @@ bool GLGizmoEmboss::load_font() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::choose_font_by_dialog() {
|
||||
bool GLGizmoEmboss::choose_font_by_wxdialog() {
|
||||
// keep last selected font did not work
|
||||
// static wxFontData data;
|
||||
// wxFontDialog font_dialog((wxWindow *) wxGetApp().mainframe, data);
|
||||
|
@ -502,6 +468,65 @@ bool GLGizmoEmboss::choose_font_by_dialog() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::choose_true_type_file()
|
||||
{
|
||||
wxArrayString input_files;
|
||||
wxString fontDir = wxEmptyString;
|
||||
wxString selectedFile = wxEmptyString;
|
||||
wxFileDialog dialog(nullptr, _L("Choose one or more files (TTF, TTC):"),
|
||||
fontDir, selectedFile, file_wildcards(FT_FONTS),
|
||||
wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
|
||||
if (input_files.IsEmpty()) return false;
|
||||
|
||||
FontList font_list;
|
||||
font_list.reserve(input_files.size());
|
||||
for (auto &input_file : input_files) {
|
||||
std::string path = std::string(input_file.c_str());
|
||||
size_t pos = path.find_last_of('\\');
|
||||
size_t pos2 = path.find_last_of('.');
|
||||
std::string name = path.substr(pos + 1, pos2 - pos - 1);
|
||||
font_list.emplace_back(name, path);
|
||||
}
|
||||
// set last added font as active
|
||||
m_font_selected = m_font_list.size() + font_list.size() - 1;
|
||||
add_fonts(font_list);
|
||||
return load_font();
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::choose_svg_file()
|
||||
{
|
||||
wxArrayString input_files;
|
||||
wxString fontDir = wxEmptyString;
|
||||
wxString selectedFile = wxEmptyString;
|
||||
wxFileDialog dialog(nullptr, _L("Choose SVG file:"), fontDir,
|
||||
selectedFile, file_wildcards(FT_SVG), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
|
||||
if (input_files.IsEmpty()) return false;
|
||||
if (input_files.size() != 1) return false;
|
||||
auto &input_file = input_files.front();
|
||||
std::string path = std::string(input_file.c_str());
|
||||
size_t pos = path.find_last_of('\\');
|
||||
size_t pos2 = path.find_last_of('.');
|
||||
std::string name = path.substr(pos + 1, pos2 - pos - 1);
|
||||
|
||||
NSVGimage *image = nsvgParseFromFile(path.c_str(), "mm", 96.0f);
|
||||
ExPolygons polys = NSVGUtils::to_ExPolygons(image);
|
||||
nsvgDelete(image);
|
||||
|
||||
BoundingBox bb;
|
||||
for (const auto &p: polys) bb.merge(p.contour.points);
|
||||
float scale = m_font_prop.size_in_mm / std::max(bb.max.x(), bb.max.y());
|
||||
auto project = std::make_unique<Emboss::ProjectScale>(
|
||||
std::make_unique<Emboss::ProjectZ>(m_font_prop.emboss / scale), scale);
|
||||
indexed_triangle_set its = Emboss::polygons2model(polys, *project);
|
||||
// test store:
|
||||
//for (auto &poly : polys) poly.scale(1e5);
|
||||
//SVG svg("converted.svg", BoundingBox(polys.front().contour.points));
|
||||
//svg.draw(polys);
|
||||
return add_volume(name, its);
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::sort_fonts() {
|
||||
// initialize original index locations
|
||||
std::vector<size_t> idx(m_font_list.size());
|
||||
|
@ -712,6 +737,11 @@ ExPolygons NSVGUtils::to_ExPolygons(NSVGimage *image,
|
|||
}
|
||||
polygons.push_back(polygon);
|
||||
}
|
||||
|
||||
// Fix Y axis
|
||||
for (Polygon &polygon : polygons)
|
||||
for (Point &p : polygon.points) p.y() *= -1;
|
||||
|
||||
return union_ex(polygons);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,16 +41,18 @@ private:
|
|||
static ModelVolume *get_selected_volume(const Selection &selection, const ModelObjectPtrs objects);
|
||||
// create volume from text - main functionality
|
||||
bool process();
|
||||
bool add_volume(const std::string& name, indexed_triangle_set& its);
|
||||
void close();
|
||||
void draw_window();
|
||||
void draw_font_list();
|
||||
void draw_add_button();
|
||||
|
||||
bool load_font();
|
||||
// try to set font_index
|
||||
bool load_font(size_t font_index);
|
||||
|
||||
bool choose_font_by_dialog();
|
||||
bool choose_font_by_wxdialog();
|
||||
bool choose_true_type_file();
|
||||
bool choose_svg_file();
|
||||
|
||||
void sort_fonts();
|
||||
void add_fonts(const FontList &font_list);
|
||||
|
|
Loading…
Reference in a new issue