From 237958819644c62e5e4e09b48a49d15f2e77cf3d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 28 Feb 2022 10:21:03 +0100 Subject: [PATCH 01/13] Tech ENABLE_GLBEGIN_GLEND_REMOVAL - Fix in GLGizmoRotate::render_angle_arc(): Tech ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL - Fix in GLModel::render() --- src/slic3r/GUI/GLModel.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 28 ++++++++++++++----------- src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 1 + 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 8620c7eaf..f0eac9a24 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -998,7 +998,7 @@ void GLModel::render(const std::pair& range) shader->set_uniform("uniform_color", data.color); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); - glsafe(::glDrawElements(mode, range.second - range.first + 1, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format)))); + glsafe(::glDrawElements(mode, range.second - range.first, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format)))); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); if (tex_coord) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index c97a4a788..a09ac8057 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -461,22 +461,26 @@ void GLGizmoRotate::render_angle() const const float ex_radius = m_radius * (1.0f + GrabberOffset); #if ENABLE_GLBEGIN_GLEND_REMOVAL - if (!m_angle_arc.is_initialized() || radius_changed) { + const bool angle_changed = std::abs(m_old_angle - m_angle) > EPSILON; + m_old_angle = m_angle; + + if (!m_angle_arc.is_initialized() || radius_changed || angle_changed) { m_angle_arc.reset(); + if (m_angle > 0.0f) { + GLModel::Geometry init_data; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.reserve_vertices(1 + AngleResolution); + init_data.reserve_indices(1 + AngleResolution); - GLModel::Geometry init_data; - init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(1 + AngleResolution); - init_data.reserve_indices(1 + AngleResolution); + // vertices + indices + for (unsigned short i = 0; i <= AngleResolution; ++i) { + const float angle = float(i) * step_angle; + init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f)); + init_data.add_ushort_index(i); + } - // vertices + indices - for (unsigned short i = 0; i <= AngleResolution; ++i) { - const float angle = float(i) * step_angle; - init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f)); - init_data.add_ushort_index(i); + m_angle_arc.init_from(std::move(init_data)); } - - m_angle_arc.init_from(std::move(init_data)); } m_angle_arc.set_color(color); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 02dd84e68..d0474df0e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -50,6 +50,7 @@ private: GrabberConnection m_grabber_connection; float m_old_radius{ 0.0f }; float m_old_hover_radius{ 0.0f }; + float m_old_angle{ 0.0f }; #endif // ENABLE_GLBEGIN_GLEND_REMOVAL ColorRGBA m_drag_color; From 5377e4c43b0bfc5c8b8078ff113a2362980c446a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 28 Feb 2022 15:53:12 +0100 Subject: [PATCH 02/13] Removed empty DoubleSliderUtils.hpp --- src/slic3r/CMakeLists.txt | 1 - src/slic3r/GUI/DoubleSlider_Utils.hpp | 8 -------- 2 files changed, 9 deletions(-) delete mode 100644 src/slic3r/GUI/DoubleSlider_Utils.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 022bba2a8..aa6268d88 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -193,7 +193,6 @@ set(SLIC3R_GUI_SOURCES GUI/Mouse3DController.hpp GUI/DoubleSlider.cpp GUI/DoubleSlider.hpp - GUI/DoubleSlider_Utils.hpp GUI/Notebook.cpp GUI/Notebook.hpp GUI/ObjectDataViewModel.cpp diff --git a/src/slic3r/GUI/DoubleSlider_Utils.hpp b/src/slic3r/GUI/DoubleSlider_Utils.hpp deleted file mode 100644 index 283d527fa..000000000 --- a/src/slic3r/GUI/DoubleSlider_Utils.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef slic3r_GUI_DoubleSlider_Utils_hpp_ -#define slic3r_GUI_DoubleSlider_Utils_hpp_ - -#include -#include - - -#endif // slic3r_GUI_DoubleSlider_Utils_hpp_ From 5f9aeb1e3840cc9f9d00a4e2dd6cc5699e00699a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 2 Mar 2022 08:30:00 +0100 Subject: [PATCH 03/13] Removed unneeded pairs glPushMatrix()/glPopMatrix() --- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 2 -- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 11 +++-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index f3ea526a0..bc0056fa6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -170,11 +170,9 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); Eigen::AngleAxisd aa(q); glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); - glsafe(::glPushMatrix()); glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); m_cylinder.render(); - glsafe(::glPopMatrix()); if (vol->is_left_handed()) glFrontFace(GL_CCW); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 3a503407c..47254e4b3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -220,17 +220,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const double cone_height = 0.75; glsafe(::glPushMatrix()); glsafe(::glTranslatef(0.f, 0.f, cone_height + support_point.head_front_radius * RenderPointScale)); - glsafe(::glPushMatrix()); glsafe(::glRotated(180., 1., 0., 0.)); glsafe(::glScaled(cone_radius, cone_radius, cone_height)); m_cone.render(); glsafe(::glPopMatrix()); - glsafe(::glTranslatef(0.f, 0.f, cone_height)); - glsafe(::glPopMatrix()); } glsafe(::glPushMatrix()); - double radius = (double)support_point.head_front_radius * RenderPointScale; + const double radius = (double)support_point.head_front_radius * RenderPointScale; glsafe(::glScaled(radius, radius, radius)); m_sphere.render(); glsafe(::glPopMatrix()); @@ -257,7 +254,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. glsafe(::glPushMatrix()); - glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2))); + glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z())); glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); if (vol->is_left_handed()) @@ -268,12 +265,10 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); - glsafe(::glPushMatrix()); + glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); m_cylinder.render(); - glsafe(::glPopMatrix()); if (vol->is_left_handed()) glFrontFace(GL_CCW); From b2fba940fe219eb306476d32126a8edc3c8c80c2 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Wed, 2 Mar 2022 09:47:29 +0100 Subject: [PATCH 04/13] Sync with PrusaSlicer-settings --- resources/profiles/PrusaResearch.idx | 1 + resources/profiles/PrusaResearch.ini | 708 ++++++++++++++++++++++++++- 2 files changed, 700 insertions(+), 9 deletions(-) diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index f90ba8279..9ee903563 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,4 +1,5 @@ min_slic3r_version = 2.4.0-rc +1.4.3 Added new filament profiles and SLA materials. 1.4.2 Added SLA material profiles. 1.4.1 Updated firmware version. 1.4.0 Updated for the PrusaSlicer 2.4.0-rc release. Updated SLA material colors. diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 71a86dde8..3182eba6b 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -5,7 +5,7 @@ name = Prusa Research # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.4.2 +config_version = 1.4.3 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/ changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% @@ -477,7 +477,7 @@ perimeter_acceleration = 800 perimeter_speed = 50 solid_infill_speed = 50 top_infill_extrusion_width = 0.4 -top_solid_layers = 7 +top_solid_layers = 8 bridge_flow_ratio = 1 bridge_speed = 25 @@ -1543,6 +1543,7 @@ filament_max_volumetric_speed = 13 [filament:*ABSMINI*] # inherits = *ABS* bed_temperature = 100 +first_layer_bed_temperature = 100 filament_retract_length = 2.7 filament_retract_speed = nil filament_deretract_speed = nil @@ -2914,6 +2915,7 @@ inherits = *PET* filament_vendor = BASF filament_cost = filament_density = 1.33 +filament_colour = #F7F7F7 first_layer_temperature = 220 first_layer_bed_temperature = 70 temperature = 215 @@ -2925,7 +2927,7 @@ bridge_fan_speed = 100 filament_type = PET disable_fan_first_layers = 1 full_fan_speed_layer = 3 -filament_notes = "BASF Forward AM Ultrafuse PET\nMaterial profile version 1.0\n\nMaterial Description\nUltrafuse PET is made from a premium PET and prints as easy as PLA, but is much stronger. The filament has a large operating window for printing (temperature vs. speed), so it can be used on every 3D-printer. PET will give you outstanding printing results: a good layer adhesion, a high resolution and it is easy to handle. Ultrafuse PET can be 100% recycled, is watertight and has great colors and finish.\n\nPrinting Recommendations:\nUltrafuse PET can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion.\n" +filament_notes = "Material Description\nUltrafuse PET is made from a premium PET and prints as easy as PLA, but is much stronger. The filament has a large operating window for printing (temperature vs. speed), so it can be used on every 3D-printer. PET will give you outstanding printing results: a good layer adhesion, a high resolution and it is easy to handle. Ultrafuse PET can be 100% recycled, is watertight and has great colors and finish.\n\nPrinting Recommendations:\nUltrafuse PET can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion." filament_retract_length = 2 filament_retract_speed = 40 filament_retract_before_travel = 2 @@ -2943,7 +2945,7 @@ filament_cost = filament_density = 1.25 filament_spool_weight = 0 filament_colour = #FFFFFF -filament_notes = "BASF Forward AM Ultrafuse PLA PRO1\nMaterial profile version 1.0\n\nMaterial Description\nPLA PRO1 is an extremely versatile tough PLA filament made for professionals. It reduces your printing time by 30% – 80%, (subject to printer and object limitations) and the strength exceeds overall mechanical properties of printed ABS parts. Printer settings can be tuned to achieve blazing fast speeds or an unrivaled surface finish. The excellent quality control ensures the highest levels of consistency between colors and batches, it will perform as expected, every time.\n\nPrinting Recommendations:\nUltrafuse PLA PRO1 can be printed directly onto a clean build plate.\n" +filament_notes = "Material Description\nPLA PRO1 is an extremely versatile tough PLA filament made for professionals. It reduces your printing time by 30% – 80%, (subject to printer and object limitations) and the strength exceeds overall mechanical properties of printed ABS parts. Printer settings can be tuned to achieve blazing fast speeds or an unrivaled surface finish. The excellent quality control ensures the highest levels of consistency between colors and batches, it will perform as expected, every time.\n\nPrinting Recommendations:\nUltrafuse PLA PRO1 can be printed directly onto a clean build plate." filament_retract_length = 2 filament_retract_lift = 0 filament_retract_speed = 40 @@ -2969,15 +2971,303 @@ max_fan_speed = 20 bed_temperature = 100 disable_fan_first_layers = 3 filament_colour = #FFFFFF -filament_notes = "BASF Forward AM Ultrafuse ABS\nMaterial profile version 1.0\n\nMaterial Description\nABS is the second most used 3D printing material. It is strong, flexible and has a high heat resistance. ABS is a preferred plastic for engineers and professional applications. ABS can be smoothened with acetone. To make a proper 3D print with ABS you will need a heated print bed. The filament is available in 9 colors.\n\nPrinting Recommendations:\n\nApply Tape, adhesion spray or glue to a clean build plate to improve adhesion.\n" -filament_retract_length = 2 -filament_retract_speed = 40 +filament_notes = "Material Description\nABS is the second most used 3D printing material. It is strong, flexible and has a high heat resistance. ABS is a preferred plastic for engineers and professional applications. ABS can be smoothened with acetone. To make a proper 3D print with ABS you will need a heated print bed. The filament is available in 9 colors.\n\nPrinting Recommendations:\n\nApply Tape, adhesion spray or glue to a clean build plate to improve adhesion." filament_retract_before_travel = 2 filament_wipe = 0 filament_retract_layer_change = 0 [filament:Ultrafuse ABS @MINI] inherits = Ultrafuse ABS; *ABSMINI* +filament_retract_layer_change = nil + +[filament:Ultrafuse ABS Fusion+] +inherits = Ultrafuse ABS +filament_density = 1.08 +first_layer_bed_temperature = 105 +temperature = 250 +filament_colour = #FFF8D9 +filament_notes = "Material Description\nABS Fusion+ made with Polyscope XILOY™ 3D is an engineering filament which has been optimized for 3D-printing. This special grade has been developed in collaboration with Polyscope Polymers - renowned for its material solutions in the automotive industry. ABS is a thermoplastic which is used in many applications. Although ABS has been classified as a standard material in 3D-printing it is known to be quite challenging to process. ABS Fusion+ combines the properties of ABS with an improved processability. The filament is based on an ABS grade which can be directly printed on glass without any adhesives or tape and has a higher success rate of prints due to extreme low warping." +filament_retract_before_travel = 2 +filament_wipe = nil +filament_retract_layer_change = 0 +filament_retract_lift = 0 + +[filament:Ultrafuse ABS Fusion+ @MINI] +inherits = Ultrafuse ABS Fusion+; *ABSMINI* +first_layer_bed_temperature = 100 +filament_retract_layer_change = nil + +[filament:Ultrafuse ASA] +inherits = Ultrafuse ABS Fusion+ +filament_density = 1.07 +filament_colour = #FFF4CA +first_layer_temperature = 275 +temperature = 275 +first_layer_bed_temperature = 110 +bed_temperature = 105 +filament_type = ASA +min_fan_speed = 25 +max_fan_speed = 50 +bridge_fan_speed = 100 +disable_fan_first_layers = 4 +filament_max_volumetric_speed = 5 +filament_notes = "Material Description\nUltrafuse ASA is a high-performance thermoplastic with similar mechanical properties as ABS. ASA offers additional benefits such as high outdoor weather resistance. The UV resistance, toughness, and rigidity make it an ideal material to 3D-print outdoor fixtures and appliances without losing its properties or color. When also taking into account the high heat resistance and high chemical resistance, this filament is a good choice for many types of applications.\n\nPrinting Recommendations:\nApply Magigoo PC, 3D lac or Dimafix to a clean build plate to improve adhesion." + +[filament:Ultrafuse ASA @MINI] +inherits = Ultrafuse ASA; *ABSMINI* +filament_type = ASA + +[filament:Ultrafuse HIPS] +inherits = Ultrafuse ABS +temperature = 250 +filament_density = 1.02 +filament_type = HIPS +min_fan_speed = 20 +max_fan_speed = 20 +filament_soluble = 1 +filament_notes = "Material Description\nUltrafuse HIPS is a high-quality engineering thermoplastic, which is well known in the 3D-printing industry as a support material for ABS. But this material has additional properties to offer like good impact resistance, good dimensional stability, and easy post-processing. HiPS is a great material to use as a support for ABS because there is a good compatibility between the two materials, and HIPS is an easy breakaway support. Now you have the opportunity to create ABS models with complex geometry. HIPS is easy to post process with glue or with sanding paper." + +[filament:Ultrafuse HIPS @MINI] +inherits = Ultrafuse HIPS; *ABSMINI* +filament_type = HIPS +min_fan_speed = 20 +max_fan_speed = 20 + +[filament:Ultrafuse PA] +inherits = Fillamentum Nylon FX256 +filament_vendor = BASF +filament_density = 1.12 +filament_colour = #ECFAFF +first_layer_temperature = 240 +temperature = 240 +first_layer_bed_temperature = 80 +bed_temperature = 70 +min_fan_speed = 0 +max_fan_speed = 0 +bridge_fan_speed = 0 +fan_below_layer_time = 30 +slowdown_below_layer_time = 20 +min_print_speed = 15 +filament_max_volumetric_speed = 11 +filament_retract_length = 1 +filament_retract_lift = 0 +filament_retract_before_travel = 2 +filament_retract_layer_change = 0 +filament_cost = 0 +filament_spool_weight = 0 +compatible_printers_condition = printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.6}0.12{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.8}0.06{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif nozzle_diameter[0]==0.8}0.01{elsif nozzle_diameter[0]==0.6}0.02{else}0.04{endif} ; Filament gcode LA 1.5\n{if printer_notes=~/.*PRINTER_MODEL_MINI.*/};{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}M900 K200{elsif nozzle_diameter[0]==0.6}M900 K12{elsif nozzle_diameter[0]==0.8};{else}M900 K20{endif} ; Filament gcode LA 1.0" +filament_notes = "Material Description\nThe key features of Ultrafuse PA are the high strength and high modulus. Furthermore, Ultrafuse PA shows a good thermal distortion stability.\n\nPrinting Recommendations:\nApply PVA glue, Kapton tape or PA adhesive to a clean buildplate to improve adhesion." + +[filament:Ultrafuse PA6 GF30] +inherits = Ultrafuse PA +filament_density = 1.17 +first_layer_temperature = 270 +temperature = 270 +first_layer_bed_temperature = 100 +bed_temperature = 100 +filament_colour = #404040 +fan_always_on = 1 +min_fan_speed = 0 +max_fan_speed = 50 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +full_fan_speed_layer = 3 +slowdown_below_layer_time = 15 +filament_max_volumetric_speed = 10 +filament_retract_length = 1.2 +filament_retract_speed = 40 +filament_deretract_speed = 30 +filament_retract_lift = nil +filament_wipe = 0 +filament_notes = "Material Description\nUltrafuse® PA6 GF30 is a unique compound specifically developed for FFF printing. Due to the glass fiber content of 30%, parts tend to warp less. In addition the excellent layer adhesion and its compatibility with the water soluble support Ultrafuse® BVOH make this material the perfect solution to develop industrial applications on an FFF printer.\n\nWith its high wear and chemical resistance, high stiffness and strength, Ultrafuse® PA6 GF30 is perfect for a wide variety of applications in automotive, electronics or transportation.\n\nUltrafuse PA6 GF30 is designed for functional prototyping and demanding applications such as industrial tooling, transportation, electronics, small appliances, sports & leisure\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nUltrafuse PA6 GF30 can be printed directly onto a clean build plate. For challenging prints, use Magigoo PA gluestick to improve adhesion." +compatible_printers_condition = nozzle_diameter[0]>=0.6 and printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + +[filament:Ultrafuse PAHT-CF15] +inherits = Ultrafuse PA6 GF30 +filament_density = 1.23 +filament_notes = "Material Description\nPAHT CF15 is a high-performance 3D printing filament that opens new application fields in FFF printing. In parallel to its advanced mechanical properties, dimensional stability, and chemical resistance, it has very good processability. It works in any FFF printer with a hardened nozzle. In addition to that, it is compatible with water-soluble support material and HiPS, which allow printing complex geometries that work in challenging environments. PAHT CF15 has high heat resistance up to 130 °C and low moisture absorption.\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nUltrafuse PAHT-CF can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion." + +[filament:Ultrafuse PC-ABS-FR] +inherits = Ultrafuse ABS +filament_colour = #505050 +filament_density = 1.17 +first_layer_temperature = 275 +temperature = 275 +first_layer_bed_temperature = 110 +bed_temperature = 105 +filament_type = PC +filament_max_volumetric_speed = 8 +filament_wipe = nil +min_fan_speed = 20 +max_fan_speed = 20 +bridge_fan_speed = 30 +disable_fan_first_layers = 4 +compatible_printers_condition = printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +filament_notes = "Material Description\nUltrafuse® PC/ABS FR Black is a V-0 flame retardant blend of Polycarbonate and ABS – two of the most used thermoplastics for engineering & electrical applications. The combination of these two materials results in a premium material with a mix of the excellent mechanical properties of PC and the comparably low printing temperature of ABS. Combined with a halogen free flame retardant, parts printed with Ultrafuse® PC/ABS FR Black feature great tensile and impact strength, higher thermal resistance than ABS and can fulfill the requirements of the UL94 V-0 standard.\n\nPrinting Recommendations:\nApply Magigoo PC to a clean build plate to improve adhesion." +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.6}0.12{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.8}0.06{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif nozzle_diameter[0]==0.8}0.02{elsif nozzle_diameter[0]==0.6}0.04{else}0.07{endif} ; Filament gcode LA 1.5\n{if printer_notes=~/.*PRINTER_MODEL_MINI.*/};{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}M900 K200{elsif nozzle_diameter[0]==0.6}M900 K24{elsif nozzle_diameter[0]==0.8};{else}M900 K45{endif} ; Filament gcode LA 1.0" + +[filament:Ultrafuse PET-CF15] +inherits = Ultrafuse PET +filament_density = 1.36 +filament_colour = #404040 +first_layer_temperature = 270 +temperature = 270 +first_layer_bed_temperature = 75 +bed_temperature = 75 +min_fan_speed = 60 +max_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +full_fan_speed_layer = 3 +slowdown_below_layer_time = 15 +fan_below_layer_time = 30 +filament_max_volumetric_speed = 10 +filament_retract_length = 1.2 +filament_retract_speed = 40 +filament_deretract_speed = 30 +filament_retract_lift = nil +filament_wipe = 0 +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.6}0.12{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.8}0.06{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif nozzle_diameter[0]==0.8}0.01{elsif nozzle_diameter[0]==0.6}0.04{else}0.05{endif} ; Filament gcode LA 1.5\n{if printer_notes=~/.*PRINTER_MODEL_MINI.*/};{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}M900 K200{elsif nozzle_diameter[0]==0.6}M900 K18{elsif nozzle_diameter[0]==0.8};{else}M900 K30{endif} ; Filament gcode LA 1.0" +filament_notes = "Material Description\nPET CF15 is a Carbon Fiber reinforced PET which has precisely tuned material properties, for a wide range of technical applications. The filament is very strong and stiff and has high heat resistance. With its high dimensional stability and low abrasiveness, the filament offers an easy to print experience which allows direct printing on glass or a PEI sheet. It is compatible with HiPS for breakaway support and water soluble support and has an excellent surface finish.\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nUltrafuse PET-CF15 can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion." +compatible_printers_condition = nozzle_diameter[0]>=0.6 and printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + +[filament:Ultrafuse PLA] +inherits = *PLA* +filament_vendor = BASF +filament_density = 1.25 +full_fan_speed_layer = 3 +filament_notes = "Material Description\nPLA is one of the most used materials for 3D printing. Ultrafuse PLA is available in a wide range of colors. The glossy feel often attracts those who print display models or items for household use. Many appreciate the plant-based origin of this material. When properly cooled, PLA has a high maximum printing speed and sharp printed corners. Combining this with low warping of the print makes it a popular plastic for home printers, hobbyists, prototyping and schools.\n\nPrinting Recommendations:\nUltrafuse PLA can be printed directly onto a clean build plate." + +[filament:Ultrafuse PP] +inherits = Ultrafuse ABS +filament_density = 0.91 +filament_colour = #F0F0F0 +first_layer_temperature = 240 +temperature = 240 +first_layer_bed_temperature = 80 +bed_temperature = 70 +min_fan_speed = 100 +max_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +full_fan_speed_layer = 3 +fan_below_layer_time = 60 +slowdown_below_layer_time = 20 +min_print_speed = 10 +filament_type = PP +filament_max_volumetric_speed = 2.5 +filament_retract_speed = 25 +filament_deretract_speed = 25 +filament_retract_layer_change = 0 +filament_wipe = nil +filament_notes = "Material Description\nUltrafuse PP is high-performance thermoplastic with low density, high elasticity and high resistance to fatigue. The mechanical properties make it an ideal material for 3D-printing applications which have to endure high stress or strain. The filament has high chemical resistance and a high isolation value. PP is one of the most used materials in the world, due to its versatility and ability to engineer lightweight tough parts.\n\nPrinting Recommendations:\nApply PP tape or Magigoo PP adhesive to the buildplate for optimal adhesion." +compatible_printers_condition = printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + +[filament:Ultrafuse PP-GF30] +inherits = Ultrafuse PP +filament_density = 1.07 +filament_colour = #404040 +first_layer_temperature = 260 +temperature = 250 +first_layer_bed_temperature = 90 +bed_temperature = 40 +min_fan_speed = 40 +max_fan_speed = 75 +fan_always_on = 1 +fan_below_layer_time = 30 +slowdown_below_layer_time = 15 +min_print_speed = 15 +filament_retract_length = 1.2 +filament_retract_speed = 40 +filament_deretract_speed = 30 +filament_retract_lift = nil +filament_wipe = 0 +filament_notes = "Ultrafuse PP GF30 is polypropylene, reinforced with 30% glass fiber content. The fibers in this compound are specially designed for 3D-printing filaments and are compatible with a wide range of standard FFF 3D-printers. The extreme stiffness makes this material highly suitable for demanding applications. Other key properties of PPGF30 are high heat resistance and improved UV-resistance. All these excellent properties make this filament highly suitable in an industrial environment.\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nApply PP strapping tape or PPGF adhesive to a clean build plate for optimal adhesion." +compatible_printers_condition = nozzle_diameter[0]>=0.6 and printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + +[filament:Ultrafuse TPC-45D] +inherits = *FLEX* +filament_vendor = BASF +extrusion_multiplier = 1 +filament_density = 1.15 +filament_colour = #0035EC +first_layer_temperature = 235 +temperature = 235 +first_layer_bed_temperature = 60 +bed_temperature = 60 +min_fan_speed = 10 +max_fan_speed = 50 +bridge_fan_speed = 80 +fan_below_layer_time = 30 +slowdown_below_layer_time = 15 +min_print_speed = 15 +fan_always_on = 1 +cooling = 1 +filament_max_volumetric_speed = 1.2 +filament_retract_length = 1.2 +filament_retract_speed = 25 +filament_deretract_speed = 25 +filament_retract_lift = 0 +filament_wipe = nil +filament_retract_before_wipe = nil +filament_retract_before_travel = 2 +filament_retract_layer_change = 0 +filament_notes = "Material Description\nTPC 45D is a flexible, shore 45D, rubber-like Thermoplastic Copolyester Elastomer (TPE-C), which is derived from rapeseed oil and combines the best properties of elastomers (rubbers) and polyesters. The material delivers excellent adhesion in the Z-direction, meaning that the printed layers do not detach - even with extreme deformation.\n\nPrinting Recommendations:\nApply Magigoo Flex to a clean build plate to improve adhesion." + +## [filament:Ultrafuse TPS-90A] +## inherits = Ultrafuse TPC-45D +## filament_density = 1.04 +## extrusion_multiplier = 1.02 +## filament_colour = #FFFFFF +## first_layer_temperature = 270 +## temperature = 265 +## first_layer_bed_temperature = 30 +## bed_temperature = 30 +## min_fan_speed = 20 +## max_fan_speed = 75 +## filament_notes = "Material Description\nUltrafuse® TPS 90A is an elastomer based on the raw material SEBS. The combination of durable and flexible building blocks leads to a very versatile material. Compared to other flexible 3D printing materials it shows more rubber-like soft touch haptics and better non-slip properties. Furthermore, the material shows a reduced moisture uptake, which allows for printing without pre-drying. Parts printed with Ultrafuse® TPS 90A show almost no visible layers or warpage, which makes it an excellent material choice for end-use parts. Producing multi-material parts is possible by printing it together with ABS.\n\nPrinting Recommendations:\nApply Tape, adhesion spray or glue to a clean build plate to improve adhesion." + +[filament:Ultrafuse TPU-64D] +inherits = Ultrafuse TPC-45D +filament_density = 1.16 +first_layer_temperature = 230 +temperature = 225 +first_layer_bed_temperature = 40 +bed_temperature = 40 +min_fan_speed = 20 +max_fan_speed = 100 +filament_notes = "Material Description\nUltrafuse® TPU 64D is the hardest elastomer in BASF Forward AM’s flexible productline. The material shows a relatively high rigidity while maintaining a certain flexibility. This filament is the perfect match for industrial applications requiring rigid parts being resistant to impact, wear and tear. Due to its property profile, the material can be used as an alternative for parts made from ABS and rubbers. Ultrafuse® TPU 64D is easy to print on direct drive and bowden style printers and is compatible with soluble BVOH support to realize the most complex geometries.\n\nPrinting Recommendations:\nUltrafuse TPU can be printed directly onto a clean build plate. A small amount of 3Dlac can make removal easier after printing." + +[filament:Ultrafuse TPU-85A] +inherits = Ultrafuse TPU-64D +filament_density = 1.11 +first_layer_temperature = 225 +temperature = 220 +filament_notes = "Material Description\nUltrafuse® TPU 85A comes in its natural white color. Chemical properties (e.g. resistance against particular substances) and tolerance for solvents can be made available, if these factors are relevant for a specific application. Generally, these properties correspond to publicly available data on polyether based TPUs. This material is not FDA conform. Good flexibility at low temperature, good wear performance and good damping behavior are the key features of Ultrafuse® TPU 85A.\n\nPrinting Recommendations:\nUltrafuse TPU can be printed directly onto a clean build plate. A small amount of 3Dlac can make removal easier after printing." + +[filament:Ultrafuse TPU-95A] +inherits = Ultrafuse TPU-85A +filament_density = 1.14 +first_layer_temperature = 230 +temperature = 225 +filament_notes = "Material Description\nUltrafuse® TPU 95A comes with a well-balanced profile of flexibility and durability. On top of that, it allows for easier and faster printing then softer TPU grades. Parts printed with Ultrafuse® TPU 95A show a high elongation, good impact resistance, excellent layer adhesion and a good resistance to oils and common industrially used chemicals. Due to its good printing behavior, Ultrafuse® TPU 95A is a good choice for starting printing flexible materials on both direct drive and bowden style printers.\n\nPrinting Recommendations:\nUltrafuse TPU can be printed directly onto a clean build plate. A small amount of 3Dlac can make removal easier after printing." + +[filament:Ultrafuse rPET] +inherits = Ultrafuse PET +filament_density = 1.27 +filament_colour = #9DC5FF +first_layer_temperature = 235 +temperature = 235 +first_layer_bed_temperature = 80 +bed_temperature = 75 +min_fan_speed = 50 +max_fan_speed = 100 +fan_below_layer_time = 15 +filament_notes = "Material Description\nPET is mainly known by the well-known PET bottle material. This recycled has a natural transparent blueish look. It has excellent 3D printing properties and good mechanical characteristics." +filament_retract_length = 1.2 +filament_retract_lift = 0.6 +filament_wipe = nil [filament:Ultrafuse Metal] inherits = *ABSC* @@ -4629,7 +4919,7 @@ material_colour = #FF8040 inherits = *common 0.025* exposure_time = 12 initial_exposure_time = 30 -material_type = Tough +material_type = Casting material_vendor = 3DM material_colour = #B0B000 @@ -5084,6 +5374,38 @@ material_type = Tough material_vendor = Ameralabs material_colour = #C0C0C0 +[sla_material:PrimaCreator Tough Light Grey @0.025] +inherits = *common 0.025* +exposure_time = 6 +initial_exposure_time = 35 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #C0C0C0 + +[sla_material:PrimaCreator Tough Clear @0.025] +inherits = *common 0.025* +exposure_time = 5 +initial_exposure_time = 35 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #F8F8F8 + +[sla_material:PrimaCreator Tough White @0.025] +inherits = *common 0.025* +exposure_time = 5 +initial_exposure_time = 35 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #FFFFFF + +[sla_material:PrimaCreator Flex Clear @0.025] +inherits = *common 0.025* +exposure_time = 4.5 +initial_exposure_time = 30 +material_type = Flexible +material_vendor = PrimaCreator +material_colour = #F8F8F8 + [sla_material:Siraya Tech Simple Clear @0.025] inherits = *common 0.025* exposure_time = 8 @@ -5371,7 +5693,7 @@ inherits = *common 0.05* exposure_time = 12 initial_exposure_time = 45 material_type = Tough -material_vendor = Monocure +material_vendor = 3DM material_colour = #EC0000 [sla_material:Esun Bio-Photopolymer Resin White @0.05] @@ -5550,6 +5872,38 @@ material_type = Tough material_vendor = Photocentric material_colour = #C0C0C0 +[sla_material:PrimaCreator Tough Light Grey @0.05] +inherits = *common 0.05* +exposure_time = 8.5 +initial_exposure_time = 35 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #C0C0C0 + +[sla_material:PrimaCreator Tough Clear @0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 35 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #F8F8F8 + +[sla_material:PrimaCreator Tough White @0.05] +inherits = *common 0.05* +exposure_time = 7.5 +initial_exposure_time = 35 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #FFFFFF + +[sla_material:PrimaCreator Flex Clear @0.05] +inherits = *common 0.05* +exposure_time = 6.5 +initial_exposure_time = 30 +material_type = Flexible +material_vendor = PrimaCreator +material_colour = #F8F8F8 + [sla_material:Siraya Tech Simple Clear @0.05] inherits = *common 0.05* exposure_time = 10 @@ -6270,6 +6624,38 @@ material_type = Tough material_vendor = Made for Prusa material_colour = #FF8040 +[sla_material:PrimaCreator Tough Light Grey @0.1] +inherits = *common 0.1* +exposure_time = 14 +initial_exposure_time = 45 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #C0C0C0 + +[sla_material:PrimaCreator Tough Clear @0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #F8F8F8 + +[sla_material:PrimaCreator Tough White @0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 +material_type = Tough +material_vendor = PrimaCreator +material_colour = #FFFFFF + +[sla_material:PrimaCreator Flex Clear @0.1] +inherits = *common 0.1* +exposure_time = 12 +initial_exposure_time = 35 +material_type = Flexible +material_vendor = PrimaCreator +material_colour = #F8F8F8 + ## SL1S materials ## ## 0.025 SL1S @@ -6916,6 +7302,310 @@ material_type = Tough material_vendor = Peopoly material_colour = #F8F8F8 +[sla_material:3DM-ABS @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.6 +initial_exposure_time = 25 +material_type = Tough +material_vendor = 3DM +material_colour = #FF8040 + +[sla_material:3DM-DENT @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.3 +initial_exposure_time = 36 +material_type = Dental +material_vendor = 3DM +material_colour = #FFEEE6 + +[sla_material:3DM-HR Green @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 5 +initial_exposure_time = 28 +material_type = Tough +material_vendor = 3DM +material_colour = #00B900 + +[sla_material:3DM-HR Red Wine @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 6 +initial_exposure_time = 32 +material_type = Tough +material_vendor = 3DM +material_colour = #EC0000 + +[sla_material:3DM-Vulcan Gold @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 5 +initial_exposure_time = 24 +material_type = Casting +material_vendor = 3DM +material_colour = #B0B000 + +[sla_material:3DM-XPRO White @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = 3DM +material_colour = #FFFFFF + +[sla_material:Asiga Denta Model @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 5 +initial_exposure_time = 24 +material_type = Dental +material_vendor = Asiga +material_colour = #FFEEE6 + +[sla_material:Asiga PlasGRAY @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 9.7 +initial_exposure_time = 48 +material_type = Tough +material_vendor = Asiga +material_colour = #C0C0C0 + +[sla_material:BlueCast EcoGray @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = BlueCast +material_colour = #808080 + +[sla_material:BlueCast Phrozen Wax @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 5.3 +initial_exposure_time = 40 +material_type = Tough +material_vendor = BlueCast +material_colour = #007EFD + +[sla_material:NextDent Model 2.0 Grey @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 4 +initial_exposure_time = 28 +material_type = Dental +material_vendor = NextDent +material_colour = #C0C0C0 + +[sla_material:NextDent Cast Purple @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3 +initial_exposure_time = 16 +material_type = Casting +material_vendor = NextDent +material_colour = #E800E8 + +[sla_material:Siraya Tech Tenacious @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.7 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #F8F8F8 + +[sla_material:Siraya Tech Blu Clear V2 @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3.3 +initial_exposure_time = 24 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #F8F8F8 + +[sla_material:Siraya Tech Blu Blue @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 4 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #007EFD + +[sla_material:Siraya Tech Fast Black @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #595959 + +[sla_material:Siraya Tech Fast Grey @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #C0C0C0 + +[sla_material:Siraya Tech Simple Clear @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #F8F8F8 + +[sla_material:Siraya Tech Sculpt @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.7 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Siraya Tech +material_colour = #C0C0C0 + +[sla_material:Harz Labs Model Resin Cherry @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 4.3 +initial_exposure_time = 16 +material_type = Tough +material_vendor = Harz Labs +material_colour = #EC0000 + +[sla_material:Harz Labs Model Resin Black @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 4.3 +initial_exposure_time = 16 +material_type = Tough +material_vendor = Harz Labs +material_colour = #595959 + +[sla_material:Harz Labs Basic Resin Red @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 4.3 +initial_exposure_time = 16 +material_type = Tough +material_vendor = Harz Labs +material_colour = #EC0000 + +[sla_material:Resinworks 3D Violet @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 5.7 +initial_exposure_time = 24 +material_type = Tough +material_vendor = Resinworks 3D +material_colour = #E800E8 + +[sla_material:FunToDo Industrial Blend Unpigmented @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 1.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = FunToDo +material_colour = #F8F8F8 + +[sla_material:FunToDo Snow White @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = FunToDo +material_colour = #FFFFFF + +[sla_material:FunToDo Ash Grey @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3 +initial_exposure_time = 32 +material_type = Tough +material_vendor = FunToDo +material_colour = #808080 + +[sla_material:Ameralabs AMD 3 LED @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 1.7 +initial_exposure_time = 24 +material_type = Tough +material_vendor = Ameralabs +material_colour = #808080 + +[sla_material:Dragon Resin Metalshine Metal Grey @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 10 +initial_exposure_time = 40 +material_type = Tough +material_vendor = Dragon Resin +material_colour = #808080 + +[sla_material:Dragon Resin Metalshine Dark Brass @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 10 +initial_exposure_time = 40 +material_type = Tough +material_vendor = Dragon Resin +material_colour = #B0B000 + +[sla_material:Dragon Resin Metalshine Brass @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 10 +initial_exposure_time = 40 +material_type = Tough +material_vendor = Dragon Resin +material_colour = #B0B000 + +[sla_material:Esun Bio-Photopolymer Resin White @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.7 +initial_exposure_time = 24 +material_type = Tough +material_vendor = Esun +material_colour = #FFFFFF + +[sla_material:Esun Standard Resin Black @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.3 +initial_exposure_time = 24 +material_type = Tough +material_vendor = Esun +material_colour = #595959 + +[sla_material:Monocure 3D Black Rapid Resin @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Monocure +material_colour = #595959 + +[sla_material:Monocure 3D Blue Rapid Resin @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Monocure +material_colour = #007EFD + +[sla_material:Monocure 3D Clear Rapid Resin @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 2.7 +initial_exposure_time = 32 +material_type = Tough +material_vendor = Monocure +material_colour = #F8F8F8 + +[sla_material:Monocure 3D Grey Rapid Resin @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3.3 +initial_exposure_time = 25 +material_type = Tough +material_vendor = Monocure +material_colour = #C0C0C0 + +[sla_material:Monocure 3D White Rapid Resin @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 3.3 +initial_exposure_time = 28 +material_type = Tough +material_vendor = Monocure +material_colour = #FFFFFF + +[sla_material:Photocentric Hard Grey @0.05 SL1S] +inherits = *0.05_sl1s* +exposure_time = 5 +initial_exposure_time = 24 +material_type = Tough +material_vendor = Photocentric +material_colour = #808080 + ## 0.1 SL1S ## Prusa Polymers 0.1 From 5193a158528a81c654bf3d474515017b41543dfd Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 2 Mar 2022 12:10:02 +0100 Subject: [PATCH 05/13] Tech ENABLE_GLBEGIN_GLEND_REMOVAL - Use 2D vertices to render GLGizmoPainterBase circle --- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index d3fd294b3..76e73ab97 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -192,7 +192,7 @@ void GLGizmoPainterBase::render_cursor_circle() GLModel::Geometry init_data; static const unsigned int StepsCount = 32; static const float StepSize = 2.0f * float(PI) / float(StepsCount); - init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f }; init_data.reserve_vertices(StepsCount); init_data.reserve_indices(StepsCount); @@ -200,7 +200,7 @@ void GLGizmoPainterBase::render_cursor_circle() // vertices + indices for (unsigned short i = 0; i < StepsCount; ++i) { const float angle = float(i * StepSize); - init_data.add_vertex(Vec3f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius, 0.0f)); + init_data.add_vertex(Vec2f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius)); init_data.add_ushort_index(i); } From 4990558dee1817ce5061d1f6fdb24b012e96f42a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 2 Mar 2022 13:28:20 +0100 Subject: [PATCH 06/13] Tech ENABLE_GLBEGIN_GLEND_REMOVAL - Fixed a few bugs when the tech is disabled --- src/slic3r/GUI/3DBed.cpp | 25 +++++++------------- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 10 ++++---- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 2 +- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 244a802db..4ed054fb9 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -593,10 +593,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) if (bottom) glsafe(::glFrontFace(GL_CW)); - unsigned int stride = m_triangles.get_vertex_data_size(); - - GLint position_id = shader->get_attrib_location("v_position"); - GLint tex_coords_id = shader->get_attrib_location("v_tex_coords"); + const unsigned int stride = m_triangles.get_vertex_data_size(); // show the temporary texture while no compressed data is available GLuint tex_id = (GLuint)m_temp_texture.get_id(); @@ -606,22 +603,16 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id)); - if (position_id != -1) { - glsafe(::glEnableVertexAttribArray(position_id)); - glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(intptr_t)m_triangles.get_position_offset())); - } - if (tex_coords_id != -1) { - glsafe(::glEnableVertexAttribArray(tex_coords_id)); - glsafe(::glVertexAttribPointer(tex_coords_id, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(intptr_t)m_triangles.get_tex_coords_offset())); - } + glsafe(::glVertexPointer(3, GL_FLOAT, stride, (const void*)(intptr_t)m_triangles.get_position_offset())); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + + glsafe(::glTexCoordPointer(2, GL_FLOAT, stride, (const void*)(intptr_t)m_triangles.get_tex_coords_offset())); + glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY)); glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)m_triangles.get_vertices_count())); - if (tex_coords_id != -1) - glsafe(::glDisableVertexAttribArray(tex_coords_id)); - - if (position_id != -1) - glsafe(::glDisableVertexAttribArray(position_id)); + glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY)); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 76e73ab97..768bdec25 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -1195,11 +1195,11 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) m_varrays[i].init_from(std::move(varrays_data[i])); } #else - for (auto* iva : { &m_iva_enforcers, &m_iva_blockers }) - iva->finalize_geometry(true); - - for (auto& iva : m_iva_seed_fills) - iva.finalize_geometry(true); +// for (auto* iva : { &m_iva_enforcers, &m_iva_blockers }) +// iva->finalize_geometry(true); +// +// for (auto& iva : m_iva_seed_fills) +// iva.finalize_geometry(true); #endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL #if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 47254e4b3..55fc52de7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -245,7 +245,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) m_cylinder.set_color(render_color); #else m_cylinder.set_color(-1, render_color); - if (shader != nu) + if (shader != nullptr) #endif // ENABLE_GLBEGIN_GLEND_REMOVAL shader->set_uniform("emission_factor", 0.5f); for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) { From 5621f00ee694e6aaedb83b190c855395a0df2dc6 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 2 Mar 2022 14:31:24 +0100 Subject: [PATCH 07/13] Some refactoring into GLGizmoSlaSupports::render_points() --- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 25 +++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 55fc52de7..3cdc4e33a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -120,10 +120,10 @@ void GLGizmoSlaSupports::on_render_for_picking() void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) { - size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); + const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); - bool has_points = (cache_size != 0); - bool has_holes = (! m_c->hollowed_mesh()->get_hollowed_mesh() + const bool has_points = (cache_size != 0); + const bool has_holes = (! m_c->hollowed_mesh()->get_hollowed_mesh() && ! m_c->selection_info()->model_object()->sla_drain_holes.empty()); if (! has_points && ! has_holes) @@ -147,9 +147,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) #endif // ENABLE_GLBEGIN_GLEND_REMOVAL const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); - const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); + const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); - float z_shift = m_c->selection_info()->get_sla_shift(); + const float z_shift = m_c->selection_info()->get_sla_shift(); glsafe(::glPushMatrix()); glsafe(::glTranslated(0.0, 0.0, z_shift)); @@ -158,7 +158,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) ColorRGBA render_color; for (size_t i = 0; i < cache_size; ++i) { const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i]; - const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false; + const bool point_selected = m_editing_mode ? m_editing_cache[i].selected : false; if (is_mesh_point_clipped(support_point.pos.cast())) continue; @@ -198,7 +198,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. glsafe(::glPushMatrix()); - glsafe(::glTranslatef(support_point.pos(0), support_point.pos(1), support_point.pos(2))); + glsafe(::glTranslatef(support_point.pos.x(), support_point.pos.y(), support_point.pos.z())); glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); if (vol->is_left_handed()) @@ -213,12 +213,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast()); - Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); - + const Eigen::AngleAxisd aa(q); + glsafe(::glPushMatrix()); + glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); const double cone_radius = 0.25; // mm const double cone_height = 0.75; - glsafe(::glPushMatrix()); glsafe(::glTranslatef(0.f, 0.f, cone_height + support_point.head_front_radius * RenderPointScale)); glsafe(::glRotated(180., 1., 0., 0.)); glsafe(::glScaled(cone_radius, cone_radius, cone_height)); @@ -226,11 +225,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glPopMatrix()); } - glsafe(::glPushMatrix()); const double radius = (double)support_point.head_front_radius * RenderPointScale; glsafe(::glScaled(radius, radius, radius)); m_sphere.render(); - glsafe(::glPopMatrix()); if (vol->is_left_handed()) glFrontFace(GL_CCW); @@ -264,7 +261,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); - Eigen::AngleAxisd aa(q); + const Eigen::AngleAxisd aa(q); glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); From a3b9d1d82fee94d74a5fa5e206487705027ca79b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 3 Mar 2022 11:47:16 +0100 Subject: [PATCH 08/13] Added a comment explaining activate_gizmo return value --- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 7df2999f1..fba02963f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -907,6 +907,10 @@ void GLGizmosManager::update_hover_state(const EType &type) m_tooltip = hovered_gizmo.get_name(); } + + +// Activate given gizmo. Returns true if successful, false in case that current +// gizmo vetoed its deactivation. bool GLGizmosManager::activate_gizmo(EType type) { assert(!m_gizmos.empty()); From 4967b940b81f54703917cf32259897c15c48ea9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 3 Mar 2022 14:56:18 +0100 Subject: [PATCH 09/13] Fixed a compiler warning. --- src/libslic3r/Brim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 0fec89ced..f48d7ff0a 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -313,7 +313,7 @@ static std::vector inner_brim_area(const Print // After 7ff76d07684858fd937ef2f5d863f105a10f798e offset and shrink don't work with CW polygons (holes), so let's make it CCW. Polygons ex_poly_holes_reversed = ex_poly.holes; polygons_reverse(ex_poly_holes_reversed); - for (const PrintInstance &instance : object->instances()) { + for ([[maybe_unused]] const PrintInstance &instance : object->instances()) { ++polygon_idx; // Increase idx because of the contour of the ExPolygon. if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner) From 3505e5a2901d27747ab81ef88147b8eeb07280ea Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 1 Mar 2022 12:03:42 +0100 Subject: [PATCH 10/13] Fix of leaking GDI resources on Win7 #8002: - Code refactoring for draw_focus_rect. - Use one PaintDC for rendering - DoubleSlider::Control::Ruler refactoring - Suppress to update ruler for horizontal slider --- src/slic3r/GUI/DoubleSlider.cpp | 76 ++++++++++++++++++++++++++------- src/slic3r/GUI/DoubleSlider.hpp | 25 +++++++++-- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index b5201d861..d2f0e89aa 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -122,6 +122,10 @@ Control::Control( wxWindow *parent, this->Bind(wxEVT_KEY_UP, &Control::OnKeyUp, this); this->Bind(wxEVT_RIGHT_DOWN, &Control::OnRightDown,this); this->Bind(wxEVT_RIGHT_UP, &Control::OnRightUp, this); + this->Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { + m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); + event.Skip(); + }); // control's view variables SLIDER_MARGIN = 4 + GUI::wxGetApp().em_unit(); @@ -137,8 +141,14 @@ Control::Control( wxWindow *parent, m_line_pens = { &DARK_GREY_PEN, &GREY_PEN, &LIGHT_GREY_PEN }; m_segm_pens = { &DARK_ORANGE_PEN, &ORANGE_PEN, &LIGHT_ORANGE_PEN }; + FOCUS_RECT_PEN = wxPen(wxColour(128, 128, 10), 1, wxPENSTYLE_DOT); + FOCUS_RECT_BRUSH = wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT); + m_font = GetFont(); this->SetMinSize(get_min_size()); + + if (style == wxSL_VERTICAL) + m_ruler.set_parent(this->GetParent()); } void Control::msw_rescale() @@ -170,6 +180,9 @@ void Control::msw_rescale() SetMinSize(get_min_size()); GetParent()->Layout(); + + m_ruler.update_dpi(); + m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); } void Control::sys_color_changed() @@ -266,7 +279,11 @@ void Control::SetMaxValue(const int max_value) void Control::SetSliderValues(const std::vector& values) { m_values = values; - m_ruler.init(m_values); + m_ruler.init(m_values, get_scroll_step()); + + // When "No sparce layer" is enabled, use m_layers_values for ruler update. + // Because of m_values has duplicate values in this case. +// m_ruler.update(this->GetParent(), m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); } void Control::draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos) @@ -426,9 +443,12 @@ void Control::SetLayersTimes(const std::vector& layers_times, float total if (m_layers_values.size() != m_layers_times.size()) for (size_t i = m_layers_times.size(); i < m_layers_values.size(); i++) m_layers_times.push_back(total_time); + m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); Refresh(); Update(); } + else + m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); } void Control::SetLayersTimes(const std::vector& layers_times) @@ -494,15 +514,17 @@ void Control::get_lower_and_higher_position(int& lower_pos, int& higher_pos) } } -void Control::draw_focus_rect() +void Control::draw_focus_rect(wxDC& dc) { if (!m_is_focused) return; const wxSize sz = GetSize(); - wxPaintDC dc(this); - const wxPen pen = wxPen(wxColour(128, 128, 10), 1, wxPENSTYLE_DOT); - dc.SetPen(pen); - dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT)); +// wxPaintDC dc(this); + //const wxPen pen = wxPen(wxColour(128, 128, 10), 1, wxPENSTYLE_DOT); + //dc.SetPen(pen); + //dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT)); + dc.SetPen(FOCUS_RECT_PEN); + dc.SetBrush(FOCUS_RECT_BRUSH); dc.DrawRectangle(1, 1, sz.x - 2, sz.y - 2); } @@ -513,11 +535,12 @@ void Control::render() #else SetBackgroundColour(GetParent()->GetBackgroundColour()); #endif // _WIN32 - draw_focus_rect(); wxPaintDC dc(this); dc.SetFont(m_font); + draw_focus_rect(dc); + const wxCoord lower_pos = get_position_from_value(m_lower_value); const wxCoord higher_pos = get_position_from_value(m_higher_value); @@ -807,7 +830,7 @@ void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, LabelType l } wxColour old_clr = dc.GetTextForeground(); - const wxPen& pen = is_wipe_tower_layer(tick) && (tick == m_lower_value || tick == m_higher_value) ? DARK_ORANGE_PEN : wxPen(old_clr); + const wxPen& pen = is_wipe_tower_layer(tick) && (tick == m_lower_value || tick == m_higher_value) ? DARK_ORANGE_PEN : /*wxPen(old_clr)*/GREY_PEN; dc.SetPen(pen); dc.SetTextForeground(pen.GetColour()); @@ -1028,8 +1051,10 @@ void Control::draw_colored_band(wxDC& dc) } } -void Control::Ruler::init(const std::vector& values) +void Control::Ruler::init(const std::vector& values, double scroll_step) { + if (!m_parent) + return; max_values.clear(); max_values.reserve(std::count(values.begin(), values.end(), values.front())); @@ -1039,14 +1064,35 @@ void Control::Ruler::init(const std::vector& values) it = std::find(it + 1, values.end(), values.front()); } max_values.push_back(*(it - 1)); + + update(values, scroll_step); } -void Control::Ruler::update(wxWindow* win, const std::vector& values, double scroll_step) +void Control::Ruler::set_parent(wxWindow* parent) { - if (values.empty()) + m_parent = parent; + update_dpi(); +} + +void Control::Ruler::update_dpi() +{ + if (m_parent) + m_DPI = GUI::get_dpi_for_window(m_parent); +} + +void Control::Ruler::update(const std::vector& values, double scroll_step) +{ + if (!m_parent || values.empty() || + // check if need to update ruler in respect to input values + values.front() == m_min_val && values.back() == m_max_val && m_scroll_step == scroll_step && max_values.size() == m_max_values_cnt) return; - int DPI = GUI::get_dpi_for_window(win); - int pixels_per_sm = lround((double)(DPI) * 5.0/25.4); + + m_min_val = values.front(); + m_max_val = values.back(); + m_scroll_step = scroll_step; + m_max_values_cnt = max_values.size(); + + int pixels_per_sm = lround((double)(m_DPI) * 5.0/25.4); if (lround(scroll_step) > pixels_per_sm) { long_step = -1.0; @@ -1091,11 +1137,11 @@ void Control::Ruler::update(wxWindow* win, const std::vector& values, do void Control::draw_ruler(wxDC& dc) { - if (m_values.empty()) + if (m_values.empty() || !m_ruler.can_draw()) return; // When "No sparce layer" is enabled, use m_layers_values for ruler update. // Because of m_values has duplicate values in this case. - m_ruler.update(this->GetParent(), m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); +// m_ruler.update(this->GetParent(), m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step()); int height, width; get_size(&width, &height); diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index e0f713d87..e4654d604 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -303,7 +303,7 @@ public: protected: void render(); - void draw_focus_rect(); + void draw_focus_rect(wxDC& dc); void draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end); void draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos); void draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection); @@ -438,19 +438,36 @@ private: wxPen GREY_PEN; wxPen LIGHT_GREY_PEN; + wxPen FOCUS_RECT_PEN; + wxBrush FOCUS_RECT_BRUSH; + std::vector m_line_pens; std::vector m_segm_pens; - struct Ruler { + class Ruler { + wxWindow* m_parent{nullptr}; // m_parent is nullptr for Unused ruler + // in this case we will not init/update/render it + // values to check if ruler has to be updated + double m_min_val; + double m_max_val; + double m_scroll_step; + size_t m_max_values_cnt; + int m_DPI; + + public: + double long_step; double short_step; std::vector max_values;// max value for each object/instance in sequence print // > 1 for sequential print - void init(const std::vector& values); - void update(wxWindow* win, const std::vector& values, double scroll_step); + void set_parent(wxWindow* parent); + void update_dpi(); + void init(const std::vector& values, double scroll_step); + void update(const std::vector& values, double scroll_step); bool is_ok() { return long_step > 0 && short_step > 0; } size_t count() { return max_values.size(); } + bool can_draw() { return m_parent != nullptr; } } m_ruler; }; From 3bf704932af693c5e47b93ed1811223ab5445b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 4 Mar 2022 19:10:50 +0100 Subject: [PATCH 11/13] Ignore CLion IDE files. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e3a9db477..c4df3f3f8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ local-lib build-linux/* deps/build-linux/* **/.DS_Store +/.idea/ From 6c51e5148c0fca15c869d344e081aad249b0244f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 7 Mar 2022 10:48:17 +0100 Subject: [PATCH 12/13] Fix of #7994 (Travel very close to the inner holes, could cross external perimeter when the avoid crossing perimeters was enabled.) --- .../GCode/AvoidCrossingPerimeters.cpp | 91 ++++++++++++------- .../GCode/AvoidCrossingPerimeters.hpp | 5 +- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp index f846d8cec..9edb35ee8 100644 --- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp +++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp @@ -13,6 +13,8 @@ #include #include +//#define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT + namespace Slic3r { struct TravelPoint @@ -354,8 +356,6 @@ static Polyline to_polyline(const std::vector &travel) return result; } -// #define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT - #ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT static void export_travel_to_svg(const Polygons &boundary, const Line &original_travel, @@ -521,6 +521,25 @@ static float get_perimeter_spacing_external(const Layer &layer) return perimeter_spacing; } +// Returns average perimeter width calculated from all LayerRegion within the layer. +static float get_external_perimeter_width(const Layer &layer) +{ + size_t regions_count = 0; + float perimeter_width = 0.f; + for (const LayerRegion *layer_region : layer.regions()) + if (layer_region != nullptr && !layer_region->slices.empty()) { + perimeter_width += float(layer_region->flow(frExternalPerimeter).scaled_width()); + ++regions_count; + } + + assert(perimeter_width >= 0.f); + if (regions_count != 0) + perimeter_width /= float(regions_count); + else + perimeter_width = get_default_perimeter_spacing(*layer.object()); + return perimeter_width; +} + // Called by avoid_perimeters() and by simplify_travel_heuristics(). static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &boundary, const Point &start, @@ -659,22 +678,22 @@ static size_t avoid_perimeters(const AvoidCrossingPerimeters::Boundary &boundary // Check if anyone of ExPolygons contains whole travel. // called by need_wipe() and AvoidCrossingPerimeters::travel_to() // FIXME Lukas H.: Maybe similar approach could also be used for ExPolygon::contains() -static bool any_expolygon_contains(const ExPolygons &ex_polygons, - const std::vector &ex_polygons_bboxes, - const EdgeGrid::Grid &grid_lslice, +static bool any_expolygon_contains(const ExPolygons &lslices_offset, + const std::vector &lslices_offset_bboxes, + const EdgeGrid::Grid &grid_lslices_offset, const Line &travel) { - assert(ex_polygons.size() == ex_polygons_bboxes.size()); - if(!grid_lslice.bbox().contains(travel.a) || !grid_lslice.bbox().contains(travel.b)) + assert(lslices_offset.size() == lslices_offset_bboxes.size()); + if(!grid_lslices_offset.bbox().contains(travel.a) || !grid_lslices_offset.bbox().contains(travel.b)) return false; - FirstIntersectionVisitor visitor(grid_lslice); + FirstIntersectionVisitor visitor(grid_lslices_offset); visitor.pt_current = &travel.a; visitor.pt_next = &travel.b; - grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor); + grid_lslices_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor); if (!visitor.intersect) { - for (const ExPolygon &ex_polygon : ex_polygons) { - const BoundingBox &bbox = ex_polygons_bboxes[&ex_polygon - &ex_polygons.front()]; + for (const ExPolygon &ex_polygon : lslices_offset) { + const BoundingBox &bbox = lslices_offset_bboxes[&ex_polygon - &lslices_offset.front()]; if (bbox.contains(travel.a) && bbox.contains(travel.b) && ex_polygon.contains(travel.a)) return true; } @@ -684,18 +703,18 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons, // Check if anyone of ExPolygons contains whole travel. // called by need_wipe() -static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice, const Polyline &travel) +static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice_offset, const Polyline &travel) { assert(ex_polygons.size() == ex_polygons_bboxes.size()); - if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice](const Point &point) { return !grid_lslice.bbox().contains(point); })) + if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice_offset](const Point &point) { return !grid_lslice_offset.bbox().contains(point); })) return false; - FirstIntersectionVisitor visitor(grid_lslice); + FirstIntersectionVisitor visitor(grid_lslice_offset); bool any_intersection = false; for (size_t line_idx = 1; line_idx < travel.size(); ++line_idx) { visitor.pt_current = &travel.points[line_idx - 1]; visitor.pt_next = &travel.points[line_idx]; - grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor); + grid_lslice_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor); any_intersection = visitor.intersect; if (any_intersection) break; } @@ -711,14 +730,14 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vec return false; } -static bool need_wipe(const GCode &gcodegen, - const EdgeGrid::Grid &grid_lslice, - const Line &original_travel, - const Polyline &result_travel, - const size_t intersection_count) +static bool need_wipe(const GCode &gcodegen, + const ExPolygons &lslices_offset, + const std::vector &lslices_offset_bboxes, + const EdgeGrid::Grid &grid_lslices_offset, + const Line &original_travel, + const Polyline &result_travel, + const size_t intersection_count) { - const ExPolygons &lslices = gcodegen.layer()->lslices; - const std::vector &lslices_bboxes = gcodegen.layer()->lslices_bboxes; bool z_lift_enabled = gcodegen.config().retract_lift.get_at(gcodegen.writer().extruder()->id()) > 0.; bool wipe_needed = false; @@ -728,16 +747,16 @@ static bool need_wipe(const GCode &gcodegen, // The original layer is intersected with defined boundaries. Then it is necessary to make a detailed test. // If the z-lift is enabled, then a wipe is needed when the original travel leads above the holes. if (z_lift_enabled) { - if (any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, original_travel)) { + if (any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, original_travel)) { // Check if original_travel and result_travel are not same. // If both are the same, then it is possible to skip testing of result_travel wipe_needed = !(result_travel.size() > 2 && result_travel.first_point() == original_travel.a && result_travel.last_point() == original_travel.b) && - !any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel); + !any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel); } else { wipe_needed = true; } } else { - wipe_needed = !any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel); + wipe_needed = !any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel); } } @@ -1163,10 +1182,8 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point & Vec2d startf = start.cast(); Vec2d endf = end .cast(); - const ExPolygons &lslices = gcodegen.layer()->lslices; - const std::vector &lslices_bboxes = gcodegen.layer()->lslices_bboxes; - bool is_support_layer = dynamic_cast(gcodegen.layer()) != nullptr; - if (!use_external && (is_support_layer || (!lslices.empty() && !any_expolygon_contains(lslices, lslices_bboxes, m_grid_lslice, travel)))) { + bool is_support_layer = dynamic_cast(gcodegen.layer()) != nullptr; + if (!use_external && (is_support_layer || (!m_lslices_offset.empty() && !any_expolygon_contains(m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel)))) { // Initialize m_internal only when it is necessary. if (m_internal.boundaries.empty()) init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer()))); @@ -1216,7 +1233,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point & } else if (max_detour_length_exceeded) { *could_be_wipe_disabled = false; } else - *could_be_wipe_disabled = !need_wipe(gcodegen, m_grid_lslice, travel, result_pl, travel_intersection_count); + *could_be_wipe_disabled = !need_wipe(gcodegen, m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel, result_pl, travel_intersection_count); return result_pl; } @@ -1227,13 +1244,21 @@ void AvoidCrossingPerimeters::init_layer(const Layer &layer) { m_internal.clear(); m_external.clear(); + m_lslices_offset.clear(); + m_lslices_offset_bboxes.clear(); + + float perimeter_offset = -get_external_perimeter_width(layer) / float(2.); + m_lslices_offset = offset_ex(layer.lslices, perimeter_offset); + + m_lslices_offset_bboxes.reserve(m_lslices_offset.size()); + for (const ExPolygon &ex_poly : m_lslices_offset) + m_lslices_offset_bboxes.emplace_back(get_extents(ex_poly)); BoundingBox bbox_slice(get_extents(layer.lslices)); bbox_slice.offset(SCALED_EPSILON); - m_grid_lslice.set_bbox(bbox_slice); - //FIXME 1mm grid? - m_grid_lslice.create(layer.lslices, coord_t(scale_(1.))); + m_grid_lslices_offset.set_bbox(bbox_slice); + m_grid_lslices_offset.create(m_lslices_offset, coord_t(scale_(1.))); } #if 0 diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.hpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.hpp index 412822c66..eb81c7972 100644 --- a/src/libslic3r/GCode/AvoidCrossingPerimeters.hpp +++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.hpp @@ -58,8 +58,11 @@ private: // we enable it by default for the first travel move in print bool m_disabled_once { true }; + // Lslices offseted by half an external perimeter width. Used for detection if line or polyline is inside of any polygon. + ExPolygons m_lslices_offset; + std::vector m_lslices_offset_bboxes; // Used for detection of line or polyline is inside of any polygon. - EdgeGrid::Grid m_grid_lslice; + EdgeGrid::Grid m_grid_lslices_offset; // Store all needed data for travels inside object Boundary m_internal; // Store all needed data for travels outside object From 8d3f4e633ee068184b1508cb022a03a657cfb4b7 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Mon, 7 Mar 2022 15:06:43 +0100 Subject: [PATCH 13/13] Added Ender 3 Pro thumbnail --- .../profiles/Creality/ENDER3PRO_thumbnail.png | Bin 0 -> 27678 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/profiles/Creality/ENDER3PRO_thumbnail.png diff --git a/resources/profiles/Creality/ENDER3PRO_thumbnail.png b/resources/profiles/Creality/ENDER3PRO_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..68ed43b7f1adc4bc6125f70b4031f561bd7115e2 GIT binary patch literal 27678 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 literal 0 HcmV?d00001