mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-26 18:31:11 +00:00
Design: Measure-style dimension labels (+ projection fix), New Design, tree auto-fit, i18n pin, UX
Sketch dimension labels — now identical to the Prepare/Preview Measure gizmo:
- draw_text repurposed to draw_dim_label: white ImGui text in a translucent-white box,
mirroring GLGizmoMeasure::render_dimensioning exactly (push_common_window_style sets the
text colour, BringWindowToDisplayFront, imgui_internal.h).
- ROOT-CAUSE FIX: world_to_screen_px multiplied two Eigen Transform3d objects
((proj * view).matrix()); a projection is not affine so Eigen mangled it -> garbage screen
coords, so labels never appeared. Now proj.matrix() * view.matrix() like Measure. (That
helper was previously [[maybe_unused]] dead code, never exercised.)
- Leaders: offset clear of the sketch line (no longer coincident with the geometry), single
point-to-point dimension line + arrows, neutral colour, width 0.6 -> 0.2.
- dim_text appends mm/in on linear dims (angles keep the degree sign).
New Design + delete:
- New "New Design" button wipes the whole document (confirm dialog) — the clear-all the
per-row Delete can't give. CadDocument::clear() now also clears bodies + display_body_meshes
(it left them stale, so solids lingered after a clear).
- on_delete_feature: a Body-row selection now shows a helpful hint (bodies are recomputed
results with no directly-removable feature) instead of silently doing nothing.
Feature tree: auto-fits its content (refresh_tree clamps height 1..9 rows, scrolls past),
instead of a fixed 140px block.
i18n (Design tab pinned English, per the UX contract):
- Restore the lost #undef _L / #define _L(s) wxString::FromUTF8(s) override atop DesignPanel.cpp;
wrap all ~54 dropdown options in _L so the single lever governs them. feature_type_name left
untranslated (machine-facing MCP JSON).
UX: per-card Value Confirm/Cancel buttons removed — the single ribbon action bar owns value
confirm/cancel via an m_value_cont guard in tool_confirm/tool_cancel. "needs a body" status
messages unified.
Both forks; DesignSketchTool.{cpp,hpp} + CadDocument.cpp byte-identical across forks. Built
clean; New Design / feature-delete / rotation / tree auto-fit live-verified on :10.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
6e11cfc49b
commit
8cbf5b393b
@@ -5,6 +5,7 @@
|
||||
#include "Plater.hpp"
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#include "Camera.hpp"
|
||||
#include "3DScene.hpp"
|
||||
@@ -39,7 +40,9 @@ static double ray_segment_dist3(const Vec3d& ro, const Vec3d& rd, const Vec3d& a
|
||||
// needs the design canvas's own camera/viewport, not the plater's.)
|
||||
[[maybe_unused]] static wxPoint world_to_screen_px(const Camera& cam, const Vec3d& world)
|
||||
{
|
||||
const Eigen::Matrix4d m = (cam.get_projection_matrix() * cam.get_view_matrix()).matrix();
|
||||
// NB: multiply the raw 4x4 matrices, NOT the Transform3d objects — the projection is not
|
||||
// affine, so Transform*Transform mangles it (Eigen assumes affine) and yields garbage w.
|
||||
const Eigen::Matrix4d m = cam.get_projection_matrix().matrix() * cam.get_view_matrix().matrix();
|
||||
const Eigen::Vector4d clip = m * world.homogeneous();
|
||||
if (std::abs(clip.w()) < 1e-9) return wxPoint(-1, -1);
|
||||
const Vec3d ndc = clip.head<3>() / clip.w();
|
||||
@@ -4913,15 +4916,21 @@ void DesignSketchTool::draw_dim_label(const std::string& txt, const Vec2d& plane
|
||||
const wxPoint sp = world_to_screen_px(cam, m_plane.to_world(plane_center));
|
||||
if (sp.x < 0 && sp.y < 0) return;
|
||||
ImGuiWrapper* imgui = wxGetApp().imgui();
|
||||
// Identical to the Prepare/Preview Measure gizmo label (GLGizmoMeasure::render_dimensioning):
|
||||
// push_common_window_style sets the white text colour + font/scale (without it the text is
|
||||
// invisible); BringWindowToDisplayFront keeps the per-frame label window on top.
|
||||
ImGuiWrapper::push_common_window_style(m_render_scale);
|
||||
imgui->set_next_window_pos((float)sp.x, (float)sp.y, ImGuiCond_Always, 0.5f, 0.5f);
|
||||
imgui->set_next_window_bg_alpha(0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(1.0f, 1.0f));
|
||||
imgui->set_next_window_pos((float)sp.x, (float)sp.y, ImGuiCond_Always, 0.5f, 0.5f);
|
||||
imgui->set_next_window_bg_alpha(0.0f);
|
||||
const std::string win = "##sketchdim" + std::to_string(m_dim_label_seq++);
|
||||
imgui->begin(win, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration
|
||||
| ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoFocusOnAppearing
|
||||
| ImGuiWindowFlags_NoNav);
|
||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
const ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
const ImVec2 ts = ImGui::CalcTextSize(txt.c_str());
|
||||
@@ -4934,6 +4943,7 @@ void DesignSketchTool::draw_dim_label(const std::string& txt, const Vec2d& plane
|
||||
imgui->text(txt);
|
||||
imgui->end();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGuiWrapper::pop_common_window_style();
|
||||
}
|
||||
|
||||
void DesignSketchTool::draw_text(GLModel& /*model*/, const std::string& s, const Vec2d& center,
|
||||
@@ -4969,15 +4979,18 @@ bool DesignSketchTool::draw_dim_quote(const DimAnnot& a, double th, const ColorR
|
||||
if (L < 1e-6) return false;
|
||||
const Vec2d u = d / L;
|
||||
const Vec2d nrm(-u.y(), u.x());
|
||||
segs.emplace_back(pa, pb); // single point-to-point dimension line
|
||||
const double side = (a.side != 0.0) ? a.side : 1.0;
|
||||
const double off = side * std::max(L * 0.18, 8.0);
|
||||
const Vec2d A2 = pa + nrm * off, B2 = pb + nrm * off; // offset clear of the sketch line
|
||||
segs.emplace_back(A2, B2); // dimension line (not on the geometry)
|
||||
const double as = std::max(L * 0.04, 2.0);
|
||||
auto arrow = [&](const Vec2d& tip, const Vec2d& dir) {
|
||||
const Vec2d back = tip + dir * as;
|
||||
segs.emplace_back(tip, back + nrm * (as * 0.5));
|
||||
segs.emplace_back(tip, back - nrm * (as * 0.5));
|
||||
};
|
||||
arrow(pa, u); arrow(pb, -u);
|
||||
out_label = (pa + pb) * 0.5 + nrm * (th * 0.8);
|
||||
arrow(A2, u); arrow(B2, -u);
|
||||
out_label = (A2 + B2) * 0.5 + nrm * (side * (th * 0.7 + 1.5));
|
||||
} else if (a.kind == DimType::Diameter || a.kind == DimType::Radius) {
|
||||
if (a.ea < 0 || a.ea >= int(m_entities.size())) return false;
|
||||
const SketchEntity& e = m_entities[a.ea];
|
||||
@@ -5035,7 +5048,7 @@ bool DesignSketchTool::draw_dim_quote(const DimAnnot& a, double th, const ColorR
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
draw_strokes(m_highlight_model, segs, 0.6, dimcol);
|
||||
draw_strokes(m_highlight_model, segs, 0.2, dimcol);
|
||||
draw_text(m_line_model, dim_text(a), out_label, th, dimcol);
|
||||
return true;
|
||||
}
|
||||
@@ -6272,6 +6285,7 @@ void DesignSketchTool::confirm_transform()
|
||||
void DesignSketchTool::render(GLCanvas3D& canvas)
|
||||
{
|
||||
m_dim_label_seq = 0;
|
||||
m_render_scale = canvas.get_scale();
|
||||
(void)canvas;
|
||||
if (!has_display()) {
|
||||
if (on_readout) on_readout(std::string()); // nothing to show -> hide HUD
|
||||
@@ -6283,6 +6297,7 @@ void DesignSketchTool::render(GLCanvas3D& canvas)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Draw-then-edit: a creation tool that just committed a new entity/feature (gesture now
|
||||
// idle) gets its result auto-selected — so render_live_quotes below computes its quotes —
|
||||
// and the primary value editor armed (opened after those quotes exist, see service block).
|
||||
|
||||
Reference in New Issue
Block a user