mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-08-05 20:36:06 +08:00
NEW:reeedit text and keep old pose
jira: none Change-Id: If0051293d23f4f4f57c5ed28688e97220521df90 (cherry picked from commit 37bb124eb45cb3d94404ce3e3789e82c8d01207c)
This commit is contained in:
parent
496d69f9d1
commit
837c962dfb
@ -231,6 +231,7 @@ static constexpr const char* SLICE_HEADER_ITEM_TAG = "header_item";
|
||||
static constexpr const char* TEXT_INFO_TAG = "text_info";
|
||||
static constexpr const char* TEXT_ATTR = "text";
|
||||
static constexpr const char* FONT_NAME_ATTR = "font_name";
|
||||
static constexpr const char *FONT_VERSION_ATTR = "font_version";
|
||||
static constexpr const char* FONT_INDEX_ATTR = "font_index";
|
||||
static constexpr const char* FONT_SIZE_ATTR = "font_size";
|
||||
static constexpr const char* THICKNESS_ATTR = "thickness";
|
||||
@ -4410,6 +4411,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
TextInfo text_info;
|
||||
text_info.m_text = xml_unescape(bbs_get_attribute_value_string(attributes, num_attributes, TEXT_ATTR));
|
||||
text_info.m_font_name = bbs_get_attribute_value_string(attributes, num_attributes, FONT_NAME_ATTR);
|
||||
text_info.m_font_version = bbs_get_attribute_value_string(attributes, num_attributes, FONT_VERSION_ATTR);
|
||||
|
||||
text_info.m_curr_font_idx = bbs_get_attribute_value_int(attributes, num_attributes, FONT_INDEX_ATTR);
|
||||
|
||||
@ -4658,7 +4660,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
if (triangle_mesh.volume() < 0)
|
||||
triangle_mesh.flip_triangles();
|
||||
|
||||
volume = object.add_volume(std::move(triangle_mesh));
|
||||
bool is_text = !volume_data->text_info.m_text.empty();
|
||||
bool modify_to_center_geometry = is_text ? false : true;//text do not modify_to_center_geometry
|
||||
volume = object.add_volume(std::move(triangle_mesh), ModelVolumeType::MODEL_PART, modify_to_center_geometry);
|
||||
|
||||
if (shared_mesh_id != -1)
|
||||
//for some cases the shared mesh is in other plate and not loaded in cli slicing
|
||||
@ -7320,6 +7324,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
|
||||
stream << TEXT_ATTR << "=\"" << xml_escape(text_info.m_text) << "\" ";
|
||||
stream << FONT_NAME_ATTR << "=\"" << text_info.m_font_name << "\" ";
|
||||
stream << FONT_VERSION_ATTR << "=\"" << text_info.m_font_version << "\" ";
|
||||
|
||||
stream << FONT_INDEX_ATTR << "=\"" << text_info.m_curr_font_idx << "\" ";
|
||||
|
||||
|
@ -816,6 +816,7 @@ struct RaycastResult
|
||||
struct TextInfo
|
||||
{
|
||||
std::string m_font_name;
|
||||
std::string m_font_version;
|
||||
float m_font_size = 16.f;
|
||||
int m_curr_font_idx = 0;
|
||||
bool m_bold = true;
|
||||
@ -830,7 +831,8 @@ struct TextInfo
|
||||
|
||||
RaycastResult m_rr;
|
||||
template<typename Archive> void serialize(Archive &ar) {
|
||||
ar(m_font_name, m_font_size, m_curr_font_idx, m_bold, m_italic, m_thickness, m_embeded_depth, m_rotate_angle, m_text_gap, m_is_surface_text, m_keep_horizontal, m_text, m_rr);
|
||||
ar(m_font_name, m_font_version, m_font_size, m_curr_font_idx, m_bold, m_italic, m_thickness, m_embeded_depth, m_rotate_angle, m_text_gap, m_is_surface_text,
|
||||
m_keep_horizontal, m_text, m_rr);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1027,7 +1029,7 @@ public:
|
||||
|
||||
void set_text_info(const TextInfo& text_info) { m_text_info = text_info; }
|
||||
const TextInfo& get_text_info() const { return m_text_info; }
|
||||
|
||||
bool is_text() const { return !m_text_info.m_text.empty(); }
|
||||
const Transform3d &get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
|
||||
void set_new_unique_id() {
|
||||
ObjectBase::set_new_unique_id();
|
||||
|
@ -4582,12 +4582,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
continue;
|
||||
const ModelVolume *hover_volume = hover_object->volumes[hover_volume_idx];
|
||||
|
||||
/* if (hover_volume->text_configuration.has_value()) {
|
||||
if (hover_volume->is_text()) {
|
||||
m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
|
||||
if (type != GLGizmosManager::EType::Text)
|
||||
m_gizmos.open_gizmo(GLGizmosManager::EType::Text);
|
||||
wxGetApp().obj_list()->update_selections();
|
||||
return;
|
||||
}
|
||||
/* else if (hover_volume->text_configuration.has_value()) {
|
||||
m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
|
||||
if (type != GLGizmosManager::EType::Emboss) m_gizmos.open_gizmo(GLGizmosManager::EType::Emboss);
|
||||
wxGetApp().obj_list()->update_selections();
|
||||
return;
|
||||
} else*/ if (hover_volume->emboss_shape.has_value()) {
|
||||
}*/
|
||||
else if(hover_volume->emboss_shape.has_value()){
|
||||
m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
|
||||
if (type != GLGizmosManager::EType::Svg)
|
||||
m_gizmos.open_gizmo(GLGizmosManager::EType::Svg);
|
||||
|
@ -396,12 +396,69 @@ void GLGizmoText::on_set_state()
|
||||
if (m_state == EState::On) {
|
||||
m_last_text_mv = nullptr;
|
||||
m_need_fix = false;
|
||||
m_show_text_normal_reset_tip = false;
|
||||
load_init_text();
|
||||
if (m_last_text_mv) {
|
||||
m_reedit_text = true;
|
||||
m_need_fix = true;
|
||||
m_load_text_tran_in_object = m_text_tran_in_object;
|
||||
if (m_really_use_surface_calc) {
|
||||
m_show_warning_regenerated = true;
|
||||
m_need_fix = false;
|
||||
use_fix_normal_position();
|
||||
} else if (m_fix_old_tran_flag && m_font_version == "") {
|
||||
m_show_warning_old_tran = false;
|
||||
auto offset = m_text_tran_in_object.get_offset();
|
||||
auto rotation = m_text_tran_in_object.get_rotation();
|
||||
float eps = 0.01f;
|
||||
int count = 0;
|
||||
bool has_rotation = rotation.norm() > eps;
|
||||
count += has_rotation ? 1 : 0;
|
||||
auto scaling_factor = m_text_tran_in_object.get_scaling_factor();
|
||||
bool has_scale = (scaling_factor - Vec3d(1, 1, 1)).norm() > eps;
|
||||
count += has_scale ? 1 : 0;
|
||||
auto mirror = m_text_tran_in_object.get_mirror();
|
||||
bool has_mirror = (mirror - Vec3d(1, 1, 1)).norm() > eps;
|
||||
count += has_mirror ? 1 : 0;
|
||||
|
||||
Geometry::Transformation expert_text_tran_in_world;
|
||||
generate_text_tran_in_world(m_fix_text_normal_in_world.cast<double>(), m_text_position_in_world, m_rotate_angle, expert_text_tran_in_world);
|
||||
auto temp_expert_text_tran_in_object = m_object_cs_to_world_tran.inverse() * expert_text_tran_in_world.get_matrix();
|
||||
Geometry::Transformation expert_text_tran_in_object(temp_expert_text_tran_in_object);
|
||||
expert_text_tran_in_object.set_offset(m_text_tran_in_object.get_offset());
|
||||
|
||||
if (count >= 2) {
|
||||
m_show_warning_old_tran = true;
|
||||
}
|
||||
if (m_is_version1_10_xoy) {
|
||||
auto rotate_tran = Geometry::assemble_transform(Vec3d::Zero(), {0.5 * M_PI, 0.0, 0.0});
|
||||
m_load_text_tran_in_object.set_from_transform(m_load_text_tran_in_object.get_matrix() * rotate_tran);
|
||||
return;
|
||||
}
|
||||
//go on
|
||||
if (has_rotation && m_show_warning_old_tran == false) {
|
||||
m_show_warning_lost_rotate = true;
|
||||
m_need_fix = false;
|
||||
use_fix_normal_position();
|
||||
}
|
||||
//not need set set_rotation//has_rotation
|
||||
if (has_scale) {
|
||||
expert_text_tran_in_object.set_scaling_factor(scaling_factor);
|
||||
}
|
||||
if (has_mirror) {
|
||||
expert_text_tran_in_object.set_mirror(mirror);
|
||||
}
|
||||
m_load_text_tran_in_object.set_from_transform(expert_text_tran_in_object.get_matrix());
|
||||
if (m_is_version1_9_xoz) {
|
||||
m_load_text_tran_in_object.set_offset(m_load_text_tran_in_object.get_offset() + Vec3d(0, -1.75, -1));//for size 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_state == EState::Off) {
|
||||
m_show_warning = false;
|
||||
m_show_text_normal_error = false;
|
||||
m_edit_text_again = false;
|
||||
m_reedit_text = false;
|
||||
m_fix_old_tran_flag = false;
|
||||
close_warning_flag_after_close_or_drag();
|
||||
reset_text_info();
|
||||
delete_temp_preview_text_volume();
|
||||
m_parent.use_slope(false);
|
||||
@ -409,6 +466,47 @@ void GLGizmoText::on_set_state()
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoText::check_text_type(bool is_surface_text, bool is_keep_horizontal) {
|
||||
if (is_surface_text && is_keep_horizontal) {
|
||||
m_text_type = TextType::SURFACE_HORIZONAL;
|
||||
} else if (is_surface_text) {
|
||||
m_text_type = TextType::SURFACE;
|
||||
} else if (is_keep_horizontal) {
|
||||
m_text_type = TextType::HORIZONAL;
|
||||
} else {
|
||||
m_text_type = TextType::HORIZONAL;
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoText::generate_text_tran_in_world(const Vec3d &text_normal_in_world, const Vec3d &text_position_in_world,float rotate_degree, Geometry::Transformation &cur_tran)
|
||||
{
|
||||
Vec3d temp_normal = text_normal_in_world;
|
||||
Vec3d cut_plane_in_world = Vec3d::UnitY();
|
||||
double epson = 1e-6;
|
||||
if (!(abs(temp_normal.x()) <= epson && abs(temp_normal.y()) <= epson && abs(temp_normal.z()) > epson)) { // temp_normal != Vec3d::UnitZ()
|
||||
Vec3d v_plane = temp_normal.cross(Vec3d::UnitZ());
|
||||
cut_plane_in_world = v_plane.cross(temp_normal);
|
||||
}
|
||||
Vec3d z_dir = text_normal_in_world;
|
||||
Vec3d y_dir = cut_plane_in_world;
|
||||
Vec3d x_dir_world = y_dir.cross(z_dir);
|
||||
if (m_text_type == TextType::SURFACE_HORIZONAL && text_normal_in_world != Vec3d::UnitZ()) {
|
||||
y_dir = Vec3d::UnitZ();
|
||||
x_dir_world = y_dir.cross(z_dir);
|
||||
z_dir = x_dir_world.cross(y_dir);
|
||||
}
|
||||
auto temp_tran = Geometry::generate_transform(x_dir_world, y_dir, z_dir, text_position_in_world);
|
||||
Geometry::Transformation rotate_trans;
|
||||
rotate_trans.set_rotation(Vec3d(0, 0, Geometry::deg2rad(rotate_degree))); // m_rotate_angle
|
||||
cur_tran.set_matrix(temp_tran.get_matrix() * rotate_trans.get_matrix());
|
||||
}
|
||||
|
||||
void GLGizmoText::use_fix_normal_position()
|
||||
{
|
||||
m_text_normal_in_world = m_fix_text_normal_in_world;
|
||||
m_text_position_in_world = m_fix_text_position_in_world;
|
||||
}
|
||||
|
||||
void GLGizmoText::load_init_text()
|
||||
{
|
||||
Plater *plater = wxGetApp().plater();
|
||||
@ -421,33 +519,60 @@ void GLGizmoText::load_init_text()
|
||||
m_last_text_mv = model_volume;
|
||||
return;
|
||||
}
|
||||
m_need_fix = false;
|
||||
if (plater) {
|
||||
plater->take_snapshot("enter Text");
|
||||
}
|
||||
auto box = model_volume->get_mesh_shared_ptr()->bounding_box();
|
||||
auto valid_z = text_info.m_embeded_depth + text_info.m_thickness;
|
||||
auto text_height = get_text_height(text_info.m_text);
|
||||
m_really_use_surface_calc = true;
|
||||
int index = -1;
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
if (abs(box.size()[i] - valid_z) < 0.1) {
|
||||
m_really_use_surface_calc = false;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (abs(box.size()[1] - text_height) > 0.1) {
|
||||
m_fix_old_tran_flag = true;
|
||||
}
|
||||
m_last_text_mv = model_volume;
|
||||
load_from_text_info(text_info);
|
||||
m_edit_text_again = true;
|
||||
m_text_volume_tran = model_volume->get_matrix();
|
||||
m_text_tran_in_object.set_matrix(m_text_volume_tran);
|
||||
int temp_object_idx;
|
||||
auto mo = m_parent.get_selection().get_selected_single_object(temp_object_idx);
|
||||
const ModelInstance *mi = mo->instances[m_parent.get_selection().get_instance_idx()];
|
||||
auto world_tran = mi->get_transformation().get_matrix() * m_text_volume_tran;
|
||||
m_object_cs_to_world_tran = mi->get_transformation().get_matrix();
|
||||
auto world_tran = m_object_cs_to_world_tran * m_text_volume_tran;
|
||||
m_text_tran_in_world.set_matrix(world_tran);
|
||||
m_text_position_in_world = m_text_tran_in_world.get_offset();
|
||||
m_text_normal_in_world = -m_text_tran_in_world.get_matrix().linear().col(1).cast<float>();
|
||||
m_text_normal_in_world = m_text_tran_in_world.get_matrix().linear().col(2).cast<float>();
|
||||
{
|
||||
TriangleMesh text_attach_mesh(mo->volumes[m_rr.mesh_id]->mesh());
|
||||
text_attach_mesh.transform(mo->volumes[m_rr.mesh_id]->get_matrix());
|
||||
MeshRaycaster temp_ray_caster(text_attach_mesh);
|
||||
Vec3f local_center = m_text_tran_in_object.get_offset().cast<float>();
|
||||
Vec3f local_center = m_text_tran_in_object.get_offset().cast<float>();//(m_text_tran_in_object.get_matrix() * box.center()).cast<float>(); //
|
||||
Vec3f temp_normal;
|
||||
Vec3f closest_pt = temp_ray_caster.get_closest_point(local_center, &temp_normal);
|
||||
m_fix_text_position_in_world = mi->get_transformation().get_matrix() * closest_pt.cast<double>();
|
||||
m_fix_text_position_in_world = m_object_cs_to_world_tran * closest_pt.cast<double>();
|
||||
m_fix_text_normal_in_world = (mi->get_transformation().get_matrix_no_offset().cast<float>() * temp_normal).normalized();
|
||||
if ((m_fix_text_position_in_world - m_text_position_in_world).norm() > 0.1) {
|
||||
m_need_fix = true;
|
||||
int face_id;
|
||||
Vec3f direction = m_text_tran_in_world.get_matrix().linear().col(2).cast<float>();
|
||||
if (index == 2 && abs(box.size()[1] - text_height) < 0.1) {
|
||||
m_is_version1_9_xoz = true;
|
||||
m_fix_old_tran_flag = true;
|
||||
}
|
||||
if (index == 1 && abs(box.size()[2] - text_height) < 0.1) {//for 1.10 version, xoy plane cut,just fix
|
||||
m_is_version1_10_xoy = true;
|
||||
direction = m_text_tran_in_world.get_matrix().linear().col(1).cast<float>();
|
||||
if (!temp_ray_caster.get_closest_point_and_normal(local_center, direction, &closest_pt, &temp_normal, &face_id)) {
|
||||
m_show_warning_error_mesh = true;
|
||||
}
|
||||
}
|
||||
else if (!temp_ray_caster.get_closest_point_and_normal(local_center, -direction, &closest_pt, &temp_normal, &face_id)) {
|
||||
m_show_warning_error_mesh = true;
|
||||
}
|
||||
}
|
||||
// m_rr.mesh_id
|
||||
@ -460,8 +585,8 @@ void GLGizmoText::load_init_text()
|
||||
|
||||
void GLGizmoText::data_changed(bool is_serializing) {
|
||||
load_init_text();
|
||||
m_rr.normal = Vec3f::Zero();
|
||||
}
|
||||
|
||||
CommonGizmosDataID GLGizmoText::on_get_requirements() const
|
||||
{
|
||||
return CommonGizmosDataID(
|
||||
@ -693,6 +818,8 @@ void GLGizmoText::on_update(const UpdateData &data)
|
||||
|
||||
if (closest_hit_mesh_id != -1) {
|
||||
m_rr = {mouse_pos, closest_hit_mesh_id, closest_hit, closest_normal};//on drag
|
||||
m_need_fix = false;
|
||||
close_warning_flag_after_close_or_drag();
|
||||
m_need_update_text = true;
|
||||
}
|
||||
}
|
||||
@ -822,10 +949,16 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||
std::string hit = "local hit x:" + formatFloat(m_rr.hit[0]) + " y:" + formatFloat(m_rr.hit[1]) + " z:" + formatFloat(m_rr.hit[2]);
|
||||
std::string normal = "normal x:" + formatFloat(m_rr.normal[0]) + " y:" + formatFloat(m_rr.normal[1]) + " z:" + formatFloat(m_rr.normal[2]);
|
||||
auto cut_dir = "cut_dir x:" + formatFloat(m_cut_plane_dir_in_world[0]) + " y:" + formatFloat(m_cut_plane_dir_in_world[1]) + " z:" + formatFloat(m_cut_plane_dir_in_world[2]);
|
||||
auto fix_position_str = "fix position:" + formatFloat(m_fix_text_position_in_world[0]) + " y:" + formatFloat(m_fix_text_position_in_world[1]) +
|
||||
" z:" + formatFloat(m_fix_text_position_in_world[2]);
|
||||
auto fix_normal_str = "fix normal:" + formatFloat(m_fix_text_normal_in_world[0]) + " y:" + formatFloat(m_fix_text_normal_in_world[1]) +
|
||||
" z:" + formatFloat(m_fix_text_normal_in_world[2]);
|
||||
m_imgui->text(world_hit);
|
||||
m_imgui->text(hit);
|
||||
m_imgui->text(normal);
|
||||
m_imgui->text(cut_dir);
|
||||
m_imgui->text(fix_position_str);
|
||||
m_imgui->text(fix_normal_str);
|
||||
#endif
|
||||
float space_size = m_imgui->get_style_scaling() * 8;
|
||||
float font_cap = m_imgui->calc_text_size(_L("Font")).x;
|
||||
@ -985,14 +1118,37 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||
if (text.empty() && m_is_modify) {
|
||||
m_imgui->warning_text(_L("Warning:Input cannot be empty!"));
|
||||
}
|
||||
if (m_show_warning) {
|
||||
if (m_show_warning_text_create_fail) {
|
||||
m_imgui->warning_text(_L("Warning:create text fail."));
|
||||
}
|
||||
if (m_show_text_normal_error) {
|
||||
m_imgui->warning_text(_L("Warning:text normal is error."));
|
||||
}
|
||||
if (m_show_text_normal_reset_tip) {
|
||||
m_imgui->warning_text(_L("Warning:text normal has been reset."));
|
||||
}
|
||||
if (m_show_warning_regenerated) {
|
||||
m_imgui->warning_text(_L("Warning:Because current text does indeed use surround algorithm,\nif continue to edit, text has to regenerated according to new location."));
|
||||
}
|
||||
if (m_show_warning_old_tran) {
|
||||
m_imgui->warning_text(_L("Warning:old matrix has at least two parameters: mirroring, scaling, and rotation. \nIf you continue editing, it may not be correct. \nPlease dragging text or cancel using current pose, \nsave and reedit again."));
|
||||
}
|
||||
if (m_show_warning_error_mesh) {
|
||||
m_imgui->warning_text(_L("Error:Detecting an incorrect mesh id or an unknown error, \nregenerating text may result in incorrect outcomes.\nPlease drag text,save it then reedit it again."));
|
||||
}
|
||||
if (m_show_warning_lost_rotate) {
|
||||
m_imgui->warning_text(_L("Warning:Due to functional upgrade, rotation information \ncannot be restored. Please drag or modify text,\n save it and reedit it will ok."));
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
if (m_need_fix && m_text_type > TextType::HORIZONAL) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::SameLine(caption_size);
|
||||
ImGui::PushItemWidth(list_width);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
if (m_imgui->bbl_checkbox(_L("Use opened text pose"), m_use_current_pose)) {
|
||||
m_need_update_text = true;
|
||||
}
|
||||
}
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
|
||||
show_tooltip_information(x, get_cur_y);
|
||||
@ -1002,17 +1158,20 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||
|
||||
ImGui::SameLine(caption_size);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
if (m_imgui->bbl_checkbox(_L("Surface"), m_is_surface_text)) {
|
||||
auto is_surface_text = m_text_type == TextType::SURFACE || m_text_type == TextType::SURFACE_HORIZONAL;
|
||||
if (m_imgui->bbl_checkbox(_L("Surface"), is_surface_text)) {
|
||||
m_need_update_text = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
auto keep_horizontal = !m_is_surface_text;
|
||||
if (m_imgui->bbl_checkbox(_L("Horizontal text"), keep_horizontal)) {
|
||||
auto is_keep_horizontal = m_text_type == TextType::HORIZONAL || m_text_type == TextType::SURFACE_HORIZONAL;
|
||||
if (m_imgui->bbl_checkbox(_L("Horizontal text"), is_keep_horizontal)) {
|
||||
m_need_update_text = true;
|
||||
if (is_surface_text && is_keep_horizontal == false) {
|
||||
update_text_normal_in_world();
|
||||
}
|
||||
}
|
||||
m_is_surface_text = !keep_horizontal;
|
||||
check_text_type(is_surface_text, is_keep_horizontal);
|
||||
|
||||
//ImGui::SameLine();
|
||||
//ImGui::AlignTextToFramePadding();
|
||||
@ -1080,7 +1239,7 @@ void GLGizmoText::reset_text_info()
|
||||
m_embeded_depth = 0.f;
|
||||
m_rotate_angle = 0;
|
||||
m_text_gap = 0.f;
|
||||
m_is_surface_text = true;
|
||||
m_text_type = TextType::SURFACE;
|
||||
m_rr = RaycastResult();
|
||||
m_is_modify = false;
|
||||
}
|
||||
@ -1126,6 +1285,66 @@ void GLGizmoText::update_font_status()
|
||||
}
|
||||
}
|
||||
|
||||
float GLGizmoText::get_text_height(const std::string &text)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> str_cnv;
|
||||
std::wstring ws = boost::nowide::widen(text);
|
||||
std::vector<std::string> alphas;
|
||||
for (auto w : ws) {
|
||||
alphas.push_back(str_cnv.to_bytes(w));
|
||||
}
|
||||
auto texts = alphas ;
|
||||
float max_height = 0.f;
|
||||
for (int i = 0; i < texts.size(); ++i) {
|
||||
std::string alpha;
|
||||
if (texts[i] == " ") {
|
||||
alpha = "i";
|
||||
} else {
|
||||
alpha = texts[i];
|
||||
}
|
||||
TextResult text_result;
|
||||
load_text_shape(alpha.c_str(), m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, text_result);
|
||||
auto height = text_result.text_mesh.bounding_box().size()[1];
|
||||
if (max_height < height ){
|
||||
max_height = height;
|
||||
}
|
||||
}
|
||||
return max_height;
|
||||
}
|
||||
|
||||
void GLGizmoText::close_warning_flag_after_close_or_drag()
|
||||
{
|
||||
m_show_warning_text_create_fail = false;
|
||||
m_show_warning_regenerated = false;
|
||||
m_show_warning_error_mesh = false;
|
||||
m_show_warning_old_tran = false;
|
||||
m_show_warning_lost_rotate = false;
|
||||
m_show_text_normal_error = false;
|
||||
m_show_text_normal_reset_tip = false;
|
||||
m_show_warning_lost_rotate = false;
|
||||
m_is_version1_10_xoy = false;
|
||||
m_is_version1_9_xoz = false;
|
||||
}
|
||||
|
||||
void GLGizmoText::update_text_normal_in_world()
|
||||
{
|
||||
int temp_object_idx;
|
||||
auto mo = m_parent.get_selection().get_selected_single_object(temp_object_idx);
|
||||
if (mo && m_rr.mesh_id >= 0) {
|
||||
const ModelInstance *mi = mo->instances[m_parent.get_selection().get_instance_idx()];
|
||||
TriangleMesh text_attach_mesh(mo->volumes[m_rr.mesh_id]->mesh());
|
||||
text_attach_mesh.transform(mo->volumes[m_rr.mesh_id]->get_matrix());
|
||||
MeshRaycaster temp_ray_caster(text_attach_mesh);
|
||||
Vec3f local_center = m_text_tran_in_object.get_offset().cast<float>(); //(m_text_tran_in_object.get_matrix() * box.center()).cast<float>(); //
|
||||
Vec3f temp_normal;
|
||||
Vec3f closest_pt = temp_ray_caster.get_closest_point(local_center, &temp_normal);
|
||||
m_text_normal_in_world = (mi->get_transformation().get_matrix_no_offset().cast<float>() * temp_normal).normalized();
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("error: update_text_normal_in_world");
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
||||
{
|
||||
std::vector<double> text_lengths;
|
||||
@ -1168,9 +1387,10 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
||||
}
|
||||
// mouse_position_world may is error after user modified
|
||||
if (m_need_fix) {
|
||||
m_need_fix = false;
|
||||
m_text_position_in_world = m_fix_text_position_in_world;
|
||||
m_text_normal_in_world = m_fix_text_normal_in_world;
|
||||
if (m_text_normal_in_world.norm() < 0.1) {
|
||||
m_show_text_normal_reset_tip = true;
|
||||
}
|
||||
use_fix_normal_position();
|
||||
}
|
||||
if (m_text_normal_in_world.norm() < 0.1) {
|
||||
m_show_text_normal_error = true;
|
||||
@ -1203,24 +1423,10 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
||||
|
||||
ModelVolume* volume = mo->volumes[volume_index];
|
||||
|
||||
Vec3d temp_normal = m_text_normal_in_world.cast<double>();
|
||||
Vec3d cut_plane_in_world = Vec3d::UnitY();
|
||||
double epson = 1e-6;
|
||||
if (!(abs(temp_normal.x()) <= epson && abs(temp_normal.y()) <= epson && abs(temp_normal.z()) > epson)) { // temp_normal != Vec3d::UnitZ()
|
||||
Vec3d v_plane = temp_normal.cross(Vec3d::UnitZ());
|
||||
cut_plane_in_world = v_plane.cross(temp_normal);
|
||||
}
|
||||
|
||||
m_cut_plane_dir_in_world = cut_plane_in_world;
|
||||
|
||||
auto y_dir = -m_text_normal_in_world.cast<double>();
|
||||
Vec3d x_dir_world = y_dir.cross(m_cut_plane_dir_in_world);
|
||||
m_text_tran_in_world = Geometry::generate_transform(x_dir_world, y_dir, m_cut_plane_dir_in_world.cast<double>(), m_text_position_in_world);
|
||||
Geometry::Transformation rotate_trans;
|
||||
rotate_trans.set_rotation(Vec3d(0, Geometry::deg2rad(m_rotate_angle), 0)); // m_rotate_angle
|
||||
m_text_tran_in_world.set_matrix(m_text_tran_in_world.get_matrix() * rotate_trans.get_matrix());
|
||||
m_cut_plane_dir_in_world = m_text_tran_in_world.get_matrix().linear().col(2);
|
||||
generate_text_tran_in_world(m_text_normal_in_world.cast<double>(), m_text_position_in_world, m_rotate_angle, m_text_tran_in_world);
|
||||
|
||||
m_cut_plane_dir_in_world = m_text_tran_in_world.get_matrix().linear().col(1);
|
||||
m_text_normal_in_world = m_text_tran_in_world.get_matrix().linear().col(2).cast<float>();
|
||||
// generate clip cs at click pos
|
||||
auto text_position_in_object = mi->get_transformation().get_matrix().inverse() * m_text_position_in_world.cast<double>();
|
||||
auto rotate_mat_inv = mi->get_transformation().get_matrix_no_offset().inverse();
|
||||
@ -1228,8 +1434,8 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
||||
auto text_tran_in_object = mi->get_transformation().get_matrix().inverse() * m_text_tran_in_world.get_matrix(); // Geometry::generate_transform(cs_x_dir, cs_y_dir, cs_z_dir, text_position_in_object); // todo modify by m_text_tran_in_world
|
||||
m_text_tran_in_object.set_matrix(text_tran_in_object);
|
||||
m_text_cs_to_world_tran = mi->get_transformation().get_matrix() * m_text_tran_in_object.get_matrix();
|
||||
|
||||
if (!m_is_surface_text) {
|
||||
auto rotate_tran = Geometry::assemble_transform(Vec3d::Zero(), {-0.5 * M_PI, 0.0, 0.0});
|
||||
if (m_text_type == TextType::HORIZONAL || (m_need_fix && m_use_current_pose)) {
|
||||
m_position_points.resize(text_num);
|
||||
m_normal_points.resize(text_num);
|
||||
|
||||
@ -1280,7 +1486,8 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
||||
}
|
||||
|
||||
MeshSlicingParams slicing_params;
|
||||
slicing_params.trafo = m_text_tran_in_object.get_matrix().inverse();
|
||||
auto cut_tran = (m_text_tran_in_object.get_matrix() * rotate_tran);
|
||||
slicing_params.trafo = cut_tran.inverse();
|
||||
// for debug
|
||||
// its_write_obj(slice_meshs.its, "D:/debug_files/mesh.obj");
|
||||
// generate polygons
|
||||
@ -1324,7 +1531,7 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
|
||||
m_cut_points_in_world.clear();
|
||||
m_cut_points_in_world.reserve(hit_ploy.points.size());
|
||||
for (int i = 0; i < hit_ploy.points.size(); ++i) {
|
||||
m_cut_points_in_world.emplace_back(m_text_cs_to_world_tran * Vec3d(unscale_(hit_ploy.points[i].x()), unscale_(hit_ploy.points[i].y()), 0));
|
||||
m_cut_points_in_world.emplace_back(m_text_cs_to_world_tran * rotate_tran * Vec3d(unscale_(hit_ploy.points[i].x()), unscale_(hit_ploy.points[i].y()), 0));
|
||||
}
|
||||
|
||||
Polygon_3D new_polygon(m_cut_points_in_world);
|
||||
@ -1667,7 +1874,13 @@ void GLGizmoText::generate_text_volume(bool is_temp)
|
||||
}
|
||||
ModelVolume * model_volume = model_object->volumes[m_volume_idx];
|
||||
ModelVolume * new_model_volume = model_object->add_volume(std::move(mesh),false);
|
||||
new_model_volume->set_transformation(m_text_tran_in_object.get_matrix());
|
||||
if (m_need_fix && // m_reedit_text//m_need_fix
|
||||
(m_text_type == TextType::HORIZONAL || (m_text_type > TextType::HORIZONAL && m_use_current_pose))) {
|
||||
new_model_volume->set_transformation(m_load_text_tran_in_object.get_matrix());
|
||||
}
|
||||
else {
|
||||
new_model_volume->set_transformation(m_text_tran_in_object.get_matrix());
|
||||
}
|
||||
new_model_volume->set_text_info(text_info);
|
||||
new_model_volume->name = model_volume->name;
|
||||
new_model_volume->set_type(model_volume->type());
|
||||
@ -1684,15 +1897,16 @@ void GLGizmoText::generate_text_volume(bool is_temp)
|
||||
cur_volume_id = obj_list->add_text_part(mesh, "text_shape", text_info, m_text_tran_in_object.get_matrix(), is_temp);
|
||||
m_preview_text_volume_id = is_temp ? cur_volume_id : -1;
|
||||
if (cur_volume_id >= 0) {
|
||||
m_show_warning = false;
|
||||
m_show_warning_text_create_fail = false;
|
||||
ModelVolume *text_model_volume = model_object->volumes[cur_volume_id];
|
||||
m_text_volume_tran = text_model_volume->get_matrix();
|
||||
}
|
||||
else {
|
||||
m_show_warning = true;
|
||||
m_show_warning_text_create_fail = true;
|
||||
}
|
||||
}
|
||||
m_need_update_text = false;
|
||||
m_need_update_text = false;
|
||||
m_show_warning_lost_rotate = false;
|
||||
}
|
||||
|
||||
void GLGizmoText::delete_temp_preview_text_volume()
|
||||
@ -1717,6 +1931,7 @@ TextInfo GLGizmoText::get_text_info()
|
||||
{
|
||||
TextInfo text_info;
|
||||
text_info.m_font_name = m_font_name;
|
||||
text_info.m_font_version = m_font_version;
|
||||
text_info.m_font_size = m_font_size;
|
||||
text_info.m_curr_font_idx = m_curr_font_idx;
|
||||
text_info.m_bold = m_bold;
|
||||
@ -1727,13 +1942,15 @@ TextInfo GLGizmoText::get_text_info()
|
||||
text_info.m_embeded_depth = m_embeded_depth;
|
||||
text_info.m_rotate_angle = m_rotate_angle;
|
||||
text_info.m_text_gap = m_text_gap;
|
||||
text_info.m_is_surface_text = m_is_surface_text;
|
||||
text_info.m_is_surface_text = m_text_type == TextType::SURFACE || m_text_type == TextType::SURFACE_HORIZONAL;
|
||||
text_info.m_keep_horizontal = m_text_type == TextType::HORIZONAL || m_text_type == TextType::SURFACE_HORIZONAL;
|
||||
return text_info;
|
||||
}
|
||||
|
||||
void GLGizmoText::load_from_text_info(const TextInfo &text_info)
|
||||
{
|
||||
m_font_name = text_info.m_font_name;
|
||||
m_font_version = text_info.m_font_version;
|
||||
m_font_size = text_info.m_font_size;
|
||||
// from other user's computer may exist case:font library size is different
|
||||
if (text_info.m_curr_font_idx < m_font_names.size()) {
|
||||
@ -1750,7 +1967,7 @@ void GLGizmoText::load_from_text_info(const TextInfo &text_info)
|
||||
m_embeded_depth = text_info.m_embeded_depth;
|
||||
m_rotate_angle = text_info.m_rotate_angle;
|
||||
m_text_gap = text_info.m_text_gap;
|
||||
m_is_surface_text = text_info.m_is_surface_text;
|
||||
check_text_type(text_info.m_is_surface_text, text_info.m_keep_horizontal);
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
|
@ -22,6 +22,7 @@ private:
|
||||
std::vector<std::string> m_avail_font_names;
|
||||
char m_text[1024] = { 0 };
|
||||
std::string m_font_name;
|
||||
std::string m_font_version{"1.0"};
|
||||
float m_font_size = 16.f;
|
||||
const float m_font_size_min = 3.f;
|
||||
const float m_font_size_max = 1000.f;
|
||||
@ -35,7 +36,14 @@ private:
|
||||
const float m_embeded_depth_max = 1000.f;
|
||||
float m_rotate_angle = 0;
|
||||
float m_text_gap = 0.f;
|
||||
bool m_is_surface_text = false;
|
||||
enum TextType {
|
||||
HORIZONAL,
|
||||
SURFACE,
|
||||
SURFACE_HORIZONAL
|
||||
};
|
||||
TextType m_text_type{TextType ::SURFACE};
|
||||
bool m_really_use_surface_calc = false;
|
||||
bool m_use_current_pose = true;
|
||||
mutable RaycastResult m_rr;
|
||||
|
||||
float m_combo_height = 0.0f;
|
||||
@ -65,12 +73,19 @@ private:
|
||||
std::mutex m_mutex;
|
||||
std::thread m_thread;
|
||||
|
||||
bool m_edit_text_again = false;
|
||||
bool m_is_modify = false;
|
||||
bool m_need_update_text = false;
|
||||
bool m_show_warning = false;
|
||||
bool m_reedit_text = false;
|
||||
bool m_show_warning_text_create_fail = false;
|
||||
bool m_show_text_normal_error = false;
|
||||
|
||||
bool m_show_text_normal_reset_tip = false;
|
||||
bool m_show_warning_regenerated = false;
|
||||
bool m_show_warning_old_tran = false;
|
||||
bool m_show_warning_error_mesh = false;
|
||||
bool m_show_warning_lost_rotate = false;
|
||||
bool m_fix_old_tran_flag = false;
|
||||
bool m_is_version1_10_xoy = false;
|
||||
bool m_is_version1_9_xoz = false;
|
||||
int m_object_idx = -1;
|
||||
int m_volume_idx = -1;
|
||||
|
||||
@ -82,9 +97,10 @@ private:
|
||||
Vec3f m_text_normal_in_world = Vec3f::Zero();
|
||||
Geometry::Transformation m_text_tran_in_object;
|
||||
Geometry::Transformation m_text_tran_in_world;
|
||||
Geometry::Transformation m_load_text_tran_in_object;
|
||||
Geometry::Transformation m_model_object_in_world_tran;
|
||||
Transform3d m_text_cs_to_world_tran;
|
||||
|
||||
Transform3d m_object_cs_to_world_tran;
|
||||
Vec3d m_cut_plane_dir_in_world = Vec3d::UnitZ();
|
||||
|
||||
std::vector<Vec3d> m_position_points;
|
||||
@ -135,10 +151,16 @@ protected:
|
||||
void show_tooltip_information(float x, float y);
|
||||
|
||||
private:
|
||||
void check_text_type(bool is_surface_text,bool is_keep_horizontal);
|
||||
void generate_text_tran_in_world(const Vec3d &text_normal_in_world, const Vec3d &text_position_in_world, float rotate_degree, Geometry::Transformation &tran);
|
||||
void use_fix_normal_position();
|
||||
void load_init_text();
|
||||
void update_text_pos_normal();
|
||||
void update_font_status();
|
||||
void reset_text_info();
|
||||
float get_text_height(const std::string &text);
|
||||
void close_warning_flag_after_close_or_drag();
|
||||
void update_text_normal_in_world();
|
||||
bool update_text_positions(const std::vector<std::string>& texts);
|
||||
TriangleMesh get_text_mesh(const char* text_str, const Vec3d &position, const Vec3d &normal, const Vec3d &text_up_dir);
|
||||
|
||||
|
@ -384,7 +384,7 @@ void MeshClipper::recalculate_triangles()
|
||||
init_data.entities.back().indices.push_back((unsigned int) idx + 2);
|
||||
}
|
||||
|
||||
if (init_data.entities.back().indices.size() != 0) {
|
||||
if (init_data.entities.back().indices.size() != 0) {
|
||||
isl->model_expanded.reset();
|
||||
isl->model_expanded.init_from(std::move(init_data));
|
||||
}
|
||||
@ -407,7 +407,7 @@ void MeshClipper::recalculate_triangles()
|
||||
void MeshClipper::reset()
|
||||
{
|
||||
if (m_result) {
|
||||
for (auto it = m_result->cut_islands.begin(); it != m_result->cut_islands.end(); ++it) {
|
||||
for (auto it = m_result->cut_islands.begin(); it != m_result->cut_islands.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
std::vector<CutIsland *>().swap(m_result->cut_islands);
|
||||
@ -575,7 +575,7 @@ bool MeshRaycaster::closest_hit(
|
||||
|
||||
size_t hit_id = 0;
|
||||
if (clipping_plane != nullptr) {
|
||||
while (hit_id < hits.size() && clipping_plane->is_point_clipped(trafo * hits[hit_id].position())) {
|
||||
while (hit_id < hits.size() && clipping_plane->is_point_clipped(trafo * hits[hit_id].position())) {
|
||||
++hit_id;
|
||||
}
|
||||
}
|
||||
@ -605,6 +605,19 @@ Vec3f MeshRaycaster::get_closest_point(const Vec3f& point, Vec3f* normal) const
|
||||
return closest_point.cast<float>();
|
||||
}
|
||||
|
||||
bool MeshRaycaster::get_closest_point_and_normal(const Vec3f &point, const Vec3f &direction, Vec3f *closest_point, Vec3f *normal, int *face_id) const
|
||||
{
|
||||
auto hits = m_emesh.query_ray_hits(point.cast<double>(), direction.cast<double>().normalized());
|
||||
if (hits.empty())
|
||||
return false; // no intersection found
|
||||
size_t hit_id = 0;
|
||||
auto & hit = hits[hit_id];
|
||||
*closest_point = hit.position().cast<float>();
|
||||
*normal = hit.normal().cast<float>();
|
||||
if (face_id) { *face_id = hit.face(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
int MeshRaycaster::get_closest_facet(const Vec3f &point) const
|
||||
{
|
||||
int facet_idx = 0;
|
||||
|
@ -201,7 +201,7 @@ public:
|
||||
// normal* can be used to also get normal of the respective triangle.
|
||||
|
||||
Vec3f get_closest_point(const Vec3f& point, Vec3f* normal = nullptr) const;
|
||||
|
||||
bool get_closest_point_and_normal(const Vec3f &point, const Vec3f &direction, Vec3f *closest_point, Vec3f *normal, int *face_id = nullptr) const;
|
||||
// Given a point in mesh coords, the method returns the closest facet from mesh.
|
||||
int get_closest_facet(const Vec3f &point) const;
|
||||
|
||||
@ -221,7 +221,7 @@ public:
|
||||
/*PickRaycaster(TriangleMesh *mesh, const Transform3d &tran) : PickRaycaster(mesh) {
|
||||
set_transform(tran);
|
||||
}*/
|
||||
PickRaycaster(TriangleMesh *mesh, int _id)
|
||||
PickRaycaster(TriangleMesh *mesh, int _id)
|
||||
{
|
||||
mesh_raycaster = std::make_shared<MeshRaycaster>(*mesh);
|
||||
m_id = _id;
|
||||
|
@ -1074,13 +1074,16 @@ std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_s
|
||||
// e.g. for right aligned embossed text
|
||||
if (m_list.size() == 1 && type == ECoordinatesType::Local) {
|
||||
const GLVolume & vol = *get_volume(*m_list.begin());
|
||||
const Transform3d vol_world_trafo = vol.world_matrix();
|
||||
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
// move center to local volume zero
|
||||
center[i] = world_zero.dot(axes[i]);
|
||||
// extend half size to bigger distance from center
|
||||
half_box_size[i] = std::max(abs(center[i] - min[i]), abs(center[i] - max[i]));
|
||||
bool condition = !vol.is_text_shape;
|
||||
if (condition){
|
||||
const Transform3d vol_world_trafo = vol.world_matrix();
|
||||
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
// move center to local volume zero
|
||||
center[i] = world_zero.dot(axes[i]);
|
||||
// extend half size to bigger distance from center
|
||||
half_box_size[i] = std::max(abs(center[i] - min[i]), abs(center[i] - max[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user