Added new base class for SLA gizmos to remove duplicated code
This commit is contained in:
parent
c28a00ae04
commit
602c48a116
10 changed files with 259 additions and 372 deletions
|
@ -39,6 +39,8 @@ set(SLIC3R_GUI_SOURCES
|
||||||
GUI/Gizmos/GLGizmosCommon.hpp
|
GUI/Gizmos/GLGizmosCommon.hpp
|
||||||
GUI/Gizmos/GLGizmoBase.cpp
|
GUI/Gizmos/GLGizmoBase.cpp
|
||||||
GUI/Gizmos/GLGizmoBase.hpp
|
GUI/Gizmos/GLGizmoBase.hpp
|
||||||
|
GUI/Gizmos/GLGizmoSlaBase.cpp
|
||||||
|
GUI/Gizmos/GLGizmoSlaBase.hpp
|
||||||
GUI/Gizmos/GLGizmoEmboss.cpp
|
GUI/Gizmos/GLGizmoEmboss.cpp
|
||||||
GUI/Gizmos/GLGizmoEmboss.hpp
|
GUI/Gizmos/GLGizmoEmboss.hpp
|
||||||
GUI/Gizmos/GLGizmoMove.cpp
|
GUI/Gizmos/GLGizmoMove.cpp
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "GLGizmoHollow.hpp"
|
#include "GLGizmoHollow.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
#include "slic3r/GUI/Camera.hpp"
|
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
@ -17,10 +17,8 @@
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
static const ColorRGBA DISABLED_COLOR = ColorRGBA::DARK_GRAY();
|
|
||||||
|
|
||||||
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoSlaBase(parent, icon_filename, sprite_id, slaposAssembly)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +56,7 @@ void GLGizmoHollow::data_changed()
|
||||||
|
|
||||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||||
if (po != nullptr && po->get_mesh_to_print().empty())
|
if (po != nullptr && po->get_mesh_to_print().empty())
|
||||||
process_mesh(slaposAssembly);
|
reslice_until_step(slaposAssembly);
|
||||||
|
|
||||||
update_volumes();
|
update_volumes();
|
||||||
|
|
||||||
|
@ -265,25 +263,6 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoHollow::render_volumes()
|
|
||||||
{
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_clip");
|
|
||||||
if (shader == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
shader->start_using();
|
|
||||||
shader->set_uniform("emission_factor", 0.0f);
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
|
||||||
|
|
||||||
ClippingPlane clipping_plane = (m_c->object_clipper()->get_position() == 0.0) ? ClippingPlane::ClipsNothing() : *m_c->object_clipper()->get_clipping_plane();
|
|
||||||
clipping_plane.set_normal(-clipping_plane.get_normal());
|
|
||||||
m_volumes.set_clipping_plane(clipping_plane.get_data());
|
|
||||||
|
|
||||||
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
|
||||||
shader->stop_using();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
||||||
{
|
{
|
||||||
if (m_c->object_clipper()->get_position() == 0.)
|
if (m_c->object_clipper()->get_position() == 0.)
|
||||||
|
@ -299,34 +278,6 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
||||||
return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point);
|
return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal
|
|
||||||
// Return false if no intersection was found, true otherwise.
|
|
||||||
bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal)
|
|
||||||
{
|
|
||||||
if (m_c->raycaster()->raycasters().size() != 1)
|
|
||||||
return false;
|
|
||||||
if (! m_c->raycaster()->raycaster())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// The raycaster query
|
|
||||||
Vec3f hit;
|
|
||||||
Vec3f normal;
|
|
||||||
if (m_c->raycaster()->raycaster()->unproject_on_mesh(
|
|
||||||
mouse_pos,
|
|
||||||
m_volumes.volumes.front()->world_matrix(),
|
|
||||||
wxGetApp().plater()->get_camera(),
|
|
||||||
hit,
|
|
||||||
normal,
|
|
||||||
m_c->object_clipper()->get_position() != 0.0 ? m_c->object_clipper()->get_clipping_plane() : nullptr)) {
|
|
||||||
// Return both the point and the facet normal.
|
|
||||||
pos_and_normal = std::make_pair(hit, normal);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
|
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
|
||||||
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
|
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
|
||||||
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
|
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
|
||||||
|
@ -509,7 +460,7 @@ void GLGizmoHollow::delete_selected_points()
|
||||||
|
|
||||||
bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event)
|
bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event)
|
||||||
{
|
{
|
||||||
if (!m_input_enabled) return true;
|
if (!is_input_enabled()) return true;
|
||||||
if (mouse_event.Moving()) return false;
|
if (mouse_event.Moving()) return false;
|
||||||
if (use_grabbers(mouse_event)) return true;
|
if (use_grabbers(mouse_event)) return true;
|
||||||
|
|
||||||
|
@ -572,13 +523,6 @@ bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoHollow::process_mesh(SLAPrintObjectStep step, bool postpone_error_messages)
|
|
||||||
{
|
|
||||||
wxGetApp().CallAfter([this, step, postpone_error_messages]() {
|
|
||||||
wxGetApp().plater()->reslice_SLA_until_step(step, *m_c->selection_info()->model_object(), postpone_error_messages);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_RAYCAST_PICKING
|
#if ENABLE_RAYCAST_PICKING
|
||||||
void GLGizmoHollow::register_hole_raycasters_for_picking()
|
void GLGizmoHollow::register_hole_raycasters_for_picking()
|
||||||
{
|
{
|
||||||
|
@ -604,22 +548,6 @@ void GLGizmoHollow::unregister_hole_raycasters_for_picking()
|
||||||
m_hole_raycasters.clear();
|
m_hole_raycasters.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoHollow::register_volume_raycasters_for_picking()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
|
||||||
const GLVolume* v = m_volumes.volumes[i];
|
|
||||||
m_volume_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i, *v->mesh_raycaster, v->world_matrix()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoHollow::unregister_volume_raycasters_for_picking()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_volume_raycasters.size(); ++i) {
|
|
||||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i);
|
|
||||||
}
|
|
||||||
m_volume_raycasters.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoHollow::update_hole_raycasters_for_picking_transform()
|
void GLGizmoHollow::update_hole_raycasters_for_picking_transform()
|
||||||
{
|
{
|
||||||
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
||||||
|
@ -646,71 +574,6 @@ void GLGizmoHollow::update_hole_raycasters_for_picking_transform()
|
||||||
}
|
}
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
static int last_completed_step(const SLAPrint& sla)
|
|
||||||
{
|
|
||||||
int step = -1;
|
|
||||||
for (int i = 0; i < (int)SLAPrintObjectStep::slaposCount; ++i) {
|
|
||||||
if (sla.is_step_done((SLAPrintObjectStep)i))
|
|
||||||
++step;
|
|
||||||
}
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoHollow::update_volumes()
|
|
||||||
{
|
|
||||||
m_volumes.clear();
|
|
||||||
unregister_volume_raycasters_for_picking();
|
|
||||||
|
|
||||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
|
||||||
if (mo == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
|
||||||
if (po == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_input_enabled = false;
|
|
||||||
|
|
||||||
TriangleMesh backend_mesh = po->get_mesh_to_print();
|
|
||||||
if (!backend_mesh.empty()) {
|
|
||||||
// The backend has generated a valid mesh. Use it
|
|
||||||
backend_mesh.transform(po->trafo().inverse());
|
|
||||||
m_volumes.volumes.emplace_back(new GLVolume());
|
|
||||||
GLVolume* new_volume = m_volumes.volumes.back();
|
|
||||||
new_volume->model.init_from(backend_mesh);
|
|
||||||
new_volume->set_instance_transformation(po->model_object()->instances[m_parent.get_selection().get_instance_idx()]->get_transformation());
|
|
||||||
new_volume->set_sla_shift_z(po->get_current_elevation());
|
|
||||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(backend_mesh);
|
|
||||||
m_input_enabled = last_completed_step(*m_c->selection_info()->print_object()->print()) >= slaposAssembly;
|
|
||||||
if (m_input_enabled)
|
|
||||||
new_volume->selected = true; // to set the proper color
|
|
||||||
else
|
|
||||||
new_volume->set_color(DISABLED_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_volumes.volumes.empty()) {
|
|
||||||
// No valid mesh found in the backend. Use the selection to duplicate the volumes
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
|
||||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
|
||||||
for (unsigned int idx : idxs) {
|
|
||||||
const GLVolume* v = selection.get_volume(idx);
|
|
||||||
if (!v->is_modifier) {
|
|
||||||
m_volumes.volumes.emplace_back(new GLVolume());
|
|
||||||
GLVolume* new_volume = m_volumes.volumes.back();
|
|
||||||
const TriangleMesh& mesh = mo->volumes[v->volume_idx()]->mesh();
|
|
||||||
new_volume->model.init_from(mesh);
|
|
||||||
new_volume->set_instance_transformation(v->get_instance_transformation());
|
|
||||||
new_volume->set_volume_transformation(v->get_volume_transformation());
|
|
||||||
new_volume->set_sla_shift_z(v->get_sla_shift_z());
|
|
||||||
new_volume->set_color(DISABLED_COLOR);
|
|
||||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register_volume_raycasters_for_picking();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>>
|
std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>>
|
||||||
GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
||||||
{
|
{
|
||||||
|
@ -802,10 +665,10 @@ RENDER_AGAIN:
|
||||||
float window_width = minimal_slider_width + std::max({settings_sliders_left, clipping_slider_left, diameter_slider_left});
|
float window_width = minimal_slider_width + std::max({settings_sliders_left, clipping_slider_left, diameter_slider_left});
|
||||||
window_width = std::max(window_width, button_preview_width);
|
window_width = std::max(window_width, button_preview_width);
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_input_enabled);
|
m_imgui->disabled_begin(!is_input_enabled());
|
||||||
|
|
||||||
if (m_imgui->button(m_desc["preview"]))
|
if (m_imgui->button(m_desc["preview"]))
|
||||||
process_mesh(slaposDrillHoles);
|
reslice_until_step(slaposDrillHoles);
|
||||||
|
|
||||||
bool config_changed = false;
|
bool config_changed = false;
|
||||||
|
|
||||||
|
@ -823,7 +686,7 @@ RENDER_AGAIN:
|
||||||
|
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_input_enabled || !m_enable_hollowing);
|
m_imgui->disabled_begin(!is_input_enabled() || !m_enable_hollowing);
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(m_desc.at("offset"));
|
m_imgui->text(m_desc.at("offset"));
|
||||||
|
@ -891,7 +754,7 @@ RENDER_AGAIN:
|
||||||
m_new_hole_radius = diameter_upper_cap / 2.f;
|
m_new_hole_radius = diameter_upper_cap / 2.f;
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_input_enabled);
|
m_imgui->disabled_begin(!is_input_enabled());
|
||||||
|
|
||||||
m_imgui->text(m_desc.at("hole_diameter"));
|
m_imgui->text(m_desc.at("hole_diameter"));
|
||||||
ImGui::SameLine(diameter_slider_left, m_imgui->get_item_spacing().x);
|
ImGui::SameLine(diameter_slider_left, m_imgui->get_item_spacing().x);
|
||||||
|
@ -958,17 +821,17 @@ RENDER_AGAIN:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_input_enabled || m_selection_empty);
|
m_imgui->disabled_begin(!is_input_enabled() || m_selection_empty);
|
||||||
remove_selected = m_imgui->button(m_desc.at("remove_selected"));
|
remove_selected = m_imgui->button(m_desc.at("remove_selected"));
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_input_enabled || mo->sla_drain_holes.empty());
|
m_imgui->disabled_begin(!is_input_enabled() || mo->sla_drain_holes.empty());
|
||||||
remove_all = m_imgui->button(m_desc.at("remove_all"));
|
remove_all = m_imgui->button(m_desc.at("remove_all"));
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
// Following is rendered in both editing and non-editing mode:
|
// Following is rendered in both editing and non-editing mode:
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
m_imgui->disabled_begin(!m_input_enabled);
|
m_imgui->disabled_begin(!is_input_enabled());
|
||||||
if (m_c->object_clipper()->get_position() == 0.f) {
|
if (m_c->object_clipper()->get_position() == 0.f) {
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||||
|
@ -1043,17 +906,6 @@ std::string GLGizmoHollow::on_get_name() const
|
||||||
return _u8L("Hollow and drill");
|
return _u8L("Hollow and drill");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CommonGizmosDataID GLGizmoHollow::on_get_requirements() const
|
|
||||||
{
|
|
||||||
return CommonGizmosDataID(
|
|
||||||
int(CommonGizmosDataID::SelectionInfo)
|
|
||||||
| int(CommonGizmosDataID::InstancesHider)
|
|
||||||
| int(CommonGizmosDataID::Raycaster)
|
|
||||||
| int(CommonGizmosDataID::ObjectClipper));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoHollow::on_set_state()
|
void GLGizmoHollow::on_set_state()
|
||||||
{
|
{
|
||||||
if (m_state == m_old_state)
|
if (m_state == m_old_state)
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#ifndef slic3r_GLGizmoHollow_hpp_
|
#ifndef slic3r_GLGizmoHollow_hpp_
|
||||||
#define slic3r_GLGizmoHollow_hpp_
|
#define slic3r_GLGizmoHollow_hpp_
|
||||||
|
|
||||||
#include "GLGizmoBase.hpp"
|
#include "GLGizmoSlaBase.hpp"
|
||||||
#include "slic3r/GUI/GLSelectionRectangle.hpp"
|
#include "slic3r/GUI/GLSelectionRectangle.hpp"
|
||||||
#include "slic3r/GUI/3DScene.hpp"
|
|
||||||
|
|
||||||
#include <libslic3r/SLA/Hollowing.hpp>
|
#include <libslic3r/SLA/Hollowing.hpp>
|
||||||
#include <libslic3r/ObjectID.hpp>
|
#include <libslic3r/ObjectID.hpp>
|
||||||
|
@ -21,11 +20,8 @@ namespace GUI {
|
||||||
|
|
||||||
enum class SLAGizmoEventType : unsigned char;
|
enum class SLAGizmoEventType : unsigned char;
|
||||||
class Selection;
|
class Selection;
|
||||||
class GLGizmoHollow : public GLGizmoBase
|
class GLGizmoHollow : public GLGizmoSlaBase
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
void data_changed() override;
|
void data_changed() override;
|
||||||
|
@ -59,30 +55,21 @@ private:
|
||||||
#else
|
#else
|
||||||
void render_points(const Selection& selection, bool picking = false);
|
void render_points(const Selection& selection, bool picking = false);
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
void render_volumes();
|
|
||||||
void process_mesh(SLAPrintObjectStep step, bool postpone_error_messages = false);
|
|
||||||
#if ENABLE_RAYCAST_PICKING
|
#if ENABLE_RAYCAST_PICKING
|
||||||
void register_hole_raycasters_for_picking();
|
void register_hole_raycasters_for_picking();
|
||||||
void unregister_hole_raycasters_for_picking();
|
void unregister_hole_raycasters_for_picking();
|
||||||
void register_volume_raycasters_for_picking();
|
|
||||||
void unregister_volume_raycasters_for_picking();
|
|
||||||
void update_hole_raycasters_for_picking_transform();
|
void update_hole_raycasters_for_picking_transform();
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
void update_volumes();
|
|
||||||
|
|
||||||
ObjectID m_old_mo_id = -1;
|
ObjectID m_old_mo_id = -1;
|
||||||
|
|
||||||
#if ENABLE_RAYCAST_PICKING
|
#if ENABLE_RAYCAST_PICKING
|
||||||
PickingModel m_cylinder;
|
PickingModel m_cylinder;
|
||||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_hole_raycasters;
|
std::vector<std::shared_ptr<SceneRaycasterItem>> m_hole_raycasters;
|
||||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_volume_raycasters;
|
|
||||||
#else
|
#else
|
||||||
GLModel m_cylinder;
|
GLModel m_cylinder;
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
GLVolumeCollection m_volumes;
|
|
||||||
bool m_input_enabled{ false };
|
|
||||||
|
|
||||||
float m_new_hole_radius = 2.f; // Size of a new hole.
|
float m_new_hole_radius = 2.f; // Size of a new hole.
|
||||||
float m_new_hole_height = 6.f;
|
float m_new_hole_height = 6.f;
|
||||||
mutable std::vector<bool> m_selected; // which holes are currently selected
|
mutable std::vector<bool> m_selected; // which holes are currently selected
|
||||||
|
@ -129,7 +116,6 @@ protected:
|
||||||
void on_stop_dragging() override;
|
void on_stop_dragging() override;
|
||||||
void on_dragging(const UpdateData &data) override;
|
void on_dragging(const UpdateData &data) override;
|
||||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||||
virtual CommonGizmosDataID on_get_requirements() const override;
|
|
||||||
|
|
||||||
std::string on_get_name() const override;
|
std::string on_get_name() const override;
|
||||||
bool on_is_activable() const override;
|
bool on_is_activable() const override;
|
||||||
|
|
171
src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp
Normal file
171
src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
#include "libslic3r/libslic3r.h"
|
||||||
|
#include "GLGizmoSlaBase.hpp"
|
||||||
|
#include "slic3r/GUI/Camera.hpp"
|
||||||
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
static const ColorRGBA DISABLED_COLOR = ColorRGBA::DARK_GRAY();
|
||||||
|
#if ENABLE_RAYCAST_PICKING
|
||||||
|
static const int VOLUME_RAYCASTERS_BASE_ID = (int)SceneRaycaster::EIdBase::Gizmo;
|
||||||
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
|
GLGizmoSlaBase::GLGizmoSlaBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, SLAPrintObjectStep min_step)
|
||||||
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
|
, m_min_sla_print_object_step((int)min_step)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void GLGizmoSlaBase::reslice_until_step(SLAPrintObjectStep step, bool postpone_error_messages)
|
||||||
|
{
|
||||||
|
wxGetApp().CallAfter([this, step, postpone_error_messages]() {
|
||||||
|
wxGetApp().plater()->reslice_SLA_until_step(step, *m_c->selection_info()->model_object(), postpone_error_messages);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonGizmosDataID GLGizmoSlaBase::on_get_requirements() const
|
||||||
|
{
|
||||||
|
return CommonGizmosDataID(
|
||||||
|
int(CommonGizmosDataID::SelectionInfo)
|
||||||
|
| int(CommonGizmosDataID::InstancesHider)
|
||||||
|
| int(CommonGizmosDataID::Raycaster)
|
||||||
|
| int(CommonGizmosDataID::ObjectClipper));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaBase::update_volumes()
|
||||||
|
{
|
||||||
|
m_volumes.clear();
|
||||||
|
unregister_volume_raycasters_for_picking();
|
||||||
|
|
||||||
|
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
if (mo == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||||
|
if (po == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_input_enabled = false;
|
||||||
|
|
||||||
|
TriangleMesh backend_mesh = po->get_mesh_to_print();
|
||||||
|
if (!backend_mesh.empty()) {
|
||||||
|
// The backend has generated a valid mesh. Use it
|
||||||
|
backend_mesh.transform(po->trafo().inverse());
|
||||||
|
m_volumes.volumes.emplace_back(new GLVolume());
|
||||||
|
GLVolume* new_volume = m_volumes.volumes.back();
|
||||||
|
new_volume->model.init_from(backend_mesh);
|
||||||
|
new_volume->set_instance_transformation(po->model_object()->instances[m_parent.get_selection().get_instance_idx()]->get_transformation());
|
||||||
|
new_volume->set_sla_shift_z(po->get_current_elevation());
|
||||||
|
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(backend_mesh);
|
||||||
|
m_input_enabled = last_completed_step(*m_c->selection_info()->print_object()->print()) >= m_min_sla_print_object_step;
|
||||||
|
if (m_input_enabled)
|
||||||
|
new_volume->selected = true; // to set the proper color
|
||||||
|
else
|
||||||
|
new_volume->set_color(DISABLED_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_volumes.volumes.empty()) {
|
||||||
|
// No valid mesh found in the backend. Use the selection to duplicate the volumes
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||||
|
for (unsigned int idx : idxs) {
|
||||||
|
const GLVolume* v = selection.get_volume(idx);
|
||||||
|
if (!v->is_modifier) {
|
||||||
|
m_volumes.volumes.emplace_back(new GLVolume());
|
||||||
|
GLVolume* new_volume = m_volumes.volumes.back();
|
||||||
|
const TriangleMesh& mesh = mo->volumes[v->volume_idx()]->mesh();
|
||||||
|
new_volume->model.init_from(mesh);
|
||||||
|
new_volume->set_instance_transformation(v->get_instance_transformation());
|
||||||
|
new_volume->set_volume_transformation(v->get_volume_transformation());
|
||||||
|
new_volume->set_sla_shift_z(v->get_sla_shift_z());
|
||||||
|
new_volume->set_color(DISABLED_COLOR);
|
||||||
|
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLE_RAYCAST_PICKING
|
||||||
|
register_volume_raycasters_for_picking();
|
||||||
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaBase::render_volumes()
|
||||||
|
{
|
||||||
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_clip");
|
||||||
|
if (shader == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shader->start_using();
|
||||||
|
shader->set_uniform("emission_factor", 0.0f);
|
||||||
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
|
||||||
|
ClippingPlane clipping_plane = (m_c->object_clipper()->get_position() == 0.0) ? ClippingPlane::ClipsNothing() : *m_c->object_clipper()->get_clipping_plane();
|
||||||
|
clipping_plane.set_normal(-clipping_plane.get_normal());
|
||||||
|
m_volumes.set_clipping_plane(clipping_plane.get_data());
|
||||||
|
|
||||||
|
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
||||||
|
shader->stop_using();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLE_RAYCAST_PICKING
|
||||||
|
void GLGizmoSlaBase::register_volume_raycasters_for_picking()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
||||||
|
const GLVolume* v = m_volumes.volumes[i];
|
||||||
|
m_volume_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, VOLUME_RAYCASTERS_BASE_ID + (int)i, *v->mesh_raycaster, v->world_matrix()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaBase::unregister_volume_raycasters_for_picking()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_volume_raycasters.size(); ++i) {
|
||||||
|
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, VOLUME_RAYCASTERS_BASE_ID + (int)i);
|
||||||
|
}
|
||||||
|
m_volume_raycasters.clear();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
|
int GLGizmoSlaBase::last_completed_step(const SLAPrint& sla)
|
||||||
|
{
|
||||||
|
int step = -1;
|
||||||
|
for (int i = 0; i < (int)SLAPrintObjectStep::slaposCount; ++i) {
|
||||||
|
if (sla.is_step_done((SLAPrintObjectStep)i))
|
||||||
|
++step;
|
||||||
|
}
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal
|
||||||
|
// Return false if no intersection was found, true otherwise.
|
||||||
|
bool GLGizmoSlaBase::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal)
|
||||||
|
{
|
||||||
|
if (m_c->raycaster()->raycasters().size() != 1)
|
||||||
|
return false;
|
||||||
|
if (!m_c->raycaster()->raycaster())
|
||||||
|
return false;
|
||||||
|
if (m_volumes.volumes.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// The raycaster query
|
||||||
|
Vec3f hit;
|
||||||
|
Vec3f normal;
|
||||||
|
if (m_c->raycaster()->raycaster()->unproject_on_mesh(
|
||||||
|
mouse_pos,
|
||||||
|
m_volumes.volumes.front()->world_matrix(),
|
||||||
|
wxGetApp().plater()->get_camera(),
|
||||||
|
hit,
|
||||||
|
normal,
|
||||||
|
m_c->object_clipper()->get_position() != 0.0 ? m_c->object_clipper()->get_clipping_plane() : nullptr)) {
|
||||||
|
// Return both the point and the facet normal.
|
||||||
|
pos_and_normal = std::make_pair(hit, normal);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GUI
|
||||||
|
} // namespace Slic3r
|
59
src/slic3r/GUI/Gizmos/GLGizmoSlaBase.hpp
Normal file
59
src/slic3r/GUI/Gizmos/GLGizmoSlaBase.hpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef slic3r_GLGizmoSlaBase_hpp_
|
||||||
|
#define slic3r_GLGizmoSlaBase_hpp_
|
||||||
|
|
||||||
|
#include "GLGizmoBase.hpp"
|
||||||
|
#include "slic3r/GUI/3DScene.hpp"
|
||||||
|
#include "slic3r/GUI/SceneRaycaster.hpp"
|
||||||
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
|
#include "libslic3r/Point.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class SLAPrint;
|
||||||
|
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
class GLCanvas3D;
|
||||||
|
|
||||||
|
class GLGizmoSlaBase : public GLGizmoBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLGizmoSlaBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, SLAPrintObjectStep min_step);
|
||||||
|
|
||||||
|
void reslice_until_step(SLAPrintObjectStep step, bool postpone_error_messages = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual CommonGizmosDataID on_get_requirements() const override;
|
||||||
|
|
||||||
|
void update_volumes();
|
||||||
|
void render_volumes();
|
||||||
|
|
||||||
|
#if ENABLE_RAYCAST_PICKING
|
||||||
|
void register_volume_raycasters_for_picking();
|
||||||
|
void unregister_volume_raycasters_for_picking();
|
||||||
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
|
bool is_input_enabled() const { return m_input_enabled; }
|
||||||
|
int get_min_sla_print_object_step() const { return m_min_sla_print_object_step; }
|
||||||
|
|
||||||
|
static int last_completed_step(const SLAPrint& sla);
|
||||||
|
|
||||||
|
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLVolumeCollection m_volumes;
|
||||||
|
bool m_input_enabled{ false };
|
||||||
|
int m_min_sla_print_object_step{ -1 };
|
||||||
|
#if ENABLE_RAYCAST_PICKING
|
||||||
|
std::vector<std::shared_ptr<SceneRaycasterItem>> m_volume_raycasters;
|
||||||
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace GUI
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // slic3r_GLGizmoSlaBase_hpp_
|
|
@ -1,8 +1,6 @@
|
||||||
|
#include "libslic3r/libslic3r.h"
|
||||||
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
|
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
|
||||||
#include "GLGizmoSlaSupports.hpp"
|
#include "GLGizmoSlaSupports.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
|
||||||
#include "slic3r/GUI/Camera.hpp"
|
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
|
|
||||||
#include "slic3r/GUI/MainFrame.hpp"
|
#include "slic3r/GUI/MainFrame.hpp"
|
||||||
#include "slic3r/Utils/UndoRedo.hpp"
|
#include "slic3r/Utils/UndoRedo.hpp"
|
||||||
|
|
||||||
|
@ -12,11 +10,9 @@
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
|
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
|
||||||
#include "slic3r/GUI/NotificationManager.hpp"
|
#include "slic3r/GUI/NotificationManager.hpp"
|
||||||
#include "slic3r/GUI/MsgDialog.hpp"
|
#include "slic3r/GUI/MsgDialog.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
@ -30,10 +26,8 @@ static const double CONE_HEIGHT = 0.75;
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
static const ColorRGBA DISABLED_COLOR = ColorRGBA::DARK_GRAY();
|
|
||||||
|
|
||||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoSlaBase(parent, icon_filename, sprite_id, slaposDrillHoles)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool GLGizmoSlaSupports::on_init()
|
bool GLGizmoSlaSupports::on_init()
|
||||||
|
@ -62,16 +56,6 @@ bool GLGizmoSlaSupports::on_init()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int last_completed_step(const SLAPrint& sla)
|
|
||||||
{
|
|
||||||
int step = -1;
|
|
||||||
for (int i = 0; i < (int)SLAPrintObjectStep::slaposCount; ++i) {
|
|
||||||
if (sla.is_step_done((SLAPrintObjectStep)i))
|
|
||||||
++step;
|
|
||||||
}
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoSlaSupports::data_changed()
|
void GLGizmoSlaSupports::data_changed()
|
||||||
{
|
{
|
||||||
if (! m_c->selection_info())
|
if (! m_c->selection_info())
|
||||||
|
@ -89,8 +73,9 @@ void GLGizmoSlaSupports::data_changed()
|
||||||
if (mo) {
|
if (mo) {
|
||||||
m_c->instances_hider()->set_hide_full_scene(true);
|
m_c->instances_hider()->set_hide_full_scene(true);
|
||||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||||
if (po != nullptr && last_completed_step(*po->print()) < (int)slaposDrillHoles)
|
const int required_step = get_min_sla_print_object_step();
|
||||||
process_mesh(slaposDrillHoles, false);
|
if (po != nullptr && last_completed_step(*po->print()) < required_step)
|
||||||
|
reslice_until_step((SLAPrintObjectStep)required_step, false);
|
||||||
|
|
||||||
update_volumes();
|
update_volumes();
|
||||||
|
|
||||||
|
@ -380,24 +365,6 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSlaSupports::render_volumes()
|
|
||||||
{
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_clip");
|
|
||||||
if (shader == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
shader->start_using();
|
|
||||||
shader->set_uniform("emission_factor", 0.0f);
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
|
||||||
|
|
||||||
ClippingPlane clipping_plane = (m_c->object_clipper()->get_position() == 0.0) ? ClippingPlane::ClipsNothing() : *m_c->object_clipper()->get_clipping_plane();
|
|
||||||
clipping_plane.set_normal(-clipping_plane.get_normal());
|
|
||||||
m_volumes.set_clipping_plane(clipping_plane.get_data());
|
|
||||||
|
|
||||||
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
|
||||||
shader->stop_using();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
|
bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||||
{
|
{
|
||||||
if (m_c->object_clipper()->get_position() == 0.)
|
if (m_c->object_clipper()->get_position() == 0.)
|
||||||
|
@ -413,33 +380,6 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||||
return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point);
|
return m_c->object_clipper()->get_clipping_plane()->is_point_clipped(transformed_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal
|
|
||||||
// Return false if no intersection was found, true otherwise.
|
|
||||||
bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal)
|
|
||||||
{
|
|
||||||
if (!m_c->raycaster()->raycaster())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// The raycaster query
|
|
||||||
Vec3f hit;
|
|
||||||
Vec3f normal;
|
|
||||||
if (m_c->raycaster()->raycaster()->unproject_on_mesh(
|
|
||||||
mouse_pos,
|
|
||||||
m_volumes.volumes.front()->world_matrix(),
|
|
||||||
wxGetApp().plater()->get_camera(),
|
|
||||||
hit,
|
|
||||||
normal,
|
|
||||||
m_c->object_clipper()->get_position() != 0.0 ? m_c->object_clipper()->get_clipping_plane() : nullptr)) {
|
|
||||||
// Return both the point and the facet normal.
|
|
||||||
pos_and_normal = std::make_pair(hit, normal);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
|
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
|
||||||
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
|
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
|
||||||
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
|
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
|
||||||
|
@ -842,7 +782,7 @@ RENDER_AGAIN:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // not in editing mode:
|
else { // not in editing mode:
|
||||||
m_imgui->disabled_begin(!m_input_enabled);
|
m_imgui->disabled_begin(!is_input_enabled());
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(m_desc.at("minimal_distance"));
|
m_imgui->text(m_desc.at("minimal_distance"));
|
||||||
|
@ -895,7 +835,7 @@ RENDER_AGAIN:
|
||||||
|
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_input_enabled || m_normal_cache.empty());
|
m_imgui->disabled_begin(!is_input_enabled() || m_normal_cache.empty());
|
||||||
remove_all = m_imgui->button(m_desc.at("remove_all"));
|
remove_all = m_imgui->button(m_desc.at("remove_all"));
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
@ -908,7 +848,7 @@ RENDER_AGAIN:
|
||||||
|
|
||||||
|
|
||||||
// Following is rendered in both editing and non-editing mode:
|
// Following is rendered in both editing and non-editing mode:
|
||||||
m_imgui->disabled_begin(!m_input_enabled);
|
m_imgui->disabled_begin(!is_input_enabled());
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (m_c->object_clipper()->get_position() == 0.f) {
|
if (m_c->object_clipper()->get_position() == 0.f) {
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
|
@ -991,17 +931,6 @@ std::string GLGizmoSlaSupports::on_get_name() const
|
||||||
return _u8L("SLA Support Points");
|
return _u8L("SLA Support Points");
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonGizmosDataID GLGizmoSlaSupports::on_get_requirements() const
|
|
||||||
{
|
|
||||||
return CommonGizmosDataID(
|
|
||||||
int(CommonGizmosDataID::SelectionInfo)
|
|
||||||
| int(CommonGizmosDataID::InstancesHider)
|
|
||||||
| int(CommonGizmosDataID::Raycaster)
|
|
||||||
| int(CommonGizmosDataID::ObjectClipper));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoSlaSupports::ask_about_changes_call_after(std::function<void()> on_yes, std::function<void()> on_no)
|
void GLGizmoSlaSupports::ask_about_changes_call_after(std::function<void()> on_yes, std::function<void()> on_no)
|
||||||
{
|
{
|
||||||
wxGetApp().CallAfter([on_yes, on_no]() {
|
wxGetApp().CallAfter([on_yes, on_no]() {
|
||||||
|
@ -1189,7 +1118,7 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
|
||||||
mo->sla_support_points.clear();
|
mo->sla_support_points.clear();
|
||||||
mo->sla_support_points = m_normal_cache;
|
mo->sla_support_points = m_normal_cache;
|
||||||
|
|
||||||
reslice_SLA_supports();
|
reslice_until_step(slaposPad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1221,17 +1150,9 @@ bool GLGizmoSlaSupports::has_backend_supports() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSlaSupports::reslice_SLA_supports(bool postpone_error_messages) const
|
|
||||||
{
|
|
||||||
wxGetApp().CallAfter([this, postpone_error_messages]() {
|
|
||||||
wxGetApp().plater()->reslice_SLA_supports(
|
|
||||||
*m_c->selection_info()->model_object(), postpone_error_messages);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLGizmoSlaSupports::on_mouse(const wxMouseEvent &mouse_event)
|
bool GLGizmoSlaSupports::on_mouse(const wxMouseEvent &mouse_event)
|
||||||
{
|
{
|
||||||
if (!m_input_enabled) return true;
|
if (!is_input_enabled()) return true;
|
||||||
if (mouse_event.Moving()) return false;
|
if (mouse_event.Moving()) return false;
|
||||||
if (!mouse_event.ShiftDown() && !mouse_event.AltDown()
|
if (!mouse_event.ShiftDown() && !mouse_event.AltDown()
|
||||||
&& use_grabbers(mouse_event)) return true;
|
&& use_grabbers(mouse_event)) return true;
|
||||||
|
@ -1324,7 +1245,7 @@ void GLGizmoSlaSupports::auto_generate()
|
||||||
|
|
||||||
if (mo->sla_points_status != sla::PointsStatus::UserModified || m_normal_cache.empty() || dlg.ShowModal() == wxID_YES) {
|
if (mo->sla_points_status != sla::PointsStatus::UserModified || m_normal_cache.empty() || dlg.ShowModal() == wxID_YES) {
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
|
||||||
wxGetApp().CallAfter([this]() { reslice_SLA_supports(); });
|
wxGetApp().CallAfter([this]() { reslice_until_step(slaposPad); });
|
||||||
mo->sla_points_status = sla::PointsStatus::Generating;
|
mo->sla_points_status = sla::PointsStatus::Generating;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1395,22 +1316,6 @@ void GLGizmoSlaSupports::unregister_point_raycasters_for_picking()
|
||||||
m_point_raycasters.clear();
|
m_point_raycasters.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoSlaSupports::register_volume_raycasters_for_picking()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
|
||||||
const GLVolume* v = m_volumes.volumes[i];
|
|
||||||
m_volume_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i, *v->mesh_raycaster, v->world_matrix()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoSlaSupports::unregister_volume_raycasters_for_picking()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_volume_raycasters.size(); ++i) {
|
|
||||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i);
|
|
||||||
}
|
|
||||||
m_volume_raycasters.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoSlaSupports::update_point_raycasters_for_picking_transform()
|
void GLGizmoSlaSupports::update_point_raycasters_for_picking_transform()
|
||||||
{
|
{
|
||||||
if (m_editing_cache.empty())
|
if (m_editing_cache.empty())
|
||||||
|
@ -1442,68 +1347,6 @@ void GLGizmoSlaSupports::update_point_raycasters_for_picking_transform()
|
||||||
}
|
}
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
void GLGizmoSlaSupports::update_volumes()
|
|
||||||
{
|
|
||||||
m_volumes.clear();
|
|
||||||
unregister_volume_raycasters_for_picking();
|
|
||||||
|
|
||||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
|
||||||
if (mo == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
|
||||||
if (po == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_input_enabled = false;
|
|
||||||
|
|
||||||
TriangleMesh backend_mesh = po->get_mesh_to_print();
|
|
||||||
if (!backend_mesh.empty()) {
|
|
||||||
// The backend has generated a valid mesh. Use it
|
|
||||||
backend_mesh.transform(po->trafo().inverse());
|
|
||||||
m_volumes.volumes.emplace_back(new GLVolume());
|
|
||||||
GLVolume* new_volume = m_volumes.volumes.back();
|
|
||||||
new_volume->model.init_from(backend_mesh);
|
|
||||||
new_volume->set_instance_transformation(po->model_object()->instances[m_parent.get_selection().get_instance_idx()]->get_transformation());
|
|
||||||
new_volume->set_sla_shift_z(po->get_current_elevation());
|
|
||||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(backend_mesh);
|
|
||||||
m_input_enabled = last_completed_step(*m_c->selection_info()->print_object()->print()) >= slaposDrillHoles;
|
|
||||||
if (m_input_enabled)
|
|
||||||
new_volume->selected = true; // to set the proper color
|
|
||||||
else
|
|
||||||
new_volume->set_color(DISABLED_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_volumes.volumes.empty()) {
|
|
||||||
// No valid mesh found in the backend. Use the selection to duplicate the volumes
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
|
||||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
|
||||||
for (unsigned int idx : idxs) {
|
|
||||||
const GLVolume* v = selection.get_volume(idx);
|
|
||||||
if (!v->is_modifier) {
|
|
||||||
m_volumes.volumes.emplace_back(new GLVolume());
|
|
||||||
GLVolume* new_volume = m_volumes.volumes.back();
|
|
||||||
const TriangleMesh& mesh = mo->volumes[v->volume_idx()]->mesh();
|
|
||||||
new_volume->model.init_from(mesh);
|
|
||||||
new_volume->set_instance_transformation(v->get_instance_transformation());
|
|
||||||
new_volume->set_volume_transformation(v->get_volume_transformation());
|
|
||||||
new_volume->set_sla_shift_z(v->get_sla_shift_z());
|
|
||||||
new_volume->set_color(DISABLED_COLOR);
|
|
||||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register_volume_raycasters_for_picking();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoSlaSupports::process_mesh(SLAPrintObjectStep step, bool postpone_error_messages)
|
|
||||||
{
|
|
||||||
wxGetApp().CallAfter([this, step, postpone_error_messages]() {
|
|
||||||
wxGetApp().plater()->reslice_SLA_until_step(step, *m_c->selection_info()->model_object(), postpone_error_messages);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
SlaGizmoHelpDialog::SlaGizmoHelpDialog()
|
SlaGizmoHelpDialog::SlaGizmoHelpDialog()
|
||||||
: wxDialog(nullptr, wxID_ANY, _L("SLA gizmo keyboard shortcuts"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
: wxDialog(nullptr, wxID_ANY, _L("SLA gizmo keyboard shortcuts"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#ifndef slic3r_GLGizmoSlaSupports_hpp_
|
#ifndef slic3r_GLGizmoSlaSupports_hpp_
|
||||||
#define slic3r_GLGizmoSlaSupports_hpp_
|
#define slic3r_GLGizmoSlaSupports_hpp_
|
||||||
|
|
||||||
#include "GLGizmoBase.hpp"
|
#include "GLGizmoSlaBase.hpp"
|
||||||
#include "slic3r/GUI/GLSelectionRectangle.hpp"
|
#include "slic3r/GUI/GLSelectionRectangle.hpp"
|
||||||
#include "slic3r/GUI/3DScene.hpp"
|
|
||||||
|
|
||||||
#include "libslic3r/SLA/SupportPoint.hpp"
|
#include "libslic3r/SLA/SupportPoint.hpp"
|
||||||
#include "libslic3r/ObjectID.hpp"
|
#include "libslic3r/ObjectID.hpp"
|
||||||
|
@ -20,11 +19,9 @@ namespace GUI {
|
||||||
class Selection;
|
class Selection;
|
||||||
enum class SLAGizmoEventType : unsigned char;
|
enum class SLAGizmoEventType : unsigned char;
|
||||||
|
|
||||||
class GLGizmoSlaSupports : public GLGizmoBase
|
class GLGizmoSlaSupports : public GLGizmoSlaBase
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
|
|
||||||
|
|
||||||
static constexpr float RenderPointScale = 1.f;
|
static constexpr float RenderPointScale = 1.f;
|
||||||
|
|
||||||
class CacheEntry {
|
class CacheEntry {
|
||||||
|
@ -65,7 +62,6 @@ public:
|
||||||
bool is_in_editing_mode() const override { return m_editing_mode; }
|
bool is_in_editing_mode() const override { return m_editing_mode; }
|
||||||
bool is_selection_rectangle_dragging() const override { return m_selection_rectangle.is_dragging(); }
|
bool is_selection_rectangle_dragging() const override { return m_selection_rectangle.is_dragging(); }
|
||||||
bool has_backend_supports() const;
|
bool has_backend_supports() const;
|
||||||
void reslice_SLA_supports(bool postpone_error_messages = false) const;
|
|
||||||
|
|
||||||
bool wants_enter_leave_snapshots() const override { return true; }
|
bool wants_enter_leave_snapshots() const override { return true; }
|
||||||
std::string get_gizmo_entering_text() const override { return _u8L("Entering SLA support points"); }
|
std::string get_gizmo_entering_text() const override { return _u8L("Entering SLA support points"); }
|
||||||
|
@ -93,17 +89,12 @@ private:
|
||||||
#else
|
#else
|
||||||
void render_points(const Selection& selection, bool picking = false);
|
void render_points(const Selection& selection, bool picking = false);
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
void render_volumes();
|
|
||||||
bool unsaved_changes() const;
|
bool unsaved_changes() const;
|
||||||
#if ENABLE_RAYCAST_PICKING
|
#if ENABLE_RAYCAST_PICKING
|
||||||
void register_point_raycasters_for_picking();
|
void register_point_raycasters_for_picking();
|
||||||
void unregister_point_raycasters_for_picking();
|
void unregister_point_raycasters_for_picking();
|
||||||
void register_volume_raycasters_for_picking();
|
|
||||||
void unregister_volume_raycasters_for_picking();
|
|
||||||
void update_point_raycasters_for_picking_transform();
|
void update_point_raycasters_for_picking_transform();
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
void update_volumes();
|
|
||||||
void process_mesh(SLAPrintObjectStep step, bool postpone_error_messages = false);
|
|
||||||
|
|
||||||
bool m_lock_unique_islands = false;
|
bool m_lock_unique_islands = false;
|
||||||
bool m_editing_mode = false; // Is editing mode active?
|
bool m_editing_mode = false; // Is editing mode active?
|
||||||
|
@ -120,15 +111,11 @@ private:
|
||||||
PickingModel m_sphere;
|
PickingModel m_sphere;
|
||||||
PickingModel m_cone;
|
PickingModel m_cone;
|
||||||
std::vector<std::pair<std::shared_ptr<SceneRaycasterItem>, std::shared_ptr<SceneRaycasterItem>>> m_point_raycasters;
|
std::vector<std::pair<std::shared_ptr<SceneRaycasterItem>, std::shared_ptr<SceneRaycasterItem>>> m_point_raycasters;
|
||||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_volume_raycasters;
|
|
||||||
#else
|
#else
|
||||||
GLModel m_cone;
|
GLModel m_cone;
|
||||||
GLModel m_sphere;
|
GLModel m_sphere;
|
||||||
#endif // ENABLE_RAYCAST_PICKING
|
#endif // ENABLE_RAYCAST_PICKING
|
||||||
|
|
||||||
GLVolumeCollection m_volumes;
|
|
||||||
bool m_input_enabled{ false };
|
|
||||||
|
|
||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
std::map<std::string, wxString> m_desc;
|
std::map<std::string, wxString> m_desc;
|
||||||
|
@ -174,7 +161,6 @@ protected:
|
||||||
std::string on_get_name() const override;
|
std::string on_get_name() const override;
|
||||||
bool on_is_activable() const override;
|
bool on_is_activable() const override;
|
||||||
bool on_is_selectable() const override;
|
bool on_is_selectable() const override;
|
||||||
virtual CommonGizmosDataID on_get_requirements() const override;
|
|
||||||
void on_load(cereal::BinaryInputArchive& ar) override;
|
void on_load(cereal::BinaryInputArchive& ar) override;
|
||||||
void on_save(cereal::BinaryOutputArchive& ar) const override;
|
void on_save(cereal::BinaryOutputArchive& ar) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -683,7 +683,7 @@ void GLGizmosManager::update_after_undo_redo(const UndoRedo::Snapshot& snapshot)
|
||||||
m_serializing = false;
|
m_serializing = false;
|
||||||
if (m_current == SlaSupports
|
if (m_current == SlaSupports
|
||||||
&& snapshot.snapshot_data.flags & UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS)
|
&& snapshot.snapshot_data.flags & UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS)
|
||||||
dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->reslice_SLA_supports(true);
|
dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->reslice_until_step(slaposPad, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
|
@ -6370,16 +6370,6 @@ void Plater::reslice()
|
||||||
p->preview->reload_print(!clean_gcode_toolpaths);
|
p->preview->reload_print(!clean_gcode_toolpaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::reslice_SLA_supports(const ModelObject &object, bool postpone_error_messages)
|
|
||||||
{
|
|
||||||
reslice_SLA_until_step(slaposPad, object, postpone_error_messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Plater::reslice_SLA_hollowing(const ModelObject &object, bool postpone_error_messages)
|
|
||||||
{
|
|
||||||
reslice_SLA_until_step(slaposDrillHoles, object, postpone_error_messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Plater::reslice_until_step_inner(int step, const ModelObject &object, bool postpone_error_messages)
|
void Plater::reslice_until_step_inner(int step, const ModelObject &object, bool postpone_error_messages)
|
||||||
{
|
{
|
||||||
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
|
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
|
||||||
|
|
|
@ -266,8 +266,6 @@ public:
|
||||||
void export_toolpaths_to_obj() const;
|
void export_toolpaths_to_obj() const;
|
||||||
void reslice();
|
void reslice();
|
||||||
void reslice_FFF_until_step(PrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false);
|
void reslice_FFF_until_step(PrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false);
|
||||||
void reslice_SLA_supports(const ModelObject &object, bool postpone_error_messages = false);
|
|
||||||
void reslice_SLA_hollowing(const ModelObject &object, bool postpone_error_messages = false);
|
|
||||||
void reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false);
|
void reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false);
|
||||||
|
|
||||||
void clear_before_change_mesh(int obj_idx);
|
void clear_before_change_mesh(int obj_idx);
|
||||||
|
|
Loading…
Reference in a new issue