Choose font by wxWidgetDialog

This commit is contained in:
Filip Sykala 2021-09-09 19:36:51 +02:00
parent 578abe4cce
commit 9d52ceee44
6 changed files with 317 additions and 109 deletions
src/slic3r/GUI/Gizmos

View file

@ -8,6 +8,9 @@
#include "libslic3r/Model.hpp"
#include <wx/font.h>
#include <wx/fontdlg.h>
namespace Slic3r::GUI {
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent,
@ -21,7 +24,8 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent,
, m_text_size(255)
, m_text(new char[m_text_size])
, m_scale(0.01f)
, m_emboss(5.f)
, m_emboss(5.f)
, m_volume(nullptr)
{
// TODO: suggest to use https://fontawesome.com/
// (copy & paste) unicode symbols from web
@ -63,18 +67,17 @@ void GLGizmoEmboss::on_render_for_picking() {}
void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
{
if (!m_gui_cfg.has_value()) m_gui_cfg.emplace(GuiCfg());
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse;
m_imgui->begin(on_get_name(), flag);
size_t max_font_name = 20; // count characters
auto& current = m_font_list[m_font_selected];
if (ImGui::BeginCombo("##font_selector", current.name.c_str())) {
for (const Emboss::FontItem &f : m_font_list) {
ImGui::PushID((void*)&f.name);
std::string name = (f.name.size() < max_font_name) ?
f.name : (f.name.substr(0,max_font_name - 3) + " ..");
std::string name = (f.name.size() < m_gui_cfg->max_font_name) ?
f.name : (f.name.substr(0,m_gui_cfg->max_font_name - 3) + " ..");
if (ImGui::Selectable(name.c_str(), &f == &current)) {
m_font_selected = &f - &m_font_list.front();
load_font();
@ -90,28 +93,52 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
ImGui::EndCombo();
}
ImGui::SameLine();
m_imgui->disabled_begin(!m_font.has_value() || m_font->count == 1);
if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) {
for (size_t i = 0; i < m_font->count; ++i) {
ImGui::PushID(1<<10 + i);
if (ImGui::Selectable(std::to_string(i).c_str(), i == m_font->index)) {
m_font->index = i;
if (m_font.has_value()) {
if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) {
for (size_t i = 0; i < m_font->count; ++i) {
ImGui::PushID(1 << 10 + i);
if (ImGui::Selectable(std::to_string(i).c_str(),
i == m_font->index)) {
m_font->index = i;
}
ImGui::PopID();
}
ImGui::PopID();
ImGui::EndCombo();
}
ImGui::EndCombo();
}
m_imgui->disabled_end();
static std::string fontName;
if (ImGui::Button(_L("choose font").c_str())) {
static wxFontData data; // keep last selected font
wxFontDialog font_dialog(nullptr, data);
font_dialog.SetTitle(_L("Select font FFF"));
if (font_dialog.ShowModal() == wxID_OK) {
data = font_dialog.GetFontData();
wxFont font = data.GetChosenFont();
fontName = boost::nowide::narrow(font.GetFaceName());
m_font = Emboss::load_font(font.GetHFONT());
m_font_glyph_cache.clear();
process();
}
}
if (!fontName.empty()) ImGui::Text(fontName.c_str());
ImGui::SameLine();
draw_add_button();
ImGui::InputFloat("Scale", &m_scale);
ImGui::InputFloat("Emboss", &m_emboss);
ImGui::InputFloat("Flatness", &m_font_prop.flatness);
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness))
m_font_glyph_cache.clear();
ImGui::InputInt("CharGap", &m_font_prop.char_gap);
ImGui::InputInt("LineGap", &m_font_prop.line_gap);
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();
m_imgui->disabled_end();
@ -129,12 +156,12 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
}
// change text size
int max_text_size = m_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 < max_text_size-1) {
while ((index+1) < max_text_size) {
if (m_text.get()[index] == '\0') break;
newData.get()[index] = m_text.get()[index];
++index;
@ -165,7 +192,7 @@ void GLGizmoEmboss::on_set_state()
// Closing gizmo. e.g. selecting another one
if (GLGizmoBase::m_state == GLGizmoBase::Off) {
// refuse outgoing during simlification
// refuse outgoing during text preview
if (false) {
GLGizmoBase::m_state = GLGizmoBase::On;
auto notification_manager = wxGetApp().plater()->get_notification_manager();
@ -175,36 +202,115 @@ void GLGizmoEmboss::on_set_state()
_u8L("ERROR: Wait until ends or Cancel process."));
return;
}
m_volume = nullptr;
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
// when open by hyperlink it needs to show up
//request_rerender();
}
}
void GLGizmoEmboss::process() {
auto project = std::make_unique<Emboss::ProjectScale>(
std::make_unique<Emboss::ProjectZ>(m_emboss/m_scale), m_scale);
// IMPROVE: Do not use gizmo_event - especialy smth with prefix SLA,
// use Bind into wxGLCanvas?
bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action,
const Vec2d & mouse_position,
bool shift_down,
bool alt_down,
bool control_down)
{
/* if (action == SLAGizmoEventType::LeftUp) {
const Camera & camera = wxGetApp().plater()->get_camera();
const Selection & selection = m_parent.get_selection();
const ModelObject * mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d & instance_trafo = mi->get_transformation()
.get_matrix();
Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop);
// Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices;
for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part())
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
Vec3f normal = Vec3f::Zero();
Vec3f hit = Vec3f::Zero();
size_t facet = 0;
Vec3f closest_hit = Vec3f::Zero();
double closest_hit_squared_distance =
std::numeric_limits<double>::max();
size_t closest_facet = 0;
int closest_hit_mesh_id = -1;
// Cast a ray on all meshes, pick the closest hit and save it for the
// respective mesh
for (int mesh_id = 0; mesh_id < int(trafo_matrices.size());
++mesh_id) {
if (m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(
mouse_position, trafo_matrices[mesh_id], camera, hit,
normal, m_c->object_clipper()->get_clipping_plane(),
&facet)) {
// In case this hit is clipped, skip it.
// Is this hit the closest to the camera so far?
double hit_squared_distance = (camera.get_position() -
trafo_matrices[mesh_id] *
hit.cast<double>())
.squaredNorm();
if (hit_squared_distance < closest_hit_squared_distance) {
closest_hit_squared_distance = hit_squared_distance;
closest_facet = facet;
closest_hit_mesh_id = mesh_id;
closest_hit = hit;
}
}
}
// get intersection
}
*/
return false;
}
void GLGizmoEmboss::process() {
if (!m_font.has_value()) return;
Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop, m_font_glyph_cache);
if (polygons.empty()) return;
auto project = std::make_unique<Emboss::ProjectScale>(
std::make_unique<Emboss::ProjectZ>(m_emboss/m_scale), m_scale);
indexed_triangle_set its = Emboss::polygons2model(polygons, *project);
if (its.indices.empty()) return;
// add object
TriangleMesh tm(its);
TriangleMesh tm(std::move(its));
tm.repair();
tm.WriteOBJFile("text_preview.obj");
//tm.WriteOBJFile("text_preview.obj");
const Selection &selection = m_parent.get_selection();
int object_idx = selection.get_object_idx();
ModelObject * obj = wxGetApp().plater()->model().objects[object_idx];
ModelVolume * v = obj->volumes.front();
v->set_mesh(tm);
v->set_new_unique_id();
obj->invalidate_bounding_box();
//if (m_volume != nullptr) {
// // TODO: fix index of m_volume
// size_t m_volume_index = obj->volumes.size() - 1;
// obj->delete_volume(m_volume_index);
//}
//m_volume = obj->add_volume(std::move(tm), ModelVolumeType::MODEL_PART);
if (m_volume == nullptr) {
m_volume = obj->add_volume(std::move(tm), ModelVolumeType::MODEL_PART);
} else {
m_volume->set_mesh(std::move(tm));
m_volume->set_new_unique_id();
m_volume->translate(-m_volume->source.mesh_offset);
m_volume->center_geometry_after_creation(true);
m_volume->calculate_convex_hull();
m_volume->get_object()->invalidate_bounding_box();
}
m_parent.reload_scene(true);
}
@ -235,7 +341,7 @@ void GLGizmoEmboss::draw_add_button() {
font_list.emplace_back(name, path);
}
// set last added font as active
m_font_selected = m_font_list.size() - 1;
m_font_selected = m_font_list.size() + font_list.size() - 1;
add_fonts(font_list);
load_font();
}
@ -250,6 +356,7 @@ bool GLGizmoEmboss::load_font()
{
auto font_path = m_font_list[m_font_selected].path.c_str();
m_font = Emboss::load_font(font_path);
m_font_glyph_cache.clear();
return m_font.has_value();
}
@ -279,5 +386,4 @@ void GLGizmoEmboss::add_fonts(const Emboss::FontList &font_list) {
sort_fonts();
}
} // namespace Slic3r::GUI