diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 133a8aa84..74dea387a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ ### Version -_Version of Slic3r used goes here_ +_Version of Slic3r Prusa Edition used goes here_ _Use `About->About Slic3r` for release versions_ @@ -7,6 +7,10 @@ _For -dev versions, use `git describe --tag` or get the hash value for the versi ### Operating system type + version _What OS are you using, and state any version #s_ +_In case of 3D rendering issues, please attach the content of menu Help -> System Info dialog_ + +### 3D printer brand / version + firmware version (if known) +_What 3D printer brand / version are you printing on, is it a stock model or did you modify the printer, what firmware is running on your printer, version of the firmware #s_ ### Behavior * _Describe the problem_ @@ -18,5 +22,5 @@ _What OS are you using, and state any version #s_ _Is this a new feature request?_ -#### STL/Config (.ZIP) where problem occurs -_Upload a zipped copy of an STL and your config (`File -> Export Config`)_ +#### Project File (.3MF) where problem occurs +_Upload a Slic3r PE Project File (.3MF) (`Plater -> Export plate as 3MF` for Slic3r PE 1.41.2 and older, `File -> Save` / `Save Project` for Slic3r PE 1.42.0-alpha and newer)_ diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e42e24e9..90ebd1e5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,9 +86,8 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) if(NOT WIN32) - # Add DEBUG flags for the debug builds in a way the Visual Studio adds these flags. + # Add DEBUG flags to debug builds. add_compile_options("$<$:-DDEBUG>") - add_compile_options("$<$:-D_DEBUG>") endif() # To be able to link libslic3r with the Perl XS module. diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 069521ee0..b6772c877 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -73,8 +73,8 @@ add_library(libslic3r STATIC GCode/CoolingBuffer.hpp GCode/PostProcessor.cpp GCode/PostProcessor.hpp - GCode/PressureEqualizer.cpp - GCode/PressureEqualizer.hpp +# GCode/PressureEqualizer.cpp +# GCode/PressureEqualizer.hpp GCode/PreviewData.cpp GCode/PreviewData.hpp GCode/PrintExtents.cpp diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 9a9020b56..482d5dc72 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -662,10 +662,14 @@ void GCode::_do_export(Print &print, FILE *file) m_cooling_buffer = make_unique(*this); if (print.config().spiral_vase.value) m_spiral_vase = make_unique(print.config()); +#ifdef HAS_PRESSURE_EQUALIZER if (print.config().max_volumetric_extrusion_rate_slope_positive.value > 0 || print.config().max_volumetric_extrusion_rate_slope_negative.value > 0) m_pressure_equalizer = make_unique(&print.config()); m_enable_extrusion_role_markers = (bool)m_pressure_equalizer; +#else /* HAS_PRESSURE_EQUALIZER */ + m_enable_extrusion_role_markers = false; +#endif /* HAS_PRESSURE_EQUALIZER */ // Write information on the generator. _write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str()); @@ -918,8 +922,10 @@ void GCode::_do_export(Print &print, FILE *file) this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), © - object.copies().data()); print.throw_if_canceled(); } +#ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) _write(file, m_pressure_equalizer->process("", true)); +#endif /* HAS_PRESSURE_EQUALIZER */ ++ finished_objects; // Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed. // Reset it when starting another object from 1st layer. @@ -975,8 +981,10 @@ void GCode::_do_export(Print &print, FILE *file) this->process_layer(file, print, layer.second, layer_tools, size_t(-1)); print.throw_if_canceled(); } +#ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) _write(file, m_pressure_equalizer->process("", true)); +#endif /* HAS_PRESSURE_EQUALIZER */ if (m_wipe_tower) // Purge the extruder, pull out the active filament. _write(file, m_wipe_tower->finalize(*this)); @@ -1619,9 +1627,8 @@ void GCode::process_layer( unsigned int copy_id = 0; for (const Point © : copies) { - if (this->config().label_printed_objects) { - gcode += ((std::ostringstream&)(std::ostringstream() << "; printing object " << print_object->model_object()->name << " id:" << layer_id << " copy " << copy_id << "\n")).str(); - } + if (this->config().gcode_label_objects) + gcode += std::string("; printing object ") + print_object->model_object()->name + " id:" + std::to_string(layer_id) + " copy " + std::to_string(copy_id) + "\n"; // When starting a new object, use the external motion planner for the first travel move. std::pair this_object_copy(print_object, copy); if (m_last_obj_copy != this_object_copy) @@ -1642,10 +1649,9 @@ void GCode::process_layer( gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[layer_id]); gcode += this->extrude_infill(print, by_region_specific, false); } - if (this->config().label_printed_objects) { - gcode += ((std::ostringstream&)(std::ostringstream() << "; stop printing object " << print_object->model_object()->name << " id:" << layer_id << " copy " << copy_id << "\n")).str(); - } - ++copy_id; + if (this->config().gcode_label_objects) + gcode += std::string("; stop printing object ") + print_object->model_object()->name + " id:" + std::to_string(layer_id) + " copy " + std::to_string(copy_id) + "\n"; + ++ copy_id; } } } @@ -1663,12 +1669,14 @@ void GCode::process_layer( if (m_cooling_buffer) gcode = m_cooling_buffer->process_layer(gcode, layer.id()); +#ifdef HAS_PRESSURE_EQUALIZER // Apply pressure equalization if enabled; // printf("G-code before filter:\n%s\n", gcode.c_str()); if (m_pressure_equalizer) gcode = m_pressure_equalizer->process(gcode.c_str(), false); // printf("G-code after filter:\n%s\n", out.c_str()); - +#endif /* HAS_PRESSURE_EQUALIZER */ + _write(file, gcode); BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << ", time estimator memory: " << diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 697f5ee59..48604af37 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -11,7 +11,6 @@ #include "Print.hpp" #include "PrintConfig.hpp" #include "GCode/CoolingBuffer.hpp" -#include "GCode/PressureEqualizer.hpp" #include "GCode/SpiralVase.hpp" #include "GCode/ToolOrdering.hpp" #include "GCode/WipeTower.hpp" @@ -22,6 +21,10 @@ #include #include +#ifdef HAS_PRESSURE_EQUALIZER +#include "GCode/PressureEqualizer.hpp" +#endif /* HAS_PRESSURE_EQUALIZER */ + namespace Slic3r { // Forward declarations. @@ -306,7 +309,9 @@ protected: std::unique_ptr m_cooling_buffer; std::unique_ptr m_spiral_vase; +#ifdef HAS_PRESSURE_EQUALIZER std::unique_ptr m_pressure_equalizer; +#endif /* HAS_PRESSURE_EQUALIZER */ std::unique_ptr m_wipe_tower; // Heights at which the skirt has already been extruded. diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp index 232bbc249..077a7c56f 100644 --- a/src/libslic3r/GCode/PreviewData.cpp +++ b/src/libslic3r/GCode/PreviewData.cpp @@ -482,14 +482,14 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: } case Extrusion::ColorPrint: { - const auto color_print_cnt = cp_values.size(); + const int color_cnt = (int)tool_colors.size()/4; + + const auto color_print_cnt = (int)cp_values.size(); for (int i = color_print_cnt; i >= 0 ; --i) { - int val = i; - while (val >= GCodePreviewData::Range::Colors_Count) - val -= GCodePreviewData::Range::Colors_Count; - GCodePreviewData::Color color = Range::Default_Colors[val]; - + GCodePreviewData::Color color; + ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (i % color_cnt) * 4), 4 * sizeof(float)); + if (color_print_cnt == 0) { items.emplace_back(Slic3r::I18N::translate(L("Default print color")), color); break; @@ -524,6 +524,12 @@ size_t GCodePreviewData::memory_used() const sizeof(shell) + sizeof(ranges); } +const std::vector& GCodePreviewData::ColorPrintColors() +{ + static std::vector color_print = {"#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6"}; + return color_print; +} + GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2) { return GCodePreviewData::Color(clamp(0.0f, 1.0f, c1.rgba[0] + c2.rgba[0]), diff --git a/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp index 6a214890f..d27f9e697 100644 --- a/src/libslic3r/GCode/PreviewData.hpp +++ b/src/libslic3r/GCode/PreviewData.hpp @@ -217,6 +217,8 @@ public: // Return an estimate of the memory consumed by the time estimator. size_t memory_used() const; + + static const std::vector& ColorPrintColors(); }; GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2); diff --git a/src/libslic3r/GCode/SpiralVase.hpp b/src/libslic3r/GCode/SpiralVase.hpp index 60aa668d8..7872b1d3c 100644 --- a/src/libslic3r/GCode/SpiralVase.hpp +++ b/src/libslic3r/GCode/SpiralVase.hpp @@ -13,7 +13,7 @@ class SpiralVase { SpiralVase(const PrintConfig &config) : enable(false), _config(&config) { - this->_reader.z() = this->_config->z_offset; + this->_reader.z() = (float)this->_config->z_offset; this->_reader.apply_config(*this->_config); }; std::string process_layer(const std::string &gcode); diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index eb41d6139..c423e6213 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -381,22 +381,7 @@ public: Writer& comment_material(WipeTowerPrusaMM::material_type material) { m_gcode += "; material : "; - switch (material) - { - case WipeTowerPrusaMM::PVA: - m_gcode += "#8 (PVA)"; - break; - case WipeTowerPrusaMM::SCAFF: - m_gcode += "#5 (Scaffold)"; - break; - case WipeTowerPrusaMM::FLEX: - m_gcode += "#4 (Flex)"; - break; - default: - m_gcode += "DEFAULT (PLA)"; - break; - } - m_gcode += "\n"; + m_gcode += WipeTowerPrusaMM::to_string(material) + "\n"; return *this; }; @@ -487,6 +472,23 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam return INVALID; } +std::string WipeTowerPrusaMM::to_string(material_type material) +{ + switch (material) { + case PLA: return "PLA"; + case ABS: return "ABS"; + case PET: return "PET"; + case HIPS: return "HIPS"; + case FLEX: return "FLEX"; + case SCAFF: return "SCAFF"; + case EDGE: return "EDGE"; + case NGEN: return "NGEN"; + case PVA: return "PVA"; + case INVALID: + default: return "INVALID"; + } +} + // Returns gcode to prime the nozzles at the front edge of the print bed. WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // print_z of the first layer. diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 42e3417d3..39e51f834 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -38,6 +38,7 @@ public: // Parse material name into material_type. static material_type parse_material(const char *name); + static std::string to_string(material_type material); // x -- x coordinates of wipe tower in mm ( left bottom corner ) // y -- y coordinates of wipe tower in mm ( left bottom corner ) diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index 13f9e7dd7..f64605a9c 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -43,7 +43,7 @@ public: } bool cmd_is(const char *cmd_test) const { const char *cmd = GCodeReader::skip_whitespaces(m_raw.c_str()); - int len = strlen(cmd_test); + size_t len = strlen(cmd_test); return strncmp(cmd, cmd_test, len) == 0 && GCodeReader::is_end_of_word(cmd[len]); } bool extruding(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) > 0; } diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 86bd0d03b..968a3e234 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -549,11 +549,18 @@ void Model::reset_auto_extruder_id() std::string Model::propose_export_file_name() const { + std::string input_file; for (const ModelObject *model_object : this->objects) for (ModelInstance *model_instance : model_object->instances) - if (model_instance->is_printable()) - return model_object->input_file; - return std::string(); + if (model_instance->is_printable()) { + input_file = model_object->name.empty() ? model_object->input_file : model_object->name; + if (! input_file.empty()) + goto end; + // Other instances will produce the same name, skip them. + break; + } +end: + return input_file; } ModelObject::~ModelObject() @@ -1686,7 +1693,7 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO return false; } -#ifdef _DEBUG +#ifndef NDEBUG // Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique. void check_model_ids_validity(const Model &model) { @@ -1732,6 +1739,6 @@ void check_model_ids_equal(const Model &model1, const Model &model2) } } } -#endif /* _DEBUG */ +#endif /* NDEBUG */ } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 0ae238510..ba109246a 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -629,11 +629,11 @@ extern bool model_object_list_extended(const Model &model_old, const Model &mode // than the old ModelObject. extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolume::Type type); -#ifdef _DEBUG +#ifndef NDEBUG // Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique. void check_model_ids_validity(const Model &model); void check_model_ids_equal(const Model &model1, const Model &model2); -#endif /* _DEBUG */ +#endif /* NDEBUG */ } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 1150e45bc..f63b97aae 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -128,8 +128,8 @@ bool Print::invalidate_state_by_config_options(const std::vectorinstances) - if (model_instance->is_printable()) { - input_file = model_object->input_file; - break; - } - if (! input_file.empty()) - break; - } - return (boost::filesystem::path(input_file).parent_path() / this->output_filename()).make_preferred().string(); - } + return (boost::filesystem::path(m_model.propose_export_file_name()).parent_path() / this->output_filename()).make_preferred().string(); // if we were supplied a directory, use it and append our automatically generated filename boost::filesystem::path p(path); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a83268667..8796314c8 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1082,13 +1082,6 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->default_value = new ConfigOptionBool(0); - def = this->add("label_printed_objects", coBool); - def->label = "Label Prints with Object ID"; - def->tooltip = "Enable this to add comments in the G-Code that label print moves with what object they belong. Can be used with Octoprint CancelObject plugin."; - def->cli = "label-printed-objects!"; - def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(0); - def = this->add("gcode_flavor", coEnum); def->label = L("G-code flavor"); def->tooltip = L("Some G/M-code commands, including temperature control and others, are not universal. " @@ -1119,6 +1112,15 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->default_value = new ConfigOptionEnum(gcfRepRap); + def = this->add("gcode_label_objects", coBool); + def->label = "Label objects"; + def->tooltip = "Enable this to add comments into the G-Code labeling print moves with what object they belong to," + " which is useful for the Octoprint CancelObject plugin. This settings is NOT compatible with " + "Single Extruder Multi Material setup and Wipe into Object / Wipe into Infill."; + def->cli = "gcode-label-objects!"; + def->mode = comAdvanced; + def->default_value = new ConfigOptionBool(0); + def = this->add("high_current_on_filament_swap", coBool); def->label = L("High extruder current on filament swap"); def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange" @@ -1439,6 +1441,7 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); +#ifdef HAS_PRESSURE_EQUALIZER def = this->add("max_volumetric_extrusion_rate_slope_positive", coFloat); def->label = L("Max volumetric slope positive"); def->tooltip = L("This experimental setting is used to limit the speed of change in extrusion rate. " @@ -1462,6 +1465,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); +#endif /* HAS_PRESSURE_EQUALIZER */ def = this->add("min_fan_speed", coInts); def->label = L("Min"); @@ -3065,6 +3069,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va "start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start", "seal_position", "vibration_limit", "bed_size", "print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe" +#ifndef HAS_PRESSURE_EQUALIZER + , "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative" +#endif /* HAS_PRESSURE_EQUALIZER */ }; if (ignore.find(opt_key) != ignore.end()) { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 7ad914297..07229b5de 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -20,6 +20,8 @@ #include "libslic3r.h" #include "Config.hpp" +// #define HAS_PRESSURE_EQUALIZER + namespace Slic3r { enum PrinterTechnology @@ -698,13 +700,15 @@ public: ConfigOptionFloats filament_cooling_final_speed; ConfigOptionStrings filament_ramming_parameters; ConfigOptionBool gcode_comments; - ConfigOptionBool label_printed_objects; ConfigOptionEnum gcode_flavor; + ConfigOptionBool gcode_label_objects; ConfigOptionString layer_gcode; ConfigOptionFloat max_print_speed; ConfigOptionFloat max_volumetric_speed; +#ifdef HAS_PRESSURE_EQUALIZER ConfigOptionFloat max_volumetric_extrusion_rate_slope_positive; ConfigOptionFloat max_volumetric_extrusion_rate_slope_negative; +#endif ConfigOptionPercents retract_before_wipe; ConfigOptionFloats retract_length; ConfigOptionFloats retract_length_toolchange; @@ -769,13 +773,15 @@ protected: OPT_PTR(filament_cooling_final_speed); OPT_PTR(filament_ramming_parameters); OPT_PTR(gcode_comments); - OPT_PTR(label_printed_objects); OPT_PTR(gcode_flavor); + OPT_PTR(gcode_label_objects); OPT_PTR(layer_gcode); OPT_PTR(max_print_speed); OPT_PTR(max_volumetric_speed); +#ifdef HAS_PRESSURE_EQUALIZER OPT_PTR(max_volumetric_extrusion_rate_slope_positive); OPT_PTR(max_volumetric_extrusion_rate_slope_negative); +#endif /* HAS_PRESSURE_EQUALIZER */ OPT_PTR(retract_before_wipe); OPT_PTR(retract_length); OPT_PTR(retract_length_toolchange); @@ -810,7 +816,7 @@ protected: class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig { STATIC_PRINT_CONFIG_CACHE_DERIVED(PrintConfig) - PrintConfig() : GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); } + PrintConfig() : MachineEnvelopeConfig(0), GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); } public: double min_object_distance() const; static double min_object_distance(const ConfigBase *config); @@ -891,7 +897,7 @@ public: ConfigOptionFloat exp_time_first; protected: - PrintConfig(int) : GCodeConfig(1) {} + PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {} void initialize(StaticCacheBase &cache, const char *base_ptr) { this->MachineEnvelopeConfig::initialize(cache, base_ptr); diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index be37e1694..b6b69ae27 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -56,3 +56,12 @@ #define ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES (1 && ENABLE_1_42_0_ALPHA4) // Bunch of fixes related to volumes centering #define ENABLE_VOLUMES_CENTERING_FIXES (1 && ENABLE_1_42_0_ALPHA4) + + +//==================== +// 1.42.0.alpha5 techs +//==================== +#define ENABLE_1_42_0_ALPHA5 1 + +// Toolbar items hidden/shown in dependence of the user mode +#define ENABLE_MODE_AWARE_TOOLBAR_ITEMS (1 && ENABLE_1_42_0_ALPHA5) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index d10d9e0eb..6b1df6ab3 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -35,6 +35,27 @@ #include "GUI.hpp" +#ifdef HAS_GLSAFE +void glAssertRecentCallImpl() +{ + GLenum err = glGetError(); + if (err == GL_NO_ERROR) + return; + const char *sErr = 0; + switch (err) { + case GL_INVALID_ENUM: sErr = "Invalid Enum"; break; + case GL_INVALID_VALUE: sErr = "Invalid Value"; break; + case GL_INVALID_OPERATION: sErr = "Invalid Operation"; break; + case GL_STACK_OVERFLOW: sErr = "Stack Overflow"; break; + case GL_STACK_UNDERFLOW: sErr = "Stack Underflow"; break; + case GL_OUT_OF_MEMORY: sErr = "Out Of Memory"; break; + default: sErr = "Unknown"; break; + } + BOOST_LOG_TRIVIAL(error) << "OpenGL error " << (int)err << ": " << sErr; + assert(false); +} +#endif + namespace Slic3r { void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) @@ -81,25 +102,25 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs) if (use_VBOs) { if (! empty()) { - glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id); - glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id); - glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glsafe(glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW)); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0)); this->vertices_and_normals_interleaved.clear(); } if (! this->triangle_indices.empty()) { - glGenBuffers(1, &this->triangle_indices_VBO_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW); + glsafe(glGenBuffers(1, &this->triangle_indices_VBO_id)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); + glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW)); this->triangle_indices.clear(); } if (! this->quad_indices.empty()) { - glGenBuffers(1, &this->quad_indices_VBO_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW); + glsafe(glGenBuffers(1, &this->quad_indices_VBO_id)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); + glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW)); this->quad_indices.clear(); } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } this->shrink_to_fit(); } @@ -107,15 +128,15 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs) void GLIndexedVertexArray::release_geometry() { if (this->vertices_and_normals_interleaved_VBO_id) { - glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id); + glsafe(glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id)); this->vertices_and_normals_interleaved_VBO_id = 0; } if (this->triangle_indices_VBO_id) { - glDeleteBuffers(1, &this->triangle_indices_VBO_id); + glsafe(glDeleteBuffers(1, &this->triangle_indices_VBO_id)); this->triangle_indices_VBO_id = 0; } if (this->quad_indices_VBO_id) { - glDeleteBuffers(1, &this->quad_indices_VBO_id); + glsafe(glDeleteBuffers(1, &this->quad_indices_VBO_id)); this->quad_indices_VBO_id = 0; } this->clear(); @@ -125,42 +146,42 @@ void GLIndexedVertexArray::release_geometry() void GLIndexedVertexArray::render() const { if (this->vertices_and_normals_interleaved_VBO_id) { - glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id); - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); } else { - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3)); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data())); } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); if (this->indexed()) { if (this->vertices_and_normals_interleaved_VBO_id) { // Render using the Vertex Buffer Objects. if (this->triangle_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id); - glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr)); } if (this->quad_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id); - glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); + glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr)); } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } else { // Render in an immediate mode. if (! this->triangle_indices.empty()) - glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data()); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data())); if (! this->quad_indices.empty()) - glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data()); + glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data())); } } else - glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6)); + glsafe(glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6))); if (this->vertices_and_normals_interleaved_VBO_id) - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(glDisableClientState(GL_NORMAL_ARRAY)); } void GLIndexedVertexArray::render( @@ -173,35 +194,35 @@ void GLIndexedVertexArray::render( if (this->vertices_and_normals_interleaved_VBO_id) { // Render using the Vertex Buffer Objects. - glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id); - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); if (this->triangle_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id); - glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4))); } if (this->quad_indices_size > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id); - glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id)); + glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4))); } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } else { // Render in an immediate mode. - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3)); + glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data())); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); if (! this->triangle_indices.empty()) - glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first)); + glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first))); if (! this->quad_indices.empty()) - glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first)); + glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first))); } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glsafe(glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(glDisableClientState(GL_NORMAL_ARRAY)); } const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; @@ -231,6 +252,7 @@ GLVolume::GLVolume(float r, float g, float b, float a) , is_modifier(false) , is_wipe_tower(false) , is_extrusion_path(false) + , force_transparent(false) , tverts_range(0, size_t(-1)) , qverts_range(0, size_t(-1)) { @@ -272,6 +294,9 @@ void GLVolume::set_render_color() set_render_color(OUTSIDE_COLOR, 4); else set_render_color(color, 4); + + if (force_transparent) + render_color[3] = color[3]; } void GLVolume::set_color_from_model_volume(const ModelVolume *model_volume) @@ -375,15 +400,15 @@ void GLVolume::render() const if (!is_active) return; - ::glCullFace(GL_BACK); - ::glPushMatrix(); + glsafe(::glCullFace(GL_BACK)); + glsafe(::glPushMatrix()); - ::glMultMatrixd(world_matrix().data()); + glsafe(::glMultMatrixd(world_matrix().data())); if (this->indexed_vertex_array.indexed()) this->indexed_vertex_array.render(this->tverts_range, this->qverts_range); else this->indexed_vertex_array.render(); - ::glPopMatrix(); + glsafe(::glPopMatrix()); } void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) const @@ -398,63 +423,63 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first)); if (n_triangles + n_quads == 0) { - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); if (color_id >= 0) { float color[4]; ::memcpy((void*)color, (const void*)render_color, 4 * sizeof(float)); - ::glUniform4fv(color_id, 1, (const GLfloat*)color); + glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color)); } else - ::glColor4fv(render_color); + glsafe(::glColor4fv(render_color)); if (detection_id != -1) - ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); + glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0)); if (worldmatrix_id != -1) - ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); + glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data())); render(); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); return; } if (color_id >= 0) - ::glUniform4fv(color_id, 1, (const GLfloat*)render_color); + glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)render_color)); else - ::glColor4fv(render_color); + glsafe(::glColor4fv(render_color)); if (detection_id != -1) - ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); + glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0)); if (worldmatrix_id != -1) - ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); + glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data())); - ::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id); - ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)); + glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); - ::glPushMatrix(); + glsafe(::glPushMatrix()); - ::glMultMatrixd(world_matrix().data()); + glsafe(::glMultMatrixd(world_matrix().data())); if (n_triangles > 0) { - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id); - ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id)); + glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4))); } if (n_quads > 0) { - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id); - ::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id)); + glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4))); } - ::glPopMatrix(); + glsafe(::glPopMatrix()); } void GLVolume::render_legacy() const @@ -467,33 +492,33 @@ void GLVolume::render_legacy() const GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first)); if (n_triangles + n_quads == 0) { - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - ::glColor4fv(render_color); + glsafe(::glColor4fv(render_color)); render(); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); return; } - ::glColor4fv(render_color); - ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3); - ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data()); + glsafe(::glColor4fv(render_color)); + glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3)); + glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data())); - ::glPushMatrix(); + glsafe(::glPushMatrix()); - ::glMultMatrixd(world_matrix().data()); + glsafe(::glMultMatrixd(world_matrix().data())); if (n_triangles > 0) - ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first); + glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first)); if (n_quads > 0) - ::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first); + glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first)); - ::glPopMatrix(); + glsafe(::glPopMatrix()); } std::vector GLVolumeCollection::load_object( @@ -705,7 +730,7 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) { Transform3d modelview_matrix; - ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); + glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data())); for (GLVolumeWithZ& volume : list) { @@ -722,18 +747,18 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface, std::function filter_func) const { - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glCullFace(GL_BACK); + glsafe(::glCullFace(GL_BACK)); if (disable_cullface) - ::glDisable(GL_CULL_FACE); + glsafe(::glDisable(GL_CULL_FACE)); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); GLint current_program_id; - ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id)); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; GLint z_range_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "z_range") : -1; GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1; @@ -742,13 +767,13 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool GLint print_box_worldmatrix_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1; if (print_box_min_id != -1) - ::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min); + glsafe(::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min)); if (print_box_max_id != -1) - ::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max); + glsafe(::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max)); if (z_range_id != -1) - ::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range); + glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range)); GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, filter_func); for (GLVolumeWithZ& volume : to_render) { @@ -756,29 +781,29 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); } - ::glBindBuffer(GL_ARRAY_BUFFER, 0); - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); if (disable_cullface) - ::glEnable(GL_CULL_FACE); + glsafe(::glEnable(GL_CULL_FACE)); - ::glDisable(GL_BLEND); + glsafe(::glDisable(GL_BLEND)); } void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) const { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(glEnable(GL_BLEND)); + glsafe(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glCullFace(GL_BACK); + glsafe(glCullFace(GL_BACK)); if (disable_cullface) - ::glDisable(GL_CULL_FACE); + glsafe(::glDisable(GL_CULL_FACE)); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + glsafe(glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(glEnableClientState(GL_NORMAL_ARRAY)); GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, std::function()); for (GLVolumeWithZ& volume : to_render) @@ -787,13 +812,13 @@ void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) volume.first->render_legacy(); } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glsafe(glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(glDisableClientState(GL_NORMAL_ARRAY)); if (disable_cullface) - ::glEnable(GL_CULL_FACE); + glsafe(::glEnable(GL_CULL_FACE)); - glDisable(GL_BLEND); + glsafe(glDisable(GL_BLEND)); } bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state) @@ -1718,44 +1743,44 @@ void GLModel::render() const void GLModel::render_VBOs() const { - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glCullFace(GL_BACK); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glCullFace(GL_BACK)); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); GLint current_program_id; - ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id)); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; m_volume.render_VBOs(color_id, -1, -1); - ::glBindBuffer(GL_ARRAY_BUFFER, 0); - ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - ::glDisable(GL_BLEND); + glsafe(::glDisable(GL_BLEND)); } void GLModel::render_legacy() const { - ::glEnable(GL_LIGHTING); - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glsafe(::glEnable(GL_LIGHTING)); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glCullFace(GL_BACK); - ::glEnableClientState(GL_VERTEX_ARRAY); - ::glEnableClientState(GL_NORMAL_ARRAY); + glsafe(::glCullFace(GL_BACK)); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); m_volume.render_legacy(); - ::glDisableClientState(GL_VERTEX_ARRAY); - ::glDisableClientState(GL_NORMAL_ARRAY); + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - ::glDisable(GL_BLEND); - ::glDisable(GL_LIGHTING); + glsafe(::glDisable(GL_BLEND)); + glsafe(::glDisable(GL_LIGHTING)); } bool GLArrow::on_init(bool useVBOs) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index e9340bd6e..2732b5a13 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -11,6 +11,19 @@ #include +#ifndef NDEBUG +#define HAS_GLSAFE +#endif + +#ifdef HAS_GLSAFE +extern void glAssertRecentCallImpl(); +inline void glAssertRecentCall() { glAssertRecentCallImpl(); } +#define glsafe(cmd) do { cmd; glAssertRecentCallImpl(); } while (false) +#else +inline void glAssertRecentCall() { } +#define glsafe(cmd) cmd +#endif + namespace Slic3r { class Print; @@ -282,6 +295,8 @@ public: bool is_wipe_tower; // Wheter or not this volume has been generated from an extrusion path bool is_extrusion_path; + // Wheter or not to always render this volume using its own alpha + bool force_transparent; // Interleaved triangles & normals with indexed triangles & quads. GLIndexedVertexArray indexed_vertex_array; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4af194d1a..0c1952a77 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1888,12 +1888,12 @@ static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); Vec3d axis = angle_axis.axis(); double angle = angle_axis.angle(); -#ifdef _DEBUG +#ifndef NDEBUG if (std::abs(angle) > 1e-8) { assert(std::abs(axis.x()) < 1e-8); assert(std::abs(axis.y()) < 1e-8); } -#endif /* _DEBUG */ +#endif /* NDEBUG */ return (axis.z() < 0) ? -angle : angle; } @@ -2881,7 +2881,7 @@ void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) { } -#ifdef _DEBUG +#ifndef NDEBUG static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); @@ -2915,7 +2915,7 @@ static void verify_instances_rotation_synchronized(const Model &model, const GLV } } } -#endif /* _DEBUG */ +#endif /* NDEBUG */ void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type) { @@ -2975,9 +2975,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType s } } -#ifdef _DEBUG +#ifndef NDEBUG verify_instances_rotation_synchronized(*m_model, *m_volumes); -#endif /* _DEBUG */ +#endif /* NDEBUG */ } void GLCanvas3D::Selection::_synchronize_unselected_volumes() @@ -3843,17 +3843,12 @@ GLCanvas3D::LegendTexture::LegendTexture() { } -bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector& tool_colors, const GLCanvas3D& canvas, bool use_error_colors) +void GLCanvas3D::LegendTexture::fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas, + std::vector>& cp_legend_values) { - reset(); - - // collects items to render - auto title = _(preview_data.get_legend_title()); - - std::vector> cp_legend_values; if (preview_data.extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint) { - const auto& config = wxGetApp().preset_bundle->full_config(); + auto& config = wxGetApp().preset_bundle->project_config; const std::vector& color_print_values = config.option("colorprint_heights")->values; const int values_cnt = color_print_values.size(); if (values_cnt > 0) { @@ -3874,7 +3869,19 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c } } } - const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors, /*color_print_values*/cp_legend_values); +} + +bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector& tool_colors, const GLCanvas3D& canvas, bool use_error_colors) +{ + reset(); + + // collects items to render + auto title = _(preview_data.get_legend_title()); + + std::vector> cp_legend_values; + fill_color_print_legend_values(preview_data, canvas, cp_legend_values); + + const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors, cp_legend_values); unsigned int items_count = (unsigned int)items.size(); if (items_count == 0) @@ -4261,6 +4268,8 @@ unsigned int GLCanvas3D::get_volumes_count() const void GLCanvas3D::reset_volumes() { + _set_current(); + if (!m_volumes.empty()) { m_selection.clear(); @@ -4372,6 +4381,13 @@ bool GLCanvas3D::is_reload_delayed() const void GLCanvas3D::enable_layers_editing(bool enable) { m_layers_editing.set_enabled(enable); + const Selection::IndicesList& idxs = m_selection.get_volume_idxs(); + for (unsigned int idx : idxs) + { + GLVolume* v = m_volumes.volumes[idx]; + if (v->is_modifier) + v->force_transparent = enable; + } } void GLCanvas3D::enable_warning_texture(bool enable) @@ -4500,6 +4516,16 @@ void GLCanvas3D::update_volumes_colors_by_extruder() m_volumes.update_colors_by_extruder(m_config); } +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS +void GLCanvas3D::update_toolbar_items_visibility() +{ + ConfigOptionMode mode = wxGetApp().get_mode(); + m_toolbar.set_item_visible("more", mode != comSimple); + m_toolbar.set_item_visible("fewer", mode != comSimple); + m_dirty = true; +} +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + // Returns a Rect object denoting size and position of the Reset button used by a gizmo. // Returns in either screen or viewport coords. #if !ENABLE_IMGUI @@ -4715,6 +4741,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; + _set_current(); + struct ModelVolumeState { ModelVolumeState(const GLVolume *volume) : model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {} @@ -4769,10 +4797,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } if (printer_technology == ptSLA) { const SLAPrint *sla_print = this->sla_print(); - #ifdef _DEBUG + #ifndef NDEBUG // Verify that the SLAPrint object is synchronized with m_model. check_model_ids_equal(*m_model, sla_print->model()); - #endif /* _DEBUG */ + #endif /* NDEBUG */ sla_support_state.reserve(sla_print->objects().size()); for (const SLAPrintObject *print_object : sla_print->objects()) { SLASupportState state; @@ -5021,6 +5049,8 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const const Print *print = this->fff_print(); if ((m_canvas != nullptr) && (print != nullptr)) { + _set_current(); + std::vector tool_colors = _parse_colors(str_tool_colors); if (m_volumes.empty()) @@ -5058,22 +5088,25 @@ void GLCanvas3D::load_sla_preview() const SLAPrint* print = this->sla_print(); if ((m_canvas != nullptr) && (print != nullptr)) { + _set_current(); _load_shells_sla(); } } -void GLCanvas3D::load_preview(const std::vector& str_tool_colors) +void GLCanvas3D::load_preview(const std::vector& str_tool_colors, const std::vector& color_print_values) { const Print *print = this->fff_print(); if (print == nullptr) return; + _set_current(); + _load_print_toolpaths(); _load_wipe_tower_toolpaths(str_tool_colors); for (const PrintObject* object : print->objects()) { if (object != nullptr) - _load_print_object_toolpaths(*object, str_tool_colors); + _load_print_object_toolpaths(*object, str_tool_colors, color_print_values); } for (GLVolume* volume : m_volumes.volumes) @@ -5083,7 +5116,14 @@ void GLCanvas3D::load_preview(const std::vector& str_tool_colors) _update_toolpath_volumes_outside_state(); _show_warning_texture_if_needed(); - reset_legend_texture(); + if (color_print_values.empty()) + reset_legend_texture(); + else { + auto preview_data = GCodePreviewData(); + preview_data.extrusion.view_type = GCodePreviewData::Extrusion::ColorPrint; + const std::vector tool_colors = _parse_colors(str_tool_colors); + _generate_legend_texture(preview_data, tool_colors); + } } void GLCanvas3D::bind_event_handlers() @@ -5278,6 +5318,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) Point pos(evt.GetX(), evt.GetY()); + if (m_picking_enabled) + _set_current(); + int selected_object_idx = m_selection.get_object_idx(); int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; m_layers_editing.select_object(*m_model, layer_editing_object_idx); @@ -5731,7 +5774,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) void GLCanvas3D::on_paint(wxPaintEvent& evt) { - render(); + if (m_initialized) + m_dirty = true; + else + // Call render directly, so it gets initialized immediately, not from On Idle handler. + this->render(); } void GLCanvas3D::on_key_down(wxKeyEvent& evt) @@ -5782,6 +5829,7 @@ Point GLCanvas3D::get_local_mouse_position() const void GLCanvas3D::reset_legend_texture() { + _set_current(); m_legend_texture.reset(); } @@ -6233,6 +6281,10 @@ bool GLCanvas3D::_init_toolbar() enable_toolbar_item("add", true); +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + update_toolbar_items_visibility(); +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + return true; } @@ -7339,7 +7391,7 @@ void GLCanvas3D::_load_print_toolpaths() volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized); } -void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors) +void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors, const std::vector& color_print_values) { std::vector tool_colors = _parse_colors(str_tool_colors); @@ -7351,6 +7403,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c bool has_infill; bool has_support; const std::vector* tool_colors; + const std::vector* color_print_values; // Number of vertices (each vertex is 6x4=24 bytes long) static const size_t alloc_size_max() { return 131072; } // 3.15MB @@ -7368,7 +7421,15 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; } int volume_idx(int extruder, int feature) const { - return this->color_by_tool() ? std::min(this->number_tools() - 1, std::max(extruder - 1, 0)) : feature; + return this->color_by_color_print() ? 0 : this->color_by_tool() ? std::min(this->number_tools() - 1, std::max(extruder - 1, 0)) : feature; + } + + // For coloring by a color_print(M600), return a parsed color. + bool color_by_color_print() const { return color_print_values!=nullptr; } + const float* color_print_by_layer_idx(const size_t layer_idx) const + { + auto it = std::lower_bound(color_print_values->begin(), color_print_values->end(), layers[layer_idx]->print_z + EPSILON); + return color_tool((it - color_print_values->begin()) % number_tools()); } } ctxt; @@ -7376,6 +7437,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c ctxt.has_infill = print_object.is_step_done(posInfill); ctxt.has_support = print_object.is_step_done(posSupportMaterial); ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors; + ctxt.color_print_values = color_print_values.empty() ? nullptr : &color_print_values; ctxt.shifted_copies = &print_object.copies(); @@ -7400,7 +7462,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start"; //FIXME Improve the heuristics for a grain size. - size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1)); + size_t grain_size = ctxt.color_by_color_print() ? size_t(1) : std::max(ctxt.layers.size() / 16, size_t(1)); tbb::spin_mutex new_volume_mutex; auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* { auto *volume = new GLVolume(color); @@ -7415,7 +7477,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c tbb::blocked_range(0, ctxt.layers.size(), grain_size), [&ctxt, &new_volume](const tbb::blocked_range& range) { GLVolumePtrs vols; - if (ctxt.color_by_tool()) { + if (ctxt.color_by_color_print()) + vols.emplace_back(new_volume(ctxt.color_print_by_layer_idx(range.begin()))); + else if (ctxt.color_by_tool()) { for (size_t i = 0; i < ctxt.number_tools(); ++i) vols.emplace_back(new_volume(ctxt.color_tool(i))); } @@ -7735,11 +7799,15 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat } case GCodePreviewData::Extrusion::ColorPrint: { + const size_t color_cnt = tool_colors.size() / 4; + int val = int(value); - while (val >= GCodePreviewData::Range::Colors_Count) - val -= GCodePreviewData::Range::Colors_Count; + while (val >= color_cnt) + val -= color_cnt; - GCodePreviewData::Color color = GCodePreviewData::Range::Default_Colors[val]; + GCodePreviewData::Color color; + ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float)); + return color; } default: @@ -8391,6 +8459,8 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state() void GLCanvas3D::_show_warning_texture_if_needed() { + _set_current(); + if (_is_any_volume_outside()) { enable_warning_texture(true); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 0d4afa11c..e7bfec0df 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -860,6 +860,8 @@ private: public: LegendTexture(); + void fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas, + std::vector>& cp_legend_values); bool generate(const GCodePreviewData& preview_data, const std::vector& tool_colors, const GLCanvas3D& canvas, bool use_error_colors); @@ -1005,6 +1007,10 @@ public: void update_volumes_colors_by_extruder(); +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + void update_toolbar_items_visibility(); +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + #if !ENABLE_IMGUI Rect get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const; bool gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const; @@ -1030,8 +1036,7 @@ public: void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); void load_sla_preview(); - void load_preview(const std::vector& str_tool_colors); - + void load_preview(const std::vector& str_tool_colors, const std::vector& color_print_values); void bind_event_handlers(); void unbind_event_handlers(); @@ -1136,7 +1141,8 @@ private: // Create 3D thick extrusion lines for object forming extrusions. // Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes, // one for perimeters, one for infill and one for supports. - void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors); + void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors, + const std::vector& color_print_values); // Create 3D thick extrusion lines for wipe tower extrusions void _load_wipe_tower_toolpaths(const std::vector& str_tool_colors); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index b15048ec6..8d04868f8 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -35,6 +35,9 @@ GLToolbarItem::Data::Data() , tooltip("") , sprite_id(-1) , is_toggable(false) +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + , visible(true) +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS { } @@ -45,61 +48,11 @@ GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Dat { } -GLToolbarItem::EState GLToolbarItem::get_state() const -{ - return m_state; -} - -void GLToolbarItem::set_state(GLToolbarItem::EState state) -{ - m_state = state; -} - -const std::string& GLToolbarItem::get_name() const -{ - return m_data.name; -} - -const std::string& GLToolbarItem::get_tooltip() const -{ - return m_data.tooltip; -} - void GLToolbarItem::do_action(wxEvtHandler *target) { wxPostEvent(target, SimpleEvent(m_data.action_event)); } -bool GLToolbarItem::is_enabled() const -{ - return m_state != Disabled; -} - -bool GLToolbarItem::is_disabled() const -{ - return m_state == Disabled; -} - -bool GLToolbarItem::is_hovered() const -{ - return (m_state == Hover) || (m_state == HoverPressed); -} - -bool GLToolbarItem::is_pressed() const -{ - return (m_state == Pressed) || (m_state == HoverPressed); -} - -bool GLToolbarItem::is_toggable() const -{ - return m_data.is_toggable; -} - -bool GLToolbarItem::is_separator() const -{ - return m_type == Separator; -} - void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const { GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(texture_size, border_size, icon_size, gap_size)); @@ -355,6 +308,46 @@ bool GLToolbar::is_item_disabled(const std::string& name) const return false; } +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS +bool GLToolbar::is_item_visible(const std::string& name) const +{ + for (GLToolbarItem* item : m_items) + { + if (item->get_name() == name) + return item->is_visible(); + } + + return false; +} + +void GLToolbar::set_item_visible(const std::string& name, bool visible) +{ + for (GLToolbarItem* item : m_items) + { + if ((item->get_name() == name) && (item->is_visible() != visible)) + { + item->set_visible(visible); + m_layout.dirty = true; + break; + } + } + + // updates separators visibility to avoid having two consecutive + bool any_item_visible = false; + for (GLToolbarItem* item : m_items) + { + if (!item->is_separator()) + any_item_visible |= item->is_visible(); + else + { + item->set_visible(any_item_visible); + any_item_visible = false; + } + } + +} +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent) { if (!m_enabled) @@ -486,6 +479,11 @@ float GLToolbar::get_main_size() const float size = 2.0f * m_layout.border * m_layout.icons_scale; for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) { +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!m_items[i]->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (m_items[i]->is_separator()) size += m_layout.separator_size * m_layout.icons_scale; else @@ -524,6 +522,11 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC for (GLToolbarItem* item : m_items) { +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!item->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (item->is_separator()) left += separator_stride; else @@ -618,6 +621,11 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan for (GLToolbarItem* item : m_items) { +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!item->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (item->is_separator()) top -= separator_stride; else @@ -714,6 +722,11 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3 { ++id; +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!item->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (item->is_separator()) left += separator_stride; else @@ -759,6 +772,11 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& { ++id; +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!item->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (item->is_separator()) top -= separator_stride; else @@ -892,6 +910,11 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const // renders icons for (const GLToolbarItem* item : m_items) { +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!item->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (item->is_separator()) left += separator_stride; else @@ -1018,6 +1041,11 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const // renders icons for (const GLToolbarItem* item : m_items) { +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (!item->is_visible()) + continue; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (item->is_separator()) top -= separator_stride; else diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 37eef5708..951d5e072 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -8,7 +8,6 @@ #include "GLTexture.hpp" #include "Event.hpp" - class wxEvtHandler; namespace Slic3r { @@ -56,6 +55,9 @@ public: unsigned int sprite_id; bool is_toggable; wxEventType action_event; +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + bool visible; +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS Data(); }; @@ -68,21 +70,25 @@ private: public: GLToolbarItem(EType type, const Data& data); - EState get_state() const; - void set_state(EState state); + EState get_state() const { return m_state; } + void set_state(EState state) { m_state = state; } - const std::string& get_name() const; - const std::string& get_tooltip() const; + const std::string& get_name() const { return m_data.name; } + const std::string& get_tooltip() const { return m_data.tooltip; } void do_action(wxEvtHandler *target); - bool is_enabled() const; - bool is_disabled() const; - bool is_hovered() const; - bool is_pressed() const; + bool is_enabled() const { return m_state != Disabled; } + bool is_disabled() const { return m_state == Disabled; } + bool is_hovered() const { return (m_state == Hover) || (m_state == HoverPressed); } + bool is_pressed() const { return (m_state == Pressed) || (m_state == HoverPressed); } - bool is_toggable() const; - bool is_separator() const; + bool is_toggable() const { return m_data.is_toggable; } +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + bool is_visible() const { return m_data.visible; } + void set_visible(bool visible) { m_data.visible = visible; } +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + bool is_separator() const { return m_type == Separator; } void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const; @@ -223,6 +229,10 @@ public: bool is_item_pressed(const std::string& name) const; bool is_item_disabled(const std::string& name) const; +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + bool is_item_visible(const std::string& name) const; + void set_item_visible(const std::string& name, bool visible); +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 00b074f7d..57c01a447 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -64,12 +64,6 @@ ObjectList::ObjectList(wxWindow* parent) : init_icons(); - // create popup menus for object and part - create_object_popupmenu(&m_menu_object); - create_part_popupmenu(&m_menu_part); - create_sla_object_popupmenu(&m_menu_sla_object); - create_instance_popupmenu(&m_menu_instance); - // describe control behavior Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { selection_changed(); @@ -106,8 +100,6 @@ ObjectList::ObjectList(wxWindow* parent) : ObjectList::~ObjectList() { - if (m_default_config) - delete m_default_config; } void ObjectList::create_objects_ctrl() @@ -141,6 +133,15 @@ void ObjectList::create_objects_ctrl() wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } +void ObjectList::create_popup_menus() +{ + // create popup menus for object and part + create_object_popupmenu(&m_menu_object); + create_part_popupmenu(&m_menu_part); + create_sla_object_popupmenu(&m_menu_sla_object); + create_instance_popupmenu(&m_menu_instance); +} + void ObjectList::set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; @@ -310,7 +311,7 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item) wxGetApp().plater()->update(); } -void ObjectList::update_name_in_model(const wxDataViewItem& item) +void ObjectList::update_name_in_model(const wxDataViewItem& item) const { const int obj_idx = m_objects_model->GetObjectIdByItem(item); if (obj_idx < 0) return; @@ -421,9 +422,6 @@ void ObjectList::show_context_menu() if (multiple_selection() && selected_instances_of_same_object()) { wxGetApp().plater()->PopupMenu(&m_menu_instance); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId()); return; } @@ -442,12 +440,6 @@ void ObjectList::show_context_menu() append_menu_item_settings(menu); wxGetApp().plater()->PopupMenu(menu); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split->GetId()); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId()); } } @@ -755,10 +747,8 @@ void ObjectList::get_settings_choice(const wxString& category_name) const ConfigOption* option = from_config.option(opt_key); if (!option) { // if current option doesn't exist in prints.get_edited_preset(), - // get it from m_default_config - if (m_default_config) delete m_default_config; - m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false)); - option = m_default_config->option(opt_key); + // get it from default config values + option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key); } m_config->set_key_value(opt_key, option->clone()); } @@ -782,10 +772,8 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) const ConfigOption* option = from_config.option(opt_key); if (!option) { // if current option doesn't exist in prints.get_edited_preset(), - // get it from m_default_config - if (m_default_config) delete m_default_config; - m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false)); - option = m_default_config->option(opt_key); + // get it from default config values + option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key); } m_config->set_key_value(opt_key, option->clone()); } @@ -964,8 +952,30 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu) [this](wxCommandEvent&) { split_instances(); }, "", menu); } +void ObjectList::append_menu_item_rename(wxMenu* menu) +{ + append_menu_item(menu, wxID_ANY, _(L("Rename")), "", + [this](wxCommandEvent&) { rename_item(); }, "", menu); + menu->AppendSeparator(); +} + +void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu) +{ + if (!is_windows10()) + return; + append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "", + [this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu); + menu->AppendSeparator(); +} + void ObjectList::create_object_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + + append_menu_item_fix_through_netfabb(menu); + // Split object to parts m_menu_item_split = append_menu_item_split(menu); menu->AppendSeparator(); @@ -973,16 +983,30 @@ void ObjectList::create_object_popupmenu(wxMenu *menu) // rest of a object_menu will be added later in: // - append_menu_items_add_volume() -> for "Add (volumes)" // - append_menu_item_settings() -> for "Add (settings)" + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(is_splittable()); }, m_menu_item_split->GetId()); } void ObjectList::create_sla_object_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + + append_menu_item_fix_through_netfabb(menu); // rest of a object_sla_menu will be added later in: // - append_menu_item_settings() -> for "Add (settings)" } void ObjectList::create_part_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + + append_menu_item_fix_through_netfabb(menu); + m_menu_item_split_part = append_menu_item_split(menu); // Append change part type @@ -991,11 +1015,17 @@ void ObjectList::create_part_popupmenu(wxMenu *menu) // rest of a object_sla_menu will be added later in: // - append_menu_item_settings() -> for "Add (settings)" + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId()); } void ObjectList::create_instance_popupmenu(wxMenu*menu) { m_menu_item_split_instances = append_menu_item_instance_to_object(menu); + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId()); } wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu) @@ -2052,6 +2082,66 @@ void ObjectList::split_instances() instances_to_separated_object(obj_idx, inst_idxs); } +void ObjectList::rename_item() +{ + const wxDataViewItem item = GetSelection(); + if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject))) + return ; + + const wxString new_name = wxGetTextFromUser(_(L("Enter new name"))+":", _(L("Renaming")), + m_objects_model->GetName(item), this); + + if (new_name.IsEmpty()) + return; + + bool is_unusable_symbol = false; + std::string chosen_name = Slic3r::normalize_utf8_nfc(new_name.ToUTF8()); + const char* unusable_symbols = "<>:/\\|?*\""; + for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { + if (chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) { + is_unusable_symbol = true; + } + } + + if (is_unusable_symbol) { + show_error(this, _(L("The supplied name is not valid;")) + "\n" + + _(L("the following characters are not allowed:")) + " <>:/\\|?*\""); + return; + } + + // The icon can't be edited so get its old value and reuse it. + wxVariant valueOld; + m_objects_model->GetValue(valueOld, item, 0); + + PrusaDataViewBitmapText bmpText; + bmpText << valueOld; + + // But replace the text with the value entered by user. + bmpText.SetText(new_name); + + wxVariant value; + value << bmpText; + m_objects_model->SetValue(value, item, 0); + m_objects_model->ItemChanged(item); + + update_name_in_model(item); +} + +void ObjectList::fix_through_netfabb() const +{ + const wxDataViewItem item = GetSelection(); + if (!item) + return; + + ItemType type = m_objects_model->GetItemType(item); + + if (type & itObject) + wxGetApp().plater()->fix_through_netfabb(m_objects_model->GetIdByItem(item)); + else if (type & itVolume) + wxGetApp().plater()->fix_through_netfabb(m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)), + m_objects_model->GetVolumeIdByItem(item)); +} + void ObjectList::ItemValueChanged(wxDataViewEvent &event) { if (event.GetColumn() == 0) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 93a3ba60f..e572bec82 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -97,9 +97,6 @@ class ObjectList : public wxDataViewCtrl } m_dragged_data; wxBoxSizer *m_sizer {nullptr}; - - DynamicPrintConfig *m_default_config {nullptr}; - wxWindow *m_parent {nullptr}; wxBitmap m_bmp_modifiermesh; @@ -153,6 +150,7 @@ public: void create_objects_ctrl(); + void create_popup_menus(); wxDataViewColumn* create_objects_list_extruder_column(int extruders_count); void update_objects_list_extruder_column(int extruders_count); // show/hide "Extruder" column for Objects List @@ -160,7 +158,7 @@ public: // update extruder in current config void update_extruder_in_config(const wxDataViewItem& item); // update changed name in the object model - void update_name_in_model(const wxDataViewItem& item); + void update_name_in_model(const wxDataViewItem& item) const; void update_extruder_values_for_items(const int max_extruder); void init_icons(); @@ -181,6 +179,8 @@ public: wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu); + void append_menu_item_rename(wxMenu* menu); + void append_menu_item_fix_through_netfabb(wxMenu* menu); void create_object_popupmenu(wxMenu *menu); void create_sla_object_popupmenu(wxMenu*menu); void create_part_popupmenu(wxMenu*menu); @@ -262,7 +262,8 @@ public: void instances_to_separated_object(const int obj_idx, const std::set& inst_idx); void split_instances(); - + void rename_item(); + void fix_through_netfabb() const; private: void OnChar(wxKeyEvent& event); void OnContextMenu(wxDataViewEvent &event); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 53ca52cb6..0ad6c3562 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -139,6 +139,14 @@ void View3D::mirror_selection(Axis axis) m_canvas->mirror_selection(axis); } +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS +void View3D::update_toolbar_items_visibility() +{ + if (m_canvas != nullptr) + m_canvas->update_toolbar_items_visibility(); +} +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS + void View3D::enable_toolbar_item(const std::string& name, bool enable) { if (m_canvas != nullptr) @@ -558,6 +566,7 @@ void Preview::create_double_slider() m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type; m_preferred_color_mode = "feature"; } + reload_print(); }); } @@ -728,10 +737,22 @@ void Preview::load_print_as_fff() m_preferred_color_mode = "tool_or_feature"; } + bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty(); // Collect colors per extruder. std::vector colors; - bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty(); - if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool)) + std::vector color_print_values = {}; + // set color print values, if it si selected "ColorPrint" view type + if (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint) + { + colors = GCodePreviewData::ColorPrintColors(); + if (! gcode_preview_data_valid) { + //FIXME accessing full_config() is pretty expensive. + // Only initialize color_print_values for the initial preview, not for the full preview where the color_print_values is extracted from the G-code. + const auto& config = wxGetApp().preset_bundle->project_config; + color_print_values = config.option("colorprint_heights")->values; + } + } + else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) ) { const ConfigOptionStrings* extruders_opt = dynamic_cast(m_config->option("extruder_colour")); const ConfigOptionStrings* filamemts_opt = dynamic_cast(m_config->option("filament_colour")); @@ -748,8 +769,9 @@ void Preview::load_print_as_fff() color = "#FFFFFF"; } - colors.push_back(color); + colors.emplace_back(color); } + color_print_values.clear(); } if (IsShown()) @@ -759,7 +781,7 @@ void Preview::load_print_as_fff() m_canvas->load_gcode_preview(*m_gcode_preview_data, colors); else // Load the initial preview based on slices, not the final G-code. - m_canvas->load_preview(colors); + m_canvas->load_preview(colors, color_print_values); show_hide_ui_elements(gcode_preview_data_valid ? "full" : "simple"); // recalculates zs and update sliders accordingly std::vector zs = m_canvas->get_current_print_zs(true); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index d4410c589..49dbed44d 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -58,6 +58,9 @@ public: void delete_selected(); void mirror_selection(Axis axis); +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + void update_toolbar_items_visibility(); +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS void enable_toolbar_item(const std::string& name, bool enable); int check_volumes_outside_state() const; diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 23169dde1..3aeda0348 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -44,7 +44,8 @@ KBShortcutsDialog::KBShortcutsDialog() for (auto& sc : m_full_shortcuts) { - auto sizer = sc.first == _(L("Main Shortcuts")) ? l_sizer : r_sizer; +// auto sizer = sc.first == _(L("Main Shortcuts")) ? l_sizer : r_sizer; + auto sizer = sc.second.second == 0 ? l_sizer : r_sizer; wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(hsizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); @@ -61,7 +62,7 @@ KBShortcutsDialog::KBShortcutsDialog() auto grid_sizer = new wxFlexGridSizer(2, 5, 15); sizer->Add(grid_sizer, 0, wxEXPAND | wxLEFT| wxRIGHT, 15); - for (auto pair : sc.second) + for (auto pair : sc.second.first) { auto shortcut = new wxStaticText(panel, wxID_ANY, _(pair.first)); shortcut->SetFont(bold_font); @@ -95,6 +96,8 @@ void KBShortcutsDialog::fill_shortcuts() const std::string alt = "Alt+"; #endif // __WXOSX__ + m_full_shortcuts.reserve(4); + Shortcuts main_shortcuts; main_shortcuts.reserve(25); @@ -122,7 +125,7 @@ void KBShortcutsDialog::fill_shortcuts() main_shortcuts.push_back(Shortcut("?" ,L("Show keyboard shortcuts list"))); main_shortcuts.push_back(Shortcut("Shift+LeftMouse", L("Select multiple object/Move multiple object"))); - m_full_shortcuts.emplace(_(L("Main Shortcuts")), main_shortcuts); + m_full_shortcuts.push_back(std::make_pair( _(L("Main Shortcuts")), std::make_pair(main_shortcuts, 0) )); Shortcuts plater_shortcuts; @@ -138,6 +141,8 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("C", L("Gizmo cut"))); plater_shortcuts.push_back(Shortcut("F", L("Gizmo Place face on bed"))); plater_shortcuts.push_back(Shortcut("L", L("Gizmo SLA support points"))); + plater_shortcuts.push_back(Shortcut("Shift+", L("Press to snap by 5% in Gizmo scale\nor by 1mm in Gizmo move"))); + plater_shortcuts.push_back(Shortcut(alt, L("Press to scale or rotate selected objects\naround their own center"))); plater_shortcuts.push_back(Shortcut("B", L("Zoom to Bed"))); plater_shortcuts.push_back(Shortcut("Z", L("Zoom to all objects in scene, if none selected"))); plater_shortcuts.push_back(Shortcut("Z", L("Zoom to selected object"))); @@ -145,16 +150,40 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("O", L("Zoom out"))); plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo, keep object selection"))); - m_full_shortcuts.emplace(_(L("Plater Shortcuts")), plater_shortcuts); + m_full_shortcuts.push_back(std::make_pair(_(L("Plater Shortcuts")), std::make_pair(plater_shortcuts, 1))); + + +// Shortcuts gizmo_shortcuts; +// gizmo_shortcuts.reserve(2); +// +// gizmo_shortcuts.push_back(Shortcut("Shift+", L("Press to snap by 5% in Gizmo Scale\n or by 1mm in Gizmo Move"))); +// gizmo_shortcuts.push_back(Shortcut(alt, L("Press to scale or rotate selected objects around their own center"))); +// +// m_full_shortcuts.push_back(std::make_pair(_(L("Gizmo Shortcuts")), std::make_pair(gizmo_shortcuts, 1))); Shortcuts preview_shortcuts; - preview_shortcuts.reserve(2); + preview_shortcuts.reserve(4); preview_shortcuts.push_back(Shortcut(L("Arrow Up"), L("Upper Layer"))); preview_shortcuts.push_back(Shortcut(L("Arrow Down"), L("Lower Layer"))); + preview_shortcuts.push_back(Shortcut("U", L("Upper Layer"))); + preview_shortcuts.push_back(Shortcut("D", L("Lower Layer"))); - m_full_shortcuts.emplace(_(L("Preview Shortcuts")), preview_shortcuts); + m_full_shortcuts.push_back(std::make_pair( _(L("Preview Shortcuts")), std::make_pair(preview_shortcuts, 0) )); + + + Shortcuts layers_slider_shortcuts; + layers_slider_shortcuts.reserve(6); + + layers_slider_shortcuts.push_back(Shortcut(L("Arrow Up"), L("Move current slider thump Up"))); + layers_slider_shortcuts.push_back(Shortcut(L("Arrow Down"), L("Move current slider thump Down"))); + layers_slider_shortcuts.push_back(Shortcut(L("Arrow Left"), L("Set upper thumb to current slider thumb"))); + layers_slider_shortcuts.push_back(Shortcut(L("Arrow Right"),L("Set lower thumb to current slider thumb"))); + layers_slider_shortcuts.push_back(Shortcut("+", L("Add color change marker for current layer"))); + layers_slider_shortcuts.push_back(Shortcut("-", L("Delete color change marker for current layer"))); + + m_full_shortcuts.push_back(std::make_pair( _(L("Layers Slider Shortcuts")), std::make_pair(layers_slider_shortcuts, 1) )); } void KBShortcutsDialog::onCloseDialog(wxEvent &) diff --git a/src/slic3r/GUI/KBShortcutsDialog.hpp b/src/slic3r/GUI/KBShortcutsDialog.hpp index 8517544b5..c5f60f0b8 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.hpp +++ b/src/slic3r/GUI/KBShortcutsDialog.hpp @@ -11,11 +11,11 @@ class KBShortcutsDialog : public wxDialog { typedef std::pair Shortcut; typedef std::vector< Shortcut > Shortcuts; - typedef std::map ShortcutsMap; + typedef std::vector< std::pair> > ShortcutsVec; wxString text_info {wxEmptyString}; - ShortcutsMap m_full_shortcuts; + ShortcutsVec m_full_shortcuts; public: KBShortcutsDialog(); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 707d3aec4..233189eb2 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -22,6 +22,7 @@ #include "AppConfig.hpp" #include "PrintHostDialogs.hpp" #include "wxExtensions.hpp" +#include "GUI_ObjectList.hpp" #include "I18N.hpp" #include @@ -132,6 +133,8 @@ void MainFrame::init_tabpanel() wxGetApp().plater_ = m_plater; m_tabpanel->AddPage(m_plater, _(L("Plater"))); + wxGetApp().obj_list()->create_popup_menus(); + // The following event is emited by Tab implementation on config value change. Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 42e404106..428ea07c6 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -896,7 +896,7 @@ std::vector& Sidebar::combos_filament() class PlaterDropTarget : public wxFileDropTarget { public: - PlaterDropTarget(Plater *plater) : plater(plater) {} + PlaterDropTarget(Plater *plater) : plater(plater) { this->SetDefaultAction(wxDragCopy); } virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames); @@ -1031,7 +1031,7 @@ struct Plater::priv void update_restart_background_process(bool force_scene_update, bool force_preview_update); void export_gcode(fs::path output_path, PrintHostJob upload_job); void reload_from_disk(); - void fix_through_netfabb(const int obj_idx); + void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void set_current_panel(wxPanel* panel); @@ -1717,6 +1717,8 @@ void Plater::priv::reset() object_list_changed(); update(); + // The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here + this->sidebar->show_sliced_info_sizer(false); auto& config = wxGetApp().preset_bundle->project_config; config.option("colorprint_heights")->values.clear(); @@ -2104,7 +2106,7 @@ void Plater::priv::reload_from_disk() remove(obj_orig_idx); } -void Plater::priv::fix_through_netfabb(const int obj_idx) +void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { if (obj_idx < 0) return; @@ -2438,6 +2440,8 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ } menu->AppendSeparator(); + sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); + wxMenu* mirror_menu = new wxMenu(); if (mirror_menu == nullptr) return false; @@ -2644,6 +2648,10 @@ bool Plater::priv::can_mirror() const void Plater::priv::update_object_menu() { sidebar->obj_list()->append_menu_items_add_volume(&object_menu); +#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS + if (view3D != nullptr) + view3D->update_toolbar_items_visibility(); +#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS } // Plater / Public @@ -3148,7 +3156,7 @@ void Plater::changed_object(int obj_idx) this->p->schedule_background_process(); } -void Plater::fix_through_netfabb(const int obj_idx) { p->fix_through_netfabb(obj_idx); } +void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); } void Plater::update_object_menu() { p->update_object_menu(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 7b19d6f31..09b7348d5 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -147,7 +147,7 @@ public: void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path()); void reslice(); void changed_object(int obj_idx); - void fix_through_netfabb(const int obj_idx); + void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void send_gcode(); void on_extruders_change(int extruders_count); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 8fc48b58b..1c3cbbb15 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -323,7 +323,10 @@ const std::vector& Preset::print_options() "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", - "max_volumetric_speed", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", + "max_volumetric_speed", +#ifdef HAS_PRESSURE_EQUALIZER + "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", +#endif /* HAS_PRESSURE_EQUALIZER */ "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", @@ -337,7 +340,7 @@ const std::vector& Preset::print_options() , "support_material_contact_distance_top" , "support_material_contact_distance_bottom" , "support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "extruder_clearance_radius", - "extruder_clearance_height", "gcode_comments", "output_filename_format", "post_process", "perimeter_extruder", + "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", @@ -356,7 +359,6 @@ const std::vector& Preset::print_options() , "remove_small_gaps" , "infill_not_connected" , "first_layer_infill_speed" - , "label_printed_objects" , "thin_walls_min_width" }; return s_opts; @@ -1180,7 +1182,7 @@ std::string PresetCollection::name() const case Preset::TYPE_PRINT: return L("print"); case Preset::TYPE_FILAMENT: return L("filament"); case Preset::TYPE_SLA_PRINT: return L("SLA print"); - case Preset::TYPE_SLA_MATERIAL: return L("SLA material"); + case Preset::TYPE_SLA_MATERIAL: return L("SLA material"); case Preset::TYPE_PRINTER: return L("printer"); default: return "invalid"; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 18b205234..2d06ae72b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1081,8 +1081,10 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Autospeed (advanced)"))); optgroup->append_single_option_line("max_print_speed"); optgroup->append_single_option_line("max_volumetric_speed"); +#ifdef HAS_PRESSURE_EQUALIZER optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive"); optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative"); +#endif /* HAS_PRESSURE_EQUALIZER */ page = add_options_page(_(L("Multiple Extruders")), "funnel.png"); optgroup = page->new_optgroup(_(L("Extruders"))); @@ -1154,7 +1156,7 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Output file"))); optgroup->append_single_option_line("gcode_comments"); - optgroup->append_single_option_line("label_printed_objects"); + optgroup->append_single_option_line("gcode_label_objects"); option = optgroup->get_option("output_filename_format"); option.opt.full_width = true; optgroup->append_single_option_line(option); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 827dcc696..d24db63ea 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1867,8 +1867,10 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc) return; } - const std::vector& clr_bytes = Slic3r::GCodePreviewData::Range::Default_Colors[0].as_bytes(); - wxColour clr = wxColour(clr_bytes[0], clr_bytes[1], clr_bytes[2], clr_bytes[3]); + const std::vector& colors = Slic3r::GCodePreviewData::ColorPrintColors(); + const size_t colors_cnt = colors.size(); + + wxColour clr(colors[0]); dc.SetPen(clr); dc.SetBrush(clr); dc.DrawRectangle(main_band); @@ -1876,15 +1878,13 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc) int i = 1; for (auto tick : m_ticks) { - if (i == Slic3r::GCodePreviewData::Range::Colors_Count) + if (i == colors_cnt) i = 0; const wxCoord pos = get_position_from_value(tick); is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) : main_band.SetBottom(pos-1); - const std::vector& clr_b = Slic3r::GCodePreviewData::Range::Default_Colors[i].as_bytes(); - - clr = wxColour(clr_b[0], clr_b[1], clr_b[2], clr_b[3]); + clr = wxColour(colors[i]); dc.SetPen(clr); dc.SetBrush(clr); dc.DrawRectangle(main_band);