mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-05 23:01:17 +00:00
Update Translations + String improvements (#16142)
Co-authored-by: Alexandre Folle de Menezes <afmenez@gmail.com>
This commit is contained in:
co-authored by
Alexandre Folle de Menezes
parent
c1e6de7e4e
commit
eb5b9a77b9
@@ -90,6 +90,7 @@ See the [Localization guide](https://github.com/OrcaSlicer/OrcaSlicer_WIKI/blob/
|
||||
- Plural entries: read `nplurals` from the catalog's `Plural-Forms` header (it is **not** always 2 — ja/ko/zh/th/vi use 1, ru/cs/pl/lt use 3, uk uses 4). Each form must be genuinely inflected for its quantity; repeating one sentence across all forms is a bug in Slavic/Baltic languages, though it is correct for Turkish and Hungarian.
|
||||
- An entry whose `msgstr` equals its `msgid` is untranslated even though it is not empty; a plural entry with any empty form is likewise incomplete.
|
||||
- Mark machine-produced translations with an `# AI Translated` translator comment. Don't add it to a human translation you didn't actually rewrite.
|
||||
- When you can't be sure of a machine translation's meaning or UI wording, also add `# Needs human review: <what to check>`. Never use `fuzzy` for this — fuzzy entries are hidden from users.
|
||||
- Don't reflow or re-wrap unrelated entries — keep the diff limited to the strings you changed.
|
||||
|
||||
### Verifying
|
||||
|
||||
+4489
-649
File diff suppressed because it is too large
Load Diff
+8876
-1712
File diff suppressed because it is too large
Load Diff
+8791
-1560
File diff suppressed because it is too large
Load Diff
+8722
-1594
File diff suppressed because it is too large
Load Diff
+4489
-624
File diff suppressed because it is too large
Load Diff
+8746
-1625
File diff suppressed because it is too large
Load Diff
+8744
-1579
File diff suppressed because it is too large
Load Diff
+7625
-902
File diff suppressed because it is too large
Load Diff
+9048
-1727
File diff suppressed because it is too large
Load Diff
+8725
-1598
File diff suppressed because it is too large
Load Diff
+8792
-1649
File diff suppressed because it is too large
Load Diff
+9019
-1748
File diff suppressed because it is too large
Load Diff
@@ -52,8 +52,6 @@ src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.h
|
||||
src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.h
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.cpp
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackNozzleItem.h
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackNozzleItem.cpp
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.h
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp
|
||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleSelect.h
|
||||
@@ -301,3 +299,64 @@ src/slic3r/GUI/Gizmos/GLGizmoPrimitive.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSketch.cpp
|
||||
src/slic3r/GUI/KeyChord.cpp
|
||||
src/slic3r/GUI/Shortcuts.cpp
|
||||
src/libslic3r/CAD/CadDocument.cpp
|
||||
src/libslic3r/Support/TreeSupport3D.cpp
|
||||
src/slic3r/Config/Snapshot.cpp
|
||||
src/slic3r/GUI/AmsMappingPopupUpdate.cpp
|
||||
src/slic3r/GUI/AuxiliaryDataViewModel.cpp
|
||||
src/slic3r/GUI/AuxiliaryDialog.cpp
|
||||
src/slic3r/GUI/BBLStatusBarPrint.cpp
|
||||
src/slic3r/GUI/BBLStatusBarSend.cpp
|
||||
src/slic3r/GUI/BaseTransparentDPIFrame.cpp
|
||||
src/slic3r/GUI/CloneDialog.cpp
|
||||
src/slic3r/GUI/ColorDecomposeDialog.cpp
|
||||
src/slic3r/GUI/ColorDecomposeSupport.cpp
|
||||
src/slic3r/GUI/ConfigWizard.cpp
|
||||
src/slic3r/GUI/DeviceCore/DevCalib.cpp
|
||||
src/slic3r/GUI/DeviceCore/DevUpgrade.cpp
|
||||
src/slic3r/GUI/DeviceTab/uiAMSBestPositionPopup.cpp
|
||||
src/slic3r/GUI/DeviceTab/wgtMsgPanel.cpp
|
||||
src/slic3r/GUI/DragDropPanel.cpp
|
||||
src/slic3r/GUI/GLCanvas3D.hpp
|
||||
src/slic3r/GUI/GUI_Utils.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp
|
||||
src/slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp
|
||||
src/slic3r/GUI/Jobs/SLAImportDialog.hpp
|
||||
src/slic3r/GUI/Jobs/TextureDisplacementBakeJob.cpp
|
||||
src/slic3r/GUI/Jobs/TextureDisplacementDebugJob.cpp
|
||||
src/slic3r/GUI/Jobs/TextureDisplacementPrepareJob.cpp
|
||||
src/slic3r/GUI/MixedFilamentDialog.cpp
|
||||
src/slic3r/GUI/ModelMall.cpp
|
||||
src/slic3r/GUI/OAuthDialog.cpp
|
||||
src/slic3r/GUI/PluginPickerDialog.cpp
|
||||
src/slic3r/GUI/PluginsConfigDialog.cpp
|
||||
src/slic3r/GUI/PluginsDialog.cpp
|
||||
src/slic3r/GUI/PublishSettingsDialog.hpp
|
||||
src/slic3r/GUI/PurgeModeDialog.cpp
|
||||
src/slic3r/GUI/TerminalDialog.cpp
|
||||
src/slic3r/GUI/TextureImportDialog.cpp
|
||||
src/slic3r/GUI/TextureLibrary.cpp
|
||||
src/slic3r/GUI/TextureProjectorFrame.cpp
|
||||
src/slic3r/GUI/UVEditorCanvas.cpp
|
||||
src/slic3r/GUI/UserManager.cpp
|
||||
src/slic3r/GUI/WebDownPluginDlg.cpp
|
||||
src/slic3r/GUI/WebViewDialog.cpp
|
||||
src/slic3r/GUI/Widgets/AMSItem.cpp
|
||||
src/slic3r/GUI/Widgets/DialogButtons.cpp
|
||||
src/slic3r/Utils/NetworkAgentFactory.cpp
|
||||
src/slic3r/plugin/PluginAuditManager.cpp
|
||||
src/slic3r/plugin/PluginConfig.cpp
|
||||
src/slic3r/plugin/PluginResolver.cpp
|
||||
src/libslic3r/CAD/SketchEngine.cpp
|
||||
src/libslic3r/CAD/GeometryEngine.cpp
|
||||
src/slic3r/GUI/CAD/DesignOffer.hpp
|
||||
src/slic3r/GUI/CAD/DesignSketchTool.cpp
|
||||
src/slic3r/GUI/EncodedFilament.cpp
|
||||
src/slic3r/GUI/HttpServer.cpp
|
||||
src/slic3r/GUI/Plater.hpp
|
||||
src/slic3r/GUI/PostProcessor.cpp
|
||||
src/slic3r/GUI/TaskManager.cpp
|
||||
src/slic3r/GUI/Widgets/ProgressDialog.hpp
|
||||
src/slic3r/GUI/Widgets/StepCtrl.cpp
|
||||
|
||||
+9035
-1689
File diff suppressed because it is too large
Load Diff
+8798
-1626
File diff suppressed because it is too large
Load Diff
+8641
-1987
File diff suppressed because it is too large
Load Diff
+8578
-1437
File diff suppressed because it is too large
Load Diff
+8976
-1838
File diff suppressed because it is too large
Load Diff
+8961
-1748
File diff suppressed because it is too large
Load Diff
+8774
-1579
File diff suppressed because it is too large
Load Diff
+8751
-1570
File diff suppressed because it is too large
Load Diff
+8948
-1751
File diff suppressed because it is too large
Load Diff
+8794
-1607
File diff suppressed because it is too large
Load Diff
+8737
-1579
File diff suppressed because it is too large
Load Diff
+8740
-1583
File diff suppressed because it is too large
Load Diff
@@ -416,8 +416,8 @@ function favDigitFromEvent(e) {
|
||||
|
||||
function resultCountText(total, shown, query) {
|
||||
return (query || "").trim() ?
|
||||
T("sd_result_count", "Showing %s actions", shown) :
|
||||
T("sd_result_count_all", "%s actions", total);
|
||||
T("sd_result_count", "Matching actions: %s", shown) :
|
||||
T("sd_result_count_all", "Actions: %s", total);
|
||||
}
|
||||
|
||||
// Display label for a notebook tab. Trim any stray whitespace; pages added with an empty title
|
||||
@@ -758,7 +758,7 @@ window.HandleStudio = function (payload) {
|
||||
var fid = payload.id;
|
||||
if (fid && FAVS.indexOf(fid) !== -1) FAVS.splice(FAVS.indexOf(fid), 1);
|
||||
render({ resize: true, keepScroll: true });
|
||||
flashHint(T("sd_favs_full", "Favourites are full (%s max)", (payload.limit || K_FAV_LIMIT)));
|
||||
flashHint(T("sd_favs_full", "Favorites are full (%s max)", (payload.limit || K_FAV_LIMIT)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -821,8 +821,8 @@ function pinSvg(on) {
|
||||
function setPinState(pin, on) {
|
||||
pin.classList.toggle("on", on);
|
||||
pin.innerHTML = pinSvg(on);
|
||||
pin.title = on ? T("sd_unpin_fav", "Unpin from favourites (%s)", shortcutCtrl() + "B") :
|
||||
T("sd_pin_fav", "Pin to favourites (%s)", shortcutCtrl() + "B");
|
||||
pin.title = on ? T("sd_unpin_fav", "Unpin from favorites (%s)", shortcutCtrl() + "B") :
|
||||
T("sd_pin_fav", "Pin to favorites (%s)", shortcutCtrl() + "B");
|
||||
}
|
||||
|
||||
// ---- render ------------------------------------------------------------------
|
||||
@@ -858,15 +858,15 @@ function renderFav() {
|
||||
badge.textContent = slot;
|
||||
// Slot "0" is the 10th favourite (Alt/Option+0).
|
||||
var slot_num = slot === "0" ? "10" : slot;
|
||||
badge.title = T("sd_fav_slot", "Favourite %s (%s)", slot_num, shortcutAlt() + slot);
|
||||
badge.title = T("sd_fav_slot", "Favorite %s (%s)", slot_num, shortcutAlt() + slot);
|
||||
tile.appendChild(badge);
|
||||
}
|
||||
// Direct removal: a hover-revealed ✕ in the tile's corner. click() stops propagation so it
|
||||
// unpins without activating the action.
|
||||
var unpin = document.createElement("button");
|
||||
unpin.className = "fav-unpin";
|
||||
unpin.title = T("sd_remove_fav", "Remove from favourites");
|
||||
unpin.setAttribute("aria-label", T("sd_remove_fav", "Remove from favourites"));
|
||||
unpin.title = T("sd_remove_fav", "Remove from favorites");
|
||||
unpin.setAttribute("aria-label", T("sd_remove_fav", "Remove from favorites"));
|
||||
unpin.innerHTML = '<svg width="9" height="9" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>';
|
||||
unpin.onclick = function (ev) { ev.stopPropagation(); toggleFav(id); };
|
||||
tile.appendChild(unpin);
|
||||
@@ -1170,7 +1170,7 @@ function renderTabList() {
|
||||
listEl.className = "dial-list";
|
||||
if (countEl) {
|
||||
countEl.hidden = false;
|
||||
countEl.textContent = q ? T("sd_tab_match_count", "%s matches", list.length) : T("sd_tab_count", "%s tabs", list.length);
|
||||
countEl.textContent = q ? T("sd_tab_match_count", "Matching tabs: %s", list.length) : T("sd_tab_count", "Tabs: %s", list.length);
|
||||
}
|
||||
list.forEach(function (t, i) { listEl.appendChild(renderTabRow(t, i)); });
|
||||
}
|
||||
|
||||
@@ -78,8 +78,9 @@ def load_table():
|
||||
if not line.startswith('{"'):
|
||||
continue
|
||||
# id, name, row, key, action, refusal, accepts, need_bodies, need_sketches, need_sheet,
|
||||
# sketch_mode, family, ... — split on top-level commas, respecting quotes.
|
||||
f, cur, q, esc = [], "", False, False
|
||||
# sketch_mode, family, ... — split on top-level commas, respecting quotes and the
|
||||
# L(...) / L_CONTEXT(...) translation markers.
|
||||
f, cur, q, esc, depth = [], "", False, False, 0
|
||||
for ch in line[1:]:
|
||||
if esc:
|
||||
cur += ch; esc = False; continue
|
||||
@@ -87,16 +88,18 @@ def load_table():
|
||||
cur += ch; esc = True; continue
|
||||
if ch == '"':
|
||||
q = not q
|
||||
if ch == "," and not q:
|
||||
if not q:
|
||||
depth += (ch == "(") - (ch == ")")
|
||||
if ch == "," and not q and depth == 0:
|
||||
f.append(cur.strip()); cur = ""; continue
|
||||
if ch == "}" and not q:
|
||||
if ch == "}" and not q and depth == 0:
|
||||
break
|
||||
cur += ch
|
||||
f.append(cur.strip())
|
||||
if len(f) < 12:
|
||||
continue
|
||||
# User-facing fields are wrapped in the L("...") gettext marker; strip it.
|
||||
lit = lambda s: None if s == "nullptr" else re.sub(r'^L\((.*)\)$', r'\1', s).strip('"')
|
||||
# User-facing fields are wrapped in L("...") or L_CONTEXT("...", ...); take the literal.
|
||||
lit = lambda s: None if s == "nullptr" else re.search(r'"((?:[^"\\]|\\.)*)"', s).group(1)
|
||||
out.append({"id": lit(f[0]), "name": lit(f[1]), "row": int(f[2]), "key": lit(f[3]),
|
||||
"action": lit(f[4]), "accepts": int(f[6].rstrip("u"), 0),
|
||||
"need_bodies": int(f[7]), "need_sketches": int(f[8]),
|
||||
|
||||
@@ -43,6 +43,11 @@ def tstr(s):
|
||||
return "nullptr" if s is None else "L(" + cstr(s) + ")"
|
||||
|
||||
|
||||
def tstr_design(s):
|
||||
# Verb name: same msgctxt as the Design panel's own tool labels.
|
||||
return "L_CONTEXT(" + cstr(s) + ', "Design")'
|
||||
|
||||
|
||||
def validate(A):
|
||||
"""Refuse an atlas the header cannot represent, naming every fault at once.
|
||||
|
||||
@@ -90,6 +95,9 @@ def main():
|
||||
"#ifndef L",
|
||||
"#define L(s) s // gettext marker, as in slic3r/GUI/I18N.hpp",
|
||||
"#endif",
|
||||
"#ifndef L_CONTEXT",
|
||||
"#define L_CONTEXT(s, context) s",
|
||||
"#endif",
|
||||
"",
|
||||
"namespace Slic3r { namespace GUI {",
|
||||
"",
|
||||
@@ -113,7 +121,7 @@ def main():
|
||||
"// nullptr -> kernel support exists, no GUI path yet (row shows disabled)",
|
||||
"struct OfferVerb {",
|
||||
" const char* id;",
|
||||
" const char* name; // drawing-office word (L10); marked L(); translated at use",
|
||||
" const char* name; // drawing-office word (L10); msgctxt \"Design\", translated at use",
|
||||
" int row; // index into kOfferRowNames, the ratified address — NEVER reorder",
|
||||
" const char* key; // shortcut shown in the row, or nullptr",
|
||||
" const char* action;",
|
||||
@@ -170,7 +178,7 @@ def main():
|
||||
n = v.get("needs") or {}
|
||||
lines.append(
|
||||
" {%s, %s, %d, %s, %s, %s, 0x%08xu, %d, %d, %s, %s, %s, %s, %s}," % (
|
||||
cstr(v["id"]), tstr(v["name"]), slots.index(v["slot"]),
|
||||
cstr(v["id"]), tstr_design(v["name"]), slots.index(v["slot"]),
|
||||
cstr(v.get("key")), cstr(v.get("action")), tstr(v.get("refusal")),
|
||||
mask, n.get("bodies", 0), n.get("sketches", 0),
|
||||
"true" if n.get("sheet") else "false",
|
||||
|
||||
+214
-218
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
#include "libslic3r/CAD/GeometryEngine.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/I18N.hpp"
|
||||
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
@@ -73,19 +74,19 @@ std::vector<TopoDS_Shape> GeometryEngine::read_step_solids(const std::string& pa
|
||||
try {
|
||||
STEPControl_Reader reader;
|
||||
if (reader.ReadFile(path.c_str()) != IFSelect_RetDone) {
|
||||
err = "cannot read STEP file";
|
||||
err = _u8L("cannot read STEP file");
|
||||
return out;
|
||||
}
|
||||
reader.TransferRoots();
|
||||
const TopoDS_Shape shape = reader.OneShape();
|
||||
if (shape.IsNull()) { err = "STEP file has no geometry"; return out; }
|
||||
if (shape.IsNull()) { err = _u8L("STEP file has no geometry"); return out; }
|
||||
// One body per top-level solid; fall back to the whole shape (shells/faces) if none.
|
||||
for (TopExp_Explorer ex(shape, TopAbs_SOLID); ex.More(); ex.Next())
|
||||
out.push_back(ex.Current());
|
||||
if (out.empty())
|
||||
out.push_back(shape);
|
||||
} catch (const Standard_Failure& e) {
|
||||
err = *e.what() ? e.what() : "OCCT failed to read STEP";
|
||||
err = *e.what() ? e.what() : _u8L("OCCT failed to read STEP");
|
||||
out.clear();
|
||||
}
|
||||
return out;
|
||||
@@ -115,7 +116,7 @@ TopoDS_Shape GeometryEngine::mesh_to_brep(const indexed_triangle_set& its,
|
||||
if (tolerance <= 0.0)
|
||||
throw std::runtime_error("mesh_to_brep: tolerance must be > 0");
|
||||
if (its.indices.empty())
|
||||
throw std::runtime_error("mesh_to_brep: mesh has no triangles");
|
||||
throw std::runtime_error(_u8L("mesh_to_brep: mesh has no triangles"));
|
||||
|
||||
// 1. Tolerance-quantized vertex dedup. A merged vertex keeps the exact coordinates of the
|
||||
// first input occurrence — vertices are grouped by a cell, never snapped onto its grid.
|
||||
@@ -150,8 +151,8 @@ TopoDS_Shape GeometryEngine::mesh_to_brep(const indexed_triangle_set& its,
|
||||
}
|
||||
stats.kept_tris = int(tris.size());
|
||||
if (tris.empty())
|
||||
throw std::runtime_error("mesh_to_brep: every triangle was rejected as degenerate "
|
||||
"(try a smaller tolerance)");
|
||||
throw std::runtime_error(_u8L("mesh_to_brep: every triangle was rejected as degenerate "
|
||||
"(try a smaller tolerance)"));
|
||||
|
||||
// 3. One face per triangle, sharing vertices and edges through the caches.
|
||||
std::vector<TopoDS_Vertex> vertex_cache(verts.size());
|
||||
@@ -361,7 +362,7 @@ TopoDS_Shape GeometryEngine::apply_fillet(const TopoDS_Shape& solid, double radi
|
||||
// A too-large radius (e.g. >= half the smallest spanned dimension) makes the
|
||||
// operation degenerate; OCCT leaves IsDone() false. Report it instead of
|
||||
// silently returning the unfilleted solid (which reads as a false success).
|
||||
if (!fillet.IsDone()) throw std::runtime_error("fillet radius too large for this geometry");
|
||||
if (!fillet.IsDone()) throw std::runtime_error(_u8L("fillet radius too large for this geometry"));
|
||||
return fillet.Shape();
|
||||
}
|
||||
|
||||
@@ -377,7 +378,7 @@ TopoDS_Shape GeometryEngine::apply_chamfer(const TopoDS_Shape& solid, double dis
|
||||
chamfer.Add(distance, edge); // symmetric chamfer
|
||||
chamfer.Build();
|
||||
|
||||
if (!chamfer.IsDone()) throw std::runtime_error("chamfer distance too large for this geometry");
|
||||
if (!chamfer.IsDone()) throw std::runtime_error(_u8L("chamfer distance too large for this geometry"));
|
||||
return chamfer.Shape();
|
||||
}
|
||||
|
||||
@@ -404,7 +405,7 @@ TopoDS_Shape GeometryEngine::apply_fillet(const TopoDS_Shape& solid, double radi
|
||||
}
|
||||
mk.Build();
|
||||
|
||||
if (!mk.IsDone()) throw std::runtime_error("apply_fillet: OCCT fillet failed");
|
||||
if (!mk.IsDone()) throw std::runtime_error(_u8L("apply_fillet: OCCT fillet failed"));
|
||||
return mk.Shape();
|
||||
}
|
||||
|
||||
@@ -421,7 +422,7 @@ TopoDS_Shape GeometryEngine::apply_chamfer(const TopoDS_Shape& solid, double dis
|
||||
}
|
||||
mk.Build();
|
||||
|
||||
if (!mk.IsDone()) throw std::runtime_error("apply_chamfer: OCCT chamfer failed");
|
||||
if (!mk.IsDone()) throw std::runtime_error(_u8L("apply_chamfer: OCCT chamfer failed"));
|
||||
return mk.Shape();
|
||||
}
|
||||
|
||||
@@ -547,12 +548,13 @@ GeometryEngine::MassProps GeometryEngine::mass_properties(const TopoDS_Shape& sh
|
||||
std::string GeometryEngine::primitive_name(PrimitiveType type)
|
||||
{
|
||||
switch (type) {
|
||||
case PrimitiveType::Box: return "Box";
|
||||
case PrimitiveType::Cylinder: return "Cylinder";
|
||||
case PrimitiveType::Sphere: return "Sphere";
|
||||
case PrimitiveType::Cone: return "Cone";
|
||||
case PrimitiveType::Torus: return "Torus";
|
||||
default: return "Unknown";
|
||||
// TRN Default name of an object created from the box primitive shape.
|
||||
case PrimitiveType::Box: return _u8L("Box");
|
||||
case PrimitiveType::Cylinder: return _u8L("Cylinder");
|
||||
case PrimitiveType::Sphere: return _u8L("Sphere");
|
||||
case PrimitiveType::Cone: return _u8L("Cone");
|
||||
case PrimitiveType::Torus: return _u8L("Torus");
|
||||
default: return _u8L("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "libslic3r/CAD/SketchEngine.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/I18N.hpp"
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <GeomAbs_SurfaceType.hxx>
|
||||
@@ -138,7 +139,7 @@ Vec3d SketchPlane::to_world(const Vec2d& pt) const
|
||||
TopoDS_Wire SketchProfile::to_occt_wire(const SketchPlane& plane) const
|
||||
{
|
||||
if (points.size() < 2)
|
||||
throw std::runtime_error("Profile has fewer than 2 points");
|
||||
throw std::runtime_error(_u8L("Profile has fewer than 2 points"));
|
||||
|
||||
BRepBuilderAPI_MakeWire builder;
|
||||
for (size_t i = 0; i < points.size(); ++i) {
|
||||
@@ -150,7 +151,7 @@ TopoDS_Wire SketchProfile::to_occt_wire(const SketchPlane& plane) const
|
||||
}
|
||||
builder.Build();
|
||||
if (!builder.IsDone())
|
||||
throw std::runtime_error("Failed to build wire from profile");
|
||||
throw std::runtime_error(_u8L("Failed to build wire from profile"));
|
||||
return builder.Wire();
|
||||
}
|
||||
|
||||
@@ -158,9 +159,9 @@ TopoDS_Wire SketchProfile::to_occt_wire(const SketchPlane& plane) const
|
||||
|
||||
TopoDS_Shape SketchEngine::make_prism(const TopoDS_Shape& base, const gp_Vec& vec)
|
||||
{
|
||||
if (vec.Magnitude() < 1e-9) throw std::runtime_error("extrude depth is zero");
|
||||
if (vec.Magnitude() < 1e-9) throw std::runtime_error(_u8L("extrude depth is zero"));
|
||||
BRepPrimAPI_MakePrism prism(base, vec);
|
||||
if (!prism.IsDone()) throw std::runtime_error("extrude failed");
|
||||
if (!prism.IsDone()) throw std::runtime_error(_u8L("extrude failed"));
|
||||
return prism.Shape();
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ static TopoDS_Shape extrude_face_internal(const TopoDS_Face& face, const gp_Dir&
|
||||
if (symmetric) {
|
||||
gp_Vec halfVec = gp_Vec(dir) * (length / 2.0);
|
||||
BRepAlgoAPI_Fuse fuse(SketchEngine::make_prism(face, halfVec), SketchEngine::make_prism(face, -halfVec));
|
||||
if (!fuse.IsDone()) throw std::runtime_error("Fuse failed");
|
||||
if (!fuse.IsDone()) throw std::runtime_error(_u8L("Fuse failed"));
|
||||
return fuse.Shape();
|
||||
}
|
||||
return SketchEngine::make_prism(face, gp_Vec(dir) * length);
|
||||
@@ -179,7 +180,7 @@ TopoDS_Shape SketchEngine::make_extrude(const TopoDS_Wire& wire, const SketchPla
|
||||
double length, bool symmetric, double taper_deg)
|
||||
{
|
||||
BRepBuilderAPI_MakeFace fm(wire);
|
||||
if (!fm.IsDone()) throw std::runtime_error("Failed to make face from wire");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("Failed to make face from wire"));
|
||||
return make_extrude(fm.Face(), plane, length, symmetric, taper_deg);
|
||||
}
|
||||
|
||||
@@ -194,7 +195,7 @@ TopoDS_Shape SketchEngine::make_extrude_two_sided(const TopoDS_Wire& wire, const
|
||||
double up, double down)
|
||||
{
|
||||
BRepBuilderAPI_MakeFace fm(wire);
|
||||
if (!fm.IsDone()) throw std::runtime_error("Failed to make face from wire");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("Failed to make face from wire"));
|
||||
return make_extrude_two_sided(fm.Face(), plane, up, down);
|
||||
}
|
||||
|
||||
@@ -206,7 +207,7 @@ TopoDS_Shape SketchEngine::make_extrude_two_sided(const TopoDS_Face& face, const
|
||||
if (d < 1e-9) return make_prism(face, gp_Vec(dir) * u);
|
||||
if (u < 1e-9) return make_prism(face, gp_Vec(dir) * -d);
|
||||
BRepAlgoAPI_Fuse fuse(make_prism(face, gp_Vec(dir) * u), make_prism(face, gp_Vec(dir) * -d));
|
||||
if (!fuse.IsDone()) throw std::runtime_error("two-sided extrude fuse failed");
|
||||
if (!fuse.IsDone()) throw std::runtime_error(_u8L("two-sided extrude fuse failed"));
|
||||
return fuse.Shape();
|
||||
}
|
||||
|
||||
@@ -216,7 +217,7 @@ TopoDS_Shape SketchEngine::make_extrude_taper(const TopoDS_Wire& wire, const Ske
|
||||
gp_Dir dir(plane.normal.x(), plane.normal.y(), plane.normal.z());
|
||||
auto straight = [&]() -> TopoDS_Shape {
|
||||
BRepBuilderAPI_MakeFace fm(wire);
|
||||
if (!fm.IsDone()) throw std::runtime_error("Failed to make face from wire");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("Failed to make face from wire"));
|
||||
return make_prism(fm.Face(), gp_Vec(dir) * length);
|
||||
};
|
||||
if (std::abs(taper_deg) >= 89.0 || std::abs(length) < 1e-9) return straight();
|
||||
@@ -262,7 +263,7 @@ TopoDS_Shape SketchEngine::make_extrude_regions(
|
||||
const SketchPlane& plane, double length, bool symmetric)
|
||||
{
|
||||
// The loop below skips regions that fail, so a zero depth is rejected before it.
|
||||
if (std::abs(length) < 1e-9) throw std::runtime_error("extrude depth is zero");
|
||||
if (std::abs(length) < 1e-9) throw std::runtime_error(_u8L("extrude depth is zero"));
|
||||
|
||||
// Drop consecutive coincident points and the closing duplicate. FreeType /
|
||||
// SVG flattening routinely emits repeated points which would build a
|
||||
@@ -348,7 +349,7 @@ TopoDS_Shape SketchEngine::make_extrude_regions(
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) throw std::runtime_error("imported regions produced no extrudable geometry");
|
||||
if (count == 0) throw std::runtime_error(_u8L("imported regions produced no extrudable geometry"));
|
||||
return count == 1 ? last : TopoDS_Shape(comp); // avoid a compound-of-one
|
||||
}
|
||||
|
||||
@@ -356,7 +357,7 @@ TopoDS_Shape SketchEngine::make_revolve(const TopoDS_Wire& wire, const gp_Ax1& a
|
||||
{
|
||||
BRepBuilderAPI_MakeFace faceMaker(wire);
|
||||
if (!faceMaker.IsDone())
|
||||
throw std::runtime_error("Failed to make face from wire");
|
||||
throw std::runtime_error(_u8L("Failed to make face from wire"));
|
||||
TopoDS_Face face = faceMaker.Face();
|
||||
|
||||
// A profile on both sides of the axis sweeps through itself; MakeRevol then fails with no
|
||||
@@ -387,7 +388,7 @@ TopoDS_Shape SketchEngine::make_revolve(const TopoDS_Wire& wire, const gp_Ax1& a
|
||||
if (angle_rad < 0) { axis.Reverse(); angle_rad = -angle_rad; }
|
||||
BRepPrimAPI_MakeRevol rev(face, axis, angle_rad);
|
||||
if (!rev.IsDone())
|
||||
throw std::runtime_error("Failed to revolve");
|
||||
throw std::runtime_error(_u8L("Failed to revolve"));
|
||||
if (!BRepCheck_Analyzer(rev.Shape()).IsValid())
|
||||
throw std::runtime_error("the profile crosses the revolve axis — it must lie on one side of it");
|
||||
return rev.Shape();
|
||||
@@ -397,29 +398,29 @@ TopoDS_Shape SketchEngine::make_sweep(const TopoDS_Wire& profile, const TopoDS_W
|
||||
{
|
||||
BRepBuilderAPI_MakeFace faceMaker(profile);
|
||||
if (!faceMaker.IsDone())
|
||||
throw std::runtime_error("Failed to make face from sweep profile");
|
||||
throw std::runtime_error(_u8L("Failed to make face from sweep profile"));
|
||||
TopoDS_Face face = faceMaker.Face();
|
||||
|
||||
BRepOffsetAPI_MakePipe pipe(path, face);
|
||||
pipe.Build();
|
||||
if (!pipe.IsDone())
|
||||
throw std::runtime_error("Failed to sweep profile along path");
|
||||
throw std::runtime_error(_u8L("Failed to sweep profile along path"));
|
||||
return pipe.Shape();
|
||||
}
|
||||
|
||||
TopoDS_Shape SketchEngine::make_loft(const std::vector<TopoDS_Wire>& profiles, bool ruled)
|
||||
{
|
||||
if (profiles.size() < 2)
|
||||
throw std::runtime_error("loft needs at least 2 profiles");
|
||||
throw std::runtime_error(_u8L("loft needs at least 2 profiles"));
|
||||
BRepOffsetAPI_ThruSections loft(true /*solid*/, ruled);
|
||||
for (const TopoDS_Wire& w : profiles) {
|
||||
if (w.IsNull()) throw std::runtime_error("loft: null profile wire");
|
||||
loft.AddWire(w);
|
||||
}
|
||||
loft.Build();
|
||||
if (!loft.IsDone()) throw std::runtime_error("loft failed");
|
||||
if (!loft.IsDone()) throw std::runtime_error(_u8L("loft failed"));
|
||||
TopoDS_Shape s = loft.Shape();
|
||||
if (s.IsNull()) throw std::runtime_error("loft produced no solid");
|
||||
if (s.IsNull()) throw std::runtime_error(_u8L("loft produced no solid"));
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -427,16 +428,16 @@ TopoDS_Shape SketchEngine::make_loft(const std::vector<TopoDS_Wire>& profiles, b
|
||||
TopoDS_Shape SketchEngine::make_loft_surface(const std::vector<TopoDS_Wire>& profiles, bool ruled)
|
||||
{
|
||||
if (profiles.size() < 2)
|
||||
throw std::runtime_error("loft needs at least 2 profiles");
|
||||
throw std::runtime_error(_u8L("loft needs at least 2 profiles"));
|
||||
BRepOffsetAPI_ThruSections loft(false /*shell, no end caps*/, ruled);
|
||||
for (const TopoDS_Wire& w : profiles) {
|
||||
if (w.IsNull()) throw std::runtime_error("loft: null profile wire");
|
||||
loft.AddWire(w);
|
||||
}
|
||||
loft.Build();
|
||||
if (!loft.IsDone()) throw std::runtime_error("loft failed");
|
||||
if (!loft.IsDone()) throw std::runtime_error(_u8L("loft failed"));
|
||||
TopoDS_Shape s = loft.Shape();
|
||||
if (s.IsNull()) throw std::runtime_error("loft produced no shape");
|
||||
if (s.IsNull()) throw std::runtime_error(_u8L("loft produced no shape"));
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -444,11 +445,11 @@ TopoDS_Shape SketchEngine::make_pocket(const TopoDS_Wire& wire, const SketchPlan
|
||||
const TopoDS_Shape& target, double depth)
|
||||
{
|
||||
BRepBuilderAPI_MakeFace fm(wire);
|
||||
if (!fm.IsDone()) throw std::runtime_error("Pocket face failed");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("Pocket face failed"));
|
||||
TopoDS_Shape tool = extrude_face_internal(fm.Face(),
|
||||
gp_Dir(plane.normal.x(), plane.normal.y(), plane.normal.z()), depth + 1.0, false);
|
||||
BRepAlgoAPI_Cut cut(target, tool);
|
||||
if (!cut.IsDone()) throw std::runtime_error("Pocket cut failed");
|
||||
if (!cut.IsDone()) throw std::runtime_error(_u8L("Pocket cut failed"));
|
||||
return cut.Shape();
|
||||
}
|
||||
|
||||
@@ -929,7 +930,7 @@ static TopoDS_Face checked_profile_face(const TopoDS_Face& f)
|
||||
TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
||||
const SketchPlane& plane)
|
||||
{
|
||||
if (wires.empty()) throw std::runtime_error("sketch has no closed loop");
|
||||
if (wires.empty()) throw std::runtime_error(_u8L("sketch has no closed loop"));
|
||||
|
||||
// The ASSEMBLED face below is built on the SKETCH's own plane rather than on a surface OCCT
|
||||
// infers from the outer wire. The inferred plane has no reason to share the sketch's normal,
|
||||
@@ -944,7 +945,7 @@ TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
||||
|
||||
if (wires.size() == 1) {
|
||||
BRepBuilderAPI_MakeFace fm(wires[0]);
|
||||
if (!fm.IsDone()) throw std::runtime_error("sketch loop does not bound a face");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("sketch loop does not bound a face"));
|
||||
return checked_profile_face(fm.Face());
|
||||
}
|
||||
|
||||
@@ -956,7 +957,7 @@ TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
||||
areas.reserve(wires.size());
|
||||
for (const TopoDS_Wire& w : wires) {
|
||||
BRepBuilderAPI_MakeFace fm(w);
|
||||
if (!fm.IsDone()) throw std::runtime_error("sketch loop does not bound a face");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("sketch loop does not bound a face"));
|
||||
faces.push_back(fm.Face());
|
||||
GProp_GProps props;
|
||||
BRepGProp::SurfaceProperties(faces.back(), props);
|
||||
@@ -982,10 +983,10 @@ TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
||||
got = true;
|
||||
break;
|
||||
}
|
||||
if (!got) throw std::runtime_error("sketch loop does not bound a face");
|
||||
if (!got) throw std::runtime_error(_u8L("sketch loop does not bound a face"));
|
||||
BRepClass_FaceClassifier fc(faces[outer], p, 1e-7);
|
||||
if (fc.State() != TopAbs_IN)
|
||||
throw std::runtime_error("sketch has two disjoint regions; put each in its own sketch");
|
||||
throw std::runtime_error(_u8L("sketch has two disjoint regions; put each in its own sketch"));
|
||||
// Add the hole loop AS-IS and let ShapeFix_Face sort the orientations out below.
|
||||
// Reversing it here only works when the sketch happened to wind both loops the same
|
||||
// way: a circle drawn clockwise inside a counter-clockwise rectangle comes out matching
|
||||
@@ -995,7 +996,7 @@ TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
||||
// 147520 — a body larger than its own bounding box, which is the signature of it.
|
||||
fm.Add(wires[i]);
|
||||
}
|
||||
if (!fm.IsDone()) throw std::runtime_error("sketch loop does not bound a face");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("sketch loop does not bound a face"));
|
||||
// Winding-independent classification of outer vs holes — the same idiom make_extrude_regions
|
||||
// already uses for imported glyphs, which is why holed TEXT extruded correctly all along
|
||||
// while a holed SKETCH did not.
|
||||
|
||||
@@ -264,7 +264,8 @@ AboutDialog::AboutDialog()
|
||||
vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5));
|
||||
auto version_string = std::string(SoftFever_VERSION); // _L("Orca Slicer ") + " " + std::string(SoftFever_VERSION);
|
||||
wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize);
|
||||
wxStaticText* credits_string = new wxStaticText(this, wxID_ANY, wxString::Format("Build %s", build_commit_label), wxDefaultPosition, wxDefaultSize);
|
||||
// TRN %s is the commit the application was built from
|
||||
wxStaticText* credits_string = new wxStaticText(this, wxID_ANY, wxString::Format(_L("Build %s"), build_commit_label), wxDefaultPosition, wxDefaultSize);
|
||||
credits_string->SetFont(_build_string_font);
|
||||
wxFont version_font = GetFont();
|
||||
version_font = version_font.Scaled(1.85f); // SetPointSize(20) not works on macOS because it uses a 72 PPI reference
|
||||
@@ -330,7 +331,7 @@ AboutDialog::AboutDialog()
|
||||
|
||||
copyright_hor_sizer->Add(copyright_ver_sizer, 0, wxLEFT, FromDIP(20));
|
||||
|
||||
wxStaticText *html_text = new wxStaticText(this, wxID_ANY, "Copyright(C) 2026 OrcaSlicer Pte Ltd All Rights Reserved", wxDefaultPosition, wxDefaultSize);
|
||||
wxStaticText *html_text = new wxStaticText(this, wxID_ANY, _L("Copyright(C) 2026 OrcaSlicer Pte Ltd All Rights Reserved"), wxDefaultPosition, wxDefaultSize);
|
||||
html_text->SetForegroundColour(wxColour(107, 107, 107));
|
||||
|
||||
copyright_ver_sizer->Add(html_text, 0, wxALL , 0);
|
||||
|
||||
@@ -329,7 +329,8 @@ void AmsMapingPopup::update_mapping_items(MachineObject* obj, const std::vector<
|
||||
|
||||
if (m_show_type == ShowType::LEFT_AND_RIGHT_DYNAMIC) {
|
||||
auto sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL);
|
||||
const auto& shown_name = td_opt->ams_id == VIRTUAL_TRAY_MAIN_ID ? "Ext-R" : "Ext-L";
|
||||
// TRN Short labels of the external spool of the right and left nozzle
|
||||
const auto& shown_name = td_opt->ams_id == VIRTUAL_TRAY_MAIN_ID ? _L("Ext-R") : _L("Ext-L");
|
||||
auto ams_mapping_item_container = new MappingContainer(m_right_marea_panel, shown_name, 1);
|
||||
ams_mapping_item_container->SetName(m_right_marea_panel->GetName());
|
||||
ams_mapping_item_container->SetSizer(sizer_mapping_list);
|
||||
@@ -506,7 +507,7 @@ void AmsMapingPopup::update_ams_tips(MachineObject* obj)
|
||||
}
|
||||
|
||||
if (obj && obj->GetFilaSwitch()->IsInstalled()) {
|
||||
const auto& msg = _L("External spools is not supported since Filament Track Switch has been installed. If you want to use external spool, please uninstall it.");
|
||||
const auto& msg = _L("External spools are not supported since Filament Track Switch has been installed. If you want to use an external spool, please uninstall it.");
|
||||
m_ams_tips_msg_panel->AddMessage(msg, "#FF6F00", "");
|
||||
}
|
||||
|
||||
@@ -588,7 +589,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data,
|
||||
// slots Ext-R / Ext-L inline in the two-nozzle left+right views (matches that overload's result).
|
||||
if ((m_show_type == ShowType::LEFT_AND_RIGHT || m_show_type == ShowType::LEFT_AND_RIGHT_DYNAMIC)
|
||||
&& (tray_data[i].id == VIRTUAL_TRAY_MAIN_ID || tray_data[i].id == VIRTUAL_TRAY_DEPUTY_ID)) {
|
||||
m_mapping_item->set_tray_index(tray_data[i].id == VIRTUAL_TRAY_MAIN_ID ? wxString("Ext-R") : wxString("Ext-L"));
|
||||
m_mapping_item->set_tray_index(tray_data[i].id == VIRTUAL_TRAY_MAIN_ID ? _L("Ext-R") : _L("Ext-L"));
|
||||
} else {
|
||||
m_mapping_item->set_tray_index(wxGetApp().transition_tridid(tray_data[i].id));
|
||||
}
|
||||
@@ -607,7 +608,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data,
|
||||
can_pick_the_item = !devPrinterUtil::IsVirtualSlot(m_mapping_item->m_ams_id);
|
||||
if (!can_pick_the_item) {
|
||||
item_tooltip_msg = _L(
|
||||
"External spools is not supported since Filament Track Switch has been installed. If you want to use external spool, please uninstall it.");
|
||||
"External spools are not supported since Filament Track Switch has been installed. If you want to use an external spool, please uninstall it.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -624,7 +625,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data,
|
||||
can_pick_the_item = !devPrinterUtil::IsVirtualSlot(m_mapping_item->m_ams_id);
|
||||
if (!can_pick_the_item) {
|
||||
item_tooltip_msg = _L(
|
||||
"External spools is not supported since Filament Track Switch has been installed. If you want to use external spool, please uninstall it.");
|
||||
"External spools are not supported since Filament Track Switch has been installed. If you want to use an external spool, please uninstall it.");
|
||||
}
|
||||
} else if (m_show_type != ShowType::RIGHT && m_show_type != ShowType::LEFT_AND_RIGHT) {
|
||||
can_pick_the_item = false;
|
||||
@@ -718,7 +719,7 @@ void AmsMapingPopup::add_ext_ams_mapping(TrayData tray_data, MappingItem* item)
|
||||
});
|
||||
}
|
||||
|
||||
item->set_tray_index("Ext");
|
||||
item->set_tray_index(_L("Ext"));
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
@@ -20,7 +20,7 @@ namespace GUI {
|
||||
|
||||
|
||||
AuxiliaryDialog::AuxiliaryDialog(wxWindow * parent)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Auxiliaryies"), wxDefaultPosition,
|
||||
: DPIDialog(parent, wxID_ANY, _L("Auxiliaries"), wxDefaultPosition,
|
||||
wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
m_aux_list = new AuxiliaryList(this);
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#ifndef L
|
||||
#define L(s) s // gettext marker, as in slic3r/GUI/I18N.hpp
|
||||
#endif
|
||||
#ifndef L_CONTEXT
|
||||
#define L_CONTEXT(s, context) s
|
||||
#endif
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@@ -52,7 +55,7 @@ inline uint32_t offer_bit(OfferSel s) { return 1u << int(s); }
|
||||
// nullptr -> kernel support exists, no GUI path yet (row shows disabled)
|
||||
struct OfferVerb {
|
||||
const char* id;
|
||||
const char* name; // drawing-office word (L10); marked L(); translated at use
|
||||
const char* name; // drawing-office word (L10); msgctxt "Design", translated at use
|
||||
int row; // index into kOfferRowNames, the ratified address — NEVER reorder
|
||||
const char* key; // shortcut shown in the row, or nullptr
|
||||
const char* action;
|
||||
@@ -99,107 +102,107 @@ static const bool kOfferRowFlat[] = {
|
||||
};
|
||||
|
||||
static const OfferVerb kOfferVerbs[] = {
|
||||
{"sketch", L("Sketch"), 0, "Shift+S", "key:S+S", L("Click a face or a reference plane in the viewport, then a sketch tool"), 0x00000403u, 0, 0, false, false, nullptr, "design_sketch", L("Click a face or a reference plane, then pick a drawing tool")},
|
||||
{"extrude", L("Extrude"), 1, "Shift+E", "key:S+E", L("Create a sketch, or pick a solid face, first"), 0x00004002u, 0, 0, false, false, nullptr, "design_extrude", L("Extrude a sketch profile, or push/pull a picked face")},
|
||||
{"revolve", L("Revolve"), 1, "Shift+R", "key:S+R", L("Create a sketch profile to revolve first"), 0x00004000u, 0, 0, false, false, nullptr, "design_revolve", L("Revolve a profile about an axis")},
|
||||
{"sweep", L("Sweep"), 1, "Shift+W", "key:S+W", L("Create a profile sketch to sweep first"), 0x00004000u, 0, 2, false, false, nullptr, "design_sweep", L("Sweep a profile along a path")},
|
||||
{"loft", L("Loft"), 1, "Shift+L", "key:S+L", L("Create at least two profile sketches to loft"), 0x00004000u, 0, 2, false, false, nullptr, "design_loft", L("Loft (skin) between two or more profiles")},
|
||||
{"thicken", L("Thicken"), 1, nullptr, "fly:material#4", L("Thicken needs a solid body — add or import one first"), 0x0000000au, 1, 0, false, false, nullptr, "design_thicken", L("Offset a solid face into a thin plate (new body)")},
|
||||
{"rib", L("Rib"), 1, "R", "fly:material#5", L("Rib needs a solid body — add or import one first"), 0x00010000u, 1, 0, false, false, nullptr, "design_rib", L("Grow a thin wall from an open sketch line, fused to a body")},
|
||||
{"boolean", L("Join"), 1, "Shift+B", "btn:bool#0", L("Boolean needs two bodies — add or import a second one"), 0x00000200u, 2, 0, false, false, nullptr, "design_boolean", L("Fuse the tool body into the target — one solid, no seam")},
|
||||
{"bool_subtract", L("Subtract"), 1, nullptr, "btn:bool#1", L("Boolean needs two bodies — add or import a second one"), 0x00000200u, 2, 0, false, false, nullptr, "design_boolean", L("Cut the tool body out of the target")},
|
||||
{"bool_intersect", L("Intersect"), 1, nullptr, "btn:bool#2", L("Boolean needs two bodies — add or import a second one"), 0x00000200u, 2, 0, false, false, nullptr, "design_boolean", L("Keep only where the two bodies overlap")},
|
||||
{"surf_extrude", L("Surface Extrude"), 1, "Shift+G", "key:S+G", L("Create a sketch first"), 0x00004000u, 0, 0, false, false, nullptr, "design_extrude", L("Extrude a sketch into a sheet body (no end caps)")},
|
||||
{"surf_revolve", L("Surface Revolve"), 1, nullptr, "fly:surface#1", L("Create a sketch profile to revolve first"), 0x00004000u, 0, 0, false, false, nullptr, "design_revolve", L("Revolve a sketch profile into a sheet body")},
|
||||
{"surf_loft", L("Surface Loft"), 1, nullptr, "fly:surface#2", L("Create at least two profile sketches to loft"), 0x00004000u, 0, 2, false, false, nullptr, "design_loft", L("Loft (skin) between 2+ profiles, open (no end caps)")},
|
||||
{"surf_fill", L("Surface Fill"), 1, nullptr, "fly:surface#3", L("Create a closed sketch first"), 0x00004000u, 0, 0, false, false, nullptr, "design_surface", L("Fill a sketch boundary with a smooth face")},
|
||||
{"thicken_surf", L("Thicken Surface"), 1, nullptr, "fly:surface#5", L("Thicken Surface needs a surface body — make one with a Surface tool first"), 0x00000100u, 0, 0, true, false, nullptr, "design_thicken", L("Thicken a sheet body into a solid")},
|
||||
{"hole", L("Hole"), 2, "Shift+H", "key:S+H", L("Pick a face or a plane to drill into"), 0x00000402u, 1, 0, false, false, nullptr, "design_hole", L("Drill a hole, centerd on a picked face or placed on a plane")},
|
||||
{"thread", L("Thread"), 2, "Shift+T", "key:S+T", L("Pick a cylindrical surface (bore / outer) or a circular edge for a thread"), 0x00000024u, 1, 0, false, false, nullptr, "design_thread", L("Thread a cylindrical surface (inner bore / outer) or a circular edge")},
|
||||
{"shell", L("Shell"), 2, "Shift+K", "key:S+K", L("Shell needs a solid body — add or import one first"), 0x00000082u, 1, 0, false, false, nullptr, "design_shell", L("Hollow the body to a wall thickness, opening a picked face")},
|
||||
{"cut", L("Cut"), 2, "Shift+X", "key:S+X", L("Cut needs a solid body — add or import one first"), 0x000004feu, 1, 0, false, false, nullptr, "design_cut", L("Trim the body with a plane — drag the offset arrow; keep one half or both")},
|
||||
{"split", L("Split"), 2, nullptr, nullptr, L("Split needs a solid body — add or import one first"), 0x000000feu, 1, 0, false, false, nullptr, nullptr, L("Split the body along a picked face into two solids")},
|
||||
{"fillet", L("Fillet"), 3, "Shift+F", "btn:dress#0", L("Pick an edge to round"), 0x000000b2u, 1, 0, false, false, nullptr, "design_filletedge", L("Pick an edge, then drag the radius arrow or type it")},
|
||||
{"chamfer", L("Chamfer"), 3, nullptr, "btn:dress#1", L("Pick an edge to bevel"), 0x000000b2u, 1, 0, false, false, nullptr, "design_chamfer", L("Pick an edge, then drag the distance arrow or type it")},
|
||||
{"draft", L("Draft"), 3, "Shift+D", "key:S+D", L("Pick a face to taper"), 0x0000000au, 1, 0, false, false, nullptr, "design_draft", L("Tilt a picked face by a draft angle")},
|
||||
{"surf_offset", L("Surface Offset"), 3, nullptr, "fly:surface#4", L("Surface Offset needs a surface body — make one with a Surface tool first"), 0x00000100u, 0, 0, true, false, nullptr, "design_offset", L("Offset a sheet body's shell by a signed distance")},
|
||||
{"pattern", L("Linear pattern"), 4, "Shift+N", "btn:pat#0", L("Pattern needs a solid body — add or import one first"), 0x00006082u, 1, 0, false, false, nullptr, "design_array", L("Repeat the body along a direction — drag the spacing, set the count")},
|
||||
{"pattern_circular", L("Circular pattern"), 4, nullptr, "btn:pat#1", L("Pattern needs a solid body — add or import one first"), 0x00006082u, 1, 0, false, false, nullptr, "design_polararray", L("Repeat the body around an axis — set the count and sweep")},
|
||||
{"mirror", L("Mirror"), 4, "Shift+Z", "key:S+Z", L("Mirror needs a body — add or import one first"), 0x000004feu, 1, 0, false, false, nullptr, "design_mirror", L("Reflect a body about a plane")},
|
||||
{"pat_curve", L("Pattern on Curve"), 4, nullptr, nullptr, L("Pattern on Curve needs a body and a curve"), 0x00000090u, 1, 0, false, false, nullptr, nullptr, L("Repeat the body along a picked curve")},
|
||||
{"transform", L("Move"), 5, "Shift+Y", "key:S+Y", L("Transform needs a body — add or import one first"), 0x000021feu, 1, 0, false, false, nullptr, "design_move", L("Move and/or rotate an existing body")},
|
||||
{"mate", L("Mate"), 5, nullptr, "fly:placement#2", L("Mate needs two coordinate systems — create them first"), 0x00001202u, 2, 0, false, false, nullptr, "design_c_coincident", L("Assembly: align two coordinate systems (fastened, planar, revolute, slider, cylindrical)")},
|
||||
{"align", L("Align to"), 5, nullptr, nullptr, L("Align needs a body — add or import one first"), 0x00000002u, 1, 0, false, false, nullptr, nullptr, L("Align the body to a picked face or plane")},
|
||||
{"plane", L("Plane"), 6, "Shift+P", "key:S+P", nullptr, 0x00000453u, 0, 0, false, false, nullptr, "design_plane", L("Reference plane (offset / tilt / midplane / tangent / two edges / coincident)")},
|
||||
{"axis", L("Axis"), 6, "Shift+A", "key:S+A", nullptr, 0x00000057u, 0, 0, false, false, nullptr, "design_line", L("Datum axis (two points, face normal, cylinder centerline, two planes, along edge)")},
|
||||
{"coordsys_v", L("Coordinate system"), 6, "Shift+C", "key:S+C", nullptr, 0x00000043u, 0, 0, false, false, nullptr, "design_point", L("Datum coordinate system (world point, or face + direction edge)")},
|
||||
{"helix", L("Helix"), 6, nullptr, "fly:plane#3", nullptr, 0x00000405u, 0, 0, false, false, nullptr, "design_thread", L("Helical curve (spring path) — use as a sweep path for coils / springs / augers")},
|
||||
{"project", L("Project"), 6, nullptr, "fly:plane#4", L("Project needs a body — add or import one first"), 0x00000482u, 1, 0, false, false, nullptr, "design_sketch", L("Project body edges onto a plane as sketch entities")},
|
||||
{"measure", L("Measure"), 6, nullptr, nullptr, nullptr, 0x000b03feu, 0, 0, false, false, nullptr, nullptr, L("Measure between the picked points, edges or faces")},
|
||||
{"mass_props", L("Volume and area"), 6, nullptr, "btn:mass", nullptr, 0x000000feu, 1, 0, false, false, nullptr, "info", L("Report the volume and surface area of the selected body")},
|
||||
{"interference", L("Interference"), 6, nullptr, "btn:interference", L("Interference needs at least two bodies"), 0x00000280u, 2, 0, false, false, nullptr, nullptr, L("Check whether two bodies overlap — reports, changes nothing")},
|
||||
{"edit_feature", L("Edit"), 7, nullptr, "btn:edit", nullptr, 0x00007d8eu, 0, 0, false, false, nullptr, "design_edit", L("Reopen the selected feature to change what it was made from")},
|
||||
{"rename", L("Rename…"), 8, "F2", "btn:rename", L("Select a feature, or a body, to rename it"), 0x00004080u, 0, 0, false, false, nullptr, nullptr, L("Give this feature a name you will recognise in the tree (a body takes its name from the feature that makes it)")},
|
||||
{"delete_face", L("Delete Face"), 7, nullptr, "fly:dressup#3", L("Delete Face needs a body — add or import one first"), 0x0000000eu, 1, 0, false, false, nullptr, "design_delete", L("Remove faces from a body and heal the solid")},
|
||||
{"colour", L("Color"), 8, nullptr, "btn:colour", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "color_palette", L("Set the selected body's display color")},
|
||||
{"delete", L("Delete"), 7, "Del", "btn:delete", nullptr, 0x000f7c00u, 0, 0, false, false, nullptr, "design_delete", L("Delete what is selected")},
|
||||
{"delete_body", L("Delete Body"), 7, nullptr, "btn:delete_body", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "design_delete", L("Delete this whole body — removes the feature it was made from")},
|
||||
{"sk_line_t", L("Line"), 0, "L", "key:L", nullptr, 0x000f8000u, 0, 0, false, true, L("Line"), "design_line", L("Line — click start, then end")},
|
||||
{"sk_polyline", L("Polyline"), 0, nullptr, "fly:design_line#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Line"), "design_polyline", L("Click points; click the first point to close the loop, right-click to end it open")},
|
||||
{"sk_rect", L("Corner rectangle"), 0, "R", "key:R", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect", L("Rectangle — click two opposite corners")},
|
||||
{"sk_rect_center", L("Center rectangle"), 0, nullptr, "fly:design_rect#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_crect", L("Click center, then a corner")},
|
||||
{"sk_rect_oblique", L("Oblique rectangle"), 0, nullptr, "fly:design_rect#2", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect_oblique", L("Click two corners of one edge, then a point for the width")},
|
||||
{"sk_rect_rounded", L("Rounded rectangle"), 0, nullptr, "fly:design_rect#3", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect_rounded", L("Click two opposite corners, then a point for the corner radius")},
|
||||
{"sk_circle", L("Center circle"), 0, "C", "key:C", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle", L("Circle — click center, then radius")},
|
||||
{"sk_circle_2pt", L("2-point circle"), 0, nullptr, "fly:design_circle#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle2pt", L("Click two ends of the diameter")},
|
||||
{"sk_circle_3pt", L("3-point circle"), 0, nullptr, "fly:design_circle#2", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle3pt", L("Click three points on the circle")},
|
||||
{"sk_arc_t", L("3-point arc"), 0, "A", "key:A", nullptr, 0x000f8000u, 0, 0, false, true, L("Arc"), "design_arc3pt", L("Arc — click start, end, then a point")},
|
||||
{"sk_arc_tangent", L("Tangent arc"), 0, nullptr, "fly:design_arc3pt#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Arc"), "design_tangentarc", L("Click start (on the last entity) then end")},
|
||||
{"sk_arc_center", L("Center-point arc"), 0, nullptr, "fly:design_arc3pt#2", nullptr, 0x000f8000u, 0, 0, false, true, L("Arc"), "design_arc_center", L("Click center, then start, then a point for the end angle")},
|
||||
{"sk_slot", L("Slot"), 0, "S", "key:S", nullptr, 0x000f8000u, 0, 0, false, true, L("Slot"), "design_slot", L("Slot — two centerline ends, then the width")},
|
||||
{"sk_slot_arc", L("Arc slot"), 0, nullptr, "fly:design_slot#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Slot"), "design_slot_arc", L("Click center, start, end, then a point for the width")},
|
||||
{"sk_ellipse", L("Ellipse"), 0, "E", "key:E", nullptr, 0x000f8000u, 0, 0, false, true, L("Ellipse"), "design_ellipse", L("Ellipse — center, major end, minor point")},
|
||||
{"sk_ellipse_arc", L("Elliptical arc"), 0, nullptr, "fly:design_ellipse#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Ellipse"), "design_ellipse_arc", L("Click center, major-axis end, minor point, then arc start and end")},
|
||||
{"sk_spline", L("Spline"), 0, "B", "key:B", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_bspline", L("Spline — click control points")},
|
||||
{"sk_poly_3", L("Triangle"), 0, nullptr, "btn:poly#3", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Triangle — click center, then a vertex")},
|
||||
{"sk_poly_4", L("Square"), 0, nullptr, "btn:poly#4", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Square — click center, then a vertex")},
|
||||
{"sk_poly_5", L("Pentagon"), 0, nullptr, "btn:poly#5", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Pentagon — click center, then a vertex")},
|
||||
{"sk_polygon", L("Hexagon"), 0, "G", "btn:poly#6", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Hexagon — click center, then a vertex")},
|
||||
{"sk_poly_8", L("Octagon"), 0, nullptr, "btn:poly#8", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Octagon — click center, then a vertex")},
|
||||
{"sk_poly_12", L("Dodecagon"), 0, nullptr, "btn:poly#12", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Dodecagon — click center, then a vertex")},
|
||||
{"sk_poly_inscribed", L("Inscribed"), 0, nullptr, "btn:polyfit#0", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Measure the polygon to its corners (inscribed)")},
|
||||
{"sk_poly_circumscribed", L("Circumscribed"), 0, nullptr, "btn:polyfit#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Measure the polygon to its flats (circumscribed)")},
|
||||
{"sk_point_t", L("Point"), 0, "P", "key:P", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_point", L("Point — click to place")},
|
||||
{"sk_text", L("Text"), 0, nullptr, "btn:text", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_text", L("Type text; it becomes a Text feature on this sketch's plane, editable later")},
|
||||
{"sk_svg", L("SVG"), 0, nullptr, "btn:svg", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_svg", L("Import an SVG outline into this sketch as editable lines")},
|
||||
{"sk_offset", L("Offset"), 1, "O", "key:O", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_offset", L("Offset — pick an entity, drag the distance")},
|
||||
{"sk_trim", L("Trim"), 2, "T", "key:T", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_trim", L("Trim — click a segment to trim it")},
|
||||
{"sk_fillet", L("Fillet"), 3, "F", "key:F", nullptr, 0x00090000u, 0, 0, false, true, nullptr, "design_filletedge", L("Fillet — pick two lines, set the radius")},
|
||||
{"sk_chamfer", L("Chamfer"), 3, "H", "key:H", nullptr, 0x00090000u, 0, 0, false, true, nullptr, "design_chamfer", L("Chamfer — pick two lines, set the distance")},
|
||||
{"sk_array", L("Linear array"), 4, nullptr, "fly:design_array#0", nullptr, 0x000b0000u, 0, 0, false, true, L("Array"), "design_array", L("Pick entities, drag the spacing handle, click the count; click empty to apply")},
|
||||
{"sk_array_polar", L("Polar array"), 4, nullptr, "fly:design_array#1", nullptr, 0x000b0000u, 0, 0, false, true, L("Array"), "design_polararray", L("Pick entities, drag the sweep handle, click the count; click empty to apply")},
|
||||
{"sk_mirror", L("Mirror"), 4, "M", "key:M", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_mirror", L("Mirror — pick axis, then entities")},
|
||||
{"sk_move", L("Move"), 5, nullptr, "fly:design_move#0", nullptr, 0x000f0000u, 0, 0, false, true, L("Move"), "design_move", L("Pick entities, then drag the handle or click the distance; click empty to apply")},
|
||||
{"sk_rotate", L("Rotate"), 5, nullptr, "fly:design_move#1", nullptr, 0x000f0000u, 0, 0, false, true, L("Move"), "design_rotate", L("Pick entities, then drag around the pivot or click the angle; click empty to apply")},
|
||||
{"sk_scale", L("Scale"), 5, nullptr, "fly:design_move#2", nullptr, 0x000f0000u, 0, 0, false, true, L("Move"), "design_scale", L("Pick entities, then drag the handle or click the factor; click empty to apply")},
|
||||
{"sk_dimension", L("Dimension"), 6, "D", "key:D", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_dimension", L("Dimension — click 2 points or an entity")},
|
||||
{"sk_constrain", L("Constrain"), 6, "K", "key:K", nullptr, 0x000f0000u, 0, 0, false, true, nullptr, "design_constrain", L("Constrain the selected sketch entities to each other")},
|
||||
{"sketch", L_CONTEXT("Sketch", "Design"), 0, "Shift+S", "key:S+S", L("Click a face or a reference plane in the viewport, then a sketch tool"), 0x00000403u, 0, 0, false, false, nullptr, "design_sketch", L("Click a face or a reference plane, then pick a drawing tool")},
|
||||
{"extrude", L_CONTEXT("Extrude", "Design"), 1, "Shift+E", "key:S+E", L("Create a sketch, or pick a solid face, first"), 0x00004002u, 0, 0, false, false, nullptr, "design_extrude", L("Extrude a sketch profile, or push/pull a picked face")},
|
||||
{"revolve", L_CONTEXT("Revolve", "Design"), 1, "Shift+R", "key:S+R", L("Create a sketch profile to revolve first"), 0x00004000u, 0, 0, false, false, nullptr, "design_revolve", L("Revolve a profile about an axis")},
|
||||
{"sweep", L_CONTEXT("Sweep", "Design"), 1, "Shift+W", "key:S+W", L("Create a profile sketch to sweep first"), 0x00004000u, 0, 2, false, false, nullptr, "design_sweep", L("Sweep a profile along a path")},
|
||||
{"loft", L_CONTEXT("Loft", "Design"), 1, "Shift+L", "key:S+L", L("Create at least two profile sketches to loft"), 0x00004000u, 0, 2, false, false, nullptr, "design_loft", L("Loft (skin) between two or more profiles")},
|
||||
{"thicken", L_CONTEXT("Thicken", "Design"), 1, nullptr, "fly:material#4", L("Thicken needs a solid body — add or import one first"), 0x0000000au, 1, 0, false, false, nullptr, "design_thicken", L("Offset a solid face into a thin plate (new body)")},
|
||||
{"rib", L_CONTEXT("Rib", "Design"), 1, "R", "fly:material#5", L("Rib needs a solid body — add or import one first"), 0x00010000u, 1, 0, false, false, nullptr, "design_rib", L("Grow a thin wall from an open sketch line, fused to a body")},
|
||||
{"boolean", L_CONTEXT("Join", "Design"), 1, "Shift+B", "btn:bool#0", L("Boolean needs two bodies — add or import a second one"), 0x00000200u, 2, 0, false, false, nullptr, "design_boolean", L("Fuse the tool body into the target — one solid, no seam")},
|
||||
{"bool_subtract", L_CONTEXT("Subtract", "Design"), 1, nullptr, "btn:bool#1", L("Boolean needs two bodies — add or import a second one"), 0x00000200u, 2, 0, false, false, nullptr, "design_boolean", L("Cut the tool body out of the target")},
|
||||
{"bool_intersect", L_CONTEXT("Intersect", "Design"), 1, nullptr, "btn:bool#2", L("Boolean needs two bodies — add or import a second one"), 0x00000200u, 2, 0, false, false, nullptr, "design_boolean", L("Keep only where the two bodies overlap")},
|
||||
{"surf_extrude", L_CONTEXT("Surface Extrude", "Design"), 1, "Shift+G", "key:S+G", L("Create a sketch first"), 0x00004000u, 0, 0, false, false, nullptr, "design_extrude", L("Extrude a sketch into a sheet body (no end caps)")},
|
||||
{"surf_revolve", L_CONTEXT("Surface Revolve", "Design"), 1, nullptr, "fly:surface#1", L("Create a sketch profile to revolve first"), 0x00004000u, 0, 0, false, false, nullptr, "design_revolve", L("Revolve a sketch profile into a sheet body")},
|
||||
{"surf_loft", L_CONTEXT("Surface Loft", "Design"), 1, nullptr, "fly:surface#2", L("Create at least two profile sketches to loft"), 0x00004000u, 0, 2, false, false, nullptr, "design_loft", L("Loft (skin) between 2+ profiles, open (no end caps)")},
|
||||
{"surf_fill", L_CONTEXT("Surface Fill", "Design"), 1, nullptr, "fly:surface#3", L("Create a closed sketch first"), 0x00004000u, 0, 0, false, false, nullptr, "design_surface", L("Fill a sketch boundary with a smooth face")},
|
||||
{"thicken_surf", L_CONTEXT("Thicken Surface", "Design"), 1, nullptr, "fly:surface#5", L("Thicken Surface needs a surface body — make one with a Surface tool first"), 0x00000100u, 0, 0, true, false, nullptr, "design_thicken", L("Thicken a sheet body into a solid")},
|
||||
{"hole", L_CONTEXT("Hole", "Design"), 2, "Shift+H", "key:S+H", L("Pick a face or a plane to drill into"), 0x00000402u, 1, 0, false, false, nullptr, "design_hole", L("Drill a hole, centerd on a picked face or placed on a plane")},
|
||||
{"thread", L_CONTEXT("Thread", "Design"), 2, "Shift+T", "key:S+T", L("Pick a cylindrical surface (bore / outer) or a circular edge for a thread"), 0x00000024u, 1, 0, false, false, nullptr, "design_thread", L("Thread a cylindrical surface (inner bore / outer) or a circular edge")},
|
||||
{"shell", L_CONTEXT("Shell", "Design"), 2, "Shift+K", "key:S+K", L("Shell needs a solid body — add or import one first"), 0x00000082u, 1, 0, false, false, nullptr, "design_shell", L("Hollow the body to a wall thickness, opening a picked face")},
|
||||
{"cut", L_CONTEXT("Cut", "Design"), 2, "Shift+X", "key:S+X", L("Cut needs a solid body — add or import one first"), 0x000004feu, 1, 0, false, false, nullptr, "design_cut", L("Trim the body with a plane — drag the offset arrow; keep one half or both")},
|
||||
{"split", L_CONTEXT("Split", "Design"), 2, nullptr, nullptr, L("Split needs a solid body — add or import one first"), 0x000000feu, 1, 0, false, false, nullptr, nullptr, L("Split the body along a picked face into two solids")},
|
||||
{"fillet", L_CONTEXT("Fillet", "Design"), 3, "Shift+F", "btn:dress#0", L("Pick an edge to round"), 0x000000b2u, 1, 0, false, false, nullptr, "design_filletedge", L("Pick an edge, then drag the radius arrow or type it")},
|
||||
{"chamfer", L_CONTEXT("Chamfer", "Design"), 3, nullptr, "btn:dress#1", L("Pick an edge to bevel"), 0x000000b2u, 1, 0, false, false, nullptr, "design_chamfer", L("Pick an edge, then drag the distance arrow or type it")},
|
||||
{"draft", L_CONTEXT("Draft", "Design"), 3, "Shift+D", "key:S+D", L("Pick a face to taper"), 0x0000000au, 1, 0, false, false, nullptr, "design_draft", L("Tilt a picked face by a draft angle")},
|
||||
{"surf_offset", L_CONTEXT("Surface Offset", "Design"), 3, nullptr, "fly:surface#4", L("Surface Offset needs a surface body — make one with a Surface tool first"), 0x00000100u, 0, 0, true, false, nullptr, "design_offset", L("Offset a sheet body's shell by a signed distance")},
|
||||
{"pattern", L_CONTEXT("Linear pattern", "Design"), 4, "Shift+N", "btn:pat#0", L("Pattern needs a solid body — add or import one first"), 0x00006082u, 1, 0, false, false, nullptr, "design_array", L("Repeat the body along a direction — drag the spacing, set the count")},
|
||||
{"pattern_circular", L_CONTEXT("Circular pattern", "Design"), 4, nullptr, "btn:pat#1", L("Pattern needs a solid body — add or import one first"), 0x00006082u, 1, 0, false, false, nullptr, "design_polararray", L("Repeat the body around an axis — set the count and sweep")},
|
||||
{"mirror", L_CONTEXT("Mirror", "Design"), 4, "Shift+Z", "key:S+Z", L("Mirror needs a body — add or import one first"), 0x000004feu, 1, 0, false, false, nullptr, "design_mirror", L("Reflect a body about a plane")},
|
||||
{"pat_curve", L_CONTEXT("Pattern on Curve", "Design"), 4, nullptr, nullptr, L("Pattern on Curve needs a body and a curve"), 0x00000090u, 1, 0, false, false, nullptr, nullptr, L("Repeat the body along a picked curve")},
|
||||
{"transform", L_CONTEXT("Move", "Design"), 5, "Shift+Y", "key:S+Y", L("Transform needs a body — add or import one first"), 0x000021feu, 1, 0, false, false, nullptr, "design_move", L("Move and/or rotate an existing body")},
|
||||
{"mate", L_CONTEXT("Mate", "Design"), 5, nullptr, "fly:placement#2", L("Mate needs two coordinate systems — create them first"), 0x00001202u, 2, 0, false, false, nullptr, "design_c_coincident", L("Assembly: align two coordinate systems (fastened, planar, revolute, slider, cylindrical)")},
|
||||
{"align", L_CONTEXT("Align to", "Design"), 5, nullptr, nullptr, L("Align needs a body — add or import one first"), 0x00000002u, 1, 0, false, false, nullptr, nullptr, L("Align the body to a picked face or plane")},
|
||||
{"plane", L_CONTEXT("Plane", "Design"), 6, "Shift+P", "key:S+P", nullptr, 0x00000453u, 0, 0, false, false, nullptr, "design_plane", L("Reference plane (offset / tilt / midplane / tangent / two edges / coincident)")},
|
||||
{"axis", L_CONTEXT("Axis", "Design"), 6, "Shift+A", "key:S+A", nullptr, 0x00000057u, 0, 0, false, false, nullptr, "design_line", L("Datum axis (two points, face normal, cylinder centerline, two planes, along edge)")},
|
||||
{"coordsys_v", L_CONTEXT("Coordinate system", "Design"), 6, "Shift+C", "key:S+C", nullptr, 0x00000043u, 0, 0, false, false, nullptr, "design_point", L("Datum coordinate system (world point, or face + direction edge)")},
|
||||
{"helix", L_CONTEXT("Helix", "Design"), 6, nullptr, "fly:plane#3", nullptr, 0x00000405u, 0, 0, false, false, nullptr, "design_thread", L("Helical curve (spring path) — use as a sweep path for coils / springs / augers")},
|
||||
{"project", L_CONTEXT("Project", "Design"), 6, nullptr, "fly:plane#4", L("Project needs a body — add or import one first"), 0x00000482u, 1, 0, false, false, nullptr, "design_sketch", L("Project body edges onto a plane as sketch entities")},
|
||||
{"measure", L_CONTEXT("Measure", "Design"), 6, nullptr, nullptr, nullptr, 0x000b03feu, 0, 0, false, false, nullptr, nullptr, L("Measure between the picked points, edges or faces")},
|
||||
{"mass_props", L_CONTEXT("Volume and area", "Design"), 6, nullptr, "btn:mass", nullptr, 0x000000feu, 1, 0, false, false, nullptr, "info", L("Report the volume and surface area of the selected body")},
|
||||
{"interference", L_CONTEXT("Interference", "Design"), 6, nullptr, "btn:interference", L("Interference needs at least two bodies"), 0x00000280u, 2, 0, false, false, nullptr, nullptr, L("Check whether two bodies overlap — reports, changes nothing")},
|
||||
{"edit_feature", L_CONTEXT("Edit", "Design"), 7, nullptr, "btn:edit", nullptr, 0x00007d8eu, 0, 0, false, false, nullptr, "design_edit", L("Reopen the selected feature to change what it was made from")},
|
||||
{"rename", L_CONTEXT("Rename…", "Design"), 8, "F2", "btn:rename", L("Select a feature, or a body, to rename it"), 0x00004080u, 0, 0, false, false, nullptr, nullptr, L("Give this feature a name you will recognise in the tree (a body takes its name from the feature that makes it)")},
|
||||
{"delete_face", L_CONTEXT("Delete Face", "Design"), 7, nullptr, "fly:dressup#3", L("Delete Face needs a body — add or import one first"), 0x0000000eu, 1, 0, false, false, nullptr, "design_delete", L("Remove faces from a body and heal the solid")},
|
||||
{"colour", L_CONTEXT("Color", "Design"), 8, nullptr, "btn:colour", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "color_palette", L("Set the selected body's display color")},
|
||||
{"delete", L_CONTEXT("Delete", "Design"), 7, "Del", "btn:delete", nullptr, 0x000f7c00u, 0, 0, false, false, nullptr, "design_delete", L("Delete what is selected")},
|
||||
{"delete_body", L_CONTEXT("Delete Body", "Design"), 7, nullptr, "btn:delete_body", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "design_delete", L("Delete this whole body — removes the feature it was made from")},
|
||||
{"sk_line_t", L_CONTEXT("Line", "Design"), 0, "L", "key:L", nullptr, 0x000f8000u, 0, 0, false, true, L("Line"), "design_line", L("Line — click start, then end")},
|
||||
{"sk_polyline", L_CONTEXT("Polyline", "Design"), 0, nullptr, "fly:design_line#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Line"), "design_polyline", L("Click points; click the first point to close the loop, right-click to end it open")},
|
||||
{"sk_rect", L_CONTEXT("Corner rectangle", "Design"), 0, "R", "key:R", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect", L("Rectangle — click two opposite corners")},
|
||||
{"sk_rect_center", L_CONTEXT("Center rectangle", "Design"), 0, nullptr, "fly:design_rect#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_crect", L("Click center, then a corner")},
|
||||
{"sk_rect_oblique", L_CONTEXT("Oblique rectangle", "Design"), 0, nullptr, "fly:design_rect#2", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect_oblique", L("Click two corners of one edge, then a point for the width")},
|
||||
{"sk_rect_rounded", L_CONTEXT("Rounded rectangle", "Design"), 0, nullptr, "fly:design_rect#3", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect_rounded", L("Click two opposite corners, then a point for the corner radius")},
|
||||
{"sk_circle", L_CONTEXT("Center circle", "Design"), 0, "C", "key:C", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle", L("Circle — click center, then radius")},
|
||||
{"sk_circle_2pt", L_CONTEXT("2-point circle", "Design"), 0, nullptr, "fly:design_circle#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle2pt", L("Click two ends of the diameter")},
|
||||
{"sk_circle_3pt", L_CONTEXT("3-point circle", "Design"), 0, nullptr, "fly:design_circle#2", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle3pt", L("Click three points on the circle")},
|
||||
{"sk_arc_t", L_CONTEXT("3-point arc", "Design"), 0, "A", "key:A", nullptr, 0x000f8000u, 0, 0, false, true, L("Arc"), "design_arc3pt", L("Arc — click start, end, then a point")},
|
||||
{"sk_arc_tangent", L_CONTEXT("Tangent arc", "Design"), 0, nullptr, "fly:design_arc3pt#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Arc"), "design_tangentarc", L("Click start (on the last entity) then end")},
|
||||
{"sk_arc_center", L_CONTEXT("Center-point arc", "Design"), 0, nullptr, "fly:design_arc3pt#2", nullptr, 0x000f8000u, 0, 0, false, true, L("Arc"), "design_arc_center", L("Click center, then start, then a point for the end angle")},
|
||||
{"sk_slot", L_CONTEXT("Slot", "Design"), 0, "S", "key:S", nullptr, 0x000f8000u, 0, 0, false, true, L("Slot"), "design_slot", L("Slot — two centerline ends, then the width")},
|
||||
{"sk_slot_arc", L_CONTEXT("Arc slot", "Design"), 0, nullptr, "fly:design_slot#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Slot"), "design_slot_arc", L("Click center, start, end, then a point for the width")},
|
||||
{"sk_ellipse", L_CONTEXT("Ellipse", "Design"), 0, "E", "key:E", nullptr, 0x000f8000u, 0, 0, false, true, L("Ellipse"), "design_ellipse", L("Ellipse — center, major end, minor point")},
|
||||
{"sk_ellipse_arc", L_CONTEXT("Elliptical arc", "Design"), 0, nullptr, "fly:design_ellipse#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Ellipse"), "design_ellipse_arc", L("Click center, major-axis end, minor point, then arc start and end")},
|
||||
{"sk_spline", L_CONTEXT("Spline", "Design"), 0, "B", "key:B", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_bspline", L("Spline — click control points")},
|
||||
{"sk_poly_3", L_CONTEXT("Triangle", "Design"), 0, nullptr, "btn:poly#3", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Triangle — click center, then a vertex")},
|
||||
{"sk_poly_4", L_CONTEXT("Square", "Design"), 0, nullptr, "btn:poly#4", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Square — click center, then a vertex")},
|
||||
{"sk_poly_5", L_CONTEXT("Pentagon", "Design"), 0, nullptr, "btn:poly#5", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Pentagon — click center, then a vertex")},
|
||||
{"sk_polygon", L_CONTEXT("Hexagon", "Design"), 0, "G", "btn:poly#6", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Hexagon — click center, then a vertex")},
|
||||
{"sk_poly_8", L_CONTEXT("Octagon", "Design"), 0, nullptr, "btn:poly#8", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Octagon — click center, then a vertex")},
|
||||
{"sk_poly_12", L_CONTEXT("Dodecagon", "Design"), 0, nullptr, "btn:poly#12", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Dodecagon — click center, then a vertex")},
|
||||
{"sk_poly_inscribed", L_CONTEXT("Inscribed", "Design"), 0, nullptr, "btn:polyfit#0", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Measure the polygon to its corners (inscribed)")},
|
||||
{"sk_poly_circumscribed", L_CONTEXT("Circumscribed", "Design"), 0, nullptr, "btn:polyfit#1", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Measure the polygon to its flats (circumscribed)")},
|
||||
{"sk_point_t", L_CONTEXT("Point", "Design"), 0, "P", "key:P", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_point", L("Point — click to place")},
|
||||
{"sk_text", L_CONTEXT("Text", "Design"), 0, nullptr, "btn:text", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_text", L("Type text; it becomes a Text feature on this sketch's plane, editable later")},
|
||||
{"sk_svg", L_CONTEXT("SVG", "Design"), 0, nullptr, "btn:svg", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_svg", L("Import an SVG outline into this sketch as editable lines")},
|
||||
{"sk_offset", L_CONTEXT("Offset", "Design"), 1, "O", "key:O", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_offset", L("Offset — pick an entity, drag the distance")},
|
||||
{"sk_trim", L_CONTEXT("Trim", "Design"), 2, "T", "key:T", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_trim", L("Trim — click a segment to trim it")},
|
||||
{"sk_fillet", L_CONTEXT("Fillet", "Design"), 3, "F", "key:F", nullptr, 0x00090000u, 0, 0, false, true, nullptr, "design_filletedge", L("Fillet — pick two lines, set the radius")},
|
||||
{"sk_chamfer", L_CONTEXT("Chamfer", "Design"), 3, "H", "key:H", nullptr, 0x00090000u, 0, 0, false, true, nullptr, "design_chamfer", L("Chamfer — pick two lines, set the distance")},
|
||||
{"sk_array", L_CONTEXT("Linear array", "Design"), 4, nullptr, "fly:design_array#0", nullptr, 0x000b0000u, 0, 0, false, true, L("Array"), "design_array", L("Pick entities, drag the spacing handle, click the count; click empty to apply")},
|
||||
{"sk_array_polar", L_CONTEXT("Polar array", "Design"), 4, nullptr, "fly:design_array#1", nullptr, 0x000b0000u, 0, 0, false, true, L("Array"), "design_polararray", L("Pick entities, drag the sweep handle, click the count; click empty to apply")},
|
||||
{"sk_mirror", L_CONTEXT("Mirror", "Design"), 4, "M", "key:M", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_mirror", L("Mirror — pick axis, then entities")},
|
||||
{"sk_move", L_CONTEXT("Move", "Design"), 5, nullptr, "fly:design_move#0", nullptr, 0x000f0000u, 0, 0, false, true, L("Move"), "design_move", L("Pick entities, then drag the handle or click the distance; click empty to apply")},
|
||||
{"sk_rotate", L_CONTEXT("Rotate", "Design"), 5, nullptr, "fly:design_move#1", nullptr, 0x000f0000u, 0, 0, false, true, L("Move"), "design_rotate", L("Pick entities, then drag around the pivot or click the angle; click empty to apply")},
|
||||
{"sk_scale", L_CONTEXT("Scale", "Design"), 5, nullptr, "fly:design_move#2", nullptr, 0x000f0000u, 0, 0, false, true, L("Move"), "design_scale", L("Pick entities, then drag the handle or click the factor; click empty to apply")},
|
||||
{"sk_dimension", L_CONTEXT("Dimension", "Design"), 6, "D", "key:D", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_dimension", L("Dimension — click 2 points or an entity")},
|
||||
{"sk_constrain", L_CONTEXT("Constrain", "Design"), 6, "K", "key:K", nullptr, 0x000f0000u, 0, 0, false, true, nullptr, "design_constrain", L("Constrain the selected sketch entities to each other")},
|
||||
// Same verb, model-mode vocabulary: offered when a SKETCH is selected (bit 14, SkLoop), the
|
||||
// state a user is in right after finishing one. Without this row the only way in was the
|
||||
// toolbar icon, and constraints read as absent — see the Onshape-comparison report.
|
||||
// It sits in the Reference row, the address the sketch-mode Constrain has: one verb, one row.
|
||||
{"constrain", L("Constrain sketch"), 6, nullptr, "btn:constrain", L("Select a sketch to constrain it"), 0x00004000u, 0, 1, false, false, nullptr, "design_constrain", L("Add dimensions and relations (coincident, tangent, parallel...) to the selected sketch")},
|
||||
{"sk_construct", L("Construction"), 6, "Q", "key:Q", nullptr, 0x000b8000u, 0, 0, false, true, nullptr, nullptr, L("Toggle construction: geometry that guides but is never built")},
|
||||
{"sk_extend", L("Extend"), 7, "X", "key:X", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_extend", L("Extend — click a line/arc to extend it")},
|
||||
{"sk_delete", L("Delete"), 7, "Del", "btn:sk_delete", nullptr, 0x000f0000u, 0, 0, false, true, nullptr, "design_delete", L("Delete the selected sketch entities")},
|
||||
{"constrain", L_CONTEXT("Constrain sketch", "Design"), 6, nullptr, "btn:constrain", L("Select a sketch to constrain it"), 0x00004000u, 0, 1, false, false, nullptr, "design_constrain", L("Add dimensions and relations (coincident, tangent, parallel...) to the selected sketch")},
|
||||
{"sk_construct", L_CONTEXT("Construction", "Design"), 6, "Q", "key:Q", nullptr, 0x000b8000u, 0, 0, false, true, nullptr, nullptr, L("Toggle construction: geometry that guides but is never built")},
|
||||
{"sk_extend", L_CONTEXT("Extend", "Design"), 7, "X", "key:X", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_extend", L("Extend — click a line/arc to extend it")},
|
||||
{"sk_delete", L_CONTEXT("Delete", "Design"), 7, "Del", "btn:sk_delete", nullptr, 0x000f0000u, 0, 0, false, true, nullptr, "design_delete", L("Delete the selected sketch entities")},
|
||||
// Typing the defining number of the element you pointed at. Three rows rather than one so
|
||||
// each names the quantity in the drawing-office word for THAT element; all three land on
|
||||
// the same handler, because dimension_kind() already resolves the quantity from the
|
||||
// selection. Without these, an element's own numbers were reachable only by arming the
|
||||
// Dimension tool and re-picking geometry that was already selected.
|
||||
{"sk_length", L("Length…"), 7, "V", "key:V", nullptr, 0x00010000u, 0, 0, false, true, nullptr, "design_dimension", L("Type the length of this line")},
|
||||
{"sk_radius", L("Radius / diameter…"), 7, "V", "key:V", nullptr, 0x00020000u, 0, 0, false, true, nullptr, "design_dimension", L("Type the radius of this arc, or the diameter of this circle")},
|
||||
{"sk_angdist", L("Angle / distance…"), 7, "V", "key:V", nullptr, 0x00080000u, 0, 0, false, true, nullptr, "design_dimension", L("Type the angle between two lines, or the distance between the two picks")},
|
||||
{"sk_length", L_CONTEXT("Length…", "Design"), 7, "V", "key:V", nullptr, 0x00010000u, 0, 0, false, true, nullptr, "design_dimension", L("Type the length of this line")},
|
||||
{"sk_radius", L_CONTEXT("Radius / diameter…", "Design"), 7, "V", "key:V", nullptr, 0x00020000u, 0, 0, false, true, nullptr, "design_dimension", L("Type the radius of this arc, or the diameter of this circle")},
|
||||
{"sk_angdist", L_CONTEXT("Angle / distance…", "Design"), 7, "V", "key:V", nullptr, 0x00080000u, 0, 0, false, true, nullptr, "design_dimension", L("Type the angle between two lines, or the distance between the two picks")},
|
||||
};
|
||||
static const int kOfferVerbCount = 92;
|
||||
|
||||
|
||||
+142
-128
@@ -110,15 +110,6 @@
|
||||
#include "slic3r/GUI/Shortcuts.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
|
||||
// English-only pin for the Design tab (see design-ux-contract): one lever
|
||||
// de-translates this whole TU so our strings never half-translate against the host's
|
||||
// localized chrome. Host UI still follows the app locale; only this tab is pinned EN.
|
||||
// GOTCHA: every _L(...) in this file must take a STRING LITERAL (FromUTF8 wants const char*).
|
||||
#ifdef _L
|
||||
#undef _L
|
||||
#endif
|
||||
#define _L(s) wxString::FromUTF8(s)
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
// Mesh -> B-rep import defaults (see GeometryEngine::mesh_to_brep).
|
||||
@@ -498,7 +489,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
}
|
||||
m_viewport->set_sketch_construction(m_construction->GetValue());
|
||||
set_status(StatusKind::Info, m_sketch_on.IsEmpty() ? hint
|
||||
: wxString::Format(_L("%s · on %s"), hint, m_sketch_on));
|
||||
: wxString::Format(_L("%s · plane: %s"), hint, m_sketch_on));
|
||||
};
|
||||
|
||||
// Sketch-tool shortcuts (single letters, active only while a sketch is open). Family tools
|
||||
@@ -731,11 +722,11 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
wxString where;
|
||||
const bool have_plane = sketch_plane_target(where);
|
||||
set_status(StatusKind::Info, have_plane
|
||||
? wxString::Format(_L("Sketching on %s — pick a tool"), where)
|
||||
? wxString::Format(_L("Sketch plane: %s — pick a tool"), where)
|
||||
: _L("Click a face or a reference plane in the viewport, then a sketch tool"));
|
||||
if (m_sketch_hint) { // the card must agree with the status line, not argue with it
|
||||
m_sketch_hint->SetLabel(have_plane
|
||||
? wxString::Format(_L("Drawing on %s.\nPick a tool, or press Menu for the list."), where)
|
||||
? wxString::Format(_L("Sketch plane: %s.\nPick a tool, or press Menu for the list."), where)
|
||||
: _L("Click a face or a reference plane, then a sketch tool."));
|
||||
m_sketch_hint->Refresh();
|
||||
m_cards->Layout();
|
||||
@@ -752,7 +743,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// Add material: every feature that grows new solid material — from a profile
|
||||
// (extrude/revolve/sweep/loft), from a face (thicken) or from a line (rib).
|
||||
feat_dropdown("material", "design_extrude", _L("Add material (extrude / revolve / sweep / loft / thicken / rib)"), {
|
||||
{"design_extrude", _L("Extrude"), _L("Extrude a sketch profile, or push/pull a picked face"),
|
||||
{"design_extrude", _L_CONTEXT("Extrude", "Design"), _L("Extrude a sketch profile, or push/pull a picked face"),
|
||||
[this] {
|
||||
// Onshape push/pull: an explicitly picked solid face (Face-level cycle, no loop
|
||||
// selected) is extruded as the profile — this takes priority over re-extruding an
|
||||
@@ -833,7 +824,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
m_sel_solid_face = -1;
|
||||
open_tool(Tool::Thicken); // syncs m_thicken_face_label from m_sel_solid_face
|
||||
}, 0},
|
||||
{"design_rib", _L("Rib"), _L("Grow a thin wall from an open sketch line, fused to a body"),
|
||||
{"design_rib", _L_CONTEXT("Rib", "Design"), _L("Grow a thin wall from an open sketch line, fused to a body"),
|
||||
[this] {
|
||||
if (m_doc.bodies.empty()) {
|
||||
set_status(StatusKind::Error, _L("Rib needs a solid body — add or import one first"));
|
||||
@@ -873,7 +864,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// shortcut at all, which also made its card unreachable to the rig.
|
||||
});
|
||||
|
||||
auto* b_pattern = icon_btn("design_pattern", _L("Pattern"));
|
||||
auto* b_pattern = icon_btn("design_pattern", _L_CONTEXT("Pattern", "Design"));
|
||||
std::function<void()> act_pattern = [this] {
|
||||
// Pattern replicates an existing body — needs at least one solid.
|
||||
if (m_doc.bodies.empty()) {
|
||||
@@ -979,7 +970,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
}, 0},
|
||||
// Project belongs here, not in Dress-up: it consumes a body but PRODUCES sketch
|
||||
// geometry, so it is reference/curve creation like the four above, not a finishing op.
|
||||
{"design_sketch", _L("Project"), _L("Project body edges onto a plane as sketch entities"),
|
||||
{"design_sketch", _L_CONTEXT("Project", "Design"), _L("Project body edges onto a plane as sketch entities"),
|
||||
[this] {
|
||||
if (m_doc.bodies.empty()) {
|
||||
set_status(StatusKind::Error, _L("Project needs a body — add or import one first"));
|
||||
@@ -1139,7 +1130,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
[this] { open_tool(Tool::Dressup); }, SHIFT('F')},
|
||||
{"design_draft", _L("Draft (taper a face)"), _L("Tilt a picked face by a draft angle"),
|
||||
[this] { open_tool(Tool::Draft); }, SHIFT('D')},
|
||||
{"design_shell", _L("Shell"), _L("Hollow the body to a wall thickness, opening a picked face"),
|
||||
{"design_shell", _L_CONTEXT("Shell", "Design"), _L("Hollow the body to a wall thickness, opening a picked face"),
|
||||
[this] { open_tool(Tool::Shell); }, SHIFT('K')},
|
||||
{"design_delete", _L("Delete Face"), _L("Remove faces from a body and heal the solid"),
|
||||
[this] {
|
||||
@@ -1165,7 +1156,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
// Hole / Thread — drilling into a solid (both face-aware)
|
||||
feat_dropdown("hole", "design_hole", _L("Hole / thread"), {
|
||||
{"design_hole", _L("Hole"), _L("Drill a hole, centerd on a picked face or placed on a plane"),
|
||||
{"design_hole", _L("Hole"), _L("Drill a hole, centered on a picked face or placed on a plane"),
|
||||
[this] {
|
||||
// #2: drill on the picked solid face, centred on it (origin = face centroid,
|
||||
// normal = inward). Otherwise fall back to the plane dropdown. m_hole_x/y then
|
||||
@@ -1542,8 +1533,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
if (n > 0) {
|
||||
m_construction->SetValue(!m_construction->GetValue()); // the mode did not move
|
||||
set_status(StatusKind::Info, wxString::Format(
|
||||
_L("Converted %d entit%s between construction and real geometry"),
|
||||
n, n == 1 ? "y" : "ies"));
|
||||
_L_PLURAL("Converted %d entity between construction and real geometry",
|
||||
"Converted %d entities between construction and real geometry", n),
|
||||
n));
|
||||
return;
|
||||
}
|
||||
m_viewport->set_sketch_construction(m_construction->GetValue()); });
|
||||
@@ -1574,26 +1566,26 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
b->Bind(wxEVT_BUTTON, [this, type](wxCommandEvent&) { apply_constraint(type); });
|
||||
cadd(b);
|
||||
};
|
||||
cbtn("design_c_horizontal", _L("Horizontal"), SketchConstraintType::Horizontal);
|
||||
cbtn("design_c_vertical", _L("Vertical"), SketchConstraintType::Vertical);
|
||||
cbtn("design_c_parallel", _L("Parallel"), SketchConstraintType::Parallel);
|
||||
cbtn("design_c_perpendicular", _L("Perpendicular"), SketchConstraintType::Perpendicular);
|
||||
cbtn("design_c_coincident", _L("Coincident"), SketchConstraintType::Coincident);
|
||||
cbtn("design_c_equal", _L("Equal length"), SketchConstraintType::EqualLength);
|
||||
cbtn("design_c_equal_radius", _L("Equal radius"), SketchConstraintType::EqualRadius);
|
||||
cbtn("design_c_collinear", _L("Collinear"), SketchConstraintType::Collinear);
|
||||
cbtn("design_c_concentric", _L("Concentric"), SketchConstraintType::Concentric);
|
||||
cbtn("design_c_tangent", _L("Tangent"), SketchConstraintType::Tangent);
|
||||
cbtn("design_c_midpoint", _L("Midpoint"), SketchConstraintType::Midpoint);
|
||||
cbtn("design_c_symmetric", _L("Symmetric"), SketchConstraintType::Symmetric);
|
||||
cbtn("design_c_sym_v", _L("Symmetric about the vertical axis"), SketchConstraintType::SymmetricAboutY);
|
||||
cbtn("design_c_sym_h", _L("Symmetric about the horizontal axis"), SketchConstraintType::SymmetricAboutX);
|
||||
cbtn("design_c_angle", _L("Angle"), SketchConstraintType::Angle);
|
||||
cbtn("design_c_radius", _L("Radius"), SketchConstraintType::Radius);
|
||||
cbtn("design_c_diameter", _L("Diameter"), SketchConstraintType::Diameter);
|
||||
cbtn("design_c_fix", _L("Fix point (anchor in place)"), SketchConstraintType::Fix);
|
||||
cbtn("design_c_dist_x", _L("Horizontal distance"), SketchConstraintType::DistanceX);
|
||||
cbtn("design_c_dist_y", _L("Vertical distance"), SketchConstraintType::DistanceY);
|
||||
cbtn("design_c_horizontal", _L_CONTEXT("Horizontal", "Sketch Constraint"), SketchConstraintType::Horizontal);
|
||||
cbtn("design_c_vertical", _L_CONTEXT("Vertical", "Sketch Constraint"), SketchConstraintType::Vertical);
|
||||
cbtn("design_c_parallel", _L_CONTEXT("Parallel", "Sketch Constraint"), SketchConstraintType::Parallel);
|
||||
cbtn("design_c_perpendicular", _L_CONTEXT("Perpendicular", "Sketch Constraint"), SketchConstraintType::Perpendicular);
|
||||
cbtn("design_c_coincident", _L_CONTEXT("Coincident", "Sketch Constraint"), SketchConstraintType::Coincident);
|
||||
cbtn("design_c_equal", _L_CONTEXT("Equal length", "Sketch Constraint"), SketchConstraintType::EqualLength);
|
||||
cbtn("design_c_equal_radius", _L_CONTEXT("Equal radius", "Sketch Constraint"), SketchConstraintType::EqualRadius);
|
||||
cbtn("design_c_collinear", _L_CONTEXT("Collinear", "Sketch Constraint"), SketchConstraintType::Collinear);
|
||||
cbtn("design_c_concentric", _L_CONTEXT("Concentric", "Sketch Constraint"), SketchConstraintType::Concentric);
|
||||
cbtn("design_c_tangent", _L_CONTEXT("Tangent", "Sketch Constraint"), SketchConstraintType::Tangent);
|
||||
cbtn("design_c_midpoint", _L_CONTEXT("Midpoint", "Sketch Constraint"), SketchConstraintType::Midpoint);
|
||||
cbtn("design_c_symmetric", _L_CONTEXT("Symmetric", "Sketch Constraint"), SketchConstraintType::Symmetric);
|
||||
cbtn("design_c_sym_v", _L_CONTEXT("Symmetric about the vertical axis", "Sketch Constraint"), SketchConstraintType::SymmetricAboutY);
|
||||
cbtn("design_c_sym_h", _L_CONTEXT("Symmetric about the horizontal axis", "Sketch Constraint"), SketchConstraintType::SymmetricAboutX);
|
||||
cbtn("design_c_angle", _L_CONTEXT("Angle", "Sketch Constraint"), SketchConstraintType::Angle);
|
||||
cbtn("design_c_radius", _L_CONTEXT("Radius", "Sketch Constraint"), SketchConstraintType::Radius);
|
||||
cbtn("design_c_diameter", _L_CONTEXT("Diameter", "Sketch Constraint"), SketchConstraintType::Diameter);
|
||||
cbtn("design_c_fix", _L_CONTEXT("Fix point (anchor in place)", "Sketch Constraint"), SketchConstraintType::Fix);
|
||||
cbtn("design_c_dist_x", _L_CONTEXT("Horizontal distance", "Sketch Constraint"), SketchConstraintType::DistanceX);
|
||||
cbtn("design_c_dist_y", _L_CONTEXT("Vertical distance", "Sketch Constraint"), SketchConstraintType::DistanceY);
|
||||
// Trim/Extend are now standalone SKETCH scissors (Mode::Trim/Extend) in the sketch
|
||||
// toolbar, NOT Constrain buttons. The other edit ops (Mirror/Offset/Fillet/Chamfer/
|
||||
// Move/…) are first-class sketch tools too. Done constraining = the action-bar ✓.
|
||||
@@ -1894,7 +1886,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
// --- Extrude dialog (consumes the selected sketch) ---
|
||||
m_box_extrude = new wxBoxSizer(wxVERTICAL);
|
||||
m_box_extrude->Add(card_header(m_cards, "design_extrude", _L("Extrude"), m_hdr_extrude), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_extrude->Add(card_header(m_cards, "design_extrude", _L_CONTEXT("Extrude", "Design"), m_hdr_extrude), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_extrude->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||
m_extrude_sketch_label = new wxStaticText(m_cards, wxID_ANY, _L("Sketch: —"));
|
||||
m_box_extrude->Add(m_extrude_sketch_label, 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
@@ -1912,9 +1904,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// End condition (order MUST match ExtrudeEnd: Blind/Symmetric/TwoSided/ThroughAll/
|
||||
// UpToFace/UpToVertex). Up-to-face uses the currently click-selected solid face.
|
||||
m_extrude_end = make_combo(m_cards);
|
||||
for (const char* s : { "Blind", "Symmetric", "Two-sided", "Through all",
|
||||
"Up to face", "Up to vertex" })
|
||||
m_extrude_end->Append(s);
|
||||
for (const char* s : { L("Blind"), L("Symmetric"), L("Two-sided"), L("Through all"),
|
||||
L("Up to face"), L("Up to vertex") })
|
||||
m_extrude_end->Append(_L(s));
|
||||
m_extrude_end->SetSelection(0);
|
||||
eform->Add(new wxStaticText(m_cards, wxID_ANY, _L("End")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
eform->Add(m_extrude_end, 0, wxEXPAND);
|
||||
@@ -1931,8 +1923,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// Order is load-bearing: index maps to BooleanMode (New=0, Add=1, Cut=2, Intersect=3).
|
||||
// Labels use Onshape wording so the choice reads as the user thinks of it.
|
||||
m_mode->Append(_L("New body")); // separate coexisting solid
|
||||
m_mode->Append(_L("Join")); // fuse into the target body (was "Add")
|
||||
m_mode->Append(_L("Cut")); // subtract from the target body
|
||||
m_mode->Append(_L_CONTEXT("Join", "Boolean Mode")); // fuse into the target body (was "Add")
|
||||
m_mode->Append(_L_CONTEXT("Cut", "Boolean Mode")); // subtract from the target body
|
||||
m_mode->Append(_L("Intersect")); // keep only the overlap
|
||||
m_mode->SetSelection(0);
|
||||
eform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
@@ -1968,6 +1960,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
m_face_group = make_combo(m_cards);
|
||||
m_face_group->Append(_L("Top")); // index 0 -> FaceGroup::Top
|
||||
m_face_group->Append(_L("Bottom")); // 1 -> Bottom
|
||||
// TRN Fillet/Chamfer edge group used when no edge is picked: the side edges, as opposed to the top and bottom ones.
|
||||
m_face_group->Append(_L("Lateral")); // 2 -> Lateral
|
||||
m_face_group->Append(_L("All")); // 3 -> All
|
||||
m_face_group->SetSelection(3);
|
||||
@@ -2129,8 +2122,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
m_revolve_mode = make_combo(m_cards);
|
||||
m_revolve_mode->Append(_L("New body")); // same four words as Extrude
|
||||
m_revolve_mode->Append(_L("Join"));
|
||||
m_revolve_mode->Append(_L("Cut"));
|
||||
m_revolve_mode->Append(_L_CONTEXT("Join", "Boolean Mode"));
|
||||
m_revolve_mode->Append(_L_CONTEXT("Cut", "Boolean Mode"));
|
||||
m_revolve_mode->Append(_L("Intersect"));
|
||||
m_revolve_mode->SetSelection(0);
|
||||
rform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
@@ -2159,8 +2152,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
m_sweep_mode = make_combo(m_cards);
|
||||
m_sweep_mode->Append(_L("New body")); // same four words as Extrude
|
||||
m_sweep_mode->Append(_L("Join"));
|
||||
m_sweep_mode->Append(_L("Cut"));
|
||||
m_sweep_mode->Append(_L_CONTEXT("Join", "Boolean Mode"));
|
||||
m_sweep_mode->Append(_L_CONTEXT("Cut", "Boolean Mode"));
|
||||
m_sweep_mode->Append(_L("Intersect"));
|
||||
m_sweep_mode->SetSelection(0);
|
||||
sform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
@@ -2172,14 +2165,14 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
// --- Pattern (replicate the target body: linear or circular) ---
|
||||
m_box_pattern = new wxBoxSizer(wxVERTICAL);
|
||||
m_box_pattern->Add(card_header(m_cards, "design_pattern", _L("Pattern"), m_hdr_pattern), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_pattern->Add(card_header(m_cards, "design_pattern", _L_CONTEXT("Pattern", "Design"), m_hdr_pattern), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_pattern->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||
{
|
||||
auto* pform = two_col_form();
|
||||
|
||||
m_pattern_type = make_combo(m_cards);
|
||||
m_pattern_type->Append(_L("Linear"));
|
||||
m_pattern_type->Append(_L("Circular"));
|
||||
m_pattern_type->Append(_L_CONTEXT("Linear", "Design"));
|
||||
m_pattern_type->Append(_L_CONTEXT("Circular", "Design"));
|
||||
m_pattern_type->SetSelection(0);
|
||||
pform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Type")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
pform->Add(m_pattern_type, 0, wxEXPAND);
|
||||
@@ -2215,7 +2208,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
auto* bform = two_col_form();
|
||||
|
||||
m_bool_op = make_combo(m_cards);
|
||||
m_bool_op->Append(_L("Join")); // the Extrude result word; the offer row says the same
|
||||
m_bool_op->Append(_L_CONTEXT("Join", "Boolean Mode")); // the Extrude result word; the offer row says the same
|
||||
m_bool_op->Append(_L("Subtract"));
|
||||
m_bool_op->Append(_L("Intersect"));
|
||||
m_bool_op->SetSelection(0);
|
||||
@@ -2255,7 +2248,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
// --- Cut (split a body with a plane): parameters only; ✓/✗ live on the ribbon ---
|
||||
m_box_cut = new wxBoxSizer(wxVERTICAL);
|
||||
m_box_cut->Add(card_header(m_cards, "design_cut", _L("Cut"), m_hdr_cut), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_cut->Add(card_header(m_cards, "design_cut", _L_CONTEXT("Cut", "Design"), m_hdr_cut), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_cut->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||
{
|
||||
auto* cform = two_col_form();
|
||||
@@ -2314,6 +2307,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
m_plane_base = make_combo(m_cards);
|
||||
populate_plane_choices(m_plane_base); // XY/XZ/YZ + any existing datum planes
|
||||
// TRN Plane tool: the reference plane (XY, XZ, YZ or a datum) the new plane is built from.
|
||||
plform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Base")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
plform->Add(m_plane_base, 0, wxEXPAND);
|
||||
|
||||
@@ -2371,8 +2365,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
m_loft_mode = make_combo(m_cards);
|
||||
m_loft_mode->Append(_L("New body")); // same four words as Extrude
|
||||
m_loft_mode->Append(_L("Join"));
|
||||
m_loft_mode->Append(_L("Cut"));
|
||||
m_loft_mode->Append(_L_CONTEXT("Join", "Boolean Mode"));
|
||||
m_loft_mode->Append(_L_CONTEXT("Cut", "Boolean Mode"));
|
||||
m_loft_mode->Append(_L("Intersect"));
|
||||
m_loft_mode->SetSelection(0);
|
||||
lform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
@@ -2515,7 +2509,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
sform->Add(m_shell_face_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
m_box_shell = new wxBoxSizer(wxVERTICAL);
|
||||
m_box_shell->Add(card_header(m_cards, "design_shell", _L("Shell"), m_hdr_shell), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_shell->Add(card_header(m_cards, "design_shell", _L_CONTEXT("Shell", "Design"), m_hdr_shell), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_shell->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||
m_box_shell->Add(new wxStaticText(m_cards, wxID_ANY,
|
||||
_L("Pick a solid face to open it, then set the wall thickness.")),
|
||||
@@ -2663,7 +2657,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
// --- Rib (thin wall from an open sketch line, fused to a body) ---
|
||||
m_box_rib = new wxBoxSizer(wxVERTICAL);
|
||||
m_box_rib->Add(card_header(m_cards, "design_rib", _L("Rib"), m_hdr_rib), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_rib->Add(card_header(m_cards, "design_rib", _L_CONTEXT("Rib", "Design"), m_hdr_rib), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_rib->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||
{
|
||||
auto* rform = two_col_form();
|
||||
@@ -2699,7 +2693,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
// --- Project (project body edges onto a plane as sketch entities) ---
|
||||
m_box_project = new wxBoxSizer(wxVERTICAL);
|
||||
m_box_project->Add(card_header(m_cards, "design_sketch", _L("Project"), m_hdr_project), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_project->Add(card_header(m_cards, "design_sketch", _L_CONTEXT("Project", "Design"), m_hdr_project), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_project->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||
{
|
||||
auto* pform = two_col_form();
|
||||
@@ -2937,11 +2931,11 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
m_cs_hx = make_spin(m_cards, 1.0, -100000.0, 100000.0);
|
||||
m_cs_hy = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||
m_cs_hz = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X hint X")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X direction X")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
csform->Add(spin_frame(m_cs_hx), 0, wxEXPAND);
|
||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X hint Y")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X direction Y")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
csform->Add(spin_frame(m_cs_hy), 0, wxEXPAND);
|
||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X hint Z")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X direction Z")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
csform->Add(spin_frame(m_cs_hz), 0, wxEXPAND);
|
||||
|
||||
m_box_coordsys->Add(csform, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
@@ -3190,7 +3184,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// one click away on a row the user has just selected — the message points at it instead
|
||||
// of describing a problem with no way out.
|
||||
if (const std::string* why = (sel >= 0) ? mate_conflict_reason(sel) : nullptr) {
|
||||
set_status(StatusKind::Error, wxString::FromUTF8(*why) + _L(" — the eye suppresses this mate"));
|
||||
set_status(StatusKind::Error, wxString::Format(_L("%s. Click the eye icon to suppress this mate."), wxString::FromUTF8(*why)));
|
||||
} else if (sel >= 0 && sel < int(m_doc.features.size())) {
|
||||
// Name the two gestures the row supports, because neither is visible on it.
|
||||
set_status(StatusKind::Info, wxString::Format(
|
||||
@@ -3882,7 +3876,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
if (got && m_viewport) m_viewport->set_escalate_on_repick(true);
|
||||
}
|
||||
const int nb = int(m_doc.bodies.size());
|
||||
const wxString bodytag = (nb > 1) ? wxString::Format(_L("Body %d "), body + 1) : wxString();
|
||||
const bool bodytag = nb > 1;
|
||||
// Each sub-element line ends by naming the NEXT click (gem). Escalation to the
|
||||
// whole body is a gesture nothing on screen would otherwise reveal, and the status line
|
||||
// is the only surface that can teach it at the moment it applies. It REPLACES the old
|
||||
@@ -3894,13 +3888,22 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
// into the panel. Say "what applies to it", never "verbs" — that is this codebase's
|
||||
// word for a tool-offer entry, not a word the drawing office uses, and the plane and
|
||||
// bodies-list lines already say it the right way.
|
||||
set_status(level == 4 ? bodytag + _L("vertex selected — click again for the whole body")
|
||||
: level == 1 ? bodytag + _L("selected (whole body) — right-click for what applies to it")
|
||||
: level == 2 ? bodytag + wxString::Format(_L("face %d selected — right-click to push/pull it, or click again for the whole body"), face)
|
||||
: level == 3 && m_sel_solid_edges.size() > 1
|
||||
? bodytag + wxString::Format(_L_PLURAL("%zu edge selected — Shift+click adds or removes one, Fillet/Chamfer dresses them all", "%zu edges selected — Shift+click adds or removes one, Fillet/Chamfer dresses them all", m_sel_solid_edges.size()), m_sel_solid_edges.size())
|
||||
: level == 3 ? bodytag + wxString::Format(_L("edge %d selected — Shift+click to add edges, or click again for the whole body"), edge)
|
||||
: _L("Nothing selected"));
|
||||
set_status(level == 4 ? (bodytag ? wxString::Format(_L("Body %d: vertex selected — click again for the whole body"), body + 1)
|
||||
: _L("Vertex selected — click again for the whole body"))
|
||||
: level == 1 ? (bodytag ? wxString::Format(_L("Body %d selected (whole body) — right-click for what applies to it"), body + 1)
|
||||
: _L("Whole body selected — right-click for what applies to it"))
|
||||
: level == 2 ? (bodytag ? wxString::Format(_L("Body %d: face %d selected — right-click to push/pull it, or click again for the whole body"), body + 1, face)
|
||||
: wxString::Format(_L("Face %d selected — right-click to push/pull it, or click again for the whole body"), face))
|
||||
: level == 3 && m_sel_solid_edges.size() > 1
|
||||
? (bodytag ? wxString::Format(_L_PLURAL("Body %d: %zu edge selected — Shift+click adds or removes one, Fillet/Chamfer dresses them all",
|
||||
"Body %d: %zu edges selected — Shift+click adds or removes one, Fillet/Chamfer dresses them all",
|
||||
unsigned(m_sel_solid_edges.size())), body + 1, m_sel_solid_edges.size())
|
||||
: wxString::Format(_L_PLURAL("%zu edge selected — Shift+click adds or removes one, Fillet/Chamfer dresses them all",
|
||||
"%zu edges selected — Shift+click adds or removes one, Fillet/Chamfer dresses them all",
|
||||
unsigned(m_sel_solid_edges.size())), m_sel_solid_edges.size()))
|
||||
: level == 3 ? (bodytag ? wxString::Format(_L("Body %d: edge %d selected — Shift+click to add edges, or click again for the whole body"), body + 1, edge)
|
||||
: wxString::Format(_L("Edge %d selected — Shift+click to add edges, or click again for the whole body"), edge))
|
||||
: _L("Nothing selected"));
|
||||
m_status->Refresh();
|
||||
});
|
||||
// A click on nothing drops a list row as it drops a pick. Not while a card is open: the
|
||||
@@ -3995,7 +3998,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
if (m_viewport && m_viewport->is_sketching())
|
||||
m_viewport->set_sketch_plane(plane_from_choice(m_ref_plane));
|
||||
}
|
||||
const char* nm = (base == 0) ? "XY" : (base == 1) ? "XZ" : (base == 2) ? "YZ" : "datum";
|
||||
const wxString nm = ref_plane_name(base);
|
||||
// Both halves named the TOOLBAR, which no longer carries either button: the tools
|
||||
// moved to the offer. Name the gesture that actually works in each mode, and say
|
||||
// what a plain click does, since the two are easy to confuse on a plane.
|
||||
@@ -4036,10 +4039,12 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
if (m_xf_angle) m_xf_angle->SetValue(sign * aa.angle() * 180.0 / M_PI);
|
||||
}
|
||||
const int nb = int(m_doc.bodies.size());
|
||||
const wxString tag = (nb > 1) ? wxString::Format(_L("Body %d "), body + 1) : wxString();
|
||||
const Vec3d t = xform.translation();
|
||||
set_status(StatusKind::Info, tag + wxString::Format(_L("placed (%.1f, %.1f, %.1f) mm — drag arrows to move, rings to rotate"),
|
||||
t.x(), t.y(), t.z()));
|
||||
set_status(StatusKind::Info, nb > 1
|
||||
? wxString::Format(_L("Body %d placed at (%.1f, %.1f, %.1f) mm — drag arrows to move, rings to rotate"),
|
||||
body + 1, t.x(), t.y(), t.z())
|
||||
: wxString::Format(_L("Placed at (%.1f, %.1f, %.1f) mm — drag arrows to move, rings to rotate"),
|
||||
t.x(), t.y(), t.z()));
|
||||
});
|
||||
|
||||
// Fillet/Chamfer radius gizmo: dragging (or editing) the edge-anchored arrow writes the
|
||||
@@ -4126,7 +4131,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
set_status(error ? StatusKind::Error : StatusKind::Info, wxString::FromUTF8(msg));
|
||||
});
|
||||
m_viewport->set_on_sketch_exit_refused([this]() {
|
||||
set_status(StatusKind::Info, _L("Sketch kept — Finish to commit it, Cancel to discard"));
|
||||
set_status(StatusKind::Info, _L("Sketch kept — Confirm to commit it, Cancel to discard"));
|
||||
});
|
||||
|
||||
// Ctrl+Z / Ctrl+Shift+Z (Ctrl+Y) from the viewport → feature-history undo/redo.
|
||||
@@ -4444,7 +4449,7 @@ void DesignPanel::apply_dof_status(int dof, bool ok, bool has_constraints)
|
||||
m_dof_status->SetLabel(_L("✓ Fully constrained"));
|
||||
} else if (dof > 0) {
|
||||
m_dof_status->SetForegroundColour(dp_ctl_text());
|
||||
m_dof_status->SetLabel(wxString::Format(_L("%d degrees of freedom"), dof));
|
||||
m_dof_status->SetLabel(wxString::Format(_L_PLURAL("%d degree of freedom", "%d degrees of freedom", dof), dof));
|
||||
} else {
|
||||
m_dof_status->SetLabel(wxString());
|
||||
}
|
||||
@@ -4521,7 +4526,7 @@ void DesignPanel::set_ui_mode(UiMode m)
|
||||
if (sketching && m_sketch_banner_txt != nullptr)
|
||||
m_sketch_banner_txt->SetLabel(
|
||||
wxString::Format(_L("Editing: Sketch %d · N = look normal to the plane · "
|
||||
"Finish or Cancel in the toolbar"),
|
||||
"Confirm or Cancel in the toolbar"),
|
||||
m_feature_counter + 1));
|
||||
m_sketch_banner->Show(sketching);
|
||||
m_sketch_banner->GetParent()->Layout();
|
||||
@@ -4778,7 +4783,7 @@ void DesignPanel::text_dialog_done(bool accepted)
|
||||
void DesignPanel::on_import_svg()
|
||||
{
|
||||
wxFileDialog dlg(this, _L("Import SVG"), wxEmptyString, wxEmptyString,
|
||||
"SVG files (*.svg)|*.svg|All files|*.*",
|
||||
_L("SVG files (*.svg)|*.svg|All files|*.*"),
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
@@ -4890,7 +4895,7 @@ bool DesignPanel::recompute_guarded(const wxString& message)
|
||||
void DesignPanel::on_import_step()
|
||||
{
|
||||
wxFileDialog dlg(this, _L("Import STEP"), wxEmptyString, wxEmptyString,
|
||||
"STEP files (*.step;*.stp)|*.step;*.stp|All files|*.*",
|
||||
_L("STEP files (*.step;*.stp)|*.step;*.stp|All files|*.*"),
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
@@ -4938,7 +4943,9 @@ void DesignPanel::on_import_step()
|
||||
set_tree_selection(int(m_doc.features.size()) - 1);
|
||||
set_status_ok(); // canonical post-recompute viewport/pick/parts refresh
|
||||
set_status(StatusKind::Info, wxString::Format(
|
||||
_L("Imported %d solid(s) — pick a face or edge, then Fillet / Cut / Shell to modify"),
|
||||
_L_PLURAL("Imported %d solid — pick a face or edge, then Fillet / Cut / Shell to modify",
|
||||
"Imported %d solids — pick a face or edge, then Fillet / Cut / Shell to modify",
|
||||
unsigned(solids.size())),
|
||||
int(solids.size())));
|
||||
}
|
||||
|
||||
@@ -4949,7 +4956,7 @@ void DesignPanel::on_import_step()
|
||||
void DesignPanel::on_import_mesh()
|
||||
{
|
||||
wxFileDialog dlg(this, _L("Import mesh"), wxEmptyString, wxEmptyString,
|
||||
"Mesh files (*.stl;*.obj)|*.stl;*.obj|All files|*.*",
|
||||
_L("Mesh files (*.stl;*.obj)|*.stl;*.obj|All files|*.*"),
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
@@ -5032,8 +5039,8 @@ void DesignPanel::on_import_mesh()
|
||||
stats.kept_tris, stats.faces_final, stats.volume));
|
||||
} else {
|
||||
set_status(StatusKind::Warning, wxString::Format(
|
||||
_L("Imported as an open shell (not watertight): %d boundary edge(s), %d non-manifold "
|
||||
"edge(s) — %d triangles → %d faces. The source mesh has holes or duplicated "
|
||||
_L("Imported as an open shell (not watertight). Boundary edges: %d, non-manifold "
|
||||
"edges: %d, triangles: %d → faces: %d. The source mesh has holes or duplicated "
|
||||
"geometry; boolean features may fail on it"),
|
||||
stats.boundary_edges, stats.nonmanifold_edges, stats.kept_tris, stats.faces_final));
|
||||
}
|
||||
@@ -5144,7 +5151,7 @@ void DesignPanel::cancel_insert()
|
||||
set_ui_mode(UiMode::Feature);
|
||||
sync_sketch_display();
|
||||
refresh_tree();
|
||||
set_status(StatusKind::Info, _L("Insert cancelled"));
|
||||
set_status(StatusKind::Info, _L("Insert canceled"));
|
||||
}
|
||||
|
||||
void DesignPanel::on_transform_imported(int feat_idx)
|
||||
@@ -5171,7 +5178,7 @@ void DesignPanel::on_add_sketch()
|
||||
m_doc.add_sketch(shape, plane, m_width->GetValue(), m_height->GetValue(),
|
||||
m_radius->GetValue(), feature_name(_L("Sketch")));
|
||||
m_doc.recompute(); // a lone sketch yields an empty body; that is expected
|
||||
set_status(StatusKind::Info, wxString::Format(_L("Sketch added on %s — select it, then right-click to Extrude"), where));
|
||||
set_status(StatusKind::Info, wxString::Format(_L("Sketch added (plane: %s) — select it, then right-click to Extrude"), where));
|
||||
refresh_tree();
|
||||
}
|
||||
|
||||
@@ -5882,7 +5889,8 @@ void DesignPanel::on_check_interference()
|
||||
body_name(sorted[k].body_b), sorted[k].volume);
|
||||
if (sorted.size() > shown)
|
||||
list += wxString::FromUTF8(", …");
|
||||
set_status(StatusKind::Warning, wxString::Format(_L("%zu overlapping pairs: %s"), sorted.size(), list));
|
||||
set_status(StatusKind::Warning, wxString::Format(_L_PLURAL("%zu overlapping pair: %s", "%zu overlapping pairs: %s",
|
||||
unsigned(sorted.size())), sorted.size(), list));
|
||||
}
|
||||
|
||||
// Volume and surface area of the selected body. A report, not a feature: it never checkpoints,
|
||||
@@ -6131,8 +6139,8 @@ SketchPlane DesignPanel::sketch_plane_from_selection(wxString& what) const
|
||||
const int fi = (m_sel_solid_face >= 0 && m_sel_solid_body >= 0) ? m_sel_solid_face : m_pick_face;
|
||||
if (fb >= 0 && fi >= 0 && m_doc.plane_of_face(fb, fi, p)) {
|
||||
what = (m_doc.bodies.size() > 1)
|
||||
? wxString::Format(_L("the picked face of Body %d"), fb + 1)
|
||||
: _L("the picked face");
|
||||
? wxString::Format(_L("Picked face (Body %d)"), fb + 1)
|
||||
: _L("Picked face");
|
||||
return p;
|
||||
}
|
||||
what = ref_plane_name(m_ref_plane);
|
||||
@@ -6150,8 +6158,8 @@ bool DesignPanel::sketch_plane_target(wxString& what) const
|
||||
SketchPlane p;
|
||||
if (fb >= 0 && fi >= 0 && m_doc.plane_of_face(fb, fi, p)) {
|
||||
what = (m_doc.bodies.size() > 1)
|
||||
? wxString::Format(_L("the picked face of Body %d"), fb + 1)
|
||||
: _L("the picked face");
|
||||
? wxString::Format(_L("Picked face (Body %d)"), fb + 1)
|
||||
: _L("Picked face");
|
||||
return true;
|
||||
}
|
||||
if (m_plane_picked) { what = ref_plane_name(m_ref_plane); return true; }
|
||||
@@ -6377,8 +6385,10 @@ static wxString sketch_step_prompt(DesignSketchTool::Mode m, int step, int picks
|
||||
switch (m) {
|
||||
case Mode::Select:
|
||||
return picks > 0
|
||||
? wxString::Format(_L("%d selected · Del removes them · Shift-click adds · "
|
||||
"double-click takes the whole loop"), picks)
|
||||
? wxString::Format(_L_PLURAL("%d selected · Del removes it · Shift-click adds · "
|
||||
"double-click takes the whole loop",
|
||||
"%d selected · Del removes them · Shift-click adds · "
|
||||
"double-click takes the whole loop", picks), picks)
|
||||
: _L("Select — click an entity to pick it · drag an endpoint or center to move it · "
|
||||
"Shift-click adds · Del removes");
|
||||
case Mode::Constrain:
|
||||
@@ -6627,8 +6637,7 @@ void DesignPanel::show_offer_menu(const wxPoint& screen_pos)
|
||||
return (v.accepts & bit) && v.need_bodies <= bodies && v.need_sketches <= sketches
|
||||
&& (!v.need_sheet || sheet);
|
||||
};
|
||||
// Names and reasons live in the generated table as plain literals; they are the same strings
|
||||
// the toolbar already ships, so the catalogue already carries their translations.
|
||||
// Row names, verb names, refusals, families and hints are L()-marked in the generated table.
|
||||
// Scope the lookup to the APPLICATION catalog. A bare wxGetTranslation() searches every
|
||||
// loaded catalog, wxWidgets' own wxstd included — so on a non-English system the two row
|
||||
// names that happen to be wx standard strings came back translated while the other six,
|
||||
@@ -6642,7 +6651,7 @@ void DesignPanel::show_offer_menu(const wxPoint& screen_pos)
|
||||
return wxGetTranslation(wxString::FromUTF8(s), SLIC3R_APP_KEY);
|
||||
};
|
||||
auto label = [&](const OfferVerb& v) {
|
||||
wxString s = tr(v.name);
|
||||
wxString s = I18N::translate(v.name, "Design");
|
||||
if (v.key && *v.key) s += "\t" + wxString::FromUTF8(v.key);
|
||||
return s;
|
||||
};
|
||||
@@ -7630,8 +7639,8 @@ void DesignPanel::flip_section_view()
|
||||
if (!m_viewport || !m_section_on) return;
|
||||
m_section_upper = !m_section_upper;
|
||||
m_viewport->set_section_plane(true, m_section_cut_z, m_section_upper);
|
||||
set_status(StatusKind::Info, wxString::Format(_L("Section view — showing the %s half"),
|
||||
m_section_upper ? _L("upper") : _L("lower")));
|
||||
set_status(StatusKind::Info, m_section_upper ? _L("Section view — showing the upper half")
|
||||
: _L("Section view — showing the lower half"));
|
||||
}
|
||||
|
||||
void DesignPanel::sync_body_visible()
|
||||
@@ -8295,8 +8304,10 @@ void DesignPanel::apply_live_constraint(SketchConstraintType type)
|
||||
// tool auto-selects only the entity it just drew — so after drawing two lines exactly
|
||||
// one is selected and the button correctly refuses. Say how many are picked, or the
|
||||
// refusal is indistinguishable from a dead button.
|
||||
fail(wxString::Format(_L("%s — %d selected. Press Esc for the Select tool, click one "
|
||||
"line, then Shift- or Ctrl-click the other."),
|
||||
fail(wxString::Format(_L_PLURAL("%s — %d selected. Press Esc for the Select tool, click one "
|
||||
"line, then Shift- or Ctrl-click the other.",
|
||||
"%s — %d selected. Press Esc for the Select tool, click one "
|
||||
"line, then Shift- or Ctrl-click the other.", unsigned(sel.size())),
|
||||
constraint_reject_text(plan.reason, type), int(sel.size())));
|
||||
return;
|
||||
case ConstraintPlan::Kind::AskValue:
|
||||
@@ -8364,7 +8375,7 @@ void DesignPanel::refresh_constrain_dof()
|
||||
m_dof_status->SetLabel(_L("✓ Fully constrained")); m_dof_status->Show(!m_dof_status->GetLabel().IsEmpty());
|
||||
} else if (r.dof > 0) {
|
||||
m_dof_status->SetForegroundColour(dp_ctl_text());
|
||||
m_dof_status->SetLabel(wxString::Format(_L("%d degrees of freedom"), r.dof)); m_dof_status->Show(!m_dof_status->GetLabel().IsEmpty());
|
||||
m_dof_status->SetLabel(wxString::Format(_L_PLURAL("%d degree of freedom", "%d degrees of freedom", r.dof), r.dof)); m_dof_status->Show(!m_dof_status->GetLabel().IsEmpty());
|
||||
} else {
|
||||
m_dof_status->SetLabel(wxString()); m_dof_status->Show(!m_dof_status->GetLabel().IsEmpty());
|
||||
}
|
||||
@@ -8398,7 +8409,8 @@ wxString DesignPanel::constraint_label(const SketchEntityConstraintDef& d) const
|
||||
// an empty string, or a NULL format string that crashes wxString::Format.
|
||||
wxString s; s << wxUniChar(c) << ei; // avoid %c assert in Unicode build
|
||||
if (r == SketchPointRole::P1) s += wxString::FromUTF8("·P1");
|
||||
else if (r == SketchPointRole::Center) s += wxString::FromUTF8("·Ctr");
|
||||
// TRN Design sketch: abbreviation of "center", appended to a point tag such as "L3·Ctr"
|
||||
else if (r == SketchPointRole::Center) s += _L("·Ctr");
|
||||
else if (r == SketchPointRole::P0) s += wxString::FromUTF8("·P0");
|
||||
return s;
|
||||
};
|
||||
@@ -8408,27 +8420,27 @@ wxString DesignPanel::constraint_label(const SketchEntityConstraintDef& d) const
|
||||
};
|
||||
switch (d.type) {
|
||||
case T::Fix: return wxString::Format(_L("Fix %s"), tag(d.ea, d.ra));
|
||||
case T::Coincident: return two(_L("Coincident"));
|
||||
case T::Horizontal: return two(_L("Horizontal"));
|
||||
case T::Vertical: return two(_L("Vertical"));
|
||||
case T::Coincident: return two(_L_CONTEXT("Coincident", "Sketch Constraint"));
|
||||
case T::Horizontal: return two(_L_CONTEXT("Horizontal", "Sketch Constraint"));
|
||||
case T::Vertical: return two(_L_CONTEXT("Vertical", "Sketch Constraint"));
|
||||
case T::Distance: return wxString::Format("%s = %s", two(_L("Distance")), en_format(d.value));
|
||||
case T::LockX: return wxString::Format(_L("Lock X %s"), tag(d.ea, d.ra));
|
||||
case T::LockY: return wxString::Format(_L("Lock Y %s"), tag(d.ea, d.ra));
|
||||
case T::EqualLength: return two(_L("Equal"));
|
||||
case T::Parallel: return two(_L("Parallel"));
|
||||
case T::Perpendicular: return two(_L("Perpendicular"));
|
||||
case T::Concentric: return two(_L("Concentric"));
|
||||
case T::Tangent: return two(_L("Tangent"));
|
||||
case T::Midpoint: return two(_L("Midpoint"));
|
||||
case T::EqualLength: return two(_L_CONTEXT("Equal", "Sketch Constraint"));
|
||||
case T::Parallel: return two(_L_CONTEXT("Parallel", "Sketch Constraint"));
|
||||
case T::Perpendicular: return two(_L_CONTEXT("Perpendicular", "Sketch Constraint"));
|
||||
case T::Concentric: return two(_L_CONTEXT("Concentric", "Sketch Constraint"));
|
||||
case T::Tangent: return two(_L_CONTEXT("Tangent", "Sketch Constraint"));
|
||||
case T::Midpoint: return two(_L_CONTEXT("Midpoint", "Sketch Constraint"));
|
||||
case T::Symmetric: return wxString::Format(_L("Symmetric %s — %s / %s"),
|
||||
tag(d.ea, d.ra), tag(d.eb, d.rb), tag(d.ec, d.rc));
|
||||
case T::SymmetricAboutY: return wxString::Format(_L("Symmetric about Y axis %s — %s"),
|
||||
tag(d.ea, d.ra), tag(d.eb, d.rb));
|
||||
case T::SymmetricAboutX: return wxString::Format(_L("Symmetric about X axis %s — %s"),
|
||||
tag(d.ea, d.ra), tag(d.eb, d.rb));
|
||||
case T::Angle: return wxString::Format(wxString::FromUTF8("%s = %s°"), two(_L("Angle")), en_format(d.value * 180.0 / M_PI, 1));
|
||||
case T::Radius: return wxString::Format("%s %s = %s", _L("Radius"), tag(d.ea, d.ra), en_format(d.value));
|
||||
case T::Diameter: return wxString::Format("%s %s = %s", _L("Diameter"), tag(d.ea, d.ra), en_format(d.value));
|
||||
case T::Angle: return wxString::Format(wxString::FromUTF8("%s = %s°"), two(_L_CONTEXT("Angle", "Sketch Constraint")), en_format(d.value * 180.0 / M_PI, 1));
|
||||
case T::Radius: return wxString::Format("%s %s = %s", _L_CONTEXT("Radius", "Sketch Constraint"), tag(d.ea, d.ra), en_format(d.value));
|
||||
case T::Diameter: return wxString::Format("%s %s = %s", _L_CONTEXT("Diameter", "Sketch Constraint"), tag(d.ea, d.ra), en_format(d.value));
|
||||
case T::PointOnLine: return two(_L("On line"));
|
||||
case T::PointOnObject: return two(_L("On edge"));
|
||||
}
|
||||
@@ -9702,7 +9714,7 @@ void DesignPanel::load_feature_into_dialog(const CadFeature& f)
|
||||
wxString s;
|
||||
for (size_t i = 0; i < m_del_faces.size(); ++i) {
|
||||
if (i > 0) s += ", ";
|
||||
s += wxString::Format("Face %d", m_del_faces[i]);
|
||||
s += wxString::Format(_L("Face %d"), m_del_faces[i]);
|
||||
}
|
||||
m_del_face_list->SetLabel(s.empty() ? _L("(none)") : s);
|
||||
}
|
||||
@@ -9768,7 +9780,7 @@ void DesignPanel::on_edit_feature()
|
||||
m_viewport->set_display_sketches({});
|
||||
m_viewport->edit_sketch(f.entities, f.entity_constraints, f.plane);
|
||||
}
|
||||
set_status(StatusKind::Info, _L("Editing sketch — drag a handle or click a quote to edit"));
|
||||
set_status(StatusKind::Info, _L("Editing sketch — drag a handle or double-click a dimension to edit it"));
|
||||
} else {
|
||||
load_feature_into_dialog(f);
|
||||
open_tool(Tool::Sketch);
|
||||
@@ -9963,7 +9975,7 @@ void DesignPanel::on_export_step()
|
||||
return;
|
||||
}
|
||||
wxFileDialog dlg(this, _L("Export STEP"), wxEmptyString, "model.step",
|
||||
"STEP files (*.step;*.stp)|*.step;*.stp",
|
||||
_L("STEP files (*.step;*.stp)|*.step;*.stp"),
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
@@ -11480,20 +11492,20 @@ void DesignPanel::open_tool(Tool t)
|
||||
};
|
||||
switch (t) {
|
||||
case Tool::Sketch: m_hdr_sketch->SetLabel(title(_L("Sketch"))); break;
|
||||
case Tool::Extrude: m_hdr_extrude->SetLabel(title(_L("Extrude"))); break;
|
||||
case Tool::Extrude: m_hdr_extrude->SetLabel(title(_L_CONTEXT("Extrude", "Design"))); break;
|
||||
case Tool::Dressup: m_hdr_dressup->SetLabel(title(
|
||||
m_dressup_type->GetSelection() == 0 ? _L("Fillet") : _L("Chamfer"))); break;
|
||||
case Tool::Hole: m_hdr_hole->SetLabel(title(_L("Hole"))); break;
|
||||
case Tool::Thread: m_hdr_thread->SetLabel(title(_L("Thread"))); break;
|
||||
case Tool::Shell: m_hdr_shell->SetLabel(title(_L("Shell"))); break;
|
||||
case Tool::Shell: m_hdr_shell->SetLabel(title(_L_CONTEXT("Shell", "Design"))); break;
|
||||
case Tool::Revolve: m_hdr_revolve->SetLabel(title(_L("Revolve"))); break;
|
||||
case Tool::Sweep: m_hdr_sweep->SetLabel(title(_L("Sweep"))); break;
|
||||
case Tool::Pattern: m_hdr_pattern->SetLabel(title(_L("Pattern"))); break;
|
||||
case Tool::Pattern: m_hdr_pattern->SetLabel(title(_L_CONTEXT("Pattern", "Design"))); break;
|
||||
case Tool::Plane: m_hdr_plane->SetLabel(title(_L("Plane"))); break;
|
||||
case Tool::Loft: m_hdr_loft->SetLabel(title(_L("Loft"))); break;
|
||||
case Tool::Draft: m_hdr_draft->SetLabel(title(_L("Draft"))); break;
|
||||
case Tool::Boolean: m_hdr_boolean->SetLabel(title(_L("Boolean"))); break;
|
||||
case Tool::Cut: m_hdr_cut->SetLabel(title(_L("Cut"))); break;
|
||||
case Tool::Cut: m_hdr_cut->SetLabel(title(_L_CONTEXT("Cut", "Design"))); break;
|
||||
case Tool::Axis: m_hdr_axis->SetLabel(title(_L("Axis"))); break;
|
||||
case Tool::CoordSys: m_hdr_coordsys->SetLabel(title(_L("Coordinate system"))); break;
|
||||
case Tool::SurfaceExtrude: m_hdr_surf_extrude->SetLabel(title(_L("Surface Extrude"))); break;
|
||||
@@ -11505,8 +11517,8 @@ void DesignPanel::open_tool(Tool t)
|
||||
case Tool::Transform: m_hdr_transform->SetLabel(title(_L("Transform"))); break;
|
||||
case Tool::Mirror: m_hdr_mirror->SetLabel(title(_L("Mirror"))); break;
|
||||
case Tool::Thicken: m_hdr_thicken->SetLabel(title(_L("Thicken"))); break;
|
||||
case Tool::Rib: m_hdr_rib->SetLabel(title(_L("Rib"))); break;
|
||||
case Tool::Project: m_hdr_project->SetLabel(title(_L("Project"))); break;
|
||||
case Tool::Rib: m_hdr_rib->SetLabel(title(_L_CONTEXT("Rib", "Design"))); break;
|
||||
case Tool::Project: m_hdr_project->SetLabel(title(_L_CONTEXT("Project", "Design"))); break;
|
||||
case Tool::DeleteFace: m_hdr_delete_face->SetLabel(title(_L("Delete Face"))); break;
|
||||
case Tool::Helix: m_hdr_helix->SetLabel(title(_L("Helix"))); break;
|
||||
case Tool::Mate: m_hdr_mate->SetLabel(title(_L("Mate"))); break;
|
||||
@@ -11743,7 +11755,7 @@ void DesignPanel::tool_cancel()
|
||||
show_move_card(false);
|
||||
feed_bodies(); // re-render the reverted placement
|
||||
update_action_bar();
|
||||
set_status(StatusKind::Info, _L("Move cancelled"));
|
||||
set_status(StatusKind::Info, _L("Move canceled"));
|
||||
return;
|
||||
}
|
||||
if (m_active == Tool::Insert) { cancel_insert(); return; }
|
||||
@@ -11873,7 +11885,7 @@ void DesignPanel::escape()
|
||||
return;
|
||||
}
|
||||
if (m_ui_mode == UiMode::Sketch) {
|
||||
set_status(StatusKind::Info, _L("Sketch kept — Finish to commit it, Cancel to discard"));
|
||||
set_status(StatusKind::Info, _L("Sketch kept — Confirm to commit it, Cancel to discard"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -11956,8 +11968,10 @@ void DesignPanel::do_undo_redo(bool redo)
|
||||
drop_selection();
|
||||
reset_edit_state();
|
||||
after_tree_edit(true); // refresh tree + viewport meshes + status from the restored doc
|
||||
set_status(StatusKind::Info, wxString::Format(redo ? _L("Redo (%zu more)") : _L("Undo (%zu more)"),
|
||||
redo ? m_doc.redo_depth() : m_doc.undo_depth()));
|
||||
const size_t depth = redo ? m_doc.redo_depth() : m_doc.undo_depth();
|
||||
set_status(StatusKind::Info, wxString::Format(redo ? _L_PLURAL("Redo (%zu more step)", "Redo (%zu more steps)", unsigned(depth))
|
||||
: _L_PLURAL("Undo (%zu more step)", "Undo (%zu more steps)", unsigned(depth)),
|
||||
depth));
|
||||
}
|
||||
|
||||
// --- Document variables panel ---------------------------------------------------------
|
||||
|
||||
@@ -1725,6 +1725,7 @@ void DesignSketchTool::open_polygon_side_editor(int fi)
|
||||
if (f.begin < 0 || f.begin >= int(m_entities.size())) return;
|
||||
const double side = (m_entities[f.begin].p1 - m_entities[f.begin].p0).norm();
|
||||
const wxPoint px(m_last_mouse_x, m_last_mouse_y);
|
||||
// TRN Design sketch: length of one side of a regular polygon (inline value editor title)
|
||||
on_inline_edit(px, side, _u8L("Side"),
|
||||
[this, fi](double v) { set_polygon_side(fi, v); },
|
||||
[]() {});
|
||||
@@ -9844,7 +9845,7 @@ std::string DesignSketchTool::build_readout() const
|
||||
std::string out = b;
|
||||
// Tell the user how to end a polyline chain — there's no other affordance for it.
|
||||
if (m_mode == Mode::Polyline && m_points.size() >= 2)
|
||||
out += " right-click or double-click to finish, click start to close";
|
||||
out += " " + _u8L("right-click or double-click to finish, click start to close");
|
||||
return out;
|
||||
}
|
||||
if (!m_active) return std::string();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "CalibUtils.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "format.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "DeviceCore/DevConfigUtil.h"
|
||||
@@ -67,13 +68,13 @@ static wxString get_default_name(wxString filament_name, CalibMode mode){
|
||||
case Slic3r::CalibMode::Calib_PA_Tower:
|
||||
break;
|
||||
case Slic3r::CalibMode::Calib_Flow_Rate:
|
||||
filament_name += " Flow Rate Calibrated";
|
||||
filament_name = format_wxstr(_L("%1% Flow Rate Calibrated"), filament_name);
|
||||
break;
|
||||
case Slic3r::CalibMode::Calib_Temp_Tower:
|
||||
filament_name += " Temperature Calibrated";
|
||||
filament_name = format_wxstr(_L("%1% Temperature Calibrated"), filament_name);
|
||||
break;
|
||||
case Slic3r::CalibMode::Calib_Vol_speed_Tower:
|
||||
filament_name += " Max Vol Speed Calibrated";
|
||||
filament_name = format_wxstr(_L("%1% Max Vol Speed Calibrated"), filament_name);
|
||||
break;
|
||||
case Slic3r::CalibMode::Calib_VFA_Tower:
|
||||
break;
|
||||
@@ -95,7 +96,7 @@ static wxString get_tray_name_by_tray_id(int tray_id)
|
||||
{
|
||||
wxString tray_name;
|
||||
if (tray_id == VIRTUAL_TRAY_MAIN_ID || tray_id == VIRTUAL_TRAY_DEPUTY_ID) {
|
||||
tray_name = "Ext";
|
||||
tray_name = _L("Ext");
|
||||
}
|
||||
else {
|
||||
int ams_id = tray_id / 4;
|
||||
|
||||
@@ -1130,7 +1130,7 @@ void PageMaterials::sort_list_data(StringList* list, bool add_All_item, bool mat
|
||||
for (const auto& item : prusa_profiles)
|
||||
list->append(item, &const_cast<std::string&>(item.get()));
|
||||
for (const auto& item : other_profiles)
|
||||
list->append(item, &const_cast<std::string&>(item.get()));
|
||||
list->append(item.get() == Materials::UNKNOWN ? _L(item.get()) : from_u8(item.get()), &const_cast<std::string&>(item.get()));
|
||||
}
|
||||
|
||||
void PageMaterials::sort_list_data(PresetList* list, const std::vector<ProfilePrintData>& data)
|
||||
@@ -1210,13 +1210,13 @@ void PageMaterials::on_activate()
|
||||
}
|
||||
|
||||
|
||||
const char *PageCustom::default_profile_name = "My Settings";
|
||||
const char *PageCustom::default_profile_name = L("My Settings");
|
||||
|
||||
PageCustom::PageCustom(ConfigWizard *parent)
|
||||
: ConfigWizardPage(parent, _L("Custom Printer Setup"), _L("Custom Printer"))
|
||||
{
|
||||
cb_custom = new wxCheckBox(this, wxID_ANY, _L("Define a custom printer profile"));
|
||||
tc_profile_name = new wxTextCtrl(this, wxID_ANY, default_profile_name);
|
||||
tc_profile_name = new wxTextCtrl(this, wxID_ANY, _L(default_profile_name));
|
||||
auto *label = new wxStaticText(this, wxID_ANY, _L("Custom profile name:"));
|
||||
|
||||
wxGetApp().UpdateDarkUI(tc_profile_name);
|
||||
@@ -1224,7 +1224,7 @@ PageCustom::PageCustom(ConfigWizard *parent)
|
||||
tc_profile_name->Enable(false);
|
||||
tc_profile_name->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &evt) {
|
||||
if (tc_profile_name->GetValue().IsEmpty()) {
|
||||
if (profile_name_prev.IsEmpty()) { tc_profile_name->SetValue(default_profile_name); }
|
||||
if (profile_name_prev.IsEmpty()) { tc_profile_name->SetValue(_L(default_profile_name)); }
|
||||
else { tc_profile_name->SetValue(profile_name_prev); }
|
||||
} else {
|
||||
profile_name_prev = tc_profile_name->GetValue();
|
||||
@@ -1463,7 +1463,7 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent)
|
||||
auto *default_bed = def_bed.get_default_value<ConfigOptionInts>();
|
||||
spin_bed->SetValue(default_bed != nullptr && default_bed->size() > 0 ? default_bed->get_at(0) : 0);
|
||||
|
||||
append_text(_L("Enter the nozzle_temperature needed for extruding your filament."));
|
||||
append_text(_L("Enter the nozzle temperature needed for extruding your filament."));
|
||||
append_text(_L("A rule of thumb is 160 to 230℃ for PLA, and 215 to 250℃ for ABS."));
|
||||
#endif
|
||||
|
||||
@@ -1720,7 +1720,7 @@ void ConfigWizardIndex::msw_rescale()
|
||||
|
||||
// Materials
|
||||
|
||||
const std::string Materials::UNKNOWN = "(Unknown)";
|
||||
const std::string Materials::UNKNOWN = L("(Unknown)");
|
||||
|
||||
void Materials::push(const Preset *preset)
|
||||
{
|
||||
@@ -2188,8 +2188,8 @@ void ConfigWizard::priv::select_default_materials_for_printer_models(Technology
|
||||
}
|
||||
printer_names += "\n\n";
|
||||
std::string message = (technology & T_FFF ?
|
||||
GUI::format(_L("Following printer profiles has no default filament: %1%Please select one manually."), printer_names) :
|
||||
GUI::format(_L("Following printer profiles has no default material: %1%Please select one manually."), printer_names));
|
||||
GUI::format(_L("The following printer profiles have no default filament: %1%Please select one manually."), printer_names) :
|
||||
GUI::format(_L("The following printer profiles have no default material: %1%Please select one manually."), printer_names));
|
||||
MessageDialog msg(q, message, _L("Notice"), wxOK);
|
||||
msg.ShowModal();
|
||||
}
|
||||
@@ -2449,7 +2449,7 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||
}
|
||||
if (!check_unsaved_preset_changes)
|
||||
if ((check_unsaved_preset_changes = install_bundles.size() > 0))
|
||||
header = _L_PLURAL("A new vendor was installed and one of its printers will be activated", "New vendors were installed and one of theirs printers will be activated", install_bundles.size());
|
||||
header = _L_PLURAL("A new vendor was installed and one of its printers will be activated", "New vendors were installed and one of their printers will be activated", install_bundles.size());
|
||||
|
||||
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
|
||||
bool snapshot = true;
|
||||
|
||||
@@ -39,7 +39,7 @@ CrealityDiscoveryDialog::CrealityDiscoveryDialog(wxWindow* parent)
|
||||
m_list->AppendColumn(_L("Hostname"), wxLIST_FORMAT_LEFT, 14 * em);
|
||||
m_list->AppendColumn(_L("IP"), wxLIST_FORMAT_LEFT, 14 * em);
|
||||
|
||||
auto* dlg_btns = new DialogButtons(this, {"Scan", "OK", "Cancel"}, "", 1 /*left_aligned*/);
|
||||
auto* dlg_btns = new DialogButtons(this, {L("Scan"), "OK", "Cancel"}, "", 1 /*left_aligned*/);
|
||||
auto* ok_btn = dlg_btns->GetOK();
|
||||
ok_btn->SetLabel(_L("Use Selected"));
|
||||
ok_btn->Disable();
|
||||
@@ -91,7 +91,7 @@ void CrealityDiscoveryDialog::run_discovery()
|
||||
if (!h.model_name.empty())
|
||||
row.model = h.model_name;
|
||||
else if (h.cfs_capable)
|
||||
row.model = "(unknown K-series)";
|
||||
row.model = _u8L("(unknown K-series)");
|
||||
else
|
||||
row.model = "Creality";
|
||||
m_rows.push_back(std::move(row));
|
||||
|
||||
@@ -652,7 +652,7 @@ DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent)
|
||||
|
||||
wxString text = _L("Desktop Integration sets this binary to be searchable by the system.\n\nPress \"Perform\" to proceed.");
|
||||
if (can_undo)
|
||||
text += "\nPress \"Undo\" to remove previous integration.";
|
||||
text += "\n" + _L("Press \"Undo\" to remove previous integration.");
|
||||
|
||||
vbox->Add(
|
||||
new wxStaticText( this, wxID_ANY, text),
|
||||
|
||||
@@ -154,7 +154,7 @@ void calib_fail_message(MachineObject* obj, std::string cali_mode, std::string r
|
||||
} else if (reason == "nozzle_diameter is not matched") {
|
||||
info = _L("Selected diameter and machine diameter do not match");
|
||||
} else if (reason == "generate auto filament cali gcode failure") {
|
||||
info = _L("Failed to generate cali gcode");
|
||||
info = _L("Failed to generate calibration G-code");
|
||||
} else {
|
||||
info = wxString(reason);
|
||||
}
|
||||
|
||||
@@ -4313,7 +4313,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
info = _L("Selected diameter and machine diameter do not match");
|
||||
}
|
||||
else if (reason == "generate auto filament cali gcode failure") {
|
||||
info = _L("Failed to generate cali G-code");
|
||||
info = _L("Failed to generate calibration G-code");
|
||||
}
|
||||
else {
|
||||
info = reason;
|
||||
|
||||
@@ -981,7 +981,7 @@ int ReselectMachineDialog::CaculateSwitcherDistribution(MachineObject* obj, cons
|
||||
}
|
||||
if (can.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY)
|
||||
{
|
||||
material = "Empty";
|
||||
material = L("Empty");
|
||||
}
|
||||
|
||||
auto itOK = std::find_if(posOK.begin(), posOK.end(), [&](const trayHelper& tray){
|
||||
|
||||
@@ -60,7 +60,7 @@ void wgtMsgPanelItem::CreateGui()
|
||||
text_sizer->Add(m_text_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
if (!m_wiki_url.IsEmpty()) {
|
||||
m_wiki_link = new wxHyperlinkCtrl(this, wxID_ANY, "Wiki->", m_wiki_url);
|
||||
m_wiki_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki->"), m_wiki_url);
|
||||
m_wiki_link->SetNormalColour(m_colour);
|
||||
m_wiki_link->SetHoverColour(wxColour(0, 0, 200));
|
||||
m_wiki_link->SetVisitedColour(*wxBLUE);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include <functional>
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
@@ -165,7 +166,7 @@ void Downloader::start_download(const std::string& full_url)
|
||||
// Orca: show error
|
||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||
ntf_mngr->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel,
|
||||
"Could not start download due to malformed URL");
|
||||
_u8L("Could not start download due to malformed URL"));
|
||||
return;
|
||||
}
|
||||
size_t id = get_next_id();
|
||||
|
||||
@@ -161,7 +161,7 @@ void FileGet::priv::get_perform()
|
||||
}
|
||||
if (!found) {
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
|
||||
evt->SetString(GUI::format_wxstr(L"Failed to find suitable filename. Last name: %1%." , (m_dest_folder / final_filename).string()));
|
||||
evt->SetString(GUI::format_wxstr(_L("Failed to find suitable filename. Last name: %1%."), (m_dest_folder / final_filename).string()));
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
return;
|
||||
@@ -367,7 +367,7 @@ void FileGet::priv::get_perform()
|
||||
//TODO: report?
|
||||
//error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path);
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
|
||||
evt->SetString("Failed to write and move.");
|
||||
evt->SetString(_L("Failed to write and move."));
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
return;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
@@ -165,7 +166,7 @@ wxString FilamentColorCode::GetFilaColorName() const
|
||||
if (it != m_fila_color_names.end() && !it->second.empty()) { return it->second; }
|
||||
|
||||
it = m_fila_color_names.find("en");// retry with English as fallback
|
||||
return (it != m_fila_color_names.end()) ? it->second : "Unknown";
|
||||
return (it != m_fila_color_names.end()) ? it->second : _L("Unknown");
|
||||
}
|
||||
|
||||
FilamentColorCode::FilamentColorCode(const wxString& color_code, FilamentColorCodes* owner, FilamentColor&& color, std::unordered_map<wxString, wxString>&& name_map)
|
||||
|
||||
@@ -75,7 +75,7 @@ void ExportPresetBundleDialog::on_script_message(const nlohmann::json& j)
|
||||
OnRequestPresets();
|
||||
} else if (strCmd == "export_local") {
|
||||
wxFileDialog dlg(this, _L("Save preset bundle"), "", "export.orca_bundle",
|
||||
"Orca Preset Bundle (*.orca_bundle)|*.orca_bundle", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
_L("Orca Preset Bundle (*.orca_bundle)|*.orca_bundle"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
wxString path;
|
||||
wxString name;
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
|
||||
@@ -2179,7 +2179,8 @@ void PrinterAgentChoice::set_value(const std::string& value, bool change_event)
|
||||
if (match == wxNOT_FOUND)
|
||||
{
|
||||
field->SetSelection(wxNOT_FOUND); // nothing shows as selected in the dropdown
|
||||
field->SetValue(from_u8(value + " (missing)")); // set a value not in the selection (upper display field)
|
||||
// TRN %1% is the ID of a printer agent that is no longer available
|
||||
field->SetValue(format_wxstr(_L("%1% (missing)"), value)); // set a value not in the selection (upper display field)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -454,7 +454,8 @@ void FilamentMapManualPanel::UpdateNozzleCountDisplay()
|
||||
if (m_right_panel->IsUseSeparation()) {
|
||||
int standard_count = getExtruderNozzleCount(preset_bundle, 1, NozzleVolumeType::nvtStandard);
|
||||
int highflow_count = getExtruderNozzleCount(preset_bundle, 1, NozzleVolumeType::nvtHighFlow);
|
||||
wxString right_title = _L("Right Nozzle") + wxString::Format("(Std: %d, HF: %d)", standard_count, highflow_count);
|
||||
// TRN Nozzle counts: Std = standard flow, HF = high flow
|
||||
wxString right_title = _L("Right Nozzle") + wxString::Format(_L("(Std: %d, HF: %d)"), standard_count, highflow_count);
|
||||
m_right_panel->UpdateLabel(right_title);
|
||||
} else {
|
||||
int right_count = getExtruderNozzleCountTotal(preset_bundle, 1);
|
||||
|
||||
@@ -209,7 +209,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
|
||||
m_avc = new ArchiveViewCtrl(this, wxSize(45 * em, 30 * em));
|
||||
wxDataViewColumn* toggle_column = m_avc->AppendToggleColumn(L"\u2714", 0, wxDATAVIEW_CELL_ACTIVATABLE, 6 * em);
|
||||
m_avc->AppendTextColumn("filename", 1);
|
||||
m_avc->AppendTextColumn(_L("filename"), 1);
|
||||
|
||||
std::vector<std::shared_ptr<ArchiveViewNode>> stack;
|
||||
|
||||
|
||||
@@ -10190,6 +10190,7 @@ void GLCanvas3D::_render_canvas_toolbar()
|
||||
[this, p]{p->toggle_show_wireframe(); m_dirty = true;}
|
||||
);
|
||||
|
||||
// TRN View toggle that draws models see-through, so hidden parts show.
|
||||
create_menu_item( _utf8(L("X-Ray")),
|
||||
m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
|
||||
p->is_show_xray(),
|
||||
|
||||
@@ -8242,7 +8242,7 @@ bool GUI_App::load_language(wxString language, bool initial)
|
||||
message += _L("\nYou may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n");
|
||||
#endif
|
||||
if (initial)
|
||||
message + "\n\nApplication will close.";
|
||||
message += "\n\n" + _L("Application will close.");
|
||||
wxMessageBox(message, _L("Orca Slicer - Switching language failed"), wxOK | wxICON_ERROR);
|
||||
if (initial)
|
||||
std::exit(EXIT_FAILURE);
|
||||
|
||||
@@ -102,6 +102,7 @@ void GLGizmoPrimitive::on_render_input_window(float x, float y, float bottom_lim
|
||||
m_params.type = (PrimitiveType)cur;
|
||||
m_preview_dirty = true;
|
||||
}
|
||||
// TRN Primitive gizmo: label in front of the preset cube size buttons
|
||||
ImGui::TextUnformatted(_u8L("Quick:").c_str());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("10mm")) apply_preset("10mm cube", 10, 10, 10);
|
||||
@@ -133,11 +134,13 @@ void GLGizmoPrimitive::on_render_input_window(float x, float y, float bottom_lim
|
||||
dim(_u8L("Radius").c_str(), m_params.sph_radius);
|
||||
break;
|
||||
case PrimitiveType::Cone:
|
||||
// TRN Primitive gizmo: bottom radius of a cone ("Top R" is the top radius)
|
||||
dim(_u8L("Bottom R").c_str(), m_params.cone_r1);
|
||||
dim(_u8L("Top R").c_str(), m_params.cone_r2);
|
||||
dim(_u8L("Height").c_str(), m_params.cone_height);
|
||||
break;
|
||||
case PrimitiveType::Torus:
|
||||
// TRN Primitive gizmo: major radius of a torus ("Minor R" is the tube radius)
|
||||
dim(_u8L("Major R").c_str(), m_params.torus_r1);
|
||||
dim(_u8L("Minor R").c_str(), m_params.torus_r2, 0.1, 1.0);
|
||||
break;
|
||||
|
||||
@@ -1351,25 +1351,25 @@ void GLGizmoSVG::draw_window()
|
||||
assert(m_volume_id.valid());
|
||||
if (m_volume == nullptr ||
|
||||
m_volume_id.invalid()) {
|
||||
ImGui::Text("Not valid state please report reproduction steps on github");
|
||||
ImGui::Text("%s", _u8L("Not valid state please report reproduction steps on github").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_volume->emboss_shape.has_value());
|
||||
if (!m_volume->emboss_shape.has_value()) {
|
||||
ImGui::Text("No embossed file");
|
||||
ImGui::Text("%s", _u8L("No embossed file").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_volume->emboss_shape->svg_file.has_value());
|
||||
if (!m_volume->emboss_shape->svg_file.has_value()){
|
||||
ImGui::Text("Missing svg file in embossed shape");
|
||||
ImGui::Text("%s", _u8L("Missing svg file in embossed shape").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_volume->emboss_shape->svg_file->file_data != nullptr);
|
||||
if (m_volume->emboss_shape->svg_file->file_data == nullptr){
|
||||
ImGui::Text("Missing data of svg file");
|
||||
ImGui::Text("%s", _u8L("Missing data of svg file").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2143,7 +2143,7 @@ std::string volume_name(const EmbossShape &shape)
|
||||
std::string file_name = get_file_name(shape.svg_file->path);
|
||||
if (!file_name.empty())
|
||||
return file_name;
|
||||
return "SVG shape";
|
||||
return _u8L("SVG shape");
|
||||
}
|
||||
|
||||
CreateVolumeParams create_input(GLCanvas3D &canvas, RaycastManager& raycaster, ModelVolumeType volume_type)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/NotificationManager.hpp"
|
||||
#include "slic3r/GUI/format.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
@@ -231,11 +232,11 @@ void GLGizmoSketch::draw_canvas()
|
||||
TopoDS_Shape GLGizmoSketch::build_combined_shape()
|
||||
{
|
||||
if (m_profiles.empty() || !m_profiles[0].closed)
|
||||
throw std::runtime_error("No outer profile");
|
||||
throw std::runtime_error(_u8L("No outer profile"));
|
||||
|
||||
TopoDS_Wire outer_wire = m_profiles[0].to_occt_wire(m_plane);
|
||||
BRepBuilderAPI_MakeFace face_maker(outer_wire);
|
||||
if (!face_maker.IsDone()) throw std::runtime_error("Failed to make outer face");
|
||||
if (!face_maker.IsDone()) throw std::runtime_error(_u8L("Failed to make outer face"));
|
||||
|
||||
for (size_t i = 1; i < m_profiles.size(); ++i) {
|
||||
if (!m_profiles[i].closed) continue;
|
||||
@@ -243,7 +244,7 @@ TopoDS_Shape GLGizmoSketch::build_combined_shape()
|
||||
face_maker.Add(inner);
|
||||
}
|
||||
face_maker.Build();
|
||||
if (!face_maker.IsDone()) throw std::runtime_error("Failed to build face with holes");
|
||||
if (!face_maker.IsDone()) throw std::runtime_error(_u8L("Failed to build face with holes"));
|
||||
|
||||
TopoDS_Face face = face_maker.Face();
|
||||
|
||||
@@ -253,7 +254,7 @@ TopoDS_Shape GLGizmoSketch::build_combined_shape()
|
||||
gp_Dir xd(m_plane.x_axis.x(), m_plane.x_axis.y(), m_plane.x_axis.z());
|
||||
gp_Ax1 axis(o, xd);
|
||||
BRepPrimAPI_MakeRevol rev(face, axis, m_sp.revolve_deg * M_PI / 180.0);
|
||||
if (!rev.IsDone()) throw std::runtime_error("Revolve failed");
|
||||
if (!rev.IsDone()) throw std::runtime_error(_u8L("Revolve failed"));
|
||||
shape = rev.Shape();
|
||||
} else {
|
||||
shape = SketchEngine::make_extrude_face(face, m_plane, m_sp.extrude_len, m_sp.extrude_sym);
|
||||
@@ -320,8 +321,9 @@ void GLGizmoSketch::on_render_input_window(float x, float y, float bottom_limit)
|
||||
bool outer = (i == 0);
|
||||
ImVec4 col = outer ? ImVec4(0,1,0,1) : ImVec4(1,0.3f,0.3f,1);
|
||||
const std::string label = outer ? _u8L("Outer") : _u8L("Hole");
|
||||
ImGui::TextColored(col, "%s %d: %zu %s %s", label.c_str(), i+1, p.points.size(),
|
||||
_u8L("points").c_str(), p.closed ? _u8L("closed").c_str() : "");
|
||||
const std::string state = p.closed ? _u8L("closed") : std::string();
|
||||
// TRN Sketch gizmo profile list: "Outer" or "Hole", profile number, point count, "closed" or nothing
|
||||
ImGui::TextColored(col, "%s", GUI::format(_u8L("%1% %2%: %3% points %4%"), label, i + 1, p.points.size(), state).c_str());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("X")) delete_profile(i);
|
||||
ImGui::PopID();
|
||||
@@ -336,9 +338,9 @@ void GLGizmoSketch::on_render_input_window(float x, float y, float bottom_limit)
|
||||
|
||||
if (ImGui::CollapsingHeader(_u8L("Operation").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
static int pi = 0;
|
||||
const std::string planes = "XY (" + _u8L("Top") + ")" + std::string(1, '\0') + "XZ (" + _u8L("Front") + ")"
|
||||
+ std::string(1, '\0') + "YZ (" + _u8L("Side") + ")" + std::string(2, '\0');
|
||||
if (ImGui::Combo(_u8L("Plane").c_str(), &pi, planes.c_str()))
|
||||
const std::string plane_names[] = {_u8L("XY (Top)"), _u8L("XZ (Front)"), _u8L("YZ (Side)")};
|
||||
const char* planes[] = {plane_names[0].c_str(), plane_names[1].c_str(), plane_names[2].c_str()};
|
||||
if (ImGui::Combo(_u8L("Plane").c_str(), &pi, planes, 3))
|
||||
m_plane = (pi==0) ? SketchPlane::XY() : (pi==1) ? SketchPlane::XZ() : SketchPlane::YZ();
|
||||
|
||||
is_revolve = (m_sp.revolve_deg > 0 && m_sp.revolve_deg < 360);
|
||||
@@ -389,7 +391,8 @@ void GLGizmoSketch::on_render_input_window(float x, float y, float bottom_limit)
|
||||
ImGui::Separator();
|
||||
|
||||
bool ok = has_closed_profile();
|
||||
if (ok) ImGui::TextColored({0,1,0,1}, "%zu %s", m_profiles.size(), _u8L("closed profile(s)").c_str());
|
||||
if (ok) ImGui::TextColored({0,1,0,1}, "%s", wxString::Format(_L_PLURAL("%zu closed profile", "%zu closed profiles",
|
||||
unsigned(m_profiles.size())), m_profiles.size()).ToUTF8().data());
|
||||
else ImGui::TextColored({0.6f,0.6f,0.6f,1}, "%s", _u8L("Draw a closed profile to enable").c_str());
|
||||
|
||||
auto btn = [&](const char* label, bool enabled) {
|
||||
@@ -404,7 +407,7 @@ void GLGizmoSketch::on_render_input_window(float x, float y, float bottom_limit)
|
||||
} else if (is_revolve) {
|
||||
if (btn(_u8L("Revolve").c_str(), ok)) apply_revolve();
|
||||
} else {
|
||||
if (btn(_u8L("Extrude").c_str(), ok)) apply_extrude();
|
||||
if (btn(_u8L_CONTEXT("Extrude", "Design").c_str(), ok)) apply_extrude();
|
||||
}
|
||||
|
||||
if (ImGui::Button(_u8L("Clear all").c_str(), {-1,0})) clear_all();
|
||||
@@ -419,7 +422,7 @@ void GLGizmoSketch::apply_extrude()
|
||||
try {
|
||||
TopoDS_Shape shape = build_combined_shape();
|
||||
TriangleMesh mesh = SketchEngine::tessellate(shape, m_sp.linear_deflection);
|
||||
if (mesh.its.indices.empty()) throw std::runtime_error("Empty result");
|
||||
if (mesh.its.indices.empty()) throw std::runtime_error(_u8L("Empty result"));
|
||||
wxGetApp().plater()->take_snapshot("Sketch Extrude");
|
||||
ModelObject* mo = wxGetApp().model().add_object();
|
||||
mo->name = "Extrusion";
|
||||
@@ -428,7 +431,7 @@ void GLGizmoSketch::apply_extrude()
|
||||
wxGetApp().plater()->update();
|
||||
clear_all();
|
||||
} catch (const std::exception& e) {
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, std::string("Extrude: ")+e.what());
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, GUI::format(_u8L("Extrude: %1%"), e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +440,7 @@ void GLGizmoSketch::apply_revolve()
|
||||
try {
|
||||
TopoDS_Shape shape = build_combined_shape();
|
||||
TriangleMesh mesh = SketchEngine::tessellate(shape, m_sp.linear_deflection);
|
||||
if (mesh.its.indices.empty()) throw std::runtime_error("Empty result");
|
||||
if (mesh.its.indices.empty()) throw std::runtime_error(_u8L("Empty result"));
|
||||
wxGetApp().plater()->take_snapshot("Sketch Revolve");
|
||||
ModelObject* mo = wxGetApp().model().add_object();
|
||||
mo->name = "Revolve";
|
||||
@@ -446,7 +449,7 @@ void GLGizmoSketch::apply_revolve()
|
||||
wxGetApp().plater()->update();
|
||||
clear_all();
|
||||
} catch (const std::exception& e) {
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, std::string("Revolve: ")+e.what());
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, GUI::format(_u8L("Revolve: %1%"), e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,20 +458,20 @@ void GLGizmoSketch::apply_pocket()
|
||||
try {
|
||||
Selection& sel = m_parent.get_selection();
|
||||
int obj_idx = sel.get_object_idx();
|
||||
if (obj_idx < 0) throw std::runtime_error("No object selected");
|
||||
if (obj_idx < 0) throw std::runtime_error(_u8L("No object selected"));
|
||||
ModelObject* mo = wxGetApp().model().objects[obj_idx];
|
||||
|
||||
TopoDS_Wire outer = m_profiles[0].to_occt_wire(m_plane);
|
||||
BRepBuilderAPI_MakeFace fm(outer);
|
||||
if (!fm.IsDone()) throw std::runtime_error("Face failed");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("Face failed"));
|
||||
for (size_t i = 1; i < m_profiles.size(); ++i)
|
||||
if (m_profiles[i].closed) fm.Add(m_profiles[i].to_occt_wire(m_plane));
|
||||
fm.Build();
|
||||
if (!fm.IsDone()) throw std::runtime_error("Face with holes failed");
|
||||
if (!fm.IsDone()) throw std::runtime_error(_u8L("Face with holes failed"));
|
||||
|
||||
TopoDS_Shape tool = SketchEngine::make_extrude_face(fm.Face(), m_plane, m_sp.extrude_len + 5.0, false);
|
||||
TriangleMesh tool_mesh = SketchEngine::tessellate(tool, m_sp.linear_deflection);
|
||||
if (tool_mesh.its.indices.empty()) throw std::runtime_error("Tool mesh empty");
|
||||
if (tool_mesh.its.indices.empty()) throw std::runtime_error(_u8L("Tool mesh empty"));
|
||||
|
||||
wxGetApp().plater()->take_snapshot("Sketch Pocket");
|
||||
mo->add_volume(std::move(tool_mesh), ModelVolumeType::NEGATIVE_VOLUME)->set_new_unique_id();
|
||||
@@ -477,7 +480,7 @@ void GLGizmoSketch::apply_pocket()
|
||||
clear_all();
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Pocket added (negative volume)").c_str());
|
||||
} catch (const std::exception& e) {
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, std::string("Pocket: ")+e.what());
|
||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, GUI::format(_u8L("Pocket: %1%"), e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@ bool GLGizmoTextureDisplacement::on_init()
|
||||
m_desc["circle"] = _L("Circle");
|
||||
m_desc["sphere"] = _L("Sphere");
|
||||
m_desc["remove_layer"] = _L("Remove");
|
||||
m_desc["bake"] = _L("Bake");
|
||||
m_desc["bake"] = _L_CONTEXT("Bake", "Texture Displacement");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3509,7 +3509,7 @@ void GLGizmoTextureDisplacement::set_layer_texture(TextureDisplacementLayer &lay
|
||||
|
||||
void GLGizmoTextureDisplacement::import_custom_texture(TextureDisplacementLayer &layer)
|
||||
{
|
||||
const wxString wildcard = "Images (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp";
|
||||
const wxString wildcard = _L("Images (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp");
|
||||
wxFileDialog dialog(nullptr, _L("Choose a texture image (height map)"), wxEmptyString, wxEmptyString, wildcard,
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (dialog.ShowModal() != wxID_OK)
|
||||
@@ -6001,8 +6001,8 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
// Midlevel: the height that means "don't move". At 0 the surface only ever bulges outwards;
|
||||
// at 0.5 mid-grey is neutral and darker texels cut inwards.
|
||||
m_preview_params_dirty |= float_row("##midlevel", _L("Midlevel"), &layer.midlevel, 0.f, 10.f, "%.2f", false, card_pad);
|
||||
hover_tip(_u8L("Which grey stays where the surface already is. At 0 the texture only pushes "
|
||||
"outwards; at 0.5 mid-grey stays put, so darker greys cut in and lighter ones "
|
||||
hover_tip(_u8L("Which gray stays where the surface already is. At 0 the texture only pushes "
|
||||
"outwards; at 0.5 mid-gray stays put, so darker grays cut in and lighter ones "
|
||||
"still push out - one image both embosses and engraves.\n\n"
|
||||
"What cuts in has to fit: inside a sharp corner or through a thin wall, a deep "
|
||||
"cut can pass through the other side."));
|
||||
@@ -6045,18 +6045,18 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
const bool has_color = decode_height_texture(layer).has_color();
|
||||
bool color_enabled = layer.color_enabled && has_color;
|
||||
m_imgui->disabled_begin(!has_color);
|
||||
if (m_imgui->bbl_checkbox(_L("Colours"), color_enabled)) {
|
||||
if (m_imgui->bbl_checkbox(_L("Colors"), color_enabled)) {
|
||||
layer.color_enabled = color_enabled;
|
||||
m_preview_params_dirty = true;
|
||||
}
|
||||
m_imgui->disabled_end();
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
||||
m_imgui->tooltip(has_color ?
|
||||
_u8L("Prints the painted area in the texture's colours as well as its "
|
||||
"relief. Each colour is matched to the nearest of your loaded "
|
||||
_u8L("Prints the painted area in the texture's colors as well as its "
|
||||
"relief. Each color is matched to the nearest of your loaded "
|
||||
"filaments; anything you did not paint keeps the object's own.") :
|
||||
_u8L("This texture is a grayscale height map, so it has no colours to "
|
||||
"apply. Import a colour image to use this."),
|
||||
_u8L("This texture is a grayscale height map, so it has no colors to "
|
||||
"apply. Import a color image to use this."),
|
||||
wrap_w);
|
||||
|
||||
// The rest of colour belongs to the whole stack, not to this layer, so it only appears once -
|
||||
@@ -6065,13 +6065,13 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
TextureDisplacementOptions &opts = mv->texture_displacement_options;
|
||||
if (m_imgui->bbl_checkbox(_L("Mix filaments"), opts.color_mix_enabled))
|
||||
m_preview_params_dirty = true;
|
||||
hover_tip(_u8L("Interleaves two filaments to fake the colours in between, so a handful "
|
||||
"of filaments can cover a photo or a gradient. An image of flat colours "
|
||||
hover_tip(_u8L("Interleaves two filaments to fake the colors in between, so a handful "
|
||||
"of filaments can cover a photo or a gradient. An image of flat colors "
|
||||
"prints the same either way. Off uses one filament per area."));
|
||||
if (opts.color_mix_enabled) {
|
||||
slider_label(_L("Mix by"));
|
||||
const std::string mix_z = _u8L("Layers");
|
||||
const std::string mix_xy = _u8L("Surface");
|
||||
const std::string mix_xy = _u8L_CONTEXT("Surface", "Texture Displacement");
|
||||
const std::string mix_auto = _u8L("Automatic");
|
||||
const char *mix_items[] = { mix_z.c_str(), mix_xy.c_str(), mix_auto.c_str() };
|
||||
int mix_mode = int(opts.color_mix_mode);
|
||||
@@ -6087,12 +6087,12 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
"any angle but can read as texture rather than as a blend.\n"
|
||||
"Automatic: layers on upright faces; flat-facing faces take the nearer "
|
||||
"single filament, since a checkerboard there shows as a pattern."));
|
||||
ImGui::TextDisabled("%s", Slic3r::format(_u8L("%1% printable colours from %2% filaments"),
|
||||
ImGui::TextDisabled("%s", Slic3r::format(_u8L("%1% printable colors from %2% filaments"),
|
||||
int(cached_palette().size()), int(m_palette_filaments.size())).c_str());
|
||||
}
|
||||
if (int_row("##color_despeckle", _L("Denoise"), &opts.color_despeckle, 0, 6, "%d", card_pad))
|
||||
m_preview_params_dirty = true;
|
||||
hover_tip(_u8L("Cleans up single stray triangles of the wrong colour, which detail finer "
|
||||
hover_tip(_u8L("Cleans up single stray triangles of the wrong color, which detail finer "
|
||||
"than the mesh leaves behind. Raise it if the result looks speckled, "
|
||||
"lower it if small features are being swallowed."));
|
||||
}
|
||||
@@ -6102,7 +6102,7 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
{
|
||||
const float x0 = ImGui::GetCursorPosX();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextDisabled("%s", _u8L("Mapping").c_str());
|
||||
ImGui::TextDisabled("%s", _u8L_CONTEXT("Mapping", "Texture Displacement").c_str());
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), x0 + label_w));
|
||||
struct MappingIcon
|
||||
@@ -6116,9 +6116,9 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
_L("Triplanar - projects the texture from all three axes at once and blends between them, so a "
|
||||
"patch wrapping around a sharp edge has no seam.") },
|
||||
{ "menu_obj_cylinder.svg", _L("Cylindrical"),
|
||||
_L("Cylindrical - wraps the texture around the painted area's own centre, for round shapes.") },
|
||||
_L("Cylindrical - wraps the texture around the painted area's own center, for round shapes.") },
|
||||
{ "menu_obj_sphere.svg", _L("Spherical"),
|
||||
_L("Spherical - wraps the texture around the painted area's own centre in both directions.") },
|
||||
_L("Spherical - wraps the texture around the painted area's own center in both directions.") },
|
||||
{ "texture_displacement_map_unwrap.svg", _L("Unwrap (LSCM)"),
|
||||
_L("Unwrap - flattens the painted area and maps the texture onto it with as little stretching as "
|
||||
"possible. The area is cut into pieces at its sharp edges first (see Seam angle), so each "
|
||||
@@ -6261,9 +6261,9 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
ImGui::TextDisabled("%s", _u8L("Blend").c_str());
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), x0 + label_w));
|
||||
const std::string blend_add = _u8L("Add");
|
||||
const std::string blend_subtract = _u8L("Subtract");
|
||||
const std::string blend_multiply = _u8L("Multiply");
|
||||
const std::string blend_add = _u8L_CONTEXT("Add", "Texture Displacement");
|
||||
const std::string blend_subtract = _u8L_CONTEXT("Subtract", "Texture Displacement");
|
||||
const std::string blend_multiply = _u8L_CONTEXT("Multiply", "Texture Displacement");
|
||||
const std::string blend_divide = _u8L("Divide");
|
||||
const char *blend_items[] = { blend_add.c_str(), blend_subtract.c_str(), blend_multiply.c_str(), blend_divide.c_str() };
|
||||
// The first layer has nothing before it to combine with - build_texture_displacement() makes it
|
||||
@@ -6535,11 +6535,11 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
// Only worth showing when a layer is actually colouring: with no colour there is no boundary for it
|
||||
// to refine and the control would do nothing whatever it is set to.
|
||||
if (mv != nullptr && any_layer_colors(*mv)) {
|
||||
if (float_row("##subdiv_color", _L("Colour detail"), &m_subdivide_color_mm, 0.f, 5.f, "%.3f mm", false, 0.f))
|
||||
if (float_row("##subdiv_color", _L("Color detail"), &m_subdivide_color_mm, 0.f, 5.f, "%.3f mm", false, 0.f))
|
||||
preview_live();
|
||||
hover_tip(_u8L("Triangle size where two colours meet. Each triangle prints in one filament, so a "
|
||||
"colour edge can only be as sharp as the triangles along it - and nothing else "
|
||||
"refines there, since the surface is flat across a change of colour. 0 turns it off."));
|
||||
hover_tip(_u8L("Triangle size where two colors meet. Each triangle prints in one filament, so a "
|
||||
"color edge can only be as sharp as the triangles along it - and nothing else "
|
||||
"refines there, since the surface is flat across a change of color. 0 turns it off."));
|
||||
}
|
||||
|
||||
ImGui::TextDisabled("%s", _u8L("Triangle budget: set with Triangles, below.").c_str());
|
||||
@@ -6657,7 +6657,7 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
"on a layer is a different thing: it blurs the image before it is used."));
|
||||
if (opts.smooth_enabled) {
|
||||
float percent = opts.smooth_strength * 100.f;
|
||||
if (float_row("##dispsmooth", _L("Strength"), &percent, 1.f, 100.f, "%.0f %%", false, 0.f)) {
|
||||
if (float_row("##dispsmooth", _L_CONTEXT("Strength", "Texture Displacement"), &percent, 1.f, 100.f, "%.0f %%", false, 0.f)) {
|
||||
opts.smooth_strength = std::clamp(percent / 100.f, 0.01f, 1.f);
|
||||
m_preview_params_dirty = true;
|
||||
}
|
||||
@@ -6699,16 +6699,17 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
}
|
||||
hover_tip(_u8L("Bake by moving the vertices the mesh already has, after preparing it (remesh, "
|
||||
"adaptive subdivision, and a cut along sharp steps in the texture). Keeps the "
|
||||
"topology, which is what colours need. The default pipeline instead refines, "
|
||||
"topology, which is what colors need. The default pipeline instead refines, "
|
||||
"cleans up sliver triangles, displaces and simplifies in one run; nothing needs "
|
||||
"preparing first, but it does not produce colours yet."));
|
||||
"preparing first, but it does not produce colors yet."));
|
||||
}
|
||||
if (opts.pipeline_v2) {
|
||||
// -1 is "auto": the row shows the recommendation, greyed; editing it makes it a fixed value.
|
||||
const bool auto_budget = opts.v2_max_triangles_k < 0;
|
||||
int shown_k = auto_budget ? v2_recommendation(*mv).budget_k : opts.v2_max_triangles_k;
|
||||
m_imgui->disabled_begin(auto_budget);
|
||||
if (int_row("##v2budget", _L("Budget"), &shown_k, 0, 4000, auto_budget ? "%d k (auto)" : "%d k", 0.f)) {
|
||||
// TRN Slider value: %d is the triangle budget in thousands
|
||||
if (int_row("##v2budget", _L("Budget"), &shown_k, 0, 4000, auto_budget ? _u8L("%d k (auto)").c_str() : "%d k", 0.f)) {
|
||||
opts.v2_max_triangles_k = shown_k;
|
||||
m_preview_params_dirty = true;
|
||||
}
|
||||
@@ -6827,7 +6828,7 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float
|
||||
ImGui::SetNextItemWidth(x0 + panel_w - ImGui::GetCursorPosX());
|
||||
float shown = auto_res ? rec.edge_mm : opts.v2_refine_mm;
|
||||
m_imgui->disabled_begin(busy || auto_res);
|
||||
if (ImGui::SliderFloat("##v2edge", &shown, 0.02f, 2.f, auto_res ? "%.2f mm (auto)" : "%.2f mm",
|
||||
if (ImGui::SliderFloat("##v2edge", &shown, 0.02f, 2.f, auto_res ? _u8L("%.2f mm (auto)").c_str() : "%.2f mm",
|
||||
ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic)) {
|
||||
opts.v2_refine_mm = shown;
|
||||
m_preview_params_dirty = true;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include "CloudProvider.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "slic3r/Utils/Http.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
||||
@@ -248,10 +249,10 @@ std::shared_ptr<HttpServer::Response> HttpServer::auth_handle_request(const std:
|
||||
GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); });
|
||||
}
|
||||
|
||||
const std::string title = login_ok ? "Authentication complete" : "Authentication failed";
|
||||
const std::string title = login_ok ? _u8L("Authentication complete") : _u8L("Authentication failed");
|
||||
const std::string message = login_ok
|
||||
? "You can return to OrcaSlicer. This window will close automatically."
|
||||
: "Something went wrong. Please return to OrcaSlicer and try again.";
|
||||
? _u8L("You can return to OrcaSlicer. This window will close automatically.")
|
||||
: _u8L("Something went wrong. Please return to OrcaSlicer and try again.");
|
||||
const std::string html =
|
||||
"<html><head><meta charset=\"utf-8\">"
|
||||
"<style>body{font-family:Arial,sans-serif;background:#f7f7f7;color:#222;margin:32px;}"
|
||||
@@ -434,9 +435,9 @@ void HttpServer::ResponseRedirect::write_response(std::stringstream& ssOut)
|
||||
"<style>body{font-family:Arial,sans-serif;background:#f7f7f7;color:#222;margin:32px;}"
|
||||
"a.button{display:inline-block;padding:10px 16px;margin-top:12px;background:#0f8bff;color:#fff;text-decoration:none;border-radius:6px;}"
|
||||
"</style></head><body><div class=\"container\">"
|
||||
"<h2>Authentication complete</h2>"
|
||||
"<p>You can return to OrcaSlicer. If your browser does not redirect automatically, use the button below.</p>"
|
||||
"<a class=\"button\" href=\"" + location_str + "\">Continue</a>"
|
||||
"<h2>" + _u8L("Authentication complete") + "</h2>"
|
||||
"<p>" + _u8L("You can return to OrcaSlicer. If your browser does not redirect automatically, use the button below.") + "</p>"
|
||||
"<a class=\"button\" href=\"" + location_str + "\">" + _u8L("Continue") + "</a>"
|
||||
"<script>setTimeout(function(){try{window.close();}catch(e){}},1500);</script>"
|
||||
"</div></body></html>";
|
||||
ssOut << "HTTP/1.1 302 Found" << std::endl;
|
||||
|
||||
@@ -527,7 +527,7 @@ void ArrangeJob::check_unprintable()
|
||||
#endif
|
||||
if (it->poly.area() < 0.001) {
|
||||
auto msg = (boost::format(
|
||||
_utf8("Object %s has zero size and can't be arranged."))
|
||||
_u8L("Object %s has zero size and can't be arranged."))
|
||||
% _utf8(it->name)).str();
|
||||
m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
|
||||
NotificationManager::NotificationLevel::WarningNotificationLevel, msg);
|
||||
|
||||
@@ -318,7 +318,7 @@ void CreateVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
|
||||
if (!::finalize(canceled, eptr, *m_input.base))
|
||||
return;
|
||||
if (m_result.its.empty())
|
||||
return create_message("Can't create empty volume.");
|
||||
return create_message(_u8L("Can't create empty volume."));
|
||||
create_volume(std::move(m_result), m_input.object_id, m_input.volume_type, m_input.trmat, *m_input.base, m_input.gizmo);
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ void CreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||
|
||||
// only for sure
|
||||
if (m_result.empty())
|
||||
return create_message("Can't create empty object.");
|
||||
return create_message(_u8L("Can't create empty object."));
|
||||
|
||||
GUI_App &app = wxGetApp();
|
||||
Plater *plater = app.plater();
|
||||
@@ -995,7 +995,7 @@ TriangleMesh create_mesh(DataBase &input, const Fnc& was_canceled, Job::Ctl& ctl
|
||||
return {};
|
||||
// only info
|
||||
ctl.call_on_main_thread([]() {
|
||||
create_message("It is used default volume for embossed text, try to change text or font to fix it.");
|
||||
create_message(_u8L("It is used default volume for embossed text, try to change text or font to fix it."));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1056,7 +1056,7 @@ void update_volume(TriangleMesh &&mesh, const DataUpdate &data, const Transform3
|
||||
{
|
||||
// for sure that some object will be created
|
||||
if (mesh.its.empty())
|
||||
return create_message("Empty mesh can't be created.");
|
||||
return create_message(_u8L("Empty mesh can't be created."));
|
||||
|
||||
Plater *plater = wxGetApp().plater();
|
||||
// Check gizmo is still open otherwise job should be canceled
|
||||
@@ -1115,10 +1115,10 @@ void create_volume(TriangleMesh &&mesh,
|
||||
// Parent object for text volume was propably removed.
|
||||
// Assumption: User know what he does, so text volume is no more needed.
|
||||
if (obj == nullptr)
|
||||
return create_message("Bad object to create volume.");
|
||||
return create_message(_u8L("Bad object to create volume."));
|
||||
|
||||
if (mesh.its.empty())
|
||||
return create_message("Can't create empty volume.");
|
||||
return create_message(_u8L("Can't create empty volume."));
|
||||
|
||||
plater->take_snapshot(_u8L("Add Emboss text Volume"));
|
||||
|
||||
|
||||
@@ -487,7 +487,7 @@ ShortcutCaptureDialog::ShortcutCaptureDialog(wxWindow* parent, Shortcut shortcut
|
||||
m_status_colour = m_status->GetForegroundColour();
|
||||
sizer->Add(m_status, 0, wxLEFT | wxRIGHT | wxTOP, FromDIP(20));
|
||||
|
||||
auto dlg_btns = new DialogButtons(this, {"Unbind", "OK", "Cancel"}, "", 1 /*left_aligned*/);
|
||||
auto dlg_btns = new DialogButtons(this, {L("Unbind"), "OK", "Cancel"}, "", 1 /*left_aligned*/);
|
||||
dlg_btns->GetFIRST()->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
m_chord = KeyChord{};
|
||||
m_conflicts.clear();
|
||||
|
||||
@@ -1676,7 +1676,7 @@ void MixedFilamentDialog::update_ok_button_state()
|
||||
wxString parts;
|
||||
for (auto it = type_groups.begin(); it != type_groups.end(); ++it) {
|
||||
if (!parts.empty())
|
||||
parts += _L(" and ");
|
||||
parts += "; ";
|
||||
wxString slots;
|
||||
for (size_t j = 0; j < it->second.size(); ++j) {
|
||||
if (!slots.empty()) slots += ", ";
|
||||
@@ -1684,7 +1684,7 @@ void MixedFilamentDialog::update_ok_button_state()
|
||||
}
|
||||
parts += wxString::Format(_L("Slot %s (%s)"), slots, wxString::FromUTF8(it->first));
|
||||
}
|
||||
m_type_mismatch_msg = parts + " " + _L("cannot be mixed. Please select the same filament type.");
|
||||
m_type_mismatch_msg = wxString::Format(_L("Different filament types cannot be mixed: %s. Please select the same filament type."), parts);
|
||||
} else {
|
||||
m_type_mismatch_msg.clear();
|
||||
}
|
||||
|
||||
@@ -493,7 +493,8 @@ MultiMachineManagerPage::MultiMachineManagerPage(wxWindow* parent)
|
||||
page_num_enter_evt();
|
||||
});
|
||||
|
||||
m_page_num_enter = new Button(m_flipping_panel, _("Go"));
|
||||
// TRN Button that jumps to the page number typed next to it
|
||||
m_page_num_enter = new Button(m_flipping_panel, _L("Go"));
|
||||
m_page_num_enter->SetMinSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
||||
|
||||
@@ -1166,7 +1166,7 @@ CloudTaskManagerPage::CloudTaskManagerPage(wxWindow* parent)
|
||||
page_num_enter_evt();
|
||||
});
|
||||
|
||||
m_page_num_enter = new Button(m_flipping_panel, _("Go"));
|
||||
m_page_num_enter = new Button(m_flipping_panel, _L("Go"));
|
||||
m_page_num_enter->SetMinSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
||||
|
||||
@@ -128,7 +128,7 @@ void NetworkPluginDownloadDialog::create_missing_plugin_ui()
|
||||
main_sizer->AddSpacer(15);
|
||||
|
||||
auto dlg_btns = new DialogButtons(this,
|
||||
{"Download and Install", "Skip for Now"},
|
||||
{L("Download and Install"), L("Skip for Now")},
|
||||
_L("Download and Install") // Primary button
|
||||
);
|
||||
|
||||
@@ -190,7 +190,7 @@ void NetworkPluginDownloadDialog::create_update_available_ui(const std::string&
|
||||
main_sizer->AddSpacer(10);
|
||||
|
||||
auto dlg_btns = new DialogButtons(this,
|
||||
{"Update Now", "Remind Later", "Skip Version"},
|
||||
{L("Update Now"), L("Remind Later"), L("Skip Version")},
|
||||
_L("Update Now")
|
||||
);
|
||||
|
||||
@@ -319,7 +319,7 @@ NetworkPluginRestartDialog::NetworkPluginRestartDialog(wxWindow* parent)
|
||||
main_sizer->AddSpacer(15);
|
||||
|
||||
auto dlg_btns = new DialogButtons(this,
|
||||
{"Restart Now", "Restart Later"},
|
||||
{L("Restart Now"), L("Restart Later")},
|
||||
_L("Restart Now") // Primary button
|
||||
);
|
||||
|
||||
|
||||
@@ -273,7 +273,8 @@ void NetworkTestDialog::start_all_job_sequence()
|
||||
void NetworkTestDialog::start_test_url(TestJob job, wxString name, wxString url)
|
||||
{
|
||||
m_in_testing[job] = true;
|
||||
wxString info = wxString::Format("test %s start...", name);
|
||||
// TRN %s is the name of the tested website
|
||||
wxString info = wxString::Format(_L("test %s start..."), name);
|
||||
|
||||
update_status(job, info);
|
||||
|
||||
@@ -295,16 +296,16 @@ void NetworkTestDialog::start_test_url(TestJob job, wxString name, wxString url)
|
||||
}
|
||||
})
|
||||
.on_ip_resolve([this,name,job](std::string ip) {
|
||||
wxString ip_report = wxString::Format("test %s ip resolved = %s", name, ip);
|
||||
wxString ip_report = wxString::Format(_L("test %s ip resolved = %s"), name, ip);
|
||||
update_status(job, ip_report);
|
||||
})
|
||||
.on_error([this,name,job](std::string body, std::string error, unsigned int status) {
|
||||
wxString info = wxString::Format("status=%u, body=%s, error=%s", status, body, error);
|
||||
this->update_status(job, wxString::Format("test %s failed", name));
|
||||
this->update_status(job, wxString::Format(_L("test %s failed"), name));
|
||||
this->update_status(-1, info);
|
||||
}).perform_sync();
|
||||
if (result == 0) {
|
||||
update_status(job, wxString::Format("test %s ok", name));
|
||||
update_status(job, wxString::Format(_L("test %s ok"), name));
|
||||
}
|
||||
m_in_testing[job] = false;
|
||||
}
|
||||
|
||||
@@ -1272,7 +1272,7 @@ bool NotificationManager::ExportFinishedNotification::on_text_click()
|
||||
}
|
||||
void NotificationManager::ExportFinishedNotification::on_eject_click()
|
||||
{
|
||||
NotificationData data{ get_data().type, get_data().level , 0, _utf8("Ejecting.") };
|
||||
NotificationData data{ get_data().type, get_data().level , 0, _u8L("Ejecting.") };
|
||||
m_eject_pending = true;
|
||||
m_multiline = false;
|
||||
update(data);
|
||||
@@ -1671,9 +1671,7 @@ void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper&
|
||||
{
|
||||
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
float uploaded = m_file_size * m_percentage;
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "% - " << uploaded << " of " << m_file_size << "MB uploaded";
|
||||
text = stream.str();
|
||||
text = into_u8(wxString::Format(_L("%d%% - %.2f of %.2fMB uploaded"), (int)(m_percentage * 100), uploaded, m_file_size));
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
|
||||
break;
|
||||
@@ -3595,7 +3593,7 @@ void NotificationManager::bbl_show_bed_filament_incompatible_notification(const
|
||||
wxGetApp().open_browser_with_warning_dialog(bed_filament_compatibility_wiki);
|
||||
return false;
|
||||
};
|
||||
push_notification_data({ NotificationType::BBLBedFilamentIncompatible,NotificationLevel::ErrorNotificationLevel,0,_u8L("Error:") + "\n" + text,"Click for more.",callback }, 0);
|
||||
push_notification_data({ NotificationType::BBLBedFilamentIncompatible,NotificationLevel::ErrorNotificationLevel,0,_u8L("Error:") + "\n" + text,_u8L("Click for more."),callback }, 0);
|
||||
}
|
||||
|
||||
void NotificationManager::bbl_close_bed_filament_incompatible_notification()
|
||||
|
||||
@@ -134,13 +134,13 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent
|
||||
m_name = "Settings to modified";
|
||||
}
|
||||
else if (type == itInstanceRoot) {
|
||||
m_name = _(_devL("Instances"));
|
||||
m_name = _L("Instances");
|
||||
m_extruder = parent->m_extruder;
|
||||
}
|
||||
else if (type == itInstance)
|
||||
{
|
||||
m_idx = parent->GetChildCount();
|
||||
m_name = wxString::Format(_(_devL("Instance %d")), m_idx + 1);
|
||||
m_name = wxString::Format(_L("Instance %d"), m_idx + 1);
|
||||
m_extruder = parent->GetParent()->m_extruder;
|
||||
set_icons();
|
||||
}
|
||||
@@ -398,10 +398,11 @@ void ObjectDataViewModelNode::SetIdx(const int &idx)
|
||||
// update name if this node is instance
|
||||
if (m_type == itInstance) {
|
||||
if (m_plate_idx > 0) {
|
||||
m_name = wxString::Format(_(_devL("[P%d]Instance %d")), m_plate_idx, m_idx + 1);
|
||||
// TRN Object list item: plate number, then instance number
|
||||
m_name = wxString::Format(_L("[P%d]Instance %d"), m_plate_idx, m_idx + 1);
|
||||
}
|
||||
else {
|
||||
m_name = wxString::Format(_(_devL("Instance %d")), m_idx + 1);
|
||||
m_name = wxString::Format(_L("Instance %d"), m_idx + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent) :
|
||||
m_presets = tab->get_presets();
|
||||
const Preset &sel_preset = m_presets->get_selected_preset();
|
||||
std::string suffix = _u8L_CONTEXT(L_CONTEXT("Copy", "PresetName"), "PresetName");
|
||||
std::string preset_name = sel_preset.is_default ? "Untitled" : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.name;
|
||||
std::string preset_name = sel_preset.is_default ? _u8L("Untitled") : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.name;
|
||||
|
||||
auto input_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
@@ -306,7 +306,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
||||
result = host->test(msg); // using test with special input because I don't want to create the generate_auth_creds func for every printer
|
||||
|
||||
// Prompt user to approve access on the machine.
|
||||
show_info(this, "API Key created. Go to the physical printer and hit \"authorize\" on the screen, then run \"Test\" again.\n"+msg, "API Key created.");
|
||||
show_info(this, _L("API Key created. Go to the physical printer and hit \"authorize\" on the screen, then run \"Test\" again.") + "\n" + msg, _L("API Key created."));
|
||||
|
||||
|
||||
}
|
||||
|
||||
+14
-15
@@ -3000,6 +3000,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
});
|
||||
|
||||
// "Variant", not "Nozzle": picking one switches the printer preset (see panel_nozzle_dia).
|
||||
// TRN Sidebar label of the printer variant (nozzle) selector; picking one switches the printer preset.
|
||||
p->label_nozzle_title = new Label(p->panel_nozzle_dia, _L("Variant"), LB_PROPAGATE_MOUSE_EVENT);
|
||||
p->label_nozzle_title->SetFont(Label::Body_10);
|
||||
|
||||
@@ -3032,7 +3033,7 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->combo_nozzle_dia->Bind(wxEVT_SET_FOCUS, [nozzle_focus_bg](auto& e) {nozzle_focus_bg(true ); e.Skip();});
|
||||
p->combo_nozzle_dia->Bind(wxEVT_KILL_FOCUS, [nozzle_focus_bg](auto& e) {nozzle_focus_bg(false); e.Skip();});
|
||||
|
||||
p->label_nozzle_type = new Label(p->panel_nozzle_dia, "Brass", LB_PROPAGATE_MOUSE_EVENT | wxST_ELLIPSIZE_END | wxALIGN_CENTRE_HORIZONTAL);
|
||||
p->label_nozzle_type = new Label(p->panel_nozzle_dia, _L("Brass"), LB_PROPAGATE_MOUSE_EVENT | wxST_ELLIPSIZE_END | wxALIGN_CENTRE_HORIZONTAL);
|
||||
p->label_nozzle_type->SetFont(Label::Body_10);
|
||||
p->label_nozzle_type->SetMinSize(FromDIP(wxSize(56, -1)));
|
||||
p->label_nozzle_type->SetMaxSize(FromDIP(wxSize(56, -1)));
|
||||
@@ -16322,7 +16323,7 @@ bool Plater::add_model(bool imperial_units, std::string fname)
|
||||
|
||||
void Plater::calib_pa(const Calib_Params& params)
|
||||
{
|
||||
const auto calib_pa_name = wxString::Format(L"Pressure Advance Test");
|
||||
const auto calib_pa_name = _L("Pressure Advance Test");
|
||||
new_project(false, false, calib_pa_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
@@ -16799,11 +16800,9 @@ void Plater::calib_flowrate(bool is_linear, int pass, InfillPattern pattern) {
|
||||
return;
|
||||
wxString calib_name;
|
||||
if (is_linear) {
|
||||
calib_name = L"Orca YOLO Flow Calibration";
|
||||
if (pass == 2)
|
||||
calib_name += L" - Perfectionist version";
|
||||
calib_name = pass == 2 ? _L("Orca YOLO Flow Calibration - Perfectionist version") : _L("Orca YOLO Flow Calibration");
|
||||
} else
|
||||
calib_name = wxString::Format(L"Flowrate Test - Pass%d", pass);
|
||||
calib_name = wxString::Format(_L("Flowrate Test - Pass%d"), pass);
|
||||
|
||||
if (new_project(false, false, calib_name) == wxID_CANCEL)
|
||||
return;
|
||||
@@ -16843,7 +16842,7 @@ void Plater::calib_temp(const Calib_Params& params) {
|
||||
constexpr double base_temp_tower_block_height = 10.0;
|
||||
constexpr int base_temp_tower_temp_step = 5;
|
||||
|
||||
const auto calib_temp_name = wxString::Format(L"Nozzle temperature test");
|
||||
const auto calib_temp_name = _L("Nozzle temperature test");
|
||||
new_project(false, false, calib_temp_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_Temp_Tower) return;
|
||||
@@ -16923,7 +16922,7 @@ void Plater::calib_temp(const Calib_Params& params) {
|
||||
|
||||
void Plater::calib_max_vol_speed(const Calib_Params& params)
|
||||
{
|
||||
const auto calib_vol_speed_name = wxString::Format(L"Max volumetric speed test");
|
||||
const auto calib_vol_speed_name = _L("Max volumetric speed test");
|
||||
new_project(false, false, calib_vol_speed_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_Vol_speed_Tower)
|
||||
@@ -17002,7 +17001,7 @@ void Plater::calib_max_vol_speed(const Calib_Params& params)
|
||||
|
||||
void Plater::calib_retraction(const Calib_Params& params)
|
||||
{
|
||||
const auto calib_retraction_name = wxString::Format(L"Retraction");
|
||||
const auto calib_retraction_name = _L("Retraction");
|
||||
new_project(false, false, calib_retraction_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_Retraction_tower)
|
||||
@@ -17064,7 +17063,7 @@ void Plater::calib_retraction(const Calib_Params& params)
|
||||
|
||||
void Plater::calib_VFA(const Calib_Params& params)
|
||||
{
|
||||
const auto calib_vfa_name = wxString::Format(L"VFA test");
|
||||
const auto calib_vfa_name = _L("VFA test");
|
||||
new_project(false, false, calib_vfa_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_VFA_Tower)
|
||||
@@ -17147,7 +17146,7 @@ void Plater::calib_VFA(const Calib_Params& params)
|
||||
|
||||
void Plater::calib_input_shaping_freq(const Calib_Params& params)
|
||||
{
|
||||
const auto calib_input_shaping_name = wxString::Format(L"Input shaping Frequency test");
|
||||
const auto calib_input_shaping_name = _L("Input shaping Frequency test");
|
||||
new_project(false, false, calib_input_shaping_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_Input_shaping_freq)
|
||||
@@ -17209,7 +17208,7 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params)
|
||||
|
||||
void Plater::calib_input_shaping_damp(const Calib_Params& params)
|
||||
{
|
||||
const auto calib_input_shaping_name = wxString::Format(L"Input shaping Damping test");
|
||||
const auto calib_input_shaping_name = _L("Input shaping Damping test");
|
||||
new_project(false, false, calib_input_shaping_name);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_Input_shaping_damp)
|
||||
@@ -17270,7 +17269,7 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params)
|
||||
|
||||
void Plater::Calib_Cornering(const Calib_Params& params)
|
||||
{
|
||||
const auto Calib_Cornering = wxString::Format(L"Cornering test");
|
||||
const auto Calib_Cornering = _L("Cornering test");
|
||||
new_project(false, false, Calib_Cornering);
|
||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||
if (params.mode != CalibMode::Calib_Cornering)
|
||||
@@ -17458,7 +17457,7 @@ void Plater::load_gcode(const wxString& filename)
|
||||
if (p->preview->get_canvas3d()->get_gcode_layers_zs().empty()) {
|
||||
MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("Does not contain valid G-code."),
|
||||
wxString(GCODEVIEWER_APP_NAME) + " - " + _L("An Error has occurred while loading the G-code file."), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal();
|
||||
set_project_filename(DEFAULT_PROJECT_NAME);
|
||||
set_project_filename(_L(DEFAULT_PROJECT_NAME));
|
||||
} else {
|
||||
set_project_filename(filename);
|
||||
}
|
||||
@@ -17809,7 +17808,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename)
|
||||
// Orca: hide the "Don't show again" checkbox, people keeps accidentally checked this then forgot
|
||||
// wxBoxSizer *m_sizer_left = new wxBoxSizer(wxHORIZONTAL);
|
||||
//
|
||||
// auto dont_show_again = create_remember_checkbox(_L("Remember my choice."), this, _L("This option can be changed later in preferences, under 'Load Behaviour'."));
|
||||
// auto dont_show_again = create_remember_checkbox(_L("Remember my choice."), this, _L("This option can be changed later in preferences, under 'Load Behavior'."));
|
||||
// m_sizer_left->Add(dont_show_again, 0, wxALL, 5);
|
||||
//
|
||||
// m_sizer_bottom->Add(m_sizer_left, 0, wxEXPAND, 5);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include "slic3r/GUI/Event.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include <string>
|
||||
#include "slic3r/GUI/ObjectDataViewModel.hpp"
|
||||
#include "slic3r/GUI/SettingsIndex.hpp"
|
||||
@@ -140,7 +141,7 @@ wxDECLARE_EVENT(EVT_NOTICE_CHILDE_SIZE_CHANGED, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent);
|
||||
using ColorEvent = Event<wxColour>;
|
||||
wxDECLARE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent);
|
||||
const wxString DEFAULT_PROJECT_NAME = "Untitled";
|
||||
const wxString DEFAULT_PROJECT_NAME = L("Untitled");
|
||||
|
||||
class SidebarProps
|
||||
{
|
||||
|
||||
@@ -265,25 +265,25 @@ PluginAvailableActions evaluate_action_policy(const PluginDialogItem& item)
|
||||
available_actions.can_toggle = !is_loading && (has_local || available_actions.toggle_installs_cloud_plugin);
|
||||
|
||||
auto add_action = [&available_actions](const char* id, const char* label, bool enabled = true, bool danger = false) {
|
||||
available_actions.context_actions.push_back(PluginContextAction{id, label, enabled, danger});
|
||||
available_actions.context_actions.push_back(PluginContextAction{id, _u8L(label), enabled, danger});
|
||||
};
|
||||
|
||||
// Owned cloud plugins fall through to the local delete: it removes the installed package only.
|
||||
// Deleting a plugin from the cloud is a plugin hub operation and is never offered here.
|
||||
if (is_cloud && !is_orphaned && !is_mine) {
|
||||
add_action("unsubscribe_plugin", "Unsubscribe", true, true);
|
||||
add_action("unsubscribe_plugin", L("Unsubscribe"), true, true);
|
||||
} else if (has_local) {
|
||||
add_action("delete_plugin", "Delete", true, true);
|
||||
add_action("delete_plugin", L("Delete"), true, true);
|
||||
}
|
||||
|
||||
add_action("open_folder", "Show in folder", has_local);
|
||||
add_action("open_folder", L("Show in folder"), has_local);
|
||||
|
||||
if (!is_orphaned) {
|
||||
if (is_cloud) {
|
||||
add_action("reinstall_plugin", "Reinstall");
|
||||
add_action("reinstall_plugin", L("Reinstall"));
|
||||
} else {
|
||||
add_action("reload_plugin", "Reload");
|
||||
add_action("clear_cache_reload_plugin", "Delete cache and reload");
|
||||
add_action("reload_plugin", L("Reload"));
|
||||
add_action("clear_cache_reload_plugin", L("Delete cache and reload"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -811,7 +811,7 @@ void PluginsDialog::toggle_plugin(const std::string& plugin_key, bool enabled)
|
||||
|
||||
if (!available_actions.can_toggle) {
|
||||
if (dialog_item.unauthorized && available_actions.toggle_installs_cloud_plugin == false && row_data.has_local_package() == false) {
|
||||
const std::string install_error = "Unauthorized cloud plugins cannot be installed.";
|
||||
const std::string install_error = _u8L("Unauthorized cloud plugins cannot be installed.");
|
||||
manager.set_plugin_error(plugin_key, install_error);
|
||||
show_status(from_u8(install_error), "warn");
|
||||
}
|
||||
@@ -1071,7 +1071,7 @@ void PluginsDialog::run_script_plugin_capability(const std::string& plugin_key,
|
||||
ExecutionResult result;
|
||||
|
||||
auto complete_with_error = [this, &manager, &plugin_key](const std::string& plugin_error, const wxString& status_message) {
|
||||
const std::string normalized_error = plugin_error.empty() ? "Script plugin failed." : plugin_error;
|
||||
const std::string normalized_error = plugin_error.empty() ? _u8L("Script plugin failed.") : plugin_error;
|
||||
if (!manager.set_plugin_error(plugin_key, normalized_error))
|
||||
BOOST_LOG_TRIVIAL(warning) << "Failed to record plugin error. plugin_key=" << plugin_key;
|
||||
|
||||
@@ -1262,34 +1262,34 @@ void PluginsDialog::reload_local_plugin(const std::string& plugin_key, bool clea
|
||||
if (clear_cache) {
|
||||
PluginDescriptor descriptor;
|
||||
if (!manager.try_get_plugin_descriptor(plugin_key, descriptor))
|
||||
return {false, "Plugin not found."};
|
||||
return {false, _u8L("Plugin not found.")};
|
||||
|
||||
boost::filesystem::path resolved_root;
|
||||
std::string resolve_error;
|
||||
if (!resolve_allowed_plugin_root(descriptor, {get_orca_plugins_dir()},
|
||||
"Refusing to clear a plugin cache outside the local plugin directory.",
|
||||
_u8L("Refusing to clear a plugin cache outside the local plugin directory."),
|
||||
resolved_root, resolve_error))
|
||||
return {false, resolve_error};
|
||||
cache_dir = resolved_root / "__whl_extracted__";
|
||||
}
|
||||
|
||||
if (!manager.unload_plugin(plugin_key))
|
||||
return {false, "Failed to unload plugin."};
|
||||
return {false, _u8L("Failed to unload plugin.")};
|
||||
|
||||
if (clear_cache) {
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove_all(cache_dir, ec);
|
||||
if (ec)
|
||||
return {false, "Failed to clear plugin cache: " + ec.message()};
|
||||
return {false, GUI::format(_u8L("Failed to clear plugin cache: %1%"), ec.message())};
|
||||
}
|
||||
|
||||
manager.load_plugin(plugin_key, false);
|
||||
std::string error;
|
||||
if (!manager.wait_for_plugin_load(plugin_key, std::chrono::minutes(5), error) || !manager.is_plugin_loaded(plugin_key))
|
||||
return {false, error.empty() ? "Plugin failed to load." : error};
|
||||
return {false, error.empty() ? _u8L("Plugin failed to load.") : error};
|
||||
|
||||
if (!was_loaded && !manager.unload_plugin(plugin_key))
|
||||
return {false, "Plugin reloaded, but failed to restore the inactive state."};
|
||||
return {false, _u8L("Plugin reloaded, but failed to restore the inactive state.")};
|
||||
|
||||
return {true, {}};
|
||||
},
|
||||
@@ -1297,7 +1297,7 @@ void PluginsDialog::reload_local_plugin(const std::string& plugin_key, bool clea
|
||||
} catch (const std::exception& ex) {
|
||||
reload_result = {false, ex.what()};
|
||||
} catch (...) {
|
||||
reload_result = {false, "Unknown plugin reload error."};
|
||||
reload_result = {false, _u8L("Unknown plugin reload error.")};
|
||||
}
|
||||
|
||||
if (!reload_result.first) {
|
||||
@@ -1344,14 +1344,14 @@ void PluginsDialog::reinstall_cloud_plugin(const PluginDescriptor& plugin)
|
||||
manager.load_plugin(plugin_key);
|
||||
std::string error;
|
||||
if (!manager.wait_for_plugin_load(plugin_key, std::chrono::minutes(5), error) || !manager.is_plugin_loaded(plugin_key))
|
||||
return {false, error.empty() ? "Plugin failed to load." : error};
|
||||
return {false, error.empty() ? _u8L("Plugin failed to load.") : error};
|
||||
return {true, {}};
|
||||
},
|
||||
_L("Reloading plugin"), _L("Reloading plugin"));
|
||||
} catch (const std::exception& ex) {
|
||||
reload_result = {false, ex.what()};
|
||||
} catch (...) {
|
||||
reload_result = {false, "Unknown plugin reload error."};
|
||||
reload_result = {false, _u8L("Unknown plugin reload error.")};
|
||||
}
|
||||
|
||||
if (!reload_result.first) {
|
||||
|
||||
@@ -120,9 +120,10 @@ static DWORD execute_process_winapi(const std::wstring& command_line)
|
||||
if (!::CreateProcessW(nullptr /* lpApplicationName */, (LPWSTR) command_line.c_str(), nullptr /* lpProcessAttributes */,
|
||||
nullptr /* lpThreadAttributes */, false /* bInheritHandles */,
|
||||
CREATE_UNICODE_ENVIRONMENT /* | CREATE_NEW_CONSOLE */ /* dwCreationFlags */, (LPVOID) envstr.c_str(),
|
||||
nullptr /* lpCurrentDirectory */, &startup_info, &process_info))
|
||||
throw Slic3r::RuntimeError(std::string("Failed starting the script ") + boost::nowide::narrow(command_line) +
|
||||
", Win32 error: " + std::to_string(int(::GetLastError())));
|
||||
nullptr /* lpCurrentDirectory */, &startup_info, &process_info)) {
|
||||
const int error = int(::GetLastError());
|
||||
throw Slic3r::RuntimeError(Slic3r::format(_u8L("Failed starting the script %1%, Win32 error: %2%"), boost::nowide::narrow(command_line), error));
|
||||
}
|
||||
::WaitForSingleObject(process_info.hProcess, INFINITE);
|
||||
ULONG rc = 0;
|
||||
::GetExitCodeProcess(process_info.hProcess, &rc);
|
||||
@@ -141,14 +142,14 @@ static int run_script(const std::string& script, const std::string& gcode, std::
|
||||
LPWSTR* szArglist = CommandLineToArgvW(boost::nowide::widen(script).c_str(), &nArgs);
|
||||
if (szArglist == nullptr || nArgs <= 0) {
|
||||
// CommandLineToArgvW failed. Maybe the command line escapment is invalid?
|
||||
throw Slic3r::RuntimeError(std::string("Post processing script ") + script + " on file " + gcode +
|
||||
" failed. CommandLineToArgvW() refused to parse the command line path.");
|
||||
throw Slic3r::RuntimeError(Slic3r::format(_u8L("Post processing script %1% on file %2% failed. CommandLineToArgvW() refused to parse the command line path."),
|
||||
script, gcode));
|
||||
}
|
||||
|
||||
std::wstring command_line;
|
||||
std::wstring command = szArglist[0];
|
||||
if (!boost::filesystem::exists(boost::filesystem::path(command)))
|
||||
throw Slic3r::RuntimeError(std::string("The configured post-processing script does not exist: ") + boost::nowide::narrow(command));
|
||||
throw Slic3r::RuntimeError(Slic3r::format(_u8L("The configured post-processing script does not exist: %1%"), boost::nowide::narrow(command)));
|
||||
if (boost::iends_with(command, L".pl")) {
|
||||
// This is a perl script. Run it through the perl interpreter.
|
||||
// The current process may be slic3r.exe or slic3r-console.exe.
|
||||
@@ -159,7 +160,7 @@ static int run_script(const std::string& script, const std::string& gcode, std::
|
||||
boost::filesystem::path path_perl = path_exe.parent_path() / "perl" / "perl.exe";
|
||||
if (!boost::filesystem::exists(path_perl)) {
|
||||
LocalFree(szArglist);
|
||||
throw Slic3r::RuntimeError(std::string("Perl interpreter ") + path_perl.string() + " does not exist.");
|
||||
throw Slic3r::RuntimeError(Slic3r::format(_u8L("Perl interpreter %1% does not exist."), path_perl.string()));
|
||||
}
|
||||
// Replace it with the current perl interpreter.
|
||||
quote_argv_winapi(boost::nowide::widen(path_perl.string()), command_line);
|
||||
@@ -294,14 +295,14 @@ static void run_post_process_plugins(const ConfigOptionStrings& capabilities,
|
||||
exec_result = cap->execute(ctx);
|
||||
} catch (const std::exception& ex) {
|
||||
const std::string msg =
|
||||
(boost::format("Post-processing plugin %1% raised an exception.\nError: %2%") % ref.capability_name % ex.what()).str();
|
||||
(boost::format(_u8L("Post-processing plugin %1% raised an exception.\nError: %2%")) % ref.capability_name % ex.what()).str();
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
throw Slic3r::RuntimeError(msg);
|
||||
}
|
||||
|
||||
if (exec_result.status == PluginResult::RecoverableError || exec_result.status == PluginResult::FatalError) {
|
||||
const std::string msg =
|
||||
(boost::format("Post-processing plugin %1% failed.\nError: %2%") % ref.capability_name % exec_result.message).str();
|
||||
(boost::format(_u8L("Post-processing plugin %1% failed.\nError: %2%")) % ref.capability_name % exec_result.message).str();
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
throw Slic3r::RuntimeError(msg);
|
||||
}
|
||||
@@ -370,7 +371,7 @@ bool run_post_process_scripts(
|
||||
std::string error_message;
|
||||
if (copy_file(src_path, path, error_message, false) != SUCCESS)
|
||||
throw Slic3r::RuntimeError(
|
||||
Slic3r::format("Failed making a temporary copy of G-code file %1% before running a post-processing script: %2%", src_path,
|
||||
Slic3r::format(_u8L("Failed making a temporary copy of G-code file %1% before running a post-processing script: %2%"), src_path,
|
||||
error_message));
|
||||
} else {
|
||||
// Don't make a copy of the G-code before running the post-processing script.
|
||||
@@ -390,7 +391,7 @@ bool run_post_process_scripts(
|
||||
|
||||
auto gcode_file = boost::filesystem::path(path);
|
||||
if (!boost::filesystem::exists(gcode_file))
|
||||
throw Slic3r::RuntimeError(std::string("Post-processor can't find exported gcode file"));
|
||||
throw Slic3r::RuntimeError(_u8L("Post-processor can't find exported gcode file"));
|
||||
|
||||
// Store print configuration into environment variables.
|
||||
config.setenv_();
|
||||
@@ -431,11 +432,11 @@ bool run_post_process_scripts(
|
||||
const int result = run_script(script, gcode_file.string(), std_err);
|
||||
if (result != 0) {
|
||||
const std::string msg = std_err.empty() ?
|
||||
(boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") %
|
||||
(boost::format(_u8L("Post-processing script %1% on file %2% failed.\nError code: %3%")) %
|
||||
script % path % result)
|
||||
.str() :
|
||||
(boost::format(
|
||||
"Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") %
|
||||
_u8L("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%")) %
|
||||
script % path % result % std_err)
|
||||
.str();
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
@@ -476,19 +477,19 @@ bool run_post_process_scripts(
|
||||
new_output_name = outpath.string();
|
||||
} else {
|
||||
if (!op.is_absolute() || !op.has_filename())
|
||||
throw Slic3r::RuntimeError("Unable to parse desired new path from output name file");
|
||||
throw Slic3r::RuntimeError(_u8L("Unable to parse desired new path from output name file"));
|
||||
}
|
||||
if (!fs::exists(fs::path(new_output_name).parent_path()))
|
||||
throw Slic3r::RuntimeError(
|
||||
Slic3r::format("Output directory does not exist: %1%", fs::path(new_output_name).parent_path().string()));
|
||||
Slic3r::format(_u8L("Output directory does not exist: %1%"), fs::path(new_output_name).parent_path().string()));
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Post-processing script changed the file name from " << output_name << " to "
|
||||
<< new_output_name;
|
||||
output_name = new_output_name;
|
||||
} catch (const std::exception& err) {
|
||||
throw Slic3r::RuntimeError(Slic3r::format("run_post_process_scripts: Failed reading a file %1% "
|
||||
"carrying the final name / path of a G-code file: %2%",
|
||||
throw Slic3r::RuntimeError("run_post_process_scripts: " +
|
||||
Slic3r::format(_u8L("Failed reading a file %1% carrying the final name / path of a G-code file: %2%"),
|
||||
path_output_name, err.what()));
|
||||
}
|
||||
remove_output_name_file();
|
||||
|
||||
@@ -1715,7 +1715,7 @@ void PreferencesDialog::create_items()
|
||||
|
||||
std::vector<wxString> projectLoadSettingsBehaviourOptions = {_L("Load All"), _L("Ask When Relevant"), _L("Always Ask"), _L("Load Geometry Only")};
|
||||
std::vector<string> projectLoadSettingsConfigOptions = { OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_ALL, OPTION_PROJECT_LOAD_BEHAVIOUR_ASK_WHEN_RELEVANT, OPTION_PROJECT_LOAD_BEHAVIOUR_ALWAYS_ASK, OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_GEOMETRY };
|
||||
auto item_project_load = create_item_combobox(_L("Load behaviour"), _L("Should printer/filament/process settings be loaded when opening a 3MF file?"), SETTING_PROJECT_LOAD_BEHAVIOUR, projectLoadSettingsBehaviourOptions, projectLoadSettingsConfigOptions);
|
||||
auto item_project_load = create_item_combobox(_L("Load behavior"), _L("Should printer/filament/process settings be loaded when opening a 3MF file?"), SETTING_PROJECT_LOAD_BEHAVIOUR, projectLoadSettingsBehaviourOptions, projectLoadSettingsConfigOptions);
|
||||
g_sizer->Add(item_project_load);
|
||||
|
||||
auto item_backup = create_item_backup(_L("Auto backup"), _L("Backup your project periodically to help with restoring from an occasional crash."));
|
||||
@@ -1801,6 +1801,7 @@ void PreferencesDialog::create_items()
|
||||
auto item_speed_dial_recents = create_item_spinctrl(
|
||||
_L("Recent actions"),
|
||||
"",
|
||||
// TRN Unit shown after the number of recent actions, as in "5 actions".
|
||||
_L("actions"),
|
||||
_L("How many recently launched actions to show at the top of the Speed Dial. Set to 0 to hide recent actions."),
|
||||
SETTING_SPEED_DIAL_RECENT_COUNT,
|
||||
@@ -1851,7 +1852,7 @@ void PreferencesDialog::create_items()
|
||||
g_sizer->AddGrowableCol(0, 1);
|
||||
|
||||
//// CONTROL > Behaviour
|
||||
g_sizer->Add(create_item_title(_L("Behaviour")), 1, wxEXPAND);
|
||||
g_sizer->Add(create_item_title(_L("Behavior")), 1, wxEXPAND);
|
||||
|
||||
std::vector<wxString> FlushOptionLabels = {_L("All"),_L("Color"),_L("None")};
|
||||
std::vector<std::string> FlushOptionValues = { "all","color change","disabled" };
|
||||
@@ -1900,7 +1901,7 @@ void PreferencesDialog::create_items()
|
||||
if (wxGetApp().is_enable_cad_feature()) {
|
||||
auto item_connector_face_glyph = create_item_checkbox(_L("Draw mate connectors as a face"),
|
||||
_L("In the Design tab, draw a mate connector as a small face instead of the conventional "
|
||||
"disc with a roll quadrant. A face's orientation is read without being learned. "
|
||||
"disc with a roll quadrant. A face shows its orientation at a glance, without learning the disc convention. "
|
||||
"Turn this off for the conventional CAD representation."), "design_connector_face_glyph");
|
||||
g_sizer->Add(item_connector_face_glyph);
|
||||
|
||||
@@ -1999,7 +2000,11 @@ void PreferencesDialog::create_items()
|
||||
);
|
||||
g_sizer->Add(item_realistic_ssao);
|
||||
|
||||
std::vector<wxString> ShadowsLabels = { _L("Off"), _L("Static"), _L("Orbit") };
|
||||
std::vector<wxString> ShadowsLabels = { _L("Off"),
|
||||
// TRN Realistic-view shadow mode: the light stays fixed in the scene.
|
||||
_L("Static"),
|
||||
// TRN Realistic-view shadow mode: the light turns with the camera.
|
||||
_L("Orbit") };
|
||||
std::vector<std::string> ShadowsValues = { "off", "static", "orbit" };
|
||||
auto item_realistic_shadows = create_item_combobox(
|
||||
_L("Shadows"),
|
||||
|
||||
@@ -2050,7 +2050,8 @@ void CrealityPrintHostSendDialog::init()
|
||||
wxBitmap* bmp = get_extruder_color_icon(slot.color, "", icon_sz, icon_sz);
|
||||
wxString label_str;
|
||||
if (slot.box_id == 0)
|
||||
label_str = wxString::Format("Ext - %s", slot.type.c_str());
|
||||
// TRN External spool slot, followed by its filament type
|
||||
label_str = wxString::Format(_L("Ext - %s"), slot.type.c_str());
|
||||
else
|
||||
label_str = wxString::Format("%s - %s", slot.tool_id.substr(1).c_str(), slot.type.c_str());
|
||||
combo->Append(label_str, bmp ? *bmp : wxNullBitmap);
|
||||
|
||||
@@ -276,7 +276,7 @@ private:
|
||||
if (params.is_discarded())
|
||||
params = json::object();
|
||||
|
||||
const std::string filter = json_string(params, "filter").empty() ? "All files (*.*)|*.*" : json_string(params, "filter");
|
||||
const std::string filter = json_string(params, "filter").empty() ? _u8L("All files (*.*)|*.*") : json_string(params, "filter");
|
||||
|
||||
wxWindow* parent = owner().GetParent();
|
||||
if (parent == nullptr)
|
||||
|
||||
@@ -59,7 +59,7 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox
|
||||
m_presets = tab->get_presets();
|
||||
|
||||
const Preset &sel_preset = m_presets->get_selected_preset();
|
||||
std::string preset_name = sel_preset.is_default ? "Untitled" : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.is_from_bundle() && !sel_preset.alias.empty() ? sel_preset.alias : sel_preset.name;
|
||||
std::string preset_name = sel_preset.is_default ? _u8L("Untitled") : sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() : sel_preset.is_from_bundle() && !sel_preset.alias.empty() ? sel_preset.alias : sel_preset.name;
|
||||
|
||||
// if name contains extension
|
||||
if (boost::iends_with(preset_name, ".ini")) {
|
||||
|
||||
@@ -1131,7 +1131,7 @@ void SelectMachineDialog::sync_ams_mapping_result(std::vector<FilamentInfo> &res
|
||||
if (result.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "ams_mapping result is empty";
|
||||
for (auto it = m_materialList.begin(); it != m_materialList.end(); it++) {
|
||||
wxString ams_id = "Ext";//
|
||||
wxString ams_id = _L("Ext");//
|
||||
wxColour ams_col = wxColour(0xCE, 0xCE, 0xCE);
|
||||
it->second->item->set_ams_info(ams_col, ams_id);
|
||||
it->second->item->set_nozzle_info(get_mapped_nozzle_str(it->first));
|
||||
@@ -1155,7 +1155,7 @@ void SelectMachineDialog::sync_ams_mapping_result(std::vector<FilamentInfo> &res
|
||||
|
||||
if (f->tray_id == VIRTUAL_TRAY_MAIN_ID || f->tray_id == VIRTUAL_TRAY_DEPUTY_ID)
|
||||
{
|
||||
ams_id = "Ext";
|
||||
ams_id = _L("Ext");
|
||||
}else if (f->tray_id >= 0) {
|
||||
ams_id = wxGetApp().transition_tridid(f->tray_id);
|
||||
} else {
|
||||
@@ -3863,7 +3863,7 @@ void SelectMachineDialog::on_refresh(wxCommandEvent &event)
|
||||
void SelectMachineDialog::on_set_finish_mapping(wxCommandEvent &evt)
|
||||
{
|
||||
auto selection_data = evt.GetString();
|
||||
auto selection_data_arr = wxSplit(selection_data.ToStdString(), '|');
|
||||
auto selection_data_arr = wxSplit(selection_data, '|');
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "The ams mapping selection result: data is " << selection_data;
|
||||
|
||||
@@ -4376,9 +4376,9 @@ static wxString _check_kval_not_default(const MachineObject* obj, const std::vec
|
||||
|
||||
wxString ams_name;
|
||||
if (info.tray_id == VIRTUAL_TRAY_MAIN_ID) {
|
||||
ams_name = "Right-Ext";
|
||||
ams_name = _L("Right-Ext");
|
||||
} else if (info.tray_id == VIRTUAL_TRAY_DEPUTY_ID) {
|
||||
ams_name = "Left-Ext";
|
||||
ams_name = _L("Left-Ext");
|
||||
} else {
|
||||
ams_name = wxGetApp().transition_tridid(info.tray_id);
|
||||
}
|
||||
@@ -5509,7 +5509,7 @@ void SelectMachineDialog::change_materialitem_tip(bool no_ams_only_ext)
|
||||
int id = iter->first;
|
||||
Material *item = iter->second;
|
||||
if (item) {
|
||||
if (no_ams_only_ext && item->item->m_ams_name == "Ext") {
|
||||
if (no_ams_only_ext && item->item->m_ams_name == _L("Ext")) {
|
||||
item->item->SetToolTip(wxEmptyString);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1020,7 +1020,7 @@ void SendMultiMachinePage::OnSelectRadio(wxMouseEvent& event)
|
||||
while (iter != m_material_list.end()) {
|
||||
Material * item = iter->second;
|
||||
MaterialItem *m = item->item;
|
||||
if (item->id == m_current_filament_id) { m->set_ams_info(wxColour("#CECECE"), "Ext", 0, std::vector<wxColour>()); }
|
||||
if (item->id == m_current_filament_id) { m->set_ams_info(wxColour("#CECECE"), _L("Ext"), 0, std::vector<wxColour>()); }
|
||||
iter++;
|
||||
}
|
||||
} else if (rs->m_param_name == "use_ams") {
|
||||
@@ -1072,7 +1072,7 @@ bool SendMultiMachinePage::get_value_radio(std::string param)
|
||||
void SendMultiMachinePage::on_set_finish_mapping(wxCommandEvent& evt)
|
||||
{
|
||||
auto selection_data = evt.GetString();
|
||||
auto selection_data_arr = wxSplit(selection_data.ToStdString(), '|');
|
||||
auto selection_data_arr = wxSplit(selection_data, '|');
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "The ams mapping selection result: data is " << selection_data;
|
||||
|
||||
@@ -1532,7 +1532,7 @@ void SendMultiMachinePage::sync_ams_list()
|
||||
|
||||
MaterialItem* item = new MaterialItem(m_main_page, colour_rgb, _L(display_materials[extruder]));
|
||||
//item->set_ams_info(wxColour("#CECECE"), "A1", 0, std::vector<wxColour>());
|
||||
item->set_ams_info(wxColour("#CECECE"), "Ext", 0, std::vector<wxColour>());
|
||||
item->set_ams_info(wxColour("#CECECE"), _L("Ext"), 0, std::vector<wxColour>());
|
||||
m_ams_list_sizer->Add(item, 0, wxALL, FromDIP(4));
|
||||
|
||||
item->Bind(wxEVT_LEFT_UP, [materials](wxMouseEvent& e) {});
|
||||
|
||||
@@ -57,10 +57,10 @@ int json_int_or(const nlohmann::json& j, const char* key, int fallback)
|
||||
wxString mode_label(ConfigOptionMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case comAdvanced: return _L("Advanced");
|
||||
case comExpert: return _L("Expert");
|
||||
case comDevelop: return _L("Developer");
|
||||
default: return _L("Simple");
|
||||
case comAdvanced: return _L_CONTEXT("Advanced", "Settings Mode");
|
||||
case comExpert: return _L_CONTEXT("Expert", "Settings Mode");
|
||||
case comDevelop: return _L_CONTEXT("Developer", "Settings Mode");
|
||||
default: return _L_CONTEXT("Simple", "Settings Mode");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,25 +106,25 @@ nlohmann::json speed_dial_ui_strings()
|
||||
{"sd_no_actions", _u8L("No actions yet")},
|
||||
{"sd_no_tabs_match", _u8L("No tabs match")},
|
||||
{"sd_no_tabs", _u8L("No tabs")},
|
||||
{"sd_result_count", _u8L("Showing %s actions")},
|
||||
{"sd_result_count_all", _u8L("%s actions")},
|
||||
{"sd_tab_count", _u8L("%s tabs")},
|
||||
{"sd_tab_match_count", _u8L("%s matches")},
|
||||
{"sd_favs_full", _u8L("Favourites are full (%s max)")},
|
||||
{"sd_result_count", _u8L("Matching actions: %s")},
|
||||
{"sd_result_count_all", _u8L("Actions: %s")},
|
||||
{"sd_tab_count", _u8L("Tabs: %s")},
|
||||
{"sd_tab_match_count", _u8L("Matching tabs: %s")},
|
||||
{"sd_favs_full", _u8L("Favorites are full (%s max)")},
|
||||
{"sd_go_to_pct", _u8L("Go to %s%% of the layer range")},
|
||||
{"sd_enter_pct", _u8L("Enter a layer percentage (0-100)")},
|
||||
{"sd_go_layer_ph", _u8L("Go to layer %% (0-100)")},
|
||||
{"sd_go_tab_ph", _u8L("Go to tab")},
|
||||
{"sd_fav_slot", _u8L("Favourite %s (%s)")},
|
||||
{"sd_pin_fav", _u8L("Pin to favourites (%s)")},
|
||||
{"sd_unpin_fav", _u8L("Unpin from favourites (%s)")},
|
||||
{"sd_remove_fav", _u8L("Remove from favourites")},
|
||||
{"sd_fav_slot", _u8L("Favorite %s (%s)")},
|
||||
{"sd_pin_fav", _u8L("Pin to favorites (%s)")},
|
||||
{"sd_unpin_fav", _u8L("Unpin from favorites (%s)")},
|
||||
{"sd_remove_fav", _u8L("Remove from favorites")},
|
||||
{"sd_move_left", _u8L("Move left")},
|
||||
{"sd_move_right", _u8L("Move right")},
|
||||
{"sd_unpin", _u8L("Unpin")},
|
||||
{"sd_mode_advanced", _u8L("Advanced")},
|
||||
{"sd_mode_expert", _u8L("Expert")},
|
||||
{"sd_mode_develop", _u8L("Developer")},
|
||||
{"sd_mode_advanced", _u8L_CONTEXT("Advanced", "Settings Mode")},
|
||||
{"sd_mode_expert", _u8L_CONTEXT("Expert", "Settings Mode")},
|
||||
{"sd_mode_develop", _u8L_CONTEXT("Developer", "Settings Mode")},
|
||||
{"sd_wiki_f1", _u8L("Wiki (F1)")},
|
||||
{"sd_no_wiki", _u8L("No wiki page for this action")},
|
||||
{"sd_show_details", _u8L("Show details")},
|
||||
|
||||
@@ -1216,7 +1216,7 @@ void PrintingTaskPanel::on_stage_clicked(wxMouseEvent &event)
|
||||
|
||||
if (obj && obj->stage_curr == 58) {
|
||||
wxWindow *top = wxGetTopLevelParent(this);
|
||||
ThermalPreconditioningDialog m_thermal_dialog(top ? top : this, obj->get_dev_id() , "Calculating...");
|
||||
ThermalPreconditioningDialog m_thermal_dialog(top ? top : this, obj->get_dev_id() , _L("Calculating..."));
|
||||
m_thermal_dialog.ShowModal();
|
||||
}
|
||||
|
||||
|
||||
@@ -1228,7 +1228,7 @@ void SyncAmsInfoDialog::sync_ams_mapping_result(std::vector<FilamentInfo> &resul
|
||||
if (result.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "ams_mapping result is empty";
|
||||
for (auto it = m_materialList.begin(); it != m_materialList.end(); it++) {
|
||||
wxString ams_id = "Ext";
|
||||
wxString ams_id = _L("Ext");
|
||||
wxColour ams_col = wxColour(0xCE, 0xCE, 0xCE);
|
||||
it->second->item->set_ams_info(ams_col, ams_id, true); // sync_ams_mapping_result
|
||||
}
|
||||
@@ -1248,7 +1248,7 @@ void SyncAmsInfoDialog::sync_ams_mapping_result(std::vector<FilamentInfo> &resul
|
||||
wxColour ams_col;
|
||||
|
||||
if (f->tray_id == VIRTUAL_TRAY_MAIN_ID || f->tray_id == VIRTUAL_TRAY_DEPUTY_ID) {
|
||||
ams_id = "Ext";
|
||||
ams_id = _L("Ext");
|
||||
}
|
||||
|
||||
else if (f->tray_id >= 0) {
|
||||
@@ -1567,13 +1567,13 @@ bool SyncAmsInfoDialog::is_nozzle_type_match(DevExtderSystem data, wxString &err
|
||||
if (nozzle_volume_type_opt) {
|
||||
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType) (nozzle_volume_type_opt->get_at(used_extruders[i]));
|
||||
if (nozzle_volume_type == NozzleVolumeType::nvtStandard) {
|
||||
used_extruders_flow[used_extruders[i]] = "Standard";
|
||||
used_extruders_flow[used_extruders[i]] = L("Standard");
|
||||
} else if (nozzle_volume_type == NozzleVolumeType::nvtTPUHighFlow) {
|
||||
used_extruders_flow[used_extruders[i]] = "TPU High Flow";
|
||||
used_extruders_flow[used_extruders[i]] = L("TPU High Flow");
|
||||
} else if (nozzle_volume_type == NozzleVolumeType::nvtE3DHighFlow) {
|
||||
used_extruders_flow[used_extruders[i]] = "E3D High Flow";
|
||||
used_extruders_flow[used_extruders[i]] = L("E3D High Flow");
|
||||
} else {
|
||||
used_extruders_flow[used_extruders[i]] = "High Flow";
|
||||
used_extruders_flow[used_extruders[i]] = L("High Flow");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1584,13 +1584,13 @@ bool SyncAmsInfoDialog::is_nozzle_type_match(DevExtderSystem data, wxString &err
|
||||
std::vector<std::string> flow_type_of_machine;
|
||||
for (auto it = data.GetExtruders().begin(); it != data.GetExtruders().end(); it++) {
|
||||
if (it->GetNozzleFlowType() == NozzleFlowType::H_FLOW) {
|
||||
flow_type_of_machine.push_back("High Flow");
|
||||
flow_type_of_machine.push_back(L("High Flow"));
|
||||
} else if (it->GetNozzleFlowType() == NozzleFlowType::S_FLOW) {
|
||||
flow_type_of_machine.push_back("Standard");
|
||||
flow_type_of_machine.push_back(L("Standard"));
|
||||
} else if (it->GetNozzleFlowType() == NozzleFlowType::U_FLOW) {
|
||||
flow_type_of_machine.push_back("TPU High Flow");
|
||||
flow_type_of_machine.push_back(L("TPU High Flow"));
|
||||
} else if (it->GetNozzleFlowType() == NozzleFlowType::E_FLOW) {
|
||||
flow_type_of_machine.push_back("E3D High Flow");
|
||||
flow_type_of_machine.push_back(L("E3D High Flow"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1612,7 +1612,7 @@ bool SyncAmsInfoDialog::is_nozzle_type_match(DevExtderSystem data, wxString &err
|
||||
error_message = wxString::Format(_L("The nozzle flow setting of %s(%s) doesn't match with the slicing file(%s). "
|
||||
"Please make sure the nozzle installed matches with settings in printer, "
|
||||
"then set the corresponding printer preset while slicing."),
|
||||
pos, flow_type_of_machine[target_machine_nozzle_id], used_extruders_flow[it->first]);
|
||||
pos, _L(flow_type_of_machine[target_machine_nozzle_id]), _L(used_extruders_flow[it->first]));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2063,7 +2063,7 @@ void SyncAmsInfoDialog::on_refresh(wxCommandEvent &event)
|
||||
void SyncAmsInfoDialog::on_set_finish_mapping(wxCommandEvent &evt)
|
||||
{
|
||||
auto selection_data = evt.GetString();
|
||||
auto selection_data_arr = wxSplit(selection_data.ToStdString(), '|');
|
||||
auto selection_data_arr = wxSplit(selection_data, '|');
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "The ams mapping selection result: data is " << selection_data;
|
||||
|
||||
|
||||
@@ -2663,7 +2663,8 @@ void Tab::update_preset_description_line()
|
||||
{
|
||||
description_line += "\n\n" + _(L("Additional information:")) + "\n";
|
||||
description_line += "\t" + _(L("vendor")) + ": " + (m_type == Slic3r::Preset::TYPE_PRINTER ? "\n\t\t" : "") + parent->vendor->name +
|
||||
", ver: " + parent->vendor->config_version.to_string();
|
||||
// TRN Short for "version"
|
||||
", " + _L("ver") + ": " + parent->vendor->config_version.to_string();
|
||||
if (m_type == Slic3r::Preset::TYPE_PRINTER) {
|
||||
const std::string &printer_model = preset.config.opt_string("printer_model");
|
||||
if (! printer_model.empty())
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/log/trivial.hpp>
|
||||
@@ -101,7 +102,7 @@ TaskStateInfo::TaskStateInfo(PrintParams param)
|
||||
//wxCommandEvent event(EVT_MULTI_SEND_LIMIT);
|
||||
//wxPostEvent(this, event);
|
||||
GUI::wxGetApp().mainframe->CallAfter([]() {
|
||||
GUI::wxGetApp().show_dialog("The printing task exceeds the limit, supporting a maximum of 6 printers.");
|
||||
GUI::wxGetApp().show_dialog(_L("The printing task exceeds the limit, supporting a maximum of 6 printers."));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ void TerminalDialog::resolve_and_run(const std::string& cmd)
|
||||
if (m_runner->is_running()) {
|
||||
nlohmann::json err;
|
||||
err["command"] = "process_error";
|
||||
err["message"] = "A command is already running.";
|
||||
err["message"] = _u8L("A command is already running.");
|
||||
call_web_handler(err);
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ void TerminalDialog::resolve_and_run(const std::string& cmd)
|
||||
if (consume_command_prefix(cmd, "python", arg_string)) {
|
||||
const std::string python_path = PythonInterpreter::bundled_python_executable();
|
||||
if (python_path.empty()) {
|
||||
send_process_error("Bundled Python executable not found.");
|
||||
send_process_error(_u8L("Bundled Python executable not found."));
|
||||
return;
|
||||
}
|
||||
executable = python_path;
|
||||
@@ -125,13 +125,13 @@ void TerminalDialog::resolve_and_run(const std::string& cmd)
|
||||
else if (consume_command_prefix(cmd, "uv", arg_string)) {
|
||||
const std::string uv_path = PythonInterpreter::bundled_uv_path();
|
||||
if (uv_path.empty()) {
|
||||
send_process_error("uv executable not found.");
|
||||
send_process_error(_u8L("uv executable not found."));
|
||||
return;
|
||||
}
|
||||
executable = uv_path;
|
||||
}
|
||||
else {
|
||||
send_process_error("Only 'python' and 'uv' commands are supported.");
|
||||
send_process_error(_u8L("Only 'python' and 'uv' commands are supported."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ void TerminalDialog::resolve_and_run(const std::string& cmd)
|
||||
if (!started) {
|
||||
nlohmann::json err;
|
||||
err["command"] = "process_error";
|
||||
err["message"] = "Failed to start process.";
|
||||
err["message"] = _u8L("Failed to start process.");
|
||||
call_web_handler(err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "TextureImportDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "format.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "ColorDecomposeDialog.hpp"
|
||||
@@ -745,7 +746,7 @@ private:
|
||||
: wxColour(128, 128, 128);
|
||||
|
||||
wxString name_str = (idx < m_names.size()) ? filament_name_to_wx_string(m_names[idx])
|
||||
: wxString::Format("Filament %d", display_number((int)idx));
|
||||
: wxString::Format(_L("Filament %d"), display_number((int)idx));
|
||||
row->SetToolTip(name_str);
|
||||
|
||||
row->Bind(wxEVT_PAINT, [this, idx, sq, sq_r, sq_x, gap1, fil_clr, name_str, row_bg, hover_bg, name_fg](wxPaintEvent& e) {
|
||||
@@ -828,7 +829,7 @@ private:
|
||||
row->SetBackgroundColour(row_bg);
|
||||
row->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
row->SetCursor(wxCursor(wxCURSOR_HAND));
|
||||
row->SetToolTip(entry.name.empty() ? wxString::Format("Filament %d", display_number(idx)) : filament_name_to_wx_string(entry.name));
|
||||
row->SetToolTip(entry.name.empty() ? wxString::Format(_L("Filament %d"), display_number(idx)) : filament_name_to_wx_string(entry.name));
|
||||
|
||||
row->Bind(wxEVT_PAINT, [this, entry, idx, row_bg, hover_bg, name_fg](wxPaintEvent& e) {
|
||||
auto* p = static_cast<wxPanel*>(e.GetEventObject());
|
||||
@@ -1790,7 +1791,7 @@ TextureImportDialog::TextureImportDialog(
|
||||
entry.dialog_index = (int)i;
|
||||
entry.color_hex = texture_normalize_color_hex(entry.color_hex);
|
||||
if (entry.name.empty())
|
||||
entry.name = "Filament " + std::to_string(i + 1);
|
||||
entry.name = GUI::format(_u8L("Filament %d"), i + 1);
|
||||
m_filament_color_strs.push_back(entry.color_hex);
|
||||
m_filament_names.push_back(entry.name);
|
||||
m_filament_colors_rgba.push_back(parse_color_string(entry.color_hex));
|
||||
@@ -2585,7 +2586,7 @@ void TextureImportDialog::on_computation_complete(wxCommandEvent&)
|
||||
m_filament_entries[i].color_hex = i < m_filament_color_strs.size() ?
|
||||
texture_normalize_color_hex(m_filament_color_strs[i]) : "#808080";
|
||||
m_filament_entries[i].name = i < m_filament_names.size() ?
|
||||
m_filament_names[i] : "Filament " + std::to_string(i + 1);
|
||||
m_filament_names[i] : GUI::format(_u8L("Filament %d"), i + 1);
|
||||
}
|
||||
m_new_filament_colors.clear();
|
||||
m_new_filament_preset_names.clear();
|
||||
@@ -2988,7 +2989,7 @@ void TextureImportDialog::compact_used_virtual_filaments()
|
||||
for (size_t i = 0; i < existing_count; ++i) {
|
||||
compact_colors.push_back(old_colors[i]);
|
||||
compact_color_strs.push_back(i < old_color_strs.size() ? old_color_strs[i] : "");
|
||||
compact_names.push_back(i < old_names.size() ? old_names[i] : "Filament " + std::to_string(i + 1));
|
||||
compact_names.push_back(i < old_names.size() ? old_names[i] : GUI::format(_u8L("Filament %d"), i + 1));
|
||||
TextureFilamentEntry entry = i < old_entries.size() ? old_entries[i] : TextureFilamentEntry{};
|
||||
entry.dialog_index = (int)i;
|
||||
entry.color_hex = texture_normalize_color_hex(compact_color_strs.back());
|
||||
@@ -3514,7 +3515,7 @@ void TextureImportDialog::show_filament_popup(size_t row_index)
|
||||
if (m_mapping_rows[row_index].target_panel) {
|
||||
wxString label = (idx >= 0 && idx < (int)m_filament_names.size())
|
||||
? filament_name_to_wx_string(m_filament_names[idx])
|
||||
: wxString::Format("Filament %d", display_number(idx));
|
||||
: wxString::Format(_L("Filament %d"), display_number(idx));
|
||||
m_mapping_rows[row_index].target_panel->SetToolTip(label);
|
||||
m_mapping_rows[row_index].target_panel->Refresh();
|
||||
}
|
||||
@@ -3663,7 +3664,7 @@ void TextureImportDialog::do_auto_match()
|
||||
// Match clusters to closest existing filaments
|
||||
std::vector<std::string> names;
|
||||
for (size_t i = 0; i < m_existing_filament_count; ++i)
|
||||
names.push_back(m_filament_names.size() > i ? m_filament_names[i] : "Filament " + std::to_string(i + 1));
|
||||
names.push_back(m_filament_names.size() > i ? m_filament_names[i] : GUI::format(_u8L("Filament %d"), i + 1));
|
||||
|
||||
std::vector<std::array<float, 4>> existing_filament_colors(
|
||||
m_filament_colors_rgba.begin(),
|
||||
@@ -3760,7 +3761,7 @@ void TextureImportDialog::rebuild_mapping_rows()
|
||||
auto get_filament_label = [this, display_number](int idx) -> wxString {
|
||||
if (idx >= 0 && idx < (int)m_filament_names.size())
|
||||
return filament_name_to_wx_string(m_filament_names[idx]);
|
||||
return wxString::Format("Filament %d", display_number(idx));
|
||||
return wxString::Format(_L("Filament %d"), display_number(idx));
|
||||
};
|
||||
|
||||
const wxColour dash_clr = StateColor::darkModeColorFor(wxColour("#ACACAC"));
|
||||
|
||||
@@ -1249,7 +1249,7 @@ bool TroubleshootDialog::ExportAsJson(const wxString& json_data, const wxString&
|
||||
|
||||
wxFileDialog dialog(this, _L("Choose where to save the exported JSON file"), defaultPath,
|
||||
export_name.IsEmpty() ? "export.json" : export_name + ".json",
|
||||
"JSON files (*.json)|*.json",
|
||||
_L("JSON files (*.json)|*.json"),
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
|
||||
);
|
||||
|
||||
|
||||
@@ -1928,7 +1928,7 @@ UVEditorPanel::UVEditorPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY)
|
||||
"texture_displacement_distortion" };
|
||||
const wxString bg_tips[3] = { _L("Height map - show the layer's texture under the islands"),
|
||||
_L("Checker - a test grid; squares stay square where the unwrap does not stretch"),
|
||||
_L("Distortion - colour each island by how much the unwrap stretches it") };
|
||||
_L("Distortion - color each island by how much the unwrap stretches it") };
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
m_background[i] = new UVToolButton(this, ID_UV_BG_HEIGHT + i, bg_icons[i], wxEmptyString, bg_tips[i], true, false, 22);
|
||||
header->Add(m_background[i], 0, wxALIGN_CENTER_VERTICAL | wxLEFT, i == 0 ? gap : FromDIP(3));
|
||||
|
||||
@@ -46,8 +46,8 @@ static const std::unordered_map<wxString, wxString> ACCESSORY_DISPLAY_STR = {
|
||||
{"O2L_10B", L("Laser 10W")},
|
||||
{"O2L_40B", L("Laser 40W")},
|
||||
{"O2L_PCM", L("Cutting Module")},
|
||||
{"O2L_ACM", "Active Cutting Module"},
|
||||
{"O2L_UCM", "Ultrasonic Cutting Module"},
|
||||
{"O2L_ACM", L("Active Cutting Module")},
|
||||
{"O2L_UCM", L("Ultrasonic Cutting Module")},
|
||||
{"O2L-AFP", L("Auto Fire Extinguishing System")},
|
||||
{"O2L-FTS", L("Filament Track Switch")},
|
||||
};
|
||||
@@ -976,7 +976,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj)
|
||||
wxString result = it->second.name.substr(0, pos);
|
||||
result.MakeUpper();
|
||||
if (auto str_it = ACCESSORY_DISPLAY_STR.find(result); str_it != ACCESSORY_DISPLAY_STR.end())
|
||||
result = str_it->second;
|
||||
result = _L(str_it->second);
|
||||
ams_device_name = result + "-%s";
|
||||
}
|
||||
|
||||
|
||||
@@ -617,7 +617,7 @@ void GuideFrame::OnScriptMessage(wxWebViewEvent &evt)
|
||||
response["sequence_id"] = "";
|
||||
|
||||
if (!m_MainPtr->preset_updater) {
|
||||
response["error"] = "Printer update service is unavailable.";
|
||||
response["error"] = _u8L("Printer update service is unavailable.");
|
||||
wxString strJS = wxString::Format("HandleStudio(%s)", response.dump(-1, ' ', true));
|
||||
wxGetApp().CallAfter([this, strJS] { RunScript(strJS); });
|
||||
} else {
|
||||
@@ -671,7 +671,7 @@ void GuideFrame::OnScriptMessage(wxWebViewEvent &evt)
|
||||
});
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Failed to check for new printers: " << e.what();
|
||||
response["error"] = "Failed to check for new printers.";
|
||||
response["error"] = _u8L("Failed to check for new printers.");
|
||||
wxString strJS = wxString::Format("HandleStudio(%s)", response.dump(-1, ' ', true));
|
||||
wxGetApp().CallAfter([this, strJS] { RunScript(strJS); });
|
||||
}
|
||||
|
||||
@@ -974,7 +974,7 @@ void WebViewPanel::OnError(wxWebViewEvent& evt)
|
||||
wxLogMessage("%s", "Error; url='" + evt.GetURL() + "', error='" + category + " (" + evt.GetString() + ")'");
|
||||
|
||||
// Show the info bar with an error
|
||||
m_info->ShowMessage(_L("An error occurred loading ") + evt.GetURL() + "\n" + "'" + category + "'", wxICON_ERROR);
|
||||
m_info->ShowMessage(wxString::Format(_L("An error occurred loading %s"), evt.GetURL()) + "\n" + "'" + category + "'", wxICON_ERROR);
|
||||
}
|
||||
|
||||
UpdateState();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "AMSItem.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "../I18N.hpp"
|
||||
#include "../format.hpp"
|
||||
#include "../GUI_App.hpp"
|
||||
#include "../FilamentBitmapUtils.hpp"
|
||||
#include "../Utils/WxFontUtils.hpp"
|
||||
@@ -1180,9 +1181,9 @@ void AMSLib::render_lite_text(wxDC& dc)
|
||||
}
|
||||
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY) {
|
||||
auto tsize = dc.GetMultiLineTextExtent(_L("/"));
|
||||
auto tsize = dc.GetMultiLineTextExtent("/");
|
||||
auto pot = wxPoint((libsize.x - tsize.x) / 2 + FromDIP(2), (libsize.y - tsize.y) / 2 + FromDIP(3));
|
||||
dc.DrawText(_L("/"), pot);
|
||||
dc.DrawText("/", pot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4055,7 +4056,7 @@ void FeedDirectionDialog::OnRadioClicked(wxCommandEvent& evt)
|
||||
m_extruderImage->setExtruderUsed("left");
|
||||
m_load_extruder_id = 1;
|
||||
{
|
||||
SetTitle(wxString::Format(_L("Load %s to ") + _L(DevPrinterConfigUtil::get_toolhead_display_name(m_printer_type, DEPUTY_EXTRUDER_ID, ToolHeadComponent::Extruder, ToolHeadNameCase::LowerCase)), m_filament_id));
|
||||
SetTitle(format_wxstr(_L("Load %1% to %2%"), m_filament_id, _L(DevPrinterConfigUtil::get_toolhead_display_name(m_printer_type, DEPUTY_EXTRUDER_ID, ToolHeadComponent::Extruder, ToolHeadNameCase::LowerCase))));
|
||||
}
|
||||
}
|
||||
else if (clicked == m_rightRadio)
|
||||
@@ -4064,7 +4065,7 @@ void FeedDirectionDialog::OnRadioClicked(wxCommandEvent& evt)
|
||||
m_extruderImage->setExtruderUsed("right");
|
||||
m_load_extruder_id = 0;
|
||||
{
|
||||
SetTitle(wxString::Format(_L("Load %s to ") + _L(DevPrinterConfigUtil::get_toolhead_display_name(m_printer_type, MAIN_EXTRUDER_ID, ToolHeadComponent::Extruder, ToolHeadNameCase::LowerCase)), m_filament_id));
|
||||
SetTitle(format_wxstr(_L("Load %1% to %2%"), m_filament_id, _L(DevPrinterConfigUtil::get_toolhead_display_name(m_printer_type, MAIN_EXTRUDER_ID, ToolHeadComponent::Extruder, ToolHeadNameCase::LowerCase))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4124,7 +4125,7 @@ void FeedDirectionDialog::SetExtruderMapping(MachineObject* obj,
|
||||
return;
|
||||
|
||||
m_filament_id = filamentID;
|
||||
SetTitle(wxString::Format(_L("Load %s to "), filamentID));
|
||||
SetTitle(wxString::Format(_L("Load %s"), filamentID));
|
||||
|
||||
std::vector<wxString> extruderMapping(extruderSlots.size());
|
||||
for (size_t i = 0; i < extruderSlots.size(); ++i) {
|
||||
|
||||
@@ -147,11 +147,8 @@ void FilamentLoad::SetFilamentStep(FilamentStep item_idx, FilamentStepType f_typ
|
||||
}
|
||||
}
|
||||
|
||||
wxString slot_info = L"AMS-";
|
||||
slot_info = slot_info + std::to_string(m_ams_id);
|
||||
slot_info = slot_info + L'-';
|
||||
slot_info = slot_info + std::to_string(m_slot_id);
|
||||
slot_info = slot_info + L" Slot";
|
||||
// TRN AMS unit number, then slot number
|
||||
wxString slot_info = wxString::Format(_L("AMS-%d-%d Slot"), m_ams_id, m_slot_id);
|
||||
step_control->SetSlotInformation(slot_info);
|
||||
}
|
||||
|
||||
|
||||
@@ -526,7 +526,7 @@ void ProgressDialog::EnsureActiveEventLoopExists()
|
||||
wxStaticText *ProgressDialog::CreateLabel(const wxString &text, wxSizer *sizer)
|
||||
{
|
||||
wxStaticText *label = new wxStaticText(this, wxID_ANY, text);
|
||||
wxStaticText *value = new wxStaticText(this, wxID_ANY, wxGetTranslation("unknown"));
|
||||
wxStaticText *value = new wxStaticText(this, wxID_ANY, _L("unknown"));
|
||||
|
||||
// Match the message label's look so the times theme with the rest of the
|
||||
// dialog: PROGRESSDIALOG_GREY_700 is a key in the dark-mode colour map, so
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "wx/progdlg.h"
|
||||
#include "wx/weakref.h"
|
||||
#include "wx/simplebook.h"
|
||||
#include "../I18N.hpp"
|
||||
#include <wx/dlimpexp.h>
|
||||
#include <wx/string.h>
|
||||
#include <cstddef>
|
||||
@@ -105,9 +106,9 @@ protected:
|
||||
void SetMaximum(int maximum);
|
||||
// Return the labels to use for showing the elapsed/estimated/remaining
|
||||
// times respectively.
|
||||
static wxString GetElapsedLabel() { return wxGetTranslation("Elapsed time:"); }
|
||||
static wxString GetEstimatedLabel() { return wxGetTranslation("Estimated time:"); }
|
||||
static wxString GetRemainingLabel() { return wxGetTranslation("Remaining time:"); }
|
||||
static wxString GetElapsedLabel() { return _L("Elapsed time:"); }
|
||||
static wxString GetEstimatedLabel() { return _L("Estimated time:"); }
|
||||
static wxString GetRemainingLabel() { return _L("Remaining time:"); }
|
||||
|
||||
// Similar to wxWindow::HasFlag() but tests for a presence of a wxPD_XXX
|
||||
// flag in our (separate) flags instead of using m_windowStyle.
|
||||
|
||||
@@ -366,7 +366,8 @@ SideTools::SideTools(wxWindow *parent, wxWindowID id, const wxPoint &pos, const
|
||||
sizer_error_code->Add(m_st_txt_error_code, 0, wxALL, 0);
|
||||
|
||||
|
||||
auto st_title_error_desc = new wxStaticText(m_side_error_panel, wxID_ANY, wxT("desc"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
// TRN Short for "description" of a connection error
|
||||
auto st_title_error_desc = new wxStaticText(m_side_error_panel, wxID_ANY, _L("desc"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
auto st_title_error_desc_doc = new wxStaticText(m_side_error_panel, wxID_ANY, ": ");
|
||||
m_st_txt_error_desc = new Label(m_side_error_panel, wxEmptyString, LB_AUTO_WRAP);
|
||||
st_title_error_desc->SetForegroundColour(0x909090);
|
||||
@@ -383,7 +384,8 @@ SideTools::SideTools(wxWindow *parent, wxWindowID id, const wxPoint &pos, const
|
||||
sizer_error_desc->Add(st_title_error_desc_doc, 0, wxALL, 0);
|
||||
sizer_error_desc->Add(m_st_txt_error_desc, 0, wxALL, 0);
|
||||
|
||||
auto st_title_extra_info = new wxStaticText(m_side_error_panel, wxID_ANY, wxT("info"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
// TRN Short for "additional information" about a connection error
|
||||
auto st_title_extra_info = new wxStaticText(m_side_error_panel, wxID_ANY, _L("info"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
auto st_title_extra_info_doc = new wxStaticText(m_side_error_panel, wxID_ANY, ": ");
|
||||
m_st_txt_extra_info = new Label(m_side_error_panel, wxEmptyString, LB_AUTO_WRAP);
|
||||
st_title_extra_info->SetForegroundColour(0x909090);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "StepCtrl.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "../I18N.hpp"
|
||||
|
||||
#include <wx/anybutton.h>
|
||||
#include <wx/checklst.h>
|
||||
@@ -423,8 +424,9 @@ void FilamentStepIndicator::doRender(wxDC& dc)
|
||||
dc.SetTextForeground(wxColour(0, 150, 136));
|
||||
int circleX = 20;
|
||||
int circleY = 20;
|
||||
wxSize sz = dc.GetTextExtent(L"Loading");
|
||||
dc.DrawText(L"Loading", circleX, circleY);
|
||||
const wxString loading = _L("Loading");
|
||||
wxSize sz = dc.GetTextExtent(loading);
|
||||
dc.DrawText(loading, circleX, circleY);
|
||||
|
||||
dc.SetFont(::Label::Body_13);
|
||||
|
||||
|
||||
@@ -480,7 +480,8 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat
|
||||
if(!ti->GetTextCtrl()->GetValue().ToULong(&t))
|
||||
return;
|
||||
if(t> 500 || t < 155){
|
||||
MessageDialog msg_dlg(nullptr, wxString::Format(L"Supported range: 170%s - 500%s",
|
||||
// TRN %s is the temperature unit
|
||||
MessageDialog msg_dlg(nullptr, wxString::Format(_L("Supported range: 170%s - 500%s"),
|
||||
_L("\u2103" /* °C */), _L("\u2103" /* °C */)),
|
||||
wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user