diff --git a/resources/profiles/X 4 Series/machine/Qidi X-Plus 4 0.4 nozzle.json b/resources/profiles/X 4 Series/machine/Qidi X-Plus 4 0.4 nozzle.json index 7f0f3c5..b9b906e 100644 --- a/resources/profiles/X 4 Series/machine/Qidi X-Plus 4 0.4 nozzle.json +++ b/resources/profiles/X 4 Series/machine/Qidi X-Plus 4 0.4 nozzle.json @@ -1,4 +1,5 @@ { + "box_id": "0", "type": "machine", "setting_id": "GM001", "name": "X-Plus 4 0.4 nozzle", diff --git a/src/QIDIStudio_app_msvc.cpp b/src/QIDIStudio_app_msvc.cpp index b364dab..2b551c8 100644 --- a/src/QIDIStudio_app_msvc.cpp +++ b/src/QIDIStudio_app_msvc.cpp @@ -42,10 +42,10 @@ public: wc.lpfnWndProc = OpenGLVersionCheck::supports_opengl2_wndproc; wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr); wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); - wc.lpszClassName = L"BambuStudio_opengl_version_check"; + wc.lpszClassName = L"QIDIStudio_opengl_version_check"; wc.style = CS_OWNDC; if (RegisterClass(&wc)) { - HWND hwnd = CreateWindowW(wc.lpszClassName, L"BambuStudio_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); + HWND hwnd = CreateWindowW(wc.lpszClassName, L"QIDIStudio_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); if (hwnd) { message_pump_exit = false; while (GetMessage(&msg, NULL, 0, 0) > 0 && !message_pump_exit) @@ -280,7 +280,7 @@ int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, #endif ); if (qidistu_main == nullptr) { - printf("could not locate the function bambustu_main in QIDIStudio.dll\n"); + printf("could not locate the function qidistu_main in QIDIStudio.dll\n"); return -1; } // argc minus the trailing nullptr of the argv diff --git a/src/libslic3r/FilamentGroup.cpp b/src/libslic3r/FilamentGroup.cpp index 2a9b5b6..7e5d8c2 100644 --- a/src/libslic3r/FilamentGroup.cpp +++ b/src/libslic3r/FilamentGroup.cpp @@ -609,7 +609,7 @@ namespace Slic3r } if (machine_filament_list.empty()) - throw FilamentGroupException(FilamentGroupException::EmptyAmsFilaments,"Empty ams filament in For-Match mode."); + throw FilamentGroupException(FilamentGroupException::EmptyAmsFilaments,"Empty box filament in For-Match mode."); std::map unprintable_limit_indices; // key stores filament idx in used_filament, value stores unprintable extruder extract_unprintable_limit_indices(ctx.model_info.unprintable_filaments, used_filaments, unprintable_limit_indices); diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 9ba4dec..aa4c196 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -1165,7 +1165,7 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first if (nozzle_nums > 1 && !check_tpu_group(used_filaments, filament_maps, print_config)) { int master_extruder_id = print_config->master_extruder_id.value - 1; // to 0 based std::string nozzle_name = master_extruder_id == 0 ? _L("left") : _L("right"); - std::string exception_str = _L("TPU is incompatible with AMS and must be printed seperately in the ") + nozzle_name + _L(" nozzle.\nPlease adjust the filament group accordingly."); + std::string exception_str = _L("TPU is incompatible with BOX and must be printed seperately in the ") + nozzle_name + _L(" nozzle.\nPlease adjust the filament group accordingly."); throw Slic3r::RuntimeError(exception_str); } } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index bf9993c..623db6e 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -992,6 +992,9 @@ static std::vector s_Preset_printer_options { ,"support_box_temp_control" //y60 ,"is_support_3mf" + //y61 + , "box_id" + , "is_support_timelapse" }; static std::vector s_Preset_sla_print_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 63a9bf3..8dc118e 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2013,7 +2013,7 @@ void Print::process(std::unordered_map* slice_time, bool if (!ToolOrdering::check_tpu_group(used_filaments, filament_maps, &m_config)) { int master_extruder_id = m_config.master_extruder_id.value - 1; // to 0 based std::string nozzle_name = master_extruder_id == 0 ? L("left") : L("right"); - std::string exception_str = L("TPU is incompatible with AMS and must be printed seperately in the ") + nozzle_name + L(" nozzle.\nPlease adjust the filament group accordingly."); + std::string exception_str = L("TPU is incompatible with BOX and must be printed seperately in the ") + nozzle_name + L(" nozzle.\nPlease adjust the filament group accordingly."); throw Slic3r::RuntimeError(exception_str); } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 349dcff..df1b13c 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3277,6 +3277,15 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; + //y61 + def = this->add("box_id", coString); + def->set_default_value(new ConfigOptionString()); + def->cli = ConfigOptionDef::nocli; + + def = this->add("is_support_timelapse", coBool); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + def = this->add("printer_variant", coString); //def->label = L("Printer variant"); def->label = "Printer variant"; @@ -3506,8 +3515,8 @@ void PrintConfigDef::init_fff_params() def->cli = ConfigOptionDef::nocli; def = this->add("extruder_ams_count", coStrings); - def->label = "Extruder ams count"; - def->tooltip = "Ams counts of per extruder"; + def->label = "Extruder box count"; + def->tooltip = "BOX counts of per extruder"; def->set_default_value(new ConfigOptionStrings { }); def = this->add("printer_extruder_id", coInts); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index fcbdc6b..87292db 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1307,7 +1307,10 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloats, counter_limit_max)) ((ConfigOptionFloats, hole_limit_min)) ((ConfigOptionFloats, hole_limit_max)) - ((ConfigOptionFloats, filament_prime_volume))) + ((ConfigOptionFloats, filament_prime_volume)) + //y61 + ((ConfigOptionString, box_id)) + ((ConfigOptionBool, is_support_timelapse))) // This object is mapped to Perl as Slic3r::Config::Full. PRINT_CONFIG_CLASS_DERIVED_DEFINE0( diff --git a/src/libslic3r/libslic3r_version.h.in b/src/libslic3r/libslic3r_version.h.in index 3ab5bab..84812a4 100644 --- a/src/libslic3r/libslic3r_version.h.in +++ b/src/libslic3r/libslic3r_version.h.in @@ -9,6 +9,5 @@ //#define SLIC3R_RC_VERSION "@SLIC3R_VERSION@" #define QDT_RELEASE_TO_PUBLIC @QDT_RELEASE_TO_PUBLIC@ #define QDT_INTERNAL_TESTING @QDT_INTERNAL_TESTING@ -#define QDT_RELEASE_TO_DEVELOPER @QDT_RELEASE_TO_DEVELOPER@ #endif /* __SLIC3R_VERSION_H */ diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 1623977..ff583e2 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -38,6 +38,8 @@ set(SLIC3R_GUI_SOURCES GUI/Widgets/ScrolledWindow.hpp GUI/Widgets/StaticBox.cpp GUI/Widgets/StaticBox.hpp + GUI/Widgets/StaticGroup.cpp + GUI/Widgets/StaticGroup.hpp GUI/Widgets/ImageSwitchButton.cpp GUI/Widgets/ImageSwitchButton.hpp GUI/Widgets/SwitchButton.cpp @@ -60,6 +62,10 @@ set(SLIC3R_GUI_SOURCES GUI/Widgets/TempInput.hpp GUI/Widgets/AMSControl.cpp GUI/Widgets/AMSControl.hpp + GUI/Widgets/AMSItem.cpp + GUI/Widgets/AMSItem.hpp + GUI/Widgets/FilamentLoad.cpp + GUI/Widgets/FilamentLoad.hpp GUI/Widgets/FanControl.cpp GUI/Widgets/FanControl.hpp GUI/Widgets/Scrollbar.cpp @@ -103,6 +109,7 @@ set(SLIC3R_GUI_SOURCES GUI/GLShader.hpp GUI/GLCanvas3D.hpp GUI/GLCanvas3D.cpp + GUI/GLEnums.hpp GUI/OpenGLManager.hpp GUI/OpenGLManager.cpp GUI/Selection.hpp @@ -169,6 +176,8 @@ set(SLIC3R_GUI_SOURCES GUI/IMToolbar.cpp GUI/GCodeViewer.hpp GUI/GCodeViewer.cpp + GUI/ImageDPIFrame.cpp + GUI/ImageDPIFrame.hpp GUI/Preferences.cpp GUI/Preferences.hpp GUI/AMSSetting.cpp @@ -279,6 +288,14 @@ set(SLIC3R_GUI_SOURCES GUI/ConfigManipulation.hpp GUI/Field.cpp GUI/Field.hpp + GUI/DragDropPanel.cpp + GUI/DragDropPanel.hpp + GUI/CapsuleButton.cpp + GUI/CapsuleButton.hpp + GUI/FilamentMapPanel.cpp + GUI/FilamentMapPanel.hpp + GUI/FilamentMapDialog.cpp + GUI/FilamentMapDialog.hpp GUI/OptionsGroup.cpp GUI/OptionsGroup.hpp GUI/OG_CustomCtrl.cpp @@ -305,6 +322,12 @@ set(SLIC3R_GUI_SOURCES GUI/SendSystemInfoDialog.hpp GUI/StepMeshDialog.cpp GUI/StepMeshDialog.hpp + GUI/BaseTransparentDPIFrame.cpp + GUI/BaseTransparentDPIFrame.hpp + GUI/SyncAmsInfoDialog.cpp + GUI/SyncAmsInfoDialog.hpp + GUI/SyncBoxInfoDialog.cpp + GUI/SyncBoxInfoDialog.hpp GUI/SurfaceDrag.cpp GUI/SurfaceDrag.hpp GUI/PlateSettingsDialog.cpp @@ -376,6 +399,8 @@ set(SLIC3R_GUI_SOURCES GUI/QDTStatusBar.cpp GUI/QDTStatusBarSend.hpp GUI/QDTStatusBarSend.cpp + GUI/QDTStatusBarPrint.hpp + GUI/QDTStatusBarPrint.cpp GUI/QDTStatusBarBind.hpp GUI/QDTStatusBarBind.cpp GUI/Mouse3DController.cpp @@ -397,6 +422,8 @@ set(SLIC3R_GUI_SOURCES GUI/InstanceCheck.hpp GUI/Search.cpp GUI/Search.hpp + GUI/FilamentGroupPopup.hpp + GUI/FilamentGroupPopup.cpp GUI/NotificationManager.cpp GUI/NotificationManager.hpp GUI/UnsavedChangesDialog.cpp @@ -423,6 +450,8 @@ set(SLIC3R_GUI_SOURCES GUI/ModelMall.cpp GUI/SelectMachine.hpp GUI/SelectMachine.cpp + GUI/SelectMachinePop.hpp + GUI/SelectMachinePop.cpp GUI/SendToPrinter.hpp GUI/SendToPrinter.cpp GUI/AmsMappingPopup.hpp @@ -523,10 +552,14 @@ set(SLIC3R_GUI_SOURCES Utils/FontConfigHelp.hpp Utils/FontUtils.cpp Utils/FontUtils.hpp + Utils/WxFontUtils.hpp + Utils/WxFontUtils.cpp GUI/Filament_web.hpp GUI/Filament_web.cpp ) +add_subdirectory(GUI/DeviceTab) + if(QDT_RELEASE_TO_PUBLIC) list(APPEND SLIC3R_GUI_SOURCES QIDI/QIDINetwork.cpp @@ -587,8 +620,8 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES}) encoding_check(libslic3r_gui) -target_link_libraries(libslic3r_gui libslic3r cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto) -#target_link_libraries(libslic3r_gui libslic3r cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi libcurl OpenSSL::SSL OpenSSL::Crypto ${wxWidgets_LIBRARIES} glfw) +target_link_libraries(libslic3r_gui libslic3r cereal imgui imguizmo minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto) +#target_link_libraries(libslic3r_gui libslic3r cereal imgui imguizmo minilzo GLEW::GLEW OpenGL::GL hidapi libcurl OpenSSL::SSL OpenSSL::Crypto ${wxWidgets_LIBRARIES} glfw) if (MSVC) target_link_libraries(libslic3r_gui Setupapi.lib) diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 05bb705..224a1f3 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -153,44 +153,47 @@ void Bed3D::load_render_colors() void Bed3D::Axes::render() const { - auto render_axis = [this](const Transform3f& transform) { - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixf(transform.data())); - m_arrow.render(); - glsafe(::glPopMatrix()); + auto render_axis = [this](const Transform3d& transform, const std::shared_ptr& shader) { + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_matrix = camera.get_view_matrix(); + const Transform3d view_model_matrix = view_matrix * transform; + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_arrow.render_geometry(); }; if (!m_arrow.is_initialized()) const_cast(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length)); - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; glsafe(::glEnable(GL_DEPTH_TEST)); - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.0f); // x axis const_cast(&m_arrow)->set_color(-1, AXIS_X_COLOR); - render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast()); + render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }), shader); // y axis const_cast(&m_arrow)->set_color(-1, AXIS_Y_COLOR); - render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast()); + render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }), shader); // z axis const_cast(&m_arrow)->set_color(-1, AXIS_Z_COLOR); - render_axis(Geometry::assemble_transform(m_origin).cast()); + render_axis(Geometry::assemble_transform(m_origin), shader); - shader->stop_using(); + wxGetApp().unbind_shader(); glsafe(::glDisable(GL_DEPTH_TEST)); } //QDS: add part plate logic -bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_height, const std::string& custom_model, bool force_as_custom, +bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_model, bool force_as_custom, const Vec2d position, bool with_reset) { /*auto check_texture = [](const std::string& texture) { @@ -228,7 +231,7 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig } //QDS: add position related logic - if (m_bed_shape == printable_area && m_build_volume.printable_height() == printable_height && m_type == type && m_model_filename == model_filename && position == m_position) + if (m_bed_shape == printable_area && m_build_volume.printable_height() == printable_height && m_type == type && m_model_filename == model_filename && position == m_position && m_extruder_shapes == extruder_areas && m_extruder_heights == extruder_heights) // No change, no need to update the UI. return false; @@ -236,16 +239,27 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":current position {%1%,%2%}, new position {%3%, %4%}") % m_position.x() % m_position.y() % position.x() % position.y(); m_position = position; m_bed_shape = printable_area; + m_extruder_shapes = extruder_areas; + m_extruder_heights = extruder_heights; if ((position(0) != 0) || (position(1) != 0)) { Pointfs new_bed_shape; for (const Vec2d& p : m_bed_shape) { Vec2d point(p(0) + m_position.x(), p(1) + m_position.y()); new_bed_shape.push_back(point); } - m_build_volume = BuildVolume { new_bed_shape, printable_height }; + std::vector new_extruder_shapes; + for (const std::vector& shape : m_extruder_shapes) { + std::vector new_extruder_shape; + for (const Vec2d& p : shape) { + Vec2d point(p(0) + m_position.x(), p(1) + m_position.y()); + new_extruder_shape.push_back(point); + } + new_extruder_shapes.push_back(new_extruder_shape); + } + m_build_volume = BuildVolume { new_bed_shape, printable_height, new_extruder_shapes, m_extruder_heights }; } else - m_build_volume = BuildVolume { printable_area, printable_height }; + m_build_volume = BuildVolume { printable_area, printable_height, m_extruder_shapes, m_extruder_heights }; m_type = type; //m_texture_filename = texture_filename; m_model_filename = model_filename; @@ -294,7 +308,7 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig //QDS: add api to set position for partplate related bed void Bed3D::set_position(Vec2d& position) { - set_shape(m_bed_shape, m_build_volume.printable_height(), m_model_filename, false, position, false); + set_shape(m_bed_shape, m_build_volume.printable_height(), m_extruder_shapes, m_extruder_heights, m_model_filename, false, position, false); } void Bed3D::set_axes_mode(bool origin) @@ -394,7 +408,8 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box(bool consider_model_offset) cons void Bed3D::calc_triangles(const ExPolygon& poly) { - if (! m_triangles.set_from_triangles(triangulate_expolygon_2f(poly, NORMALS_UP), GROUND_Z)) + m_triangles.reset(); + if (!m_triangles.init_model_from_poly(triangulate_expolygon_2f(poly, NORMALS_UP), GROUND_Z)) BOOST_LOG_TRIVIAL(error) << "Unable to create bed triangles"; } @@ -538,9 +553,9 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const } if (m_triangles.get_vertices_count() > 0) { - GLShaderProgram* shader = wxGetApp().get_shader("printbed"); + const auto& shader = wxGetApp().get_shader("printbed"); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("transparent_background", bottom); shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg")); @@ -603,7 +618,7 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const if (bottom) glsafe(::glDepthMask(GL_TRUE)); - shader->stop_using(); + wxGetApp().unbind_shader(); } } }*/ @@ -628,8 +643,11 @@ void Bed3D::update_model_offset() const const_cast(m_extended_bounding_box) = calc_extended_bounding_box(); } -GeometryBuffer Bed3D::update_bed_triangles() const +void Bed3D::update_bed_triangles() { + if (m_triangles.is_initialized()) { + return; + } GeometryBuffer new_triangles; Vec3d shift = m_extended_bounding_box.center(); shift(2) = -0.03; @@ -638,7 +656,7 @@ GeometryBuffer Bed3D::update_bed_triangles() const //QDS: TODO: hack for default bed BoundingBoxf3 build_volume; - if (!m_build_volume.valid()) return new_triangles; + if (!m_build_volume.valid()) return; (*model_offset_ptr)(0) = m_build_volume.bounding_volume2d().min.x(); (*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y(); @@ -654,12 +672,9 @@ GeometryBuffer Bed3D::update_bed_triangles() const new_bed_shape.push_back(new_point); } ExPolygon poly{ Polygon::new_scale(new_bed_shape) }; - if (!new_triangles.set_from_triangles(triangulate_expolygon_2f(poly, NORMALS_UP), GROUND_Z)) { - ; - } + calc_triangles(poly); // update extended bounding box const_cast(m_extended_bounding_box) = calc_extended_bounding_box(); - return new_triangles; } void Bed3D::render_model() const @@ -676,20 +691,39 @@ void Bed3D::render_model() const } if (!model->get_filename().empty()) { - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const Camera & camera = wxGetApp().plater()->get_camera(); + const Transform3d &view_matrix = camera.get_view_matrix(); + const Transform3d &projection_matrix = camera.get_projection_matrix(); + const auto& shader = wxGetApp().get_shader("hotbed"); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.0f); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z())); - model->render(); - glsafe(::glPopMatrix()); - shader->stop_using(); + const Transform3d model_matrix = Geometry::assemble_transform(m_model_offset); + shader->set_uniform("volume_world_matrix", model_matrix); + shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); + if (m_build_volume.get_extruder_area_count() > 0) { + const BuildVolume::BuildSharedVolume& shared_volume = m_build_volume.get_shared_volume(); + std::array xy_data = shared_volume.data; + shader->set_uniform("print_volume.type", shared_volume.type); + shader->set_uniform("print_volume.xy_data", xy_data); + std::array zs = shared_volume.zs; + zs[0] = -1; + shader->set_uniform("print_volume.z_data", zs); + } + else { + //use -1 ad a invalid type + shader->set_uniform("print_volume.type", -1); + } + model->render_geometry(); + wxGetApp().unbind_shader(); } } } -void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) const +void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) { if (m_model_filename.empty()) { render_default(bottom); @@ -703,46 +737,37 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) const render_texture(bottom, canvas);*/ } -void Bed3D::render_default(bool bottom) const +void Bed3D::render_default(bool bottom) { bool picking = false; const_cast(&m_texture)->reset(); - + update_bed_triangles(); unsigned int triangles_vcount = m_triangles.get_vertices_count(); - GeometryBuffer default_triangles = update_bed_triangles(); if (triangles_vcount > 0) { + const auto &shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) return; + wxGetApp().bind_shader(shader); + const Camera & camera = wxGetApp().plater()->get_camera(); + const Transform3d &view_matrix = camera.get_view_matrix(); + const Transform3d &projection_matrix = camera.get_projection_matrix(); + shader->set_uniform("view_model_matrix", view_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + bool has_model = !m_model.get_filename().empty(); glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - if (!has_model && !bottom) { - // draw background glsafe(::glDepthMask(GL_FALSE)); - glsafe(::glColor4fv(picking ? PICKING_MODEL_COLOR.data() : (m_is_dark ? DEFAULT_MODEL_COLOR_DARK.data() : DEFAULT_MODEL_COLOR.data()))); - glsafe(::glNormal3d(0.0f, 0.0f, 1.0f)); - glsafe(::glVertexPointer(3, GL_FLOAT, default_triangles.get_vertex_data_size(), (GLvoid*)default_triangles.get_vertices_data())); - glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)triangles_vcount)); + m_triangles.set_color(DEFAULT_MODEL_COLOR); + m_triangles.render_geometry(); glsafe(::glDepthMask(GL_TRUE)); } - /*if (!picking) { - // draw grid - glsafe(::glLineWidth(1.5f * m_scale_factor)); - if (has_model && !bottom) - glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 1.0f)); - else - glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.6f)); - glsafe(::glVertexPointer(3, GL_FLOAT, default_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data())); - glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)m_gridlines.get_vertices_count())); - }*/ - - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisable(GL_BLEND)); + wxGetApp().unbind_shader(); } } diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 5d7f1a9..89e5517 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -91,7 +91,7 @@ private: BoundingBoxf3 m_extended_bounding_box; // Slightly expanded print bed polygon, for collision detection. //Polygon m_polygon; - GeometryBuffer m_triangles; + GLModel m_triangles; //GeometryBuffer m_gridlines; GLTexture m_texture; // temporary texture shown until the main texture has still no levels compressed @@ -105,6 +105,8 @@ private: //QDS: add part plate related logic Vec2d m_position{ Vec2d::Zero() }; std::vector m_bed_shape; + std::vector> m_extruder_shapes; + std::vector m_extruder_heights; bool m_is_dark = false; public: @@ -116,7 +118,7 @@ public: //FIXME if the build volume max print height is updated, this function still returns zero // as this class does not use it, thus there is no need to update the UI. // QDS - bool set_shape(const Pointfs& printable_area, const double printable_height, const std::string& custom_model, bool force_as_custom = false, + bool set_shape(const Pointfs& printable_area, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_model, bool force_as_custom = false, const Vec2d position = Vec2d::Zero(), bool with_reset = true); void set_position(Vec2d& position); @@ -154,7 +156,7 @@ private: void calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox); void update_model_offset() const; //QDS: with offset - GeometryBuffer update_bed_triangles() const; + void update_bed_triangles(); static std::tuple detect_type(const Pointfs& shape); void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes); @@ -162,8 +164,8 @@ private: void render_system(GLCanvas3D& canvas, bool bottom) const; //void render_texture(bool bottom, GLCanvas3D& canvas) const; void render_model() const; - void render_custom(GLCanvas3D& canvas, bool bottom) const; - void render_default(bool bottom) const; + void render_custom(GLCanvas3D& canvas, bool bottom); + void render_default(bool bottom); void release_VBOs(); }; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 2fbda57..c15ca90 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -70,25 +70,6 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char } #endif // HAS_GLSAFE -// QDS -std::vector> get_extruders_colors() -{ - unsigned char rgba_color[4] = {}; - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - std::vector> colors_out(colors.size()); - for (const std::string &color : colors) { - Slic3r::GUI::BitmapCache::parse_color4(color, rgba_color); - size_t color_idx = &color - &colors.front(); - colors_out[color_idx] = { - float(rgba_color[0]) / 255.f, - float(rgba_color[1]) / 255.f, - float(rgba_color[2]) / 255.f, - float(rgba_color[3]) / 255.f, - }; - } - - return colors_out; -} float FullyTransparentMaterialThreshold = 0.1f; float FullTransparentModdifiedToFixAlpha = 0.3f; const float BlackThreshold = 0.2f; @@ -273,17 +254,26 @@ void GLIndexedVertexArray::release_geometry() this->clear(); } -void GLIndexedVertexArray::render() const +void GLIndexedVertexArray::render(const std::shared_ptr& shader) const { assert(this->vertices_and_normals_interleaved_VBO_id != 0); assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); 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)); + int position_id = -1; + int normal_id = -1; + + position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(position_id)); + } + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr)); + glsafe(::glEnableVertexAttribArray(normal_id)); + } // Render using the Vertex Buffer Objects. if (this->triangle_indices_size > 0) { @@ -297,30 +287,50 @@ void GLIndexedVertexArray::render() const glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (position_id != -1) { + glsafe(::glDisableVertexAttribArray(position_id)); + } + if (normal_id != -1) { + glsafe(::glDisableVertexAttribArray(normal_id)); + } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } void GLIndexedVertexArray::render( + const std::shared_ptr& shader, const std::pair& tverts_range, const std::pair& qverts_range) const { - // this method has been called before calling finalize() ? - if (this->vertices_and_normals_interleaved_VBO_id == 0 && !this->vertices_and_normals_interleaved.empty()) + if (0 == vertices_and_normals_interleaved_VBO_id) { + if (!vertices_and_normals_interleaved.empty()) { + BOOST_LOG_TRIVIAL(info) << boost::format("finalize_geometry"); + const_cast(this)->finalize_geometry(true); + } + } + if (0 == vertices_and_normals_interleaved_VBO_id) { return; + } - assert(this->vertices_and_normals_interleaved_VBO_id != 0); - assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); + if (0 == triangle_indices_VBO_id && 0 == quad_indices_VBO_id) { + return; + } // Render using the Vertex Buffer Objects. 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)); + int position_id = -1; + int normal_id = -1; - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(position_id)); + } + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr)); + glsafe(::glEnableVertexAttribArray(normal_id)); + } if (this->triangle_indices_size > 0) { glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); @@ -333,8 +343,12 @@ void GLIndexedVertexArray::render( glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (position_id != -1) { + glsafe(::glDisableVertexAttribArray(position_id)); + } + if (normal_id != -1) { + glsafe(::glDisableVertexAttribArray(normal_id)); + } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } @@ -343,12 +357,21 @@ const float GLVolume::SinkingContours::HalfWidth = 0.25f; void GLVolume::SinkingContours::render() { + const auto& shader = GUI::wxGetApp().get_shader("flat"); + if (!shader) { + return; + } + + GUI::wxGetApp().bind_shader(shader); + update(); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_shift.x(), m_shift.y(), m_shift.z())); - m_model.render(); - glsafe(::glPopMatrix()); + const GUI::Camera& camera = GUI::wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_shift)); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + m_model.render_geometry(); + + GUI::wxGetApp().unbind_shader(); } void GLVolume::SinkingContours::update() @@ -495,12 +518,14 @@ GLVolume::GLVolume(float r, float g, float b, float a, bool create_index_data) , partly_inside(false) , hover(HS_None) , is_modifier(false) + , slice_error(false) , is_wipe_tower(false) , is_extrusion_path(false) , force_transparent(false) , force_native_color(false) , force_neutral_color(false) , force_sinking_contours(false) + , picking(false) , tverts_range(0, size_t(-1)) , qverts_range(0, size_t(-1)) , tverts_range_lod(0, size_t(-1)) @@ -537,7 +562,7 @@ void GLVolume::set_render_color() bool outside = is_outside || is_below_printbed(); if (force_native_color || force_neutral_color) { -#ifdef ENABLE_OUTSIDE_COLOR +#ifdef ENABBLE_OUTSIDE_COLOR if (outside && shader_outside_printer_detection_enabled) set_render_color(OUTSIDE_COLOR); else { @@ -722,9 +747,15 @@ Transform3d GLVolume::world_matrix() const bool GLVolume::is_left_handed() const { - const Vec3d &m1 = m_instance_transformation.get_mirror(); - const Vec3d &m2 = m_volume_transformation.get_mirror(); - return m1.x() * m1.y() * m1.z() * m2.x() * m2.y() * m2.z() < 0.; + // reference page 84 + // link: https://www.realtimerendering.com/ + const auto model_matrix = world_matrix().matrix(); + Eigen::Matrix3d subMatrix = model_matrix.block<3, 3>(0, 0); + const auto det = subMatrix.determinant(); + if (det < 1e-6f) { + return true; + } + return false; } const BoundingBoxf3& GLVolume::transformed_bounding_box() const @@ -795,7 +826,7 @@ void GLVolume::set_range(double min_z, double max_z) this->qverts_range.first = this->offsets[i * 2]; this->tverts_range.first = this->offsets[i * 2 + 1]; // Some layers are above $min_z. Which? - for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i); + for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i); if (i < this->print_zs.size()) { this->qverts_range.second = this->offsets[i * 2]; this->tverts_range.second = this->offsets[i * 2 + 1]; @@ -807,7 +838,7 @@ void GLVolume::set_range(double min_z, double max_z) //QDS: add outline related logic //static unsigned char stencil_data[1284][2944]; -void GLVolume::render(bool with_outline, const std::array& body_color) const +void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const std::array& body_color) const { if (!is_active) return; @@ -815,14 +846,11 @@ void GLVolume::render(bool with_outline, const std::array& body_color) if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - glsafe(::glPushMatrix()); - auto camera = GUI::wxGetApp().plater()->get_camera(); auto zoom = camera.get_zoom(); Transform3d vier_mat = camera.get_view_matrix(); Matrix4d vier_proj_mat = camera.get_projection_matrix().matrix() * vier_mat.matrix(); const std::array &viewport = camera.get_viewport(); - // QDS: add logic for mmu segmentation rendering auto render_body = [&]() { bool color_volume = false; @@ -839,7 +867,7 @@ void GLVolume::render(bool with_outline, const std::array& body_color) if (mv->mmu_segmentation_facets.empty()) break; - std::vector> colors = get_extruders_colors(); + std::vector> colors = GUI::wxGetApp().plater()->get_extruders_colors(); if (colors.size() == 1) { break; } @@ -852,6 +880,7 @@ void GLVolume::render(bool with_outline, const std::array& body_color) std::vector its_per_color; mv->mmu_segmentation_facets.get_facets(*mv, its_per_color); mmuseg_ivas.resize(its_per_color.size()); + for (int idx = 0; idx < its_per_color.size(); idx++) { if (its_per_color[idx].indices.size() > 0) { mmuseg_ivas[idx].load_its_flat_shading(its_per_color[idx]); @@ -864,16 +893,15 @@ void GLVolume::render(bool with_outline, const std::array& body_color) } } while (0); - if (color_volume) { - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); - std::vector> colors = get_extruders_colors(); + const auto shader = GUI::wxGetApp().get_current_shader(); + if (color_volume && !picking) { + std::vector> colors = GUI::wxGetApp().plater()->get_extruders_colors(); //when force_transparent, we need to keep the alpha if (force_native_color && (render_color[3] < 1.0)) { for (int index = 0; index < colors.size(); index ++) colors[index][3] = render_color[3]; } - glsafe(::glMultMatrixd(world_matrix().data())); for (int idx = 0; idx < mmuseg_ivas.size(); idx++) { GLIndexedVertexArray* iva = &mmuseg_ivas[idx]; if (iva->triangle_indices_size == 0 && iva->quad_indices_size == 0) @@ -905,7 +933,7 @@ void GLVolume::render(bool with_outline, const std::array& body_color) } } } - iva->render(this->tverts_range, this->qverts_range); + iva->render(shader, this->tverts_range, this->qverts_range); /*if (force_native_color && (render_color[3] < 1.0)) { BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, tverts_range {%3,%4}, qverts_range{%5%, %6%}") %this %this->name %this->tverts_range.first %this->tverts_range.second @@ -914,20 +942,18 @@ void GLVolume::render(bool with_outline, const std::array& body_color) } } else { - glsafe(::glMultMatrixd(world_matrix().data())); - auto render_which = [this](std::shared_ptr cur) { + auto render_which = [this](std::shared_ptr cur, const std::shared_ptr& shader) { if (cur->vertices_and_normals_interleaved_VBO_id > 0) { - cur->render(tverts_range_lod, qverts_range_lod); + cur->render(shader, tverts_range_lod, qverts_range_lod); } else {// if (cur->vertices_and_normals_interleaved_VBO_id == 0) if (cur->triangle_indices.size() > 0) { cur->finalize_geometry(true); - cur->render(tverts_range_lod, qverts_range_lod); + cur->render(shader, tverts_range_lod, qverts_range_lod); } else { - indexed_vertex_array->render(this->tverts_range, this->qverts_range); + indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } } }; - Transform3d world_tran = world_matrix(); m_lod_update_index++; if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY){ m_lod_update_index = 0; @@ -935,17 +961,17 @@ void GLVolume::render(bool with_outline, const std::array& body_color) m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); } if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small) { - render_which(indexed_vertex_array_small); + render_which(indexed_vertex_array_small, shader); } else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle) { - render_which(indexed_vertex_array_middle); + render_which(indexed_vertex_array_middle, shader); } else { - this->indexed_vertex_array->render(this->tverts_range, this->qverts_range); + this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } } }; //QDS: add logic of outline rendering - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); + const auto shader = GUI::wxGetApp().get_current_shader(); //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader; if (with_outline && shader != nullptr) { @@ -1050,13 +1076,11 @@ void GLVolume::render(bool with_outline, const std::array& body_color) shader->set_uniform("uniform_color", body_color); shader->set_uniform("is_outline", true); - glsafe(::glPopMatrix()); - glsafe(::glPushMatrix()); Transform3d matrix = world_matrix(); Transform3d world_tran = matrix; matrix.scale(scale); - glsafe(::glMultMatrixd(matrix.data())); + shader->set_uniform("view_model_matrix", view_matrix * matrix); m_lod_update_index++; if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY) { m_lod_update_index = 0; @@ -1064,11 +1088,11 @@ void GLVolume::render(bool with_outline, const std::array& body_color) m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); } if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small && indexed_vertex_array_small->vertices_and_normals_interleaved_VBO_id > 0) { - this->indexed_vertex_array_small->render(this->tverts_range_lod, this->qverts_range_lod); + this->indexed_vertex_array_small->render(shader, this->tverts_range_lod, this->qverts_range_lod); } else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle && indexed_vertex_array_middle->vertices_and_normals_interleaved_VBO_id > 0) { - this->indexed_vertex_array_middle->render(this->tverts_range_lod, this->qverts_range_lod); + this->indexed_vertex_array_middle->render(shader, this->tverts_range_lod, this->qverts_range_lod); } else { - this->indexed_vertex_array->render(this->tverts_range, this->qverts_range); + this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name(); shader->set_uniform("is_outline", false); @@ -1085,18 +1109,16 @@ void GLVolume::render(bool with_outline, const std::array& body_color) render_body(); //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, normal render.")%__LINE__; } - glsafe(::glPopMatrix()); if (this->is_left_handed()) glFrontFace(GL_CCW); } //QDS add render for simple case -void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_objects, std::vector> &extruder_colors, bool ban_light) const +void GLVolume::simple_render(const std::shared_ptr& shader, ModelObjectPtrs &model_objects, std::vector> &extruder_colors, bool ban_light) const { if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - glsafe(::glPushMatrix()); bool color_volume = false; ModelObject* model_object = nullptr; @@ -1127,8 +1149,7 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj } } while (0); - if (color_volume) { - glsafe(::glMultMatrixd(world_matrix().data())); + if (color_volume && !picking) { for (int idx = 0; idx < mmuseg_ivas.size(); idx++) { GLIndexedVertexArray& iva = mmuseg_ivas[idx]; if (iva.triangle_indices_size == 0 && iva.quad_indices_size == 0) @@ -1166,15 +1187,13 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj } } } - iva.render(this->tverts_range, this->qverts_range); + iva.render(shader, this->tverts_range, this->qverts_range); } } else { - glsafe(::glMultMatrixd(world_matrix().data())); - this->indexed_vertex_array->render(this->tverts_range, this->qverts_range); + this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } - glsafe(::glPopMatrix()); if (this->is_left_handed()) glFrontFace(GL_CCW); } @@ -1214,7 +1233,7 @@ GLWipeTowerVolume::GLWipeTowerVolume(const std::vector>& co m_colors = colors; } -void GLWipeTowerVolume::render(bool with_outline,const std::array &body_color) const +void GLWipeTowerVolume::render(const Transform3d& view_matrix, bool with_outline,const std::array &body_color) const { if (!is_active) return; @@ -1222,22 +1241,28 @@ void GLWipeTowerVolume::render(bool with_outline,const std::array &bod if (m_colors.size() == 0 || m_colors.size() != iva_per_colors.size()) return; + const auto shader = GUI::wxGetApp().get_current_shader(); + if (!shader) { + return; + } + if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(world_matrix().data())); - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); for (int i = 0; i < m_colors.size(); i++) { - if (shader) { - std::array new_color = adjust_color_for_rendering(m_colors[i]); - shader->set_uniform("uniform_color", new_color); + if (!picking) { + ColorRGBA new_color = adjust_color_for_rendering(m_colors[i]); + std::array final_color; + final_color[0] = new_color.r(); + final_color[1] = new_color.g(); + final_color[2] = new_color.b(); + final_color[3] = new_color.a(); + shader->set_uniform("uniform_color", final_color); } - this->iva_per_colors[i].render(); + this->iva_per_colors[i].render(shader); } - glsafe(::glPopMatrix()); if (this->is_left_handed()) glFrontFace(GL_CCW); } @@ -1288,7 +1313,7 @@ int GLVolumeCollection::load_object_volume( GLVolume& v = *new_volume; v.set_color(color_from_model_volume(*model_volume)); v.name = model_volume->name; - v.is_text_shape = model_volume->get_text_info().m_text.empty(); + v.is_text_shape = model_volume->is_text(); const TriangleMesh* mesh_ptr = model_volume->mesh_ptr(); new_volume->ori_mesh = mesh_ptr; @@ -1448,7 +1473,7 @@ int GLVolumeCollection::load_wipe_tower_preview( if (height == 0.0f) height = 0.1f; - std::vector> extruder_colors = get_extruders_colors(); + std::vector> extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors(); std::vector> colors; GUI::PartPlateList& ppl = GUI::wxGetApp().plater()->get_partplate_list(); std::vector plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true); @@ -1489,6 +1514,49 @@ int GLVolumeCollection::load_wipe_tower_preview( return int(volumes.size() - 1); } +int GLVolumeCollection::load_real_wipe_tower_preview( + int obj_idx, float pos_x, float pos_y, const TriangleMesh& wt_mesh,const TriangleMesh &brim_mesh,bool render_brim, float rotation_angle, bool size_unknown, bool opengl_initialized) +{ + int plate_idx = obj_idx - 1000; + if (wt_mesh.its.vertices.empty()) return int(this->volumes.size() - 1); + + std::vector> extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors(); + GUI::PartPlateList &ppl = GUI::wxGetApp().plater()->get_partplate_list(); + std::vector plate_extruders = ppl.get_plate(plate_idx)->get_extruders(true); + std::vector> colors; + if (!plate_extruders.empty()) { + if (plate_extruders.front() <= extruder_colors.size()) + colors.push_back(extruder_colors[plate_extruders.front() - 1]); + else + colors.push_back(extruder_colors[0]); + } + if (colors.empty()) return int(this->volumes.size() - 1); + volumes.emplace_back(new GLWipeTowerVolume({colors})); + GLWipeTowerVolume &v = *dynamic_cast(volumes.back()); + auto mesh = wt_mesh; + if (render_brim) { + mesh.merge(brim_mesh); + } + if (!colors.empty()) { + v.iva_per_colors.resize(1); + v.iva_per_colors[0].load_mesh(mesh); + v.iva_per_colors[0].finalize_geometry(opengl_initialized); + } + TriangleMesh wipe_tower_shell = mesh.convex_hull_3d(); + v.indexed_vertex_array->load_mesh(wipe_tower_shell); + v.indexed_vertex_array->finalize_geometry(opengl_initialized); + v.set_convex_hull(wipe_tower_shell); + v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0)); + v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle)); + v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0); + v.geometry_id.first = 0; + v.geometry_id.second = wipe_tower_instance_id().id + (obj_idx - 1000); + v.is_wipe_tower = true; + v.shader_outside_printer_detection_enabled = !size_unknown; + return int(volumes.size() - 1); +} + + GLVolume* GLVolumeCollection::new_toolpath_volume(const std::array& rgba, size_t reserve_vbo_floats) { GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats); @@ -1552,19 +1620,22 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo } //QDS: add outline drawing logic -void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, +void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pipeline_stage, + GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d & view_matrix, + const Transform3d& projection_matrix, std::function filter_func, bool with_outline, - const std::array & body_color, - bool partly_inside_enable) const + const std::array & body_color, + bool partly_inside_enable, + std::vector * printable_heights) const { GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func); if (to_render.empty()) return; - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); + const auto shader = GUI::wxGetApp().get_current_shader(); if (shader == nullptr) return; @@ -1574,13 +1645,17 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, } glsafe(::glCullFace(GL_BACK)); - if (disable_cullface) + if (disable_cullface) { glsafe(::glDisable(GL_CULL_FACE)); + } + else { + glsafe(::glEnable(GL_CULL_FACE)); + } auto camera = GUI::wxGetApp().plater()->get_camera(); for (GLVolumeWithIdAndZ& volume : to_render) { auto world_box = volume.first->transformed_bounding_box(); - if (!camera.getFrustum().intersects(world_box, camera.get_type_as_string() == "perspective")) { + if (!camera.getFrustum().intersects(world_box)) { continue; } #if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT @@ -1598,62 +1673,90 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, #endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT // render sinking contours of non-hovered volumes - if (m_show_sinking_contours) - if (volume.first->is_sinking() && !volume.first->is_below_printbed() && - volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { - shader->stop_using(); - volume.first->render_sinking_contours(); - shader->start_using(); + if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { + if (m_show_sinking_contours) + if (volume.first->is_sinking() && !volume.first->is_below_printbed() && + volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { + GUI::wxGetApp().unbind_shader(); + volume.first->render_sinking_contours(); + GUI::wxGetApp().bind_shader(shader); + } + } + + if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { + shader->set_uniform("is_text_shape", volume.first->is_text_shape); + shader->set_uniform("uniform_color", volume.first->render_color); + shader->set_uniform("z_range", m_z_range, 2); + shader->set_uniform("clipping_plane", m_clipping_plane, 4); + //BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") + // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] + // %with_outline%volume.first->selected; + + //QDS set print_volume to render volume + //shader->set_uniform("print_volume.type", static_cast(m_render_volume.type)); + //shader->set_uniform("print_volume.xy_data", m_render_volume.data); + //shader->set_uniform("print_volume.z_data", m_render_volume.zs); + if (printable_heights) { + std::array extruder_printable_heights; + if ((*printable_heights).size() > 0) { + extruder_printable_heights[0] = 2.0f; + extruder_printable_heights[1] = (*printable_heights)[0]; + extruder_printable_heights[2] = (*printable_heights)[1]; + shader->set_uniform("extruder_printable_heights", extruder_printable_heights); + shader->set_uniform("print_volume.xy_data", m_print_volume.data); + } + else { + extruder_printable_heights[0] = 0.0f; + shader->set_uniform("extruder_printable_heights", extruder_printable_heights); + } + } + if (volume.first->partly_inside && partly_inside_enable) { + //only partly inside volume need to be painted with boundary check + shader->set_uniform("print_volume.type", static_cast(m_print_volume.type)); + shader->set_uniform("print_volume.z_data", m_print_volume.zs); + if (!printable_heights || (printable_heights && (*printable_heights).size() == 0)) { + shader->set_uniform("print_volume.xy_data", m_print_volume.data); + } + } + else { + //use -1 ad a invalid type + shader->set_uniform("print_volume.type", -1); } - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + bool enable_support; + int support_threshold_angle = get_selection_support_threshold_angle(enable_support); - shader->set_uniform("is_text_shape", volume.first->is_text_shape); - shader->set_uniform("uniform_color", volume.first->render_color); - shader->set_uniform("z_range", m_z_range, 2); - shader->set_uniform("clipping_plane", m_clipping_plane, 4); - //BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") - // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] - // %with_outline%volume.first->selected; + float normal_z = -::cos(Geometry::deg2rad((float)support_threshold_angle)); - //QDS set print_volume to render volume - //shader->set_uniform("print_volume.type", static_cast(m_render_volume.type)); - //shader->set_uniform("print_volume.xy_data", m_render_volume.data); - //shader->set_uniform("print_volume.z_data", m_render_volume.zs); - - if (volume.first->partly_inside && partly_inside_enable) { - //only partly inside volume need to be painted with boundary check - shader->set_uniform("print_volume.type", static_cast(m_print_volume.type)); - shader->set_uniform("print_volume.xy_data", m_print_volume.data); - shader->set_uniform("print_volume.z_data", m_print_volume.zs); - } - else { - //use -1 ad a invalid type - shader->set_uniform("print_volume.type", -1); - } - - bool enable_support; - int support_threshold_angle = get_selection_support_threshold_angle(enable_support); - - float normal_z = -::cos(Geometry::deg2rad((float) support_threshold_angle)); - - shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); - shader->set_uniform("slope.actived", m_slope.isGlobalActive && !volume.first->is_modifier && !volume.first->is_wipe_tower); - shader->set_uniform("slope.volume_world_normal_matrix", static_cast(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast())); - shader->set_uniform("slope.normal_z", normal_z); + shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); + shader->set_uniform("slope.actived", m_slope.isGlobalActive && !volume.first->is_modifier && !volume.first->is_wipe_tower); + shader->set_uniform("slope.volume_world_normal_matrix", static_cast(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast())); + shader->set_uniform("slope.normal_z", normal_z); #if ENABLE_ENVIRONMENT_MAP - unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id(); - bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1"; - shader->set_uniform("use_environment_tex", use_environment_texture); - if (use_environment_texture) - glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id)); + unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id(); + bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get("use_environment_map") == "1"; + shader->set_uniform("use_environment_tex", use_environment_texture); + if (use_environment_texture) + glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id)); #endif // ENABLE_ENVIRONMENT_MAP - glcheck(); + glcheck(); - //QDS: add outline related logic - volume.first->render(with_outline && volume.first->selected, body_color); + const Transform3d matrix = view_matrix * volume.first->world_matrix(); + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + + //QDS: add outline related logic + auto red_color = std::array({ 1.0f, 0.0f, 0.0f, 1.0f });//slice_error + volume.first->render(view_matrix, with_outline&& volume.first->selected, volume.first->slice_error ? red_color : body_color); + } + else { + if (volume.first->selected) { + shader->set_uniform("u_model_matrix", volume.first->world_matrix()); + volume.first->render(view_matrix, false, body_color); + } + } #if ENABLE_ENVIRONMENT_MAP if (use_environment_texture) @@ -1662,21 +1765,20 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); } - if (m_show_sinking_contours) { - for (GLVolumeWithIdAndZ& volume : to_render) { - // render sinking contours of hovered/displaced volumes - if (volume.first->is_sinking() && !volume.first->is_below_printbed() && - (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { - shader->stop_using(); - glsafe(::glDepthFunc(GL_ALWAYS)); - volume.first->render_sinking_contours(); - glsafe(::glDepthFunc(GL_LESS)); - shader->start_using(); + if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { + if (m_show_sinking_contours) { + for (GLVolumeWithIdAndZ& volume : to_render) { + // render sinking contours of hovered/displaced volumes + if (volume.first->is_sinking() && !volume.first->is_below_printbed() && + (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { + GUI::wxGetApp().unbind_shader(); + glsafe(::glDepthFunc(GL_ALWAYS)); + volume.first->render_sinking_contours(); + glsafe(::glDepthFunc(GL_LESS)); + GUI::wxGetApp().bind_shader(shader); + } } } } @@ -1688,7 +1790,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, glsafe(::glDisable(GL_BLEND)); } -bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state) const +bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state, ObjectFilamentResults* object_results) const { if (GUI::wxGetApp().plater() == NULL) { @@ -1710,19 +1812,25 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo auto volume_convex_mesh = [volume_sinking, &model](GLVolume& volume) -> const TriangleMesh& { return volume_sinking(volume) ? model.objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : *volume.convex_hull(); }; - ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside; + ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Fully_Outside; bool contained_min_one = false; //QDS: add instance judge logic, besides to original volume judge logic - std::map model_state; + //std::map model_state; GUI::PartPlate* curr_plate = GUI::wxGetApp().plater()->get_partplate_list().get_selected_plate(); const Pointfs& pp_bed_shape = curr_plate->get_shape(); - BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height()); + BuildVolume plate_build_volume(pp_bed_shape, build_volume.printable_height(), build_volume.extruder_areas(), build_volume.extruder_heights()); const std::vector& exclude_areas = curr_plate->get_exclude_areas(); + std::map>> objects_unprintable_filaments; + int extruder_count = build_volume.get_extruder_area_count(); + std::vector> unprintable_filament_ids(extruder_count, std::set()); + std::set partly_objects_set; + const ModelObjectPtrs &model_objects = model.objects; for (GLVolume* volume : this->volumes) { + std::vector inside_extruders; if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) { BuildVolume::ObjectState state; const BoundingBoxf3& bb = volume_bbox(*volume); @@ -1733,37 +1841,76 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo case BuildVolume::Type::Rectangle: //FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects. state = plate_build_volume.volume_state_bbox(bb); + if ((state == BuildVolume::ObjectState::Inside) && (extruder_count > 1)) + { + state = plate_build_volume.check_volume_bbox_state_with_extruder_areas(bb, inside_extruders); + } break; case BuildVolume::Type::Circle: case BuildVolume::Type::Convex: //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. case BuildVolume::Type::Custom: - state = plate_build_volume.object_state(volume_convex_mesh(*volume).its, volume->world_matrix().cast(), volume_sinking(*volume)); + { + const indexed_triangle_set& convex_mesh_it = volume_convex_mesh(*volume).its; + const Transform3f trafo = volume->world_matrix().cast(); + state = plate_build_volume.object_state(convex_mesh_it, trafo, volume_sinking(*volume)); + if ((state == BuildVolume::ObjectState::Inside) && (extruder_count > 1)) + { + state = plate_build_volume.check_object_state_with_extruder_areas(convex_mesh_it, trafo, inside_extruders); + } break; + } default: // Ignore, don't produce any collision. state = BuildVolume::ObjectState::Inside; break; } assert(state != BuildVolume::ObjectState::Below); + + if (state == BuildVolume::ObjectState::Limited) { + //unprintable_filament_ids.resize(inside_extruders.size()); + ModelObject *model_object = model_objects[volume->object_idx()]; + // Only check for single-color object + std::set object_filaments; + for (ModelVolume *m_volume : model_object->volumes) { + std::vector filaments = m_volume->get_extruders(); + object_filaments.insert(filaments.begin(), filaments.end()); + } + if (object_filaments.size() == 1) { + ModelVolume *model_volume = model_object->volumes[volume->volume_idx()]; + for (size_t i = 0; i < inside_extruders.size(); ++i) { + if (!inside_extruders[i]) { + std::vector filaments = model_volume->get_extruders(); + unprintable_filament_ids[i].insert(filaments.begin(), filaments.end()); + if (object_results) { + std::map> &obj_extruder_filament_maps = objects_unprintable_filaments[model_object]; + std::set &obj_extruder_filaments = obj_extruder_filament_maps[i + 1]; + obj_extruder_filaments.insert(filaments.begin(), filaments.end()); + } + } + } + } + } } - int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id); - volume->is_outside = state != BuildVolume::ObjectState::Inside; - //volume->partly_inside = (state == BuildVolume::ObjectState::Colliding); + //int64_t comp_id = ((int64_t)volume->composite_id.object_id << 32) | ((int64_t)volume->composite_id.instance_id); + volume->is_outside = (state != BuildVolume::ObjectState::Inside && state != BuildVolume::ObjectState::Limited); + volume->partly_inside = (state == BuildVolume::ObjectState::Colliding); if (volume->printable) { - if (overall_state == ModelInstancePVS_Inside && volume->is_outside) { - overall_state = ModelInstancePVS_Fully_Outside; - } - - if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && (state == BuildVolume::ObjectState::Colliding)) + if (state == BuildVolume::ObjectState::Colliding) { overall_state = ModelInstancePVS_Partly_Outside; + partly_objects_set.emplace(model_objects[volume->object_idx()]); + } + else if ((state == BuildVolume::ObjectState::Limited) && (overall_state != ModelInstancePVS_Partly_Outside)) + overall_state = ModelInstancePVS_Limited; + else if ((state == BuildVolume::ObjectState::Inside) && (overall_state == ModelInstancePVS_Fully_Outside)) { + overall_state = ModelInstancePVS_Fully_Outside; } contained_min_one |= !volume->is_outside; } - ModelInstanceEPrintVolumeState volume_state; + /*ModelInstanceEPrintVolumeState volume_state; //if (volume->is_outside && (plate_build_volume.bounding_volume().intersects(volume->bounding_box()))) if (volume->is_outside && (state == BuildVolume::ObjectState::Colliding)) volume_state = ModelInstancePVS_Partly_Outside; @@ -1792,11 +1939,121 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo if (model_state[comp_id] == ModelInstancePVS_Partly_Outside) { overall_state = ModelInstancePVS_Partly_Outside; BOOST_LOG_TRIVIAL(debug) << "instance includes " << volume->name << " is partially outside of bed"; + }*/ + } + } + + std::vector> unprintable_filament_vec; + for (const std::set& filamnt_ids : unprintable_filament_ids) { + unprintable_filament_vec.emplace_back(std::vector(filamnt_ids.begin(), filamnt_ids.end())); + } + + if (object_results && !partly_objects_set.empty()) { + object_results->partly_outside_objects = std::vector(partly_objects_set.begin(), partly_objects_set.end()); + } + + //check per-object error for extruder areas + if (object_results && (extruder_count > 1)) + { + const auto& project_config = Slic3r::GUI::wxGetApp().preset_bundle->project_config; + object_results->mode = curr_plate->get_real_filament_map_mode(project_config); + if (object_results->mode < FilamentMapMode::fmmManual) + { + std::vector conflict_filament_vector; + for (int index = 0; index < extruder_count; index++ ) + { + if (!unprintable_filament_vec[index].empty()) + { + std::sort (unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end()); + if (index == 0) + conflict_filament_vector = unprintable_filament_vec[index]; + else + { + std::vector result_filaments; + //result_filaments.reserve(conflict_filaments.size()); + std::set_intersection (conflict_filament_vector.begin(), conflict_filament_vector.end(), unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end(), insert_iterator>(result_filaments, result_filaments.begin())); + conflict_filament_vector = result_filaments; + } + } + else + { + conflict_filament_vector.clear(); + break; + } + } + + if (!conflict_filament_vector.empty()) + { + std::set conflict_filaments_set(conflict_filament_vector.begin(), conflict_filament_vector.end()); + object_results->filaments = conflict_filament_vector; + + for (auto& object_map: objects_unprintable_filaments) + { + ModelObject *model_object = object_map.first; + std::map>& obj_extruder_filament_maps = object_map.second; + std::set obj_filaments_set; + ObjectFilamentInfo object_filament_info; + object_filament_info.object = model_object; + + for (std::map>::iterator extruder_map_iter = obj_extruder_filament_maps.begin(); extruder_map_iter != obj_extruder_filament_maps.end(); extruder_map_iter++ ) + { + int extruder_id = extruder_map_iter->first; + std::set& filaments_set = extruder_map_iter->second; + + for (int filament: filaments_set) + { + if (conflict_filaments_set.find(filament) != conflict_filaments_set.end()) + { + obj_filaments_set.emplace(filament); + } + } + } + if (!obj_filaments_set.empty()) { + object_filament_info.auto_filaments = std::vector(obj_filaments_set.begin(), obj_filaments_set.end()); + object_results->object_filaments.push_back(std::move(object_filament_info)); + } + } + } + } + else + { + std::set conflict_filaments_set; + const auto& project_config = Slic3r::GUI::wxGetApp().preset_bundle->project_config; + std::vector filament_maps = curr_plate->get_real_filament_maps(project_config); + for (auto& object_map: objects_unprintable_filaments) + { + ModelObject *model_object = object_map.first; + std::map>& obj_extruder_filament_maps = object_map.second; + ObjectFilamentInfo object_filament_info; + object_filament_info.object = model_object; + + for (std::map>::iterator extruder_map_iter = obj_extruder_filament_maps.begin(); extruder_map_iter != obj_extruder_filament_maps.end(); extruder_map_iter++ ) + { + int extruder_id = extruder_map_iter->first; + std::set& filaments_set = extruder_map_iter->second; + + for (int filament: filaments_set) + { + if (filament_maps[filament - 1] == extruder_id) + { + object_filament_info.manual_filaments.emplace(filament, extruder_id); + object_results->filament_maps[filament] = extruder_id; + conflict_filaments_set.emplace(filament); + } + } + } + if (!object_filament_info.manual_filaments.empty()) + { + object_results->object_filaments.push_back(std::move(object_filament_info)); + } + } + if (!conflict_filaments_set.empty()) { + object_results->filaments = std::vector(conflict_filaments_set.begin(), conflict_filaments_set.end()); } } } - for (GLVolume* volume : this->volumes) + /*for (GLVolume* volume : this->volumes) { if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) { @@ -1810,7 +2067,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo volume->partly_inside = false; } } - } + }*/ if (out_state != nullptr) *out_state = overall_state; diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index a3533ed..6d9c033 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -7,14 +7,17 @@ #include "libslic3r/TriangleMesh.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Geometry.hpp" +#include "libslic3r/PrintConfig.hpp" // QDS #include "libslic3r/ObjectID.hpp" #include "MeshUtils.hpp" #include "GLShader.hpp" +#include "GLEnums.hpp" #include #include +#include #ifndef NDEBUG #define HAS_GLSAFE @@ -30,7 +33,6 @@ #define glsafe(cmd) cmd #define glcheck() #endif // HAS_GLSAFE -extern std::vector> get_extruders_colors(); extern float FullyTransparentMaterialThreshold; extern float FullTransparentModdifiedToFixAlpha; extern std::array adjust_color_for_rendering(const std::array &colors); @@ -53,6 +55,22 @@ enum ModelInstanceEPrintVolumeState : unsigned char; using ModelObjectPtrs = std::vector; +struct ObjectFilamentInfo { + ModelObject* object; + std::map manual_filaments; //manual mode: filament id -> extruder id can not be printed + + std::vector auto_filaments; //auto mode: filaments in all extruder's outside area +}; + +struct ObjectFilamentResults { + FilamentMapMode mode; + std::vector filaments; //filaments has conflicts + std::map filament_maps; //filament maps + std::vector partly_outside_objects; //partly outside objects + + std::vector object_filaments; +}; + // Return appropriate color based on the ModelVolume. std::array color_from_model_volume(const ModelVolume& model_volume); @@ -212,8 +230,8 @@ public: // Release the geometry data, release OpenGL VBOs. void release_geometry(); - void render() const; - void render(const std::pair& tverts_range, const std::pair& qverts_range) const; + void render(const std::shared_ptr& shader) const; + void render(const std::shared_ptr& shader, const std::pair& tverts_range, const std::pair& qverts_range) const; // Is there any geometry data stored? bool empty() const { return vertices_and_normals_interleaved_size == 0; } @@ -256,7 +274,6 @@ public: private: BoundingBox m_bounding_box; }; - enum LOD_LEVEL { HIGH, // Origin data MIDDLE, @@ -270,6 +287,7 @@ class GLVolume { static float LAST_CAMERA_ZOOM_VALUE; mutable LOD_LEVEL m_cur_lod_level = LOD_LEVEL::HIGH; mutable unsigned char m_lod_update_index = 0; + public: std::string name; bool is_text_shape{false}; @@ -433,6 +451,9 @@ public: bool force_neutral_color : 1; // Whether or not to force rendering of sinking contours bool force_sinking_contours : 1; + // slice error + bool slice_error : 1; + bool picking : 1; }; // Is mouse or rectangle selection over this object to select/deselect it ? @@ -490,7 +511,6 @@ public: double get_instance_rotation(Axis axis) const { return m_instance_transformation.get_rotation(axis); } void set_instance_rotation(const Vec3d& rotation) { m_instance_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); } - void set_instance_rotation(Axis axis, double rotation) { m_instance_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); } Vec3d get_instance_scaling_factor() const { return m_instance_transformation.get_scaling_factor(); } double get_instance_scaling_factor(Axis axis) const { return m_instance_transformation.get_scaling_factor(axis); } @@ -518,7 +538,6 @@ public: double get_volume_rotation(Axis axis) const { return m_volume_transformation.get_rotation(axis); } void set_volume_rotation(const Vec3d& rotation) { m_volume_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); } - void set_volume_rotation(Axis axis, double rotation) { m_volume_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); } const Vec3d& get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); } double get_volume_scaling_factor(Axis axis) const { return m_volume_transformation.get_scaling_factor(axis); } @@ -566,11 +585,12 @@ public: void set_range(double low, double high); //QDS: add outline related logic and add virtual specifier - virtual void render(bool with_outline = false, + virtual void render(const Transform3d& view_matrix, + bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f} ) const; //QDS: add simple render function for thumbnail - void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector>& extruder_colors,bool ban_light =false) const; + void simple_render(const std::shared_ptr& shader, ModelObjectPtrs& model_objects, std::vector>& extruder_colors,bool ban_light =false) const; void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array->finalize_geometry(opengl_initialized); } void release_geometry() { this->indexed_vertex_array->release_geometry(); } @@ -598,7 +618,7 @@ public: class GLWipeTowerVolume : public GLVolume { public: GLWipeTowerVolume(const std::vector>& colors); - virtual void render(bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f}) const; + void render(const Transform3d& view_matrix, bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f}) const override; std::vector iva_per_colors; bool IsTransparent(); @@ -611,6 +631,7 @@ typedef std::vector GLVolumePtrs; typedef std::pair> GLVolumeWithIdAndZ; typedef std::vector GLVolumeWithIdAndZList; + class GLVolumeCollection { public: @@ -699,21 +720,24 @@ public: int load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized); - + int load_real_wipe_tower_preview( + int obj_idx, float pos_x, float pos_y,const TriangleMesh& wt_mesh,const TriangleMesh &brim_mesh,bool render_brim, float rotation_angle, bool size_unknown, bool opengl_initialized); GLVolume* new_toolpath_volume(const std::array& rgba, size_t reserve_vbo_floats = 0); GLVolume* new_nontoolpath_volume(const std::array& rgba, size_t reserve_vbo_floats = 0); int get_selection_support_threshold_angle(bool&) const; // Render the volumes by OpenGL. //QDS: add outline drawing logic - void render(ERenderType type, + void render(GUI::ERenderPipelineStage render_pipeline_stage, + ERenderType type, bool disable_cullface, const Transform3d & view_matrix, - std::function filter_func = std::function(), - bool with_outline = true, - const std::array& body_color = {1.0f, 1.0f, 1.0f, 1.0f}, - bool partly_inside_enable =true - ) const; + const Transform3d& projection_matrix, + std::function filter_func = std::function(), + bool with_outline = true, + const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}, + bool partly_inside_enable = true, + std::vector * printable_heights = nullptr) const; // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects @@ -734,6 +758,12 @@ public: void set_z_range(float min_z, float max_z) { m_z_range[0] = min_z; m_z_range[1] = max_z; } void set_clipping_plane(const double* coeffs) { m_clipping_plane[0] = coeffs[0]; m_clipping_plane[1] = coeffs[1]; m_clipping_plane[2] = coeffs[2]; m_clipping_plane[3] = coeffs[3]; } + void set_clipping_plane(double coeffs[4]){ + m_clipping_plane[0] = coeffs[0]; + m_clipping_plane[1] = coeffs[1]; + m_clipping_plane[2] = coeffs[2]; + m_clipping_plane[3] = coeffs[3]; + } bool is_slope_GlobalActive() const { return m_slope.isGlobalActive; } bool is_slope_active() const { return m_slope.active; } @@ -747,7 +777,7 @@ public: // returns true if all the volumes are completely contained in the print volume // returns the containment state in the given out_state, if non-null - bool check_outside_state(const Slic3r::BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state) const; + bool check_outside_state(const Slic3r::BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state, ObjectFilamentResults* object_results) const; void reset_outside_state(); void update_colors_by_extruder(const DynamicPrintConfig *config, bool is_update_alpha = true); diff --git a/src/slic3r/GUI/AMSMaterialsSetting.cpp b/src/slic3r/GUI/AMSMaterialsSetting.cpp index 550f9d7..9659ef2 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.cpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.cpp @@ -15,13 +15,16 @@ wxDEFINE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent); static std::string float_to_string_with_precision(float value, int precision = 3) { + if (value < 0) + return std::string(); + std::stringstream stream; stream << std::fixed << std::setprecision(precision) << value; return stream.str(); } AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id) - : DPIDialog(parent, id, _L("BOX Materials Setting"), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE) + : DPIDialog(parent, id, _L("BOX Materials Setting"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) , m_color_picker_popup(ColorPickerPopup(this)) { create(); @@ -43,11 +46,10 @@ void AMSMaterialsSetting::create() m_sizer_button->Add(0, 0, 1, wxEXPAND, 0); m_button_confirm = new Button(this, _L("Confirm")); - // y96 - m_btn_bg_blue = StateColor(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + m_btn_bg_blue = StateColor(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_confirm->SetBackgroundColor(m_btn_bg_blue); - m_button_confirm->SetBorderColor(wxColour(68, 121, 251)); // y96 + m_button_confirm->SetBorderColor(wxColour(68, 121, 251)); m_button_confirm->SetTextColor(wxColour("#FFFFFE")); m_button_confirm->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE); m_button_confirm->SetCornerRadius(FromDIP(12)); @@ -77,7 +79,7 @@ void AMSMaterialsSetting::create() m_sizer_button->Add(m_button_close, 0, wxALIGN_CENTER, 0); m_sizer_main->Add(m_panel_normal, 0, wxALL, FromDIP(2)); - + m_sizer_main->Add(m_panel_kn, 0, wxALL, FromDIP(2)); m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(24)); @@ -147,13 +149,15 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent) m_sizer_filament->Add(m_comboBox_filament, 1, wxALIGN_CENTER, 0); - m_readonly_filament = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, wxTE_READONLY | wxRIGHT); - m_readonly_filament->SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int)StateColor::Focused), std::make_pair(0x4479FB, (int)StateColor::Hovered), + // make the style the same with disable m_input_k_val, FIXME + m_readonly_filament = new TextInput(parent, wxEmptyString, "", "", wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, wxTE_CENTRE | wxTE_PROCESS_ENTER); + m_readonly_filament->SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int)StateColor::Focused), std::make_pair(0x4479fb, (int)StateColor::Hovered), std::make_pair(0xDBDBDB, (int)StateColor::Normal))); m_readonly_filament->SetFont(::Label::Body_14); m_readonly_filament->SetLabelColor(AMS_MATERIALS_SETTING_GREY800); m_readonly_filament->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [](auto& e) {}); m_readonly_filament->GetTextCtrl()->Hide(); + m_readonly_filament->Disable(); m_sizer_filament->Add(m_readonly_filament, 1, wxALIGN_CENTER, 0); m_readonly_filament->Hide(); @@ -259,7 +263,7 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent) m_panel_SN->Fit(); wxBoxSizer* m_tip_sizer = new wxBoxSizer(wxHORIZONTAL); - m_tip_readonly = new Label(parent, _L("")); + m_tip_readonly = new Label(parent, ""); m_tip_readonly->SetForegroundColour(*wxBLACK); m_tip_readonly->SetBackgroundColour(*wxWHITE); m_tip_readonly->SetMinSize(wxSize(FromDIP(380), -1)); @@ -284,18 +288,24 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent) void AMSMaterialsSetting::create_panel_kn(wxWindow* parent) { auto sizer = new wxBoxSizer(wxVERTICAL); + auto cali_title_sizer = new wxBoxSizer(wxHORIZONTAL); // title - m_ratio_text = new wxStaticText(parent, wxID_ANY, _L("Factors of Flow Dynamics Calibration")); + m_ratio_text = new wxStaticText(parent, wxID_ANY, _L("Factors of Flow Dynamics Calibration")); m_ratio_text->SetForegroundColour(wxColour(50, 58, 61)); m_ratio_text->SetFont(Label::Head_14); - m_ratio_text->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); - m_ratio_text->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); - - m_ratio_text->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { - wxLaunchDefaultBrowser(wxT("https://wiki.qidi3d.com/en/software/qidi-studio/calibration_pa")); - }); - + std::string language = wxGetApp().app_config->get("language"); + wxString region = "en"; + if (language.find("zh") == 0) + region = "zh"; + wxString link_url = wxString::Format("https://wiki.qiditech.com/%s/software/qidi-studio/calibration_pa", region); + m_wiki_ctrl = new wxHyperlinkCtrl(parent, wxID_ANY, "Wiki", link_url); + m_wiki_ctrl->SetNormalColour(*wxBLUE); + m_wiki_ctrl->SetHoverColour(wxColour(0, 0, 200)); + m_wiki_ctrl->SetVisitedColour(*wxBLUE); + m_wiki_ctrl->SetFont(Label::Head_14); + cali_title_sizer->Add(m_ratio_text, 0, wxALIGN_CENTER_VERTICAL); + cali_title_sizer->Add(m_wiki_ctrl, 0, wxALIGN_CENTER_VERTICAL); wxBoxSizer *m_sizer_cali_resutl = new wxBoxSizer(wxHORIZONTAL); // pa profile @@ -345,8 +355,8 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent) m_input_n_val->Hide(); sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); - sizer->Add(m_ratio_text, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20)); - sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + sizer->Add(cali_title_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20)); + sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); sizer->Add(m_sizer_cali_resutl, 0, wxLEFT | wxRIGHT, FromDIP(20)); sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); sizer->Add(kn_val_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20)); @@ -414,8 +424,6 @@ void AMSMaterialsSetting::update() void AMSMaterialsSetting::enable_confirm_button(bool en) { - m_tip_readonly->SetLabelText(wxEmptyString); - if (!en) { m_button_confirm->Show(obj->is_support_filament_setting_inprinting); } @@ -424,6 +432,7 @@ void AMSMaterialsSetting::enable_confirm_button(bool en) } if (!m_is_third) { + m_tip_readonly->SetLabelText(wxEmptyString); m_tip_readonly->Hide(); } else { @@ -433,6 +442,8 @@ void AMSMaterialsSetting::enable_confirm_button(bool en) } else { m_tip_readonly->SetLabelText(_L("Setting Virtual slot information while printing is not supported")); } + } else { + m_tip_readonly->SetLabelText(wxEmptyString); } m_tip_readonly->Wrap(FromDIP(380)); @@ -458,21 +469,32 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) { long nozzle_temp_max_int = 0; wxColour color = *wxWHITE; char col_buf[10]; - sprintf(col_buf, "%02X%02X%02XFF", (int)color.Red(), (int)color.Green(), (int)color.Blue()); + sprintf(col_buf, "%02X%02X%02X00", (int)color.Red(), (int)color.Green(), (int)color.Blue()); + std::string color_str; // reset use empty string + + std::string selected_ams_id; + PresetBundle *preset_bundle = wxGetApp().preset_bundle; + if (preset_bundle) { + for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) { + auto filament_item = map_filament_items[m_comboBox_filament->GetValue().ToStdString()]; + std::string filament_id = filament_item.filament_id; + if (it->filament_id.compare(filament_id) == 0) { + selected_ams_id = it->filament_id; + break; + } + } + } if (obj) { - // set filament - if (is_virtual_tray()) { - obj->command_ams_filament_settings(255, VIRTUAL_TRAY_ID, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int); - } - else if(m_is_third){ - obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int); + if(m_is_third){ + obj->command_ams_filament_settings(ams_id, slot_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, + nozzle_temp_max_int); } // set k / n value if (obj->cali_version <= -1 && obj->get_printer_series() == PrinterSeries::SERIES_P1P) { // set extrusion cali ratio - int cali_tray_id = ams_id * 4 + tray_id; + int cali_tray_id = ams_id * 4 + slot_id; double k = 0.0; try { @@ -493,10 +515,19 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) { } else { PACalibIndexInfo select_index_info; + int tray_id = ams_id * 4 + slot_id; + if (is_virtual_tray()) { + tray_id = ams_id; + if (!obj->is_enable_np) { + tray_id = VIRTUAL_TRAY_DEPUTY_ID; + } + } select_index_info.tray_id = tray_id; - select_index_info.nozzle_diameter = obj->nozzle_diameter; + select_index_info.ams_id = ams_id; + select_index_info.slot_id = slot_id; + select_index_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; select_index_info.cali_idx = -1; - select_index_info.filament_id = ams_filament_id; + select_index_info.filament_id = selected_ams_id; CalibUtils::select_PA_calib_result(select_index_info); } } @@ -519,19 +550,20 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) //check is it in the filament blacklist - if (!is_virtual_tray() && wxGetApp().app_config->get("skip_ams_blacklist_check") != "true") { + if (wxGetApp().app_config->get("skip_ams_blacklist_check") != "true") { bool in_blacklist = false; std::string action; std::string info; std::string filamnt_type; + std::string filamnt_name; it->get_filament_type(filamnt_type); - auto vendor = dynamic_cast (it->config.option("filament_vendor")); + auto vendor = dynamic_cast(it->config.option("filament_vendor")); + if (vendor && (vendor->values.size() > 0)) { std::string vendor_name = vendor->values[0]; - DeviceManager::check_filaments_in_blacklist(vendor_name, filamnt_type, in_blacklist, action, info); + DeviceManager::check_filaments_in_blacklist(obj->printer_type, vendor_name, filamnt_type, ams_id, slot_id, it->name, in_blacklist, action, info); } - if (in_blacklist) { if (action == "prohibition") { @@ -576,14 +608,9 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) // set filament if (m_is_third) { - if (is_virtual_tray()) { - obj->command_ams_filament_settings(255, VIRTUAL_TRAY_ID, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int); - } - else { - obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int); - } + obj->command_ams_filament_settings(ams_id, slot_id, ams_filament_id, ams_setting_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int); } - + //reset param wxString k_text = m_input_k_val->GetTextCtrl()->GetValue(); wxString n_text = m_input_n_val->GetTextCtrl()->GetValue(); @@ -613,10 +640,17 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) ; } + auto vt_tray = ams_id; + if (!obj->is_enable_np) { + vt_tray = VIRTUAL_TRAY_DEPUTY_ID; + } + if (obj->cali_version >= 0) { PACalibIndexInfo select_index_info; - select_index_info.tray_id = tray_id; - select_index_info.nozzle_diameter = obj->nozzle_diameter; + select_index_info.tray_id = vt_tray; + select_index_info.ams_id = ams_id; + select_index_info.slot_id = 0; + select_index_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; auto cali_select_id = m_comboBox_cali_result->GetSelection(); if (m_pa_profile_items.size() > 0 && cali_select_id >= 0) { @@ -631,11 +665,11 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) CalibUtils::select_PA_calib_result(select_index_info); } else { - obj->command_extrusion_cali_set(VIRTUAL_TRAY_ID, "", "", k, n); + obj->command_extrusion_cali_set(vt_tray, "", "", k, n); } } else { - int cali_tray_id = ams_id * 4 + tray_id; + int cali_tray_id = ams_id * 4 + slot_id; double k = 0.0; try { k_text.ToDouble(&k); @@ -655,10 +689,12 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) if (obj->cali_version >= 0) { PACalibIndexInfo select_index_info; select_index_info.tray_id = cali_tray_id; - select_index_info.nozzle_diameter = obj->nozzle_diameter; + select_index_info.ams_id = ams_id; + select_index_info.slot_id = slot_id; + select_index_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; auto cali_select_id = m_comboBox_cali_result->GetSelection(); - if (m_pa_profile_items.size() > 0 && cali_select_id >= 0) { + if (m_pa_profile_items.size() > 0 && cali_select_id > 0) { select_index_info.cali_idx = m_pa_profile_items[cali_select_id].cali_idx; select_index_info.filament_id = m_pa_profile_items[cali_select_id].filament_id; } @@ -742,7 +778,7 @@ void AMSMaterialsSetting::on_clr_picker(wxMouseEvent &event) bool AMSMaterialsSetting::is_virtual_tray() { - if (tray_id == VIRTUAL_TRAY_ID) + if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) return true; return false; } @@ -778,17 +814,8 @@ bool AMSMaterialsSetting::Show(bool show) m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); //m_clr_picker->set_color(m_clr_picker->GetParent()->GetBackgroundColour()); - /*if (obj && (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI) || obj->is_high_printer_type())) { - m_ratio_text->Show(); - m_k_param->Show(); - m_input_k_val->Show(); - } - else { - m_ratio_text->Hide(); - m_k_param->Hide(); - m_input_k_val->Hide(); - }*/ m_ratio_text->Show(); + m_wiki_ctrl->Show(); m_k_param->Show(); m_input_k_val->Show(); Layout(); @@ -798,6 +825,15 @@ bool AMSMaterialsSetting::Show(bool show) return DPIDialog::Show(show); } +static void _collect_filament_info(const wxString& shown_name, + const Preset& filament, + unordered_map& query_filament_vendors, + unordered_map& query_filament_types) +{ + query_filament_vendors[shown_name] = filament.config.get_filament_vendor(); + query_filament_vendors[shown_name] = filament.config.get_filament_type(); +} + void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_min, wxString temp_max, wxString k, wxString n) { if (!obj) return; @@ -811,17 +847,20 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi m_input_k_val->GetTextCtrl()->SetValue(k); m_input_n_val->GetTextCtrl()->SetValue(n); - int selection_idx = -1, idx = 0; + int idx = 0; wxArrayString filament_items; wxString qidi_filament_name; + wxString hint_filament_name; // the hint type to be selected + std::unordered_map query_filament_vendors;// some information for sort + std::unordered_map query_filament_types; // std::set filament_id_set; PresetBundle * preset_bundle = wxGetApp().preset_bundle; std::ostringstream stream; - stream << std::fixed << std::setprecision(1) << obj->nozzle_diameter; + stream << std::fixed << std::setprecision(1) << obj->m_extder_data.extders[0].current_nozzle_diameter; std::string nozzle_diameter_str = stream.str(); std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), nozzle_diameter_str); - + if (preset_bundle) { BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size(); for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) { @@ -833,7 +872,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) { continue; } - + ConfigOption * printer_opt = filament_it->config.option("compatible_printers"); ConfigOptionStrings *printer_strs = dynamic_cast(printer_opt); for (auto printer_str : printer_strs->values) { @@ -845,6 +884,8 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi // name matched if (filament_it->is_system) { filament_items.push_back(filament_it->alias); + _collect_filament_info(filament_it->alias, preset, query_filament_vendors, query_filament_types); + FilamentInfos filament_infos; filament_infos.filament_id = filament_it->filament_id; filament_infos.setting_id = filament_it->setting_id; @@ -858,6 +899,8 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi user_preset_alias = wx_user_preset_alias.ToStdString(); filament_items.push_back(user_preset_alias); + _collect_filament_info(user_preset_alias, preset, query_filament_vendors, query_filament_types); + FilamentInfos filament_infos; filament_infos.filament_id = filament_it->filament_id; filament_infos.setting_id = filament_it->setting_id; @@ -866,9 +909,9 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi } if (filament_it->filament_id == ams_filament_id) { - selection_idx = idx; - qidi_filament_name = filament_it->alias; - + hint_filament_name = from_u8(filament_it->alias); + qidi_filament_name = from_u8(filament_it->alias); + // update if nozzle_temperature_range is found ConfigOption *opt_min = filament_it->config.option("nozzle_temperature_range_low"); @@ -892,7 +935,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi } } } - + } } @@ -914,7 +957,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi else { m_readonly_filament->SetLabel(qidi_filament_name); } - + m_input_nozzle_min->GetTextCtrl()->SetValue(temp_min); m_input_nozzle_max->GetTextCtrl()->SetValue(temp_max); } @@ -938,6 +981,74 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi //m_button_confirm->Show(); } + // Sort the filaments + { + static std::unordered_map sorted_names + { {"QIDI PLA Basic", 0}, + {"QIDI PLA Matte", 1}, + {"QIDI PETG HF", 2}, + {"QIDI ABS", 3}, + {"QIDI PLA Silk", 4}, + {"QIDI PLA-CF" , 5}, + {"QIDI PLA Galaxy", 6}, + {"QIDI PLA Metal", 7}, + {"QIDI PLA Marble", 8}, + {"QIDI PETG-CF", 9}, + {"QIDI PETG Translucent", 10}, + {"QIDI ABS-GF", 11} + }; + + static std::vector sorted_vendors { "QIDI Tech", "Generic" }; + static std::vector sorted_types { "PLA", "PETG", "ABS", "TPU" }; + auto _filament_sorter = [&query_filament_vendors, &query_filament_types](const wxString& left, const wxString& right) -> bool + { + { // Compare name order + const auto& iter1 = sorted_names.find(left); + int name_order1 = (iter1 != sorted_names.end()) ? iter1->second : INT_MAX; + + const auto& iter2 = sorted_names.find(right); + int name_order2 = (iter2 != sorted_names.end()) ? iter2->second : INT_MAX; + if (name_order1 != name_order2) + { + return name_order1 < name_order2; + } + } + { // Compare vendor + auto iter1 = std::find(sorted_vendors.begin(), sorted_vendors.end(), query_filament_vendors[left]); + auto iter2 = std::find(sorted_vendors.begin(), sorted_vendors.end(), query_filament_vendors[right]); + if (iter1 != iter2) + { + return iter1 < iter2; + }; + } + { // Compare type + auto iter1 = std::find(sorted_types.begin(), sorted_types.end(), query_filament_types[left]); + auto iter2 = std::find(sorted_types.begin(), sorted_types.end(), query_filament_types[right]); + if (iter1 != iter2) + { + return iter1 < iter2; + } + } + + return left < right; + }; + + std::sort(filament_items.begin(), filament_items.end(), _filament_sorter); + } + + // traverse the hint selection idx + int selection_idx = -1; + { + for(int i = 0; i < filament_items.size(); i++) + { + if (hint_filament_name == filament_items[i]) + { + selection_idx = i; + break; + } + } + } + m_comboBox_filament->Set(filament_items); m_comboBox_filament->SetSelection(selection_idx); post_select_event(selection_idx); @@ -983,14 +1094,14 @@ void AMSMaterialsSetting::on_select_cali_result(wxCommandEvent &evt) void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) { // Get the flag whether to open the filament setting dialog from the device page - int *from_printer = static_cast(m_comboBox_filament->GetClientData()); + int* from_printer = static_cast(m_comboBox_filament->GetClientData()); m_filament_type = ""; PresetBundle* preset_bundle = wxGetApp().preset_bundle; if (preset_bundle) { std::ostringstream stream; if (obj) - stream << std::fixed << std::setprecision(1) << obj->nozzle_diameter; + stream << std::fixed << std::setprecision(1) << obj->m_extder_data.extders[0].current_nozzle_diameter; std::string nozzle_diameter_str = stream.str(); std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), nozzle_diameter_str); @@ -1101,19 +1212,42 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) m_pa_profile_items.clear(); m_comboBox_cali_result->SetValue(wxEmptyString); - auto get_cali_index = [this](const std::string &str) -> int { + auto get_cali_index = [this](const std::string& str) -> int{ for (int i = 0; i < int(m_pa_profile_items.size()); ++i) { - if (m_pa_profile_items[i].name == str) return i; + if (m_pa_profile_items[i].name == str) + return i; } return 0; }; + int extruder_id = obj->get_extruder_id_by_ams_id(std::to_string(ams_id)); + if (obj->is_nozzle_flow_type_supported() && (obj->get_nozzle_flow_type(extruder_id) == NozzleFlowType::NONE_FLOWTYPE)) + { + MessageDialog dlg(nullptr, _L("The nozzle flow is not set. Please set the nozzle flow rate before editing the filament.\n'Device -> Print parts'"), _L("Warning"), wxICON_WARNING | wxOK); + dlg.ShowModal(); + } + + NozzleFlowType nozzle_flow_type = obj->get_nozzle_flow_type(extruder_id); + NozzleVolumeType nozzle_volume_type = NozzleVolumeType::nvtStandard; + if (nozzle_flow_type != NozzleFlowType::NONE_FLOWTYPE) + { + nozzle_volume_type = NozzleVolumeType(nozzle_flow_type - 1); + } + if (obj->cali_version >= 0) { // add default item PACalibResult default_item; - default_item.filament_id = ams_filament_id; default_item.cali_idx = -1; - get_default_k_n_value(ams_filament_id, default_item.k_value, default_item.n_coef); + default_item.filament_id = ams_filament_id; + std::vector machine_list = {"N1", "N2S", "C11", "C12", "C13", "BL-P001", "BL-P002"}; + auto iter = std::find(machine_list.begin(), machine_list.end(), obj->printer_type); + if (iter == machine_list.end()) { + default_item.k_value = -1; + default_item.n_coef = -1; + } + else { + get_default_k_n_value(ams_filament_id, default_item.k_value, default_item.n_coef); + } m_pa_profile_items.emplace_back(default_item); items.push_back(_L("Default")); @@ -1121,54 +1255,56 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) std::vector cali_history = this->obj->pa_calib_tab; for (auto cali_item : cali_history) { if (cali_item.filament_id == ams_filament_id) { + if (obj->is_multi_extruders() && (cali_item.extruder_id != extruder_id || cali_item.nozzle_volume_type != nozzle_volume_type)) { + continue; + } items.push_back(from_u8(cali_item.name)); m_pa_profile_items.push_back(cali_item); } } m_comboBox_cali_result->Set(items); - if (tray_id == VIRTUAL_TRAY_ID) { + if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) { if (from_printer && (*from_printer == 1)) { - AmsTray selected_tray = this->obj->vt_tray; - cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, selected_tray.cali_idx); - if (cali_select_idx >= 0) { - m_comboBox_cali_result->SetSelection(cali_select_idx); - } else { - m_comboBox_cali_result->SetSelection(0); + for (auto slot : obj->vt_slot) { + if (slot.id == std::to_string(ams_id)) + cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, slot.cali_idx); } + + if (cali_select_idx >= 0) + m_comboBox_cali_result->SetSelection(cali_select_idx); + else + m_comboBox_cali_result->SetSelection(0); } else { -#ifdef __APPLE__ - cali_select_idx = get_cali_index(m_comboBox_filament->GetValue().ToStdString()); -#else - cali_select_idx = get_cali_index(m_comboBox_filament->GetLabel().ToStdString()); -#endif - m_comboBox_cali_result->SetSelection(cali_select_idx); + int index = get_cali_index(m_comboBox_filament->GetLabel().ToStdString()); + m_comboBox_cali_result->SetSelection(index); } } else { if (from_printer && (*from_printer == 1)) { - Ams *selected_ams = this->obj->amsList[std::to_string(ams_id)]; - if (!selected_ams) return; - AmsTray *selected_tray = selected_ams->trayList[std::to_string(tray_id)]; - if (!selected_tray) return; - cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, selected_tray->cali_idx); - if (cali_select_idx >= 0) { + if (this->obj->amsList.find(std::to_string(ams_id)) != this->obj->amsList.end()) { + Ams* selected_ams = this->obj->amsList[std::to_string(ams_id)]; + if (!selected_ams) + return; + AmsTray* selected_tray = selected_ams->trayList[std::to_string(slot_id)]; + if (!selected_tray) + return; + cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, selected_tray->cali_idx); + if (cali_select_idx < 0) { + BOOST_LOG_TRIVIAL(info) << "extrusion_cali_status_error: cannot find pa profile, ams_id = " << ams_id + << ", slot_id = " << slot_id << ", cali_idx = " << selected_tray->cali_idx; + cali_select_idx = 0; + } m_comboBox_cali_result->SetSelection(cali_select_idx); - } else { - m_comboBox_cali_result->SetSelection(0); } } else { -#ifdef __APPLE__ - cali_select_idx = get_cali_index(m_comboBox_filament->GetValue().ToStdString()); -#else - cali_select_idx = get_cali_index(m_comboBox_filament->GetLabel().ToStdString()); -#endif - m_comboBox_cali_result->SetSelection(cali_select_idx); + int index = get_cali_index(m_comboBox_filament->GetLabel().ToStdString()); + m_comboBox_cali_result->SetSelection(index); } } - + if (cali_select_idx >= 0) { m_input_k_val->GetTextCtrl()->SetValue(float_to_string_with_precision(m_pa_profile_items[cali_select_idx].k_value)); m_input_n_val->GetTextCtrl()->SetValue(float_to_string_with_precision(m_pa_profile_items[cali_select_idx].n_coef)); @@ -1196,6 +1332,7 @@ void AMSMaterialsSetting::on_dpi_changed(const wxRect &suggested_rect) { m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); + m_input_k_val->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); //m_clr_picker->msw_rescale(); degree->msw_rescale(); bitmap_max_degree->SetBitmap(degree->bmp()); @@ -1655,7 +1792,7 @@ void ColorPickerPopup::paintEvent(wxPaintEvent& evt) void ColorPickerPopup::OnDismiss() {} -void ColorPickerPopup::Popup() +void ColorPickerPopup::Popup() { PopupWindow::Popup(); } diff --git a/src/slic3r/GUI/AMSMaterialsSetting.hpp b/src/slic3r/GUI/AMSMaterialsSetting.hpp index c282fdd..960516e 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.hpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.hpp @@ -118,7 +118,7 @@ public: void on_picker_color(wxCommandEvent& color); MachineObject* obj{ nullptr }; int ams_id { 0 }; /* 0 ~ 3 */ - int tray_id { 0 }; /* 0 ~ 3 */ + int slot_id { 0 }; /* 0 ~ 3 */ std::string ams_filament_id; std::string ams_setting_id; @@ -171,6 +171,7 @@ protected: wxPanel * m_panel_kn; wxStaticText* m_ratio_text; + wxHyperlinkCtrl * m_wiki_ctrl; wxStaticText* m_k_param; TextInput* m_input_k_val; wxStaticText* m_n_param; diff --git a/src/slic3r/GUI/AMSSetting.cpp b/src/slic3r/GUI/AMSSetting.cpp index 795ea90..7e494c2 100644 --- a/src/slic3r/GUI/AMSSetting.cpp +++ b/src/slic3r/GUI/AMSSetting.cpp @@ -152,9 +152,7 @@ void AMSSetting::create() // tip line m_sizer_remain_inline = new wxBoxSizer(wxVERTICAL); - m_tip_remain_line1 = new Label(m_panel_body, - _L("The BOX will estimate QIDI filament's remaining capacity after the filament info is updated. During printing, remaining capacity will be updated automatically.") - ); + m_tip_remain_line1 = new Label(m_panel_body, _L("BOX will attempt to estimate the remaining capacity of the QIDI Tech filaments.")); m_tip_remain_line1->SetFont(::Label::Body_13); m_tip_remain_line1->SetForegroundColour(AMS_SETTING_GREY700); m_tip_remain_line1->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1)); diff --git a/src/slic3r/GUI/AVVideoDecoder.cpp b/src/slic3r/GUI/AVVideoDecoder.cpp index bc2fab5..25bd2bb 100644 --- a/src/slic3r/GUI/AVVideoDecoder.cpp +++ b/src/slic3r/GUI/AVVideoDecoder.cpp @@ -47,12 +47,27 @@ int AVVideoDecoder::open(QIDI_StreamInfo const &info) int AVVideoDecoder::decode(const QIDI_Sample &sample) { - auto pkt = av_packet_alloc(); - int ret = av_new_packet(pkt, sample.size); - if (ret == 0) - memcpy(pkt->data, sample.buffer, size_t(sample.size)); - got_frame_ = avcodec_receive_frame(codec_ctx_, frame_) == 0; + int ret = -1; + AVPacket *pkt = av_packet_alloc(); + if (!pkt) { + return ret; + } + + ret = av_new_packet(pkt, sample.size); + if (ret != 0) { + av_packet_free(&pkt); + return ret; + } + + memcpy(pkt->data, sample.buffer, size_t(sample.size)); + ret = avcodec_send_packet(codec_ctx_, pkt); + if (ret == 0) { + got_frame_ = avcodec_receive_frame(codec_ctx_, frame_) == 0; + } + + av_packet_unref(pkt); + av_packet_free(&pkt); return ret; } diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index eff18a0..6f7c826 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -331,7 +331,7 @@ AboutDialog::AboutDialog() copyright_hor_sizer->Add(copyright_ver_sizer, 0, wxLEFT, FromDIP(20)); - wxStaticText *html_text = new wxStaticText(this, wxID_ANY, "Copyright(C) 2024 QIDI All Rights Reserved", wxDefaultPosition, wxDefaultSize); + wxStaticText *html_text = new wxStaticText(this, wxID_ANY, "Copyright(C) 2021-2025 QIDI All Rights Reserved", wxDefaultPosition, wxDefaultSize); html_text->SetForegroundColour(wxColour(107, 107, 107)); copyright_ver_sizer->Add(html_text, 0, wxALL , 0); diff --git a/src/slic3r/GUI/AmsMappingPopup.cpp b/src/slic3r/GUI/AmsMappingPopup.cpp index 738ec16..b09a287 100644 --- a/src/slic3r/GUI/AmsMappingPopup.cpp +++ b/src/slic3r/GUI/AmsMappingPopup.cpp @@ -18,20 +18,50 @@ #include #include #include +#include #include "Plater.hpp" #include "BitmapCache.hpp" #include "BindDialog.hpp" namespace Slic3r { namespace GUI { +#define MATERIAL_ITEM_SIZE wxSize(FromDIP(65), FromDIP(50)) +#define MATERIAL_REC_WHEEL_SIZE wxSize(FromDIP(17), FromDIP(16)) +#define MAPPING_ITEM_REAL_SIZE wxSize(FromDIP(48), FromDIP(60)) + wxDEFINE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent); +const int LEFT_OFFSET = 2; - MaterialItem::MaterialItem(wxWindow *parent, wxColour mcolour, wxString mname) - : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) +static void _add_containers(const AmsMapingPopup * win, + std::list & one_slot_containers, + const std::vector &four_slots_containers, + wxBoxSizer * target_sizer) +{ + for (auto container : four_slots_containers) { target_sizer->Add(container, 0, wxTOP, win->FromDIP(5)); } + + while (!one_slot_containers.empty()) { + wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); + for (int i = 0; i < 3; i++) { + if (one_slot_containers.empty()) { break; } + + sizer->Add(one_slot_containers.front(), 0, wxLEFT, (i == 0) ? 0 : win->FromDIP(5)); + one_slot_containers.pop_front(); + } + + target_sizer->Add(sizer, 0, wxTOP, win->FromDIP(5)); + } +} + + MaterialItem::MaterialItem(wxWindow *parent, wxColour mcolour, wxString mname) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) { - m_arraw_bitmap_gray = ScalableBitmap(this, "drop_down", FromDIP(12)); - m_arraw_bitmap_white = ScalableBitmap(this, "topbar_dropdown", FromDIP(12)); - m_transparent_mitem = ScalableBitmap(this, "transparent_material_item", FromDIP(32)); + m_arraw_bitmap_gray = ScalableBitmap(this, "drop_down2", FromDIP(8)); + m_arraw_bitmap_white = ScalableBitmap(this, "topbar_dropdown", 12); + m_transparent_mitem = ScalableBitmap(this, "transparent_material_up", 20); + m_filament_wheel_transparent = ScalableBitmap(this, "filament_transparent", 25);//wxGetApp().dark_mode() ? "filament_dark_transparent" + //m_ams_wheel_mitem = ScalableBitmap(this, "ams_wheel", FromDIP(25)); + m_ams_wheel_mitem = ScalableBitmap(this, "ams_wheel_narrow", 25); + m_ams_not_match = ScalableBitmap(this, "filament_not_mactch", 25); m_material_coloul = mcolour; m_material_name = mname; @@ -53,34 +83,58 @@ wxDEFINE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent); MaterialItem::~MaterialItem() {} void MaterialItem::msw_rescale() { - m_arraw_bitmap_gray = ScalableBitmap(this, "drop_down", FromDIP(12)); - m_arraw_bitmap_white = ScalableBitmap(this, "topbar_dropdown", FromDIP(12)); - m_transparent_mitem = ScalableBitmap(this, "transparent_material_item", FromDIP(32)); + m_arraw_bitmap_gray.msw_rescale(); + m_arraw_bitmap_white.msw_rescale(); + m_transparent_mitem.msw_rescale(); + m_ams_wheel_mitem.msw_rescale(); } -void MaterialItem::set_ams_info(wxColour col, wxString txt, int ctype, std::vector cols) +void MaterialItem::allow_paint_dropdown(bool flag) { + if (m_dropdown_allow_painted != flag) { + m_dropdown_allow_painted = flag; + } +} + +void MaterialItem::set_ams_info(wxColour col, wxString txt, int ctype, std::vector cols, bool record_back_info) { auto need_refresh = false; + if (record_back_info) { + m_back_ams_cols = cols; + m_back_ams_ctype = ctype; + m_back_ams_coloul = col; + m_back_ams_name = txt; + } if (m_ams_cols != cols) { m_ams_cols = cols; need_refresh = true; } if (m_ams_ctype != ctype) { m_ams_ctype = ctype; need_refresh = true; } if (m_ams_coloul != col) { m_ams_coloul = col; need_refresh = true;} if (m_ams_name != txt) { m_ams_name = txt; need_refresh = true; } if (need_refresh) { Refresh();} + BOOST_LOG_TRIVIAL(info) << "set_ams_info " << m_ams_name; +} + +void MaterialItem::reset_ams_info() { + m_ams_name = "-"; + m_ams_coloul = wxColour(0xCE, 0xCE, 0xCE); + m_ams_cols.clear(); + m_ams_ctype = 0; + Refresh(); } void MaterialItem::disable() { if (IsEnabled()) { - this->Disable(); - Refresh(); + //this->Disable(); + //Refresh(); + m_enable = false; } } void MaterialItem::enable() { if (!IsEnabled()) { - this->Enable(); - Refresh(); + /*this->Enable(); + Refresh();*/ + m_enable = true; } } @@ -110,18 +164,29 @@ void MaterialItem::on_normal() } -void MaterialItem::paintEvent(wxPaintEvent &evt) -{ +void MaterialItem::paintEvent(wxPaintEvent &evt) +{ wxPaintDC dc(this); render(dc); //PrepareDC(buffdc); //PrepareDC(dc); - + } -void MaterialItem::render(wxDC &dc) +void MaterialItem::render(wxDC &dc) { + + wxString mapping_txt = wxEmptyString; + if (m_ams_name.empty()) { + mapping_txt = "-"; + } else { + mapping_txt = m_ams_name; + } + + if (mapping_txt == "-") { m_match = false;} + else {m_match = true;} + #ifdef __WXMSW__ wxSize size = GetSize(); wxMemoryDC memdc; @@ -160,34 +225,35 @@ void MaterialItem::render(wxDC &dc) } auto material_txt_size = dc.GetTextExtent(m_material_name); - dc.DrawText(m_material_name, wxPoint((MATERIAL_ITEM_SIZE.x - material_txt_size.x) / 2, (FromDIP(22) - material_txt_size.y) / 2)); + dc.DrawText(m_material_name, wxPoint((GetSize().x - material_txt_size.x) / 2, ((float)GetSize().y * 2 / 5 - material_txt_size.y) / 2)); - // mapping num - dc.SetFont(::Label::Body_10); - dc.SetTextForeground(acolor.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30)); - if (acolor.Alpha() == 0) { - dc.SetTextForeground(wxColour(0x26, 0x2E, 0x30)); - } - - wxString mapping_txt = wxEmptyString; - if (m_ams_name.empty()) { - mapping_txt = "-"; - } else { - mapping_txt = m_ams_name; - } auto mapping_txt_size = dc.GetTextExtent(mapping_txt); - dc.DrawText(mapping_txt, wxPoint((MATERIAL_ITEM_SIZE.x - mapping_txt_size.x) / 2, FromDIP(20) + (FromDIP(14) - mapping_txt_size.y) / 2)); + + dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(0x26, 0x2E, 0x30))); + dc.SetFont(::Label::Head_12); + m_text_pos_y =((float)GetSize().y * 3 / 5 - mapping_txt_size.y) / 2 + (float)GetSize().y * 2 / 5; + + if (m_match) { + dc.DrawText(mapping_txt, wxPoint(GetSize().x / 2 + (GetSize().x / 2 - mapping_txt_size.x) / 2 - FromDIP(8) - FromDIP(LEFT_OFFSET), m_text_pos_y)); + } } -void MaterialItem::doRender(wxDC &dc) + +void MaterialItem::match(bool mat) +{ + m_match = mat; + Refresh(); +} + +void MaterialItem::doRender(wxDC& dc) { wxSize size = GetSize(); auto mcolor = m_material_coloul; auto acolor = m_ams_coloul; change_the_opacity(acolor); - if (mcolor.Alpha() == 0 || acolor.Alpha() == 0) { + if (mcolor.Alpha() == 0) { dc.DrawBitmap(m_transparent_mitem.bmp(), FromDIP(1), FromDIP(1)); } @@ -199,16 +265,27 @@ void MaterialItem::doRender(wxDC &dc) //top dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(wxBrush(mcolor)); - dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(18), 5); - + dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, FromDIP(20), 5); + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(mcolor)); + dc.DrawRectangle(0, FromDIP(10), MATERIAL_ITEM_SIZE.x, FromDIP(10)); + + dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.DrawLine(FromDIP(1), FromDIP(20), FromDIP(MATERIAL_ITEM_SIZE.x), FromDIP(20)); + + //bottom rectangle in wheel bitmap, size is MATERIAL_REC_WHEEL_SIZE(22) + auto left = (size.x / 2 - MATERIAL_REC_WHEEL_SIZE.x) / 2 + FromDIP(3); + auto up = (size.y * 0.4 + (size.y * 0.6 - MATERIAL_REC_WHEEL_SIZE.y) / 2); + auto right = left + MATERIAL_REC_WHEEL_SIZE.x - FromDIP(3); + dc.SetPen(*wxTRANSPARENT_PEN); //bottom if (m_ams_cols.size() > 1) { - int left = FromDIP(1); - int gwidth = std::round(MATERIAL_ITEM_REAL_SIZE.x / (m_ams_cols.size() - 1)); + int gwidth = std::round(MATERIAL_REC_WHEEL_SIZE.x / (m_ams_cols.size() - 1)); //gradient if (m_ams_ctype == 0) { for (int i = 0; i < m_ams_cols.size() - 1; i++) { - auto rect = wxRect(left, FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16)); + auto rect = wxRect(left, up, right - left, MATERIAL_REC_WHEEL_SIZE.y); dc.GradientFillLinear(rect, m_ams_cols[i], m_ams_cols[i + 1], wxEAST); left += gwidth; } @@ -217,135 +294,443 @@ void MaterialItem::doRender(wxDC &dc) int cols_size = m_ams_cols.size(); for (int i = 0; i < cols_size; i++) { dc.SetBrush(wxBrush(m_ams_cols[i])); - float x = left + ((float)MATERIAL_ITEM_REAL_SIZE.x) * i / cols_size; + float x = left + ((float)MATERIAL_REC_WHEEL_SIZE.x) * i / cols_size; if (i != cols_size - 1) { - dc.DrawRoundedRectangle(x, FromDIP(18), ((float)MATERIAL_ITEM_REAL_SIZE.x) / cols_size + FromDIP(3), FromDIP(16), 3); + dc.DrawRoundedRectangle(x - FromDIP(LEFT_OFFSET), up, ((float) MATERIAL_REC_WHEEL_SIZE.x) / cols_size + FromDIP(3), MATERIAL_REC_WHEEL_SIZE.y, 3); } else { - dc.DrawRoundedRectangle(x, FromDIP(18), ((float)MATERIAL_ITEM_REAL_SIZE.x) / cols_size , FromDIP(16), 3); + dc.DrawRoundedRectangle(x - FromDIP(LEFT_OFFSET), up, ((float) MATERIAL_REC_WHEEL_SIZE.x) / cols_size - FromDIP(1), MATERIAL_REC_WHEEL_SIZE.y, 3); } } - } } else { - - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(wxColour(acolor))); - dc.DrawRoundedRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16), 5); - ////middle - - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(acolor)); - dc.DrawRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8)); + if (m_match) { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(wxColour(acolor))); + dc.DrawRectangle((size.x / 2 - MATERIAL_REC_WHEEL_SIZE.x) / 2 + FromDIP(3) - FromDIP(LEFT_OFFSET), up, MATERIAL_REC_WHEEL_SIZE.x - FromDIP(1), + MATERIAL_REC_WHEEL_SIZE.y); + } } - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(mcolor)); - dc.DrawRectangle(FromDIP(1), FromDIP(11), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8)); - ////border -#if __APPLE__ - if (mcolor == *wxWHITE || acolor == *wxWHITE) { - dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5); +//#if __APPLE__ +// if (m_match) { +// dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); +// } else { +// dc.SetPen(wxPen(wxColour(234, 31, 48), 2)); +// } +// dc.SetBrush(*wxTRANSPARENT_BRUSH); +// dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_SIZE.x - FromDIP(1), MATERIAL_ITEM_SIZE.y - FromDIP(1), 5); +// +// if (m_selected) { +// dc.SetPen(wxColour(0x44, 0x79, 0xFB)); +// dc.SetBrush(*wxTRANSPARENT_BRUSH); +// dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_SIZE.x - FromDIP(1), MATERIAL_ITEM_SIZE.y - FromDIP(1), 5); +// } +//#else + + if (m_match) { + dc.SetPen(wxPen(wxGetApp().dark_mode() ? wxColour(107, 107, 107) : wxColour(0xAC, 0xAC, 0xAC), FromDIP(1))); + } else { + dc.SetPen(wxPen(wxColour(234, 31, 48), FromDIP(1))); } + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(FromDIP(0), FromDIP(0), MATERIAL_ITEM_SIZE.x - FromDIP(0), MATERIAL_ITEM_SIZE.y - FromDIP(0), 5); + + if (m_selected) { + dc.SetPen(wxPen(wxColour(0x44, 0x79, 0xFB), FromDIP(2))); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_SIZE.x - FromDIP(1), MATERIAL_ITEM_SIZE.y - FromDIP(1), 5); + } +//#endif + if (m_text_pos_y > 0 && m_match) { + // arrow (remove arrow) + if ((acolor.Red() > 160 && acolor.Green() > 160 && acolor.Blue() > 160) && (acolor.Red() < 180 && acolor.Green() < 180 && acolor.Blue() < 180)) { + dc.DrawBitmap(m_arraw_bitmap_white.bmp(), size.x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(4)- FromDIP(LEFT_OFFSET), m_text_pos_y + FromDIP(3)); + } else { + dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), size.x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(4)- FromDIP(LEFT_OFFSET), m_text_pos_y + FromDIP(3)); + } + } + + auto wheel_left = (GetSize().x / 2 - m_ams_wheel_mitem.GetBmpSize().x) / 2 + FromDIP(2); + auto wheel_top = ((float)GetSize().y * 0.6 - m_ams_wheel_mitem.GetBmpSize().y) / 2 + (float)GetSize().y * 0.4; + + if (!m_match) { + wheel_left += m_ams_wheel_mitem.GetBmpSize().x; + dc.DrawBitmap(m_ams_not_match.bmp(), (size.x - m_ams_not_match.GetBmpWidth()) / 2 - FromDIP(LEFT_OFFSET), wheel_top); + } else { + if (acolor.Alpha() == 0) { + dc.DrawBitmap(m_filament_wheel_transparent.bmp(), wheel_left - FromDIP(LEFT_OFFSET), wheel_top); + } else { + dc.DrawBitmap(m_ams_wheel_mitem.bmp(), wheel_left - FromDIP(LEFT_OFFSET), wheel_top); + } + } +} + +void MaterialItem::reset_valid_info() { + set_ams_info(m_back_ams_coloul, m_back_ams_name, m_back_ams_ctype, m_back_ams_cols); +} + + MaterialSyncItem::MaterialSyncItem(wxWindow *parent, wxColour mcolour, wxString mname) : MaterialItem(parent, mcolour, mname) +{ + +} + +MaterialSyncItem::~MaterialSyncItem() {} + +int MaterialSyncItem::get_real_offset() { + int real_left_offset = m_dropdown_allow_painted ? LEFT_OFFSET : -2; + return real_left_offset; +} + +void MaterialSyncItem::render(wxDC &dc) +{ + wxString mapping_txt = wxEmptyString; + if (m_ams_name.empty()) { + mapping_txt = "-"; + } else { + mapping_txt = m_ams_name; + } + + if (mapping_txt == "-") { + m_match = false; + mapping_txt = _L("Unmapped"); + SetToolTip(_L("Upper half area: Original\nLower half area: The filament from original project will be used when unmapped.\nAnd you can click it to modify")); + } else { + m_match = true; + if (m_dropdown_allow_painted) { + SetToolTip(_L("Upper half area: Original\nLower half area: Filament in Box\nAnd you can click it to modify")); + } else { + SetToolTip(_L("Upper half area: Original\nLower half area: Filament in Box\nAnd you cannot click it to modify")); + } + } + dc.SetFont(::Label::Body_12); + if (dc.GetTextExtent(m_material_name).x > GetSize().x - 10) { + dc.SetFont(::Label::Body_10); + } + auto mapping_txt_size = dc.GetTextExtent(mapping_txt); + m_text_pos_y = ((float) GetSize().y * 3 / 5 - mapping_txt_size.y) / 2 + (float) GetSize().y * 2 / 5; +#ifdef __WXMSW__ + wxSize size = GetSize(); + wxMemoryDC memdc; + wxBitmap bmp(size.x, size.y); + memdc.SelectObject(bmp); + memdc.Blit({0, 0}, size, &dc, {0, 0}); + + { + wxGCDC dc2(memdc); + doRender(dc2); + } + + memdc.SelectObject(wxNullBitmap); + dc.DrawBitmap(bmp, 0, 0); +#else + doRender(dc); +#endif + + auto mcolor = m_material_coloul; + auto acolor = m_ams_coloul; + change_the_opacity(acolor); + if (!IsEnabled()) { + mcolor = wxColour(0x90, 0x90, 0x90); + acolor = wxColour(0x90, 0x90, 0x90); + } + + // materials name + dc.SetFont(::Label::Body_12); + + auto material_name_colour = mcolor.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30); + if (mcolor.Alpha() == 0) { material_name_colour = wxColour(0x26, 0x2E, 0x30); } + dc.SetTextForeground(material_name_colour); + + auto full_text = m_material_index + " " + m_material_name; + if (dc.GetTextExtent(full_text).x > GetSize().x - 10) { + dc.SetFont(::Label::Body_10); + } + + auto material_txt_size = dc.GetTextExtent(full_text); + dc.DrawText(full_text, wxPoint((GetSize().x - material_txt_size.x) / 2, ((float) GetSize().y * 2 / 5 - material_txt_size.y) / 2)); + int real_left_offset = get_real_offset(); + if (m_match) { + dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(0x26, 0x2E, 0x30))); + dc.SetFont(::Label::Head_12); + dc.DrawText(mapping_txt, wxPoint(GetSize().x / 2 + (GetSize().x / 2 - mapping_txt_size.x) / 2 - FromDIP(8) - FromDIP(real_left_offset), m_text_pos_y)); + } + else { + if (mcolor.Alpha() == 0) {//Because there is no unknown background color + material_name_colour = StateColor::darkModeColorFor(wxColour(0x26, 0x2E, 0x30)); + } + dc.SetTextForeground(material_name_colour); + if (mapping_txt_size.x > GetSize().x - 10) { + dc.SetFont(::Label::Body_10); + mapping_txt_size = dc.GetTextExtent(mapping_txt); + } + dc.DrawText(mapping_txt, wxPoint(GetSize().x / 2 - mapping_txt_size.x / 2 , m_text_pos_y)); + } +} + +void MaterialSyncItem::doRender(wxDC &dc) +{ + wxSize size = GetSize(); + auto mcolor = m_material_coloul; + auto acolor = m_ams_coloul; + change_the_opacity(acolor); + + if (mcolor.Alpha() == 0) { + dc.DrawBitmap(m_transparent_mitem.bmp(), FromDIP(0), FromDIP(0)); + } + + if (!IsEnabled()) { + mcolor = wxColour(0x90, 0x90, 0x90); + acolor = wxColour(0x90, 0x90, 0x90); + } + + // top + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(mcolor)); + dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, FromDIP(20), 5); + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(mcolor)); + dc.DrawRectangle(0, FromDIP(10), MATERIAL_ITEM_SIZE.x, FromDIP(10)); + + dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.DrawLine(FromDIP(1), FromDIP(20), FromDIP(MATERIAL_ITEM_SIZE.x), FromDIP(20)); + // bottom rectangle in wheel bitmap, size is MATERIAL_REC_WHEEL_SIZE(22) + auto left = (size.x / 2 - MATERIAL_REC_WHEEL_SIZE.x) / 2 + FromDIP(3); + auto up = (size.y * 0.4 + (size.y * 0.6 - MATERIAL_REC_WHEEL_SIZE.y) / 2); + auto right = left + MATERIAL_REC_WHEEL_SIZE.x - FromDIP(3); + dc.SetPen(*wxTRANSPARENT_PEN); + int real_left_offset = get_real_offset(); + // bottom + if (m_match) { + if (m_ams_cols.size() > 1) { + int gwidth = std::round(MATERIAL_REC_WHEEL_SIZE.x / (m_ams_cols.size() - 1)); + // gradient + if (m_ams_ctype == 0) { + if (!m_dropdown_allow_painted) { + left += FromDIP(5); + right += FromDIP(5); + } + for (int i = 0; i < m_ams_cols.size() - 1; i++) { + auto rect = wxRect(left, up, right - left, MATERIAL_REC_WHEEL_SIZE.y); + dc.GradientFillLinear(rect, m_ams_cols[i], m_ams_cols[i + 1], wxEAST); + left += gwidth; + } + } else { + if (!m_dropdown_allow_painted) { + left += FromDIP(5); + } + int cols_size = m_ams_cols.size(); + for (int i = 0; i < cols_size; i++) { + dc.SetBrush(wxBrush(m_ams_cols[i])); + float x = left + ((float) MATERIAL_REC_WHEEL_SIZE.x) * i / cols_size; + if (i != cols_size - 1) { + dc.DrawRoundedRectangle(x - FromDIP(real_left_offset), up, ((float) MATERIAL_REC_WHEEL_SIZE.x) / cols_size + FromDIP(3), MATERIAL_REC_WHEEL_SIZE.y, 3); + } else { + dc.DrawRoundedRectangle(x - FromDIP(real_left_offset), up, ((float) MATERIAL_REC_WHEEL_SIZE.x) / cols_size - FromDIP(1), MATERIAL_REC_WHEEL_SIZE.y, 3); + } + } + } + } else { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(wxColour(acolor))); + dc.DrawRectangle((size.x / 2 - MATERIAL_REC_WHEEL_SIZE.x) / 2 + FromDIP(3) - FromDIP(real_left_offset), up, MATERIAL_REC_WHEEL_SIZE.x - FromDIP(1), + MATERIAL_REC_WHEEL_SIZE.y); + } + } + else { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(mcolor)); + dc.DrawRoundedRectangle(0, FromDIP(21), MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y - FromDIP(21), 5); + + dc.DrawRectangle(0, FromDIP(21), MATERIAL_ITEM_SIZE.x, FromDIP(10)); + } + + ////border +#if __APPLE__ + dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5); + if (m_selected) { dc.SetPen(wxColour(0x44, 0x79, 0xFB)); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5); } #else - if (mcolor == *wxWHITE || acolor == *wxWHITE || acolor.Alpha() == 0) { - dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5); - } + + dc.SetPen(wxPen(wxGetApp().dark_mode() ? wxColour(107, 107, 107) : wxColour(0xAC, 0xAC, 0xAC), FromDIP(1))); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5); if (m_selected) { - dc.SetPen(wxColour(0x44, 0x79, 0xfb)); // y96 modify selected btn_underline color + dc.SetPen(wxPen(wxColour(0x44, 0x79, 0xFB), FromDIP(2))); dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5); + dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_SIZE.x - FromDIP(1), MATERIAL_ITEM_SIZE.y - FromDIP(1), 5); } #endif - //arrow - if ( (acolor.Red() > 160 && acolor.Green() > 160 && acolor.Blue() > 160) && - (acolor.Red() < 180 && acolor.Green() < 180 && acolor.Blue() < 180)) { - dc.DrawBitmap(m_arraw_bitmap_white.bmp(), size.x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_white.GetBmpSize().y); - } - else { - dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), size.x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_gray.GetBmpSize().y); - } - + if (m_text_pos_y > 0 && m_match && m_dropdown_allow_painted) { + // arrow (remove arrow) + if ((acolor.Red() > 160 && acolor.Green() > 160 && acolor.Blue() > 160) && (acolor.Red() < 180 && acolor.Green() < 180 && acolor.Blue() < 180)) { + dc.DrawBitmap(m_arraw_bitmap_white.bmp(), size.x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(4) - FromDIP(real_left_offset), m_text_pos_y + FromDIP(3)); + } else { + dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), size.x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(4) - FromDIP(real_left_offset), m_text_pos_y + FromDIP(3)); + } + } + auto wheel_left = (GetSize().x / 2 - m_ams_wheel_mitem.GetBmpSize().x) / 2 + FromDIP(2); + auto wheel_top = ((float) GetSize().y * 0.6 - m_ams_wheel_mitem.GetBmpSize().y) / 2 + (float) GetSize().y * 0.4; + if (m_match) {// different with parent + if (acolor.Alpha() == 0) { + dc.DrawBitmap(m_filament_wheel_transparent.bmp(), wheel_left - FromDIP(real_left_offset), wheel_top); + } else { + dc.DrawBitmap(m_ams_wheel_mitem.bmp(), wheel_left - FromDIP(real_left_offset), wheel_top); + } + } + //not draw m_ams_not_match } - AmsMapingPopup::AmsMapingPopup(wxWindow *parent) - : PopupWindow(parent, wxBORDER_NONE) +void MaterialSyncItem::set_material_index_str(std::string str) { + m_material_index = str; +} + +AmsMapingPopup::AmsMapingPopup(wxWindow *parent, bool use_in_sync_dialog) : + PopupWindow(parent, wxBORDER_NONE), m_use_in_sync_dialog(use_in_sync_dialog) { - SetSize(wxSize(FromDIP(252), -1)); - SetMinSize(wxSize(FromDIP(252), -1)); - SetMaxSize(wxSize(FromDIP(252), -1)); Bind(wxEVT_PAINT, &AmsMapingPopup::paintEvent, this); - - #if __APPLE__ - Bind(wxEVT_LEFT_DOWN, &AmsMapingPopup::on_left_down, this); + #ifdef __APPLE__ + Bind(wxEVT_LEFT_DOWN, &AmsMapingPopup::on_left_down, this); #endif + SetBackgroundColour(*wxWHITE); - m_sizer_main = new wxBoxSizer(wxVERTICAL); - //m_sizer_main->Add(0, 0, 1, wxEXPAND, 0); + + m_sizer_main = new wxBoxSizer(wxVERTICAL); + m_sizer_ams = new wxBoxSizer(wxHORIZONTAL); + m_sizer_ams_left = new wxBoxSizer(wxVERTICAL); + m_sizer_ams_right = new wxBoxSizer(wxVERTICAL); + m_sizer_ams_left_horizonal = new wxBoxSizer(wxHORIZONTAL); + m_sizer_ams_right_horizonal = new wxBoxSizer(wxHORIZONTAL); + m_sizer_ams_basket_left = new wxBoxSizer(wxVERTICAL); + m_sizer_ams_basket_right = new wxBoxSizer(wxVERTICAL); + auto title_panel = new wxPanel(this, wxID_ANY); - title_panel->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8)); + title_panel->SetBackgroundColour(StateColor::darkModeColorFor("#F1F1F1")); title_panel->SetSize(wxSize(-1, FromDIP(30))); title_panel->SetMinSize(wxSize(-1, FromDIP(30))); - + wxBoxSizer *title_sizer_h= new wxBoxSizer(wxHORIZONTAL); - wxBoxSizer *title_sizer_v = new wxBoxSizer(wxVERTICAL); - auto title_text = new wxStaticText(title_panel, wxID_ANY, _L("BOX Slots")); - title_text->SetForegroundColour(wxColour(0x32, 0x3A, 0x3D)); - title_text->SetFont(::Label::Head_13); - title_sizer_v->Add(title_text, 0, wxALIGN_CENTER, 5); + m_title_text = new wxStaticText(title_panel, wxID_ANY, _L("BOX Slots")); + m_title_text->SetForegroundColour(wxColour(0x32, 0x3A, 0x3D)); + m_title_text->SetFont(::Label::Head_13); + title_sizer_v->Add(m_title_text, 0, wxALIGN_CENTER, 5); title_sizer_h->Add(title_sizer_v, 1, wxALIGN_CENTER, 5); title_panel->SetSizer(title_sizer_h); title_panel->Layout(); title_panel->Fit(); - m_sizer_list = new wxBoxSizer(wxVERTICAL); - for (auto i = 0; i < AMS_TOTAL_COUNT; i++) { - auto sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL); - /*auto ams_mapping_item_container = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("ams_mapping_container", this, 78), wxDefaultPosition, - wxSize(FromDIP(230), FromDIP(78)), 0);*/ - auto ams_mapping_item_container = new MappingContainer(this); - ams_mapping_item_container->SetSizer(sizer_mapping_list); - ams_mapping_item_container->Layout(); - //ams_mapping_item_container->Hide(); - m_amsmapping_container_sizer_list.push_back(sizer_mapping_list); - m_amsmapping_container_list.push_back(ams_mapping_item_container); - m_sizer_list->Add(ams_mapping_item_container, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, FromDIP(5)); - } + m_left_marea_panel = new wxPanel(this); + m_left_marea_panel->SetName("left"); + m_right_marea_panel = new wxPanel(this); + m_right_marea_panel->SetName("right"); + m_left_first_text_panel = new wxPanel(m_left_marea_panel); + m_right_first_text_panel = new wxPanel(m_right_marea_panel); + auto sizer_temp = new wxBoxSizer(wxHORIZONTAL); + /*left ext*/ + m_left_extra_slot = new MappingItem(m_left_marea_panel); + m_left_extra_slot->m_ams_id = VIRTUAL_TRAY_DEPUTY_ID; + m_left_extra_slot->m_slot_id = 0; + m_left_extra_slot->SetSize(wxSize(FromDIP(48), FromDIP(60))); + m_left_extra_slot->SetMinSize(wxSize(FromDIP(48), FromDIP(60))); + m_left_extra_slot->SetMaxSize(wxSize(FromDIP(48), FromDIP(60))); - m_warning_text = new wxStaticText(this, wxID_ANY, wxEmptyString); - m_warning_text->SetForegroundColour(wxColour(0xFF, 0x6F, 0x00)); - m_warning_text->SetFont(::Label::Body_12); - auto cant_not_match_tip = _L("Note: Only the BOX slots loaded with the same material type can be selected."); - m_warning_text->SetLabel(format_text(cant_not_match_tip)); - m_warning_text->SetMinSize(wxSize(FromDIP(248), FromDIP(-1))); - m_warning_text->Wrap(FromDIP(248)); + auto left_panel = new wxPanel(m_left_marea_panel); + left_panel->SetSize(wxSize(FromDIP(182), FromDIP(60))); + left_panel->SetMinSize(wxSize(FromDIP(182), FromDIP(60))); + left_panel->SetMaxSize(wxSize(FromDIP(182), FromDIP(60))); + + sizer_temp->Add(m_left_extra_slot); + sizer_temp->Add(left_panel); + + /*right ext*/ + m_right_extra_slot = new MappingItem(m_right_marea_panel); + m_right_extra_slot->m_ams_id = VIRTUAL_TRAY_MAIN_ID; + m_right_extra_slot->m_slot_id = 0; + m_right_extra_slot->SetSize(wxSize(FromDIP(48), FromDIP(60))); + m_right_extra_slot->SetMinSize(wxSize(FromDIP(48), FromDIP(60))); + m_right_extra_slot->SetMaxSize(wxSize(FromDIP(48), FromDIP(60))); + + m_single_tip_text = _L("Please select from the following filaments"); + m_left_tip_text = _L("Select filament that installed to the left nozzle"); + m_right_tip_text = _L("Select filament that installed to the right nozzle"); + + m_left_tips = new Label(m_left_first_text_panel); + m_left_tips->SetForegroundColour(StateColor::darkModeColorFor("0x262E30")); + m_left_tips->SetBackgroundColour(StateColor::darkModeColorFor("0xFFFFFF")); + m_left_tips->SetFont(::Label::Body_13); + m_left_tips->SetLabel(m_left_tip_text); + m_sizer_ams_left_horizonal->Add(m_left_tips, 0, wxEXPAND, 0); + m_left_first_text_panel->SetSizer(m_sizer_ams_left_horizonal); + + m_sizer_ams_left->Add(m_left_first_text_panel, 0, wxEXPAND | wxBOTTOM | wxTOP , FromDIP(8)); + m_left_split_ams_sizer = create_split_sizer(m_left_marea_panel, _L("Left BOX")); + m_sizer_ams_left->Add(m_left_split_ams_sizer, 0, wxEXPAND, 0); + m_sizer_ams_left->Add(m_sizer_ams_basket_left, 0, wxEXPAND|wxTOP, FromDIP(8)); + m_sizer_ams_left->Add(create_split_sizer(m_left_marea_panel, _L("External")), 0, wxEXPAND|wxTOP, FromDIP(8)); + //m_sizer_ams_left->Add(m_left_extra_slot, 0, wxEXPAND|wxTOP, FromDIP(8)); + m_sizer_ams_left->Add(sizer_temp, 0, wxEXPAND | wxTOP, FromDIP(8)); + + m_right_tips = new Label(m_right_first_text_panel); + m_right_tips->SetForegroundColour(StateColor::darkModeColorFor("0x262E30")); + m_right_tips->SetBackgroundColour(StateColor::darkModeColorFor("0xFFFFFF")); + m_right_tips->SetFont(::Label::Body_13); + m_right_tips->SetLabel(m_right_tip_text); + m_sizer_ams_right_horizonal->Add(m_right_tips, 0, wxEXPAND , 0); + + m_reset_btn = new ScalableButton(m_right_first_text_panel, wxID_ANY, wxGetApp().dark_mode() ? "erase_dark" : "erase", wxEmptyString, wxDefaultSize, wxDefaultPosition, + wxBU_EXACTFIT | wxNO_BORDER, true, 14); + m_reset_btn->SetName(wxGetApp().dark_mode() ? "erase_dark" : "erase"); + m_reset_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { reset_ams_info(); }); + m_reset_btn->SetBackgroundColour(*wxWHITE); + m_reset_btn->SetToolTip(_L("Reset current filament mapping")); + + m_sizer_ams_right_horizonal->AddStretchSpacer(); + m_sizer_ams_right_horizonal->AddSpacer(FromDIP(5)); + m_sizer_ams_right_horizonal->Add(m_reset_btn, 0, wxALIGN_TOP | wxEXPAND ); + m_reset_btn->Hide(); + m_right_first_text_panel->SetSizer(m_sizer_ams_right_horizonal); + const int same_height = 15; + m_left_first_text_panel->SetMaxSize(wxSize(-1, FromDIP(same_height))); + m_right_first_text_panel->SetMaxSize(wxSize(-1, FromDIP(same_height))); + + m_sizer_ams_right->Add(m_right_first_text_panel, 0, wxEXPAND | wxBOTTOM | wxTOP, FromDIP(8)); + m_right_split_ams_sizer = create_split_sizer(m_right_marea_panel, _L("Right BOX")); + m_sizer_ams_right->Add(m_right_split_ams_sizer, 0, wxEXPAND, 0); + m_sizer_ams_right->Add(m_sizer_ams_basket_right, 0, wxEXPAND|wxTOP, FromDIP(8)); + m_sizer_ams_right->Add(create_split_sizer(m_right_marea_panel, _L("External")), 0, wxEXPAND|wxTOP, FromDIP(8)); + m_sizer_ams_right->Add(m_right_extra_slot, 0, wxEXPAND|wxTOP, FromDIP(8)); + + + m_left_marea_panel->SetSizer(m_sizer_ams_left); + m_right_marea_panel->SetSizer(m_sizer_ams_right); + + //m_sizer_ams->Add(m_left_marea_panel, 0, wxEXPAND, FromDIP(0)); + m_sizer_ams->Add(m_left_marea_panel, 0, wxRIGHT, FromDIP(10)); + m_sizer_ams->Add(0, 0, 0, wxEXPAND, FromDIP(15)); + m_sizer_ams->Add(m_right_marea_panel, 1, wxEXPAND, FromDIP(0)); m_sizer_main->Add(title_panel, 0, wxEXPAND | wxALL, FromDIP(2)); - m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); - m_sizer_main->Add(m_sizer_list, 0, wxEXPAND | wxALL, FromDIP(0)); - m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); - m_sizer_main->Add(m_warning_text, 0, wxEXPAND | wxALL, FromDIP(6)); + m_sizer_main->Add(m_sizer_ams, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(14)); + m_sizer_main->Add( 0, 0, 0, wxTOP, FromDIP(14)); SetSizer(m_sizer_main); Layout(); @@ -360,38 +745,78 @@ void MaterialItem::doRender(wxDC &dc) }); } - wxString AmsMapingPopup::format_text(wxString &m_msg) + void AmsMapingPopup::reset_ams_info() { - if (wxGetApp().app_config->get("language") != "zh_CN") { return m_msg; } - - wxString out_txt = m_msg; - wxString count_txt = ""; - int new_line_pos = 0; - - for (int i = 0; i < m_msg.length(); i++) { - auto text_size = m_warning_text->GetTextExtent(count_txt); - if (text_size.x < (FromDIP(280))) { - count_txt += m_msg[i]; - } else { - out_txt.insert(i - 1, '\n'); - count_txt = ""; - } + if (m_reset_callback) { + m_reset_callback(m_material_index); } - return out_txt; } -void AmsMapingPopup::update_materials_list(std::vector list) -{ +void AmsMapingPopup::set_reset_callback(ResetCallback callback) { + m_reset_callback = callback; +} + +void AmsMapingPopup::show_reset_button() { + m_reset_btn->Show(); +} + +void AmsMapingPopup::set_only_show_ext_spool(bool flag) { + m_only_show_ext_spool = flag; +} + +void AmsMapingPopup::msw_rescale() +{ + m_left_extra_slot->msw_rescale(); + m_right_extra_slot->msw_rescale(); + for (auto item : m_mapping_item_list) { item->msw_rescale(); } + for (auto container : m_amsmapping_container_list) { container->msw_rescale(); } + + Fit(); + Refresh(); +}; + + void AmsMapingPopup::set_sizer_title(wxBoxSizer *sizer, wxString text) { + if (!sizer) { return; } + wxSizerItemList items = sizer->GetChildren(); + for (wxSizerItemList::iterator it = items.begin(); it != items.end(); ++it) { + wxSizerItem *item = *it; + auto temp_label = dynamic_cast