mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-04 06:11:02 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
391c53a8da |
@@ -304,7 +304,8 @@ ConfigOption* ConfigOptionDef::create_default_option() const
|
||||
return new ConfigOptionEnumGeneric(this->enum_keys_map, this->default_value->getInt());
|
||||
|
||||
if (type == coEnums) {
|
||||
if (this->default_value->nullable()) {
|
||||
auto dft = this->default_value->clone();
|
||||
if (dft->nullable()) {
|
||||
ConfigOptionEnumsGenericNullable *opt = dynamic_cast<ConfigOptionEnumsGenericNullable *>(this->default_value->clone());
|
||||
opt->keys_map = this->enum_keys_map;
|
||||
return opt;
|
||||
@@ -313,6 +314,7 @@ ConfigOption* ConfigOptionDef::create_default_option() const
|
||||
opt->keys_map = this->enum_keys_map;
|
||||
return opt;
|
||||
}
|
||||
delete dft;
|
||||
}
|
||||
|
||||
return this->default_value->clone();
|
||||
|
||||
@@ -360,7 +360,7 @@ void Layer::simplify_support_entity_collection(ExtrusionEntityCollection* entity
|
||||
//BBS: method to simplify support path
|
||||
void Layer::simplify_support_path(ExtrusionPath * path)
|
||||
{
|
||||
const auto print_config = this->object()->print()->config();
|
||||
const PrintConfig &print_config = this->object()->print()->config();
|
||||
const bool spiral_mode = print_config.spiral_mode;
|
||||
const bool enable_arc_fitting = print_config.enable_arc_fitting;
|
||||
const auto scaled_resolution = scaled<double>(print_config.resolution.value);
|
||||
@@ -375,7 +375,7 @@ void Layer::simplify_support_path(ExtrusionPath * path)
|
||||
//BBS: method to simplify support path
|
||||
void Layer::simplify_support_multi_path(ExtrusionMultiPath* multipath)
|
||||
{
|
||||
const auto print_config = this->object()->print()->config();
|
||||
const PrintConfig &print_config = this->object()->print()->config();
|
||||
const bool spiral_mode = print_config.spiral_mode;
|
||||
const bool enable_arc_fitting = print_config.enable_arc_fitting;
|
||||
const auto scaled_resolution = scaled<double>(print_config.resolution.value);
|
||||
@@ -392,7 +392,7 @@ void Layer::simplify_support_multi_path(ExtrusionMultiPath* multipath)
|
||||
//BBS: method to simplify support path
|
||||
void Layer::simplify_support_loop(ExtrusionLoop* loop)
|
||||
{
|
||||
const auto print_config = this->object()->print()->config();
|
||||
const PrintConfig &print_config = this->object()->print()->config();
|
||||
const bool spiral_mode = print_config.spiral_mode;
|
||||
const bool enable_arc_fitting = print_config.enable_arc_fitting;
|
||||
const auto scaled_resolution = scaled<double>(print_config.resolution.value);
|
||||
|
||||
@@ -1074,7 +1074,7 @@ void LayerRegion::simplify_entity_collection(ExtrusionEntityCollection* entity_c
|
||||
|
||||
void LayerRegion::simplify_path(ExtrusionPath* path)
|
||||
{
|
||||
const auto print_config = this->layer()->object()->print()->config();
|
||||
const PrintConfig &print_config = this->layer()->object()->print()->config();
|
||||
const bool spiral_mode = print_config.spiral_mode;
|
||||
const bool enable_arc_fitting = print_config.enable_arc_fitting;
|
||||
const auto scaled_resolution = scaled<double>(print_config.resolution.value);
|
||||
@@ -1092,7 +1092,7 @@ void LayerRegion::simplify_path(ExtrusionPath* path)
|
||||
|
||||
void LayerRegion::simplify_multi_path(ExtrusionMultiPath* multipath)
|
||||
{
|
||||
const auto print_config = this->layer()->object()->print()->config();
|
||||
const PrintConfig &print_config = this->layer()->object()->print()->config();
|
||||
const bool spiral_mode = print_config.spiral_mode;
|
||||
const bool enable_arc_fitting = print_config.enable_arc_fitting;
|
||||
const auto scaled_resolution = scaled<double>(print_config.resolution.value);
|
||||
@@ -1112,7 +1112,7 @@ void LayerRegion::simplify_multi_path(ExtrusionMultiPath* multipath)
|
||||
|
||||
void LayerRegion::simplify_loop(ExtrusionLoop* loop)
|
||||
{
|
||||
const auto print_config = this->layer()->object()->print()->config();
|
||||
const PrintConfig &print_config = this->layer()->object()->print()->config();
|
||||
const bool spiral_mode = print_config.spiral_mode;
|
||||
const bool enable_arc_fitting = print_config.enable_arc_fitting;
|
||||
const auto scaled_resolution = scaled<double>(print_config.resolution.value);
|
||||
|
||||
+17
-18
@@ -2087,6 +2087,11 @@ void ModelVolume::reset_extra_facets()
|
||||
this->seam_facets.reset();
|
||||
this->mmu_segmentation_facets.reset();
|
||||
this->fuzzy_skin_facets.reset();
|
||||
// Texture-displacement paint data has no remap-across-topology-change support yet (see
|
||||
// build_texture_displacement()'s documented limitation), so it must be dropped here rather
|
||||
// than left referring to a mesh that no longer matches it.
|
||||
for (int i = 0; i < int(TEXTURE_DISPLACEMENT_MAX_LAYERS); ++i)
|
||||
this->texture_displacement_facet(i).reset();
|
||||
}
|
||||
|
||||
std::optional<TriangleSelector::SavedPainting> ModelVolume::save_painting() const
|
||||
@@ -2648,22 +2653,16 @@ std::vector<int> ModelVolume::get_extruders() const
|
||||
return std::vector<int>();
|
||||
|
||||
if (mmu_segmentation_facets.timestamp() != mmuseg_ts) {
|
||||
std::vector<indexed_triangle_set> its_per_type;
|
||||
mmuseg_extruders.clear();
|
||||
mmuseg_ts = mmu_segmentation_facets.timestamp();
|
||||
// ORCA: without painting data every facet keeps its default (NONE) state, so no extruder
|
||||
// other than the volume's own one can be painted on it. Skip get_facets() then: it builds a
|
||||
// TriangleSelector with one node per facet over the whole mesh (tens of MiB on a dense one)
|
||||
// only to hand back empty sets for every extruder.
|
||||
if (! mmu_segmentation_facets.empty()) {
|
||||
std::vector<indexed_triangle_set> its_per_type;
|
||||
mmu_segmentation_facets.get_facets(*this, its_per_type);
|
||||
for (int idx = 1; idx < its_per_type.size(); idx++) {
|
||||
indexed_triangle_set& its = its_per_type[idx];
|
||||
if (its.indices.empty())
|
||||
continue;
|
||||
mmu_segmentation_facets.get_facets(*this, its_per_type);
|
||||
for (int idx = 1; idx < its_per_type.size(); idx++) {
|
||||
indexed_triangle_set& its = its_per_type[idx];
|
||||
if (its.indices.empty())
|
||||
continue;
|
||||
|
||||
mmuseg_extruders.push_back(idx);
|
||||
}
|
||||
mmuseg_extruders.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2995,6 +2994,11 @@ void ModelVolume::assign_new_unique_ids_recursive()
|
||||
seam_facets.set_new_unique_id();
|
||||
mmu_segmentation_facets.set_new_unique_id();
|
||||
fuzzy_skin_facets.set_new_unique_id();
|
||||
// As set_new_unique_id() already does: the undo/redo stack stores FacetsAnnotation contents keyed
|
||||
// by ObjectID, so a clone left sharing these ids with its source can be handed the source's mask
|
||||
// on an undo - after which a paint mask and the mesh it was recorded against no longer match.
|
||||
for (int i = 0; i < int(TEXTURE_DISPLACEMENT_MAX_LAYERS); ++i)
|
||||
texture_displacement_facet(i).set_new_unique_id();
|
||||
}
|
||||
|
||||
void ModelVolume::rotate(double angle, Axis axis)
|
||||
@@ -3632,11 +3636,6 @@ ModelInstanceEPrintVolumeState ModelInstance::calc_print_volume_state(const Buil
|
||||
|
||||
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||
{
|
||||
// ORCA: nothing is painted, so only the NONE state can have facets. Answering for any other
|
||||
// state needs no TriangleSelector (one node per facet of the whole mesh) at all.
|
||||
if (this->empty() && type != EnforcerBlockerType::NONE)
|
||||
return {};
|
||||
|
||||
TriangleSelector selector(mv.mesh());
|
||||
// Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize().
|
||||
selector.deserialize(m_data, false);
|
||||
|
||||
+13
-11
@@ -2604,6 +2604,11 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
||||
|
||||
void PrintObject::set_shared_object(PrintObject *object)
|
||||
{
|
||||
// Orca: from now on m_layers / m_support_layers only alias the shared object's layers, so release the
|
||||
// ones this object still owns (it may have sliced itself before it became shareable again).
|
||||
// Both are no-ops once m_shared_object is set, so this cannot free layers owned by another object.
|
||||
clear_support_layers();
|
||||
clear_layers();
|
||||
m_shared_object = object;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": this=%1%, found shared object from %2%")%this%m_shared_object;
|
||||
}
|
||||
@@ -4329,9 +4334,9 @@ bool Print::is_dynamic_group_reorder() const
|
||||
return true;
|
||||
}
|
||||
|
||||
int Print::get_filament_config_indx(int filament_id, int layer_id, bool use_cache)
|
||||
int Print::get_filament_config_indx(int filament_id, int layer_id)
|
||||
{
|
||||
return get_config_index(filament_id, layer_id, m_config.filament_extruder_variant.values, m_filament_self_index, use_cache ? &m_filament_index_map : nullptr);
|
||||
return get_config_index(filament_id, layer_id, m_config.filament_extruder_variant.values, m_filament_self_index, m_filament_index_map);
|
||||
}
|
||||
|
||||
void Print::update_filament_self_index_cache()
|
||||
@@ -4374,7 +4379,7 @@ int Print::get_nozzle_config_index(int filament_id, int layer_id)
|
||||
return get_config_index(filament_id, layer_id, m_default_region_config.print_extruder_variant.values, m_default_region_config.print_extruder_id.values, m_nozzle_index_map);
|
||||
}
|
||||
|
||||
int Print::get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, FilamentIndexMap *index_map)
|
||||
int Print::get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, FilamentIndexMap &index_map)
|
||||
{
|
||||
auto group_result = get_layered_nozzle_group_result();
|
||||
// Orca: defensive — when no grouping producer has published a result yet, fall back to the
|
||||
@@ -4385,8 +4390,7 @@ int Print::get_config_index(int filament_id, int layer_id, const std::vector<std
|
||||
if (!nozzle_info.has_value()) {
|
||||
// Orca: this fallback runs per-filament/per-layer in the g-code hot path — log once per filament
|
||||
// (reset each slice) instead of flooding thousands of identical lines that bury the real error.
|
||||
// Without the cache, the log set is left alone too; the cached caller reports the same filament.
|
||||
if (index_map && m_missing_nozzle_group_logged.insert(filament_id).second)
|
||||
if (m_missing_nozzle_group_logged.insert(filament_id).second)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__
|
||||
<< boost::format(", Line %1%: could not found group_nozzle_info corresponding to filament_id %2%, layer_id %3% (further occurrences for this filament suppressed)") % __LINE__ % filament_id %
|
||||
layer_id;
|
||||
@@ -4395,17 +4399,15 @@ int Print::get_config_index(int filament_id, int layer_id, const std::vector<std
|
||||
|
||||
ExtruderType extruder_type = ExtruderType(m_config.extruder_type.get_at(nozzle_info->extruder_id));
|
||||
NozzleVolumeType nozzle_volume_type = nozzle_info->volume_type;
|
||||
if (!index_map)
|
||||
return get_config_index_base(nozzle_volume_type, extruder_type, filament_id + 1, variant_list, self_index_list);
|
||||
|
||||
FilamentIndexKey key{filament_id, extruder_type, nozzle_volume_type};
|
||||
auto iter = index_map->find(key);
|
||||
if (iter == index_map->end()) {
|
||||
auto iter = index_map.find(key);
|
||||
if (iter == index_map.end()) {
|
||||
int index = get_config_index_base(nozzle_volume_type, extruder_type, filament_id + 1, variant_list, self_index_list);
|
||||
(*index_map)[key] = index;
|
||||
index_map[key] = index;
|
||||
return index;
|
||||
} else {
|
||||
return iter->second;
|
||||
return index_map[key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -987,6 +987,9 @@ void PrintObject::generate_support_material()
|
||||
this->_generate_support_material();
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
// Orca: the tree support collision/avoidance caches and support nodes are only used while this step runs
|
||||
// (detect_overhangs() rebuilds them from scratch), so don't keep them resident until the next slice.
|
||||
this->clear_tree_support_preview_cache();
|
||||
this->set_done(posSupportMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1346,7 +1346,7 @@ void PrintObject::slice_volumes()
|
||||
if (min_growth < 0.f || elfoot > 0.f) {
|
||||
// Apply the negative XY compensation. (the ones that is <0)
|
||||
ExPolygons trimming;
|
||||
static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
|
||||
const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
|
||||
if (elfoot > 0.f) {
|
||||
ExPolygons expolygons_to_compensate = offset_ex(layer->merged(eps), -eps);
|
||||
lslices_elfoot_uncompensated[layer_id] = expolygons_to_compensate;
|
||||
|
||||
@@ -1820,37 +1820,15 @@ coordf_t TreeSupport::get_radius(const SupportNode* node)
|
||||
return node->radius;
|
||||
}
|
||||
|
||||
ExPolygons TreeSupport::get_avoidance(coordf_t radius, size_t obj_layer_nr)
|
||||
// Orca: these are hit up to several times per node per layer in drop_nodes(), so hand out a
|
||||
// reference into the TreeSupportData cache instead of copying the ExPolygons out of it.
|
||||
const ExPolygons& TreeSupport::get_avoidance(coordf_t radius, size_t obj_layer_nr)
|
||||
{
|
||||
#if USE_SUPPORT_3D
|
||||
if (m_model_volumes) {
|
||||
bool on_build_plate = m_object_config->support_on_build_plate_only.value;
|
||||
const Polygons& avoid_polys = m_model_volumes->getAvoidance(radius, obj_layer_nr, TreeSupport3D::TreeModelVolumes::AvoidanceType::FastSafe, on_build_plate, true);
|
||||
ExPolygons expolys;
|
||||
for (auto& poly : avoid_polys)
|
||||
expolys.emplace_back(std::move(poly));
|
||||
return expolys;
|
||||
}
|
||||
return ExPolygons();
|
||||
#else
|
||||
return m_ts_data->get_avoidance(radius, obj_layer_nr);
|
||||
#endif
|
||||
}
|
||||
ExPolygons TreeSupport::get_collision(coordf_t radius, size_t layer_nr)
|
||||
const ExPolygons& TreeSupport::get_collision(coordf_t radius, size_t layer_nr)
|
||||
{
|
||||
#if USE_SUPPORT_3D
|
||||
if (m_model_volumes) {
|
||||
bool on_build_plate = m_object_config->support_on_build_plate_only.value;
|
||||
const Polygons& collision_polys = m_model_volumes->getCollision(radius, layer_nr, true);
|
||||
ExPolygons expolys;
|
||||
for (auto& poly : collision_polys)
|
||||
expolys.emplace_back(std::move(poly));
|
||||
return expolys;
|
||||
}
|
||||
#else
|
||||
return m_ts_data->get_collision(radius, layer_nr);
|
||||
#endif
|
||||
return ExPolygons();
|
||||
}
|
||||
Polygons TreeSupport::get_collision_polys(coordf_t radius, size_t layer_nr)
|
||||
{
|
||||
@@ -2639,7 +2617,11 @@ void TreeSupport::draw_circles()
|
||||
#endif // SUPPORT_TREE_DEBUG_TO_SVG
|
||||
|
||||
SupportLayerPtrs& ts_layers = m_object->support_layers();
|
||||
auto iter = std::remove_if(ts_layers.begin(), ts_layers.end(), [](SupportLayer* ts_layer) { return ts_layer->height < EPSILON; });
|
||||
// Orca: the vector owns its layers, so the dropped ones have to be deleted, not just unlinked.
|
||||
// std::stable_partition (unlike std::remove_if) leaves exactly the dropped layers in the tail.
|
||||
auto iter = std::stable_partition(ts_layers.begin(), ts_layers.end(), [](SupportLayer* ts_layer) { return ts_layer->height >= EPSILON; });
|
||||
for (auto it = iter; it != ts_layers.end(); ++it)
|
||||
delete *it;
|
||||
ts_layers.erase(iter, ts_layers.end());
|
||||
for (int layer_nr = 0; layer_nr < ts_layers.size(); layer_nr++) {
|
||||
ts_layers[layer_nr]->upper_layer = layer_nr != ts_layers.size() - 1 ? ts_layers[layer_nr + 1] : nullptr;
|
||||
@@ -2882,7 +2864,7 @@ void TreeSupport::drop_nodes()
|
||||
//Insert a completely new node and let both original nodes fade.
|
||||
Point next_position = (node.position + neighbours[0]) / 2; //Average position of the two nodes.
|
||||
coordf_t next_radius = calc_radius(node.dist_mm_to_top+height_next);
|
||||
auto avoid_layer = get_avoidance(next_radius, obj_layer_nr_next);
|
||||
const ExPolygons& avoid_layer = get_avoidance(next_radius, obj_layer_nr_next);
|
||||
if (group_index == 0)
|
||||
{
|
||||
//Avoid collisions.
|
||||
@@ -3069,7 +3051,7 @@ void TreeSupport::drop_nodes()
|
||||
}
|
||||
#endif
|
||||
coordf_t next_radius = calc_radius(node.dist_mm_to_top + height_next);
|
||||
auto avoidance_next = get_avoidance(next_radius, obj_layer_nr_next);
|
||||
const ExPolygons& avoidance_next = get_avoidance(next_radius, obj_layer_nr_next);
|
||||
|
||||
Point to_outside = projection_onto(avoidance_next, node.position);
|
||||
Point direction_to_outer = to_outside - node.position;
|
||||
@@ -3123,7 +3105,7 @@ void TreeSupport::drop_nodes()
|
||||
if (is_outside) { next_layer_vertex = candidate_vertex; }
|
||||
}
|
||||
}
|
||||
auto next_collision = get_collision(0, obj_layer_nr_next);
|
||||
const ExPolygons& next_collision = get_collision(0, obj_layer_nr_next);
|
||||
const bool to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[obj_layer_nr_next], next_layer_vertex);
|
||||
// don't increase radius if next node will collide partially with the object (STUDIO-7883)
|
||||
to_outside = projection_onto(next_collision, next_layer_vertex);
|
||||
|
||||
@@ -511,9 +511,9 @@ private:
|
||||
coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor, bool use_min_distance=true);
|
||||
coordf_t calc_radius(coordf_t mm_to_top);
|
||||
coordf_t get_radius(const SupportNode* node);
|
||||
ExPolygons get_avoidance(coordf_t radius, size_t obj_layer_nr);
|
||||
const ExPolygons& get_avoidance(coordf_t radius, size_t obj_layer_nr);
|
||||
// layer's expolygon expanded by radius+m_xy_distance
|
||||
ExPolygons get_collision(coordf_t radius, size_t layer_nr);
|
||||
const ExPolygons& get_collision(coordf_t radius, size_t layer_nr);
|
||||
// get Polygons instead of ExPolygons
|
||||
Polygons get_collision_polys(coordf_t radius, size_t layer_nr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user