mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-17 19:36:28 +02:00
feat(slicing): build-plate override in the SliceModal (#1337)
Slicing an STL via the integrated slicer always defaulted to whatever
curr_bed_type lived in the chosen process preset (typically "Cool
Plate"), which the slicer CLI rejected for high-temp filaments with
"Plate 1: Cool Plate does not support filament 1". The user had no
way to switch plates without cloning the preset in BambuStudio.
The Slice modal now exposes a Build plate dropdown with the six
canonical BambuStudio / OrcaSlicer plates (Cool Plate, Cool Plate
SuperTack, Engineering Plate, High Temp Plate, Textured PEI Plate,
Smooth PEI Plate) plus an "Auto (use process preset)" option that
preserves the previous behavior. Positioned between Process profile
and Filament rows so a long filament list never pushes it off the
modal's scrolled viewport, and always enabled regardless of whether
the user picked a Printer Preset Bundle.
A new bed_type field on SliceRequest flows through both dispatch
paths:
- Resolved-preset path: _patch_process_bed_type overwrites
curr_bed_type on the process JSON before forwarding to the sidecar.
Works end-to-end today, no sidecar change needed.
- Bundle dispatch path: slice_with_bundle adds a bedType form field
to the sidecar multipart. The sidecar (maziggy/orca-slicer-api
fork) needs a matching change to honor it as --curr_bed_type on
the CLI invocation; until then the field is silently ignored and
the slice runs with the bundle's default plate.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""Regression tests for the #1337 bed-type override on slice requests.
|
||||
|
||||
The SliceRequest schema accepts an optional `bed_type` string that the
|
||||
slice route patches onto the resolved process-profile JSON as
|
||||
`curr_bed_type` before forwarding to the sidecar. Without this hook,
|
||||
slicing high-temp filaments (ABS, ASA, PC) onto a process preset whose
|
||||
default plate is "Cool Plate" fails with the slicer-CLI error
|
||||
"Plate 1: Cool Plate does not support filament 1" and the user has no
|
||||
way to switch plates short of cloning the preset.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from backend.app.api.routes.library import _patch_process_bed_type
|
||||
from backend.app.schemas.slicer import PresetRef, SliceRequest
|
||||
|
||||
|
||||
class TestSliceRequestBedTypeField:
|
||||
def test_bed_type_defaults_to_none(self):
|
||||
req = SliceRequest(
|
||||
printer_preset=PresetRef(source="local", id="1"),
|
||||
process_preset=PresetRef(source="local", id="2"),
|
||||
filament_preset=PresetRef(source="local", id="3"),
|
||||
)
|
||||
assert req.bed_type is None
|
||||
|
||||
def test_bed_type_accepts_canonical_values(self):
|
||||
for value in (
|
||||
"Cool Plate",
|
||||
"Cool Plate (SuperTack)",
|
||||
"Engineering Plate",
|
||||
"High Temp Plate",
|
||||
"Textured PEI Plate",
|
||||
"Smooth PEI Plate",
|
||||
):
|
||||
req = SliceRequest(
|
||||
printer_preset=PresetRef(source="local", id="1"),
|
||||
process_preset=PresetRef(source="local", id="2"),
|
||||
filament_preset=PresetRef(source="local", id="3"),
|
||||
bed_type=value,
|
||||
)
|
||||
assert req.bed_type == value
|
||||
|
||||
def test_bed_type_rejects_overlong_input(self):
|
||||
with pytest.raises(ValidationError):
|
||||
SliceRequest(
|
||||
printer_preset=PresetRef(source="local", id="1"),
|
||||
process_preset=PresetRef(source="local", id="2"),
|
||||
filament_preset=PresetRef(source="local", id="3"),
|
||||
bed_type="x" * 65,
|
||||
)
|
||||
|
||||
|
||||
class TestPatchProcessBedType:
|
||||
def test_overwrites_existing_curr_bed_type(self):
|
||||
process_json = json.dumps({"name": "0.20mm Standard", "curr_bed_type": "Cool Plate"})
|
||||
result = _patch_process_bed_type(process_json, "Textured PEI Plate")
|
||||
assert json.loads(result)["curr_bed_type"] == "Textured PEI Plate"
|
||||
|
||||
def test_adds_curr_bed_type_when_missing(self):
|
||||
process_json = json.dumps({"name": "0.20mm Standard"})
|
||||
result = _patch_process_bed_type(process_json, "Engineering Plate")
|
||||
parsed = json.loads(result)
|
||||
assert parsed["curr_bed_type"] == "Engineering Plate"
|
||||
# Other fields preserved
|
||||
assert parsed["name"] == "0.20mm Standard"
|
||||
|
||||
def test_returns_input_unchanged_when_json_is_invalid(self):
|
||||
# The slicer would error on this anyway; the patch helper is a
|
||||
# straight passthrough so failure modes stay attributable to the
|
||||
# original input rather than the patch.
|
||||
bogus = "not a json document"
|
||||
assert _patch_process_bed_type(bogus, "Cool Plate") is bogus
|
||||
|
||||
def test_returns_input_unchanged_when_json_is_not_a_dict(self):
|
||||
not_a_dict = json.dumps(["this", "is", "an", "array"])
|
||||
assert _patch_process_bed_type(not_a_dict, "Cool Plate") is not_a_dict
|
||||
Reference in New Issue
Block a user