mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-06 23:31:19 +00:00
Design tab: Text is its own feature, previewed in the view and editable
Reported on the rig: Text showed no preview where it would go, its dialog was pinned over the middle of the window (GNOME attaches a modal dialog to its parent and it cannot be moved), and once confirmed the text could not be edited and did not appear in the feature tree. Inside an open sketch it became loose lines of that sketch. - Text is always a feature, "Text N" in the tree. A new text goes on the plane of the open sketch (committed first when it holds anything, closed when it is empty), else centred on the picked face, else on the reference plane. - The dialog is modeless and opens at the top right of the window. The feature is created at the first character and redrawn on every change, so the text appears in the view where it will be as it is typed. Enter inserts it, then the usual move/scale gizmo and Confirm; Esc, Cancel or closing the dialog takes it out again (undo to the checkpoint taken when it appeared). - CadFeature keeps text_string, text_font (the WxFontUtils descriptor) and text_height, appended at the end of the framed recipe. Editing a Text feature reopens the dialog with them and redraws the outline in place, keeping its placement. The outlines are still saved, so the project opens the same on a machine without that font. - The MCP control refuses writes while the Text dialog is open. Tests: the text parameters survive a save and load along with the outline; the truncated-recipe test accounts for the new tail fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
This commit is contained in:
@@ -2348,11 +2348,12 @@ TEST_CASE("a truncated feature keeps what it could read", "[CadDocument][recipe]
|
||||
|
||||
// Shorten feature 1 so it ends right after coordsys_face_kind: drop coordsys_face_edges
|
||||
// (4 bytes), the two flags appended after it (thread_major_nominal, pattern_inclusive:
|
||||
// 1 byte each) and the empty dressup_edges list (its 8-byte size tag). Rewrite its length
|
||||
// prefix and erase the tail bytes. The reader then runs out inside fa(f), throws, and keeps
|
||||
// everything it had already assigned — that is the whole point of the try/catch. (Cut on a
|
||||
// field boundary: a field cut in half is read as whatever half arrived.)
|
||||
const size_t drop = sizeof(uint32_t) + 2 * sizeof(bool) + sizeof(cereal::size_type);
|
||||
// 1 byte each), the empty dressup_edges list and the two empty text strings (an 8-byte size
|
||||
// tag each) and text_height (a double). Rewrite its length prefix and erase the tail bytes.
|
||||
// The reader then runs out inside fa(f), throws, and keeps everything it had already
|
||||
// assigned — that is the whole point of the try/catch. (Cut on a field boundary: a field
|
||||
// cut in half is read as whatever half arrived.)
|
||||
const size_t drop = sizeof(uint32_t) + 2 * sizeof(bool) + 3 * sizeof(cereal::size_type) + sizeof(double);
|
||||
REQUIRE(f_len[1] > drop);
|
||||
std::string shortened = blob;
|
||||
shortened.erase(f_off[1] + 4 + f_len[1] - drop, drop);
|
||||
@@ -2371,6 +2372,7 @@ TEST_CASE("a truncated feature keeps what it could read", "[CadDocument][recipe]
|
||||
REQUIRE_FALSE(loaded.features[1].thread_major_nominal); // ...and so were the later flags
|
||||
REQUIRE_FALSE(loaded.features[1].pattern_inclusive);
|
||||
REQUIRE(loaded.features[1].dressup_edges.empty());
|
||||
REQUIRE_FALSE(loaded.features[1].is_text());
|
||||
REQUIRE(loaded.features[0].name == doc.features[0].name);
|
||||
REQUIRE(loaded.features[2].name == doc.features[2].name);
|
||||
}
|
||||
@@ -8079,6 +8081,31 @@ TEST_CASE("extrude: a profile that folds back on itself is refused with a reason
|
||||
REQUIRE(mp.volume > 0.0);
|
||||
}
|
||||
|
||||
TEST_CASE("text feature: its string, font and height survive a save and load", "[CadDocument][recipe]")
|
||||
{
|
||||
CadDocument doc;
|
||||
CadFeature f;
|
||||
f.type = CadFeatureType::Sketch;
|
||||
f.name = "Text 1";
|
||||
f.plane = SketchPlane::XY();
|
||||
f.imported_regions = { { { Vec2d(0, 0), Vec2d(4, 0), Vec2d(4, 6), Vec2d(0, 6) } } };
|
||||
f.text_string = "Ab ÷ 12";
|
||||
f.text_font = "Noto Sans;Bold";
|
||||
f.text_height = 7.5;
|
||||
doc.features.push_back(f);
|
||||
REQUIRE(doc.recompute());
|
||||
|
||||
CadDocument back;
|
||||
REQUIRE(back.deserialize_recipe(doc.serialize_recipe()));
|
||||
REQUIRE(back.features.size() == 1);
|
||||
const CadFeature& g = back.features[0];
|
||||
REQUIRE(g.is_text());
|
||||
REQUIRE(g.text_string == f.text_string);
|
||||
REQUIRE(g.text_font == f.text_font);
|
||||
REQUIRE(g.text_height == f.text_height);
|
||||
REQUIRE(g.imported_regions == f.imported_regions); // the outline is saved, not re-derived
|
||||
}
|
||||
|
||||
// Several picked edges dressed by ONE feature: every id is resolved against the same body, so
|
||||
// capturing them up-front is correct here (unlike the chain of single-edge features above).
|
||||
TEST_CASE("dressup: one fillet on four picked edges equals the Top face group", "[CadDocument][dressup]")
|
||||
|
||||
Reference in New Issue
Block a user