mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-18 14:32:36 +00:00
Design: Text and SVG draw INTO the open sketch instead of beside it
Mirror of snaporca 1fb7786d9a (DesignPanel.cpp and DesignCanvas.cpp applied as patches; parity 30 / 16, shared files byte-identical). With a sketch open, Text/SVG outlines become ordinary Line entities via push_closed_lines() instead of a separate Sketch feature carrying rigid imported_regions — so the letters can be constrained, trimmed and extruded like anything drawn by hand. The buttons and offer actions arm Select first when in Sketch mode, since begin_sketch() does not run until a tool is armed. add_imported_regions() calls reset_autoedit(): without it the glyph contours entered the draw-then-edit queue and opened a Length field on the first segment, which freezes the canvas. Caught on the rig, not by reading. No sketch open: unchanged — a new Sketch feature, still dropped on a picked face. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LyRwbuq6fjn3VV9U9UvhBM
This commit is contained in:
co-authored by
Claude Opus 5
parent
447c71a0d2
commit
bc4fb3b680
@@ -389,6 +389,14 @@ void DesignCanvas::set_sketch_construction(bool c)
|
||||
m_sketch_tool.set_construction(c);
|
||||
}
|
||||
|
||||
bool DesignCanvas::add_sketch_regions(
|
||||
const std::vector<std::vector<std::vector<Vec2d>>>& regions)
|
||||
{
|
||||
const bool ok = m_sketch_tool.add_imported_regions(regions);
|
||||
if (ok) request_repaint();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void DesignCanvas::set_sketch_polygon_sides(int n)
|
||||
{
|
||||
m_sketch_tool.set_polygon_sides(n);
|
||||
|
||||
@@ -53,6 +53,8 @@ public:
|
||||
void set_sketch_tool(DesignSketchTool::Mode mode);
|
||||
void set_sketch_plane(const SketchPlane& plane); // re-plane the live sketch when a reference plane is clicked in 3D
|
||||
void set_sketch_construction(bool c);
|
||||
// Text / SVG art into the LIVE sketch, as ordinary editable lines. False = no session.
|
||||
bool add_sketch_regions(const std::vector<std::vector<std::vector<Vec2d>>>& regions);
|
||||
void set_sketch_polygon_sides(int n);
|
||||
void set_sketch_polygon_circumscribed(bool c);
|
||||
void finish_sketch();
|
||||
|
||||
@@ -1170,19 +1170,32 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// the sketch tools, not in the generic Features strip. Each places the art
|
||||
// in-canvas, then commits via the Insert card's Confirm.
|
||||
{
|
||||
// In Sketch MODE the art must land in the sketch — but begin_sketch() does not run
|
||||
// until the first tool is armed, so pressing Sketch and then Text would find no
|
||||
// session and commit a separate feature. Arm Select first: it starts the session on
|
||||
// the picked plane without drawing anything, so Text behaves the same whether or not
|
||||
// you had already drawn a line. (MODE vs SESSION — the distinction that has bitten
|
||||
// this panel before.)
|
||||
auto ensure_sketch = [this, select_tool] {
|
||||
if (m_ui_mode == UiMode::Sketch && m_viewport && !m_viewport->is_sketching())
|
||||
select_tool(DesignSketchTool::Mode::Select,
|
||||
_L("Select — click to select; Shift to add"));
|
||||
};
|
||||
auto* b_text = icon_btn("design_text", _L("Text — emboss text as a profile"));
|
||||
b_text->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_add_text(); });
|
||||
b_text->Bind(wxEVT_BUTTON, [this, ensure_sketch](wxCommandEvent&) {
|
||||
ensure_sketch(); on_add_text(); });
|
||||
sadd(b_text);
|
||||
auto* b_svg = icon_btn("design_svg", _L("SVG — import an outline as a profile"));
|
||||
b_svg->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_import_svg(); });
|
||||
b_svg->Bind(wxEVT_BUTTON, [this, ensure_sketch](wxCommandEvent&) {
|
||||
ensure_sketch(); on_import_svg(); });
|
||||
sadd(b_svg);
|
||||
// …and reachable from the offer's Create row. These were on the atlas's chrome_only
|
||||
// list under "document-level actions act on the DOCUMENT, not on a selection" — which
|
||||
// is not what they do: both call add_imported_sketch(), which drops the art ON a
|
||||
// picked solid face (SketchPlane::from_face, centred on it) exactly as Sketch does.
|
||||
// Selection-consuming profile creators, so they belong with the other Create verbs.
|
||||
m_verb_actions["btn:text"] = [this] { on_add_text(); };
|
||||
m_verb_actions["btn:svg"] = [this] { on_import_svg(); };
|
||||
m_verb_actions["btn:text"] = [this, ensure_sketch] { ensure_sketch(); on_add_text(); };
|
||||
m_verb_actions["btn:svg"] = [this, ensure_sketch] { ensure_sketch(); on_import_svg(); };
|
||||
}
|
||||
add_sep(m_tb_sketch);
|
||||
// In-canvas edit-op tools (drag gizmo / click label), grouped by family.
|
||||
@@ -4044,6 +4057,17 @@ void DesignPanel::add_imported_sketch(
|
||||
m_status->Refresh();
|
||||
return;
|
||||
}
|
||||
// DRAWING, not importing: if a sketch is open, the art belongs IN it. The outlines become
|
||||
// ordinary line entities, so they can be constrained, trimmed and extruded with everything
|
||||
// else on that plane. Committing a separate Sketch feature while the user is mid-sketch put
|
||||
// the text on its own plane-origin feature and left the sketch they were drawing untouched.
|
||||
if (m_viewport && m_viewport->is_sketching() && m_viewport->add_sketch_regions(regions)) {
|
||||
m_status->SetForegroundColour(wxNullColour);
|
||||
m_status->SetLabel(wxString::Format(_L("%s added to the sketch — Confirm to commit it"),
|
||||
base_name));
|
||||
m_status->Refresh();
|
||||
return;
|
||||
}
|
||||
m_doc.checkpoint(); // undo boundary: importing Text/SVG art
|
||||
m_feature_counter++;
|
||||
CadFeature f;
|
||||
|
||||
@@ -2317,6 +2317,29 @@ void DesignSketchTool::push_line(const Vec2d& a, const Vec2d& b)
|
||||
m_entities.push_back(e);
|
||||
}
|
||||
|
||||
bool DesignSketchTool::add_imported_regions(
|
||||
const std::vector<std::vector<std::vector<Vec2d>>>& regions)
|
||||
{
|
||||
if (!m_active) return false; // no session to draw into; caller makes a feature
|
||||
const bool saved = m_construction;
|
||||
m_construction = false; // art is real geometry, never construction lines
|
||||
size_t before = m_entities.size();
|
||||
for (const auto& region : regions)
|
||||
for (const auto& loop : region)
|
||||
push_closed_lines(loop); // every glyph contour, holes included
|
||||
m_construction = saved;
|
||||
if (m_entities.size() == before) return false; // nothing importable — say so, do not lie
|
||||
// Art is not "just drawn", so it must NOT enter the draw-then-edit queue. Without this the
|
||||
// glyph contours are treated as fresh entities and a Length field opens on the first of
|
||||
// them — on a word, that is one value editor per segment, and an open field freezes the
|
||||
// canvas (snaporca-yce). reset_autoedit() marks every entity as already seen.
|
||||
reset_autoedit();
|
||||
// The new lines carry no constraints, so the solver has nothing to move; resolve anyway so
|
||||
// the degrees-of-freedom readout counts them instead of going stale.
|
||||
resolve_live();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DesignSketchTool::push_closed_lines(const std::vector<Vec2d>& corners)
|
||||
{
|
||||
const size_t n = corners.size();
|
||||
|
||||
@@ -79,6 +79,13 @@ public:
|
||||
void begin_edit(const std::vector<SketchEntity>& entities,
|
||||
const std::vector<SketchEntityConstraintDef>& constraints,
|
||||
const SketchPlane& plane);
|
||||
// Drop rigid 2D art (Text / SVG outlines) INTO the live sketch as ordinary line entities,
|
||||
// so it joins the sketch being drawn instead of committing a separate Sketch feature.
|
||||
// `regions` are loops in PLANE coordinates; every closed loop becomes a closed polyline, so
|
||||
// the result is editable, constrainable and extrudable like anything else drawn by hand —
|
||||
// unlike imported_regions, which are rigid and carry no solver entities.
|
||||
// Returns false when no session is live, so the caller can fall back to a new feature.
|
||||
bool add_imported_regions(const std::vector<std::vector<std::vector<Vec2d>>>& regions);
|
||||
void set_tool(Mode mode); // switch tool, keep accumulated entities
|
||||
void set_plane(const SketchPlane& plane) { m_plane = plane; } // re-plane a live sketch (a reference plane was clicked mid-session); entities are 2D, re-lifted through the new plane
|
||||
void set_construction(bool c) { m_construction = c; }
|
||||
|
||||
Reference in New Issue
Block a user