diff --git a/deps/wxWidgets/wxWidgets.cmake b/deps/wxWidgets/wxWidgets.cmake index c993d89487..73d841014d 100644 --- a/deps/wxWidgets/wxWidgets.cmake +++ b/deps/wxWidgets/wxWidgets.cmake @@ -13,7 +13,7 @@ prusaslicer_add_cmake_project(wxWidgets # GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" # GIT_TAG tm_cross_compile #${_wx_git_tag} URL https://github.com/prusa3d/wxWidgets/archive/refs/heads/v3.1.4-patched.zip - URL_HASH SHA256=21ed12eb5c215b00999f0374af652be0a6f785df10d18d0dfec8d81ed4abaea3 + URL_HASH SHA256=ed36a2159c781cce07b06378664e683ebd8cb2f51914aba9acd3bfca3d63d7d3 DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} dep_TIFF dep_JPEG CMAKE_ARGS -DwxBUILD_PRECOMP=ON diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 2d4780d0ec..f5902f403e 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -740,11 +740,7 @@ ConfigSubstitutions ConfigBase::load(const boost::property_tree::ptree &tree, Fo } // Load the config keys from the given string. -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT size_t ConfigBase::load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions) -#else -static inline size_t load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions) -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT { if (str == nullptr) return 0; diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 429f5901c8..b8a838f0d5 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -2017,9 +2017,7 @@ public: // Set all the nullable values to nils. void null_nullables(); -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT static size_t load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions); -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT private: // Set a configuration value from a string. diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 3271e2c384..0e44cc14ea 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -2710,16 +2710,10 @@ namespace Slic3r { bool _3MF_Exporter::_add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items) { -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED // This happens for empty projects -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED if (build_items.size() == 0) { add_error("No build item found"); -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED return true; -#else - return false; -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } stream << " <" << BUILD_TAG << ">\n"; diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 30f7d72fa3..ff4831a6cb 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -759,9 +759,7 @@ const std::vector> GCodeProces { EProducer::PrusaSlicer, "generated by PrusaSlicer" }, { EProducer::Slic3rPE, "generated by Slic3r Prusa Edition" }, { EProducer::Slic3r, "generated by Slic3r" }, -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT { EProducer::SuperSlicer, "generated by SuperSlicer" }, -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT { EProducer::Cura, "Cura_SteamEngine" }, { EProducer::Simplify3D, "G-Code generated by Simplify3D(R)" }, { EProducer::CraftWare, "CraftWare" }, @@ -824,9 +822,7 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i } GCodeProcessor::GCodeProcessor() -#if ENABLE_FIX_PREVIEW_OPTIONS_Z : m_options_z_corrector(m_result) -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z { reset(); m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n"; @@ -1190,9 +1186,7 @@ void GCodeProcessor::reset() m_use_volumetric_e = false; m_last_default_color_id = 0; -#if ENABLE_FIX_PREVIEW_OPTIONS_Z m_options_z_corrector.reset(); -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_mm3_per_mm_compare.reset(); @@ -1249,10 +1243,8 @@ void GCodeProcessor::process_file(const std::string& filename, std::function> GCodeProcessor::get_roles_time(Prin return ret; } -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT ConfigSubstitutions load_from_superslicer_gcode_file(const std::string& filename, DynamicPrintConfig& config, ForwardCompatibilitySubstitutionRule compatibility_rule) { // for reference, see: ConfigBase::load_from_gcode_file() @@ -1431,7 +1422,6 @@ void GCodeProcessor::apply_config_superslicer(const std::string& filename) load_from_superslicer_gcode_file(filename, config, ForwardCompatibilitySubstitutionRule::EnableSilent); apply_config(config); } -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT std::vector GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const { @@ -1868,9 +1858,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers store_move_vertex(EMoveType::Color_change); CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::ColorChange, extruder_id + 1, color, "" }; m_result.custom_gcode_per_print_z.emplace_back(item); -#if ENABLE_FIX_PREVIEW_OPTIONS_Z m_options_z_corrector.set(); -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z process_custom_gcode_time(CustomGCode::ColorChange); process_filaments(CustomGCode::ColorChange); } @@ -1883,9 +1871,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers store_move_vertex(EMoveType::Pause_Print); CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::PausePrint, m_extruder_id + 1, "", "" }; m_result.custom_gcode_per_print_z.emplace_back(item); -#if ENABLE_FIX_PREVIEW_OPTIONS_Z m_options_z_corrector.set(); -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z process_custom_gcode_time(CustomGCode::PausePrint); return; } @@ -1895,9 +1881,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers store_move_vertex(EMoveType::Custom_GCode); CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::Custom, m_extruder_id + 1, "", "" }; m_result.custom_gcode_per_print_z.emplace_back(item); -#if ENABLE_FIX_PREVIEW_OPTIONS_Z m_options_z_corrector.set(); -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z return; } @@ -1923,9 +1907,7 @@ bool GCodeProcessor::process_producers_tags(const std::string_view comment) { case EProducer::Slic3rPE: case EProducer::Slic3r: -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT case EProducer::SuperSlicer: -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT case EProducer::PrusaSlicer: { return process_prusaslicer_tags(comment); } case EProducer::Cura: { return process_cura_tags(comment); } case EProducer::Simplify3D: { return process_simplify3d_tags(comment); } @@ -2478,12 +2460,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (m_forced_height > 0.0f) m_height = m_forced_height; else { - if (m_end_position[Z] > m_extruded_last_z + EPSILON) { + if (m_end_position[Z] > m_extruded_last_z + EPSILON) m_height = m_end_position[Z] - m_extruded_last_z; -#if !ENABLE_FIX_PREVIEW_OPTIONS_Z - m_extruded_last_z = m_end_position[Z]; -#endif // !ENABLE_FIX_PREVIEW_OPTIONS_Z - } } if (m_height == 0.0f) @@ -2492,10 +2470,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (m_end_position[Z] == 0.0f) m_end_position[Z] = m_height; -#if ENABLE_FIX_PREVIEW_OPTIONS_Z m_extruded_last_z = m_end_position[Z]; m_options_z_corrector.update(m_height); -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_height_compare.update(m_height, m_extrusion_role); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index da1a696c0c..7377fca610 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -398,7 +398,6 @@ namespace Slic3r { bool has_first_vertex() const { return m_first_vertex.has_value(); } }; -#if ENABLE_FIX_PREVIEW_OPTIONS_Z // Helper class used to fix the z for color change, pause print and // custom gcode markes class OptionsZCorrector @@ -435,7 +434,6 @@ namespace Slic3r { m_custom_gcode_per_print_z_id.reset(); } }; -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_GCODE_VIEWER_DATA_CHECKING struct DataChecker @@ -541,9 +539,7 @@ namespace Slic3r { CpColor m_cp_color; bool m_use_volumetric_e; SeamsDetector m_seams_detector; -#if ENABLE_FIX_PREVIEW_OPTIONS_Z OptionsZCorrector m_options_z_corrector; -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z size_t m_last_default_color_id; #if ENABLE_GCODE_VIEWER_STATISTICS std::chrono::time_point m_start_time; @@ -555,9 +551,7 @@ namespace Slic3r { PrusaSlicer, Slic3rPE, Slic3r, -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT SuperSlicer, -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT Cura, Simplify3D, CraftWare, @@ -618,9 +612,7 @@ namespace Slic3r { private: void apply_config(const DynamicPrintConfig& config); void apply_config_simplify3d(const std::string& filename); -#if ENABLE_FIX_SUPERSLICER_GCODE_IMPORT void apply_config_superslicer(const std::string& filename); -#endif // ENABLE_FIX_SUPERSLICER_GCODE_IMPORT void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled); // Process tags embedded into comments diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index b900a62984..efc66f4781 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -160,13 +160,7 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig if (!result) throw Slic3r::RuntimeError("Loading of a model file failed."); -#if !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED - if (model.objects.empty()) - throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty"); -#endif // !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED - - for (ModelObject *o : model.objects) - { + for (ModelObject *o : model.objects) { // if (boost::algorithm::iends_with(input_file, ".zip.amf")) // { // // we remove the .zip part of the extension to avoid it be added to filenames when exporting diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index c1878bd87b..34e3129d98 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -920,7 +920,7 @@ static PrintObjectRegions* generate_print_object_regions( const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id]; const ModelVolume &parent_volume = *parent_region.model_volume; if (parent_volume.is_model_part() || parent_volume.is_modifier()) - if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox)) + if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox)) { // Only create new region for a modifier, which actually modifies config of it's parent. if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders); config != parent_region.region->config()) { @@ -928,6 +928,7 @@ static PrintObjectRegions* generate_print_object_regions( layer_range.volume_regions.push_back({ &volume, parent_region_id, get_create_region(std::move(config)), bbox }); } else if (parent_model_part_id == -1 && parent_volume.is_model_part()) parent_model_part_id = parent_region_id; + } } if (! added && parent_model_part_id >= 0) // This modifier does not override any printable volume's configuration, however it may in the future. diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 2e0e2ff18b..7af71fe309 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -72,7 +72,8 @@ static t_config_enum_values s_keys_map_PrintHostType { { "duet", htDuet }, { "flashair", htFlashAir }, { "astrobox", htAstroBox }, - { "repetier", htRepetier } + { "repetier", htRepetier }, + { "mks", htMKS } }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType) @@ -1854,12 +1855,14 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("flashair"); def->enum_values.push_back("astrobox"); def->enum_values.push_back("repetier"); + def->enum_values.push_back("mks"); def->enum_labels.push_back("PrusaLink"); def->enum_labels.push_back("OctoPrint"); def->enum_labels.push_back("Duet"); def->enum_labels.push_back("FlashAir"); def->enum_labels.push_back("AstroBox"); def->enum_labels.push_back("Repetier"); + def->enum_labels.push_back("MKS"); def->mode = comAdvanced; def->cli = ConfigOptionDef::nocli; def->set_default_value(new ConfigOptionEnum(htOctoPrint)); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 68dbd68d35..657f34ad14 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -44,7 +44,7 @@ enum class MachineLimitsUsage { }; enum PrintHostType { - htPrusaLink, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier + htPrusaLink, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS }; enum AuthorizationType { diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 84b2129389..4b91714e58 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -379,11 +379,7 @@ static std::vector> slices_to_regions( int j = i; bool merged = false; ExPolygons &expolygons = temp_slices[i].expolygons; - for (++ j; - j < int(temp_slices.size()) && - temp_slices[i].region_id == temp_slices[j].region_id && - (clip_multipart_objects || temp_slices[i].volume_id == temp_slices[j].volume_id); - ++ j) + for (++ j; j < int(temp_slices.size()) && temp_slices[i].region_id == temp_slices[j].region_id; ++ j) if (ExPolygons &expolygons2 = temp_slices[j].expolygons; ! expolygons2.empty()) { if (expolygons.empty()) { expolygons = std::move(expolygons2); @@ -392,7 +388,10 @@ static std::vector> slices_to_regions( merged = true; } } - if (merged) + // Don't unite the regions if ! clip_multipart_objects. In that case it is user's responsibility + // to handle region overlaps. Indeed, one may intentionally let the regions overlap to produce crossing perimeters + // for example. + if (merged && clip_multipart_objects) expolygons = closing_ex(expolygons, float(scale_(EPSILON))); slices_by_region[temp_slices[i].region_id][z_idx] = std::move(expolygons); i = j; diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 7ef289757d..9eb83eea1b 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -2354,8 +2354,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta Polygons &layer_support_area = layer_support_areas[layer_id]; Polygons *layer_buildplate_covered = buildplate_covered.empty() ? nullptr : &buildplate_covered[layer_id]; // Filtering the propagated support columns to two extrusions, overlapping by maximum 20%. - float column_propagation_filtering_radius = scaled(0.8 * 0.5 * (m_support_params.support_material_flow.spacing() + m_support_params.support_material_flow.width())); - task_group.run([&grid_params, &overhangs_projection, &overhangs_projection_raw, &layer, &layer_support_area, layer_buildplate_covered, column_propagation_filtering_radius +// float column_propagation_filtering_radius = scaled(0.8 * 0.5 * (m_support_params.support_material_flow.spacing() + m_support_params.support_material_flow.width())); + task_group.run([&grid_params, &overhangs_projection, &overhangs_projection_raw, &layer, &layer_support_area, layer_buildplate_covered /* , column_propagation_filtering_radius */ #ifdef SLIC3R_DEBUG , iRun, layer_id #endif /* SLIC3R_DEBUG */ diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index b17da416d5..6a26eb7e20 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -36,43 +36,6 @@ #define ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS 1 -//==================== -// 2.4.0.alpha1 techs -//==================== -#define ENABLE_2_4_0_ALPHA1 1 - -// Enable implementation of retract acceleration in gcode processor -#define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA1) -// Enable rendering seams (and other options) in preview using models -#define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA1) -// Enable save and save as commands to be enabled also when the plater is empty and allow to load empty projects -#define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA1) - - -//==================== -// 2.4.0.alpha2 techs -//==================== -#define ENABLE_2_4_0_ALPHA2 1 - -// Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 -#define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) -// Enable fixing the z position of color change, pause print and custom gcode markers in preview -#define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) -// Enable replacing a missing file during reload from disk command -#define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2) -// Enable fixing the synchronization of seams with the horizontal slider in preview -#define ENABLE_FIX_SEAMS_SYNCH (1 && ENABLE_2_4_0_ALPHA2) - - -//==================== -// 2.4.0.alpha3 techs -//==================== -#define ENABLE_2_4_0_ALPHA3 1 - -// Enable fixing loading of gcode files generated with SuperSlicer in GCodeViewer -#define ENABLE_FIX_SUPERSLICER_GCODE_IMPORT (1 && ENABLE_2_4_0_ALPHA3) - - //==================== // 2.4.0.beta1 techs //==================== @@ -109,4 +72,5 @@ // Enable showing time estimate for travel moves in legend #define ENABLE_TRAVEL_TIME (1 && ENABLE_2_4_0_RC) + #endif // _prusaslicer_technologies_h_ diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 5eafd68842..93a09a0d98 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -1090,7 +1090,7 @@ indexed_triangle_set its_convex_hull(const std::vector &pts) centroid += pt; centroid /= float(pts.size()); #endif // NDEBUG - for (const orgQhull::QhullFacet facet : qhull.facetList()) { + for (const orgQhull::QhullFacet &facet : qhull.facetList()) { // Collect face vertices first, allocate unique vertices in dst_vertices based on QHull's vertex ID. Vec3i indices; int cnt = 0; diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index 05936f1394..ae917756b0 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -560,9 +560,9 @@ void slice_facet_with_slabs( // Save the open edge for sure. type = FacetSliceType::Slicing; } else { +#ifndef NDEBUG const stl_triangle_vertex_indices &neighbor = mesh_triangles[neighbor_idx]; float z = *it; -#ifndef NDEBUG int num_on_plane = (mesh_vertices[neighbor(0)].z() == z) + (mesh_vertices[neighbor(1)].z() == z) + (mesh_vertices[neighbor(2)].z() == z); assert(num_on_plane == 2 || num_on_plane == 3); #endif // NDEBUG diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index f0c2338e9d..34cc980513 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -237,6 +237,10 @@ set(SLIC3R_GUI_SOURCES Utils/UndoRedo.hpp Utils/HexFile.cpp Utils/HexFile.hpp + Utils/TCPConsole.cpp + Utils/TCPConsole.hpp + Utils/MKS.cpp + Utils/MKS.hpp ) if (APPLE) @@ -250,7 +254,6 @@ if (APPLE) GUI/InstanceCheckMac.h ) FIND_LIBRARY(DISKARBITRATION_LIBRARY DiskArbitration) - endif () add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES}) @@ -259,8 +262,12 @@ encoding_check(libslic3r_gui) target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES}) -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") +if (MSVC) + target_link_libraries(libslic3r_gui Setupapi.lib) +elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_libraries(libslic3r_gui ${DBUS_LIBRARIES}) +elseif (APPLE) + target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY}) endif() if (SLIC3R_STATIC) @@ -269,10 +276,6 @@ if (SLIC3R_STATIC) target_compile_definitions(libslic3r_gui PUBLIC -DwxDEBUG_LEVEL=0) endif() -if(APPLE) - target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY}) -endif() - if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_CURL AND UNIX AND NOT APPLE) target_compile_definitions(libslic3r_gui PRIVATE OPENSSL_CERT_OVERRIDE) endif () diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index 8f88de4726..e0f713d879 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -115,7 +115,7 @@ class TickCodeInfo bool m_suppress_plus = false; bool m_suppress_minus = false; bool m_use_default_colors= false; - int m_default_color_idx = 0; +// int m_default_color_idx = 0; std::vector* m_colors {nullptr}; diff --git a/src/slic3r/GUI/ExtraRenderers.cpp b/src/slic3r/GUI/ExtraRenderers.cpp index 874df1b4ab..d72e1dd328 100644 --- a/src/slic3r/GUI/ExtraRenderers.cpp +++ b/src/slic3r/GUI/ExtraRenderers.cpp @@ -223,7 +223,8 @@ bool BitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value if (!text_editor || text_editor->GetValue().IsEmpty()) return false; - if (m_was_unusable_symbol = Slic3r::GUI::Plater::has_illegal_filename_characters(text_editor->GetValue())) + m_was_unusable_symbol = Slic3r::GUI::Plater::has_illegal_filename_characters(text_editor->GetValue()); + if (m_was_unusable_symbol) return false; // The icon can't be edited so get its old value and reuse it. diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index ea4b72cf17..03b1b5ff32 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -89,7 +89,6 @@ void GCodeViewer::VBuffer::reset() count = 0; } -#if ENABLE_SEAMS_USING_MODELS void GCodeViewer::InstanceVBuffer::Ranges::reset() { for (Range& range : ranges) { @@ -107,7 +106,6 @@ void GCodeViewer::InstanceVBuffer::reset() buffer.clear(); render_ranges.reset(); } -#endif // ENABLE_SEAMS_USING_MODELS void GCodeViewer::IBuffer::reset() { @@ -150,12 +148,10 @@ bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex& move) co } } -#if ENABLE_SEAMS_USING_MODELS void GCodeViewer::TBuffer::Model::reset() { instances.reset(); } -#endif // ENABLE_SEAMS_USING_MODELS void GCodeViewer::TBuffer::reset() { @@ -167,9 +163,7 @@ void GCodeViewer::TBuffer::reset() indices.clear(); paths.clear(); render_paths.clear(); -#if ENABLE_SEAMS_USING_MODELS model.reset(); -#endif // ENABLE_SEAMS_USING_MODELS } void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id) @@ -297,12 +291,8 @@ void GCodeViewer::SequentialView::Marker::render() const imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Tool position") + ":"); ImGui::SameLine(); char buf[1024]; -#if ENABLE_FIX_SEAMS_SYNCH const Vec3f position = m_world_position + m_world_offset; sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", position.x(), position.y(), position.z()); -#else - sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", m_world_position.x(), m_world_position.y(), m_world_position.z()); -#endif // ENABLE_FIX_SEAMS_SYNCH imgui.text(std::string(buf)); // force extra frame to automatically update window size @@ -594,48 +584,11 @@ const GCodeViewer::Color GCodeViewer::Neutral_Color = { 0.25f, 0.25f, 0.25f, 1.0 GCodeViewer::GCodeViewer() { -#if !ENABLE_SEAMS_USING_MODELS - // initializes non OpenGL data of TBuffers - // OpenGL data are initialized into render().init_gl_data() - for (size_t i = 0; i < m_buffers.size(); ++i) { - TBuffer& buffer = m_buffers[i]; - switch (buffer_type(i)) - { - default: { break; } - case EMoveType::Tool_change: - case EMoveType::Color_change: - case EMoveType::Pause_Print: - case EMoveType::Custom_GCode: - case EMoveType::Retract: - case EMoveType::Unretract: - case EMoveType::Seam: { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; - buffer.vertices.format = VBuffer::EFormat::Position; - break; - } - case EMoveType::Wipe: - case EMoveType::Extrude: { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; - buffer.vertices.format = VBuffer::EFormat::PositionNormal3; - break; - } - case EMoveType::Travel: { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; - buffer.vertices.format = VBuffer::EFormat::PositionNormal1; - break; - } - } - } - - set_toolpath_move_type_visible(EMoveType::Extrude, true); -#endif // !ENABLE_SEAMS_USING_MODELS - m_extrusions.reset_role_visibility_flags(); // m_sequential_view.skip_invisible_moves = true; } -#if ENABLE_SEAMS_USING_MODELS void GCodeViewer::init() { if (m_gl_data_initialized) @@ -655,7 +608,6 @@ void GCodeViewer::init() case EMoveType::Retract: case EMoveType::Unretract: case EMoveType::Seam: { -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; buffer.shader = "gouraud_light_instanced"; @@ -673,20 +625,6 @@ void GCodeViewer::init() buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; } break; -#else - if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; - buffer.shader = "gouraud_light_instanced"; - buffer.model.model.init_from(diamond(16)); - buffer.model.color = option_color(type); - } - else { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; - buffer.vertices.format = VBuffer::EFormat::Position; - buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; - } - break; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS } case EMoveType::Wipe: case EMoveType::Extrude: { @@ -716,7 +654,6 @@ void GCodeViewer::init() m_gl_data_initialized = true; } -#endif // ENABLE_SEAMS_USING_MODELS void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& print, bool initialized) { @@ -932,72 +869,11 @@ void GCodeViewer::reset() void GCodeViewer::render() { -#if !ENABLE_SEAMS_USING_MODELS - auto init_gl_data = [this]() { - // initializes opengl data of TBuffers - for (size_t i = 0; i < m_buffers.size(); ++i) { - TBuffer& buffer = m_buffers[i]; - EMoveType type = buffer_type(i); - switch (type) - { - default: { break; } - case EMoveType::Tool_change: - case EMoveType::Color_change: - case EMoveType::Pause_Print: - case EMoveType::Custom_GCode: - case EMoveType::Retract: - case EMoveType::Unretract: - case EMoveType::Seam: { - if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; - buffer.shader = "gouraud_light_instanced"; - buffer.model.model.init_from(diamond(16)); - buffer.model.color = option_color(type); - } - else { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; - buffer.vertices.format = VBuffer::EFormat::Position; - buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; - } - break; - } - case EMoveType::Wipe: - case EMoveType::Extrude: { - buffer.shader = "gouraud_light"; - break; - } - case EMoveType::Travel: { - buffer.shader = "toolpaths_lines"; - break; - } - } - } - - // initializes tool marker - m_sequential_view.marker.init(); - - // initializes point sizes - std::array point_sizes; - ::glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_sizes.data()); - m_detected_point_sizes = { static_cast(point_sizes[0]), static_cast(point_sizes[1]) }; - m_gl_data_initialized = true; - }; -#endif // !ENABLE_SEAMS_USING_MODELS - #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.reset_opengl(); -#if ENABLE_SEAMS_USING_MODELS m_statistics.total_instances_gpu_size = 0; -#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_GCODE_VIEWER_STATISTICS -#if !ENABLE_SEAMS_USING_MODELS - // OpenGL data must be initialized after the glContext has been created. - // This is ensured when this method is called by GLCanvas3D::_render_gcode(). - if (!m_gl_data_initialized) - init_gl_data(); -#endif // !ENABLE_SEAMS_USING_MODELS - if (m_roles.empty()) return; @@ -1008,9 +884,7 @@ void GCodeViewer::render() render_legend(legend_height); if (m_sequential_view.current.last != m_sequential_view.endpoints.last) { m_sequential_view.marker.set_world_position(m_sequential_view.current_position); -#if ENABLE_FIX_SEAMS_SYNCH m_sequential_view.marker.set_world_offset(m_sequential_view.current_offset); -#endif // ENABLE_FIX_SEAMS_SYNCH m_sequential_view.render(legend_height); } #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1558,7 +1432,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) sq_prev_length = sq_length; }; -#if ENABLE_SEAMS_USING_MODELS // format data into the buffers to be rendered as instanced model auto add_model_instance = [](const GCodeProcessorResult::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { // append position @@ -1574,7 +1447,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) instances_ids.push_back(move_id); }; -#if ENABLE_SEAMS_USING_BATCHED_MODELS // format data into the buffers to be rendered as batched model auto add_vertices_as_model_batch = [](const GCodeProcessorResult::MoveVertex& curr, const GLModel::InitializationData& data, VertexBuffer& vertices, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { const double width = static_cast(1.5f * curr.width); @@ -1615,8 +1487,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) } } }; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS auto start_time = std::chrono::high_resolution_clock::now(); @@ -1656,46 +1526,32 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) if (wxGetApp().is_editor()) m_contained_in_bed = wxGetApp().plater()->build_volume().all_paths_inside(gcode_result, m_paths_bounding_box); -#if ENABLE_FIX_SEAMS_SYNCH m_sequential_view.gcode_ids.clear(); for (size_t i = 0; i < gcode_result.moves.size(); ++i) { const GCodeProcessorResult::MoveVertex& move = gcode_result.moves[i]; if (move.type != EMoveType::Seam) m_sequential_view.gcode_ids.push_back(move.gcode_id); } -#else - for (const GCodeProcessorResult::MoveVertex& move : gcode_result.moves) { - m_sequential_view.gcode_ids.push_back(move.gcode_id); - } -#endif // ENABLE_FIX_SEAMS_SYNCH std::vector vertices(m_buffers.size()); std::vector indices(m_buffers.size()); -#if ENABLE_SEAMS_USING_MODELS std::vector instances(m_buffers.size()); std::vector instances_ids(m_buffers.size()); -#endif // ENABLE_SEAMS_USING_MODELS -#if ENABLE_FIX_SEAMS_SYNCH std::vector instances_offsets(m_buffers.size()); -#endif // ENABLE_FIX_SEAMS_SYNCH std::vector options_zs; -#if ENABLE_FIX_SEAMS_SYNCH size_t seams_count = 0; std::vector seams_ids; -#endif // ENABLE_FIX_SEAMS_SYNCH // toolpaths data -> extract vertices from result for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessorResult::MoveVertex& curr = gcode_result.moves[i]; -#if ENABLE_FIX_SEAMS_SYNCH if (curr.type == EMoveType::Seam) { ++seams_count; seams_ids.push_back(i); } size_t move_id = i - seams_count; -#endif // ENABLE_FIX_SEAMS_SYNCH // skip first vertex if (i == 0) @@ -1715,13 +1571,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) const unsigned char id = buffer_id(curr.type); TBuffer& t_buffer = m_buffers[id]; MultiVertexBuffer& v_multibuffer = vertices[id]; -#if ENABLE_SEAMS_USING_MODELS InstanceBuffer& inst_buffer = instances[id]; InstanceIdBuffer& inst_id_buffer = instances_ids[id]; -#if ENABLE_FIX_SEAMS_SYNCH InstancesOffsets& inst_offsets = instances_offsets[id]; -#endif // ENABLE_FIX_SEAMS_SYNCH -#endif // ENABLE_SEAMS_USING_MODELS // ensure there is at least one vertex buffer if (v_multibuffer.empty()) @@ -1729,21 +1581,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // add another vertex buffer -#if ENABLE_SEAMS_USING_BATCHED_MODELS size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { -#else - if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS v_multibuffer.push_back(VertexBuffer()); if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { Path& last_path = t_buffer.paths.back(); if (prev.type == curr.type && last_path.matches(curr)) -#if ENABLE_FIX_SEAMS_SYNCH last_path.add_sub_path(prev, static_cast(v_multibuffer.size()) - 1, 0, move_id - 1); -#else - last_path.add_sub_path(prev, static_cast(v_multibuffer.size()) - 1, 0, i - 1); -#endif // ENABLE_FIX_SEAMS_SYNCH } } @@ -1753,21 +1597,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) { case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } -#if ENABLE_FIX_SEAMS_SYNCH case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, move_id); break; } -#else - case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, i); break; } -#endif // ENABLE_FIX_SEAMS_SYNCH -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS case TBuffer::ERenderPrimitiveType::InstancedModel: { -#if ENABLE_FIX_SEAMS_SYNCH add_model_instance(curr, inst_buffer, inst_id_buffer, move_id); inst_offsets.push_back(prev.position - curr.position); -#else - add_model_instance(curr, inst_buffer, inst_id_buffer, i); -#endif // ENABLE_FIX_SEAMS_SYNCH #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.instances_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1775,32 +1609,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) } case TBuffer::ERenderPrimitiveType::BatchedModel: { -#if ENABLE_FIX_SEAMS_SYNCH add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, move_id); inst_offsets.push_back(prev.position - curr.position); -#else - add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i); -#endif // ENABLE_FIX_SEAMS_SYNCH #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.batched_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS break; } -#else - case TBuffer::ERenderPrimitiveType::Model: - { -#if ENABLE_FIX_SEAMS_SYNCH - add_model_instance(curr, inst_buffer, inst_id_buffer, move_id); -#else - add_model_instance(curr, inst_buffer, inst_id_buffer, i); -#endif // ENABLE_FIX_SEAMS_SYNCH -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.instances_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - break; - } -#endif // ENABLE_SEAMS_USING_MODELS -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS } // collect options zs for later use @@ -1812,11 +1627,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) } // smooth toolpaths corners for the given TBuffer using triangles -#if ENABLE_FIX_SEAMS_SYNCH auto smooth_triangle_toolpaths_corners = [&gcode_result, &seams_ids](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) { -#else - auto smooth_triangle_toolpaths_corners = [&gcode_result](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) { -#endif // ENABLE_FIX_SEAMS_SYNCH auto extract_position_at = [](const VertexBuffer& vertices, size_t offset) { return Vec3f(vertices[offset + 0], vertices[offset + 1], vertices[offset + 2]); }; @@ -1890,7 +1701,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) } }; -#if ENABLE_FIX_SEAMS_SYNCH auto extract_move_id = [&seams_ids](size_t id) { for (int i = seams_ids.size() - 1; i >= 0; --i) { if (seams_ids[i] < id + i + 1) @@ -1898,7 +1708,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) } return id; }; -#endif // ENABLE_FIX_SEAMS_SYNCH size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats(); for (const Path& path : t_buffer.paths) { @@ -1910,16 +1719,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) const float half_width = 0.5f * path.width; for (size_t j = 1; j < path_vertices_count - 1; ++j) { size_t curr_s_id = path.sub_paths.front().first.s_id + j; -#if ENABLE_FIX_SEAMS_SYNCH size_t move_id = extract_move_id(curr_s_id); const Vec3f& prev = gcode_result.moves[move_id - 1].position; const Vec3f& curr = gcode_result.moves[move_id].position; const Vec3f& next = gcode_result.moves[move_id + 1].position; -#else - const Vec3f& prev = gcode_result.moves[curr_s_id - 1].position; - const Vec3f& curr = gcode_result.moves[curr_s_id].position; - const Vec3f& next = gcode_result.moves[curr_s_id + 1].position; -#endif // ENABLE_FIX_SEAMS_SYNCH // select the subpaths which contains the previous/next segments if (!path.sub_paths[prev_sub_path_id].contains(curr_s_id)) @@ -1986,10 +1789,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) } } -#if ENABLE_FIX_SEAMS_SYNCH // dismiss, no more needed std::vector().swap(seams_ids); -#endif // ENABLE_FIX_SEAMS_SYNCH for (MultiVertexBuffer& v_multibuffer : vertices) { for (VertexBuffer& v_buffer : v_multibuffer) { @@ -2008,16 +1809,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // send vertices data to gpu, where needed for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { const InstanceBuffer& inst_buffer = instances[i]; if (!inst_buffer.empty()) { t_buffer.model.instances.buffer = inst_buffer; t_buffer.model.instances.s_ids = instances_ids[i]; -#if ENABLE_FIX_SEAMS_SYNCH t_buffer.model.instances.offsets = instances_offsets[i]; -#endif // ENABLE_FIX_SEAMS_SYNCH } } else { @@ -2026,25 +1823,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) if (!inst_buffer.empty()) { t_buffer.model.instances.buffer = inst_buffer; t_buffer.model.instances.s_ids = instances_ids[i]; -#if ENABLE_FIX_SEAMS_SYNCH t_buffer.model.instances.offsets = instances_offsets[i]; -#endif // ENABLE_FIX_SEAMS_SYNCH } } -#else - if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { - const InstanceBuffer& inst_buffer = instances[i]; - if (!inst_buffer.empty()) { - t_buffer.model.instances.buffer = inst_buffer; - t_buffer.model.instances.s_ids = instances_ids[i]; -#if ENABLE_FIX_SEAMS_SYNCH - t_buffer.model.instances.offsets = instances_offsets[i]; -#endif // ENABLE_FIX_SEAMS_SYNCH - } - } - else { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS const MultiVertexBuffer& v_multibuffer = vertices[i]; for (const VertexBuffer& v_buffer : v_multibuffer) { const size_t size_elements = v_buffer.size(); @@ -2067,9 +1848,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) t_buffer.vertices.vbos.push_back(static_cast(id)); t_buffer.vertices.sizes.push_back(size_bytes); } -#if ENABLE_SEAMS_USING_MODELS } -#endif // ENABLE_SEAMS_USING_MODELS } #if ENABLE_GCODE_VIEWER_STATISTICS @@ -2080,10 +1859,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // dismiss vertices data, no more needed std::vector().swap(vertices); -#if ENABLE_SEAMS_USING_MODELS std::vector().swap(instances); std::vector().swap(instances_ids); -#endif // ENABLE_SEAMS_USING_MODELS // toolpaths data -> extract indices from result // paths may have been filled while extracting vertices, @@ -2100,18 +1877,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) using VboIndexList = std::vector; std::vector vbo_indices(m_buffers.size()); -#if ENABLE_FIX_SEAMS_SYNCH seams_count = 0; -#endif // ENABLE_FIX_SEAMS_SYNCH for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessorResult::MoveVertex& curr = gcode_result.moves[i]; -#if ENABLE_FIX_SEAMS_SYNCH if (curr.type == EMoveType::Seam) ++seams_count; size_t move_id = i - seams_count; -#endif // ENABLE_FIX_SEAMS_SYNCH // skip first vertex if (i == 0) @@ -2139,63 +1912,37 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // ensure there is at least one index buffer if (i_multibuffer.empty()) { i_multibuffer.push_back(IndexBuffer()); -#if ENABLE_SEAMS_USING_MODELS if (!t_buffer.vertices.vbos.empty()) -#endif // ENABLE_SEAMS_USING_MODELS vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); } // if adding the indices for the current segment exceeds the threshold size of the current index buffer // create another index buffer -#if ENABLE_SEAMS_USING_BATCHED_MODELS size_t indiced_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.indices_size_bytes() : t_buffer.max_indices_per_segment_size_bytes(); if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - indiced_size_to_add) { -#else - if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.max_indices_per_segment_size_bytes()) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS i_multibuffer.push_back(IndexBuffer()); vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { -#else - if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); -#if ENABLE_FIX_SEAMS_SYNCH last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, move_id - 1); -#else - last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); -#endif // ENABLE_FIX_SEAMS_SYNCH } } // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // create another index buffer -#if ENABLE_SEAMS_USING_BATCHED_MODELS size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { -#else - if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS i_multibuffer.push_back(IndexBuffer()); ++curr_vertex_buffer.first; curr_vertex_buffer.second = 0; vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { -#else - if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); -#if ENABLE_FIX_SEAMS_SYNCH last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, move_id - 1); -#else - last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); -#endif // ENABLE_FIX_SEAMS_SYNCH } } @@ -2204,38 +1951,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) switch (t_buffer.render_primitive_type) { case TBuffer::ERenderPrimitiveType::Point: { -#if ENABLE_FIX_SEAMS_SYNCH add_indices_as_point(curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, move_id); -#else - add_indices_as_point(curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, i); -#endif // ENABLE_FIX_SEAMS_SYNCH curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); break; } case TBuffer::ERenderPrimitiveType::Line: { -#if ENABLE_FIX_SEAMS_SYNCH add_indices_as_line(prev, curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, move_id); -#else - add_indices_as_line(prev, curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, i); -#endif // ENABLE_FIX_SEAMS_SYNCH curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); break; } case TBuffer::ERenderPrimitiveType::Triangle: { -#if ENABLE_FIX_SEAMS_SYNCH add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, move_id); -#else - add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, i); -#endif // ENABLE_FIX_SEAMS_SYNCH break; } -#if ENABLE_SEAMS_USING_BATCHED_MODELS case TBuffer::ERenderPrimitiveType::BatchedModel: { add_indices_as_model_batch(t_buffer.model.data, i_buffer, curr_vertex_buffer.second); curr_vertex_buffer.second += t_buffer.model.data.vertices_count(); break; } -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS default: { break; } } } @@ -2249,13 +1982,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // toolpaths data -> send indices data to gpu for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel) { -#else - if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS const MultiIndexBuffer& i_multibuffer = indices[i]; for (const IndexBuffer& i_buffer : i_multibuffer) { const size_t size_elements = i_buffer.size(); @@ -2278,9 +2005,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_bytes, i_buffer.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } -#if ENABLE_SEAMS_USING_MODELS } -#endif // ENABLE_SEAMS_USING_MODELS } if (progress_dialog != nullptr) { @@ -2321,34 +2046,22 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // layers zs / roles / extruder ids -> extract from result size_t last_travel_s_id = 0; -#if ENABLE_FIX_SEAMS_SYNCH seams_count = 0; -#endif // ENABLE_FIX_SEAMS_SYNCH for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessorResult::MoveVertex& move = gcode_result.moves[i]; -#if ENABLE_FIX_SEAMS_SYNCH if (move.type == EMoveType::Seam) ++seams_count; size_t move_id = i - seams_count; -#endif // ENABLE_FIX_SEAMS_SYNCH if (move.type == EMoveType::Extrude) { // layers zs const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); const double z = static_cast(move.position.z()); if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) -#if ENABLE_FIX_SEAMS_SYNCH m_layers.append(z, { last_travel_s_id, move_id }); -#else - m_layers.append(z, { last_travel_s_id, i }); -#endif // ENABLE_FIX_SEAMS_SYNCH else -#if ENABLE_FIX_SEAMS_SYNCH m_layers.get_ranges().back().last = move_id; -#else - m_layers.get_ranges().back().last = i; -#endif // ENABLE_FIX_SEAMS_SYNCH // extruder ids m_extruder_ids.emplace_back(move.extruder_id); // roles @@ -2356,17 +2069,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) m_roles.emplace_back(move.extrusion_role); } else if (move.type == EMoveType::Travel) { -#if ENABLE_FIX_SEAMS_SYNCH if (move_id - last_travel_s_id > 1 && !m_layers.empty()) m_layers.get_ranges().back().last = move_id; last_travel_s_id = move_id; -#else - if (i - last_travel_s_id > 1 && !m_layers.empty()) - m_layers.get_ranges().back().last = i; - - last_travel_s_id = i; -#endif // ENABLE_FIX_SEAMS_SYNCH } } @@ -2551,9 +2257,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_GCODE_VIEWER_STATISTICS Statistics* statistics = const_cast(&m_statistics); statistics->render_paths_size = 0; -#if ENABLE_SEAMS_USING_MODELS statistics->models_instances_size = 0; -#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_GCODE_VIEWER_STATISTICS const bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; @@ -2574,13 +2278,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (!buffer.visible) continue; -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { -#else - if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t id : buffer.model.instances.s_ids) { if (id < m_layers.get_range_at(m_layers_z_range[0]).first || m_layers.get_range_at(m_layers_z_range[1]).last < id) continue; @@ -2598,7 +2297,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } } else { -#endif // ENABLE_SEAMS_USING_MODELS for (size_t i = 0; i < buffer.paths.size(); ++i) { const Path& path = buffer.paths[i]; if (path.type == EMoveType::Travel) { @@ -2632,9 +2330,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } } } -#if ENABLE_SEAMS_USING_MODELS } -#endif // ENABLE_SEAMS_USING_MODELS } // update current sequential position @@ -2644,30 +2340,21 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // get the world position from the vertex buffer bool found = false; for (const TBuffer& buffer : m_buffers) { -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { -#else - if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { size_t offset = i * buffer.model.instances.instance_size_floats(); sequential_view->current_position.x() = buffer.model.instances.buffer[offset + 0]; sequential_view->current_position.y() = buffer.model.instances.buffer[offset + 1]; sequential_view->current_position.z() = buffer.model.instances.buffer[offset + 2]; -#if ENABLE_FIX_SEAMS_SYNCH sequential_view->current_offset = buffer.model.instances.offsets[i]; -#endif // ENABLE_FIX_SEAMS_SYNCH - found = true; break; } } } else { -#endif // ENABLE_SEAMS_USING_MODELS // searches the path containing the current position for (const Path& path : buffer.paths) { if (path.contains(m_sequential_view.current.last)) { @@ -2699,18 +2386,13 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); -#if ENABLE_FIX_SEAMS_SYNCH sequential_view->current_offset = Vec3f::Zero(); -#endif // ENABLE_FIX_SEAMS_SYNCH - found = true; break; } } } -#if ENABLE_SEAMS_USING_MODELS } -#endif // ENABLE_SEAMS_USING_MODELS if (found) break; @@ -2817,20 +2499,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #endif } -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS // second pass: for buffers using instanced and batched models, update the instances render ranges -#else - // second pass: for buffers using instanced models, update the instances render ranges -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t b = 0; b < m_buffers.size(); ++b) { TBuffer& buffer = const_cast(m_buffers[b]); -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel && buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) -#else - if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS continue; buffer.model.instances.render_ranges.reset(); @@ -2846,11 +2519,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (m_sequential_view.current.first <= buffer.model.instances.s_ids.back() && buffer.model.instances.s_ids.front() <= m_sequential_view.current.last) { for (size_t id : buffer.model.instances.s_ids) { if (has_second_range) { -#if ENABLE_FIX_PREVIEW_OPTIONS_Z if (id < m_sequential_view.endpoints.first) { -#else - if (id <= m_sequential_view.endpoints.first) { -#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z ++buffer.model.instances.render_ranges.ranges.front().offset; if (id <= m_sequential_view.current.first) ++buffer.model.instances.render_ranges.ranges.back().offset; @@ -2873,14 +2542,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } } } -#endif // ENABLE_SEAMS_USING_MODELS // set sequential data to their final value sequential_view->endpoints = top_layer_only ? top_layer_endpoints : global_endpoints; sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, sequential_view->endpoints.first, sequential_view->endpoints.last) : sequential_view->endpoints.first; -#if ENABLE_SEAMS_USING_MODELS sequential_view->global = global_endpoints; -#endif // ENABLE_SEAMS_USING_MODELS // updates sequential range caps std::array* sequential_range_caps = const_cast*>(&m_sequential_range_caps); @@ -3002,11 +2668,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int); statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t); } -#if ENABLE_SEAMS_USING_MODELS statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.buffer, float); statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.s_ids, size_t); statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.render_ranges.ranges, InstanceVBuffer::Ranges::Range); -#endif // ENABLE_SEAMS_USING_MODELS } statistics->refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -3095,7 +2759,6 @@ void GCodeViewer::render_toolpaths() } }; -#if ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS auto render_as_instanced_model = [this] #else @@ -3121,7 +2784,6 @@ void GCodeViewer::render_toolpaths() } }; -#if ENABLE_SEAMS_USING_BATCHED_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { #else @@ -3179,8 +2841,6 @@ void GCodeViewer::render_toolpaths() buffer_range.first = buffer_range.last; } }; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS auto line_width = [](double zoom) { return (zoom < 5.0) ? 1.0 : (1.0 + 5.0 * (zoom - 5.0) / (100.0 - 5.0)); @@ -3190,11 +2850,7 @@ void GCodeViewer::render_toolpaths() unsigned char end_id = buffer_id(EMoveType::Count); for (unsigned char i = begin_id; i < end_id; ++i) { -#if ENABLE_SEAMS_USING_MODELS TBuffer& buffer = m_buffers[i]; -#else - const TBuffer& buffer = m_buffers[i]; -#endif // ENABLE_SEAMS_USING_MODELS if (!buffer.visible || !buffer.has_data()) continue; @@ -3202,25 +2858,17 @@ void GCodeViewer::render_toolpaths() if (shader != nullptr) { shader->start_using(); -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { -#else - if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS shader->set_uniform("emission_factor", 0.25f); render_as_instanced_model(buffer, *shader); shader->set_uniform("emission_factor", 0.0f); } -#if ENABLE_SEAMS_USING_BATCHED_MODELS else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { shader->set_uniform("emission_factor", 0.25f); render_as_batched_model(buffer, *shader); shader->set_uniform("emission_factor", 0.0f); } -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS else { -#endif // ENABLE_SEAMS_USING_MODELS for (size_t j = 0; j < buffer.indices.size(); ++j) { const IBuffer& i_buffer = buffer.indices[j]; @@ -3261,9 +2909,7 @@ void GCodeViewer::render_toolpaths() glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -#if ENABLE_SEAMS_USING_MODELS } -#endif // ENABLE_SEAMS_USING_MODELS shader->stop_using(); } @@ -3384,11 +3030,7 @@ void GCodeViewer::render_legend(float& legend_height) bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; -#if ENABLE_SEAMS_USING_BATCHED_MODELS auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, -#else - auto append_item = [this, icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array& offsets = { 0.0f, 0.0f, 0.0f, 0.0f }, double used_filament_m = 0.0, double used_filament_g = 0.0, std::function callback = nullptr) { @@ -3406,19 +3048,7 @@ void GCodeViewer::render_legend(float& legend_height) } case EItemType::Circle: { ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); -#if !ENABLE_SEAMS_USING_BATCHED_MODELS - if (m_buffers[buffer_id(EMoveType::Retract)].shader == "options_120") { - draw_list->AddCircleFilled(center, 0.5f * icon_size, - ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); - float radius = 0.5f * icon_size; - draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); - radius = 0.5f * icon_size * 0.01f * 33.0f; - draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); - } - else -#endif // !ENABLE_SEAMS_USING_BATCHED_MODELS - draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); - + draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); break; } case EItemType::Hexagon: { @@ -4178,11 +3808,7 @@ void GCodeViewer::render_legend(float& legend_height) auto add_option = [this, append_item](EMoveType move_type, EOptionsColors color, const std::string& text) { const TBuffer& buffer = m_buffers[buffer_id(move_type)]; if (buffer.visible && buffer.has_data()) -#if ENABLE_SEAMS_USING_BATCHED_MODELS append_item(EItemType::Circle, Options_Colors[static_cast(color)], text); -#else - append_item((buffer.shader == "options_110") ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast(color)], text); -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS }; // options section @@ -4608,13 +4234,9 @@ void GCodeViewer::render_statistics() add_counter(std::string("Multi GL_LINES:"), m_statistics.gl_multi_lines_calls_count); add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); -#if ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_counter(std::string("Instanced models:"), m_statistics.gl_instanced_models_calls_count); -#if ENABLE_SEAMS_USING_BATCHED_MODELS add_counter(std::string("Batched models:"), m_statistics.gl_batched_models_calls_count); -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS } if (ImGui::CollapsingHeader("CPU memory")) { @@ -4623,17 +4245,13 @@ void GCodeViewer::render_statistics() ImGui::Separator(); add_memory(std::string("Paths:"), m_statistics.paths_size); add_memory(std::string("Render paths:"), m_statistics.render_paths_size); -#if ENABLE_SEAMS_USING_MODELS add_memory(std::string("Models instances:"), m_statistics.models_instances_size); -#endif // ENABLE_SEAMS_USING_MODELS } if (ImGui::CollapsingHeader("GPU memory")) { add_memory(std::string("Vertices:"), m_statistics.total_vertices_gpu_size); add_memory(std::string("Indices:"), m_statistics.total_indices_gpu_size); -#if ENABLE_SEAMS_USING_MODELS add_memory(std::string("Instances:"), m_statistics.total_instances_gpu_size); -#endif // ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_memory(std::string("Max VBuffer:"), m_statistics.max_vbuffer_gpu_size); add_memory(std::string("Max IBuffer:"), m_statistics.max_ibuffer_gpu_size); @@ -4643,12 +4261,8 @@ void GCodeViewer::render_statistics() add_counter(std::string("Travel segments count:"), m_statistics.travel_segments_count); add_counter(std::string("Wipe segments count:"), m_statistics.wipe_segments_count); add_counter(std::string("Extrude segments count:"), m_statistics.extrude_segments_count); -#if ENABLE_SEAMS_USING_MODELS add_counter(std::string("Instances count:"), m_statistics.instances_count); -#if ENABLE_SEAMS_USING_BATCHED_MODELS add_counter(std::string("Batched count:"), m_statistics.batched_count); -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_counter(std::string("VBuffers count:"), m_statistics.vbuffers_count); add_counter(std::string("IBuffers count:"), m_statistics.ibuffers_count); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 908aa3bafe..9e33cb6a87 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -27,13 +27,9 @@ class GCodeViewer using MultiVertexBuffer = std::vector; using IndexBuffer = std::vector; using MultiIndexBuffer = std::vector; -#if ENABLE_SEAMS_USING_MODELS using InstanceBuffer = std::vector; using InstanceIdBuffer = std::vector; -#endif // ENABLE_SEAMS_USING_MODELS -#if ENABLE_FIX_SEAMS_SYNCH using InstancesOffsets = std::vector; -#endif // ENABLE_FIX_SEAMS_SYNCH static const std::vector Extrusion_Role_Colors; static const std::vector Options_Colors; @@ -107,17 +103,10 @@ class GCodeViewer void reset(); }; -#if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_BATCHED_MODELS // buffer containing instances data used to render a toolpaths using instanced or batched models // instance record format: // instanced models: 5 floats -> position.x|position.y|position.z|width|height (which are sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced()) // batched models: 3 floats -> position.x|position.y|position.z -#else - // buffer containing instances data used to render a toolpaths using instanced models - // instance record format: 5 floats -> position.x|position.y|position.z|width|height - // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced() -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS struct InstanceVBuffer { // ranges used to render only subparts of the intances @@ -140,7 +129,6 @@ class GCodeViewer void reset(); }; -#if ENABLE_SEAMS_USING_BATCHED_MODELS enum class EFormat : unsigned char { InstancedModel, @@ -148,21 +136,17 @@ class GCodeViewer }; EFormat format; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS // cpu-side buffer containing all instances data InstanceBuffer buffer; // indices of the moves for all instances std::vector s_ids; -#if ENABLE_FIX_SEAMS_SYNCH // position offsets, used to show the correct value of the tool position InstancesOffsets offsets; -#endif // ENABLE_FIX_SEAMS_SYNCH Ranges render_ranges; size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } -#if ENABLE_SEAMS_USING_BATCHED_MODELS size_t instance_size_floats() const { switch (format) { @@ -171,14 +155,10 @@ class GCodeViewer default: { return 0; } } } -#else - size_t instance_size_floats() const { return 5; } -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS size_t instance_size_bytes() const { return instance_size_floats() * sizeof(float); } void reset(); }; -#endif // ENABLE_SEAMS_USING_MODELS // ibo buffer containing indices data (for lines/triangles) used to render a specific toolpath type struct IBuffer @@ -313,17 +293,9 @@ class GCodeViewer { Point, Line, -#if ENABLE_SEAMS_USING_MODELS Triangle, -#if ENABLE_SEAMS_USING_BATCHED_MODELS InstancedModel, BatchedModel -#else - Model -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#else - Triangle -#endif // ENABLE_SEAMS_USING_MODELS }; ERenderPrimitiveType render_primitive_type; @@ -332,22 +304,18 @@ class GCodeViewer VBuffer vertices; std::vector indices; -#if ENABLE_SEAMS_USING_MODELS struct Model { GLModel model; Color color; InstanceVBuffer instances; -#if ENABLE_SEAMS_USING_BATCHED_MODELS GLModel::InitializationData data; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS void reset(); }; // contain the buffer for model primitive types Model model; -#endif // ENABLE_SEAMS_USING_MODELS std::string shader; std::vector paths; @@ -396,7 +364,6 @@ class GCodeViewer } size_t max_indices_per_segment_size_bytes() const { return max_indices_per_segment() * sizeof(IBufferType); } -#if ENABLE_SEAMS_USING_MODELS bool has_data() const { switch (render_primitive_type) { @@ -405,23 +372,14 @@ class GCodeViewer case ERenderPrimitiveType::Triangle: { return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } -#if ENABLE_SEAMS_USING_BATCHED_MODELS case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } case ERenderPrimitiveType::BatchedModel: { return model.data.vertices_count() > 0 && model.data.indices_count() && !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } -#else - case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.buffer.empty(); } -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS default: { return false; } } } -#else - bool has_data() const { - return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; - } -#endif // ENABLE_SEAMS_USING_MODELS }; // helper to render shells @@ -590,36 +548,24 @@ class GCodeViewer int64_t gl_multi_lines_calls_count{ 0 }; int64_t gl_multi_triangles_calls_count{ 0 }; int64_t gl_triangles_calls_count{ 0 }; -#if ENABLE_SEAMS_USING_MODELS int64_t gl_instanced_models_calls_count{ 0 }; -#if ENABLE_SEAMS_USING_BATCHED_MODELS int64_t gl_batched_models_calls_count{ 0 }; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS // memory int64_t results_size{ 0 }; int64_t total_vertices_gpu_size{ 0 }; int64_t total_indices_gpu_size{ 0 }; -#if ENABLE_SEAMS_USING_MODELS int64_t total_instances_gpu_size{ 0 }; -#endif // ENABLE_SEAMS_USING_MODELS int64_t max_vbuffer_gpu_size{ 0 }; int64_t max_ibuffer_gpu_size{ 0 }; int64_t paths_size{ 0 }; int64_t render_paths_size{ 0 }; -#if ENABLE_SEAMS_USING_MODELS int64_t models_instances_size{ 0 }; -#endif // ENABLE_SEAMS_USING_MODELS // other int64_t travel_segments_count{ 0 }; int64_t wipe_segments_count{ 0 }; int64_t extrude_segments_count{ 0 }; -#if ENABLE_SEAMS_USING_MODELS int64_t instances_count{ 0 }; -#if ENABLE_SEAMS_USING_BATCHED_MODELS int64_t batched_count{ 0 }; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS int64_t vbuffers_count{ 0 }; int64_t ibuffers_count{ 0 }; @@ -645,40 +591,28 @@ class GCodeViewer gl_multi_lines_calls_count = 0; gl_multi_triangles_calls_count = 0; gl_triangles_calls_count = 0; -#if ENABLE_SEAMS_USING_MODELS gl_instanced_models_calls_count = 0; -#if ENABLE_SEAMS_USING_BATCHED_MODELS gl_batched_models_calls_count = 0; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS } void reset_sizes() { results_size = 0; total_vertices_gpu_size = 0; total_indices_gpu_size = 0; -#if ENABLE_SEAMS_USING_MODELS total_instances_gpu_size = 0; -#endif // ENABLE_SEAMS_USING_MODELS max_vbuffer_gpu_size = 0; max_ibuffer_gpu_size = 0; paths_size = 0; render_paths_size = 0; -#if ENABLE_SEAMS_USING_MODELS models_instances_size = 0; -#endif // ENABLE_SEAMS_USING_MODELS } void reset_others() { travel_segments_count = 0; wipe_segments_count = 0; - extrude_segments_count = 0; -#if ENABLE_SEAMS_USING_MODELS + extrude_segments_count = 0; instances_count = 0; -#if ENABLE_SEAMS_USING_BATCHED_MODELS batched_count = 0; -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS vbuffers_count = 0; ibuffers_count = 0; } @@ -693,12 +627,10 @@ public: GLModel m_model; Vec3f m_world_position; Transform3f m_world_transform; -#if ENABLE_FIX_SEAMS_SYNCH // for seams, the position of the marker is on the last endpoint of the toolpath containing it // the offset is used to show the correct value of tool position in the "ToolPosition" window // see implementation of render() method Vec3f m_world_offset; -#endif // ENABLE_FIX_SEAMS_SYNCH float m_z_offset{ 0.5f }; bool m_visible{ true }; @@ -708,9 +640,7 @@ public: const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); } void set_world_position(const Vec3f& position); -#if ENABLE_FIX_SEAMS_SYNCH void set_world_offset(const Vec3f& offset) { m_world_offset = offset; } -#endif // ENABLE_FIX_SEAMS_SYNCH bool is_visible() const { return m_visible; } void set_visible(bool visible) { m_visible = visible; } @@ -764,13 +694,9 @@ public: Endpoints endpoints; Endpoints current; Endpoints last_current; -#if ENABLE_SEAMS_USING_MODELS Endpoints global; -#endif // ENABLE_SEAMS_USING_MODELS Vec3f current_position{ Vec3f::Zero() }; -#if ENABLE_FIX_SEAMS_SYNCH Vec3f current_offset{ Vec3f::Zero() }; -#endif // ENABLE_FIX_SEAMS_SYNCH Marker marker; GCodeWindow gcode_window; std::vector gcode_ids; @@ -847,9 +773,7 @@ public: GCodeViewer(); ~GCodeViewer() { reset(); } -#if ENABLE_SEAMS_USING_MODELS void init(); -#endif // ENABLE_SEAMS_USING_MODELS // extract rendering data from the given parameters void load(const GCodeProcessorResult& gcode_result, const Print& print, bool initialized); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 04c801a332..1f1683f1bb 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1422,10 +1422,8 @@ void GLCanvas3D::render() if (!is_initialized() && !init()) return; -#if ENABLE_SEAMS_USING_MODELS if (!m_main_toolbar.is_enabled()) m_gcode_viewer.init(); -#endif // ENABLE_SEAMS_USING_MODELS if (! m_bed.build_volume().valid()) { // this happens at startup when no data is still saved under <>\AppData\Roaming\Slic3rPE @@ -4148,24 +4146,15 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const } } -#if !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED - if (visible_volumes.empty()) - return; -#endif // !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED - BoundingBoxf3 volumes_box; -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED if (!visible_volumes.empty()) { -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED for (const GLVolume* vol : visible_volumes) { volumes_box.merge(vol->transformed_bounding_box()); } -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } else // This happens for empty projects volumes_box = m_bed.extended_bounding_box(); -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED Camera camera; camera.set_type(camera_type); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8af6528ec8..0cbd27ed00 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -623,9 +623,7 @@ public: void reset_volumes(); ModelInstanceEPrintVolumeState check_volumes_outside_state() const; -#if ENABLE_SEAMS_USING_MODELS void init_gcode_viewer() { m_gcode_viewer.init(); } -#endif // ENABLE_SEAMS_USING_MODELS void reset_gcode_toolpaths() { m_gcode_viewer.reset(); } const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); } void update_gcode_sequential_view_current(unsigned int first, unsigned int last) { m_gcode_viewer.update_sequential_view_current(first, last); } diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index fb27aced50..422b654080 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -17,7 +17,6 @@ namespace Slic3r { namespace GUI { -#if ENABLE_SEAMS_USING_BATCHED_MODELS size_t GLModel::InitializationData::vertices_count() const { size_t ret = 0; @@ -35,7 +34,6 @@ size_t GLModel::InitializationData::indices_count() const } return ret; } -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS void GLModel::init_from(const InitializationData& data) { @@ -231,7 +229,6 @@ void GLModel::render() const } } -#if ENABLE_SEAMS_USING_MODELS void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const { if (instances_vbo == 0) @@ -308,7 +305,6 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -#endif // ENABLE_SEAMS_USING_MODELS void GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices) { diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index f2fc9da9b3..d47c56fd93 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -49,14 +49,12 @@ namespace GUI { std::vector entities; -#if ENABLE_SEAMS_USING_BATCHED_MODELS size_t vertices_count() const; size_t vertices_size_floats() const { return vertices_count() * 6; } size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } size_t indices_count() const; size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); } -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS }; private: @@ -80,9 +78,7 @@ namespace GUI { void reset(); void render() const; -#if ENABLE_SEAMS_USING_MODELS void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; -#endif // ENABLE_SEAMS_USING_MODELS bool is_initialized() const { return !m_render_data.empty(); } diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index e1d66fa5db..7fc03d4217 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -33,31 +33,13 @@ std::pair GLShadersManager::init() bool valid = true; -#if ENABLE_SEAMS_USING_BATCHED_MODELS // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview -#else - // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); // used to render printbed valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview -#if ENABLE_SEAMS_USING_BATCHED_MODELS if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); -#else -#if ENABLE_SEAMS_USING_MODELS - if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) - valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); - else { -#endif // ENABLE_SEAMS_USING_MODELS - valid &= append_shader("options_110", { "options_110.vs", "options_110.fs" }); - if (GUI::wxGetApp().is_glsl_version_greater_or_equal_to(1, 20)) - valid &= append_shader("options_120", { "options_120.vs", "options_120.fs" }); -#if ENABLE_SEAMS_USING_MODELS - } -#endif // ENABLE_SEAMS_USING_MODELS -#endif // ENABLE_SEAMS_USING_BATCHED_MODELS // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 80c3709cff..df31fd6c82 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,8 @@ #include #endif +using namespace std::literals; + namespace Slic3r { namespace GUI { @@ -471,39 +474,86 @@ static bool run_updater_win() } #endif //_WIN32 +struct FileWildcards { + std::string_view title; + std::vector file_extensions; +}; + +static const FileWildcards file_wildcards_by_type[FT_SIZE] = { + /* FT_STL */ { "STL files"sv, { ".stl"sv } }, + /* FT_OBJ */ { "OBJ files"sv, { ".obj"sv } }, + /* FT_AMF */ { "AMF files"sv, { ".amf"sv, ".zip.amf"sv, ".xml"sv } }, + /* FT_3MF */ { "3MF files"sv, { ".3mf"sv } }, + /* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".gco"sv, ".g"sv, ".ngc"sv } }, + /* FT_MODEL */ { "Known files"sv, { ".stl"sv, ".obj"sv, ".3mf"sv, ".amf"sv, ".zip.amf"sv, ".xml"sv } }, + /* FT_PROJECT */ { "Project files"sv, { ".3mf"sv, ".amf"sv, ".zip.amf"sv } }, + /* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } }, + + /* FT_INI */ { "INI files"sv, { ".ini"sv } }, + /* FT_SVG */ { "SVG files"sv, { ".svg"sv } }, + + /* FT_TEX */ { "Texture"sv, { ".png"sv, ".svg"sv } }, + + /* FT_SL1 */ { "Masked SLA files"sv, { ".sl1"sv, ".sl1s"sv } }, +}; + +// This function produces a Win32 file dialog file template mask to be consumed by wxWidgets on all platforms. +// The function accepts a custom extension parameter. If the parameter is provided, the custom extension +// will be added as a fist to the list. This is important for a "file save" dialog on OSX, which strips +// an extension from the provided initial file name and substitutes it with the default extension (the first one in the template). wxString file_wildcards(FileType file_type, const std::string &custom_extension) { - static const std::string defaults[FT_SIZE] = { - /* FT_STL */ "STL files (*.stl)|*.stl;*.STL", - /* FT_OBJ */ "OBJ files (*.obj)|*.obj;*.OBJ", - /* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML", - /* FT_3MF */ "3MF files (*.3mf)|*.3mf;*.3MF;", - /* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC", - /* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF", - /* FT_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF", - /* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ", + const FileWildcards data = file_wildcards_by_type[file_type]; + std::string title; + std::string mask; + std::string custom_ext_lower; - /* FT_INI */ "INI files (*.ini)|*.ini;*.INI", - /* FT_SVG */ "SVG files (*.svg)|*.svg;*.SVG", - - /* FT_TEX */ "Texture (*.png, *.svg)|*.png;*.PNG;*.svg;*.SVG", - - /* FT_SL1 */ "Masked SLA files (*.sl1, *.sl1s)|*.sl1;*.SL1;*.sl1s;*.SL1S", - // Workaround for OSX file picker, for some reason it always saves with the 1st extension. - /* FT_SL1S */ "Masked SLA files (*.sl1s, *.sl1)|*.sl1s;*.SL1S;*.sl1;*.SL1", - }; - - std::string out = defaults[file_type]; if (! custom_extension.empty()) { - // Find the custom extension in the template. - if (out.find(std::string("*") + custom_extension + ",") == std::string::npos && out.find(std::string("*") + custom_extension + ")") == std::string::npos) { - // The custom extension was not found in the template. - // Append the custom extension to the wildcards, so that the file dialog would not add the default extension to it. - boost::replace_first(out, ")|", std::string(", *") + custom_extension + ")|"); - out += std::string(";*") + custom_extension; + // Generate an extension into the title mask and into the list of extensions. + custom_ext_lower = custom_extension; + boost::to_lower(custom_ext_lower); + std::string custom_ext_upper = custom_extension; + boost::to_upper(custom_ext_upper); + if (custom_ext_lower == custom_extension) { + // Add a lower case version. + title = std::string("*") + custom_ext_lower; + mask = title; + // Add an upper case version. + mask += ";*"; + mask += custom_ext_upper; + } else if (custom_ext_upper == custom_extension) { + // Add an upper case version. + title = std::string("*") + custom_ext_upper; + mask = title; + // Add a lower case version. + mask += ";*"; + mask += custom_ext_lower; + } else { + // Add the mixed case version only. + title = std::string("*") + custom_extension; + mask = title; } } - return from_u8(out); + + for (const std::string_view &ext : data.file_extensions) + // Only add an extension if it was not added first as the custom extension. + if (ext != custom_ext_lower) { + if (title.empty()) { + title = "*"; + title += ext; + mask = title; + } else { + title += ", *"; + title += ext; + mask += ";*"; + mask += ext; + } + mask += ";*"; + std::string ext_upper{ ext }; + boost::to_upper(ext_upper); + mask += ext_upper; + } + return GUI::format("%s (%s)|%s", data.title, title, mask); } static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 95ac8c0259..9e8e913f69 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -66,13 +66,11 @@ enum FileType FT_TEX, FT_SL1, - // Workaround for OSX file picker, for some reason it always saves with the 1st extension. - FT_SL1S, FT_SIZE, }; -extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string()); +extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string{}); enum ConfigMenuIDs { ConfigMenuWizard, diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 588d02cbcd..04a3921692 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -484,6 +484,10 @@ void MenuFactory::append_menu_items_add_volume(wxMenu* menu) menu->Destroy(settings_id); } + // Update "Height range Modifier" item (delete old & create new) + if (const auto range_id = menu->FindItem(_L("Height range Modifier")); range_id != wxNOT_FOUND) + menu->Destroy(range_id); + const ConfigOptionMode mode = wxGetApp().get_mode(); if (mode == comAdvanced) { @@ -513,6 +517,8 @@ void MenuFactory::append_menu_items_add_volume(wxMenu* menu) append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second, []() { return obj_list()->is_instance_or_object_selected(); }, m_parent); } + + append_menu_item_layers_editing(menu); } wxMenuItem* MenuFactory::append_menu_item_layers_editing(wxMenu* menu) @@ -944,11 +950,7 @@ void MenuFactory::create_object_menu() []() { return plater()->can_split(true) && wxGetApp().get_mode() > comSimple; }, m_parent); m_object_menu.AppendSeparator(); - // Layers Editing for object - append_menu_item_layers_editing(&m_object_menu); - m_object_menu.AppendSeparator(); - - // "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume() + // "Height range Modifier" and "Add (volumes)" menu items will be added later in append_menu_items_add_volume() } void MenuFactory::create_sla_object_menu() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 0eaf9cf0a7..577db8ed5a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -97,7 +97,7 @@ public: // will be also extended to support additional states, requiring at least one state to remain free out of 19 states. static const constexpr size_t EXTRUDERS_LIMIT = 16; - virtual const float get_cursor_radius_min() const { return CursorRadiusMin; } + const float get_cursor_radius_min() const override { return CursorRadiusMin; } protected: std::array get_cursor_sphere_left_button_color() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index a2f8193879..39093e14d6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -39,7 +39,7 @@ protected: virtual void on_render() override; virtual void on_render_for_picking() override{}; - virtual CommonGizmosDataID on_get_requirements() const; + CommonGizmosDataID on_get_requirements() const override; private: void apply_simplify(); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 9310354006..f447128e16 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -831,26 +831,15 @@ bool MainFrame::can_start_new_project() const bool MainFrame::can_save() const { -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED return (m_plater != nullptr) && !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false) && m_plater->is_project_dirty(); -#else - return (m_plater != nullptr) && !m_plater->model().objects.empty() && - !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false) && - !m_plater->get_project_filename().empty() && m_plater->is_project_dirty(); -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } bool MainFrame::can_save_as() const { -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED return (m_plater != nullptr) && !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false); -#else - return (m_plater != nullptr) && !m_plater->model().objects.empty() && - !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false); -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } void MainFrame::save_project() diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d449974a9d..3be9027948 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1856,9 +1856,7 @@ struct Plater::priv } void export_gcode(fs::path output_path, bool output_path_on_removable_media, PrintHostJob upload_job); void reload_from_disk(); -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE bool replace_volume_with_stl(int object_idx, int volume_idx, const fs::path& new_path, const wxString& snapshot = ""); -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE void replace_with_stl(); void reload_all_from_disk(); void set_current_panel(wxPanel* panel); @@ -2925,6 +2923,7 @@ void Plater::priv::remove(size_t obj_idx) if (view3D->is_layers_editing_enabled()) view3D->enable_layers_editing(false); + m_ui_jobs.cancel_all(); model.delete_object(obj_idx); update(); // Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model. @@ -2939,6 +2938,7 @@ void Plater::priv::delete_object_from_model(size_t obj_idx) if (! model.objects[obj_idx]->name.empty()) snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str()); Plater::TakeSnapshot snapshot(q, snapshot_label); + m_ui_jobs.cancel_all(); model.delete_object(obj_idx); update(); object_list_changed(); @@ -2956,6 +2956,8 @@ void Plater::priv::delete_all_objects_from_model() view3D->get_canvas3d()->reset_sequential_print_clearance(); + m_ui_jobs.cancel_all(); + // Stop and reset the Print content. background_process.reset(); model.clear_objects(); @@ -2986,6 +2988,8 @@ void Plater::priv::reset() view3D->get_canvas3d()->reset_sequential_print_clearance(); + m_ui_jobs.cancel_all(); + // Stop and reset the Print content. this->background_process.reset(); model.clear_objects(); @@ -3371,7 +3375,6 @@ void Plater::priv::update_sla_scene() this->update_restart_background_process(true, true); } -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const fs::path& new_path, const wxString& snapshot) { const std::string path = new_path.string(); @@ -3439,7 +3442,6 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const return true; } -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE void Plater::priv::replace_with_stl() { @@ -3477,72 +3479,8 @@ void Plater::priv::replace_with_stl() return; } -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE if (!replace_volume_with_stl(object_idx, volume_idx, out_path, _L("Replace with STL"))) return; -#else - const auto& path = out_path.string(); - wxBusyCursor wait; - wxBusyInfo info(_L("Replace from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas()); - - Model new_model; - try { - new_model = Model::read_from_file(path, nullptr, nullptr, Model::LoadAttribute::AddDefaultInstances); - for (ModelObject* model_object : new_model.objects) { - model_object->center_around_origin(); - model_object->ensure_on_bed(); - } - } - catch (std::exception&) { - // error while loading - return; - } - - if (new_model.objects.size() > 1 || new_model.objects[0]->volumes.size() > 1) { - MessageDialog dlg(q, _L("Unable to replace with more than one volume"), _L("Error during replace"), wxOK | wxOK_DEFAULT | wxICON_WARNING); - dlg.ShowModal(); - return; - } - - Plater::TakeSnapshot snapshot(q, _L("Replace with STL")); - - ModelObject* old_model_object = model.objects[object_idx]; - ModelVolume* old_volume = old_model_object->volumes[volume_idx]; - - bool sinking = old_model_object->bounding_box().min.z() < SINKING_Z_THRESHOLD; - - ModelObject* new_model_object = new_model.objects[0]; - old_model_object->add_volume(*new_model_object->volumes[0]); - ModelVolume* new_volume = old_model_object->volumes.back(); - new_volume->set_new_unique_id(); - new_volume->config.apply(old_volume->config); - new_volume->set_type(old_volume->type()); - new_volume->set_material_id(old_volume->material_id()); - new_volume->set_transformation(old_volume->get_transformation()); - new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset)); - assert(! old_volume->source.is_converted_from_inches || ! old_volume->source.is_converted_from_meters); - if (old_volume->source.is_converted_from_inches) - new_volume->convert_from_imperial_units(); - else if (old_volume->source.is_converted_from_meters) - new_volume->convert_from_meters(); - new_volume->supported_facets.assign(old_volume->supported_facets); - new_volume->seam_facets.assign(old_volume->seam_facets); - new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets); - std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back()); - old_model_object->delete_volume(old_model_object->volumes.size() - 1); - if (!sinking) - old_model_object->ensure_on_bed(); - old_model_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1"); - - // if object has just one volume, rename object too - if (old_model_object->volumes.size() == 1) - old_model_object->name = old_model_object->volumes[0]->name; - - // update new name in ObjectList - sidebar->obj_list()->update_name_in_list(object_idx, volume_idx); - - sla::reproject_points_and_holes(old_model_object); -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE // update 3D scene update(); @@ -3591,9 +3529,7 @@ void Plater::priv::reload_from_disk() // collects paths of files to load std::vector input_paths; std::vector missing_input_paths; -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE std::vector replace_paths; -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE for (const SelectedVolume& v : selected_volumes) { const ModelObject* object = model.objects[v.object_idx]; const ModelVolume* volume = object->volumes[v.volume_idx]; @@ -3601,7 +3537,6 @@ void Plater::priv::reload_from_disk() if (!volume->source.input_file.empty()) { if (fs::exists(volume->source.input_file)) input_paths.push_back(volume->source.input_file); -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE else { // searches the source in the same folder containing the object bool found = false; @@ -3619,10 +3554,6 @@ void Plater::priv::reload_from_disk() if (!found) missing_input_paths.push_back(volume->source.input_file); } -#else - else - missing_input_paths.push_back(volume->source.input_file); -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE } else if (!object->input_file.empty() && volume->is_model_part() && !volume->name.empty() && !volume->source.is_from_builtin_objects) missing_input_paths.push_back(volume->name); @@ -3665,7 +3596,6 @@ void Plater::priv::reload_from_disk() } } else { -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE wxString message = _L("The selected file") + " (" + from_u8(sel_filename) + ") " + _L("differs from the original file") + " (" + from_u8(search.filename().string()) + ").\n" + _L("Do you want to replace it") + " ?"; //wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION); @@ -3673,23 +3603,14 @@ void Plater::priv::reload_from_disk() if (dlg.ShowModal() == wxID_YES) replace_paths.push_back(sel_filename_path); missing_input_paths.pop_back(); -#else - wxString message = _L("It is not allowed to change the file to reload") + " (" + from_u8(search.filename().string()) + ").\n" + _L("Do you want to retry") + " ?"; - //wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION); - MessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION); - if (dlg.ShowModal() != wxID_YES) - return; -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE } } std::sort(input_paths.begin(), input_paths.end()); input_paths.erase(std::unique(input_paths.begin(), input_paths.end()), input_paths.end()); -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE std::sort(replace_paths.begin(), replace_paths.end()); replace_paths.erase(std::unique(replace_paths.begin(), replace_paths.end()), replace_paths.end()); -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE std::vector fail_list; @@ -3785,7 +3706,6 @@ void Plater::priv::reload_from_disk() } } -#if ENABLE_RELOAD_FROM_DISK_REPLACE_FILE for (size_t i = 0; i < replace_paths.size(); ++i) { const auto& path = replace_paths[i].string(); for (const SelectedVolume& sel_v : selected_volumes) { @@ -3797,7 +3717,6 @@ void Plater::priv::reload_from_disk() } } } -#endif // ENABLE_RELOAD_FROM_DISK_REPLACE_FILE if (!fail_list.empty()) { wxString message = _L("Unable to reload:") + "\n"; @@ -3911,9 +3830,7 @@ void Plater::priv::set_current_panel(wxPanel* panel) bool export_in_progress = this->background_process.is_export_scheduled(); bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside; if (!model.objects.empty() && !export_in_progress && model_fits) { -#if ENABLE_SEAMS_USING_MODELS preview->get_canvas3d()->init_gcode_viewer(); -#endif // ENABLE_SEAMS_USING_MODELS q->reslice(); } // keeps current gcode preview, if any @@ -4644,7 +4561,7 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const double max_print_he bool Plater::priv::can_delete() const { - return !get_selection().is_empty() && !get_selection().is_wipe_tower() && !m_ui_jobs.is_any_running(); + return !get_selection().is_empty() && !get_selection().is_wipe_tower(); } bool Plater::priv::can_delete_all() const @@ -5502,6 +5419,7 @@ void Plater::remove_selected() return; Plater::TakeSnapshot snapshot(this, _L("Delete Selected Objects")); + p->m_ui_jobs.cancel_all(); p->view3D->delete_selected(); } @@ -5735,7 +5653,7 @@ void Plater::export_gcode(bool prefer_removable) wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _L("Save G-code file as:") : _L("Save SL1 / SL1S file as:"), start_dir, from_path(default_output_file.filename()), - GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : boost::iequals(ext, ".sl1s") ? FT_SL1S : FT_SL1, ext), + GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_SL1, ext), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if (dlg.ShowModal() == wxID_OK) { @@ -5934,16 +5852,11 @@ void Plater::export_amf() bool Plater::export_3mf(const boost::filesystem::path& output_path) { -#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED if (p->model.objects.empty()) { MessageDialog dialog(nullptr, _L("The plater is empty.\nDo you want to save the project?"), _L("Save project"), wxYES_NO); if (dialog.ShowModal() != wxID_YES) return false; } -#else - if (p->model.objects.empty()) - return false; -#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED wxString path; bool export_config = true; @@ -6138,11 +6051,12 @@ void Plater::send_gcode() upload_job.printhost->get_groups(groups); } - PrintHostSendDialog dlg(default_output_file, upload_job.printhost->can_start_print(), groups); + PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups); if (dlg.ShowModal() == wxID_OK) { upload_job.upload_data.upload_path = dlg.filename(); - upload_job.upload_data.start_print = dlg.start_print(); + upload_job.upload_data.post_action = dlg.post_action(); upload_job.upload_data.group = dlg.group(); + p->export_gcode(fs::path(), false, std::move(upload_job)); } } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 4359d600b8..d6422bbadb 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -481,14 +481,18 @@ void PreferencesDialog::build(size_t selected_tab) option = Option(def, "dark_color_mode"); m_optgroup_dark_mode->append_single_option_line(option); - def.label = L("Use system menu for application"); - def.type = coBool; - def.tooltip = L("If enabled, application will use the standart Windows system menu,\n" - "but on some combination od display scales it can look ugly. " - "If disabled, old UI will be used."); - def.set_default_value(new ConfigOptionBool{ app_config->get("sys_menu_enabled") == "1" }); - option = Option(def, "sys_menu_enabled"); - m_optgroup_dark_mode->append_single_option_line(option); + if (wxPlatformInfo::Get().GetOSMajorVersion() >= 10) // Use system menu just for Window newer then Windows 10 + // Use menu with ownerdrawn items by default on systems older then Windows 10 + { + def.label = L("Use system menu for application"); + def.type = coBool; + def.tooltip = L("If enabled, application will use the standart Windows system menu,\n" + "but on some combination od display scales it can look ugly. " + "If disabled, old UI will be used."); + def.set_default_value(new ConfigOptionBool{ app_config->get("sys_menu_enabled") == "1" }); + option = Option(def, "sys_menu_enabled"); + m_optgroup_dark_mode->append_single_option_line(option); + } activate_options_tab(m_optgroup_dark_mode); } diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index da6840ef8a..2cea580be3 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -23,7 +23,6 @@ #include "GUI_App.hpp" #include "MsgDialog.hpp" #include "I18N.hpp" -#include "../Utils/PrintHost.hpp" #include "MainFrame.hpp" #include "libslic3r/AppConfig.hpp" #include "NotificationManager.hpp" @@ -35,13 +34,13 @@ namespace Slic3r { namespace GUI { static const char *CONFIG_KEY_PATH = "printhost_path"; -static const char *CONFIG_KEY_PRINT = "printhost_print"; static const char *CONFIG_KEY_GROUP = "printhost_group"; -PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_print, const wxArrayString &groups) +PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups) : MsgDialog(static_cast(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:")) , txt_filename(new wxTextCtrl(this, wxID_ANY)) , combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr) + , post_upload_action(PrintHostPostUploadAction::None) { #ifdef __APPLE__ txt_filename->OSXDisableAllSmartSubstitutions(); @@ -77,38 +76,47 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr txt_filename->SetValue(recent_path); txt_filename->SetFocus(); - wxString suffix = recent_path.substr(recent_path.find_last_of('.')); + m_valid_suffix = recent_path.substr(recent_path.find_last_of('.')); + // .gcode suffix control + auto validate_path = [this](const wxString &path) -> bool { + if (! path.Lower().EndsWith(m_valid_suffix.Lower())) { + MessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), m_valid_suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); + if (msg_wingow.ShowModal() == wxID_NO) + return false; + } + return true; + }; - if (can_start_print) { + if (post_actions.has(PrintHostPostUploadAction::StartPrint)) { auto* btn_print = add_button(wxID_YES, false, _L("Upload and Print")); - btn_print->Bind(wxEVT_BUTTON, [this, suffix](wxCommandEvent&) { - wxString path = txt_filename->GetValue(); - // .gcode suffix control - if (!path.Lower().EndsWith(suffix.Lower())) - { - MessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); - if (msg_wingow.ShowModal() == wxID_NO) - return; + btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { + if (validate_path(txt_filename->GetValue())) { + post_upload_action = PrintHostPostUploadAction::StartPrint; + EndDialog(wxID_OK); } - start_print_selected = true; - EndDialog(wxID_OK); - }); + }); } + + if (post_actions.has(PrintHostPostUploadAction::StartSimulation)) { + auto* btn_print = add_button(wxID_YES, false, _L("Upload and Simulate")); + btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { + if (validate_path(txt_filename->GetValue())) { + post_upload_action = PrintHostPostUploadAction::StartSimulation; + EndDialog(wxID_OK); + } + }); + } + add_button(wxID_CANCEL); if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) { btn_ok->SetLabel(_L("Upload")); - btn_ok->Bind(wxEVT_BUTTON, [this, suffix](wxCommandEvent&) { - wxString path = txt_filename->GetValue(); - // .gcode suffix control - if (!path.Lower().EndsWith(suffix.Lower())) - { - MessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); - if (msg_wingow.ShowModal() == wxID_NO) - return; + btn_ok->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { + if (validate_path(txt_filename->GetValue())) { + post_upload_action = PrintHostPostUploadAction::None; + EndDialog(wxID_OK); } - EndDialog(wxID_OK); - }); + }); } finalize(); @@ -137,9 +145,9 @@ fs::path PrintHostSendDialog::filename() const return into_path(txt_filename->GetValue()); } -bool PrintHostSendDialog::start_print() const +PrintHostPostUploadAction PrintHostSendDialog::post_action() const { - return start_print_selected; + return post_upload_action; } std::string PrintHostSendDialog::group() const @@ -165,8 +173,7 @@ void PrintHostSendDialog::EndModal(int ret) AppConfig *app_config = wxGetApp().app_config; app_config->set("recent", CONFIG_KEY_PATH, into_u8(path)); - app_config->set("recent", CONFIG_KEY_PRINT, start_print() ? "1" : "0"); - + if (combo_groups != nullptr) { wxString group = combo_groups->GetValue(); app_config->set("recent", CONFIG_KEY_GROUP, into_u8(group)); diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp index fa3505f709..ff3eb60125 100644 --- a/src/slic3r/GUI/PrintHostDialogs.hpp +++ b/src/slic3r/GUI/PrintHostDialogs.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_PrintHostSendDialog_hpp_ #define slic3r_PrintHostSendDialog_hpp_ +#include #include #include @@ -10,34 +11,32 @@ #include "GUI_Utils.hpp" #include "MsgDialog.hpp" +#include "../Utils/PrintHost.hpp" class wxButton; class wxTextCtrl; +class wxChoice; class wxComboBox; -class wxCheckBox; class wxDataViewListCtrl; - namespace Slic3r { -struct PrintHostJob; - namespace GUI { - class PrintHostSendDialog : public GUI::MsgDialog { public: - PrintHostSendDialog(const boost::filesystem::path &path, bool can_start_print, const wxArrayString& groups); + PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups); boost::filesystem::path filename() const; - bool start_print() const; + PrintHostPostUploadAction post_action() const; std::string group() const; virtual void EndModal(int ret) override; private: wxTextCtrl *txt_filename; wxComboBox *combo_groups; - bool start_print_selected { false }; + PrintHostPostUploadAction post_upload_action; + wxString m_valid_suffix; }; diff --git a/src/slic3r/Utils/AstroBox.cpp b/src/slic3r/Utils/AstroBox.cpp index 20560f1c16..8781549a20 100644 --- a/src/slic3r/Utils/AstroBox.cpp +++ b/src/slic3r/Utils/AstroBox.cpp @@ -115,11 +115,11 @@ bool AstroBox::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Error % url % upload_filename.string() % upload_parent_path.string() - % upload_data.start_print; + % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); auto http = Http::post(std::move(url)); set_auth(http); - http.form_add("print", upload_data.start_print ? "true" : "false") + http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) .on_complete([&](std::string body, unsigned status) { diff --git a/src/slic3r/Utils/AstroBox.hpp b/src/slic3r/Utils/AstroBox.hpp index f24018b1b8..15a8863a90 100644 --- a/src/slic3r/Utils/AstroBox.hpp +++ b/src/slic3r/Utils/AstroBox.hpp @@ -26,7 +26,7 @@ public: bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; bool has_auto_discovery() const override { return true; } bool can_test() const override { return true; } - bool can_start_print() const override { return true; } + PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } std::string get_host() const override { return host; } protected: diff --git a/src/slic3r/Utils/Duet.cpp b/src/slic3r/Utils/Duet.cpp index ba93603a1f..3293a3ff2b 100644 --- a/src/slic3r/Utils/Duet.cpp +++ b/src/slic3r/Utils/Duet.cpp @@ -67,10 +67,10 @@ bool Duet::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn e bool dsf = (connectionType == ConnectionType::dsf); auto upload_cmd = get_upload_url(upload_data.upload_path.string(), connectionType); - BOOST_LOG_TRIVIAL(info) << boost::format("Duet: Uploading file %1%, filepath: %2%, print: %3%, command: %4%") + BOOST_LOG_TRIVIAL(info) << boost::format("Duet: Uploading file %1%, filepath: %2%, post_action: %3%, command: %4%") % upload_data.source_path % upload_data.upload_path - % upload_data.start_print + % int(upload_data.post_action) % upload_cmd; auto http = (dsf ? Http::put(std::move(upload_cmd)) : Http::post(std::move(upload_cmd))); @@ -87,9 +87,15 @@ bool Duet::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn e BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Request completed but error code was received: %1%") % err_code; error_fn(format_error(body, L("Unknown error occured"), 0)); res = false; - } else if (upload_data.start_print) { + } else if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) { wxString errormsg; - res = start_print(errormsg, upload_data.upload_path.string(), connectionType); + res = start_print(errormsg, upload_data.upload_path.string(), connectionType, false); + if (! res) { + error_fn(std::move(errormsg)); + } + } else if (upload_data.post_action == PrintHostPostUploadAction::StartSimulation) { + wxString errormsg; + res = start_print(errormsg, upload_data.upload_path.string(), connectionType, true); if (! res) { error_fn(std::move(errormsg)); } @@ -230,7 +236,7 @@ std::string Duet::timestamp_str() const return std::string(buffer); } -bool Duet::start_print(wxString &msg, const std::string &filename, ConnectionType connectionType) const +bool Duet::start_print(wxString &msg, const std::string &filename, ConnectionType connectionType, bool simulationMode) const { assert(connectionType != ConnectionType::error); @@ -240,14 +246,18 @@ bool Duet::start_print(wxString &msg, const std::string &filename, ConnectionTyp auto url = dsf ? (boost::format("%1%machine/code") % get_base_url()).str() - : (boost::format("%1%rr_gcode?gcode=M32%%20\"0:/gcodes/%2%\"") + : (boost::format(simulationMode + ? "%1%rr_gcode?gcode=M37%%20P\"0:/gcodes/%2%\"" + : "%1%rr_gcode?gcode=M32%%20\"0:/gcodes/%2%\"") % get_base_url() % Http::url_encode(filename)).str(); auto http = (dsf ? Http::post(std::move(url)) : Http::get(std::move(url))); if (dsf) { http.set_post_body( - (boost::format("M32 \"0:/gcodes/%1%\"") + (boost::format(simulationMode + ? "M37 P\"0:/gcodes/%1%\"" + : "M32 \"0:/gcodes/%1%\"") % filename).str() ); } diff --git a/src/slic3r/Utils/Duet.hpp b/src/slic3r/Utils/Duet.hpp index e5aec548bb..edca66ce0c 100644 --- a/src/slic3r/Utils/Duet.hpp +++ b/src/slic3r/Utils/Duet.hpp @@ -25,7 +25,7 @@ public: bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; bool has_auto_discovery() const override { return false; } bool can_test() const override { return true; } - bool can_start_print() const override { return true; } + PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint | PrintHostPostUploadAction::StartSimulation; } std::string get_host() const override { return host; } private: @@ -39,7 +39,7 @@ private: std::string timestamp_str() const; ConnectionType connect(wxString &msg) const; void disconnect(ConnectionType connectionType) const; - bool start_print(wxString &msg, const std::string &filename, ConnectionType connectionType) const; + bool start_print(wxString &msg, const std::string &filename, ConnectionType connectionType, bool simulationMode) const; int get_err_code_from_body(const std::string &body) const; }; diff --git a/src/slic3r/Utils/FlashAir.hpp b/src/slic3r/Utils/FlashAir.hpp index 181405d469..14e3f00156 100644 --- a/src/slic3r/Utils/FlashAir.hpp +++ b/src/slic3r/Utils/FlashAir.hpp @@ -26,7 +26,7 @@ public: bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; bool has_auto_discovery() const override { return false; } bool can_test() const override { return true; } - bool can_start_print() const override { return false; } + PrintHostPostUploadActions get_post_upload_actions() const override { return {}; } std::string get_host() const override { return host; } private: diff --git a/src/slic3r/Utils/MKS.cpp b/src/slic3r/Utils/MKS.cpp new file mode 100644 index 0000000000..80a79537d5 --- /dev/null +++ b/src/slic3r/Utils/MKS.cpp @@ -0,0 +1,150 @@ +#include "MKS.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "libslic3r/PrintConfig.hpp" +#include "slic3r/GUI/GUI.hpp" +#include "slic3r/GUI/I18N.hpp" +#include "slic3r/GUI/MsgDialog.hpp" +#include "Http.hpp" + +namespace fs = boost::filesystem; +namespace pt = boost::property_tree; + +namespace Slic3r { + +MKS::MKS(DynamicPrintConfig* config) : + m_host(config->opt_string("print_host")), m_console_port("8080") +{} + +const char* MKS::get_name() const { return "MKS"; } + +bool MKS::test(wxString& msg) const +{ + Utils::TCPConsole console(m_host, m_console_port); + + console.enqueue_cmd("M105"); + bool ret = console.run_queue(); + + if (!ret) + msg = wxString::FromUTF8(console.error_message().c_str()); + + return ret; +} + +wxString MKS::get_test_ok_msg() const +{ + return _(L("Connection to MKS works correctly.")); +} + +wxString MKS::get_test_failed_msg(wxString& msg) const +{ + return GUI::from_u8((boost::format("%s: %s") + % _utf8(L("Could not connect to MKS")) + % std::string(msg.ToUTF8())).str()); +} + +bool MKS::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const +{ + bool res = true; + + auto upload_cmd = get_upload_url(upload_data.upload_path.string()); + BOOST_LOG_TRIVIAL(info) << boost::format("MKS: Uploading file %1%, filepath: %2%, print: %3%, command: %4%") + % upload_data.source_path + % upload_data.upload_path + % (upload_data.post_action == PrintHostPostUploadAction::StartPrint) + % upload_cmd; + + auto http = Http::post(std::move(upload_cmd)); + http.set_post_body(upload_data.source_path); + + http.on_complete([&](std::string body, unsigned status) { + BOOST_LOG_TRIVIAL(debug) << boost::format("MKS: File uploaded: HTTP %1%: %2%") % status % body; + + int err_code = get_err_code_from_body(body); + if (err_code != 0) { + BOOST_LOG_TRIVIAL(error) << boost::format("MKS: Request completed but error code was received: %1%") % err_code; + error_fn(format_error(body, L("Unknown error occured"), 0)); + res = false; + } + else if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) { + wxString errormsg; + res = start_print(errormsg, upload_data.upload_path.string()); + if (!res) { + error_fn(std::move(errormsg)); + } + } + }) + .on_error([&](std::string body, std::string error, unsigned status) { + BOOST_LOG_TRIVIAL(error) << boost::format("MKS: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body; + error_fn(format_error(body, error, status)); + res = false; + }) + .on_progress([&](Http::Progress progress, bool& cancel) { + prorgess_fn(std::move(progress), cancel); + if (cancel) { + // Upload was canceled + BOOST_LOG_TRIVIAL(info) << "MKS: Upload canceled"; + res = false; + } + }).perform_sync(); + + + return res; +} + +std::string MKS::get_upload_url(const std::string& filename) const +{ + return (boost::format("http://%1%/upload?X-Filename=%2%") + % m_host + % Http::url_encode(filename)).str(); +} + +bool MKS::start_print(wxString& msg, const std::string& filename) const +{ + // For some reason printer firmware does not want to respond on gcode commands immediately after file upload. + // So we just introduce artificial delay to workaround it. + // TODO: Inspect reasons + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + + Utils::TCPConsole console(m_host, m_console_port); + + console.enqueue_cmd(std::string("M23 ") + filename); + console.enqueue_cmd("M24"); + + bool ret = console.run_queue(); + + if (!ret) + msg = wxString::FromUTF8(console.error_message().c_str()); + + return ret; +} + +int MKS::get_err_code_from_body(const std::string& body) const +{ + pt::ptree root; + std::istringstream iss(body); // wrap returned json to istringstream + pt::read_json(iss, root); + + return root.get("err", 0); +} + +} // Slic3r diff --git a/src/slic3r/Utils/MKS.hpp b/src/slic3r/Utils/MKS.hpp new file mode 100644 index 0000000000..22455436ae --- /dev/null +++ b/src/slic3r/Utils/MKS.hpp @@ -0,0 +1,42 @@ +#ifndef slic3r_MKS_hpp_ +#define slic3r_MKS_hpp_ + +#include +#include + +#include "PrintHost.hpp" +#include "TCPConsole.hpp" + +namespace Slic3r { +class DynamicPrintConfig; +class Http; + +class MKS : public PrintHost +{ +public: + explicit MKS(DynamicPrintConfig* config); + ~MKS() override = default; + + const char* get_name() const override; + + bool test(wxString& curl_msg) const override; + wxString get_test_ok_msg() const override; + wxString get_test_failed_msg(wxString& msg) const override; + bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; + bool has_auto_discovery() const override { return false; } + bool can_test() const override { return true; } + PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } + std::string get_host() const override { return m_host; } + +private: + std::string m_host; + std::string m_console_port; + + std::string get_upload_url(const std::string& filename) const; + bool start_print(wxString& msg, const std::string& filename) const; + int get_err_code_from_body(const std::string& body) const; +}; + +} + +#endif diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index 12db505b2a..d9448b62ec 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -137,11 +137,11 @@ bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Erro % url % upload_filename.string() % upload_parent_path.string() - % upload_data.start_print; + % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); auto http = Http::post(std::move(url)); set_auth(http); - http.form_add("print", upload_data.start_print ? "true" : "false") + http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) .on_complete([&](std::string body, unsigned status) { diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp index 481b797313..7945cfdb1a 100644 --- a/src/slic3r/Utils/OctoPrint.hpp +++ b/src/slic3r/Utils/OctoPrint.hpp @@ -28,7 +28,7 @@ public: bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; bool has_auto_discovery() const override { return true; } bool can_test() const override { return true; } - bool can_start_print() const override { return true; } + PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } std::string get_host() const override { return m_host; } const std::string& get_apikey() const { return m_apikey; } const std::string& get_cafile() const { return m_cafile; } @@ -57,7 +57,7 @@ public: wxString get_test_ok_msg() const override; wxString get_test_failed_msg(wxString &msg) const override; - bool can_start_print() const override { return false; } + PrintHostPostUploadActions get_post_upload_actions() const override { return {}; } protected: bool validate_version_text(const boost::optional &version_text) const override; @@ -82,7 +82,7 @@ public: wxString get_test_ok_msg() const override; wxString get_test_failed_msg(wxString& msg) const override; - bool can_start_print() const override { return true; } + PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } protected: bool validate_version_text(const boost::optional& version_text) const override; diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp index 53200a4c9a..86f6101b6d 100644 --- a/src/slic3r/Utils/PrintHost.cpp +++ b/src/slic3r/Utils/PrintHost.cpp @@ -18,6 +18,7 @@ #include "FlashAir.hpp" #include "AstroBox.hpp" #include "Repetier.hpp" +#include "MKS.hpp" #include "../GUI/PrintHostDialogs.hpp" namespace fs = boost::filesystem; @@ -51,6 +52,7 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config) case htAstroBox: return new AstroBox(config); case htRepetier: return new Repetier(config); case htPrusaLink: return new PrusaLink(config); + case htMKS: return new MKS(config); default: return nullptr; } } else { diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp index 35a870b299..dd22e60b7d 100644 --- a/src/slic3r/Utils/PrintHost.hpp +++ b/src/slic3r/Utils/PrintHost.hpp @@ -2,12 +2,14 @@ #define slic3r_PrintHost_hpp_ #include +#include #include #include #include #include +#include #include "Http.hpp" class wxArrayString; @@ -16,6 +18,13 @@ namespace Slic3r { class DynamicPrintConfig; +enum class PrintHostPostUploadAction { + None, + StartPrint, + StartSimulation +}; +using PrintHostPostUploadActions = enum_bitmask; +ENABLE_ENUM_BITMASK_OPERATORS(PrintHostPostUploadAction); struct PrintHostUpload { @@ -24,10 +33,9 @@ struct PrintHostUpload std::string group; - bool start_print = false; + PrintHostPostUploadAction post_action { PrintHostPostUploadAction::None }; }; - class PrintHost { public: @@ -44,7 +52,7 @@ public: virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const = 0; virtual bool has_auto_discovery() const = 0; virtual bool can_test() const = 0; - virtual bool can_start_print() const = 0; + virtual PrintHostPostUploadActions get_post_upload_actions() const = 0; // A print host usually does not support multiple printers, with the exception of Repetier server. virtual bool supports_multiple_printers() const { return false; } virtual std::string get_host() const = 0; diff --git a/src/slic3r/Utils/Repetier.cpp b/src/slic3r/Utils/Repetier.cpp index 094d1baa2c..0569d97fae 100644 --- a/src/slic3r/Utils/Repetier.cpp +++ b/src/slic3r/Utils/Repetier.cpp @@ -107,7 +107,9 @@ bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Error bool res = true; - auto url = upload_data.start_print?make_url((boost::format("printer/job/%1%") % port).str()):make_url((boost::format("printer/model/%1%") % port).str()); + auto url = upload_data.post_action == PrintHostPostUploadAction::StartPrint + ? make_url((boost::format("printer/job/%1%") % port).str()) + : make_url((boost::format("printer/model/%1%") % port).str()); BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, group: %7%") % name @@ -115,17 +117,17 @@ bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Error % url % upload_filename.string() % upload_parent_path.string() - % upload_data.start_print + % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") % upload_data.group; auto http = Http::post(std::move(url)); set_auth(http); - + if (! upload_data.group.empty() && upload_data.group != _utf8(L("Default"))) { http.form_add("group", upload_data.group); } - - if(upload_data.start_print) { + + if(upload_data.post_action == PrintHostPostUploadAction::StartPrint) { http.form_add("name", upload_filename.string()); } diff --git a/src/slic3r/Utils/Repetier.hpp b/src/slic3r/Utils/Repetier.hpp index 0575754178..6f33102604 100644 --- a/src/slic3r/Utils/Repetier.hpp +++ b/src/slic3r/Utils/Repetier.hpp @@ -7,7 +7,6 @@ #include "PrintHost.hpp" - namespace Slic3r { class DynamicPrintConfig; @@ -27,7 +26,7 @@ public: bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; bool has_auto_discovery() const override { return false; } bool can_test() const override { return true; } - bool can_start_print() const override { return true; } + PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } bool supports_multiple_printers() const override { return true; } std::string get_host() const override { return host; } diff --git a/src/slic3r/Utils/TCPConsole.cpp b/src/slic3r/Utils/TCPConsole.cpp new file mode 100644 index 0000000000..3c943cc632 --- /dev/null +++ b/src/slic3r/Utils/TCPConsole.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "TCPConsole.hpp" + +using boost::asio::steady_timer; +using boost::asio::ip::tcp; + +namespace Slic3r { +namespace Utils { + +void TCPConsole::transmit_next_command() +{ + if (m_cmd_queue.empty()) { + m_io_context.stop(); + return; + } + + std::string cmd = m_cmd_queue.front(); + m_cmd_queue.pop_front(); + + BOOST_LOG_TRIVIAL(debug) << boost::format("TCPConsole: transmitting '%3%' to %1%:%2%") + % m_host_name + % m_port_name + % cmd; + + m_send_buffer = cmd + m_newline; + + set_deadline_in(m_write_timeout); + boost::asio::async_write( + m_socket, + boost::asio::buffer(m_send_buffer), + boost::bind(&TCPConsole::handle_write, this, _1, _2) + ); +} + +void TCPConsole::wait_next_line() +{ + set_deadline_in(m_read_timeout); + boost::asio::async_read_until( + m_socket, + m_recv_buffer, + m_newline, + boost::bind(&TCPConsole::handle_read, this, _1, _2) + ); +} + +// TODO: Use std::optional here +std::string TCPConsole::extract_next_line() +{ + char linebuf[1024]; + std::istream is(&m_recv_buffer); + is.getline(linebuf, sizeof(linebuf)); + return is.good() ? linebuf : std::string{}; +} + +void TCPConsole::handle_read( + const boost::system::error_code& ec, + std::size_t bytes_transferred) +{ + m_error_code = ec; + + if (ec) { + BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Can't read from %1%:%2%: %3%") + % m_host_name + % m_port_name + % ec.message(); + + m_io_context.stop(); + } + else { + std::string line = extract_next_line(); + boost::trim(line); + + BOOST_LOG_TRIVIAL(debug) << boost::format("TCPConsole: received '%3%' from %1%:%2%") + % m_host_name + % m_port_name + % line; + + boost::to_lower(line); + + if (line == m_done_string) + transmit_next_command(); + else + wait_next_line(); + } +} + +void TCPConsole::handle_write( + const boost::system::error_code& ec, + std::size_t) +{ + m_error_code = ec; + if (ec) { + BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Can't write to %1%:%2%: %3%") + % m_host_name + % m_port_name + % ec.message(); + + m_io_context.stop(); + } + else { + wait_next_line(); + } +} + +void TCPConsole::handle_connect(const boost::system::error_code& ec) +{ + m_error_code = ec; + + if (ec) { + BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Can't connect to %1%:%2%: %3%") + % m_host_name + % m_port_name + % ec.message(); + + m_io_context.stop(); + } + else { + m_is_connected = true; + BOOST_LOG_TRIVIAL(info) << boost::format("TCPConsole: connected to %1%:%2%") + % m_host_name + % m_port_name; + + transmit_next_command(); + } +} + +void TCPConsole::set_deadline_in(std::chrono::steady_clock::duration d) +{ + m_deadline = std::chrono::steady_clock::now() + d; +} +bool TCPConsole::is_deadline_over() const +{ + return m_deadline < std::chrono::steady_clock::now(); +} + +bool TCPConsole::run_queue() +{ + try { + // TODO: Add more resets and initializations after previous run (reset() method?..) + set_deadline_in(m_connect_timeout); + m_is_connected = false; + m_io_context.restart(); + + auto endpoints = m_resolver.resolve(m_host_name, m_port_name); + + m_socket.async_connect(endpoints->endpoint(), + boost::bind(&TCPConsole::handle_connect, this, _1) + ); + + // Loop until we get any reasonable result. Negative result is also result. + // TODO: Rewrite to more graceful way using deadlime_timer + bool timeout = false; + while (!(timeout = is_deadline_over()) && !m_io_context.stopped()) { + if (m_error_code) { + m_io_context.stop(); + } + m_io_context.run_for(boost::asio::chrono::milliseconds(100)); + } + + // Override error message if timeout is set + if (timeout) + m_error_code = make_error_code(boost::asio::error::timed_out); + + // Socket is not closed automatically by boost + m_socket.close(); + + if (m_error_code) { + // We expect that message is logged in handler + return false; + } + + // It's expected to have empty queue after successful exchange + if (!m_cmd_queue.empty()) { + BOOST_LOG_TRIVIAL(error) << "TCPConsole: command queue is not empty after end of exchange"; + return false; + } + } + catch (std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Exception while talking with %1%:%2%: %3%") + % m_host_name + % m_port_name + % e.what(); + + return false; + } + + return true; +} + +} // namespace Utils +} // namespace Slic3r diff --git a/src/slic3r/Utils/TCPConsole.hpp b/src/slic3r/Utils/TCPConsole.hpp new file mode 100644 index 0000000000..7c0e1d2901 --- /dev/null +++ b/src/slic3r/Utils/TCPConsole.hpp @@ -0,0 +1,91 @@ +#ifndef slic3r_Utils_TCPConsole_hpp_ +#define slic3r_Utils_TCPConsole_hpp_ + +#include +#include +#include +#include +#include +#include + +namespace Slic3r { +namespace Utils { + +using boost::asio::ip::tcp; + +class TCPConsole +{ +public: + TCPConsole() : m_resolver(m_io_context), m_socket(m_io_context) { set_defaults(); } + TCPConsole(const std::string& host_name, const std::string& port_name) : m_resolver(m_io_context), m_socket(m_io_context) + { set_defaults(); set_remote(host_name, port_name); } + ~TCPConsole() = default; + + void set_defaults() + { + m_newline = "\n"; + m_done_string = "ok"; + m_connect_timeout = std::chrono::milliseconds(5000); + m_write_timeout = std::chrono::milliseconds(10000); + m_read_timeout = std::chrono::milliseconds(10000); + } + + void set_line_delimiter(const std::string& newline) { + m_newline = newline; + } + void set_command_done_string(const std::string& done_string) { + m_done_string = done_string; + } + + void set_remote(const std::string& host_name, const std::string& port_name) + { + m_host_name = host_name; + m_port_name = port_name; + } + + bool enqueue_cmd(const std::string& cmd) { + // TODO: Add multithread protection to queue + m_cmd_queue.push_back(cmd); + return true; + } + + bool run_queue(); + std::string error_message() const { return m_error_code.message(); } + +private: + void handle_connect(const boost::system::error_code& ec); + void handle_read(const boost::system::error_code& ec, std::size_t bytes_transferred); + void handle_write(const boost::system::error_code& ec, std::size_t bytes_transferred); + + void transmit_next_command(); + void wait_next_line(); + std::string extract_next_line(); + + void set_deadline_in(std::chrono::steady_clock::duration); + bool is_deadline_over() const; + + std::string m_host_name; + std::string m_port_name; + std::string m_newline; + std::string m_done_string; + std::chrono::steady_clock::duration m_connect_timeout; + std::chrono::steady_clock::duration m_write_timeout; + std::chrono::steady_clock::duration m_read_timeout; + + std::deque m_cmd_queue; + + boost::asio::io_context m_io_context; + tcp::resolver m_resolver; + tcp::socket m_socket; + boost::asio::streambuf m_recv_buffer; + std::string m_send_buffer; + + bool m_is_connected; + boost::system::error_code m_error_code; + std::chrono::steady_clock::time_point m_deadline; +}; + +} // Utils +} // Slic3r + +#endif diff --git a/tests/libslic3r/test_config.cpp b/tests/libslic3r/test_config.cpp index 8dfda789ee..025459d689 100644 --- a/tests/libslic3r/test_config.cpp +++ b/tests/libslic3r/test_config.cpp @@ -220,8 +220,8 @@ SCENARIO("DynamicPrintConfig serialization", "[Config]") { cereal::BinaryOutputArchive oarchive(ss); oarchive(cfg); serialized = ss.str(); - } catch (std::runtime_error &e) { - e.what(); + } catch (const std::runtime_error & /* e */) { + // e.what(); } THEN("Config object contains ini file options.") { @@ -230,8 +230,8 @@ SCENARIO("DynamicPrintConfig serialization", "[Config]") { std::stringstream ss(serialized); cereal::BinaryInputArchive iarchive(ss); iarchive(cfg2); - } catch (std::runtime_error &e) { - e.what(); + } catch (const std::runtime_error & /* e */) { + // e.what(); } REQUIRE(cfg == cfg2); } diff --git a/tests/libslic3r/test_indexed_triangle_set.cpp b/tests/libslic3r/test_indexed_triangle_set.cpp index 7e2d511c77..0bb85b7ed0 100644 --- a/tests/libslic3r/test_indexed_triangle_set.cpp +++ b/tests/libslic3r/test_indexed_triangle_set.cpp @@ -117,15 +117,18 @@ static float triangle_area(const Vec3crd &triangle_inices, const std::vector its_sample_surface(const indexed_triangle_set &its, double sample_per_mm2, - std::mt19937 random_generator = create_random_generator()) + std::mt19937 random_generator) // = create_random_generator()) { std::vector samples; std::uniform_real_distribution rand01(0.f, 1.f); diff --git a/tests/slic3rutils/CMakeLists.txt b/tests/slic3rutils/CMakeLists.txt index ef4287b6cb..e1ac113aef 100644 --- a/tests/slic3rutils/CMakeLists.txt +++ b/tests/slic3rutils/CMakeLists.txt @@ -4,7 +4,14 @@ add_executable(${_TEST_NAME}_tests ) target_link_libraries(${_TEST_NAME}_tests test_common libslic3r_gui libslic3r) +if (MSVC) + target_link_libraries(${_TEST_NAME}_tests Setupapi.lib) +endif () set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests") +if (WIN32) + prusaslicer_copy_dlls(${_TEST_NAME}_tests) +endif() + # catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ") add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests "${CATCH_EXTRA_ARGS} exclude:[NotWorking]")