Custom supports data are saved into ModelObject and propagate to the backend
Invalidation of supports after they change is not implemented yet.
This commit is contained in:
parent
46ade45ced
commit
546b0702f9
@ -1149,6 +1149,8 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
||||
for (ModelVolume *volume : volumes) {
|
||||
const auto volume_matrix = volume->get_matrix();
|
||||
|
||||
volume->m_supported_facets.clear();
|
||||
|
||||
if (! volume->is_model_part()) {
|
||||
// Modifiers are not cut, but we still need to add the instance transformation
|
||||
// to the modifier volume transformation to preserve their shape properly.
|
||||
@ -1848,6 +1850,41 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::vector<int> FacetsAnnotation::get_facets(FacetSupportType type) const
|
||||
{
|
||||
std::vector<int> out;
|
||||
for (auto& [facet_idx, this_type] : m_data)
|
||||
if (this_type == type)
|
||||
out.push_back(facet_idx);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FacetsAnnotation::set_facet(int idx, FacetSupportType type)
|
||||
{
|
||||
bool changed = true;
|
||||
|
||||
if (type == FacetSupportType::NONE)
|
||||
changed = m_data.erase(idx) != 0;
|
||||
else
|
||||
m_data[idx] = type;
|
||||
|
||||
if (changed)
|
||||
update_timestamp();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FacetsAnnotation::clear()
|
||||
{
|
||||
m_data.clear();
|
||||
update_timestamp();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
||||
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
||||
bool model_object_list_equal(const Model &model_old, const Model &model_new)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
namespace cereal {
|
||||
class BinaryInputArchive;
|
||||
@ -391,6 +392,35 @@ enum class ModelVolumeType : int {
|
||||
SUPPORT_BLOCKER,
|
||||
};
|
||||
|
||||
enum class FacetSupportType : int8_t {
|
||||
NONE = 0,
|
||||
ENFORCER = 1,
|
||||
BLOCKER = 2
|
||||
};
|
||||
|
||||
class FacetsAnnotation {
|
||||
public:
|
||||
using ClockType = std::chrono::steady_clock;
|
||||
|
||||
|
||||
std::vector<int> get_facets(FacetSupportType type) const;
|
||||
void set_facet(int idx, FacetSupportType type);
|
||||
void clear();
|
||||
|
||||
ClockType::time_point get_timestamp() const { return timestamp; }
|
||||
bool is_newer_than(const FacetsAnnotation& other) const {
|
||||
return timestamp > other.get_timestamp();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<int, FacetSupportType> m_data;
|
||||
|
||||
ClockType::time_point timestamp;
|
||||
void update_timestamp() {
|
||||
timestamp = ClockType::now();
|
||||
}
|
||||
};
|
||||
|
||||
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
||||
// ModelVolume instances are owned by a ModelObject.
|
||||
class ModelVolume final : public ObjectBase
|
||||
@ -421,6 +451,9 @@ public:
|
||||
// overriding the global Slic3r settings and the ModelObject settings.
|
||||
ModelConfig config;
|
||||
|
||||
// List of mesh facets to be supported/unsupported.
|
||||
FacetsAnnotation m_supported_facets;
|
||||
|
||||
// A parent object owning this modifier volume.
|
||||
ModelObject* get_object() const { return this->object; };
|
||||
ModelVolumeType type() const { return m_type; }
|
||||
@ -548,7 +581,9 @@ private:
|
||||
// Copying an existing volume, therefore this volume will get a copy of the ID assigned.
|
||||
ModelVolume(ModelObject *object, const ModelVolume &other) :
|
||||
ObjectBase(other),
|
||||
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation)
|
||||
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
|
||||
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
|
||||
m_supported_facets(other.m_supported_facets)
|
||||
{
|
||||
assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id());
|
||||
assert(this->id() == other.id() && this->config.id() == other.config.id());
|
||||
@ -565,6 +600,8 @@ private:
|
||||
if (mesh.stl.stats.number_of_facets > 1)
|
||||
calculate_convex_hull();
|
||||
assert(this->config.id().valid()); assert(this->config.id() != other.config.id()); assert(this->id() != this->config.id());
|
||||
|
||||
m_supported_facets.clear();
|
||||
}
|
||||
|
||||
ModelVolume& operator=(ModelVolume &rhs) = delete;
|
||||
|
@ -404,6 +404,7 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst,
|
||||
// Copy the ModelVolume data.
|
||||
mv_dst.name = mv_src.name;
|
||||
static_cast<DynamicPrintConfig&>(mv_dst.config) = static_cast<const DynamicPrintConfig&>(mv_src.config);
|
||||
mv_dst.m_supported_facets = mv_src.m_supported_facets;
|
||||
//FIXME what to do with the materials?
|
||||
// mv_dst.m_material_id = mv_src.m_material_id;
|
||||
++ i_src;
|
||||
@ -881,7 +882,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
}
|
||||
}
|
||||
}
|
||||
// Synchronize (just copy) the remaining data of ModelVolumes (name, config).
|
||||
// Synchronize (just copy) the remaining data of ModelVolumes (name, config, custom supports data).
|
||||
//FIXME What to do with m_material_id?
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART);
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
|
||||
|
||||
@ -187,7 +188,16 @@ void GLGizmoFdmSupports::update_mesh()
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
const TriangleMesh* mesh = &mv->mesh();
|
||||
|
||||
m_selected_facets[volume_id].assign(mesh->its.indices.size(), SelType::NONE);
|
||||
m_selected_facets[volume_id].assign(mesh->its.indices.size(), FacetSupportType::NONE);
|
||||
|
||||
// Load current state from ModelVolume.
|
||||
for (FacetSupportType type : {FacetSupportType::ENFORCER, FacetSupportType::BLOCKER}) {
|
||||
const std::vector<int>& list = mv->m_supported_facets.get_facets(type);
|
||||
for (int i : list)
|
||||
m_selected_facets[volume_id][i] = type;
|
||||
}
|
||||
update_vertex_buffers(mv, volume_id, true, true);
|
||||
|
||||
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
||||
|
||||
// Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets
|
||||
@ -243,16 +253,16 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
|| action == SLAGizmoEventType::RightDown
|
||||
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) {
|
||||
|
||||
SelType new_state = SelType::NONE;
|
||||
FacetSupportType new_state = FacetSupportType::NONE;
|
||||
if (! shift_down) {
|
||||
if (action == SLAGizmoEventType::Dragging)
|
||||
new_state = m_button_down == Button::Left
|
||||
? SelType::ENFORCER
|
||||
: SelType::BLOCKER;
|
||||
? FacetSupportType::ENFORCER
|
||||
: FacetSupportType::BLOCKER;
|
||||
else
|
||||
new_state = action == SLAGizmoEventType::LeftDown
|
||||
? SelType::ENFORCER
|
||||
: SelType::BLOCKER;
|
||||
? FacetSupportType::ENFORCER
|
||||
: FacetSupportType::BLOCKER;
|
||||
}
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
@ -379,9 +389,9 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
|
||||
// Now just select all facets that passed.
|
||||
for (size_t next_facet : facets_to_select) {
|
||||
SelType& facet = m_selected_facets[mesh_id][next_facet];
|
||||
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
||||
|
||||
if (facet != new_state && facet != SelType::NONE) {
|
||||
if (facet != new_state && facet != FacetSupportType::NONE) {
|
||||
// this triangle is currently in the other VBA.
|
||||
// Both VBAs need to be refreshed.
|
||||
update_both = true;
|
||||
@ -391,8 +401,8 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
}
|
||||
|
||||
update_vertex_buffers(mv, mesh_id,
|
||||
new_state == SelType::ENFORCER || update_both,
|
||||
new_state == SelType::BLOCKER || update_both
|
||||
new_state == FacetSupportType::ENFORCER || update_both,
|
||||
new_state == FacetSupportType::BLOCKER || update_both
|
||||
);
|
||||
}
|
||||
|
||||
@ -416,6 +426,18 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
||||
&& m_button_down != Button::None) {
|
||||
m_button_down = Button::None;
|
||||
|
||||
// Synchronize gizmo with ModelVolume data.
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
++idx;
|
||||
if (! mv->is_model_part())
|
||||
continue;
|
||||
for (int i=0; i<int(m_selected_facets[idx].size()); ++i)
|
||||
mv->m_supported_facets.set_facet(i, m_selected_facets[idx][i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -430,16 +452,16 @@ void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
||||
{
|
||||
const TriangleMesh* mesh = &mv->mesh();
|
||||
|
||||
for (SelType type : {SelType::ENFORCER, SelType::BLOCKER}) {
|
||||
if ((type == SelType::ENFORCER && ! update_enforcers)
|
||||
|| (type == SelType::BLOCKER && ! update_blockers))
|
||||
for (FacetSupportType type : {FacetSupportType::ENFORCER, FacetSupportType::BLOCKER}) {
|
||||
if ((type == FacetSupportType::ENFORCER && ! update_enforcers)
|
||||
|| (type == FacetSupportType::BLOCKER && ! update_blockers))
|
||||
continue;
|
||||
|
||||
GLIndexedVertexArray& iva = m_ivas[mesh_id][type==SelType::ENFORCER ? 0 : 1];
|
||||
GLIndexedVertexArray& iva = m_ivas[mesh_id][type==FacetSupportType::ENFORCER ? 0 : 1];
|
||||
iva.release_geometry();
|
||||
size_t triangle_cnt=0;
|
||||
for (size_t facet_idx=0; facet_idx<m_selected_facets[mesh_id].size(); ++facet_idx) {
|
||||
SelType status = m_selected_facets[mesh_id][facet_idx];
|
||||
FacetSupportType status = m_selected_facets[mesh_id][facet_idx];
|
||||
if (status != type)
|
||||
continue;
|
||||
for (int i=0; i<3; ++i)
|
||||
|
@ -9,6 +9,9 @@
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class FacetSupportType : int8_t;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
enum class SLAGizmoEventType : unsigned char;
|
||||
@ -26,15 +29,9 @@ private:
|
||||
static constexpr float CursorRadiusMax = 8.f;
|
||||
static constexpr float CursorRadiusStep = 0.2f;
|
||||
|
||||
enum class SelType : int8_t {
|
||||
NONE,
|
||||
ENFORCER,
|
||||
BLOCKER
|
||||
};
|
||||
|
||||
// For each model-part volume, store a list of statuses of
|
||||
// individual facets (one of the enum values above).
|
||||
std::vector<std::vector<SelType>> m_selected_facets;
|
||||
std::vector<std::vector<FacetSupportType>> m_selected_facets;
|
||||
|
||||
// Store two vertex buffer arrays (for enforcers/blockers)
|
||||
// for each model-part volume.
|
||||
|
Loading…
Reference in New Issue
Block a user