From d10fd37b2f7245f766fe1331d41b1844073c3636 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Fri, 28 Jan 2022 19:33:57 +0100 Subject: [PATCH] Creation by jobs --- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 328 +----------------------- src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp | 34 +-- src/slic3r/GUI/Jobs/EmbossJob.cpp | 224 +++++++++++++++- src/slic3r/GUI/Jobs/EmbossJob.hpp | 117 +++++++-- 4 files changed, 324 insertions(+), 379 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 5d91666db..cc91d7100 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -114,14 +114,12 @@ static void draw_fine_position(const Selection &selection) } #endif // SHOW_FINE_POSITION -#include "libslic3r/BuildVolume.hpp" void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos) { assert(volume_type == ModelVolumeType::MODEL_PART || volume_type == ModelVolumeType::NEGATIVE_VOLUME || volume_type == ModelVolumeType::PARAMETER_MODIFIER); - if (!m_is_initialized) initialize(); - std::shared_ptr &font_file = m_font_manager.get_font_file(); + if (!m_is_initialized) initialize(); set_default_text(); Vec2d screen_coor = mouse_pos; @@ -135,71 +133,14 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous std::optional object_idx; const Selection &selection = m_parent.get_selection(); if (!selection.is_empty()) object_idx = selection.get_object_idx(); - auto &worker = wxGetApp().plater()->get_ui_job_worker(); - queue_job( worker, [volume_type, - screen_coor, - object_idx, - ff = font_file, - text = m_text, - &raycast_manager = m_raycast_manager, - name = create_volume_name(), - tc = create_configuration(), - fi = m_font_manager.get_font_item() - ](Job::Ctl &ctl) { - // It is neccessary to create some shape - // Emboss text window is opened by creation new embosstext object - TriangleMesh tm = (ff == nullptr) ? - create_default_mesh() : - create_mesh(text.c_str(), *ff, fi.prop); - if (tm.its.empty()) tm = create_default_mesh(); - if (ctl.was_canceled()) return; - - std::optional hit; - if (object_idx.has_value()) { - // By position of cursor create transformation to put text on surface of model - const ModelObjectPtrs &objects = wxGetApp().plater()->model().objects; - raycast_manager.actualize(objects); - if (ctl.was_canceled()) return; - hit = raycast_manager.unproject(screen_coor); - - // context menu for add text could be open only by right click on an object. - // After right click, object is selected and object_idx is set also hit must exist. - // But there is proper behavior when hit doesn't exists. - // When this assert appear distquish remove of it. - assert(hit.has_value()); - } - - if (!hit.has_value()) { - // create new object - // calculate X,Y offset position for lay on platter in place of - // mouse click - const Camera &camera = wxGetApp().plater()->get_camera(); - Vec2d bed_coor = CameraUtils::get_z0_position(camera, screen_coor); - - // check point is on build plate: - Pointfs bed_shape = wxGetApp().plater()->build_volume().bed_shape(); - Points bed_shape_; - bed_shape_.reserve(bed_shape.size()); - for (const Vec2d &p : bed_shape) - bed_shape_.emplace_back(p.cast()); - Polygon bed(bed_shape_); - if (!bed.contains(bed_coor.cast())) - // mouse pose is out of build plate so create object in center of plate - bed_coor = bed.centroid().cast(); - - double z = tc.font_item.prop.emboss / 2; - Vec3d offset(bed_coor.x(), bed_coor.y(), z); - offset -= tm.center(); - Transform3d::TranslationType tt(offset.x(), offset.y(), offset.z()); - Transform3d trmat(tt); - create_emboss_object(std::move(tm), trmat, name, tc); - // Gizmo will open when successfuly create new object - // Gizmo can't be open when selection is empty - } else { - Transform3d transformation = Emboss::create_transformation_onto_surface(hit->position, hit->normal); - create_emboss_volume(std::move(tm), transformation, name, tc, volume_type, *object_idx); - } - }); + auto data = + std::make_unique(m_font_manager.get_font_file(), + create_configuration(), + create_volume_name(), volume_type, + screen_coor, object_idx, + &m_raycast_manager); + auto &worker = wxGetApp().plater()->get_ui_job_worker(); + queue_job(worker, std::make_unique(std::move(data))); } #ifdef DRAW_PLACE_TO_ADD_TEXT @@ -561,42 +502,6 @@ void GLGizmoEmboss::set_default_text() m_text = _u8L("Embossed text"); } -Slic3r::TriangleMesh GLGizmoEmboss::create_default_mesh() -{ - // When cant load any font use default object loaded from file - std::string path = Slic3r::resources_dir() + "/data/embossed_text.stl"; - TriangleMesh triangle_mesh; - if (!load_obj(path.c_str(), &triangle_mesh)) { - // when can't load mesh use cube - return TriangleMesh(its_make_cube(36., 4., 2.5)); - } - return triangle_mesh; -} - -Slic3r::TriangleMesh GLGizmoEmboss::create_mesh() -{ - // It is neccessary to create some shape - // Emboss text window is opened by creation new embosstext object - std::shared_ptr& font_file = m_font_manager.get_font_file(); - if (font_file == nullptr) return create_default_mesh(); - const FontItem &fi = m_font_manager.get_font_item(); - TriangleMesh result = create_mesh(m_text.c_str(), *font_file, fi.prop); - if (result.its.empty()) return create_default_mesh(); - return result; -} - -Slic3r::TriangleMesh GLGizmoEmboss::create_mesh(const char * text, - Emboss::FontFile &font, - const FontProp & font_prop) -{ - ExPolygons shapes = Emboss::text2shapes(font, text, font_prop); - float scale = font_prop.size_in_mm / font.ascent; - float depth = font_prop.emboss / scale; - auto projectZ = std::make_unique(depth); - Emboss::ProjectScale project(std::move(projectZ), scale); - return TriangleMesh(Emboss::polygons2model(shapes, project)); -} - #include "imgui/imgui_internal.h" // to unfocus input --> ClearActiveID void GLGizmoEmboss::check_selection() { @@ -665,12 +570,12 @@ bool GLGizmoEmboss::process() // exist loaded font? std::shared_ptr& font_file = m_font_manager.get_font_file(); if (font_file == nullptr) return false; - auto data = std::make_unique(font_file, + auto data = std::make_unique(font_file, create_configuration(), create_volume_name(), m_volume); auto &worker = wxGetApp().plater()->get_ui_job_worker(); - replace_job(worker, std::make_unique(std::move(data))); + replace_job(worker, std::make_unique(std::move(data))); // notification is removed befor object is changed by job remove_notification_not_valid_font(); @@ -1672,216 +1577,5 @@ std::string GLGizmoEmboss::get_file_name(const std::string &file_path) return file_path.substr(offset, count); } -namespace Slic3r::GUI { - -class Priv -{ -public: - Priv() = delete; - struct EmbossObject - { - TriangleMesh mesh; - Transform3d transformation; - std::string name; - TextConfiguration cfg; - EmbossObject(TriangleMesh && mesh, - const Transform3d& transformation, - const std::string& name, - const TextConfiguration& cfg) - : mesh(std::move(mesh)) - , transformation(transformation) // copy - , name(name) // copy - , cfg(cfg) // copy - {} - }; - struct EmbossVolume : public EmbossObject - { - ModelVolumeType type; - size_t object_idx; - EmbossVolume(TriangleMesh && mesh, - const Transform3d& transformation, - const std::string& name, - const TextConfiguration& cfg, - ModelVolumeType type, - size_t object_idx) - : EmbossObject(std::move(mesh), transformation, name, cfg) - , type(type) - , object_idx(object_idx) - {} - }; - static void create_emboss_object(EmbossObject &data); - static void create_emboss_volume(EmbossVolume &data); -}; - -} // namespace Slic3r - -void GLGizmoEmboss::create_emboss_object(TriangleMesh &&mesh, - const Transform3d& transformation, - const std::string& name, - const TextConfiguration& cfg) -{ - // Move data to call after is not working - // data are owned by lambda - auto data = new Priv::EmbossObject(std::move(mesh), transformation, name, cfg); - wxGetApp().plater()->CallAfter([data]() { - ScopeGuard sg([data]() { delete data; }); - Priv::create_emboss_object(*data); - }); -} - -void GLGizmoEmboss::create_emboss_volume(TriangleMesh && mesh, - Transform3d transformation, - std::string name, - TextConfiguration cfg, - ModelVolumeType type, - size_t object_idx) -{ - // Move data to call after is not working - // data are owen by lambda - auto data = new Priv::EmbossVolume(std::move(mesh), transformation, name, cfg, type, object_idx); - wxGetApp().plater()->CallAfter([data]() { - ScopeGuard sg([data]() { delete data; }); - Priv::create_emboss_volume(*data); - }); -} - -void Priv::create_emboss_object(EmbossObject &data) -{ - GUI_App & app = wxGetApp(); - Plater * plater = app.plater(); - ObjectList * obj_list = app.obj_list(); - GLCanvas3D * canvas = plater->canvas3D(); - - plater->take_snapshot(_L("Add Emboss text object")); - // Create new object and change selection - bool center = false; - obj_list->load_mesh_object(std::move(data.mesh), data.name, center, &data.cfg, &data.transformation); - - // When add new object selection is empty. - // Gizmo is automaticaly close when Selection is empty - // new object successfuly added so open gizmo when it was closed - GLGizmosManager &manager = canvas->get_gizmos_manager(); - if(manager.get_current_type() != GLGizmosManager::Emboss) - manager.open_gizmo(GLGizmosManager::Emboss); - - // redraw scene - canvas->reload_scene(true); - - // Gizmo is not open during time of creation object - // When cursor move and no one object is selected than Manager::reset_all() -} - -void Priv::create_emboss_volume(EmbossVolume &data) -{ - GUI_App & app = wxGetApp(); - Plater * plater = app.plater(); - ObjectList *obj_list = app.obj_list(); - GLCanvas3D *canvas = plater->canvas3D(); - - size_t object_idx = data.object_idx; - ModelVolumeType type = data.type; - - // create new volume inside of object - Model &model = plater->model(); - if (model.objects.size() <= object_idx) return; - ModelObject *obj = model.objects[object_idx]; - ModelVolume *volume = obj->add_volume(std::move(data.mesh)); - - // set a default extruder value, since user can't add it manually - volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - - // do not allow model reload from disk - volume->source.is_from_builtin_objects = true; - volume->set_type(type); - volume->name = data.name; - volume->text_configuration = data.cfg; - volume->set_transformation(data.transformation); - - // update volume name in object list - // updata selection after new volume added - // change name of volume in right panel - // select only actual volume - // when new volume is created change selection to this volume - auto add_to_selection = [volume](const ModelVolume *vol) { - return vol == volume; - }; - wxDataViewItemArray sel = - obj_list->reorder_volumes_and_get_selection((int) object_idx, - add_to_selection); - if (!sel.IsEmpty()) obj_list->select_item(sel.front()); - - // update printable state on canvas - if (type == ModelVolumeType::MODEL_PART) - canvas->update_instance_printable_state_for_object(object_idx); - - obj_list->selection_changed(); - - // WHY selection_changed set manipulation to world ??? - // so I set it back to local --> RotationGizmo need it - ObjectManipulation *manipul = wxGetApp().obj_manipul(); - manipul->set_coordinates_type(ECoordinatesType::Local); - - - // redraw scene - canvas->reload_scene(true); -} - -void GLGizmoEmboss::update_emboss_volume(TriangleMesh && mesh, - const std::string& name, - const TextConfiguration& cfg, - ModelVolume * volume) -{ - // for sure that some object is created from shape - if (mesh.its.indices.empty()) return; - - GUI_App & app = wxGetApp(); // may be move to input - Plater * plater = app.plater(); - ObjectList * obj_list = app.obj_list(); - GLCanvas3D * canvas = plater->canvas3D(); - GLGizmosManager &manager = canvas->get_gizmos_manager(); - - // Check emboss gizmo is still open - if (manager.get_current_type() != GLGizmosManager::Emboss) return; - - plater->take_snapshot(_L("Emboss text") + ": " + name); - - // find volume by object id - NOT WORK - // -> edit text change volume id so could apper not found volume - // ModelVolume *volume = nullptr; - // Model &model = plater->model(); - // for (auto obj : model.objects) - // for (auto vol : obj->volumes) - // if (vol->id() == volume_id) { - // volume = vol; - // break; - // } - // if (volume == nullptr) return; - assert(volume != nullptr); - - // update volume - volume->set_mesh(std::move(mesh)); - volume->set_new_unique_id(); - volume->calculate_convex_hull(); - volume->get_object()->invalidate_bounding_box(); - volume->name = name; - volume->text_configuration = cfg; - - // update volume in right panel( volume / object name) - const Selection &selection = canvas->get_selection(); - const GLVolume * gl_volume = selection.get_volume( - *selection.get_volume_idxs().begin()); - int object_idx = gl_volume->object_idx(); - int volume_idx = gl_volume->volume_idx(); - obj_list->update_name_in_list(object_idx, volume_idx); - - // update printable state on canvas - if (volume->type() == ModelVolumeType::MODEL_PART) - canvas->update_instance_printable_state_for_object( - (size_t) object_idx); - - // redraw scene - canvas->reload_scene(true); -} - // any existing icon filename to not influence GUI const std::string GLGizmoEmboss::M_ICON_FILENAME = "cut.svg"; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp index 91a65b507..fb5ba2312 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp @@ -28,12 +28,10 @@ namespace Slic3r{ } namespace Slic3r::GUI { -class EmbossJob; class MeshRaycaster; class GLGizmoEmboss : public GLGizmoBase -{ - friend EmbossJob; +{ public: GLGizmoEmboss(GLCanvas3D& parent); @@ -76,20 +74,6 @@ protected: private: void initialize(); void set_default_text(); - static TriangleMesh create_default_mesh(); - TriangleMesh create_mesh(); - - /// - /// Create mesh from text - /// - /// Text to convert on mesh - /// Define shape of characters. - /// NOTE: Can't be const cache glyphs - /// Property of font - /// Triangle mesh model - static TriangleMesh create_mesh(const char * text, - Emboss::FontFile & font, - const FontProp &font_prop); void check_selection(); // more general function --> move to select @@ -219,22 +203,6 @@ private: void store_font_list_to_app_config() const; void store_font_item_to_app_config() const; - // call after functions to work outside of drawing - static void create_emboss_object(TriangleMesh && mesh, - const Transform3d &transformation, - const std::string &name, - const TextConfiguration &cfg); - static void create_emboss_volume(TriangleMesh && mesh, - Transform3d transformation, - std::string name, - TextConfiguration cfg, - ModelVolumeType type, - size_t object_idx); - static void update_emboss_volume(TriangleMesh && mesh, - const std::string & name, - const TextConfiguration &cfg, - ModelVolume * volume); - // only temporary solution static const std::string M_ICON_FILENAME; diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp index adaf4bbc5..9082568c3 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.cpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp @@ -1,6 +1,8 @@ #include "EmbossJob.hpp" -#include "libslic3r/Model.hpp" +#include +#include // load_obj for default mesh +#include #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/NotificationManager.hpp" @@ -9,12 +11,15 @@ #include "slic3r/GUI/MainFrame.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/Gizmos/GLGizmoEmboss.hpp" +#include "slic3r/GUI/CameraUtils.hpp" using namespace Slic3r; using namespace GUI; -void EmbossJob::process(Ctl &ctl) { +void EmbossUpdateJob::process(Ctl &ctl) +{ // Changing cursor to busy must be inside main thread // GTK is not thread safe. //wxBeginBusyCursor(); @@ -24,7 +29,7 @@ void EmbossJob::process(Ctl &ctl) { assert(m_input != nullptr); // check if exist valid font - if (m_input->font == nullptr) return; + if (m_input->font_file == nullptr) return; const TextConfiguration &cfg = m_input->text_configuration; const std::string & text = cfg.text; @@ -32,7 +37,7 @@ void EmbossJob::process(Ctl &ctl) { if (text.empty()) return; const FontProp &prop = cfg.font_item.prop; - ExPolygons shapes = Emboss::text2shapes(*m_input->font, text.c_str(), prop); + ExPolygons shapes = Emboss::text2shapes(*m_input->font_file, text.c_str(), prop); if (ctl.was_canceled()) return; @@ -40,7 +45,7 @@ void EmbossJob::process(Ctl &ctl) { // (no shape means that font hasn't any of text symbols) if (shapes.empty()) return; - float scale = prop.size_in_mm / m_input->font->ascent; + float scale = prop.size_in_mm / m_input->font_file->ascent; auto projectZ = std::make_unique(prop.emboss / scale); Emboss::ProjectScale project(std::move(projectZ), scale); m_result = TriangleMesh(Emboss::polygons2model(shapes, project)); @@ -52,14 +57,213 @@ void EmbossJob::process(Ctl &ctl) { m_result.translate(-shift.cast()); } -void EmbossJob::finalize(bool canceled, std::exception_ptr &) { +void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &) +{ if (canceled) return; // for sure that some object is created from shape if (m_result.its.indices.empty()) return; - GLGizmoEmboss::update_emboss_volume(std::move(m_result), - m_input->volume_name, - m_input->text_configuration, - m_input->volume); + GUI_App & app = wxGetApp(); // may be move to input + Plater * plater = app.plater(); + ObjectList * obj_list = app.obj_list(); + GLCanvas3D * canvas = plater->canvas3D(); + GLGizmosManager &manager = canvas->get_gizmos_manager(); + + // Check emboss gizmo is still open + if (manager.get_current_type() != GLGizmosManager::Emboss) return; + + plater->take_snapshot(_L("Emboss text") + ": " + m_input->volume_name); + + ModelVolume *volume = m_input->volume; + // find volume by object id - NOT WORK + // -> edit text change volume id so could apper not found volume + // ModelVolume *volume = nullptr; + // Model &model = plater->model(); + // for (auto obj : model.objects) + // for (auto vol : obj->volumes) + // if (vol->id() == volume_id) { + // volume = vol; + // break; + // } + // if (volume == nullptr) return; + assert(volume != nullptr); + + // update volume + volume->set_mesh(std::move(m_result)); + volume->set_new_unique_id(); + volume->calculate_convex_hull(); + volume->get_object()->invalidate_bounding_box(); + volume->name = m_input->volume_name; + volume->text_configuration = m_input->text_configuration; + + // update volume in right panel( volume / object name) + const Selection &selection = canvas->get_selection(); + const GLVolume * gl_volume = selection.get_volume( + *selection.get_volume_idxs().begin()); + int object_idx = gl_volume->object_idx(); + int volume_idx = gl_volume->volume_idx(); + obj_list->update_name_in_list(object_idx, volume_idx); + + // update printable state on canvas + if (volume->type() == ModelVolumeType::MODEL_PART) + canvas->update_instance_printable_state_for_object( + (size_t) object_idx); + + // redraw scene + canvas->reload_scene(true); } + +void EmbossCreateJob::process(Ctl &ctl) { + // It is neccessary to create some shape + // Emboss text window is opened by creation new emboss text object + m_result = (m_input->font_file == nullptr) ? + create_default_mesh() : + create_mesh(m_input->text_configuration.text.c_str(), + *m_input->font_file, + m_input->text_configuration.font_item.prop); + if (m_result.its.empty()) m_result = create_default_mesh(); + if (ctl.was_canceled()) return; + + Plater * plater = wxGetApp().plater(); // may be move to input + + std::optional hit; + if (m_input->object_idx.has_value()) { + // By position of cursor create transformation to put text on surface of model + const ModelObjectPtrs &objects = wxGetApp().plater()->model().objects; + m_input->raycast_manager->actualize(objects); + if (ctl.was_canceled()) return; + hit = m_input->raycast_manager->unproject(m_input->screen_coor); + + // context menu for add text could be open only by right click on an + // object. After right click, object is selected and object_idx is set + // also hit must exist. But there is proper behavior when hit doesn't + // exists. When this assert appear distquish remove of it. + assert(hit.has_value()); + if (!hit.has_value()) m_input->object_idx.reset(); + } + if (!hit.has_value()) { + // create new object + // calculate X,Y offset position for lay on platter in place of + // mouse click + const Camera &camera = plater->get_camera(); + Vec2d bed_coor = CameraUtils::get_z0_position(camera, m_input->screen_coor); + + // check point is on build plate: + Pointfs bed_shape = plater->build_volume().bed_shape(); + Points bed_shape_; + bed_shape_.reserve(bed_shape.size()); + for (const Vec2d &p : bed_shape) + bed_shape_.emplace_back(p.cast()); + Polygon bed(bed_shape_); + if (!bed.contains(bed_coor.cast())) + // mouse pose is out of build plate so create object in center of plate + bed_coor = bed.centroid().cast(); + + double z = m_input->text_configuration.font_item.prop.emboss / 2; + Vec3d offset(bed_coor.x(), bed_coor.y(), z); + offset -= m_result.center(); + Transform3d::TranslationType tt(offset.x(), offset.y(), offset.z()); + m_transformation = Transform3d(tt); + } else { + m_transformation = Emboss::create_transformation_onto_surface( + hit->position, hit->normal); + } +} + +void EmbossCreateJob::finalize(bool canceled, std::exception_ptr &) +{ + if (canceled) return; + + GUI_App & app = wxGetApp(); + Plater * plater = app.plater(); + ObjectList *obj_list = app.obj_list(); + GLCanvas3D *canvas = plater->canvas3D(); + + // decide if create object or volume + bool create_object = !m_input->object_idx.has_value(); + if (create_object) { + plater->take_snapshot(_L("Add Emboss text object")); + // Create new object and change selection + bool center = false; + obj_list->load_mesh_object(std::move(m_result), m_input->volume_name, center, + &m_input->text_configuration, &m_transformation); + + // When add new object selection is empty. + // When cursor move and no one object is selected than Manager::reset_all() + // So Gizmo could be closed on end of creation object + GLGizmosManager &manager = canvas->get_gizmos_manager(); + if (manager.get_current_type() != GLGizmosManager::Emboss) + manager.open_gizmo(GLGizmosManager::Emboss); + } else { + // create volume in object + size_t object_idx = *m_input->object_idx; + ModelVolumeType type = m_input->volume_type; + + // create new volume inside of object + Model &model = plater->model(); + if (model.objects.size() <= object_idx) return; + ModelObject *obj = model.objects[object_idx]; + ModelVolume *volume = obj->add_volume(std::move(m_result)); + + // set a default extruder value, since user can't add it manually + volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + + // do not allow model reload from disk + volume->source.is_from_builtin_objects = true; + volume->set_type(type); + volume->name = m_input->volume_name; + volume->text_configuration = m_input->text_configuration; + volume->set_transformation(m_transformation); + + // update volume name in object list + // updata selection after new volume added + // change name of volume in right panel + // select only actual volume + // when new volume is created change selection to this volume + auto add_to_selection = [volume](const ModelVolume *vol) { + return vol == volume; + }; + wxDataViewItemArray sel = + obj_list->reorder_volumes_and_get_selection((int) object_idx, + add_to_selection); + if (!sel.IsEmpty()) obj_list->select_item(sel.front()); + + // update printable state on canvas + if (type == ModelVolumeType::MODEL_PART) + canvas->update_instance_printable_state_for_object(object_idx); + + obj_list->selection_changed(); + + // WHY selection_changed set manipulation to world ??? + // so I set it back to local --> RotationGizmo need it + ObjectManipulation *manipul = wxGetApp().obj_manipul(); + manipul->set_coordinates_type(ECoordinatesType::Local); + } + // redraw scene + canvas->reload_scene(true); +} + +TriangleMesh EmbossCreateJob::create_default_mesh() +{ + // When cant load any font use default object loaded from file + std::string path = Slic3r::resources_dir() + "/data/embossed_text.stl"; + TriangleMesh triangle_mesh; + if (!load_obj(path.c_str(), &triangle_mesh)) { + // when can't load mesh use cube + return TriangleMesh(its_make_cube(36., 4., 2.5)); + } + return triangle_mesh; +} + +TriangleMesh EmbossCreateJob::create_mesh(const char * text, + Emboss::FontFile &font, + const FontProp & font_prop) +{ + ExPolygons shapes = Emboss::text2shapes(font, text, font_prop); + float scale = font_prop.size_in_mm / font.ascent; + float depth = font_prop.emboss / scale; + auto projectZ = std::make_unique(depth); + Emboss::ProjectScale project(std::move(projectZ), scale); + return TriangleMesh(Emboss::polygons2model(shapes, project)); +} \ No newline at end of file diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp index bf7c03b87..6ec2d35df 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.hpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp @@ -1,7 +1,9 @@ #ifndef slic3r_EmbossJob_hpp_ #define slic3r_EmbossJob_hpp_ -#include "libslic3r/Emboss.hpp" +#include +#include +#include "slic3r/Utils/RaycastManager.hpp" #include "Job.hpp" namespace Slic3r { @@ -11,42 +13,119 @@ class TriangleMesh; namespace Slic3r::GUI { -struct EmbossData +struct EmbossDataUpdate; +struct EmbossDataCreate; + +class EmbossUpdateJob : public Job +{ + std::unique_ptr m_input; + TriangleMesh m_result; +public: + EmbossUpdateJob(std::unique_ptr input) : m_input(std::move(input)) {} + void process(Ctl &ctl) override; + void finalize(bool canceled, std::exception_ptr &) override; +}; + +class EmbossCreateJob : public Job +{ + std::unique_ptr m_input; + TriangleMesh m_result; + Transform3d m_transformation; +public: + EmbossCreateJob(std::unique_ptr input): m_input(std::move(input)){} + void process(Ctl &ctl) override; + void finalize(bool canceled, std::exception_ptr &) override; + +private: + static TriangleMesh create_default_mesh(); + + /// + /// Create mesh from text + /// + /// Text to convert on mesh + /// Define shape of characters. + /// NOTE: Can't be const cache glyphs + /// Property of font + /// Triangle mesh model + static TriangleMesh create_mesh(const char * text, + Emboss::FontFile &font, + const FontProp & font_prop); +}; + + +/// +/// Base data holder for embossing +/// +struct EmbossDataBase { // Pointer on Data of font (glyph shapes) - std::shared_ptr font; + std::shared_ptr font_file; // font item is not used for create object TextConfiguration text_configuration; // new volume name created from text std::string volume_name; + EmbossDataBase(std::shared_ptr font_file, + TextConfiguration text_configuration, + std::string volume_name) + : font_file(std::move(font_file)) + , text_configuration(text_configuration) + , volume_name(volume_name) + {} +}; +/// +/// Hold neccessary data to update embossed text object in job +/// +struct EmbossDataUpdate : public EmbossDataBase +{ // unique identifier of volume to change // I can't proove of alive pointer ModelVolume *volume; // unique identifier of volume to change // Change of volume change id, last change could disapear - //ObjectID volume_id; - - EmbossData(std::shared_ptr font, - TextConfiguration text_configuration, - std::string volume_name, - ModelVolume * volume) - : font(std::move(font)) - , text_configuration(text_configuration) - , volume_name(volume_name) + // ObjectID volume_id; + EmbossDataUpdate(std::shared_ptr font_file, + TextConfiguration text_configuration, + std::string volume_name, + ModelVolume * volume) + : EmbossDataBase(std::move(font_file), text_configuration, volume_name) , volume(volume) {} }; -class EmbossJob : public Job +/// +/// Hold neccessary data to create embossed text object in job +/// +struct EmbossDataCreate: public EmbossDataBase { - std::unique_ptr m_input; - TriangleMesh m_result; -public: - EmbossJob(std::unique_ptr input) : m_input(std::move(input)) {} - void process(Ctl &ctl) override; - void finalize(bool canceled, std::exception_ptr &) override; + // define embossed volume type + ModelVolumeType volume_type; + + // define position on screen where to create object + Vec2d screen_coor; + + // when exist ModelObject where to create volume + std::optional object_idx; + + // used to find point on surface where to create new object + RaycastManager *raycast_manager; + // It is inside of GLGizmoEmboss object, + // so I hope it will survive + + EmbossDataCreate(std::shared_ptr font_file, + const TextConfiguration & text_configuration, + const std::string & volume_name, + ModelVolumeType volume_type, + Vec2d screen_coor, + std::optional object_idx, + RaycastManager * raycast_manager) + : EmbossDataBase(std::move(font_file), text_configuration, volume_name) + , volume_type(volume_type) + , screen_coor(screen_coor) + , object_idx(object_idx) + , raycast_manager(raycast_manager) + {} }; } // namespace Slic3r::GUI