From b29879e5acff3e48ab073ae9af694ea24070ea57 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 4 Sep 2026 04:16:40 +0000 Subject: [PATCH 1/4] fix(cli): trim .stl name by 4 chars in assemble-list (#560) STL object names were trimmed by 3 chars, leaving a trailing '.' on the assemble-list CLI path. Trim 4 chars for .stl only; leave .obj at 3 chars. construct_assemble_list entry name unchanged. Co-authored-by: aceRage --- src/Snapmaker_Orca.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Snapmaker_Orca.cpp b/src/Snapmaker_Orca.cpp index 7ba92e92d3f6..9fb8630e8551 100644 --- a/src/Snapmaker_Orca.cpp +++ b/src/Snapmaker_Orca.cpp @@ -1034,7 +1034,7 @@ static int construct_assemble_list(std::vector &assemble_ BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": found no mesh data from stl file %1%, plate index %2%, object index %3%") % assemble_object.path % (index + 1) % (obj_index + 1); return CLI_DATA_FILE_ERROR; } - object_name.erase(object_name.end() - 3, object_name.end()); + object_name.erase(object_name.end() - 4, object_name.end()); } else if (boost::algorithm::iends_with(assemble_object.path, ".obj")) { From 312dcf9b94b2589d6c95967fb6b88e74779e1b30 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 4 Sep 2026 04:16:59 +0000 Subject: [PATCH 2/4] fix(partplate): null-safe plate name texture + invalidate (#560) CLI assemble-list plate loading has no GUI plater/canvas. Early-return generate_plate_name_texture when canvas is unavailable, and invalidate the name texture/raycaster from clear() and set_plate_name instead of raw reset/generate. Encapsulates Ultra's m_name_texture.reset() so GUI lazy-regenerate still works. Co-authored-by: aceRage --- src/slic3r/GUI/PartPlate.cpp | 24 +++++++++++++++++++++--- src/slic3r/GUI/PartPlate.hpp | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index c60366cb0c66..bb35ea3aa5c0 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1827,7 +1827,7 @@ void PartPlate::clear(bool clear_sliced_result) m_ready_for_slice = true; update_slice_result_valid_state(false); } - m_name_texture.reset(); + invalidate_plate_name_texture(); return; } @@ -1917,6 +1917,10 @@ Vec3d PartPlate::get_center_origin() void PartPlate::generate_plate_name_texture() { + auto canvas = (m_partplate_list != nullptr && m_partplate_list->m_plater != nullptr) ? m_partplate_list->m_plater->get_view3D_canvas3D() : nullptr; + if (canvas == nullptr) + return; + m_plate_name_icon.reset(); // generate m_name_texture texture from m_name with generate_from_text_string @@ -1954,11 +1958,25 @@ void PartPlate::generate_plate_name_texture() if (!init_model_from_poly(m_plate_name_icon, poly, GROUND_Z)) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; - auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D(); canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6)); calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon); register_model_for_picking(*canvas, m_plate_name_edit_icon, picking_id_component(6)); } + +void PartPlate::invalidate_plate_name_texture() +{ + // Ultra: encapsulate the existing clear() texture reset so set_plate_name + // still lazy-regenerates via render_plate_name_texture (get_id() == 0). + m_name_texture.reset(); + m_plate_name_edit_icon.mesh_raycaster.reset(); + + auto canvas = (m_plater != nullptr) ? m_plater->get_view3D_canvas3D() : nullptr; + if (canvas != nullptr) { + canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6)); + canvas->set_as_dirty(); + } +} + void PartPlate::set_plate_name(const std::string& name) { // compare if name equal to m_name, case sensitive @@ -1969,7 +1987,7 @@ void PartPlate::set_plate_name(const std::string& name) if (m_print != nullptr) m_print->set_plate_name(name); - generate_plate_name_texture(); + invalidate_plate_name_texture(); } //get the print's object, result and index diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index e73364037bd1..b1aeaa74dfe6 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -193,6 +193,7 @@ class PartPlate : public ObjectBase void render_icons(bool bottom, bool only_name = false, int hover_id = -1); void render_only_numbers(bool bottom); void render_plate_name_texture(); + void invalidate_plate_name_texture(); void register_raycasters_for_picking(GLCanvas3D& canvas); int picking_id_component(int idx) const; From 80eae2299366a0d7423d0bfaefcaad78d87aa94c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 4 Sep 2026 04:17:26 +0000 Subject: [PATCH 3/4] fix(partplate): skip GUI set_shape work when m_plater == nullptr (#560) CLI plate loading has no plater. Keep non-GUI set_shape work (calc_bounding_boxes, height limit) and skip logo/mesh/icon/grid/ raycaster/name-texture initialization when m_plater is null. Co-authored-by: aceRage --- src/slic3r/GUI/PartPlate.cpp | 74 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index bb35ea3aa5c0..360ede46fd62 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2713,43 +2713,43 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve calc_bounding_boxes(); - ExPolygon logo_poly; - generate_logo_polygon(logo_poly); - m_logo_triangles.reset(); - if (!init_model_from_poly(m_logo_triangles, logo_poly, GROUND_Z + 0.02f)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create logo triangles\n"; - - ExPolygon poly; - /*for (const Vec2d& p : m_shape) { - poly.contour.append({ scale_(p(0)), scale_(p(1)) }); - }*/ - generate_print_polygon(poly); - calc_triangles(poly); - init_raycaster_from_model(m_triangles); - - ExPolygon exclude_poly; - /*for (const Vec2d& p : m_exclude_area) { - exclude_poly.contour.append({ scale_(p(0)), scale_(p(1)) }); - }*/ - generate_exclude_polygon(exclude_poly); - calc_exclude_triangles(exclude_poly); - - const BoundingBox& pp_bbox = poly.contour.bounding_box(); - calc_gridlines(poly, pp_bbox); - - //calc_vertex_for_icons_background(5, m_del_and_background_icon); - //calc_vertex_for_icons(4, m_del_icon); - calc_vertex_for_icons(0, m_del_icon); - calc_vertex_for_icons(1, m_orient_icon); - calc_vertex_for_icons(2, m_arrange_icon); - calc_vertex_for_icons(3, m_lock_icon); - calc_vertex_for_icons(4, m_plate_settings_icon); - calc_vertex_for_icons(5, m_move_front_icon); - // ORCA also change bed_icon_count number in calc_vertex_for_icons() after adding or removing icons for circular shaped beds that uses vertical alingment for icons - - //calc_vertex_for_number(0, (m_plate_index < 9), m_plate_idx_icon); - calc_vertex_for_number(0, false, m_plate_idx_icon); - if (m_plater) { + if (m_plater != nullptr) { + ExPolygon logo_poly; + generate_logo_polygon(logo_poly); + m_logo_triangles.reset(); + if (!init_model_from_poly(m_logo_triangles, logo_poly, GROUND_Z + 0.02f)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create logo triangles\n"; + + ExPolygon poly; + /*for (const Vec2d& p : m_shape) { + poly.contour.append({ scale_(p(0)), scale_(p(1)) }); + }*/ + generate_print_polygon(poly); + calc_triangles(poly); + init_raycaster_from_model(m_triangles); + + ExPolygon exclude_poly; + /*for (const Vec2d& p : m_exclude_area) { + exclude_poly.contour.append({ scale_(p(0)), scale_(p(1)) }); + }*/ + generate_exclude_polygon(exclude_poly); + calc_exclude_triangles(exclude_poly); + + const BoundingBox& pp_bbox = poly.contour.bounding_box(); + calc_gridlines(poly, pp_bbox); + + //calc_vertex_for_icons_background(5, m_del_and_background_icon); + //calc_vertex_for_icons(4, m_del_icon); + calc_vertex_for_icons(0, m_del_icon); + calc_vertex_for_icons(1, m_orient_icon); + calc_vertex_for_icons(2, m_arrange_icon); + calc_vertex_for_icons(3, m_lock_icon); + calc_vertex_for_icons(4, m_plate_settings_icon); + calc_vertex_for_icons(5, m_move_front_icon); + // ORCA also change bed_icon_count number in calc_vertex_for_icons() after adding or removing icons for circular shaped beds that uses vertical alingment for icons + + //calc_vertex_for_number(0, (m_plate_index < 9), m_plate_idx_icon); + calc_vertex_for_number(0, false, m_plate_idx_icon); // calc vertex for plate name generate_plate_name_texture(); } From 3954065948968bf16125b34800aecc132a49e26d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 4 Sep 2026 04:17:37 +0000 Subject: [PATCH 4/4] fix(cli): skip expand_plate_extruders in get_extruders_under_cli (#562) expand_plate_extruders needs GUI preset_bundle. Skip it only on the CLI extruder path; leave GUI get_extruders helpers and dual-nozzle paths unchanged. Ultra CLI debug logs around the function retained. Co-authored-by: aceRage --- src/slic3r/GUI/PartPlate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 360ede46fd62..7af3ca3e8eb7 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1604,7 +1604,8 @@ std::vector PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D std::sort(plate_extruders.begin(), plate_extruders.end()); auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end()); plate_extruders.resize(std::distance(plate_extruders.begin(), it_end)); - expand_plate_extruders(plate_extruders); + // Do not call expand_plate_extruders() from the CLI path. It depends on + // wxGetApp().preset_bundle, which is GUI state and may be unavailable here. std::ostringstream extruders_list; for (size_t i = 0; i < plate_extruders.size(); ++i) { if (i != 0)