Merge branch 'lm_sla_supports_auto2' of https://github.com/prusa3d/Slic3r into lm_sla_supports_auto2
This commit is contained in:
commit
9a8a9bac28
@ -2630,28 +2630,19 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->default_value = new ConfigOptionFloat(5.0);
|
def->default_value = new ConfigOptionFloat(5.0);
|
||||||
|
|
||||||
def = this->add("support_density_at_horizontal", coInt);
|
def = this->add("support_points_density_relative", coInt);
|
||||||
def->label = L("Density on horizontal surfaces");
|
def->label = L("Support points density");
|
||||||
def->category = L("Supports");
|
def->category = L("Supports");
|
||||||
def->tooltip = L("How many support points (approximately) should be placed on horizontal surface.");
|
def->tooltip = L("This is a relative measure of support points density.");
|
||||||
def->sidetext = L("points per square dm");
|
def->sidetext = L("%");
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->default_value = new ConfigOptionInt(500);
|
def->default_value = new ConfigOptionInt(100);
|
||||||
|
|
||||||
def = this->add("support_density_at_45", coInt);
|
def = this->add("support_points_minimal_distance", coFloat);
|
||||||
def->label = L("Density on surfaces at 45 degrees");
|
def->label = L("Minimal distance of the support points");
|
||||||
def->category = L("Supports");
|
def->category = L("Supports");
|
||||||
def->tooltip = L("How many support points (approximately) should be placed on surface sloping at 45 degrees.");
|
def->tooltip = L("No support points will be placed closer than this threshold.");
|
||||||
def->sidetext = L("points per square dm");
|
|
||||||
def->cli = "";
|
|
||||||
def->min = 0;
|
|
||||||
def->default_value = new ConfigOptionInt(250);
|
|
||||||
|
|
||||||
def = this->add("support_minimal_z", coFloat);
|
|
||||||
def->label = L("Minimal support point height");
|
|
||||||
def->category = L("Supports");
|
|
||||||
def->tooltip = L("No support points will be placed lower than this value from the bottom.");
|
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
@ -1002,9 +1002,8 @@ public:
|
|||||||
ConfigOptionFloat support_object_elevation /*= 5.0*/;
|
ConfigOptionFloat support_object_elevation /*= 5.0*/;
|
||||||
|
|
||||||
/////// Following options influence automatic support points placement:
|
/////// Following options influence automatic support points placement:
|
||||||
ConfigOptionInt support_density_at_horizontal;
|
ConfigOptionInt support_points_density_relative;
|
||||||
ConfigOptionInt support_density_at_45;
|
ConfigOptionFloat support_points_minimal_distance;
|
||||||
ConfigOptionFloat support_minimal_z;
|
|
||||||
|
|
||||||
// Now for the base pool (pad) /////////////////////////////////////////////
|
// Now for the base pool (pad) /////////////////////////////////////////////
|
||||||
|
|
||||||
@ -1040,9 +1039,8 @@ protected:
|
|||||||
OPT_PTR(support_base_height);
|
OPT_PTR(support_base_height);
|
||||||
OPT_PTR(support_critical_angle);
|
OPT_PTR(support_critical_angle);
|
||||||
OPT_PTR(support_max_bridge_length);
|
OPT_PTR(support_max_bridge_length);
|
||||||
OPT_PTR(support_density_at_horizontal);
|
OPT_PTR(support_points_density_relative);
|
||||||
OPT_PTR(support_density_at_45);
|
OPT_PTR(support_points_minimal_distance);
|
||||||
OPT_PTR(support_minimal_z);
|
|
||||||
OPT_PTR(support_object_elevation);
|
OPT_PTR(support_object_elevation);
|
||||||
OPT_PTR(pad_enable);
|
OPT_PTR(pad_enable);
|
||||||
OPT_PTR(pad_wall_thickness);
|
OPT_PTR(pad_wall_thickness);
|
||||||
|
@ -233,7 +233,7 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
|
|||||||
// s.supports_force_inherited /= std::max(1.f, (layer_height / 0.3f) * e_area / s.area);
|
// s.supports_force_inherited /= std::max(1.f, (layer_height / 0.3f) * e_area / s.area);
|
||||||
s.supports_force_inherited /= std::max(1.f, 0.17f * (s.overhangs_area) / s.area);
|
s.supports_force_inherited /= std::max(1.f, 0.17f * (s.overhangs_area) / s.area);
|
||||||
|
|
||||||
float force_deficit = s.support_force_deficit(m_config.tear_pressure);
|
float force_deficit = s.support_force_deficit(m_config.tear_pressure());
|
||||||
if (s.islands_below.empty()) { // completely new island - needs support no doubt
|
if (s.islands_below.empty()) { // completely new island - needs support no doubt
|
||||||
uniformly_cover({ *s.polygon }, s, point_grid, true);
|
uniformly_cover({ *s.polygon }, s, point_grid, true);
|
||||||
} else if (! s.dangling_areas.empty()) {
|
} else if (! s.dangling_areas.empty()) {
|
||||||
@ -439,16 +439,16 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru
|
|||||||
{
|
{
|
||||||
//int num_of_points = std::max(1, (int)((island.area()*pow(SCALING_FACTOR, 2) * m_config.tear_pressure)/m_config.support_force));
|
//int num_of_points = std::max(1, (int)((island.area()*pow(SCALING_FACTOR, 2) * m_config.tear_pressure)/m_config.support_force));
|
||||||
|
|
||||||
const float support_force_deficit = structure.support_force_deficit(m_config.tear_pressure);
|
const float support_force_deficit = structure.support_force_deficit(m_config.tear_pressure());
|
||||||
if (support_force_deficit < 0)
|
if (support_force_deficit < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Number of newly added points.
|
// Number of newly added points.
|
||||||
const size_t poisson_samples_target = size_t(ceil(support_force_deficit / m_config.support_force));
|
const size_t poisson_samples_target = size_t(ceil(support_force_deficit / m_config.support_force()));
|
||||||
|
|
||||||
const float density_horizontal = m_config.tear_pressure / m_config.support_force;
|
const float density_horizontal = m_config.tear_pressure() / m_config.support_force();
|
||||||
//FIXME why?
|
//FIXME why?
|
||||||
float poisson_radius = 1.f / (5.f * density_horizontal);
|
float poisson_radius = std::max(m_config.minimal_distance, 1.f / (5.f * density_horizontal));
|
||||||
// const float poisson_radius = 1.f / (15.f * density_horizontal);
|
// const float poisson_radius = 1.f / (15.f * density_horizontal);
|
||||||
const float samples_per_mm2 = 30.f / (float(M_PI) * poisson_radius * poisson_radius);
|
const float samples_per_mm2 = 30.f / (float(M_PI) * poisson_radius * poisson_radius);
|
||||||
// Minimum distance between samples, in 3D space.
|
// Minimum distance between samples, in 3D space.
|
||||||
@ -465,13 +465,13 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru
|
|||||||
[&structure, &grid3d, min_spacing](const Vec2f &pos) {
|
[&structure, &grid3d, min_spacing](const Vec2f &pos) {
|
||||||
return grid3d.collides_with(pos, &structure, min_spacing);
|
return grid3d.collides_with(pos, &structure, min_spacing);
|
||||||
});
|
});
|
||||||
if (poisson_samples.size() >= poisson_samples_target)
|
if (poisson_samples.size() >= poisson_samples_target || m_config.minimal_distance > poisson_radius-EPSILON)
|
||||||
break;
|
break;
|
||||||
float coeff = 0.5f;
|
float coeff = 0.5f;
|
||||||
if (poisson_samples.size() * 2 > poisson_samples_target)
|
if (poisson_samples.size() * 2 > poisson_samples_target)
|
||||||
coeff = float(poisson_samples.size()) / float(poisson_samples_target);
|
coeff = float(poisson_samples.size()) / float(poisson_samples_target);
|
||||||
poisson_radius *= coeff;
|
poisson_radius = std::max(m_config.minimal_distance, poisson_radius * coeff);
|
||||||
min_spacing *= coeff;
|
min_spacing = std::max(m_config.minimal_distance, min_spacing * coeff);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SLA_AUTOSUPPORTS_DEBUG
|
#ifdef SLA_AUTOSUPPORTS_DEBUG
|
||||||
@ -494,7 +494,7 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru
|
|||||||
}
|
}
|
||||||
for (const Vec2f &pt : poisson_samples) {
|
for (const Vec2f &pt : poisson_samples) {
|
||||||
m_output.emplace_back(float(pt(0)), float(pt(1)), structure.height, 0.2f, is_new_island);
|
m_output.emplace_back(float(pt(0)), float(pt(1)), structure.height, 0.2f, is_new_island);
|
||||||
structure.supports_force_this_layer += m_config.support_force;
|
structure.supports_force_this_layer += m_config.support_force();
|
||||||
grid3d.insert(pt, &structure);
|
grid3d.insert(pt, &structure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,11 @@ namespace Slic3r {
|
|||||||
class SLAAutoSupports {
|
class SLAAutoSupports {
|
||||||
public:
|
public:
|
||||||
struct Config {
|
struct Config {
|
||||||
float density_at_horizontal;
|
float density_relative;
|
||||||
float density_at_45;
|
float minimal_distance;
|
||||||
float minimal_z;
|
|
||||||
///////////////
|
///////////////
|
||||||
// float support_force = 30.f; // a force one point can support (arbitrary force unit)
|
inline float support_force() const { return 10.f / density_relative; } // a force one point can support (arbitrary force unit)
|
||||||
float support_force = 10.f; // a force one point can support (arbitrary force unit)
|
inline float tear_pressure() const { return 1.f; } // pressure that the display exerts (the force unit per mm2)
|
||||||
float tear_pressure = 1.f; // pressure that the display exerts (the force unit per mm2)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices,
|
SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices,
|
||||||
|
@ -33,6 +33,7 @@ struct SupportPoint {
|
|||||||
pos(data(0), data(1), data(2)), head_front_radius(data(3)), is_new_island(data(4) != 0.f) {}
|
pos(data(0), data(1), data(2)), head_front_radius(data(3)), is_new_island(data(4) != 0.f) {}
|
||||||
|
|
||||||
bool operator==(const SupportPoint& sp) const { return (pos==sp.pos) && head_front_radius==sp.head_front_radius && is_new_island==sp.is_new_island; }
|
bool operator==(const SupportPoint& sp) const { return (pos==sp.pos) && head_front_radius==sp.head_front_radius && is_new_island==sp.is_new_island; }
|
||||||
|
bool operator!=(const SupportPoint& sp) const { return !(sp == (*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -532,9 +532,8 @@ void SLAPrint::process()
|
|||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
SLAAutoSupports::Config config;
|
SLAAutoSupports::Config config;
|
||||||
const SLAPrintObjectConfig& cfg = po.config();
|
const SLAPrintObjectConfig& cfg = po.config();
|
||||||
config.minimal_z = float(cfg.support_minimal_z);
|
config.density_relative = (float)cfg.support_points_density_relative / 100.f; // the config value is in percents
|
||||||
config.density_at_45 = cfg.support_density_at_45 / 10000.f;
|
config.minimal_distance = cfg.support_points_minimal_distance;
|
||||||
config.density_at_horizontal = cfg.support_density_at_horizontal / 10000.f;
|
|
||||||
|
|
||||||
// Construction of this object does the calculation.
|
// Construction of this object does the calculation.
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
@ -1064,7 +1063,10 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
|||||||
for (const t_config_option_key &opt_key : opt_keys) {
|
for (const t_config_option_key &opt_key : opt_keys) {
|
||||||
if (opt_key == "layer_height") {
|
if (opt_key == "layer_height") {
|
||||||
steps.emplace_back(slaposObjectSlice);
|
steps.emplace_back(slaposObjectSlice);
|
||||||
} else if (opt_key == "supports_enable") {
|
} else if (
|
||||||
|
opt_key == "supports_enable"
|
||||||
|
|| opt_key == "support_points_density_relative"
|
||||||
|
|| opt_key == "support_points_minimal_distance") {
|
||||||
steps.emplace_back(slaposSupportPoints);
|
steps.emplace_back(slaposSupportPoints);
|
||||||
} else if (
|
} else if (
|
||||||
opt_key == "support_head_front_diameter"
|
opt_key == "support_head_front_diameter"
|
||||||
|
@ -3158,6 +3158,7 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec
|
|||||||
float cnv_h = (float)canvas.get_canvas_size().get_height();
|
float cnv_h = (float)canvas.get_canvas_size().get_height();
|
||||||
float height = _get_total_overlay_height();
|
float height = _get_total_overlay_height();
|
||||||
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
||||||
|
|
||||||
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||||
{
|
{
|
||||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||||
@ -5448,10 +5449,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
|
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
/*else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse() && evt.RightDown()) {
|
else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::RightDown))
|
||||||
if (m_gizmos.get_current_type() == Gizmos::SlaSupports)
|
{
|
||||||
m_gizmos.delete_current_grabber();
|
// event was taken care of by the SlaSupports gizmo
|
||||||
}*/
|
}
|
||||||
else if (view_toolbar_contains_mouse != -1)
|
else if (view_toolbar_contains_mouse != -1)
|
||||||
{
|
{
|
||||||
if (m_view_toolbar != nullptr)
|
if (m_view_toolbar != nullptr)
|
||||||
@ -5691,9 +5692,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
||||||
}
|
}
|
||||||
else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging()
|
else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging()
|
||||||
&& !is_layers_editing_enabled() && m_gizmos.get_current_type() != Gizmos::SlaSupports)
|
&& !is_layers_editing_enabled() && (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown())))
|
||||||
{
|
{
|
||||||
// SLA gizmo cannot be deselected by clicking in canvas area to avoid inadvertent unselection and losing manual changes
|
// SLA gizmo cannot be deselected by clicking in canvas area to avoid inadvertent unselection and losing manual changes
|
||||||
|
// that's why the mouse_event function was called so that the gizmo can refuse the deselection in manual editing mode
|
||||||
|
|
||||||
// deselect and propagate event through callback
|
// deselect and propagate event through callback
|
||||||
if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event)
|
if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event)
|
||||||
|
@ -136,6 +136,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
|
|||||||
enum class SLAGizmoEventType {
|
enum class SLAGizmoEventType {
|
||||||
LeftDown = 1,
|
LeftDown = 1,
|
||||||
LeftUp,
|
LeftUp,
|
||||||
|
RightDown,
|
||||||
Dragging,
|
Dragging,
|
||||||
Delete,
|
Delete,
|
||||||
SelectAll,
|
SelectAll,
|
||||||
|
@ -1784,23 +1784,15 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G
|
|||||||
|
|
||||||
m_active_instance = selection.get_instance_idx();
|
m_active_instance = selection.get_instance_idx();
|
||||||
|
|
||||||
if ((model_object != nullptr) && selection.is_from_single_instance())
|
if (model_object && selection.is_from_single_instance())
|
||||||
{
|
{
|
||||||
if (is_mesh_update_necessary())
|
if (is_mesh_update_necessary())
|
||||||
update_mesh();
|
update_mesh();
|
||||||
|
|
||||||
// If there are no points, let's ask the backend if it calculated some.
|
// If there are no points, let's ask the backend if it calculated some.
|
||||||
if (m_editing_mode_cache.empty() && m_parent.sla_print()->is_step_done(slaposSupportPoints)) {
|
if (m_editing_mode_cache.empty() && m_parent.sla_print()->is_step_done(slaposSupportPoints))
|
||||||
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
|
get_data_from_backend();
|
||||||
if (po->model_object()->id() == model_object->id()) {
|
|
||||||
const std::vector<sla::SupportPoint>& points = po->get_support_points();
|
|
||||||
auto mat = po->trafo().inverse().cast<float>();
|
|
||||||
for (unsigned int i=0; i<points.size();++i)
|
|
||||||
m_editing_mode_cache.emplace_back(sla::SupportPoint(mat * points[i].pos, points[i].head_front_radius, points[i].is_new_island), false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_model_object != m_old_model_object)
|
if (m_model_object != m_old_model_object)
|
||||||
m_editing_mode = false;
|
m_editing_mode = false;
|
||||||
if (m_state == On) {
|
if (m_state == On) {
|
||||||
@ -1919,7 +1911,7 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
::glColor3fv(render_color);
|
::glColor3fv(render_color);
|
||||||
float render_color_emissive[4] = { 0.5 * render_color[0], 0.5 * render_color[1], 0.5 * render_color[2], 1.f};
|
float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f};
|
||||||
::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive);
|
::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive);
|
||||||
|
|
||||||
// Now render the sphere. Inverse matrix of the instance scaling is applied so that the
|
// Now render the sphere. Inverse matrix of the instance scaling is applied so that the
|
||||||
@ -1981,9 +1973,7 @@ void GLGizmoSlaSupports::update_mesh()
|
|||||||
m_AABB.init(m_V, m_F);
|
m_AABB.init(m_V, m_F);
|
||||||
|
|
||||||
// we'll now reload support points (selection might have changed):
|
// we'll now reload support points (selection might have changed):
|
||||||
m_editing_mode_cache.clear();
|
editing_mode_reload_cache();
|
||||||
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
|
||||||
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
|
Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
|
||||||
@ -2045,7 +2035,7 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
m_canvas_height = m_parent.get_canvas_size().get_height();
|
m_canvas_height = m_parent.get_canvas_size().get_height();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_editing_mode_cache[m_hover_id].second = true;
|
select_point(m_hover_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2075,16 +2065,16 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Regardless of whether the user clicked the object or not, we will unselect all points:
|
// Regardless of whether the user clicked the object or not, we will unselect all points:
|
||||||
for (unsigned int i=0; i<m_editing_mode_cache.size(); ++i)
|
select_point(NoPoints);
|
||||||
m_editing_mode_cache[i].second = false;
|
|
||||||
|
|
||||||
Vec3f new_pos;
|
Vec3f new_pos;
|
||||||
try {
|
try {
|
||||||
new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new point in that case
|
new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new point in that case
|
||||||
m_editing_mode_cache.emplace_back(std::make_pair(sla::SupportPoint(new_pos, m_new_point_head_diameter/2.f, false), true));
|
m_editing_mode_cache.emplace_back(std::make_pair(sla::SupportPoint(new_pos, m_new_point_head_diameter/2.f, false), true));
|
||||||
|
m_unsaved_changes = true;
|
||||||
}
|
}
|
||||||
catch (...) { // not clicked on object
|
catch (...) { // not clicked on object
|
||||||
return false; // GLCanvas3D might want to deselect the gizmo
|
return true; // prevents deselection of the gizmo by GLCanvas3D
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2148,9 +2138,18 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action == SLAGizmoEventType::RightDown) {
|
||||||
|
if (m_hover_id != -1) {
|
||||||
|
select_point(NoPoints);
|
||||||
|
select_point(m_hover_id);
|
||||||
|
delete_selected_points();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (action == SLAGizmoEventType::SelectAll) {
|
if (action == SLAGizmoEventType::SelectAll) {
|
||||||
for (auto& point_and_selection : m_editing_mode_cache)
|
select_point(AllPoints);
|
||||||
point_and_selection.second = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2163,8 +2162,10 @@ void GLGizmoSlaSupports::delete_selected_points()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
|
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
|
||||||
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands))
|
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands)) {
|
||||||
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
|
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
|
||||||
|
m_unsaved_changes = true;
|
||||||
|
}
|
||||||
// This should trigger the support generation
|
// This should trigger the support generation
|
||||||
// wxGetApp().plater()->reslice();
|
// wxGetApp().plater()->reslice();
|
||||||
}
|
}
|
||||||
@ -2182,6 +2183,7 @@ void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Sel
|
|||||||
catch (...) { return; }
|
catch (...) { return; }
|
||||||
m_editing_mode_cache[m_hover_id].first.pos = new_pos;
|
m_editing_mode_cache[m_hover_id].first.pos = new_pos;
|
||||||
m_editing_mode_cache[m_hover_id].first.is_new_island = false;
|
m_editing_mode_cache[m_hover_id].first.is_new_island = false;
|
||||||
|
m_unsaved_changes = true;
|
||||||
// Do not update immediately, wait until the mouse is released.
|
// Do not update immediately, wait until the mouse is released.
|
||||||
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||||
}
|
}
|
||||||
@ -2237,6 +2239,7 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
if (m_editing_mode) {
|
if (m_editing_mode) {
|
||||||
m_imgui->text(_(L("Left mouse click - add point")));
|
m_imgui->text(_(L("Left mouse click - add point")));
|
||||||
|
m_imgui->text(_(L("Right mouse click - remove point")));
|
||||||
m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)")));
|
m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)")));
|
||||||
m_imgui->text(" "); // vertical gap
|
m_imgui->text(" "); // vertical gap
|
||||||
|
|
||||||
@ -2250,12 +2253,16 @@ RENDER_AGAIN:
|
|||||||
force_refresh |= (old_combo_state != m_combo_box_open);
|
force_refresh |= (old_combo_state != m_combo_box_open);
|
||||||
|
|
||||||
float current_number = atof(str);
|
float current_number = atof(str);
|
||||||
|
if (old_combo_state && !m_combo_box_open) // closing the combo must always change the sizes (even if the selection did not change)
|
||||||
|
for (auto& point_and_selection : m_editing_mode_cache)
|
||||||
|
if (point_and_selection.second) {
|
||||||
|
point_and_selection.first.head_front_radius = current_number / 2.f;
|
||||||
|
m_unsaved_changes = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::abs(current_number - m_new_point_head_diameter) > 0.001) {
|
if (std::abs(current_number - m_new_point_head_diameter) > 0.001) {
|
||||||
force_refresh = true;
|
force_refresh = true;
|
||||||
m_new_point_head_diameter = current_number;
|
m_new_point_head_diameter = current_number;
|
||||||
for (auto& point_and_selection : m_editing_mode_cache)
|
|
||||||
if (point_and_selection.second)
|
|
||||||
point_and_selection.first.head_front_radius = current_number / 2.f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool changed = m_lock_unique_islands;
|
bool changed = m_lock_unique_islands;
|
||||||
@ -2268,30 +2275,25 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
bool apply_changes = m_imgui->button(_(L("Apply changes")));
|
bool apply_changes = m_imgui->button(_(L("Apply changes")));
|
||||||
if (apply_changes) {
|
if (apply_changes) {
|
||||||
m_model_object->sla_support_points.clear();
|
editing_mode_apply_changes();
|
||||||
for (const std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache)
|
|
||||||
m_model_object->sla_support_points.push_back(point_and_selection.first);
|
|
||||||
m_editing_mode = false;
|
|
||||||
force_refresh = true;
|
force_refresh = true;
|
||||||
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
bool discard_changes = m_imgui->button(_(L("Discard changes")));
|
bool discard_changes = m_imgui->button(_(L("Discard changes")));
|
||||||
if (discard_changes) {
|
if (discard_changes) {
|
||||||
m_editing_mode_cache.clear();
|
editing_mode_discard_changes();
|
||||||
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
|
||||||
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
|
||||||
m_editing_mode = false;
|
|
||||||
force_refresh = true;
|
force_refresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//m_imgui->text("Some settings could");
|
/* ImGui::PushItemWidth(50.0f);
|
||||||
//m_imgui->text("be exposed here...");
|
m_imgui->text(_(L("Minimal points distance: ")));
|
||||||
m_imgui->text("");
|
ImGui::SameLine();
|
||||||
m_imgui->text("");
|
bool value_changed = ImGui::InputDouble("mm", &m_minimal_point_distance, 0.0f, 0.0f, "%.2f");
|
||||||
|
m_imgui->text(_(L("Support points density: ")));
|
||||||
m_imgui->text("");
|
ImGui::SameLine();
|
||||||
|
value_changed |= ImGui::InputDouble("%", &m_density, 0.0f, 0.0f, "%.f");*/
|
||||||
|
|
||||||
bool generate = m_imgui->button(_(L("Auto-generate points")));
|
bool generate = m_imgui->button(_(L("Auto-generate points")));
|
||||||
|
|
||||||
@ -2302,10 +2304,10 @@ RENDER_AGAIN:
|
|||||||
force_refresh = true;
|
force_refresh = true;
|
||||||
#else
|
#else
|
||||||
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L(
|
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L(
|
||||||
"Autogeneration will erase all currently assigned points.\n\n"
|
"Autogeneration will erase all manually edited points.\n\n"
|
||||||
"Are you sure you want to do it?\n"
|
"Are you sure you want to do it?\n"
|
||||||
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
|
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
|
||||||
if (dlg.ShowModal() == wxID_YES) {
|
if (m_model_object->sla_support_points.empty() || dlg.ShowModal() == wxID_YES) {
|
||||||
m_model_object->sla_support_points.clear();
|
m_model_object->sla_support_points.clear();
|
||||||
m_editing_mode_cache.clear();
|
m_editing_mode_cache.clear();
|
||||||
wxGetApp().plater()->reslice();
|
wxGetApp().plater()->reslice();
|
||||||
@ -2316,7 +2318,7 @@ RENDER_AGAIN:
|
|||||||
if (m_show_modal) {
|
if (m_show_modal) {
|
||||||
if (ImGui::BeginPopupModal(_(L("Warning")), &m_show_modal/*, ImGuiWindowFlags_NoDecoration*/))
|
if (ImGui::BeginPopupModal(_(L("Warning")), &m_show_modal/*, ImGuiWindowFlags_NoDecoration*/))
|
||||||
{
|
{
|
||||||
m_imgui->text(_(L("Autogeneration will erase all currently assigned points.")));
|
m_imgui->text(_(L("Autogeneration will erase all manually edited points.")));
|
||||||
m_imgui->text("");
|
m_imgui->text("");
|
||||||
m_imgui->text(_(L("Are you sure you want to do it?")));
|
m_imgui->text(_(L("Are you sure you want to do it?")));
|
||||||
|
|
||||||
@ -2341,12 +2343,11 @@ RENDER_AGAIN:
|
|||||||
force_refresh = true;
|
force_refresh = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ImGui::SameLine();
|
m_imgui->text("");
|
||||||
bool editing_clicked = m_imgui->button("Editing");
|
m_imgui->text("");
|
||||||
|
bool editing_clicked = m_imgui->button(_(L("Manual editing")));
|
||||||
if (editing_clicked) {
|
if (editing_clicked) {
|
||||||
m_editing_mode_cache.clear();
|
editing_mode_reload_cache();
|
||||||
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
|
||||||
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
|
||||||
m_editing_mode = true;
|
m_editing_mode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2376,8 +2377,17 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const
|
bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const
|
||||||
{
|
{
|
||||||
return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA)
|
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
|
||||||
&& selection.is_from_single_instance();
|
|| !selection.is_from_single_instance())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check that none of the selected volumes is outside.
|
||||||
|
const GLCanvas3D::Selection::IndicesList& list = selection.get_volume_idxs();
|
||||||
|
for (const auto& idx : list)
|
||||||
|
if (selection.get_volume(idx)->is_outside)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoSlaSupports::on_is_selectable() const
|
bool GLGizmoSlaSupports::on_is_selectable() const
|
||||||
@ -2401,12 +2411,19 @@ void GLGizmoSlaSupports::on_set_state()
|
|||||||
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
|
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
|
||||||
}
|
}
|
||||||
if (m_state == Off) {
|
if (m_state == Off) {
|
||||||
|
if (m_old_state != Off && m_model_object) { // the gizmo was just turned Off
|
||||||
|
|
||||||
|
if (m_unsaved_changes) {
|
||||||
|
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
|
||||||
|
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
|
||||||
|
if (dlg.ShowModal() == wxID_YES)
|
||||||
|
editing_mode_apply_changes();
|
||||||
|
else
|
||||||
|
editing_mode_discard_changes();
|
||||||
|
}
|
||||||
|
|
||||||
m_parent.toggle_model_objects_visibility(true);
|
m_parent.toggle_model_objects_visibility(true);
|
||||||
m_editing_mode_cache.clear();
|
m_editing_mode = false; // so it is not active next time the gizmo opens
|
||||||
if (m_model_object)
|
|
||||||
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
|
||||||
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
|
||||||
m_editing_mode = false;
|
|
||||||
|
|
||||||
#if SLAGIZMO_IMGUI_MODAL
|
#if SLAGIZMO_IMGUI_MODAL
|
||||||
if (m_show_modal) {
|
if (m_show_modal) {
|
||||||
@ -2416,14 +2433,72 @@ void GLGizmoSlaSupports::on_set_state()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_old_state = m_state;
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection)
|
void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection)
|
||||||
{
|
{
|
||||||
if (m_hover_id != -1)
|
if (m_hover_id != -1) {
|
||||||
for (unsigned int i=0;i<m_editing_mode_cache.size();++i)
|
select_point(NoPoints);
|
||||||
m_editing_mode_cache[i].second = ((int)i == m_hover_id);
|
select_point(m_hover_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaSupports::select_point(int i)
|
||||||
|
{
|
||||||
|
if (i == AllPoints || i == NoPoints) {
|
||||||
|
for (auto& point_and_selection : m_editing_mode_cache)
|
||||||
|
point_and_selection.second = ( i == AllPoints ? true : false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_editing_mode_cache[i].second = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaSupports::editing_mode_discard_changes()
|
||||||
|
{
|
||||||
|
m_editing_mode_cache.clear();
|
||||||
|
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
||||||
|
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
||||||
|
m_editing_mode = false;
|
||||||
|
m_unsaved_changes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaSupports::editing_mode_apply_changes()
|
||||||
|
{
|
||||||
|
// If there are no changes, don't touch the front-end. The data in the cache could have been
|
||||||
|
// taken from the backend and copying them to ModelObject would needlessly invalidate them.
|
||||||
|
if (m_unsaved_changes) {
|
||||||
|
m_model_object->sla_support_points.clear();
|
||||||
|
for (const std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache)
|
||||||
|
m_model_object->sla_support_points.push_back(point_and_selection.first);
|
||||||
|
}
|
||||||
|
m_editing_mode = false;
|
||||||
|
m_unsaved_changes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaSupports::editing_mode_reload_cache()
|
||||||
|
{
|
||||||
|
m_editing_mode_cache.clear();
|
||||||
|
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
||||||
|
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
||||||
|
m_unsaved_changes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoSlaSupports::get_data_from_backend()
|
||||||
|
{
|
||||||
|
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
|
||||||
|
if (po->model_object()->id() == m_model_object->id()) {
|
||||||
|
const std::vector<sla::SupportPoint>& points = po->get_support_points();
|
||||||
|
auto mat = po->trafo().inverse().cast<float>();
|
||||||
|
for (unsigned int i=0; i<points.size();++i)
|
||||||
|
m_editing_mode_cache.emplace_back(sla::SupportPoint(mat * points[i].pos, points[i].head_front_radius, points[i].is_new_island), false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_unsaved_changes = false;
|
||||||
|
|
||||||
|
// We don't copy the data into ModelObject, as this would stop the background processing.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// GLGizmoCut
|
// GLGizmoCut
|
||||||
|
@ -492,6 +492,8 @@ private:
|
|||||||
bool m_lock_unique_islands = false;
|
bool m_lock_unique_islands = false;
|
||||||
bool m_editing_mode = false;
|
bool m_editing_mode = false;
|
||||||
float m_new_point_head_diameter = 0.4f;
|
float m_new_point_head_diameter = 0.4f;
|
||||||
|
double m_minimal_point_distance = 20.;
|
||||||
|
double m_density = 100.;
|
||||||
std::vector<std::pair<sla::SupportPoint, bool>> m_editing_mode_cache; // a support point and whether it is currently selected
|
std::vector<std::pair<sla::SupportPoint, bool>> m_editing_mode_cache; // a support point and whether it is currently selected
|
||||||
|
|
||||||
bool m_selection_rectangle_active = false;
|
bool m_selection_rectangle_active = false;
|
||||||
@ -499,12 +501,26 @@ private:
|
|||||||
Vec2d m_selection_rectangle_end_corner;
|
Vec2d m_selection_rectangle_end_corner;
|
||||||
bool m_ignore_up_event = false;
|
bool m_ignore_up_event = false;
|
||||||
bool m_combo_box_open = false;
|
bool m_combo_box_open = false;
|
||||||
|
bool m_unsaved_changes = false;
|
||||||
|
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
|
||||||
#if SLAGIZMO_IMGUI_MODAL
|
#if SLAGIZMO_IMGUI_MODAL
|
||||||
bool m_show_modal = false;
|
bool m_show_modal = false;
|
||||||
#endif
|
#endif
|
||||||
int m_canvas_width;
|
int m_canvas_width;
|
||||||
int m_canvas_height;
|
int m_canvas_height;
|
||||||
|
|
||||||
|
// Methods that do the model_object and editing cache synchronization,
|
||||||
|
// editing mode selection, etc:
|
||||||
|
enum {
|
||||||
|
AllPoints = -2,
|
||||||
|
NoPoints,
|
||||||
|
};
|
||||||
|
void select_point(int i);
|
||||||
|
void editing_mode_apply_changes();
|
||||||
|
void editing_mode_discard_changes();
|
||||||
|
void editing_mode_reload_cache();
|
||||||
|
void get_data_from_backend();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void on_set_state() override;
|
void on_set_state() override;
|
||||||
void on_start_dragging(const GLCanvas3D::Selection& selection) override;
|
void on_start_dragging(const GLCanvas3D::Selection& selection) override;
|
||||||
|
@ -2232,7 +2232,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS) {
|
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS) {
|
||||||
// Update SLA gizmo
|
// Update SLA gizmo (reload_scene calls update_gizmos_data)
|
||||||
q->canvas3D()->reload_scene(true);
|
q->canvas3D()->reload_scene(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,9 +457,8 @@ const std::vector<std::string>& Preset::sla_print_options()
|
|||||||
"support_critical_angle",
|
"support_critical_angle",
|
||||||
"support_max_bridge_length",
|
"support_max_bridge_length",
|
||||||
"support_object_elevation",
|
"support_object_elevation",
|
||||||
"support_density_at_horizontal",
|
"support_points_density_relative",
|
||||||
"support_density_at_45",
|
"support_points_minimal_distance",
|
||||||
"support_minimal_z",
|
|
||||||
"pad_enable",
|
"pad_enable",
|
||||||
"pad_wall_thickness",
|
"pad_wall_thickness",
|
||||||
"pad_wall_height",
|
"pad_wall_height",
|
||||||
|
@ -3202,9 +3202,8 @@ void TabSLAPrint::build()
|
|||||||
optgroup->append_single_option_line("support_max_bridge_length");
|
optgroup->append_single_option_line("support_max_bridge_length");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Automatic generation")));
|
optgroup = page->new_optgroup(_(L("Automatic generation")));
|
||||||
optgroup->append_single_option_line("support_density_at_horizontal");
|
optgroup->append_single_option_line("support_points_density_relative");
|
||||||
optgroup->append_single_option_line("support_density_at_45");
|
optgroup->append_single_option_line("support_points_minimal_distance");
|
||||||
optgroup->append_single_option_line("support_minimal_z");
|
|
||||||
|
|
||||||
page = add_options_page(_(L("Pad")), "brick.png");
|
page = add_options_page(_(L("Pad")), "brick.png");
|
||||||
optgroup = page->new_optgroup(_(L("Pad")));
|
optgroup = page->new_optgroup(_(L("Pad")));
|
||||||
|
Loading…
Reference in New Issue
Block a user