Compare commits

..

93 Commits

Author SHA1 Message Date
Joseph Robertson
75770321dd Update Belt-Printer (#14425) 2026-06-25 22:40:26 -05:00
Joseph Robertson
c950c3fb6b Add BabyBelt Pro Profile, Courtesy of Rexit (#14424) 2026-06-25 22:39:12 -05:00
Joseph Robertson
2ca843a38e Belt Printing: Bugfix: Solid Organic Tree Base, Slim Tree Skirt, Renderer (#14395)
* fix tree support brim
* treesupport3d part 1: more diagnostic logging.  (todo once things are fixed: remove this / gate it properly)
* make area under Z=0 in rotated slice pipeline not solid
* fix solid Z=0 layer for belt printers
* fix renderer
* clean up logging
* final review pass
2026-06-24 22:01:29 -05:00
Joseph Robertson
0ef7c6d581 Belt Printing: Update (#14393)
# Description

<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
  > * What issue does this PR address or fix?
  > * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->

# Screenshots/Recordings/Graphs

<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->

## Tests

<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->

<!--
> A guide for users on how to download the artifacts from this PR.
-->

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
2026-06-24 21:34:53 -05:00
Joseph Robertson
34b0d36cda Belt Printer Initial Push (#14385)
# Description

Initial push - documentation available at #12998 

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
2026-06-24 09:42:40 -05:00
Joseph Robertson
d619c7e19c Merge branch 'belt-printer' into belt/baseChanges 2026-06-24 09:42:25 -05:00
Joseph Robertson
31b44cb731 Merge pull request #66 from HarrierPigeon/belt/tommyb-rendererChanges
Clean up and implement @tommasobbianchi's belt renderer changes
2026-06-23 00:27:39 -05:00
harrierpigeon
ddbee84e68 render the G-code preview upright (designed view) + toggle UI 2026-06-23 00:14:17 -05:00
Joseph Robertson
bf6cce1f40 Merge pull request #45 from tommasobbianchi/feat/belt-gcode-cartesian-preview
belt: render the G-code preview upright (model/Cartesian space)
2026-06-22 19:59:27 -05:00
Joseph Robertson
8bdf0df00a Merge branch 'main' into belt/baseChanges 2026-06-22 19:36:17 -05:00
Joseph Robertson
d6c9187c71 Merge branch 'main' into belt/baseChanges 2026-06-22 19:36:17 -05:00
Ian Bassi
0cdfb88357 Lang: Gettext update (#14361) 2026-06-22 20:16:55 -03:00
foXaCe
14cec7239b i18n(fr): translate strings added after the post-refactor sync (#14304) 2026-06-22 20:13:19 -03:00
Heiko Liebscher
86c6a1a66f Improve German (de) translation (#14352)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 15:40:14 -03:00
SoftFever
07f08dfe40 bump version to 2.5.0-dev 2026-06-22 00:50:51 +08:00
Noisyfox
a4fb5af9e1 Don't allow adding more colors for non-semm printers on obj import color remapping dialog (#14275) 2026-06-21 18:20:58 +08:00
Tommaso Bianchi
8593d66a39 belt: correct the designed-view preview's belt-Z origin and reject mis-mapped outliers
The Cartesian designed-view preview over-extended the toolpaths past the model
shell by a height-proportional amount (up to ~20mm tall parts), most visibly on
long multi-part prints; compact parts like a calibration cube looked fine.

Two coupled causes:
- Belt start G-code that primes with a Z advance and a 'G92 Z0' reset leaves a
  constant machine-Z origin in the GCodeProcessor, so move positions are stored as
  gcode_Z + origin. The linear back-transform mixes that constant with the
  gantry-Y term, leaving a per-move designed-Y error that min-corner anchoring
  cannot cancel when an elevated move (e.g. a bridge) happens to cancel it at the
  bbox minimum. Expose GCodeProcessorResult::belt_z_origin (the m_origin[Z] left by
  the start G-code) and subtract it before the back-transform.
- Elevated features (bridges/overhangs) are mis-mapped by the linear inverse to
  outside the model body; build the anchor bbox only from moves within model_bb +/-
  10mm, with a fallback to the full bbox when the clip would drop the bulk (object
  placed away from the belt entry) so the gross-offset case still anchors.

Preview-only; G-code output is unchanged.
2026-06-21 06:48:44 +02:00
Tommaso Bianchi
3fc3b8a8ae belt: anchor the designed-view G-code preview onto the model bounding box
The belt designed (upright) preview back-transforms the machine-frame G-code
into model space with the linear belt inverse. That inverse recovers the
print's shape and orientation, but not the per-object placement/lift
translation: the object's position on the belt, the BeltSliceStrategy min-Z
lift, and the centering pre-translate are applied OUTSIDE
build_forward_transform() (see PrintObjectSlice.cpp), so its linear inverse
cannot undo them. The result was a constant offset (~20 mm on the belt-advance
axis) of the toolpaths from the model shell, on every model.

Recover the missing translation generally — independent of the offset's exact
source or the axis remap — by anchoring the back-transformed object body
(extrusions on layer_id >= 1, i.e. excluding the layer-0 prime/skirt) onto the
upright model bounding box, the same space the shells render in, and folding
that translation into the belt inverse before converting to libvgcode.

Replaces the previous Y=0 anchoring in LibVGCodeWrapper, which pinned the
toolpaths to the belt entry rather than to the model and so left the offset in
place for any object not sitting at the origin.
2026-06-21 06:48:44 +02:00
Tommaso Bianchi
695a1f897a belt: render the G-code preview in model (Cartesian) space
On a belt printer the emitted G-code is in the machine frame (45-deg sheared,
axis-remapped, scaled), so the toolpath preview shows the print as a sheared
slab floating off the bed. Map each toolpath vertex back to model/Cartesian
space for the "designed" view.

The back-transform is the inverse of the full G-code forward pipeline
(BeltGCodeWriter::to_machine_coords):
  model = [BeltForward^-1 if !gcode_back_transform] . AxisRemap^-1 . MachineFrame^-1
built from config, so it handles any rotation / shear / scale / axis-remap
combination, not just plain 45-deg belt slicing. Computed in load_as_gcode()
from print.config() and applied per-vertex inside libvgcode::convert (display
position only; layer_id, times and the volumetric/flow math keep the raw
machine values, so the layer slider and stats are unaffected).

- Toggle with the existing "Show designed view" checkbox / hotkey B; off shows
  the raw machine-frame G-code (useful for debugging the transform itself).
  Defaults to on.
- Belt printers skip the same-result-id load cache so the upright view applies
  and the toggle takes effect even when the G-code is unchanged.
- The object extrusions (layer_id >= 1) are anchored to the belt entry to drop
  the constant machine-origin offset (start-G-code belt advance) that the linear
  back-transform alone does not capture; start-G-code prime lines are excluded
  so they don't steal the anchor.
2026-06-21 06:48:44 +02:00
Tommaso Bianchi
2d69f6e17c belt: expose MachineFrameTransform's composed matrix
Add a const accessor for the shear*scale transform so the G-code viewer can
build the machine->model back-transform for the upright belt preview.
2026-06-21 06:48:44 +02:00
Joseph Robertson
340ce575e2 Merge branch 'main' into belt/baseChanges 2026-06-20 15:56:59 -05:00
Joseph Robertson
d795900fcf Merge pull request #64 from tommasobbianchi/feat/esun-pla-maxvolspeed-tuning
IdeaFormer IR3 V2: tune eSUN PLA white speed from HW max-vol-speed calibration
2026-06-18 09:42:19 -05:00
Joseph Robertson
9b1fb2217a Merge branch 'main' into belt/baseChanges 2026-06-18 09:41:14 -05:00
Tommaso Bianchi
ef6f65eacc IdeaFormer IR3 V2: tune eSUN PLA white speed from HW max-vol-speed calibration
Physical max-volumetric-speed test (belt #62 v4 asset) on the IR3 V2 with eSUN
PLA white: the wall stayed clean up to ~100 mm/s = ~20 mm3/s before
under-extrusion. The shipped cap of 10 mm3/s was ~half the real ceiling and
was silently throttling infill.

- eSUN PLA @IdeaFormer IR3 V2: filament_max_volumetric_speed 10 -> 20
- 0.20mm Standard @IdeaFormer IR3 V2: sparse_infill_speed 200 (~18 mm3/s at the
  new cap, no longer throttled). Outer wall (45), PA (0.12), accel (1000)
  unchanged — accuracy preserved.
- IdeaFormer.json version bump for profile-cache refresh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 07:13:59 +02:00
Joseph Robertson
0add523e1b Merge branch 'main' into belt/baseChanges 2026-06-13 08:23:47 -05:00
Joseph Robertson
375036f330 Merge pull request #44 from tommasobbianchi/feat/belt-skip-height-check
belt: don't reject long objects (skip build-height check on belt printers)
2026-06-13 08:23:26 -05:00
Joseph Robertson
fbbeb1fab0 Merge pull request #58 from HarrierPigeon/belt/tempTower-TommyB
Belt/temp tower tommy b
2026-06-12 05:53:32 -05:00
harrierpigeon
0bca3fd2e5 make belt printer specific temp tower only accessible to belt printers 2026-06-12 05:13:08 -05:00
Tommaso Bianchi
85fd613cf7 feat(belt/calib): add Overhang temperature-tower model (selectable) (#48)
Belt printers can't slice a tall vertical temperature tower. This adds a
belt-specific temperature-tower model — a row of discrete, individually
engraved provini laid along the belt, each printed at one temperature via
custom per-layer M104. Each provino is an inverted-L overhang that stresses
print quality, so the operator reads the best temperature off overhang
quality rather than a continuous ramp.

It is offered as a "Test model" choice in the temperature calibration dialog
(mirroring the Cornering test's selector), so users keep Joe's counter-rotated
sectioned tower as "Standard" and can pick this one as "Overhang":
- Calib_Params::test_model (existing field) carries the choice.
- Temp_Calibration_Dlg gets a Standard/Overhang radio.
- Plater::calib_temp belt branch: test_model 0 -> _calib_temp_belt_sectioned
  (unchanged Standard path), 1 -> the discrete-provini Overhang path.

Assets: belt_temp_provino_unit.stl + belt_temp_tower_<start>_<end>.stl (6
ranges) + gen_belt_temp_tower.py (manifold engraving). Based on
belt/generic-calibrations. The Overhang path is HW-validated on the IdeaFormer
IR3 V2 (discrete M104 + engraved numbers); not re-validated since the rebase.
2026-06-12 05:13:07 -05:00
Joseph Robertson
0da24cd38b Belt/Standard calibrations (#54)
Enables supported printing of standard Orcaslicer calibration profiles.

* Build 2 Checkpoint

* fix support generation wedge, ghost layers

* flip cornering tests 180 deg to waste less supports

* fix row spacing on the flow ratio calibrations

* more testing, this didn't fix anything

* switched rotation tools, same issue

* fixed Z-offset issues

* add rest of PA features, may look a bit weird on a belt

* make temp towers work

* re-enable spiral on calibrations that want it

* Final cleanup pre-PR and community testing
2026-06-12 03:14:12 -05:00
Rodrigo Faselli
d7b75540d0 Merge branch 'main' into belt/baseChanges 2026-06-11 11:59:53 -03:00
Tommaso Bianchi
b7bda9912b belt: fix IR3 V2 end G-code reversing the belt into the part (#56)
The IdeaFormer IR3 V2 End G-code ran `G28 ; home all`, which homes the
Z (belt) and Y (gantry) axes. On a belt printer Z is the conveyor, so
homing it runs the belt all the way back to origin, dragging the finished
part back under the gantry that G28 has just lowered — the head knocks the
print (reported by an IR3 V2 user; the `G1 Y50` lift came after the G28,
too late).

Replace the end sequence with a belt-safe one: switch to relative mode
(G91), lift the gantry for clearance, advance the belt forward one full
machine-depth (Z676, the 676 mm product depth) to eject the part and cycle
the belt surface clean, then home X only — never the Z/belt axis.
2026-06-11 09:30:35 -05:00
Tommaso Bianchi
4f3a608009 belt: don't flag the lead-in as an empty-layer error on belt printers (#47)
collect_layers_to_print() warns (CRITICAL) when an extrusion layer sits above
the previous one with an empty gap below — the fixed-bed assumption that
material with nothing under it is floating and unprintable. On a belt printer a
*leading* empty range (the gap starts at Z=0, no prior extrusion layer) is not
floating: it is the conveyor lead-in, and the part rests on the advancing belt
as the first material is laid down well above Z=0. A part not designed for a
belt (e.g. a flat test model tilted into the belt frame) then trips this as a
false "Object can't be printed for empty layer between 0 and N" error.

Suppress only the leading case (belt_printer && last_extrusion_layer == null);
genuine internal gaps are still flagged, since on a belt those can be an
over-angle overhang printing into air. Non-belt output is unchanged.
2026-06-10 23:54:02 -05:00
Tommaso Bianchi
f682ab5cd3 belt: replace height-check skip with a belt-correct vertical-clearance check
The original PR skipped the max-print-height check entirely on belt printers
because the sliced (virtual) Z is belt travel, not build height. As the reviewer
noted, that removed the only working height guard. Restore a correct guard:

- Print::validate: on belt printers, compare the upright object height
  (max over instances of the scene-space bbox) against printable_height directly.
  printable_height is the usable VERTICAL clearance above the belt: the gantry
  travels up the tilted plane (reach = height/cos(tilt)) and its axis range is
  sized for that (IR3 V2: ~354 mm gantry travel = 250 mm vertical at 45deg, and
  printable_height = 250). Hardware-confirmed 250 mm vertical clearance, so no
  cos(tilt) factor is applied.
- BuildVolume::set_belt_printer: drop the diagonal Z scaling; the build-volume Z
  already equals printable_height, keeping the live 'outside build volume'
  highlight in agreement with validate().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 21:41:18 +02:00
harrierpigeon
2bcb775b90 update IdeaFormer profiles to new generic belt printer config 2026-06-10 05:10:20 -05:00
Joseph Robertson
e29a82c672 add attribution and design notes 2026-06-10 05:10:20 -05:00
Joseph Robertson
5b243eec92 Relocate Pre-Slice remap logic 2026-06-10 05:10:20 -05:00
Joseph Robertson
fee6be98b2 unify frame tilt work 2026-06-10 05:10:20 -05:00
Joseph Robertson
9405ac5976 remove mesh origin snapping 2026-06-10 05:10:20 -05:00
Tommaso Bianchi
6ed2437848 Add IdeaFormer IR3 V2 belt printer profile - credit: tommasobbianchi (#43)
* Add IdeaFormer IR3 V2 belt printer profile

Self-contained vendor profile for the IdeaFormer IR3 V2 (45 deg belt printer):
machine (0.4 nozzle) + 0.20mm process + Generic PLA/PETG filaments, with the
belt machine-frame transforms set explicitly on the machine preset
(belt_printer, belt_slice_rotation x/45/global, build_plate_tilt_x=45,
gcode_remap_x/y/z, gcode_shear_z=pos_tan, gcode_scale_y=inv_cos).

The vendor bundles its own machine/process commons (fdm_belt_common,
fdm_klipper_common, fdm_machine_common, fdm_process_common) on purpose:
OrcaSlicer resolves system-preset inheritance per-vendor, so a profile that
inherits the Custom vendor's commons cross-vendor fails to resolve its parent
and the whole IdeaFormer vendor silently fails to load. Bundling the commons
(and listing them in IdeaFormer.json in dependency order) keeps the vendor
self-contained, matching how every other vendor folder is structured.

Machine limits, bed temperature (75 C for belt PLA) and start/end G-code are
taken from a working IdeaFormer IR3 V2.



* feat(belt/profile): eSUN PLA @IdeaFormer IR3 V2 — HW-calibrated belt filament

Add an eSUN PLA belt profile for the IR3 V2, inheriting Generic PLA @IdeaFormer
IR3 V2 (self-contained: parent is in the same IdeaFormer vendor, registered
after it in filament_list). HW-calibrated on the IR3 V2:
- nozzle_temperature 200/200 (temp-tower calibration)
- pressure_advance 0.12 (PA calibration)
- filament_max_volumetric_speed 10 mm³/s (max-vol-speed calibration: wall
  failed at 126 mm/s → 126 × 0.0798 mm³/mm ≈ 10 mm³/s)
2026-06-10 04:13:56 -05:00
Joseph Robertson
da3fee2dfa Merge branch 'main' into belt/baseChanges 2026-06-05 11:55:44 -05:00
Joseph Robertson
c0d6ae8540 Merge branch 'main' into belt/baseChanges 2026-06-05 03:12:27 -05:00
Joseph Robertson
573e1c6544 Belt/fix profiles and minor oopsies (#42)
* fix duplicate printer, bump version

* clean up extra tab in space

* fix generic defaults
2026-06-05 03:11:38 -05:00
Rodrigo Faselli
20be78a96e Merge branch 'main' into belt/baseChanges 2026-06-04 17:32:35 -03:00
Joseph Robertson
02d45c3258 Finish Fixes from Copilot Review (#39)
* fix: restore BuildVolume bounds when toggling belt mode

set_belt_printer() mutated m_bboxf when enabling but never restored
the original extents on disable or when switching infinite_y true->false,
leaving stale max.y/max.z values that broke collision and object_state
checks. Recompute m_bboxf from m_bed_shape + m_max_print_height at the
top of each call, then apply belt-specific adjustments on top.

Addresses Copilot review comment on PR #12998 (BuildVolume.cpp:196).

* chore: drop [BELT-DEBUG] to_machine_coords log to trace

Was emitting at warning level once per 0.2mm Z bucket during every belt
print export, polluting default user logs. Trace level matches the rest
of the belt diagnostics and is silent in production.

Addresses Copilot review comment on PR #12998 (BeltGCodeWriter.cpp:86).

* chore: drop [BELTRACE] make_perimeters/support logs to trace

Eight warning-level traces around make_perimeters and
generate_support_material were emitting on every call/exit during normal
slicing, cluttering default logs. They're concurrency-debug breadcrumbs
not user-facing diagnostics, so drop them to trace.

Addresses Copilot review comment on PR #12998 (PrintObject.cpp:438).

* perf: gate BeltSliceStrategy diagnostic bbox tracking behind compile flag

apply_to_trafo() walked every model vertex twice (once for min_z, once
for per-volume mesh/slicer bboxes) and emitted seven trace logs per
call. The bboxes and logs are diagnostic only; min_z is the load-bearing
output. Wrap the bbox accumulation, logging, and supporting headers in
SLIC3R_BELT_DIAGNOSTIC_LOG so production builds do the bare min_z scan.

Addresses Copilot review comment on PR #12998 (BeltSliceStrategy.cpp:95).

* fix: apply part_cooling_fan_min_pwm to first-layer plane fan crossings

apply_first_layer_plane_fan_eval emitted band-crossing M106 commands
through GCodeWriter::set_fan() without the per-printer PWM floor that
every other set_fan call in CoolingBuffer applies. On printers with a
non-zero part_cooling_fan_min_pwm, fans could fail to spin up at low
requested speeds near the belt surface.

Addresses Copilot review comment on PR #12998 (CoolingBuffer.cpp:1227).
2026-06-04 14:40:45 -05:00
harrierpigeon
f9888c7d7a Merge remote-tracking branch 'upstream/main' into belt/baseChanges 2026-05-31 05:17:32 -05:00
Joseph Robertson
0bda684dd7 delete mesh transforms (#37)
* delete mesh shear, scale and refactor logger

* clean up config options

* reorder UI elements
2026-05-31 05:08:42 -05:00
Joseph Robertson
8a578cdf00 Merge branch 'main' into belt/baseChanges 2026-05-30 21:39:03 -05:00
Rodrigo Faselli
6b256db012 Merge branch 'main' into belt/baseChanges 2026-05-28 07:44:43 -03:00
Joseph Robertson
2dc4900292 Copilot review fixes & upstream code interaction fix (#34)
* first pass at review issue 8
* delete detritus
* fix build compile error due to upstream changes
2026-05-27 21:53:04 -05:00
Joseph Robertson
0f75d6bc4e Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-27 19:25:02 -05:00
Joseph Robertson
e913621369 Merge branch 'main' into belt/baseChanges 2026-05-27 11:50:16 -05:00
Joseph Robertson
48b6db93b8 Belt/slice rotate (#33)
* initial commit
* fix upper bounds for assemblies
* significantly less Z shift issues, still not quite tamped down yet though
* add instrumentation to logs
* finally found the issue
* update printer defaults
2026-05-27 11:45:38 -05:00
Joseph Robertson
72cafcbe06 Merge branch 'main' into belt/baseChanges 2026-05-22 15:23:07 -05:00
Joseph Robertson
a9bae54f20 Rotate instead of shear for slicing stage (#30)
* initial commit

* fix upper bounds for assemblies

* significantly less Z shift issues, still not quite tamped down yet though

* add instrumentation to logs

* finally found the issue

* update printer defaults
2026-05-22 15:21:33 -05:00
Joseph Robertson
218881c6f6 fix assembly bounding box truncation problems noticed by hotcubcar (#28) 2026-05-20 02:46:41 -05:00
Joseph Robertson
cd5fb68d38 Merge branch 'main' into belt/baseChanges 2026-05-19 23:00:14 -05:00
Joseph Robertson
f87a46ec6e fix X mirroring (#26)
Thanks to @hotcubcar for catching this!
2026-05-19 22:54:50 -05:00
Rodrigo Faselli
8dc91d8b1d Merge branch 'main' into belt/baseChanges 2026-05-19 08:06:57 -03:00
Joseph Robertson
da8b11b8ab HOTFIX: update generic belt printer profile (#23)
oops
2026-05-19 01:06:39 -05:00
Joseph Robertson
c79970bedb Clean Up Settings Interface, Update Generic Profile (#22)
* clean up UI elements

* further cleaning

* final cleanup for first round of settings UI streamlining

* update generic belt printer settings

* fix generic again
2026-05-19 00:56:08 -05:00
harrierpigeon
7252f6acb7 Merge upstream/main into belt/rebase/may-18
Reconciles the belt-printer branch with upstream PRs through #13723. Six
files had conflicts; three additional files needed manual follow-up fixes
where the auto-merge produced code that referenced upstream-renamed fields
or changed function signatures.

Notable reconciliations:
- TreeSupport.cpp: kept belt-floor early-exit branches around HEAD's
  drop-down logic, folded upstream's `(distance_to_top > 0 ? 1 : 0)`
  formula into the non-belt-floor path (upstream PR #11812). Dropped dead
  `roof_enabled`/`force_tip_to_roof` locals.
- TreeSupport3D.cpp: combined upstream's safety-offset + remove_small
  changes with HEAD's belt-floor clip in the per-slice trim loop. Dropped
  HEAD's `else` block (superseded by upstream's rewritten bottom-contact
  propagation) and re-added the belt-floor clip into the new propagation
  loop. Gated the propagation on belt printers to prevent OOM when
  belt-floor clipping produces empty initial slices.
- TriangleSelector.{cpp,hpp}: merged both new `select_patch` parameters
  (HEAD's `up_direction` and upstream's `select_partially`); body uses
  `dot(up_direction)` for the overhang angle check and forwards
  `select_partially` to `select_triangle`.
- SupportMaterial.cpp: `slicing_params.soluble_interface` →
  `zero_gap_interface_bottom` in HEAD's `detect_belt_floor_bottom_contacts`,
  matching upstream's same-purpose rename at line 2495.
- Custom.json, GCodeWriter.cpp: simple additive merges (kept entries /
  includes from both sides).

Verified by building OrcaSlicer (RelWithDebInfo) after a full deps
rebuild (Eigen v5.0.1, libigl v2.6.0 are now managed deps) and slicing
a scaled Benchy on the NORMALIZER belt-printer profile without OOM.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 21:53:24 -05:00
Joseph Robertson
6a2d690f45 Decouple Slicing From Machine Frame Logic (#21)
* minor logic swap

* first attempt, has a race condition

* fixed the offset issue

* found a solution, I think things work now (at least once I quash this race condition)

* still chasing down race conditions

* add manual shear / scale order strategy swap

* tweak manual shear, fix ui uninitialization crash

* fix z height / g-code desync issue

* fix shear then scale cutoff planes

* getting closer

* fix support termination planes

* fix incorrect offsets in shear-then-scale mode

* test - fix overextrusion due to model/layer scale
2026-05-18 19:01:43 -05:00
RF47
8fa6a4602b fix profile indentation 2026-05-09 19:51:18 -03:00
harrierpigeon
0f29437135 Merge remote-tracking branch 'upstream/main' into belt/baseChanges
Conflicts resolved in src/libslic3r/GCode.cpp and src/slic3r/GUI/GUI_Factories.cpp.

GCode.cpp: combined upstream's air-filtration per-extruder gating
(activate_air_filtration_during_print / _on_completion), the new
extrusion-role-change gcode lambda, ZAA's path.z_contoured arc-fit
disable, raft-aware slow_down_layers branch, and Vec3d/Line3 ZAA
plumbing with the local belt-printer changes (path_on_first_layer,
effective_layer_index_for_point, should_disable_arc_fitting). All
auto-merged m_writer.X() calls converted to m_writer->X() to match
the local unique_ptr<GCodeWriter> refactor.

GUI_Factories.cpp: inserted brim_flow_ratio in the Support category
list and renumbered around the local build_plate_tilt_x/y entries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:23:41 -05:00
SoftFever
75cc0de071 Merge branch 'main' into belt/baseChanges 2026-04-17 15:44:03 +08:00
Joseph Robertson
bc6d0ef0fb Add first layer detection and fan control - prototype 2026-04-13 22:29:23 -05:00
Joseph Robertson
c17ae25bbc Merge branch 'main' into belt/baseChanges 2026-04-13 21:34:34 -05:00
harrierpigeon
e981a517cd Merge branch 'belt/global-mesh-transform' into temp-pr19-merge 2026-04-10 11:49:37 -05:00
harrierpigeon
0703728e56 add global mesh transform option 2026-04-10 11:39:08 -05:00
SoftFever
1e9ee0c120 add a generic belt printer 2026-04-09 23:07:08 -05:00
harrierpigeon
e9a579b604 switch default shear axis, swap to tan(a) instead of cot(a) 2026-04-09 23:07:07 -05:00
harrierpigeon
783acd932a revert CLAUDE.md 2026-04-09 23:07:07 -05:00
harrierpigeon
c8a1bf3a99 Part 3.2: decouple axis remapping, enable viewing settings in Developer mode or when Belt mode is active 2026-04-09 23:07:07 -05:00
harrierpigeon
2facaac9e8 Part 3.1: refactor BeltTransform pipeline
add BeltGCodeWriter

add BeltGCode

consolidate changes into shared classes for BeltGcode
2026-04-09 23:07:07 -05:00
harrierpigeon
9bbac19de4 Part 2.7: Add G-code back-transform and tree support belt floor clipping
- Add BeltBackTransform class that inverts the shear/scale matrix and
  applies it in GCodeWriter::to_machine_coords() so G-code outputs in
  the machine's physical coordinate space, gated by new
  belt_gcode_back_transform config option
- Extend belt floor clipping to all three tree support pipelines
  (Prusa-style, Orca organic, TreeModelVolumes) with per-layer polygon
  clipping, anti-overhang integration, and belt raft extension layers
- Fix tree drop_nodes() belt termination, organic support global Z
  offset, collision calculation index bug, and first-layer brim/empty
  layer checks for belt printers

two-shot - first build built but didn't plumb to UI.  Woah.

add pre-slice axis remap, because Y needs to be Z

going to change tactic and move based on bbox min

switch to per axis snapping

per axis swap snap now per object

build plate tilt wasn't invalidating slicer settings

support upper bound now correct, need to get lower bound corrected

axis swapped support termination corrected

Z Shear works with and without pre-slice remap now
2026-04-09 23:07:07 -05:00
harrierpigeon
ea5c6776b3 Part 2.6: Add belt floor support clipping for all support types
- Fix support clipping z-shift calculation by removing coordinate-space
  mismatch and sync belt_floor_z_shift with global_z_offset; fix
  invalidation so posSupportMaterial no longer resets slicing params
- Add belt floor polygon clipping to non-organic tree support
  (slim/strong/hybrid) with collision surface integration in
  TreeSupportData, belt extension layers, and first-layer brim
  suppression
- Add belt floor clipping to organic tree support pipeline with virtual
  belt raft layers, per-layer polygons in TreeModelVolumes, and
  post-generation layer trimming; fix pre-existing processing_last_mesh
  bug in calculateCollision()

Fix belt floor support clipping: z-shift, invalidation, and global offset

- Fix support clipping z-shift calculation by removing coordinate-space
  mismatch (raw_bounding_box min.z vs trafo_centered m_belt_min_z) and
  sync belt_floor_z_shift with global_z_offset in global shear mode
- Fix invalidation so posSupportMaterial no longer resets slicing params,
  preventing the exact posSlice z-shift from being overwritten by the
  bounding-box approximation on support-only setting changes
- Remove double-counting of global z_offset on support layers — support
  already inherits the offset from object layers during generation

This Work Was Co-Authored-By Claude Opus 4.6 (1M context) <noreply@anthropic.com>

UI: gray out inactive belt sub-options, rename to mesh transforms, move to Advanced

Fix mesh clipping through build plate after belt shear/scale transform

Generalize G-code viewer designed-view toggle for full belt transform

Clip support layers to transformed belt floor plane

Supports below the tilted build plate (Z = shear_factor * from_axis - min_z)
are now clipped via half-plane intersection after generation. Belt floor
parameters stored in SlicingParameters and populated in both update_slicing_parameters()
and the static slicing_parameters() overload.

Make belt G-code viewer toggle more prominent, add B keyboard shortcut

- Add separator + teal "Belt Printer" header in legend panel
- Append [B] hint to checkbox label
- Add B key shortcut in GLCanvas3D to toggle designed/machine view
- Read belt_printer_angle from loaded G-code headers to enable belt view

Add per-axis global transform option for belt printer shear

New belt_shear_{x,y,z}_global bool configs. When enabled, shear incorporates
instance shift so objects at different bed positions get position-aware
transform (Z += factor * instance_shift_on_from_axis).

Fix global shear: use layer Z offset instead of mesh transform, add config invalidation

- Global shear offset applied as post-slicing layer print_z adjustment
  instead of mesh transform (which was absorbed by min_z normalization
  or shifted mesh out of slice range)
- Register all belt transform options in Print::invalidate_state_by_config_options
  to trigger posSlice re-slicing (the fallback only invalidated Print steps,
  not PrintObject steps — belt changes had no effect without manual re-slice)
- Belt gcode remap options added to steps_gcode (gcode-export only)
- Skip empty-first-layer check for belt objects with global Z offset

WIP: split instances for global shear, relative Z offsets, debug logging

- PrintApply: when belt global mode active, prevent instance grouping by
  adding unique Z perturbation to trafo — each copy becomes its own
  PrintObject with independent layers
- PrintObjectSlice: compute global Z offset relative to minimum Y shift
  across all PrintObjects (lowest-Y object stays at Z=0)
- Debug logging (warning level) for belt global shift values and offsets

Known issues:
- Cached posSlice results cause stale offsets when mixing copies with
  individually-added objects — need to compute min baseline outside slice()
- Supports still generate to Z=0 instead of object's global Z offset

Fix global shear for copied objects: disable shared-object layer optimization

When belt global Z shear is active, each object needs unique layer Z
values based on its bed position. The shared-object optimization was
causing copies to reuse the source object's layers (and its Z offset)
instead of computing their own position-based offset.

started work on getting supports to work properly

one step forward, one step back

this version didn't quite work.  Getting somewhere though

about to add UI controllable tests

added configuration options for supports

tweak CLAUDE.md to be more aggressive for my machine.  This commit should probably be pulled out before contributing upstream

still chasing down some bugs

moving objects between slices no longer results in improper Z-height because of caching

added more data to the debug logs

Z offset is getting more global again

still not quite there, I think there's a fundamental logic flaw?

hunting for bugs

finally have a functional fix

Add belt floor clipping to tree supports (organic and non-organic)

- Add belt floor polygon clipping to non-organic tree support
  (slim/strong/hybrid) in draw_circles() and terminate nodes at the
  belt surface instead of the horizontal build plate
- Add belt floor clipping to organic tree support pipeline with virtual
  belt raft layers for sub-floor branch generation, per-layer belt
  floor polygons in TreeModelVolumes, and post-generation layer trimming
- Fix pre-existing processing_last_mesh bug in TreeModelVolumes that
  prevented m_anti_overhang (support blockers) from ever being applied;
  skip empty first layer check for belt printers

Commits:

current approach: make a face surface to build supports to

closer!

supports now terminate on shear plane, now need to get shear plane to correct Z height

nearly there

chasing down logic issues still

committing for checkpoint, this still does not work

still got logic problems...

cull support clipping

stashing changes for now.  Going to focus on getting the global shear OFF support generation dialed first.

beginning per object shear calcs

Local shear transform is on correct Z offset now

local shear finally works now and needs more testing

global shear works now, needs thorough testing

debugging non-45 degree angles

debugging part 2

supports at all angles work now

remove debug logging

Add belt floor collision to non-organic tree support pipeline

- Integrate belt floor as a collision surface in TreeSupportData so
  branches route around the belt naturally, replacing the explicit
  termination checks in drop_nodes()
- Add belt extension layers below the object after draw_circles() to
  allow support geometry to extend to the diagonal belt surface instead
  of terminating at a horizontal first layer
- Fix coordinate overflow in belt floor polygons (scale_(1e4) exceeds
  int32), skip first-layer brim expansion for belt printers, and
  extend empty first layer check bypass to all belt modes

add debug logging, Z translate for tree supports

still not seeing any cutoff surface yet

adding debug options

attempt #2 at trees

if hit Z buildplate stop but don't set to_buildplate true

getting closer

tree support almost there, just need to get rid of the circles at the beginning

getting closer

belt / shear plane clip works, need to figure out the buidlplate plane issues

more logic, added debugging logs

supports now extend somewhat below Z=0 in global shear mode

fix bad alloc, add 10mm below build plate

fully works now

shear transform + prusa tree support generation works now.

pull out debug logging
2026-04-09 23:07:07 -05:00
harrierpigeon
98f4d34dcb Part 2.5: Add global shear transform, support clipping, and belt UI improvements
- Implement per-object global shear transform in PrintObject with
  layer Z-offset calculation, config invalidation, and fix for
  shared-object layer optimization breaking copied objects
- Clip support layers to the transformed belt floor plane and begin
  work on tree support adaptation for sheared coordinate space
- Improve belt UI: gray out inactive sub-options, add B keyboard
  shortcut for G-code viewer design-view toggle, fix mesh clipping
  through build plate after shear/scale transform

y' = y + z·cot(α),
  while x' = x and z' = z

getting closer to customizable variant

getting closer

X/Y/Z shear initial

clean up UI

add 1/sin(a) transform, idea taken from blackbelt cura plugin

Things work now (turns out I've been using the wrong set of  transforms)
2026-04-09 23:07:07 -05:00
harrierpigeon
501aff7e53 Part 2: Replace belt rotation w/ per-axis shear transforms and G-code axis remap
- Replace monolithic belt rotation transform with independent per-axis
    shear controls (mode/angle/source-axis for X, Y, Z) and G-code axis
    remapping, giving full flexibility to match any belt printer's
    coordinate system
  - Remove all rotation mode logic and intermediate type+axes dropdowns,
    simplifying the pipeline to pure shear matrices while preserving the
    default behavior (Y += Z*cot(45deg) with identity remap)
  - Clean up GCodeWriter, GCodeProcessor, and GCodeViewer for the new
    shear-only model; expose 12 new settings in printer UI via
    Tab.cpp/Preset.cpp

Implement belt printer tilted slicing

Implement the core belt slicing pipeline that makes the slicer
tilt-aware:

Step 1: GCodeWriter::to_machine_coords() - R(+alpha, X) rotation
  from slicing frame to machine frame
Step 2: PrintObject - belt-rotated object height calculation
  (y*sin(a) + z*cos(a)) for correct layer count
Step 3: PrintObjectSlice - apply R(-alpha, X) rotation trafo so
  horizontal slice planes correspond to belt-parallel planes,
  with Z-shift computed from model volumes
Step 4: GCodeProcessor - machine-frame preview (no transform needed)
Step 5: 3DBed - rotate bed visualization about X by belt angle

Fix: belt surface IS the build plate, no mesh rotation

Currently still slicing perpendicular to the belt normal.  Need to figure out why.

Fix G-code Z sign: use R(-alpha, X) so Z+ is away from belt

The previous R(+alpha, X) transform produced negative Z values
(-y*sin(a) term dominated). Changed to R(-alpha, X) which gives
machine_z = y*sin(a) + z*cos(a), always positive for points
above the belt surface. Z increases with each layer as expected.

reverting and changing slice methodology

Add pink slicing direction arrow from origin

Shows the effective slicing direction (gantry normal) as a pink
arrow from the origin. Shorter and wider than the gravity arrow.
Direction: R(+alpha, X) * Z = (0, -sin(a), cos(a)), which is
the layer stacking direction in the original mesh frame.

Fix slicing arrow visibility and add raw G-code toggle

- Disable depth test for pink slicing arrow so it renders on top of
  the tilted bed geometry (was being occluded)
- Remove unnecessary 5mm Z-offset from arrow position
- Add m_belt_show_raw toggle to GCodeViewer
- Add "Show raw G-code (slicing frame)" checkbox in legend when
  belt mode is active

Implement to_machine_coords inverse rotation for belt printer G-code

The slicing pipeline rotates the mesh by R(-alpha, X) and shifts Z to
start at 0. The G-code output now undoes this transform via
to_machine_coords: R(+alpha, X) * T(0,0,+z_shift), recovering the
original machine-frame coordinates where Y is horizontal and Z is
vertical.

Changes:
- GCodeWriter: implement to_machine_coords with inverse rotation + Z-shift
- GCodeWriter: add belt_z_shift member and setter/getter
- GCode.cpp: compute Z-shift from print objects (same logic as
  PrintObjectSlice) and pass to writer; write z_shift to G-code header
- GCodeProcessor: parse belt_z_shift from G-code header
- GCodeViewer: store belt_z_shift from processor result

Wire raw G-code toggle to apply slicing-frame view transform

When "Show raw G-code (slicing frame)" is checked in the preview
legend, the view matrix is modified to apply R(-alpha, X) * T(0,0,-z_shift)
to the toolpath rendering. This shows the G-code as it was during
slicing: rotated part with horizontal layers.

Default (unchecked): machine-frame view — upright part with tilted layers.

Remove belt printer placeholder comment from GCodeProcessor

The preview now correctly displays machine-frame G-code with the
optional raw view toggle. No transform is needed in the processor.
2026-04-09 23:07:06 -05:00
harrierpigeon
c808653565 Add belt printer transform pipeline: slicing rotation, G-code coords, preview
- Implement core belt slicing pipeline: R(-alpha, X) mesh rotation in PrintObjectSlice with corrected object height calculation for proper layer count
Add to_machine_coords() in GCodeWriter to convert slicing-frame coordinates back to machine-frame, propagated through GCode,
GCodeProcessor, and GCodeViewer
Add belt-mode UI: tilted bed visualization, slicing-direction arrow, and raw G-code toggle to switch between machine-frame and slicing-frame views

This is a combination of 6 commits.

checkpoint 1: initial MVP.  Slicing functions, but rotates instead of skews are happening and a lot of other stuff too

getting somewhere, getting to the point where I need to figure out how to verify this stuff

this appears to be a dead end.

getting somewhere I think maybe

I'm pretty sure we've completely lost the plot at this point and need to restart this process...

remove slice logic in preparation for new, more invasive plan
2026-04-09 23:07:06 -05:00
harrierpigeon
a7441c7f48 stage in changes from off-plate-gravity and remove stuff I didn't need 2026-04-09 23:07:06 -05:00
SoftFever
3bc13e5cfd add a generic belt printer 2026-04-07 10:37:34 +08:00
SoftFever
141749a6f2 Merge branch 'main' into belt/baseChanges 2026-04-06 22:52:31 +08:00
harrierpigeon
4634a5dfd7 switch default shear axis, swap to tan(a) instead of cot(a) 2026-03-30 13:25:40 -05:00
harrierpigeon
372139c770 revert CLAUDE.md 2026-03-30 13:25:40 -05:00
harrierpigeon
44eebdb8ad Part 3.2: decouple axis remapping, enable viewing settings in Developer mode or when Belt mode is active 2026-03-30 13:25:40 -05:00
harrierpigeon
c7aa4ca3ef Part 3.1: refactor BeltTransform pipeline
add BeltGCodeWriter

add BeltGCode

consolidate changes into shared classes for BeltGcode
2026-03-30 13:25:40 -05:00
harrierpigeon
b297f68921 Part 2.7: Add G-code back-transform and tree support belt floor clipping
- Add BeltBackTransform class that inverts the shear/scale matrix and
  applies it in GCodeWriter::to_machine_coords() so G-code outputs in
  the machine's physical coordinate space, gated by new
  belt_gcode_back_transform config option
- Extend belt floor clipping to all three tree support pipelines
  (Prusa-style, Orca organic, TreeModelVolumes) with per-layer polygon
  clipping, anti-overhang integration, and belt raft extension layers
- Fix tree drop_nodes() belt termination, organic support global Z
  offset, collision calculation index bug, and first-layer brim/empty
  layer checks for belt printers

two-shot - first build built but didn't plumb to UI.  Woah.

add pre-slice axis remap, because Y needs to be Z

going to change tactic and move based on bbox min

switch to per axis snapping

per axis swap snap now per object

build plate tilt wasn't invalidating slicer settings

support upper bound now correct, need to get lower bound corrected

axis swapped support termination corrected

Z Shear works with and without pre-slice remap now
2026-03-30 13:25:40 -05:00
harrierpigeon
7ff6bc42b1 Part 2.6: Add belt floor support clipping for all support types
- Fix support clipping z-shift calculation by removing coordinate-space
  mismatch and sync belt_floor_z_shift with global_z_offset; fix
  invalidation so posSupportMaterial no longer resets slicing params
- Add belt floor polygon clipping to non-organic tree support
  (slim/strong/hybrid) with collision surface integration in
  TreeSupportData, belt extension layers, and first-layer brim
  suppression
- Add belt floor clipping to organic tree support pipeline with virtual
  belt raft layers, per-layer polygons in TreeModelVolumes, and
  post-generation layer trimming; fix pre-existing processing_last_mesh
  bug in calculateCollision()

Fix belt floor support clipping: z-shift, invalidation, and global offset

- Fix support clipping z-shift calculation by removing coordinate-space
  mismatch (raw_bounding_box min.z vs trafo_centered m_belt_min_z) and
  sync belt_floor_z_shift with global_z_offset in global shear mode
- Fix invalidation so posSupportMaterial no longer resets slicing params,
  preventing the exact posSlice z-shift from being overwritten by the
  bounding-box approximation on support-only setting changes
- Remove double-counting of global z_offset on support layers — support
  already inherits the offset from object layers during generation

This Work Was Co-Authored-By Claude Opus 4.6 (1M context) <noreply@anthropic.com>

UI: gray out inactive belt sub-options, rename to mesh transforms, move to Advanced

Fix mesh clipping through build plate after belt shear/scale transform

Generalize G-code viewer designed-view toggle for full belt transform

Clip support layers to transformed belt floor plane

Supports below the tilted build plate (Z = shear_factor * from_axis - min_z)
are now clipped via half-plane intersection after generation. Belt floor
parameters stored in SlicingParameters and populated in both update_slicing_parameters()
and the static slicing_parameters() overload.

Make belt G-code viewer toggle more prominent, add B keyboard shortcut

- Add separator + teal "Belt Printer" header in legend panel
- Append [B] hint to checkbox label
- Add B key shortcut in GLCanvas3D to toggle designed/machine view
- Read belt_printer_angle from loaded G-code headers to enable belt view

Add per-axis global transform option for belt printer shear

New belt_shear_{x,y,z}_global bool configs. When enabled, shear incorporates
instance shift so objects at different bed positions get position-aware
transform (Z += factor * instance_shift_on_from_axis).

Fix global shear: use layer Z offset instead of mesh transform, add config invalidation

- Global shear offset applied as post-slicing layer print_z adjustment
  instead of mesh transform (which was absorbed by min_z normalization
  or shifted mesh out of slice range)
- Register all belt transform options in Print::invalidate_state_by_config_options
  to trigger posSlice re-slicing (the fallback only invalidated Print steps,
  not PrintObject steps — belt changes had no effect without manual re-slice)
- Belt gcode remap options added to steps_gcode (gcode-export only)
- Skip empty-first-layer check for belt objects with global Z offset

WIP: split instances for global shear, relative Z offsets, debug logging

- PrintApply: when belt global mode active, prevent instance grouping by
  adding unique Z perturbation to trafo — each copy becomes its own
  PrintObject with independent layers
- PrintObjectSlice: compute global Z offset relative to minimum Y shift
  across all PrintObjects (lowest-Y object stays at Z=0)
- Debug logging (warning level) for belt global shift values and offsets

Known issues:
- Cached posSlice results cause stale offsets when mixing copies with
  individually-added objects — need to compute min baseline outside slice()
- Supports still generate to Z=0 instead of object's global Z offset

Fix global shear for copied objects: disable shared-object layer optimization

When belt global Z shear is active, each object needs unique layer Z
values based on its bed position. The shared-object optimization was
causing copies to reuse the source object's layers (and its Z offset)
instead of computing their own position-based offset.

started work on getting supports to work properly

one step forward, one step back

this version didn't quite work.  Getting somewhere though

about to add UI controllable tests

added configuration options for supports

tweak CLAUDE.md to be more aggressive for my machine.  This commit should probably be pulled out before contributing upstream

still chasing down some bugs

moving objects between slices no longer results in improper Z-height because of caching

added more data to the debug logs

Z offset is getting more global again

still not quite there, I think there's a fundamental logic flaw?

hunting for bugs

finally have a functional fix

Add belt floor clipping to tree supports (organic and non-organic)

- Add belt floor polygon clipping to non-organic tree support
  (slim/strong/hybrid) in draw_circles() and terminate nodes at the
  belt surface instead of the horizontal build plate
- Add belt floor clipping to organic tree support pipeline with virtual
  belt raft layers for sub-floor branch generation, per-layer belt
  floor polygons in TreeModelVolumes, and post-generation layer trimming
- Fix pre-existing processing_last_mesh bug in TreeModelVolumes that
  prevented m_anti_overhang (support blockers) from ever being applied;
  skip empty first layer check for belt printers

Commits:

current approach: make a face surface to build supports to

closer!

supports now terminate on shear plane, now need to get shear plane to correct Z height

nearly there

chasing down logic issues still

committing for checkpoint, this still does not work

still got logic problems...

cull support clipping

stashing changes for now.  Going to focus on getting the global shear OFF support generation dialed first.

beginning per object shear calcs

Local shear transform is on correct Z offset now

local shear finally works now and needs more testing

global shear works now, needs thorough testing

debugging non-45 degree angles

debugging part 2

supports at all angles work now

remove debug logging

Add belt floor collision to non-organic tree support pipeline

- Integrate belt floor as a collision surface in TreeSupportData so
  branches route around the belt naturally, replacing the explicit
  termination checks in drop_nodes()
- Add belt extension layers below the object after draw_circles() to
  allow support geometry to extend to the diagonal belt surface instead
  of terminating at a horizontal first layer
- Fix coordinate overflow in belt floor polygons (scale_(1e4) exceeds
  int32), skip first-layer brim expansion for belt printers, and
  extend empty first layer check bypass to all belt modes

add debug logging, Z translate for tree supports

still not seeing any cutoff surface yet

adding debug options

attempt #2 at trees

if hit Z buildplate stop but don't set to_buildplate true

getting closer

tree support almost there, just need to get rid of the circles at the beginning

getting closer

belt / shear plane clip works, need to figure out the buidlplate plane issues

more logic, added debugging logs

supports now extend somewhat below Z=0 in global shear mode

fix bad alloc, add 10mm below build plate

fully works now

shear transform + prusa tree support generation works now.

pull out debug logging
2026-03-30 13:25:40 -05:00
harrierpigeon
719af2d81d Part 2.5: Add global shear transform, support clipping, and belt UI improvements
- Implement per-object global shear transform in PrintObject with
  layer Z-offset calculation, config invalidation, and fix for
  shared-object layer optimization breaking copied objects
- Clip support layers to the transformed belt floor plane and begin
  work on tree support adaptation for sheared coordinate space
- Improve belt UI: gray out inactive sub-options, add B keyboard
  shortcut for G-code viewer design-view toggle, fix mesh clipping
  through build plate after shear/scale transform

y' = y + z·cot(α),
  while x' = x and z' = z

getting closer to customizable variant

getting closer

X/Y/Z shear initial

clean up UI

add 1/sin(a) transform, idea taken from blackbelt cura plugin

Things work now (turns out I've been using the wrong set of  transforms)
2026-03-30 13:25:40 -05:00
harrierpigeon
cb13a22e57 Part 2: Replace belt rotation w/ per-axis shear transforms and G-code axis remap
- Replace monolithic belt rotation transform with independent per-axis
    shear controls (mode/angle/source-axis for X, Y, Z) and G-code axis
    remapping, giving full flexibility to match any belt printer's
    coordinate system
  - Remove all rotation mode logic and intermediate type+axes dropdowns,
    simplifying the pipeline to pure shear matrices while preserving the
    default behavior (Y += Z*cot(45deg) with identity remap)
  - Clean up GCodeWriter, GCodeProcessor, and GCodeViewer for the new
    shear-only model; expose 12 new settings in printer UI via
    Tab.cpp/Preset.cpp

Implement belt printer tilted slicing

Implement the core belt slicing pipeline that makes the slicer
tilt-aware:

Step 1: GCodeWriter::to_machine_coords() - R(+alpha, X) rotation
  from slicing frame to machine frame
Step 2: PrintObject - belt-rotated object height calculation
  (y*sin(a) + z*cos(a)) for correct layer count
Step 3: PrintObjectSlice - apply R(-alpha, X) rotation trafo so
  horizontal slice planes correspond to belt-parallel planes,
  with Z-shift computed from model volumes
Step 4: GCodeProcessor - machine-frame preview (no transform needed)
Step 5: 3DBed - rotate bed visualization about X by belt angle

Fix: belt surface IS the build plate, no mesh rotation

Currently still slicing perpendicular to the belt normal.  Need to figure out why.

Fix G-code Z sign: use R(-alpha, X) so Z+ is away from belt

The previous R(+alpha, X) transform produced negative Z values
(-y*sin(a) term dominated). Changed to R(-alpha, X) which gives
machine_z = y*sin(a) + z*cos(a), always positive for points
above the belt surface. Z increases with each layer as expected.

reverting and changing slice methodology

Add pink slicing direction arrow from origin

Shows the effective slicing direction (gantry normal) as a pink
arrow from the origin. Shorter and wider than the gravity arrow.
Direction: R(+alpha, X) * Z = (0, -sin(a), cos(a)), which is
the layer stacking direction in the original mesh frame.

Fix slicing arrow visibility and add raw G-code toggle

- Disable depth test for pink slicing arrow so it renders on top of
  the tilted bed geometry (was being occluded)
- Remove unnecessary 5mm Z-offset from arrow position
- Add m_belt_show_raw toggle to GCodeViewer
- Add "Show raw G-code (slicing frame)" checkbox in legend when
  belt mode is active

Implement to_machine_coords inverse rotation for belt printer G-code

The slicing pipeline rotates the mesh by R(-alpha, X) and shifts Z to
start at 0. The G-code output now undoes this transform via
to_machine_coords: R(+alpha, X) * T(0,0,+z_shift), recovering the
original machine-frame coordinates where Y is horizontal and Z is
vertical.

Changes:
- GCodeWriter: implement to_machine_coords with inverse rotation + Z-shift
- GCodeWriter: add belt_z_shift member and setter/getter
- GCode.cpp: compute Z-shift from print objects (same logic as
  PrintObjectSlice) and pass to writer; write z_shift to G-code header
- GCodeProcessor: parse belt_z_shift from G-code header
- GCodeViewer: store belt_z_shift from processor result

Wire raw G-code toggle to apply slicing-frame view transform

When "Show raw G-code (slicing frame)" is checked in the preview
legend, the view matrix is modified to apply R(-alpha, X) * T(0,0,-z_shift)
to the toolpath rendering. This shows the G-code as it was during
slicing: rotated part with horizontal layers.

Default (unchecked): machine-frame view — upright part with tilted layers.

Remove belt printer placeholder comment from GCodeProcessor

The preview now correctly displays machine-frame G-code with the
optional raw view toggle. No transform is needed in the processor.
2026-03-30 13:25:40 -05:00
harrierpigeon
ed6ea086a2 Add belt printer transform pipeline: slicing rotation, G-code coords, preview
- Implement core belt slicing pipeline: R(-alpha, X) mesh rotation in PrintObjectSlice with corrected object height calculation for proper layer count
Add to_machine_coords() in GCodeWriter to convert slicing-frame coordinates back to machine-frame, propagated through GCode,
GCodeProcessor, and GCodeViewer
Add belt-mode UI: tilted bed visualization, slicing-direction arrow, and raw G-code toggle to switch between machine-frame and slicing-frame views

This is a combination of 6 commits.

checkpoint 1: initial MVP.  Slicing functions, but rotates instead of skews are happening and a lot of other stuff too

getting somewhere, getting to the point where I need to figure out how to verify this stuff

this appears to be a dead end.

getting somewhere I think maybe

I'm pretty sure we've completely lost the plot at this point and need to restart this process...

remove slice logic in preparation for new, more invasive plan
2026-03-30 13:25:40 -05:00
harrierpigeon
08aa277974 stage in changes from off-plate-gravity and remove stuff I didn't need 2026-03-30 13:25:40 -05:00
149 changed files with 8742 additions and 1552 deletions

View File

@@ -315,7 +315,7 @@ jobs:
"ARCH_SUFFIX=_arm64" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
} else {
"BUILD_DIR=build" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
"ARCH_SUFFIX=_x64" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
"ARCH_SUFFIX=" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
}
- name: setup MSVC
@@ -405,7 +405,7 @@ jobs:
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/${{ env.BUILD_DIR }}/OrcaSlicer_Windows_Installer_${{ env.ver }}${{ env.ARCH_SUFFIX }}.exe
asset_path: ${{ github.workspace }}/${{ env.BUILD_DIR }}/OrcaSlicer_Windows_Installer_${{ env.ver }}.exe
asset_name: OrcaSlicer_Windows_Installer${{ env.ARCH_SUFFIX }}_nightly${{ env.nightly_suffix }}.exe
asset_content_type: application/x-msdownload
max_releases: 1

View File

@@ -92,11 +92,9 @@ jobs:
# binaries are already unzipped. Copy the inner binary for each platform.
# -type f is required (some artifact *folders* are named "*.flatpak").
# Windows installers (x64 + arm64): the .exe inside each installer
# artifact, NOT the orca-slicer.exe in the portable app folder. CPack
# now bakes the arch into the filename (…_x64.exe / …_arm64.exe), so
# copy them straight through.
find artifacts -type f -name '*.exe' -path '*OrcaSlicer_Windows_V*' ! -path '*_portable*' -exec cp -v {} upload/ \;
# Windows installer: the .exe inside the installer artifact, NOT the
# orca-slicer.exe that lives in the portable app folder.
find artifacts -type f -name '*.exe' -path '*OrcaSlicer_Windows_*' ! -path '*_portable*' -exec cp -v {} upload/ \;
# macOS universal DMG (profile-validator DMG isn't downloaded).
find artifacts -type f -name '*.dmg' -path '*OrcaSlicer_Mac_universal_*' -exec cp -v {} upload/ \;
# Linux AppImage.
@@ -106,16 +104,15 @@ jobs:
# Windows debug symbols (PDB archive, for developers).
find artifacts -type f -name 'Debug_PDB_*.7z' -exec cp -v {} upload/ \;
# Portable Windows builds (x64 + arm64) are unzipped folder artifacts;
# re-zip each to its released filename (these stay .zip on the release).
mapfile -t portable_dirs < <(find artifacts -maxdepth 1 -type d -name 'OrcaSlicer_Windows_*_portable')
if [ ${#portable_dirs[@]} -eq 0 ]; then
echo "::warning::Windows portable artifact not found."
fi
for portable_dir in "${portable_dirs[@]}"; do
# Portable Windows build is an unzipped folder artifact; re-zip it to the
# released filename (this one stays a .zip on the release).
portable_dir=$(find artifacts -maxdepth 1 -type d -name 'OrcaSlicer_Windows_*_portable' | head -n1)
if [ -n "${portable_dir:-}" ]; then
( cd "$portable_dir" && zip -qr "$GITHUB_WORKSPACE/upload/$(basename "$portable_dir").zip" . )
echo "Zipped portable -> $(basename "$portable_dir").zip"
done
else
echo "::warning::Windows portable artifact not found."
fi
echo "Assets to upload:"
ls -lh upload

View File

@@ -934,16 +934,6 @@ set (CPACK_PACKAGE_VERSION_MAJOR "${ORCA_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${ORCA_VERSION_MINOR}")
set (CPACK_PACKAGE_VERSION_PATCH "${ORCA_VERSION_PATCH}")
set (CPACK_PACKAGE_FILE_NAME "OrcaSlicer_Windows_Installer_V${SoftFever_VERSION}")
# Suffix the Windows installer with its target arch so the x64 and arm64 builds
# produce distinct filenames (matches ARCH_SUFFIX in build_orca.yml). Same
# CMAKE_SYSTEM_PROCESSOR mapping used by orcaslicer_copy_dlls() above.
if (WIN32)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
string (APPEND CPACK_PACKAGE_FILE_NAME "_arm64")
else ()
string (APPEND CPACK_PACKAGE_FILE_NAME "_x64")
endif ()
endif ()
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Orca Slicer is an open source slicer for FDM printers")
set (CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/OrcaSlicer/OrcaSlicer")
set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -1675,20 +1675,6 @@ msgstr ""
msgid "Untitled"
msgstr ""
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr ""
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1716,12 +1702,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr ""
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, possible-c-format, possible-boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr ""
@@ -4970,12 +4950,6 @@ msgstr ""
msgid "Stats"
msgstr ""
msgid "Slice"
msgstr ""
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr ""
@@ -5042,7 +5016,7 @@ msgstr ""
msgid "Size:"
msgstr ""
#, possible-boost-format
#, possible-c-format, possible-boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr ""
@@ -10675,12 +10649,6 @@ msgstr ""
msgid "Generating skirt & brim"
msgstr ""
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr ""
@@ -12213,6 +12181,7 @@ msgstr ""
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, possible-c-format, possible-boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -14883,6 +14852,9 @@ msgstr ""
msgid "Export the objects as multiple STLs to directory."
msgstr ""
msgid "Slice"
msgstr ""
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2025-03-15 10:55+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -1720,20 +1720,6 @@ msgstr "OrcaSlicer ha tingut una excepció no gestionada: %1%"
msgid "Untitled"
msgstr "Sense títol"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Des de la versió 2.4.0, OrcaSlicer sincronitza els perfils d'usuari a través d'Orca Cloud en lloc de Bambu Cloud.\n\nPer migrar els teus perfils existents, inicia la sessió a Orca Cloud i es transferiran automàticament. Per obtenir més informació sobre com OrcaSlicer emmagatzema i sincronitza els teus perfils, o per migrar els teus perfils manualment, consulta la nostra wiki.\n\nSi no feies servir Bambu Cloud per sincronitzar perfils, aquest canvi no t'afecta i pots ignorar aquest missatge amb tranquil·litat."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Recarregant el connector de xarxa..."
@@ -1763,12 +1749,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "El camí de recursos no existeix o no és un directori: %s"
@@ -5227,12 +5207,6 @@ msgstr "Totes les plaques"
msgid "Stats"
msgstr "Estadístiques"
msgid "Slice"
msgstr "Llesca"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Tornar a Agrupar"
@@ -5301,7 +5275,7 @@ msgid "Size:"
msgstr "Mida:"
# TODO: Review, changed by lang refactor. PR 14254
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "S'han trobat conflictes de rutes gcode a la capa %d, Z = %.2lfmm. Si us plau, separeu els objectes conflictius més lluny ( %s <-> %s )."
@@ -11219,12 +11193,6 @@ msgstr "La contracció del filament no s'utilitzarà perquè la contracció del
msgid "Generating skirt & brim"
msgstr "Generant Faldilla i Vora d'Adherència"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exportant el Codi-G"
@@ -12969,6 +12937,7 @@ msgstr "Ús de múltiples línies per al patró de farciment, si el patró de fa
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15880,6 +15849,9 @@ msgstr "Exportar diversos STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Exportar els objectes com a diversos STL al directori"
msgid "Slice"
msgstr "Llesca"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Laminar les plaques: 0-totes les plaques, i-placa i, altres-no vàlides"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Jakub Hencl\n"
"Language-Team: \n"
@@ -1713,20 +1713,6 @@ msgstr "OrcaSlicer narazil na neošetřenou výjimku: %1%"
msgid "Untitled"
msgstr "Bez názvu"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Od verze 2.4.0 OrcaSlicer synchronizuje uživatelské profily prostřednictvím Orca Cloud namísto Bambu Cloud.\n\nChcete-li migrovat své stávající profily, přihlaste se k Orca Cloud a budou automaticky přeneseny. Další informace o tom, jak OrcaSlicer ukládá a synchronizuje vaše profily, nebo o ruční migraci vašich předvoleb najdete na naší wiki.\n\nPokud jste k synchronizaci profilů nepoužívali Bambu Cloud, tato změna se vás netýká a můžete tuto zprávu klidně ignorovat."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Znovunačítání síťového plug-inu..."
@@ -1756,12 +1742,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Cesta ke zdrojům neexistuje nebo není adresář: %s"
@@ -5224,12 +5204,6 @@ msgstr "Všechny desky"
msgid "Stats"
msgstr "Statistiky"
msgid "Slice"
msgstr "Slicovat"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Návrat k sestavě"
@@ -5297,7 +5271,7 @@ msgstr "Objem:"
msgid "Size:"
msgstr "Velikost:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Byly nalezeny konflikty drah G-kódu ve vrstvě %d, Z = %.2lf mm. Oddělte prosím konfliktní objekty více od sebe (%s <-> %s)."
@@ -11223,12 +11197,6 @@ msgstr "Smrštění filamentu nebude použito, protože hodnoty smrštění pou
msgid "Generating skirt & brim"
msgstr "Generování sukně a lemu"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exportuji G-code"
@@ -12974,6 +12942,7 @@ msgstr "Použití více řádků pro vzor výplně, pokud to daný vzor podporuj
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15921,6 +15890,9 @@ msgstr "Exportovat více STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Exportovat objekty jako více STL do adresáře."
msgid "Slice"
msgstr "Slicovat"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Slicovat desky: 0-všechny desky, i-deska i, ostatní-neplatné"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Heiko Liebscher <hliebschergmail.com>\n"
"Language-Team: \n"
@@ -1716,20 +1716,6 @@ msgstr "OrcaSlicer hat eine unbehandelte Ausnahme erzeugt: %1%"
msgid "Untitled"
msgstr "Unbenannt"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Seit Version 2.4.0 synchronisiert OrcaSlicer Benutzerprofile über Orca Cloud anstelle der Bambu Cloud.\n\nUm Ihre vorhandenen Profile zu migrieren, melden Sie sich bei Orca Cloud an, dann werden sie automatisch übertragen. Weitere Informationen darüber, wie OrcaSlicer Ihre Profile speichert und synchronisiert, oder wie Sie Ihre Profile manuell migrieren, finden Sie in unserem Wiki.\n\nWenn Sie die Bambu Cloud nicht zum Synchronisieren von Profilen verwendet haben, betrifft Sie diese Änderung nicht und Sie können diese Meldung ignorieren."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr "Mehr erfahren"
msgid "Reloading network plug-in..."
msgstr "Netzwerk-Plugin wird neu geladen..."
@@ -1759,12 +1745,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2-Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Ressourcenpfad existiert nicht oder ist kein Verzeichnis: %s"
@@ -5236,12 +5216,6 @@ msgstr "alle Druckplatten"
msgid "Stats"
msgstr "Statistiken"
msgid "Slice"
msgstr "Slice"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Zurücksetzen der Montage"
@@ -5309,7 +5283,7 @@ msgstr "Volumen:"
msgid "Size:"
msgstr "Größe:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Konflikte von G-Code-Pfaden wurden bei Layer %d, Z = %.2lf mm gefunden.Bitte trennen Sie die konfliktbehafteten Objekte weiter voneinander (%s <-> %s)."
@@ -11262,12 +11236,6 @@ msgstr "Filament-Schrumpfung wird nicht verwendet, da sich die Filament-Schrumpf
msgid "Generating skirt & brim"
msgstr "Generieren von Schürze und Rand (skirt & brim)"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exportiere G-Code"
@@ -13087,7 +13055,7 @@ msgid "Z-buckling bias optimization (experimental)"
msgstr "Z-Buckling-Bias-Optimierung (experimentell)"
# TODO: Review, changed by lang refactor. PR 14254
#, fuzzy
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "Strafft die Gyroid-Welle entlang der Z-Achse (vertikal) bei geringer Fülldichte, um die effektive vertikale Säulenlänge zu verkürzen und die Z-Achsen-Kompressions-Knickfestigkeit zu verbessern. Der Filamentverbrauch bleibt erhalten. Keine Auswirkung bei ~30% einfacher Fülldichte und darüber. Gilt nur, wenn das einfache Füllmuster auf Gyroid eingestellt ist."
@@ -16056,6 +16024,9 @@ msgstr "Mehrere STLs exportieren"
msgid "Export the objects as multiple STLs to directory."
msgstr "Exportieren Sie die Objekte als mehrere STLs in ein Verzeichnis"
msgid "Slice"
msgstr "Slice"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Slicen sie die Druckplatten: 0-alle Druckplatten; i-Druckplatte i; andere ungültig"
@@ -20351,6 +20322,9 @@ msgstr ""
#~ msgid "Automatic calibration only supports cases where the left and right nozzle diameters are identical."
#~ msgstr "Die automatische Kalibrierung unterstützt nur Fälle, in denen die linken und rechten Düsendurchmesser identisch sind."
#~ msgid "Learn more"
#~ msgstr "Mehr erfahren"
#~ msgid "✖ Skipped %1%: %2%, same file\n"
#~ msgstr "✖ %1% übersprungen: %2%, gleiche Datei\n"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2026-06-17 15:44-0300\n"
"Last-Translator: Alexandre Folle de Menezes\n"
"Language-Team: \n"
@@ -1671,20 +1671,6 @@ msgstr ""
msgid "Untitled"
msgstr ""
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr ""
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1712,12 +1698,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr ""
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr ""
@@ -4966,12 +4946,6 @@ msgstr ""
msgid "Stats"
msgstr ""
msgid "Slice"
msgstr ""
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr ""
@@ -5038,7 +5012,7 @@ msgstr ""
msgid "Size:"
msgstr ""
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr ""
@@ -10671,12 +10645,6 @@ msgstr ""
msgid "Generating skirt & brim"
msgstr ""
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr ""
@@ -12209,6 +12177,7 @@ msgstr ""
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -14879,6 +14848,9 @@ msgstr ""
msgid "Export the objects as multiple STLs to directory."
msgstr ""
msgid "Slice"
msgstr ""
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr ""

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Ian A. Bassi <>\n"
"Language-Team: \n"
@@ -1711,20 +1711,6 @@ msgstr "OrcaSlicer recibió una notificación de excepción no controlada: %1%"
msgid "Untitled"
msgstr "Sin título"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Desde la versión 2.4.0, OrcaSlicer sincroniza los perfiles de usuario a través de Orca Cloud en lugar de Bambu Cloud.\n\nPara migrar tus perfiles existentes, inicia sesión en Orca Cloud y se transferirán automáticamente. Para obtener más información sobre cómo OrcaSlicer almacena y sincroniza tus perfiles, o para migrar tus perfiles manualmente, consulta nuestra wiki.\n\nSi no usabas Bambu Cloud para sincronizar perfiles, este cambio no te afecta y puedes ignorar este mensaje con seguridad."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Recargando el complemento de red..."
@@ -1756,12 +1742,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "La ruta de recursos no existe o no es un directorio: %s"
@@ -5233,12 +5213,6 @@ msgstr "Todas las camas"
msgid "Stats"
msgstr "Estadísticas"
msgid "Slice"
msgstr "Laminar"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Volver a agrupar"
@@ -5306,7 +5280,7 @@ msgstr "Volumen:"
msgid "Size:"
msgstr "Tamaño:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Se han encontrado conflictos de rutas G-Code en la capa %d, Z = %.2lfmm. Por favor, separe más los objetos en conflicto (%s <-> %s)."
@@ -11251,12 +11225,6 @@ msgstr "La contracción del filamento no se utilizará porque la contracción de
msgid "Generating skirt & brim"
msgstr "Generando falda y borde de adherencia"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exportando G-Code"
@@ -13084,7 +13052,7 @@ msgid "Z-buckling bias optimization (experimental)"
msgstr "Optimización del desplazamiento por deformación en Z (experimental)"
# TODO: Review, changed by lang refactor. PR 14254
#, fuzzy
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "Ajusta la onda giroide a lo largo del eje Z (vertical) con una densidad de relleno baja para acortar la longitud efectiva de la columna vertical y mejorar la resistencia al pandeo por compresión en el eje Z. Se mantiene el consumo de filamento. No tiene efecto con una densidad de relleno escasa de aproximadamente el ~30% o superior. Solo se aplica cuando el patrón de relleno escaso está configurado en «Giroide»."
@@ -16056,6 +16024,9 @@ msgstr "Exportar múltiples STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Exportar los objetos como múltiples STL a un directorio."
msgid "Slice"
msgstr "Laminar"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Cortar las camas: 0-todas las camas, i-cama i, otras-inválidas"

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: Guislain Cyril, Thomas Lété\n"
@@ -1695,20 +1695,6 @@ msgstr "Orca Slicer a reçu une exception non gérée : %1%"
msgid "Untitled"
msgstr "Sans titre"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Depuis la version 2.4.0, OrcaSlicer synchronise les profils utilisateur via Orca Cloud au lieu de Bambu Cloud.\n\nPour migrer vos profils existants, connectez-vous à Orca Cloud et ils seront transférés automatiquement. Pour en savoir plus sur la façon dont OrcaSlicer stocke et synchronise vos profils, ou pour migrer vos préréglages manuellement, consultez notre wiki.\n\nSi vous n'utilisiez pas Bambu Cloud pour synchroniser vos profils, ce changement ne vous concerne pas et vous pouvez ignorer ce message."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Rechargement du plug-in réseau…"
@@ -1738,12 +1724,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Le chemin des ressources n'existe pas ou n'est pas un répertoire : %s"
@@ -5109,12 +5089,6 @@ msgstr "Toutes les plaques"
msgid "Stats"
msgstr "Statistiques"
msgid "Slice"
msgstr "Découper"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Retour d'assemblage"
@@ -5181,7 +5155,7 @@ msgstr "Volume :"
msgid "Size:"
msgstr "Taille :"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Des conflits de chemins G-code ont été trouvés au niveau de la couche %d, z = %.2lfmm. Veuillez séparer davantage les objets en conflit (%s <-> %s)."
@@ -11011,12 +10985,6 @@ msgstr "Le rétrécissement du filament ne sera pas utilisé car le rétrécisse
msgid "Generating skirt & brim"
msgstr "Génération jupe et bord"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exportation du G-code"
@@ -12788,7 +12756,7 @@ msgid "Z-buckling bias optimization (experimental)"
msgstr "Optimisation du biais de flambage en Z (expérimental)"
# TODO: Review, changed by lang refactor. PR 14254
#, fuzzy
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "Resserre londe gyroïde le long de laxe Z (vertical) à faible densité de remplissage afin de raccourcir la longueur effective des colonnes verticales et daméliorer la résistance au flambage en compression selon laxe Z. La consommation de filament est préservée. Aucun effet à partir denviron 30 % de densité de remplissage. Sapplique uniquement lorsque le motif de remplissage est réglé sur Gyroïde."
@@ -15662,6 +15630,9 @@ msgstr "Exporter plusieurs STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Exporter les objets sous forme de STLs multiples dans un répertoire"
msgid "Slice"
msgstr "Découper"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Trancher toutes les plaques : 0-toutes, i-plaque i, autres-invalides"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -1708,20 +1708,6 @@ msgstr "Az OrcaSlicer kezeletlen kivételt kapott: %1%"
msgid "Untitled"
msgstr "Névtelen"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "A 2.4.0-s verziótól kezdve az OrcaSlicer a felhasználói profilokat a Bambu Cloud helyett az Orca Cloudon keresztül szinkronizálja.\n\nMeglévő profiljai átviteléhez jelentkezzen be az Orca Cloudba, és azok automatikusan átkerülnek. Ha többet szeretne megtudni arról, hogyan tárolja és szinkronizálja az OrcaSlicer a profiljait, vagy ha kézzel szeretné átvinni a beállításait, tekintse meg a wikinket.\n\nHa nem használta a Bambu Cloudot a profilok szinkronizálásához, ez a változás nem érinti Önt, és nyugodtan figyelmen kívül hagyhatja ezt az üzenetet."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Hálózati bővítmény újratöltése..."
@@ -1751,12 +1737,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Az erőforrások elérési útja nem létezik vagy nem könyvtár: %s"
@@ -5218,12 +5198,6 @@ msgstr "Összes tálca"
msgid "Stats"
msgstr "Statisztika"
msgid "Slice"
msgstr "Szeletelés"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Vissza az összeszereléshez"
@@ -5291,7 +5265,7 @@ msgstr "Térfogat:"
msgid "Size:"
msgstr "Méret:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "G-kód útvonalütközés található a(z) %d. rétegen, Z = %.2lfmm. Helyezd távolabb egymástól az ütköző objektumokat (%s <-> %s)."
@@ -11234,12 +11208,6 @@ msgstr "A filament zsugorodása nem lesz figyelembe véve, mert a használt fila
msgid "Generating skirt & brim"
msgstr "Szoknya & perem generálása"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "G-kód exportálása"
@@ -12991,7 +12959,7 @@ msgid "Z-buckling bias optimization (experimental)"
msgstr "Z-kihajlási torzítás optimalizálása (kísérleti)"
# TODO: Review, changed by lang refactor. PR 14254
#, fuzzy
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "Alacsony feltöltési sűrűség mellett megfeszíti a gyroid hullámot a Z (függőleges) tengely mentén, hogy lerövidítse a tényleges függőleges oszlophosszt és javítsa a Z-tengely összenyomódási kihajlási ellenállását. A filamenthasználat megmarad. Nincs hatása ~30%-os és afeletti ritka kitöltési sűrűségnél. Csak akkor érvényes, ha a Ritka kitöltési minta Gyroid-ra van állítva."
@@ -15960,6 +15928,9 @@ msgstr "Több STL exportálása"
msgid "Export the objects as multiple STLs to directory."
msgstr "Az objektumok exportálása több STL fájlként egy könyvtárba."
msgid "Slice"
msgstr "Szeletelés"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Tálcák szeletelése: 0 - összes tálca, i - i tálca, egyéb - érvénytelen"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -1711,20 +1711,6 @@ msgstr "OrcaSlicer ha ricevuto un'eccezione non gestita: %1%"
msgid "Untitled"
msgstr "Senza titolo"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Dalla versione 2.4.0, OrcaSlicer sincronizza i profili utente tramite Orca Cloud anziché Bambu Cloud.\n\nPer migrare i tuoi profili esistenti, accedi a Orca Cloud e verranno trasferiti automaticamente. Per saperne di più su come OrcaSlicer memorizza e sincronizza i tuoi profili, o per migrare i tuoi profili manualmente, consulta la nostra wiki.\n\nSe non utilizzavi Bambu Cloud per sincronizzare i profili, questa modifica non ti riguarda e puoi ignorare questo messaggio."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Ricaricamento modulo di rete..."
@@ -1754,12 +1740,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Il percorso delle risorse non esiste o non è una directory: %s"
@@ -5219,12 +5199,6 @@ msgstr "Tutte le piastre"
msgid "Stats"
msgstr "Statistiche"
msgid "Slice"
msgstr "Elabora"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Ritorna al montaggio"
@@ -5292,7 +5266,7 @@ msgstr ""
msgid "Size:"
msgstr "Dimensione:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Sono stati trovati conflitti di percorsi nel G-code sullo strato %d, Z = %.2lfmm. Si prega di separare gli oggetti in conflitto (%s <-> %s)."
@@ -11216,12 +11190,6 @@ msgstr "La compensazione del restringimento del materiale non verrà utilizzata
msgid "Generating skirt & brim"
msgstr "Generazione gonna e tesa"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Esportazione G-code"
@@ -12973,6 +12941,7 @@ msgstr "Utilizzo di linee multiple per il pattern di riempimento, se supportato
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15925,6 +15894,9 @@ msgstr "Esporta STL multipli"
msgid "Export the objects as multiple STLs to directory."
msgstr "Esporta gli oggetti come STL multipli nella directory."
msgid "Slice"
msgstr "Elabora"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Elaborazione dei piatti: 0-tutti i piatti, i-piatto i, altri-non valido"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -1709,20 +1709,6 @@ msgstr "OrcaSlicerで未処理の例外が発生しました: %1%"
msgid "Untitled"
msgstr "名称未設定"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "バージョン 2.4.0 以降、OrcaSlicer はユーザープロファイルを Bambu Cloud ではなく Orca Cloud を通じて同期します。\n\n既存のプロファイルを移行するには、Orca Cloud にログインしてください。自動的に転送されます。OrcaSlicer がプロファイルを保存・同期する仕組みの詳細や、プリセットを手動で移行する方法については、Wiki をご覧ください。\n\nプロファイルの同期に Bambu Cloud を使用していなかった場合、この変更の影響はありません。このメッセージは無視して問題ありません。"
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "ネットワークプラグインを再読み込み中..."
@@ -1752,12 +1738,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "リソースパスが存在しないかディレクトリではありません: %s"
@@ -5192,12 +5172,6 @@ msgstr "全プレート"
msgid "Stats"
msgstr "統計"
msgid "Slice"
msgstr "スライス"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "戻る"
@@ -5265,7 +5239,7 @@ msgstr "ボリューム"
msgid "Size:"
msgstr "サイズ:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "レイヤー%d、Z = %.2lfmmでG-codeパスの衝突が検出されました。衝突するオブジェクトをもっと離してください%s <-> %s。"
@@ -11134,12 +11108,6 @@ msgstr "使用するフィラメントの収縮率が大きく異なるため、
msgid "Generating skirt & brim"
msgstr "スカートとブリムを生成"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "G-codeをエクスポート中"
@@ -12735,6 +12703,7 @@ msgstr "充填パターンが対応している場合は、複数のラインを
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15508,6 +15477,9 @@ msgstr ""
msgid "Export the objects as multiple STLs to directory."
msgstr ""
msgid "Slice"
msgstr "スライス"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "プレートをスライス: 0: 全て, i:プレートi, その他: 無効"

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2025-06-02 17:12+0900\n"
"Last-Translator: crwusiz <crwusiz@gmail.com>\n"
"Language-Team: \n"
@@ -1715,20 +1715,6 @@ msgstr "Orca Slicer에 처리되지 않은 예외가 발생했습니다: %1%"
msgid "Untitled"
msgstr "제목 없음"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "버전 2.4.0부터 OrcaSlicer는 사용자 프로파일을 Bambu Cloud 대신 Orca Cloud를 통해 동기화합니다.\n\n기존 프로파일을 이전하려면 Orca Cloud에 로그인하세요. 자동으로 전송됩니다. OrcaSlicer가 프로파일을 저장하고 동기화하는 방식에 대해 자세히 알아보거나 사전 설정을 수동으로 이전하려면 위키를 참조하세요.\n\n프로파일 동기화에 Bambu Cloud를 사용하지 않았다면 이 변경 사항은 영향을 주지 않으므로 이 메시지를 무시해도 됩니다."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "네트워크 플러그인 재로드 중..."
@@ -1758,12 +1744,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 런타임"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "리소스 경로가 존재하지 않거나 디렉토리가 아닙니다: %s"
@@ -5218,12 +5198,6 @@ msgstr "전체 플레이트"
msgid "Stats"
msgstr "통계"
msgid "Slice"
msgstr "슬라이스"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "조립 되돌리기"
@@ -5291,7 +5265,7 @@ msgstr "용량:"
msgid "Size:"
msgstr "크기:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "레이어 %d, Z = %.2lf mm에서 Gcode 경로 충돌이 발견되었습니다. 충돌하는 객체를 더 멀리 분리하세요 (%s <-> %s)."
@@ -11178,12 +11152,6 @@ msgstr ""
msgid "Generating skirt & brim"
msgstr "스커트 & 브림 생성 중"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Gcode 내보내는 중"
@@ -12892,6 +12860,7 @@ msgstr "채우기 패턴에서 지원되는 경우 채우기 패턴에 여러
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15785,6 +15754,9 @@ msgstr "여러 STL을 내보내기"
msgid "Export the objects as multiple STLs to directory."
msgstr "객체를 여러 STL로 경로에 내보내기"
msgid "Slice"
msgstr "슬라이스"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "플레이트 슬라이스: 0-모든 플레이트, i-플레이트 i, 기타-잘못됨"

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2025-10-25 23:01+0300\n"
"Last-Translator: Gintaras Kučinskas <sharanchius@gmail.com>\n"
"Language-Team: \n"
@@ -1719,20 +1719,6 @@ msgstr "OrcaSlicer susidūrė su neapdorota klaida: %1%"
msgid "Untitled"
msgstr "Be pavadinimo"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Nuo 2.4.0 versijos OrcaSlicer sinchronizuoja naudotojo profilius per Orca Cloud, o ne Bambu Cloud.\n\nNorėdami perkelti esamus profilius, prisijunkite prie Orca Cloud ir jie bus perkelti automatiškai. Norėdami sužinoti daugiau apie tai, kaip OrcaSlicer saugo ir sinchronizuoja jūsų profilius, arba norėdami perkelti profilius rankiniu būdu, apsilankykite mūsų wiki.\n\nJei profiliams sinchronizuoti nenaudojote Bambu Cloud, šis pakeitimas jums neaktualus ir šį pranešimą galite ignoruoti."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1762,12 +1748,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "\"WebView2\" paleidimo terpė"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Išteklių kelias neegzistuoja arba nėra katalogas: %s"
@@ -5211,12 +5191,6 @@ msgstr "Visos plokštės"
msgid "Stats"
msgstr "Statistika"
msgid "Slice"
msgstr "Sluoksniuoti"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Sugrąžinti surinkimą"
@@ -5284,7 +5258,7 @@ msgstr "Tūris:"
msgid "Size:"
msgstr "Dydis:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Rasta G-kode judėjimo kelių konfliktų %d sluoksnyje, Z = %.2lfmm. Prašome labiau atskirti konfliktinius objektus (%s <-> %s)."
@@ -11167,12 +11141,6 @@ msgstr "Gijų susitraukimas nenaudojamas, nes naudojamų gijų susitraukimas lab
msgid "Generating skirt & brim"
msgstr "Generuojamas apvadas ir kraštas"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Eksportuojamas G-kodas"
@@ -12879,6 +12847,7 @@ msgstr "Naudoti kelias linijas užpildymo šablonui, jei tai palaiko užpildymo
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15782,6 +15751,9 @@ msgstr "Eksportuoti kaip kelis STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Eksportuokite objektus kaip kelis STL į katalogą."
msgid "Slice"
msgstr "Sluoksniuoti"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Sluoksniuoja plokštes: 0-visos plokštės, i-plokštė i, kitos-negaliojančios"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -1696,20 +1696,6 @@ msgstr "OrcaSlicer kreeg een onbehandelde uitzondering: %1%"
msgid "Untitled"
msgstr "Naamloos"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Sinds versie 2.4.0 synchroniseert OrcaSlicer gebruikersprofielen via Orca Cloud in plaats van Bambu Cloud.\n\nOm je bestaande profielen te migreren, log je in bij Orca Cloud en worden ze automatisch overgezet. Raadpleeg onze wiki voor meer informatie over hoe OrcaSlicer je profielen opslaat en synchroniseert, of om je voorinstellingen handmatig te migreren.\n\nAls je Bambu Cloud niet gebruikte om profielen te synchroniseren, heeft deze wijziging geen invloed op jou en kun je dit bericht veilig negeren."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1739,12 +1725,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr ""
@@ -5158,12 +5138,6 @@ msgstr "Alle platen"
msgid "Stats"
msgstr "Statistieken"
msgid "Slice"
msgstr ""
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Montage terug"
@@ -5231,7 +5205,7 @@ msgstr ""
msgid "Size:"
msgstr "Maat:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr ""
@@ -11063,12 +11037,6 @@ msgstr ""
msgid "Generating skirt & brim"
msgstr "Skirt en brim worden gegenereerd"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "G-code exporteren"
@@ -12660,6 +12628,7 @@ msgstr ""
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15437,6 +15406,9 @@ msgstr ""
msgid "Export the objects as multiple STLs to directory."
msgstr ""
msgid "Slice"
msgstr ""
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Slice de printbedden: 0-alle printbedden, i-printbed i, andere-onjuist"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: OrcaSlicer 2.3.0-rc\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: \n"
"Last-Translator: Krzysztof Morga <<tlumaczeniebs@gmail.com>>\n"
"Language-Team: \n"
@@ -1716,20 +1716,6 @@ msgstr "OrcaSlicer napotkał nieobsługiwany wyjątek: %1%"
msgid "Untitled"
msgstr "Bez tytułu"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Od wersji 2.4.0 OrcaSlicer synchronizuje profile użytkownika za pośrednictwem Orca Cloud zamiast Bambu Cloud.\n\nAby przenieść istniejące profile, zaloguj się do Orca Cloud, a zostaną one przeniesione automatycznie. Aby dowiedzieć się więcej o tym, jak OrcaSlicer przechowuje i synchronizuje Twoje profile, lub aby ręcznie przenieść swoje profile, zajrzyj do naszej wiki.\n\nJeśli nie korzystano z Bambu Cloud do synchronizacji profili, ta zmiana Cię nie dotyczy i możesz zignorować tę wiadomość."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1759,12 +1745,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr ""
@@ -5215,12 +5195,6 @@ msgstr ""
msgid "Stats"
msgstr ""
msgid "Slice"
msgstr ""
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Powrót do montażu"
@@ -5288,7 +5262,7 @@ msgstr "Objętość:"
msgid "Size:"
msgstr "Rozmiar:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Wykryto konflikty ścieżek G-code na warstwie %d, Z = %.2lfmm. Proszę oddalić od siebie obiekty będące w konflikcie (%s <-> %s)."
@@ -11193,12 +11167,6 @@ msgstr "Kompensacja skurczu filamentu nie będzie zastosowana, ponieważ skurcz
msgid "Generating skirt & brim"
msgstr "Generowanie skirtu i brimu"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Eksportowanie G-code"
@@ -12907,6 +12875,7 @@ msgstr "Wypełnienie przy użyciu wielu linii, jeśli jest to obsługiwane przez
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15802,6 +15771,9 @@ msgstr "Eksportuj jako wiele plików STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Eksportuj obiekty jako wiele plików STL do katalogu."
msgid "Slice"
msgstr ""
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Slice podłoża: 0-wszystkie podłoża, i-podłoże i, inne-nieważne"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2026-06-19 20:49-0300\n"
"Last-Translator: Alexandre Folle de Menezes\n"
"Language-Team: Portuguese, Brazilian\n"
@@ -1695,20 +1695,6 @@ msgstr "OrcaSlicer encontrou uma exceção não tratada: %1%"
msgid "Untitled"
msgstr "Sem título"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Desde a versão 2.4.0, o OrcaSlicer sincroniza os perfis de usuário através do Orca Cloud em vez do Bambu Cloud.\n\nPara migrar seus perfis existentes, faça login no Orca Cloud e eles serão transferidos automaticamente. Para saber mais sobre como o OrcaSlicer armazena e sincroniza seus perfis, ou para migrar suas predefinições manualmente, consulte nossa wiki.\n\nSe você não usava o Bambu Cloud para sincronizar perfis, esta mudança não afeta você e você pode ignorar esta mensagem com segurança."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr "Saber mais"
msgid "Reloading network plug-in..."
msgstr "Recarregando o plug-in de rede…"
@@ -1738,12 +1724,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "Tempo de execução WebView2"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "O caminho dos recursos não existe ou não é um diretório: %s"
@@ -5148,12 +5128,6 @@ msgstr "Todas as Placas"
msgid "Stats"
msgstr "Estatísticas"
msgid "Slice"
msgstr "Fatiar"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Retornar à Montagem"
@@ -5221,7 +5195,7 @@ msgstr "Volume:"
msgid "Size:"
msgstr "Tamanho:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Foram encontrados conflitos de caminhos de G-code na camada %d, Z = %.2lfmm. Por favor, separe mais os objetos em conflito (%s <-> %s)."
@@ -11140,12 +11114,6 @@ msgstr "A contração de filamento não será usada porque a contração dos fil
msgid "Generating skirt & brim"
msgstr "Gerando saia e borda"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exportando G-code"
@@ -12892,6 +12860,7 @@ msgstr "Usar múltiplas linhas para o padrão de preenchimento, se suportado pel
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15854,6 +15823,9 @@ msgstr "Exportar vários STLs"
msgid "Export the objects as multiple STLs to directory."
msgstr "Exportar os objetos como vários STLs para o diretório."
msgid "Slice"
msgstr "Fatiar"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Fatiar as placas: 0-todas as placas, i-placa i, outros-inválido"
@@ -20004,6 +19976,9 @@ msgstr ""
#~ msgid "Wiki Guide: Input Shaping Calibration"
#~ msgstr "Wiki Guide: Calibração da Modelagem de Entrada"
#~ msgid "Learn more"
#~ msgstr "Saber mais"
#~ msgid "Tips: You can drag the filaments to reassign them to different nozzles."
#~ msgstr "Dica: Você pode arrastar os filamentos para reatribuí-los a diferentes bicos."

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -1687,20 +1687,6 @@ msgstr ""
msgid "Untitled"
msgstr "Ej namngiven"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Från och med version 2.4.0 synkroniserar OrcaSlicer användarprofiler via Orca Cloud i stället för Bambu Cloud.\n\nLogga in på Orca Cloud för att migrera dina befintliga profiler, så överförs de automatiskt. Läs mer om hur OrcaSlicer lagrar och synkroniserar dina profiler, eller om hur du migrerar dina förinställningar manuellt, i vår wiki.\n\nOm du inte använde Bambu Cloud för att synkronisera profiler påverkar den här ändringen dig inte och du kan ignorera det här meddelandet."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1728,12 +1714,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr ""
@@ -5149,12 +5129,6 @@ msgstr "Alla plattor"
msgid "Stats"
msgstr "Statistik"
msgid "Slice"
msgstr "Bered"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Monterings retur"
@@ -5222,7 +5196,7 @@ msgstr "Volym:"
msgid "Size:"
msgstr "Storlek:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr ""
@@ -11039,12 +11013,6 @@ msgstr ""
msgid "Generating skirt & brim"
msgstr "Skapar Skirt & Brim"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Exporterar G-kod"
@@ -12633,6 +12601,7 @@ msgstr ""
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15409,6 +15378,9 @@ msgstr ""
msgid "Export the objects as multiple STLs to directory."
msgstr ""
msgid "Slice"
msgstr "Bered"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Bered plattorna: 0-alla plattor, i-platta i, andra-ogiltiga"

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2026-06-19 13:40+0700\n"
"Last-Translator: Icezaza\n"
"Language-Team: Thai\n"
@@ -1693,20 +1693,6 @@ msgstr "OrcaSlicer พบข้อยกเว้นที่ไม่ได้
msgid "Untitled"
msgstr "ไม่มีชื่อ"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "ตั้งแต่เวอร์ชัน 2.4.0 เป็นต้นไป OrcaSlicer จะซิงค์โปรไฟล์ผู้ใช้ผ่าน Orca Cloud แทน Bambu Cloud\n\nหากต้องการย้ายโปรไฟล์ที่มีอยู่ของคุณ ให้เข้าสู่ระบบ Orca Cloud แล้วระบบจะถ่ายโอนให้โดยอัตโนมัติ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีที่ OrcaSlicer จัดเก็บและซิงค์โปรไฟล์ของคุณ หรือต้องการย้ายพรีเซ็ตด้วยตนเอง โปรดดูที่วิกิของเรา\n\nหากคุณไม่ได้ใช้ Bambu Cloud ในการซิงค์โปรไฟล์ การเปลี่ยนแปลงนี้จะไม่ส่งผลต่อคุณ และคุณสามารถเพิกเฉยต่อข้อความนี้ได้"
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "กำลังโหลดปลั๊กอินเครือข่ายใหม่..."
@@ -1736,12 +1722,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "รันไทม์ WebView2"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "ไม่มีเส้นทางทรัพยากรหรือไม่ใช่ไดเรกทอรี: %s"
@@ -5103,12 +5083,6 @@ msgstr "ทุกแผ่น"
msgid "Stats"
msgstr "สถิติ"
msgid "Slice"
msgstr "สไลซ์"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "การส่งคืนการประกอบ"
@@ -5175,7 +5149,7 @@ msgstr "ปริมาณ:"
msgid "Size:"
msgstr "ขนาด:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "พบความขัดแย้งของเส้นทางรหัส G ที่เลเยอร์ %d, Z = %.2lfmm โปรดแยกวัตถุที่ขัดแย้งกันให้ไกลออกไป (%s <-> %s)"
@@ -10987,12 +10961,6 @@ msgstr "การหดตัวของเส้นพลาสติกจะ
msgid "Generating skirt & brim"
msgstr "กำลังสร้าง เส้นล้อมชิ้นงาน และ ขอบยึดชิ้นงาน"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "กำลังส่งออก G-code"
@@ -12762,7 +12730,7 @@ msgstr "การใช้หลายบรรทัดสำหรับรู
msgid "Z-buckling bias optimization (experimental)"
msgstr "การปรับชดเชยการโก่งตัวตามแกน Z ให้เหมาะสม (ทดลอง)"
#, fuzzy
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "ปรับคลื่นไจรอยด์ให้ถี่ขึ้นตามแกน Z (แนวตั้ง) เมื่อความหนาแน่นไส้ในต่ำ เพื่อลดความยาวช่วงเสาแนวตั้งที่มีผลจริง และเพิ่มความต้านทานการโก่งตัวจากแรงอัดตามแกน Z โดยยังใช้เส้นพลาสติกเท่าเดิม ไม่มีผลเมื่อความหนาแน่นไส้ในแบบโปร่งประมาณ ~30% ขึ้นไป ใช้เฉพาะเมื่อรูปแบบไส้ในแบบโปร่งตั้งเป็นไจรอยด์เท่านั้น"
@@ -15632,6 +15600,9 @@ msgstr "ส่งออก STL หลายรายการ"
msgid "Export the objects as multiple STLs to directory."
msgstr "ส่งออกวัตถุเป็น STL หลายรายการไปยังไดเร็กทอรี"
msgid "Slice"
msgstr "สไลซ์"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "แบ่งเพลต: 0-เพลตทั้งหมด, i-เพลท i, อื่นๆ-ไม่ถูกต้อง"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2026-04-08 23:59+0300\n"
"Last-Translator: GlauTech\n"
"Language-Team: \n"
@@ -1712,20 +1712,6 @@ msgstr "OrcaSlicer'da işlenmeyen bir istisna oluştu: %1%"
msgid "Untitled"
msgstr "İsimsiz"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "OrcaSlicer, 2.4.0 sürümünden itibaren kullanıcı profillerini Bambu Cloud yerine Orca Cloud üzerinden senkronize eder.\n\nMevcut profillerinizi taşımak için Orca Cloud'da oturum açın; profilleriniz otomatik olarak aktarılacaktır. OrcaSlicer'ın profillerinizi nasıl depolayıp senkronize ettiği hakkında daha fazla bilgi edinmek veya ön ayarlarınızı elle taşımak için wiki'mize göz atın.\n\nProfilleri senkronize etmek için Bambu Cloud kullanmadıysanız bu değişiklik sizi etkilemez ve bu mesajı güvenle yoksayabilirsiniz."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr "Ağ eklentisi yeniden yükleniyor..."
@@ -1755,12 +1741,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Çalışma Zamanı"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Kaynak yolu mevcut değil veya bir dizin değil: %s"
@@ -5219,12 +5199,6 @@ msgstr "Tüm Plakalar"
msgid "Stats"
msgstr "İstatistikler"
msgid "Slice"
msgstr "Dilimle"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Montaj İptali"
@@ -5292,7 +5266,7 @@ msgstr "Hacim:"
msgid "Size:"
msgstr "Boyut:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "%d katmanında gcode yollarında çakışmalar bulundu, Z = %.2lfmm. Lütfen çakışan nesneleri daha uzağa ayırın (%s <-> %s)."
@@ -11198,12 +11172,6 @@ msgstr "Filament büzülmesi kullanılmayacaktır çünkü kullanılan filamentl
msgid "Generating skirt & brim"
msgstr "Etek ve kenar oluşturma"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "G kodu dışa aktarılıyor"
@@ -12939,6 +12907,7 @@ msgstr "Dolgu deseni tarafından destekleniyorsa, dolgu deseni için birden fazl
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15847,6 +15816,9 @@ msgstr "Birden çok STLyi dışa aktar"
msgid "Export the objects as multiple STLs to directory."
msgstr "Nesneleri birden fazla STL olarak dizine aktarın."
msgid "Slice"
msgstr "Dilimle"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Plakaları dilimleyin: 0-tüm plakalar, i-plaka i, diğerleri-geçersiz"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: orcaslicerua\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2025-03-07 09:30+0200\n"
"Last-Translator: \n"
"Language-Team: Ukrainian\n"
@@ -1721,20 +1721,6 @@ msgstr "Невідома помилка OrcaSlicer : %1%"
msgid "Untitled"
msgstr "Без назви"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Починаючи з версії 2.4.0, OrcaSlicer синхронізує профілі користувача через Orca Cloud замість Bambu Cloud.\n\nЩоб перенести наявні профілі, увійдіть до Orca Cloud, і вони будуть перенесені автоматично. Щоб дізнатися більше про те, як OrcaSlicer зберігає та синхронізує ваші профілі, або щоб перенести свої шаблони вручну, перегляньте нашу вікі.\n\nЯкщо ви не використовували Bambu Cloud для синхронізації профілів, ця зміна вас не стосується, і ви можете сміливо проігнорувати це повідомлення."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1764,12 +1750,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "Виконання WebView2"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr ""
@@ -5220,12 +5200,6 @@ msgstr ""
msgid "Stats"
msgstr ""
msgid "Slice"
msgstr "Нарізка"
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Повернення збірки"
@@ -5294,7 +5268,7 @@ msgid "Size:"
msgstr "Розмір:"
# TODO: Review, changed by lang refactor. PR 14254
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr ""
"Виявлено конфлікти шляхів gcode на рівні %d, Z = %.2lf мм. Будь ласка \n"
@@ -11203,12 +11177,6 @@ msgstr ""
msgid "Generating skirt & brim"
msgstr "Генерація спідниці та кайми"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Експорт G-code"
@@ -12923,6 +12891,7 @@ msgstr ""
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15818,6 +15787,9 @@ msgstr "Експортувати декілька STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Експортувати об'єкти як декілька STL у папку"
msgid "Slice"
msgstr "Нарізка"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Нарізати пластини: 0-всі пластини, i-пластина i, інші-неприпустимі"

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2025-10-02 17:43+0700\n"
"Last-Translator: \n"
"Language-Team: hainguyen.ts13@gmail.com\n"
@@ -1712,20 +1712,6 @@ msgstr "OrcaSlicer gặp ngoại lệ không xử lý được: %1%"
msgid "Untitled"
msgstr "Không tiêu đề"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "Kể từ phiên bản 2.4.0, OrcaSlicer đồng bộ hồ sơ người dùng thông qua Orca Cloud thay vì Bambu Cloud.\n\nĐể di chuyển các hồ sơ hiện có của bạn, hãy đăng nhập vào Orca Cloud và chúng sẽ được chuyển tự động. Để tìm hiểu thêm về cách OrcaSlicer lưu trữ và đồng bộ hồ sơ của bạn, hoặc để di chuyển các cài đặt sẵn theo cách thủ công, hãy xem wiki của chúng tôi.\n\nNếu bạn không sử dụng Bambu Cloud để đồng bộ hồ sơ, thay đổi này không ảnh hưởng đến bạn và bạn có thể bỏ qua thông báo này."
msgid "Profile syncing change"
msgstr ""
msgid "Learn more"
msgstr ""
msgid "Reloading network plug-in..."
msgstr ""
@@ -1755,12 +1741,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr ""
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "Đường dẫn tài nguyên không tồn tại hoặc không phải thư mục: %s"
@@ -5191,12 +5171,6 @@ msgstr "Tất cả plate"
msgid "Stats"
msgstr "Thống kê"
msgid "Slice"
msgstr ""
msgid "Review"
msgstr ""
msgid "Assembly Return"
msgstr "Trở về lắp ráp"
@@ -5264,7 +5238,7 @@ msgstr "Thể tích:"
msgid "Size:"
msgstr "Kích thước:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "Đã tìm thấy xung đột đường đi G-code tại lớp %d, Z = %.2lfmm. Vui lòng tách các vật thể xung đột ra xa hơn (%s <-> %s)."
@@ -11121,12 +11095,6 @@ msgstr "Co ngót filament sẽ không được sử dụng vì co ngót filament
msgid "Generating skirt & brim"
msgstr "Đang tạo viền & brim"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr ""
msgid "Exporting G-code"
msgstr "Đang xuất G-code"
@@ -12833,6 +12801,7 @@ msgstr "Sử dụng nhiều đường cho mẫu infill, nếu được hỗ tr
msgid "Z-buckling bias optimization (experimental)"
msgstr ""
#, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr ""
@@ -15736,6 +15705,9 @@ msgstr "Xuất nhiều STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "Xuất các đối tượng dưới dạng nhiều STL vào thư mục."
msgid "Slice"
msgstr ""
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "Slice các bản: 0-tất cả bản, i-bản i, khác-không hợp lệ"

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Slic3rPE\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2026-06-11 12:37-0300\n"
"Last-Translator: Handle <mail@bysb.net>\n"
"Language-Team: \n"
@@ -249,7 +249,7 @@ msgid "Reset"
msgstr "重置"
msgid "Enter"
msgstr "回车"
msgstr ""
msgid "Shortcut Key "
msgstr "快捷键 "
@@ -1454,7 +1454,7 @@ msgid "Restart selection"
msgstr "重新选择"
msgid "Esc"
msgstr "Esc"
msgstr ""
msgid "Cancel a feature until exit"
msgstr "取消一个特征直到退出"
@@ -1710,20 +1710,6 @@ msgstr "OrcaSlicer 捕捉到一个未处理的异常:%1%"
msgid "Untitled"
msgstr "未命名"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "自 2.4.0 版本起OrcaSlicer 通过 Orca Cloud而非 Bambu Cloud同步用户配置文件。\n\n要迁移您现有的配置文件请登录 Orca Cloud配置文件将被自动转移。若要进一步了解 OrcaSlicer 如何存储和同步您的配置文件,或手动迁移您的预设,请查看我们的 Wiki。\n\n如果您此前未使用 Bambu Cloud 同步配置文件,则此变更不会影响您,您可以放心忽略此消息。"
msgid "Profile syncing change"
msgstr "配置文件同步方式变更"
msgid "Learn more"
msgstr "了解更多"
msgid "Reloading network plug-in..."
msgstr "正在重新加载网络插件..."
@@ -1753,12 +1739,6 @@ msgstr ""
msgid "WebView2 Runtime"
msgstr "WebView2 运行库"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr "无法安装 Microsoft WebView2 运行库。\n在安装之前包括设置向导在内的部分功能可能显示为空白。\n请从 https://developer.microsoft.com/microsoft-edge/webview2/ 手动安装,然后重启 Orca Slicer。"
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "资源路径不存在或不是目录:%s"
@@ -1831,7 +1811,7 @@ msgid "Choose one file (GCODE/3MF):"
msgstr "选择一个文件GCODE/3MF"
msgid "Ext"
msgstr "外置"
msgstr ""
msgid "Some presets are modified."
msgstr "预设已被修改。"
@@ -2840,7 +2820,7 @@ msgid "Plate"
msgstr "盘"
msgid "Brim"
msgstr "Brim"
msgstr ""
msgid "Object/Part Settings"
msgstr "对象/零件设置"
@@ -4053,11 +4033,11 @@ msgstr "热床形状"
#, c-format, boost-format
msgid "A minimum temperature above %d℃ is recommended for %s.\n"
msgstr "建议最低温度高于 %d℃适用于 %s。\n"
msgstr ""
#, c-format, boost-format
msgid "A maximum temperature below %d℃ is recommended for %s.\n"
msgstr "建议最高温度低于 %d℃适用于 %s。\n"
msgstr ""
msgid "The recommended minimum temperature cannot be higher than the recommended maximum temperature.\n"
msgstr "推荐最低温度不能大于推荐最高温度。\n"
@@ -4080,7 +4060,7 @@ msgid "The recommended nozzle temperature for this filament type is [%d, %d] deg
msgstr "该耗材的推荐喷嘴温度是[%d, %d]摄氏度"
msgid "Adaptive Pressure Advance model validation failed:\n"
msgstr "自适应压力提前模型验证失败:\n"
msgstr ""
# TODO: Review, changed by lang refactor. PR 14254
msgid ""
@@ -4664,7 +4644,7 @@ msgid "Invalid format. Expected vector format: \"%1%\""
msgstr "无效格式,应该是\"%1%\"这种数组格式"
msgid "N/A"
msgstr "不适用"
msgstr ""
msgid "Pick"
msgstr "选择"
@@ -5212,12 +5192,6 @@ msgstr "所有打印板"
msgid "Stats"
msgstr "统计"
msgid "Slice"
msgstr "切片"
msgid "Review"
msgstr "查看"
msgid "Assembly Return"
msgstr "退出装配体视图"
@@ -5285,7 +5259,7 @@ msgstr "体积:"
msgid "Size:"
msgstr "尺寸:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "发现G-code路径在层%d高度为%.2lf mm处有冲突。请将有冲突的对象分离得更远(%s <-> %s)。"
@@ -8157,13 +8131,13 @@ msgid "Renders cast shadows on the plate in realistic view."
msgstr "在写实渲染中渲染投射到打印板上的阴影。"
msgid "Smooth normals"
msgstr "平滑法线"
msgstr ""
msgid ""
"Applies smooth normals to the realistic view.\n"
"\n"
"Requires manual scene reload to take effect (right-click on 3D view → \"Reload All\")."
msgstr "在写实渲染中应用平滑法线。\n\n需要手动重新加载场景才能生效在 3D 视图中右键单击 →“重新加载全部”)。"
msgstr ""
msgid "Anti-aliasing"
msgstr "抗锯齿"
@@ -8294,10 +8268,10 @@ msgid "Color only"
msgstr "仅颜色"
msgid "Bambu network plug-in"
msgstr "Bambu网络插件"
msgstr ""
msgid "Enable Bambu network plug-in"
msgstr "启用Bambu网络插件"
msgstr ""
msgid "Network plug-in version"
msgstr "网络插件版本"
@@ -11200,7 +11174,7 @@ msgid "The precise wall option will be ignored for outer-inner or inner-outer-in
msgstr "当壁序列为外内或内外内时,精确墙壁选项将被忽略。"
msgid "The Adaptive Pressure Advance model for one or more extruders may contain invalid values."
msgstr "一个或多个挤出机的自适应压力提前模型可能包含无效值。"
msgstr ""
msgid "Filament shrinkage will not be used because filament shrinkage for the used filaments does not match."
msgstr "不会使用耗材收缩率,因为所用耗材的耗材收缩率不匹配。"
@@ -11208,12 +11182,6 @@ msgstr "不会使用耗材收缩率,因为所用耗材的耗材收缩率不匹
msgid "Generating skirt & brim"
msgstr "正在生成裙边和brim"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr "在“逐件”打印顺序下,物体之间无法容纳逐物体裙边。\n\n请增大物体之间的距离、减小 brim/裙边尺寸、将裙边类型切换为“组合”,或将打印顺序切换为“逐层”。"
msgid "Exporting G-code"
msgstr "正在导出G-code"
@@ -12552,7 +12520,7 @@ msgstr "为悬垂启用自适应压力提前(试验)"
msgid ""
"Enable adaptive PA for overhangs as well as when flow changes within the same feature. This is an experimental option, as if the PA profile is not set accurately, it will cause uniformity issues on the external surfaces before and after overhangs.\n"
"Not compatible with Prusa printers as they pause to process PA changes, which causes delays and defects."
msgstr "针对悬垂以及同一特征内的流量变化启用自适应 PA。这是一个实验性选项因为如果未准确设置 PA 配置文件,将导致悬垂前后外表面出现均匀性问题。\n与 Prusa 打印机不兼容,因为它们会暂停以处理 PA 变化,从而导致延迟和瑕疵。"
msgstr ""
msgid "Pressure advance for bridges"
msgstr "为搭桥启用压力提前"
@@ -12945,7 +12913,7 @@ msgid "Filament price, for statistical purposes only."
msgstr "耗材丝的价格。只用于统计信息。"
msgid "money/kg"
msgstr "金额/kg"
msgstr ""
msgid "Vendor"
msgstr "供应商"
@@ -13001,6 +12969,8 @@ msgstr "如果填充图案支持,使用多线进行填充。"
msgid "Z-buckling bias optimization (experimental)"
msgstr "Z 轴屈曲偏置优化(实验性)"
# TODO: Review, changed by lang refactor. PR 14254
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "在低填充密度下沿 Z垂直轴收紧螺旋Gyroid波形以缩短有效的垂直柱长提升 Z 轴抗压屈曲能力。耗材用量保持不变。在约 30% 及以上的稀疏填充密度下无效果。仅当稀疏填充图案设置为 Gyroid 时适用。"
@@ -13249,7 +13219,7 @@ msgid "Travel speed of the first layer."
msgstr "首层空驶速度"
msgid "Number of slow layers"
msgstr "慢速层数量"
msgstr ""
msgid "The first few layers are printed slower than normal. The speed is gradually increased in a linear fashion over the specified number of layers."
msgstr ""
@@ -15970,6 +15940,9 @@ msgstr "导出多个STL"
msgid "Export the objects as multiple STLs to directory."
msgstr "将对象导出为多个STL到目录。"
msgid "Slice"
msgstr "切片"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "对打印板切片0-所有板i-第i个板其他-无效"
@@ -18118,7 +18091,7 @@ msgstr ""
#, c-format, boost-format
msgid "Printing %1s material with %2s nozzle may cause nozzle damage."
msgstr "使用 %1s 材料搭配 %2s 喷嘴打印可能会损坏喷嘴。"
msgstr ""
msgid "Need select printer"
msgstr "需要选择打印机"

View File

@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-06-26 10:26+0800\n"
"POT-Creation-Date: 2026-06-22 20:13-0300\n"
"PO-Revision-Date: 2025-11-28 13:48-0600\n"
"Last-Translator: tntchn <15895303+tntchn@users.noreply.github.com>\n"
"Language-Team: \n"
@@ -252,7 +252,7 @@ msgid "Reset"
msgstr "重設"
msgid "Enter"
msgstr "Enter"
msgstr ""
msgid "Shortcut Key "
msgstr "快捷鍵 "
@@ -874,13 +874,13 @@ msgid "ITALIC"
msgstr "斜體"
msgid "SWISS"
msgstr "瑞士體"
msgstr ""
msgid "MODERN"
msgstr "現代"
msgstr ""
msgid "First font"
msgstr "第一個字型"
msgstr ""
msgid "Default font"
msgstr "預設字型"
@@ -1458,7 +1458,7 @@ msgid "Restart selection"
msgstr "重新開始選取"
msgid "Esc"
msgstr "Esc"
msgstr ""
msgid "Cancel a feature until exit"
msgstr "在退出前取消功能"
@@ -1712,20 +1712,6 @@ msgstr "Orca Slicer 遭遇到一個未處理的例外:%1%"
msgid "Untitled"
msgstr "未命名"
msgid ""
"Since version 2.4.0, OrcaSlicer syncs user profiles through Orca Cloud instead of Bambu Cloud.\n"
"\n"
"To migrate your existing profiles, log in to Orca Cloud and they will be transferred automatically. To learn more about how OrcaSlicer stores and syncs your profiles, or to migrate your presets manually, check out our wiki.\n"
"\n"
"If you did not use Bambu Cloud to sync profiles, this change does not affect you and you can safely ignore this message."
msgstr "自 2.4.0 版本起OrcaSlicer 透過 Orca Cloud而非 Bambu Cloud同步使用者設定檔。\n\n若要移轉您現有的設定檔請登入 Orca Cloud設定檔將會自動轉移。若要進一步了解 OrcaSlicer 如何儲存與同步您的設定檔,或手動移轉您的預設,請參閱我們的 wiki。\n\n若您先前並未使用 Bambu Cloud 同步設定檔,則此變更不會影響您,您可以放心忽略此訊息。"
msgid "Profile syncing change"
msgstr "設定檔同步方式變更"
msgid "Learn more"
msgstr "了解更多"
msgid "Reloading network plug-in..."
msgstr "正在重新載入網路外掛程式..."
@@ -1753,12 +1739,6 @@ msgstr "Orca Slicer 需要 Microsoft WebView2 Runtime 才能操作某些功能
msgid "WebView2 Runtime"
msgstr "WebView2 Runtime"
msgid ""
"The Microsoft WebView2 Runtime could not be installed.\n"
"Some features, including the setup wizard, may appear blank until it is installed.\n"
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."
msgstr "無法安裝 Microsoft WebView2 Runtime。\n在安裝完成前包括設定精靈在內的部分功能可能顯示為空白。\n請從 https://developer.microsoft.com/microsoft-edge/webview2/ 手動安裝,然後重新啟動 Orca Slicer。"
#, c-format, boost-format
msgid "Resources path does not exist or is not a directory: %s"
msgstr "資源路徑不存在或並非目錄:%s"
@@ -2173,7 +2153,7 @@ msgid "Delete the selected object"
msgstr "刪除所選物件"
msgid "Backspace"
msgstr "Backspace"
msgstr ""
msgid "Load..."
msgstr "載入..."
@@ -2557,7 +2537,7 @@ msgid "Center"
msgstr "居中"
msgid "Drop"
msgstr "下降"
msgstr ""
msgid "Edit Process Settings"
msgstr "編輯列印參數"
@@ -2966,7 +2946,7 @@ msgid "Check the status of current system services"
msgstr "請檢查目前系統服務狀態"
msgid "code"
msgstr "代碼"
msgstr ""
msgid "Failed to connect to cloud service"
msgstr "無法連接到雲端服務"
@@ -3491,7 +3471,7 @@ msgid "Orca Slicer is based on PrusaSlicer and BambuStudio"
msgstr "Orca Slicer 基於 PrusaSlicer 與 BambuStudio"
msgid "Libraries"
msgstr "函式庫"
msgstr ""
msgid "This software uses open source components whose copyright and other proprietary rights belong to their respective owners"
msgstr "本軟體採用了開源組件,其版權及相關專有權歸屬於各自的所有者"
@@ -4098,7 +4078,7 @@ msgid "The recommended nozzle temperature for this filament type is [%d, %d] deg
msgstr "該線材的推薦噴嘴溫度是攝氏 [%d, %d] 度"
msgid "Adaptive Pressure Advance model validation failed:\n"
msgstr "自適應壓力補償模型驗證失敗:\n"
msgstr ""
# TODO: Review, changed by lang refactor. PR 14254
msgid ""
@@ -4706,7 +4686,7 @@ msgid "Invalid format. Expected vector format: \"%1%\""
msgstr "無效格式,應該是「%1%」這種格式"
msgid "N/A"
msgstr "不適用"
msgstr ""
msgid "Pick"
msgstr "選取"
@@ -4805,7 +4785,7 @@ msgid "Gap infill"
msgstr "填縫"
msgid "Skirt"
msgstr "Skirt"
msgstr ""
msgid "Support interface"
msgstr "支撐面"
@@ -5254,12 +5234,6 @@ msgstr "所有列印板"
msgid "Stats"
msgstr "統計"
msgid "Slice"
msgstr "切片"
msgid "Review"
msgstr "檢視"
msgid "Assembly Return"
msgstr "退出組裝視角"
@@ -5327,7 +5301,7 @@ msgstr "體積:"
msgid "Size:"
msgstr "尺寸:"
#, boost-format
#, c-format, boost-format
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
msgstr "發現 G-code 路徑在 %d 層Z = %.2lf mm 處的衝突。請將有衝突的物件分離得更遠(%s <-> %s。"
@@ -8214,13 +8188,13 @@ msgid "Renders cast shadows on the plate in realistic view."
msgstr "在擬真檢視中於列印板上算繪投射陰影。"
msgid "Smooth normals"
msgstr "平滑法線"
msgstr ""
msgid ""
"Applies smooth normals to the realistic view.\n"
"\n"
"Requires manual scene reload to take effect (right-click on 3D view → \"Reload All\")."
msgstr "將平滑法線套用至擬真檢視。\n\n需要手動重新載入場景才能生效在 3D 檢視中按一下滑鼠右鍵 →「重新載入所有物件」)。"
msgstr ""
msgid "Anti-aliasing"
msgstr "抗鋸齒"
@@ -8351,10 +8325,10 @@ msgid "Color only"
msgstr "僅顏色"
msgid "Bambu network plug-in"
msgstr "Bambu 網路外掛程式"
msgstr ""
msgid "Enable Bambu network plug-in"
msgstr "啟用 Bambu 網路外掛程式"
msgstr ""
msgid "Network plug-in version"
msgstr "網路外掛程式版本"
@@ -11261,7 +11235,7 @@ msgid "The precise wall option will be ignored for outer-inner or inner-outer-in
msgstr "當壁序列為外內或內外內時,精確牆壁選項將被忽略。"
msgid "The Adaptive Pressure Advance model for one or more extruders may contain invalid values."
msgstr "一個或多個擠出機的自適應壓力補償模型可能包含無效值。"
msgstr ""
msgid "Filament shrinkage will not be used because filament shrinkage for the used filaments does not match."
msgstr "線材收縮補償將被停用,因為所使用的線材之間的收縮率差異過大。"
@@ -11269,12 +11243,6 @@ msgstr "線材收縮補償將被停用,因為所使用的線材之間的收縮
msgid "Generating skirt & brim"
msgstr "正在產生 Skirt 和 Brim"
msgid ""
"Per-object skirts cannot fit between the objects in By object print sequence.\n"
"\n"
"Move the objects farther apart, reduce brim/skirt size, switch Skirt type to Combined, or switch Print sequence to By layer."
msgstr "在「逐件」列印順序下,物件之間無法容納各別物件的 Skirt。\n\n請加大物件之間的距離、縮小 Brim/Skirt 尺寸、將 Skirt 類型切換為「合併」,或將列印順序切換為「逐層」。"
msgid "Exporting G-code"
msgstr "正在匯出 G-code"
@@ -12624,7 +12592,7 @@ msgstr "啟用懸挑自適應壓力補償 (beta)"
msgid ""
"Enable adaptive PA for overhangs as well as when flow changes within the same feature. This is an experimental option, as if the PA profile is not set accurately, it will cause uniformity issues on the external surfaces before and after overhangs.\n"
"Not compatible with Prusa printers as they pause to process PA changes, which causes delays and defects."
msgstr "針對懸空以及同一特徵內的流量變化啟用自適應壓力補償 (PA)。這是一個實驗性選項,因為若 PA 設定檔設定不準確,將會導致懸空前後的外表面出現均勻性問題。\n與 Prusa 印表機不相容,因為它們會暫停以處理 PA 變更,進而導致延遲與瑕疵。"
msgstr ""
msgid "Pressure advance for bridges"
msgstr "橋接的壓力補償"
@@ -13060,7 +13028,7 @@ msgid "Z-buckling bias optimization (experimental)"
msgstr "Z 軸挫曲偏置最佳化(實驗性)"
# TODO: Review, changed by lang refactor. PR 14254
#, fuzzy
#, fuzzy, c-format, boost-format
msgid "Tightens the gyroid wave along the Z (vertical) axis at low infill density to shorten the effective vertical column length and improve Z-axis compression buckling resistance. Filament use is preserved. No effect at ~30% sparse infill density and above. Only applies when Sparse infill pattern is set to Gyroid."
msgstr "在低填充密度時,沿 Z垂直軸收緊螺旋體波形以縮短有效垂直柱長度並提升 Z 軸抗壓挫曲能力。線材用量維持不變。在約 30% 稀疏填充密度及以上時無效果。僅在稀疏填充圖案設為螺旋體時適用。"
@@ -13309,7 +13277,7 @@ msgid "Travel speed of the first layer."
msgstr "首層空駛速度"
msgid "Number of slow layers"
msgstr "慢速層數量"
msgstr ""
msgid "The first few layers are printed slower than normal. The speed is gradually increased in a linear fashion over the specified number of layers."
msgstr "減慢前幾層的列印速度。列印速度會逐漸加速到滿速。"
@@ -16015,6 +15983,9 @@ msgstr "匯出為多個 STL 檔案"
msgid "Export the objects as multiple STLs to directory."
msgstr "將物件匯出為多個 STL 檔案至指定資料夾"
msgid "Slice"
msgstr "切片"
msgid "Slice the plates: 0-all plates, i-plate i, others-invalid"
msgstr "切片板選項0 代表所有板i 代表第 i 塊板,其餘則為無效輸入"
@@ -18167,7 +18138,7 @@ msgstr ""
#, c-format, boost-format
msgid "Printing %1s material with %2s nozzle may cause nozzle damage."
msgstr "使用 %1s 材料搭配 %2s 噴嘴列印可能會損壞噴嘴。"
msgstr ""
msgid "Need select printer"
msgstr "需要選擇列印設備"

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""Belt temperature-tower asset generator (discrete-provini design).
A vertical temperature tower cannot be sliced on a belt printer, so lay a row of
DISCRETE provini (one per temperature) along the belt (designed Y) with a fixed
surface gap. Each provino is the chevron+arc unit (belt_temp_provino_unit.stl,
keel-first); its temperature is ENGRAVED upright into the 50 mm face — a raised
number would be an unsupported overhang on the belt. The C++ calib_temp belt branch
(Plater.cpp) injects one M104 per zone 70 layers INTO provino i:
print_z[i] = i * PITCH * cos(theta) + 70 * layer_height (theta = 45)
inside the body, not in the empty inter-provino gap (which has no sliced layers for
the event to attach to). PITCH below is the shared geometry contract with that code —
keep them in sync.
Generates one STL per filament temp range used by Temp_Calibration_Dlg.
"""
import numpy as np, trimesh, os
from matplotlib.textpath import TextPath
from matplotlib.font_manager import FontProperties
from shapely.geometry import Polygon as ShPoly
from shapely.ops import unary_union
HERE = os.path.dirname(os.path.abspath(__file__))
UNIT = os.path.join(HERE, 'belt_temp_provino_unit.stl') # single provino, keel-first
SURF_GAP = 25.0 # surface-to-surface gap between provini (mm) — user spec
TEXT_H = 9.0
TEXT_DEPTH = 0.8 # engraving depth (numbers are CUT into the face, not raised:
# a raised number is an unsupported Y-overhang on the belt)
TEXT_OVERSHOOT = 0.6 # extra height poking out of the face for a clean boolean cut
# Temperature ranges (start, end) per filament family, 5 C step. File name encodes them.
RANGES = [(230,190),(270,230),(250,230),(280,240),(240,210),(320,280)]
unit = trimesh.load(UNIT)
dY = unit.bounds[1,1] - unit.bounds[0,1]
PITCH = dY + SURF_GAP # designed-Y pitch == C++ contract constant
print(f"unit dY={dY:.2f} PITCH={PITCH:.3f} (C++ contract: print_z[i]=i*{PITCH:.3f}*cos45)")
# 50 mm face normal (0,-1,1)/sqrt2 ; UPRIGHT basis u=+X det(+1) (verified non-mirrored)
n = np.array([0,-1,1.])/np.sqrt(2)
u = np.array([1,0,0.]); v = np.array([0,1,1.])/np.sqrt(2)
R = np.column_stack([u,v,n])
fn = unit.face_normals; fc = unit.triangles_center; fa = unit.area_faces
sel = (fn@n) > 0.9
face_c = (fc[sel]*fa[sel,None]).sum(0)/fa[sel].sum()
def text_mesh(s):
tp = TextPath((0,0), s, size=TEXT_H, prop=FontProperties(family='DejaVu Sans'))
rings = [ShPoly(p) for p in tp.to_polygons() if len(p)>=3]
rings.sort(key=lambda r:r.area, reverse=True)
used=[False]*len(rings); parts=[]
for i,o in enumerate(rings):
if used[i]: continue
holes=[]
for j in range(i+1,len(rings)):
if not used[j] and o.contains(rings[j]): holes.append(rings[j].exterior.coords); used[j]=True
parts.append(ShPoly(o.exterior.coords,holes)); used[i]=True
poly = unary_union(parts)
geoms = list(poly.geoms) if poly.geom_type=='MultiPolygon' else [poly]
m = trimesh.util.concatenate([trimesh.creation.extrude_polygon(g,height=TEXT_DEPTH+TEXT_OVERSHOOT) for g in geoms])
c = m.bounds.mean(axis=0); m.apply_translation([-c[0],-c[1],0]); return m
for t_start, t_end in RANGES:
temps = list(range(t_start, t_end-1, -5))
parts=[]
for i,T in enumerate(temps):
c = unit.copy(); c.apply_translation([0, i*PITCH, 0])
t = text_mesh(str(T)); M=np.eye(4); M[:3,:3]=R; t.apply_transform(M)
# place the text spanning from TEXT_DEPTH inside the face to TEXT_OVERSHOOT outside,
# then CUT it out of the provino (engrave) — no raised material, no Y-overhang.
t.apply_translation(face_c - n*TEXT_DEPTH + np.array([0,i*PITCH,0]))
c = trimesh.boolean.difference([c, t], engine='manifold')
parts.append(c)
asset = trimesh.util.concatenate(parts)
out = os.path.join(HERE, f"belt_temp_tower_{t_start}_{t_end}.stl")
asset.export(out)
dims = np.round(asset.bounds[1]-asset.bounds[0],1)
wt = all(p.is_watertight for p in parts)
print(f" {t_start}->{t_end}: {len(temps)} zones bbox={dims} watertight={wt} -> {os.path.basename(out)}")

View File

@@ -1,9 +1,13 @@
{
"name": "Custom Printer",
"version": "02.04.00.00",
"version": "02.04.00.03",
"force_update": "0",
"description": "My configurations",
"machine_model_list": [
{
"name": "Generic Belt Printer",
"sub_path": "machine/MyBeltPrinter.json"
},
{
"name": "Generic Klipper Printer",
"sub_path": "machine/MyKlipper.json"
@@ -262,18 +266,38 @@
"name": "MyKlipper 0.8 nozzle",
"sub_path": "machine/MyKlipper 0.8 nozzle.json"
},
{
"name": "fdm_belt_common",
"sub_path": "machine/fdm_belt_common.json"
},
{
"name": "fdm_toolchanger_common",
"sub_path": "machine/fdm_toolchanger_common.json"
},
{
"name": "MyRepetier 0.4 nozzle",
"sub_path": "machine/MyRepetier 0.4 nozzle.json"
},
{
"name": "MyRRF 0.4 nozzle",
"sub_path": "machine/MyRRF 0.4 nozzle.json"
},
{
"name": "MyBeltPrinter 0.2 nozzle",
"sub_path": "machine/MyBeltPrinter 0.2 nozzle.json"
},
{
"name": "MyBeltPrinter 0.4 nozzle",
"sub_path": "machine/MyBeltPrinter 0.4 nozzle.json"
},
{
"name": "MyBeltPrinter 0.6 nozzle",
"sub_path": "machine/MyBeltPrinter 0.6 nozzle.json"
},
{
"name": "MyBeltPrinter 0.8 nozzle",
"sub_path": "machine/MyBeltPrinter 0.8 nozzle.json"
},
{
"name": "MyRepetier 0.4 nozzle",
"sub_path": "machine/MyRepetier 0.4 nozzle.json"
},
{
"name": "MyToolChanger 0.2 nozzle",
"sub_path": "machine/MyToolChanger 0.2 nozzle.json"

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,26 @@
{
"type": "machine",
"name": "MyBeltPrinter 0.2 nozzle",
"inherits": "fdm_belt_common",
"from": "system",
"setting_id": "GM_BELT_001",
"instantiation": "true",
"printer_model": "Generic Belt Printer",
"nozzle_diameter": [
"0.2"
],
"max_layer_height": [
"0.16"
],
"min_layer_height": [
"0.04"
],
"printer_variant": "0.2",
"printable_area": [
"0x0",
"350x0",
"350x350",
"0x350"
],
"printable_height": "300"
}

View File

@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "MyBeltPrinter 0.4 nozzle",
"inherits": "fdm_belt_common",
"from": "system",
"setting_id": "GM_BELT_002",
"instantiation": "true",
"printer_model": "Generic Belt Printer",
"nozzle_diameter": [
"0.4"
],
"printer_variant": "0.4",
"printable_area": [
"0x0",
"350x0",
"350x350",
"0x350"
],
"printable_height": "300"
}

View File

@@ -0,0 +1,26 @@
{
"type": "machine",
"name": "MyBeltPrinter 0.6 nozzle",
"inherits": "fdm_belt_common",
"from": "system",
"setting_id": "GM_BELT_003",
"instantiation": "true",
"printer_model": "Generic Belt Printer",
"nozzle_diameter": [
"0.6"
],
"max_layer_height": [
"0.4"
],
"min_layer_height": [
"0.12"
],
"printer_variant": "0.6",
"printable_area": [
"0x0",
"350x0",
"350x350",
"0x350"
],
"printable_height": "300"
}

View File

@@ -0,0 +1,26 @@
{
"type": "machine",
"name": "MyBeltPrinter 0.8 nozzle",
"inherits": "fdm_belt_common",
"from": "system",
"setting_id": "GM_BELT_004",
"instantiation": "true",
"printer_model": "Generic Belt Printer",
"nozzle_diameter": [
"0.8"
],
"max_layer_height": [
"0.6"
],
"min_layer_height": [
"0.2"
],
"printer_variant": "0.8",
"printable_area": [
"0x0",
"350x0",
"350x350",
"0x350"
],
"printable_height": "300"
}

View File

@@ -0,0 +1,12 @@
{
"type": "machine_model",
"name": "Generic Belt Printer",
"model_id": "my_belt_01",
"nozzle_diameter": "0.4;0.2;0.6;0.8",
"machine_tech": "FFF",
"family": "MyPrinter",
"bed_model": "Custom_350_bed.stl",
"bed_texture": "orcaslicer_bed_texture.svg",
"hotend_model": "",
"default_materials": "Generic PLA @System;Generic PLA-CF @System;Generic PETG @System;Generic TPU @System;Generic PC @System;Generic PVA @System;Generic PA @System;Generic PA-CF @System"
}

View File

@@ -0,0 +1,99 @@
{
"type": "machine",
"name": "fdm_belt_common",
"inherits": "fdm_klipper_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "klipper",
"single_extruder_multi_material": "0",
"default_filament_profile": [
"Generic PLA @System"
],
"default_print_profile": "0.20mm Standard @System",
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"deretraction_speed": [
"30"
],
"extruder_colour": [
"#FCE94F"
],
"extruder_offset": [
"0x0"
],
"long_retractions_when_cut": [
"0"
],
"nozzle_diameter": [
"0.4"
],
"retract_before_wipe": [
"70%"
],
"retract_length_toolchange": [
"2"
],
"retract_lift_above": [
"0"
],
"retract_lift_below": [
"0"
],
"retract_lift_enforce": [
"All Surfaces"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retract_when_changing_layer": [
"1"
],
"retraction_distances_when_cut": [
"18"
],
"retraction_length": [
"0.8"
],
"retraction_minimum_travel": [
"1"
],
"retraction_speed": [
"30"
],
"travel_slope": [
"3"
],
"wipe": [
"1"
],
"wipe_distance": [
"1"
],
"z_hop": [
"0.4"
],
"z_hop_types": [
"Normal Lift"
],
"gcode_remap_x": "rev_x",
"gcode_remap_y": "pos_z",
"gcode_remap_z": "pos_y",
"printer_extruder_id": [
"1"
],
"belt_printer": "1",
"belt_slice_rotation": "x",
"belt_slice_rotation_angle": "45",
"belt_slice_rotation_global": "1",
"build_plate_tilt_x": "45",
"purge_in_prime_tower": "0",
"scan_first_layer": "0",
"auxiliary_fan": "0"
}

View File

@@ -0,0 +1,54 @@
{
"name": "IdeaFormer",
"version": "02.00.00.02",
"force_update": "0",
"description": "IdeaFormer belt printer configurations",
"machine_model_list": [
{
"name": "IdeaFormer IR3 V2",
"sub_path": "machine/IdeaFormer IR3 V2.json"
}
],
"process_list": [
{
"name": "fdm_process_common",
"sub_path": "process/fdm_process_common.json"
},
{
"name": "0.20mm Standard @IdeaFormer IR3 V2",
"sub_path": "process/0.20mm Standard @IdeaFormer IR3 V2.json"
}
],
"filament_list": [
{
"name": "Generic PLA @IdeaFormer IR3 V2",
"sub_path": "filament/Generic PLA @IdeaFormer IR3 V2.json"
},
{
"name": "eSUN PLA @IdeaFormer IR3 V2",
"sub_path": "filament/eSUN PLA @IdeaFormer IR3 V2.json"
},
{
"name": "Generic PETG @IdeaFormer IR3 V2",
"sub_path": "filament/Generic PETG @IdeaFormer IR3 V2.json"
}
],
"machine_list": [
{
"name": "fdm_machine_common",
"sub_path": "machine/fdm_machine_common.json"
},
{
"name": "fdm_klipper_common",
"sub_path": "machine/fdm_klipper_common.json"
},
{
"name": "fdm_belt_common",
"sub_path": "machine/fdm_belt_common.json"
},
{
"name": "IdeaFormer IR3 V2 0.4 nozzle",
"sub_path": "machine/IdeaFormer IR3 V2 0.4 nozzle.json"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

View File

@@ -0,0 +1,112 @@
{
"type": "filament",
"name": "Generic PETG @IdeaFormer IR3 V2",
"inherits": "Generic PETG @System",
"from": "system",
"instantiation": "true",
"compatible_printers": [
"IdeaFormer IR3 V2 0.4 nozzle"
],
"filament_type": [
"PETG"
],
"filament_vendor": [
"Generic"
],
"filament_settings_id": [
"Generic PETG @IdeaFormer IR3 V2"
],
"filament_diameter": [
"1.75"
],
"filament_density": [
"1.27"
],
"filament_flow_ratio": [
"0.95"
],
"filament_cost": [
"25"
],
"filament_max_volumetric_speed": [
"10"
],
"nozzle_temperature": [
"240"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature_range_low": [
"220"
],
"nozzle_temperature_range_high": [
"260"
],
"temperature_vitrification": [
"70"
],
"hot_plate_temp": [
"80"
],
"hot_plate_temp_initial_layer": [
"80"
],
"cool_plate_temp": [
"80"
],
"cool_plate_temp_initial_layer": [
"80"
],
"textured_plate_temp": [
"80"
],
"textured_plate_temp_initial_layer": [
"80"
],
"fan_min_speed": [
"40"
],
"fan_max_speed": [
"60"
],
"overhang_fan_threshold": [
"25%"
],
"overhang_fan_speed": [
"80"
],
"close_fan_the_first_x_layers": [
"3"
],
"full_fan_speed_layer": [
"8"
],
"slow_down_min_speed": [
"20"
],
"slow_down_layer_time": [
"4"
],
"fan_cooling_layer_time": [
"100"
],
"reduce_fan_stop_start_freq": [
"1"
],
"filament_retraction_length": [
"2"
],
"filament_retraction_speed": [
"40"
],
"filament_deretraction_speed": [
"40"
],
"filament_z_hop": [
"0.4"
],
"filament_start_gcode": [
"; Generic PETG @IdeaFormer IR3 V2 — belt PETG, bed 80C"
]
}

View File

@@ -0,0 +1,112 @@
{
"type": "filament",
"name": "Generic PLA @IdeaFormer IR3 V2",
"inherits": "Generic PLA @System",
"from": "system",
"instantiation": "true",
"compatible_printers": [
"IdeaFormer IR3 V2 0.4 nozzle"
],
"filament_type": [
"PLA"
],
"filament_vendor": [
"Generic"
],
"filament_settings_id": [
"Generic PLA @IdeaFormer IR3 V2"
],
"filament_diameter": [
"1.75"
],
"filament_density": [
"1.24"
],
"filament_flow_ratio": [
"0.98"
],
"filament_cost": [
"20"
],
"filament_max_volumetric_speed": [
"12"
],
"nozzle_temperature": [
"215"
],
"nozzle_temperature_initial_layer": [
"220"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"240"
],
"temperature_vitrification": [
"45"
],
"hot_plate_temp": [
"75"
],
"hot_plate_temp_initial_layer": [
"75"
],
"cool_plate_temp": [
"75"
],
"cool_plate_temp_initial_layer": [
"75"
],
"textured_plate_temp": [
"75"
],
"textured_plate_temp_initial_layer": [
"75"
],
"fan_min_speed": [
"100"
],
"fan_max_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"overhang_fan_speed": [
"100"
],
"close_fan_the_first_x_layers": [
"3"
],
"full_fan_speed_layer": [
"8"
],
"slow_down_min_speed": [
"20"
],
"slow_down_layer_time": [
"4"
],
"fan_cooling_layer_time": [
"100"
],
"reduce_fan_stop_start_freq": [
"1"
],
"filament_retraction_length": [
"1.5"
],
"filament_retraction_speed": [
"35"
],
"filament_deretraction_speed": [
"30"
],
"filament_z_hop": [
"0.4"
],
"filament_start_gcode": [
"; Generic PLA @IdeaFormer IR3 V2 — belt PLA, bed 75C"
]
}

View File

@@ -0,0 +1,34 @@
{
"type": "filament",
"name": "eSUN PLA @IdeaFormer IR3 V2",
"inherits": "Generic PLA @IdeaFormer IR3 V2",
"from": "system",
"instantiation": "true",
"compatible_printers": [
"IdeaFormer IR3 V2 0.4 nozzle"
],
"filament_type": [
"PLA"
],
"filament_vendor": [
"eSUN"
],
"filament_settings_id": [
"eSUN PLA @IdeaFormer IR3 V2"
],
"nozzle_temperature_initial_layer": [
"200"
],
"nozzle_temperature": [
"200"
],
"enable_pressure_advance": [
"1"
],
"pressure_advance": [
"0.12"
],
"filament_max_volumetric_speed": [
"20"
]
}

View File

@@ -0,0 +1,94 @@
{
"type": "machine",
"name": "IdeaFormer IR3 V2 0.4 nozzle",
"inherits": "fdm_belt_common",
"from": "system",
"setting_id": "GMIF001",
"instantiation": "true",
"printer_model": "IdeaFormer IR3 V2",
"printer_variant": "0.4",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"250x0",
"250x2000",
"0x2000"
],
"printable_height": "250",
"belt_printer_infinite_y": "1",
"thumbnails": [
"48x48/PNG",
"300x300/PNG"
],
"default_filament_profile": [
"Generic PLA @IdeaFormer IR3 V2"
],
"default_print_profile": "0.20mm Standard @IdeaFormer IR3 V2",
"use_relative_e_distances": "1",
"machine_max_acceleration_e": [
"5000"
],
"machine_max_acceleration_extruding": [
"5000"
],
"machine_max_acceleration_retracting": [
"1000"
],
"machine_max_acceleration_travel": [
"9000"
],
"machine_max_acceleration_x": [
"5000"
],
"machine_max_acceleration_y": [
"5000"
],
"machine_max_acceleration_z": [
"100"
],
"machine_max_jerk_e": [
"2.5"
],
"machine_max_jerk_x": [
"10"
],
"machine_max_jerk_y": [
"10"
],
"machine_max_jerk_z": [
"0.4"
],
"machine_max_speed_e": [
"60"
],
"machine_max_speed_x": [
"500"
],
"machine_max_speed_y": [
"500"
],
"machine_max_speed_z": [
"20"
],
"retraction_length": [
"2"
],
"retraction_speed": [
"40"
],
"deretraction_speed": [
"40"
],
"z_hop": [
"0.4"
],
"retract_lift_below": [
"300"
],
"machine_start_gcode": "; === IdeaFormer IR3 V2 Belt Printer Start ===\n; Axes: X=lateral, Y=gantry height (probe), Z=belt\nG90 ; absolute positioning\nM82 ; absolute extruder\nG21 ; millimeters\nG28 ; home all axes\nG1 Y20 F500 ; lift nozzle 20mm from belt\n; Bed + hotend temps come from the active filament profile. Belt PLA requires 75 C bed — use Generic/eSun PLA @IdeaFormer IR3 V2 filament presets to get it automatically.\nM140 S[hot_plate_temp_initial_layer] ; set bed temp\nM104 S[nozzle_temperature_initial_layer] ; hotend temp\nM109 S[nozzle_temperature_initial_layer] ; wait hotend\nM190 S[hot_plate_temp_initial_layer] ; wait bed\n; --- Purge blob ---\nG92 E0 ; zero extruder\nG1 Y.1 ; nozzle 0.1mm above belt\nG1 E15 F1000 ; purge 15mm blob\nG1 Z20 E25 F800 ; belt advance 20mm + extrude\nG1 E23 ; retract 2mm\nG28 Y ; re-probe belt surface\nG1 E25 ; de-retract\n; --- Prime lines (full 250mm bed width) ---\nFMS_on ; filament motion sensor\nG1 X250 E50 F2000 ; prime line 1\nG92 Z0 ; reset belt origin\nG1 Z.4 ; belt advance 0.4mm\nG1 X0 E75 ; prime line 2\nG1 F1000 ; default feedrate\nG92 E0 Z0 ; zero extruder + belt = print origin\n",
"machine_end_gcode": "; === IdeaFormer IR3 V2 Belt Printer End ===\nM400 ; wait for moves to finish\nM104 S0 ; heater off\nM140 S0 ; bed off\nG92 E0 ; zero extruder\nG1 E-5 F300 ; retract 5mm\nG4 P5000 ; wait for ooze\nG91 ; relative mode - keep every end move relative on a belt\nG1 Y20 F1000 ; raise gantry 20mm for clearance over the part\nG1 Z676 F3000 ; advance belt one full machine-depth to eject the part and clean the belt\nG90 ; back to absolute\nG28 X ; home X only - NEVER 'G28' all: that homes Z/belt and reverses the whole print back into the gantry\nFMS_off ; filament motion sensor off\nBED_MESH_CLEAR\nM84 ; disable motors\n",
"machine_pause_gcode": "PAUSE",
"layer_change_gcode": "G92 E0 ; belt: reset extruder at layer change (relative E)"
}

View File

@@ -0,0 +1,12 @@
{
"type": "machine_model",
"name": "IdeaFormer IR3 V2",
"model_id": "IdeaFormer_IR3_V2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "IdeaFormer",
"bed_model": "",
"bed_texture": "",
"hotend_model": "",
"default_materials": "Generic PLA @IdeaFormer IR3 V2;Generic PETG @IdeaFormer IR3 V2"
}

View File

@@ -0,0 +1,99 @@
{
"type": "machine",
"name": "fdm_belt_common",
"inherits": "fdm_klipper_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "klipper",
"single_extruder_multi_material": "0",
"default_filament_profile": [
"Generic PLA @System"
],
"default_print_profile": "0.20mm Standard @System",
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"deretraction_speed": [
"30"
],
"extruder_colour": [
"#FCE94F"
],
"extruder_offset": [
"0x0"
],
"long_retractions_when_cut": [
"0"
],
"nozzle_diameter": [
"0.4"
],
"retract_before_wipe": [
"70%"
],
"retract_length_toolchange": [
"2"
],
"retract_lift_above": [
"0"
],
"retract_lift_below": [
"0"
],
"retract_lift_enforce": [
"All Surfaces"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retract_when_changing_layer": [
"1"
],
"retraction_distances_when_cut": [
"18"
],
"retraction_length": [
"0.8"
],
"retraction_minimum_travel": [
"1"
],
"retraction_speed": [
"30"
],
"travel_slope": [
"3"
],
"wipe": [
"1"
],
"wipe_distance": [
"1"
],
"z_hop": [
"0.4"
],
"z_hop_types": [
"Normal Lift"
],
"gcode_remap_x": "rev_x",
"gcode_remap_y": "pos_z",
"gcode_remap_z": "pos_y",
"printer_extruder_id": [
"1"
],
"belt_printer": "1",
"belt_slice_rotation": "x",
"belt_slice_rotation_angle": "45",
"belt_slice_rotation_global": "1",
"build_plate_tilt_x": "45",
"purge_in_prime_tower": "0",
"scan_first_layer": "0",
"auxiliary_fan": "0"
}

View File

@@ -0,0 +1,141 @@
{
"type": "machine",
"name": "fdm_klipper_common",
"inherits": "fdm_machine_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "klipper",
"machine_max_acceleration_e": [
"5000",
"5000"
],
"machine_max_acceleration_extruding": [
"20000",
"20000"
],
"machine_max_acceleration_retracting": [
"5000",
"5000"
],
"machine_max_acceleration_travel": [
"20000",
"20000"
],
"machine_max_acceleration_x": [
"20000",
"20000"
],
"machine_max_acceleration_y": [
"20000",
"20000"
],
"machine_max_acceleration_z": [
"500",
"200"
],
"machine_max_speed_e": [
"25",
"25"
],
"machine_max_speed_x": [
"500",
"200"
],
"machine_max_speed_y": [
"500",
"200"
],
"machine_max_speed_z": [
"12",
"12"
],
"machine_max_jerk_e": [
"2.5",
"2.5"
],
"machine_max_jerk_x": [
"9",
"9"
],
"machine_max_jerk_y": [
"9",
"9"
],
"machine_max_jerk_z": [
"0.2",
"0.4"
],
"machine_min_extruding_rate": [
"0",
"0"
],
"machine_min_travel_rate": [
"0",
"0"
],
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"printable_height": "250",
"extruder_clearance_radius": "65",
"extruder_clearance_height_to_rod": "36",
"extruder_clearance_height_to_lid": "140",
"printer_settings_id": "",
"printer_technology": "FFF",
"printer_variant": "0.4",
"retraction_minimum_travel": [
"1"
],
"retract_before_wipe": [
"70%"
],
"retract_when_changing_layer": [
"1"
],
"retraction_length": [
"0.8"
],
"retract_length_toolchange": [
"2"
],
"z_hop": [
"0.4"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retraction_speed": [
"30"
],
"deretraction_speed": [
"30"
],
"z_hop_types": "Normal Lift",
"silent_mode": "0",
"single_extruder_multi_material": "1",
"change_filament_gcode": "",
"wipe": [
"1"
],
"default_filament_profile": [
"Generic PLA @System"
],
"default_print_profile": "0.20mm Standard @MyKlipper",
"bed_exclude_area": [
"0x0"
],
"machine_start_gcode": "M190 S[bed_temperature_initial_layer_single]\nM109 S[nozzle_temperature_initial_layer]\nPRINT_START EXTRUDER=[nozzle_temperature_initial_layer] BED=[bed_temperature_initial_layer_single]\n",
"machine_end_gcode": "PRINT_END",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n",
"machine_pause_gcode": "PAUSE",
"scan_first_layer": "0",
"nozzle_type": "undefine",
"auxiliary_fan": "0"
}

View File

@@ -0,0 +1,119 @@
{
"type": "machine",
"name": "fdm_machine_common",
"from": "system",
"instantiation": "false",
"printer_technology": "FFF",
"deretraction_speed": [
"40"
],
"extruder_colour": [
"#FCE94F"
],
"extruder_offset": [
"0x0"
],
"gcode_flavor": "marlin",
"silent_mode": "0",
"machine_max_acceleration_e": [
"5000"
],
"machine_max_acceleration_extruding": [
"10000"
],
"machine_max_acceleration_retracting": [
"1000"
],
"machine_max_acceleration_x": [
"10000"
],
"machine_max_acceleration_y": [
"10000"
],
"machine_max_acceleration_z": [
"500"
],
"machine_max_speed_e": [
"60"
],
"machine_max_speed_x": [
"500"
],
"machine_max_speed_y": [
"500"
],
"machine_max_speed_z": [
"10"
],
"machine_max_jerk_e": [
"5"
],
"machine_max_jerk_x": [
"8"
],
"machine_max_jerk_y": [
"8"
],
"machine_max_jerk_z": [
"0.4"
],
"machine_min_extruding_rate": [
"0"
],
"machine_min_travel_rate": [
"0"
],
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"printable_height": "250",
"extruder_clearance_radius": "65",
"extruder_clearance_height_to_rod": "36",
"extruder_clearance_height_to_lid": "140",
"nozzle_diameter": [
"0.4"
],
"printer_settings_id": "",
"printer_variant": "0.4",
"retraction_minimum_travel": [
"2"
],
"retract_before_wipe": [
"70%"
],
"retract_when_changing_layer": [
"1"
],
"retraction_length": [
"1"
],
"retract_length_toolchange": [
"1"
],
"z_hop": [
"0"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retraction_speed": [
"60"
],
"single_extruder_multi_material": "1",
"change_filament_gcode": "",
"wipe": [
"1"
],
"default_print_profile": "",
"machine_start_gcode": "G0 Z20 F9000\nG92 E0; G1 E-10 F1200\nG28\nM970 Q1 A10 B10 C130 K0\nM970 Q1 A10 B131 C250 K1\nM974 Q1 S1 P0\nM970 Q0 A10 B10 C130 H20 K0\nM970 Q0 A10 B131 C250 K1\nM974 Q0 S1 P0\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nG29 ;Home\nG90;\nG92 E0 ;Reset Extruder \nG1 Z2.0 F3000 ;Move Z Axis up \nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nM109 S205;\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder \nG1 X110 Y110 Z2.0 F3000 ;Move Z Axis up",
"machine_end_gcode": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-4.0 F3600; retract \nG91\nG1 Z3;\nM104 S0 ; turn off hotend\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nG90 \nG0 X110 Y200 F3600 \nprint_end",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n",
"machine_pause_gcode": "M601"
}

View File

@@ -0,0 +1,22 @@
{
"type": "process",
"name": "0.20mm Standard @IdeaFormer IR3 V2",
"inherits": "fdm_process_common",
"from": "system",
"instantiation": "true",
"layer_height": "0.2",
"initial_layer_print_height": "0.2",
"initial_layer_line_width": "0.42",
"wall_loops": "2",
"reduce_infill_retraction": "1",
"detect_overhang_wall": "1",
"skirt_loops": "0",
"skirt_distance": "0",
"sparse_infill_pattern": "grid",
"sparse_infill_speed": "200",
"support_base_pattern": "rectilinear",
"support_interface_pattern": "rectilinear",
"compatible_printers": [
"IdeaFormer IR3 V2 0.4 nozzle"
]
}

View File

@@ -0,0 +1,108 @@
{
"type": "process",
"name": "fdm_process_common",
"from": "system",
"instantiation": "false",
"adaptive_layer_height": "0",
"reduce_crossing_wall": "0",
"max_travel_detour_distance": "0",
"bottom_surface_pattern": "monotonic",
"bottom_shell_thickness": "0",
"bridge_speed": "50",
"brim_width": "5",
"brim_object_gap": "0.1",
"compatible_printers": [],
"compatible_printers_condition": "",
"print_sequence": "by layer",
"default_acceleration": "1000",
"initial_layer_acceleration": "500",
"top_surface_acceleration": "1000",
"travel_acceleration": "1000",
"inner_wall_acceleration": "1000",
"outer_wall_acceleration": "700",
"bridge_no_support": "0",
"draft_shield": "disabled",
"elefant_foot_compensation": "0",
"enable_arc_fitting": "0",
"wall_infill_order": "inner wall/outer wall/infill",
"infill_direction": "45",
"sparse_infill_density": "15%",
"sparse_infill_pattern": "crosshatch",
"initial_layer_print_height": "0.2",
"infill_combination": "0",
"infill_wall_overlap": "25%",
"interface_shells": "0",
"ironing_flow": "10%",
"ironing_spacing": "0.15",
"ironing_speed": "30",
"ironing_type": "no ironing",
"reduce_infill_retraction": "1",
"filename_format": "{input_filename_base}_{layer_height}mm_{filament_type[initial_tool]}_{printer_model}_{print_time}.gcode",
"detect_overhang_wall": "1",
"slowdown_for_curled_perimeters": "1",
"overhang_1_4_speed": "0",
"overhang_2_4_speed": "50",
"overhang_3_4_speed": "30",
"overhang_4_4_speed": "10",
"line_width": "110%",
"inner_wall_line_width": "110%",
"outer_wall_line_width": "100%",
"top_surface_line_width": "93.75%",
"sparse_infill_line_width": "110%",
"initial_layer_line_width": "120%",
"internal_solid_infill_line_width": "120%",
"support_line_width": "96%",
"wall_loops": "3",
"print_settings_id": "",
"raft_layers": "0",
"seam_position": "aligned",
"skirt_distance": "2",
"skirt_height": "3",
"min_skirt_length": "4",
"skirt_loops": "0",
"minimum_sparse_infill_area": "15",
"spiral_mode": "0",
"standby_temperature_delta": "-5",
"enable_support": "0",
"resolution": "0.012",
"support_type": "normal(auto)",
"support_on_build_plate_only": "0",
"support_top_z_distance": "0.2",
"support_bottom_z_distance": "0.2",
"support_filament": "0",
"support_interface_loop_pattern": "0",
"support_interface_filament": "0",
"support_interface_top_layers": "2",
"support_interface_bottom_layers": "2",
"support_interface_spacing": "0.5",
"support_interface_speed": "80",
"support_base_pattern": "default",
"support_base_pattern_spacing": "2.5",
"support_speed": "150",
"support_threshold_angle": "30",
"support_object_xy_distance": "0.35",
"tree_support_branch_angle": "30",
"tree_support_wall_count": "0",
"tree_support_with_infill": "0",
"detect_thin_wall": "0",
"top_surface_pattern": "monotonicline",
"top_shell_thickness": "0.8",
"enable_prime_tower": "1",
"wipe_tower_no_sparse_layers": "0",
"prime_tower_width": "60",
"xy_hole_compensation": "0",
"xy_contour_compensation": "0",
"layer_height": "0.2",
"bottom_shell_layers": "3",
"top_shell_layers": "4",
"bridge_flow": "1",
"initial_layer_speed": "45",
"initial_layer_infill_speed": "45",
"outer_wall_speed": "45",
"inner_wall_speed": "80",
"sparse_infill_speed": "150",
"internal_solid_infill_speed": "150",
"top_surface_speed": "50",
"gap_infill_speed": "30",
"travel_speed": "200"
}

View File

@@ -0,0 +1,54 @@
{
"name": "Printcepts",
"version": "01.00.00.00",
"force_update": "0",
"description": "Printcepts belt printer configurations",
"machine_model_list": [
{
"name": "BabyBelt Pro",
"sub_path": "machine/BabyBelt Pro.json"
}
],
"process_list": [
{
"name": "fdm_process_common",
"sub_path": "process/fdm_process_common.json"
},
{
"name": "0.20mm Standard @BabyBelt Pro",
"sub_path": "process/0.20mm Standard @BabyBelt Pro.json"
}
],
"filament_list": [
{
"name": "Generic PLA @BabyBelt Pro",
"sub_path": "filament/Generic PLA @BabyBelt Pro.json"
},
{
"name": "eSUN PLA @BabyBelt Pro",
"sub_path": "filament/eSUN PLA @BabyBelt Pro.json"
},
{
"name": "Generic PETG @BabyBelt Pro",
"sub_path": "filament/Generic PETG @BabyBelt Pro.json"
}
],
"machine_list": [
{
"name": "fdm_machine_common",
"sub_path": "machine/fdm_machine_common.json"
},
{
"name": "fdm_klipper_common",
"sub_path": "machine/fdm_klipper_common.json"
},
{
"name": "fdm_belt_common",
"sub_path": "machine/fdm_belt_common.json"
},
{
"name": "BabyBelt Pro 0.4 nozzle",
"sub_path": "machine/BabyBelt Pro 0.4 nozzle.json"
}
]
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95.0mm" height="500.0mm" viewBox="0 0 95.0 500.0" preserveAspectRatio="xMidYMid meet">
<!-- Printcepts BabyBelt Pro bed texture: 95 x 500 mm belt plate. -->
<!-- Transparent plate; green (#195F30) BabyBelt Pro logo centered along X, near the bottom edge. -->
<rect x="0" y="0" width="95.0" height="500.0" fill="none"/>
<g transform="translate(14.2500,436.3488) scale(0.067538)">
<g transform="translate(-11.000000,692.938562) scale(0.100000,-0.100000)"
fill="#195F30" stroke="none">
<path d="M1963 5604 l-1423 -1324 0 -2050 0 -2050 443 0 c244 0 741 3 1105 7
l662 6 0 746 c-1 575 -4 768 -14 841 -47 324 -179 486 -473 581 -40 12 -73 26
-73 30 0 4 32 17 72 29 212 64 333 166 378 320 35 121 38 191 32 868 l-5 662
-629 0 c-395 0 -628 4 -628 10 0 5 635 601 1410 1325 776 724 1410 1318 1410
1321 0 2 -190 4 -422 3 l-423 0 -1422 -1325z m-334 -2029 c143 -16 174 -96
173 -446 -2 -411 -24 -458 -224 -462 l-93 -2 -3 450 c-1 248 0 456 3 463 3 9
18 12 47 8 24 -3 67 -8 97 -11z m-4 -1556 c160 -29 173 -62 182 -469 9 -455
-14 -593 -108 -641 -39 -19 -193 -44 -210 -33 -10 6 -13 1147 -3 1157 6 6 45
2 139 -14z"/>
<path d="M3464 5979 c-142 -132 -263 -245 -268 -250 -6 -5 69 -9 190 -9 l199
1 268 249 267 250 -198 0 -198 0 -260 -241z"/>
<path d="M3650 5649 c-135 -126 -254 -238 -265 -249 -19 -20 -18 -20 177 -20
l197 0 228 211 c125 116 246 229 268 250 l40 39 -200 -1 -200 0 -245 -230z"/>
<path d="M2537 5089 c-101 -24 -204 -105 -251 -197 -96 -190 -19 -420 172
-514 l67 -33 2670 0 2670 0 57 27 c74 34 146 107 184 183 43 88 43 230 0 322
-35 76 -113 153 -193 191 l-58 27 -2640 2 c-1513 0 -2656 -3 -2678 -8z m5063
-77 c-57 -37 -118 -111 -140 -168 -31 -82 -25 -206 12 -279 26 -49 93 -121
133 -143 15 -8 -640 -11 -2410 -11 l-2430 0 30 21 c200 146 201 425 1 569
l-39 29 2434 -1 c2263 0 2432 -1 2409 -17z m-4890 -43 c270 -122 185 -526
-109 -522 -257 2 -370 324 -170 485 74 60 194 76 279 37z m5201 -12 c94 -55
140 -135 140 -242 0 -285 -393 -374 -517 -117 -26 54 -30 162 -9 219 28 74 97
139 173 164 53 17 166 4 213 -24z"/>
<path d="M2917 3973 c-4 -174 -7 -550 -7 -835 l0 -518 326 0 326 0 -7 150 -7
150 110 0 110 0 11 -32 c5 -18 26 -86 46 -150 l36 -118 325 0 c179 0 323 4
320 9 -3 4 -155 374 -337 822 -182 448 -333 820 -336 827 -4 9 -105 12 -457
12 l-453 0 -6 -317z m773 -745 c0 -5 -47 -8 -104 -8 l-103 0 -7 92 c-3 50 -6
202 -5 337 l1 246 109 -330 c60 -181 109 -333 109 -337z"/>
<path d="M4680 3455 l0 -835 448 0 c693 1 885 16 985 80 99 63 126 132 134
340 12 327 -44 405 -342 476 -28 7 -27 8 25 19 199 42 255 95 267 248 11 146
-32 285 -110 353 -145 126 -329 153 -1049 154 l-358 0 0 -835z m846 520 c36
-23 44 -54 44 -162 0 -152 -29 -183 -170 -183 l-40 0 0 186 0 187 71 -6 c39
-3 82 -13 95 -22z m4 -625 c33 -18 40 -52 40 -208 0 -200 -9 -214 -143 -228
l-67 -7 0 233 0 233 74 -6 c41 -3 84 -10 96 -17z"/>
<path d="M6150 4286 c0 -3 131 -242 290 -531 l290 -526 0 -304 0 -305 385 0
385 0 0 299 0 299 305 533 305 534 -377 3 c-207 1 -381 -2 -385 -6 -16 -16
-110 -258 -172 -444 l-62 -187 -18 77 c-18 75 -139 450 -171 525 l-15 37 -380
0 c-209 0 -380 -2 -380 -4z"/>
<path d="M2910 1355 l0 -1185 830 0 830 0 0 240 0 240 -350 0 -350 0 0 255 0
255 300 0 300 0 0 230 0 230 -300 0 -300 0 0 220 0 220 320 0 320 0 0 240 0
240 -800 0 -800 0 0 -1185z"/>
<path d="M4680 1355 l0 -1185 775 0 775 0 0 240 0 240 -295 0 -295 0 0 945 0
945 -480 0 -480 0 0 -1185z"/>
<path d="M5800 2300 l0 -240 280 0 280 0 0 -945 0 -945 480 0 480 0 0 945 0
945 285 0 285 0 0 240 0 240 -1045 0 -1045 0 0 -240z"/>
<path d="M8032 1358 l-2 -1188 1008 1 c621 1 971 5 912 10 -309 27 -631 139
-885 306 -593 391 -984 1122 -1025 1918 -4 77 -8 -394 -8 -1047z"/>
<path d="M7441 1934 c-43 -36 -59 -70 -70 -148 -18 -124 16 -252 76 -291 32
-21 226 -33 328 -20 114 14 161 97 153 269 -5 96 -24 151 -68 191 -20 18 -39
20 -205 23 l-182 3 -32 -27z m389 -199 c7 -8 10 -22 6 -30 -4 -13 -34 -15
-186 -15 -189 0 -202 3 -186 45 8 22 348 22 366 0z"/>
<path d="M7450 1267 c-14 -6 -35 -32 -47 -57 -21 -41 -23 -58 -23 -222 l0
-178 270 0 270 0 0 105 0 105 -121 0 -120 0 3 28 3 27 118 3 117 3 0 99 0 100
-113 0 c-121 0 -138 -7 -162 -65 -8 -19 -9 -19 -12 2 -10 55 -116 84 -183 50z
m134 -203 c15 -38 8 -44 -54 -44 -62 0 -69 6 -54 44 9 23 99 23 108 0z"/>
<path d="M466 1193 l-29 -43 -163 0 -164 0 0 -235 0 -235 165 0 165 0 27 -42
28 -42 3 163 c1 89 1 233 0 319 l-3 157 -29 -42z"/>
<path d="M7443 620 c-48 -20 -58 -60 -61 -262 l-4 -188 271 0 271 0 0 110 0
110 -110 0 -110 0 0 70 c0 76 -21 145 -51 160 -22 12 -176 12 -206 0z m161
-186 c15 -39 8 -44 -64 -44 -72 0 -79 5 -64 44 9 23 119 23 128 0z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -0,0 +1,112 @@
{
"type": "filament",
"name": "Generic PETG @BabyBelt Pro",
"inherits": "Generic PETG @System",
"from": "system",
"instantiation": "true",
"compatible_printers": [
"BabyBelt Pro 0.4 nozzle"
],
"filament_type": [
"PETG"
],
"filament_vendor": [
"Generic"
],
"filament_settings_id": [
"Generic PETG @BabyBelt Pro"
],
"filament_diameter": [
"1.75"
],
"filament_density": [
"1.27"
],
"filament_flow_ratio": [
"0.95"
],
"filament_cost": [
"25"
],
"filament_max_volumetric_speed": [
"10"
],
"nozzle_temperature": [
"240"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature_range_low": [
"220"
],
"nozzle_temperature_range_high": [
"260"
],
"temperature_vitrification": [
"70"
],
"hot_plate_temp": [
"80"
],
"hot_plate_temp_initial_layer": [
"80"
],
"cool_plate_temp": [
"80"
],
"cool_plate_temp_initial_layer": [
"80"
],
"textured_plate_temp": [
"80"
],
"textured_plate_temp_initial_layer": [
"80"
],
"fan_min_speed": [
"40"
],
"fan_max_speed": [
"60"
],
"overhang_fan_threshold": [
"25%"
],
"overhang_fan_speed": [
"80"
],
"close_fan_the_first_x_layers": [
"3"
],
"full_fan_speed_layer": [
"8"
],
"slow_down_min_speed": [
"20"
],
"slow_down_layer_time": [
"4"
],
"fan_cooling_layer_time": [
"100"
],
"reduce_fan_stop_start_freq": [
"1"
],
"filament_retraction_length": [
"2"
],
"filament_retraction_speed": [
"40"
],
"filament_deretraction_speed": [
"40"
],
"filament_z_hop": [
"0.4"
],
"filament_start_gcode": [
"; Generic PETG @BabyBelt Pro — belt PETG, bed 80C"
]
}

View File

@@ -0,0 +1,112 @@
{
"type": "filament",
"name": "Generic PLA @BabyBelt Pro",
"inherits": "Generic PLA @System",
"from": "system",
"instantiation": "true",
"compatible_printers": [
"BabyBelt Pro 0.4 nozzle"
],
"filament_type": [
"PLA"
],
"filament_vendor": [
"Generic"
],
"filament_settings_id": [
"Generic PLA @BabyBelt Pro"
],
"filament_diameter": [
"1.75"
],
"filament_density": [
"1.24"
],
"filament_flow_ratio": [
"0.98"
],
"filament_cost": [
"20"
],
"filament_max_volumetric_speed": [
"12"
],
"nozzle_temperature": [
"215"
],
"nozzle_temperature_initial_layer": [
"220"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"240"
],
"temperature_vitrification": [
"45"
],
"hot_plate_temp": [
"75"
],
"hot_plate_temp_initial_layer": [
"75"
],
"cool_plate_temp": [
"75"
],
"cool_plate_temp_initial_layer": [
"75"
],
"textured_plate_temp": [
"75"
],
"textured_plate_temp_initial_layer": [
"75"
],
"fan_min_speed": [
"100"
],
"fan_max_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"overhang_fan_speed": [
"100"
],
"close_fan_the_first_x_layers": [
"3"
],
"full_fan_speed_layer": [
"8"
],
"slow_down_min_speed": [
"20"
],
"slow_down_layer_time": [
"4"
],
"fan_cooling_layer_time": [
"100"
],
"reduce_fan_stop_start_freq": [
"1"
],
"filament_retraction_length": [
"1.5"
],
"filament_retraction_speed": [
"35"
],
"filament_deretraction_speed": [
"30"
],
"filament_z_hop": [
"0.4"
],
"filament_start_gcode": [
"; Generic PLA @BabyBelt Pro — belt PLA, bed 75C"
]
}

View File

@@ -0,0 +1,34 @@
{
"type": "filament",
"name": "eSUN PLA @BabyBelt Pro",
"inherits": "Generic PLA @BabyBelt Pro",
"from": "system",
"instantiation": "true",
"compatible_printers": [
"BabyBelt Pro 0.4 nozzle"
],
"filament_type": [
"PLA"
],
"filament_vendor": [
"eSUN"
],
"filament_settings_id": [
"eSUN PLA @BabyBelt Pro"
],
"nozzle_temperature_initial_layer": [
"200"
],
"nozzle_temperature": [
"200"
],
"enable_pressure_advance": [
"1"
],
"pressure_advance": [
"0.12"
],
"filament_max_volumetric_speed": [
"20"
]
}

View File

@@ -0,0 +1,87 @@
{
"type": "machine",
"name": "BabyBelt Pro 0.4 nozzle",
"inherits": "fdm_belt_common",
"from": "system",
"setting_id": "GMPC0BBP01",
"instantiation": "true",
"printer_model": "BabyBelt Pro",
"printer_variant": "0.4",
"nozzle_diameter": [
"0.4"
],
"default_filament_profile": [
"Generic PLA @BabyBelt Pro"
],
"default_print_profile": "0.20mm Standard @BabyBelt Pro",
"printable_area": [
"0x0",
"95x0",
"95x500",
"0x500"
],
"printable_height": "100",
"best_object_pos": "0.5,0.05",
"nozzle_type": [
"hardened_steel"
],
"printer_extruder_id": [
"1"
],
"printer_extruder_variant": [
"Direct Drive Standard"
],
"thumbnails": [
"48x48/PNG",
"300x300/PNG"
],
"machine_max_acceleration_e": [
"500",
"5000"
],
"machine_max_acceleration_extruding": [
"500",
"20000"
],
"machine_max_acceleration_retracting": [
"500",
"5000"
],
"machine_max_acceleration_x": [
"500",
"20000"
],
"machine_max_acceleration_y": [
"500",
"20000"
],
"machine_max_junction_deviation": [
"0.01"
],
"machine_max_speed_x": [
"50",
"200"
],
"machine_max_speed_y": [
"50",
"200"
],
"machine_max_speed_z": [
"5",
"12"
],
"retraction_length": [
"1.5"
],
"retraction_speed": [
"20"
],
"deretraction_speed": [
"25"
],
"retract_lift_enforce": [
"Top and Bottom"
],
"support_chamber_temp_control": "0",
"machine_start_gcode": ";Start GCode\nPRINT_START ANGLE=[belt_slice_rotation_angle] EXTRUDER=[nozzle_temperature_initial_layer] BED=[hot_plate_temp_initial_layer] MATERIAL=[filament_type]\n"
}

View File

@@ -0,0 +1,12 @@
{
"type": "machine_model",
"name": "BabyBelt Pro",
"model_id": "Printcepts_BabyBelt_Pro",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Printcepts",
"bed_model": "",
"bed_texture": "BabyBelt Pro_bed_texture.svg",
"hotend_model": "",
"default_materials": "Generic PLA @BabyBelt Pro;Generic PETG @BabyBelt Pro"
}

View File

@@ -0,0 +1,99 @@
{
"type": "machine",
"name": "fdm_belt_common",
"inherits": "fdm_klipper_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "klipper",
"single_extruder_multi_material": "0",
"default_filament_profile": [
"Generic PLA @System"
],
"default_print_profile": "0.20mm Standard @System",
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"deretraction_speed": [
"30"
],
"extruder_colour": [
"#FCE94F"
],
"extruder_offset": [
"0x0"
],
"long_retractions_when_cut": [
"0"
],
"nozzle_diameter": [
"0.4"
],
"retract_before_wipe": [
"70%"
],
"retract_length_toolchange": [
"2"
],
"retract_lift_above": [
"0"
],
"retract_lift_below": [
"0"
],
"retract_lift_enforce": [
"All Surfaces"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retract_when_changing_layer": [
"1"
],
"retraction_distances_when_cut": [
"18"
],
"retraction_length": [
"0.8"
],
"retraction_minimum_travel": [
"1"
],
"retraction_speed": [
"30"
],
"travel_slope": [
"3"
],
"wipe": [
"1"
],
"wipe_distance": [
"1"
],
"z_hop": [
"0.4"
],
"z_hop_types": [
"Normal Lift"
],
"gcode_remap_x": "rev_x",
"gcode_remap_y": "pos_z",
"gcode_remap_z": "pos_y",
"printer_extruder_id": [
"1"
],
"belt_printer": "1",
"belt_slice_rotation": "x",
"belt_slice_rotation_angle": "45",
"belt_slice_rotation_global": "1",
"build_plate_tilt_x": "45",
"purge_in_prime_tower": "0",
"scan_first_layer": "0",
"auxiliary_fan": "0"
}

View File

@@ -0,0 +1,141 @@
{
"type": "machine",
"name": "fdm_klipper_common",
"inherits": "fdm_machine_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "klipper",
"machine_max_acceleration_e": [
"5000",
"5000"
],
"machine_max_acceleration_extruding": [
"20000",
"20000"
],
"machine_max_acceleration_retracting": [
"5000",
"5000"
],
"machine_max_acceleration_travel": [
"20000",
"20000"
],
"machine_max_acceleration_x": [
"20000",
"20000"
],
"machine_max_acceleration_y": [
"20000",
"20000"
],
"machine_max_acceleration_z": [
"500",
"200"
],
"machine_max_speed_e": [
"25",
"25"
],
"machine_max_speed_x": [
"500",
"200"
],
"machine_max_speed_y": [
"500",
"200"
],
"machine_max_speed_z": [
"12",
"12"
],
"machine_max_jerk_e": [
"2.5",
"2.5"
],
"machine_max_jerk_x": [
"9",
"9"
],
"machine_max_jerk_y": [
"9",
"9"
],
"machine_max_jerk_z": [
"0.2",
"0.4"
],
"machine_min_extruding_rate": [
"0",
"0"
],
"machine_min_travel_rate": [
"0",
"0"
],
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"printable_height": "250",
"extruder_clearance_radius": "65",
"extruder_clearance_height_to_rod": "36",
"extruder_clearance_height_to_lid": "140",
"printer_settings_id": "",
"printer_technology": "FFF",
"printer_variant": "0.4",
"retraction_minimum_travel": [
"1"
],
"retract_before_wipe": [
"70%"
],
"retract_when_changing_layer": [
"1"
],
"retraction_length": [
"0.8"
],
"retract_length_toolchange": [
"2"
],
"z_hop": [
"0.4"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retraction_speed": [
"30"
],
"deretraction_speed": [
"30"
],
"z_hop_types": "Normal Lift",
"silent_mode": "0",
"single_extruder_multi_material": "1",
"change_filament_gcode": "",
"wipe": [
"1"
],
"default_filament_profile": [
"Generic PLA @System"
],
"default_print_profile": "0.20mm Standard @MyKlipper",
"bed_exclude_area": [
"0x0"
],
"machine_start_gcode": "M190 S[bed_temperature_initial_layer_single]\nM109 S[nozzle_temperature_initial_layer]\nPRINT_START EXTRUDER=[nozzle_temperature_initial_layer] BED=[bed_temperature_initial_layer_single]\n",
"machine_end_gcode": "PRINT_END",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n",
"machine_pause_gcode": "PAUSE",
"scan_first_layer": "0",
"nozzle_type": "undefine",
"auxiliary_fan": "0"
}

View File

@@ -0,0 +1,119 @@
{
"type": "machine",
"name": "fdm_machine_common",
"from": "system",
"instantiation": "false",
"printer_technology": "FFF",
"deretraction_speed": [
"40"
],
"extruder_colour": [
"#FCE94F"
],
"extruder_offset": [
"0x0"
],
"gcode_flavor": "marlin",
"silent_mode": "0",
"machine_max_acceleration_e": [
"5000"
],
"machine_max_acceleration_extruding": [
"10000"
],
"machine_max_acceleration_retracting": [
"1000"
],
"machine_max_acceleration_x": [
"10000"
],
"machine_max_acceleration_y": [
"10000"
],
"machine_max_acceleration_z": [
"500"
],
"machine_max_speed_e": [
"60"
],
"machine_max_speed_x": [
"500"
],
"machine_max_speed_y": [
"500"
],
"machine_max_speed_z": [
"10"
],
"machine_max_jerk_e": [
"5"
],
"machine_max_jerk_x": [
"8"
],
"machine_max_jerk_y": [
"8"
],
"machine_max_jerk_z": [
"0.4"
],
"machine_min_extruding_rate": [
"0"
],
"machine_min_travel_rate": [
"0"
],
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"printable_height": "250",
"extruder_clearance_radius": "65",
"extruder_clearance_height_to_rod": "36",
"extruder_clearance_height_to_lid": "140",
"nozzle_diameter": [
"0.4"
],
"printer_settings_id": "",
"printer_variant": "0.4",
"retraction_minimum_travel": [
"2"
],
"retract_before_wipe": [
"70%"
],
"retract_when_changing_layer": [
"1"
],
"retraction_length": [
"1"
],
"retract_length_toolchange": [
"1"
],
"z_hop": [
"0"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retraction_speed": [
"60"
],
"single_extruder_multi_material": "1",
"change_filament_gcode": "",
"wipe": [
"1"
],
"default_print_profile": "",
"machine_start_gcode": "G0 Z20 F9000\nG92 E0; G1 E-10 F1200\nG28\nM970 Q1 A10 B10 C130 K0\nM970 Q1 A10 B131 C250 K1\nM974 Q1 S1 P0\nM970 Q0 A10 B10 C130 H20 K0\nM970 Q0 A10 B131 C250 K1\nM974 Q0 S1 P0\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nG29 ;Home\nG90;\nG92 E0 ;Reset Extruder \nG1 Z2.0 F3000 ;Move Z Axis up \nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nM109 S205;\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder \nG1 X110 Y110 Z2.0 F3000 ;Move Z Axis up",
"machine_end_gcode": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-4.0 F3600; retract \nG91\nG1 Z3;\nM104 S0 ; turn off hotend\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nG90 \nG0 X110 Y200 F3600 \nprint_end",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n",
"machine_pause_gcode": "M601"
}

View File

@@ -0,0 +1,22 @@
{
"type": "process",
"name": "0.20mm Standard @BabyBelt Pro",
"inherits": "fdm_process_common",
"from": "system",
"instantiation": "true",
"layer_height": "0.2",
"initial_layer_print_height": "0.2",
"initial_layer_line_width": "0.42",
"wall_loops": "2",
"reduce_infill_retraction": "1",
"detect_overhang_wall": "1",
"skirt_loops": "0",
"skirt_distance": "0",
"sparse_infill_pattern": "grid",
"sparse_infill_speed": "200",
"support_base_pattern": "rectilinear",
"support_interface_pattern": "rectilinear",
"compatible_printers": [
"BabyBelt Pro 0.4 nozzle"
]
}

View File

@@ -0,0 +1,108 @@
{
"type": "process",
"name": "fdm_process_common",
"from": "system",
"instantiation": "false",
"adaptive_layer_height": "0",
"reduce_crossing_wall": "0",
"max_travel_detour_distance": "0",
"bottom_surface_pattern": "monotonic",
"bottom_shell_thickness": "0",
"bridge_speed": "50",
"brim_width": "5",
"brim_object_gap": "0.1",
"compatible_printers": [],
"compatible_printers_condition": "",
"print_sequence": "by layer",
"default_acceleration": "1000",
"initial_layer_acceleration": "500",
"top_surface_acceleration": "1000",
"travel_acceleration": "1000",
"inner_wall_acceleration": "1000",
"outer_wall_acceleration": "700",
"bridge_no_support": "0",
"draft_shield": "disabled",
"elefant_foot_compensation": "0",
"enable_arc_fitting": "0",
"wall_infill_order": "inner wall/outer wall/infill",
"infill_direction": "45",
"sparse_infill_density": "15%",
"sparse_infill_pattern": "crosshatch",
"initial_layer_print_height": "0.2",
"infill_combination": "0",
"infill_wall_overlap": "25%",
"interface_shells": "0",
"ironing_flow": "10%",
"ironing_spacing": "0.15",
"ironing_speed": "30",
"ironing_type": "no ironing",
"reduce_infill_retraction": "1",
"filename_format": "{input_filename_base}_{layer_height}mm_{filament_type[initial_tool]}_{printer_model}_{print_time}.gcode",
"detect_overhang_wall": "1",
"slowdown_for_curled_perimeters": "1",
"overhang_1_4_speed": "0",
"overhang_2_4_speed": "50",
"overhang_3_4_speed": "30",
"overhang_4_4_speed": "10",
"line_width": "110%",
"inner_wall_line_width": "110%",
"outer_wall_line_width": "100%",
"top_surface_line_width": "93.75%",
"sparse_infill_line_width": "110%",
"initial_layer_line_width": "120%",
"internal_solid_infill_line_width": "120%",
"support_line_width": "96%",
"wall_loops": "3",
"print_settings_id": "",
"raft_layers": "0",
"seam_position": "aligned",
"skirt_distance": "2",
"skirt_height": "3",
"min_skirt_length": "4",
"skirt_loops": "0",
"minimum_sparse_infill_area": "15",
"spiral_mode": "0",
"standby_temperature_delta": "-5",
"enable_support": "0",
"resolution": "0.012",
"support_type": "normal(auto)",
"support_on_build_plate_only": "0",
"support_top_z_distance": "0.2",
"support_bottom_z_distance": "0.2",
"support_filament": "0",
"support_interface_loop_pattern": "0",
"support_interface_filament": "0",
"support_interface_top_layers": "2",
"support_interface_bottom_layers": "2",
"support_interface_spacing": "0.5",
"support_interface_speed": "80",
"support_base_pattern": "default",
"support_base_pattern_spacing": "2.5",
"support_speed": "150",
"support_threshold_angle": "30",
"support_object_xy_distance": "0.35",
"tree_support_branch_angle": "30",
"tree_support_wall_count": "0",
"tree_support_with_infill": "0",
"detect_thin_wall": "0",
"top_surface_pattern": "monotonicline",
"top_shell_thickness": "0.8",
"enable_prime_tower": "1",
"wipe_tower_no_sparse_layers": "0",
"prime_tower_width": "60",
"xy_hole_compensation": "0",
"xy_contour_compensation": "0",
"layer_height": "0.2",
"bottom_shell_layers": "3",
"top_shell_layers": "4",
"bridge_flow": "1",
"initial_layer_speed": "45",
"initial_layer_infill_speed": "45",
"outer_wall_speed": "45",
"inner_wall_speed": "80",
"sparse_infill_speed": "150",
"internal_solid_infill_speed": "150",
"top_surface_speed": "50",
"gap_infill_speed": "30",
"travel_speed": "200"
}

View File

@@ -26,6 +26,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform vec4 uniform_color;

View File

@@ -23,6 +23,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform mat4 view_model_matrix;
@@ -71,8 +72,8 @@ void main()
// Point in homogenous coordinates.
world_pos = volume_world_matrix * vec4(v_position, 1.0);
// z component of normal vector in world coordinate used for slope shading
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
// dot product of world normal with up direction, used for slope shading
world_normal_z = slope.actived ? dot(normalize(slope.volume_world_normal_matrix * v_normal), slope.up_direction) : 0.0;
gl_Position = projection_matrix * position;
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.

View File

@@ -37,6 +37,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform SlopeDetection slope;
@@ -85,7 +86,7 @@ void main()
color = LightBlue;
alpha = 1.0;
}
else if( transformed_normal.z < slope.normal_z - EPSILON)
else if( dot(transformed_normal, slope.up_direction) < slope.normal_z - EPSILON)
{
color = color * 0.5 + LightRed * 0.5;
alpha = 1.0;

View File

@@ -24,6 +24,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform SlopeDetection slope;
void main()

View File

@@ -26,6 +26,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform vec4 uniform_color;

View File

@@ -23,6 +23,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform mat4 view_model_matrix;
@@ -71,8 +72,8 @@ void main()
// Point in homogenous coordinates.
world_pos = volume_world_matrix * vec4(v_position, 1.0);
// z component of normal vector in world coordinate used for slope shading
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
// dot product of world normal with up direction, used for slope shading
world_normal_z = slope.actived ? dot(normalize(slope.volume_world_normal_matrix * v_normal), slope.up_direction) : 0.0;
gl_Position = projection_matrix * position;
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.

View File

@@ -37,6 +37,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform SlopeDetection slope;
@@ -87,7 +88,7 @@ void main()
color = LightBlue;
alpha = 1.0;
}
else if( transformed_normal.z < slope.normal_z - EPSILON)
else if( dot(transformed_normal, slope.up_direction) < slope.normal_z - EPSILON)
{
color = color * 0.5 + LightRed * 0.5;
alpha = 1.0;

View File

@@ -24,6 +24,7 @@ struct SlopeDetection
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
vec3 up_direction;
};
uniform SlopeDetection slope;
void main()

View File

@@ -0,0 +1,76 @@
#include "BeltGCode.hpp"
#include "BeltGCodeWriter.hpp"
#include "BeltTransform.hpp"
#include "Print.hpp"
namespace Slic3r {
void BeltGCode::init_belt_writer(Print &print, bool is_bbl_printers)
{
if (!print.config().belt_printer.value)
return;
auto belt_writer = std::make_unique<BeltGCodeWriter>();
belt_writer->set_is_bbl_machine(is_bbl_printers);
// Axis remap and build volume max are set by base GCode after init_belt_writer returns.
belt_writer->set_belt_back_transform(print.config());
belt_writer->set_machine_frame_transform(print.config());
m_writer = std::move(belt_writer);
}
void BeltGCode::write_belt_header(GCodeOutputStream &file, const Print &print)
{
if (!print.config().belt_printer.value)
return;
const auto &full_cfg = print.full_print_config();
// Slicing rotation: the belt tilt (axis + angle) and the single source of truth
// for the physical tilt the G-code viewer uses to enable belt view.
file.write_format("; belt_slice_rotation = %s\n", full_cfg.opt_serialize("belt_slice_rotation").c_str());
file.write_format("; belt_slice_rotation_angle = %.1f\n", print.config().belt_slice_rotation_angle.value);
file.write_format("; belt_slice_rotation_global = %d\n", print.config().belt_slice_rotation_global.value ? 1 : 0);
// Pre-slice remap configs
file.write_format("; preslice_remap_x = %s\n", full_cfg.opt_serialize("preslice_remap_x").c_str());
file.write_format("; preslice_remap_y = %s\n", full_cfg.opt_serialize("preslice_remap_y").c_str());
file.write_format("; preslice_remap_z = %s\n", full_cfg.opt_serialize("preslice_remap_z").c_str());
file.write_format("; preslice_remap_global = %d\n", print.config().preslice_remap_global.value ? 1 : 0);
file.write_format("; belt_preslice_global = %d\n", print.config().belt_preslice_global.value ? 1 : 0);
// Machine-frame transform: shear (tan) + scale (1/cos) derived from the belt
// tilt angle (or belt_frame_tilt_angle when decoupled).
file.write_format("; belt_frame_tilt_decouple = %d\n", print.config().belt_frame_tilt_decouple.value ? 1 : 0);
file.write_format("; belt_frame_tilt_angle = %.1f\n", print.config().belt_frame_tilt_angle.value);
}
void BeltGCode::on_set_origin(const PrintObject * /*obj*/, const Point & /*inst_shift*/)
{
// Global pre-slice mode: adjust origin using computed correction.
// Transform the origin through the belt pipeline so that
// back_transform(T * origin) = origin (correct machine position).
//
// Flags that trigger this path:
// belt_preslice_global — full pipeline (rotation * remap) is global
// preslice_remap_global — only the pre-slice remap is global
// belt_slice_rotation_global — slicing rotation treated as global (matches
// the per-instance Z-offset added in PrintObjectSlice.cpp)
// The XY origin adjustment uses the FULL forward transform, because the
// back_transform applied during G-code emission is always the inverse of
// the full pipeline.
bool use_global = m_config.belt_preslice_global.value
|| (m_config.preslice_remap_global.value
&& BeltTransformPipeline::has_preslice_remap(m_config))
|| (m_config.belt_slice_rotation_global.value
&& m_config.belt_slice_rotation.value != BeltRotationAxis::None
&& std::abs(m_config.belt_slice_rotation_angle.value) > EPSILON);
if (!use_global || !m_config.belt_printer.value)
return;
// Adjust origin: transform through belt forward pipeline so that
// the back-transform correctly recovers model-space positions.
Transform3d T = BeltTransformPipeline::build_forward_transform(m_config);
Vec2d cur_origin = this->origin();
Vec3d origin3d(cur_origin.x(), cur_origin.y(), 0.);
Vec3d adjusted = T.linear() * origin3d;
this->set_origin(Vec2d(adjusted.x(), adjusted.y()));
}
} // namespace Slic3r

View File

@@ -0,0 +1,23 @@
#pragma once
#include "GCode.hpp"
namespace Slic3r {
// Belt-printer-specific GCode export.
//
// Inherits from GCode and overrides virtual hooks to:
// - Create a BeltGCodeWriter instead of a plain GCodeWriter
// - Write belt configuration to the G-code header
// - Adjust the origin for global pre-slice transforms when switching instances
// - Disable arc fitting (G2/G3 not supported on belt printers)
class BeltGCode : public GCode
{
protected:
void init_belt_writer(Print &print, bool is_bbl_printers) override;
void write_belt_header(GCodeOutputStream &file, const Print &print) override;
void on_set_origin(const PrintObject *obj, const Point &inst_shift) override;
bool should_disable_arc_fitting() const override { return true; }
};
} // namespace Slic3r

View File

@@ -0,0 +1,264 @@
#include "BeltGCodeWriter.hpp"
#include "FirstLayerPlane.hpp"
#include "Geometry.hpp"
#include <boost/log/trivial.hpp>
namespace Slic3r {
namespace {
// Decide whether a particular destination point gets first-layer treatment.
// When the plane evaluator is active, distance from the plane wins; otherwise
// fall back to the layer-coarse m_is_first_layer flag set by the caller.
inline bool belt_point_on_first_layer(
const FirstLayerPlane *plane,
double first_layer_thickness_mm,
bool layer_first_flag,
const Vec3d &point_slicing_mm)
{
if (plane && plane->is_active())
return plane->is_first_layer(point_slicing_mm, first_layer_thickness_mm);
return layer_first_flag;
}
} // namespace
// ---- Belt configuration ---------------------------------------------------
void BeltGCodeWriter::set_belt_back_transform(const PrintConfig &config)
{
m_belt_back_transform.init_from_config(config);
}
void BeltGCodeWriter::set_machine_frame_transform(const PrintConfig &config)
{
m_machine_frame_transform.init_from_config(config);
}
Vec3d BeltGCodeWriter::to_machine_coords(const Vec3d &pos) const
{
// Step 1+2: To Cartesian (back_transform + axis_remap).
// In world-coordinates mode (PA line / PA pattern calibration) the input
// already describes a point relative to the belt surface, so the
// slicer->world back-transform is skipped and only the machine kinematics
// (axis remap + frame shear/scale) are applied.
Vec3d after_back = m_world_coordinates ? pos : m_belt_back_transform.apply(pos);
Vec3d result = apply_axis_remap(after_back);
Vec3d after_remap = result;
// Step 3: Machine-frame transform (belt frame tilt) applied LAST so it acts
// as a global linear transform on the placed coords.
Vec3d final = m_machine_frame_transform.apply(result);
// [BELT-DEBUG] One-shot log per layer transition (i.e. when the input Z
// crosses an integer mm boundary) to keep the log volume manageable while
// still capturing one sample per ~5 layers. Shows the full pipeline so
// Case A vs Case B can be compared step-by-step.
static thread_local int s_last_logged_z = std::numeric_limits<int>::min();
int z_bucket = static_cast<int>(std::floor(pos.z() * 5.0)); // every 0.2mm
if (z_bucket != s_last_logged_z) {
s_last_logged_z = z_bucket;
BOOST_LOG_TRIVIAL(trace) << "[BELT-DEBUG] to_machine_coords"
<< " slicer_in=(" << pos.x() << "," << pos.y() << "," << pos.z() << ")"
<< " after_back=(" << after_back.x() << "," << after_back.y() << "," << after_back.z() << ")"
<< " after_remap=(" << after_remap.x() << "," << after_remap.y() << "," << after_remap.z() << ")"
<< " final=(" << final.x() << "," << final.y() << "," << final.z() << ")"
<< " mft_active=" << m_machine_frame_transform.is_active()
<< " back_active=" << m_belt_back_transform.is_active();
}
return final;
}
// ---- Overridden movement methods ------------------------------------------
std::string BeltGCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment)
{
m_pos(0) = point(0);
m_pos(1) = point(1);
this->set_current_position_clear(true);
Vec2d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset };
// Belt printer: transform to machine coordinates (XY travel also needs Z due to YZ rotation)
Vec3d machine = to_machine_coords(Vec3d(point_on_plate.x(), point_on_plate.y(), m_pos.z()));
GCodeG1Formatter w;
w.emit_xyz(machine);
const bool first_layer_for_point = belt_point_on_first_layer(
m_first_layer_plane, m_first_layer_thickness_mm, m_is_first_layer,
Vec3d(point.x(), point.y(), m_pos.z()));
auto speed = first_layer_for_point
? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
w.emit_f(speed * 60.0);
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
return w.string();
}
std::string BeltGCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase)
{
// Belt printer: force NormalLift since SpiralLift and SlopeLift compute
// slope angles that don't account for the YZ coordinate rotation.
return GCodeWriter::lazy_lift(LiftType::NormalLift, spiral_vase);
}
std::string BeltGCodeWriter::eager_lift(const LiftType type)
{
// Belt printer: force NormalLift (SpiralLift/SlopeLift don't account for YZ rotation).
return GCodeWriter::eager_lift(LiftType::NormalLift);
}
std::string BeltGCodeWriter::_travel_to_z(double z, const std::string &comment)
{
m_pos(2) = z;
double speed = this->config.travel_speed_z.value;
if (speed == 0.) {
const bool first_layer_for_point = belt_point_on_first_layer(
m_first_layer_plane, m_first_layer_thickness_mm, m_is_first_layer,
Vec3d(m_pos.x(), m_pos.y(), z));
speed = first_layer_for_point ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
}
// Belt printer: a Z-only move in slicing frame needs to emit both Y and Z in machine coords.
Vec3d machine = to_machine_coords(Vec3d(m_pos.x() - m_x_offset, m_pos.y() - m_y_offset, z));
GCodeG1Formatter w;
w.emit_xyz(machine);
w.emit_f(speed * 60.0);
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
return w.string();
}
std::string BeltGCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std::string &comment, bool force_no_extrusion)
{
m_pos(0) = point(0);
m_pos(1) = point(1);
if (std::abs(dE) <= std::numeric_limits<double>::epsilon())
force_no_extrusion = true;
if (!force_no_extrusion)
filament()->extrude(dE);
Vec2d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset };
// Belt printer: transform and emit XYZ (Y and Z are coupled)
Vec3d machine = to_machine_coords(Vec3d(point_on_plate.x(), point_on_plate.y(), m_pos.z()));
GCodeG1Formatter w;
w.emit_xyz(machine);
if (!force_no_extrusion)
w.emit_e(filament()->E());
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
return w.string();
}
std::string BeltGCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment, bool force_no_extrusion)
{
m_pos = point;
m_lifted = 0;
if (!force_no_extrusion)
filament()->extrude(dE);
Vec3d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset, point(2) };
point_on_plate = to_machine_coords(point_on_plate);
GCodeG1Formatter w;
w.emit_xyz(point_on_plate);
if (!force_no_extrusion)
w.emit_e(filament()->E());
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
return w.string();
}
std::string BeltGCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment, bool force_z)
{
// Belt-specific override of travel_to_xyz.
// Key differences from base:
// 1. All coordinates go through to_machine_coords()
// 2. Always emit full XYZ (can't split XY and Z due to coupling)
// 3. Lift type forced to NormalLift (handled by lazy_lift/eager_lift overrides)
Vec3d dest_point = point;
const bool first_layer_for_point = belt_point_on_first_layer(
m_first_layer_plane, m_first_layer_thickness_mm, m_is_first_layer, point);
auto travel_speed =
first_layer_for_point ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
// Handle pending z_hop
if (std::abs(m_to_lift) > EPSILON) {
assert(std::abs(m_lifted) < EPSILON);
if ((!this->is_current_position_clear() || m_pos != dest_point) &&
m_to_lift + m_pos(2) > point(2)) {
m_lifted = m_to_lift + m_pos(2) - point(2);
dest_point(2) = m_to_lift + m_pos(2);
}
m_to_lift = 0.;
std::string slop_move;
Vec3d source = { m_pos(0) - m_x_offset, m_pos(1) - m_y_offset, m_pos(2) };
Vec3d target = { dest_point(0) - m_x_offset, dest_point(1) - m_y_offset, dest_point(2) };
Vec3d delta = target - source;
Vec2d delta_no_z = { delta(0), delta(1) };
if (delta(2) > 0 && delta_no_z.norm() != 0.0f) {
// Belt: SpiralLift and SlopeLift are disabled (lazy_lift forces NormalLift),
// but handle NormalLift and fallthrough.
if (m_to_lift_type == LiftType::SlopeLift &&
this->is_current_position_clear() &&
atan2(delta(2), delta_no_z.norm()) < this->filament()->travel_slope()) {
Vec2d temp = delta_no_z.normalized() * delta(2) / tan(this->filament()->travel_slope());
Vec3d slope_top_point = Vec3d(temp(0), temp(1), delta(2)) + source;
slope_top_point = to_machine_coords(slope_top_point);
GCodeG1Formatter w0;
w0.emit_xyz(slope_top_point);
w0.emit_f(travel_speed * 60.0);
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
slop_move = w0.string();
}
else if (m_to_lift_type == LiftType::NormalLift) {
slop_move = _travel_to_z(target.z(), "normal lift Z");
}
}
std::string xy_z_move;
{
Vec3d emit_target = to_machine_coords(target);
GCodeG1Formatter w0;
// Belt mode: always emit full XYZ since Y and Z are coupled
w0.emit_xyz(emit_target);
w0.emit_f(travel_speed * 60.0);
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
xy_z_move = w0.string();
}
m_pos = dest_point;
this->set_current_position_clear(true);
return slop_move + xy_z_move;
}
else if (!force_z && !this->will_move_z(point(2))) {
double nominal_z = m_pos(2) - m_lifted;
m_lifted -= (point(2) - nominal_z);
if (std::abs(m_lifted) < EPSILON)
m_lifted = 0.;
this->set_current_position_clear(true);
return this->travel_to_xy(to_2d(point));
}
else {
m_lifted = 0;
}
Vec3d point_on_plate = { dest_point(0) - m_x_offset, dest_point(1) - m_y_offset, dest_point(2) };
point_on_plate = to_machine_coords(point_on_plate);
// Belt mode: always emit full XYZ
GCodeG1Formatter w;
w.emit_xyz(point_on_plate);
w.emit_f(this->config.travel_speed.value * 60.0);
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
m_pos = dest_point;
this->set_current_position_clear(true);
return w.string();
}
} // namespace Slic3r

View File

@@ -0,0 +1,64 @@
#pragma once
#include "GCodeWriter.hpp"
#include "GCode/BeltBackTransform.hpp"
#include "GCode/MachineFrameTransform.hpp"
namespace Slic3r {
class FirstLayerPlane;
// Belt-printer-specific GCode writer.
//
// Inherits from GCodeWriter and overrides movement methods to apply
// coordinate transformation (back-transform, axis remap, machine-frame
// transform) and emit coupled XYZ moves (Y and Z are coupled due to belt tilt).
class BeltGCodeWriter : public GCodeWriter
{
public:
BeltGCodeWriter() : GCodeWriter() {}
// Belt configuration (axis remap is inherited from GCodeWriter)
void set_belt_back_transform(const PrintConfig &config);
void set_machine_frame_transform(const PrintConfig &config);
Vec3d to_machine_coords(const Vec3d &pos) const;
// World-coordinates mode: incoming coordinates are treated as points
// relative to the physical belt surface (X across, Y along the belt,
// Z height above it) instead of slicing-frame coordinates — the
// slicer->world back-transform is skipped. Used by the PA line / PA
// pattern calibration generators, whose logical bed coordinates describe
// first-layer drawings on the build surface.
void set_world_coordinates(bool enable) { m_world_coordinates = enable; }
// First-layer plane: when set to a non-null active evaluator, travel
// speed selection consults the plane per-move and uses
// initial_layer_travel_speed for points within first_layer_height_mm
// of the plane (regardless of slicing layer index).
void set_first_layer_plane(const FirstLayerPlane *plane,
double first_layer_height_mm) {
m_first_layer_plane = plane;
m_first_layer_thickness_mm = first_layer_height_mm;
}
// Overridden movement methods
std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string()) override;
std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string(), bool force_z = false) override;
std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string(), bool force_no_extrusion = false) override;
std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string(), bool force_no_extrusion = false) override;
std::string lazy_lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false) override;
std::string eager_lift(const LiftType type) override;
protected:
std::string _travel_to_z(double z, const std::string &comment) override;
private:
BeltBackTransform m_belt_back_transform;
MachineFrameTransform m_machine_frame_transform;
bool m_world_coordinates = false;
// Borrowed pointer; lifetime owned by GCode. null = inactive.
const FirstLayerPlane *m_first_layer_plane = nullptr;
double m_first_layer_thickness_mm = 0.;
};
} // namespace Slic3r

View File

@@ -0,0 +1,143 @@
#include "BeltSliceStrategy.hpp"
#include "Model.hpp"
#include <limits>
#include <boost/log/trivial.hpp>
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
#include <iomanip>
#include <sstream>
#include <thread>
#endif
namespace Slic3r {
void BeltSliceStrategy::apply_preslice_transforms(Transform3d &trafo,
const PrintConfig &config,
const ModelVolumePtrs &model_volumes,
double *out_belt_min_z)
{
// 1. Standalone pre-slice axis remap (works without belt mode).
const bool has_remap = BeltTransformPipeline::has_preslice_remap(config);
if (has_remap)
trafo = BeltTransformPipeline::build_preslice_remap(config) * trafo;
// 2. Belt rotation — the sole mesh-side belt transform (matching
// BeltTransformPipeline::build_forward_transform). Only active in
// belt-printer mode.
bool has_rotation = false;
if (config.belt_printer.value) {
const Matrix3d rot = BeltTransformPipeline::build_rotation_matrix(config, &has_rotation);
if (has_rotation) {
Transform3d belt_xform = Transform3d::Identity();
belt_xform.linear() = rot;
trafo = belt_xform * trafo;
}
}
if (!has_remap && !has_rotation)
return;
// 3. Z-shift — detect if the mesh clips below the build plate after the
// transforms and lift it. Each mesh vertex must be brought into object space
// via mv->get_matrix() before applying the full trafo (which is in object
// space). Missing this on assemblies (where per-volume get_matrix() positions
// each volume within the object) would compute min_z against mesh-local vertex
// coordinates rather than object-space coordinates, so volumes translated along
// the slicer's Z axis would be silently excluded from the bound check.
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
// Capture the incoming trafo for diagnostic logging.
// This is the slicer-frame transform AFTER remap + rotation but BEFORE z_shift.
const Transform3d trafo_pre_shift = trafo;
auto log_mat = [](const Matrix3d &m) {
std::ostringstream ss;
ss << std::fixed << std::setprecision(4);
ss << "[[" << m(0,0) << "," << m(0,1) << "," << m(0,2) << "],"
<< "[" << m(1,0) << "," << m(1,1) << "," << m(1,2) << "],"
<< "[" << m(2,0) << "," << m(2,1) << "," << m(2,2) << "]]";
return ss.str();
};
auto log_vec3 = [](const Vec3d &v) {
std::ostringstream ss;
ss << std::fixed << std::setprecision(4);
ss << "(" << v.x() << "," << v.y() << "," << v.z() << ")";
return ss.str();
};
BOOST_LOG_TRIVIAL(trace) << "[BELT-DEBUG] apply_preslice_transforms enter"
<< " has_rotation=" << has_rotation
<< " has_remap=" << has_remap
<< " trafo.linear=" << log_mat(trafo_pre_shift.linear())
<< " trafo.translation=" << log_vec3(trafo_pre_shift.translation())
<< " volumes=" << model_volumes.size();
#endif
double min_z = std::numeric_limits<double>::max();
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
int vol_idx = 0;
#endif
for (const ModelVolume *mv : model_volumes) {
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
if (!mv->is_model_part()) { ++vol_idx; continue; }
#else
if (!mv->is_model_part()) continue;
#endif
Transform3d vol_trafo = trafo * mv->get_matrix();
const auto &its = mv->mesh().its;
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
// Per-volume bbox in mesh-frame and post-trafo slicer-frame.
Vec3d mesh_min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
Vec3d mesh_max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
Vec3d slicer_min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
Vec3d slicer_max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
double vol_min_z = std::numeric_limits<double>::max();
#endif
for (const stl_vertex &v : its.vertices) {
Vec3d vm = v.cast<double>();
Vec3d pt = vol_trafo * vm;
min_z = std::min(min_z, pt.z());
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
mesh_min = mesh_min.cwiseMin(vm);
mesh_max = mesh_max.cwiseMax(vm);
slicer_min = slicer_min.cwiseMin(pt);
slicer_max = slicer_max.cwiseMax(pt);
vol_min_z = std::min(vol_min_z, pt.z());
#endif
}
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
BOOST_LOG_TRIVIAL(trace) << "[BELT-DEBUG] vol[" << vol_idx
<< "] id=" << mv->id().id << " name='" << mv->name << "'"
<< " mesh_bbox_min=" << log_vec3(mesh_min) << " mesh_bbox_max=" << log_vec3(mesh_max)
<< " get_matrix.translation=" << log_vec3(mv->get_matrix().translation())
<< " slicer_bbox_min=" << log_vec3(slicer_min) << " slicer_bbox_max=" << log_vec3(slicer_max)
<< " vol_min_z=" << vol_min_z;
++vol_idx;
#endif
}
const double z_shift_val = (min_z < 0. && min_z != std::numeric_limits<double>::max()) ? -min_z : 0.;
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
BOOST_LOG_TRIVIAL(trace) << "[BELT-DEBUG] combined min_z=" << min_z
<< " z_shift_val=" << z_shift_val;
#endif
if (z_shift_val > 0.) {
Transform3d z_shift = Transform3d::Identity();
z_shift.matrix()(2, 3) = z_shift_val;
trafo = z_shift * trafo;
}
// out_belt_min_z is only meaningful in belt mode; the standalone-remap path
// never reported it.
if (out_belt_min_z && config.belt_printer.value) {
const double new_val = (min_z != std::numeric_limits<double>::max()) ? min_z : 0.;
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
BOOST_LOG_TRIVIAL(trace) << "[BELT-DEBUG] write m_belt_min_z tid=" << std::this_thread::get_id()
<< " target=" << out_belt_min_z << " old=" << *out_belt_min_z << " new=" << new_val;
#endif
*out_belt_min_z = new_val;
}
#ifdef SLIC3R_BELT_DIAGNOSTIC_LOG
BOOST_LOG_TRIVIAL(trace) << "[BELT-DEBUG] apply_preslice_transforms exit"
<< " final_trafo.linear=" << log_mat(trafo.linear())
<< " final_trafo.translation=" << log_vec3(trafo.translation());
#endif
}
} // namespace Slic3r

View File

@@ -0,0 +1,36 @@
#pragma once
#include "libslic3r.h"
#include "Point.hpp"
#include "BeltTransform.hpp"
#include "PrintConfig.hpp"
#include "Model.hpp"
namespace Slic3r {
// Belt printer / pre-slice transform strategy.
//
// Composes, in order, the pre-slice mesh transforms applied before slicing:
// 1. Pre-slice axis remap (standalone — works without belt mode)
// 2. Belt rotation (the sole mesh-side belt transform; shear & scale are a
// g-code-side stage, see MachineFrameTransform)
// 3. Per-object Z-shift that lifts the mesh above the build plate
//
// Isolates this belt/remap-specific logic from the generic slicing pipeline in
// PrintObjectSlice.cpp.
class BeltSliceStrategy
{
public:
// Apply the pre-slice remap + belt rotation + Z-shift to `trafo` in place.
// No-op when neither a remap nor a belt rotation is configured.
//
// out_belt_min_z (if non-null) receives the minimum mesh Z after the
// transforms, but only in belt-printer mode — the standalone-remap path
// never reported it.
static void apply_preslice_transforms(Transform3d &trafo,
const PrintConfig &config,
const ModelVolumePtrs &model_volumes,
double *out_belt_min_z = nullptr);
};
} // namespace Slic3r

View File

@@ -0,0 +1,223 @@
#include "BeltTransform.hpp"
#include "Model.hpp"
#include <limits>
namespace Slic3r {
// ---- Matrix builders ------------------------------------------------------
Transform3d BeltTransformPipeline::build_preslice_remap(const PrintConfig &config)
{
Transform3d pre_remap = Transform3d::Identity();
if (!has_preslice_remap(config))
return pre_remap;
int pre_rx = int(config.preslice_remap_x.value);
int pre_ry = int(config.preslice_remap_y.value);
int pre_rz = int(config.preslice_remap_z.value);
// Each remap value selects a source axis and sign.
auto remap_column = [](int r) -> Vec3d {
int axis = r % 3;
Vec3d col = Vec3d::Zero();
if (r < 3) col[axis] = 1.0; // +axis
else if (r < 6) col[axis] = -1.0; // -axis
else col[axis] = -1.0; // Rev: max - pos = -(pos - max)
return col;
};
Matrix3d remap_lin;
remap_lin.col(0) = remap_column(pre_rx);
remap_lin.col(1) = remap_column(pre_ry);
remap_lin.col(2) = remap_column(pre_rz);
pre_remap.linear() = remap_lin;
// Translation for Rev modes (needs build volume extents).
if (pre_rx >= 6 || pre_ry >= 6 || pre_rz >= 6) {
BoundingBoxf bbox_bed(config.printable_area.values);
Vec3d vol_max(bbox_bed.max.x(), bbox_bed.max.y(),
config.printable_height.value);
Vec3d remap_trans = Vec3d::Zero();
auto add_rev = [&](int r, int out) {
if (r >= 6) remap_trans[out] = vol_max[r % 3];
};
add_rev(pre_rx, 0);
add_rev(pre_ry, 1);
add_rev(pre_rz, 2);
pre_remap.translation() = remap_trans;
}
return pre_remap;
}
Matrix3d BeltTransformPipeline::build_rotation_matrix(const PrintConfig &config, bool *has_rot_out)
{
BeltRotationAxis axis = config.belt_slice_rotation.value;
double angle_deg = config.belt_slice_rotation_angle.value;
bool active = axis != BeltRotationAxis::None && std::abs(angle_deg) > EPSILON;
if (has_rot_out) *has_rot_out = active;
if (!active)
return Matrix3d::Identity();
double angle_rad = Geometry::deg2rad(angle_deg);
Vec3d unit_axis;
switch (axis) {
case BeltRotationAxis::X: unit_axis = Vec3d::UnitX(); break;
case BeltRotationAxis::Y: unit_axis = Vec3d::UnitY(); break;
case BeltRotationAxis::Z: unit_axis = Vec3d::UnitZ(); break;
default: return Matrix3d::Identity();
}
return Eigen::AngleAxisd(angle_rad, unit_axis).toRotationMatrix();
}
Transform3d BeltTransformPipeline::build_forward_transform(const PrintConfig &config)
{
// Mesh-side belt transform: rotation applied after the pre-slice axis remap.
// (Shear & scale are a g-code-side stage, not part of the mesh transform.)
Transform3d pre_remap = build_preslice_remap(config);
Matrix3d rot = build_rotation_matrix(config);
Transform3d combined = Transform3d::Identity();
combined.linear() = rot;
combined = combined * pre_remap;
return combined;
}
// ---- Bounding box remap ---------------------------------------------------
BoundingBoxf3 BeltTransformPipeline::remap_bbox(const BoundingBoxf3 &bb, const PrintConfig &config)
{
int pre_rx = int(config.preslice_remap_x.value);
int pre_ry = int(config.preslice_remap_y.value);
int pre_rz = int(config.preslice_remap_z.value);
if (pre_rx == int(RemapAxis::PosX) &&
pre_ry == int(RemapAxis::PosY) &&
pre_rz == int(RemapAxis::PosZ))
return bb; // Identity remap.
auto remap_coord = [](int r, const Vec3d &v) -> double {
int axis = r % 3;
if (r < 3) return v[axis];
return -v[axis];
};
Vec3d mn = bb.min.cast<double>(), mx = bb.max.cast<double>();
BoundingBoxf3 rbb;
for (int i = 0; i < 8; ++i) {
Vec3d c((i & 1) ? mx.x() : mn.x(),
(i & 2) ? mx.y() : mn.y(),
(i & 4) ? mx.z() : mn.z());
Vec3d rc(remap_coord(pre_rx, c), remap_coord(pre_ry, c), remap_coord(pre_rz, c));
if (i == 0) rbb = BoundingBoxf3(rc, rc);
else rbb.merge(rc);
}
return rbb;
}
BoundingBoxf3 BeltTransformPipeline::remap_bbox(const ModelObject &model_object, const PrintConfig &config)
{
return remap_bbox(model_object.raw_bounding_box(), config);
}
// ---- Belt floor parameters ------------------------------------------------
// Shared implementation for both PrintConfig and DynamicPrintConfig.
// Template avoids duplicating the math for the two config types.
namespace {
template<typename Config>
BeltTransformPipeline::BeltHeightResult compute_belt_height_and_floor_impl(
const Config &config, const BoundingBoxf3 &bb, double original_height)
{
BeltTransformPipeline::BeltHeightResult result;
result.object_height = original_height;
// Extract the mesh rotation from config (the sole mesh-side belt transform).
BeltRotationAxis rot_axis;
double rot_angle;
if constexpr (std::is_same_v<Config, PrintConfig>) {
rot_axis = config.belt_slice_rotation.value;
rot_angle = config.belt_slice_rotation_angle.value;
} else {
// DynamicPrintConfig path
auto get_float = [&](const char *key) {
auto *opt = config.template option<ConfigOptionFloat>(key);
return opt ? opt->value : 0.0;
};
auto get_rot_axis = [&](const char *key) {
auto *opt = config.template option<ConfigOptionEnum<BeltRotationAxis>>(key);
return opt ? opt->value : BeltRotationAxis::None;
};
rot_axis = get_rot_axis("belt_slice_rotation");
rot_angle = get_float("belt_slice_rotation_angle");
}
bool has_rotation = rot_axis != BeltRotationAxis::None && std::abs(rot_angle) > EPSILON;
if (!has_rotation)
return result;
// Rotation path: sweep the 8 bbox corners through R to get the rotated height,
// then derive the belt floor (the image of machine-Z = 0 under R).
double angle_rad = Geometry::deg2rad(rot_angle);
Vec3d unit_axis;
switch (rot_axis) {
case BeltRotationAxis::X: unit_axis = Vec3d::UnitX(); break;
case BeltRotationAxis::Y: unit_axis = Vec3d::UnitY(); break;
case BeltRotationAxis::Z: unit_axis = Vec3d::UnitZ(); break;
default: unit_axis = Vec3d::UnitX(); break;
}
Matrix3d R = Eigen::AngleAxisd(angle_rad, unit_axis).toRotationMatrix();
double min_rz = std::numeric_limits<double>::max();
double max_rz = std::numeric_limits<double>::lowest();
for (int i = 0; i < 8; ++i) {
Vec3d c((i & 1) ? bb.max.x() : bb.min.x(),
(i & 2) ? bb.max.y() : bb.min.y(),
(i & 4) ? bb.max.z() : bb.min.z());
double z = (R * c).z();
min_rz = std::min(min_rz, z);
max_rz = std::max(max_rz, z);
}
result.object_height = max_rz - min_rz;
// Belt floor in slicer-frame is the image of z_machine = 0 under R.
// R(+α, X): point (·, y, 0) → (·, cos α · y, sin α · y) ⇒ z = tan(α) · y_s
// R(+α, Y): point (x, ·, 0) → (cos α · x, ·, -sin α · x) ⇒ z = -tan(α) · x_s
// R(+α, Z): point (·, ·, 0) → (·, ·, 0); no tilt → no floor
double sin_a = std::sin(angle_rad), cos_a = std::cos(angle_rad);
switch (rot_axis) {
case BeltRotationAxis::X:
result.floor_params.shear_factor = (std::abs(cos_a) > EPSILON) ? sin_a / cos_a : 0.;
result.floor_params.from_axis = 1; // Y
break;
case BeltRotationAxis::Y:
result.floor_params.shear_factor = (std::abs(cos_a) > EPSILON) ? -sin_a / cos_a : 0.;
result.floor_params.from_axis = 0; // X
break;
case BeltRotationAxis::Z:
default:
result.floor_params.shear_factor = 0.0;
result.floor_params.from_axis = 1;
break;
}
result.floor_params.z_shift = bb.min.z() + ((min_rz < 0.) ? -min_rz : 0.);
return result;
}
} // anonymous namespace
BeltTransformPipeline::BeltHeightResult BeltTransformPipeline::compute_belt_height_and_floor(
const PrintConfig &config, const BoundingBoxf3 &remapped_bbox, double original_height)
{
return compute_belt_height_and_floor_impl(config, remapped_bbox, original_height);
}
BeltTransformPipeline::BeltHeightResult BeltTransformPipeline::compute_belt_height_and_floor(
const DynamicPrintConfig &config, const BoundingBoxf3 &remapped_bbox, double original_height)
{
return compute_belt_height_and_floor_impl(config, remapped_bbox, original_height);
}
} // namespace Slic3r

View File

@@ -0,0 +1,152 @@
#pragma once
#include "libslic3r.h"
#include "Point.hpp"
#include "BoundingBox.hpp"
#include "PrintConfig.hpp"
#include "Geometry.hpp"
#include <cmath>
namespace Slic3r {
class ModelObject;
// Shared belt-printer transform math.
//
// The pre-slice pipeline applied in PrintObjectSlice.cpp is:
// trafo_out = z_shift * rotation * pre_remap * trafo_in
//
// Rotation is the sole mesh-side belt transform; shear & scale are applied
// to the g-code instead (see MachineFrameTransform). This class provides the
// building blocks so every call site uses the same implementation. z_shift is
// object-dependent (computed from mesh vertex bounds) and is NOT included in
// build_forward_transform(). The machine-frame shear/scale is derived directly
// from the tilt angle in MachineFrameTransform and no longer lives here.
//
// Design note: this mesh-rotation approach replaced an earlier pre-shear
// method (now removed). While that initial pre-shear method was instrumental
// in getting belt printer slicing off the ground in the first place, its place is
// in the past. A big thank you goes to the Unlayered3D team, who recommended
// switching to a pre-slice rotation stage instead. Doing so keeps the slicing
// operation isometric — no distortion of the sliced geometry — while the
// non-orthogonal machine-axis compensation is confined to a g-code-side shear/scale
// derived from the same tilt angle.
//
// This fixed a number of issues, including several issues noticed by hotcubcar
// regarding adaptive infills not working, gyroid becoming anisotropic, and more
// that were all mostly resolved as a result of the switch.
//
// This also means that the pre-slice rotation transform methodology can be used
// more cleanly on non-belt printers.
// - HarrierPigeon (Joseph Robertson)
class BeltTransformPipeline
{
public:
// ---- Identity checks --------------------------------------------------
static bool has_preslice_remap(const PrintConfig &config)
{
return int(config.preslice_remap_x.value) != int(RemapAxis::PosX) ||
int(config.preslice_remap_y.value) != int(RemapAxis::PosY) ||
int(config.preslice_remap_z.value) != int(RemapAxis::PosZ);
}
// Overload accepting DynamicPrintConfig (used in static slicing_parameters).
static bool has_preslice_remap(const DynamicPrintConfig &config)
{
auto get_int = [&](const char *key) -> int {
auto *opt = config.option<ConfigOptionEnum<RemapAxis>>(key);
return opt ? int(opt->value) : 0;
};
return get_int("preslice_remap_x") != int(RemapAxis::PosX) ||
get_int("preslice_remap_y") != int(RemapAxis::PosY) ||
get_int("preslice_remap_z") != int(RemapAxis::PosZ);
}
static bool has_rotation(const PrintConfig &config)
{
return config.belt_slice_rotation.value != BeltRotationAxis::None &&
std::abs(config.belt_slice_rotation_angle.value) > EPSILON;
}
// Physical belt tilt derived from the slicing rotation — the single source of
// truth for bed rendering, support gravity tilt and the bed-exclusion
// projection. Returns the tilt magnitude in degrees split onto the X and Y
// build-plate tilt axes according to the rotation axis:
// rotation about X → tilt_x = angle (gantry tilts in the YZ plane)
// rotation about Y → tilt_y = angle (gantry tilts in the XZ plane)
// rotation about Z / None → no tilt (in-plane spin doesn't tilt the belt)
// The magnitude uses abs(angle) so a negative rotation still reports a positive
// physical tilt.
struct PhysicalTilt { double tilt_x_deg = 0.; double tilt_y_deg = 0.; };
static PhysicalTilt physical_tilt(BeltRotationAxis axis, double angle_deg)
{
PhysicalTilt t;
double mag = std::abs(angle_deg);
switch (axis) {
case BeltRotationAxis::X: t.tilt_x_deg = mag; break;
case BeltRotationAxis::Y: t.tilt_y_deg = mag; break;
default: break; // Z / None: no physical tilt
}
return t;
}
static PhysicalTilt physical_tilt(const PrintConfig &config)
{
return physical_tilt(config.belt_slice_rotation.value,
config.belt_slice_rotation_angle.value);
}
// ---- Matrix builders --------------------------------------------------
// Build the pre-slice axis remap transform (includes Rev-mode translation).
static Transform3d build_preslice_remap(const PrintConfig &config);
// Build the 3x3 rotation matrix from belt_slice_rotation* config.
// Returns Identity if rotation axis is None or angle is ~0.
// Also sets has_rot_out if non-null.
static Matrix3d build_rotation_matrix(const PrintConfig &config, bool *has_rot_out = nullptr);
// Combined forward transform (rotation * pre_remap) — the mesh-side belt
// transform that BeltSliceStrategy applies and BeltBackTransform inverts.
// Does NOT include the per-object Z-shift.
static Transform3d build_forward_transform(const PrintConfig &config);
// ---- Bounding box remap -----------------------------------------------
// Remap a bounding box through the pre-slice axis remap.
// Returns the original bbox if remap is identity.
static BoundingBoxf3 remap_bbox(const BoundingBoxf3 &bb, const PrintConfig &config);
static BoundingBoxf3 remap_bbox(const ModelObject &model_object, const PrintConfig &config);
// ---- Belt floor parameters --------------------------------------------
struct BeltFloorParams {
double shear_factor = 0.0;
int from_axis = 1;
double z_shift = 0.0;
};
// Result of computing belt height + floor params.
struct BeltHeightResult {
double object_height; // Effective object height after shear/scale
BeltFloorParams floor_params;
};
// Compute effective object height and belt floor parameters from config
// and pre-remapped bounding box. original_height is the input height
// (bb.size().z() or model_object.max_z()).
static BeltHeightResult compute_belt_height_and_floor(
const PrintConfig &config, const BoundingBoxf3 &remapped_bbox,
double original_height);
// Overload for DynamicPrintConfig (used by static slicing_parameters).
static BeltHeightResult compute_belt_height_and_floor(
const DynamicPrintConfig &config, const BoundingBoxf3 &remapped_bbox,
double original_height);
};
} // namespace Slic3r

View File

@@ -895,6 +895,10 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
std::map<ObjectID, ExPolygons>* objectBrimAreasOut,
std::map<ObjectID, ExPolygons>* supportBrimAreasOut)
{
// Belt printer: brim is not compatible with belt printing.
if (print.config().belt_printer.value)
return;
std::map<ObjectID, double> brim_width_map;
std::map<ObjectID, ExPolygons> brimAreaMap;
std::map<ObjectID, ExPolygons> supportBrimAreaMap;

View File

@@ -176,6 +176,31 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
BOOST_LOG_TRIVIAL(debug) << "BuildVolume printable_area clasified as: " << this->type_name();
}
void BuildVolume::set_belt_printer(bool enabled, double angle_deg, bool infinite_y)
{
m_is_belt_printer = enabled;
m_belt_angle = angle_deg;
m_belt_infinite_y = infinite_y;
// Restart from the unmodified bbox each call. Without this, toggling
// belt mode off (or switching infinite_y true→false) would leave the
// extents inflated and break collision / object_state checks.
BoundingBoxf bboxf = get_extents(m_bed_shape);
m_bboxf = BoundingBoxf3{ to_3d(bboxf.min, 0.), to_3d(bboxf.max, m_max_print_height) };
if (enabled) {
if (infinite_y) {
// Extend the Y bound to a very large value for infinite belt.
m_bboxf.max.y() = 100000.;
}
// Belt printer: the Z extent already equals printable_height (set above), which
// is the usable vertical clearance above the belt. The gantry's axis range is
// sized to reach height/cos(tilt), so no diagonal scaling is applied here — this
// keeps the live "outside build volume" highlight in agreement with Print::validate().
(void) angle_deg;
}
}
#if 0
// Tests intersections of projected triangles, not just their vertices against a bounding box.
// This test also correctly evaluates collision of a non-convex object with the bounding box.
@@ -384,6 +409,11 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
build_volume.max.z() = std::numeric_limits<double>::max();
if (ignore_bottom)
build_volume.min.z() = -std::numeric_limits<double>::max();
// Belt printer: extend Y bounds for infinite Y.
if (m_is_belt_printer && m_belt_infinite_y) {
build_volume.min.y() = -std::numeric_limits<double>::max();
build_volume.max.y() = std::numeric_limits<double>::max();
}
BoundingBox3Base<Vec3f> build_volumef(build_volume.min.cast<float>(), build_volume.max.cast<float>());
// The following test correctly interprets intersection of a non-convex object with a rectangular build volume.
//return rectangle_test(its, trafo, to_2d(build_volume.min), to_2d(build_volume.max), build_volume.max.z());

View File

@@ -57,6 +57,10 @@ public:
// Initialize from PrintConfig::printable_area and PrintConfig::printable_height
BuildVolume(const std::vector<Vec2d> &printable_area, const double printable_height, const std::vector<std::vector<Vec2d>> &extruder_areas, const std::vector<double>& extruder_printable_heights);
// Belt printer configuration.
void set_belt_printer(bool enabled, double angle_deg, bool infinite_y);
bool is_belt_printer() const { return m_is_belt_printer; }
// Source data, unscaled coordinates.
const std::vector<Vec2d>& printable_area() const { return m_bed_shape; }
double printable_height() const { return m_max_print_height; }
@@ -80,7 +84,7 @@ public:
indexed_triangle_set bounding_mesh(bool scale=true) const;
// Center of the print bed, unscaled.
Vec2d bed_center() const { return to_2d(m_bboxf.center()); }
Vec2d bed_center() const { return get_extents(m_bed_shape).center(); }
// Convex hull of polygon(), scaled.
const Polygon& convex_hull() const { return m_convex_hull; }
// Smallest enclosing circle of polygon(), scaled.
@@ -139,6 +143,10 @@ private:
// Source definition of the print volume height (PrintConfig::printable_height)
double m_max_print_height { 0.f };
std::vector<double> m_extruder_printable_height;
// Belt printer state.
bool m_is_belt_printer { false };
double m_belt_angle { 0. };
bool m_belt_infinite_y { false };
// Derived values.
BuildVolume_Type m_type { BuildVolume_Type::Invalid };

View File

@@ -79,6 +79,16 @@ set(lisbslic3r_sources
BoundingBox.hpp
BridgeDetector.cpp
BridgeDetector.hpp
BeltGCode.cpp
BeltGCode.hpp
BeltGCodeWriter.cpp
BeltGCodeWriter.hpp
BeltSliceStrategy.cpp
BeltSliceStrategy.hpp
BeltTransform.cpp
BeltTransform.hpp
FirstLayerPlane.cpp
FirstLayerPlane.hpp
Brim.cpp
BrimEarsPoint.hpp
Brim.hpp
@@ -209,6 +219,10 @@ set(lisbslic3r_sources
GCode/AdaptivePAProcessor.hpp
GCode/AvoidCrossingPerimeters.cpp
GCode/AvoidCrossingPerimeters.hpp
GCode/BeltBackTransform.cpp
GCode/BeltBackTransform.hpp
GCode/MachineFrameTransform.cpp
GCode/MachineFrameTransform.hpp
GCode/ConflictChecker.cpp
GCode/ConflictChecker.hpp
GCode/CoolingBuffer.cpp
@@ -416,6 +430,8 @@ set(lisbslic3r_sources
SlicingAdaptive.hpp
Slicing.cpp
Slicing.hpp
Support/BeltFloorContext.cpp
Support/BeltFloorContext.hpp
Support/SupportCommon.cpp
Support/SupportCommon.hpp
Support/SupportLayer.hpp

View File

@@ -396,6 +396,11 @@ inline void translate(ExPolygons &expolys, const Point &p) {
expoly.translate(p);
}
inline void translate(Polygons &polys, const Point &p) {
for (Polygon &poly : polys)
poly.translate(p);
}
inline void polygons_append(Polygons &dst, const ExPolygon &src)
{
dst.reserve(dst.size() + src.holes.size() + 1);

View File

@@ -0,0 +1,225 @@
#include "FirstLayerPlane.hpp"
#include "BeltTransform.hpp"
#include <algorithm>
#include <climits>
#include <cmath>
namespace Slic3r {
namespace {
// Build the row of the gcode-axis-remap matrix R that produces machine_Z,
// AS A FUNCTION OF a slicing-frame point in the GCode generator's coordinate
// space. Without back-transform this is just R.row(2). With back-transform
// the writer applies F^-1 before R, so the effective row is (R * F^-1).row(2).
//
// Returns a pair (gradient, constant) such that:
// machine_Z(p_slicing) = gradient.dot(p_slicing) + constant
struct MachineZAffine {
Vec3d gradient = Vec3d::UnitZ();
double constant = 0.0;
};
MachineZAffine compute_machine_z_affine(const PrintConfig &config)
{
MachineZAffine out;
// R is the matrix form of GCodeWriter::apply_axis_remap. Each output axis
// i picks one slicing-frame component (with sign + optional Rev mode
// translation) based on m_remap_{x,y,z}. We only need row 2 (the z output)
// since machine_Z is what defines the first-layer plane.
int rz = int(config.gcode_remap_z.value);
int axis = rz % 3;
double sign;
double trans;
if (rz < int(RemapAxis::NegX)) { // 0..2 = PosX/Y/Z
sign = 1.0;
trans = 0.0;
} else if (rz < int(RemapAxis::RevX)) { // 3..5 = NegX/Y/Z
sign = -1.0;
trans = 0.0;
} else { // 6..8 = RevX/Y/Z
sign = -1.0;
BoundingBoxf bbox_bed(config.printable_area.values);
Vec3d vol_max(bbox_bed.max.x(),
bbox_bed.max.y(),
config.printable_height.value);
trans = vol_max[axis];
}
Vec3d r_row = Vec3d::Zero();
r_row[axis] = sign;
// Without back-transform, machine_Z(slicing) = r_row · slicing + trans.
out.gradient = r_row;
out.constant = trans;
if (config.gcode_back_transform.value && config.belt_printer.value) {
// BeltGCodeWriter applies F^-1 before R when back-transform is on.
// So machine_Z(slicing) = r_row · (F^-1 · slicing) + trans
// = (r_row^T · F^-1) · slicing + trans
// We need to compose r_row with F^-1 from the LEFT (treating r_row as
// a row vector). Eigen makes this easy: it's just F^-1.transpose() * r_row.
Transform3d forward = BeltTransformPipeline::build_forward_transform(config);
Transform3d inverse = forward.inverse();
// Note: forward.translation() is normally zero (per-print transforms
// don't add a translation; the per-object z_shift is added separately
// in PrintObjectSlice). We still incorporate inverse.translation() in
// case a Rev-mode preslice_remap puts a translation in F.
Vec3d composed_grad = inverse.linear().transpose() * r_row;
double composed_trans =
r_row.dot(inverse.translation()) + trans;
out.gradient = composed_grad;
out.constant = composed_trans;
}
return out;
}
} // namespace
FirstLayerPlane::FirstLayerPlane(const PrintConfig &config)
{
// -------- Resolve Auto -------------------------------------------------
FirstLayerPlaneMode mode = config.first_layer_plane.value;
if (mode == FirstLayerPlaneMode::Auto) {
bool belt_affine_active = config.belt_printer.value &&
config.belt_slice_rotation.value != BeltRotationAxis::None &&
std::abs(config.belt_slice_rotation_angle.value) > EPSILON;
mode = belt_affine_active ? FirstLayerPlaneMode::BeltAffine
: FirstLayerPlaneMode::XY;
}
m_mode = mode;
// -------- Band thickness ----------------------------------------------
// Note: layer_height lives in PrintObjectConfig, not PrintConfig, so we
// can't fall back to it from here. initial_layer_print_height is in
// PrintConfig and is the right default anyway (the legacy first-layer
// semantics used initial_layer_print_height, not the regular one).
double thickness = config.first_layer_plane_thickness.value;
if (thickness <= 0.0)
thickness = config.initial_layer_print_height.value;
if (thickness <= 0.0)
thickness = 0.2;
m_thickness_mm = thickness;
const double user_offset = config.first_layer_plane_offset.value;
// -------- Build the plane ---------------------------------------------
auto set_axis_aligned = [&](const Vec3d &n_unit, double offset_along_n) {
m_normal = n_unit;
m_offset = offset_along_n;
};
switch (mode) {
case FirstLayerPlaneMode::XY:
// Legacy XY plane. Inactive: short-circuit to layer-index path.
set_axis_aligned(Vec3d::UnitZ(), user_offset);
m_active = false;
return;
case FirstLayerPlaneMode::YZ:
set_axis_aligned(Vec3d::UnitX(), user_offset);
m_active = true;
return;
case FirstLayerPlaneMode::XZ:
set_axis_aligned(Vec3d::UnitY(), user_offset);
m_active = true;
return;
case FirstLayerPlaneMode::BeltAffine: {
// Compute the slicing-frame plane that maps to machine_Z = user_offset
// under the gcode axis remap (and optional back-transform).
MachineZAffine mz = compute_machine_z_affine(config);
double cmag = mz.gradient.norm();
if (cmag < EPSILON) {
// Degenerate: slicing point doesn't affect machine_Z. Fall back.
set_axis_aligned(Vec3d::UnitZ(), user_offset);
m_active = false;
return;
}
// Plane equation: gradient · slicing = user_offset - constant
const double K = user_offset - mz.constant;
m_normal = mz.gradient / cmag;
m_offset = K / cmag;
m_active = true;
return;
}
case FirstLayerPlaneMode::Auto:
// Should have been resolved above.
m_active = false;
return;
}
m_active = false;
}
double FirstLayerPlane::distance_from_plane(const Vec3d &point_slicing_mm) const
{
return m_normal.dot(point_slicing_mm) - m_offset;
}
bool FirstLayerPlane::is_first_layer(const Vec3d &point_slicing_mm,
double first_layer_height_mm) const
{
if (!m_active)
return false;
return distance_from_plane(point_slicing_mm) < first_layer_height_mm;
}
int FirstLayerPlane::effective_layer_index(const Vec3d &point_slicing_mm) const
{
if (!m_active)
return INT_MAX / 2; // Effectively "way past first layer".
double d = distance_from_plane(point_slicing_mm);
if (d <= 0.0)
return 0;
return int(std::floor(d / m_thickness_mm));
}
int FirstLayerPlane::min_effective_index_for_xy_bbox(
const BoundingBoxf &xy_bbox_mm, double slicing_z_mm) const
{
if (!m_active)
return INT_MAX / 2;
// For the rectangular bbox in (x, y) at fixed z, the smallest value of
// (n.x*x + n.y*y + n.z*z - offset) is achieved at one of the four
// corners, with the smaller component picked when the corresponding
// normal coefficient is positive.
const double x_for_min = (m_normal.x() >= 0.0)
? xy_bbox_mm.min.x() : xy_bbox_mm.max.x();
const double y_for_min = (m_normal.y() >= 0.0)
? xy_bbox_mm.min.y() : xy_bbox_mm.max.y();
const double dmin = m_normal.x() * x_for_min
+ m_normal.y() * y_for_min
+ m_normal.z() * slicing_z_mm
- m_offset;
if (dmin <= 0.0)
return 0;
return int(std::floor(dmin / m_thickness_mm));
}
int FirstLayerPlane::min_effective_index_for_bbox3(
const BoundingBoxf3 &bbox_mm) const
{
if (!m_active)
return INT_MAX / 2;
const double x_for_min = (m_normal.x() >= 0.0)
? bbox_mm.min.x() : bbox_mm.max.x();
const double y_for_min = (m_normal.y() >= 0.0)
? bbox_mm.min.y() : bbox_mm.max.y();
const double z_for_min = (m_normal.z() >= 0.0)
? bbox_mm.min.z() : bbox_mm.max.z();
const double dmin = m_normal.x() * x_for_min
+ m_normal.y() * y_for_min
+ m_normal.z() * z_for_min
- m_offset;
if (dmin <= 0.0)
return 0;
return int(std::floor(dmin / m_thickness_mm));
}
} // namespace Slic3r

View File

@@ -0,0 +1,76 @@
#ifndef slic3r_FirstLayerPlane_hpp_
#define slic3r_FirstLayerPlane_hpp_
#include "libslic3r.h"
#include "Point.hpp"
#include "BoundingBox.hpp"
#include "PrintConfig.hpp"
namespace Slic3r {
// Decides which extrusions get "first layer" treatment (no fan, slow speed,
// initial-layer accel/jerk, deferred temperature drop) by reference to a
// configurable plane in slicing-frame coordinates rather than the slicing
// layer index.
//
// On a normal flat-bed printer the plane is XY at slicing_Z = 0 and the
// evaluator is INACTIVE — every call site short-circuits back to the legacy
// `Layer::id() == 0` test. On a belt printer with a Z-from-Y shear the
// belt surface (machine_Z = 0) maps to a plane in slicing-frame coordinates
// derived from the gcode axis remap, so layer-index-based detection no
// longer matches the physical first printed surface.
//
// Plane representation: unit normal `n` (slicing frame) and offset along
// the normal such that the plane equation is `n · p == offset`. Signed
// perpendicular distance is `d(p) = n · p - offset`. Positive distance
// means "away from the belt surface", negative means "below the plane".
class FirstLayerPlane
{
public:
explicit FirstLayerPlane(const PrintConfig &config);
// Inactive when the legacy XY layer-index path should be used. This
// covers all non-belt printers and any belt printer where the user
// explicitly picked XY mode.
bool is_active() const { return m_active; }
FirstLayerPlaneMode effective_mode() const{ return m_mode; }
double band_thickness_mm() const { return m_thickness_mm; }
const Vec3d & normal() const { return m_normal; }
double plane_offset() const { return m_offset; }
// Signed perpendicular distance from a slicing-frame point to the plane.
double distance_from_plane(const Vec3d &point_slicing_mm) const;
// True if perpendicular distance < first_layer_height_mm. When the
// evaluator is inactive this returns false (call sites should fall back
// to the legacy per-layer path before reaching this function).
bool is_first_layer(const Vec3d &point_slicing_mm,
double first_layer_height_mm) const;
// floor((distance - 0) / band_thickness), clamped to [0, +inf). Used
// for "first N layers" thresholds (fan, slow_down_layers). Returns 0
// for points within the band. Returns INT_MAX/2 when inactive.
int effective_layer_index(const Vec3d &point_slicing_mm) const;
// Min effective index over a 2D bbox at a fixed slicing_Z. Used for
// layer-level decisions (e.g. temperature transition gate) where we
// don't want to walk every extrusion in the layer. For axis-aligned
// planes this is exact; for tilted planes it's a tight lower bound
// (the plane projection of the bbox's extreme corner).
int min_effective_index_for_xy_bbox(const BoundingBoxf &xy_bbox_mm,
double slicing_z_mm) const;
// Same as above but the bbox spans a Z range too.
int min_effective_index_for_bbox3(const BoundingBoxf3 &bbox_mm) const;
private:
bool m_active = false;
FirstLayerPlaneMode m_mode = FirstLayerPlaneMode::XY;
Vec3d m_normal = Vec3d::UnitZ(); // unit, slicing frame
double m_offset = 0.0; // n·p == m_offset
double m_thickness_mm = 0.0;
};
} // namespace Slic3r
#endif // slic3r_FirstLayerPlane_hpp_

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,8 @@
#include "libslic3r.h"
#include "ExPolygon.hpp"
#include "GCodeWriter.hpp"
#include "BeltGCodeWriter.hpp"
#include "FirstLayerPlane.hpp"
#include "Layer.hpp"
#include "Point.hpp"
#include "PlaceholderParser.hpp"
@@ -206,16 +208,18 @@ public:
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max())),
// BBS
m_toolchange_count(0),
m_nominal_z(0.)
m_nominal_z(0.),
m_writer(std::make_unique<GCodeWriter>())
{}
~GCode() = default;
virtual ~GCode() = default;
public:
// throws std::runtime_exception on error,
// throws CanceledException through print->throw_if_canceled().
void do_export(Print* print, const char* path, GCodeProcessorResult* result = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
void export_layer_filaments(GCodeProcessorResult* result);
//BBS: set offset for gcode writer
void set_gcode_offset(double x, double y) { m_writer.set_xy_offset(x, y); m_processor.set_xy_offset(x, y);}
void set_gcode_offset(double x, double y) { m_writer->set_xy_offset(x, y); m_processor.set_xy_offset(x, y);}
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
const Vec2d& origin() const { return m_origin; }
@@ -229,8 +233,8 @@ public:
Vec3d point_to_gcode_quantized(const Point3& point) const;
const FullPrintConfig &config() const { return m_config; }
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
const GCodeWriter& writer() const { return m_writer; }
GCodeWriter& writer() { return *m_writer; }
const GCodeWriter& writer() const { return *m_writer; }
PlaceholderParser& placeholder_parser() { return m_placeholder_parser_integration.parser; }
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser_integration.parser; }
// Process a template through the placeholder parser, collect error messages to be reported
@@ -252,7 +256,7 @@ public:
std::string travel_to(const Point& point, ExtrusionRole role, std::string comment, double z = DBL_MAX);
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::NormalLift, bool apply_instantly = false, ExtrusionRole role = erNone);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string unretract() { return m_writer->unlift() + m_writer->unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z, bool by_object=false, int toolchange_temp_override = -1);
bool is_BBL_Printer();
WipeTowerType wipe_tower_type();
@@ -304,7 +308,15 @@ public:
}
};
private:
// Public accessor for the first-layer plane evaluator. Used by
// CoolingBuffer (which is constructed with a GCode reference and needs
// to read the plane for per-segment fan re-evaluation). All other
// first-layer-plane access points (on_first_layer overload, effective
// index helper) are in the protected section since they're called from
// GCode internals only.
const FirstLayerPlane *first_layer_plane() const { return m_first_layer_plane.get(); }
protected:
class GCodeOutputStream {
public:
GCodeOutputStream(FILE *f, GCodeProcessor &processor) : f(f), m_processor(processor) {}
@@ -332,9 +344,17 @@ private:
FILE *f = nullptr;
GCodeProcessor &m_processor;
};
// Virtual hooks for belt printer subclass (BeltGCode).
// No-ops in base GCode; overridden in BeltGCode.
virtual void init_belt_writer(Print &print, bool is_bbl_printers) {}
virtual void write_belt_header(GCodeOutputStream &file, const Print &print) {}
virtual void on_set_origin(const PrintObject *obj, const Point &inst_shift) {}
virtual bool should_disable_arc_fitting() const { return false; }
void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb);
static std::vector<LayerToPrint> collect_layers_to_print(const PrintObject &object);
static std::vector<LayerToPrint> collect_layers_to_print(const PrintObject &object, bool skip_empty_first_layer = false);
static std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> collect_layers_to_print(const Print &print);
std::string generate_skirt(const Print &print,
@@ -518,7 +538,7 @@ private:
DynamicConfig m_calib_config;
// scaled G-code resolution
double m_scaled_resolution;
GCodeWriter m_writer;
std::unique_ptr<GCodeWriter> m_writer;
struct PlaceholderParserIntegration {
void reset();
@@ -609,6 +629,11 @@ private:
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
std::unique_ptr<SpiralVase> m_spiral_vase;
// First-layer plane evaluator. Constructed once per print from the
// PrintConfig. is_active() == false on non-belt printers and on belt
// printers without a Z-axis shear; in that case all per-path plane
// checks short-circuit to the legacy Layer::id() == 0 path.
std::unique_ptr<FirstLayerPlane> m_first_layer_plane;
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
@@ -668,6 +693,25 @@ private:
// On the first printing layer. This flag triggers first layer speeds.
//BBS
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0 && abs(m_layer->bottom_z()) < EPSILON; }
// Per-point first-layer test. When the FirstLayerPlane evaluator is
// active, the result depends on the supplied slicing-frame point;
// otherwise we delegate to the legacy per-layer test. This is the
// entry point used by per-path call sites in _extrude.
bool on_first_layer(const Vec3d &point_slicing_mm) const {
if (m_first_layer_plane && m_first_layer_plane->is_active())
return m_first_layer_plane->is_first_layer(
point_slicing_mm, m_config.initial_layer_print_height.value);
return on_first_layer();
}
// "Effective layer index" used to drive layer-count thresholds like
// slow_down_layers. When the evaluator is active this returns the
// perpendicular distance to the plane in band_thickness_mm units;
// otherwise it returns the legacy slicing layer index.
int effective_layer_index_for_point(const Vec3d &point_slicing_mm) const {
if (m_first_layer_plane && m_first_layer_plane->is_active())
return m_first_layer_plane->effective_layer_index(point_slicing_mm);
return on_first_layer() ? 0 : layer_id();
}
int layer_id() const {
if (m_layer == nullptr)
return -1;

View File

@@ -0,0 +1,40 @@
#include "BeltBackTransform.hpp"
#include "../BeltTransform.hpp"
namespace Slic3r {
bool BeltBackTransform::init_from_config(const PrintConfig &config)
{
m_active = false;
m_inverse = Transform3d::Identity();
if (!config.belt_printer.value || !config.gcode_back_transform.value)
return false;
// Require at least one active transform to proceed.
bool has_global_rotation = config.belt_slice_rotation_global.value
&& config.belt_slice_rotation.value != BeltRotationAxis::None;
bool has_preslice_global = config.belt_preslice_global.value
|| config.preslice_remap_global.value;
if (!has_global_rotation && !has_preslice_global
&& !BeltTransformPipeline::has_preslice_remap(config))
return false;
// Build the forward pipeline (rotation * pre_remap) and store its inverse.
Transform3d forward = BeltTransformPipeline::build_forward_transform(config);
if (forward.isApprox(Transform3d::Identity()))
return false;
m_inverse = forward.inverse();
m_active = true;
return true;
}
Vec3d BeltBackTransform::apply(const Vec3d &pos) const
{
if (!m_active)
return pos;
return m_inverse * pos;
}
} // namespace Slic3r

View File

@@ -0,0 +1,45 @@
#ifndef slic3r_BeltBackTransform_hpp_
#define slic3r_BeltBackTransform_hpp_
#include "../libslic3r.h"
#include "../Point.hpp"
#include "../PrintConfig.hpp"
namespace Slic3r {
// Reverses the pre-slice remap + shear + scale transforms that
// PrintObjectSlice.cpp applies to belt printer geometry, converting G-code
// coordinates from the sliced (remapped/sheared/scaled) frame back to the
// machine's real coordinate space.
//
// Initialized once from PrintConfig, then applied per-point in
// GCodeWriter::to_machine_coords() before axis remapping.
//
// Active when gcode_back_transform is true AND at least one of:
// - a shear axis has global mode enabled, or
// - a pre-slice axis remap is non-identity.
class BeltBackTransform
{
public:
BeltBackTransform() = default;
// Initialize from belt printer config. Rebuilds the same pre-slice remap,
// shear, and scale matrices as PrintObjectSlice.cpp and precomputes the
// affine inverse. Returns true if a non-identity back-transform was computed.
bool init_from_config(const PrintConfig &config);
// Apply the inverse transform to a point. Returns pos unchanged if
// no back-transform is active.
Vec3d apply(const Vec3d &pos) const;
// True if a non-identity back-transform is active.
bool is_active() const { return m_active; }
private:
bool m_active = false;
Transform3d m_inverse = Transform3d::Identity();
};
} // namespace Slic3r
#endif // slic3r_BeltBackTransform_hpp_

View File

@@ -1,10 +1,14 @@
#include "../GCode.hpp"
#include "../FirstLayerPlane.hpp"
#include "CoolingBuffer.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/log/trivial.hpp>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <float.h>
#include <string_view>
#include <system_error>
#include <unordered_map>
@@ -28,6 +32,12 @@ CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_t
m_num_extruders = std::max(ex.id() + 1, m_num_extruders);
m_extruder_ids.emplace_back(ex.id());
}
// Borrow the first-layer plane from the GCode generator. When inactive
// (non-belt printers and belt printers without Z shear), per-line fan
// re-evaluation is skipped and behavior is bit-identical to the legacy
// per-layer path.
m_first_layer_plane = gcodegen.first_layer_plane();
}
void CoolingBuffer::reset(const Vec3d &position)
@@ -328,6 +338,13 @@ std::string CoolingBuffer::process_layer(std::string &&gcode, size_t layer_id, b
std::vector<PerExtruderAdjustments> per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos);
float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments);
out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments);
// First-layer plane: per-segment fan re-evaluation post-pass. Walks
// the cooled-down gcode and inserts inline M106 commands at band
// crossings (where the path's perpendicular distance to the plane
// crosses close_fan_the_first_x_layers thresholds). No-op when
// the evaluator is inactive.
if (m_first_layer_plane && m_first_layer_plane->is_active())
out = this->apply_first_layer_plane_fan_eval(std::move(out), layer_id, layer_time_stretched);
m_gcode.clear();
}
return out;
@@ -1014,4 +1031,214 @@ std::string CoolingBuffer::apply_layer_cooldown(
return new_gcode;
}
// Pure helper: compute the main fan speed for a given effective layer index.
// Mirrors the inline logic in change_extruder_set_fan but is callable from
// per-line code in apply_first_layer_plane_fan_eval.
int CoolingBuffer::compute_main_fan_speed(int effective_layer_id, float layer_time,
unsigned int extruder_id) const
{
#define EXTRUDER_CFG(opt) m_config.opt.get_at(extruder_id)
float fan_min_speed = EXTRUDER_CFG(fan_min_speed);
float fan_max_speed = EXTRUDER_CFG(fan_max_speed);
bool reduce_fan_stop_start_freq = EXTRUDER_CFG(reduce_fan_stop_start_freq);
int close_fan_the_first_x_layers = EXTRUDER_CFG(close_fan_the_first_x_layers);
int full_fan_speed_layer = EXTRUDER_CFG(full_fan_speed_layer);
float slow_down_layer_time = float(EXTRUDER_CFG(slow_down_layer_time));
float fan_cooling_layer_time = float(EXTRUDER_CFG(fan_cooling_layer_time));
#undef EXTRUDER_CFG
if (close_fan_the_first_x_layers <= 0 && full_fan_speed_layer > 0)
close_fan_the_first_x_layers = 1;
float fan_speed_new = reduce_fan_stop_start_freq ? fan_min_speed : 0.f;
if (effective_layer_id >= close_fan_the_first_x_layers) {
if (layer_time < slow_down_layer_time) {
fan_speed_new = fan_max_speed;
} else if (layer_time < fan_cooling_layer_time) {
double t = (layer_time - slow_down_layer_time) /
(fan_cooling_layer_time - slow_down_layer_time);
fan_speed_new = float(int(floor(t * fan_min_speed +
(1. - t) * fan_max_speed) + 0.5));
}
if (effective_layer_id + 1 < full_fan_speed_layer) {
float factor = float(effective_layer_id + 1 - close_fan_the_first_x_layers)
/ float(full_fan_speed_layer - close_fan_the_first_x_layers);
fan_speed_new = float(std::clamp(int(fan_speed_new * factor + 0.5f), 0, 255));
}
} else {
fan_speed_new = 0.f;
}
return int(fan_speed_new);
}
// Post-pass: walk the cooled-down gcode line by line, track XYZ position,
// and insert M106 commands at first-layer-plane band crossings so the fan
// follows perpendicular distance to the plane rather than the slicing-layer
// index. Only invoked when the FirstLayerPlane evaluator is active.
//
// This implementation is intentionally minimal: it overrides only the MAIN
// fan (the one set by GCodeWriter::set_fan); overhang/internal-bridge/etc
// special fans remain at their layer-level values from apply_layer_cooldown.
// That keeps the per-line logic small while still giving the user precise
// fan control near the belt surface, which is the main quality concern.
std::string CoolingBuffer::apply_first_layer_plane_fan_eval(
std::string &&gcode_in, size_t /*layer_id*/, float layer_time)
{
if (!m_first_layer_plane || !m_first_layer_plane->is_active())
return std::move(gcode_in);
const std::string &gcode = gcode_in;
std::string out;
out.reserve(gcode.size() + 256);
// Match the PWM floor applied at every other set_fan call in this file so
// band-crossing M106 emissions start the fan reliably at low speeds.
const unsigned int part_cooling_fan_min_pwm = static_cast<unsigned int>(std::max(0, m_config.part_cooling_fan_min_pwm.value));
// Track position in slicing-frame mm. Seed from m_current_pos which the
// CoolingBuffer keeps up-to-date across layers.
Vec3d cur_pos_mm(m_current_pos[0], m_current_pos[1], m_current_pos[2]);
// Track current main fan speed by parsing M106 commands as we walk so
// we can restore it after a band exit.
int current_main_fan = m_fan_speed;
int pre_band_main_fan = current_main_fan;
// Implicit initial state: assume the layer started "out of the band"
// (i.e., the layer-level fan setting from apply_layer_cooldown is in
// effect). The first movement we encounter will reconcile this.
bool in_first_layer_band = false;
unsigned int active_extruder = m_current_extruder;
auto parse_xyz_into = [](const std::string_view &line_sv, Vec3d &p) {
if (line_sv.size() < 3) return false;
if (line_sv[0] != 'G') return false;
if (line_sv[1] != '0' && line_sv[1] != '1') return false;
if (line_sv[2] != ' ' && line_sv[2] != '\t') return false;
const char *c = line_sv.data() + 3;
const char *end = line_sv.data() + line_sv.size();
bool any = false;
while (c < end && *c != ';') {
while (c < end && (*c == ' ' || *c == '\t')) ++c;
if (c >= end || *c == ';' || *c == '\n' || *c == '\r') break;
char axis = *c;
++c;
if (axis == 'X' || axis == 'Y' || axis == 'Z') {
char *next;
double v = std::strtod(c, &next);
if (next != c) {
if (axis == 'X') p.x() = v;
else if (axis == 'Y') p.y() = v;
else p.z() = v;
c = next;
any = true;
continue;
}
}
// Skip unrecognized word.
while (c < end && *c != ' ' && *c != '\t' && *c != ';' && *c != '\n')
++c;
}
return any;
};
auto parse_m106 = [](const std::string_view &line_sv) -> int {
// Returns -1 if not an M106, otherwise the S value (0..255).
if (line_sv.size() < 4 || line_sv[0] != 'M') return -1;
if (!(line_sv[1] == '1' && line_sv[2] == '0' && line_sv[3] == '6'))
return -1;
// Find S<value>
size_t s_pos = line_sv.find('S');
if (s_pos == std::string_view::npos) return -1;
const char *c = line_sv.data() + s_pos + 1;
char *next;
long v = std::strtol(c, &next, 10);
if (next == c) return -1;
return int(std::clamp<long>(v, 0, 255));
};
auto parse_m107 = [](const std::string_view &line_sv) -> bool {
return line_sv.size() >= 4 && line_sv[0] == 'M' &&
line_sv[1] == '1' && line_sv[2] == '0' && line_sv[3] == '7';
};
auto parse_tool_change = [this](const std::string_view &line_sv) -> int {
// Returns the new extruder id, or -1 if not a toolchange.
if (line_sv.size() < m_toolchange_prefix.size() + 1) return -1;
if (line_sv.compare(0, m_toolchange_prefix.size(), m_toolchange_prefix) != 0)
return -1;
const char *c = line_sv.data() + m_toolchange_prefix.size();
char *next;
long v = std::strtol(c, &next, 10);
if (next == c) return -1;
return int(v);
};
const char *p = gcode.c_str();
const char *end = gcode.c_str() + gcode.size();
while (p < end) {
const char *line_end = p;
while (line_end < end && *line_end != '\n') ++line_end;
const char *next_line = line_end;
if (next_line < end) ++next_line; // include the '\n'
std::string_view line_sv(p, line_end - p);
// Track tool changes so the per-line fan eval uses the right extruder.
int new_tool = parse_tool_change(line_sv);
if (new_tool >= 0)
active_extruder = unsigned(new_tool);
// Track existing fan commands so we can restore the right value when
// exiting a band.
int m106_speed = parse_m106(line_sv);
if (m106_speed >= 0) {
current_main_fan = m106_speed;
if (!in_first_layer_band)
pre_band_main_fan = m106_speed;
} else if (parse_m107(line_sv)) {
current_main_fan = 0;
if (!in_first_layer_band)
pre_band_main_fan = 0;
}
// Movement line: parse XYZ, evaluate plane, possibly emit a fan
// change BEFORE this line.
bool moved = parse_xyz_into(line_sv, cur_pos_mm);
if (moved) {
const int eff_idx = m_first_layer_plane->effective_layer_index(cur_pos_mm);
const int close_n = m_config.close_fan_the_first_x_layers.get_at(active_extruder);
const bool now_in_band = eff_idx < std::max(close_n, 1);
if (now_in_band != in_first_layer_band) {
// Band crossing: emit a M106 with the appropriate speed.
int target_fan;
if (now_in_band) {
// Entering the first-layer band: fan off.
pre_band_main_fan = current_main_fan;
target_fan = compute_main_fan_speed(eff_idx, layer_time, active_extruder);
} else {
// Exiting the band: restore the layer's normal fan speed.
// Use compute_main_fan_speed with the effective index so
// the linear ramp factor (close_fan→full_fan_speed_layer)
// also follows distance from the plane.
target_fan = compute_main_fan_speed(eff_idx, layer_time, active_extruder);
if (target_fan == 0)
target_fan = pre_band_main_fan;
}
if (target_fan != current_main_fan) {
out += GCodeWriter::set_fan(m_config.gcode_flavor, target_fan, part_cooling_fan_min_pwm);
current_main_fan = target_fan;
m_fan_speed = target_fan;
m_current_fan_speed = target_fan;
}
in_first_layer_band = now_in_band;
}
}
out.append(p, next_line - p);
p = next_line;
}
return out;
}
} // namespace Slic3r

View File

@@ -10,6 +10,7 @@ namespace Slic3r {
class GCode;
class Layer;
class FirstLayerPlane;
struct PerExtruderAdjustments;
// A standalone G-code filter, to control cooling of the print.
@@ -18,7 +19,7 @@ struct PerExtruderAdjustments;
//
// The simple it sounds, the actual implementation is significantly more complex.
// Namely, for a multi-extruder print, each material may require a different cooling logic.
// For example, some materials may not like to print too slowly, while with some materials
// For example, some materials may not like to print too slowly, while with some materials
// we may slow down significantly.
//
class CoolingBuffer {
@@ -36,6 +37,21 @@ private:
// Returns the adjusted G-code.
std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector<PerExtruderAdjustments> &per_extruder_adjustments);
// First-layer plane: per-line fan re-evaluation post-pass. Walks the
// post-cooldown gcode, tracks XYZ position, and inserts M106 commands at
// band-crossing transitions in slicing-frame coordinates. Only runs
// when m_first_layer_plane is active.
std::string apply_first_layer_plane_fan_eval(std::string &&gcode_in,
size_t layer_id,
float layer_time);
// Pure helper: compute the main fan speed for a given effective layer
// index (layer-id units, mapped through the plane evaluator) and the
// current extruder. Mirrors the inline logic in the change_extruder_set_fan
// lambda but is callable from per-line code.
int compute_main_fan_speed(int effective_layer_id, float layer_time,
unsigned int extruder_id) const;
// G-code snippet cached for the support layers preceding an object layer.
std::string m_gcode;
// Internal data.
@@ -57,6 +73,9 @@ private:
unsigned int m_current_extruder;
//BBS: current fan speed
int m_current_fan_speed;
// First-layer plane evaluator, borrowed from GCode. Null = inactive
// (legacy per-layer fan control).
const FirstLayerPlane *m_first_layer_plane = nullptr;
};
}

View File

@@ -3072,6 +3072,44 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
return;
}
// Belt printer: derive the physical tilt magnitude from the slicing-rotation
// angle header comment (used to enable the preview's belt view).
if (boost::starts_with(comment, " belt_slice_rotation_angle = ")) {
try {
m_result.belt_tilt_angle = std::abs(std::stof(std::string(comment.substr(29))));
} catch (...) {}
return;
}
// Belt printer: parse pre-slice axis remap from header comments.
{
auto trim = [](const std::string &s) -> std::string {
size_t start = s.find_first_not_of(" \t\r\n");
size_t end = s.find_last_not_of(" \t\r\n");
return (start == std::string::npos) ? "" : s.substr(start, end - start + 1);
};
// Pre-slice axis remap
auto parse_remap_axis = [](const std::string &s) -> RemapAxis {
if (s == "pos_x") return RemapAxis::PosX;
if (s == "pos_y") return RemapAxis::PosY;
if (s == "pos_z") return RemapAxis::PosZ;
if (s == "neg_x") return RemapAxis::NegX;
if (s == "neg_y") return RemapAxis::NegY;
if (s == "neg_z") return RemapAxis::NegZ;
if (s == "rev_x") return RemapAxis::RevX;
if (s == "rev_y") return RemapAxis::RevY;
if (s == "rev_z") return RemapAxis::RevZ;
return RemapAxis::PosX;
};
if (boost::starts_with(comment, " preslice_remap_x = ")) {
m_result.preslice_remap_x = parse_remap_axis(trim(std::string(comment.substr(25)))); return;
}
if (boost::starts_with(comment, " preslice_remap_y = ")) {
m_result.preslice_remap_y = parse_remap_axis(trim(std::string(comment.substr(25)))); return;
}
if (boost::starts_with(comment, " preslice_remap_z = ")) {
m_result.preslice_remap_z = parse_remap_axis(trim(std::string(comment.substr(25)))); return;
}
}
// wipe start tag
if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
m_wiping = true;
@@ -4895,6 +4933,13 @@ void GCodeProcessor::process_G92(const GCodeReader::GCodeLine& line)
if (line.has_z()) {
m_origin[Z] = m_end_position[Z] - line.z() * lengths_scale_factor;
any_found = true;
// Belt only: the start G-code's purge-blob advance + G92 Z0 resets leave a constant
// machine-Z origin offset here; the designed-view back-transform subtracts it so
// toolpaths map to the model's belt coordinate (gcode Z). Gated on belt_tilt_angle
// (set from the belt header, parsed before the body) so non-belt G-code processing
// is byte-identical — no unconditional work on the shared path.
if (m_result.belt_tilt_angle != 0.f)
m_result.belt_z_origin = m_origin[Z];
}
if (line.has_e()) {

View File

@@ -245,6 +245,17 @@ class Print;
bool support_traditional_timelapse{true};
float printable_height;
float z_offset;
// Belt printer: physical tilt magnitude (deg) parsed from the slicing-rotation
// header comment; used to enable the preview's belt view.
float belt_tilt_angle{ 0.f };
// Belt printer: machine-Z origin offset (mm) left in m_origin[Z] by the start
// G-code (purge-blob belt advance + G92 Z0 resets). Move positions are stored
// as gcode_Z + this offset, so the designed-view back-transform must subtract it
// to recover the model's belt coordinate.
float belt_z_origin{ 0.f };
RemapAxis preslice_remap_x{ RemapAxis::PosX };
RemapAxis preslice_remap_y{ RemapAxis::PosY };
RemapAxis preslice_remap_z{ RemapAxis::PosZ };
SettingsIds settings_ids;
size_t filaments_count;
bool backtrace_enabled;
@@ -310,6 +321,11 @@ class Print;
optimal_assignment = other.optimal_assignment;
filament_change_count_map = other.filament_change_count_map;
initial_layer_time = other.initial_layer_time;
belt_tilt_angle = other.belt_tilt_angle;
belt_z_origin = other.belt_z_origin;
preslice_remap_x = other.preslice_remap_x;
preslice_remap_y = other.preslice_remap_y;
preslice_remap_z = other.preslice_remap_z;
#if ENABLE_GCODE_VIEWER_STATISTICS
time = other.time;
#endif

View File

@@ -0,0 +1,74 @@
#include "MachineFrameTransform.hpp"
#include "../Geometry.hpp"
#include <cmath>
namespace Slic3r {
bool MachineFrameTransform::init_from_config(const PrintConfig &config)
{
m_active = false;
m_transform = Transform3d::Identity();
if (!config.belt_printer.value)
return false;
// The machine-frame transform is derived from the single belt tilt (axis +
// angle) that also drives the pre-slice mesh rotation. Expert decouple lets
// the machine-frame angle differ from the slicing rotation; otherwise both
// use belt_slice_rotation_angle.
const BeltRotationAxis axis = config.belt_slice_rotation.value;
if (axis == BeltRotationAxis::None || axis == BeltRotationAxis::Z)
return false; // Z is an in-plane spin: no machine-frame tilt.
const double angle_deg = config.belt_frame_tilt_decouple.value
? config.belt_frame_tilt_angle.value
: config.belt_slice_rotation_angle.value;
if (std::abs(angle_deg) <= EPSILON)
return false;
const double angle_rad = Geometry::deg2rad(angle_deg);
const double cos_a = std::cos(angle_rad);
if (std::abs(cos_a) <= EPSILON)
return false;
const double tan_a = std::sin(angle_rad) / cos_a;
const double inv_cos = 1.0 / cos_a;
// Couple the height axis (Z) to the belt-feed axis and stretch the belt-feed
// axis by 1/cos so a unit slicing move maps to the correct belt travel. The
// shear sign matches the belt-floor slope derived from the same rotation in
// BeltTransformPipeline::compute_belt_height_and_floor:
// tilt about X: feed axis Y, Z += +tan·Y, scale Y *= 1/cos
// tilt about Y: feed axis X, Z += -tan·X, scale X *= 1/cos
Matrix3d shear = Matrix3d::Identity();
Matrix3d scale = Matrix3d::Identity();
if (axis == BeltRotationAxis::X) {
shear(2, 1) = tan_a; // Z from Y
scale(1, 1) = inv_cos; // Y
} else { // BeltRotationAxis::Y
shear(2, 0) = -tan_a; // Z from X
scale(0, 0) = inv_cos; // X
}
// Apply shear first, then scale (the historical default ShearThenScale order:
// result = scale * shear * p). For the canonical 45°/X belt this maps
// (x,y,z) -> (x, y/cos, y + z), matching the previous per-axis config.
Transform3d combined = Transform3d::Identity();
combined.linear() = scale * shear;
if (combined.isApprox(Transform3d::Identity()))
return false;
m_transform = combined;
m_active = true;
return true;
}
Vec3d MachineFrameTransform::apply(const Vec3d &pos) const
{
if (!m_active)
return pos;
return m_transform * pos;
}
} // namespace Slic3r

View File

@@ -0,0 +1,48 @@
#ifndef slic3r_MachineFrameTransform_hpp_
#define slic3r_MachineFrameTransform_hpp_
#include "../libslic3r.h"
#include "../Point.hpp"
#include "../PrintConfig.hpp"
namespace Slic3r {
// Post-stage machine-frame transform for belt printers.
//
// Applied in BeltGCodeWriter::to_machine_coords AFTER the back-transform and
// the gcode_remap_* axis remap. Maps Cartesian (axis-permuted) G-code
// coordinates into the printer's physical machine frame.
//
// Derived entirely from the single belt tilt (belt_slice_rotation axis +
// belt_slice_rotation_angle): a shear coupling the height axis to the belt-feed
// axis (factor tan a) plus a 1/cos a scale on the belt-feed axis. The expert
// belt_frame_tilt_decouple flag lets the machine-frame angle differ from the
// pre-slice rotation angle via belt_frame_tilt_angle.
class MachineFrameTransform
{
public:
MachineFrameTransform() = default;
// Initialize from belt printer config. Returns true if a non-identity
// transform was computed. Inactive when belt_printer is disabled or
// both shear and scale are identity.
bool init_from_config(const PrintConfig &config);
// Apply the transform to a point. Returns pos unchanged if not active.
Vec3d apply(const Vec3d &pos) const;
bool is_active() const { return m_active; }
// The composed shear*scale transform (identity when inactive). Exposed so the
// G-code viewer can build the machine->model back-transform for the upright
// ("designed") belt preview.
const Transform3d& transform() const { return m_transform; }
private:
bool m_active = false;
Transform3d m_transform = Transform3d::Identity();
};
} // namespace Slic3r
#endif // slic3r_MachineFrameTransform_hpp_

Some files were not shown because too many files have changed in this diff Show More