Creation by jobs
This commit is contained in:
parent
53ee0092b0
commit
d10fd37b2f
4 changed files with 324 additions and 379 deletions
|
@ -1,6 +1,8 @@
|
|||
#include "EmbossJob.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include <libslic3r/Model.hpp>
|
||||
#include <libslic3r/Format/OBJ.hpp> // load_obj for default mesh
|
||||
#include <libslic3r/BuildVolume.hpp>
|
||||
|
||||
#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<Emboss::ProjectZ>(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<float>());
|
||||
}
|
||||
|
||||
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<RaycastManager::Hit> 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<int>());
|
||||
Polygon bed(bed_shape_);
|
||||
if (!bed.contains(bed_coor.cast<int>()))
|
||||
// mouse pose is out of build plate so create object in center of plate
|
||||
bed_coor = bed.centroid().cast<double>();
|
||||
|
||||
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<Emboss::ProjectZ>(depth);
|
||||
Emboss::ProjectScale project(std::move(projectZ), scale);
|
||||
return TriangleMesh(Emboss::polygons2model(shapes, project));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue