Add editing of text volume
This commit is contained in:
parent
8226f74413
commit
8add695de9
7 changed files with 440 additions and 131 deletions
src
libslic3r
slic3r/GUI/Gizmos
|
@ -206,6 +206,7 @@ add_library(libslic3r STATIC
|
|||
Technologies.hpp
|
||||
Tesselate.cpp
|
||||
Tesselate.hpp
|
||||
TextConfiguration.hpp
|
||||
TriangleMesh.cpp
|
||||
TriangleMesh.hpp
|
||||
TriangleMeshSlicer.cpp
|
||||
|
|
|
@ -10,18 +10,6 @@
|
|||
|
||||
using namespace Slic3r;
|
||||
|
||||
Emboss::FontItem::FontItem(const std::string &name, const std::string &path)
|
||||
: name(name), path(path), type(Type::file_path)
|
||||
{}
|
||||
Emboss::FontItem::FontItem(const std::string &name, const std::string &path, Type type)
|
||||
: name(name), path(path), type(type)
|
||||
{}
|
||||
Emboss::FontItem::FontItem(const std::wstring &name, const std::wstring &path)
|
||||
: name(boost::nowide::narrow(name.c_str()))
|
||||
, path(boost::nowide::narrow(path.c_str()))
|
||||
, type(Type::file_path)
|
||||
{}
|
||||
|
||||
// do not expose out of this file stbtt_ data types
|
||||
class Privat
|
||||
{
|
||||
|
@ -30,6 +18,9 @@ public:
|
|||
|
||||
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::Font &font);
|
||||
static std::optional<Emboss::Glyph> get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness = 2.f);
|
||||
|
||||
|
||||
static FontItem create_font_item(std::wstring name, std::wstring path);
|
||||
};
|
||||
|
||||
std::optional<stbtt_fontinfo> Privat::load_font_info(const Emboss::Font &font)
|
||||
|
@ -103,6 +94,11 @@ std::optional<Emboss::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int un
|
|||
return glyph;
|
||||
}
|
||||
|
||||
FontItem Privat::create_font_item(std::wstring name, std::wstring path) {
|
||||
return FontItem(boost::nowide::narrow(name.c_str()),
|
||||
boost::nowide::narrow(path.c_str()));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <wingdi.h>
|
||||
|
@ -238,15 +234,14 @@ void get_OS_font()
|
|||
}
|
||||
|
||||
|
||||
Emboss::FontList Emboss::get_font_list()
|
||||
FontList Emboss::get_font_list()
|
||||
{
|
||||
//auto a = get_font_path(L"none");
|
||||
get_OS_font();
|
||||
//get_OS_font();
|
||||
//choose_font_dlg();
|
||||
//FontList list1 = get_font_list_by_enumeration();
|
||||
//FontList list2 = get_font_list_by_register();
|
||||
//FontList list3 = get_font_list_by_folder();
|
||||
|
||||
//FontList list3 = get_font_list_by_folder();
|
||||
return get_font_list_by_register();
|
||||
}
|
||||
|
||||
|
@ -260,7 +255,7 @@ bool exists_file(const std::wstring &name)
|
|||
}
|
||||
}
|
||||
|
||||
Emboss::FontList Emboss::get_font_list_by_register() {
|
||||
FontList Emboss::get_font_list_by_register() {
|
||||
static const LPWSTR fontRegistryPath = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
||||
HKEY hKey;
|
||||
LONG result;
|
||||
|
@ -310,7 +305,7 @@ Emboss::FontList Emboss::get_font_list_by_register() {
|
|||
if (pos >= font_name_w.size()) continue;
|
||||
// remove TrueType text from name
|
||||
font_name_w = std::wstring(font_name_w, 0, pos);
|
||||
font_list.emplace_back(font_name_w, path_w);
|
||||
font_list.emplace_back(Privat::create_font_item(font_name_w, path_w));
|
||||
} while (result != ERROR_NO_MORE_ITEMS);
|
||||
delete[] font_name;
|
||||
delete[] fileTTF_name;
|
||||
|
@ -336,7 +331,7 @@ bool CALLBACK EnumFamCallBack(LPLOGFONT lplf,
|
|||
UNREFERENCED_PARAMETER(lpntm);
|
||||
}
|
||||
|
||||
Emboss::FontList Emboss::get_font_list_by_enumeration() {
|
||||
FontList Emboss::get_font_list_by_enumeration() {
|
||||
|
||||
HDC hDC = GetDC(NULL);
|
||||
std::vector<std::wstring> font_names;
|
||||
|
@ -345,12 +340,12 @@ Emboss::FontList Emboss::get_font_list_by_enumeration() {
|
|||
|
||||
FontList font_list;
|
||||
for (const std::wstring &font_name : font_names) {
|
||||
font_list.emplace_back(font_name, L"");
|
||||
font_list.emplace_back(Privat::create_font_item(font_name, L""));
|
||||
}
|
||||
return font_list;
|
||||
}
|
||||
|
||||
Emboss::FontList Emboss::get_font_list_by_folder() {
|
||||
FontList Emboss::get_font_list_by_folder() {
|
||||
FontList result;
|
||||
WCHAR winDir[MAX_PATH];
|
||||
UINT winDir_size = GetWindowsDirectory(winDir, MAX_PATH);
|
||||
|
@ -367,7 +362,7 @@ Emboss::FontList Emboss::get_font_list_by_folder() {
|
|||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
||||
std::wstring file_name(fd.cFileName);
|
||||
// TODO: find font name instead of filename
|
||||
result.emplace_back(file_name, search_dir + file_name);
|
||||
result.emplace_back(Privat::create_font_item(file_name, search_dir + file_name));
|
||||
} while (::FindNextFile(hFind, &fd));
|
||||
::FindClose(hFind);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <memory>
|
||||
#include <admesh/stl.h> // indexed_triangle_set
|
||||
#include "Polygon.hpp"
|
||||
#include "TextConfiguration.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -19,28 +20,10 @@ class Emboss
|
|||
public:
|
||||
Emboss() = delete;
|
||||
|
||||
struct FontItem
|
||||
{
|
||||
std::string name;
|
||||
std::string path;
|
||||
enum class Type;
|
||||
Type type;
|
||||
FontItem(const std::string &name, const std::string &path);
|
||||
FontItem(const std::string &name, const std::string &path, Type type);
|
||||
FontItem(const std::wstring &name, const std::wstring &path);
|
||||
|
||||
// way of load font described in path string
|
||||
enum class Type {
|
||||
file_path, // path is file loacation on computer - no move between computers
|
||||
wx_font_descr // path is font descriptor generated by wxWidgets - limits for os/language move
|
||||
};
|
||||
};
|
||||
using FontList = std::vector<FontItem>;
|
||||
|
||||
/// <summary>
|
||||
/// Collect fonts registred inside OS
|
||||
/// </summary>
|
||||
/// <returns>OS resistred TTF font files(full path) with names</returns>
|
||||
/// <returns>OS registred TTF font files(full path) with names</returns>
|
||||
static FontList get_font_list();
|
||||
#ifdef _WIN32
|
||||
static FontList get_font_list_by_register();
|
||||
|
@ -55,24 +38,6 @@ public:
|
|||
/// <returns>File path to font when found</returns>
|
||||
static std::optional<std::wstring> get_font_path(const std::wstring &font_face_name);
|
||||
|
||||
// user defined font property
|
||||
struct FontProp
|
||||
{
|
||||
// define extra space between letters, negative mean closer letter
|
||||
int char_gap = 0;
|
||||
// define extra space between lines, negative mean closer lines
|
||||
int line_gap = 0;
|
||||
// Precision of lettter outline curve in conversion to lines
|
||||
float flatness = 2.0;
|
||||
// Height of letter [in mm]
|
||||
float size_in_mm = 10;
|
||||
// Z depth of text [in mm]
|
||||
float emboss = 5;
|
||||
// TODO: add enum class Align: center/left/right
|
||||
|
||||
FontProp() = default;
|
||||
};
|
||||
|
||||
// description of one letter
|
||||
struct Glyph
|
||||
{
|
||||
|
@ -185,7 +150,7 @@ public:
|
|||
return std::make_pair(res.first * m_scale, res.second * m_scale);
|
||||
}
|
||||
|
||||
float m_scale;
|
||||
float m_scale;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
#include "Arrange.hpp"
|
||||
#include "CustomGCode.hpp"
|
||||
#include "enum_bitmask.hpp"
|
||||
#include "TextConfiguration.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
namespace cereal {
|
||||
class BinaryInputArchive;
|
||||
|
@ -636,6 +638,10 @@ public:
|
|||
// List of mesh facets painted for MMU segmentation.
|
||||
FacetsAnnotation mmu_segmentation_facets;
|
||||
|
||||
// Is set only when volume is Embossed Text type
|
||||
// Contain information how to re-create volume
|
||||
std::optional<TextConfiguration> text_configuration;
|
||||
|
||||
// A parent object owning this modifier volume.
|
||||
ModelObject* get_object() const { return this->object; }
|
||||
ModelVolumeType type() const { return m_type; }
|
||||
|
|
70
src/libslic3r/TextConfiguration.hpp
Normal file
70
src/libslic3r/TextConfiguration.hpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#ifndef slic3r_TextConfiguration_hpp_
|
||||
#define slic3r_TextConfiguration_hpp_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// represent selected font
|
||||
// Name must be human readable is visible in gui
|
||||
// (Path + Type) must define how to open font for using on different OS
|
||||
struct FontItem
|
||||
{
|
||||
std::string name;
|
||||
std::string path;
|
||||
enum class Type;
|
||||
Type type;
|
||||
|
||||
FontItem() : type(Type::undefined) {}
|
||||
FontItem(const std::string &name, const std::string &path, Type type = Type::file_path)
|
||||
: name(name), path(path), type(type)
|
||||
{}
|
||||
|
||||
// way of load font described in path string
|
||||
enum class Type {
|
||||
undefined = 0,
|
||||
file_path, // path is file loacation on computer - no move between computers
|
||||
wx_font_descr, // path is font descriptor generated by wxWidgets - limits for os/language move
|
||||
};
|
||||
};
|
||||
using FontList = std::vector<FontItem>;
|
||||
|
||||
// user defined font property
|
||||
struct FontProp
|
||||
{
|
||||
// define extra space between letters, negative mean closer letter
|
||||
int char_gap = 0;
|
||||
// define extra space between lines, negative mean closer lines
|
||||
int line_gap = 0;
|
||||
// Precision of lettter outline curve in conversion to lines
|
||||
float flatness = 2.0;
|
||||
// Height of letter [in mm]
|
||||
float size_in_mm = 10;
|
||||
// Z depth of text [in mm]
|
||||
float emboss = 5;
|
||||
// TODO: add enum class Align: center/left/right
|
||||
|
||||
FontProp() = default;
|
||||
};
|
||||
|
||||
// define how to create 'Text volume'
|
||||
struct TextConfiguration
|
||||
{
|
||||
// define font
|
||||
FontItem font_item;
|
||||
// user modification of font
|
||||
FontProp font_prop;
|
||||
|
||||
std::string text;
|
||||
|
||||
TextConfiguration() = default;
|
||||
TextConfiguration(const FontItem & font_item,
|
||||
const FontProp & font_prop,
|
||||
const std::string &text)
|
||||
: font_item(font_item), font_prop(font_prop), text(text)
|
||||
{}
|
||||
};
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_TextConfiguration_hpp_
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
#include "nanosvg/nanosvg.h" // load SVG file
|
||||
|
||||
#include <wx/font.h>
|
||||
#include <wx/fontdlg.h>
|
||||
|
||||
|
@ -21,13 +23,12 @@ public:
|
|||
// os specific load of wxFont
|
||||
static std::optional<Slic3r::Emboss::Font> load_font(const wxFont &font);
|
||||
// Must be in gui because of wxWidget
|
||||
static std::optional<Slic3r::Emboss::Font> load_font(const Emboss::FontItem &fi);
|
||||
static std::optional<Slic3r::Emboss::Font> load_font(const FontItem &fi);
|
||||
|
||||
|
||||
static Slic3r::Emboss::FontItem get_font_item(const wxFont &font);
|
||||
static FontItem get_font_item(const wxFont &font);
|
||||
|
||||
// load font used by Operating system as default GUI
|
||||
static Slic3r::Emboss::FontItem get_os_font();
|
||||
static FontItem get_os_font();
|
||||
static std::string get_human_readable_name(const wxFont &font);
|
||||
|
||||
// serialize / deserialize font
|
||||
|
@ -52,23 +53,20 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
|||
{
|
||||
// TODO: suggest to use https://fontawesome.com/
|
||||
// (copy & paste) unicode symbols from web
|
||||
bool is_font_loaded = load_font();
|
||||
add_fonts(Emboss::get_font_list());
|
||||
add_fonts({WxFontUtils::get_os_font()});
|
||||
|
||||
if (!is_font_loaded) {
|
||||
bool is_font_loaded = load_font();
|
||||
FontList fl = Emboss::get_font_list();
|
||||
m_font_list.insert(m_font_list.end(), fl.begin(), fl.end());
|
||||
m_font_list.emplace_back(WxFontUtils::get_os_font());
|
||||
while (!is_font_loaded && !m_font_list.empty()) {
|
||||
// can't load so erase it from list
|
||||
m_font_list.erase(m_font_list.begin() + m_font_selected);
|
||||
m_font_selected = 0; // select first
|
||||
do{
|
||||
is_font_loaded = load_font();
|
||||
if (!is_font_loaded) m_font_list.erase(m_font_list.begin());
|
||||
} while (!is_font_loaded && !m_font_list.empty());
|
||||
m_font_selected = 0; // select first
|
||||
is_font_loaded = load_font();
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (char &c : _u8L("Embossed text")) { m_text[index++] = c; }
|
||||
m_text[index] = '\0';
|
||||
sort_fonts();
|
||||
set_default_configuration();
|
||||
}
|
||||
|
||||
GLGizmoEmboss::~GLGizmoEmboss() {}
|
||||
|
@ -88,50 +86,156 @@ std::string GLGizmoEmboss::on_get_name() const
|
|||
void GLGizmoEmboss::on_render() {}
|
||||
void GLGizmoEmboss::on_render_for_picking() {}
|
||||
|
||||
// took from nanosvgrast.h function nsvgRasterize->nsvg__flattenShape
|
||||
void flatten_cubic_bez(Slic3r::Polygon &polygon,
|
||||
float tessTol,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
float x4,
|
||||
float y4,
|
||||
int level)
|
||||
{
|
||||
float x12, y12, x23, y23, x34, y34, x123, y123, x234, y234, x1234,
|
||||
y1234;
|
||||
float dx, dy, d2, d3;
|
||||
|
||||
if (level == 0) return;
|
||||
|
||||
x12 = (x1 + x2) * 0.5f;
|
||||
y12 = (y1 + y2) * 0.5f;
|
||||
x23 = (x2 + x3) * 0.5f;
|
||||
y23 = (y2 + y3) * 0.5f;
|
||||
x34 = (x3 + x4) * 0.5f;
|
||||
y34 = (y3 + y4) * 0.5f;
|
||||
x123 = (x12 + x23) * 0.5f;
|
||||
y123 = (y12 + y23) * 0.5f;
|
||||
|
||||
dx = x4 - x1;
|
||||
dy = y4 - y1;
|
||||
d2 = std::abs(((x2 - x4) * dy - (y2 - y4) * dx));
|
||||
d3 = std::abs(((x3 - x4) * dy - (y3 - y4) * dx));
|
||||
|
||||
if ((d2 + d3) * (d2 + d3) < tessTol * (dx * dx + dy * dy)) {
|
||||
polygon.points.emplace_back(x4, y4);
|
||||
return;
|
||||
}
|
||||
|
||||
--level;
|
||||
if (level == 0) return;
|
||||
x234 = (x23 + x34) * 0.5f;
|
||||
y234 = (y23 + y34) * 0.5f;
|
||||
x1234 = (x123 + x234) * 0.5f;
|
||||
y1234 = (y123 + y234) * 0.5f;
|
||||
flatten_cubic_bez(polygon, tessTol, x1, y1, x12, y12, x123, y123, x1234, y1234, level);
|
||||
flatten_cubic_bez(polygon, tessTol, x1234, y1234, x234, y234, x34, y34, x4, y4, level);
|
||||
}
|
||||
|
||||
Slic3r::ExPolygons to_ExPolygons(NSVGimage *image,
|
||||
float tessTol = 10.,
|
||||
int max_level = 10)
|
||||
{
|
||||
Polygons polygons;
|
||||
for (NSVGshape *shape = image->shapes; shape != NULL;
|
||||
shape = shape->next) {
|
||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) continue;
|
||||
Slic3r::Polygon polygon;
|
||||
if (shape->fill.type != NSVG_PAINT_NONE) {
|
||||
for (NSVGpath *path = shape->paths; path != NULL;
|
||||
path = path->next) {
|
||||
// Flatten path
|
||||
polygon.points.emplace_back(path->pts[0], path->pts[1]);
|
||||
for (size_t i = 0; i < path->npts - 1; i += 3) {
|
||||
float *p = &path->pts[i * 2];
|
||||
flatten_cubic_bez(polygon, tessTol, p[0], p[1], p[2],
|
||||
p[3], p[4], p[5], p[6], p[7],
|
||||
max_level);
|
||||
}
|
||||
|
||||
if (path->closed) {
|
||||
polygons.push_back(polygon);
|
||||
polygon = Slic3r::Polygon();
|
||||
}
|
||||
}
|
||||
}
|
||||
polygons.push_back(polygon);
|
||||
}
|
||||
return union_ex(polygons);
|
||||
}
|
||||
#include "libslic3r/SVG.hpp"
|
||||
|
||||
void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
if (!m_gui_cfg.has_value()) m_gui_cfg.emplace(GuiCfg());
|
||||
check_selection();
|
||||
|
||||
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoCollapse;
|
||||
m_imgui->begin(on_get_name(), flag);
|
||||
|
||||
if (!m_font.has_value()) {
|
||||
ImGui::Text("Warning: No font is selected. Select correct one.");
|
||||
}
|
||||
|
||||
draw_font_list();
|
||||
|
||||
static std::string fontName;
|
||||
if (ImGui::Button(_L("choose font").c_str())) {
|
||||
static wxFontData data; // keep last selected font
|
||||
wxFontDialog font_dialog((wxWindow*)wxGetApp().mainframe, data);
|
||||
font_dialog.SetTitle(_L("Select font for Emboss"));
|
||||
if (font_dialog.ShowModal() == wxID_OK) {
|
||||
data = font_dialog.GetFontData();
|
||||
wxFont font = data.GetChosenFont();
|
||||
auto fontOpt = WxFontUtils::load_font(font);
|
||||
if (fontOpt.has_value()) {
|
||||
Emboss::FontItem fontItem = WxFontUtils::get_font_item(font);
|
||||
m_font_selected = m_font_list.size();
|
||||
add_fonts({fontItem});
|
||||
m_font = fontOpt;
|
||||
process();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (!fontName.empty()) ImGui::Text(fontName.c_str());
|
||||
|
||||
ImGui::SameLine();
|
||||
draw_add_button();
|
||||
|
||||
ImGui::InputFloat("Size[in mm]", &m_font_prop.size_in_mm);
|
||||
ImGui::InputFloat("Emboss[in mm]", &m_font_prop.emboss);
|
||||
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness))
|
||||
if(m_font.has_value()) m_font->cache.clear();
|
||||
ImGui::InputInt("CharGap[in font points]", &m_font_prop.char_gap);
|
||||
ImGui::InputInt("LineGap[in font points]", &m_font_prop.line_gap);
|
||||
ImGui::InputFloat3("Origin", m_orientation.origin.data());
|
||||
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";
|
||||
NSVGimage *image = nsvgParseFromFile(filePath.c_str(), "mm", 96.0f);
|
||||
ExPolygons polys = 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();
|
||||
|
||||
m_imgui->disabled_begin(!m_font.has_value());
|
||||
if (ImGui::Button("Preview")) process();
|
||||
|
||||
// create default text
|
||||
if (m_volume == nullptr) {
|
||||
if (ImGui::Button("Generate preview")) process();
|
||||
}
|
||||
|
||||
m_imgui->disabled_end();
|
||||
ImVec2 input_size(-FLT_MIN, ImGui::GetTextLineHeight() * 6);
|
||||
ImGuiInputTextFlags flags =
|
||||
|
@ -149,17 +253,7 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||
// change text size
|
||||
int max_text_size = static_cast<int>(m_text_size);
|
||||
if (ImGui::InputInt("max text size", &max_text_size, 8, 64)) {
|
||||
if (max_text_size < 4) max_text_size = 4;
|
||||
std::unique_ptr<char[]> newData(new char[max_text_size]);
|
||||
size_t index = 0;
|
||||
while ((index+1) < max_text_size) {
|
||||
if (m_text.get()[index] == '\0') break;
|
||||
newData.get()[index] = m_text.get()[index];
|
||||
++index;
|
||||
}
|
||||
newData.get()[index] = '\0';
|
||||
m_text = std::move(newData);
|
||||
m_text_size = max_text_size;
|
||||
set_max_text_size(static_cast<size_t>(max_text_size));
|
||||
}
|
||||
|
||||
// draw 2d triangle in IMGUI
|
||||
|
@ -172,7 +266,6 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||
m_imgui->end();
|
||||
}
|
||||
|
||||
|
||||
bool GLGizmoEmboss::on_is_activable() const
|
||||
{
|
||||
return !m_parent.get_selection().is_empty();
|
||||
|
@ -195,8 +288,10 @@ void GLGizmoEmboss::on_set_state()
|
|||
}
|
||||
m_volume = nullptr;
|
||||
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
|
||||
if(!set_volume()) set_default_configuration();
|
||||
|
||||
// when open by hyperlink it needs to show up
|
||||
//request_rerender();
|
||||
m_parent.reload_scene(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,6 +358,63 @@ bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action,
|
|||
return false;
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::set_default_configuration() {
|
||||
set_text(_u8L("Embossed text"));
|
||||
m_font_prop = FontProp();
|
||||
// may be set default font?
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::check_selection()
|
||||
{
|
||||
// is text created?
|
||||
if (m_volume == nullptr) return;
|
||||
ModelVolume* vol = get_selected_volume();
|
||||
|
||||
// is same volume selected?
|
||||
if (m_volume == vol) return;
|
||||
|
||||
// Do not use actual edited value when switch volume
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
|
||||
// is selected volume embossed?
|
||||
if (vol!= nullptr && vol->text_configuration.has_value()) {
|
||||
m_volume = vol;
|
||||
load_configuration(*vol->text_configuration);
|
||||
return;
|
||||
}
|
||||
|
||||
// behave like adding new text
|
||||
m_volume == nullptr;
|
||||
}
|
||||
|
||||
ModelVolume *GLGizmoEmboss::get_selected_volume()
|
||||
{
|
||||
return get_selected_volume(m_parent.get_selection(),
|
||||
wxGetApp().plater()->model().objects);
|
||||
}
|
||||
|
||||
ModelVolume *GLGizmoEmboss::get_selected_volume(const Selection &selection,
|
||||
const ModelObjectPtrs objects)
|
||||
{
|
||||
int object_idx = selection.get_object_idx();
|
||||
// is more object selected?
|
||||
if (object_idx == -1) return nullptr;
|
||||
|
||||
auto volume_idxs = selection.get_volume_idxs();
|
||||
// is more volumes selected?
|
||||
if (volume_idxs.size() != 1) return nullptr;
|
||||
unsigned int vol_id_gl = *volume_idxs.begin();
|
||||
const GLVolume * vol_gl = selection.get_volume(vol_id_gl);
|
||||
const GLVolume::CompositeID &id = vol_gl->composite_id;
|
||||
|
||||
if (id.object_id >= objects.size()) return nullptr;
|
||||
ModelObject *object = objects[id.object_id];
|
||||
|
||||
if (id.volume_id >= object->volumes.size()) return nullptr;
|
||||
return object->volumes[id.volume_id];
|
||||
}
|
||||
|
||||
// create_text_volume()
|
||||
void GLGizmoEmboss::process() {
|
||||
if (!m_font.has_value()) return;
|
||||
|
||||
|
@ -305,6 +457,7 @@ void GLGizmoEmboss::process() {
|
|||
|
||||
// set a default extruder value, since user can't add it manually
|
||||
m_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||
m_volume->text_configuration = create_configuration();
|
||||
|
||||
// select new added volume
|
||||
ModelVolume *new_volume = m_volume;
|
||||
|
@ -343,7 +496,7 @@ void GLGizmoEmboss::draw_add_button() {
|
|||
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
|
||||
if (input_files.IsEmpty()) return;
|
||||
|
||||
Emboss::FontList font_list;
|
||||
FontList font_list;
|
||||
font_list.reserve(input_files.size());
|
||||
for (auto &input_file : input_files) {
|
||||
std::string path = std::string(input_file.c_str());
|
||||
|
@ -368,7 +521,7 @@ void GLGizmoEmboss::draw_font_list()
|
|||
{
|
||||
auto ¤t = m_font_list[m_font_selected];
|
||||
if (ImGui::BeginCombo("##font_selector", current.name.c_str())) {
|
||||
for (const Emboss::FontItem &f : m_font_list) {
|
||||
for (const FontItem &f : m_font_list) {
|
||||
ImGui::PushID((void *) &f.name);
|
||||
std::string name =
|
||||
(f.name.size() < m_gui_cfg->max_font_name) ?
|
||||
|
@ -411,6 +564,14 @@ void GLGizmoEmboss::draw_font_list()
|
|||
}
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::load_font(size_t font_index)
|
||||
{
|
||||
std::swap(font_index, m_font_selected);
|
||||
bool is_loaded = load_font();
|
||||
if (!is_loaded) std::swap(font_index, m_font_selected);
|
||||
return is_loaded;
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::load_font() {
|
||||
if (m_font_selected >= m_font_list.size()) return false;
|
||||
auto font = WxFontUtils::load_font(m_font_list[m_font_selected]);
|
||||
|
@ -419,18 +580,62 @@ bool GLGizmoEmboss::load_font() {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::optional<Emboss::Font> WxFontUtils::load_font(const Emboss::FontItem &fi)
|
||||
void GLGizmoEmboss::set_text(const std::string &text) {
|
||||
if (text.size() > m_text_size-1)
|
||||
set_max_text_size(text.size() + 1);
|
||||
|
||||
int index = 0;
|
||||
for (const char &c : text) m_text[index++] = c;
|
||||
m_text[index] = '\0';
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::set_max_text_size(size_t size) {
|
||||
if (size < 4) size = 4;
|
||||
std::unique_ptr<char[]> newData(new char[size]);
|
||||
size_t index = 0;
|
||||
while ((index + 1) < size) {
|
||||
if (m_text.get()[index] == '\0') break;
|
||||
newData.get()[index] = m_text.get()[index];
|
||||
++index;
|
||||
}
|
||||
newData.get()[index] = '\0';
|
||||
m_text = std::move(newData);
|
||||
m_text_size = size;
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::choose_font_by_dialog() {
|
||||
// keep last selected font did not work
|
||||
// static wxFontData data;
|
||||
// wxFontDialog font_dialog((wxWindow *) wxGetApp().mainframe, data);
|
||||
|
||||
wxFontDialog font_dialog(nullptr);
|
||||
font_dialog.SetTitle(_L("Select font for Emboss"));
|
||||
if (font_dialog.ShowModal() != wxID_OK) return false;
|
||||
wxFontData data = font_dialog.GetFontData();
|
||||
wxFont font = data.GetChosenFont();
|
||||
size_t font_index = m_font_list.size();
|
||||
m_font_list.emplace_back(WxFontUtils::get_font_item(font));
|
||||
if (!load_font(font_index)) {
|
||||
m_font_list.pop_back();
|
||||
return false;
|
||||
}
|
||||
sort_fonts();
|
||||
process();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<Emboss::Font> WxFontUtils::load_font(const FontItem &fi)
|
||||
{
|
||||
switch (fi.type) {
|
||||
case Emboss::FontItem::Type::file_path:
|
||||
case FontItem::Type::file_path:
|
||||
return Emboss::load_font(fi.path.c_str());
|
||||
case Emboss::FontItem::Type::wx_font_descr:
|
||||
case FontItem::Type::wx_font_descr:
|
||||
return WxFontUtils::load_font(WxFontUtils::load_wxFont(fi.path));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Slic3r::Emboss::Font> WxFontUtils::load_font(const wxFont &font)
|
||||
std::optional<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
|
||||
{
|
||||
if (!font.IsOk()) return {};
|
||||
#ifdef _WIN32
|
||||
|
@ -448,18 +653,18 @@ std::optional<Slic3r::Emboss::Font> WxFontUtils::load_font(const wxFont &font)
|
|||
#endif
|
||||
}
|
||||
|
||||
Slic3r::Emboss::FontItem WxFontUtils::get_font_item(const wxFont &font)
|
||||
FontItem WxFontUtils::get_font_item(const wxFont &font)
|
||||
{
|
||||
std::string name = get_human_readable_name(font);
|
||||
std::string fontDesc = store_wxFont(font);
|
||||
return Emboss::FontItem(name, fontDesc, Emboss::FontItem::Type::wx_font_descr);
|
||||
return FontItem(name, fontDesc, FontItem::Type::wx_font_descr);
|
||||
}
|
||||
|
||||
Slic3r::Emboss::FontItem WxFontUtils::get_os_font()
|
||||
FontItem WxFontUtils::get_os_font()
|
||||
{
|
||||
wxSystemSettings ss;
|
||||
wxFont ss_font = ss.GetFont(wxSYS_ANSI_VAR_FONT);
|
||||
Emboss::FontItem fi = get_font_item(ss_font);
|
||||
FontItem fi = get_font_item(ss_font);
|
||||
fi.name += +" (" + _u8L("OS default") + ")";
|
||||
return get_font_item(ss_font);
|
||||
}
|
||||
|
@ -502,7 +707,7 @@ void GLGizmoEmboss::sort_fonts() {
|
|||
return m_font_list[i1].name < m_font_list[i2].name;
|
||||
});
|
||||
|
||||
Emboss::FontList font_list;
|
||||
FontList font_list;
|
||||
font_list.reserve(m_font_list.size());
|
||||
size_t selected = 0;
|
||||
for (const size_t &i : idx) {
|
||||
|
@ -513,18 +718,68 @@ void GLGizmoEmboss::sort_fonts() {
|
|||
m_font_selected = selected;
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::add_fonts(const Emboss::FontList &font_list) {
|
||||
void GLGizmoEmboss::add_fonts(const FontList &font_list) {
|
||||
m_font_list.insert(m_font_list.end(), font_list.begin(), font_list.end());
|
||||
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() {
|
||||
std::string text((const char *) m_text.get());
|
||||
return TextConfiguration(m_font_list[m_font_selected], m_font_prop, text);
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::load_configuration(const TextConfiguration &configuration)
|
||||
{
|
||||
size_t index = m_font_list.size();
|
||||
for (const auto &font_item : m_font_list) {
|
||||
if (font_item.type == configuration.font_item.type &&
|
||||
font_item.path == configuration.font_item.path) {
|
||||
index = &font_item - &m_font_list.front();
|
||||
}
|
||||
}
|
||||
size_t prev_font_selected = m_font_selected;
|
||||
// when not in font list add to list
|
||||
if (index >= m_font_list.size()) {
|
||||
m_font_selected = m_font_list.size();
|
||||
add_fonts({configuration.font_item});
|
||||
} else {
|
||||
m_font_selected = index;
|
||||
}
|
||||
// When can't load font
|
||||
if (!load_font()) {
|
||||
// remove bad loadabled font, for correct prev index
|
||||
m_font_list.erase(m_font_list.begin() + m_font_selected);
|
||||
m_font_selected = prev_font_selected;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_font_prop = configuration.font_prop;
|
||||
set_text(configuration.text);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GLGizmoEmboss::create_volume_name()
|
||||
{
|
||||
size_t max_len = 20;
|
||||
std::string text((const char *)m_text.get());
|
||||
if (text.size() > max_len)
|
||||
text = text.substr(0, max_len - 3) + " ..";
|
||||
return _u8L("Text") + ": " + text;
|
||||
return _u8L("Text") + " - " + text;
|
||||
}
|
||||
|
||||
// any existing icon filename to not influence GUI
|
||||
|
|
|
@ -37,14 +37,31 @@ protected:
|
|||
virtual void on_set_state() override;
|
||||
|
||||
private:
|
||||
void set_default_configuration();
|
||||
void check_selection();
|
||||
// more general function --> move to select
|
||||
ModelVolume *get_selected_volume();
|
||||
static ModelVolume *get_selected_volume(const Selection &selection, const ModelObjectPtrs objects);
|
||||
void process();
|
||||
void close();
|
||||
void draw_font_list();
|
||||
void draw_add_button();
|
||||
bool load_font();
|
||||
// try to set font_index
|
||||
bool load_font(size_t font_index);
|
||||
void set_text(const std::string &text);
|
||||
void set_max_text_size(size_t size);
|
||||
|
||||
bool choose_font_by_dialog();
|
||||
|
||||
void sort_fonts();
|
||||
void add_fonts(const Emboss::FontList &font_list);
|
||||
void add_fonts(const FontList &font_list);
|
||||
|
||||
bool set_volume();
|
||||
|
||||
// Create object described how to make a Volume
|
||||
TextConfiguration create_configuration();
|
||||
bool load_configuration(const TextConfiguration& configuration);
|
||||
|
||||
std::string create_volume_name();
|
||||
|
||||
|
@ -58,15 +75,15 @@ private:
|
|||
};
|
||||
std::optional<GuiCfg> m_gui_cfg;
|
||||
|
||||
Emboss::FontList m_font_list;
|
||||
size_t m_font_selected;// index to m_font_list
|
||||
FontList m_font_list;
|
||||
size_t m_font_selected;// index to m_font_list
|
||||
|
||||
std::optional<Emboss::Font> m_font;
|
||||
|
||||
size_t m_text_size;
|
||||
std::unique_ptr<char[]> m_text;
|
||||
|
||||
Emboss::FontProp m_font_prop;
|
||||
FontProp m_font_prop;
|
||||
|
||||
// text position
|
||||
struct Orientation
|
||||
|
|
Loading…
Reference in a new issue