Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7eadc93ecc | ||
|
|
6146a793ab | ||
|
|
0d80446301 |
@@ -1,11 +1,7 @@
|
||||
# clang-tidy configuration, enforced by the clang-tidy CI job on the lines a pull
|
||||
# request changes (scripts/clang_tidy_diff.py). Only missing includes are reported
|
||||
# for now: a file should include the header for every symbol it uses, not rely on
|
||||
# the precompiled header or another header's includes. Run with --fix to add them.
|
||||
# Every check listed here gates pull requests, so enable a new one only once the
|
||||
# code it flags on touched lines is reasonable to fix in passing.
|
||||
# clang-tidy configuration. Only missing includes are reported for now: a file
|
||||
# should include the header for every symbol it uses, not rely on the
|
||||
# precompiled header or another header's includes. Run with --fix to add them.
|
||||
Checks: '-*,misc-include-cleaner'
|
||||
WarningsAsErrors: '*'
|
||||
CheckOptions:
|
||||
# Missing includes only. Builds without the precompiled header break on these.
|
||||
misc-include-cleaner.UnusedIncludes: false
|
||||
|
||||
@@ -405,13 +405,9 @@ page object to insert and remove by pointer). `LazyPage(parent, name, order, fac
|
||||
factory is `new Panel(parent)`. Its `Show(true)` builds the panel the first time (only once the
|
||||
top-level frame is shown — `MainFrame::Show` completes the start page on the frame's first show) and
|
||||
forwards later shows/hides to the panel, so the panel's own `Show()` override stays its activation
|
||||
hook. The build runs before the placeholder's own `wxPanel::Show(true)`, so an on-demand build creates
|
||||
its controls in a hidden window as a prebuild does: on MSW each control created or moved inside a
|
||||
shown window re-clips and repaints its shown siblings, which made a large panel's first show take
|
||||
seconds. A lazy panel's constructor therefore runs off screen (except the start page's) and must not
|
||||
rely on `IsShownOnScreen()`. A panel built while its page is hidden stays hidden, and `when_built`
|
||||
gives it the dark-UI pass the frame ran before it existed (`apply_dark_ui_to_lazy_panel`).
|
||||
`pending()` is true only while the page is in the book.
|
||||
hook. A panel built while its page is hidden stays hidden, and `when_built` gives it the dark-UI pass
|
||||
the frame ran before it existed (`apply_dark_ui_to_lazy_panel`). `pending()` is true only while the page
|
||||
is in the book.
|
||||
|
||||
### Staged construction: StagedBuild
|
||||
|
||||
@@ -645,10 +641,8 @@ Spacing constants come from `SidebarProps` (`Plater.hpp`): `TitlebarMargin()`, `
|
||||
|
||||
### Docking
|
||||
|
||||
Docks are `AuiMgr`s (`AuiMgr.hpp`), a `wxAuiManager` subclass carrying Orca's dock art, theme and
|
||||
Wayland rule (`references/webview-gl-aui-media.md`). `Plater::priv` owns `m_aui_mgr`, managing the
|
||||
plater; the Design tab owns its own for its sidebar (`DesignPanel::m_aui`, layout in
|
||||
`design_window_layout`). Plater panes: `"sidebar"` (left, no close
|
||||
`Plater::priv` owns `AuiMgr m_aui_mgr` (a `wxAuiManager` subclass whose `CreateFloatingFrame` returns a
|
||||
themed `FloatFrame : wxAuiFloatingFrame`), managing the plater. Panes: `"sidebar"` (left, no close
|
||||
button, not top/bottom dockable), `"main"` (`CenterPane()`, the `panel_3d`), `"uv_editor"` (right,
|
||||
hidden until the texture-displacement gizmo shows it), plus dynamic dock panes. The default perspective
|
||||
is saved right after `AddPane`; the app-config `window_layout` is applied with
|
||||
|
||||
@@ -271,14 +271,6 @@ Each bullet names the mechanism and the file that owns it.
|
||||
- **Painting:** in 3.3.2 windows are not double-buffered by default (the 3.3.0 global
|
||||
`WS_EX_COMPOSITED` was reverted, `docs/changes.txt:308`). Custom widgets buffer by hand →
|
||||
`references/painting-custom-widgets.md`.
|
||||
- **Building large panels:** every control is a native child window, and outside a sizer pass a move
|
||||
or resize is immediate, repainting when the window is shown [source: `src/msw/window.cpp:2036`
|
||||
`DoMoveSibling` → `MSWMoveWindowToAnyPosition(..., IsShown())`]; `wxStaticText::SetLabel`/`SetFont`
|
||||
resize the control that way (`src/common/stattextcmn.cpp:334` `AutoResizeIfNecessary`). Created
|
||||
inside a shown parent, each control re-clips and erases its shown, overlapping siblings, so the
|
||||
cost grows with the number already built and hundreds of controls take seconds. Build a large
|
||||
panel while its parent is hidden and show it once complete — `LazyPage::Show` builds its panel
|
||||
before showing the page for this reason → `references/orca-architecture.md` §Deferred construction.
|
||||
- **Modal loops:** idle events do not run inside the Windows sizing/moving modal loop, so the 3D
|
||||
canvas renders from `on_paint` on MSW (c06a0223a7) → `references/webview-gl-aui-media.md` §GLCanvas3D rendering.
|
||||
- **Mouse capture:** `wxEVT_MOUSE_CAPTURE_LOST` and `wxEVT_MOUSE_CAPTURE_CHANGED` are delivered →
|
||||
@@ -482,7 +474,7 @@ start there when looking for prior art. The sites below are exemplars, cited by
|
||||
data-view cell editors an explicit top-level transient parent.
|
||||
`DropDown::ShouldDismissOnTopWindowDeactivate` handles Wayland chains.
|
||||
- `CheckBox::CheckBox`, `SwitchButton`, `RadioBox`, `ScalableButton` (`wxExtensions.cpp`),
|
||||
`PresetComboBoxes` call `RemoveButtonBorder`; `TextInput` and `SpinInput` call
|
||||
`ObjColorDialog`, `PresetComboBoxes` call `RemoveButtonBorder`; `TextInput` and `SpinInput` call
|
||||
`RemoveInputBorder` on their inner `wxTextCtrl`.
|
||||
- `Plater::priv::priv` together with `sanitize_window_layout_for_wayland`: AUI floating is disabled on
|
||||
Wayland.
|
||||
@@ -820,7 +812,7 @@ widgets do it in their constructors.
|
||||
(`"*.GtkBitmapToggleButton"`, class `"GtkEntry"`). The first call changes every matching widget in
|
||||
the process, not just the one passed in.
|
||||
|
||||
**Callers:** `CheckBox::CheckBox`, `SwitchButton`, `RadioBox`, `ScalableButton` and
|
||||
**Callers:** `CheckBox::CheckBox`, `SwitchButton`, `RadioBox`, `ScalableButton`, `ObjColorDialog` and
|
||||
`PresetComboBoxes` (`RemoveButtonBorder`); the inner `wxTextCtrl` of `TextInput` and `SpinInput`
|
||||
(`RemoveInputBorder`). A new owner-drawn control built on a native GTK widget needs the same call.
|
||||
|
||||
|
||||
@@ -88,7 +88,6 @@ available; GTK2/WebKit1 is an opt-out configuration the GUI does not support.
|
||||
24. ImGui text uses `_u8L`; ImGui sizes are physical pixels (scale by `GLCanvas3D::get_scale()`);
|
||||
a font atlas must fit `GL_MAX_TEXTURE_SIZE`. §[ImGui boundary](#the-imgui-layer-boundary)
|
||||
25. After `AddPane` or any `wxAuiPaneInfo` change, call `wxAuiManager::Update()` once for the batch.
|
||||
Keep a docked pane hidden until the managed window has been laid out.
|
||||
§[AUI](#wxauimanager-and-orcas-docking)
|
||||
26. Give every pane a unique, stable `Name()` free of layout delimiters (`|`, `;`, `=`, `\`).
|
||||
§[AUI](#wxauimanager-and-orcas-docking)
|
||||
@@ -921,16 +920,6 @@ widgets beside the canvas (a sibling, not a child over it), or in a popup.
|
||||
- **Update.** "Update() must be invoked after AddPane() or InsertPane() … any number of changes may be
|
||||
made to wxAuiPaneInfo structures (retrieved with wxAuiManager::GetPane), but to realize the changes,
|
||||
Update() must be called" (`interface/wx/aui/framemanager.h:747-756`). Batch, then `Update()` once.
|
||||
- **Dock size** [source]. The docs limit "any new dock" to a `SetDockSizeConstraint` fraction of the
|
||||
window (`interface/wx/aui/framemanager.h:660-672`). The source applies it to the managed window's client
|
||||
size at the `Update()` that creates the dock, sizing the dock from its panes' `best_size` and then
|
||||
raising it to their `min_size` (`src/aui/framemanager.cpp:2748-2848`); a dock with a resizable pane
|
||||
keeps that size (`2674-2677`), and resizing the managed window only re-lays the docks out
|
||||
(`4542-4546`). A pane first shown before its managed window is laid out — a `wxDefaultSize` window is
|
||||
20×20 until its first sizer layout (`references/sizers-layout.md`) — docks at that width or its
|
||||
`min_size` and stays there. Hiding a dock's last shown pane empties it, and the next `Update()`
|
||||
removes it (`2733-2738`) with any `dock_size` a `LoadPerspective` restored, so the pane comes back
|
||||
at its `best_size`.
|
||||
- **Names** [source]. A duplicate `Name()` hits `wxFAIL` (silent in Orca); duplicate and empty names
|
||||
get a random identifier (`src/aui/framemanager.cpp:949-1010`), which `LoadPerspective` can never
|
||||
match. `AddPane` rejects a null window, but its "already managed" check looks up `paneInfo.window`
|
||||
@@ -964,12 +953,11 @@ widgets beside the canvas (a sibling, not a child over it), or in a popup.
|
||||
- `wxAuiNotebook` (not used by Orca): page indices are logical; use `GetPagePosition()` for on-screen
|
||||
order (`docs/changes.txt:121-126`); the default tab art changed (`35-37`).
|
||||
|
||||
**OrcaSlicer.** Orca's docks use `AuiMgr` (`AuiMgr.hpp`), a `wxAuiManager` whose `CreateFloatingFrame`
|
||||
returns a `wxAuiFloatingFrame` that applies `UpdateFrameDarkUI`. `init(window)` calls
|
||||
`SetManagedWindow(window)` and `SetDockSizeConstraint(1, 1)`, clears `wxAUI_MGR_ALLOW_FLOATING` on
|
||||
Wayland and sets the dock-art metrics and colours; `apply_color_mode()` re-colours captions, sashes and
|
||||
borders and is called from the owner's theme-switch handler. `Plater::priv::m_aui_mgr` manages the
|
||||
Plater (Prepare and Preview); `DesignPanel::m_aui` manages the Design tab's body below its toolbar.
|
||||
**OrcaSlicer.** `Plater::priv` owns `AuiMgr m_aui_mgr`, a `wxAuiManager` whose `CreateFloatingFrame`
|
||||
returns `FloatFrame : wxAuiFloatingFrame` (applies `UpdateFrameDarkUI`).
|
||||
- Setup: `SetManagedWindow(q)` (the Plater), `SetDockSizeConstraint(1, 1)`; on Wayland clears
|
||||
`wxAUI_MGR_ALLOW_FLOATING` (`disable_wayland_floating`); dock-art metrics set here, colours in the
|
||||
dark-mode update (`Plater::priv::apply_color_mode`).
|
||||
- Panes: `"sidebar"` (left, no close button, not top/bottom dockable, `BestSize` in em units),
|
||||
`"uv_editor"` (right, hidden; forced hidden again after a layout load), `"main"`
|
||||
(`CenterPane().PaneBorder(false)`, holding `panel_3d` with View3D, Preview and AssembleView in one
|
||||
@@ -978,8 +966,8 @@ Plater (Prepare and Preview); `DesignPanel::m_aui` manages the Design tab's body
|
||||
`window_layout` app-config string goes through `sanitize_window_layout_for_wayland` (strips
|
||||
floating/floatable bits on Wayland) and `LoadPerspective(layout, false)`, falling back to the default
|
||||
on failure; then one `Update()`. `Plater::priv::reset` saves `SavePerspective()` back to
|
||||
`window_layout`. `AuiMgr::track_docked_size` copies a docked pane's size into `BestSize` on idle
|
||||
(wxAUI does not record a dragged sash there), so the width persists. `Plater::priv::reset_window_layout` is the model for
|
||||
`window_layout`. An idle handler copies the docked sidebar width into `BestSize` (wxAUI does not record
|
||||
a dragged sash there), so the width persists. `Plater::priv::reset_window_layout` is the model for
|
||||
re-establishing panes after a load: it loads the default perspective, then re-shows each plugin pane
|
||||
the perspective does not list.
|
||||
- Plugin panes: `Plater::add_dock_pane(window, name, caption, dock, size, on_close)` (window must be a
|
||||
@@ -989,29 +977,13 @@ Plater (Prepare and Preview); `DesignPanel::m_aui` manages the Design tab's body
|
||||
`Destroy()`s without running `on_close`; `show_dock_pane` toggles and updates. Pane names come from
|
||||
`plugin_pane_name` (`DockPanel.cpp`), which replaces `|`, `;`, `=`, `\` — the perspective-string
|
||||
delimiters.
|
||||
- Other pages: a page outside the Plater docks through its own `AuiMgr` member, since the Plater's
|
||||
manages only the Plater. Its managed window is a body panel below the page's toolbar; a sidebar
|
||||
takes `AuiMgr::sidebar_pane_info()`; the layout has its own app-config key, is reset from
|
||||
`Plater::reset_window_layout`, and is saved by a `shutdown()` called from `MainFrame::shutdown`,
|
||||
which also detaches a floating pane (Lifetime below). Where floating is disabled it forces
|
||||
`Dock().Floatable(false)` after loading, as plugin panes do. A `LazyPage` builds its panel at 20×20
|
||||
and lays it out only as the tab shows, so the sidebar stays hidden until the tab is first shown (Dock
|
||||
size above). `DesignPanel` is the model
|
||||
(`docs/HLSD/design-tab.md`). A `GLCanvas3D` beside such a sidebar gets that sidebar's collapse
|
||||
button with `set_collapse_toolbar`; without it the canvas falls back to the Plater's button, which
|
||||
collapses Prepare's sidebar.
|
||||
- Lifetime: no explicit `UnInit`. `m_aui_mgr` is a `Plater::priv` member, so it is destroyed in
|
||||
`~Plater`, before `~wxWindow` destroys the Plater's children (`wxWindowBase::DestroyChildren`,
|
||||
`src/common/wincmn.cpp:586-609`); a floating frame is such a child (`CreateFloatingFrame(m_frame, …)`,
|
||||
`src/aui/framemanager.cpp:3151`), so a pane still floating at that point outlives the manager [source].
|
||||
Plugin panes are removed earlier (`MainFrame::shutdown` → `Plater::remove_dock_panes`). A handler
|
||||
that can outlive its pane looks the pane up when it runs, as `track_docked_size` does: an idle
|
||||
handler bound on the pane's window outlives the `DetachPane` in `DesignPanel::shutdown`. Never detach
|
||||
a pane whose `GetPane()` reference is captured (Pane references above). `DesignPanel::shutdown` is
|
||||
the model for a member manager: it detaches a
|
||||
floating sidebar, which `Destroy()`s the frame into the pending-delete list, and the main frame's
|
||||
deletion deletes pending top-level children before its own children (`~wxTopLevelWindowBase`,
|
||||
`src/common/toplvcmn.cpp:67-93`), while the panel and its manager are still alive [source].
|
||||
Plugin panes are removed earlier (`MainFrame::shutdown` → `Plater::remove_dock_panes`). The sidebar
|
||||
`GetPane()` reference captured by the idle lambda is safe across `AddPane`; never `DetachPane` a pane
|
||||
whose reference is captured.
|
||||
|
||||
**Pitfalls.**
|
||||
- **Rule:** Call `Update()` once after a batch of `AddPane`/`wxAuiPaneInfo` changes.
|
||||
|
||||
@@ -198,7 +198,7 @@ change, its line, and what it means for Orca.
|
||||
| `wxAuiGenericTabArt` subclasses (also via `wxAuiMSWTabArt`) override `DrawPageTab()`/`GetPageTabSize()` instead of `DrawTab()`/`GetTabSize()`; direct `wxAuiTabArt` subclasses still work | :115-120 | none: no Orca tab art |
|
||||
| `wxAuiNotebook` page index is logical (reorder-independent); `GetPagePosition()` gives the screen position | :122-126 | none; index math under `wxAUI_NB_TAB_MOVE` is what breaks |
|
||||
| `wxListbook`/`wxChoicebook` interpret mnemonics in page titles "just as the other wx*book classes already did" | :128-130 | Orca uses neither (`BedShapeDialog` uses `wxSimplebook` + a combo); every book interprets `&` (`interface/wx/bookctrl.h:141-147`) → rule 11 |
|
||||
| `wxAUI_MGR_HINT_FADE` is not in the default `wxAuiManager` style | :132-133 | Orca's `AuiMgr` keeps the default flags (minus `wxAUI_MGR_ALLOW_FLOATING` on Wayland, `AuiMgr::init`), so the docking hint no longer fades; add the flag if wanted |
|
||||
| `wxAUI_MGR_HINT_FADE` is not in the default `wxAuiManager` style | :132-133 | Plater's `AuiMgr` keeps the default flags (minus `wxAUI_MGR_ALLOW_FLOATING` on Wayland, `Plater::priv::priv`), so the docking hint no longer fades; add the flag if wanted |
|
||||
| `wxPrintDialogData::SetAllPages(false)`/`SetSelection(false)` changed meaning | :135-137 | none |
|
||||
| `wxGetTranslation()` returns `wxString` by value | :139-142 | pitfall below |
|
||||
| `wxWindow::Raise()` no longer shows a hidden window on any port | :144-146 | pitfall below; ba867cc534 |
|
||||
|
||||
@@ -10,6 +10,3 @@
|
||||
# resume after `call :label`. With LF endings that offset can land wrong and the
|
||||
# label lookup fails, so keep these CRLF whatever the platform.
|
||||
*.bat text eol=crlf
|
||||
|
||||
# OCCT BRep fixtures, kept byte for byte as OCCT wrote them.
|
||||
*.brep -text
|
||||
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
|
||||
uses: ./.github/workflows/build_check_cache.yml
|
||||
with:
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-15' }}
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }}
|
||||
arch: ${{ matrix.arch }}
|
||||
build-deps-only: ${{ inputs.build-deps-only || false }}
|
||||
force-build: ${{ github.event_name == 'schedule' }}
|
||||
@@ -138,7 +138,7 @@ jobs:
|
||||
if: ${{ !cancelled() && needs.build_macos_arch.result == 'success' && !inputs.build-deps-only && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
|
||||
uses: ./.github/workflows/build_orca.yml
|
||||
with:
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-15' }}
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }}
|
||||
arch: universal
|
||||
macos-combine-only: true
|
||||
secrets: inherit
|
||||
@@ -182,7 +182,7 @@ jobs:
|
||||
if: ${{ !cancelled() && success() }}
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-15' }}
|
||||
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }}
|
||||
artifact: ${{ github.sha }}-tests-macos-arm64
|
||||
test-dir: build/arm64/tests
|
||||
# Slice a two-colour cube through every shipped printer, and through every
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
# Anything that changes how the tree is built belongs in the key, or a job
|
||||
# restores one it cannot use. Linux amd64 passes no arch deliberately, so
|
||||
# 'linux-clang' keeps the cache it already has.
|
||||
cache-os: ${{ runner.os == 'macOS' && format('{0}-{1}', inputs.os, inputs.arch) || (runner.os == 'Windows' && format('windows-{0}-{1}', inputs.arch, inputs.compiler) || format('linux-clang{0}', inputs.arch && format('-{0}', inputs.arch) || '')) }}
|
||||
cache-os: ${{ runner.os == 'macOS' && format('macos-{0}', inputs.arch) || (runner.os == 'Windows' && format('windows-{0}-{1}', inputs.arch, inputs.compiler) || format('linux-clang{0}', inputs.arch && format('-{0}', inputs.arch) || '')) }}
|
||||
# The Windows ARM64 deps build in build-arm64, all others under build;
|
||||
# build_deps.yml and build_orca.yml pass the Windows directory to build_win.bat.
|
||||
dep-folder-name: ${{ runner.os == 'macOS' && format('/{0}', inputs.arch) || (runner.os == 'Windows' && inputs.arch == 'arm64') && '-arm64/OrcaSlicer_dep' || '/OrcaSlicer_dep' }}
|
||||
|
||||
@@ -183,12 +183,10 @@ jobs:
|
||||
- name: Free disk space
|
||||
if: runner.os == 'macOS' && !inputs.macos-combine-only && !vars.SELF_HOSTED
|
||||
run: |
|
||||
df -hI /
|
||||
# Keep only the selected Xcode
|
||||
xcode=$(basename "$(cd "$(xcode-select -p)/../.." && pwd -P)")
|
||||
sudo find /Applications -maxdepth 1 -type d -name "Xcode_*.app" ! -name "$xcode" -exec rm -rf {} +
|
||||
df -hI /dev/disk3s1s1
|
||||
sudo find /Applications -maxdepth 1 -type d -name "Xcode_*.app" ! -name "Xcode_15.4.app" -exec rm -rf {} +
|
||||
sudo rm -rf ~/Library/Developer/CoreSimulator/Caches/*
|
||||
df -hI /
|
||||
df -hI /dev/disk3s1s1
|
||||
|
||||
- name: Build slicer mac
|
||||
if: runner.os == 'macOS' && !inputs.macos-combine-only
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
name: clang-tidy
|
||||
|
||||
# Runs clang-tidy, with the checks in .clang-tidy, over the C++ lines a pull
|
||||
# request changes (scripts/clang_tidy_diff.py). The compile database is
|
||||
# configured without the precompiled header, so code that only builds because
|
||||
# the PCH supplied an include fails here.
|
||||
#
|
||||
# No paths filter: the job is a required check, and a workflow skipped by a
|
||||
# paths filter leaves a required check pending forever. A PR with no C++
|
||||
# changes finishes after the first step.
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- release/*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
clang_tidy:
|
||||
# Branch protection requires this check by name. Renaming the job disables
|
||||
# that gate.
|
||||
name: clang-tidy
|
||||
runs-on: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
lfs: 'false'
|
||||
# The PR merge commit plus its first parent, the base it is diffed against.
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Look for changed C++ files
|
||||
id: changes
|
||||
run: |
|
||||
if git diff --name-only HEAD^1 -- src tests | grep -qE '\.(cpp|cc|cxx|hpp|h|hxx)$'; then
|
||||
echo "cpp=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "No C++ changes under src/ or tests/."
|
||||
fi
|
||||
|
||||
# Parsing needs the dependency headers, not a build of this PR's deps/, so
|
||||
# a PR that changes deps/ falls back to the newest cache main has.
|
||||
- name: Restore cached deps
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep
|
||||
key: linux-clang-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }}
|
||||
restore-keys: linux-clang-cache-orcaslicer_deps-build-
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Apt-Install Dependencies
|
||||
if: steps.changes.outputs.cpp == 'true' && !vars.SELF_HOSTED
|
||||
uses: ./.github/actions/apt-install-deps
|
||||
|
||||
- name: Install clang-tidy
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: |
|
||||
python3 -m venv "$RUNNER_TEMP/clang-tidy"
|
||||
"$RUNNER_TEMP/clang-tidy/bin/pip" install --quiet -r scripts/clang_tidy_requirements.txt
|
||||
|
||||
# DEP_BUILD_DIR is named outright: CMake would otherwise derive it from the build
|
||||
# directory's name and look for the dependencies in deps/build-tidy.
|
||||
- name: Configure without the precompiled header
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: >
|
||||
cmake -S . -B build-tidy -G Ninja
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
-DSLIC3R_PCH=OFF -DORCA_TOOLS=ON -DBUILD_TESTS=ON
|
||||
-DDEP_BUILD_DIR=${{ github.workspace }}/deps/build
|
||||
|
||||
# The one header the build generates rather than the configure.
|
||||
- name: Generate git_commit_hash.h
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: cmake --build build-tidy --target git_commit_hash_header
|
||||
|
||||
- name: Run clang-tidy on the changed lines
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: >
|
||||
python3 scripts/clang_tidy_diff.py -p build-tidy --base HEAD^1
|
||||
--clang-tidy "$RUNNER_TEMP/clang-tidy/bin/clang-tidy" -j "$(nproc)"
|
||||
@@ -36,7 +36,6 @@ ctest --test-dir ./tests/fff_print -C Release
|
||||
|
||||
- C++17, selective C++20. PascalCase classes, snake_case functions/variables
|
||||
- `#pragma once` for headers. Smart pointers and RAII preferred
|
||||
- Include what you use: include the header for every symbol a file uses, and keep headers compilable on their own. Never rely on the precompiled header or a transitive include. The `clang-tidy` CI job enforces this on changed lines; run the same check locally with `scripts/run_clang_tidy.sh` (`scripts\run_clang_tidy.ps1` on Windows), which sets up everything it needs
|
||||
- Parallelization via TBB — be mindful of shared state
|
||||
- Always use `SetSizerAndFit(sizer)` instead of `SetSizer(sizer)` on top level window. Unless `SetSizer` must be called before the full layout is built, call `sizer->SetSizeHints(window)` afterwards in this case.
|
||||
|
||||
|
||||
@@ -1131,8 +1131,7 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
||||
if (NOT OCCT_LIBS)
|
||||
message(FATAL_ERROR "OCCT_LIBS is not set; libslic3r must be configured first.")
|
||||
endif ()
|
||||
string(TOUPPER "${config}" _config_upper)
|
||||
set(_occt_bin "${OCCT_BIN_DIR_${_config_upper}}")
|
||||
set(_occt_bin "${CMAKE_PREFIX_PATH}/bin/occt")
|
||||
set(_occt_dlls "")
|
||||
set(_occt_staged "")
|
||||
set(_missing_occt "")
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake
|
||||
index 00000000..00000001 100644
|
||||
--- a/adm/cmake/occt_defs_flags.cmake
|
||||
+++ b/adm/cmake/occt_defs_flags.cmake
|
||||
@@ -134,7 +134,11 @@
|
||||
set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
# Optimize size of binaries
|
||||
- set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
+ # clang-cl reports the Clang compiler ID, and OCCT builds shared on Windows,
|
||||
+ # where the MSVC-style linker gets this flag as an argument it does not know.
|
||||
+ if (NOT WIN32)
|
||||
+ set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
+ endif()
|
||||
elseif(MINGW)
|
||||
add_definitions(-D_WIN32_WINNT=0x0601)
|
||||
# _WIN32_WINNT=0x0601 (use Windows 7 SDK)
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index d98acc0f..28eb8eb4 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -225,7 +225,7 @@ if (NOT DEFINED INSTALL_DIR_BIN)
|
||||
if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix")
|
||||
set (INSTALL_DIR_BIN "bin" CACHE PATH "${INSTALL_DIR_BIN_DESCR}")
|
||||
else()
|
||||
- set (INSTALL_DIR_BIN "${OS_WITH_BIT}/${COMPILER}/bin" CACHE PATH "${INSTALL_DIR_BIN_DESCR}")
|
||||
+ set (INSTALL_DIR_BIN "bin/occt" CACHE PATH "${INSTALL_DIR_BIN_DESCR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -243,11 +243,11 @@ if (NOT DEFINED INSTALL_DIR_LIB)
|
||||
if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix")
|
||||
set (INSTALL_DIR_LIB "lib" CACHE PATH "${INSTALL_DIR_LIB_DESCR}")
|
||||
else()
|
||||
- set (INSTALL_DIR_LIB "${OS_WITH_BIT}/${COMPILER}/lib" CACHE PATH "${INSTALL_DIR_LIB_DESCR}")
|
||||
+ set (INSTALL_DIR_LIB "lib/occt" CACHE PATH "${INSTALL_DIR_LIB_DESCR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
-# OCCT headers: <prefix>/inc for windows,
|
||||
+# OCCT headers: <prefix>/include for windows,
|
||||
# <prefix>/include/opencascade-7.0.0 for unix
|
||||
if (NOT DEFINED INSTALL_DIR_INCLUDE)
|
||||
if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix")
|
||||
@@ -256,7 +256,7 @@ if (NOT DEFINED INSTALL_DIR_INCLUDE)
|
||||
set (INSTALL_DIR_INCLUDE "include/opencascade-${OCC_VERSION_STRING_EXT}" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}" FORCE)
|
||||
endif()
|
||||
else()
|
||||
- set (INSTALL_DIR_INCLUDE "inc" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}")
|
||||
+ set (INSTALL_DIR_INCLUDE "include/occt" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -330,7 +330,7 @@ if (NOT DEFINED INSTALL_DIR_CMAKE)
|
||||
set (INSTALL_DIR_CMAKE "lib/cmake/opencascade" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}")
|
||||
endif()
|
||||
else()
|
||||
- set (INSTALL_DIR_CMAKE "cmake" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}")
|
||||
+ set (INSTALL_DIR_CMAKE "lib/cmake/occt" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -338,13 +338,13 @@ endif()
|
||||
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_resources")
|
||||
|
||||
# install LICENSE_LGPL_21.txt and OCCT_LGPL_EXCEPTION.txt files
|
||||
-if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix")
|
||||
- OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" "${INSTALL_DIR_DOC}")
|
||||
- OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" "${INSTALL_DIR_DOC}")
|
||||
-else()
|
||||
- OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" ".")
|
||||
- OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" ".")
|
||||
-endif()
|
||||
+#if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix")
|
||||
+# OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" "${INSTALL_DIR_DOC}")
|
||||
+# OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" "${INSTALL_DIR_DOC}")
|
||||
+#else()
|
||||
+# OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" ".")
|
||||
+# OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" ".")
|
||||
+#endif()
|
||||
|
||||
if(APPLE)
|
||||
set (INSTALL_NAME_DIR "" CACHE STRING "install_name library suffix on OS X (e.g. @executable_path/../Frameworks)")
|
||||
@@ -850,34 +850,34 @@ endif()
|
||||
|
||||
# build directories
|
||||
if (SINGLE_GENERATOR)
|
||||
- set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib${BIN_LETTER}")
|
||||
- set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin${BIN_LETTER}")
|
||||
- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib${BIN_LETTER}")
|
||||
+ set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/occt")
|
||||
+ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/occt")
|
||||
+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/occt")
|
||||
if (WIN32)
|
||||
- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin${BIN_LETTER}")
|
||||
+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/occt")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
-set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib")
|
||||
-set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin")
|
||||
-set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib")
|
||||
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib/occt")
|
||||
+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin/occt")
|
||||
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib/occt")
|
||||
|
||||
-set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libi")
|
||||
-set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bini")
|
||||
-set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libi")
|
||||
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib/occt/RelWithDebInfo")
|
||||
+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin/occt/RelWithDebInfo")
|
||||
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib/occt/RelWithDebInfo")
|
||||
|
||||
-set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libd")
|
||||
-set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bind")
|
||||
-set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libd")
|
||||
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib/occt/Debug")
|
||||
+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin/occt/Debug")
|
||||
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib/occt/Debug")
|
||||
|
||||
if (WIN32)
|
||||
- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin")
|
||||
- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bini")
|
||||
- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bind")
|
||||
+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin/occt")
|
||||
+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin/occt/RelWithDebInfo")
|
||||
+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin/occt/Debug")
|
||||
endif()
|
||||
|
||||
string(TIMESTAMP CURRENT_TIME "%H:%M:%S")
|
||||
-message (STATUS "\nInfo: \(${CURRENT_TIME}\) Start collecting all OCCT header files into ${CMAKE_BINARY_DIR}/inc ...")
|
||||
+message (STATUS "\nInfo: \(${CURRENT_TIME}\) Start collecting all OCCT header files into ${CMAKE_BINARY_DIR}/include/occt ...")
|
||||
|
||||
# collect all the headers to <binary dir>/inc folder
|
||||
COLLECT_AND_INSTALL_OCCT_HEADER_FILES ("${CMAKE_BINARY_DIR}" "${BUILD_TOOLKITS}" "${CMAKE_SOURCE_DIR}/src" "${INSTALL_DIR_INCLUDE}")
|
||||
@@ -984,9 +984,9 @@ if (EXISTS "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}")
|
||||
|
||||
set (CUSTOM_CONTENT "${CUSTOM_CONTENT} ${ADDITIONAL_CUSTOM_CONTENT}")
|
||||
|
||||
- file (WRITE "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}" "${CUSTOM_CONTENT}")
|
||||
+ #file (WRITE "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}" "${CUSTOM_CONTENT}")
|
||||
else()
|
||||
- OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.${SCRIPT_EXT}.main" "custom.${SCRIPT_EXT}" "custom.${SCRIPT_EXT}" "${INSTALL_DIR_SCRIPT}")
|
||||
+ #OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.${SCRIPT_EXT}.main" "custom.${SCRIPT_EXT}" "custom.${SCRIPT_EXT}" "${INSTALL_DIR_SCRIPT}")
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
@@ -1007,7 +1007,7 @@ endforeach()
|
||||
|
||||
# write current custom.bat/sh (for install directory)
|
||||
set (SUB_CUSTOM_BUILD_NAME "custom_${COMPILER}_${COMPILER_BITNESS}.install.${SCRIPT_EXT}")
|
||||
-OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.install.${SCRIPT_EXT}.in" "${SUB_CUSTOM_BUILD_NAME}" "${SUB_CUSTOM_NAME}" "${INSTALL_DIR_SCRIPT}")
|
||||
+#OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.install.${SCRIPT_EXT}.in" "${SUB_CUSTOM_BUILD_NAME}" "${SUB_CUSTOM_NAME}" "${INSTALL_DIR_SCRIPT}")
|
||||
|
||||
# write current custom.bat/sh (for build directory)
|
||||
OCCT_CONFIGURE ("adm/templates/custom.build.${SCRIPT_EXT}.in" "${SUB_CUSTOM_NAME}")
|
||||
@@ -1019,9 +1019,9 @@ endif()
|
||||
|
||||
if (WIN32)
|
||||
# env script for draw in building environment
|
||||
- OCCT_CONFIGURE ("adm/templates/env.${SCRIPT_EXT}.in" "env.${SCRIPT_EXT}")
|
||||
+ #OCCT_CONFIGURE ("adm/templates/env.${SCRIPT_EXT}.in" "env.${SCRIPT_EXT}")
|
||||
# install env script
|
||||
- install (FILES "${CMAKE_BINARY_DIR}/env.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}")
|
||||
+ #install (FILES "${CMAKE_BINARY_DIR}/env.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}")
|
||||
# copy build.bat and install.bat scripts to CMake binary folder
|
||||
OCCT_COPY_FILE_OR_DIR ("adm/templates/build.bat" "${CMAKE_BINARY_DIR}")
|
||||
OCCT_COPY_FILE_OR_DIR ("adm/templates/install.bat" "${CMAKE_BINARY_DIR}")
|
||||
@@ -1043,12 +1043,12 @@ endif()
|
||||
FILE_TO_LIST ("adm/RESOURCES" RESOURCES)
|
||||
foreach(RESOURCE ${RESOURCES})
|
||||
get_filename_component(RESOURCE_FOLDER ${RESOURCE} DIRECTORY)
|
||||
- if(NOT "${RESOURCE_FOLDER}" STREQUAL "")
|
||||
- get_filename_component(RESOURCE_FOLDER ${RESOURCE_FOLDER} NAME)
|
||||
- OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}/${RESOURCE_FOLDER}")
|
||||
- else()
|
||||
- OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}")
|
||||
- endif()
|
||||
+ #if(NOT "${RESOURCE_FOLDER}" STREQUAL "")
|
||||
+ # get_filename_component(RESOURCE_FOLDER ${RESOURCE_FOLDER} NAME)
|
||||
+ # OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}/${RESOURCE_FOLDER}")
|
||||
+ #else()
|
||||
+ # OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}")
|
||||
+ #endif()
|
||||
endforeach()
|
||||
|
||||
if (BUILD_SAMPLES_QT)
|
||||
diff --git a/adm/cmake/occt_macros.cmake b/adm/cmake/occt_macros.cmake
|
||||
index 224c96b1..8c94a1c5 100644
|
||||
--- a/adm/cmake/occt_macros.cmake
|
||||
+++ b/adm/cmake/occt_macros.cmake
|
||||
@@ -608,7 +608,7 @@ macro (OCCT_INSERT_CODE_FOR_TARGET)
|
||||
install(CODE "if (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$\")
|
||||
set (OCCT_INSTALL_BIN_LETTER \"\")
|
||||
elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$\")
|
||||
- set (OCCT_INSTALL_BIN_LETTER \"i\")
|
||||
+ set (OCCT_INSTALL_BIN_LETTER \"\")
|
||||
elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
|
||||
set (OCCT_INSTALL_BIN_LETTER \"d\")
|
||||
endif()")
|
||||
diff --git a/adm/cmake/occt_toolkit.cmake b/adm/cmake/occt_toolkit.cmake
|
||||
index 550e0e2f..7ac1a3b8 100644
|
||||
--- a/adm/cmake/occt_toolkit.cmake
|
||||
+++ b/adm/cmake/occt_toolkit.cmake
|
||||
@@ -241,7 +241,7 @@
|
||||
else()
|
||||
set (aReleasePdbConf)
|
||||
endif()
|
||||
- install (FILES ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin\${OCCT_INSTALL_BIN_LETTER}/${PROJECT_NAME}.pdb
|
||||
+ install (FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
|
||||
CONFIGURATIONS Debug ${aReleasePdbConf} RelWithDebInfo
|
||||
DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}")
|
||||
endif()
|
||||
diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx
|
||||
index 5ae9899f..0a17372b 100644
|
||||
--- a/src/Font/Font_FTFont.cxx
|
||||
+++ b/src/Font/Font_FTFont.cxx
|
||||
@@ -103,9 +103,11 @@ bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData,
|
||||
{
|
||||
throw Standard_ProgramError ("Font_FTFont, Light and Normal hinting styles are mutually exclusive");
|
||||
}
|
||||
+#ifdef HAVE_FREETYPE
|
||||
setLoadFlag (FT_LOAD_TARGET_LIGHT, (theParams.FontHinting & Font_Hinting_Light) != 0);
|
||||
setLoadFlag (FT_LOAD_NO_HINTING, (theParams.FontHinting & Font_Hinting_Normal) == 0
|
||||
&& (theParams.FontHinting & Font_Hinting_Light) == 0);
|
||||
+#endif
|
||||
|
||||
// manage native / autohinting
|
||||
if ((theParams.FontHinting & Font_Hinting_ForceAutohint) != 0
|
||||
@@ -113,8 +115,10 @@ bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData,
|
||||
{
|
||||
throw Standard_ProgramError ("Font_FTFont, ForceAutohint and NoAutohint are mutually exclusive");
|
||||
}
|
||||
+#ifdef HAVE_FREETYPE
|
||||
setLoadFlag (FT_LOAD_FORCE_AUTOHINT, (theParams.FontHinting & Font_Hinting_ForceAutohint) != 0);
|
||||
setLoadFlag (FT_LOAD_NO_AUTOHINT, (theParams.FontHinting & Font_Hinting_NoAutohint) != 0);
|
||||
+#endif
|
||||
|
||||
if (!myFTLib->IsValid())
|
||||
{
|
||||
From 7236e83dcc1e7284e66dc61e612154617ef715d6 Mon Sep 17 00:00:00 2001
|
||||
From: dpasukhi <dpasukhi@opencascade.com>
|
||||
Date: Tue, 27 Aug 2024 11:33:29 +0100
|
||||
Subject: [PATCH] 0033808: Coding - FreeType Use unsigned point and contour
|
||||
indexing in `FT_Outline`
|
||||
|
||||
Changes to auto instead of specific type
|
||||
---
|
||||
src/StdPrs/StdPrs_BRepFont.cxx | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/StdPrs/StdPrs_BRepFont.cxx b/src/StdPrs/StdPrs_BRepFont.cxx
|
||||
index ab2d9b3c9f..cd701879b1 100644
|
||||
--- a/src/StdPrs/StdPrs_BRepFont.cxx
|
||||
+++ b/src/StdPrs/StdPrs_BRepFont.cxx
|
||||
@@ -457,7 +457,7 @@ Standard_Boolean StdPrs_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
for (short aContour = 0, aStartIndex = 0; aContour < anOutline->n_contours; ++aContour)
|
||||
{
|
||||
const FT_Vector* aPntList = &anOutline->points[aStartIndex];
|
||||
- const char* aTags = &anOutline->tags[aStartIndex];
|
||||
+ const auto* aTags = &anOutline->tags[aStartIndex];
|
||||
const short anEndIndex = anOutline->contours[aContour];
|
||||
const short aPntsNb = (anEndIndex - aStartIndex) + 1;
|
||||
aStartIndex = anEndIndex + 1;
|
||||
@@ -1,5 +1,5 @@
|
||||
# clang-cl cannot emit some OCCT sources for ARM64 (llvm/llvm-project#62081).
|
||||
# cl and clang-cl share an ABI.
|
||||
# clang-cl cannot emit IGESAppli_GeneralModule.cxx on ARM64
|
||||
# (llvm/llvm-project#62081). cl and clang-cl share an ABI.
|
||||
set(_occt_compiler_args "")
|
||||
if ("${DEPS_ARCH}" STREQUAL "arm64" AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(_occt_compiler_args -DCMAKE_C_COMPILER:STRING=cl -DCMAKE_CXX_COMPILER:STRING=cl)
|
||||
@@ -15,31 +15,31 @@ endif()
|
||||
# (fillet/offset/loft), whose only consumer is the parametric Design/CAD tab. With it OFF
|
||||
# the deps prefix matches upstream exactly.
|
||||
#
|
||||
# With it ON OCCT also builds TKFillet (used via BRepFilletAPI), TKOffset (used via
|
||||
# BRepOffsetAPI), and TKFeat, TKHelix, TKXMesh and TKExpress, which nothing here references
|
||||
# but which the module flag builds anyway, since module flags are all-or-nothing. The
|
||||
# module's other toolkits are built either way, because DataExchange (the STEP path)
|
||||
# depends on them.
|
||||
# With it ON the delta is THREE toolkits, not two: TKFillet (7.40 MiB archive, used via
|
||||
# BRepFilletAPI), TKOffset (5.38 MiB, used via BRepOffsetAPI) and TKFeat (4.42 MiB), which
|
||||
# nothing here references but which the module flag builds anyway -- it is all-or-nothing
|
||||
# per module. The module's other nine toolkits are built either way, because DataExchange
|
||||
# (the STEP path upstream already ships) depends on them.
|
||||
#
|
||||
# On macOS/Linux OCCT links statically, so an unreferenced toolkit costs build time and no
|
||||
# shipped bytes. Windows ships only the DLLs libslic3r links, so the tab adds the TKFillet,
|
||||
# TKOffset and TKBool DLLs. See docs/HLSD/design-tab.md.
|
||||
# shipped bytes. The Windows figure is a real DLL cost and has NOT been measured -- an
|
||||
# earlier "3.77 MiB, Windows only" note here covered only two of the three toolkits and is
|
||||
# not a number to quote. See docs/HLSD/design-tab.md.
|
||||
|
||||
if (IN_GIT_REPO)
|
||||
set(OCCT_DIRECTORY_FLAG --directory ${BINARY_DIR_REL}/dep_OCCT-prefix/src/dep_OCCT)
|
||||
endif ()
|
||||
|
||||
orcaslicer_add_cmake_project(OCCT
|
||||
URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V8_0_1.zip
|
||||
URL_HASH SHA256=7c033d917ee8f040c0512d289dcc5f02c148889d5bac17c3e25639accb44f0da
|
||||
URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_0.zip
|
||||
URL_HASH SHA256=28334f0e98f1b1629799783e9b4d21e05349d89e695809d7e6dfa45ea43e1dbc
|
||||
#PATCH_COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch
|
||||
PATCH_COMMAND git apply ${OCCT_DIRECTORY_FLAG} --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch
|
||||
#DEPENDS dep_Boost
|
||||
DEPENDS ${FREETYPE_PKG}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
-DBUILD_LIBRARY_TYPE=${library_build_type}
|
||||
# With the Unix layout, OCCT's resources and licenses go under share/ and its scripts
|
||||
# into bin/occt on Windows too. libslic3r finds the CMake package in lib/cmake/occt.
|
||||
-DINSTALL_DIR_LAYOUT=Unix
|
||||
-DINSTALL_DIR_BIN=bin/occt
|
||||
-DINSTALL_DIR_LIB=lib/occt
|
||||
-DINSTALL_DIR_INCLUDE=include/occt
|
||||
-DINSTALL_DIR_CMAKE=lib/cmake/occt
|
||||
-DUSE_TK=OFF
|
||||
-DUSE_TBB=OFF
|
||||
#-DUSE_FREETYPE=OFF
|
||||
|
||||
@@ -75,19 +75,6 @@ static FILE *stl_open_count_facets(stl_file *stl, const char *file, unsigned int
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Zero normals and coordinates like 10 or 15 have no byte above 127, so the test above can miss a binary file.
|
||||
// Its size still matches its facet count; text read as that count would need a file of gigabytes.
|
||||
if (stl->stats.type == ascii) {
|
||||
uint32_t header_num_facets;
|
||||
fseek(fp, custom_header_length, SEEK_SET);
|
||||
if (fread(&header_num_facets, sizeof(uint32_t), 1, fp) == 1) {
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
stl_internal_reverse_quads((char*)&header_num_facets, 4);
|
||||
#endif /* BOOST_ENDIAN_BIG_BYTE */
|
||||
if (header_size + uint64_t(header_num_facets) * SIZEOF_STL_FACET == file_size)
|
||||
stl->stats.type = binary;
|
||||
}
|
||||
}
|
||||
rewind(fp);
|
||||
|
||||
uint32_t num_facets = 0;
|
||||
|
||||
@@ -38,11 +38,7 @@ no wx dependency and is unit-tested.
|
||||
The notebook needs a page object for a tab to exist and for tabs to be inserted and
|
||||
removed by pointer, and the placeholder is that object. It builds the real panel inside
|
||||
itself the first time it is shown and forwards showing and hiding afterwards, so a panel's
|
||||
own show handling stays its activation hook. The build runs before the placeholder shows
|
||||
itself, so a panel built on demand is created in a hidden window as a prebuilt one is: on
|
||||
Windows every control created or moved inside a shown window re-clips and repaints its
|
||||
shown siblings, which makes building a large panel into a shown page many times slower.
|
||||
Nothing builds while the main window is
|
||||
own show handling stays its activation hook. Nothing builds while the main window is
|
||||
hidden; the window's first show builds the start page. A page that is out of the book is
|
||||
not prebuilt. A panel built while its page is hidden stays hidden, and gets the theming
|
||||
the window applied before the panel existed.
|
||||
|
||||
@@ -13,9 +13,8 @@ known.
|
||||
Its coupling to the rest of the application is deliberately narrow. It adds no stage to the
|
||||
slicing pipeline and touches neither the preset system nor `Tab`. It reaches the rest of Orca
|
||||
in two places: **Commit to Plate**, which hands finished solids to Prepare as ordinary model
|
||||
objects (by default one assembly object with a part per body, which keeps the bodies' relative
|
||||
placement, or one object per body), and one optional 3MF archive entry that carries the recipe.
|
||||
Everything else is contained in `src/libslic3r/CAD/` and `src/slic3r/GUI/CAD/`.
|
||||
objects, and one optional 3MF archive entry that carries the recipe. Everything else is
|
||||
contained in `src/libslic3r/CAD/` and `src/slic3r/GUI/CAD/`.
|
||||
|
||||
The user-facing manual lives in the wiki
|
||||
([Design Tab](https://www.orcaslicer.com/wiki/design_tab)), not here. This document covers the
|
||||
@@ -52,13 +51,14 @@ widens the existing OCCT build by one module flag in `deps/OCCT/OCCT.cmake`:
|
||||
-DBUILD_MODULE_ModelingAlgorithms=${SLIC3R_CAD}
|
||||
```
|
||||
|
||||
Most of that module's toolkits are built either way, because `DataExchange`, which the STEP
|
||||
importer uses, depends on them. With the flag on, OCCT also builds `TKFillet` (used through
|
||||
`BRepFilletAPI`), `TKOffset` (`BRepOffsetAPI`), and `TKFeat`, `TKHelix`, `TKXMesh` and
|
||||
`TKExpress`, which nothing here references but which the module flag builds anyway, because
|
||||
OCCT's module flags are all-or-nothing. On macOS and Linux OCCT links statically, so an
|
||||
unreferenced toolkit costs build time and no shipped bytes. On Windows OCCT builds shared and
|
||||
only the linked toolkits ship, so the tab adds the `TKFillet`, `TKOffset` and `TKBool` DLLs.
|
||||
Most of that module's twelve toolkits were already being built, because `DataExchange` — the
|
||||
STEP path upstream ships — depends on them. The delta is `TKFillet` (used through
|
||||
`BRepFilletAPI`), `TKOffset` (`BRepOffsetAPI`) and `TKFeat`, which nothing here references but
|
||||
which the module flag builds anyway, because OCCT's module flags are all-or-nothing. On macOS
|
||||
and Linux OCCT links statically, so an unreferenced toolkit costs build time and no shipped
|
||||
bytes; on Windows OCCT builds shared, so the cost there is real DLL bytes. That Windows figure
|
||||
has not been measured, and `OCCT.cmake` says so rather than carrying a number that was derived
|
||||
from an incomplete toolkit list.
|
||||
|
||||
On Windows the packaging step asserts that every linked OCCT toolkit has a shipped DLL and
|
||||
fails the configure with the name of any that is missing, because the alternative failure — a
|
||||
@@ -117,11 +117,6 @@ that keep it survivable are:
|
||||
`Import` features embed the imported solid as an OCCT BRep string inside the recipe rather than
|
||||
referencing the source file, so a project opens without the STEP or mesh it was built from.
|
||||
The cost is that saved projects are coupled to an OCCT BRep revision.
|
||||
`tests/data/cad_brep_occt76.brep` holds a solid written by OCCT 7.6, and its test fails if the
|
||||
bundled OCCT can no longer read it.
|
||||
A Text feature follows the same rule: it stores the outlines it was vectorised into alongside
|
||||
its string, font and height, so the project opens identically on a machine that lacks the font;
|
||||
the three parameters are only what an edit reopens the dialog with.
|
||||
|
||||
## The interaction contract
|
||||
|
||||
@@ -136,7 +131,7 @@ contract between them is stated in code rather than spread across handlers.
|
||||
| `Transient` | a value field or a popup menu | closes it; the tool stays armed |
|
||||
| `Gesture` | an uncommitted delta — an entity being drawn, a body being dragged | reverts it; committed work is untouched |
|
||||
| `Tool` | a feature card, an armed sketch tool, a constrain session | exits it; drawn entities survive |
|
||||
| `Idle` | nothing transient | clears the selection, a Feature tree or Bodies row included; leaves a sketch session only if it is empty |
|
||||
| `Idle` | nothing transient | clears the selection; leaves a sketch session only if it is empty |
|
||||
|
||||
`cad_escape_level()` is a `constexpr` free function over a POD of four booleans rather than a
|
||||
method on the panel, so the ordering that is the entire contract is checkable without a window,
|
||||
@@ -149,126 +144,26 @@ explicit selection, the sketch ribbon's Cancel, which asks first, or `Ctrl+Z`. A
|
||||
*session* is deliberately not a `Tool` level; it is the environment the `Idle` level lives in,
|
||||
which makes the destructive path unrepresentable rather than merely unlikely.
|
||||
|
||||
Right-click is read at button-up against one budget, 3 px of drift, applied to the whole press
|
||||
rather than to its end points: a press that wandered past the budget at any moment is
|
||||
navigation, even if it comes back to where it started, which is what stops a slow, careful
|
||||
orbit from ending in a menu. There is no time budget — a gesture that means something different
|
||||
when it is slow is exactly what the interaction charter rules out. The raycast uses the press
|
||||
position, not the release. An armed sketch tool that already consumed the right
|
||||
Right-click is read at button-up against two independent budgets — 3 px of drift and 200 ms —
|
||||
because drift alone still popped a menu at the end of a slow, careful orbit. The raycast uses
|
||||
the press position, not the release. An armed sketch tool that already consumed the right
|
||||
button (to terminate a chain, say) declines to also open a menu, through a read-and-clear flag.
|
||||
Past either budget the event is navigation, and navigation does not transition the state
|
||||
machine.
|
||||
|
||||
Navigation itself is Prepare's: the camera reads the drag actions set in Preferences > Control
|
||||
for each button. The left button is shared with picking, so a whole body is swept with a
|
||||
rectangle on plain left-drag only while no camera action is assigned to it, and with
|
||||
Shift+left-drag otherwise — Prepare's own rectangle selection.
|
||||
|
||||
Entering a sketch changes three things at once so the mode is legible: a banner above the
|
||||
canvas (a sibling of the canvas, not a child over it — on GTK a child window over a
|
||||
`wxGLCanvas` is a native window and does not reliably stack over GL), the printer bed muted so
|
||||
a plate grid is never read as a sketch grid, and `N` to look normal to the plane. Code that
|
||||
changes any of the three belongs with a change to this section.
|
||||
|
||||
## Rendering the bodies
|
||||
|
||||
The tab draws its bodies through the same `GLCanvas3D` object path as Prepare, so how they look
|
||||
is decided in the shared object shader, not in the tab. The slicer's two lights both sit near
|
||||
the camera, which leaves the sides of a part in nearly one tone; the Design canvas asks for a
|
||||
studio model instead — a world-space sky/ground hemisphere, a key and a fill light, a
|
||||
plastic-like highlight and a darker silhouette — through `GLCanvas3D::set_studio_lighting()`
|
||||
and the phong shader's `lighting_model` uniform. The program is shared by every canvas, so each
|
||||
use sets the uniform (0 for the slicer's canvases) rather than relying on a default: a canvas
|
||||
that left it alone would inherit whatever the last canvas chose.
|
||||
|
||||
The B-rep edges of every body are drawn over it by the sketch overlay as thin view-facing
|
||||
ribbons, depth tested and pulled a few pixels toward the eye so they win against the faces that
|
||||
meet at them and still hide behind faces in front; lines are not used because they do not
|
||||
rasterise under the software GL context the tab also supports. Seams of closed surfaces and
|
||||
degenerate edges are left out (`GeometryEngine::display_edges`), and the polylines are sampled
|
||||
once per shape, keyed by its `TShape`, because a recompute that leaves a body unchanged is the
|
||||
common case.
|
||||
|
||||
While a feature card is open, its preview ghost is the whole model the candidate would produce,
|
||||
drawn translucent over the bodies, so every face the feature leaves alone is in both at the same
|
||||
depth. The ghost is drawn with a depth bias that pushes it back (`GLVolume::depth_bias`), so on a shared face
|
||||
the body always wins instead of the two copies z-fighting, and the ghost shows only where the
|
||||
result reaches past the bodies. Material a feature removes lies inside the old solid and would not
|
||||
show at all, so the tools whose result mostly coincides with the body — Fillet/Chamfer, Draft,
|
||||
Hole and the Mate hover — hide the bodies once the preview is valid and draw the result alone,
|
||||
opaque.
|
||||
|
||||
## Showing what is selected
|
||||
|
||||
A selection is drawn on the faces it names, never as a tint over the body: a translucent
|
||||
selection colour blended into the body's own colour turns a different hue on every body and
|
||||
vanishes on one close to it. Selected faces are split out of their body into a volume of their
|
||||
own, which the canvas draws opaque in the selection colour through the same shader and lighting
|
||||
as the body (`DesignCanvas::rebuild_bodies`); the sketch overlay outlines them with a cased line
|
||||
— a dark band under a selection-coloured one — so the outline still reads on a body that wears
|
||||
the selection colour itself. A body picked whole, a face picked in the viewport and the faces of
|
||||
the Feature tree's selected feature all draw this way. The hover pre-highlight is the outline
|
||||
alone, uncased: it promises a click, it is not one. The automatic body colours keep clear of the
|
||||
selection colour's blues and teals, so no body looks selected before anything is picked; a colour
|
||||
the user sets on a body is theirs, and the cased outline keeps its selection readable.
|
||||
|
||||
Selecting a feature row lights the faces that feature made, not the whole body it sits on, so a
|
||||
fillet row shows its round and the extrude under it keeps the faces the fillet trimmed.
|
||||
`CadDocument::faces_made_by` answers it without per-feature history: it replays the recipe to
|
||||
just before the feature and then the feature alone, and a face of the finished model belongs to
|
||||
the feature when an interior point of it lies on the boundary afterwards and not before, facing
|
||||
the same way — the facing keeps a block stacked on a base the owner of its bottom face. A feature
|
||||
that makes no face of its own, such as a Boolean union, answers with the bodies it changed. The
|
||||
replay costs up to a recompute, so the panel finds the faces once per row and topology
|
||||
generation, off the UI thread, and only while no feature card is open. One selection is live at
|
||||
a time: a viewport pick clears the feature row and a feature row clears the viewport pick, as the
|
||||
Feature tree and Bodies list do between themselves. `Esc`, a click on empty space and an
|
||||
empty rubber band all let go of it, whichever list or pick made it.
|
||||
|
||||
## Following the app
|
||||
|
||||
The tab is a page of Orca's main window and answers to the same settings as Prepare.
|
||||
|
||||
- **Theme.** Its chrome is coloured from a table of light/dark token pairs. A theme switch
|
||||
reaches `DesignPanel::on_sys_color_changed` from `MainFrame`, which moves every colour that is
|
||||
one theme's token onto the other theme's and then runs the app's own dark pass; the icons are
|
||||
Orca's sidebar grey, which the icon cache maps per theme, so they are re-rasterised rather
|
||||
than re-tinted.
|
||||
- **Scale.** Sizes are in DIP, and a DPI change reaches `DesignPanel::msw_rescale`, which
|
||||
re-rasterises every icon (button faces, flyout rows, card headers, the feature and body lists'
|
||||
row icons).
|
||||
- **Sidebar icons.** Every clickable icon in the sidebar shows a hover chip. The card-header and
|
||||
constraint-row buttons are Orca's self-painted `Button`, because a native button cannot take a
|
||||
hover background on macOS. The Feature tree and Bodies lists are a custom-drawn
|
||||
`DesignRowList` rather than a `wxTreeCtrl`, so each row carries its own actions — Edit,
|
||||
Show/hide and Delete on a feature, Move, Show/hide and Delete on a body — and the eye shows
|
||||
whether that row is hidden.
|
||||
- **Viewport text.** The status line and the active tool's values are drawn by the canvas in
|
||||
its ImGui pass, so they go with the canvas: a top-level window over GL does not follow its
|
||||
frame and was left floating over other applications.
|
||||
- **Undo.** The tab keeps its own history (the recipe is not part of Prepare's snapshots), but
|
||||
it has no Undo/Redo of its own: the top bar, `Ctrl+Z` and Edit drive it while the tab is
|
||||
shown, greyed to what an undo would actually do.
|
||||
- **Docking.** The sidebar docks like Prepare's — either side, floating, resized, or collapsed
|
||||
with the canvas's collapse button or `Shift+Tab` — through its own AUI manager under the
|
||||
toolbar, because Prepare's manages the Plater and the Plater is not on this page. The button is
|
||||
the canvas's own toolbar rather than Prepare's, which collapses Prepare's sidebar. The layout,
|
||||
collapse included, is kept apart from Prepare's (`design_window_layout`) and starts where
|
||||
Prepare's sidebar is, at its width, so the canvas edge holds still across the tab switch until
|
||||
the user moves one of them. A floating sidebar is a top-level window, so it is hidden with the
|
||||
tab rather than left over the other pages, and View > Reset Window Layout resets both tabs.
|
||||
|
||||
## The offer is generated, not hand-written
|
||||
|
||||
Right-clicking geometry opens the *offer*: eight families in a fixed order, each verb at a
|
||||
permanent row index, verbs that do not apply shown disabled **in place with their reason**
|
||||
rather than removed. The invariant is that a verb's row index is identical in every selection
|
||||
where it appears and that adding a verb never moves an existing one — the hand learns the
|
||||
position, so the menu is never re-sorted, compacted or adaptively ordered. Above the families
|
||||
sits one *flat* row, holding Rename and Color — what a selection is opened for most: its verbs are
|
||||
items of their own at the top of the menu rather than a family's submenu. It is appended after
|
||||
the eight, so it moved no existing index, and it reads the same from the viewport and from a row
|
||||
of the Bodies list.
|
||||
position, so the menu is never re-sorted, compacted or adaptively ordered.
|
||||
|
||||
An invariant across 92 verbs and 20 selection kinds does not survive by review, so the map
|
||||
exists once, as data: `scripts/CAD/tool_atlas.json` carries every verb with its row, key, icon,
|
||||
@@ -299,7 +194,6 @@ scripted action and a clicked one cannot diverge. It is off unless the variable
|
||||
| `src/libslic3r/CAD/SketchSolver.*` | constraint solving, over the vendored solver |
|
||||
| `src/libslic3r/slvs/` | vendored 2D constraint solver (GPLv3) |
|
||||
| `src/slic3r/GUI/CAD/DesignPanel.*` | the tab: toolbar, feature cards, tree, key maps |
|
||||
| `src/slic3r/GUI/CAD/DesignRowList.*` | the Feature tree and Bodies lists, with per-row actions |
|
||||
| `src/slic3r/GUI/CAD/DesignCanvas.*` | viewport integration |
|
||||
| `src/slic3r/GUI/CAD/DesignSketchTool.*` | in-canvas sketching |
|
||||
| `src/slic3r/GUI/CAD/DesignInteraction.hpp` | the Esc level contract |
|
||||
|
||||
@@ -2,584 +2,238 @@
|
||||
|
||||
## Purpose and scope
|
||||
|
||||
Precise Seam lets a helper volume decide where the seam of an object goes. The
|
||||
user attaches a mesh to an object as a Precise Seam modifier. On every layer,
|
||||
the part of the external perimeter that lies inside the modifier's slice
|
||||
determines where the seam must, may or must not be placed. The helper is a
|
||||
persistent model object rather than paint on the surface, so it keeps working
|
||||
when the design changes. A body swept along a path on the surface can guide the
|
||||
seam along any trajectory.
|
||||
Precise Seam places the seam where a helper volume intersects the external
|
||||
wall. The user attaches a mesh to an object as a Precise Seam modifier, and on
|
||||
every layer the seam placer reads the modifier's slice to decide where the seam
|
||||
of each external perimeter may, must or must not go. The same mesh keeps
|
||||
working after the model changes, so the seam does not have to be repainted
|
||||
after every design revision, and a swept helper body can guide the seam along
|
||||
any path.
|
||||
|
||||
The modifier is non-printing geometry. It takes no part in object slicing,
|
||||
region assignment, filament selection or brim adhesion, and it affects only seam
|
||||
placement during G-code export. Objects without Precise Seam volumes follow the
|
||||
regular seam placement unchanged.
|
||||
The modifier is non-printing geometry. It does not take part in slicing, region
|
||||
assignment, filament selection or brim adhesion. It affects only seam
|
||||
placement, which runs during G-code export.
|
||||
|
||||
Precise Seam does not replace the seam placer. It feeds it: a modifier inserts
|
||||
the points it needs into the perimeter and changes the enforced/blocked type of
|
||||
seam candidates, the same typing mechanism as seam painting, and the configured
|
||||
seam position then chooses among them.
|
||||
## Volume types and priority
|
||||
|
||||
## Modifier types
|
||||
|
||||
Precise Seam adds six `ModelVolumeType` values after `SUPPORT_ENFORCER`, strong
|
||||
types first and weak types after them. `is_precise_seam()`,
|
||||
Precise Seam adds six `ModelVolumeType` values after `SUPPORT_ENFORCER`. The
|
||||
strong types come first and the weak types follow. `is_precise_seam()`,
|
||||
`is_precise_seam_strong()` and `is_precise_seam_weak()` are range checks that
|
||||
depend on this order.
|
||||
|
||||
| Type | Group | Effect on an intersected perimeter |
|
||||
| Type | Group | Effect on the perimeter |
|
||||
| --- | --- | --- |
|
||||
| `PRECISE_SEAM_CENTER` | strong | seam at the midpoint, by arc length, of the intersection |
|
||||
| `PRECISE_SEAM_CENTER` | strong | seam at the arc-length midpoint of the intersection |
|
||||
| `PRECISE_SEAM_LEFT` | strong | seam at the first point of the intersection |
|
||||
| `PRECISE_SEAM_RIGHT` | strong | seam at the last point of the intersection |
|
||||
| `PRECISE_SEAM_ENFORCED` | weak | intersection marked as enforced |
|
||||
| `PRECISE_SEAM_BLOCKED` | weak | intersection marked as blocked |
|
||||
| `PRECISE_SEAM_NEUTRAL` | weak | intersection reset to neutral |
|
||||
|
||||
A strong modifier fixes a single point. The perimeter gets exactly one enforced
|
||||
seam candidate there, and every other candidate is blocked. A weak modifier
|
||||
retypes, and where needed adds, the candidates inside its intersection, like
|
||||
painting does.
|
||||
|
||||
An **intersection** is a continuous part of the external perimeter's centerline
|
||||
that lies inside the modifier's slice on that layer. It is a portion of the
|
||||
perimeter, never a chord through the object. The centerline lies half an
|
||||
extrusion width inside the model surface and depends on print settings, so a
|
||||
modifier must reach clearly past the surface to cross it unambiguously.
|
||||
|
||||
### Terms
|
||||
|
||||
- **Segment:** an intersection as the code represents it (`PerimeterSegment`).
|
||||
User-facing texts call it an intersection.
|
||||
- **Fragment:** a piece of the perimeter returned by clipping, before it is tied
|
||||
to the source contour.
|
||||
- **Interval:** the bound part of one source edge, given by the edge index and a
|
||||
parameter range on that edge.
|
||||
- **Zone:** a weak segment with its type (Enforced, Blocked or Neutral).
|
||||
- **Boundary:** an end of a zone, inserted into the perimeter polygon.
|
||||
- **Candidate:** a seam candidate of the seam placer, built from the points of
|
||||
the processed perimeter polygon (painted enforcers may add more).
|
||||
|
||||
First and last are taken along the perimeter oriented counter-clockwise as seen
|
||||
from above. On an outer wall seen from outside, Left is therefore the left end
|
||||
of the intersection. On the wall of a hole seen from inside the hole, the two
|
||||
ends are swapped. Mirroring an object does not mirror the mode: perimeters stay
|
||||
counter-clockwise, so Left remains the left end seen from outside, and the seam
|
||||
moves to the other end of the modifier instead of following the mirrored model.
|
||||
|
||||
## Priority
|
||||
A strong modifier fixes one point. A weak modifier only changes the
|
||||
enforced/blocked type of seam candidates, and the configured seam position then
|
||||
chooses among them. First and last are taken along the perimeter made
|
||||
counter-clockwise seen from above. On an outer wall seen from outside, Left is
|
||||
the left end of the intersection. On the wall of a hole seen from inside the
|
||||
hole, the two ends are swapped.
|
||||
|
||||
The order of volumes in the object is the priority order, highest first.
|
||||
`ModelObject::sort_volumes()` keeps every strong modifier before every weak one
|
||||
and preserves the user's order within each group. The object list lets the user
|
||||
drag a modifier only within its own group. A type change that crosses the group
|
||||
boundary moves the volume to the end of its new group, with the lowest priority
|
||||
there.
|
||||
drag a modifier only within its own group. A type change that crosses a group
|
||||
boundary moves the volume to the end of its new group, where it has the lowest
|
||||
priority. Strong modifiers are tried in this order, and the first one that
|
||||
yields a seam on a perimeter wins. Weak modifiers are applied from the lowest
|
||||
priority to the highest, so the highest one overwrites any overlapping zone.
|
||||
|
||||
- **Strong:** modifiers are tried in priority order on each perimeter. The first
|
||||
one that yields a usable segment decides the seam. Within that modifier the
|
||||
longest segment wins; lengths are never compared across modifiers. Once a
|
||||
strong point is placed, no later strong modifier and no weak modifier is
|
||||
processed for that perimeter.
|
||||
- **Weak:** every weak modifier applies. They are applied from the lowest
|
||||
priority to the highest, so the highest one overwrites overlapping zones. A
|
||||
Blocked modifier that fully contains a perimeter is the exception: it is
|
||||
skipped there (see [Full containment](#full-containment)).
|
||||
## Model storage and 3MF compatibility
|
||||
|
||||
A strong modifier without a usable segment, even one whose fragments were all
|
||||
discarded, passes the turn to the next one.
|
||||
|
||||
## Data flow
|
||||
|
||||
1. **Invalidation.** `Print::apply()` treats a change of Precise Seam volumes as
|
||||
a change of seam placement and invalidates G-code export; the object is not
|
||||
resliced (see [Print invalidation](#print-invalidation)).
|
||||
2. **Modifier slices.** `SeamPlacer::init()` collects each object's Precise Seam
|
||||
volumes once, slices every volume separately and caches its regions with
|
||||
their bounding boxes.
|
||||
3. **Perimeters.** Seam candidates are gathered in parallel over the layers.
|
||||
For objects with Precise Seam volumes, each external perimeter polygon is
|
||||
normalized and prepared once for all modifiers.
|
||||
4. **Extraction.** For each modifier, the perimeter is clipped against the
|
||||
modifier's regions on that layer. The clipped fragments are bound back to the
|
||||
source edges of the perimeter and assembled into segments.
|
||||
5. **Strong, then weak.** Strong modifiers try to insert one seam point into the
|
||||
perimeter polygon. If none succeeds, weak modifiers insert their zone
|
||||
boundaries and subdivide enforced edges.
|
||||
6. **Candidates.** The seam placer builds candidates from the modified polygon.
|
||||
Painting assigns types first, weak zones overwrite them, and a strong point
|
||||
makes its candidate the only enforced one.
|
||||
7. **Selection and restoration.** The configured seam position chooses the
|
||||
seams and aligns them. Afterwards the exact strong points are restored.
|
||||
8. **Warnings.** After all objects are processed, `SeamPlacer::init()` prepares
|
||||
one combined warning text if any problem was found; G-code export issues it.
|
||||
|
||||
## Modifier slices
|
||||
|
||||
`init_precise_seam_data()` collects the Precise Seam volumes of each object:
|
||||
strong ones in priority order and weak ones in reverse, so that weak zones can
|
||||
be applied with last-write-wins. Each volume is sliced separately with
|
||||
`PrintObject::slice_single_volume_regions()`, at the object's layer heights and
|
||||
with the same centered transformation as the object. The slices keep every
|
||||
region's outer contour together with its holes as an `ExPolygon`. Volumes are
|
||||
not merged, so each keeps its own priority, and a modifier may have several
|
||||
regions on one layer.
|
||||
|
||||
`prepare_modifier_slices()` moves the slices into `ModifierRegionsCache`,
|
||||
pairing each region with the bounding box of its exterior. Empty layers keep
|
||||
their slots, so the cache is indexed by object layer; `Layer::id()` includes raft
|
||||
layers, which are subtracted. The cache is filled before candidates are gathered
|
||||
and is only read afterwards, shared by both modifier kinds and all worker
|
||||
threads without locking.
|
||||
|
||||
## Perimeter preparation
|
||||
|
||||
The seam placer works on external perimeter loops, including the walls of
|
||||
holes. For objects with Precise Seam volumes, consecutive duplicate points and
|
||||
the repeated closing point of each extrusion loop are removed: adjacent
|
||||
extrusion paths share endpoints, and the resulting zero-length edges would
|
||||
prevent point insertion at their junctions. Distinct visits to one point of a
|
||||
self-touching contour are kept. Objects without Precise Seam volumes keep their
|
||||
original points, so ordinary seam candidates are unaffected.
|
||||
|
||||
Each polygon is made counter-clockwise. A single `PreparedPerimeter` is then
|
||||
built for all modifiers of that perimeter. It holds a validity check (at least
|
||||
three points, no consecutive or closing duplicates), the bounding box, and the
|
||||
clipping line: the polygon as an open polyline with its first point repeated at
|
||||
the end. The preparation borrows the polygon and is used only while the polygon
|
||||
is unchanged: strong processing returns immediately after inserting its point,
|
||||
and weak processing collects all segments before it inserts anything. An
|
||||
invalid perimeter receives no Precise Seam processing.
|
||||
|
||||
## Segment extraction
|
||||
|
||||
`extract_perimeter_segments()` turns one modifier's regions on one layer into
|
||||
segments of the perimeter, each with its geometry and its position on the
|
||||
source contour. Both modifier kinds consume these segments; the extractor is
|
||||
told the modifier type so that it prepares only the data that type needs.
|
||||
|
||||
### Clipping
|
||||
|
||||
Regions whose bounding box does not overlap the perimeter's are skipped. The
|
||||
clipping line is intersected with each remaining region by `intersection_pl()`,
|
||||
which clips an open path against an `ExPolygon` with its holes attached, using
|
||||
the nonzero rule. Clipping an open line yields only pieces of the perimeter, so
|
||||
a modifier crossing the whole object produces two separate pieces rather than a
|
||||
chord through the body. Holes in a modifier and several regions of one modifier
|
||||
simply produce more pieces. The line is cut at vertex zero, so a piece crossing
|
||||
that vertex arrives as two fragments. A border that only touches the line can
|
||||
come back as a single point; such fragments carry no coverage and are dropped
|
||||
before binding.
|
||||
|
||||
### Binding fragments to source edges
|
||||
|
||||
Clipper returns coordinates only. Insertion needs the source edge of every
|
||||
point, and coordinates alone are ambiguous where a contour visits the same
|
||||
point twice. Each fragment is therefore bound to the source edges it covers,
|
||||
producing intervals: an edge index with a parameter range on that edge.
|
||||
|
||||
- **Exact path.** For fragments with interior points, the second point is used
|
||||
as an anchor that must equal a source vertex exactly. Clipping keeps the
|
||||
vertices of an open path unchanged, including collinear ones. The following
|
||||
points must match successive source vertices in either direction; later
|
||||
occurrences of the anchor are tried if a sequence does not match. Only the two
|
||||
end cuts are projected onto their edges.
|
||||
- **Projection path.** Two-point fragments, and fragments the exact path cannot
|
||||
match, are bound by projection. The first source edge that holds both points
|
||||
of the first pair, with distinct parameters, establishes the edge and
|
||||
direction. Every following pair must continue on the same edge or cross to the
|
||||
neighboring edge at their actual shared vertex, in the same direction. A pair
|
||||
continuing on the same edge reuses the previous pair's parameter for their
|
||||
shared point, so the two projections of one point cannot differ.
|
||||
- **Failure.** A fragment that cannot be bound continuously is rolled back and
|
||||
discarded. Earlier fragments and other fragments are unaffected. The failure
|
||||
is counted, logged and reported to the user (see
|
||||
[Diagnostics](#diagnostics-and-warnings)).
|
||||
|
||||
Two rare rounding cases are handled only after both paths have failed, so the
|
||||
normal path never pays for them:
|
||||
|
||||
- **Cut beside a vertex.** When a modifier boundary crosses within about one
|
||||
coordinate unit of a source vertex, Clipper can place the cut at the vertex's
|
||||
height but a few units beside it. The end pair then collapses to the vertex's
|
||||
parameter or misses both neighboring edges. An end cut closer than the
|
||||
snapping radius to a vertex of the fragment's own chain is snapped to that
|
||||
vertex: either its neighbor in the fragment (the cut is a rounded copy of it
|
||||
and is dropped) or a vertex that shares a source edge with that neighbor. The
|
||||
neighbor wins whenever it is within the radius. Ends that are themselves source
|
||||
vertices and ambiguous choices are left unchanged. Binding is then retried
|
||||
once with the same strict rules, so a wrong candidate can only fail again.
|
||||
- **Contact.** A fragment that still fails but is shorter than the snapping
|
||||
radius is accepted as a contact and binds nothing. Insertion would collapse it
|
||||
onto one point anyway.
|
||||
|
||||
Both outcomes are recoveries, not failures: they show no user warning but leave
|
||||
a log marker.
|
||||
|
||||
### Assembling segments
|
||||
|
||||
The intervals are sorted by edge and parameter. Intervals on the same occurrence
|
||||
of an edge are united when they overlap or meet, by parameter or at the same
|
||||
integer point; equal coordinates on different edges are never united. A
|
||||
parameter of 1 is stored as parameter 0 of the next edge, so intervals on
|
||||
adjacent edges meet exactly at their shared vertex. Consecutive intervals that
|
||||
meet form one `PerimeterSegment`, and the last segment is joined with the first
|
||||
when they meet at vertex zero, undoing the artificial cut of the clipping line.
|
||||
|
||||
Each segment keeps its polyline, the source edge of every polyline edge, and its
|
||||
begin and end positions on the source contour.
|
||||
|
||||
### Full containment
|
||||
|
||||
A modifier that covers the whole perimeter has no boundaries on it. The policy
|
||||
follows seam painting, where painting a whole perimeter green is a meaningful
|
||||
choice and forbidding the seam all round is not:
|
||||
|
||||
- **Seam Enforced** types the whole perimeter, like a perimeter painted green all
|
||||
round, with subdivision applied as described under [Weak modifiers](#weak-modifiers).
|
||||
- **Seam Neutral** types the whole perimeter Neutral, like an unmarked perimeter,
|
||||
clearing painting and lower zones.
|
||||
- **Seam Blocked** is skipped for the perimeter, with the full-containment
|
||||
warning. The seam cannot avoid the whole perimeter, so the modifier does not
|
||||
override anything below it: lower zones and painting stay in effect.
|
||||
- **Seam Center, Left and Right** are skipped with the same warning: there is no
|
||||
intersection to place the point on.
|
||||
|
||||
Enforced and Neutral take part in the usual priority order (see
|
||||
[Weak modifiers](#weak-modifiers)).
|
||||
|
||||
The perimeter is fully contained when the united intervals cover every source
|
||||
edge from parameter 0 to 1. A modifier boundary that merely touches the
|
||||
perimeter counts as well:
|
||||
|
||||
- At a vertex or on an axis-aligned edge, clipping splits the line exactly at the
|
||||
touch, the pieces meet at one point, and the coverage is complete.
|
||||
- On an inclined edge the touching point is usually not representable on the
|
||||
integer grid. The boundary pokes a few units across and leaves a real gap, so
|
||||
a single segment covers everything except that gap.
|
||||
|
||||
Weak insertion would collapse such a segment's boundaries onto one vertex and
|
||||
turn the intended zone into a single candidate, and strong would put the seam at
|
||||
the touch. A single segment is therefore also full containment in the cases
|
||||
where insertion collapses it, exactly up to edges shorter than 2 µm:
|
||||
|
||||
- the uncovered length from its end to its begin is below 1 µm, or
|
||||
- the gap spans one vertex, or starts at a vertex and ends on the next edge, and
|
||||
both ends lie within 1 µm of the vertex that ends the first gap edge, since
|
||||
each end then snaps onto it from its own edge.
|
||||
|
||||
A cheap filter runs first: both cases bring the segment's ends within 2 µm of
|
||||
each other.
|
||||
|
||||
## Strong modifiers
|
||||
|
||||
For a strong modifier, the extractor prepares each segment's target point
|
||||
before anything is inserted, together with the source edge it lies on:
|
||||
|
||||
- **Left:** the segment's first point.
|
||||
- **Right:** the segment's last point.
|
||||
- **Center:** the point at half the segment's arc length.
|
||||
|
||||
Arc length is the sum of Euclidean edge lengths, not the chord or a vertex count.
|
||||
|
||||
`insert_strong_seam_point()` selects the longest segment of the first modifier
|
||||
that has one. Exactly equal lengths are resolved by the prepared target points:
|
||||
greater bed Y first, then smaller X; a complete tie keeps the first segment.
|
||||
Slice coordinates already include instance rotation and have the bed axes;
|
||||
centering and XY translation do not change this order. Nearly equal lengths are
|
||||
not treated as equal, so exact ties occur mainly on axis-aligned geometry.
|
||||
Geometrically equal segments, such as a symmetric modifier crossing both faces
|
||||
of a thin wall, differ only by rounding noise that varies between layers, so
|
||||
the chosen face may alternate. This is accepted deliberately: such a modifier is
|
||||
ambiguous by itself: more than one segment raises the "multiple intersections"
|
||||
warning. The user should make the modifier cross the perimeter once.
|
||||
|
||||
The selected point is inserted on its source edge. A point within 1 µm of an
|
||||
existing vertex is snapped to that vertex. Helper points are added 1 µm on both
|
||||
sides of it, except on an adjacent edge shorter than 2 µm, which already bounds
|
||||
the distance.
|
||||
|
||||
When the candidates are built, the candidate at the inserted point is the only
|
||||
enforced one and becomes the central enforcer; every other candidate is blocked.
|
||||
Every seam position mode therefore selects it. Alignment and random placement
|
||||
can still move the final position, so after alignment
|
||||
`restore_precise_seam_positions()` writes the exact point and its index back
|
||||
into every perimeter that has a strong seam.
|
||||
|
||||
## Weak modifiers
|
||||
|
||||
`collect_weak_modifier_segments()` extracts the segments of every weak modifier
|
||||
before the polygon is modified, so all positions refer to the same contour. Each
|
||||
segment becomes a zone with a type and two boundaries, kept in application
|
||||
order, lowest priority first. Full containment of an Enforced or Neutral
|
||||
modifier becomes a whole-perimeter zone at its place in that order: it has no
|
||||
boundaries and takes part in no insertion or helper step below. The boundaries
|
||||
carry their positions on the source contour; these remain as provenance after
|
||||
insertion and are not indices into the modified polygon.
|
||||
|
||||
`prepare_weak_modifier_segments()` then changes the polygon:
|
||||
|
||||
1. **Boundary insertion.** Insertion events are sorted by decreasing source edge
|
||||
and parameter, and the polygon is modified from its end towards its start. A
|
||||
pending boundary's source index therefore stays valid. Vertex zero has the
|
||||
canonical position `(0, 0)` and is
|
||||
processed last, and a point on the closing edge is appended rather than
|
||||
inserted at index zero. A boundary within 1 µm of either endpoint of its
|
||||
current edge, an original vertex or a boundary inserted earlier, is snapped to
|
||||
that point, so coincident boundaries share a vertex. A zone narrower than
|
||||
1 µm collapses into a single vertex.
|
||||
2. **Helper points.** A helper point is added 1 µm outside every boundary,
|
||||
unless the edge there is shorter than 2 µm, which already bounds it. The
|
||||
helpers keep the edges at a boundary short, so a seam placed along such an
|
||||
edge stays close to the boundary. Coincident boundaries share their helpers.
|
||||
3. **Enforced subdivision.** Zone types are resolved for the polygon's edges in
|
||||
priority order. The edges of a zone are those from its left boundary up to,
|
||||
but not including, its right boundary; a whole-perimeter zone types every
|
||||
edge. Enforced edges longer than `SeamPlacer::enforcer_oversampling_distance`
|
||||
(0.2 mm) are subdivided into steps of at most that length; shorter edges and
|
||||
existing vertices are kept.
|
||||
The regular seam placer then chooses the seam as for painted seams.
|
||||
|
||||
When candidates are built, painting assigns their types first.
|
||||
`apply_weak_modifiers_to_perimeter()` then overwrites the types of the
|
||||
candidates between the boundaries of each zone, both boundaries included,
|
||||
lowest priority first; a whole-perimeter zone types every candidate. Blocked
|
||||
and Enforced zones therefore take precedence over painting, and Neutral clears
|
||||
painting inside its zone.
|
||||
|
||||
## Numeric tolerances
|
||||
|
||||
Coordinates are integers in scaled units: 1 nm by default, and 10 nm when a bed
|
||||
larger than 2147 mm switches `SCALING_FACTOR`. Both Precise Seam tolerances are
|
||||
deliberately defined in units rather than physical distances. Clipper truncates
|
||||
cuts to whole units at any scale, so the on-edge tolerance must follow the unit; the
|
||||
snapping radius scales with it to keep its margin over single-precision
|
||||
candidate coordinates, which are coarser on large beds. Distances quoted in
|
||||
this document in nanometers and
|
||||
micrometers assume the default unit; on large printers they are ten times
|
||||
larger. The enforced subdivision step is a physical distance and stays 0.2 mm.
|
||||
|
||||
| Value | Role |
|
||||
| --- | --- |
|
||||
| `MACHINE_PRECISION_SQUARED` (2.5 units², about 1.6 nm) | A point lies on an edge if it is this close. It absorbs Clipper's truncation of cuts to whole units (under √2 units from the edge) and never bridges a real gap: a one-unit uncovered gap stays a gap. |
|
||||
| `TOLERANCE_LINEAR` (1000 units, 1 µm) | Insertion snaps points this close to an existing vertex, and helper points are placed this far from boundaries. The same radius bounds the rounding fallback, contacts and the sub-micron full-containment rule, so those decisions match what insertion would produce anyway. |
|
||||
| `enforcer_oversampling_distance` (0.2 mm) | Maximum step of enforced subdivision. |
|
||||
|
||||
Raising the on-edge tolerance would not help with cuts beside a vertex: more
|
||||
points past a vertex would be clamped to its parameter and collapse. Lowering it
|
||||
would reject ordinary rounded cuts. The snapping radius is kept far above
|
||||
clipping precision for robustness: seam candidates hold single-precision
|
||||
coordinates, whose step is about 8 to 15 nm at typical object coordinates
|
||||
(about 0.25 µm 3 m from the object's centre, on large beds only), and
|
||||
weak boundaries and the strong point are located among the candidates by those
|
||||
coordinates, so distinct points must stay clearly distinct. 1 µm is also far
|
||||
below printing precision.
|
||||
|
||||
## Diagnostics and warnings
|
||||
|
||||
One `PreciseSeamWarnings` instance is shared by all objects and layers of a
|
||||
`SeamPlacer::init()` call. After all objects are processed, `SeamPlacer::init()`
|
||||
prepares at most one warning text, available through `precise_seam_warning()`.
|
||||
G-code export issues it as one non-critical warning with the ID
|
||||
`SlicingPreciseSeamWarning`. It is a single line, "Precise Seam: <causes>. Seam
|
||||
placement may differ from expected.", because the export warnings dialog shows
|
||||
only the first line of each warning. Repeated warning events replace the
|
||||
notification instead of appending to it. Except for the "had no effect" cause,
|
||||
the causes name the modifier types involved, as the menu names them, in menu
|
||||
order and each type once, for example "(Seam Left, Seam Enforced)".
|
||||
The causes are:
|
||||
|
||||
- **failed to process some intersections (types):** at least one fragment was
|
||||
discarded by binding. Other segments remain usable.
|
||||
- **multiple intersections with a perimeter, only one was used (types):**
|
||||
a Seam Center, Left or Right modifier had more than one segment on a
|
||||
perimeter (see [Strong modifiers](#strong-modifiers)).
|
||||
- **a perimeter is fully inside a modifier, the modifier was not applied to it
|
||||
(types):** a Seam Center, Left, Right or Blocked modifier was skipped for a
|
||||
perimeter (see [Full containment](#full-containment)).
|
||||
- **modifier "<name>" of "<object>" had no effect on the seam (it might not reach
|
||||
the centerline of the printed perimeter):** a modifier was evaluated on at
|
||||
least one perimeter and never gave a segment, full containment or a discarded
|
||||
fragment. Only the first such modifier in print and volume order is named,
|
||||
followed by "(N in total)" when there are several.
|
||||
|
||||
Only the effect is certain, so the cause is given as a hint. A modifier is
|
||||
evaluated only when its turn comes: on a perimeter where a higher strong
|
||||
modifier placed the seam, lower strong and all weak modifiers are not
|
||||
evaluated. A modifier that was never evaluated is not reported, since nothing
|
||||
is known about it. A point contact gives no segment and does not count as
|
||||
reaching the perimeter.
|
||||
|
||||
The log records the following diagnostic markers:
|
||||
|
||||
- `[PreciseSeamIntersectionFailed]` for a discarded fragment, with object,
|
||||
modifier, layer, height, fragment and failing pair, the failure reason and
|
||||
point counts.
|
||||
- `[PreciseSeamFragmentRecovered]` for a recovery, with `outcome=bound` or
|
||||
`outcome=contact`, the same location fields and the original failure reason.
|
||||
- `[PreciseSeamNoEffect]` for every modifier of the "had no effect" cause, with
|
||||
the object and modifier names. Unlike the user warning, the log lists all of
|
||||
them.
|
||||
|
||||
Failures and recoveries are counted separately. The first 10 of each per
|
||||
`init()` call are logged in detail, in parallel processing order; if a limit is
|
||||
exceeded, one summary marker reports the total and the number omitted.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- **The modifier must reach the perimeter centerline.** Contacts are taken as
|
||||
clipping returns them, without offsets or tangency rules, so boundaries that
|
||||
only graze the centerline are the user's responsibility. Several near-touches
|
||||
on inclined edges can leave several segments separated by gaps of a few units;
|
||||
their zones then cover nearly the whole perimeter instead of being treated as
|
||||
full containment.
|
||||
- **Self-touching perimeters.** Extraction keeps distinct visits of one
|
||||
coordinate apart through its source-edge bindings, but the consumers locate
|
||||
inserted points by coordinates. A weak zone is typed and subdivided from the
|
||||
first vertex with its boundary coordinate, while boundary helpers are added at
|
||||
every such vertex. A strong point marks every candidate at its coordinate as
|
||||
enforced, and the last one is restored after alignment. If a boundary or a
|
||||
strong point falls exactly on a repeated coordinate, a zone may therefore start
|
||||
from another visit, or the seam may start at another visit of the same point.
|
||||
Carrying visit identity through insertion, refinement, candidates and
|
||||
restoration would touch the whole pipeline, so it is not done for this rare
|
||||
geometry. Overlapping source visits are likewise outside the binding contract.
|
||||
|
||||
## Integration with the application
|
||||
|
||||
### Other seam settings
|
||||
|
||||
- Precise Seam takes part only in outer and hole perimeter seam placement. In
|
||||
spiral vase mode the seam placer is not used for perimeters, so the modifiers
|
||||
have no effect.
|
||||
- Scarf seams, the seam gap and wiping start from the chosen point exactly as
|
||||
they would from an ordinary seam.
|
||||
- Seam painting acts only from model parts, the volumes the seam gizmo shows and
|
||||
edits, and from negative volumes. Painting retained on a volume after a change
|
||||
from part to a Precise Seam, ordinary or support modifier is ignored. A type
|
||||
change back to a model part reactivates any retained painting.
|
||||
Negative volumes keep it on purpose: painting a
|
||||
part and turning it into a negative volume is the only way to paint the wall
|
||||
of the hole it cuts. That painting still affects the seam but is invisible in
|
||||
the gizmo and cannot be edited there; this is known technical debt.
|
||||
If painting them is ever made editable, G-code invalidation must track it too:
|
||||
`model_custom_seam_data_changed()` checks model parts only.
|
||||
|
||||
### Model storage and 3MF compatibility
|
||||
|
||||
Projects must stay readable by earlier releases, and a Precise Seam volume must
|
||||
not change a print there. Both 3MF writers therefore store it as an ordinary
|
||||
parameter modifier: `modifier_part` in the Bambu-format part subtype, and
|
||||
`ParameterModifier` together with the legacy `modifier` flag in the
|
||||
Prusa-format volume metadata. The seam mode is written separately under
|
||||
Projects must stay readable by earlier releases, and the modifier must not
|
||||
change a print there. Both 3MF writers therefore store a Precise Seam volume as
|
||||
an ordinary parameter modifier: `modifier_part` in the Bambu-format part
|
||||
subtype, and `ParameterModifier` together with the legacy `modifier` flag in
|
||||
the Prusa-format volume metadata. The seam mode is written separately under
|
||||
`precise_seam_type`, using the names from `ModelVolume::type_to_string()`
|
||||
(`precise_seam_center` and so on).
|
||||
|
||||
On load, the mode is applied after all other volume metadata, regardless of XML
|
||||
key order, and only when the base type is a modifier. A missing or unknown mode
|
||||
leaves an ordinary modifier, and seam metadata on any other base type is
|
||||
ignored. Files that stored the seam mode directly as the volume type still load.
|
||||
A project saved again by an earlier release loses the seam mode for good: the
|
||||
volumes stay ordinary modifiers without settings.
|
||||
On load, the mode applies after all other volume metadata, regardless of XML
|
||||
key order, and only when the base type is a modifier. Missing or unknown modes
|
||||
leave an ordinary modifier. Seam metadata on any other base type is ignored.
|
||||
Files that stored the seam mode directly as the volume type still load.
|
||||
|
||||
A Precise Seam volume keeps any per-volume settings it had as a part or
|
||||
modifier, but they are inactive and the object list shows no settings item for
|
||||
it. The writers prefix these keys with `precise_seam_config:`, so an earlier
|
||||
reader drops them as unknown options and loads a modifier without settings,
|
||||
which has no effect on the print. The current reader restores the keys only when
|
||||
the volume ends up as a Precise Seam type, so the settings return when the user
|
||||
changes the type back.
|
||||
reader drops them as unknown options. The volume therefore loads there as a
|
||||
modifier without settings and has no effect on the print. The current reader
|
||||
restores the keys only when the volume ends up as a Precise Seam type, so the
|
||||
settings return when the user changes the type back. Configuration values are
|
||||
XML-escaped in both writers, for every volume type.
|
||||
|
||||
### Print invalidation
|
||||
## Print invalidation
|
||||
|
||||
`Print::apply()` compares the Precise Seam volumes of each object by type, ID
|
||||
and transformation. Adding, removing, moving, reordering or retyping one cancels
|
||||
background processing and invalidates only `psGCodeExport`; the sliced layers
|
||||
are kept. `model_volume_list_update_supports_and_seams()` then brings the
|
||||
support and Precise Seam volumes of the print's model copy in line with the new
|
||||
model in one pass. A volume may switch between these two families, since neither
|
||||
affects object slicing; such a switch also changes the support volumes, so the
|
||||
support step is invalidated as well.
|
||||
and transformation. Adding, removing, moving, reordering or retyping one
|
||||
cancels background processing and invalidates only `psGCodeExport`; the sliced
|
||||
layers are kept. `model_volume_list_update_supports_and_seams()` then brings
|
||||
the support and Precise Seam volumes of the print's model copy in line with the
|
||||
new model in one pass. A volume may switch between the two families, since
|
||||
neither affects slicing. A conversion to or from a part or ordinary modifier
|
||||
changes the solid and modifier volume lists and reslices as before.
|
||||
|
||||
A conversion to or from a part or an ordinary modifier changes the solid and
|
||||
modifier volume lists and reslices the object as before. The volume keeps its
|
||||
ID across the type change, so the region cache treats a former support or
|
||||
Precise Seam volume that became a part or modifier as new, since it was never
|
||||
cached.
|
||||
## Modifier slices
|
||||
|
||||
Removing the last helper of a single-part object reslices it, as removing any
|
||||
last modifier would.
|
||||
`SeamPlacer::init()` collects the Precise Seam volumes of each object once:
|
||||
strong ones in priority order and weak ones reversed. It slices each volume
|
||||
separately with `PrintObject::slice_single_volume()`, which shares
|
||||
`slice_modifier_volumes()` with support blockers and enforcers but does not
|
||||
merge volumes, so each keeps its own priority. The result is cached per volume
|
||||
and indexed by object layer; `Layer::id()` includes raft layers, which are
|
||||
subtracted. Seam candidates are then gathered in parallel over the layers and
|
||||
read the cache without locking.
|
||||
|
||||
### User interface
|
||||
Objects without Precise Seam volumes follow the unchanged seam placement path.
|
||||
For objects that have them, perimeter extraction also removes consecutive
|
||||
duplicate points and the repeated closing point of each extrusion loop.
|
||||
Zero-length edges at path junctions would otherwise prevent point insertion
|
||||
there. Distinct visits to one point of a self-touching contour are kept.
|
||||
|
||||
## Finding the wall segment
|
||||
|
||||
The seam placer works on the external perimeter loops of each layer, both
|
||||
outer contours and holes, each made counter-clockwise. For every modifier
|
||||
polygon on the layer that overlaps the perimeter's bounding box, the region
|
||||
enclosed by the perimeter is clipped against the modifier polygon. The boundary
|
||||
of each intersection polygon alternates between runs that follow the perimeter
|
||||
and runs that follow the modifier outline. The wall segment is the longest
|
||||
continuous run of intersection vertices that lie on the perimeter, measured in
|
||||
vertices.
|
||||
|
||||
The fast path first finds an intersection vertex that exactly matches a
|
||||
perimeter vertex. It then walks forward and backward, expecting the adjacent
|
||||
perimeter vertex and falling back to projection when Clipper has merged or
|
||||
split collinear edges. A vertex counts as on the perimeter when its projection
|
||||
is within about 1.6 nm, which covers Clipper's rounding. If no vertex matches
|
||||
exactly, or every vertex lies on the perimeter, the general path projects all
|
||||
vertices. When every vertex is on the perimeter, the edge midpoints are checked
|
||||
instead: a modifier chord can join two perimeter vertices directly, and the
|
||||
chords split the vertex ring into runs. If no edge leaves the perimeter, the
|
||||
perimeter lies entirely inside the modifier.
|
||||
|
||||
`Polygon::point_projection()` optionally reports the edge that holds the
|
||||
projection, and every point of the segment keeps the index of its perimeter
|
||||
edge. New points are inserted on that edge. A point within 1 µm of an existing
|
||||
vertex snaps to that vertex instead.
|
||||
|
||||
## Strong modifiers
|
||||
|
||||
For a strong modifier, the target is the first point, the last point or the
|
||||
arc-length midpoint of the segment. The midpoint is projected back onto the
|
||||
original perimeter, because Clipper may have merged several perimeter edges
|
||||
into one segment edge. The target is inserted into the perimeter, and a helper
|
||||
point is inserted 1 µm before and after it. Strong modifiers are tried in
|
||||
priority order, the first valid intersection decides the seam, and weak
|
||||
modifiers are not processed for that perimeter.
|
||||
|
||||
When candidates are built, the inserted point is the only enforced candidate
|
||||
and becomes the central enforcer; every other candidate is blocked. The seam
|
||||
position modes then pick that point: Aligned and Aligned Back prefer the central
|
||||
enforcer, while Back, Random and Nearest rank enforced candidates above blocked
|
||||
ones. Alignment and random placement can still move the final position along an
|
||||
edge. After alignment, `restore_precise_seam_positions()` writes the exact point
|
||||
and its index back into every perimeter that has a strong seam. Inner walls take
|
||||
their seam from the external seam as usual, including staggering.
|
||||
|
||||
## Weak modifiers
|
||||
|
||||
Weak modifiers produce one segment per intersection polygon, so one modifier can
|
||||
mark several zones on one perimeter. All segment boundaries are inserted into
|
||||
the perimeter in order of decreasing arc length. Each insertion then leaves the
|
||||
indices of the pending, shorter ones unchanged; a point on the closing edge is
|
||||
appended rather than inserted at index zero. A helper point is added 1 µm
|
||||
outside each boundary. Random placement picks a position along the edge that
|
||||
follows a candidate. These helpers keep that edge 1 µm long at each boundary, so
|
||||
a zone cannot extend or intrude further than that. Boundaries that coincide
|
||||
share their helper points.
|
||||
|
||||
The zone types are then resolved in priority order, and the edges of enforced
|
||||
zones are subdivided into steps of at most
|
||||
`SeamPlacer::enforcer_oversampling_distance` (0.2 mm). The middle candidate of
|
||||
the longest enforced patch is therefore close to the geometric middle of the
|
||||
zone. That patch is measured in candidates, across the closing edge, regardless
|
||||
of where the contour starts; the same rule applies to painted seams.
|
||||
|
||||
Candidates first receive their type from seam painting. The weak zones then
|
||||
overwrite it, lowest priority first. Blocked and Enforced zones therefore take
|
||||
precedence over painting, and Neutral clears painting inside its zone.
|
||||
|
||||
## Unsupported geometry and warnings
|
||||
|
||||
Some modifier shapes cannot be resolved to one seam or one zone per crossing.
|
||||
They are detected cheaply and reported rather than guessed:
|
||||
|
||||
- A strong modifier that crosses a perimeter in more than one place uses only
|
||||
its first valid segment. The other crossings are ignored.
|
||||
- A modifier that crosses the whole region enclosed by the perimeter is
|
||||
detected when the modifier outline minus that region leaves more than one
|
||||
piece, none of them a hole. Its intersection holds two wall runs, and only
|
||||
one of them is used.
|
||||
- A modifier whose slice has a hole on a layer, found as a clockwise polygon in
|
||||
the flattened slice, is skipped on that layer. The flattened slice no longer
|
||||
records which hole belongs to which contour.
|
||||
- A perimeter that lies entirely inside a modifier is ignored by that modifier.
|
||||
|
||||
The conditions are atomic flags shared by all layers and objects. After all
|
||||
objects are processed, `SeamPlacer::init()` issues at most one non-critical
|
||||
warning with the ID `SlicingPreciseSeamWarning`. The warning is a single line
|
||||
that lists every cause found, because the export warnings dialog shows only the
|
||||
first line of each warning. Repeated warning events replace this notification
|
||||
instead of appending text to it.
|
||||
|
||||
## User interface
|
||||
|
||||
- *Add Precise Seam* in the object menu creates a Center modifier from a
|
||||
primitive or a loaded mesh. Text and SVG volumes cannot become Precise Seam
|
||||
modifiers: the menu does not offer it, and `ObjectList::set_volume_type()`
|
||||
modifiers: the menu does not offer them, and `ObjectList::set_volume_type()`
|
||||
refuses the change.
|
||||
- *Change Type* has a single *Precise Seam* entry. It converts other volumes to
|
||||
Center and keeps the mode of volumes that are already Precise Seam. The
|
||||
*Precise Seam Type* submenu appears only when every selected item is a Precise
|
||||
Seam volume, including settings rows that resolve to one, and sets the chosen
|
||||
mode on all of them.
|
||||
*Precise Seam Type* submenu appears only when every selected item is a
|
||||
Precise Seam volume, including settings rows that resolve to one. It sets the
|
||||
chosen mode on all selected volumes.
|
||||
- Each mode has its own icon in the object list and its own color in the 3D
|
||||
view, at 60% opacity: warm orange, gold and dark orange for Center, Left and
|
||||
Right; green, red and gray for Enforced, Blocked and Neutral. The three strong
|
||||
colors are close shades of one orange because all three mark strong
|
||||
modifiers; the object list icons tell the modes apart.
|
||||
- Precise Seam volumes have no filament and cannot be pasted into SLA objects.
|
||||
Python plugins see them as `ModelVolumeType` values and through the
|
||||
`is_precise_seam*()` methods.
|
||||
view, at 60% opacity: warm oranges for the strong modes, and green, red and
|
||||
gray for Enforced, Blocked and Neutral.
|
||||
- Object list drops map visible rows to volume indices while skipping hidden
|
||||
cut connectors, and they refresh the row-to-volume map of the object.
|
||||
- Precise Seam volumes have no filament, block pasting into SLA, and are exposed
|
||||
to Python plugins as `ModelVolumeType` values plus the `is_precise_seam*()`
|
||||
methods.
|
||||
|
||||
## Implementation and verification
|
||||
|
||||
- [PreciseSeam.cpp](../../src/libslic3r/GCode/PreciseSeam.cpp) implements the
|
||||
modifier cache, perimeter preparation, segment extraction and binding, strong
|
||||
selection and insertion, weak-zone preparation and application, and position
|
||||
restoration. [PreciseSeam.hpp](../../src/libslic3r/GCode/PreciseSeam.hpp)
|
||||
declares the contracts; [PreciseSeamInternal.hpp](../../src/libslic3r/GCode/PreciseSeamInternal.hpp)
|
||||
exposes the binding internals to tests.
|
||||
- [SeamPlacer.cpp](../../src/libslic3r/GCode/SeamPlacer.cpp) fills the cache,
|
||||
normalizes perimeters, calls both consumers while gathering candidates,
|
||||
restores strong positions after alignment and prepares the warning text, which
|
||||
[GCode.cpp](../../src/libslic3r/GCode.cpp) issues during G-code export.
|
||||
- [PreciseSeam.cpp](../../src/libslic3r/GCode/PreciseSeam.cpp) implements segment
|
||||
detection, point insertion, weak-zone resolution and position restoration.
|
||||
[SeamPlacer.cpp](../../src/libslic3r/GCode/SeamPlacer.cpp) integrates it into
|
||||
candidate gathering and issues the warning.
|
||||
- [Model.hpp](../../src/libslic3r/Model.hpp) defines the types and their order,
|
||||
[PrintApply.cpp](../../src/libslic3r/PrintApply.cpp) handles invalidation, and
|
||||
[PrintObjectSlice.cpp](../../src/libslic3r/PrintObjectSlice.cpp) slices single
|
||||
volumes into structured regions. [bbs_3mf.cpp](../../src/libslic3r/Format/bbs_3mf.cpp)
|
||||
and [3mf.cpp](../../src/libslic3r/Format/3mf.cpp) store them.
|
||||
[PrintObjectSlice.cpp](../../src/libslic3r/PrintObjectSlice.cpp) slices the
|
||||
modifiers. [bbs_3mf.cpp](../../src/libslic3r/Format/bbs_3mf.cpp) and
|
||||
[3mf.cpp](../../src/libslic3r/Format/3mf.cpp) store them.
|
||||
- [GUI_Factories.cpp](../../src/slic3r/GUI/GUI_Factories.cpp) and
|
||||
[GUI_ObjectList.cpp](../../src/slic3r/GUI/GUI_ObjectList.cpp) provide the menus,
|
||||
type changes and ordering; [3DScene.cpp](../../src/slic3r/GUI/3DScene.cpp)
|
||||
defines the colors.
|
||||
- [Segment extraction tests](../../tests/libslic3r/test_precise_seam.cpp) cover
|
||||
clipping and binding: holes and components, contour origin and reversal,
|
||||
repeated coordinates, collinear vertices and rounding, rollback and the
|
||||
diagnostic limits, the rounding fallback on synthetic and real Clipper
|
||||
fragments, contacts, and full containment including touches and sub-micron
|
||||
gaps on inclined edges and around vertices.
|
||||
type changes and ordering.
|
||||
- [Precise Seam tests](../../tests/fff_print/test_precise_seam.cpp) cover the
|
||||
consumers: strong targets in every mode, including a midpoint on an existing
|
||||
vertex or the closing edge, longest-arc selection and tie order in bed axes,
|
||||
priorities, weak boundaries that coincide or share an edge, enforced
|
||||
subdivision, whole-perimeter weak zones with painting and priorities, weak
|
||||
zones over painting's oversampled candidates, the warning type masks, usage
|
||||
tracking for the "had no effect" warning, volume sorting of strong and weak
|
||||
groups, restoration of strong points after alignment, raft layer indexing and
|
||||
structured slices. End-to-end tests slice a real object with Precise Seam
|
||||
volumes and check the outer wall starts in the exported G-code: every strong
|
||||
mode under several seam positions and with a raft, Enforced and Blocked zones,
|
||||
a modifier with a hole, and the user warning.
|
||||
strong positions, including a midpoint on an existing vertex or the closing
|
||||
edge. They also cover shared and coincident weak boundaries, every warning,
|
||||
and the priority order.
|
||||
- [Seam placer tests](../../tests/fff_print/test_seam_placer.cpp) cover
|
||||
enforced-patch selection independent of the contour start, fully painted
|
||||
contours, duplicate removal, and `Print::apply()` synchronization through type
|
||||
changes and restored model snapshots. The duplicate-removal test also checks
|
||||
the "had no effect" warning text prepared by `init()` for a helper that never
|
||||
reaches the loop. Further tests check that adding, moving, retyping or
|
||||
removing a Precise Seam volume invalidates only G-code export, and that seam
|
||||
painting acts only from model parts and negative volumes, including after a
|
||||
type change back to part.
|
||||
contours, duplicate removal, and `Print::apply()` synchronization through
|
||||
type changes and restored model snapshots.
|
||||
- [3MF tests](../../tests/libslic3r/test_precise_seam_3mf.cpp) cover the round
|
||||
trip of every mode and of inactive settings, attribute escaping, and the
|
||||
metadata combinations that restore a seam mode.
|
||||
trip of every mode and of inactive settings, attribute escaping, and which
|
||||
metadata combinations restore a seam mode.
|
||||
[Plugin tests](../../tests/slic3rutils/test_precise_seam_plugin.cpp) cover the
|
||||
Python bindings.
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# Prusa CORE One INDX profiles
|
||||
|
||||
The Prusa bundle provides separate four-tool and eight-tool CORE One INDX models
|
||||
with 0.4 mm high-flow nozzles and a 248 x 205 x 270 mm printable volume. These are
|
||||
independent-tool printers, not single-extruder MMU3 machines. Both inherit
|
||||
`fdm_machine_common_coreone_indx`, which inherits the ordinary CORE One HF
|
||||
printer; the concrete printer presets supply their tool-count-dependent arrays. The bed and wizard resources come from Prusa.
|
||||
|
||||
The source configuration is PrusaResearch 2.5.10 from
|
||||
[Prusa's profile repository](https://github.com/prusa3d/PrusaSlicer-settings-prusa-fff/blob/65c5c8f1e1c3836f306119c49d717759cbc368db/PrusaResearch/2.5.10.ini).
|
||||
Its printer, process and filament settings are translated to Orca option names.
|
||||
The supplied process presets cover 0.10, 0.15, 0.20 and 0.25 mm layers. Their
|
||||
shared `fdm_process_coreone_indx` base inherits the ordinary CORE One HF SPEED
|
||||
process, with explicit INDX differences and layer-specific child settings.
|
||||
Material presets are shared with the ordinary CORE One family.
|
||||
|
||||
## Tool changes and extrusion state
|
||||
|
||||
The start script initializes a persistent `tool_init` vector, counts the tools
|
||||
used by the job, homes and probes using a loaded tool, calibrates the used tools,
|
||||
and primes the initial tool at the cleaning station. The change script preserves
|
||||
Prusa's `G27`, `P0`, `T`, `G12`, `G750` and `M906` sequences. It updates
|
||||
`e_retracted` so Orca's subsequent unretraction agrees with the script's extrusion.
|
||||
Per-tool temperature commands are guarded by `is_extruder_used`.
|
||||
|
||||
The off-bed purge station is the default. With a prime tower enabled, a newly
|
||||
used tool still receives its initial station purge, while an initialized tool
|
||||
uses the source's wipe-tower preparation path. `tool_init` persists across these
|
||||
changes; treating every tool selection as first use would change the purge and
|
||||
deretraction sequence.
|
||||
|
||||
Purge volume uses the filament's minimal purge setting. Orca's optional flush
|
||||
volumetric speed is divided by filament cross-sectional area before it is used
|
||||
as a linear extrusion-speed override. Prusa's separate `filament_flush_volume`
|
||||
override is not available in these profiles. The source's `EXCLUDE_E_START` and
|
||||
`EXCLUDE_E_END` internal markers become comments rather than printer commands.
|
||||
|
||||
Pressure-advance restoration and automatic pressure-advance emission use the
|
||||
selected filament preset's settings. These profiles do not impose machine-owned
|
||||
filament overrides. Dock-fan control retains the source's material and layer
|
||||
conditions; shutdown parks the tool and turns off the used heaters and dock fan.
|
||||
|
||||
## Configuration boundaries
|
||||
|
||||
The scripts use Orca's temperature, retraction, fan and speed option names. The
|
||||
nozzle-check high-flow flag is fixed because these presets describe HF nozzles;
|
||||
the abrasive-material flag is derived from the filament's required nozzle HRC.
|
||||
An unset idle temperature uses Orca's zero sentinel. ABS's source XY shrinkage
|
||||
compensation is represented using Orca's retained-size percentage.
|
||||
|
||||
Prusa's consistent-surface cooling strategy and filament-specific infill crossing
|
||||
speed limits have no direct Orca profile equivalent. These presets use Orca's
|
||||
native layer-time cooling and material volumetric limits. They do not add slicer
|
||||
features or change existing Prusa printer profiles.
|
||||
@@ -22855,28 +22855,3 @@ msgstr ""
|
||||
#: resources/data/hints.ini: [hint:Avoid warping]
|
||||
msgid "Avoid warping\nDid you know that when printing materials that are prone to warping such as ABS, appropriately increasing the heatbed temperature can reduce the probability of warping?"
|
||||
msgstr ""
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "failed to process some intersections (%1%)"
|
||||
msgstr ""
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "multiple intersections with a perimeter, only one was used (%1%)"
|
||||
msgstr ""
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "a perimeter is fully inside a modifier, the modifier was not applied to it (%1%)"
|
||||
msgstr ""
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "modifier \"%1%\" of \"%2%\" had no effect on the seam (it might not reach the centerline of the printed perimeter)"
|
||||
msgstr ""
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "modifier \"%1%\" of \"%2%\" (%3% in total) had no effect on the seam (it might not reach the centerline of the printed perimeter)"
|
||||
msgstr ""
|
||||
|
||||
@@ -74,8 +74,11 @@ src/slic3r/GUI/Gizmos/GizmoObjectManipulation.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoText.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoText.hpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp
|
||||
@@ -174,6 +177,7 @@ src/slic3r/GUI/PresetHints.cpp
|
||||
src/slic3r/GUI/ProgressStatusBar.cpp
|
||||
src/slic3r/GUI/PlateSettingsDialog.cpp
|
||||
src/slic3r/GUI/PrivacyUpdateDialog.cpp
|
||||
src/slic3r/GUI/PublishDialog.cpp
|
||||
src/slic3r/GUI/PublishSettingsDialog.cpp
|
||||
src/slic3r/GUI/SavePresetDialog.cpp
|
||||
src/slic3r/GUI/SceneBenchmark.cpp
|
||||
@@ -192,6 +196,7 @@ src/slic3r/GUI/Tab.hpp
|
||||
src/slic3r/GUI/UnsavedChangesDialog.cpp
|
||||
src/slic3r/GUI/Auxiliary.cpp
|
||||
src/slic3r/GUI/UpdateDialogs.cpp
|
||||
src/slic3r/GUI/ObjColorDialog.cpp
|
||||
src/slic3r/GUI/SyncAmsInfoDialog.cpp
|
||||
src/slic3r/GUI/WipeTowerDialog.cpp
|
||||
src/slic3r/GUI/wxExtensions.cpp
|
||||
@@ -253,6 +258,7 @@ src/slic3r/Utils/MKS.cpp
|
||||
src/slic3r/Utils/Moonraker.cpp
|
||||
src/slic3r/Utils/OctoPrint.cpp
|
||||
src/slic3r/Utils/Repetier.cpp
|
||||
src/slic3r/Utils/ProfileDescription.hpp
|
||||
src/slic3r/GUI/SendMultiMachinePage.cpp
|
||||
src/slic3r/GUI/MultiMachinePage.cpp
|
||||
src/slic3r/GUI/MultiMachineManagerPage.cpp
|
||||
@@ -293,10 +299,7 @@ src/slic3r/GUI/AMSDryControl.cpp
|
||||
src/slic3r/GUI/AMSDryControl.hpp
|
||||
src/libslic3r/PresetBundle.cpp
|
||||
src/slic3r/GUI/CAD/DesignPanel.cpp
|
||||
src/slic3r/GUI/CAD/DesignSketchTool.cpp
|
||||
src/slic3r/GUI/CAD/SketchInlineEditor.cpp
|
||||
src/slic3r/GUI/CAD/DesignOffer.hpp
|
||||
src/slic3r/GUI/CAD/DesignTextDialog.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoPrimitive.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSketch.cpp
|
||||
src/slic3r/GUI/KeyChord.cpp
|
||||
|
||||
@@ -27362,30 +27362,17 @@ msgstr ""
|
||||
msgid "Precise Seam"
|
||||
msgstr "Точный шов"
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "failed to process some intersections (%1%)"
|
||||
msgstr "не удалось обработать некоторые пересечения (%1%)"
|
||||
msgid "multiple intersections with a perimeter detected"
|
||||
msgstr "обнаружены множественные пересечения с периметром"
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "multiple intersections with a perimeter, only one was used (%1%)"
|
||||
msgstr "несколько пересечений с периметром, использовано только одно (%1%)"
|
||||
msgid "modifier fully crosses the printable perimeter"
|
||||
msgstr "модификатор пересекает печатаемый периметр насквозь"
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "a perimeter is fully inside a modifier, the modifier was not applied to it (%1%)"
|
||||
msgstr "периметр целиком внутри модификатора, модификатор для него не применён (%1%)"
|
||||
msgid "modifier shape is not solid (has holes inside) and was ignored"
|
||||
msgstr "форма модификатора не сплошная (имеет отверстия) и была проигнорирована"
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "modifier \"%1%\" of \"%2%\" had no effect on the seam (it might not reach the centerline of the printed perimeter)"
|
||||
msgstr "модификатор «%1%» модели «%2%» не повлиял на шов (возможно, он не достигает осевой линии печатаемого периметра)"
|
||||
|
||||
#: src/libslic3r/GCode/SeamPlacer.cpp
|
||||
#, possible-boost-format
|
||||
msgid "modifier \"%1%\" of \"%2%\" (%3% in total) had no effect on the seam (it might not reach the centerline of the printed perimeter)"
|
||||
msgstr "модификатор «%1%» модели «%2%» (всего: %3%) не повлиял на шов (возможно, он не достигает осевой линии печатаемого периметра)"
|
||||
msgid "perimeter is fully contained inside modifier and was ignored"
|
||||
msgstr "периметр полностью содержится внутри модификатора и был проигнорирован"
|
||||
|
||||
msgid "Seam placement may differ from expected."
|
||||
msgstr "Размещение шва может отличаться от ожидаемого."
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17 A11 11 0 0 1 20 17"/><circle cx="4" cy="17" r="1.5" fill="#949494" stroke="none"/><circle cx="12" cy="7" r="1.5" fill="#949494" stroke="none"/><circle cx="20" cy="17" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17 A11 11 0 0 1 20 17"/><circle cx="4" cy="17" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="12" cy="7" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="20" cy="17" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 18 A13 13 0 0 1 18 5"/><path d="M5 5 5 18M5 5 18 5" stroke-dasharray="2.5 2.5" opacity="0.5"/><circle cx="5" cy="5" r="2" fill="#949494" stroke="none"/><circle cx="5" cy="18" r="1.5" fill="#949494" stroke="none"/><circle cx="18" cy="5" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 18 A13 13 0 0 1 18 5"/><path d="M5 5 5 18M5 5 18 5" stroke-dasharray="2.5 2.5" opacity="0.5"/><circle cx="5" cy="5" r="2" fill="#b6b6b6" stroke="none"/><circle cx="5" cy="18" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="18" cy="5" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 472 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="6" height="6"/><rect x="15" y="3" width="6" height="6"/><rect x="3" y="15" width="6" height="6"/><rect x="15" y="15" width="6" height="6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="6" height="6"/><rect x="15" y="3" width="6" height="6"/><rect x="3" y="15" width="6" height="6"/><rect x="15" y="15" width="6" height="6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="9" cy="12" r="6"/>
|
||||
<circle cx="15" cy="12" r="6"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 253 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 19 C 6 5, 12 5, 12 12 S 18 19, 21 5"/><circle cx="3" cy="19" r="1.5" fill="#949494" stroke="none"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/><circle cx="21" cy="5" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 19 C 6 5, 12 5, 12 12 S 18 19, 21 5"/><circle cx="3" cy="19" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="21" cy="5" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h16M4 20 16 6"/><path d="M11 20 A7 7 0 0 0 9.1 15.2"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h16M4 20 16 6"/><path d="M11 20 A7 7 0 0 0 9.1 15.2"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 254 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2.2" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2.2" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12h20" stroke-dasharray="1.5 1.5"/><path d="M5 12h5M14 12h5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12h20" stroke-dasharray="1.5 1.5"/><path d="M5 12h5M14 12h5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 260 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3.5"/><circle cx="12" cy="12" r="1.3" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3.5"/><circle cx="12" cy="12" r="1.3" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 312 B After Width: | Height: | Size: 312 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="7"/><path d="M6.3 17.7 17.7 6.3"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="7"/><path d="M6.3 17.7 17.7 6.3"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 247 B After Width: | Height: | Size: 247 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6v12M18 6v12M6 12h12M6 12l2.5-2M6 12l2.5 2M18 12l-2.5-2M18 12l-2.5 2"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6v12M18 6v12M6 12h12M6 12l2.5-2M6 12l2.5 2M18 12l-2.5-2M18 12l-2.5 2"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6h12M6 18h12M12 6v12M12 6l-2 2.5M12 6l2 2.5M12 18l-2-2.5M12 18l2-2.5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6h12M6 18h12M12 6v12M12 6l-2 2.5M12 6l2 2.5M12 18l-2-2.5M12 18l2-2.5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 9h14M5 15h14"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 9h14M5 15h14"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 213 B After Width: | Height: | Size: 213 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="4" cy="12" r="2.5"/><circle cx="15" cy="12" r="4.5"/><path d="M8 10h2M8 14h2"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="4" cy="12" r="2.5"/><circle cx="15" cy="12" r="4.5"/><path d="M8 10h2M8 14h2"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 277 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5.5" r="2"/><path d="M12 7.5V20M8.5 10h7M6 14a6 6 0 0 0 12 0"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5.5" r="2"/><path d="M12 7.5V20M8.5 10h7M6 14a6 6 0 0 0 12 0"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18M3 9v6M21 9v6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18M3 9v6M21 9v6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 219 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16M4 9v6M20 9v6"/><circle cx="12" cy="12" r="2" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16M4 9v6M20 9v6"/><circle cx="12" cy="12" r="2" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M7 20 13 4M13 20 19 4"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M7 20 13 4M13 20 19 4"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 219 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v15h15M6 13h5v5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v15h15M6 13h5v5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 217 B After Width: | Height: | Size: 217 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><path d="M12 12h8M17.5 9.5 20 12 17.5 14.5"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><path d="M12 12h8M17.5 9.5 20 12 17.5 14.5"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 324 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M8 6h8M8 18h8"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M8 6h8M8 18h8"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 272 B After Width: | Height: | Size: 272 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M6 8v8M18 8v8"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M6 8v8M18 8v8"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 272 B After Width: | Height: | Size: 272 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M8 8 4 12 8 16M16 8l4 4-4 4"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M8 8 4 12 8 16M16 8l4 4-4 4"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 286 B After Width: | Height: | Size: 286 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="14.5" r="5"/><path d="M3 9.5h18"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="14.5" r="5"/><path d="M3 9.5h18"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 240 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18M9 3h6M9 21h6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18M9 3h6M9 21h6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 219 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5v8l6 6h8"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5v8l6 6h8"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l4 4L19 6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l4 4L19 6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="7.5"/><path d="M6.7 6.7 17.3 17.3" stroke-dasharray="2.5 2.5" opacity="0.5"/><circle cx="6.7" cy="6.7" r="1.5" fill="#949494" stroke="none"/><circle cx="17.3" cy="17.3" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="7.5"/><path d="M6.7 6.7 17.3 17.3" stroke-dasharray="2.5 2.5" opacity="0.5"/><circle cx="6.7" cy="6.7" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="17.3" cy="17.3" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="4" r="1.5" fill="#949494" stroke="none"/><circle cx="5.07" cy="16" r="1.5" fill="#949494" stroke="none"/><circle cx="18.93" cy="16" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="4" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="5.07" cy="16" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="18.93" cy="16" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16" stroke-dasharray="3 3"/><circle cx="4" cy="12" r="1.5" fill="#949494" stroke="none"/><circle cx="20" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16" stroke-dasharray="3 3"/><circle cx="4" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="20" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 352 B After Width: | Height: | Size: 352 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="6" width="16" height="12" rx="1"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="6" width="16" height="12" rx="1"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 297 B |
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M6 8.5l6-3 6 3v7l-6 3-6-3z"/>
|
||||
<line x1="3" y1="14" x2="21" y2="10"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 268 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13M10 11v6M14 11v6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13M10 11v6M14 11v6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7v10M20 7v10M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7v10M20 7v10M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 247 B After Width: | Height: | Size: 247 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4H18L15 20H9Z"/><path d="M9 20V4" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M9 14a4 4 0 0 0 1.3 3"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4H18L15 20H9Z"/><path d="M9 20V4" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M9 14a4 4 0 0 0 1.3 3"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 307 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V10a6 6 0 0 1 6-6h10"/><path d="M4 20h4M20 4v4" stroke-dasharray="2.5 2.5" opacity="0.5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20V10a6 6 0 0 1 6-6h10"/><path d="M4 20h4M20 4v4" stroke-dasharray="2.5 2.5" opacity="0.5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h4L19 9l-4-4L4 16z"/><path d="M14 6l4 4"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20h4L19 9l-4-4L4 16z"/><path d="M14 6l4 4"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 242 B After Width: | Height: | Size: 242 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="12" rx="9.5" ry="5.5"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="12" rx="9.5" ry="5.5"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 292 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13 A9.5 5.5 0 0 1 21 10"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/><circle cx="3" cy="13" r="1.5" fill="#949494" stroke="none"/><circle cx="21" cy="10" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13 A9.5 5.5 0 0 1 21 10"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="3" cy="13" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="21" cy="10" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 409 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h11"/><path d="M14 12h7m-3-3l3 3-3 3"/><path d="M14 12h7" stroke-dasharray="2.5 2.5" opacity="0.5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h11"/><path d="M14 12h7m-3-3l3 3-3 3"/><path d="M14 12h7" stroke-dasharray="2.5 2.5" opacity="0.5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="11" width="16" height="9" rx="1"/><path d="M12 8V2M9 5l3-3 3 3"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="11" width="16" height="9" rx="1"/><path d="M12 8V2M9 5l3-3 3 3"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12C5 6 19 6 22 12 19 18 5 18 2 12Z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12C5 6 19 6 22 12 19 18 5 18 2 12Z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M2 8.5C5 14.5 19 14.5 22 8.5"/><path d="M12 13v3M5.97 11.9l-1.4 2.5M18.03 11.9l1.4 2.5M3.2 10.1l-1.8 1.8M20.8 10.1l1.8 1.8"/></svg>
|
||||
|
Before Width: | Height: | Size: 320 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5v8a6 6 0 0 0 6 6h8"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5v8a6 6 0 0 0 6 6h8"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 220 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="12" cy="12" r="4"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="12" cy="12" r="4"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19 19 5"/><circle cx="5" cy="19" r="1.5" fill="#949494" stroke="none"/><circle cx="19" cy="5" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19 19 5"/><circle cx="5" cy="19" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="19" cy="5" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 330 B After Width: | Height: | Size: 330 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="15.5" width="8.5" height="4.5" rx="0.5"/><ellipse cx="16.5" cy="6" rx="4" ry="1.7"/><path d="M3.2 15.5 12.6 4.8M11.4 20 20.4 7.2"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="15.5" width="8.5" height="4.5" rx="0.5"/><ellipse cx="16.5" cy="6" rx="4" ry="1.7"/><path d="M3.2 15.5 12.6 4.8M11.4 20 20.4 7.2"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M8 7 4 12 8 17Z"/><path d="M16 7l4 5-4 5Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18" stroke-dasharray="2.5 2.5" opacity="0.5"/><path d="M8 7 4 12 8 17Z"/><path d="M16 7l4 5-4 5Z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="6" height="6" rx="1"/><path d="M12 8V2M9.6 4.4 12 2 14.4 4.4M12 16v6M9.6 19.6 12 22 14.4 19.6M8 12H2M4.4 9.6 2 12 4.4 14.4M16 12h6M19.6 9.6 22 12 19.6 14.4"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="6" height="6" rx="1"/><path d="M12 8V2M9.6 4.4 12 2 14.4 4.4M12 16v6M9.6 19.6 12 22 14.4 19.6M8 12H2M4.4 9.6 2 12 4.4 14.4M16 12h6M19.6 9.6 22 12 19.6 14.4"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M6 13l6 6 6-6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M6 13l6 6 6-6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 219 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M6 11l6-6 6 6"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M6 11l6-6 6 6"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 219 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 20V10A7 7 0 0 1 10 3H20"/><path d="M7 20V10A3 3 0 0 1 10 7H20"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 20V10A7 7 0 0 1 10 3H20"/><path d="M7 20V10A3 3 0 0 1 10 7H20"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="9" width="6" height="6" rx="1"/><rect x="10.5" y="9" width="6" height="6" rx="1"/><rect x="18" y="9" width="3.6" height="6" rx="1" stroke-dasharray="2.5 2.5" opacity="0.5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="9" width="6" height="6" rx="1"/><rect x="10.5" y="9" width="6" height="6" rx="1"/><rect x="18" y="9" width="3.6" height="6" rx="1" stroke-dasharray="2.5 2.5" opacity="0.5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 374 B After Width: | Height: | Size: 374 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8 13 8 21 15 11 15Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8 13 8 21 15 11 15Z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 220 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v3.4M12 16.6v3.4M4 12h3.4M16.6 12h3.4"/><circle cx="12" cy="12" r="2.2" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v3.4M12 16.6v3.4M4 12h3.4M16.6 12h3.4"/><circle cx="12" cy="12" r="2.2" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 302 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8" stroke-dasharray="2.5 2.5" opacity="0.5"/><circle cx="12" cy="12" r="1.4" fill="#949494" stroke="none"/><circle cx="12" cy="4" r="1.8" fill="#949494" stroke="none"/><circle cx="18.9" cy="8" r="1.8" fill="#949494" stroke="none"/><circle cx="18.9" cy="16" r="1.8" fill="#949494" stroke="none"/><circle cx="12" cy="20" r="1.8" fill="#949494" stroke="none"/><circle cx="5.1" cy="16" r="1.8" fill="#949494" stroke="none"/><circle cx="5.1" cy="8" r="1.8" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8" stroke-dasharray="2.5 2.5" opacity="0.5"/><circle cx="12" cy="12" r="1.4" fill="#b6b6b6" stroke="none"/><circle cx="12" cy="4" r="1.8" fill="#b6b6b6" stroke="none"/><circle cx="18.9" cy="8" r="1.8" fill="#b6b6b6" stroke="none"/><circle cx="18.9" cy="16" r="1.8" fill="#b6b6b6" stroke="none"/><circle cx="12" cy="20" r="1.8" fill="#b6b6b6" stroke="none"/><circle cx="5.1" cy="16" r="1.8" fill="#b6b6b6" stroke="none"/><circle cx="5.1" cy="8" r="1.8" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 695 B After Width: | Height: | Size: 695 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l8 4.5v9L12 21l-8-4.5v-9Z"/><circle cx="12" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l8 4.5v9L12 21l-8-4.5v-9Z"/><circle cx="12" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18 9 9 14 15 21 5"/><circle cx="3" cy="18" r="1.5" fill="#949494" stroke="none"/><circle cx="9" cy="9" r="1.5" fill="#949494" stroke="none"/><circle cx="14" cy="15" r="1.5" fill="#949494" stroke="none"/><circle cx="21" cy="5" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18 9 9 14 15 21 5"/><circle cx="3" cy="18" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="9" cy="9" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="14" cy="15" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="21" cy="5" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 462 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="6" width="16" height="12" rx="1"/><circle cx="4" cy="6" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="6" width="16" height="12" rx="1"/><circle cx="4" cy="6" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 295 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 16 10 6 20 8 14 18Z"/><circle cx="4" cy="16" r="1.5" fill="#949494" stroke="none"/><circle cx="10" cy="6" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M4 16 10 6 20 8 14 18Z"/><circle cx="4" cy="16" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="10" cy="6" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 342 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="6" width="17" height="12" rx="4.5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="6" width="17" height="12" rx="4.5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 16.5 A9 9 0 0 1 21 16.5 L16 16.5 A4 4 0 0 0 8 16.5 Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 16.5 A9 9 0 0 1 21 16.5 L16 16.5 A4 4 0 0 0 8 16.5 Z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 253 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="18" width="18" height="3" rx="0.5"/><rect x="6" y="6" width="2.5" height="12" rx="0.5"/><path d="M8.5 9L17 18"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="18" width="18" height="3" rx="0.5"/><rect x="6" y="6" width="2.5" height="12" rx="0.5"/><path d="M8.5 9L17 18"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3.5-7.1"/><path d="M21 3 21 8 16 8"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3.5-7.1"/><path d="M21 3 21 8 16 8"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 249 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="6" height="6" rx="1"/><path d="M8 8 3 3M3 7 3 3 7 3M16 8 21 3M17 3 21 3 21 7M8 16 3 21M3 17 3 21 7 21M16 16 21 21M17 21 21 21 21 17"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="6" height="6" rx="1"/><path d="M8 8 3 3M3 7 3 3 7 3M16 8 21 3M17 3 21 3 21 7M8 16 3 21M3 17 3 21 7 21M16 16 21 21M17 21 21 21 21 17"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 345 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 3 5 17.5 8.8 14.2 11.3 20.3 13.4 19.4 11 13.6 15.9 13.6Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5 3 5 17.5 8.8 14.2 11.3 20.3 13.4 19.4 11 13.6 15.9 13.6Z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="1"/><path d="M8 4v12h8V4"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="1"/><path d="M8 4v12h8V4"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 258 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M16 3.5a2.1 2.1 0 0 1 3 3L7.5 18l-4 1 1-4Z"/><path d="M14.5 5 19 9.5"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M16 3.5a2.1 2.1 0 0 1 3 3L7.5 18l-4 1 1-4Z"/><path d="M14.5 5 19 9.5"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M8 7h8a5 5 0 0 1 0 10H8a5 5 0 0 1 0-10Z"/><circle cx="8" cy="12" r="1.5" fill="#949494" stroke="none"/><circle cx="16" cy="12" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M8 7h8a5 5 0 0 1 0 10H8a5 5 0 0 1 0-10Z"/><circle cx="8" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="16" cy="12" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 360 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5.3 13 A8 8 0 0 1 12.9 17 A2.5 2.5 0 0 0 17.3 14.5 A13 13 0 0 0 4.9 8 A2.5 2.5 0 0 0 5.3 13Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M5.3 13 A8 8 0 0 1 12.9 17 A2.5 2.5 0 0 0 17.3 14.5 A13 13 0 0 0 4.9 8 A2.5 2.5 0 0 0 5.3 13Z"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 291 B After Width: | Height: | Size: 291 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M3.0 9.0 L16.0 9.0 L16.0 21.0 L3.0 21.0 ZM3.0 9.0 L7.0 5.0 L20.0 5.0 L16.0 9.0M20.0 5.0 L20.0 17.0 L16.0 21.0" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.168410256410256 13.423897435897436V13.868410256410256Q5.908923076923077 13.744307692307691 5.678769230769231 13.683384615384615Q5.448615384615385 13.622461538461538 5.23425641025641 13.622461538461538Q4.861948717948718 13.622461538461538 4.66 13.766871794871793Q4.458051282051283 13.91128205128205 4.458051282051283 14.177538461538461Q4.458051282051283 14.400923076923076 4.592307692307693 14.514871794871794Q4.726564102564103 14.628820512820512 5.101128205128205 14.69876923076923L5.3764102564102565 14.755179487179486Q5.886358974358975 14.852205128205128 6.128923076923078 15.09702564102564Q6.37148717948718 15.341846153846152 6.37148717948718 15.75251282051282Q6.37148717948718 16.242153846153844 6.043179487179488 16.49487179487179Q5.7148717948717955 16.747589743589742 5.080820512820513 16.747589743589742Q4.841641025641026 16.747589743589742 4.572000000000001 16.693435897435897Q4.302358974358975 16.639282051282052 4.013538461538462 16.53323076923077V16.063897435897434Q4.291076923076924 16.219589743589744 4.557333333333334 16.2985641025641Q4.823589743589745 16.37753846153846 5.080820512820513 16.37753846153846Q5.471179487179487 16.37753846153846 5.683282051282052 16.224102564102562Q5.895384615384616 16.070666666666664 5.895384615384616 15.786358974358974Q5.895384615384616 15.538153846153845 5.743076923076924 15.398256410256408Q5.590769230769231 15.258358974358973 5.243282051282051 15.188410256410256L4.965743589743591 15.134256410256409Q4.455794871794872 15.032717948717949 4.227897435897436 14.816102564102565Q4.000000000000001 14.599487179487179 4.000000000000001 14.213641025641024Q4.000000000000001 13.766871794871793 4.314769230769231 13.509641025641024Q4.629538461538462 13.252410256410256 5.182358974358975 13.252410256410256Q5.419282051282051 13.252410256410256 5.665230769230769 13.29528205128205Q5.911179487179488 13.338153846153846 6.168410256410256 13.423897435897436ZM6.615179487179487 13.313333333333333H9.46502564102564V13.696923076923076H8.269128205128204V16.682153846153845H7.811076923076923V13.696923076923076H6.615179487179487ZM9.905025641025642 13.313333333333333H12.035076923076925V13.696923076923076H10.360820512820514V14.69425641025641H11.965128205128206V15.077846153846153H10.360820512820514V16.2985641025641H12.075692307692309V16.682153846153845H9.905025641025642ZM13.280615384615384 13.687897435897435V14.953743589743588H13.85374358974359Q14.171897435897435 14.953743589743588 14.345641025641026 14.78902564102564Q14.519384615384615 14.624307692307692 14.519384615384615 14.319692307692307Q14.519384615384615 14.017333333333333 14.345641025641026 13.852615384615383Q14.171897435897435 13.687897435897435 13.85374358974359 13.687897435897435ZM12.824820512820512 13.313333333333333H13.85374358974359Q14.420102564102564 13.313333333333333 14.710051282051282 13.569435897435897Q15.0 13.82553846153846 15.0 14.319692307692307Q15.0 14.818358974358974 14.710051282051282 15.073333333333332Q14.420102564102564 15.32830769230769 13.85374358974359 15.32830769230769H13.280615384615384V16.682153846153845H12.824820512820512Z" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M3.0 9.0 L16.0 9.0 L16.0 21.0 L3.0 21.0 ZM3.0 9.0 L7.0 5.0 L20.0 5.0 L16.0 9.0M20.0 5.0 L20.0 17.0 L16.0 21.0" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.168410256410256 13.423897435897436V13.868410256410256Q5.908923076923077 13.744307692307691 5.678769230769231 13.683384615384615Q5.448615384615385 13.622461538461538 5.23425641025641 13.622461538461538Q4.861948717948718 13.622461538461538 4.66 13.766871794871793Q4.458051282051283 13.91128205128205 4.458051282051283 14.177538461538461Q4.458051282051283 14.400923076923076 4.592307692307693 14.514871794871794Q4.726564102564103 14.628820512820512 5.101128205128205 14.69876923076923L5.3764102564102565 14.755179487179486Q5.886358974358975 14.852205128205128 6.128923076923078 15.09702564102564Q6.37148717948718 15.341846153846152 6.37148717948718 15.75251282051282Q6.37148717948718 16.242153846153844 6.043179487179488 16.49487179487179Q5.7148717948717955 16.747589743589742 5.080820512820513 16.747589743589742Q4.841641025641026 16.747589743589742 4.572000000000001 16.693435897435897Q4.302358974358975 16.639282051282052 4.013538461538462 16.53323076923077V16.063897435897434Q4.291076923076924 16.219589743589744 4.557333333333334 16.2985641025641Q4.823589743589745 16.37753846153846 5.080820512820513 16.37753846153846Q5.471179487179487 16.37753846153846 5.683282051282052 16.224102564102562Q5.895384615384616 16.070666666666664 5.895384615384616 15.786358974358974Q5.895384615384616 15.538153846153845 5.743076923076924 15.398256410256408Q5.590769230769231 15.258358974358973 5.243282051282051 15.188410256410256L4.965743589743591 15.134256410256409Q4.455794871794872 15.032717948717949 4.227897435897436 14.816102564102565Q4.000000000000001 14.599487179487179 4.000000000000001 14.213641025641024Q4.000000000000001 13.766871794871793 4.314769230769231 13.509641025641024Q4.629538461538462 13.252410256410256 5.182358974358975 13.252410256410256Q5.419282051282051 13.252410256410256 5.665230769230769 13.29528205128205Q5.911179487179488 13.338153846153846 6.168410256410256 13.423897435897436ZM6.615179487179487 13.313333333333333H9.46502564102564V13.696923076923076H8.269128205128204V16.682153846153845H7.811076923076923V13.696923076923076H6.615179487179487ZM9.905025641025642 13.313333333333333H12.035076923076925V13.696923076923076H10.360820512820514V14.69425641025641H11.965128205128206V15.077846153846153H10.360820512820514V16.2985641025641H12.075692307692309V16.682153846153845H9.905025641025642ZM13.280615384615384 13.687897435897435V14.953743589743588H13.85374358974359Q14.171897435897435 14.953743589743588 14.345641025641026 14.78902564102564Q14.519384615384615 14.624307692307692 14.519384615384615 14.319692307692307Q14.519384615384615 14.017333333333333 14.345641025641026 13.852615384615383Q14.171897435897435 13.687897435897435 13.85374358974359 13.687897435897435ZM12.824820512820512 13.313333333333333H13.85374358974359Q14.420102564102564 13.313333333333333 14.710051282051282 13.569435897435897Q15.0 13.82553846153846 15.0 14.319692307692307Q15.0 14.818358974358974 14.710051282051282 15.073333333333332Q14.420102564102564 15.32830769230769 13.85374358974359 15.32830769230769H13.280615384615384V16.682153846153845H12.824820512820512Z" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 14C7 10 11 18 15 14L21 9C17 13 13 5 9 9Z"/><path d="M6 11.5 12 6.5" stroke-opacity="0.55"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 14C7 10 11 18 15 14L21 9C17 13 13 5 9 9Z"/><path d="M6 11.5 12 6.5" stroke-opacity="0.55"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M7.081932245922209 8.669636135508153V9.608908406524465Q6.5336260978670015 9.346675031367628 6.047302383939774 9.217942283563362Q5.560978670012547 9.089209535759096 5.108030112923463 9.089209535759096Q4.321329987452948 9.089209535759096 3.894604767879548 9.39435382685069Q3.467879548306148 9.699498117942282 3.467879548306148 10.262107904642408Q3.467879548306148 10.734127979924716 3.751568381430364 10.974905897114176Q4.03525721455458 11.215683814303638 4.8267252195734 11.363488080301128L5.40840652446675 11.482685069008781Q6.48594730238394 11.687703889585945 6.9984943538268505 12.205018820577163Q7.511041405269761 12.72233375156838 7.511041405269761 13.5900878293601Q7.511041405269761 14.624717691342532 6.817314930991217 15.158720200752821Q6.123588456712673 15.69272271016311 4.7838143036386445 15.69272271016311Q4.278419071518194 15.69272271016311 3.708657465495609 15.578293601003763Q3.138895859473024 15.463864491844415 2.528607277289837 15.239774153074025V14.248055207026347Q3.115056461731493 14.577038895859472 3.6776662484316187 14.743914680050187Q4.240276035131744 14.910790464240902 4.7838143036386445 14.910790464240902Q5.608657465495608 14.910790464240902 6.056838143036387 14.586574654956085Q6.505018820577165 14.262358845671265 6.505018820577165 13.66160602258469Q6.505018820577165 13.137139272271014 6.183186951066499 12.841530740276033Q5.861355081555834 12.545922208281052 5.1271016311166875 12.398117942283562L4.540652446675031 12.283688833124215Q3.4631116687578416 12.069134253450438 2.981555834378921 11.611417816813049Q2.5 11.153701380175658 2.5 10.338393977415306Q2.5 9.39435382685069 3.165119196988708 8.850815558343788Q3.830238393977415 8.307277289836886 4.998368883312422 8.307277289836886Q5.498996235884567 8.307277289836886 6.018695106649937 8.397867001254703Q6.538393977415307 8.48845671267252 7.081932245922209 8.669636135508153ZM10.848557089084066 15.554454203262232 8.13086574654956 8.436010037641154H9.136888331242158L11.392095357590966 14.42923462986198L13.652070263488081 8.436010037641154H14.653324968632372L11.940401505646173 15.554454203262232ZM20.546424090338768 14.538895859473023V12.626976160602258H18.97302383939774V11.835508155583437H21.499999999999996V14.891718946047677Q20.942158092848178 15.287452948557087 20.26988707653701 15.4900878293601Q19.597616060225846 15.69272271016311 18.83475533249686 15.69272271016311Q17.16599749058971 15.69272271016311 16.224341279799248 14.717691342534504Q15.282685069008783 13.742659974905896 15.282685069008783 12.002383939774152Q15.282685069008783 10.257340025094102 16.224341279799248 9.282308657465494Q17.16599749058971 8.307277289836886 18.83475533249686 8.307277289836886Q19.53086574654956 8.307277289836886 20.15784190715182 8.478920953575908Q20.784818067754077 8.650564617314929 21.31405269761606 8.984316185696361V10.009410288582181Q20.78005018820577 9.556461731493098 20.179297365119197 9.327603513174402Q19.57854454203262 9.098745294855707 18.915809284818067 9.098745294855707Q17.609410288582183 9.098745294855707 16.953826850690085 9.828230865746548Q16.29824341279799 10.557716436637389 16.29824341279799 12.002383939774152Q16.29824341279799 13.442283563362608 16.953826850690085 14.171769134253449Q17.609410288582183 14.90125470514429 18.915809284818067 14.90125470514429Q19.425972396486824 14.90125470514429 19.826474278544538 14.813048933500625Q20.226976160602256 14.724843161856962 20.546424090338768 14.538895859473023Z" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M7.081932245922209 8.669636135508153V9.608908406524465Q6.5336260978670015 9.346675031367628 6.047302383939774 9.217942283563362Q5.560978670012547 9.089209535759096 5.108030112923463 9.089209535759096Q4.321329987452948 9.089209535759096 3.894604767879548 9.39435382685069Q3.467879548306148 9.699498117942282 3.467879548306148 10.262107904642408Q3.467879548306148 10.734127979924716 3.751568381430364 10.974905897114176Q4.03525721455458 11.215683814303638 4.8267252195734 11.363488080301128L5.40840652446675 11.482685069008781Q6.48594730238394 11.687703889585945 6.9984943538268505 12.205018820577163Q7.511041405269761 12.72233375156838 7.511041405269761 13.5900878293601Q7.511041405269761 14.624717691342532 6.817314930991217 15.158720200752821Q6.123588456712673 15.69272271016311 4.7838143036386445 15.69272271016311Q4.278419071518194 15.69272271016311 3.708657465495609 15.578293601003763Q3.138895859473024 15.463864491844415 2.528607277289837 15.239774153074025V14.248055207026347Q3.115056461731493 14.577038895859472 3.6776662484316187 14.743914680050187Q4.240276035131744 14.910790464240902 4.7838143036386445 14.910790464240902Q5.608657465495608 14.910790464240902 6.056838143036387 14.586574654956085Q6.505018820577165 14.262358845671265 6.505018820577165 13.66160602258469Q6.505018820577165 13.137139272271014 6.183186951066499 12.841530740276033Q5.861355081555834 12.545922208281052 5.1271016311166875 12.398117942283562L4.540652446675031 12.283688833124215Q3.4631116687578416 12.069134253450438 2.981555834378921 11.611417816813049Q2.5 11.153701380175658 2.5 10.338393977415306Q2.5 9.39435382685069 3.165119196988708 8.850815558343788Q3.830238393977415 8.307277289836886 4.998368883312422 8.307277289836886Q5.498996235884567 8.307277289836886 6.018695106649937 8.397867001254703Q6.538393977415307 8.48845671267252 7.081932245922209 8.669636135508153ZM10.848557089084066 15.554454203262232 8.13086574654956 8.436010037641154H9.136888331242158L11.392095357590966 14.42923462986198L13.652070263488081 8.436010037641154H14.653324968632372L11.940401505646173 15.554454203262232ZM20.546424090338768 14.538895859473023V12.626976160602258H18.97302383939774V11.835508155583437H21.499999999999996V14.891718946047677Q20.942158092848178 15.287452948557087 20.26988707653701 15.4900878293601Q19.597616060225846 15.69272271016311 18.83475533249686 15.69272271016311Q17.16599749058971 15.69272271016311 16.224341279799248 14.717691342534504Q15.282685069008783 13.742659974905896 15.282685069008783 12.002383939774152Q15.282685069008783 10.257340025094102 16.224341279799248 9.282308657465494Q17.16599749058971 8.307277289836886 18.83475533249686 8.307277289836886Q19.53086574654956 8.307277289836886 20.15784190715182 8.478920953575908Q20.784818067754077 8.650564617314929 21.31405269761606 8.984316185696361V10.009410288582181Q20.78005018820577 9.556461731493098 20.179297365119197 9.327603513174402Q19.57854454203262 9.098745294855707 18.915809284818067 9.098745294855707Q17.609410288582183 9.098745294855707 16.953826850690085 9.828230865746548Q16.29824341279799 10.557716436637389 16.29824341279799 12.002383939774152Q16.29824341279799 13.442283563362608 16.953826850690085 14.171769134253449Q17.609410288582183 14.90125470514429 18.915809284818067 14.90125470514429Q19.425972396486824 14.90125470514429 19.826474278544538 14.813048933500625Q20.226976160602256 14.724843161856962 20.546424090338768 14.538895859473023Z" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="17" r="2.4"/><path d="M6 17 C 7 9, 15 15, 18 6"/><path d="M15.2 6.6 18 6 17.7 8.9"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="17" r="2.4"/><path d="M6 17 C 7 9, 15 15, 18 6"/><path d="M15.2 6.6 18 6 17.7 8.9"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 289 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#949494" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18h8"/><path d="M11 18 A7 7 0 0 1 18 11"/><circle cx="3" cy="18" r="1.5" fill="#949494" stroke="none"/><circle cx="11" cy="18" r="1.5" fill="#949494" stroke="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#b6b6b6" stroke-width="0.85" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18h8"/><path d="M11 18 A7 7 0 0 1 18 11"/><circle cx="3" cy="18" r="1.5" fill="#b6b6b6" stroke="none"/><circle cx="11" cy="18" r="1.5" fill="#b6b6b6" stroke="none"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |