From 5f2f0829ddf321219bac5e1977dc1b4278b8d75c Mon Sep 17 00:00:00 2001 From: Dark98 Date: Sun, 25 Jan 2026 03:59:24 +0000 Subject: [PATCH] Auto Arrange Rotation & Bed Edge Clearance --- .../slicebeam/config/ConfigObject.java | 2 + .../fragment/PrinterConfigFragment.java | 5 ++ .../ru/ytkab0bp/slicebeam/slic3r/Bed3D.java | 3 - .../slicebeam/slic3r/Slic3rConfigWrapper.java | 2 +- app/src/main/jni/libslic3r/PrintConfig.cpp | 14 +++++ app/src/main/jni/slicebeam/beam_native.cpp | 60 ++++++++++++++++++- 6 files changed, 81 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/ru/ytkab0bp/slicebeam/config/ConfigObject.java b/app/src/main/java/ru/ytkab0bp/slicebeam/config/ConfigObject.java index e761902..39b83df 100644 --- a/app/src/main/java/ru/ytkab0bp/slicebeam/config/ConfigObject.java +++ b/app/src/main/java/ru/ytkab0bp/slicebeam/config/ConfigObject.java @@ -92,6 +92,8 @@ public class ConfigObject implements ProfileListFragment.ProfileListItem { ConfigObject custom = new ConfigObject(SliceBeam.INSTANCE.getString(R.string.IntroCustomProfileName)); custom.put("printer_technology", "FFF"); custom.put("bed_shape", "0x0,200x0,200x200,0x200"); + custom.put("auto_arrange_bed_clearance", "5"); + custom.put("auto_arrange_rotate", "1"); custom.put("binary_gcode", "0"); custom.put("gcode_flavor", "marlin"); custom.put("max_print_height", "200"); diff --git a/app/src/main/java/ru/ytkab0bp/slicebeam/fragment/PrinterConfigFragment.java b/app/src/main/java/ru/ytkab0bp/slicebeam/fragment/PrinterConfigFragment.java index 32804f8..88b1c17 100644 --- a/app/src/main/java/ru/ytkab0bp/slicebeam/fragment/PrinterConfigFragment.java +++ b/app/src/main/java/ru/ytkab0bp/slicebeam/fragment/PrinterConfigFragment.java @@ -165,6 +165,11 @@ public class PrinterConfigFragment extends ProfileListFragment { )); } list.addAll(Arrays.asList( + new OptionElement(R.drawable.settings_outline_28, "Advanced"), + new OptionElement(new SubHeader("Auto arrange")), + new OptionElement(def.options.get("auto_arrange_bed_clearance")), + new OptionElement(def.options.get("auto_arrange_rotate")), + new OptionElement(R.drawable.note_pen_outline_96, "Notes"), new OptionElement(new SubHeader("Notes")), new OptionElement(def.options.get("printer_notes")), diff --git a/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Bed3D.java b/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Bed3D.java index 4465d18..0e2110b 100644 --- a/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Bed3D.java +++ b/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Bed3D.java @@ -88,9 +88,6 @@ public class Bed3D { assertTrue(projectionMatrix.length == 16); DoubleMatrix.setIdentityM(modelMatrix, 0); - if (!likelyDelta) { - DoubleMatrix.translateM(modelMatrix, 0, -getVolumeMin().x * 2, -getVolumeMin().y * 2, -getVolumeMin().z); - } DoubleMatrix.multiplyMM(outModelMatrix, 0, viewModelMatrix, 0, modelMatrix, 0); renderDefaultBed(shadersManager, bottom, outModelMatrix, projectionMatrix); axes.render(shadersManager, viewModelMatrix, projectionMatrix, 0.25f, invZoom); diff --git a/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Slic3rConfigWrapper.java b/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Slic3rConfigWrapper.java index 4d5f2d7..68b6112 100644 --- a/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Slic3rConfigWrapper.java +++ b/app/src/main/java/ru/ytkab0bp/slicebeam/slic3r/Slic3rConfigWrapper.java @@ -80,7 +80,7 @@ public class Slic3rConfigWrapper { ); public final static List PRINTER_CONFIG_KEYS = Arrays.asList( "printer_technology", "autoemit_temperature_commands", - "bed_shape", "bed_custom_texture", "bed_custom_model", "binary_gcode", "z_offset", "gcode_flavor", "use_relative_e_distances", + "bed_shape", "auto_arrange_bed_clearance", "auto_arrange_rotate", "bed_custom_texture", "bed_custom_model", "binary_gcode", "z_offset", "gcode_flavor", "use_relative_e_distances", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height", "prefer_clockwise_movements", //FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset. "host_type", "print_host", "printhost_apikey", "printhost_cafile", diff --git a/app/src/main/jni/libslic3r/PrintConfig.cpp b/app/src/main/jni/libslic3r/PrintConfig.cpp index ab1f64a..16e9fb0 100644 --- a/app/src/main/jni/libslic3r/PrintConfig.cpp +++ b/app/src/main/jni/libslic3r/PrintConfig.cpp @@ -345,6 +345,20 @@ void PrintConfigDef::init_common_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }); + def = this->add("auto_arrange_bed_clearance", coFloat); + def->label = L("Auto-arrange bed clearance"); + def->tooltip = L("Minimum distance from the bed edge when auto arranging."); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(5.0)); + + def = this->add("auto_arrange_rotate", coBool); + def->label = L("Auto-arrange rotation"); + def->tooltip = L("Allow auto-arrange to rotate objects on the bed."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(true)); + def = this->add("bed_custom_texture", coString); def->label = L("Bed custom texture"); def->mode = comAdvanced; diff --git a/app/src/main/jni/slicebeam/beam_native.cpp b/app/src/main/jni/slicebeam/beam_native.cpp index aa1f325..d4b99fa 100644 --- a/app/src/main/jni/slicebeam/beam_native.cpp +++ b/app/src/main/jni/slicebeam/beam_native.cpp @@ -23,6 +23,7 @@ #include #include +#include using namespace Slic3r; using namespace Slic3r::GUI; @@ -1428,7 +1429,64 @@ extern "C" { DynamicPrintConfig config = ref->config; arr2::ArrangeBed bed = arr2::to_arrange_bed(get_bed_shape(config)); arr2::ArrangeSettings arrange_cfg; - return arrange_objects(mRef->model, bed, arrange_cfg); + arrange_cfg.set_arrange_strategy(arr2::ArrangeSettingsView::asPullToCenter); + arrange_cfg.set_xl_alignment(arr2::ArrangeSettingsView::xlpCenter); + float bed_clearance = 5.0f; + if (const auto* clearance_opt = config.opt("auto_arrange_bed_clearance")) { + bed_clearance = clearance_opt->value; + } + arrange_cfg.set_distance_from_bed(bed_clearance); + bool allow_rotation = false; + if (const auto* rotate_opt = config.opt("auto_arrange_rotate")) { + allow_rotation = rotate_opt->value; + } + arrange_cfg.set_rotation_enabled(allow_rotation); + const bool arranged = arrange_objects(mRef->model, bed, arrange_cfg); + + if (!mRef->model.objects.empty()) { + const BoundingBoxf3 bed_bb = ref->build_volume.bounding_volume(); + const BoundingBoxf3 pile_bb = mRef->model.bounding_box_exact(); + const double margin = arrange_cfg.get_distance_from_bed(); + + const double allowed_min_x = bed_bb.min.x() + margin; + const double allowed_max_x = bed_bb.max.x() - margin; + const double allowed_min_y = bed_bb.min.y() + margin; + const double allowed_max_y = bed_bb.max.y() - margin; + + const double width = pile_bb.size().x(); + const double height = pile_bb.size().y(); + const Vec3d pile_center = pile_bb.center(); + + const double min_center_x = allowed_min_x + width * 0.5; + const double max_center_x = allowed_max_x - width * 0.5; + const double min_center_y = allowed_min_y + height * 0.5; + const double max_center_y = allowed_max_y - height * 0.5; + + double target_center_x = pile_center.x(); + if (min_center_x <= max_center_x) { + target_center_x = std::max(min_center_x, std::min(pile_center.x(), max_center_x)); + } else { + target_center_x = (allowed_min_x + allowed_max_x) * 0.5; + } + + double target_center_y = pile_center.y(); + if (min_center_y <= max_center_y) { + target_center_y = std::max(min_center_y, std::min(pile_center.y(), max_center_y)); + } else { + target_center_y = (allowed_min_y + allowed_max_y) * 0.5; + } + + const double dx = target_center_x - pile_center.x(); + const double dy = target_center_y - pile_center.y(); + if (std::abs(dx) > 1e-6 || std::abs(dy) > 1e-6) { + const Vec3d shift(dx, dy, 0.0); + for (ModelObject* obj : mRef->model.objects) { + obj->translate_instances(shift); + } + } + } + + return arranged; } JNIEXPORT jdoubleArray JNICALL Java_ru_ytkab0bp_slicebeam_slic3r_Native_bed_1get_1bounding_1volume(JNIEnv* env, jclass, jlong ptr) {