mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +00:00
Merge branch 'main' into dev/bbs-support
This commit is contained in:
+7
-1
@@ -3575,10 +3575,16 @@ int CLI::run(int argc, char **argv)
|
||||
// this affects volumes:
|
||||
o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), Y);
|
||||
} else if (opt_key == "scale") {
|
||||
float ratio = m_config.opt_float(opt_key);
|
||||
if (ratio <= 0.f) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Invalid params:invalid scale ratio %1%")%ratio;
|
||||
record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info);
|
||||
flush_and_exit(CLI_INVALID_PARAMS);
|
||||
}
|
||||
for (auto &model : m_models)
|
||||
for (auto &o : model.objects)
|
||||
// this affects volumes:
|
||||
o->scale(m_config.get_abs_value(opt_key, 1));
|
||||
o->scale(ratio));
|
||||
} else if (opt_key == "scale_to_fit") {
|
||||
const Vec3d &opt = m_config.opt<ConfigOptionPoint3>(opt_key)->value;
|
||||
if (opt.x() <= 0 || opt.y() <= 0 || opt.z() <= 0) {
|
||||
|
||||
@@ -2290,7 +2290,11 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
||||
|
||||
if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times
|
||||
{
|
||||
op1 = AddOutPt(horzEdge, e->Curr);
|
||||
#ifdef CLIPPERLIB_USE_XYZ
|
||||
if (dir == dLeftToRight) SetZ(e->Curr, *horzEdge, *e);
|
||||
else SetZ(e->Curr, *e, *horzEdge);
|
||||
#endif
|
||||
op1 = AddOutPt(horzEdge, e->Curr);
|
||||
TEdge* eNextHorz = m_SortedEdges;
|
||||
while (eNextHorz)
|
||||
{
|
||||
@@ -2614,7 +2618,10 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||
{
|
||||
e->Curr.x() = TopX( *e, topY );
|
||||
e->Curr.y() = topY;
|
||||
}
|
||||
#ifdef CLIPPERLIB_USE_XYZ
|
||||
e->Curr.z() = topY == e->Top.y() ? e->Top.z() : (topY == e->Bot.y() ? e->Bot.z() : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//When StrictlySimple and 'e' is being touched by another edge, then
|
||||
//make sure both edges have a vertex here ...
|
||||
|
||||
@@ -82,6 +82,40 @@ struct CSGPart {
|
||||
{}
|
||||
};
|
||||
|
||||
//Prusa
|
||||
// Check if there are only positive parts (Union) within the collection.
|
||||
template<class Cont> bool is_all_positive(const Cont &csgmesh)
|
||||
{
|
||||
bool is_all_pos =
|
||||
std::all_of(csgmesh.begin(),
|
||||
csgmesh.end(),
|
||||
[](auto &part) {
|
||||
return csg::get_operation(part) == csg::CSGType::Union;
|
||||
});
|
||||
|
||||
return is_all_pos;
|
||||
}
|
||||
|
||||
//Prusa
|
||||
// Merge all the positive parts of the collection into a single triangle mesh without performing
|
||||
// any booleans.
|
||||
template<class Cont>
|
||||
indexed_triangle_set csgmesh_merge_positive_parts(const Cont &csgmesh)
|
||||
{
|
||||
indexed_triangle_set m;
|
||||
for (auto &csgpart : csgmesh) {
|
||||
auto op = csg::get_operation(csgpart);
|
||||
const indexed_triangle_set * pmesh = csg::get_mesh(csgpart);
|
||||
if (pmesh && op == csg::CSGType::Union) {
|
||||
indexed_triangle_set mcpy = *pmesh;
|
||||
its_transform(mcpy, csg::get_transform(csgpart), true);
|
||||
its_merge(m, mcpy);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::csg
|
||||
|
||||
#endif // CSGMESH_HPP
|
||||
|
||||
@@ -257,7 +257,7 @@ void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm,
|
||||
|
||||
|
||||
template<class It, class Visitor>
|
||||
std::tuple<BooleanFailReason,std::string> check_csgmesh_booleans(const Range<It> &csgrange, Visitor &&vfn)
|
||||
std::tuple<BooleanFailReason,std::string, It> check_csgmesh_booleans(const Range<It> &csgrange, Visitor &&vfn)
|
||||
{
|
||||
using namespace detail_cgal;
|
||||
BooleanFailReason fail_reason = BooleanFailReason::OK;
|
||||
@@ -304,23 +304,23 @@ std::tuple<BooleanFailReason,std::string> check_csgmesh_booleans(const Range<It>
|
||||
};
|
||||
execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part);
|
||||
|
||||
//It ret = csgrange.end();
|
||||
//for (size_t i = 0; i < csgrange.size(); ++i) {
|
||||
// if (!cgalmeshes[i]) {
|
||||
// auto it = csgrange.begin();
|
||||
// std::advance(it, i);
|
||||
// vfn(it);
|
||||
It ret = csgrange.end();
|
||||
for (size_t i = 0; i < csgrange.size(); ++i) {
|
||||
if (!cgalmeshes[i]) {
|
||||
auto it = csgrange.begin();
|
||||
std::advance(it, i);
|
||||
vfn(it);
|
||||
|
||||
// if (ret == csgrange.end())
|
||||
// ret = it;
|
||||
// }
|
||||
//}
|
||||
if (ret == csgrange.end())
|
||||
ret = it;
|
||||
}
|
||||
}
|
||||
|
||||
return { fail_reason,fail_part_name };
|
||||
return { fail_reason,fail_part_name, ret};
|
||||
}
|
||||
|
||||
template<class It>
|
||||
std::tuple<BooleanFailReason, std::string> check_csgmesh_booleans(const Range<It> &csgrange, bool use_mcut=false)
|
||||
std::tuple<BooleanFailReason, std::string, It> check_csgmesh_booleans(const Range<It> &csgrange, bool use_mcut=false)
|
||||
{
|
||||
if(!use_mcut)
|
||||
return check_csgmesh_booleans(csgrange, [](auto &) {});
|
||||
@@ -354,7 +354,7 @@ std::tuple<BooleanFailReason, std::string> check_csgmesh_booleans(const Range<It
|
||||
McutMeshes[i] = std::move(m);
|
||||
};
|
||||
execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part);
|
||||
return { fail_reason,fail_part_name };
|
||||
return { fail_reason,fail_part_name, csgrange.end() };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-14
@@ -729,6 +729,8 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
gcode += gcodegen.writer().unlift(); // Make sure there is no z-hop (in most cases, there isn't).
|
||||
|
||||
double current_z = gcodegen.writer().get_position().z();
|
||||
|
||||
|
||||
if (z == -1.) // in case no specific z was provided, print at current_z pos
|
||||
z = current_z;
|
||||
|
||||
@@ -741,7 +743,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
|| !needs_toolchange // this is just finishing the tower with no toolchange
|
||||
|| is_ramming);
|
||||
|
||||
if (should_travel_to_tower) {
|
||||
if (should_travel_to_tower || gcodegen.m_need_change_layer_lift_z) {
|
||||
// FIXME: It would be better if the wipe tower set the force_travel flag for all toolchanges,
|
||||
// then we could simplify the condition and make it more readable.
|
||||
gcode += gcodegen.retract();
|
||||
@@ -767,10 +769,10 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z); // TODO: toolchange_z vs print_z
|
||||
if (gcodegen.config().enable_prime_tower) {
|
||||
deretraction_str += gcodegen.writer().travel_to_z(z, "restore layer Z");
|
||||
Vec3d position{gcodegen.writer().get_position()};
|
||||
position.z() = z;
|
||||
gcodegen.writer().set_position(position);
|
||||
deretraction_str += gcodegen.unretract();
|
||||
Vec3d position{gcodegen.writer().get_position()};
|
||||
position.z() = z;
|
||||
gcodegen.writer().set_position(position);
|
||||
deretraction_str += gcodegen.unretract();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4516,12 +4518,11 @@ std::string GCode::change_layer(coordf_t print_z)
|
||||
comment << "move to next layer (" << m_layer_index << ")";
|
||||
gcode += m_writer.travel_to_z(z, comment.str());
|
||||
}
|
||||
else {
|
||||
//BBS: set m_need_change_layer_lift_z to be true so that z lift can be done in travel_to() function
|
||||
m_need_change_layer_lift_z = true;
|
||||
}
|
||||
|
||||
m_need_change_layer_lift_z = true;
|
||||
|
||||
m_nominal_z = z;
|
||||
m_writer.get_position().z() = z;
|
||||
|
||||
// forget last wiping path as wiping after raising Z is pointless
|
||||
// BBS. Dont forget wiping path to reduce stringing.
|
||||
@@ -6005,14 +6006,15 @@ std::string GCode::travel_to(const Point& point, ExtrusionRole role, std::string
|
||||
if (m_spiral_vase) {
|
||||
// No lazy z lift for spiral vase mode
|
||||
for (size_t i = 1; i < travel.size(); ++i) {
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment + " travel_to_xy");
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment);
|
||||
}
|
||||
} else {
|
||||
if (travel.size() == 2) {
|
||||
// No extra movements emitted by avoid_crossing_perimeters, simply move to the end point with z change
|
||||
const auto& dest2d = this->point_to_gcode(travel.points.back());
|
||||
Vec3d dest3d(dest2d(0), dest2d(1), z == DBL_MAX ? m_nominal_z : z);
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment + " travel_to_xyz");
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment, m_need_change_layer_lift_z);
|
||||
m_need_change_layer_lift_z = false;
|
||||
} else {
|
||||
// Extra movements emitted by avoid_crossing_perimeters, lift the z to normal height at the beginning, then apply the z
|
||||
// ratio at the last point
|
||||
@@ -6021,21 +6023,23 @@ std::string GCode::travel_to(const Point& point, ExtrusionRole role, std::string
|
||||
// Lift to normal z at beginning
|
||||
Vec2d dest2d = this->point_to_gcode(travel.points[i]);
|
||||
Vec3d dest3d(dest2d(0), dest2d(1), m_nominal_z);
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment + " travel_to_xyz");
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment, m_need_change_layer_lift_z);
|
||||
m_need_change_layer_lift_z = false;
|
||||
} else if (z != DBL_MAX && i == travel.size() - 1) {
|
||||
// Apply z_ratio for the very last point
|
||||
Vec2d dest2d = this->point_to_gcode(travel.points[i]);
|
||||
Vec3d dest3d(dest2d(0), dest2d(1), z);
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment + " travel_to_xyz");
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment);
|
||||
} else {
|
||||
// For all points in between, no z change
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment + " travel_to_xy");
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this->set_last_pos(travel.points.back());
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
||||
@@ -893,7 +893,8 @@ void WipeTower2::toolchange_Unload(
|
||||
float remaining = xr - xl ; // keeps track of distance to the next turnaround
|
||||
float e_done = 0; // measures E move done from each segment
|
||||
|
||||
const bool do_ramming = m_semm || m_filpar[m_current_tool].multitool_ramming;
|
||||
// Orca: Do ramming when SEMM and ramming is enabled or when multi tool head when ramming is enabled on the multi tool.
|
||||
const bool do_ramming = (m_semm && m_enable_filament_ramming) || m_filpar[m_current_tool].multitool_ramming;
|
||||
const bool cold_ramming = m_is_mk4mmu3;
|
||||
|
||||
if (do_ramming) {
|
||||
@@ -1126,7 +1127,7 @@ void WipeTower2::toolchange_Load(
|
||||
WipeTowerWriter2 &writer,
|
||||
const WipeTower::box_coordinates &cleaning_box)
|
||||
{
|
||||
if (m_semm && (m_parking_pos_retraction != 0 || m_extra_loading_move != 0)) {
|
||||
if (m_semm && m_enable_filament_ramming && (m_parking_pos_retraction != 0 || m_extra_loading_move != 0)) {
|
||||
float xl = cleaning_box.ld.x() + m_perimeter_width * 0.75f;
|
||||
float xr = cleaning_box.rd.x() - m_perimeter_width * 0.75f;
|
||||
float oldx = writer.x(); // the nozzle is in place to do the first wiping moves, we will remember the position
|
||||
@@ -1544,7 +1545,8 @@ void WipeTower2::plan_toolchange(float z_par, float layer_height_par, unsigned i
|
||||
float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_filpar[old_tool].ramming_speed.begin(), m_filpar[old_tool].ramming_speed.end(), 0.f),
|
||||
m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator,
|
||||
layer_height_par);
|
||||
float ramming_depth = (int(length_to_extrude / width) + 1) * (m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator) * m_extra_spacing_ramming;
|
||||
// Orca: Set ramming depth to 0 if ramming is disabled.
|
||||
float ramming_depth = m_enable_filament_ramming ? ((int(length_to_extrude / width) + 1) * (m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator) * m_extra_spacing_ramming) : 0;
|
||||
float first_wipe_line = - (width*((length_to_extrude / width)-int(length_to_extrude / width)) - width);
|
||||
|
||||
float first_wipe_volume = length_to_volume(first_wipe_line, m_perimeter_width * m_extra_flow, layer_height_par);
|
||||
|
||||
@@ -440,7 +440,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
|
||||
return w.string();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment)
|
||||
std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment, bool force_z)
|
||||
{
|
||||
// FIXME: This function was not being used when travel_speed_z was separated (bd6badf).
|
||||
// Calculation of feedrate was not updated accordingly. If you want to use
|
||||
@@ -526,7 +526,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
|
||||
this->set_current_position_clear(true);
|
||||
return slop_move + xy_z_move;
|
||||
}
|
||||
else if (!this->will_move_z(point(2))) {
|
||||
else if (!force_z && !this->will_move_z(point(2))) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
m_lifted -= (point(2) - nominal_z);
|
||||
// In case that z_hop == layer_height we could end up with almost zero in_m_lifted
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
// SoftFever NOTE: the returned speed is mm/minute
|
||||
double get_current_speed() const { return m_current_speed;}
|
||||
std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string());
|
||||
std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string());
|
||||
std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string(), bool force_z = false);
|
||||
std::string travel_to_z(double z, const std::string &comment = std::string());
|
||||
bool will_move_z(double z) const;
|
||||
std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string(), bool force_no_extrusion = false);
|
||||
@@ -81,7 +81,8 @@ public:
|
||||
std::string unretract();
|
||||
std::string lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false);
|
||||
std::string unlift();
|
||||
Vec3d get_position() const { return m_pos; }
|
||||
const Vec3d& get_position() const { return m_pos; }
|
||||
Vec3d& get_position() { return m_pos; }
|
||||
void set_position(const Vec3d& in) { m_pos = in; }
|
||||
double get_zhop() const { return m_lifted; }
|
||||
|
||||
|
||||
@@ -735,6 +735,12 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
if(paths.empty()) continue;
|
||||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||
} else {
|
||||
if (overhangs_reverse && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) {
|
||||
// Always reverse if detect overhang wall is not enabled
|
||||
steep_overhang_contour = true;
|
||||
steep_overhang_hole = true;
|
||||
}
|
||||
|
||||
ExtrusionPath path(role);
|
||||
//BBS.
|
||||
path.polyline = polygon.split_at_first_point();
|
||||
@@ -1219,6 +1225,12 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (overhangs_reverse && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) {
|
||||
// Always reverse if detect overhang wall is not enabled
|
||||
steep_overhang_contour = true;
|
||||
steep_overhang_hole = true;
|
||||
}
|
||||
|
||||
extrusion_paths_append(paths, *extrusion, role, is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow);
|
||||
}
|
||||
|
||||
|
||||
@@ -1056,7 +1056,8 @@ void PrintConfigDef::init_fff_params()
|
||||
def->category = L("Quality");
|
||||
// xgettext:no-c-format, no-boost-format
|
||||
def->tooltip = L("Number of mm the overhang need to be for the reversal to be considered useful. Can be a % of the perimeter width."
|
||||
"\nValue 0 enables reversal on every even layers regardless.");
|
||||
"\nValue 0 enables reversal on every even layers regardless."
|
||||
"\nWhen Detect overhang wall is not enabled, this option is ignored and reversal happens on every even layers regardless.");
|
||||
def->sidetext = L("mm or %");
|
||||
def->ratio_over = "line_width";
|
||||
def->min = 0;
|
||||
@@ -2124,6 +2125,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_values.push_back("PET-CF");
|
||||
def->enum_values.push_back("PETG");
|
||||
def->enum_values.push_back("PETG-CF");
|
||||
def->enum_values.push_back("PETG-CF10");
|
||||
def->enum_values.push_back("PHA");
|
||||
def->enum_values.push_back("PLA");
|
||||
def->enum_values.push_back("PLA-AERO");
|
||||
|
||||
@@ -736,8 +736,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||
bool has_detect_overhang_wall = config->opt_bool("detect_overhang_wall");
|
||||
bool has_overhang_reverse = config->opt_bool("overhang_reverse");
|
||||
bool force_wall_direction = config->opt_enum<WallDirection>("wall_direction") != WallDirection::Auto;
|
||||
bool allow_overhang_reverse = has_detect_overhang_wall && !has_spiral_vase && !force_wall_direction;
|
||||
bool allow_overhang_reverse = !has_spiral_vase && !force_wall_direction;
|
||||
toggle_field("overhang_reverse", allow_overhang_reverse);
|
||||
toggle_field("overhang_reverse_threshold", has_detect_overhang_wall);
|
||||
toggle_line("overhang_reverse_threshold", allow_overhang_reverse && has_overhang_reverse);
|
||||
toggle_line("overhang_reverse_internal_only", allow_overhang_reverse && has_overhang_reverse);
|
||||
bool has_overhang_reverse_internal_only = config->opt_bool("overhang_reverse_internal_only");
|
||||
|
||||
@@ -47,20 +47,20 @@ static const std::vector<std::string> filament_vendors =
|
||||
"Duramic", "ELEGOO", "Eryone", "Essentium", "eSUN",
|
||||
"Extrudr", "Fiberforce", "Fiberlogy", "FilaCube", "Filamentive",
|
||||
"Fillamentum", "FLASHFORGE", "Formfutura", "Francofil", "FilamentOne",
|
||||
"Fil X", "GEEETECH", "Giantarm", "Gizmo Dorks", "GreenGate3D",
|
||||
"Fil X", "GEEETECH", "Giantarm", "Gizmo Dorks", "GreenGate3D",
|
||||
"HATCHBOX", "Hello3D", "IC3D", "IEMAI", "IIID Max",
|
||||
"INLAND", "iProspect", "iSANMATE", "Justmaker", "Keene Village Plastics",
|
||||
"Kexcelled", "MakerBot", "MatterHackers", "MIKA3D", "NinjaTek",
|
||||
"Nobufil", "Novamaker", "OVERTURE", "OVVNYXE", "Polymaker",
|
||||
"Priline", "Printed Solid", "Protopasta", "Prusament", "Push Plastic",
|
||||
"R3D", "Re-pet3D", "Recreus", "Regen", "Sain SMART",
|
||||
"SliceWorx", "Snapmaker", "SnoLabs", "Spectrum", "SUNLU",
|
||||
"TTYT3D", "Tianse", "UltiMaker", "Valment", "Verbatim",
|
||||
"VO3D", "Voxelab", "VOXELPLA", "YOOPAI", "Yousu",
|
||||
"Ziro", "Zyltech"};
|
||||
"R3D", "Re-pet3D", "Recreus", "Regen", "RatRig",
|
||||
"Sain SMART", "SliceWorx", "Snapmaker", "SnoLabs", "Spectrum",
|
||||
"SUNLU", "TTYT3D", "Tianse", "UltiMaker", "Valment",
|
||||
"Verbatim", "VO3D", "Voxelab", "VOXELPLA", "YOOPAI",
|
||||
"Yousu", "Ziro", "Zyltech"};
|
||||
|
||||
static const std::vector<std::string> filament_types = {"PLA", "rPLA", "PLA+", "PLA Tough", "PETG", "ABS", "ASA", "FLEX", "HIPS", "PA", "PACF",
|
||||
"NYLON", "PVA", "PVB", "PC", "PCABS", "PCTG", "PCCF", "PHA", "PP", "PEI", "PET", "PETG",
|
||||
"NYLON", "PVA", "PVB", "PC", "PCABS", "PCTG", "PCCF", "PHA", "PP", "PEI", "PET",
|
||||
"PETGCF", "PTBA", "PTBA90A", "PEEK", "TPU93A", "TPU75D", "TPU", "TPU92A", "TPU98A", "Misc",
|
||||
"TPE", "GLAZE", "Nylon", "CPE", "METAL", "ABST", "Carbon Fiber", "SBS"};
|
||||
|
||||
|
||||
@@ -2541,59 +2541,9 @@ void PartPlate::generate_print_polygon(ExPolygon &print_polygon)
|
||||
}
|
||||
};
|
||||
|
||||
int points_count = 8;
|
||||
if (m_shape.size() == 4)
|
||||
{
|
||||
//rectangle case
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
const Vec2d& p = m_shape[i];
|
||||
Vec2d center;
|
||||
double start_angle, stop_angle, radius_x, radius_y, radius;
|
||||
switch (i) {
|
||||
case 0:
|
||||
radius = 5.f;
|
||||
center(0) = p(0) + radius;
|
||||
center(1) = p(1) + radius;
|
||||
start_angle = PI;
|
||||
stop_angle = 1.5 * PI;
|
||||
compute_points(center, radius, start_angle, stop_angle, points_count);
|
||||
break;
|
||||
case 1:
|
||||
print_polygon.contour.append({ scale_(p(0)), scale_(p(1)) });
|
||||
break;
|
||||
case 2:
|
||||
radius_x = (int)(p(0)) % 10;
|
||||
radius_y = (int)(p(1)) % 10;
|
||||
radius = (radius_x > radius_y)?radius_y: radius_x;
|
||||
if (radius < 5.0)
|
||||
radius = 5.f;
|
||||
center(0) = p(0) - radius;
|
||||
center(1) = p(1) - radius;
|
||||
start_angle = 0;
|
||||
stop_angle = 0.5 * PI;
|
||||
compute_points(center, radius, start_angle, stop_angle, points_count);
|
||||
break;
|
||||
case 3:
|
||||
radius_x = (int)(p(0)) % 10;
|
||||
radius_y = (int)(p(1)) % 10;
|
||||
radius = (radius_x > radius_y)?radius_y: radius_x;
|
||||
if (radius < 5.0)
|
||||
radius = 5.f;
|
||||
center(0) = p(0) + radius;
|
||||
center(1) = p(1) - radius;
|
||||
start_angle = 0.5 * PI;
|
||||
stop_angle = PI;
|
||||
compute_points(center, radius, start_angle, stop_angle, points_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const Vec2d& p : m_shape) {
|
||||
print_polygon.contour.append({ scale_(p(0)), scale_(p(1)) });
|
||||
for (const Vec2d& p : m_shape) {
|
||||
print_polygon.contour.append({scale_(p(0)), scale_(p(1))});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon)
|
||||
|
||||
@@ -11686,14 +11686,37 @@ void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
|
||||
}
|
||||
|
||||
// Following lambda generates a combined mesh for export with normals pointing outwards.
|
||||
auto mesh_to_export_fff_no_boolean = [](const ModelObject &mo, int instance_id) {
|
||||
auto mesh_to_export_fff_no_boolean = [this](const ModelObject &mo, int instance_id) {
|
||||
TriangleMesh mesh;
|
||||
for (const ModelVolume *v : mo.volumes)
|
||||
if (v->is_model_part()) {
|
||||
TriangleMesh vol_mesh(v->mesh());
|
||||
vol_mesh.transform(v->get_matrix(), true);
|
||||
mesh.merge(vol_mesh);
|
||||
}
|
||||
|
||||
//Prusa export negative parts
|
||||
std::vector<csg::CSGPart> csgmesh;
|
||||
csgmesh.reserve(2 * mo.volumes.size());
|
||||
csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh),
|
||||
csg::mpartsPositive | csg::mpartsNegative | csg::mpartsDoSplits);
|
||||
|
||||
auto csgrange = range(csgmesh);
|
||||
if (csg::is_all_positive(csgrange)) {
|
||||
mesh = TriangleMesh{csg::csgmesh_merge_positive_parts(csgrange)};
|
||||
} else if (std::get<2>(csg::check_csgmesh_booleans(csgrange)) == csgrange.end()) {
|
||||
try {
|
||||
auto cgalm = csg::perform_csgmesh_booleans(csgrange);
|
||||
mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*cgalm);
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
if (mesh.empty()) {
|
||||
get_notification_manager()->push_plater_error_notification(
|
||||
_u8L("Unable to perform boolean operation on model meshes. "
|
||||
"Only positive parts will be exported."));
|
||||
|
||||
for (const ModelVolume* v : mo.volumes)
|
||||
if (v->is_model_part()) {
|
||||
TriangleMesh vol_mesh(v->mesh());
|
||||
vol_mesh.transform(v->get_matrix(), true);
|
||||
mesh.merge(vol_mesh);
|
||||
}
|
||||
}
|
||||
if (instance_id == -1) {
|
||||
TriangleMesh vols_mesh(mesh);
|
||||
mesh = TriangleMesh();
|
||||
|
||||
@@ -31,14 +31,13 @@ void NotificationManager::SlicingProgressNotification::init()
|
||||
m_endlines.push_back(0);
|
||||
}
|
||||
if (m_lines_count >= 2) {
|
||||
m_lines_count = 3;
|
||||
m_lines_count = std::min((size_t)3, m_lines_count);
|
||||
m_multiline = true;
|
||||
while (m_endlines.size() < 3)
|
||||
while (m_endlines.size() < m_lines_count)
|
||||
m_endlines.push_back(m_endlines.back());
|
||||
}
|
||||
else {
|
||||
m_lines_count = 2;
|
||||
m_endlines.push_back(m_endlines.back());
|
||||
m_lines_count = 1;
|
||||
m_multiline = false;
|
||||
}
|
||||
if (m_state == EState::Shown)
|
||||
@@ -222,7 +221,7 @@ void NotificationManager::SlicingProgressNotification::render(GLCanvas3D& canvas
|
||||
const ImVec2 dailytips_child_window_padding = m_dailytips_panel->is_expanded() ? ImVec2(15.f, 10.f) * scale : ImVec2(15.f, 0.f) * scale;
|
||||
const ImVec2 bottom_padding = ImVec2(0.f, 0.f) * scale;
|
||||
const float progress_panel_width = (m_window_width - 2 * progress_child_window_padding.x);
|
||||
const float progress_panel_height = (58.0f * scale);
|
||||
const float progress_panel_height = (58.0f * scale) + (m_lines_count - 1) * m_line_height;
|
||||
const float dailytips_panel_width = (m_window_width - 2 * dailytips_child_window_padding.x);
|
||||
const float gcodeviewer_height = wxGetApp().plater()->get_preview_canvas3D()->get_gcode_viewer().get_legend_height();
|
||||
//const float dailytips_panel_height = std::min(380.0f * scale, std::max(90.0f, (cnv_size.get_height() - gcodeviewer_height - progress_panel_height - dailytips_child_window_padding.y - initial_y - m_line_height * 4)));
|
||||
@@ -272,11 +271,12 @@ void NotificationManager::SlicingProgressNotification::render(GLCanvas3D& canvas
|
||||
if (ImGui::BeginChild(child_name.c_str(), ImVec2(progress_panel_width, progress_panel_height), false, child_window_flags)) {
|
||||
ImVec2 child_window_pos = ImGui::GetWindowPos();
|
||||
ImVec2 button_size = ImVec2(38.f, 38.f) * scale;
|
||||
ImVec2 button_pos = child_window_pos + ImVec2(progress_panel_width - button_size.x, (progress_panel_height - button_size.y) / 2.0f);
|
||||
float margin_x = 8.0f * scale;
|
||||
ImVec2 progress_bar_pos = child_window_pos + ImVec2(0, progress_panel_height / 2.0f);
|
||||
ImVec2 progress_bar_size = ImVec2(progress_panel_width - button_size.x - margin_x, 4.0f * scale);
|
||||
ImVec2 text_pos = ImVec2(progress_bar_pos.x, progress_bar_pos.y - m_line_height * 1.2f);
|
||||
float text_bottom = progress_bar_size.y + m_line_height * 1.2f + 7.f * scale;
|
||||
ImVec2 progress_bar_pos = child_window_pos + ImVec2(0, progress_panel_height - text_bottom);
|
||||
ImVec2 button_pos = child_window_pos + ImVec2(progress_panel_width - button_size.x, progress_panel_height - text_bottom - button_size.y / 2.0f);
|
||||
ImVec2 text_pos = ImVec2(progress_bar_pos.x, progress_bar_pos.y - m_line_height * (1.2f + m_lines_count - 1));
|
||||
|
||||
render_text(text_pos);
|
||||
render_close_button(button_pos, button_size);
|
||||
@@ -353,9 +353,13 @@ void Slic3r::GUI::NotificationManager::SlicingProgressNotification::render_text(
|
||||
imgui.pop_bold_font();
|
||||
}
|
||||
if(m_sp_state == SlicingProgressState::SP_PROGRESS) {
|
||||
//one line text
|
||||
ImGui::SetCursorScreenPos(pos);
|
||||
imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
|
||||
// multi-line text
|
||||
int last_end = 0;
|
||||
for (auto i = 0; i < m_lines_count; i++) {
|
||||
ImGui::SetCursorScreenPos(pos + ImVec2(0, i * m_line_height));
|
||||
imgui.text(m_text1.substr(last_end, m_endlines[i] - last_end).c_str());
|
||||
last_end = m_endlines[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user