mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 17:27:52 -06:00
ENH: optimize text interaction
Change-Id: I1d132124816ba0946fd4d05310f8cd6da17a7e45 (cherry picked from commit f741a33a3651e266edfd4c191322f8988a3666f2)
This commit is contained in:
parent
1041b8b026
commit
c7ec112420
6 changed files with 207 additions and 14 deletions
|
@ -458,6 +458,19 @@ void MenuFactory::append_menu_item_delete(wxMenu* menu)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MenuFactory::append_menu_item_edit_text(wxMenu *menu)
|
||||||
|
{
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
append_menu_item(
|
||||||
|
menu, wxID_ANY, _L("Edit Text"), "", [](wxCommandEvent &) { plater()->edit_text(); }, "", nullptr,
|
||||||
|
[]() { return plater()->can_edit_text(); }, m_parent);
|
||||||
|
#else
|
||||||
|
append_menu_item(
|
||||||
|
menu, wxID_ANY, _L("Edit Text"), "", [](wxCommandEvent &) { plater()->edit_text(); }, "", nullptr,
|
||||||
|
[]() { return plater()->can_edit_text(); }, m_parent);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType type) {
|
wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType type) {
|
||||||
auto sub_menu = new wxMenu;
|
auto sub_menu = new wxMenu;
|
||||||
|
|
||||||
|
@ -1072,6 +1085,7 @@ void MenuFactory::create_bbl_part_menu()
|
||||||
wxMenu* menu = &m_part_menu;
|
wxMenu* menu = &m_part_menu;
|
||||||
|
|
||||||
append_menu_item_delete(menu);
|
append_menu_item_delete(menu);
|
||||||
|
append_menu_item_edit_text(menu);
|
||||||
append_menu_item_fix_through_netfabb(menu);
|
append_menu_item_fix_through_netfabb(menu);
|
||||||
append_menu_item_simplify(menu);
|
append_menu_item_simplify(menu);
|
||||||
append_menu_item_center(menu);
|
append_menu_item_center(menu);
|
||||||
|
|
|
@ -128,6 +128,7 @@ private:
|
||||||
void append_menu_item_change_extruder(wxMenu* menu);
|
void append_menu_item_change_extruder(wxMenu* menu);
|
||||||
void append_menu_item_set_visible(wxMenu* menu);
|
void append_menu_item_set_visible(wxMenu* menu);
|
||||||
void append_menu_item_delete(wxMenu* menu);
|
void append_menu_item_delete(wxMenu* menu);
|
||||||
|
void append_menu_item_edit_text(wxMenu *menu);
|
||||||
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
|
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
|
||||||
void append_menu_items_convert_unit(wxMenu* menu); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
|
void append_menu_items_convert_unit(wxMenu* menu); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
|
||||||
void append_menu_items_flush_options(wxMenu* menu);
|
void append_menu_items_flush_options(wxMenu* menu);
|
||||||
|
|
|
@ -147,6 +147,8 @@ bool GLGizmoText::on_init()
|
||||||
|
|
||||||
m_desc["rotate_text_caption"] = _L("Shift + Mouse movement");
|
m_desc["rotate_text_caption"] = _L("Shift + Mouse movement");
|
||||||
m_desc["rotate_text"] = _L("Rotate preview text");
|
m_desc["rotate_text"] = _L("Rotate preview text");
|
||||||
|
|
||||||
|
m_grabbers.push_back(Grabber());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +217,10 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const ModelObject * mo = m_c->selection_info()->model_object();
|
const ModelObject * mo = m_c->selection_info()->model_object();
|
||||||
|
if (m_is_modify) {
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
mo = selection.get_model()->objects[m_object_idx];
|
||||||
|
}
|
||||||
if (mo == nullptr)
|
if (mo == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -232,6 +238,9 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
||||||
if (action == SLAGizmoEventType::Moving) {
|
if (action == SLAGizmoEventType::Moving) {
|
||||||
if (shift_down) {
|
if (shift_down) {
|
||||||
float angle = m_rotate_angle + 0.5 * (m_mouse_position - mouse_position).y();
|
float angle = m_rotate_angle + 0.5 * (m_mouse_position - mouse_position).y();
|
||||||
|
if (angle == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
while (angle < 0)
|
while (angle < 0)
|
||||||
angle += 360;
|
angle += 360;
|
||||||
|
|
||||||
|
@ -240,6 +249,7 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
||||||
|
|
||||||
m_rotate_angle = angle;
|
m_rotate_angle = angle;
|
||||||
m_shift_down = true;
|
m_shift_down = true;
|
||||||
|
m_need_update_text = true;
|
||||||
} else {
|
} else {
|
||||||
m_shift_down = false;
|
m_shift_down = false;
|
||||||
m_origin_mouse_position = mouse_position;
|
m_origin_mouse_position = mouse_position;
|
||||||
|
@ -247,6 +257,14 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
||||||
m_mouse_position = mouse_position;
|
m_mouse_position = mouse_position;
|
||||||
}
|
}
|
||||||
else if (action == SLAGizmoEventType::LeftDown) {
|
else if (action == SLAGizmoEventType::LeftDown) {
|
||||||
|
if (!selection.is_empty() && get_hover_id() != -1) {
|
||||||
|
start_dragging();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_is_modify)
|
||||||
|
return false;
|
||||||
|
|
||||||
Vec3f normal = Vec3f::Zero();
|
Vec3f normal = Vec3f::Zero();
|
||||||
Vec3f hit = Vec3f::Zero();
|
Vec3f hit = Vec3f::Zero();
|
||||||
size_t facet = 0;
|
size_t facet = 0;
|
||||||
|
@ -260,7 +278,9 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit
|
||||||
if (mesh_id == m_preview_text_volume_id)
|
if (mesh_id == m_preview_text_volume_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal,
|
MeshRaycaster mesh_raycaster = MeshRaycaster(mo->volumes[mesh_id]->mesh());
|
||||||
|
|
||||||
|
if (mesh_raycaster.unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal,
|
||||||
m_c->object_clipper()->get_clipping_plane(), &facet)) {
|
m_c->object_clipper()->get_clipping_plane(), &facet)) {
|
||||||
// In case this hit is clipped, skip it.
|
// In case this hit is clipped, skip it.
|
||||||
if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id]))
|
if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id]))
|
||||||
|
@ -352,6 +372,9 @@ bool GLGizmoText::on_is_activable() const
|
||||||
|
|
||||||
void GLGizmoText::on_render()
|
void GLGizmoText::on_render()
|
||||||
{
|
{
|
||||||
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
std::string text = std::string(m_text);
|
std::string text = std::string(m_text);
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
delete_temp_preview_text_volume();
|
delete_temp_preview_text_volume();
|
||||||
|
@ -378,7 +401,7 @@ void GLGizmoText::on_render()
|
||||||
if (!plater)
|
if (!plater)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_is_modify) {
|
if (!m_is_modify || m_shift_down) {
|
||||||
const Camera &camera = wxGetApp().plater()->get_camera();
|
const Camera &camera = wxGetApp().plater()->get_camera();
|
||||||
// Precalculate transformations of individual meshes.
|
// Precalculate transformations of individual meshes.
|
||||||
std::vector<Transform3d> trafo_matrices;
|
std::vector<Transform3d> trafo_matrices;
|
||||||
|
@ -386,7 +409,18 @@ void GLGizmoText::on_render()
|
||||||
if (mv->is_model_part()) trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
|
if (mv->is_model_part()) trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
|
||||||
}
|
}
|
||||||
// Raycast and return if there's no hit.
|
// Raycast and return if there's no hit.
|
||||||
bool position_changed = update_raycast_cache(m_shift_down ? m_origin_mouse_position : m_parent.get_local_mouse_position(), camera, trafo_matrices);
|
Vec2d mouse_pos;
|
||||||
|
if (m_shift_down) {
|
||||||
|
if (m_is_modify)
|
||||||
|
mouse_pos = m_rr.mouse_position;
|
||||||
|
else
|
||||||
|
mouse_pos = m_origin_mouse_position;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mouse_pos = m_parent.get_local_mouse_position();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool position_changed = update_raycast_cache(mouse_pos, camera, trafo_matrices);
|
||||||
|
|
||||||
if (m_rr.mesh_id == -1) {
|
if (m_rr.mesh_id == -1) {
|
||||||
delete_temp_preview_text_volume();
|
delete_temp_preview_text_volume();
|
||||||
|
@ -396,6 +430,25 @@ void GLGizmoText::on_render()
|
||||||
if (!position_changed && !m_need_update_text && !m_shift_down)
|
if (!position_changed && !m_need_update_text && !m_shift_down)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_is_modify && m_grabbers.size() == 1) {
|
||||||
|
std::vector<Transform3d> trafo_matrices;
|
||||||
|
for (const ModelVolume *mv : mo->volumes) {
|
||||||
|
if (mv->is_model_part()) {
|
||||||
|
trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mouse_position_world = trafo_matrices[m_rr.mesh_id] * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2));
|
||||||
|
|
||||||
|
float mean_size = (float) (GLGizmoBase::Grabber::FixedGrabberSize);
|
||||||
|
|
||||||
|
m_grabbers[0].center = m_mouse_position_world;
|
||||||
|
m_grabbers[0].enabled = true;
|
||||||
|
std::array<float, 4> color = picking_color_component(0);
|
||||||
|
m_grabbers[0].color = color;
|
||||||
|
m_grabbers[0].render_for_picking(mean_size);
|
||||||
|
}
|
||||||
|
|
||||||
delete_temp_preview_text_volume();
|
delete_temp_preview_text_volume();
|
||||||
|
|
||||||
|
@ -408,7 +461,98 @@ void GLGizmoText::on_render()
|
||||||
|
|
||||||
void GLGizmoText::on_render_for_picking()
|
void GLGizmoText::on_render_for_picking()
|
||||||
{
|
{
|
||||||
// TODO:
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
|
int obejct_idx, volume_idx;
|
||||||
|
ModelVolume *model_volume = get_selected_single_volume(obejct_idx, volume_idx);
|
||||||
|
if (model_volume && !model_volume->get_text_info().m_text.empty()) {
|
||||||
|
if (m_grabbers.size() == 1) {
|
||||||
|
ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
|
if (m_is_modify) {
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
mo = selection.get_model()->objects[m_object_idx];
|
||||||
|
}
|
||||||
|
if (mo == nullptr) return;
|
||||||
|
|
||||||
|
const Selection & selection = m_parent.get_selection();
|
||||||
|
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
||||||
|
|
||||||
|
// 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(mi->get_transformation().get_matrix() * mv->get_matrix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mouse_position_world = trafo_matrices[m_rr.mesh_id] * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2));
|
||||||
|
|
||||||
|
float mean_size = (float) (GLGizmoBase::Grabber::FixedGrabberSize);
|
||||||
|
m_grabbers[0].center = m_mouse_position_world;
|
||||||
|
m_grabbers[0].enabled = true;
|
||||||
|
std::array<float, 4> color = picking_color_component(0);
|
||||||
|
m_grabbers[0].color = color;
|
||||||
|
m_grabbers[0].render_for_picking(mean_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoText::on_update(const UpdateData &data)
|
||||||
|
{
|
||||||
|
Vec2d mouse_pos = Vec2d(data.mouse_pos.x(), data.mouse_pos.y());
|
||||||
|
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
|
if (m_is_modify) {
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
mo = selection.get_model()->objects[m_object_idx];
|
||||||
|
}
|
||||||
|
if (mo == nullptr) return;
|
||||||
|
|
||||||
|
const Selection & selection = m_parent.get_selection();
|
||||||
|
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
||||||
|
const Camera & camera = wxGetApp().plater()->get_camera();
|
||||||
|
|
||||||
|
std::vector<Transform3d> trafo_matrices;
|
||||||
|
for (const ModelVolume *mv : mo->volumes) {
|
||||||
|
if (mv->is_model_part()) { trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3f normal = Vec3f::Zero();
|
||||||
|
Vec3f hit = Vec3f::Zero();
|
||||||
|
size_t facet = 0;
|
||||||
|
Vec3f closest_hit = Vec3f::Zero();
|
||||||
|
Vec3f closest_normal = Vec3f::Zero();
|
||||||
|
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
||||||
|
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 (mesh_id == m_volume_idx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MeshRaycaster mesh_raycaster = MeshRaycaster(mo->volumes[mesh_id]->mesh());
|
||||||
|
|
||||||
|
if (mesh_raycaster.unproject_on_mesh(mouse_pos, trafo_matrices[mesh_id], camera, hit, normal, m_c->object_clipper()->get_clipping_plane(),
|
||||||
|
&facet)) {
|
||||||
|
// In case this hit is clipped, skip it.
|
||||||
|
if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id])) continue;
|
||||||
|
|
||||||
|
// 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_hit_mesh_id = mesh_id;
|
||||||
|
closest_hit = hit;
|
||||||
|
closest_normal = normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest_hit == Vec3f::Zero() && closest_normal == Vec3f::Zero()) return;
|
||||||
|
|
||||||
|
if (closest_hit_mesh_id != -1) {
|
||||||
|
m_rr = {mouse_pos, closest_hit_mesh_id, closest_hit, closest_normal};
|
||||||
|
m_need_update_text = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoText::push_button_style(bool pressed) {
|
void GLGizmoText::push_button_style(bool pressed) {
|
||||||
|
@ -533,11 +677,13 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||||
float depth_cap = m_imgui->calc_text_size(_L("Embeded depth")).x;
|
float depth_cap = m_imgui->calc_text_size(_L("Embeded depth")).x;
|
||||||
float caption_size = std::max(std::max(font_cap, size_cap), std::max(depth_cap, input_cap)) + space_size + ImGui::GetStyle().WindowPadding.x;
|
float caption_size = std::max(std::max(font_cap, size_cap), std::max(depth_cap, input_cap)) + space_size + ImGui::GetStyle().WindowPadding.x;
|
||||||
|
|
||||||
float input_text_size = m_imgui->scaled(12.0f);
|
float input_text_size = m_imgui->scaled(10.0f);
|
||||||
float button_size = ImGui::GetFrameHeight();
|
float button_size = ImGui::GetFrameHeight();
|
||||||
|
|
||||||
ImVec2 selectable_size(std::max((input_text_size + ImGui::GetFrameHeight() * 2), m_combo_width + SELECTABLE_INNER_OFFSET * currt_scale), m_combo_height);
|
ImVec2 selectable_size(std::max((input_text_size + ImGui::GetFrameHeight() * 2), m_combo_width + SELECTABLE_INNER_OFFSET * currt_scale), m_combo_height);
|
||||||
float list_width = selectable_size.x + ImGui::GetStyle().ScrollbarSize + 2 * currt_scale;
|
//float list_width = selectable_size.x + ImGui::GetStyle().ScrollbarSize + 2 * currt_scale;
|
||||||
|
|
||||||
|
float list_width = m_imgui->scaled(10.0f);
|
||||||
|
|
||||||
float input_size = list_width - button_size * 2 - ImGui::GetStyle().ItemSpacing.x * 4;
|
float input_size = list_width - button_size * 2 - ImGui::GetStyle().ItemSpacing.x * 4;
|
||||||
|
|
||||||
|
@ -691,13 +837,13 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||||
float f_scale = m_parent.get_gizmos_manager().get_layout_scale();
|
float f_scale = m_parent.get_gizmos_manager().get_layout_scale();
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
|
||||||
|
|
||||||
ImGui::SameLine();
|
//ImGui::SameLine();
|
||||||
ImGui::AlignTextToFramePadding();
|
//ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(_L("Status:"));
|
//m_imgui->text(_L("Status:"));
|
||||||
float status_cap = m_imgui->calc_text_size(_L("Status:")).x + space_size + ImGui::GetStyle().WindowPadding.x;
|
//float status_cap = m_imgui->calc_text_size(_L("Status:")).x + space_size + ImGui::GetStyle().WindowPadding.x;
|
||||||
ImGui::SameLine();
|
//ImGui::SameLine();
|
||||||
m_imgui->text(m_is_modify ? _L("Modify") : _L("Add"));
|
//m_imgui->text(m_is_modify ? _L("Modify") : _L("Add"));
|
||||||
ImGui::PopStyleVar(2);
|
//ImGui::PopStyleVar(2);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
@ -770,7 +916,7 @@ void GLGizmoText::reset_text_info()
|
||||||
m_embeded_depth = 0.f;
|
m_embeded_depth = 0.f;
|
||||||
m_rotate_angle = 0;
|
m_rotate_angle = 0;
|
||||||
m_text_gap = 0.f;
|
m_text_gap = 0.f;
|
||||||
m_is_surface_text = false;
|
m_is_surface_text = true;
|
||||||
m_keep_horizontal = false;
|
m_keep_horizontal = false;
|
||||||
|
|
||||||
m_is_modify = false;
|
m_is_modify = false;
|
||||||
|
|
|
@ -92,6 +92,7 @@ protected:
|
||||||
virtual bool on_is_activable() const override;
|
virtual bool on_is_activable() const override;
|
||||||
virtual void on_render() override;
|
virtual void on_render() override;
|
||||||
virtual void on_render_for_picking() override;
|
virtual void on_render_for_picking() override;
|
||||||
|
virtual void on_update(const UpdateData &data) override;
|
||||||
void push_combo_style(const float scale);
|
void push_combo_style(const float scale);
|
||||||
void pop_combo_style();
|
void pop_combo_style();
|
||||||
void push_button_style(bool pressed);
|
void push_button_style(bool pressed);
|
||||||
|
|
|
@ -2081,6 +2081,7 @@ struct Plater::priv
|
||||||
|
|
||||||
bool can_delete() const;
|
bool can_delete() const;
|
||||||
bool can_delete_all() const;
|
bool can_delete_all() const;
|
||||||
|
bool can_edit_text() const;
|
||||||
bool can_add_plate() const;
|
bool can_add_plate() const;
|
||||||
bool can_delete_plate() const;
|
bool can_delete_plate() const;
|
||||||
bool can_increase_instances() const;
|
bool can_increase_instances() const;
|
||||||
|
@ -6975,6 +6976,24 @@ bool Plater::priv::can_delete_all() const
|
||||||
return !model.objects.empty();
|
return !model.objects.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Plater::priv::can_edit_text() const
|
||||||
|
{
|
||||||
|
const Selection &selection = view3D->get_canvas3d()->get_selection();
|
||||||
|
if (selection.is_single_full_instance())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (selection.is_single_volume()) {
|
||||||
|
const GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
|
int out_object_idx = gl_volume->object_idx();
|
||||||
|
ModelObject * model_object = selection.get_model()->objects[out_object_idx];
|
||||||
|
int out_volume_idx = gl_volume->volume_idx();
|
||||||
|
ModelVolume * model_volume = model_object->volumes[out_volume_idx];
|
||||||
|
if (model_volume)
|
||||||
|
return !model_volume->get_text_info().m_text.empty();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Plater::priv::can_add_plate() const
|
bool Plater::priv::can_add_plate() const
|
||||||
{
|
{
|
||||||
return q->get_partplate_list().get_plate_count() < PartPlateList::MAX_PLATES_COUNT;
|
return q->get_partplate_list().get_plate_count() < PartPlateList::MAX_PLATES_COUNT;
|
||||||
|
@ -11399,6 +11418,14 @@ void Plater::show_status_message(std::string s)
|
||||||
BOOST_LOG_TRIVIAL(trace) << "show_status_message:" << s;
|
BOOST_LOG_TRIVIAL(trace) << "show_status_message:" << s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::edit_text()
|
||||||
|
{
|
||||||
|
auto &manager = get_view3D_canvas3D()->get_gizmos_manager();
|
||||||
|
manager.open_gizmo(GLGizmosManager::Text);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Plater::can_edit_text() const { return p->can_edit_text(); }
|
||||||
bool Plater::can_delete() const { return p->can_delete(); }
|
bool Plater::can_delete() const { return p->can_delete(); }
|
||||||
bool Plater::can_delete_all() const { return p->can_delete_all(); }
|
bool Plater::can_delete_all() const { return p->can_delete_all(); }
|
||||||
bool Plater::can_add_model() const { return !is_background_process_slicing(); }
|
bool Plater::can_add_model() const { return !is_background_process_slicing(); }
|
||||||
|
|
|
@ -447,6 +447,10 @@ public:
|
||||||
//BBS:
|
//BBS:
|
||||||
void fill_color(int extruder_id);
|
void fill_color(int extruder_id);
|
||||||
|
|
||||||
|
//BBS:
|
||||||
|
void edit_text();
|
||||||
|
bool can_edit_text() const;
|
||||||
|
|
||||||
bool can_delete() const;
|
bool can_delete() const;
|
||||||
bool can_delete_all() const;
|
bool can_delete_all() const;
|
||||||
bool can_add_model() const;
|
bool can_add_model() const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue