Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb5b9a77b9 | ||
|
|
c1e6de7e4e | ||
|
|
1496906939 | ||
|
|
6b8df05d40 | ||
|
|
47f1f2de5f | ||
|
|
5dcf89d094 | ||
|
|
318f6178ab | ||
|
|
37dbad5752 |
@@ -38,7 +38,7 @@ jobs:
|
|||||||
- name: Look for changed C++ files
|
- name: Look for changed C++ files
|
||||||
id: changes
|
id: changes
|
||||||
run: |
|
run: |
|
||||||
if git diff --name-only HEAD^1 -- src tests | grep -qE '\.(cpp|cc|cxx|hpp|h|hxx)$'; then
|
if git -c core.quotePath=false diff --name-only HEAD^1 -- src tests | grep -qE '\.(cpp|cc|cxx|hpp|h|hxx)$'; then
|
||||||
echo "cpp=true" >> "$GITHUB_OUTPUT"
|
echo "cpp=true" >> "$GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
echo "No C++ changes under src/ or tests/."
|
echo "No C++ changes under src/ or tests/."
|
||||||
|
|||||||
@@ -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.
|
- 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.
|
- 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.
|
- 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.
|
- Don't reflow or re-wrap unrelated entries — keep the diff limited to the strings you changed.
|
||||||
|
|
||||||
### Verifying
|
### Verifying
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.h
|
|||||||
src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp
|
src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp
|
||||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.h
|
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.h
|
||||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRack.cpp
|
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.h
|
||||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp
|
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleRackUpdate.cpp
|
||||||
src/slic3r/GUI/DeviceTab/wgtDeviceNozzleSelect.h
|
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/Gizmos/GLGizmoSketch.cpp
|
||||||
src/slic3r/GUI/KeyChord.cpp
|
src/slic3r/GUI/KeyChord.cpp
|
||||||
src/slic3r/GUI/Shortcuts.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
|
||||||
|
|||||||
@@ -1,4 +1 @@
|
|||||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10,0h0c5.52,0,10,4.48,10,10h0c0,5.52-4.48,10-10,10h0C4.48,20,0,15.52,0,10h0C0,4.48,4.48,0,10,0Z" style="fill:#009688; isolation:isolate; opacity:.5;"/><polyline points="5.5 10.5 8.62 13.38 14.5 7.5" style="fill:none; stroke:#fff; stroke-linecap:round; stroke-linejoin:round;"/></svg>
|
||||||
<rect width="20" height="20" rx="10" fill="#00AF42" fill-opacity="0.2"/>
|
|
||||||
<path d="M14.0828 8.14395L9.08284 13.144C9.0393 13.1877 8.98755 13.2223 8.93057 13.246C8.87359 13.2696 8.81251 13.2818 8.75081 13.2818C8.68912 13.2818 8.62803 13.2696 8.57105 13.246C8.51408 13.2223 8.46233 13.1877 8.41878 13.144L6.23128 10.9565C6.18768 10.9129 6.15309 10.8611 6.12949 10.8041C6.1059 10.7471 6.09375 10.6861 6.09375 10.6244C6.09375 10.5628 6.1059 10.5017 6.12949 10.4447C6.15309 10.3878 6.18768 10.336 6.23128 10.2924C6.27488 10.2488 6.32665 10.2142 6.38362 10.1906C6.44059 10.167 6.50165 10.1549 6.56331 10.1549C6.62498 10.1549 6.68604 10.167 6.74301 10.1906C6.79998 10.2142 6.85174 10.2488 6.89534 10.2924L8.7512 12.1482L13.4196 7.48067C13.5076 7.39261 13.6271 7.34314 13.7516 7.34314C13.8761 7.34314 13.9956 7.39261 14.0836 7.48067C14.1717 7.56873 14.2212 7.68817 14.2212 7.8127C14.2212 7.93724 14.1717 8.05667 14.0836 8.14473L14.0828 8.14395Z" fill="#00AF42" stroke="#00AF42" stroke-width="0.833333"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 398 B |
@@ -1,3 +1 @@
|
|||||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M4.86,13.27L14.86,5.02c.37-.3.9-.3,1.27,0l10,8.24c.23.19.36.47.36.77v12.53c0,.55-.45,1-1,1h-5c-.55,0-1-.45-1-1v-7c0-.55-.45-1-1-1h-6c-.55,0-1,.45-1,1v7c0,.55-.45,1-1,1h-5c-.55,0-1-.45-1-1v-12.53c0-.3.13-.58.36-.77Z" style="fill:#009688; isolation:isolate; opacity:.5;"/><path d="M4.86,13.27L14.86,5.02c.37-.3.9-.3,1.27,0l10,8.24c.23.19.36.47.36.77v12.53c0,.55-.45,1-1,1h-5c-.55,0-1-.45-1-1v-7c0-.55-.45-1-1-1h-6c-.55,0-1,.45-1,1v7c0,.55-.45,1-1,1h-5c-.55,0-1-.45-1-1v-12.53c0-.3.13-.58.36-.77Z" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/></svg>
|
||||||
<path d="M28.0424 15.4264C28.6059 15.3044 28.7112 14.8962 28.2789 14.5156L16.5815 4.28496C16.1473 3.90625 15.438 3.9044 15.0038 4.28311L3.26759 14.5156C2.83346 14.8943 2.93876 15.3026 3.5022 15.4245L4.90989 15.7275C5.47333 15.8494 5.93332 16.4202 5.93332 16.9966V26.5216C5.93332 27.0979 6.4044 27.569 6.98077 27.569H11.9354C12.5117 27.569 12.9828 27.0979 12.9828 26.5216V21.9512C12.9828 21.3748 13.4539 20.9038 14.0303 20.9038H17.3721C17.9485 20.9038 18.4196 21.3748 18.4196 21.9512V26.5216C18.4196 27.0979 18.8907 27.569 19.467 27.569H24.5657C25.1421 27.569 25.6132 27.0979 25.6132 26.5216V16.9966C25.6132 16.4202 26.0732 15.8494 26.6366 15.7293L28.0424 15.4264Z" fill="#00AE42" fill-opacity="0.2" stroke="#00AE42" stroke-width="0.784708" stroke-miterlimit="10" stroke-linecap="round"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 891 B After Width: | Height: | Size: 696 B |
@@ -1,4 +1 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M3.39,15.61C-2,6.97,4.47.5,18.5.5c0,14.03-6.47,20.5-15.11,15.11Z" style="fill:#009688; isolation:isolate; opacity:.5;"/><path d="M3.39,15.61C-2,6.97,4.47.5,18.5.5c0,14.03-6.47,20.5-15.11,15.11Z" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round; stroke-width:1.08px;"/><line x1=".5" y1="18.5" x2="15.5" y2="3.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/><line x1="5.5" y1="13.5" x2="10.5" y2="14.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/><line x1="4.5" y1="8.5" x2="5.5" y2="13.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/><line x1="7.5" y1="5.5" x2="8.5" y2="10.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/><line x1="11.5" y1="3.5" x2="12.5" y2="6.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/><line x1="8.5" y1="10.5" x2="13.5" y2="11.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/><line x1="12.5" y1="6.5" x2="15.5" y2="7.5" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/></svg>
|
||||||
<path opacity="0.2" d="M5.98183 18.0178C1.49214 10.5356 7.48183 3.05343 20.1981 3.80156C20.9462 16.5216 13.464 22.5075 5.98183 18.0178Z" fill="#00AF42"/>
|
|
||||||
<path d="M20.9489 3.75655C20.9381 3.57307 20.8604 3.39991 20.7305 3.26994C20.6005 3.13998 20.4273 3.06226 20.2439 3.05155C13.1067 2.63249 7.38979 4.78124 4.95229 8.81249C4.10738 10.1915 3.69103 11.7903 3.75604 13.4062C3.80948 14.8987 4.24448 16.4062 5.04885 17.8922L3.21979 19.7203C3.07906 19.861 3 20.0519 3 20.2509C3 20.4499 3.07906 20.6408 3.21979 20.7815C3.36052 20.9223 3.55139 21.0013 3.75042 21.0013C3.94944 21.0013 4.14031 20.9223 4.28104 20.7815L6.10917 18.9525C7.59417 19.7559 9.1026 20.1909 10.5942 20.2444C10.6985 20.2481 10.8026 20.25 10.9064 20.25C12.4174 20.254 13.8997 19.8379 15.1879 19.0481C19.2192 16.6106 21.3689 10.8947 20.9489 3.75655ZM14.4145 17.7656C12.2817 19.0575 9.75698 19.0781 7.22292 17.8378L15.532 9.52967C15.6017 9.45999 15.6569 9.37727 15.6947 9.28622C15.7324 9.19518 15.7518 9.0976 15.7518 8.99905C15.7518 8.9005 15.7324 8.80292 15.6947 8.71188C15.6569 8.62083 15.6017 8.53811 15.532 8.46842C15.4623 8.39874 15.3796 8.34347 15.2885 8.30575C15.1975 8.26804 15.0999 8.24863 15.0014 8.24863C14.9028 8.24863 14.8052 8.26804 14.7142 8.30575C14.6231 8.34347 14.5404 8.39874 14.4707 8.46842L6.1626 16.7812C4.92604 14.25 4.94385 11.7187 6.23479 9.58967C8.30573 6.17061 13.2285 4.29842 19.4826 4.52155C19.7067 10.7709 17.8335 15.6947 14.4145 17.7656Z" fill="#00AF42"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -2,8 +2,8 @@
|
|||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9.51613C0 9.78336 0.237026 10 0.529412 10C3.55073 10 6 7.76142 6 5C6 2.23858 3.55073 0 0.529412 0C0.237026 0 0 0.216637 0 0.483871C0 0.751105 0.237026 0.967742 0.529412 0.967742C2.96596 0.967742 4.94118 2.77305 4.94118 5C4.94118 7.22695 2.96596 9.03226 0.529412 9.03226C0.237026 9.03226 0 9.24889 0 9.51613Z" fill="url(#paint0_linear_46765_16184)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9.51613C0 9.78336 0.237026 10 0.529412 10C3.55073 10 6 7.76142 6 5C6 2.23858 3.55073 0 0.529412 0C0.237026 0 0 0.216637 0 0.483871C0 0.751105 0.237026 0.967742 0.529412 0.967742C2.96596 0.967742 4.94118 2.77305 4.94118 5C4.94118 7.22695 2.96596 9.03226 0.529412 9.03226C0.237026 9.03226 0 9.24889 0 9.51613Z" fill="url(#paint0_linear_46765_16184)"/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0_linear_46765_16184" x1="0.622561" y1="9.52006" x2="5.48816e-08" y2="0.52972" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear_46765_16184" x1="0.622561" y1="9.52006" x2="5.48816e-08" y2="0.52972" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#00AE42"/>
|
<stop stop-color="#009688"/>
|
||||||
<stop offset="1" stop-color="#00AE42" stop-opacity="0"/>
|
<stop offset="1" stop-color="#009688" stop-opacity="0"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 758 B After Width: | Height: | Size: 758 B |
@@ -2,8 +2,8 @@
|
|||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9.51613C0 9.78336 0.237026 10 0.529412 10C3.55073 10 6 7.76142 6 5C6 2.23858 3.55073 0 0.529412 0C0.237026 0 0 0.216637 0 0.483871C0 0.751105 0.237026 0.967742 0.529412 0.967742C2.96596 0.967742 4.94118 2.77305 4.94118 5C4.94118 7.22695 2.96596 9.03226 0.529412 9.03226C0.237026 9.03226 0 9.24889 0 9.51613Z" fill="url(#paint0_linear_46765_16184)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9.51613C0 9.78336 0.237026 10 0.529412 10C3.55073 10 6 7.76142 6 5C6 2.23858 3.55073 0 0.529412 0C0.237026 0 0 0.216637 0 0.483871C0 0.751105 0.237026 0.967742 0.529412 0.967742C2.96596 0.967742 4.94118 2.77305 4.94118 5C4.94118 7.22695 2.96596 9.03226 0.529412 9.03226C0.237026 9.03226 0 9.24889 0 9.51613Z" fill="url(#paint0_linear_46765_16184)"/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0_linear_46765_16184" x1="0.622561" y1="9.52006" x2="0" y2="0.52972" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear_46765_16184" x1="0.622561" y1="9.52006" x2="0" y2="0.52972" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#00AE42"/>
|
<stop stop-color="#009688"/>
|
||||||
<stop offset="1" stop-color="#00AE42" stop-opacity="0"/>
|
<stop offset="1" stop-color="#009688" stop-opacity="0"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 748 B After Width: | Height: | Size: 748 B |
@@ -2,8 +2,8 @@
|
|||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.483871 0C0.216637 0 0 0.237026 0 0.529412C0 3.55073 2.23858 6 5 6C7.76142 6 10 3.55073 10 0.529412C10 0.237026 9.78336 0 9.51613 0C9.24889 0 9.03226 0.237026 9.03226 0.529412C9.03226 2.96596 7.22695 4.94118 5 4.94118C2.77305 4.94118 0.967742 2.96596 0.967742 0.529412C0.967742 0.237026 0.751105 0 0.483871 0Z" transform="translate(-2, 2)" fill="url(#paint0_linear_46765_16184)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.483871 0C0.216637 0 0 0.237026 0 0.529412C0 3.55073 2.23858 6 5 6C7.76142 6 10 3.55073 10 0.529412C10 0.237026 9.78336 0 9.51613 0C9.24889 0 9.03226 0.237026 9.03226 0.529412C9.03226 2.96596 7.22695 4.94118 5 4.94118C2.77305 4.94118 0.967742 2.96596 0.967742 0.529412C0.967742 0.237026 0.751105 0 0.483871 0Z" transform="translate(-2, 2)" fill="url(#paint0_linear_46765_16184)"/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0_linear_46765_16184" x1="0.52972" y1="0.622561" x2="9.52006" y2="0.622561" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear_46765_16184" x1="0.52972" y1="0.622561" x2="9.52006" y2="0.622561" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#00AE42"/>
|
<stop stop-color="#009688"/>
|
||||||
<stop offset="1" stop-color="#00AE42" stop-opacity="0"/>
|
<stop offset="1" stop-color="#009688" stop-opacity="0"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 785 B After Width: | Height: | Size: 785 B |
@@ -2,8 +2,8 @@
|
|||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 0.483871C6 0.216637 5.76297 0 5.47059 0C2.44927 0 0 2.23858 0 5C0 7.76142 2.44927 10 5.47059 10C5.76297 10 6 9.78336 6 9.51613C6 9.24889 5.76297 9.03226 5.47059 9.03226C3.03404 9.03226 1.05882 7.22695 1.05882 5C1.05882 2.77305 3.03404 0.967742 5.47059 0.967742C5.76297 0.967742 6 0.751105 6 0.483871Z" fill="url(#paint0_linear_46765_16184)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 0.483871C6 0.216637 5.76297 0 5.47059 0C2.44927 0 0 2.23858 0 5C0 7.76142 2.44927 10 5.47059 10C5.76297 10 6 9.78336 6 9.51613C6 9.24889 5.76297 9.03226 5.47059 9.03226C3.03404 9.03226 1.05882 7.22695 1.05882 5C1.05882 2.77305 3.03404 0.967742 5.47059 0.967742C5.76297 0.967742 6 0.751105 6 0.483871Z" fill="url(#paint0_linear_46765_16184)"/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0_linear_46765_16184" x1="5.37744" y1="0.47994" x2="6" y2="9.47028" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear_46765_16184" x1="5.37744" y1="0.47994" x2="6" y2="9.47028" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#00AE42"/>
|
<stop stop-color="#009688"/>
|
||||||
<stop offset="1" stop-color="#00AE42" stop-opacity="0"/>
|
<stop offset="1" stop-color="#009688" stop-opacity="0"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 740 B After Width: | Height: | Size: 740 B |
@@ -2,8 +2,8 @@
|
|||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.51613 6C9.78336 6 10 5.76297 10 5.47059C10 2.44927 7.76142 0 5 0C2.23858 0 0 2.44927 0 5.47059C0 5.76297 0.216637 6 0.483871 6C0.751105 6 0.967742 5.76297 0.967742 5.47059C0.967742 3.03404 2.77305 1.05882 5 1.05882C7.22695 1.05882 9.03226 3.03404 9.03226 5.47059C9.03226 5.76297 9.24889 6 9.51613 6Z" transform="translate(-4, -2)" fill="url(#paint0_linear_46765_16184)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.51613 6C9.78336 6 10 5.76297 10 5.47059C10 2.44927 7.76142 0 5 0C2.23858 0 0 2.44927 0 5.47059C0 5.76297 0.216637 6 0.483871 6C0.751105 6 0.967742 5.76297 0.967742 5.47059C0.967742 3.03404 2.77305 1.05882 5 1.05882C7.22695 1.05882 9.03226 3.03404 9.03226 5.47059C9.03226 5.76297 9.24889 6 9.51613 6Z" transform="translate(-4, -2)" fill="url(#paint0_linear_46765_16184)"/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0_linear_46765_16184" x1="9.47028" y1="5.37744" x2="0.47994" y2="5.37744" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear_46765_16184" x1="9.47028" y1="5.37744" x2="0.47994" y2="5.37744" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#00AE42"/>
|
<stop stop-color="#009688"/>
|
||||||
<stop offset="1" stop-color="#00AE42" stop-opacity="0"/>
|
<stop offset="1" stop-color="#009688" stop-opacity="0"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 775 B After Width: | Height: | Size: 775 B |
@@ -1,4 +1 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.5.5c-.55,0-1,.45-1,1v5c0,9,8.5,12,8.5,12,0,0,8.5-3,8.5-12V1.5c0-.55-.45-1-1-1H2.5Z" style="fill:#009688; isolation:isolate; opacity:.5;"/><path d="M2.5.5c-.55,0-1,.45-1,1v5c0,9,8.5,12,8.5,12,0,0,8.5-3,8.5-12V1.5c0-.55-.45-1-1-1H2.5Z" style="fill:none; stroke:#009688; stroke-linecap:round; stroke-linejoin:round;"/></svg>
|
||||||
<path opacity="0.2" d="M20.25 5.25V10.5C20.25 19.5 12 21.75 12 21.75C12 21.75 3.75 19.5 3.75 10.5V5.25C3.75 5.05109 3.82902 4.86032 3.96967 4.71967C4.11032 4.57902 4.30109 4.5 4.5 4.5H19.5C19.6989 4.5 19.8897 4.57902 20.0303 4.71967C20.171 4.86032 20.25 5.05109 20.25 5.25Z" fill="#00AF42"/>
|
|
||||||
<path d="M19.5 3.75H4.5C4.10218 3.75 3.72064 3.90804 3.43934 4.18934C3.15804 4.47064 3 4.85218 3 5.25V10.5C3 15.4425 5.3925 18.4378 7.39969 20.0803C9.56156 21.8484 11.7122 22.4494 11.8059 22.4738C11.9348 22.5088 12.0708 22.5088 12.1997 22.4738C12.2934 22.4494 14.4413 21.8484 16.6059 20.0803C18.6075 18.4378 21 15.4425 21 10.5V5.25C21 4.85218 20.842 4.47064 20.5607 4.18934C20.2794 3.90804 19.8978 3.75 19.5 3.75ZM19.5 10.5C19.5 13.9753 18.2194 16.7962 15.6937 18.8831C14.5943 19.7885 13.344 20.493 12 20.9644C10.6736 20.5012 9.4387 19.8092 8.35125 18.9197C5.79563 16.8291 4.5 13.9969 4.5 10.5V5.25H19.5V10.5Z" fill="#00AF42"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1023 B After Width: | Height: | Size: 438 B |
@@ -416,8 +416,8 @@ function favDigitFromEvent(e) {
|
|||||||
|
|
||||||
function resultCountText(total, shown, query) {
|
function resultCountText(total, shown, query) {
|
||||||
return (query || "").trim() ?
|
return (query || "").trim() ?
|
||||||
T("sd_result_count", "Showing %s actions", shown) :
|
T("sd_result_count", "Matching actions: %s", shown) :
|
||||||
T("sd_result_count_all", "%s actions", total);
|
T("sd_result_count_all", "Actions: %s", total);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display label for a notebook tab. Trim any stray whitespace; pages added with an empty title
|
// 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;
|
var fid = payload.id;
|
||||||
if (fid && FAVS.indexOf(fid) !== -1) FAVS.splice(FAVS.indexOf(fid), 1);
|
if (fid && FAVS.indexOf(fid) !== -1) FAVS.splice(FAVS.indexOf(fid), 1);
|
||||||
render({ resize: true, keepScroll: true });
|
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) {
|
function setPinState(pin, on) {
|
||||||
pin.classList.toggle("on", on);
|
pin.classList.toggle("on", on);
|
||||||
pin.innerHTML = pinSvg(on);
|
pin.innerHTML = pinSvg(on);
|
||||||
pin.title = on ? T("sd_unpin_fav", "Unpin from favourites (%s)", shortcutCtrl() + "B") :
|
pin.title = on ? T("sd_unpin_fav", "Unpin from favorites (%s)", shortcutCtrl() + "B") :
|
||||||
T("sd_pin_fav", "Pin to favourites (%s)", shortcutCtrl() + "B");
|
T("sd_pin_fav", "Pin to favorites (%s)", shortcutCtrl() + "B");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- render ------------------------------------------------------------------
|
// ---- render ------------------------------------------------------------------
|
||||||
@@ -858,15 +858,15 @@ function renderFav() {
|
|||||||
badge.textContent = slot;
|
badge.textContent = slot;
|
||||||
// Slot "0" is the 10th favourite (Alt/Option+0).
|
// Slot "0" is the 10th favourite (Alt/Option+0).
|
||||||
var slot_num = slot === "0" ? "10" : slot;
|
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);
|
tile.appendChild(badge);
|
||||||
}
|
}
|
||||||
// Direct removal: a hover-revealed ✕ in the tile's corner. click() stops propagation so it
|
// Direct removal: a hover-revealed ✕ in the tile's corner. click() stops propagation so it
|
||||||
// unpins without activating the action.
|
// unpins without activating the action.
|
||||||
var unpin = document.createElement("button");
|
var unpin = document.createElement("button");
|
||||||
unpin.className = "fav-unpin";
|
unpin.className = "fav-unpin";
|
||||||
unpin.title = 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 favourites"));
|
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.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); };
|
unpin.onclick = function (ev) { ev.stopPropagation(); toggleFav(id); };
|
||||||
tile.appendChild(unpin);
|
tile.appendChild(unpin);
|
||||||
@@ -1170,7 +1170,7 @@ function renderTabList() {
|
|||||||
listEl.className = "dial-list";
|
listEl.className = "dial-list";
|
||||||
if (countEl) {
|
if (countEl) {
|
||||||
countEl.hidden = false;
|
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)); });
|
list.forEach(function (t, i) { listEl.appendChild(renderTabRow(t, i)); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,8 +78,9 @@ def load_table():
|
|||||||
if not line.startswith('{"'):
|
if not line.startswith('{"'):
|
||||||
continue
|
continue
|
||||||
# id, name, row, key, action, refusal, accepts, need_bodies, need_sketches, need_sheet,
|
# id, name, row, key, action, refusal, accepts, need_bodies, need_sketches, need_sheet,
|
||||||
# sketch_mode, family, ... — split on top-level commas, respecting quotes.
|
# sketch_mode, family, ... — split on top-level commas, respecting quotes and the
|
||||||
f, cur, q, esc = [], "", False, False
|
# L(...) / L_CONTEXT(...) translation markers.
|
||||||
|
f, cur, q, esc, depth = [], "", False, False, 0
|
||||||
for ch in line[1:]:
|
for ch in line[1:]:
|
||||||
if esc:
|
if esc:
|
||||||
cur += ch; esc = False; continue
|
cur += ch; esc = False; continue
|
||||||
@@ -87,16 +88,18 @@ def load_table():
|
|||||||
cur += ch; esc = True; continue
|
cur += ch; esc = True; continue
|
||||||
if ch == '"':
|
if ch == '"':
|
||||||
q = not q
|
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
|
f.append(cur.strip()); cur = ""; continue
|
||||||
if ch == "}" and not q:
|
if ch == "}" and not q and depth == 0:
|
||||||
break
|
break
|
||||||
cur += ch
|
cur += ch
|
||||||
f.append(cur.strip())
|
f.append(cur.strip())
|
||||||
if len(f) < 12:
|
if len(f) < 12:
|
||||||
continue
|
continue
|
||||||
# User-facing fields are wrapped in the L("...") gettext marker; strip it.
|
# User-facing fields are wrapped in L("...") or L_CONTEXT("...", ...); take the literal.
|
||||||
lit = lambda s: None if s == "nullptr" else re.sub(r'^L\((.*)\)$', r'\1', s).strip('"')
|
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]),
|
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),
|
"action": lit(f[4]), "accepts": int(f[6].rstrip("u"), 0),
|
||||||
"need_bodies": int(f[7]), "need_sketches": int(f[8]),
|
"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) + ")"
|
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):
|
def validate(A):
|
||||||
"""Refuse an atlas the header cannot represent, naming every fault at once.
|
"""Refuse an atlas the header cannot represent, naming every fault at once.
|
||||||
|
|
||||||
@@ -90,6 +95,9 @@ def main():
|
|||||||
"#ifndef L",
|
"#ifndef L",
|
||||||
"#define L(s) s // gettext marker, as in slic3r/GUI/I18N.hpp",
|
"#define L(s) s // gettext marker, as in slic3r/GUI/I18N.hpp",
|
||||||
"#endif",
|
"#endif",
|
||||||
|
"#ifndef L_CONTEXT",
|
||||||
|
"#define L_CONTEXT(s, context) s",
|
||||||
|
"#endif",
|
||||||
"",
|
"",
|
||||||
"namespace Slic3r { namespace GUI {",
|
"namespace Slic3r { namespace GUI {",
|
||||||
"",
|
"",
|
||||||
@@ -113,7 +121,7 @@ def main():
|
|||||||
"// nullptr -> kernel support exists, no GUI path yet (row shows disabled)",
|
"// nullptr -> kernel support exists, no GUI path yet (row shows disabled)",
|
||||||
"struct OfferVerb {",
|
"struct OfferVerb {",
|
||||||
" const char* id;",
|
" 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",
|
" int row; // index into kOfferRowNames, the ratified address — NEVER reorder",
|
||||||
" const char* key; // shortcut shown in the row, or nullptr",
|
" const char* key; // shortcut shown in the row, or nullptr",
|
||||||
" const char* action;",
|
" const char* action;",
|
||||||
@@ -170,7 +178,7 @@ def main():
|
|||||||
n = v.get("needs") or {}
|
n = v.get("needs") or {}
|
||||||
lines.append(
|
lines.append(
|
||||||
" {%s, %s, %d, %s, %s, %s, 0x%08xu, %d, %d, %s, %s, %s, %s, %s}," % (
|
" {%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")),
|
cstr(v.get("key")), cstr(v.get("action")), tstr(v.get("refusal")),
|
||||||
mask, n.get("bodies", 0), n.get("sketches", 0),
|
mask, n.get("bodies", 0), n.get("sketches", 0),
|
||||||
"true" if n.get("sheet") else "false",
|
"true" if n.get("sheet") else "false",
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ EXCLUDED_DIRS = ("src/glad/", "tests/catch2/")
|
|||||||
# Per file. A deleted include can leave hundreds of follow-on errors.
|
# Per file. A deleted include can leave hundreds of follow-on errors.
|
||||||
MAX_REPORTED = 30
|
MAX_REPORTED = 30
|
||||||
|
|
||||||
|
# Subprocess output is UTF-8 whatever the locale, which is cp1252 on Windows.
|
||||||
|
UTF8 = {"encoding": "utf-8", "errors": "replace"}
|
||||||
|
|
||||||
HUNK_RE = re.compile(r"^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@")
|
HUNK_RE = re.compile(r"^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@")
|
||||||
DIAGNOSTIC_RE = re.compile(r"^(.+?):(\d+):(\d+): (error|warning): (.*)$")
|
DIAGNOSTIC_RE = re.compile(r"^(.+?):(\d+):(\d+): (error|warning): (.*)$")
|
||||||
FIX_MESSAGE_RE = re.compile(r"^\s+Message:\s+(['\"])(.*)\1$")
|
FIX_MESSAGE_RE = re.compile(r"^\s+Message:\s+(['\"])(.*)\1$")
|
||||||
@@ -72,7 +75,8 @@ def parse_diff(diff):
|
|||||||
change = None
|
change = None
|
||||||
for line in diff.splitlines():
|
for line in diff.splitlines():
|
||||||
if line.startswith("+++ "):
|
if line.startswith("+++ "):
|
||||||
target = line[4:]
|
# git appends a tab to the header of a path that contains a space.
|
||||||
|
target = line[4:].removesuffix("\t")
|
||||||
change = changes.setdefault(target[2:], FileChange()) if target.startswith("b/") else None
|
change = changes.setdefault(target[2:], FileChange()) if target.startswith("b/") else None
|
||||||
continue
|
continue
|
||||||
if change is None:
|
if change is None:
|
||||||
@@ -98,8 +102,10 @@ def is_checked(path):
|
|||||||
|
|
||||||
def changed_files(merge_base):
|
def changed_files(merge_base):
|
||||||
# Against the working tree, so a local run covers uncommitted edits too.
|
# Against the working tree, so a local run covers uncommitted edits too.
|
||||||
diff = subprocess.run(["git", "diff", "-U0", "--no-color", "--no-ext-diff", "--diff-filter=AMR", merge_base],
|
# core.quotePath=false keeps a non-ASCII path unquoted, so parse_diff sees its b/ prefix.
|
||||||
check=True, capture_output=True, text=True).stdout
|
diff = subprocess.run(["git", "-c", "core.quotePath=false", "diff", "-U0", "--no-color", "--no-ext-diff",
|
||||||
|
"--diff-filter=AMR", merge_base],
|
||||||
|
check=True, capture_output=True, **UTF8).stdout
|
||||||
return {path: change for path, change in parse_diff(diff).items() if is_checked(path)}
|
return {path: change for path, change in parse_diff(diff).items() if is_checked(path)}
|
||||||
|
|
||||||
|
|
||||||
@@ -117,8 +123,9 @@ def run_clang_tidy(clang_tidy, build_dir, path, lines, extra_args):
|
|||||||
cmd = [clang_tidy, "-p", build_dir, "--quiet", "--export-fixes=" + fixes,
|
cmd = [clang_tidy, "-p", build_dir, "--quiet", "--export-fixes=" + fixes,
|
||||||
"--extra-arg=-Wno-unknown-warning-option", "--extra-arg=-ferror-limit=0", *extra_args, path]
|
"--extra-arg=-Wno-unknown-warning-option", "--extra-arg=-ferror-limit=0", *extra_args, path]
|
||||||
if lines is not None:
|
if lines is not None:
|
||||||
cmd.insert(1, "--line-filter=" + json.dumps([{"name": path, "lines": lines}]))
|
# clang-tidy matches the name against the end of the file's native path.
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
cmd.insert(1, "--line-filter=" + json.dumps([{"name": os.path.normpath(path), "lines": lines}]))
|
||||||
|
result = subprocess.run(cmd, capture_output=True, **UTF8)
|
||||||
suggestions = parse_suggested_includes(fixes)
|
suggestions = parse_suggested_includes(fixes)
|
||||||
output = result.stdout + result.stderr
|
output = result.stdout + result.stderr
|
||||||
return result.returncode, output, parse_diagnostics(output, suggestions)
|
return result.returncode, output, parse_diagnostics(output, suggestions)
|
||||||
@@ -178,7 +185,7 @@ def error_sites(errors, text):
|
|||||||
|
|
||||||
def errors_alone_at(revision, clang_tidy, build_dir, path):
|
def errors_alone_at(revision, clang_tidy, build_dir, path):
|
||||||
"""The error sites a header had when compiled on its own at `revision`."""
|
"""The error sites a header had when compiled on its own at `revision`."""
|
||||||
shown = subprocess.run(["git", "show", f"{revision}:{path}"], capture_output=True, text=True)
|
shown = subprocess.run(["git", "show", f"{revision}:{path}"], capture_output=True, **UTF8)
|
||||||
if shown.returncode != 0:
|
if shown.returncode != 0:
|
||||||
return Counter()
|
return Counter()
|
||||||
# Beside the original, so its quoted includes resolve the same way.
|
# Beside the original, so its quoted includes resolve the same way.
|
||||||
@@ -234,6 +241,8 @@ def main():
|
|||||||
parser.add_argument("-j", "--jobs", type=int, default=os.cpu_count())
|
parser.add_argument("-j", "--jobs", type=int, default=os.cpu_count())
|
||||||
parser.add_argument("extra_args", nargs="*", help="passed to clang-tidy after --, e.g. -- --fix")
|
parser.add_argument("extra_args", nargs="*", help="passed to clang-tidy after --, e.g. -- --fix")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
# A piped stdout on Windows is cp1252, which cannot encode every character clang-tidy prints.
|
||||||
|
sys.stdout.reconfigure(errors="replace")
|
||||||
|
|
||||||
merge_base = subprocess.run(["git", "merge-base", args.base, "HEAD"], check=True,
|
merge_base = subprocess.run(["git", "merge-base", args.base, "HEAD"], check=True,
|
||||||
capture_output=True, text=True).stdout.strip()
|
capture_output=True, text=True).stdout.strip()
|
||||||
|
|||||||
@@ -54,6 +54,21 @@ function Has([string]$Command) {
|
|||||||
return [bool](Get-Command $Command -ErrorAction SilentlyContinue)
|
return [bool](Get-Command $Command -ErrorAction SilentlyContinue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Runs a native command with its output, stderr included, streamed to $Log or dropped.
|
||||||
|
function Invoke-Quiet([scriptblock]$Command, [string]$Log) {
|
||||||
|
# Under "Stop", 2>&1 turns every stderr line of a native command into a terminating error.
|
||||||
|
$ErrorActionPreference = "Continue"
|
||||||
|
$lines = {
|
||||||
|
& $Command 2>&1 | ForEach-Object {
|
||||||
|
# "$_" turns a blank stderr line into the text System.Management.Automation.RemoteException.
|
||||||
|
if ($_ -isnot [System.Management.Automation.ErrorRecord]) { $_ }
|
||||||
|
elseif ($null -ne $_.TargetObject) { $_.TargetObject }
|
||||||
|
else { $_.Exception.Message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($Log) { & $lines | Out-File -Encoding utf8 -LiteralPath $Log } else { & $lines | Out-Null }
|
||||||
|
}
|
||||||
|
|
||||||
function Request-Install([string]$What, [string]$Command) {
|
function Request-Install([string]$What, [string]$Command) {
|
||||||
Write-Host "Missing: $What"
|
Write-Host "Missing: $What"
|
||||||
if (Ask "Install it now with: $Command ?") {
|
if (Ask "Install it now with: $Command ?") {
|
||||||
@@ -78,11 +93,11 @@ if (-not (Has "git")) { Request-Install "Git" "build_win.bat --install-deps" }
|
|||||||
# Python: the py launcher, else a python.exe that is not the Microsoft Store stub.
|
# Python: the py launcher, else a python.exe that is not the Microsoft Store stub.
|
||||||
$Python = $null
|
$Python = $null
|
||||||
if (Has "py") {
|
if (Has "py") {
|
||||||
& py -3 --version *> $null
|
Invoke-Quiet { & py -3 --version }
|
||||||
if ($LASTEXITCODE -eq 0) { $Python = @("py", "-3") }
|
if ($LASTEXITCODE -eq 0) { $Python = @("py", "-3") }
|
||||||
}
|
}
|
||||||
if (-not $Python -and (Has "python")) {
|
if (-not $Python -and (Has "python")) {
|
||||||
& python --version *> $null
|
Invoke-Quiet { & python --version }
|
||||||
if ($LASTEXITCODE -eq 0) { $Python = @("python") }
|
if ($LASTEXITCODE -eq 0) { $Python = @("python") }
|
||||||
}
|
}
|
||||||
if (-not $Python) { Request-Install "Python 3" "winget install -e --id Python.Python.3.12" }
|
if (-not $Python) { Request-Install "Python 3" "winget install -e --id Python.Python.3.12" }
|
||||||
@@ -100,7 +115,12 @@ if (-not $VsPath) { Request-Install "Visual Studio with the C++ tools" "build_wi
|
|||||||
# Load the developer environment, as build_win.bat does.
|
# Load the developer environment, as build_win.bat does.
|
||||||
$HostArch = if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "x64" }
|
$HostArch = if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "x64" }
|
||||||
$VsDevCmd = Join-Path $VsPath "Common7\Tools\VsDevCmd.bat"
|
$VsDevCmd = Join-Path $VsPath "Common7\Tools\VsDevCmd.bat"
|
||||||
$envLines = & cmd /c "`"$VsDevCmd`" -arch=$Arch -host_arch=$HostArch -no_logo >nul && set"
|
# Ignores VsDevCmd's exit code, as build_win.bat does, and checks the variables it sets
|
||||||
|
# before applying any, cleared in cmd so values inherited from a developer shell do not count.
|
||||||
|
$envLines = & cmd /c "set VCToolsInstallDir=& set WindowsSdkDir=& `"$VsDevCmd`" -arch=$Arch -host_arch=$HostArch -no_logo >nul 2>nul & set"
|
||||||
|
if (-not ($envLines -match '^VCToolsInstallDir=.') -or -not ($envLines -match '^WindowsSdkDir=.')) {
|
||||||
|
throw "Loading the Visual Studio $Arch environment failed. Run `"$VsDevCmd`" -arch=$Arch -host_arch=$HostArch in cmd to see why."
|
||||||
|
}
|
||||||
foreach ($line in $envLines) {
|
foreach ($line in $envLines) {
|
||||||
$i = $line.IndexOf("=")
|
$i = $line.IndexOf("=")
|
||||||
if ($i -gt 0) { Set-Item -Path ("env:" + $line.Substring(0, $i)) -Value $line.Substring($i + 1) }
|
if ($i -gt 0) { Set-Item -Path ("env:" + $line.Substring(0, $i)) -Value $line.Substring($i + 1) }
|
||||||
@@ -190,13 +210,17 @@ $cmakeArgs = @("-S", ".", "-B", $BuildDir, "-G", "Ninja", "-DCMAKE_BUILD_TYPE=Re
|
|||||||
Write-Host "Configuring $BuildDir with $Compiler"
|
Write-Host "Configuring $BuildDir with $Compiler"
|
||||||
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
|
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
|
||||||
$Log = Join-Path $BuildDir "configure.log"
|
$Log = Join-Path $BuildDir "configure.log"
|
||||||
& cmake @cmakeArgs *> $Log
|
Invoke-Quiet { & cmake @cmakeArgs } $Log
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Get-Content $Log -Tail 20
|
Get-Content -LiteralPath $Log -Tail 20
|
||||||
throw "Configuring failed; the full log is in $Log."
|
throw "Configuring failed; the full log is in $Log."
|
||||||
}
|
}
|
||||||
& cmake --build $BuildDir --target git_commit_hash_header *> $null
|
$HashLog = Join-Path $BuildDir "git_commit_hash.log"
|
||||||
if ($LASTEXITCODE -ne 0) { throw "Generating git_commit_hash.h failed." }
|
Invoke-Quiet { & cmake --build $BuildDir --target git_commit_hash_header } $HashLog
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Get-Content -LiteralPath $HashLog -Tail 20
|
||||||
|
throw "Generating git_commit_hash.h failed; the full log is in $HashLog."
|
||||||
|
}
|
||||||
|
|
||||||
# --- Base revision ------------------------------------------------------------
|
# --- Base revision ------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ external deps).
|
|||||||
Run from the repo root: python -m unittest discover -s scripts/tests -v
|
Run from the repo root: python -m unittest discover -s scripts/tests -v
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
|
||||||
@@ -62,6 +65,10 @@ class TestParseChangedLines(unittest.TestCase):
|
|||||||
def test_pure_rename_has_no_changed_lines(self):
|
def test_pure_rename_has_no_changed_lines(self):
|
||||||
self.assertNotIn("src/libslic3r/Renamed.cpp", self.changed)
|
self.assertNotIn("src/libslic3r/Renamed.cpp", self.changed)
|
||||||
|
|
||||||
|
def test_path_with_a_space_drops_the_tab_git_appends(self):
|
||||||
|
changed = clang_tidy_diff.parse_diff("+++ b/src/libslic3r/Foo Bar.cpp\t\n@@ -1,0 +2 @@\n+int x;\n")
|
||||||
|
self.assertEqual(changed["src/libslic3r/Foo Bar.cpp"].lines, [[2, 2]])
|
||||||
|
|
||||||
|
|
||||||
class TestNamesRemovedInclude(unittest.TestCase):
|
class TestNamesRemovedInclude(unittest.TestCase):
|
||||||
def test_matches_however_the_include_was_spelled(self):
|
def test_matches_however_the_include_was_spelled(self):
|
||||||
@@ -128,5 +135,37 @@ class TestParseSuggestedIncludes(unittest.TestCase):
|
|||||||
self.assertEqual(clang_tidy_diff.parse_suggested_includes("/nonexistent/fixes.yaml"), {})
|
self.assertEqual(clang_tidy_diff.parse_suggested_includes("/nonexistent/fixes.yaml"), {})
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubprocessCalls(unittest.TestCase):
|
||||||
|
def run_patched(self, function, *args, returncode=0, stdout=""):
|
||||||
|
done = subprocess.CompletedProcess([], returncode, stdout, "")
|
||||||
|
with mock.patch.object(clang_tidy_diff.subprocess, "run", return_value=done) as run, \
|
||||||
|
mock.patch.object(clang_tidy_diff.os.path, "normpath", wraps=os.path.normpath) as normpath:
|
||||||
|
result = function(*args)
|
||||||
|
return result, run.call_args, normpath
|
||||||
|
|
||||||
|
def test_line_filter_names_the_file_with_native_separators(self):
|
||||||
|
_, call, normpath = self.run_patched(clang_tidy_diff.run_clang_tidy, "clang-tidy", "build",
|
||||||
|
"src/libslic3r/Color.cpp", [[4, 4]], [])
|
||||||
|
line_filter = next(arg for arg in call.args[0] if arg.startswith("--line-filter="))
|
||||||
|
self.assertEqual(json.loads(line_filter.split("=", 1)[1]),
|
||||||
|
[{"name": os.path.join("src", "libslic3r", "Color.cpp"), "lines": [[4, 4]]}])
|
||||||
|
normpath.assert_any_call("src/libslic3r/Color.cpp")
|
||||||
|
|
||||||
|
def test_changed_files_reads_non_ascii_paths_and_text_as_utf8(self):
|
||||||
|
diff = "+++ b/src/libslic3r/Über.cpp\n@@ -1,0 +2 @@\n+// 打印\n"
|
||||||
|
files, call, _ = self.run_patched(clang_tidy_diff.changed_files, "base", stdout=diff)
|
||||||
|
self.assertIn("core.quotePath=false", call.args[0])
|
||||||
|
self.assertEqual(call.kwargs["encoding"], "utf-8")
|
||||||
|
self.assertEqual(files["src/libslic3r/Über.cpp"].lines, [[2, 2]])
|
||||||
|
|
||||||
|
def test_clang_tidy_and_git_show_output_is_decoded_as_utf8(self):
|
||||||
|
_, call, _ = self.run_patched(clang_tidy_diff.run_clang_tidy, "clang-tidy", "build",
|
||||||
|
"src/libslic3r/Color.cpp", None, [])
|
||||||
|
self.assertEqual(call.kwargs["encoding"], "utf-8")
|
||||||
|
_, call, _ = self.run_patched(clang_tidy_diff.errors_alone_at, "base", "clang-tidy", "build",
|
||||||
|
"src/libslic3r/Color.hpp", returncode=128)
|
||||||
|
self.assertEqual(call.kwargs["encoding"], "utf-8")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "libslic3r/CAD/GeometryEngine.hpp"
|
#include "libslic3r/CAD/GeometryEngine.hpp"
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
|
#include "libslic3r/I18N.hpp"
|
||||||
|
|
||||||
#include <BRepMesh_IncrementalMesh.hxx>
|
#include <BRepMesh_IncrementalMesh.hxx>
|
||||||
#include <BRep_Tool.hxx>
|
#include <BRep_Tool.hxx>
|
||||||
@@ -73,19 +74,19 @@ std::vector<TopoDS_Shape> GeometryEngine::read_step_solids(const std::string& pa
|
|||||||
try {
|
try {
|
||||||
STEPControl_Reader reader;
|
STEPControl_Reader reader;
|
||||||
if (reader.ReadFile(path.c_str()) != IFSelect_RetDone) {
|
if (reader.ReadFile(path.c_str()) != IFSelect_RetDone) {
|
||||||
err = "cannot read STEP file";
|
err = _u8L("cannot read STEP file");
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
reader.TransferRoots();
|
reader.TransferRoots();
|
||||||
const TopoDS_Shape shape = reader.OneShape();
|
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.
|
// 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())
|
for (TopExp_Explorer ex(shape, TopAbs_SOLID); ex.More(); ex.Next())
|
||||||
out.push_back(ex.Current());
|
out.push_back(ex.Current());
|
||||||
if (out.empty())
|
if (out.empty())
|
||||||
out.push_back(shape);
|
out.push_back(shape);
|
||||||
} catch (const Standard_Failure& e) {
|
} 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();
|
out.clear();
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -115,7 +116,7 @@ TopoDS_Shape GeometryEngine::mesh_to_brep(const indexed_triangle_set& its,
|
|||||||
if (tolerance <= 0.0)
|
if (tolerance <= 0.0)
|
||||||
throw std::runtime_error("mesh_to_brep: tolerance must be > 0");
|
throw std::runtime_error("mesh_to_brep: tolerance must be > 0");
|
||||||
if (its.indices.empty())
|
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
|
// 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.
|
// 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());
|
stats.kept_tris = int(tris.size());
|
||||||
if (tris.empty())
|
if (tris.empty())
|
||||||
throw std::runtime_error("mesh_to_brep: every triangle was rejected as degenerate "
|
throw std::runtime_error(_u8L("mesh_to_brep: every triangle was rejected as degenerate "
|
||||||
"(try a smaller tolerance)");
|
"(try a smaller tolerance)"));
|
||||||
|
|
||||||
// 3. One face per triangle, sharing vertices and edges through the caches.
|
// 3. One face per triangle, sharing vertices and edges through the caches.
|
||||||
std::vector<TopoDS_Vertex> vertex_cache(verts.size());
|
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
|
// A too-large radius (e.g. >= half the smallest spanned dimension) makes the
|
||||||
// operation degenerate; OCCT leaves IsDone() false. Report it instead of
|
// operation degenerate; OCCT leaves IsDone() false. Report it instead of
|
||||||
// silently returning the unfilleted solid (which reads as a false success).
|
// 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();
|
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.Add(distance, edge); // symmetric chamfer
|
||||||
chamfer.Build();
|
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();
|
return chamfer.Shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,7 +405,7 @@ TopoDS_Shape GeometryEngine::apply_fillet(const TopoDS_Shape& solid, double radi
|
|||||||
}
|
}
|
||||||
mk.Build();
|
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();
|
return mk.Shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +422,7 @@ TopoDS_Shape GeometryEngine::apply_chamfer(const TopoDS_Shape& solid, double dis
|
|||||||
}
|
}
|
||||||
mk.Build();
|
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();
|
return mk.Shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,12 +548,13 @@ GeometryEngine::MassProps GeometryEngine::mass_properties(const TopoDS_Shape& sh
|
|||||||
std::string GeometryEngine::primitive_name(PrimitiveType type)
|
std::string GeometryEngine::primitive_name(PrimitiveType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PrimitiveType::Box: return "Box";
|
// TRN Default name of an object created from the box primitive shape.
|
||||||
case PrimitiveType::Cylinder: return "Cylinder";
|
case PrimitiveType::Box: return _u8L("Box");
|
||||||
case PrimitiveType::Sphere: return "Sphere";
|
case PrimitiveType::Cylinder: return _u8L("Cylinder");
|
||||||
case PrimitiveType::Cone: return "Cone";
|
case PrimitiveType::Sphere: return _u8L("Sphere");
|
||||||
case PrimitiveType::Torus: return "Torus";
|
case PrimitiveType::Cone: return _u8L("Cone");
|
||||||
default: return "Unknown";
|
case PrimitiveType::Torus: return _u8L("Torus");
|
||||||
|
default: return _u8L("Unknown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "libslic3r/CAD/SketchEngine.hpp"
|
#include "libslic3r/CAD/SketchEngine.hpp"
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
|
#include "libslic3r/I18N.hpp"
|
||||||
|
|
||||||
#include <Standard_Handle.hxx>
|
#include <Standard_Handle.hxx>
|
||||||
#include <GeomAbs_SurfaceType.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
|
TopoDS_Wire SketchProfile::to_occt_wire(const SketchPlane& plane) const
|
||||||
{
|
{
|
||||||
if (points.size() < 2)
|
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;
|
BRepBuilderAPI_MakeWire builder;
|
||||||
for (size_t i = 0; i < points.size(); ++i) {
|
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();
|
builder.Build();
|
||||||
if (!builder.IsDone())
|
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();
|
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)
|
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);
|
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();
|
return prism.Shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +170,7 @@ static TopoDS_Shape extrude_face_internal(const TopoDS_Face& face, const gp_Dir&
|
|||||||
if (symmetric) {
|
if (symmetric) {
|
||||||
gp_Vec halfVec = gp_Vec(dir) * (length / 2.0);
|
gp_Vec halfVec = gp_Vec(dir) * (length / 2.0);
|
||||||
BRepAlgoAPI_Fuse fuse(SketchEngine::make_prism(face, halfVec), SketchEngine::make_prism(face, -halfVec));
|
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 fuse.Shape();
|
||||||
}
|
}
|
||||||
return SketchEngine::make_prism(face, gp_Vec(dir) * length);
|
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)
|
double length, bool symmetric, double taper_deg)
|
||||||
{
|
{
|
||||||
BRepBuilderAPI_MakeFace fm(wire);
|
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);
|
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)
|
double up, double down)
|
||||||
{
|
{
|
||||||
BRepBuilderAPI_MakeFace fm(wire);
|
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);
|
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 (d < 1e-9) return make_prism(face, gp_Vec(dir) * u);
|
||||||
if (u < 1e-9) return make_prism(face, gp_Vec(dir) * -d);
|
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));
|
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();
|
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());
|
gp_Dir dir(plane.normal.x(), plane.normal.y(), plane.normal.z());
|
||||||
auto straight = [&]() -> TopoDS_Shape {
|
auto straight = [&]() -> TopoDS_Shape {
|
||||||
BRepBuilderAPI_MakeFace fm(wire);
|
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);
|
return make_prism(fm.Face(), gp_Vec(dir) * length);
|
||||||
};
|
};
|
||||||
if (std::abs(taper_deg) >= 89.0 || std::abs(length) < 1e-9) return straight();
|
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)
|
const SketchPlane& plane, double length, bool symmetric)
|
||||||
{
|
{
|
||||||
// The loop below skips regions that fail, so a zero depth is rejected before it.
|
// 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 /
|
// Drop consecutive coincident points and the closing duplicate. FreeType /
|
||||||
// SVG flattening routinely emits repeated points which would build a
|
// 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
|
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);
|
BRepBuilderAPI_MakeFace faceMaker(wire);
|
||||||
if (!faceMaker.IsDone())
|
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();
|
TopoDS_Face face = faceMaker.Face();
|
||||||
|
|
||||||
// A profile on both sides of the axis sweeps through itself; MakeRevol then fails with no
|
// 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; }
|
if (angle_rad < 0) { axis.Reverse(); angle_rad = -angle_rad; }
|
||||||
BRepPrimAPI_MakeRevol rev(face, axis, angle_rad);
|
BRepPrimAPI_MakeRevol rev(face, axis, angle_rad);
|
||||||
if (!rev.IsDone())
|
if (!rev.IsDone())
|
||||||
throw std::runtime_error("Failed to revolve");
|
throw std::runtime_error(_u8L("Failed to revolve"));
|
||||||
if (!BRepCheck_Analyzer(rev.Shape()).IsValid())
|
if (!BRepCheck_Analyzer(rev.Shape()).IsValid())
|
||||||
throw std::runtime_error("the profile crosses the revolve axis — it must lie on one side of it");
|
throw std::runtime_error("the profile crosses the revolve axis — it must lie on one side of it");
|
||||||
return rev.Shape();
|
return rev.Shape();
|
||||||
@@ -397,29 +398,29 @@ TopoDS_Shape SketchEngine::make_sweep(const TopoDS_Wire& profile, const TopoDS_W
|
|||||||
{
|
{
|
||||||
BRepBuilderAPI_MakeFace faceMaker(profile);
|
BRepBuilderAPI_MakeFace faceMaker(profile);
|
||||||
if (!faceMaker.IsDone())
|
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();
|
TopoDS_Face face = faceMaker.Face();
|
||||||
|
|
||||||
BRepOffsetAPI_MakePipe pipe(path, face);
|
BRepOffsetAPI_MakePipe pipe(path, face);
|
||||||
pipe.Build();
|
pipe.Build();
|
||||||
if (!pipe.IsDone())
|
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();
|
return pipe.Shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
TopoDS_Shape SketchEngine::make_loft(const std::vector<TopoDS_Wire>& profiles, bool ruled)
|
TopoDS_Shape SketchEngine::make_loft(const std::vector<TopoDS_Wire>& profiles, bool ruled)
|
||||||
{
|
{
|
||||||
if (profiles.size() < 2)
|
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);
|
BRepOffsetAPI_ThruSections loft(true /*solid*/, ruled);
|
||||||
for (const TopoDS_Wire& w : profiles) {
|
for (const TopoDS_Wire& w : profiles) {
|
||||||
if (w.IsNull()) throw std::runtime_error("loft: null profile wire");
|
if (w.IsNull()) throw std::runtime_error("loft: null profile wire");
|
||||||
loft.AddWire(w);
|
loft.AddWire(w);
|
||||||
}
|
}
|
||||||
loft.Build();
|
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();
|
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;
|
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)
|
TopoDS_Shape SketchEngine::make_loft_surface(const std::vector<TopoDS_Wire>& profiles, bool ruled)
|
||||||
{
|
{
|
||||||
if (profiles.size() < 2)
|
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);
|
BRepOffsetAPI_ThruSections loft(false /*shell, no end caps*/, ruled);
|
||||||
for (const TopoDS_Wire& w : profiles) {
|
for (const TopoDS_Wire& w : profiles) {
|
||||||
if (w.IsNull()) throw std::runtime_error("loft: null profile wire");
|
if (w.IsNull()) throw std::runtime_error("loft: null profile wire");
|
||||||
loft.AddWire(w);
|
loft.AddWire(w);
|
||||||
}
|
}
|
||||||
loft.Build();
|
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();
|
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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,11 +445,11 @@ TopoDS_Shape SketchEngine::make_pocket(const TopoDS_Wire& wire, const SketchPlan
|
|||||||
const TopoDS_Shape& target, double depth)
|
const TopoDS_Shape& target, double depth)
|
||||||
{
|
{
|
||||||
BRepBuilderAPI_MakeFace fm(wire);
|
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(),
|
TopoDS_Shape tool = extrude_face_internal(fm.Face(),
|
||||||
gp_Dir(plane.normal.x(), plane.normal.y(), plane.normal.z()), depth + 1.0, false);
|
gp_Dir(plane.normal.x(), plane.normal.y(), plane.normal.z()), depth + 1.0, false);
|
||||||
BRepAlgoAPI_Cut cut(target, tool);
|
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();
|
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,
|
TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
||||||
const SketchPlane& plane)
|
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
|
// 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,
|
// 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) {
|
if (wires.size() == 1) {
|
||||||
BRepBuilderAPI_MakeFace fm(wires[0]);
|
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());
|
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());
|
areas.reserve(wires.size());
|
||||||
for (const TopoDS_Wire& w : wires) {
|
for (const TopoDS_Wire& w : wires) {
|
||||||
BRepBuilderAPI_MakeFace fm(w);
|
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());
|
faces.push_back(fm.Face());
|
||||||
GProp_GProps props;
|
GProp_GProps props;
|
||||||
BRepGProp::SurfaceProperties(faces.back(), props);
|
BRepGProp::SurfaceProperties(faces.back(), props);
|
||||||
@@ -982,10 +983,10 @@ TopoDS_Face SketchEngine::wires_to_face(const std::vector<TopoDS_Wire>& wires,
|
|||||||
got = true;
|
got = true;
|
||||||
break;
|
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);
|
BRepClass_FaceClassifier fc(faces[outer], p, 1e-7);
|
||||||
if (fc.State() != TopAbs_IN)
|
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.
|
// 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
|
// 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
|
// 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.
|
// 147520 — a body larger than its own bounding box, which is the signature of it.
|
||||||
fm.Add(wires[i]);
|
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
|
// 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
|
// already uses for imported glyphs, which is why holed TEXT extruded correctly all along
|
||||||
// while a holed SKETCH did not.
|
// while a holed SKETCH did not.
|
||||||
|
|||||||
@@ -5301,7 +5301,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->set_default_value(new ConfigOptionEnum<InputShaperType>(InputShaperType::Default));
|
def->set_default_value(new ConfigOptionEnum<InputShaperType>(InputShaperType::Default));
|
||||||
|
|
||||||
def = this->add("input_shaping_freq_x", coFloat);
|
def = this->add("input_shaping_freq_x", coFloat);
|
||||||
def->label = L("X");
|
def->label = L_CONTEXT("X", "Axis");
|
||||||
def->tooltip = L("Resonant frequency for the X axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
|
def->tooltip = L("Resonant frequency for the X axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
|
||||||
def->sidetext = L("Hz"); // Hertz, CIS languages need translation
|
def->sidetext = L("Hz"); // Hertz, CIS languages need translation
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
@@ -5310,7 +5310,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->set_default_value(new ConfigOptionFloat(0));
|
def->set_default_value(new ConfigOptionFloat(0));
|
||||||
|
|
||||||
def = this->add("input_shaping_freq_y", coFloat);
|
def = this->add("input_shaping_freq_y", coFloat);
|
||||||
def->label = L("Y");
|
def->label = L_CONTEXT("Y", "Axis");
|
||||||
def->tooltip = L("Resonant frequency for the Y axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.");
|
def->tooltip = L("Resonant frequency for the Y axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.");
|
||||||
def->sidetext = L("Hz"); // Hertz, CIS languages need translation
|
def->sidetext = L("Hz"); // Hertz, CIS languages need translation
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
@@ -5319,7 +5319,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->set_default_value(new ConfigOptionFloat(0));
|
def->set_default_value(new ConfigOptionFloat(0));
|
||||||
|
|
||||||
def = this->add("input_shaping_damp_x", coFloat);
|
def = this->add("input_shaping_damp_x", coFloat);
|
||||||
def->label = L("X");
|
def->label = L_CONTEXT("X", "Axis");
|
||||||
def->tooltip = L("Damping ratio for the X axis input shaper.\nZero will use the firmware damping ratio.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
|
def->tooltip = L("Damping ratio for the X axis input shaper.\nZero will use the firmware damping ratio.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->max = 1;
|
def->max = 1;
|
||||||
@@ -5327,7 +5327,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->set_default_value(new ConfigOptionFloat(0.1));
|
def->set_default_value(new ConfigOptionFloat(0.1));
|
||||||
|
|
||||||
def = this->add("input_shaping_damp_y", coFloat);
|
def = this->add("input_shaping_damp_y", coFloat);
|
||||||
def->label = L("Y");
|
def->label = L_CONTEXT("Y", "Axis");
|
||||||
def->tooltip = L("Damping ratio for the Y axis input shaper.\nZero will use the firmware damping ratio.\nTo disable input shaping, use the Disable type.");
|
def->tooltip = L("Damping ratio for the Y axis input shaper.\nZero will use the firmware damping ratio.\nTo disable input shaping, use the Disable type.");
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->max = 1;
|
def->max = 1;
|
||||||
@@ -8530,14 +8530,14 @@ void PrintConfigDef::init_sla_params()
|
|||||||
|
|
||||||
def = this->add("display_pixels_x", coInt);
|
def = this->add("display_pixels_x", coInt);
|
||||||
//def->full_label = L("");
|
//def->full_label = L("");
|
||||||
def->label = ("X");
|
def->label = L_CONTEXT("X", "Axis");
|
||||||
//def->tooltip = L("");
|
//def->tooltip = L("");
|
||||||
def->min = 100;
|
def->min = 100;
|
||||||
def->set_default_value(new ConfigOptionInt(2560));
|
def->set_default_value(new ConfigOptionInt(2560));
|
||||||
|
|
||||||
def = this->add("display_pixels_y", coInt);
|
def = this->add("display_pixels_y", coInt);
|
||||||
//def->full_label = L("");
|
//def->full_label = L("");
|
||||||
def->label = ("Y");
|
def->label = L_CONTEXT("Y", "Axis");
|
||||||
//def->tooltip = L("");
|
//def->tooltip = L("");
|
||||||
def->min = 100;
|
def->min = 100;
|
||||||
def->set_default_value(new ConfigOptionInt(1440));
|
def->set_default_value(new ConfigOptionInt(1440));
|
||||||
|
|||||||
@@ -1228,11 +1228,11 @@ void AMSDryCtrWin::update_normal_description(DevAms* dev_ams)
|
|||||||
for (const auto& lim : ams_limits) {
|
for (const auto& lim : ams_limits) {
|
||||||
if (dev_ams->GetAmsType() == lim.type) {
|
if (dev_ams->GetAmsType() == lim.type) {
|
||||||
if (temp_val > lim.max_temp) {
|
if (temp_val > lim.max_temp) {
|
||||||
wxString msg = wxString::Format(_L("%s maximum drying temperature is %d°C."), wxString(lim.name), lim.max_temp);
|
wxString msg = wxString::Format(_L("%s maximum drying temperature is %d\u2103." /* °C */), wxString(lim.name), lim.max_temp);
|
||||||
warning_text += msg + "\n";
|
warning_text += msg + "\n";
|
||||||
can_enable_button = false;
|
can_enable_button = false;
|
||||||
} else if (temp_val < lim.min_temp) {
|
} else if (temp_val < lim.min_temp) {
|
||||||
wxString msg = wxString::Format(_L("%s minimum drying temperature is %d°C."), wxString(lim.name), lim.min_temp);
|
wxString msg = wxString::Format(_L("%s minimum drying temperature is %d\u2103." /* °C */), wxString(lim.name), lim.min_temp);
|
||||||
warning_text += msg + "\n";
|
warning_text += msg + "\n";
|
||||||
can_enable_button = false;
|
can_enable_button = false;
|
||||||
}
|
}
|
||||||
@@ -1260,7 +1260,7 @@ void AMSDryCtrWin::update_normal_description(DevAms* dev_ams)
|
|||||||
auto limit_temperature = preset.value().filament_dev_ams_drying_heat_distortion_temperature;
|
auto limit_temperature = preset.value().filament_dev_ams_drying_heat_distortion_temperature;
|
||||||
if (temp_val > limit_temperature) {
|
if (temp_val > limit_temperature) {
|
||||||
warning_text += _L("The temperature shall not exceed the filament's heat distortion temperature") + "(" +
|
warning_text += _L("The temperature shall not exceed the filament's heat distortion temperature") + "(" +
|
||||||
wxString::Format(wxT("%d"), static_cast<int>(limit_temperature)) + wxString::FromUTF8("°C)\n");
|
wxString::Format(wxT("%d"), static_cast<int>(limit_temperature)) + wxString::FromUTF8(u8"\u2103" /* °C */) + ")\n";
|
||||||
can_enable_button = false;
|
can_enable_button = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,8 @@ AboutDialog::AboutDialog()
|
|||||||
vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5));
|
vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5));
|
||||||
auto version_string = std::string(SoftFever_VERSION); // _L("Orca Slicer ") + " " + std::string(SoftFever_VERSION);
|
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* 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);
|
credits_string->SetFont(_build_string_font);
|
||||||
wxFont version_font = GetFont();
|
wxFont version_font = GetFont();
|
||||||
version_font = version_font.Scaled(1.85f); // SetPointSize(20) not works on macOS because it uses a 72 PPI reference
|
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));
|
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));
|
html_text->SetForegroundColour(wxColour(107, 107, 107));
|
||||||
|
|
||||||
copyright_ver_sizer->Add(html_text, 0, wxALL , 0);
|
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) {
|
if (m_show_type == ShowType::LEFT_AND_RIGHT_DYNAMIC) {
|
||||||
auto sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL);
|
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);
|
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->SetName(m_right_marea_panel->GetName());
|
||||||
ams_mapping_item_container->SetSizer(sizer_mapping_list);
|
ams_mapping_item_container->SetSizer(sizer_mapping_list);
|
||||||
@@ -506,7 +507,7 @@ void AmsMapingPopup::update_ams_tips(MachineObject* obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj && obj->GetFilaSwitch()->IsInstalled()) {
|
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", "");
|
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).
|
// 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)
|
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)) {
|
&& (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 {
|
} else {
|
||||||
m_mapping_item->set_tray_index(wxGetApp().transition_tridid(tray_data[i].id));
|
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);
|
can_pick_the_item = !devPrinterUtil::IsVirtualSlot(m_mapping_item->m_ams_id);
|
||||||
if (!can_pick_the_item) {
|
if (!can_pick_the_item) {
|
||||||
item_tooltip_msg = _L(
|
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);
|
can_pick_the_item = !devPrinterUtil::IsVirtualSlot(m_mapping_item->m_ams_id);
|
||||||
if (!can_pick_the_item) {
|
if (!can_pick_the_item) {
|
||||||
item_tooltip_msg = _L(
|
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) {
|
} else if (m_show_type != ShowType::RIGHT && m_show_type != ShowType::LEFT_AND_RIGHT) {
|
||||||
can_pick_the_item = false;
|
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
|
} // namespace Slic3r::GUI
|
||||||
@@ -1152,6 +1152,7 @@ void AuxiliaryPanel::update_all_cover()
|
|||||||
m_sizer_description->Add(m_text_description, 0, wxALIGN_TOP | wxRIGHT, FromDIP(10));
|
m_sizer_description->Add(m_text_description, 0, wxALIGN_TOP | wxRIGHT, FromDIP(10));
|
||||||
m_input_description = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
m_input_description = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||||
wxSize(FromDIP(450), FromDIP(300)), wxTE_MULTILINE | wxTE_PROCESS_ENTER);
|
wxSize(FromDIP(450), FromDIP(300)), wxTE_MULTILINE | wxTE_PROCESS_ENTER);
|
||||||
|
m_input_description->SetBackgroundColour(*wxWHITE);
|
||||||
m_input_description->SetFont(::Label::Body_14);
|
m_input_description->SetFont(::Label::Body_14);
|
||||||
m_sizer_description->Add(m_input_description, 0, wxALIGN_CENTER, 0);
|
m_sizer_description->Add(m_input_description, 0, wxALIGN_CENTER, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace GUI {
|
|||||||
|
|
||||||
|
|
||||||
AuxiliaryDialog::AuxiliaryDialog(wxWindow * parent)
|
AuxiliaryDialog::AuxiliaryDialog(wxWindow * parent)
|
||||||
: DPIDialog(parent, wxID_ANY, _L("Auxiliaryies"), wxDefaultPosition,
|
: DPIDialog(parent, wxID_ANY, _L("Auxiliaries"), wxDefaultPosition,
|
||||||
wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||||
{
|
{
|
||||||
m_aux_list = new AuxiliaryList(this);
|
m_aux_list = new AuxiliaryList(this);
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#ifndef L
|
#ifndef L
|
||||||
#define L(s) s // gettext marker, as in slic3r/GUI/I18N.hpp
|
#define L(s) s // gettext marker, as in slic3r/GUI/I18N.hpp
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef L_CONTEXT
|
||||||
|
#define L_CONTEXT(s, context) s
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
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)
|
// nullptr -> kernel support exists, no GUI path yet (row shows disabled)
|
||||||
struct OfferVerb {
|
struct OfferVerb {
|
||||||
const char* id;
|
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
|
int row; // index into kOfferRowNames, the ratified address — NEVER reorder
|
||||||
const char* key; // shortcut shown in the row, or nullptr
|
const char* key; // shortcut shown in the row, or nullptr
|
||||||
const char* action;
|
const char* action;
|
||||||
@@ -99,107 +102,107 @@ static const bool kOfferRowFlat[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const OfferVerb kOfferVerbs[] = {
|
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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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)")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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_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("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")},
|
{"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("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_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("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_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("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_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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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", 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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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)")},
|
{"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("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")},
|
{"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("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)")},
|
{"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("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)")},
|
{"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("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)")},
|
{"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("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")},
|
{"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("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")},
|
{"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("Measure"), 6, nullptr, nullptr, nullptr, 0x000b03feu, 0, 0, false, false, nullptr, nullptr, L("Measure between the picked points, edges or faces")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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")},
|
{"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("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)")},
|
{"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("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")},
|
{"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("Color"), 8, nullptr, "btn:colour", nullptr, 0x000001feu, 1, 0, false, false, nullptr, "color_palette", L("Set the selected body's display color")},
|
{"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("Delete"), 7, "Del", "btn:delete", nullptr, 0x000f7c00u, 0, 0, false, false, nullptr, "design_delete", L("Delete what is selected")},
|
{"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("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")},
|
{"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("Line"), 0, "L", "key:L", nullptr, 0x000f8000u, 0, 0, false, true, L("Line"), "design_line", L("Line — click start, then end")},
|
{"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("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_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("Corner rectangle"), 0, "R", "key:R", nullptr, 0x000f8000u, 0, 0, false, true, L("Rectangle"), "design_rect", L("Rectangle — click two opposite corners")},
|
{"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("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_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("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_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("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_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("Center circle"), 0, "C", "key:C", nullptr, 0x000f8000u, 0, 0, false, true, L("Circle"), "design_circle", L("Circle — click center, then 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("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_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("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_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("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_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("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_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("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_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("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", 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("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_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("Ellipse"), 0, "E", "key:E", nullptr, 0x000f8000u, 0, 0, false, true, L("Ellipse"), "design_ellipse", L("Ellipse — center, major end, minor point")},
|
{"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("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_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("Spline"), 0, "B", "key:B", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_bspline", L("Spline — click control points")},
|
{"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("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_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("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_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("Pentagon"), 0, nullptr, "btn:poly#5", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Pentagon — 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("Hexagon"), 0, "G", "btn:poly#6", nullptr, 0x000f8000u, 0, 0, false, true, L("Polygon"), "design_polygon", L("Hexagon — 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("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_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("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_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("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_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("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_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("Point"), 0, "P", "key:P", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_point", L("Point — click to place")},
|
{"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("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_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("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_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("Offset"), 1, "O", "key:O", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_offset", L("Offset — pick an entity, drag the distance")},
|
{"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("Trim"), 2, "T", "key:T", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_trim", L("Trim — click a segment to trim it")},
|
{"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("Fillet"), 3, "F", "key:F", nullptr, 0x00090000u, 0, 0, false, true, nullptr, "design_filletedge", L("Fillet — pick two lines, set the radius")},
|
{"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("Chamfer"), 3, "H", "key:H", nullptr, 0x00090000u, 0, 0, false, true, nullptr, "design_chamfer", L("Chamfer — pick two lines, set the distance")},
|
{"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("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", 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("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_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("Mirror"), 4, "M", "key:M", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_mirror", L("Mirror — pick axis, then entities")},
|
{"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("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_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("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_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("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_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("Dimension"), 6, "D", "key:D", nullptr, 0x000f8000u, 0, 0, false, true, nullptr, "design_dimension", L("Dimension — click 2 points or an entity")},
|
{"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("Constrain"), 6, "K", "key:K", nullptr, 0x000f0000u, 0, 0, false, true, nullptr, "design_constrain", L("Constrain the selected sketch entities to each other")},
|
{"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
|
// 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
|
// 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.
|
// 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.
|
// 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")},
|
{"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("Construction"), 6, "Q", "key:Q", nullptr, 0x000b8000u, 0, 0, false, true, nullptr, nullptr, L("Toggle construction: geometry that guides but is never built")},
|
{"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("Extend"), 7, "X", "key:X", nullptr, 0x000b0000u, 0, 0, false, true, nullptr, "design_extend", L("Extend — click a line/arc to extend it")},
|
{"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("Delete"), 7, "Del", "btn:sk_delete", nullptr, 0x000f0000u, 0, 0, false, true, nullptr, "design_delete", L("Delete the selected sketch entities")},
|
{"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
|
// 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
|
// 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
|
// 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
|
// selection. Without these, an element's own numbers were reachable only by arming the
|
||||||
// Dimension tool and re-picking geometry that was already selected.
|
// 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_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("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_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("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_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;
|
static const int kOfferVerbCount = 92;
|
||||||
|
|
||||||
|
|||||||
@@ -110,15 +110,6 @@
|
|||||||
#include "slic3r/GUI/Shortcuts.hpp"
|
#include "slic3r/GUI/Shortcuts.hpp"
|
||||||
#include "slic3r/GUI/I18N.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 {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
// Mesh -> B-rep import defaults (see GeometryEngine::mesh_to_brep).
|
// 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());
|
m_viewport->set_sketch_construction(m_construction->GetValue());
|
||||||
set_status(StatusKind::Info, m_sketch_on.IsEmpty() ? hint
|
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
|
// Sketch-tool shortcuts (single letters, active only while a sketch is open). Family tools
|
||||||
@@ -731,11 +722,11 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
wxString where;
|
wxString where;
|
||||||
const bool have_plane = sketch_plane_target(where);
|
const bool have_plane = sketch_plane_target(where);
|
||||||
set_status(StatusKind::Info, have_plane
|
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"));
|
: _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
|
if (m_sketch_hint) { // the card must agree with the status line, not argue with it
|
||||||
m_sketch_hint->SetLabel(have_plane
|
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."));
|
: _L("Click a face or a reference plane, then a sketch tool."));
|
||||||
m_sketch_hint->Refresh();
|
m_sketch_hint->Refresh();
|
||||||
m_cards->Layout();
|
m_cards->Layout();
|
||||||
@@ -752,7 +743,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
// Add material: every feature that grows new solid material — from a profile
|
// 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).
|
// (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)"), {
|
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] {
|
[this] {
|
||||||
// Onshape push/pull: an explicitly picked solid face (Face-level cycle, no loop
|
// 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
|
// 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;
|
m_sel_solid_face = -1;
|
||||||
open_tool(Tool::Thicken); // syncs m_thicken_face_label from m_sel_solid_face
|
open_tool(Tool::Thicken); // syncs m_thicken_face_label from m_sel_solid_face
|
||||||
}, 0},
|
}, 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] {
|
[this] {
|
||||||
if (m_doc.bodies.empty()) {
|
if (m_doc.bodies.empty()) {
|
||||||
set_status(StatusKind::Error, _L("Rib needs a solid body — add or import one first"));
|
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.
|
// 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] {
|
std::function<void()> act_pattern = [this] {
|
||||||
// Pattern replicates an existing body — needs at least one solid.
|
// Pattern replicates an existing body — needs at least one solid.
|
||||||
if (m_doc.bodies.empty()) {
|
if (m_doc.bodies.empty()) {
|
||||||
@@ -979,7 +970,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
}, 0},
|
}, 0},
|
||||||
// Project belongs here, not in Dress-up: it consumes a body but PRODUCES sketch
|
// 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.
|
// 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] {
|
[this] {
|
||||||
if (m_doc.bodies.empty()) {
|
if (m_doc.bodies.empty()) {
|
||||||
set_status(StatusKind::Error, _L("Project needs a body — add or import one first"));
|
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')},
|
[this] { open_tool(Tool::Dressup); }, SHIFT('F')},
|
||||||
{"design_draft", _L("Draft (taper a face)"), _L("Tilt a picked face by a draft angle"),
|
{"design_draft", _L("Draft (taper a face)"), _L("Tilt a picked face by a draft angle"),
|
||||||
[this] { open_tool(Tool::Draft); }, SHIFT('D')},
|
[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')},
|
[this] { open_tool(Tool::Shell); }, SHIFT('K')},
|
||||||
{"design_delete", _L("Delete Face"), _L("Remove faces from a body and heal the solid"),
|
{"design_delete", _L("Delete Face"), _L("Remove faces from a body and heal the solid"),
|
||||||
[this] {
|
[this] {
|
||||||
@@ -1165,7 +1156,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
|
|
||||||
// Hole / Thread — drilling into a solid (both face-aware)
|
// Hole / Thread — drilling into a solid (both face-aware)
|
||||||
feat_dropdown("hole", "design_hole", _L("Hole / thread"), {
|
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] {
|
[this] {
|
||||||
// #2: drill on the picked solid face, centred on it (origin = face centroid,
|
// #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
|
// 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) {
|
if (n > 0) {
|
||||||
m_construction->SetValue(!m_construction->GetValue()); // the mode did not move
|
m_construction->SetValue(!m_construction->GetValue()); // the mode did not move
|
||||||
set_status(StatusKind::Info, wxString::Format(
|
set_status(StatusKind::Info, wxString::Format(
|
||||||
_L("Converted %d entit%s between construction and real geometry"),
|
_L_PLURAL("Converted %d entity between construction and real geometry",
|
||||||
n, n == 1 ? "y" : "ies"));
|
"Converted %d entities between construction and real geometry", n),
|
||||||
|
n));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_viewport->set_sketch_construction(m_construction->GetValue()); });
|
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); });
|
b->Bind(wxEVT_BUTTON, [this, type](wxCommandEvent&) { apply_constraint(type); });
|
||||||
cadd(b);
|
cadd(b);
|
||||||
};
|
};
|
||||||
cbtn("design_c_horizontal", _L("Horizontal"), SketchConstraintType::Horizontal);
|
cbtn("design_c_horizontal", _L_CONTEXT("Horizontal", "Sketch Constraint"), SketchConstraintType::Horizontal);
|
||||||
cbtn("design_c_vertical", _L("Vertical"), SketchConstraintType::Vertical);
|
cbtn("design_c_vertical", _L_CONTEXT("Vertical", "Sketch Constraint"), SketchConstraintType::Vertical);
|
||||||
cbtn("design_c_parallel", _L("Parallel"), SketchConstraintType::Parallel);
|
cbtn("design_c_parallel", _L_CONTEXT("Parallel", "Sketch Constraint"), SketchConstraintType::Parallel);
|
||||||
cbtn("design_c_perpendicular", _L("Perpendicular"), SketchConstraintType::Perpendicular);
|
cbtn("design_c_perpendicular", _L_CONTEXT("Perpendicular", "Sketch Constraint"), SketchConstraintType::Perpendicular);
|
||||||
cbtn("design_c_coincident", _L("Coincident"), SketchConstraintType::Coincident);
|
cbtn("design_c_coincident", _L_CONTEXT("Coincident", "Sketch Constraint"), SketchConstraintType::Coincident);
|
||||||
cbtn("design_c_equal", _L("Equal length"), SketchConstraintType::EqualLength);
|
cbtn("design_c_equal", _L_CONTEXT("Equal length", "Sketch Constraint"), SketchConstraintType::EqualLength);
|
||||||
cbtn("design_c_equal_radius", _L("Equal radius"), SketchConstraintType::EqualRadius);
|
cbtn("design_c_equal_radius", _L_CONTEXT("Equal radius", "Sketch Constraint"), SketchConstraintType::EqualRadius);
|
||||||
cbtn("design_c_collinear", _L("Collinear"), SketchConstraintType::Collinear);
|
cbtn("design_c_collinear", _L_CONTEXT("Collinear", "Sketch Constraint"), SketchConstraintType::Collinear);
|
||||||
cbtn("design_c_concentric", _L("Concentric"), SketchConstraintType::Concentric);
|
cbtn("design_c_concentric", _L_CONTEXT("Concentric", "Sketch Constraint"), SketchConstraintType::Concentric);
|
||||||
cbtn("design_c_tangent", _L("Tangent"), SketchConstraintType::Tangent);
|
cbtn("design_c_tangent", _L_CONTEXT("Tangent", "Sketch Constraint"), SketchConstraintType::Tangent);
|
||||||
cbtn("design_c_midpoint", _L("Midpoint"), SketchConstraintType::Midpoint);
|
cbtn("design_c_midpoint", _L_CONTEXT("Midpoint", "Sketch Constraint"), SketchConstraintType::Midpoint);
|
||||||
cbtn("design_c_symmetric", _L("Symmetric"), SketchConstraintType::Symmetric);
|
cbtn("design_c_symmetric", _L_CONTEXT("Symmetric", "Sketch Constraint"), SketchConstraintType::Symmetric);
|
||||||
cbtn("design_c_sym_v", _L("Symmetric about the vertical axis"), SketchConstraintType::SymmetricAboutY);
|
cbtn("design_c_sym_v", _L_CONTEXT("Symmetric about the vertical axis", "Sketch Constraint"), SketchConstraintType::SymmetricAboutY);
|
||||||
cbtn("design_c_sym_h", _L("Symmetric about the horizontal axis"), SketchConstraintType::SymmetricAboutX);
|
cbtn("design_c_sym_h", _L_CONTEXT("Symmetric about the horizontal axis", "Sketch Constraint"), SketchConstraintType::SymmetricAboutX);
|
||||||
cbtn("design_c_angle", _L("Angle"), SketchConstraintType::Angle);
|
cbtn("design_c_angle", _L_CONTEXT("Angle", "Sketch Constraint"), SketchConstraintType::Angle);
|
||||||
cbtn("design_c_radius", _L("Radius"), SketchConstraintType::Radius);
|
cbtn("design_c_radius", _L_CONTEXT("Radius", "Sketch Constraint"), SketchConstraintType::Radius);
|
||||||
cbtn("design_c_diameter", _L("Diameter"), SketchConstraintType::Diameter);
|
cbtn("design_c_diameter", _L_CONTEXT("Diameter", "Sketch Constraint"), SketchConstraintType::Diameter);
|
||||||
cbtn("design_c_fix", _L("Fix point (anchor in place)"), SketchConstraintType::Fix);
|
cbtn("design_c_fix", _L_CONTEXT("Fix point (anchor in place)", "Sketch Constraint"), SketchConstraintType::Fix);
|
||||||
cbtn("design_c_dist_x", _L("Horizontal distance"), SketchConstraintType::DistanceX);
|
cbtn("design_c_dist_x", _L_CONTEXT("Horizontal distance", "Sketch Constraint"), SketchConstraintType::DistanceX);
|
||||||
cbtn("design_c_dist_y", _L("Vertical distance"), SketchConstraintType::DistanceY);
|
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
|
// 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/
|
// toolbar, NOT Constrain buttons. The other edit ops (Mirror/Offset/Fillet/Chamfer/
|
||||||
// Move/…) are first-class sketch tools too. Done constraining = the action-bar ✓.
|
// Move/…) are first-class sketch tools too. Done constraining = the action-bar ✓.
|
||||||
@@ -1860,9 +1852,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
mform->Add(spin_frame(m_move_dz), 0, wxEXPAND);
|
mform->Add(spin_frame(m_move_dz), 0, wxEXPAND);
|
||||||
|
|
||||||
m_move_axis = make_combo(m_cards);
|
m_move_axis = make_combo(m_cards);
|
||||||
m_move_axis->Append(_L("X"));
|
m_move_axis->Append(_L_CONTEXT("X", "Axis"));
|
||||||
m_move_axis->Append(_L("Y"));
|
m_move_axis->Append(_L_CONTEXT("Y", "Axis"));
|
||||||
m_move_axis->Append(_L("Z"));
|
m_move_axis->Append(_L_CONTEXT("Z", "Axis"));
|
||||||
m_move_axis->SetSelection(2);
|
m_move_axis->SetSelection(2);
|
||||||
mform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Rotation axis")), 0, wxALIGN_CENTER_VERTICAL);
|
mform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Rotation axis")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
mform->Add(m_move_axis, 0, wxEXPAND);
|
mform->Add(m_move_axis, 0, wxEXPAND);
|
||||||
@@ -1894,7 +1886,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
|
|
||||||
// --- Extrude dialog (consumes the selected sketch) ---
|
// --- Extrude dialog (consumes the selected sketch) ---
|
||||||
m_box_extrude = new wxBoxSizer(wxVERTICAL);
|
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_box_extrude->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||||
m_extrude_sketch_label = new wxStaticText(m_cards, wxID_ANY, _L("Sketch: —"));
|
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);
|
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/
|
// End condition (order MUST match ExtrudeEnd: Blind/Symmetric/TwoSided/ThroughAll/
|
||||||
// UpToFace/UpToVertex). Up-to-face uses the currently click-selected solid face.
|
// UpToFace/UpToVertex). Up-to-face uses the currently click-selected solid face.
|
||||||
m_extrude_end = make_combo(m_cards);
|
m_extrude_end = make_combo(m_cards);
|
||||||
for (const char* s : { "Blind", "Symmetric", "Two-sided", "Through all",
|
for (const char* s : { L("Blind"), L("Symmetric"), L("Two-sided"), L("Through all"),
|
||||||
"Up to face", "Up to vertex" })
|
L("Up to face"), L("Up to vertex") })
|
||||||
m_extrude_end->Append(s);
|
m_extrude_end->Append(_L(s));
|
||||||
m_extrude_end->SetSelection(0);
|
m_extrude_end->SetSelection(0);
|
||||||
eform->Add(new wxStaticText(m_cards, wxID_ANY, _L("End")), 0, wxALIGN_CENTER_VERTICAL);
|
eform->Add(new wxStaticText(m_cards, wxID_ANY, _L("End")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
eform->Add(m_extrude_end, 0, wxEXPAND);
|
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).
|
// 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.
|
// 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("New body")); // separate coexisting solid
|
||||||
m_mode->Append(_L("Join")); // fuse into the target body (was "Add")
|
m_mode->Append(_L_CONTEXT("Join", "Boolean Mode")); // fuse into the target body (was "Add")
|
||||||
m_mode->Append(_L("Cut")); // subtract from the target body
|
m_mode->Append(_L_CONTEXT("Cut", "Boolean Mode")); // subtract from the target body
|
||||||
m_mode->Append(_L("Intersect")); // keep only the overlap
|
m_mode->Append(_L("Intersect")); // keep only the overlap
|
||||||
m_mode->SetSelection(0);
|
m_mode->SetSelection(0);
|
||||||
eform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
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 = make_combo(m_cards);
|
||||||
m_face_group->Append(_L("Top")); // index 0 -> FaceGroup::Top
|
m_face_group->Append(_L("Top")); // index 0 -> FaceGroup::Top
|
||||||
m_face_group->Append(_L("Bottom")); // 1 -> Bottom
|
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("Lateral")); // 2 -> Lateral
|
||||||
m_face_group->Append(_L("All")); // 3 -> All
|
m_face_group->Append(_L("All")); // 3 -> All
|
||||||
m_face_group->SetSelection(3);
|
m_face_group->SetSelection(3);
|
||||||
@@ -1988,9 +1981,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
auto* hform = two_col_form();
|
auto* hform = two_col_form();
|
||||||
|
|
||||||
m_hole_plane = make_combo(m_cards);
|
m_hole_plane = make_combo(m_cards);
|
||||||
m_hole_plane->Append(_L("XY"));
|
m_hole_plane->Append(_L_CONTEXT("XY", "Axis"));
|
||||||
m_hole_plane->Append(_L("XZ"));
|
m_hole_plane->Append(_L_CONTEXT("XZ", "Axis"));
|
||||||
m_hole_plane->Append(_L("YZ"));
|
m_hole_plane->Append(_L_CONTEXT("YZ", "Axis"));
|
||||||
m_hole_plane->SetSelection(0);
|
m_hole_plane->SetSelection(0);
|
||||||
// Picking a plane here is an explicit choice: drop any on-face hijack (a stale face pick
|
// Picking a plane here is an explicit choice: drop any on-face hijack (a stale face pick
|
||||||
// could keep m_hole_on_face true, so the dropdown was ignored and the hole drilled on the
|
// could keep m_hole_on_face true, so the dropdown was ignored and the hole drilled on the
|
||||||
@@ -2041,9 +2034,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
auto* tform = two_col_form();
|
auto* tform = two_col_form();
|
||||||
|
|
||||||
m_thread_plane = make_combo(m_cards);
|
m_thread_plane = make_combo(m_cards);
|
||||||
m_thread_plane->Append(_L("XY"));
|
m_thread_plane->Append(_L_CONTEXT("XY", "Axis"));
|
||||||
m_thread_plane->Append(_L("XZ"));
|
m_thread_plane->Append(_L_CONTEXT("XZ", "Axis"));
|
||||||
m_thread_plane->Append(_L("YZ"));
|
m_thread_plane->Append(_L_CONTEXT("YZ", "Axis"));
|
||||||
m_thread_plane->SetSelection(0);
|
m_thread_plane->SetSelection(0);
|
||||||
tform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Thread plane")), 0, wxALIGN_CENTER_VERTICAL);
|
tform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Thread plane")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
tform->Add(m_thread_plane, 0, wxEXPAND);
|
tform->Add(m_thread_plane, 0, wxEXPAND);
|
||||||
@@ -2129,8 +2122,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
|
|
||||||
m_revolve_mode = make_combo(m_cards);
|
m_revolve_mode = make_combo(m_cards);
|
||||||
m_revolve_mode->Append(_L("New body")); // same four words as Extrude
|
m_revolve_mode->Append(_L("New body")); // same four words as Extrude
|
||||||
m_revolve_mode->Append(_L("Join"));
|
m_revolve_mode->Append(_L_CONTEXT("Join", "Boolean Mode"));
|
||||||
m_revolve_mode->Append(_L("Cut"));
|
m_revolve_mode->Append(_L_CONTEXT("Cut", "Boolean Mode"));
|
||||||
m_revolve_mode->Append(_L("Intersect"));
|
m_revolve_mode->Append(_L("Intersect"));
|
||||||
m_revolve_mode->SetSelection(0);
|
m_revolve_mode->SetSelection(0);
|
||||||
rform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
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 = make_combo(m_cards);
|
||||||
m_sweep_mode->Append(_L("New body")); // same four words as Extrude
|
m_sweep_mode->Append(_L("New body")); // same four words as Extrude
|
||||||
m_sweep_mode->Append(_L("Join"));
|
m_sweep_mode->Append(_L_CONTEXT("Join", "Boolean Mode"));
|
||||||
m_sweep_mode->Append(_L("Cut"));
|
m_sweep_mode->Append(_L_CONTEXT("Cut", "Boolean Mode"));
|
||||||
m_sweep_mode->Append(_L("Intersect"));
|
m_sweep_mode->Append(_L("Intersect"));
|
||||||
m_sweep_mode->SetSelection(0);
|
m_sweep_mode->SetSelection(0);
|
||||||
sform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
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) ---
|
// --- Pattern (replicate the target body: linear or circular) ---
|
||||||
m_box_pattern = new wxBoxSizer(wxVERTICAL);
|
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);
|
m_box_pattern->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||||
{
|
{
|
||||||
auto* pform = two_col_form();
|
auto* pform = two_col_form();
|
||||||
|
|
||||||
m_pattern_type = make_combo(m_cards);
|
m_pattern_type = make_combo(m_cards);
|
||||||
m_pattern_type->Append(_L("Linear"));
|
m_pattern_type->Append(_L_CONTEXT("Linear", "Design"));
|
||||||
m_pattern_type->Append(_L("Circular"));
|
m_pattern_type->Append(_L_CONTEXT("Circular", "Design"));
|
||||||
m_pattern_type->SetSelection(0);
|
m_pattern_type->SetSelection(0);
|
||||||
pform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Type")), 0, wxALIGN_CENTER_VERTICAL);
|
pform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Type")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
pform->Add(m_pattern_type, 0, wxEXPAND);
|
pform->Add(m_pattern_type, 0, wxEXPAND);
|
||||||
@@ -2215,7 +2208,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
auto* bform = two_col_form();
|
auto* bform = two_col_form();
|
||||||
|
|
||||||
m_bool_op = make_combo(m_cards);
|
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("Subtract"));
|
||||||
m_bool_op->Append(_L("Intersect"));
|
m_bool_op->Append(_L("Intersect"));
|
||||||
m_bool_op->SetSelection(0);
|
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 ---
|
// --- Cut (split a body with a plane): parameters only; ✓/✗ live on the ribbon ---
|
||||||
m_box_cut = new wxBoxSizer(wxVERTICAL);
|
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);
|
m_box_cut->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||||
{
|
{
|
||||||
auto* cform = two_col_form();
|
auto* cform = two_col_form();
|
||||||
@@ -2314,6 +2307,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
|
|
||||||
m_plane_base = make_combo(m_cards);
|
m_plane_base = make_combo(m_cards);
|
||||||
populate_plane_choices(m_plane_base); // XY/XZ/YZ + any existing datum planes
|
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(new wxStaticText(m_cards, wxID_ANY, _L("Base")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
plform->Add(m_plane_base, 0, wxEXPAND);
|
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 = make_combo(m_cards);
|
||||||
m_loft_mode->Append(_L("New body")); // same four words as Extrude
|
m_loft_mode->Append(_L("New body")); // same four words as Extrude
|
||||||
m_loft_mode->Append(_L("Join"));
|
m_loft_mode->Append(_L_CONTEXT("Join", "Boolean Mode"));
|
||||||
m_loft_mode->Append(_L("Cut"));
|
m_loft_mode->Append(_L_CONTEXT("Cut", "Boolean Mode"));
|
||||||
m_loft_mode->Append(_L("Intersect"));
|
m_loft_mode->Append(_L("Intersect"));
|
||||||
m_loft_mode->SetSelection(0);
|
m_loft_mode->SetSelection(0);
|
||||||
lform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Result")), 0, wxALIGN_CENTER_VERTICAL);
|
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);
|
sform->Add(m_shell_face_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
m_box_shell = new wxBoxSizer(wxVERTICAL);
|
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 wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||||
m_box_shell->Add(new wxStaticText(m_cards, wxID_ANY,
|
m_box_shell->Add(new wxStaticText(m_cards, wxID_ANY,
|
||||||
_L("Pick a solid face to open it, then set the wall thickness.")),
|
_L("Pick a solid face to open it, then set the wall thickness.")),
|
||||||
@@ -2564,9 +2558,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
xform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Translate Z")), 0, wxALIGN_CENTER_VERTICAL);
|
xform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Translate Z")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
xform->Add(spin_frame(m_xf_dz), 0, wxEXPAND);
|
xform->Add(spin_frame(m_xf_dz), 0, wxEXPAND);
|
||||||
m_xf_axis = make_combo(m_cards);
|
m_xf_axis = make_combo(m_cards);
|
||||||
m_xf_axis->Append(_L("X"));
|
m_xf_axis->Append(_L_CONTEXT("X", "Axis"));
|
||||||
m_xf_axis->Append(_L("Y"));
|
m_xf_axis->Append(_L_CONTEXT("Y", "Axis"));
|
||||||
m_xf_axis->Append(_L("Z"));
|
m_xf_axis->Append(_L_CONTEXT("Z", "Axis"));
|
||||||
m_xf_axis->SetSelection(2); // default Z
|
m_xf_axis->SetSelection(2); // default Z
|
||||||
m_xf_axis->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { refresh_preview(); });
|
m_xf_axis->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { refresh_preview(); });
|
||||||
xform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Rotate axis")), 0, wxALIGN_CENTER_VERTICAL);
|
xform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Rotate axis")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
@@ -2663,7 +2657,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
|
|
||||||
// --- Rib (thin wall from an open sketch line, fused to a body) ---
|
// --- Rib (thin wall from an open sketch line, fused to a body) ---
|
||||||
m_box_rib = new wxBoxSizer(wxVERTICAL);
|
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);
|
m_box_rib->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||||
{
|
{
|
||||||
auto* rform = two_col_form();
|
auto* rform = two_col_form();
|
||||||
@@ -2699,7 +2693,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
|
|
||||||
// --- Project (project body edges onto a plane as sketch entities) ---
|
// --- Project (project body edges onto a plane as sketch entities) ---
|
||||||
m_box_project = new wxBoxSizer(wxVERTICAL);
|
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);
|
m_box_project->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
|
||||||
{
|
{
|
||||||
auto* pform = two_col_form();
|
auto* pform = two_col_form();
|
||||||
@@ -2904,11 +2898,11 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
m_cs_x = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
m_cs_x = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||||
m_cs_y = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
m_cs_y = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||||
m_cs_z = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
m_cs_z = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("X")), 0, wxALIGN_CENTER_VERTICAL);
|
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L_CONTEXT("X", "Axis")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
csform->Add(spin_frame(m_cs_x), 0, wxEXPAND);
|
csform->Add(spin_frame(m_cs_x), 0, wxEXPAND);
|
||||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Y")), 0, wxALIGN_CENTER_VERTICAL);
|
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L_CONTEXT("Y", "Axis")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
csform->Add(spin_frame(m_cs_y), 0, wxEXPAND);
|
csform->Add(spin_frame(m_cs_y), 0, wxEXPAND);
|
||||||
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L("Z")), 0, wxALIGN_CENTER_VERTICAL);
|
csform->Add(new wxStaticText(m_cards, wxID_ANY, _L_CONTEXT("Z", "Axis")), 0, wxALIGN_CENTER_VERTICAL);
|
||||||
csform->Add(spin_frame(m_cs_z), 0, wxEXPAND);
|
csform->Add(spin_frame(m_cs_z), 0, wxEXPAND);
|
||||||
|
|
||||||
auto cs_pick = [&](const wxString& label, ::Button*& btn, wxStaticText*& lbl, CoordSysPick target) {
|
auto cs_pick = [&](const wxString& label, ::Button*& btn, wxStaticText*& lbl, CoordSysPick target) {
|
||||||
@@ -2937,11 +2931,11 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
|||||||
m_cs_hx = make_spin(m_cards, 1.0, -100000.0, 100000.0);
|
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_hy = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||||
m_cs_hz = 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(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(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);
|
csform->Add(spin_frame(m_cs_hz), 0, wxEXPAND);
|
||||||
|
|
||||||
m_box_coordsys->Add(csform, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 12);
|
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
|
// 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.
|
// of describing a problem with no way out.
|
||||||
if (const std::string* why = (sel >= 0) ? mate_conflict_reason(sel) : nullptr) {
|
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())) {
|
} else if (sel >= 0 && sel < int(m_doc.features.size())) {
|
||||||
// Name the two gestures the row supports, because neither is visible on it.
|
// Name the two gestures the row supports, because neither is visible on it.
|
||||||
set_status(StatusKind::Info, wxString::Format(
|
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);
|
if (got && m_viewport) m_viewport->set_escalate_on_repick(true);
|
||||||
}
|
}
|
||||||
const int nb = int(m_doc.bodies.size());
|
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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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.
|
// bodies-list lines already say it the right way.
|
||||||
set_status(level == 4 ? bodytag + _L("vertex selected — click again for the whole body")
|
set_status(level == 4 ? (bodytag ? wxString::Format(_L("Body %d: vertex selected — click again for the whole body"), body + 1)
|
||||||
: level == 1 ? bodytag + _L("selected (whole body) — right-click for what applies to it")
|
: _L("Vertex selected — click again for the whole body"))
|
||||||
: level == 2 ? bodytag + wxString::Format(_L("face %d selected — right-click to push/pull it, or click again for the whole body"), face)
|
: level == 1 ? (bodytag ? wxString::Format(_L("Body %d selected (whole body) — right-click for what applies to it"), body + 1)
|
||||||
: level == 3 && m_sel_solid_edges.size() > 1
|
: _L("Whole body selected — right-click for what applies to it"))
|
||||||
? 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 == 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)
|
||||||
: level == 3 ? bodytag + wxString::Format(_L("edge %d selected — Shift+click to add edges, or click again for the whole body"), edge)
|
: wxString::Format(_L("Face %d selected — right-click to push/pull it, or click again for the whole body"), face))
|
||||||
: _L("Nothing selected"));
|
: 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();
|
m_status->Refresh();
|
||||||
});
|
});
|
||||||
// A click on nothing drops a list row as it drops a pick. Not while a card is open: the
|
// 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())
|
if (m_viewport && m_viewport->is_sketching())
|
||||||
m_viewport->set_sketch_plane(plane_from_choice(m_ref_plane));
|
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
|
// 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
|
// 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.
|
// 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);
|
if (m_xf_angle) m_xf_angle->SetValue(sign * aa.angle() * 180.0 / M_PI);
|
||||||
}
|
}
|
||||||
const int nb = int(m_doc.bodies.size());
|
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();
|
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"),
|
set_status(StatusKind::Info, nb > 1
|
||||||
t.x(), t.y(), t.z()));
|
? 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
|
// 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));
|
set_status(error ? StatusKind::Error : StatusKind::Info, wxString::FromUTF8(msg));
|
||||||
});
|
});
|
||||||
m_viewport->set_on_sketch_exit_refused([this]() {
|
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.
|
// 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"));
|
m_dof_status->SetLabel(_L("✓ Fully constrained"));
|
||||||
} else if (dof > 0) {
|
} else if (dof > 0) {
|
||||||
m_dof_status->SetForegroundColour(dp_ctl_text());
|
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 {
|
} else {
|
||||||
m_dof_status->SetLabel(wxString());
|
m_dof_status->SetLabel(wxString());
|
||||||
}
|
}
|
||||||
@@ -4521,7 +4526,7 @@ void DesignPanel::set_ui_mode(UiMode m)
|
|||||||
if (sketching && m_sketch_banner_txt != nullptr)
|
if (sketching && m_sketch_banner_txt != nullptr)
|
||||||
m_sketch_banner_txt->SetLabel(
|
m_sketch_banner_txt->SetLabel(
|
||||||
wxString::Format(_L("Editing: Sketch %d · N = look normal to the plane · "
|
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_feature_counter + 1));
|
||||||
m_sketch_banner->Show(sketching);
|
m_sketch_banner->Show(sketching);
|
||||||
m_sketch_banner->GetParent()->Layout();
|
m_sketch_banner->GetParent()->Layout();
|
||||||
@@ -4778,7 +4783,7 @@ void DesignPanel::text_dialog_done(bool accepted)
|
|||||||
void DesignPanel::on_import_svg()
|
void DesignPanel::on_import_svg()
|
||||||
{
|
{
|
||||||
wxFileDialog dlg(this, _L("Import SVG"), wxEmptyString, wxEmptyString,
|
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);
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
@@ -4890,7 +4895,7 @@ bool DesignPanel::recompute_guarded(const wxString& message)
|
|||||||
void DesignPanel::on_import_step()
|
void DesignPanel::on_import_step()
|
||||||
{
|
{
|
||||||
wxFileDialog dlg(this, _L("Import STEP"), wxEmptyString, wxEmptyString,
|
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);
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
@@ -4938,7 +4943,9 @@ void DesignPanel::on_import_step()
|
|||||||
set_tree_selection(int(m_doc.features.size()) - 1);
|
set_tree_selection(int(m_doc.features.size()) - 1);
|
||||||
set_status_ok(); // canonical post-recompute viewport/pick/parts refresh
|
set_status_ok(); // canonical post-recompute viewport/pick/parts refresh
|
||||||
set_status(StatusKind::Info, wxString::Format(
|
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())));
|
int(solids.size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4949,7 +4956,7 @@ void DesignPanel::on_import_step()
|
|||||||
void DesignPanel::on_import_mesh()
|
void DesignPanel::on_import_mesh()
|
||||||
{
|
{
|
||||||
wxFileDialog dlg(this, _L("Import mesh"), wxEmptyString, wxEmptyString,
|
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);
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
@@ -5032,8 +5039,8 @@ void DesignPanel::on_import_mesh()
|
|||||||
stats.kept_tris, stats.faces_final, stats.volume));
|
stats.kept_tris, stats.faces_final, stats.volume));
|
||||||
} else {
|
} else {
|
||||||
set_status(StatusKind::Warning, wxString::Format(
|
set_status(StatusKind::Warning, wxString::Format(
|
||||||
_L("Imported as an open shell (not watertight): %d boundary edge(s), %d non-manifold "
|
_L("Imported as an open shell (not watertight). Boundary edges: %d, non-manifold "
|
||||||
"edge(s) — %d triangles → %d faces. The source mesh has holes or duplicated "
|
"edges: %d, triangles: %d → faces: %d. The source mesh has holes or duplicated "
|
||||||
"geometry; boolean features may fail on it"),
|
"geometry; boolean features may fail on it"),
|
||||||
stats.boundary_edges, stats.nonmanifold_edges, stats.kept_tris, stats.faces_final));
|
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);
|
set_ui_mode(UiMode::Feature);
|
||||||
sync_sketch_display();
|
sync_sketch_display();
|
||||||
refresh_tree();
|
refresh_tree();
|
||||||
set_status(StatusKind::Info, _L("Insert cancelled"));
|
set_status(StatusKind::Info, _L("Insert canceled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignPanel::on_transform_imported(int feat_idx)
|
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_doc.add_sketch(shape, plane, m_width->GetValue(), m_height->GetValue(),
|
||||||
m_radius->GetValue(), feature_name(_L("Sketch")));
|
m_radius->GetValue(), feature_name(_L("Sketch")));
|
||||||
m_doc.recompute(); // a lone sketch yields an empty body; that is expected
|
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();
|
refresh_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5882,7 +5889,8 @@ void DesignPanel::on_check_interference()
|
|||||||
body_name(sorted[k].body_b), sorted[k].volume);
|
body_name(sorted[k].body_b), sorted[k].volume);
|
||||||
if (sorted.size() > shown)
|
if (sorted.size() > shown)
|
||||||
list += wxString::FromUTF8(", …");
|
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,
|
// Volume and surface area of the selected body. A report, not a feature: it never checkpoints,
|
||||||
@@ -6082,7 +6090,7 @@ void DesignPanel::populate_plane_choices(ComboBox* c) const
|
|||||||
if (!c) return;
|
if (!c) return;
|
||||||
const int keep = c->GetSelection();
|
const int keep = c->GetSelection();
|
||||||
c->Clear();
|
c->Clear();
|
||||||
c->Append(_L("XY")); c->Append(_L("XZ")); c->Append(_L("YZ"));
|
c->Append(_L_CONTEXT("XY", "Axis")); c->Append(_L_CONTEXT("XZ", "Axis")); c->Append(_L_CONTEXT("YZ", "Axis"));
|
||||||
for (const auto& dp : m_doc.resolve_datum_planes())
|
for (const auto& dp : m_doc.resolve_datum_planes())
|
||||||
c->Append(wxString::FromUTF8(dp.first));
|
c->Append(wxString::FromUTF8(dp.first));
|
||||||
c->SetSelection((keep >= 0 && keep < int(c->GetCount())) ? keep : 0);
|
c->SetSelection((keep >= 0 && keep < int(c->GetCount())) ? keep : 0);
|
||||||
@@ -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;
|
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)) {
|
if (fb >= 0 && fi >= 0 && m_doc.plane_of_face(fb, fi, p)) {
|
||||||
what = (m_doc.bodies.size() > 1)
|
what = (m_doc.bodies.size() > 1)
|
||||||
? wxString::Format(_L("the picked face of Body %d"), fb + 1)
|
? wxString::Format(_L("Picked face (Body %d)"), fb + 1)
|
||||||
: _L("the picked face");
|
: _L("Picked face");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
what = ref_plane_name(m_ref_plane);
|
what = ref_plane_name(m_ref_plane);
|
||||||
@@ -6150,8 +6158,8 @@ bool DesignPanel::sketch_plane_target(wxString& what) const
|
|||||||
SketchPlane p;
|
SketchPlane p;
|
||||||
if (fb >= 0 && fi >= 0 && m_doc.plane_of_face(fb, fi, p)) {
|
if (fb >= 0 && fi >= 0 && m_doc.plane_of_face(fb, fi, p)) {
|
||||||
what = (m_doc.bodies.size() > 1)
|
what = (m_doc.bodies.size() > 1)
|
||||||
? wxString::Format(_L("the picked face of Body %d"), fb + 1)
|
? wxString::Format(_L("Picked face (Body %d)"), fb + 1)
|
||||||
: _L("the picked face");
|
: _L("Picked face");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (m_plane_picked) { what = ref_plane_name(m_ref_plane); 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) {
|
switch (m) {
|
||||||
case Mode::Select:
|
case Mode::Select:
|
||||||
return picks > 0
|
return picks > 0
|
||||||
? wxString::Format(_L("%d selected · Del removes them · Shift-click adds · "
|
? wxString::Format(_L_PLURAL("%d selected · Del removes it · Shift-click adds · "
|
||||||
"double-click takes the whole loop"), picks)
|
"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 · "
|
: _L("Select — click an entity to pick it · drag an endpoint or center to move it · "
|
||||||
"Shift-click adds · Del removes");
|
"Shift-click adds · Del removes");
|
||||||
case Mode::Constrain:
|
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
|
return (v.accepts & bit) && v.need_bodies <= bodies && v.need_sketches <= sketches
|
||||||
&& (!v.need_sheet || sheet);
|
&& (!v.need_sheet || sheet);
|
||||||
};
|
};
|
||||||
// Names and reasons live in the generated table as plain literals; they are the same strings
|
// Row names, verb names, refusals, families and hints are L()-marked in the generated table.
|
||||||
// the toolbar already ships, so the catalogue already carries their translations.
|
|
||||||
// Scope the lookup to the APPLICATION catalog. A bare wxGetTranslation() searches every
|
// 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
|
// 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,
|
// 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);
|
return wxGetTranslation(wxString::FromUTF8(s), SLIC3R_APP_KEY);
|
||||||
};
|
};
|
||||||
auto label = [&](const OfferVerb& v) {
|
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);
|
if (v.key && *v.key) s += "\t" + wxString::FromUTF8(v.key);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
@@ -7630,8 +7639,8 @@ void DesignPanel::flip_section_view()
|
|||||||
if (!m_viewport || !m_section_on) return;
|
if (!m_viewport || !m_section_on) return;
|
||||||
m_section_upper = !m_section_upper;
|
m_section_upper = !m_section_upper;
|
||||||
m_viewport->set_section_plane(true, m_section_cut_z, 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"),
|
set_status(StatusKind::Info, m_section_upper ? _L("Section view — showing the upper half")
|
||||||
m_section_upper ? _L("upper") : _L("lower")));
|
: _L("Section view — showing the lower half"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignPanel::sync_body_visible()
|
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
|
// 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
|
// one is selected and the button correctly refuses. Say how many are picked, or the
|
||||||
// refusal is indistinguishable from a dead button.
|
// refusal is indistinguishable from a dead button.
|
||||||
fail(wxString::Format(_L("%s — %d selected. Press Esc for the Select tool, click one "
|
fail(wxString::Format(_L_PLURAL("%s — %d selected. Press Esc for the Select tool, click one "
|
||||||
"line, then Shift- or Ctrl-click the other."),
|
"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())));
|
constraint_reject_text(plan.reason, type), int(sel.size())));
|
||||||
return;
|
return;
|
||||||
case ConstraintPlan::Kind::AskValue:
|
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());
|
m_dof_status->SetLabel(_L("✓ Fully constrained")); m_dof_status->Show(!m_dof_status->GetLabel().IsEmpty());
|
||||||
} else if (r.dof > 0) {
|
} else if (r.dof > 0) {
|
||||||
m_dof_status->SetForegroundColour(dp_ctl_text());
|
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 {
|
} else {
|
||||||
m_dof_status->SetLabel(wxString()); m_dof_status->Show(!m_dof_status->GetLabel().IsEmpty());
|
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.
|
// an empty string, or a NULL format string that crashes wxString::Format.
|
||||||
wxString s; s << wxUniChar(c) << ei; // avoid %c assert in Unicode build
|
wxString s; s << wxUniChar(c) << ei; // avoid %c assert in Unicode build
|
||||||
if (r == SketchPointRole::P1) s += wxString::FromUTF8("·P1");
|
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");
|
else if (r == SketchPointRole::P0) s += wxString::FromUTF8("·P0");
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
@@ -8408,27 +8420,27 @@ wxString DesignPanel::constraint_label(const SketchEntityConstraintDef& d) const
|
|||||||
};
|
};
|
||||||
switch (d.type) {
|
switch (d.type) {
|
||||||
case T::Fix: return wxString::Format(_L("Fix %s"), tag(d.ea, d.ra));
|
case T::Fix: return wxString::Format(_L("Fix %s"), tag(d.ea, d.ra));
|
||||||
case T::Coincident: return two(_L("Coincident"));
|
case T::Coincident: return two(_L_CONTEXT("Coincident", "Sketch Constraint"));
|
||||||
case T::Horizontal: return two(_L("Horizontal"));
|
case T::Horizontal: return two(_L_CONTEXT("Horizontal", "Sketch Constraint"));
|
||||||
case T::Vertical: return two(_L("Vertical"));
|
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::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::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::LockY: return wxString::Format(_L("Lock Y %s"), tag(d.ea, d.ra));
|
||||||
case T::EqualLength: return two(_L("Equal"));
|
case T::EqualLength: return two(_L_CONTEXT("Equal", "Sketch Constraint"));
|
||||||
case T::Parallel: return two(_L("Parallel"));
|
case T::Parallel: return two(_L_CONTEXT("Parallel", "Sketch Constraint"));
|
||||||
case T::Perpendicular: return two(_L("Perpendicular"));
|
case T::Perpendicular: return two(_L_CONTEXT("Perpendicular", "Sketch Constraint"));
|
||||||
case T::Concentric: return two(_L("Concentric"));
|
case T::Concentric: return two(_L_CONTEXT("Concentric", "Sketch Constraint"));
|
||||||
case T::Tangent: return two(_L("Tangent"));
|
case T::Tangent: return two(_L_CONTEXT("Tangent", "Sketch Constraint"));
|
||||||
case T::Midpoint: return two(_L("Midpoint"));
|
case T::Midpoint: return two(_L_CONTEXT("Midpoint", "Sketch Constraint"));
|
||||||
case T::Symmetric: return wxString::Format(_L("Symmetric %s — %s / %s"),
|
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));
|
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"),
|
case T::SymmetricAboutY: return wxString::Format(_L("Symmetric about Y axis %s — %s"),
|
||||||
tag(d.ea, d.ra), tag(d.eb, d.rb));
|
tag(d.ea, d.ra), tag(d.eb, d.rb));
|
||||||
case T::SymmetricAboutX: return wxString::Format(_L("Symmetric about X axis %s — %s"),
|
case T::SymmetricAboutX: return wxString::Format(_L("Symmetric about X axis %s — %s"),
|
||||||
tag(d.ea, d.ra), tag(d.eb, d.rb));
|
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::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("Radius"), tag(d.ea, d.ra), en_format(d.value));
|
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("Diameter"), 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::PointOnLine: return two(_L("On line"));
|
||||||
case T::PointOnObject: return two(_L("On edge"));
|
case T::PointOnObject: return two(_L("On edge"));
|
||||||
}
|
}
|
||||||
@@ -9702,7 +9714,7 @@ void DesignPanel::load_feature_into_dialog(const CadFeature& f)
|
|||||||
wxString s;
|
wxString s;
|
||||||
for (size_t i = 0; i < m_del_faces.size(); ++i) {
|
for (size_t i = 0; i < m_del_faces.size(); ++i) {
|
||||||
if (i > 0) s += ", ";
|
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);
|
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->set_display_sketches({});
|
||||||
m_viewport->edit_sketch(f.entities, f.entity_constraints, f.plane);
|
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 {
|
} else {
|
||||||
load_feature_into_dialog(f);
|
load_feature_into_dialog(f);
|
||||||
open_tool(Tool::Sketch);
|
open_tool(Tool::Sketch);
|
||||||
@@ -9963,7 +9975,7 @@ void DesignPanel::on_export_step()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wxFileDialog dlg(this, _L("Export STEP"), wxEmptyString, "model.step",
|
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);
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
@@ -11480,20 +11492,20 @@ void DesignPanel::open_tool(Tool t)
|
|||||||
};
|
};
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case Tool::Sketch: m_hdr_sketch->SetLabel(title(_L("Sketch"))); break;
|
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(
|
case Tool::Dressup: m_hdr_dressup->SetLabel(title(
|
||||||
m_dressup_type->GetSelection() == 0 ? _L("Fillet") : _L("Chamfer"))); break;
|
m_dressup_type->GetSelection() == 0 ? _L("Fillet") : _L("Chamfer"))); break;
|
||||||
case Tool::Hole: m_hdr_hole->SetLabel(title(_L("Hole"))); 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::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::Revolve: m_hdr_revolve->SetLabel(title(_L("Revolve"))); break;
|
||||||
case Tool::Sweep: m_hdr_sweep->SetLabel(title(_L("Sweep"))); 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::Plane: m_hdr_plane->SetLabel(title(_L("Plane"))); break;
|
||||||
case Tool::Loft: m_hdr_loft->SetLabel(title(_L("Loft"))); 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::Draft: m_hdr_draft->SetLabel(title(_L("Draft"))); break;
|
||||||
case Tool::Boolean: m_hdr_boolean->SetLabel(title(_L("Boolean"))); 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::Axis: m_hdr_axis->SetLabel(title(_L("Axis"))); break;
|
||||||
case Tool::CoordSys: m_hdr_coordsys->SetLabel(title(_L("Coordinate system"))); 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;
|
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::Transform: m_hdr_transform->SetLabel(title(_L("Transform"))); break;
|
||||||
case Tool::Mirror: m_hdr_mirror->SetLabel(title(_L("Mirror"))); 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::Thicken: m_hdr_thicken->SetLabel(title(_L("Thicken"))); break;
|
||||||
case Tool::Rib: m_hdr_rib->SetLabel(title(_L("Rib"))); break;
|
case Tool::Rib: m_hdr_rib->SetLabel(title(_L_CONTEXT("Rib", "Design"))); break;
|
||||||
case Tool::Project: m_hdr_project->SetLabel(title(_L("Project"))); 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::DeleteFace: m_hdr_delete_face->SetLabel(title(_L("Delete Face"))); break;
|
||||||
case Tool::Helix: m_hdr_helix->SetLabel(title(_L("Helix"))); break;
|
case Tool::Helix: m_hdr_helix->SetLabel(title(_L("Helix"))); break;
|
||||||
case Tool::Mate: m_hdr_mate->SetLabel(title(_L("Mate"))); break;
|
case Tool::Mate: m_hdr_mate->SetLabel(title(_L("Mate"))); break;
|
||||||
@@ -11743,7 +11755,7 @@ void DesignPanel::tool_cancel()
|
|||||||
show_move_card(false);
|
show_move_card(false);
|
||||||
feed_bodies(); // re-render the reverted placement
|
feed_bodies(); // re-render the reverted placement
|
||||||
update_action_bar();
|
update_action_bar();
|
||||||
set_status(StatusKind::Info, _L("Move cancelled"));
|
set_status(StatusKind::Info, _L("Move canceled"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_active == Tool::Insert) { cancel_insert(); return; }
|
if (m_active == Tool::Insert) { cancel_insert(); return; }
|
||||||
@@ -11873,7 +11885,7 @@ void DesignPanel::escape()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_ui_mode == UiMode::Sketch) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -11956,8 +11968,10 @@ void DesignPanel::do_undo_redo(bool redo)
|
|||||||
drop_selection();
|
drop_selection();
|
||||||
reset_edit_state();
|
reset_edit_state();
|
||||||
after_tree_edit(true); // refresh tree + viewport meshes + status from the restored doc
|
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)"),
|
const size_t depth = redo ? m_doc.redo_depth() : m_doc.undo_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 ---------------------------------------------------------
|
// --- 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;
|
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 double side = (m_entities[f.begin].p1 - m_entities[f.begin].p0).norm();
|
||||||
const wxPoint px(m_last_mouse_x, m_last_mouse_y);
|
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"),
|
on_inline_edit(px, side, _u8L("Side"),
|
||||||
[this, fi](double v) { set_polygon_side(fi, v); },
|
[this, fi](double v) { set_polygon_side(fi, v); },
|
||||||
[]() {});
|
[]() {});
|
||||||
@@ -9844,7 +9845,7 @@ std::string DesignSketchTool::build_readout() const
|
|||||||
std::string out = b;
|
std::string out = b;
|
||||||
// Tell the user how to end a polyline chain — there's no other affordance for it.
|
// 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)
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
if (!m_active) return std::string();
|
if (!m_active) return std::string();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "CalibUtils.hpp"
|
#include "CalibUtils.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
#include "Widgets/Label.hpp"
|
#include "Widgets/Label.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
#include "DeviceCore/DevConfigUtil.h"
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
@@ -67,13 +68,13 @@ static wxString get_default_name(wxString filament_name, CalibMode mode){
|
|||||||
case Slic3r::CalibMode::Calib_PA_Tower:
|
case Slic3r::CalibMode::Calib_PA_Tower:
|
||||||
break;
|
break;
|
||||||
case Slic3r::CalibMode::Calib_Flow_Rate:
|
case Slic3r::CalibMode::Calib_Flow_Rate:
|
||||||
filament_name += " Flow Rate Calibrated";
|
filament_name = format_wxstr(_L("%1% Flow Rate Calibrated"), filament_name);
|
||||||
break;
|
break;
|
||||||
case Slic3r::CalibMode::Calib_Temp_Tower:
|
case Slic3r::CalibMode::Calib_Temp_Tower:
|
||||||
filament_name += " Temperature Calibrated";
|
filament_name = format_wxstr(_L("%1% Temperature Calibrated"), filament_name);
|
||||||
break;
|
break;
|
||||||
case Slic3r::CalibMode::Calib_Vol_speed_Tower:
|
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;
|
break;
|
||||||
case Slic3r::CalibMode::Calib_VFA_Tower:
|
case Slic3r::CalibMode::Calib_VFA_Tower:
|
||||||
break;
|
break;
|
||||||
@@ -95,7 +96,7 @@ static wxString get_tray_name_by_tray_id(int tray_id)
|
|||||||
{
|
{
|
||||||
wxString tray_name;
|
wxString tray_name;
|
||||||
if (tray_id == VIRTUAL_TRAY_MAIN_ID || tray_id == VIRTUAL_TRAY_DEPUTY_ID) {
|
if (tray_id == VIRTUAL_TRAY_MAIN_ID || tray_id == VIRTUAL_TRAY_DEPUTY_ID) {
|
||||||
tray_name = "Ext";
|
tray_name = _L("Ext");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int ams_id = tray_id / 4;
|
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)
|
for (const auto& item : prusa_profiles)
|
||||||
list->append(item, &const_cast<std::string&>(item.get()));
|
list->append(item, &const_cast<std::string&>(item.get()));
|
||||||
for (const auto& item : other_profiles)
|
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)
|
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)
|
PageCustom::PageCustom(ConfigWizard *parent)
|
||||||
: ConfigWizardPage(parent, _L("Custom Printer Setup"), _L("Custom Printer"))
|
: ConfigWizardPage(parent, _L("Custom Printer Setup"), _L("Custom Printer"))
|
||||||
{
|
{
|
||||||
cb_custom = new wxCheckBox(this, wxID_ANY, _L("Define a custom printer profile"));
|
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:"));
|
auto *label = new wxStaticText(this, wxID_ANY, _L("Custom profile name:"));
|
||||||
|
|
||||||
wxGetApp().UpdateDarkUI(tc_profile_name);
|
wxGetApp().UpdateDarkUI(tc_profile_name);
|
||||||
@@ -1224,7 +1224,7 @@ PageCustom::PageCustom(ConfigWizard *parent)
|
|||||||
tc_profile_name->Enable(false);
|
tc_profile_name->Enable(false);
|
||||||
tc_profile_name->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &evt) {
|
tc_profile_name->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &evt) {
|
||||||
if (tc_profile_name->GetValue().IsEmpty()) {
|
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 { tc_profile_name->SetValue(profile_name_prev); }
|
||||||
} else {
|
} else {
|
||||||
profile_name_prev = tc_profile_name->GetValue();
|
profile_name_prev = tc_profile_name->GetValue();
|
||||||
@@ -1463,7 +1463,7 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent)
|
|||||||
auto *default_bed = def_bed.get_default_value<ConfigOptionInts>();
|
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);
|
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."));
|
append_text(_L("A rule of thumb is 160 to 230℃ for PLA, and 215 to 250℃ for ABS."));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1720,7 +1720,7 @@ void ConfigWizardIndex::msw_rescale()
|
|||||||
|
|
||||||
// Materials
|
// Materials
|
||||||
|
|
||||||
const std::string Materials::UNKNOWN = "(Unknown)";
|
const std::string Materials::UNKNOWN = L("(Unknown)");
|
||||||
|
|
||||||
void Materials::push(const Preset *preset)
|
void Materials::push(const Preset *preset)
|
||||||
{
|
{
|
||||||
@@ -2188,8 +2188,8 @@ void ConfigWizard::priv::select_default_materials_for_printer_models(Technology
|
|||||||
}
|
}
|
||||||
printer_names += "\n\n";
|
printer_names += "\n\n";
|
||||||
std::string message = (technology & T_FFF ?
|
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("The following printer profiles have 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 material: %1%Please select one manually."), printer_names));
|
||||||
MessageDialog msg(q, message, _L("Notice"), wxOK);
|
MessageDialog msg(q, message, _L("Notice"), wxOK);
|
||||||
msg.ShowModal();
|
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)
|
||||||
if ((check_unsaved_preset_changes = install_bundles.size() > 0))
|
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
|
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
|
||||||
bool snapshot = true;
|
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("Hostname"), wxLIST_FORMAT_LEFT, 14 * em);
|
||||||
m_list->AppendColumn(_L("IP"), 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();
|
auto* ok_btn = dlg_btns->GetOK();
|
||||||
ok_btn->SetLabel(_L("Use Selected"));
|
ok_btn->SetLabel(_L("Use Selected"));
|
||||||
ok_btn->Disable();
|
ok_btn->Disable();
|
||||||
@@ -91,7 +91,7 @@ void CrealityDiscoveryDialog::run_discovery()
|
|||||||
if (!h.model_name.empty())
|
if (!h.model_name.empty())
|
||||||
row.model = h.model_name;
|
row.model = h.model_name;
|
||||||
else if (h.cfs_capable)
|
else if (h.cfs_capable)
|
||||||
row.model = "(unknown K-series)";
|
row.model = _u8L("(unknown K-series)");
|
||||||
else
|
else
|
||||||
row.model = "Creality";
|
row.model = "Creality";
|
||||||
m_rows.push_back(std::move(row));
|
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.");
|
wxString text = _L("Desktop Integration sets this binary to be searchable by the system.\n\nPress \"Perform\" to proceed.");
|
||||||
if (can_undo)
|
if (can_undo)
|
||||||
text += "\nPress \"Undo\" to remove previous integration.";
|
text += "\n" + _L("Press \"Undo\" to remove previous integration.");
|
||||||
|
|
||||||
vbox->Add(
|
vbox->Add(
|
||||||
new wxStaticText( this, wxID_ANY, text),
|
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") {
|
} else if (reason == "nozzle_diameter is not matched") {
|
||||||
info = _L("Selected diameter and machine diameter do not match");
|
info = _L("Selected diameter and machine diameter do not match");
|
||||||
} else if (reason == "generate auto filament cali gcode failure") {
|
} 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 {
|
} else {
|
||||||
info = wxString(reason);
|
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");
|
info = _L("Selected diameter and machine diameter do not match");
|
||||||
}
|
}
|
||||||
else if (reason == "generate auto filament cali gcode failure") {
|
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 {
|
else {
|
||||||
info = reason;
|
info = reason;
|
||||||
|
|||||||
@@ -981,7 +981,7 @@ int ReselectMachineDialog::CaculateSwitcherDistribution(MachineObject* obj, cons
|
|||||||
}
|
}
|
||||||
if (can.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY)
|
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){
|
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);
|
text_sizer->Add(m_text_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
if (!m_wiki_url.IsEmpty()) {
|
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->SetNormalColour(m_colour);
|
||||||
m_wiki_link->SetHoverColour(wxColour(0, 0, 200));
|
m_wiki_link->SetHoverColour(wxColour(0, 0, 200));
|
||||||
m_wiki_link->SetVisitedColour(*wxBLUE);
|
m_wiki_link->SetVisitedColour(*wxBLUE);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
|
||||||
#include <wx/arrstr.h>
|
#include <wx/arrstr.h>
|
||||||
|
|
||||||
@@ -165,7 +166,7 @@ void Downloader::start_download(const std::string& full_url)
|
|||||||
// Orca: show error
|
// Orca: show error
|
||||||
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
|
||||||
ntf_mngr->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel,
|
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;
|
return;
|
||||||
}
|
}
|
||||||
size_t id = get_next_id();
|
size_t id = get_next_id();
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ void FileGet::priv::get_perform()
|
|||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
|
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);
|
evt->SetInt(m_id);
|
||||||
m_evt_handler->QueueEvent(evt);
|
m_evt_handler->QueueEvent(evt);
|
||||||
return;
|
return;
|
||||||
@@ -367,7 +367,7 @@ void FileGet::priv::get_perform()
|
|||||||
//TODO: report?
|
//TODO: report?
|
||||||
//error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path);
|
//error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path);
|
||||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
|
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);
|
evt->SetInt(m_id);
|
||||||
m_evt_handler->QueueEvent(evt);
|
m_evt_handler->QueueEvent(evt);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ EditGCodeDialog::EditGCodeDialog(wxWindow* parent, const std::string& key, const
|
|||||||
m_search_bar->ShowCancelButton(true);
|
m_search_bar->ShowCancelButton(true);
|
||||||
m_search_bar->SetDescriptiveText(_L("Search G-code placeholders"));
|
m_search_bar->SetDescriptiveText(_L("Search G-code placeholders"));
|
||||||
m_search_bar->SetForegroundColour(*wxBLACK);
|
m_search_bar->SetForegroundColour(*wxBLACK);
|
||||||
|
m_search_bar->SetBackgroundColour(*wxWHITE);
|
||||||
wxGetApp().UpdateDarkUI(m_search_bar);
|
wxGetApp().UpdateDarkUI(m_search_bar);
|
||||||
|
|
||||||
m_search_bar->Bind(wxEVT_SET_FOCUS, [](wxFocusEvent&) {
|
m_search_bar->Bind(wxEVT_SET_FOCUS, [](wxFocusEvent&) {
|
||||||
@@ -90,6 +91,7 @@ EditGCodeDialog::EditGCodeDialog(wxWindow* parent, const std::string& key, const
|
|||||||
param_sizer->Add(m_search_bar, 0, wxEXPAND | wxALL, border);
|
param_sizer->Add(m_search_bar, 0, wxEXPAND | wxALL, border);
|
||||||
|
|
||||||
m_params_list = new ParamsViewCtrl(this, wxDefaultSize);
|
m_params_list = new ParamsViewCtrl(this, wxDefaultSize);
|
||||||
|
m_params_list->SetBackgroundColour(*wxWHITE);
|
||||||
m_params_list->SetFont(wxGetApp().code_font());
|
m_params_list->SetFont(wxGetApp().code_font());
|
||||||
wxGetApp().UpdateDarkUI(m_params_list);
|
wxGetApp().UpdateDarkUI(m_params_list);
|
||||||
param_sizer->Add(m_params_list, 1, wxEXPAND | wxALL, border);
|
param_sizer->Add(m_params_list, 1, wxEXPAND | wxALL, border);
|
||||||
@@ -104,6 +106,7 @@ EditGCodeDialog::EditGCodeDialog(wxWindow* parent, const std::string& key, const
|
|||||||
);
|
);
|
||||||
|
|
||||||
m_gcode_editor->SetFont(wxGetApp().code_font());
|
m_gcode_editor->SetFont(wxGetApp().code_font());
|
||||||
|
m_gcode_editor->SetBackgroundColour(*wxWHITE);
|
||||||
m_gcode_editor->SetInsertionPointEnd();
|
m_gcode_editor->SetInsertionPointEnd();
|
||||||
wxGetApp().UpdateDarkUI(m_gcode_editor);
|
wxGetApp().UpdateDarkUI(m_gcode_editor);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
|
|
||||||
using json = nlohmann::json;
|
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; }
|
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
|
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)
|
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();
|
OnRequestPresets();
|
||||||
} else if (strCmd == "export_local") {
|
} else if (strCmd == "export_local") {
|
||||||
wxFileDialog dlg(this, _L("Save preset bundle"), "", "export.orca_bundle",
|
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 path;
|
||||||
wxString name;
|
wxString name;
|
||||||
if (dlg.ShowModal() == wxID_OK) {
|
if (dlg.ShowModal() == wxID_OK) {
|
||||||
|
|||||||
@@ -1015,8 +1015,11 @@ void TextCtrl::BUILD() {
|
|||||||
if (m_opt.is_code)
|
if (m_opt.is_code)
|
||||||
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||||
|
|
||||||
|
if(m_opt.multiline){
|
||||||
|
temp->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#262E30"))); // only effects wxTextCtrl
|
||||||
|
temp->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
||||||
|
}
|
||||||
|
|
||||||
temp->SetForegroundColour(StateColor::darkModeColorFor(*wxBLACK));
|
|
||||||
wxGetApp().UpdateDarkUI(temp);
|
wxGetApp().UpdateDarkUI(temp);
|
||||||
|
|
||||||
if (! m_opt.multiline && !wxOSX)
|
if (! m_opt.multiline && !wxOSX)
|
||||||
@@ -2176,7 +2179,8 @@ void PrinterAgentChoice::set_value(const std::string& value, bool change_event)
|
|||||||
if (match == wxNOT_FOUND)
|
if (match == wxNOT_FOUND)
|
||||||
{
|
{
|
||||||
field->SetSelection(wxNOT_FOUND); // nothing shows as selected in the dropdown
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -2505,7 +2509,7 @@ nlohmann::json plugin_overrides_as_json(const std::string& text)
|
|||||||
|
|
||||||
void PluginConfigField::BUILD()
|
void PluginConfigField::BUILD()
|
||||||
{
|
{
|
||||||
m_button = new ::Button(m_parent, _L("Configure"));
|
m_button = new ::Button(m_parent, _L("Configure") + dots);
|
||||||
// ButtonType::Parameter gives the button the same height as the parameter fields above it.
|
// ButtonType::Parameter gives the button the same height as the parameter fields above it.
|
||||||
m_button->SetStyle(ButtonStyle::Regular, ButtonType::Parameter);
|
m_button->SetStyle(ButtonStyle::Regular, ButtonType::Parameter);
|
||||||
|
|
||||||
@@ -2535,7 +2539,7 @@ void PluginConfigField::update_button_label()
|
|||||||
const nlohmann::json entries = plugin_overrides_as_json(m_json);
|
const nlohmann::json entries = plugin_overrides_as_json(m_json);
|
||||||
const size_t count = entries.is_array() ? entries.size() : 0;
|
const size_t count = entries.is_array() ? entries.size() : 0;
|
||||||
|
|
||||||
m_button->SetLabel(count == 0 ? _L("Configure")
|
m_button->SetLabel(count == 0 ? _L("Configure" + dots)
|
||||||
: wxString::Format(_L("Configure (%d)"), int(count)));
|
: wxString::Format(_L("Configure (%d)"), int(count)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ FilamentMapDialog::FilamentMapDialog(wxWindow *parent,
|
|||||||
|
|
||||||
bottom_sizer->Add(dlg_btns, 0, wxEXPAND);
|
bottom_sizer->Add(dlg_btns, 0, wxEXPAND);
|
||||||
}
|
}
|
||||||
main_sizer->Add(bottom_panel, 0, wxEXPAND);
|
main_sizer->Add(bottom_panel, 0, wxEXPAND | wxTOP, FromDIP(15));
|
||||||
|
|
||||||
m_ok_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_ok, this);
|
m_ok_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_ok, this);
|
||||||
m_cancel_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_cancel, this);
|
m_cancel_btn->Bind(wxEVT_BUTTON, &FilamentMapDialog::on_cancel, this);
|
||||||
|
|||||||
@@ -454,7 +454,8 @@ void FilamentMapManualPanel::UpdateNozzleCountDisplay()
|
|||||||
if (m_right_panel->IsUseSeparation()) {
|
if (m_right_panel->IsUseSeparation()) {
|
||||||
int standard_count = getExtruderNozzleCount(preset_bundle, 1, NozzleVolumeType::nvtStandard);
|
int standard_count = getExtruderNozzleCount(preset_bundle, 1, NozzleVolumeType::nvtStandard);
|
||||||
int highflow_count = getExtruderNozzleCount(preset_bundle, 1, NozzleVolumeType::nvtHighFlow);
|
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);
|
m_right_panel->UpdateLabel(right_title);
|
||||||
} else {
|
} else {
|
||||||
int right_count = getExtruderNozzleCountTotal(preset_bundle, 1);
|
int right_count = getExtruderNozzleCountTotal(preset_bundle, 1);
|
||||||
@@ -524,22 +525,26 @@ GUI::FilamentMapBtnPanel::FilamentMapBtnPanel(wxWindow *parent, const wxString &
|
|||||||
m_btn = new wxBitmapButton(this, wxID_ANY, icon_enabled, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
|
m_btn = new wxBitmapButton(this, wxID_ANY, icon_enabled, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
|
||||||
m_btn->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
m_btn->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||||
|
|
||||||
|
auto icon_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
icon_sizer->Add(m_btn , 0, wxLEFT, horizontal_margin);
|
||||||
|
|
||||||
m_label = new wxStaticText(this, wxID_ANY, label);
|
m_label = new wxStaticText(this, wxID_ANY, label);
|
||||||
m_label->SetFont(Label::Head_14);
|
m_label->SetFont(Label::Head_14);
|
||||||
m_label->SetForegroundColour(TextNormalBlackColor);
|
m_label->SetForegroundColour(TextNormalBlackColor);
|
||||||
|
|
||||||
auto label_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto label_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
label_sizer->AddStretchSpacer();
|
label_sizer->Add(m_label, 0, wxLEFT, horizontal_margin);
|
||||||
label_sizer->Add(m_btn, 0, wxEXPAND | wxLEFT, FromDIP(1));
|
|
||||||
label_sizer->Add(m_label, 0, wxEXPAND| wxALL, FromDIP(3));
|
|
||||||
label_sizer->AddStretchSpacer();
|
|
||||||
|
|
||||||
m_disable_tip = new Label(this, _L("(Sync with printer)"));
|
m_disable_tip = new Label(this, _L("(Sync with printer)"));
|
||||||
|
m_disable_tip->SetFont(Label::Body_12);
|
||||||
|
label_sizer->AddSpacer(FromDIP(2));
|
||||||
|
label_sizer->Add(m_disable_tip, 0, wxLEFT, horizontal_margin);
|
||||||
|
|
||||||
sizer->AddSpacer(FromDIP(32));
|
sizer->AddSpacer(FromDIP(15));
|
||||||
|
sizer->Add(icon_sizer, 0, wxEXPAND);
|
||||||
|
sizer->AddSpacer(FromDIP(10));
|
||||||
sizer->Add(label_sizer, 0, wxEXPAND);
|
sizer->Add(label_sizer, 0, wxEXPAND);
|
||||||
sizer->Add(m_disable_tip, 0, wxALIGN_CENTER);
|
sizer->AddSpacer(FromDIP(6));
|
||||||
sizer->AddSpacer(FromDIP(3));
|
|
||||||
|
|
||||||
auto detail_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto detail_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
m_detail = new Label(this, detail);
|
m_detail = new Label(this, detail);
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
|||||||
|
|
||||||
m_avc = new ArchiveViewCtrl(this, wxSize(45 * em, 30 * em));
|
m_avc = new ArchiveViewCtrl(this, wxSize(45 * em, 30 * em));
|
||||||
wxDataViewColumn* toggle_column = m_avc->AppendToggleColumn(L"\u2714", 0, wxDATAVIEW_CELL_ACTIVATABLE, 6 * 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;
|
std::vector<std::shared_ptr<ArchiveViewNode>> stack;
|
||||||
|
|
||||||
|
|||||||
@@ -675,7 +675,14 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
|||||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(9.f, 1.f) * m_scale);
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(9.f, 1.f) * m_scale);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 0.f));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 0.f));
|
||||||
|
|
||||||
|
ImVec4 scroll_col = ImVec4(0.77f, 0.77f, 0.77f, m_is_dark ? .6f : 1.0f); // same color with sliced plates toolbar scrollbar
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImVec4(0.f, 0.f, 0.f, 0.f)); // ORCA using background color with opacity creates a second color. This prevents secondary color
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, scroll_col);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, scroll_col);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, scroll_col);
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered , style.Colors[ImGuiCol_TableHeaderBg]);
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered , style.Colors[ImGuiCol_TableHeaderBg]);
|
||||||
|
|
||||||
const int hover_id = m_actual_speed_imgui_widget.plot("##ActualSpeedProfile", { -1.f, plot_height});
|
const int hover_id = m_actual_speed_imgui_widget.plot("##ActualSpeedProfile", { -1.f, plot_height});
|
||||||
const ImGuiTableFlags table_flags = ImGuiTableFlags_Borders | (needs_scroll ? ImGuiTableFlags_ScrollY : 0);
|
const ImGuiTableFlags table_flags = ImGuiTableFlags_Borders | (needs_scroll ? ImGuiTableFlags_ScrollY : 0);
|
||||||
if (ImGui::BeginTable("ToolPositionTable", 2, table_flags, ImVec2(0.0f, needs_scroll ? table_view_h : 0.0f))) {
|
if (ImGui::BeginTable("ToolPositionTable", 2, table_flags, ImVec2(0.0f, needs_scroll ? table_view_h : 0.0f))) {
|
||||||
@@ -703,7 +710,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
|||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(5);
|
||||||
imgui.end();
|
imgui.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6322,9 +6322,9 @@ void GLCanvas3D::_render_3d_navigator()
|
|||||||
style.Colors[ImGuizmo::COLOR::DIRECTION_Z] = ImGuiWrapper::to_ImVec4(ColorRGBA::X());
|
style.Colors[ImGuizmo::COLOR::DIRECTION_Z] = ImGuiWrapper::to_ImVec4(ColorRGBA::X());
|
||||||
style.Colors[ImGuizmo::COLOR::TEXT] = m_is_dark ? ImVec4(224 / 255.f, 224 / 255.f, 224 / 255.f, 1.f) : ImVec4(.2f, .2f, .2f, 1.0f);
|
style.Colors[ImGuizmo::COLOR::TEXT] = m_is_dark ? ImVec4(224 / 255.f, 224 / 255.f, 224 / 255.f, 1.f) : ImVec4(.2f, .2f, .2f, 1.0f);
|
||||||
style.Colors[ImGuizmo::COLOR::FACE] = m_is_dark ? ImVec4(0.23f, 0.23f, 0.23f, 1.f) : ImVec4(0.77f, 0.77f, 0.77f, 1);
|
style.Colors[ImGuizmo::COLOR::FACE] = m_is_dark ? ImVec4(0.23f, 0.23f, 0.23f, 1.f) : ImVec4(0.77f, 0.77f, 0.77f, 1);
|
||||||
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_X], "Y"); // ORCA use uppercase to match text on tranform widgets
|
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_X], _u8L_CONTEXT("Y", "Axis").c_str()); // ORCA use uppercase to match text on tranform widgets
|
||||||
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Y], "Z"); // ORCA use uppercase to match text on tranform widgets
|
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Y], _u8L_CONTEXT("Z", "Axis").c_str()); // ORCA use uppercase to match text on tranform widgets
|
||||||
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Z], "X"); // ORCA use uppercase to match text on tranform widgets
|
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Z], _u8L_CONTEXT("X", "Axis").c_str()); // ORCA use uppercase to match text on tranform widgets
|
||||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_FRONT], _u8L_CONTEXT("Front", "Camera View").c_str());
|
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_FRONT], _u8L_CONTEXT("Front", "Camera View").c_str());
|
||||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _u8L_CONTEXT("Back", "Camera View").c_str());
|
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _u8L_CONTEXT("Back", "Camera View").c_str());
|
||||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_TOP], _u8L_CONTEXT("Top", "Camera View").c_str());
|
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_TOP], _u8L_CONTEXT("Top", "Camera View").c_str());
|
||||||
@@ -9627,7 +9627,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
|||||||
int item_count = m_sel_plate_toolbar.m_items.size() + (m_sel_plate_toolbar.show_stats_item ? 1 : 0);
|
int item_count = m_sel_plate_toolbar.m_items.size() + (m_sel_plate_toolbar.show_stats_item ? 1 : 0);
|
||||||
float window_height_calc = (item_count * (button_height + (margin_size + button_margin) * 2.0f) + (item_count - 1) * ImGui::GetStyle().ItemSpacing.y + ImGui::GetStyle().WindowPadding.y * 2.0f);
|
float window_height_calc = (item_count * (button_height + (margin_size + button_margin) * 2.0f) + (item_count - 1) * ImGui::GetStyle().ItemSpacing.y + ImGui::GetStyle().WindowPadding.y * 2.0f);
|
||||||
bool show_scroll = m_sel_plate_toolbar.is_display_scrollbar && (window_height_calc > window_height_max);
|
bool show_scroll = m_sel_plate_toolbar.is_display_scrollbar && (window_height_calc > window_height_max);
|
||||||
float scrollbar_size = 10.0f * f_scale ;
|
float scrollbar_size = 14.0f * f_scale;
|
||||||
float window_height = std::min(window_height_calc, window_height_max);
|
float window_height = std::min(window_height_calc, window_height_max);
|
||||||
float window_width = button_width + (margin_size + button_margin + ImGui::GetStyle().WindowPadding.x) * 2 + (show_scroll ? scrollbar_size : 0);
|
float window_width = button_width + (margin_size + button_margin + ImGui::GetStyle().WindowPadding.x) * 2 + (show_scroll ? scrollbar_size : 0);
|
||||||
|
|
||||||
@@ -9653,7 +9653,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
|
|||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, scrollbar_size);
|
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, scrollbar_size);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, show_scroll ? (4.0f * f_scale) : (button_radius + margin_size + frame_padding + ImGui::GetStyle().WindowPadding.x));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, show_scroll ? (6.f * f_scale) : (button_radius + margin_size + frame_padding + ImGui::GetStyle().WindowPadding.x));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, button_radius + margin_size);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, button_radius + margin_size);
|
||||||
|
|
||||||
imgui.set_next_window_pos(canvas_w * 0 + 5.0f * f_scale, canvas_h * 0 + y_offset, ImGuiCond_Always, 0, 0); // ORCA Add slight gap on left edge so toolbar looks like floating and it creates separation with sidebar
|
imgui.set_next_window_pos(canvas_w * 0 + 5.0f * f_scale, canvas_h * 0 + y_offset, ImGuiCond_Always, 0, 0); // ORCA Add slight gap on left edge so toolbar looks like floating and it creates separation with sidebar
|
||||||
@@ -10132,7 +10132,7 @@ void GLCanvas3D::_render_canvas_toolbar()
|
|||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding , ImVec2(4.f, 10.f) * sc);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding , ImVec2(4.f, 10.f) * sc);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing , ImVec2(0.f, 8.f ) * sc);
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing , ImVec2(0.f, 8.f ) * sc);
|
||||||
|
|
||||||
if (ImGui::BeginPopup("CanvasToolbarMenu")) {
|
if (ImGui::BeginPopup("CanvasToolbarMenu", ImGuiWindowFlags_NoMove)) {
|
||||||
ImGui::PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true);
|
ImGui::PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true);
|
||||||
|
|
||||||
Plater* p = wxGetApp().plater();
|
Plater* p = wxGetApp().plater();
|
||||||
@@ -10190,6 +10190,7 @@ void GLCanvas3D::_render_canvas_toolbar()
|
|||||||
[this, p]{p->toggle_show_wireframe(); m_dirty = true;}
|
[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")),
|
create_menu_item( _utf8(L("X-Ray")),
|
||||||
m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
|
m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
|
||||||
p->is_show_xray(),
|
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");
|
message += _L("\nYou may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n");
|
||||||
#endif
|
#endif
|
||||||
if (initial)
|
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);
|
wxMessageBox(message, _L("Orca Slicer - Switching language failed"), wxOK | wxICON_ERROR);
|
||||||
if (initial)
|
if (initial)
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
|
|||||||
@@ -2938,10 +2938,10 @@ void ObjectTablePanel::load_data()
|
|||||||
|
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_printable, _L("Printable"));
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_printable, _L("Printable"));
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_printable_reset, "");
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_printable_reset, "");
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_plate_index, wxString::Format("%S%S", _L("Plate"), wxString::FromUTF8("\u2191\u2193")));
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_plate_index, wxString::Format("%S %S", _L("Plate"), wxString::FromUTF8("\u2191\u2193")));
|
||||||
/*m_object_grid->SetColLabelValue(ObjectGridTable::col_assemble_name, L("Module"));*/
|
/*m_object_grid->SetColLabelValue(ObjectGridTable::col_assemble_name, L("Module"));*/
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_name, wxString::Format("%S%S", _L("Name"), wxString::FromUTF8("\u2191\u2193")));
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_name, wxString::Format("%S %S", _L("Name"), wxString::FromUTF8("\u2191\u2193")));
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments, wxString::Format("%S%S", _L("Filament"), wxString::FromUTF8("\u2191\u2193")));
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments, wxString::Format("%S %S", _L("Filament"), wxString::FromUTF8("\u2191\u2193")));
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments_reset, "");
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments_reset, "");
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_layer_height, _L("Layer height"));
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_layer_height, _L("Layer height"));
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_layer_height_reset, "");
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_layer_height_reset, "");
|
||||||
@@ -2956,8 +2956,8 @@ void ObjectTablePanel::load_data()
|
|||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter, _L("Outer wall speed"));
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter, _L("Outer wall speed"));
|
||||||
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter_reset, "");
|
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter_reset, "");
|
||||||
m_object_grid->SetLabelFont(Label::Head_13);
|
m_object_grid->SetLabelFont(Label::Head_13);
|
||||||
m_object_grid->SetLabelTextColour(StateColor::darkModeColorFor(wxColour("#303A3C")));
|
m_object_grid->SetLabelTextColour(StateColor::darkModeColorFor(wxColour("#363636")));
|
||||||
m_object_grid->SetLabelBackgroundColour( wxColour("#FFFFFF"));
|
m_object_grid->SetLabelBackgroundColour( StateColor::darkModeColorFor(wxColour("#D9D9D9")));
|
||||||
#else
|
#else
|
||||||
m_object_grid->HideColLabels();
|
m_object_grid->HideColLabels();
|
||||||
#endif
|
#endif
|
||||||
@@ -2996,6 +2996,12 @@ void ObjectTablePanel::load_data()
|
|||||||
//m_object_grid->SetSelectionForeground(wxColour(0xDB,0xFD,0xE7));
|
//m_object_grid->SetSelectionForeground(wxColour(0xDB,0xFD,0xE7));
|
||||||
//m_object_grid->SetSelectionBackground(*wxWHITE);
|
//m_object_grid->SetSelectionBackground(*wxWHITE);
|
||||||
m_object_grid->SetDefaultCellBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
m_object_grid->SetDefaultCellBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
||||||
|
m_object_grid->SetSelectionBackground(StateColor::darkModeColorFor(wxColour("#BFE1DE"))); // its not fully working since background of control's covers cell
|
||||||
|
|
||||||
|
m_object_grid->SetCellHighlightColour(StateColor::darkModeColorFor(wxColour("#009688")));
|
||||||
|
m_object_grid->SetCellHighlightPenWidth(FromDIP(1));
|
||||||
|
m_object_grid->SetCellHighlightROPenWidth(FromDIP(1)); // Highlight for read-only cells
|
||||||
|
|
||||||
for (int col = 0; col < cols; col++)
|
for (int col = 0; col < cols; col++)
|
||||||
{
|
{
|
||||||
ObjectGridTable::ObjectGridCol* grid_col = m_object_grid_table->get_grid_col(col);
|
ObjectGridTable::ObjectGridCol* grid_col = m_object_grid_table->get_grid_col(col);
|
||||||
|
|||||||
@@ -665,6 +665,42 @@ void RemoveInputBorder(wxWindow* win)
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetGaugeColor(wxGauge* gauge, const wxString& barColor, const wxString& troughColor)
|
||||||
|
{
|
||||||
|
GtkWidget* widget = gauge->GetHandle(); // native GtkWidget*
|
||||||
|
if (!widget) return;
|
||||||
|
|
||||||
|
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||||
|
// GTK3+: use CSS provider
|
||||||
|
GtkCssProvider* provider = gtk_css_provider_new();
|
||||||
|
wxString css = wxString::Format(
|
||||||
|
"progressbar trough { background-color: %s; }"
|
||||||
|
"progressbar progress { background-color: %s; background-image: none; }",
|
||||||
|
troughColor,
|
||||||
|
barColor
|
||||||
|
);
|
||||||
|
|
||||||
|
#if GTK_CHECK_VERSION(4, 0, 0)
|
||||||
|
// GTK4
|
||||||
|
gtk_css_provider_load_from_data(provider, css.utf8_str(), -1);
|
||||||
|
#else
|
||||||
|
// GTK3
|
||||||
|
gtk_css_provider_load_from_data(provider, css.utf8_str(), -1, nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GtkStyleContext* ctx = gtk_widget_get_style_context(widget);
|
||||||
|
gtk_style_context_add_provider(
|
||||||
|
ctx,
|
||||||
|
GTK_STYLE_PROVIDER(provider),
|
||||||
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
|
);
|
||||||
|
|
||||||
|
g_object_unref(provider);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|||||||
@@ -37,6 +37,10 @@
|
|||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Color.hpp"
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
#include "wx/gauge.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class wxCheckBox;
|
class wxCheckBox;
|
||||||
class wxTopLevelWindow;
|
class wxTopLevelWindow;
|
||||||
@@ -495,6 +499,7 @@ void set_window_corner_radius(wxWindow* win, int radius);
|
|||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
void RemoveButtonBorder(wxWindow* win); // for wxButton/wxBitmapToggleButton based controls (SwitchButton, CheckBox)
|
void RemoveButtonBorder(wxWindow* win); // for wxButton/wxBitmapToggleButton based controls (SwitchButton, CheckBox)
|
||||||
void RemoveInputBorder(wxWindow* win); // for TextCtrl based controls (TextInput, ComboBox, SpinInput..)
|
void RemoveInputBorder(wxWindow* win); // for TextCtrl based controls (TextInput, ComboBox, SpinInput..)
|
||||||
|
void SetGaugeColor(wxGauge* gauge, const wxString& barColor, const wxString& troughColor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__WXOSX__) || defined(__linux__)
|
#if defined(__WXOSX__) || defined(__linux__)
|
||||||
|
|||||||
@@ -1055,7 +1055,7 @@ void GLGizmoMmuSegmentation::render_filament_remap_ui(float window_width, float
|
|||||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg));
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Border , ImGui::ColorConvertFloat4ToU32(ImGuiWrapper::COL_ORCA));
|
ImGui::PushStyleColor(ImGuiCol_Border , ImGui::ColorConvertFloat4ToU32(ImGuiWrapper::COL_ORCA));
|
||||||
|
|
||||||
if (ImGui::BeginPopup(pop_id.c_str())) {
|
if (ImGui::BeginPopup(pop_id.c_str(), ImGuiWindowFlags_NoMove)) {
|
||||||
|
|
||||||
m_imgui->text(_L("To:"));
|
m_imgui->text(_L("To:"));
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ void GLGizmoPrimitive::on_render_input_window(float x, float y, float bottom_lim
|
|||||||
m_params.type = (PrimitiveType)cur;
|
m_params.type = (PrimitiveType)cur;
|
||||||
m_preview_dirty = true;
|
m_preview_dirty = true;
|
||||||
}
|
}
|
||||||
|
// TRN Primitive gizmo: label in front of the preset cube size buttons
|
||||||
ImGui::TextUnformatted(_u8L("Quick:").c_str());
|
ImGui::TextUnformatted(_u8L("Quick:").c_str());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::SmallButton("10mm")) apply_preset("10mm cube", 10, 10, 10);
|
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);
|
dim(_u8L("Radius").c_str(), m_params.sph_radius);
|
||||||
break;
|
break;
|
||||||
case PrimitiveType::Cone:
|
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("Bottom R").c_str(), m_params.cone_r1);
|
||||||
dim(_u8L("Top R").c_str(), m_params.cone_r2);
|
dim(_u8L("Top R").c_str(), m_params.cone_r2);
|
||||||
dim(_u8L("Height").c_str(), m_params.cone_height);
|
dim(_u8L("Height").c_str(), m_params.cone_height);
|
||||||
break;
|
break;
|
||||||
case PrimitiveType::Torus:
|
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("Major R").c_str(), m_params.torus_r1);
|
||||||
dim(_u8L("Minor R").c_str(), m_params.torus_r2, 0.1, 1.0);
|
dim(_u8L("Minor R").c_str(), m_params.torus_r2, 0.1, 1.0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1351,25 +1351,25 @@ void GLGizmoSVG::draw_window()
|
|||||||
assert(m_volume_id.valid());
|
assert(m_volume_id.valid());
|
||||||
if (m_volume == nullptr ||
|
if (m_volume == nullptr ||
|
||||||
m_volume_id.invalid()) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_volume->emboss_shape.has_value());
|
assert(m_volume->emboss_shape.has_value());
|
||||||
if (!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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_volume->emboss_shape->svg_file.has_value());
|
assert(m_volume->emboss_shape->svg_file.has_value());
|
||||||
if (!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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_volume->emboss_shape->svg_file->file_data != nullptr);
|
assert(m_volume->emboss_shape->svg_file->file_data != nullptr);
|
||||||
if (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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2143,7 +2143,7 @@ std::string volume_name(const EmbossShape &shape)
|
|||||||
std::string file_name = get_file_name(shape.svg_file->path);
|
std::string file_name = get_file_name(shape.svg_file->path);
|
||||||
if (!file_name.empty())
|
if (!file_name.empty())
|
||||||
return file_name;
|
return file_name;
|
||||||
return "SVG shape";
|
return _u8L("SVG shape");
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateVolumeParams create_input(GLCanvas3D &canvas, RaycastManager& raycaster, ModelVolumeType volume_type)
|
CreateVolumeParams create_input(GLCanvas3D &canvas, RaycastManager& raycaster, ModelVolumeType volume_type)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/NotificationManager.hpp"
|
#include "slic3r/GUI/NotificationManager.hpp"
|
||||||
|
#include "slic3r/GUI/format.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||||
@@ -231,11 +232,11 @@ void GLGizmoSketch::draw_canvas()
|
|||||||
TopoDS_Shape GLGizmoSketch::build_combined_shape()
|
TopoDS_Shape GLGizmoSketch::build_combined_shape()
|
||||||
{
|
{
|
||||||
if (m_profiles.empty() || !m_profiles[0].closed)
|
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);
|
TopoDS_Wire outer_wire = m_profiles[0].to_occt_wire(m_plane);
|
||||||
BRepBuilderAPI_MakeFace face_maker(outer_wire);
|
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) {
|
for (size_t i = 1; i < m_profiles.size(); ++i) {
|
||||||
if (!m_profiles[i].closed) continue;
|
if (!m_profiles[i].closed) continue;
|
||||||
@@ -243,7 +244,7 @@ TopoDS_Shape GLGizmoSketch::build_combined_shape()
|
|||||||
face_maker.Add(inner);
|
face_maker.Add(inner);
|
||||||
}
|
}
|
||||||
face_maker.Build();
|
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();
|
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_Dir xd(m_plane.x_axis.x(), m_plane.x_axis.y(), m_plane.x_axis.z());
|
||||||
gp_Ax1 axis(o, xd);
|
gp_Ax1 axis(o, xd);
|
||||||
BRepPrimAPI_MakeRevol rev(face, axis, m_sp.revolve_deg * M_PI / 180.0);
|
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();
|
shape = rev.Shape();
|
||||||
} else {
|
} else {
|
||||||
shape = SketchEngine::make_extrude_face(face, m_plane, m_sp.extrude_len, m_sp.extrude_sym);
|
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);
|
bool outer = (i == 0);
|
||||||
ImVec4 col = outer ? ImVec4(0,1,0,1) : ImVec4(1,0.3f,0.3f,1);
|
ImVec4 col = outer ? ImVec4(0,1,0,1) : ImVec4(1,0.3f,0.3f,1);
|
||||||
const std::string label = outer ? _u8L("Outer") : _u8L("Hole");
|
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(),
|
const std::string state = p.closed ? _u8L("closed") : std::string();
|
||||||
_u8L("points").c_str(), p.closed ? _u8L("closed").c_str() : "");
|
// 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();
|
ImGui::SameLine();
|
||||||
if (ImGui::SmallButton("X")) delete_profile(i);
|
if (ImGui::SmallButton("X")) delete_profile(i);
|
||||||
ImGui::PopID();
|
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)) {
|
if (ImGui::CollapsingHeader(_u8L("Operation").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
static int pi = 0;
|
static int pi = 0;
|
||||||
const std::string planes = "XY (" + _u8L("Top") + ")" + std::string(1, '\0') + "XZ (" + _u8L("Front") + ")"
|
const std::string plane_names[] = {_u8L("XY (Top)"), _u8L("XZ (Front)"), _u8L("YZ (Side)")};
|
||||||
+ std::string(1, '\0') + "YZ (" + _u8L("Side") + ")" + std::string(2, '\0');
|
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.c_str()))
|
if (ImGui::Combo(_u8L("Plane").c_str(), &pi, planes, 3))
|
||||||
m_plane = (pi==0) ? SketchPlane::XY() : (pi==1) ? SketchPlane::XZ() : SketchPlane::YZ();
|
m_plane = (pi==0) ? SketchPlane::XY() : (pi==1) ? SketchPlane::XZ() : SketchPlane::YZ();
|
||||||
|
|
||||||
is_revolve = (m_sp.revolve_deg > 0 && m_sp.revolve_deg < 360);
|
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();
|
ImGui::Separator();
|
||||||
|
|
||||||
bool ok = has_closed_profile();
|
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());
|
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) {
|
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) {
|
} else if (is_revolve) {
|
||||||
if (btn(_u8L("Revolve").c_str(), ok)) apply_revolve();
|
if (btn(_u8L("Revolve").c_str(), ok)) apply_revolve();
|
||||||
} else {
|
} 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();
|
if (ImGui::Button(_u8L("Clear all").c_str(), {-1,0})) clear_all();
|
||||||
@@ -419,7 +422,7 @@ void GLGizmoSketch::apply_extrude()
|
|||||||
try {
|
try {
|
||||||
TopoDS_Shape shape = build_combined_shape();
|
TopoDS_Shape shape = build_combined_shape();
|
||||||
TriangleMesh mesh = SketchEngine::tessellate(shape, m_sp.linear_deflection);
|
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");
|
wxGetApp().plater()->take_snapshot("Sketch Extrude");
|
||||||
ModelObject* mo = wxGetApp().model().add_object();
|
ModelObject* mo = wxGetApp().model().add_object();
|
||||||
mo->name = "Extrusion";
|
mo->name = "Extrusion";
|
||||||
@@ -428,7 +431,7 @@ void GLGizmoSketch::apply_extrude()
|
|||||||
wxGetApp().plater()->update();
|
wxGetApp().plater()->update();
|
||||||
clear_all();
|
clear_all();
|
||||||
} catch (const std::exception& e) {
|
} 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 {
|
try {
|
||||||
TopoDS_Shape shape = build_combined_shape();
|
TopoDS_Shape shape = build_combined_shape();
|
||||||
TriangleMesh mesh = SketchEngine::tessellate(shape, m_sp.linear_deflection);
|
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");
|
wxGetApp().plater()->take_snapshot("Sketch Revolve");
|
||||||
ModelObject* mo = wxGetApp().model().add_object();
|
ModelObject* mo = wxGetApp().model().add_object();
|
||||||
mo->name = "Revolve";
|
mo->name = "Revolve";
|
||||||
@@ -446,7 +449,7 @@ void GLGizmoSketch::apply_revolve()
|
|||||||
wxGetApp().plater()->update();
|
wxGetApp().plater()->update();
|
||||||
clear_all();
|
clear_all();
|
||||||
} catch (const std::exception& e) {
|
} 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 {
|
try {
|
||||||
Selection& sel = m_parent.get_selection();
|
Selection& sel = m_parent.get_selection();
|
||||||
int obj_idx = sel.get_object_idx();
|
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];
|
ModelObject* mo = wxGetApp().model().objects[obj_idx];
|
||||||
|
|
||||||
TopoDS_Wire outer = m_profiles[0].to_occt_wire(m_plane);
|
TopoDS_Wire outer = m_profiles[0].to_occt_wire(m_plane);
|
||||||
BRepBuilderAPI_MakeFace fm(outer);
|
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)
|
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));
|
if (m_profiles[i].closed) fm.Add(m_profiles[i].to_occt_wire(m_plane));
|
||||||
fm.Build();
|
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);
|
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);
|
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");
|
wxGetApp().plater()->take_snapshot("Sketch Pocket");
|
||||||
mo->add_volume(std::move(tool_mesh), ModelVolumeType::NEGATIVE_VOLUME)->set_new_unique_id();
|
mo->add_volume(std::move(tool_mesh), ModelVolumeType::NEGATIVE_VOLUME)->set_new_unique_id();
|
||||||
@@ -477,7 +480,7 @@ void GLGizmoSketch::apply_pocket()
|
|||||||
clear_all();
|
clear_all();
|
||||||
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Pocket added (negative volume)").c_str());
|
wxGetApp().notification_manager()->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Pocket added (negative volume)").c_str());
|
||||||
} catch (const std::exception& e) {
|
} 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["circle"] = _L("Circle");
|
||||||
m_desc["sphere"] = _L("Sphere");
|
m_desc["sphere"] = _L("Sphere");
|
||||||
m_desc["remove_layer"] = _L("Remove");
|
m_desc["remove_layer"] = _L("Remove");
|
||||||
m_desc["bake"] = _L("Bake");
|
m_desc["bake"] = _L_CONTEXT("Bake", "Texture Displacement");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3509,7 +3509,7 @@ void GLGizmoTextureDisplacement::set_layer_texture(TextureDisplacementLayer &lay
|
|||||||
|
|
||||||
void GLGizmoTextureDisplacement::import_custom_texture(TextureDisplacementLayer &layer)
|
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,
|
wxFileDialog dialog(nullptr, _L("Choose a texture image (height map)"), wxEmptyString, wxEmptyString, wildcard,
|
||||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dialog.ShowModal() != wxID_OK)
|
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;
|
// 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.
|
// 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);
|
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 "
|
hover_tip(_u8L("Which gray 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 "
|
"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"
|
"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 "
|
"What cuts in has to fit: inside a sharp corner or through a thin wall, a deep "
|
||||||
"cut can pass through the other side."));
|
"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();
|
const bool has_color = decode_height_texture(layer).has_color();
|
||||||
bool color_enabled = layer.color_enabled && has_color;
|
bool color_enabled = layer.color_enabled && has_color;
|
||||||
m_imgui->disabled_begin(!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;
|
layer.color_enabled = color_enabled;
|
||||||
m_preview_params_dirty = true;
|
m_preview_params_dirty = true;
|
||||||
}
|
}
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
|
||||||
m_imgui->tooltip(has_color ?
|
m_imgui->tooltip(has_color ?
|
||||||
_u8L("Prints the painted area in the texture's colours as well as its "
|
_u8L("Prints the painted area in the texture's colors as well as its "
|
||||||
"relief. Each colour is matched to the nearest of your loaded "
|
"relief. Each color is matched to the nearest of your loaded "
|
||||||
"filaments; anything you did not paint keeps the object's own.") :
|
"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 "
|
_u8L("This texture is a grayscale height map, so it has no colors to "
|
||||||
"apply. Import a colour image to use this."),
|
"apply. Import a color image to use this."),
|
||||||
wrap_w);
|
wrap_w);
|
||||||
|
|
||||||
// The rest of colour belongs to the whole stack, not to this layer, so it only appears once -
|
// 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;
|
TextureDisplacementOptions &opts = mv->texture_displacement_options;
|
||||||
if (m_imgui->bbl_checkbox(_L("Mix filaments"), opts.color_mix_enabled))
|
if (m_imgui->bbl_checkbox(_L("Mix filaments"), opts.color_mix_enabled))
|
||||||
m_preview_params_dirty = true;
|
m_preview_params_dirty = true;
|
||||||
hover_tip(_u8L("Interleaves two filaments to fake the colours in between, so a handful "
|
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 colours "
|
"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."));
|
"prints the same either way. Off uses one filament per area."));
|
||||||
if (opts.color_mix_enabled) {
|
if (opts.color_mix_enabled) {
|
||||||
slider_label(_L("Mix by"));
|
slider_label(_L("Mix by"));
|
||||||
const std::string mix_z = _u8L("Layers");
|
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 std::string mix_auto = _u8L("Automatic");
|
||||||
const char *mix_items[] = { mix_z.c_str(), mix_xy.c_str(), mix_auto.c_str() };
|
const char *mix_items[] = { mix_z.c_str(), mix_xy.c_str(), mix_auto.c_str() };
|
||||||
int mix_mode = int(opts.color_mix_mode);
|
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"
|
"any angle but can read as texture rather than as a blend.\n"
|
||||||
"Automatic: layers on upright faces; flat-facing faces take the nearer "
|
"Automatic: layers on upright faces; flat-facing faces take the nearer "
|
||||||
"single filament, since a checkerboard there shows as a pattern."));
|
"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());
|
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))
|
if (int_row("##color_despeckle", _L("Denoise"), &opts.color_despeckle, 0, 6, "%d", card_pad))
|
||||||
m_preview_params_dirty = true;
|
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, "
|
"than the mesh leaves behind. Raise it if the result looks speckled, "
|
||||||
"lower it if small features are being swallowed."));
|
"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();
|
const float x0 = ImGui::GetCursorPosX();
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::TextDisabled("%s", _u8L("Mapping").c_str());
|
ImGui::TextDisabled("%s", _u8L_CONTEXT("Mapping", "Texture Displacement").c_str());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), x0 + label_w));
|
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), x0 + label_w));
|
||||||
struct MappingIcon
|
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 "
|
_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.") },
|
"patch wrapping around a sharp edge has no seam.") },
|
||||||
{ "menu_obj_cylinder.svg", _L("Cylindrical"),
|
{ "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"),
|
{ "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)"),
|
{ "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 "
|
_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 "
|
"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::TextDisabled("%s", _u8L("Blend").c_str());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), x0 + label_w));
|
ImGui::SetCursorPosX(std::max(ImGui::GetCursorPosX(), x0 + label_w));
|
||||||
const std::string blend_add = _u8L("Add");
|
const std::string blend_add = _u8L_CONTEXT("Add", "Texture Displacement");
|
||||||
const std::string blend_subtract = _u8L("Subtract");
|
const std::string blend_subtract = _u8L_CONTEXT("Subtract", "Texture Displacement");
|
||||||
const std::string blend_multiply = _u8L("Multiply");
|
const std::string blend_multiply = _u8L_CONTEXT("Multiply", "Texture Displacement");
|
||||||
const std::string blend_divide = _u8L("Divide");
|
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() };
|
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
|
// 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
|
// 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.
|
// to refine and the control would do nothing whatever it is set to.
|
||||||
if (mv != nullptr && any_layer_colors(*mv)) {
|
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();
|
preview_live();
|
||||||
hover_tip(_u8L("Triangle size where two colours meet. Each triangle prints in one filament, so a "
|
hover_tip(_u8L("Triangle size where two colors meet. Each triangle prints in one filament, so a "
|
||||||
"colour edge can only be as sharp as the triangles along it - and nothing else "
|
"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 colour. 0 turns it off."));
|
"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());
|
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."));
|
"on a layer is a different thing: it blurs the image before it is used."));
|
||||||
if (opts.smooth_enabled) {
|
if (opts.smooth_enabled) {
|
||||||
float percent = opts.smooth_strength * 100.f;
|
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);
|
opts.smooth_strength = std::clamp(percent / 100.f, 0.01f, 1.f);
|
||||||
m_preview_params_dirty = true;
|
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, "
|
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 "
|
"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 "
|
"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) {
|
if (opts.pipeline_v2) {
|
||||||
// -1 is "auto": the row shows the recommendation, greyed; editing it makes it a fixed value.
|
// -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;
|
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;
|
int shown_k = auto_budget ? v2_recommendation(*mv).budget_k : opts.v2_max_triangles_k;
|
||||||
m_imgui->disabled_begin(auto_budget);
|
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;
|
opts.v2_max_triangles_k = shown_k;
|
||||||
m_preview_params_dirty = true;
|
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());
|
ImGui::SetNextItemWidth(x0 + panel_w - ImGui::GetCursorPosX());
|
||||||
float shown = auto_res ? rec.edge_mm : opts.v2_refine_mm;
|
float shown = auto_res ? rec.edge_mm : opts.v2_refine_mm;
|
||||||
m_imgui->disabled_begin(busy || auto_res);
|
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)) {
|
ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_Logarithmic)) {
|
||||||
opts.v2_refine_mm = shown;
|
opts.v2_refine_mm = shown;
|
||||||
m_preview_params_dirty = true;
|
m_preview_params_dirty = true;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include "CloudProvider.hpp"
|
#include "CloudProvider.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
#include "slic3r/Utils/Http.hpp"
|
#include "slic3r/Utils/Http.hpp"
|
||||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||||
#include "slic3r/Utils/BBLNetworkPlugin.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); });
|
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
|
const std::string message = login_ok
|
||||||
? "You can return to OrcaSlicer. This window will close automatically."
|
? _u8L("You can return to OrcaSlicer. This window will close automatically.")
|
||||||
: "Something went wrong. Please return to OrcaSlicer and try again.";
|
: _u8L("Something went wrong. Please return to OrcaSlicer and try again.");
|
||||||
const std::string html =
|
const std::string html =
|
||||||
"<html><head><meta charset=\"utf-8\">"
|
"<html><head><meta charset=\"utf-8\">"
|
||||||
"<style>body{font-family:Arial,sans-serif;background:#f7f7f7;color:#222;margin:32px;}"
|
"<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;}"
|
"<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;}"
|
"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\">"
|
"</style></head><body><div class=\"container\">"
|
||||||
"<h2>Authentication complete</h2>"
|
"<h2>" + _u8L("Authentication complete") + "</h2>"
|
||||||
"<p>You can return to OrcaSlicer. If your browser does not redirect automatically, use the button below.</p>"
|
"<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 + "\">Continue</a>"
|
"<a class=\"button\" href=\"" + location_str + "\">" + _u8L("Continue") + "</a>"
|
||||||
"<script>setTimeout(function(){try{window.close();}catch(e){}},1500);</script>"
|
"<script>setTimeout(function(){try{window.close();}catch(e){}},1500);</script>"
|
||||||
"</div></body></html>";
|
"</div></body></html>";
|
||||||
ssOut << "HTTP/1.1 302 Found" << std::endl;
|
ssOut << "HTTP/1.1 302 Found" << std::endl;
|
||||||
|
|||||||
@@ -1524,7 +1524,7 @@ void IMSlider::render_add_menu()
|
|||||||
ImGui::OpenPopup("slider_add_menu_popup");
|
ImGui::OpenPopup("slider_add_menu_popup");
|
||||||
m_show_menu = false;
|
m_show_menu = false;
|
||||||
}
|
}
|
||||||
if (ImGui::BeginPopup("slider_add_menu_popup")) {
|
if (ImGui::BeginPopup("slider_add_menu_popup", ImGuiWindowFlags_NoMove)) {
|
||||||
bool menu_item_enable = m_draw_mode != dmSequentialFffPrint;
|
bool menu_item_enable = m_draw_mode != dmSequentialFffPrint;
|
||||||
bool hovered = false;
|
bool hovered = false;
|
||||||
{
|
{
|
||||||
@@ -1579,7 +1579,7 @@ void IMSlider::render_edit_menu(const TickCode& tick)
|
|||||||
ImGui::OpenPopup("slider_edit_menu_popup");
|
ImGui::OpenPopup("slider_edit_menu_popup");
|
||||||
m_show_menu = false;
|
m_show_menu = false;
|
||||||
}
|
}
|
||||||
if (ImGui::BeginPopup("slider_edit_menu_popup")) {
|
if (ImGui::BeginPopup("slider_edit_menu_popup", ImGuiWindowFlags_NoMove)) {
|
||||||
switch (tick.type)
|
switch (tick.type)
|
||||||
{
|
{
|
||||||
case CustomGCode::PausePrint:
|
case CustomGCode::PausePrint:
|
||||||
|
|||||||
@@ -527,7 +527,7 @@ void ArrangeJob::check_unprintable()
|
|||||||
#endif
|
#endif
|
||||||
if (it->poly.area() < 0.001) {
|
if (it->poly.area() < 0.001) {
|
||||||
auto msg = (boost::format(
|
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();
|
% _utf8(it->name)).str();
|
||||||
m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
|
m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo,
|
||||||
NotificationManager::NotificationLevel::WarningNotificationLevel, msg);
|
NotificationManager::NotificationLevel::WarningNotificationLevel, msg);
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ void CreateVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
|
|||||||
if (!::finalize(canceled, eptr, *m_input.base))
|
if (!::finalize(canceled, eptr, *m_input.base))
|
||||||
return;
|
return;
|
||||||
if (m_result.its.empty())
|
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);
|
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
|
// only for sure
|
||||||
if (m_result.empty())
|
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();
|
GUI_App &app = wxGetApp();
|
||||||
Plater *plater = app.plater();
|
Plater *plater = app.plater();
|
||||||
@@ -995,7 +995,7 @@ TriangleMesh create_mesh(DataBase &input, const Fnc& was_canceled, Job::Ctl& ctl
|
|||||||
return {};
|
return {};
|
||||||
// only info
|
// only info
|
||||||
ctl.call_on_main_thread([]() {
|
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
|
// for sure that some object will be created
|
||||||
if (mesh.its.empty())
|
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();
|
Plater *plater = wxGetApp().plater();
|
||||||
// Check gizmo is still open otherwise job should be canceled
|
// 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.
|
// Parent object for text volume was propably removed.
|
||||||
// Assumption: User know what he does, so text volume is no more needed.
|
// Assumption: User know what he does, so text volume is no more needed.
|
||||||
if (obj == nullptr)
|
if (obj == nullptr)
|
||||||
return create_message("Bad object to create volume.");
|
return create_message(_u8L("Bad object to create volume."));
|
||||||
|
|
||||||
if (mesh.its.empty())
|
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"));
|
plater->take_snapshot(_u8L("Add Emboss text Volume"));
|
||||||
|
|
||||||
|
|||||||
@@ -487,7 +487,7 @@ ShortcutCaptureDialog::ShortcutCaptureDialog(wxWindow* parent, Shortcut shortcut
|
|||||||
m_status_colour = m_status->GetForegroundColour();
|
m_status_colour = m_status->GetForegroundColour();
|
||||||
sizer->Add(m_status, 0, wxLEFT | wxRIGHT | wxTOP, FromDIP(20));
|
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&) {
|
dlg_btns->GetFIRST()->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||||
m_chord = KeyChord{};
|
m_chord = KeyChord{};
|
||||||
m_conflicts.clear();
|
m_conflicts.clear();
|
||||||
|
|||||||
@@ -1676,7 +1676,7 @@ void MixedFilamentDialog::update_ok_button_state()
|
|||||||
wxString parts;
|
wxString parts;
|
||||||
for (auto it = type_groups.begin(); it != type_groups.end(); ++it) {
|
for (auto it = type_groups.begin(); it != type_groups.end(); ++it) {
|
||||||
if (!parts.empty())
|
if (!parts.empty())
|
||||||
parts += _L(" and ");
|
parts += "; ";
|
||||||
wxString slots;
|
wxString slots;
|
||||||
for (size_t j = 0; j < it->second.size(); ++j) {
|
for (size_t j = 0; j < it->second.size(); ++j) {
|
||||||
if (!slots.empty()) slots += ", ";
|
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));
|
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 {
|
} else {
|
||||||
m_type_mismatch_msg.clear();
|
m_type_mismatch_msg.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -493,7 +493,8 @@ MultiMachineManagerPage::MultiMachineManagerPage(wxWindow* parent)
|
|||||||
page_num_enter_evt();
|
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->SetMinSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||||
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||||
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
||||||
|
|||||||
@@ -1166,7 +1166,7 @@ CloudTaskManagerPage::CloudTaskManagerPage(wxWindow* parent)
|
|||||||
page_num_enter_evt();
|
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->SetMinSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||||
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||||
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ void NetworkPluginDownloadDialog::create_missing_plugin_ui()
|
|||||||
main_sizer->AddSpacer(15);
|
main_sizer->AddSpacer(15);
|
||||||
|
|
||||||
auto dlg_btns = new DialogButtons(this,
|
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
|
_L("Download and Install") // Primary button
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ void NetworkPluginDownloadDialog::create_update_available_ui(const std::string&
|
|||||||
main_sizer->AddSpacer(10);
|
main_sizer->AddSpacer(10);
|
||||||
|
|
||||||
auto dlg_btns = new DialogButtons(this,
|
auto dlg_btns = new DialogButtons(this,
|
||||||
{"Update Now", "Remind Later", "Skip Version"},
|
{L("Update Now"), L("Remind Later"), L("Skip Version")},
|
||||||
_L("Update Now")
|
_L("Update Now")
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -319,7 +319,7 @@ NetworkPluginRestartDialog::NetworkPluginRestartDialog(wxWindow* parent)
|
|||||||
main_sizer->AddSpacer(15);
|
main_sizer->AddSpacer(15);
|
||||||
|
|
||||||
auto dlg_btns = new DialogButtons(this,
|
auto dlg_btns = new DialogButtons(this,
|
||||||
{"Restart Now", "Restart Later"},
|
{L("Restart Now"), L("Restart Later")},
|
||||||
_L("Restart Now") // Primary button
|
_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)
|
void NetworkTestDialog::start_test_url(TestJob job, wxString name, wxString url)
|
||||||
{
|
{
|
||||||
m_in_testing[job] = true;
|
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);
|
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) {
|
.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);
|
update_status(job, ip_report);
|
||||||
})
|
})
|
||||||
.on_error([this,name,job](std::string body, std::string error, unsigned int status) {
|
.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);
|
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);
|
this->update_status(-1, info);
|
||||||
}).perform_sync();
|
}).perform_sync();
|
||||||
if (result == 0) {
|
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;
|
m_in_testing[job] = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1272,7 +1272,7 @@ bool NotificationManager::ExportFinishedNotification::on_text_click()
|
|||||||
}
|
}
|
||||||
void NotificationManager::ExportFinishedNotification::on_eject_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_eject_pending = true;
|
||||||
m_multiline = false;
|
m_multiline = false;
|
||||||
update(data);
|
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);
|
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||||
float uploaded = m_file_size * m_percentage;
|
float uploaded = m_file_size * m_percentage;
|
||||||
std::stringstream stream;
|
text = into_u8(wxString::Format(_L("%d%% - %.2f of %.2fMB uploaded"), (int)(m_percentage * 100), uploaded, m_file_size));
|
||||||
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "% - " << uploaded << " of " << m_file_size << "MB uploaded";
|
|
||||||
text = stream.str();
|
|
||||||
ImGui::SetCursorPosX(m_left_indentation);
|
ImGui::SetCursorPosX(m_left_indentation);
|
||||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
|
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
|
||||||
break;
|
break;
|
||||||
@@ -3595,7 +3593,7 @@ void NotificationManager::bbl_show_bed_filament_incompatible_notification(const
|
|||||||
wxGetApp().open_browser_with_warning_dialog(bed_filament_compatibility_wiki);
|
wxGetApp().open_browser_with_warning_dialog(bed_filament_compatibility_wiki);
|
||||||
return false;
|
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()
|
void NotificationManager::bbl_close_bed_filament_incompatible_notification()
|
||||||
|
|||||||
@@ -134,13 +134,13 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent
|
|||||||
m_name = "Settings to modified";
|
m_name = "Settings to modified";
|
||||||
}
|
}
|
||||||
else if (type == itInstanceRoot) {
|
else if (type == itInstanceRoot) {
|
||||||
m_name = _(_devL("Instances"));
|
m_name = _L("Instances");
|
||||||
m_extruder = parent->m_extruder;
|
m_extruder = parent->m_extruder;
|
||||||
}
|
}
|
||||||
else if (type == itInstance)
|
else if (type == itInstance)
|
||||||
{
|
{
|
||||||
m_idx = parent->GetChildCount();
|
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;
|
m_extruder = parent->GetParent()->m_extruder;
|
||||||
set_icons();
|
set_icons();
|
||||||
}
|
}
|
||||||
@@ -398,10 +398,11 @@ void ObjectDataViewModelNode::SetIdx(const int &idx)
|
|||||||
// update name if this node is instance
|
// update name if this node is instance
|
||||||
if (m_type == itInstance) {
|
if (m_type == itInstance) {
|
||||||
if (m_plate_idx > 0) {
|
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 {
|
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();
|
m_presets = tab->get_presets();
|
||||||
const Preset &sel_preset = m_presets->get_selected_preset();
|
const Preset &sel_preset = m_presets->get_selected_preset();
|
||||||
std::string suffix = _u8L_CONTEXT(L_CONTEXT("Copy", "PresetName"), "PresetName");
|
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);
|
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
|
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.
|
// 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."));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -936,7 +936,7 @@ struct Sidebar::priv
|
|||||||
// that Orca's sidebar has no counterpart for, so these are parented to p->scrolled.
|
// that Orca's sidebar has no counterpart for, so these are parented to p->scrolled.
|
||||||
wxPanel* m_btn_add_mixed_filament{nullptr}; // "+ Add Mixed Filament" full-width button
|
wxPanel* m_btn_add_mixed_filament{nullptr}; // "+ Add Mixed Filament" full-width button
|
||||||
wxPanel* m_panel_mixed_title{nullptr}; // title row: "Mixed Filament" + add/del buttons
|
wxPanel* m_panel_mixed_title{nullptr}; // title row: "Mixed Filament" + add/del buttons
|
||||||
wxStaticText* m_text_mixed_title{nullptr};
|
StaticLine* m_text_mixed_title{nullptr};
|
||||||
ScalableButton* m_btn_mixed_add{nullptr};
|
ScalableButton* m_btn_mixed_add{nullptr};
|
||||||
ScalableButton* m_btn_mixed_del{nullptr};
|
ScalableButton* m_btn_mixed_del{nullptr};
|
||||||
wxScrolledWindow* m_mixed_scroll_area{nullptr}; // independent scrollbar for mixed rows
|
wxScrolledWindow* m_mixed_scroll_area{nullptr}; // independent scrollbar for mixed rows
|
||||||
@@ -3000,6 +3000,7 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
});
|
});
|
||||||
|
|
||||||
// "Variant", not "Nozzle": picking one switches the printer preset (see panel_nozzle_dia).
|
// "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 = new Label(p->panel_nozzle_dia, _L("Variant"), LB_PROPAGATE_MOUSE_EVENT);
|
||||||
p->label_nozzle_title->SetFont(Label::Body_10);
|
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_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->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->SetFont(Label::Body_10);
|
||||||
p->label_nozzle_type->SetMinSize(FromDIP(wxSize(56, -1)));
|
p->label_nozzle_type->SetMinSize(FromDIP(wxSize(56, -1)));
|
||||||
p->label_nozzle_type->SetMaxSize(FromDIP(wxSize(56, -1)));
|
p->label_nozzle_type->SetMaxSize(FromDIP(wxSize(56, -1)));
|
||||||
@@ -3436,10 +3437,10 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
p->m_panel_mixed_title->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
p->m_panel_mixed_title->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
|
||||||
{
|
{
|
||||||
auto* title_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto* title_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
p->m_text_mixed_title = new wxStaticText(p->m_panel_mixed_title, wxID_ANY, _L("Mixed Filament"));
|
p->m_text_mixed_title = new StaticLine(p->m_panel_mixed_title, false, _L("Mixed Filament"));
|
||||||
p->m_text_mixed_title->SetFont(::Label::Head_14);
|
p->m_text_mixed_title->SetFont(::Label::Head_14);
|
||||||
title_sizer->Add(p->m_text_mixed_title, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
|
p->m_text_mixed_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636")));
|
||||||
title_sizer->AddStretchSpacer();
|
title_sizer->Add(p->m_text_mixed_title, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
|
||||||
|
|
||||||
p->m_btn_mixed_del = new ScalableButton(p->m_panel_mixed_title, wxID_ANY, "delete_filament");
|
p->m_btn_mixed_del = new ScalableButton(p->m_panel_mixed_title, wxID_ANY, "delete_filament");
|
||||||
p->m_btn_mixed_del->SetToolTip(_L("Remove last mixed filament"));
|
p->m_btn_mixed_del->SetToolTip(_L("Remove last mixed filament"));
|
||||||
@@ -3579,6 +3580,7 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
search_sizer->Fit(p->m_search_bar);
|
search_sizer->Fit(p->m_search_bar);
|
||||||
|
|
||||||
p->m_object_list = new ObjectList(p->scrolled);
|
p->m_object_list = new ObjectList(p->scrolled);
|
||||||
|
p->m_object_list->SetBackgroundColour(*wxWHITE);
|
||||||
p->m_object_list->Bind(wxCUSTOMEVT_EXIT_SEARCH, [this](wxCommandEvent&) {
|
p->m_object_list->Bind(wxCUSTOMEVT_EXIT_SEARCH, [this](wxCommandEvent&) {
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
this->p->m_search_item->Enable(true);
|
this->p->m_search_item->Enable(true);
|
||||||
@@ -4306,7 +4308,7 @@ void Sidebar::update_mixed_filament_list()
|
|||||||
wxWindowUpdateLocker noUpdates(this);
|
wxWindowUpdateLocker noUpdates(this);
|
||||||
|
|
||||||
const wxColour mc_bg = StateColor::darkModeColorFor(*wxWHITE);
|
const wxColour mc_bg = StateColor::darkModeColorFor(*wxWHITE);
|
||||||
const wxColour mc_border = StateColor::darkModeColorFor(wxColour("#CECECE"));
|
const wxColour mc_border = StateColor::darkModeColorFor(wxColour("#DBDBDB")); // same color with filament combo box border
|
||||||
const wxColour mc_text = StateColor::darkModeColorFor(wxColour("#262E30"));
|
const wxColour mc_text = StateColor::darkModeColorFor(wxColour("#262E30"));
|
||||||
const wxColour mc_dim = StateColor::darkModeColorFor(wxColour("#ACACAC"));
|
const wxColour mc_dim = StateColor::darkModeColorFor(wxColour("#ACACAC"));
|
||||||
|
|
||||||
@@ -4421,7 +4423,8 @@ void Sidebar::update_mixed_filament_list()
|
|||||||
size_t cfg_idx = mixed_indices[i];
|
size_t cfg_idx = mixed_indices[i];
|
||||||
auto* combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto* combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
combo_and_btn_sizer->Add(FromDIP(10), 0, 0, 0, 0);
|
if (i == 0 || i % 2 == 0) // dont add left margin for right column items so all horizontal margins will be equal like on filaments section
|
||||||
|
combo_and_btn_sizer->AddSpacer(FromDIP(SidebarProps::ContentMargin()));
|
||||||
|
|
||||||
// Parse components and ratios from config strings (supports 2-N components)
|
// Parse components and ratios from config strings (supports 2-N components)
|
||||||
std::vector<unsigned int> comp_ids;
|
std::vector<unsigned int> comp_ids;
|
||||||
@@ -4511,10 +4514,12 @@ void Sidebar::update_mixed_filament_list()
|
|||||||
dc.DrawText(txt, (sz.GetWidth() - txt_sz.GetWidth()) / 2,
|
dc.DrawText(txt, (sz.GetWidth() - txt_sz.GetWidth()) / 2,
|
||||||
(sz.GetHeight() - txt_sz.GetHeight()) / 2);
|
(sz.GetHeight() - txt_sz.GetHeight()) / 2);
|
||||||
});
|
});
|
||||||
combo_and_btn_sizer->Add(grad_panel, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(4));
|
grad_panel->Bind(wxEVT_LEFT_UP, [this, i](wxMouseEvent&) { edit_mixed_filament(i); }); // ORCA also open edit color dialog with clicking swatch
|
||||||
|
combo_and_btn_sizer->Add(grad_panel, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
|
||||||
} else {
|
} else {
|
||||||
combo_and_btn_sizer->Add(make_swatch_panel(p->m_panel_mixed_content, mix_col, mix_num),
|
auto swatch_panel = make_swatch_panel(p->m_panel_mixed_content, mix_col, mix_num);
|
||||||
0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(4));
|
swatch_panel->Bind(wxEVT_LEFT_UP, [this, i](wxMouseEvent&) { edit_mixed_filament(i); }); // ORCA also open edit color dialog with clicking swatch
|
||||||
|
combo_and_btn_sizer->Add(swatch_panel, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* content_panel = new wxPanel(p->m_panel_mixed_content, wxID_ANY);
|
auto* content_panel = new wxPanel(p->m_panel_mixed_content, wxID_ANY);
|
||||||
@@ -4738,9 +4743,9 @@ void Sidebar::update_mixed_filament_list()
|
|||||||
|
|
||||||
PopupMenu(&menu);
|
PopupMenu(&menu);
|
||||||
});
|
});
|
||||||
combo_and_btn_sizer->Add(menu_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(4));
|
combo_and_btn_sizer->Add(menu_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
|
||||||
|
|
||||||
combo_and_btn_sizer->Add(FromDIP(16), 0, 0, 0, 0);
|
combo_and_btn_sizer->Add(FromDIP(SidebarProps::ContentMargin()), 0, 0, 0, 0);
|
||||||
|
|
||||||
int side = i % 2;
|
int side = i % 2;
|
||||||
auto* col = (side == 0) ? left_col : right_col;
|
auto* col = (side == 0) ? left_col : right_col;
|
||||||
@@ -16318,7 +16323,7 @@ bool Plater::add_model(bool imperial_units, std::string fname)
|
|||||||
|
|
||||||
void Plater::calib_pa(const Calib_Params& params)
|
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);
|
new_project(false, false, calib_pa_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
@@ -16795,11 +16800,9 @@ void Plater::calib_flowrate(bool is_linear, int pass, InfillPattern pattern) {
|
|||||||
return;
|
return;
|
||||||
wxString calib_name;
|
wxString calib_name;
|
||||||
if (is_linear) {
|
if (is_linear) {
|
||||||
calib_name = L"Orca YOLO Flow Calibration";
|
calib_name = pass == 2 ? _L("Orca YOLO Flow Calibration - Perfectionist version") : _L("Orca YOLO Flow Calibration");
|
||||||
if (pass == 2)
|
|
||||||
calib_name += L" - Perfectionist version";
|
|
||||||
} else
|
} 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)
|
if (new_project(false, false, calib_name) == wxID_CANCEL)
|
||||||
return;
|
return;
|
||||||
@@ -16839,7 +16842,7 @@ void Plater::calib_temp(const Calib_Params& params) {
|
|||||||
constexpr double base_temp_tower_block_height = 10.0;
|
constexpr double base_temp_tower_block_height = 10.0;
|
||||||
constexpr int base_temp_tower_temp_step = 5;
|
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);
|
new_project(false, false, calib_temp_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_Temp_Tower) return;
|
if (params.mode != CalibMode::Calib_Temp_Tower) return;
|
||||||
@@ -16919,7 +16922,7 @@ void Plater::calib_temp(const Calib_Params& params) {
|
|||||||
|
|
||||||
void Plater::calib_max_vol_speed(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);
|
new_project(false, false, calib_vol_speed_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_Vol_speed_Tower)
|
if (params.mode != CalibMode::Calib_Vol_speed_Tower)
|
||||||
@@ -16998,7 +17001,7 @@ void Plater::calib_max_vol_speed(const Calib_Params& params)
|
|||||||
|
|
||||||
void Plater::calib_retraction(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);
|
new_project(false, false, calib_retraction_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_Retraction_tower)
|
if (params.mode != CalibMode::Calib_Retraction_tower)
|
||||||
@@ -17060,7 +17063,7 @@ void Plater::calib_retraction(const Calib_Params& params)
|
|||||||
|
|
||||||
void Plater::calib_VFA(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);
|
new_project(false, false, calib_vfa_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_VFA_Tower)
|
if (params.mode != CalibMode::Calib_VFA_Tower)
|
||||||
@@ -17143,7 +17146,7 @@ void Plater::calib_VFA(const Calib_Params& params)
|
|||||||
|
|
||||||
void Plater::calib_input_shaping_freq(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);
|
new_project(false, false, calib_input_shaping_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_Input_shaping_freq)
|
if (params.mode != CalibMode::Calib_Input_shaping_freq)
|
||||||
@@ -17205,7 +17208,7 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params)
|
|||||||
|
|
||||||
void Plater::calib_input_shaping_damp(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);
|
new_project(false, false, calib_input_shaping_name);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_Input_shaping_damp)
|
if (params.mode != CalibMode::Calib_Input_shaping_damp)
|
||||||
@@ -17266,7 +17269,7 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params)
|
|||||||
|
|
||||||
void Plater::Calib_Cornering(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);
|
new_project(false, false, Calib_Cornering);
|
||||||
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
|
||||||
if (params.mode != CalibMode::Calib_Cornering)
|
if (params.mode != CalibMode::Calib_Cornering)
|
||||||
@@ -17454,7 +17457,7 @@ void Plater::load_gcode(const wxString& filename)
|
|||||||
if (p->preview->get_canvas3d()->get_gcode_layers_zs().empty()) {
|
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."),
|
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();
|
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 {
|
} else {
|
||||||
set_project_filename(filename);
|
set_project_filename(filename);
|
||||||
}
|
}
|
||||||
@@ -17805,7 +17808,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename)
|
|||||||
// Orca: hide the "Don't show again" checkbox, people keeps accidentally checked this then forgot
|
// Orca: hide the "Don't show again" checkbox, people keeps accidentally checked this then forgot
|
||||||
// wxBoxSizer *m_sizer_left = new wxBoxSizer(wxHORIZONTAL);
|
// 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_left->Add(dont_show_again, 0, wxALL, 5);
|
||||||
//
|
//
|
||||||
// m_sizer_bottom->Add(m_sizer_left, 0, wxEXPAND, 5);
|
// m_sizer_bottom->Add(m_sizer_left, 0, wxEXPAND, 5);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "slic3r/GUI/Event.hpp"
|
#include "slic3r/GUI/Event.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "slic3r/GUI/ObjectDataViewModel.hpp"
|
#include "slic3r/GUI/ObjectDataViewModel.hpp"
|
||||||
#include "slic3r/GUI/SettingsIndex.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);
|
wxDECLARE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent);
|
||||||
using ColorEvent = Event<wxColour>;
|
using ColorEvent = Event<wxColour>;
|
||||||
wxDECLARE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent);
|
wxDECLARE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent);
|
||||||
const wxString DEFAULT_PROJECT_NAME = "Untitled";
|
const wxString DEFAULT_PROJECT_NAME = L("Untitled");
|
||||||
|
|
||||||
class SidebarProps
|
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);
|
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) {
|
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.
|
// 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.
|
// Deleting a plugin from the cloud is a plugin hub operation and is never offered here.
|
||||||
if (is_cloud && !is_orphaned && !is_mine) {
|
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) {
|
} 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_orphaned) {
|
||||||
if (is_cloud) {
|
if (is_cloud) {
|
||||||
add_action("reinstall_plugin", "Reinstall");
|
add_action("reinstall_plugin", L("Reinstall"));
|
||||||
} else {
|
} else {
|
||||||
add_action("reload_plugin", "Reload");
|
add_action("reload_plugin", L("Reload"));
|
||||||
add_action("clear_cache_reload_plugin", "Delete cache and 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 (!available_actions.can_toggle) {
|
||||||
if (dialog_item.unauthorized && available_actions.toggle_installs_cloud_plugin == false && row_data.has_local_package() == false) {
|
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);
|
manager.set_plugin_error(plugin_key, install_error);
|
||||||
show_status(from_u8(install_error), "warn");
|
show_status(from_u8(install_error), "warn");
|
||||||
}
|
}
|
||||||
@@ -1071,7 +1071,7 @@ void PluginsDialog::run_script_plugin_capability(const std::string& plugin_key,
|
|||||||
ExecutionResult result;
|
ExecutionResult result;
|
||||||
|
|
||||||
auto complete_with_error = [this, &manager, &plugin_key](const std::string& plugin_error, const wxString& status_message) {
|
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))
|
if (!manager.set_plugin_error(plugin_key, normalized_error))
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Failed to record plugin error. plugin_key=" << plugin_key;
|
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) {
|
if (clear_cache) {
|
||||||
PluginDescriptor descriptor;
|
PluginDescriptor descriptor;
|
||||||
if (!manager.try_get_plugin_descriptor(plugin_key, 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;
|
boost::filesystem::path resolved_root;
|
||||||
std::string resolve_error;
|
std::string resolve_error;
|
||||||
if (!resolve_allowed_plugin_root(descriptor, {get_orca_plugins_dir()},
|
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))
|
resolved_root, resolve_error))
|
||||||
return {false, resolve_error};
|
return {false, resolve_error};
|
||||||
cache_dir = resolved_root / "__whl_extracted__";
|
cache_dir = resolved_root / "__whl_extracted__";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manager.unload_plugin(plugin_key))
|
if (!manager.unload_plugin(plugin_key))
|
||||||
return {false, "Failed to unload plugin."};
|
return {false, _u8L("Failed to unload plugin.")};
|
||||||
|
|
||||||
if (clear_cache) {
|
if (clear_cache) {
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
boost::filesystem::remove_all(cache_dir, ec);
|
boost::filesystem::remove_all(cache_dir, ec);
|
||||||
if (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);
|
manager.load_plugin(plugin_key, false);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!manager.wait_for_plugin_load(plugin_key, std::chrono::minutes(5), error) || !manager.is_plugin_loaded(plugin_key))
|
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))
|
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, {}};
|
return {true, {}};
|
||||||
},
|
},
|
||||||
@@ -1297,7 +1297,7 @@ void PluginsDialog::reload_local_plugin(const std::string& plugin_key, bool clea
|
|||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
reload_result = {false, ex.what()};
|
reload_result = {false, ex.what()};
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
reload_result = {false, "Unknown plugin reload error."};
|
reload_result = {false, _u8L("Unknown plugin reload error.")};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reload_result.first) {
|
if (!reload_result.first) {
|
||||||
@@ -1344,14 +1344,14 @@ void PluginsDialog::reinstall_cloud_plugin(const PluginDescriptor& plugin)
|
|||||||
manager.load_plugin(plugin_key);
|
manager.load_plugin(plugin_key);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!manager.wait_for_plugin_load(plugin_key, std::chrono::minutes(5), error) || !manager.is_plugin_loaded(plugin_key))
|
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, {}};
|
return {true, {}};
|
||||||
},
|
},
|
||||||
_L("Reloading plugin"), _L("Reloading plugin"));
|
_L("Reloading plugin"), _L("Reloading plugin"));
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
reload_result = {false, ex.what()};
|
reload_result = {false, ex.what()};
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
reload_result = {false, "Unknown plugin reload error."};
|
reload_result = {false, _u8L("Unknown plugin reload error.")};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reload_result.first) {
|
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 */,
|
if (!::CreateProcessW(nullptr /* lpApplicationName */, (LPWSTR) command_line.c_str(), nullptr /* lpProcessAttributes */,
|
||||||
nullptr /* lpThreadAttributes */, false /* bInheritHandles */,
|
nullptr /* lpThreadAttributes */, false /* bInheritHandles */,
|
||||||
CREATE_UNICODE_ENVIRONMENT /* | CREATE_NEW_CONSOLE */ /* dwCreationFlags */, (LPVOID) envstr.c_str(),
|
CREATE_UNICODE_ENVIRONMENT /* | CREATE_NEW_CONSOLE */ /* dwCreationFlags */, (LPVOID) envstr.c_str(),
|
||||||
nullptr /* lpCurrentDirectory */, &startup_info, &process_info))
|
nullptr /* lpCurrentDirectory */, &startup_info, &process_info)) {
|
||||||
throw Slic3r::RuntimeError(std::string("Failed starting the script ") + boost::nowide::narrow(command_line) +
|
const int error = int(::GetLastError());
|
||||||
", Win32 error: " + std::to_string(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);
|
::WaitForSingleObject(process_info.hProcess, INFINITE);
|
||||||
ULONG rc = 0;
|
ULONG rc = 0;
|
||||||
::GetExitCodeProcess(process_info.hProcess, &rc);
|
::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);
|
LPWSTR* szArglist = CommandLineToArgvW(boost::nowide::widen(script).c_str(), &nArgs);
|
||||||
if (szArglist == nullptr || nArgs <= 0) {
|
if (szArglist == nullptr || nArgs <= 0) {
|
||||||
// CommandLineToArgvW failed. Maybe the command line escapment is invalid?
|
// CommandLineToArgvW failed. Maybe the command line escapment is invalid?
|
||||||
throw Slic3r::RuntimeError(std::string("Post processing script ") + script + " on file " + gcode +
|
throw Slic3r::RuntimeError(Slic3r::format(_u8L("Post processing script %1% on file %2% failed. CommandLineToArgvW() refused to parse the command line path."),
|
||||||
" failed. CommandLineToArgvW() refused to parse the command line path.");
|
script, gcode));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring command_line;
|
std::wstring command_line;
|
||||||
std::wstring command = szArglist[0];
|
std::wstring command = szArglist[0];
|
||||||
if (!boost::filesystem::exists(boost::filesystem::path(command)))
|
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")) {
|
if (boost::iends_with(command, L".pl")) {
|
||||||
// This is a perl script. Run it through the perl interpreter.
|
// This is a perl script. Run it through the perl interpreter.
|
||||||
// The current process may be slic3r.exe or slic3r-console.exe.
|
// 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";
|
boost::filesystem::path path_perl = path_exe.parent_path() / "perl" / "perl.exe";
|
||||||
if (!boost::filesystem::exists(path_perl)) {
|
if (!boost::filesystem::exists(path_perl)) {
|
||||||
LocalFree(szArglist);
|
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.
|
// Replace it with the current perl interpreter.
|
||||||
quote_argv_winapi(boost::nowide::widen(path_perl.string()), command_line);
|
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);
|
exec_result = cap->execute(ctx);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
const std::string msg =
|
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;
|
BOOST_LOG_TRIVIAL(error) << msg;
|
||||||
throw Slic3r::RuntimeError(msg);
|
throw Slic3r::RuntimeError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exec_result.status == PluginResult::RecoverableError || exec_result.status == PluginResult::FatalError) {
|
if (exec_result.status == PluginResult::RecoverableError || exec_result.status == PluginResult::FatalError) {
|
||||||
const std::string msg =
|
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;
|
BOOST_LOG_TRIVIAL(error) << msg;
|
||||||
throw Slic3r::RuntimeError(msg);
|
throw Slic3r::RuntimeError(msg);
|
||||||
}
|
}
|
||||||
@@ -370,7 +371,7 @@ bool run_post_process_scripts(
|
|||||||
std::string error_message;
|
std::string error_message;
|
||||||
if (copy_file(src_path, path, error_message, false) != SUCCESS)
|
if (copy_file(src_path, path, error_message, false) != SUCCESS)
|
||||||
throw Slic3r::RuntimeError(
|
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));
|
error_message));
|
||||||
} else {
|
} else {
|
||||||
// Don't make a copy of the G-code before running the post-processing script.
|
// 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);
|
auto gcode_file = boost::filesystem::path(path);
|
||||||
if (!boost::filesystem::exists(gcode_file))
|
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.
|
// Store print configuration into environment variables.
|
||||||
config.setenv_();
|
config.setenv_();
|
||||||
@@ -431,11 +432,11 @@ bool run_post_process_scripts(
|
|||||||
const int result = run_script(script, gcode_file.string(), std_err);
|
const int result = run_script(script, gcode_file.string(), std_err);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
const std::string msg = std_err.empty() ?
|
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)
|
script % path % result)
|
||||||
.str() :
|
.str() :
|
||||||
(boost::format(
|
(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)
|
script % path % result % std_err)
|
||||||
.str();
|
.str();
|
||||||
BOOST_LOG_TRIVIAL(error) << msg;
|
BOOST_LOG_TRIVIAL(error) << msg;
|
||||||
@@ -476,19 +477,19 @@ bool run_post_process_scripts(
|
|||||||
new_output_name = outpath.string();
|
new_output_name = outpath.string();
|
||||||
} else {
|
} else {
|
||||||
if (!op.is_absolute() || !op.has_filename())
|
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()))
|
if (!fs::exists(fs::path(new_output_name).parent_path()))
|
||||||
throw Slic3r::RuntimeError(
|
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 "
|
BOOST_LOG_TRIVIAL(trace) << "Post-processing script changed the file name from " << output_name << " to "
|
||||||
<< new_output_name;
|
<< new_output_name;
|
||||||
output_name = new_output_name;
|
output_name = new_output_name;
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
throw Slic3r::RuntimeError(Slic3r::format("run_post_process_scripts: Failed reading a file %1% "
|
throw Slic3r::RuntimeError("run_post_process_scripts: " +
|
||||||
"carrying the final name / path of a G-code file: %2%",
|
Slic3r::format(_u8L("Failed reading a file %1% carrying the final name / path of a G-code file: %2%"),
|
||||||
path_output_name, err.what()));
|
path_output_name, err.what()));
|
||||||
}
|
}
|
||||||
remove_output_name_file();
|
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<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 };
|
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);
|
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."));
|
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(
|
auto item_speed_dial_recents = create_item_spinctrl(
|
||||||
_L("Recent actions"),
|
_L("Recent actions"),
|
||||||
"",
|
"",
|
||||||
|
// TRN Unit shown after the number of recent actions, as in "5 actions".
|
||||||
_L("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."),
|
_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,
|
SETTING_SPEED_DIAL_RECENT_COUNT,
|
||||||
@@ -1851,7 +1852,7 @@ void PreferencesDialog::create_items()
|
|||||||
g_sizer->AddGrowableCol(0, 1);
|
g_sizer->AddGrowableCol(0, 1);
|
||||||
|
|
||||||
//// CONTROL > Behaviour
|
//// 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<wxString> FlushOptionLabels = {_L("All"),_L("Color"),_L("None")};
|
||||||
std::vector<std::string> FlushOptionValues = { "all","color change","disabled" };
|
std::vector<std::string> FlushOptionValues = { "all","color change","disabled" };
|
||||||
@@ -1900,7 +1901,7 @@ void PreferencesDialog::create_items()
|
|||||||
if (wxGetApp().is_enable_cad_feature()) {
|
if (wxGetApp().is_enable_cad_feature()) {
|
||||||
auto item_connector_face_glyph = create_item_checkbox(_L("Draw mate connectors as a face"),
|
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 "
|
_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");
|
"Turn this off for the conventional CAD representation."), "design_connector_face_glyph");
|
||||||
g_sizer->Add(item_connector_face_glyph);
|
g_sizer->Add(item_connector_face_glyph);
|
||||||
|
|
||||||
@@ -1999,7 +2000,11 @@ void PreferencesDialog::create_items()
|
|||||||
);
|
);
|
||||||
g_sizer->Add(item_realistic_ssao);
|
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" };
|
std::vector<std::string> ShadowsValues = { "off", "static", "orbit" };
|
||||||
auto item_realistic_shadows = create_item_combobox(
|
auto item_realistic_shadows = create_item_combobox(
|
||||||
_L("Shadows"),
|
_L("Shadows"),
|
||||||
@@ -2305,18 +2310,18 @@ void PreferencesDialog::create_items()
|
|||||||
auto item_show_unsupported = create_item_checkbox(_L("Show unsupported presets"), _L("Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."), "show_unsupported_presets");
|
auto item_show_unsupported = create_item_checkbox(_L("Show unsupported presets"), _L("Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."), "show_unsupported_presets");
|
||||||
g_sizer->Add(item_show_unsupported);
|
g_sizer->Add(item_show_unsupported);
|
||||||
|
|
||||||
auto item_plugin_printer_agents = create_item_checkbox(
|
|
||||||
_L("(Experimental) Use printer agents instead of print hosts"), _L(
|
|
||||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\nWhen disabled, OrcaSlicer uses the legacy print-host behavior."),
|
|
||||||
"use_printer_agents");
|
|
||||||
g_sizer->Add(item_plugin_printer_agents);
|
|
||||||
|
|
||||||
//// DEVELOPER > Experimental Features
|
//// DEVELOPER > Experimental Features
|
||||||
g_sizer->Add(create_item_title(_L("Experimental Features")), 1, wxEXPAND);
|
g_sizer->Add(create_item_title(_L("Experimental Features")), 1, wxEXPAND);
|
||||||
|
|
||||||
auto item_keep_painting = create_item_checkbox(_L("Keep painted feature after mesh change"), _L("Attempt to keep painted features (color/seam/support/fuzzy etc.) after changing the object mesh (such as cut/reload from disk/simplify/fix etc.)\nHighly experimental! Slow and may create artifact."), "keep_painting");
|
auto item_keep_painting = create_item_checkbox(_L("Keep painted feature after mesh change"), _L("Attempt to keep painted features (color/seam/support/fuzzy etc.) after changing the object mesh (such as cut/reload from disk/simplify/fix etc.)\nHighly experimental! Slow and may create artifact."), "keep_painting");
|
||||||
g_sizer->Add(item_keep_painting);
|
g_sizer->Add(item_keep_painting);
|
||||||
|
|
||||||
|
auto item_plugin_printer_agents = create_item_checkbox(
|
||||||
|
_L("Use printer agents instead of print hosts"), _L(
|
||||||
|
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\nWhen disabled, OrcaSlicer uses the legacy print-host behavior."),
|
||||||
|
"use_printer_agents");
|
||||||
|
g_sizer->Add(item_plugin_printer_agents);
|
||||||
|
|
||||||
//// DEVELOPER > Storage
|
//// DEVELOPER > Storage
|
||||||
|
|
||||||
g_sizer->Add(create_item_title(_L("Storage")), 1, wxEXPAND);
|
g_sizer->Add(create_item_title(_L("Storage")), 1, wxEXPAND);
|
||||||
|
|||||||