mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-09 08:41:14 +00:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bf0901a95 | ||
|
|
9d32c1c545 | ||
|
|
67a16dabca | ||
|
|
59fc97fb28 | ||
|
|
7d44b60ae4 | ||
|
|
776ca6a3e4 | ||
|
|
ee26e94170 | ||
|
|
d401d4f837 | ||
|
|
18b70844d1 | ||
|
|
c8f2498681 | ||
|
|
30902561c0 | ||
|
|
3fc515f48d | ||
|
|
6cd5feed79 | ||
|
|
09530ef7c4 |
@@ -61,8 +61,10 @@ available; GTK2/WebKit1 is an opt-out configuration the GUI does not support.
|
|||||||
11. A web host that re-themes in place handles `EVT_WEBVIEW_RECREATED` without `Skip()`; one that
|
11. A web host that re-themes in place handles `EVT_WEBVIEW_RECREATED` without `Skip()`; one that
|
||||||
needs a reload lets it through. §[Orca wrapper](#orca-webview-wrapper-widgetswebview)
|
needs a reload lets it through. §[Orca wrapper](#orca-webview-wrapper-widgetswebview)
|
||||||
12. Keep `WebViewWebKit`'s destructor removing the `"wx"` handler. §[Orca wrapper](#orca-webview-wrapper-widgetswebview)
|
12. Keep `WebViewWebKit`'s destructor removing the `"wx"` handler. §[Orca wrapper](#orca-webview-wrapper-widgetswebview)
|
||||||
13. Do not widen `WEBKIT_DISABLE_COMPOSITING_MODE` beyond Orca's default-path XWayland case, and never
|
13. Do not widen `WEBKIT_DISABLE_COMPOSITING_MODE` beyond Orca's default-path XWayland case. Disable the
|
||||||
make a page's progress depend only on a C++→JS callback. §[WebKitGTK on Linux](#webkitgtk-on-linux-sessions)
|
WebKit DMA-BUF renderer only for the NVIDIA proprietary driver on native Wayland (GNOME/gtk#8056), and
|
||||||
|
never make a page's progress depend only on a C++→JS callback.
|
||||||
|
§[WebKitGTK on Linux](#webkitgtk-on-linux-sessions)
|
||||||
14. GL attribute lists: legacy `int[]` lists end with `0` and spell out `WX_GL_RGBA` and
|
14. GL attribute lists: legacy `int[]` lists end with `0` and spell out `WX_GL_RGBA` and
|
||||||
`WX_GL_DOUBLEBUFFER`; `wxGLAttributes`/`wxGLContextAttrs` end with `EndList()`; MSAA is requested
|
`WX_GL_DOUBLEBUFFER`; `wxGLAttributes`/`wxGLContextAttrs` end with `EndList()`; MSAA is requested
|
||||||
explicitly. §[wxGLCanvas](#wxglcanvas-and-wxglcontext)
|
explicitly. §[wxGLCanvas](#wxglcanvas-and-wxglcontext)
|
||||||
@@ -599,6 +601,25 @@ Runtime backend detection elsewhere uses Orca's `is_running_on_wayland()` / `is_
|
|||||||
Cite: c12912e0df (`src/OrcaSlicer.cpp`; `resources/web/guide/0/load.js` `OnInit`
|
Cite: c12912e0df (`src/OrcaSlicer.cpp`; `resources/web/guide/0/load.js` `OnInit`
|
||||||
`setTimeout("JumpToTarget()", …)`), 9446030079 (the `GDK_BACKEND=x11` opt-in branch).
|
`setTimeout("JumpToTarget()", …)`), 9446030079 (the `GDK_BACKEND=x11` opt-in branch).
|
||||||
|
|
||||||
|
**DMA-BUF renderer / explicit sync (NVIDIA + Wayland).**
|
||||||
|
- **Rule:** On the Wayland default path, set `WEBKIT_DISABLE_DMABUF_RENDERER=1` non-replacing, gated to
|
||||||
|
`__linux__` + native Wayland (not the forced-X11 fallback) + `/proc/driver/nvidia/version` +
|
||||||
|
`WebView::WebKitAtLeast(2, 46)`. The version gate uses the runtime `webkit_get_major_version()` /
|
||||||
|
`webkit_get_minor_version()` getters (no GTK init needed), not a compile-time macro, and 2.46 is the
|
||||||
|
oldest release with a confirmed crash report — narrower gates (e.g. 2.54) would miss 2.46–2.52 victims.
|
||||||
|
**Why:** WebKitGTK's DMA-BUF renderer arms `linux-drm-syncobj-v1` on the toplevel surface; GTK3 then
|
||||||
|
commits its first shared-memory frame without an acquire point, and KWin/Mutter reject the commit with
|
||||||
|
`Error 71 (Protocol error)` — GDK turns that into `_exit(1)` before Orca logs anything. The defect is
|
||||||
|
GTK3's `gdk_wayland_window_attach_image()` (GNOME/gtk#8056); WebKit only triggers it, the NVIDIA
|
||||||
|
proprietary driver has no implicit-sync fallback (Mesa tolerates it), and no upstream fix or PR exists.
|
||||||
|
This is a different variable from `WEBKIT_DISABLE_COMPOSITING_MODE` and does not replace it.
|
||||||
|
```cpp
|
||||||
|
// Wayland default path, before GTK init
|
||||||
|
if (!x11_backend && wayland && ::access("/proc/driver/nvidia/version", F_OK) == 0 &&
|
||||||
|
WebView::WebKitAtLeast(2, 46))
|
||||||
|
::setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", /* replace */ false);
|
||||||
|
```
|
||||||
|
|
||||||
## wxGLCanvas and wxGLContext
|
## wxGLCanvas and wxGLContext
|
||||||
|
|
||||||
**Attributes.**
|
**Attributes.**
|
||||||
|
|||||||
+36
-3
@@ -8,9 +8,10 @@ SCRIPT_PATH=$(dirname "$(readlink -f "${0}")")
|
|||||||
pushd "${SCRIPT_PATH}" > /dev/null
|
pushd "${SCRIPT_PATH}" > /dev/null
|
||||||
|
|
||||||
function usage() {
|
function usage() {
|
||||||
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-F][-g][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L]"
|
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-F][-g][-h][-i][-j N][-J N][-p][-r][-s][-t][-u][-l][-L]"
|
||||||
echo " -1: limit builds to one core (where possible)"
|
echo " -1: limit builds to one core (where possible)"
|
||||||
echo " -j N: limit builds to N cores (where possible)"
|
echo " -j N: limit builds to N cores (where possible)"
|
||||||
|
echo " -J N: build up to N dependencies at a time, each still using -j jobs (default: 1)"
|
||||||
echo " -b: build in Debug mode"
|
echo " -b: build in Debug mode"
|
||||||
echo " -c: force a clean build"
|
echo " -c: force a clean build"
|
||||||
echo " -C: enable ANSI-colored compile output (GNU/Clang only)"
|
echo " -C: enable ANSI-colored compile output (GNU/Clang only)"
|
||||||
@@ -36,12 +37,13 @@ function usage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SLIC3R_PRECOMPILED_HEADERS="ON"
|
SLIC3R_PRECOMPILED_HEADERS="ON"
|
||||||
|
DEPS_PARALLEL=""
|
||||||
|
|
||||||
unset name
|
unset name
|
||||||
BUILD_DIR=build
|
BUILD_DIR=build
|
||||||
BUILD_CONFIG=Release
|
BUILD_CONFIG=Release
|
||||||
FORWARDED_ARGS=()
|
FORWARDED_ARGS=()
|
||||||
while getopts ":1j:bcCdDeFghiprstulL" opt ; do
|
while getopts ":1j:J:bcCdDeFghiprstulL" opt ; do
|
||||||
case ${opt} in
|
case ${opt} in
|
||||||
1 )
|
1 )
|
||||||
export CMAKE_BUILD_PARALLEL_LEVEL=1
|
export CMAKE_BUILD_PARALLEL_LEVEL=1
|
||||||
@@ -51,6 +53,10 @@ while getopts ":1j:bcCdDeFghiprstulL" opt ; do
|
|||||||
export CMAKE_BUILD_PARALLEL_LEVEL=$OPTARG
|
export CMAKE_BUILD_PARALLEL_LEVEL=$OPTARG
|
||||||
FORWARDED_ARGS+=("-j" "$OPTARG")
|
FORWARDED_ARGS+=("-j" "$OPTARG")
|
||||||
;;
|
;;
|
||||||
|
J )
|
||||||
|
DEPS_PARALLEL=$OPTARG
|
||||||
|
FORWARDED_ARGS+=("-J" "$OPTARG")
|
||||||
|
;;
|
||||||
b )
|
b )
|
||||||
BUILD_DIR=build-dbg
|
BUILD_DIR=build-dbg
|
||||||
BUILD_CONFIG=Debug
|
BUILD_CONFIG=Debug
|
||||||
@@ -135,6 +141,11 @@ if [[ -n "${CLEAN_DOCKER_IMAGE}" ]] && [[ -z "${USE_DOCKER}" ]] ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${DEPS_PARALLEL}" ]] && ! [[ "${DEPS_PARALLEL}" =~ ^[1-9][0-9]*$ ]] ; then
|
||||||
|
echo "Error: -J expects a positive integer."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
function check_available_memory_and_disk() {
|
function check_available_memory_and_disk() {
|
||||||
FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev)
|
FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev)
|
||||||
MIN_MEM_GB=10
|
MIN_MEM_GB=10
|
||||||
@@ -537,7 +548,29 @@ if [[ -n "${BUILD_DEPS}" ]] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_and_run cmake -S deps -B deps/$BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G Ninja "${COLORED_OUTPUT}" "${BUILD_ARGS[@]}"
|
print_and_run cmake -S deps -B deps/$BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G Ninja "${COLORED_OUTPUT}" "${BUILD_ARGS[@]}"
|
||||||
print_and_run cmake --build deps/$BUILD_DIR -j1
|
# The top-level build runs one dependency at a time by default, which keeps the console
|
||||||
|
# output readable and lets that dependency's own build use all of CMAKE_BUILD_PARALLEL_LEVEL.
|
||||||
|
# -J raises the top level instead, and -j still applies in full to every dependency, so the
|
||||||
|
# worst case is -J times -j compile jobs at once. Ninja has no job server to share a pool
|
||||||
|
# across the nested builds, so that ceiling is not enforced anywhere: pick -J to suit the RAM.
|
||||||
|
DEPS_JOBS=1
|
||||||
|
if [[ -n "${DEPS_PARALLEL}" ]] ; then
|
||||||
|
DEPS_JOBS=${DEPS_PARALLEL}
|
||||||
|
SAVED_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL-}
|
||||||
|
export CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL:-$(nproc)}
|
||||||
|
echo "Building up to ${DEPS_JOBS} dependencies at a time, ${CMAKE_BUILD_PARALLEL_LEVEL} jobs each: up to $(( DEPS_JOBS * CMAKE_BUILD_PARALLEL_LEVEL )) compile jobs at once."
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_and_run cmake --build deps/$BUILD_DIR -j"${DEPS_JOBS}"
|
||||||
|
|
||||||
|
if [[ -n "${DEPS_PARALLEL}" ]] ; then
|
||||||
|
# Give the whole -j back to the OrcaSlicer build below.
|
||||||
|
if [[ -n "${SAVED_PARALLEL_LEVEL}" ]] ; then
|
||||||
|
export CMAKE_BUILD_PARALLEL_LEVEL=${SAVED_PARALLEL_LEVEL}
|
||||||
|
else
|
||||||
|
unset CMAKE_BUILD_PARALLEL_LEVEL
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
|
if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# Separated infills — High Level Design
|
||||||
|
|
||||||
|
## Purpose and scope
|
||||||
|
|
||||||
|
An object's infill patterns are laid out from one reference point, the center
|
||||||
|
of the object. When an object groups several parts that do not touch, every
|
||||||
|
part cuts the same object-wide pattern at a different place, so equal parts get
|
||||||
|
different infill. `separated_infills` lays the infill of every connected body
|
||||||
|
out from the center of that body instead, as if the body were sliced on its own.
|
||||||
|
|
||||||
|
The option covers sparse infill, internal solid infill and bridges. Top and
|
||||||
|
bottom surfaces are left to `center_of_surface_pattern`, which centers the
|
||||||
|
Archimedean Chords and Octagram Spiral surface patterns. The option is off by
|
||||||
|
default; with it off, or for an object made of a single body, no fill changes.
|
||||||
|
Adaptive Cubic and Support Cubic do not depend on the option: they always fill
|
||||||
|
each body on its own (see Octree infill).
|
||||||
|
|
||||||
|
## Bodies
|
||||||
|
|
||||||
|
`PrintObject::prepare_infill()` groups the islands of every layer (`lslices`)
|
||||||
|
into 3D connected bodies before bridges are detected, so bridge anchors and
|
||||||
|
printed infill share one origin. Islands on adjacent layers belong to one body
|
||||||
|
when their slices overlap. Parts that touch or overlap form one body. Separate
|
||||||
|
parts, disconnected islands of one mesh, and interleaved parts that never touch,
|
||||||
|
such as chain links, each form their own. Every island stores the index of its
|
||||||
|
body in `Layer::lslices_separated_component_ids`, and
|
||||||
|
`PrintObject::separated_body_bboxes()` holds the bounding box of each body over
|
||||||
|
all its layers.
|
||||||
|
|
||||||
|
The pass runs when a region uses separated infills, per-model surface centering
|
||||||
|
or an octree infill pattern. It is skipped when the object has one model part
|
||||||
|
that cannot be split, since a single body already shares the object center.
|
||||||
|
|
||||||
|
## Centering a fill
|
||||||
|
|
||||||
|
`infill_body()` matches each fill region to the island it overlaps most, among
|
||||||
|
the islands whose bounding boxes overlap it, and the filler takes the bounding
|
||||||
|
box of that island's body instead of the object's. The box covers every layer
|
||||||
|
of the body, which is the box the body gets when sliced alone, so patterns that
|
||||||
|
depend on its extent as well as its center come out the same too. Bridge
|
||||||
|
anchoring (`Layer::generate_sparse_infill_polylines_for_anchoring()`) makes the
|
||||||
|
same choice, so the anchors match the printed infill.
|
||||||
|
|
||||||
|
The patterns follow the body's box in one of two ways:
|
||||||
|
|
||||||
|
- Rectilinear and its variants, Line, Grid, Triangles, Tri-hexagon, Cubic,
|
||||||
|
Quarter Cubic, Lateral Lattice, Lateral Honeycomb and the plane-path patterns
|
||||||
|
(Hilbert Curve, Archimedean Chords, Octagram Spiral) are laid out from the
|
||||||
|
box: they phase their lines through its center, and Hilbert Curve and the Zig
|
||||||
|
Zag links start from its corner. `Fill::extended_object_bounding_box()`
|
||||||
|
extends the box about its center, so it also serves a box that is not
|
||||||
|
centered on the origin.
|
||||||
|
- Honeycomb, 3D Honeycomb, Cross Hatch, Gyroid, TPMS-D and TPMS-FK are laid out
|
||||||
|
from the coordinate origin, which is the object center. They return true from
|
||||||
|
`Fill::aligned_to_origin()`, and `Fill::fill_surface()` moves each region so
|
||||||
|
that the box center lands on the origin, fills it, and moves the paths back.
|
||||||
|
With the default box the center is the origin, so nothing moves.
|
||||||
|
|
||||||
|
`is_separable_infill_pattern()` lists these patterns. The settings show the
|
||||||
|
option only when the sparse infill pattern is one of them.
|
||||||
|
|
||||||
|
## Octree infill
|
||||||
|
|
||||||
|
Adaptive Cubic and Support Cubic take their lines from an octree, laid out from
|
||||||
|
the center of the mesh it is built from and refined near its surfaces. An
|
||||||
|
octree of the whole object would lay every part out from the object's center
|
||||||
|
and refine it near the other parts, so these patterns
|
||||||
|
(`is_octree_infill_pattern()`) always fill each body on its own, and the
|
||||||
|
settings hide the option for them.
|
||||||
|
|
||||||
|
For an object of several bodies, `PrintObject::prepare_adaptive_infill_data()`
|
||||||
|
builds one octree per body (`FillAdaptive::Octrees`) from the triangles of that
|
||||||
|
body only, which is the octree the body gets when sliced alone. Each connected
|
||||||
|
component of the mesh goes to the body that most of a few sampled triangles lie
|
||||||
|
on. A sample is taken a layer height inside the solid, behind the triangle, and
|
||||||
|
looked up in the islands of the nearest layer. Each internal bridge surface goes
|
||||||
|
to the body of its island. The fill takes the octree of the region's body, from
|
||||||
|
the same `infill_body()`. The octree of the whole object is built only for an
|
||||||
|
object of a single body, or when some body received no triangles, which then
|
||||||
|
uses it.
|
||||||
|
|
||||||
|
## Patterns left out
|
||||||
|
|
||||||
|
Lightning grows its trees over the whole object, so moving a reference point
|
||||||
|
cannot center it on one body. Concentric and Spiral Inset follow the outline of
|
||||||
|
each region and need no centering.
|
||||||
|
|
||||||
|
Solid infill at full density spaces its lines over the extent of each region,
|
||||||
|
so it is already independent of the other bodies. Only bridges, which keep
|
||||||
|
their line spacing, and the plane-path solid patterns depend on the center.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Elegoo",
|
"name": "Elegoo",
|
||||||
"version": "02.04.00.12",
|
"version": "02.04.00.11",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "Elegoo configurations",
|
"description": "Elegoo configurations",
|
||||||
"machine_model_list": [
|
"machine_model_list": [
|
||||||
|
|||||||
@@ -15,6 +15,6 @@
|
|||||||
"Elegoo"
|
"Elegoo"
|
||||||
],
|
],
|
||||||
"filament_start_gcode": [
|
"filament_start_gcode": [
|
||||||
"; Elegoo PLA filament start gcode\n"
|
"; filament start gcode\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Orca Arena Printer",
|
"name": "Orca Arena Printer",
|
||||||
"url": "",
|
"url": "",
|
||||||
"version": "02.04.00.08",
|
"version": "02.04.00.07",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "Orca Arena configuration files",
|
"description": "Orca Arena configuration files",
|
||||||
"machine_model_list": [
|
"machine_model_list": [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "OrcaFilamentLibrary",
|
"name": "OrcaFilamentLibrary",
|
||||||
"version": "02.04.00.19",
|
"version": "02.04.00.15",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "Orca Filament Library",
|
"description": "Orca Filament Library",
|
||||||
"filament_list": [
|
"filament_list": [
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
"60"
|
"60"
|
||||||
],
|
],
|
||||||
"filament_start_gcode": [
|
"filament_start_gcode": [
|
||||||
"; Elegoo PLA filament start gcode\n"
|
"; filament start gcode\n"
|
||||||
],
|
],
|
||||||
"filament_end_gcode": [
|
"filament_end_gcode": [
|
||||||
"; filament end gcode \n"
|
"; filament end gcode \n"
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ using json = nlohmann::json;
|
|||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
#include "slic3r/GUI/GUI_Init.hpp"
|
#include "slic3r/GUI/GUI_Init.hpp"
|
||||||
|
#include "slic3r/GUI/Widgets/WebView.hpp"
|
||||||
// BBLPrinterAgent::from_orca_filament_id(); the map and its lookups live in libslic3r_gui,
|
// BBLPrinterAgent::from_orca_filament_id(); the map and its lookups live in libslic3r_gui,
|
||||||
// which only a SLIC3R_GUI build links (see target_link_libraries(OrcaSlicer libslic3r_gui)
|
// which only a SLIC3R_GUI build links (see target_link_libraries(OrcaSlicer libslic3r_gui)
|
||||||
// in CMakeLists).
|
// in CMakeLists).
|
||||||
@@ -1155,6 +1156,12 @@ int CLI::run(int argc, char **argv)
|
|||||||
// unset preserves WebKit hardware acceleration on Device / Setup
|
// unset preserves WebKit hardware acceleration on Device / Setup
|
||||||
// Wizard / login / store. The default path still applies it on
|
// Wizard / login / store. The default path still applies it on
|
||||||
// XWayland sessions as a conservative fallback for older WebKit.
|
// XWayland sessions as a conservative fallback for older WebKit.
|
||||||
|
//
|
||||||
|
// The default path also disables WebKit's DMA-BUF renderer when the
|
||||||
|
// NVIDIA proprietary driver is in use on native Wayland. That is a
|
||||||
|
// separate switch from compositing and is needed because GTK3 commits
|
||||||
|
// a shared-memory frame onto an explicit-sync surface (GNOME/gtk#8056),
|
||||||
|
// which KWin/Mutter reject with "Error 71 (Protocol error)".
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
const char* gdk_backend = ::getenv("GDK_BACKEND");
|
const char* gdk_backend = ::getenv("GDK_BACKEND");
|
||||||
@@ -1218,6 +1225,34 @@ int CLI::run(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebKitGTK's DMA-BUF renderer arms explicit sync
|
||||||
|
// (linux-drm-syncobj-v1) on the toplevel Wayland surface. If the
|
||||||
|
// first painted frame is a shared-memory buffer, GTK3's
|
||||||
|
// gdk_wayland_window_attach_image() commits it without an acquire
|
||||||
|
// point, and compositors that enforce the protocol (KWin, Mutter)
|
||||||
|
// terminate the client with "Error 71 (Protocol error)" before the
|
||||||
|
// app can log anything (GNOME/gtk#8056). NVIDIA's proprietary
|
||||||
|
// driver has no implicit-sync fallback, so the crash only happens
|
||||||
|
// there; Mesa tolerates the missing point. Scope the workaround to
|
||||||
|
// NVIDIA on native Wayland, on WebKitGTK >= 2.46 (the oldest release
|
||||||
|
// with a confirmed report; the DMA-BUF renderer predates it).
|
||||||
|
// Non-replacing, so a user who does not hit the bug can opt back in
|
||||||
|
// with WEBKIT_DISABLE_DMABUF_RENDERER=0.
|
||||||
|
#if defined(__linux__)
|
||||||
|
{
|
||||||
|
const char* gdk_backend_wk = ::getenv("GDK_BACKEND");
|
||||||
|
// The EGL-less fallback above may have just forced X11.
|
||||||
|
const bool x11_backend_wk = gdk_backend_wk && boost::starts_with(gdk_backend_wk, "x11");
|
||||||
|
const char* wayland_env_dmabuf = ::getenv("WAYLAND_DISPLAY");
|
||||||
|
if (!x11_backend_wk && wayland_env_dmabuf && *wayland_env_dmabuf &&
|
||||||
|
::access("/proc/driver/nvidia/version", F_OK) == 0 &&
|
||||||
|
WebView::WebKitAtLeast(2, 46)) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "NVIDIA proprietary driver on Wayland: disabling the WebKit DMA-BUF renderer (GNOME/gtk#8056 workaround).";
|
||||||
|
::setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", /* replace */ false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// XInitThreads is needed before GStreamer may use Xlib. On
|
// XInitThreads is needed before GStreamer may use Xlib. On
|
||||||
// native Wayland without DISPLAY, GStreamer uses waylandsink
|
// native Wayland without DISPLAY, GStreamer uses waylandsink
|
||||||
// (no Xlib involved), so the call is skipped.
|
// (no Xlib involved), so the call is skipped.
|
||||||
@@ -4094,6 +4129,8 @@ int CLI::run(int argc, char **argv)
|
|||||||
flush_and_exit(CLI_MIXED_FILAMENT_INVALID);
|
flush_and_exit(CLI_MIXED_FILAMENT_INVALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (filament_count > 0)
|
||||||
|
resize_mixed_filament_metadata(m_print_config, size_t(filament_count), size_t(filament_count));
|
||||||
|
|
||||||
m_print_config.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology", true)->value = printer_technology;
|
m_print_config.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology", true)->value = printer_technology;
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,6 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <functional>
|
|
||||||
#include <gp_XY.hxx>
|
#include <gp_XY.hxx>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|||||||
@@ -261,8 +261,6 @@ set(lisbslic3r_sources
|
|||||||
GCode/PreciseSeam.cpp
|
GCode/PreciseSeam.cpp
|
||||||
GCode/PreciseSeam.hpp
|
GCode/PreciseSeam.hpp
|
||||||
GCode/PreciseSeamInternal.hpp
|
GCode/PreciseSeamInternal.hpp
|
||||||
#GCodeSender.cpp
|
|
||||||
#GCodeSender.hpp
|
|
||||||
GCode/SmallAreaInfillFlowCompensator.cpp
|
GCode/SmallAreaInfillFlowCompensator.cpp
|
||||||
GCode/SmallAreaInfillFlowCompensator.hpp
|
GCode/SmallAreaInfillFlowCompensator.hpp
|
||||||
GCode/SpiralVase.cpp
|
GCode/SpiralVase.cpp
|
||||||
@@ -447,7 +445,6 @@ set(lisbslic3r_sources
|
|||||||
SLA/SupportTreeBuildsteps.hpp
|
SLA/SupportTreeBuildsteps.hpp
|
||||||
SLA/SupportTree.cpp
|
SLA/SupportTree.cpp
|
||||||
SLA/SupportTree.hpp
|
SLA/SupportTree.hpp
|
||||||
#SLA/SupportTreeIGL.cpp
|
|
||||||
SLA/SupportTreeMesher.cpp
|
SLA/SupportTreeMesher.cpp
|
||||||
SLA/SupportTreeMesher.hpp
|
SLA/SupportTreeMesher.hpp
|
||||||
SlicesToTriangleMesh.cpp
|
SlicesToTriangleMesh.cpp
|
||||||
|
|||||||
@@ -2589,7 +2589,6 @@ void priv::create_face_types(FaceTypeMap &map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include <CGAL/Polygon_mesh_processing/clip.h>
|
#include <CGAL/Polygon_mesh_processing/clip.h>
|
||||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
|
||||||
bool priv::clip_cut(SurfacePatch &cut, CutMesh clipper)
|
bool priv::clip_cut(SurfacePatch &cut, CutMesh clipper)
|
||||||
{
|
{
|
||||||
CutMesh& tm = cut.mesh;
|
CutMesh& tm = cut.mesh;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "Emboss.hpp"
|
#include "Emboss.hpp"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <numeric>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <boost/nowide/convert.hpp>
|
#include <boost/nowide/convert.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|||||||
+31
-25
@@ -29,6 +29,7 @@
|
|||||||
#include "ExtrusionEntity.hpp"
|
#include "ExtrusionEntity.hpp"
|
||||||
#include "Fill.hpp"
|
#include "Fill.hpp"
|
||||||
#include "libslic3r/Fill/FillBase.hpp"
|
#include "libslic3r/Fill/FillBase.hpp"
|
||||||
|
#include "FillAdaptive.hpp"
|
||||||
#include "FillRectilinear.hpp"
|
#include "FillRectilinear.hpp"
|
||||||
#include "FillLightning.hpp"
|
#include "FillLightning.hpp"
|
||||||
#include "FillConcentricInternal.hpp"
|
#include "FillConcentricInternal.hpp"
|
||||||
@@ -926,7 +927,6 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||||||
params.lateral_lattice_angle_2 = region_config.lateral_lattice_angle_2;
|
params.lateral_lattice_angle_2 = region_config.lateral_lattice_angle_2;
|
||||||
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
params.infill_overhang_angle = region_config.infill_overhang_angle;
|
||||||
params.center_of_surface_pattern = region_config.center_of_surface_pattern;
|
params.center_of_surface_pattern = region_config.center_of_surface_pattern;
|
||||||
params.separated_infills = region_config.separated_infills;
|
|
||||||
if (params.pattern == ipLockedZag) {
|
if (params.pattern == ipLockedZag) {
|
||||||
params.infill_lock_depth = scale_(region_config.infill_lock_depth);
|
params.infill_lock_depth = scale_(region_config.infill_lock_depth);
|
||||||
params.skin_infill_depth = scale_(region_config.skin_infill_depth);
|
params.skin_infill_depth = scale_(region_config.skin_infill_depth);
|
||||||
@@ -999,6 +999,9 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||||||
// (which would unnecessarily split fill batching).
|
// (which would unnecessarily split fill batching).
|
||||||
// Stored on SurfaceFillParams; copied to FillParams during conversion.
|
// Stored on SurfaceFillParams; copied to FillParams during conversion.
|
||||||
params.gyroid_optimized = (params.pattern == ipGyroid) && region_config.gyroid_optimized;
|
params.gyroid_optimized = (params.pattern == ipGyroid) && region_config.gyroid_optimized;
|
||||||
|
// Orca: Likewise separated_infills only where it can move the pattern.
|
||||||
|
params.separated_infills = region_config.separated_infills && is_separable_infill_pattern(params.pattern) &&
|
||||||
|
params.extrusion_role != erTopSolidInfill && params.extrusion_role != erBottomSurface;
|
||||||
|
|
||||||
if (params.extrusion_role == erInternalInfill) {
|
if (params.extrusion_role == erInternalInfill) {
|
||||||
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.infill_direction.value,
|
params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.infill_direction.value,
|
||||||
@@ -1073,7 +1076,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||||||
//get locked region param
|
//get locked region param
|
||||||
if (params.pattern == ipLockedZag){
|
if (params.pattern == ipLockedZag){
|
||||||
const PrintObject *object = layerm.layer()->object();
|
const PrintObject *object = layerm.layer()->object();
|
||||||
auto nozzle_diameter = float(object->print()->config().nozzle_diameter.get_at(layerm.region().extruder(extrusion_role) - 1));
|
auto nozzle_diameter = float(nozzle_diameter_for_filament(object->print()->config(), layerm.region().extruder(extrusion_role), object->print()->is_BBL_printer()));
|
||||||
Flow skin_flow = params.bridge ? params.flow : Flow::new_from_config_width(extrusion_role, region_config.skin_infill_line_width, nozzle_diameter, float((surface.thickness == -1) ? layer.height : surface.thickness));
|
Flow skin_flow = params.bridge ? params.flow : Flow::new_from_config_width(extrusion_role, region_config.skin_infill_line_width, nozzle_diameter, float((surface.thickness == -1) ? layer.height : surface.thickness));
|
||||||
//add skin flow
|
//add skin flow
|
||||||
append_flow_param(lock_param.skin_flow_params, skin_flow, surface.expolygon);
|
append_flow_param(lock_param.skin_flow_params, skin_flow, surface.expolygon);
|
||||||
@@ -1271,29 +1274,28 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
|
|||||||
|
|
||||||
// Orca: Anchors and printed infill must share the same body origin. Keep the choice
|
// Orca: Anchors and printed infill must share the same body origin. Keep the choice
|
||||||
// here so per-model surface centering and separated sparse infill cannot drift apart.
|
// here so per-model surface centering and separated sparse infill cannot drift apart.
|
||||||
static BoundingBox infill_bounding_box(const Layer &layer, const SurfaceFill &fill, const ExPolygon &expoly, BoundingBox bbox)
|
// Returns the connected body the fill region is laid out on, or -1 to keep the object's origin.
|
||||||
|
static int infill_body(const Layer &layer, const SurfaceFill &fill, const ExPolygon &expoly)
|
||||||
{
|
{
|
||||||
const auto ¶ms = fill.params;
|
const auto ¶ms = fill.params;
|
||||||
const auto &config = layer.regions()[fill.region_id]->region().config();
|
const bool per_model = (params.extrusion_role == erTopSolidInfill || params.extrusion_role == erBottomSurface) &&
|
||||||
const bool external = params.extrusion_role == erTopSolidInfill || params.extrusion_role == erBottomSurface;
|
params.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model &&
|
||||||
const bool per_model = external && params.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model &&
|
|
||||||
(params.pattern == ipArchimedeanChords || params.pattern == ipOctagramSpiral);
|
(params.pattern == ipArchimedeanChords || params.pattern == ipOctagramSpiral);
|
||||||
const bool separate = !external && params.separated_infills &&
|
int body = -1;
|
||||||
(is_separable_infill_pattern(params.pattern) || !config.solid_infill_rotate_template.value.empty() ||
|
if (per_model || params.separated_infills || is_octree_infill_pattern(params.pattern)) {
|
||||||
!config.sparse_infill_rotate_template.value.empty());
|
const BoundingBox box = get_extents(expoly);
|
||||||
if (per_model || separate) {
|
double best_overlap = 0.;
|
||||||
double best_overlap = 0.;
|
for (size_t i = 0; i < layer.lslices.size() && i < layer.lslices_separated_component_ids.size(); ++i) {
|
||||||
for (size_t i = 0; i < layer.lslices.size() && i < layer.lslices_separated_component_bboxes.size(); ++i) {
|
if (! layer.lslices_bboxes[i].overlap(box))
|
||||||
|
continue;
|
||||||
const double overlap = area(intersection_ex(layer.lslices[i], expoly));
|
const double overlap = area(intersection_ex(layer.lslices[i], expoly));
|
||||||
if (overlap > best_overlap) {
|
if (overlap > best_overlap) {
|
||||||
best_overlap = overlap;
|
best_overlap = overlap;
|
||||||
const Point center = layer.lslices_separated_component_bboxes[i].center();
|
body = int(layer.lslices_separated_component_ids[i]);
|
||||||
bbox = layer.object()->bounding_box();
|
|
||||||
bbox.translate(center.x(), center.y());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bbox;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
@@ -1318,7 +1320,7 @@ void export_group_fills_to_svg(const char *path, const std::vector<SurfaceFill>
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// friend to Layer
|
// friend to Layer
|
||||||
void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator)
|
void Layer::make_fills(const FillAdaptive::Octrees* adaptive_fill_octrees, const FillAdaptive::Octrees* support_fill_octrees, FillLightning::Generator* lightning_generator)
|
||||||
{
|
{
|
||||||
for (LayerRegion *layerm : m_regions)
|
for (LayerRegion *layerm : m_regions)
|
||||||
layerm->fills.clear();
|
layerm->fills.clear();
|
||||||
@@ -1351,7 +1353,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
f->z = this->print_z;
|
f->z = this->print_z;
|
||||||
f->angle = surface_fill.params.angle;
|
f->angle = surface_fill.params.angle;
|
||||||
f->fixed_angle = surface_fill.params.fixed_angle;
|
f->fixed_angle = surface_fill.params.fixed_angle;
|
||||||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
const FillAdaptive::Octrees *octrees = surface_fill.params.pattern == ipSupportCubic ? support_fill_octrees : adaptive_fill_octrees;
|
||||||
f->print_config = &this->object()->print()->config();
|
f->print_config = &this->object()->print()->config();
|
||||||
f->print_object_config = &this->object()->config();
|
f->print_object_config = &this->object()->config();
|
||||||
if (surface_fill.params.pattern == ipConcentricInternal) {
|
if (surface_fill.params.pattern == ipConcentricInternal) {
|
||||||
@@ -1443,8 +1445,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
params.can_reverse = false;
|
params.can_reverse = false;
|
||||||
for (ExPolygon& expoly : surface_fill.expolygons) {
|
for (ExPolygon& expoly : surface_fill.expolygons) {
|
||||||
|
|
||||||
// Orca: Reuse the body origin used for bridge anchoring, resetting it for each surface.
|
// Orca: Reuse the body box and octree used for bridge anchoring, resetting them for each surface.
|
||||||
f->set_bounding_box(infill_bounding_box(*this, surface_fill, expoly, bbox));
|
const int body = infill_body(*this, surface_fill, expoly);
|
||||||
|
f->set_bounding_box(body >= 0 ? this->object()->separated_body_bboxes()[body] : bbox);
|
||||||
|
f->adapt_fill_octree = octrees ? octrees->get(body) : nullptr;
|
||||||
|
|
||||||
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
||||||
if (params.symmetric_infill_y_axis) {
|
if (params.symmetric_infill_y_axis) {
|
||||||
@@ -1512,7 +1516,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
* - For lightning/adaptive patterns, the respective generators are wired so their
|
* - For lightning/adaptive patterns, the respective generators are wired so their
|
||||||
* polylines match the final infill layout.
|
* polylines match the final infill layout.
|
||||||
*/
|
*/
|
||||||
Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) const
|
Polylines Layer::generate_sparse_infill_polylines_for_anchoring(const FillAdaptive::Octrees* adaptive_fill_octrees, const FillAdaptive::Octrees* support_fill_octrees, FillLightning::Generator* lightning_generator) const
|
||||||
{
|
{
|
||||||
LockRegionParam skin_inner_param;
|
LockRegionParam skin_inner_param;
|
||||||
std::vector<SurfaceFill> surface_fills = group_fills(*this, skin_inner_param);
|
std::vector<SurfaceFill> surface_fills = group_fills(*this, skin_inner_param);
|
||||||
@@ -1570,7 +1574,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
|||||||
f->z = this->print_z;
|
f->z = this->print_z;
|
||||||
f->angle = surface_fill.params.angle;
|
f->angle = surface_fill.params.angle;
|
||||||
f->fixed_angle = surface_fill.params.fixed_angle;
|
f->fixed_angle = surface_fill.params.fixed_angle;
|
||||||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
const FillAdaptive::Octrees *octrees = surface_fill.params.pattern == ipSupportCubic ? support_fill_octrees : adaptive_fill_octrees;
|
||||||
f->print_config = &this->object()->print()->config();
|
f->print_config = &this->object()->print()->config();
|
||||||
f->print_object_config = &this->object()->config();
|
f->print_object_config = &this->object()->config();
|
||||||
|
|
||||||
@@ -1617,8 +1621,10 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
|||||||
params.extrusion_role = surface_fill.params.extrusion_role;
|
params.extrusion_role = surface_fill.params.extrusion_role;
|
||||||
|
|
||||||
for (ExPolygon &expoly : surface_fill.expolygons) {
|
for (ExPolygon &expoly : surface_fill.expolygons) {
|
||||||
// Orca: Match the per-body origin of make_fills() before generating physical anchors.
|
// Orca: Match the per-body box and octree of make_fills() before generating physical anchors.
|
||||||
f->set_bounding_box(infill_bounding_box(*this, surface_fill, expoly, bbox));
|
const int body = infill_body(*this, surface_fill, expoly);
|
||||||
|
f->set_bounding_box(body >= 0 ? this->object()->separated_body_bboxes()[body] : bbox);
|
||||||
|
f->adapt_fill_octree = octrees ? octrees->get(body) : nullptr;
|
||||||
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
||||||
f->spacing = surface_fill.params.spacing;
|
f->spacing = surface_fill.params.spacing;
|
||||||
surface_fill.surface.expolygon = std::move(expoly);
|
surface_fill.surface.expolygon = std::move(expoly);
|
||||||
@@ -1788,7 +1794,7 @@ void Layer::make_ironing()
|
|||||||
|
|
||||||
// Create the ironing extrusions for regions <i, j)
|
// Create the ironing extrusions for regions <i, j)
|
||||||
ExPolygons ironing_areas;
|
ExPolygons ironing_areas;
|
||||||
double nozzle_dmr = this->object()->print()->config().nozzle_diameter.get_at(ironing_params.extruder - 1);
|
double nozzle_dmr = nozzle_diameter_for_filament(this->object()->print()->config(), ironing_params.extruder, this->object()->print()->is_BBL_printer());
|
||||||
if (ironing_params.just_infill) {
|
if (ironing_params.just_infill) {
|
||||||
//TODO just_infill is currently not used.
|
//TODO just_infill is currently not used.
|
||||||
// Just infill.
|
// Just infill.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public:
|
|||||||
// pattern is placed on top of previous layers
|
// pattern is placed on top of previous layers
|
||||||
bool use_bridge_flow() const override { return false; }
|
bool use_bridge_flow() const override { return false; }
|
||||||
bool is_self_crossing() override { return false; }
|
bool is_self_crossing() override { return false; }
|
||||||
|
bool aligned_to_origin() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _fill_surface_single(
|
void _fill_surface_single(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "libslic3r/BoundingBox.hpp"
|
#include "libslic3r/BoundingBox.hpp"
|
||||||
#include "libslic3r/ExPolygon.hpp"
|
#include "libslic3r/ExPolygon.hpp"
|
||||||
#include "FillBase.hpp"
|
#include "FillBase.hpp"
|
||||||
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <Eigen/Geometry>
|
#include <Eigen/Geometry>
|
||||||
@@ -37,6 +38,27 @@ struct Octree;
|
|||||||
struct OctreeDeleter { void operator()(Octree *p); };
|
struct OctreeDeleter { void operator()(Octree *p); };
|
||||||
using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>;
|
using OctreePtr = std::unique_ptr<Octree, OctreeDeleter>;
|
||||||
|
|
||||||
|
// Orca: One octree per body (see Layer::lslices_separated_component_ids), and one of the whole object
|
||||||
|
// for objects of a single body or with a body that has none of its own.
|
||||||
|
struct Octrees
|
||||||
|
{
|
||||||
|
OctreePtr object;
|
||||||
|
std::vector<OctreePtr> bodies;
|
||||||
|
|
||||||
|
// A body without an octree, or body -1, uses the object's, or any body's when the object has none.
|
||||||
|
Octree *get(int body) const
|
||||||
|
{
|
||||||
|
if (body >= 0 && size_t(body) < bodies.size() && bodies[body])
|
||||||
|
return bodies[body].get();
|
||||||
|
if (object)
|
||||||
|
return object.get();
|
||||||
|
for (const OctreePtr &octree : bodies)
|
||||||
|
if (octree)
|
||||||
|
return octree.get();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Calculate line spacing for
|
// Calculate line spacing for
|
||||||
// 1) adaptive cubic infill
|
// 1) adaptive cubic infill
|
||||||
// 2) adaptive internal support cubic infill
|
// 2) adaptive internal support cubic infill
|
||||||
|
|||||||
@@ -128,6 +128,9 @@ Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms)
|
|||||||
{
|
{
|
||||||
// Perform offset.
|
// Perform offset.
|
||||||
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(scale_(this->overlap - 0.5 * this->spacing)));
|
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(scale_(this->overlap - 0.5 * this->spacing)));
|
||||||
|
// Orca: Separated infills move the box center onto each body; origin-aligned patterns follow it.
|
||||||
|
const Point shift = this->aligned_to_origin() && ! empty(this->bounding_box) ? this->bounding_box.center() : Point::Zero();
|
||||||
|
translate(expp, -shift);
|
||||||
// Create the infills for each of the regions.
|
// Create the infills for each of the regions.
|
||||||
Polylines polylines_out;
|
Polylines polylines_out;
|
||||||
for (size_t i = 0; i < expp.size(); ++ i)
|
for (size_t i = 0; i < expp.size(); ++ i)
|
||||||
@@ -137,6 +140,8 @@ Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms)
|
|||||||
_infill_direction(surface),
|
_infill_direction(surface),
|
||||||
std::move(expp[i]),
|
std::move(expp[i]),
|
||||||
polylines_out);
|
polylines_out);
|
||||||
|
for (Polyline &pl : polylines_out)
|
||||||
|
pl.translate(shift);
|
||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1591,13 +1596,18 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
|||||||
// The extended bounding box of the whole object that covers any rotation of every layer.
|
// The extended bounding box of the whole object that covers any rotation of every layer.
|
||||||
BoundingBox Fill::extended_object_bounding_box() const
|
BoundingBox Fill::extended_object_bounding_box() const
|
||||||
{
|
{
|
||||||
BoundingBox out = bounding_box;
|
// Orca: Extend about the box center, which separated infills move off the origin.
|
||||||
|
const Point c = this->bounding_box.center();
|
||||||
|
BoundingBox out = this->bounding_box;
|
||||||
|
out.translate(-c.x(), -c.y());
|
||||||
out.merge(Point(out.min.y(), out.min.x()));
|
out.merge(Point(out.min.y(), out.min.x()));
|
||||||
out.merge(Point(out.max.y(), out.max.x()));
|
out.merge(Point(out.max.y(), out.max.x()));
|
||||||
|
|
||||||
// The bounding box is scaled by sqrt(2.) to ensure that the bounding box
|
// The bounding box is scaled by sqrt(2.) to ensure that the bounding box
|
||||||
// covers any possible rotations.
|
// covers any possible rotations.
|
||||||
return out.scaled(sqrt(2.));
|
out = out.scaled(sqrt(2.));
|
||||||
|
out.translate(c.x(), c.y());
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fill::connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms)
|
void Fill::connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms)
|
||||||
|
|||||||
@@ -188,6 +188,9 @@ public:
|
|||||||
// Return true if infill has a consistent pattern between layers.
|
// Return true if infill has a consistent pattern between layers.
|
||||||
virtual bool has_consistent_pattern() const { return false; }
|
virtual bool has_consistent_pattern() const { return false; }
|
||||||
|
|
||||||
|
// Orca: Is the pattern laid out from the origin instead of the bounding box center?
|
||||||
|
virtual bool aligned_to_origin() const { return false; }
|
||||||
|
|
||||||
// Perform the fill.
|
// Perform the fill.
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
|
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public:
|
|||||||
Fill *clone() const override { return new FillCrossHatch(*this); };
|
Fill *clone() const override { return new FillCrossHatch(*this); };
|
||||||
~FillCrossHatch() override {}
|
~FillCrossHatch() override {}
|
||||||
bool is_self_crossing() override { return false; }
|
bool is_self_crossing() override { return false; }
|
||||||
|
bool aligned_to_origin() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _fill_surface_single(
|
void _fill_surface_single(
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public:
|
|||||||
// require bridge flow since most of this pattern hangs in air
|
// require bridge flow since most of this pattern hangs in air
|
||||||
bool use_bridge_flow() const override { return false; }
|
bool use_bridge_flow() const override { return false; }
|
||||||
bool is_self_crossing() override { return false; }
|
bool is_self_crossing() override { return false; }
|
||||||
|
bool aligned_to_origin() const override { return true; }
|
||||||
|
|
||||||
// Correction applied to regular infill angle to maximize printing
|
// Correction applied to regular infill angle to maximize printing
|
||||||
// speed in default configuration (degrees)
|
// speed in default configuration (degrees)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class FillHoneycomb : public Fill
|
|||||||
public:
|
public:
|
||||||
~FillHoneycomb() override {}
|
~FillHoneycomb() override {}
|
||||||
bool is_self_crossing() override { return false; }
|
bool is_self_crossing() override { return false; }
|
||||||
|
bool aligned_to_origin() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill* clone() const override { return new FillHoneycomb(*this); };
|
Fill* clone() const override { return new FillHoneycomb(*this); };
|
||||||
|
|||||||
@@ -2750,23 +2750,6 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The extended bounding box of the whole object that covers any rotation of every layer.
|
|
||||||
BoundingBox FillRectilinear::extended_object_bounding_box() const {
|
|
||||||
// Build the extension around the box center. The transpose merge and the sqrt(2.) scaling
|
|
||||||
// (which covers any possible rotation) are both defined about the origin, so a box that is not
|
|
||||||
// origin-centered — e.g. a separated-infill box re-centered on a single assembly part — would be
|
|
||||||
// distorted. Shift to the origin first and back afterwards; for the default origin-centered box
|
|
||||||
// the two translations cancel and this is identical to the original behavior.
|
|
||||||
const Point c = this->bounding_box.center();
|
|
||||||
BoundingBox out = this->bounding_box;
|
|
||||||
out.translate(-c.x(), -c.y());
|
|
||||||
out.merge(Point(out.min.y(), out.min.x()));
|
|
||||||
out.merge(Point(out.max.y(), out.max.x()));
|
|
||||||
out = out.scaled(sqrt(2.));
|
|
||||||
out.translate(c.x(), c.y());
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out)
|
bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out)
|
||||||
{
|
{
|
||||||
// At the end, only the new polylines will be rotated back.
|
// At the end, only the new polylines will be rotated back.
|
||||||
@@ -2801,7 +2784,13 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||||||
// For infill that needs to be consistent between layers (like Zig Zag),
|
// For infill that needs to be consistent between layers (like Zig Zag),
|
||||||
// we use bounding box of whole object to match vertical lines between layers.
|
// we use bounding box of whole object to match vertical lines between layers.
|
||||||
BoundingBox bounding_box_src = poly_with_offset.bounding_box_src();
|
BoundingBox bounding_box_src = poly_with_offset.bounding_box_src();
|
||||||
BoundingBox bounding_box = this->has_consistent_pattern() ? this->extended_object_bounding_box() : bounding_box_src;
|
BoundingBox bounding_box = bounding_box_src;
|
||||||
|
if (this->has_consistent_pattern()) {
|
||||||
|
// Orca: The polygons are rotated about the origin, so follow the box center to where it was rotated.
|
||||||
|
const Point c = this->bounding_box.center();
|
||||||
|
bounding_box = this->extended_object_bounding_box();
|
||||||
|
bounding_box.translate(c.rotated(- rotate_vector.first) - c);
|
||||||
|
}
|
||||||
|
|
||||||
// define flow spacing according to requested density
|
// define flow spacing according to requested density
|
||||||
if (params.full_infill() && !params.dont_adjust) {
|
if (params.full_infill() && !params.dont_adjust) {
|
||||||
|
|||||||
@@ -42,9 +42,6 @@ protected:
|
|||||||
};
|
};
|
||||||
bool fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out);
|
bool fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out);
|
||||||
bool fill_surface_trapezoidal(const Surface *surface, FillParams params, Polylines &polylines_out, int Pattern_type);
|
bool fill_surface_trapezoidal(const Surface *surface, FillParams params, Polylines &polylines_out, int Pattern_type);
|
||||||
|
|
||||||
// The extended bounding box of the whole object that covers any rotation of every layer.
|
|
||||||
BoundingBox extended_object_bounding_box() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillAlignedRectilinear : public FillRectilinear
|
class FillAlignedRectilinear : public FillRectilinear
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
Polylines& polylines_out) override;
|
Polylines& polylines_out) override;
|
||||||
|
|
||||||
bool is_self_crossing() override { return false; }
|
bool is_self_crossing() override { return false; }
|
||||||
|
bool aligned_to_origin() const override { return true; }
|
||||||
|
|
||||||
// Density adjustment to have a good %of weight.
|
// Density adjustment to have a good %of weight.
|
||||||
static constexpr double DensityAdjust = 2.1;
|
static constexpr double DensityAdjust = 2.1;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
Polylines& polylines_out) override;
|
Polylines& polylines_out) override;
|
||||||
|
|
||||||
bool is_self_crossing() override { return false; }
|
bool is_self_crossing() override { return false; }
|
||||||
|
bool aligned_to_origin() const override { return true; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -241,14 +241,14 @@ Flow support_material_flow(const PrintObject *object, float layer_height)
|
|||||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||||
(object->config().support_line_width.value > 0) ? object->config().support_line_width : object->config().line_width,
|
(object->config().support_line_width.value > 0) ? object->config().support_line_width : object->config().line_width,
|
||||||
// if object->config().support_filament == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
// if object->config().support_filament == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
||||||
float(object->print()->config().nozzle_diameter.get_at(object->config().support_filament-1)),
|
float(nozzle_diameter_for_filament(object->print()->config(), object->config().support_filament, object->print()->is_BBL_printer())),
|
||||||
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
|
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
|
||||||
}
|
}
|
||||||
//BBS
|
//BBS
|
||||||
Flow support_transition_flow(const PrintObject* object)
|
Flow support_transition_flow(const PrintObject* object)
|
||||||
{
|
{
|
||||||
//BBS: support transition of tree support is bridge flow
|
//BBS: support transition of tree support is bridge flow
|
||||||
float dmr = float(object->print()->config().nozzle_diameter.get_at(object->config().support_filament - 1));
|
float dmr = float(nozzle_diameter_for_filament(object->print()->config(), object->config().support_filament, object->print()->is_BBL_printer()));
|
||||||
return Flow::bridging_flow(dmr, dmr);
|
return Flow::bridging_flow(dmr, dmr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ Flow support_material_1st_layer_flow(const PrintObject *object, float layer_heig
|
|||||||
frSupportMaterial,
|
frSupportMaterial,
|
||||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||||
(width.value > 0) ? width : object->config().line_width,
|
(width.value > 0) ? width : object->config().line_width,
|
||||||
float(print_config.nozzle_diameter.get_at(object->config().support_filament-1)),
|
float(nozzle_diameter_for_filament(print_config, object->config().support_filament, object->print()->is_BBL_printer())),
|
||||||
(layer_height > 0.f) ? layer_height : float(print_config.initial_layer_print_height.value));
|
(layer_height > 0.f) ? layer_height : float(print_config.initial_layer_print_height.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ Flow support_material_interface_flow(const PrintObject *object, float layer_heig
|
|||||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||||
(object->config().support_line_width > 0) ? object->config().support_line_width : object->config().line_width,
|
(object->config().support_line_width > 0) ? object->config().support_line_width : object->config().line_width,
|
||||||
// if object->config().support_interface_filament == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
// if object->config().support_interface_filament == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
||||||
float(object->print()->config().nozzle_diameter.get_at(object->config().support_interface_filament-1)),
|
float(nozzle_diameter_for_filament(object->print()->config(), object->config().support_interface_filament, object->print()->is_BBL_printer())),
|
||||||
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
|
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
#include "TDataStd_Name.hxx"
|
#include "TDataStd_Name.hxx"
|
||||||
#include "BRepBuilderAPI_Transform.hxx"
|
#include "BRepBuilderAPI_Transform.hxx"
|
||||||
#include "TopExp_Explorer.hxx"
|
#include "TopExp_Explorer.hxx"
|
||||||
#include "TopExp_Explorer.hxx"
|
|
||||||
#include "BRep_Tool.hxx"
|
#include "BRep_Tool.hxx"
|
||||||
#include "BRepTools.hxx"
|
#include "BRepTools.hxx"
|
||||||
#include <IMeshTools_Parameters.hxx>
|
#include <IMeshTools_Parameters.hxx>
|
||||||
|
|||||||
+41
-65
@@ -43,7 +43,6 @@
|
|||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "libslic3r.h"
|
|
||||||
#include "LocalesUtils.hpp"
|
#include "LocalesUtils.hpp"
|
||||||
#include "libslic3r/format.hpp"
|
#include "libslic3r/format.hpp"
|
||||||
#include "Time.hpp"
|
#include "Time.hpp"
|
||||||
@@ -155,14 +154,9 @@ static const float g_purge_volume_one_time = 135.f;
|
|||||||
static const int g_max_flush_count = 4;
|
static const int g_max_flush_count = 4;
|
||||||
static const size_t g_max_label_object = 64;
|
static const size_t g_max_label_object = 64;
|
||||||
|
|
||||||
static bool is_bambu_x2d_printer(const FullPrintConfig &config)
|
|
||||||
{
|
|
||||||
return config.printer_model.value == "Bambu Lab X2D";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multi-nozzle printer predicate: an extruder carries a nozzle cluster (extruder_max_nozzle_count
|
// Multi-nozzle printer predicate: an extruder carries a nozzle cluster (extruder_max_nozzle_count
|
||||||
// entry > 1). Today only H2C profiles trip it, so every existing single- and dual-extruder printer
|
// entry > 1). Today only H2C profiles trip it, so every existing single- and dual-extruder printer
|
||||||
// is excluded and keeps its historic placeholder values.
|
// is excluded and keeps its historic first-filament marker.
|
||||||
static bool is_multi_nozzle_printer(const FullPrintConfig &config)
|
static bool is_multi_nozzle_printer(const FullPrintConfig &config)
|
||||||
{
|
{
|
||||||
return std::any_of(config.extruder_max_nozzle_count.values.begin(),
|
return std::any_of(config.extruder_max_nozzle_count.values.begin(),
|
||||||
@@ -170,33 +164,20 @@ static bool is_multi_nozzle_printer(const FullPrintConfig &config)
|
|||||||
[](int v) { return v > 1; });
|
[](int v) { return v > 1; });
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hotend_id_for_gcode_placeholder(const FullPrintConfig &config, int hotend_id)
|
// current_hotend / next_hotend value. On a BBL printer: the real nozzle id only while the print uses a
|
||||||
|
// dynamic nozzle map (a filament moves between nozzles across layers), else -1. Bambu firmware reads an
|
||||||
|
// explicit hotend index as a request for the Filament Track Switch and rejects the job on a printer
|
||||||
|
// without one. group_result may be null on slicing paths that don't populate it, which resolves to -1.
|
||||||
|
// Any other printer has no firmware hotend selection and gets the filament's extruder index, whatever
|
||||||
|
// its nozzle map, so existing custom G-code keeps its values.
|
||||||
|
static int hotend_id_for_gcode_placeholder(const std::shared_ptr<MultiNozzleUtils::LayeredNozzleGroupResult> &group_result,
|
||||||
|
bool is_bbl_printer, int filament_id, int extruder_id, int layer_id = -1)
|
||||||
{
|
{
|
||||||
return is_bambu_x2d_printer(config) ? -1 : hotend_id;
|
if (!is_bbl_printer)
|
||||||
}
|
return extruder_id;
|
||||||
|
if (group_result && group_result->is_support_dynamic_nozzle_map() && filament_id >= 0)
|
||||||
// current_hotend / next_hotend value. For multi-nozzle printers a dynamic nozzle map yields the real
|
return group_result->get_nozzle_id(filament_id, layer_id);
|
||||||
// nozzle id, a static map yields -1:
|
return -1;
|
||||||
// - multi-nozzle (H2C): dynamic nozzle map -> real nozzle id; static -> -1.
|
|
||||||
// The dynamic branch is dormant today: the selector create() overload that sets the flag has no
|
|
||||||
// callers yet (deferred with the nozzle-assignment pipeline), so H2C currently resolves to -1.
|
|
||||||
// - X2D: keeps its historic -1 (single-nozzle -> falls through to the fallback helper).
|
|
||||||
// - every other (existing single-nozzle) printer: keeps its historic extruder-id value, so
|
|
||||||
// existing g-code stays byte-identical.
|
|
||||||
// group_result may be null on slicing paths that don't populate it -> the dynamic branch is simply
|
|
||||||
// skipped, so we never dereference null.
|
|
||||||
static int hotend_id_for_gcode_placeholder(const FullPrintConfig &config,
|
|
||||||
const std::shared_ptr<MultiNozzleUtils::LayeredNozzleGroupResult> &group_result,
|
|
||||||
int filament_id,
|
|
||||||
int extruder_id,
|
|
||||||
int layer_id = -1)
|
|
||||||
{
|
|
||||||
if (is_multi_nozzle_printer(config)) {
|
|
||||||
if (group_result && group_result->is_support_dynamic_nozzle_map() && filament_id >= 0)
|
|
||||||
return group_result->get_nozzle_id(filament_id, layer_id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return hotend_id_for_gcode_placeholder(config, extruder_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logical nozzle id for the *_nozzle_id placeholders. Null-safe: falls back to the
|
// Logical nozzle id for the *_nozzle_id placeholders. Null-safe: falls back to the
|
||||||
@@ -211,24 +192,20 @@ static int nozzle_id_for_gcode_placeholder(const std::shared_ptr<MultiNozzleUtil
|
|||||||
|
|
||||||
// Init variants: the start-gcode init sites (first_non_support_hotend / initial_no_support_hotend /
|
// Init variants: the start-gcode init sites (first_non_support_hotend / initial_no_support_hotend /
|
||||||
// current_hotend / initial_nozzle_id / filament_start current_nozzle_id) use get_first_nozzle_for_filament
|
// current_hotend / initial_nozzle_id / filament_start current_nozzle_id) use get_first_nozzle_for_filament
|
||||||
// (the nozzle a filament FIRST uses) rather than the layer-based get_nozzle_id. Same hotend-value semantics
|
// (the nozzle a filament FIRST uses) rather than the layer-based get_nozzle_id. Same hotend-value rule
|
||||||
// as hotend_id_for_gcode_placeholder above (multi-nozzle static -> -1; dynamic branch dormant;
|
// as hotend_id_for_gcode_placeholder above; they differ from the layer-based helper only on the dynamic
|
||||||
// existing printers -> extruder id; X2D -> -1); they differ from the layer-based helper only on the dormant
|
// path for a filament first used after layer 0.
|
||||||
// dynamic path for a filament first used after layer 0.
|
static int first_hotend_id_for_gcode_placeholder(const std::shared_ptr<MultiNozzleUtils::LayeredNozzleGroupResult> &group_result,
|
||||||
static int first_hotend_id_for_gcode_placeholder(const FullPrintConfig &config,
|
bool is_bbl_printer, int filament_id, int extruder_id)
|
||||||
const std::shared_ptr<MultiNozzleUtils::LayeredNozzleGroupResult> &group_result,
|
|
||||||
int filament_id,
|
|
||||||
int extruder_id)
|
|
||||||
{
|
{
|
||||||
if (is_multi_nozzle_printer(config)) {
|
if (!is_bbl_printer)
|
||||||
if (group_result && group_result->is_support_dynamic_nozzle_map() && filament_id >= 0) {
|
return extruder_id;
|
||||||
auto nozzle = group_result->get_first_nozzle_for_filament(filament_id);
|
if (group_result && group_result->is_support_dynamic_nozzle_map() && filament_id >= 0) {
|
||||||
if (nozzle)
|
auto nozzle = group_result->get_first_nozzle_for_filament(filament_id);
|
||||||
return nozzle->group_id;
|
if (nozzle)
|
||||||
}
|
return nozzle->group_id;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return hotend_id_for_gcode_placeholder(config, extruder_id);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int first_nozzle_id_for_gcode_placeholder(const std::shared_ptr<MultiNozzleUtils::LayeredNozzleGroupResult> &group_result,
|
static int first_nozzle_id_for_gcode_placeholder(const std::shared_ptr<MultiNozzleUtils::LayeredNozzleGroupResult> &group_result,
|
||||||
@@ -1215,12 +1192,11 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||||||
|
|
||||||
config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
||||||
config.set_key_value("next_extruder", new ConfigOptionInt(new_filament_id));
|
config.set_key_value("next_extruder", new ConfigOptionInt(new_filament_id));
|
||||||
// current_hotend/next_hotend (see hotend_id_for_gcode_placeholder): multi-nozzle H2C -> -1
|
const bool is_bbl_printer = gcodegen.m_print->is_BBL_printer();
|
||||||
// (static; dynamic branch dormant), X2D -> -1, existing printers -> extruder id.
|
|
||||||
config.set_key_value("current_hotend", new ConfigOptionInt(
|
config.set_key_value("current_hotend", new ConfigOptionInt(
|
||||||
hotend_id_for_gcode_placeholder(gcodegen.m_config, group_result, old_filament_id, old_extruder_id, m_layer_idx)));
|
hotend_id_for_gcode_placeholder(group_result, is_bbl_printer, old_filament_id, old_extruder_id, m_layer_idx)));
|
||||||
config.set_key_value("next_hotend", new ConfigOptionInt(
|
config.set_key_value("next_hotend", new ConfigOptionInt(
|
||||||
hotend_id_for_gcode_placeholder(gcodegen.m_config, group_result, new_filament_id, (int) gcodegen.get_extruder_id(new_filament_id), m_layer_idx)));
|
hotend_id_for_gcode_placeholder(group_result, is_bbl_printer, new_filament_id, (int) gcodegen.get_extruder_id(new_filament_id), m_layer_idx)));
|
||||||
config.set_key_value("current_nozzle_id", new ConfigOptionInt(old_nozzle_id));
|
config.set_key_value("current_nozzle_id", new ConfigOptionInt(old_nozzle_id));
|
||||||
config.set_key_value("next_nozzle_id", new ConfigOptionInt(next_nozzle_id));
|
config.set_key_value("next_nozzle_id", new ConfigOptionInt(next_nozzle_id));
|
||||||
config.set_key_value("current_filament_id", new ConfigOptionInt(old_filament_id));
|
config.set_key_value("current_filament_id", new ConfigOptionInt(old_filament_id));
|
||||||
@@ -1499,7 +1475,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||||||
gcodegen.placeholder_parser().set("current_nozzle_id",
|
gcodegen.placeholder_parser().set("current_nozzle_id",
|
||||||
nozzle_id_for_gcode_placeholder(group_result, new_filament_id, new_extruder_id, m_layer_idx));
|
nozzle_id_for_gcode_placeholder(group_result, new_filament_id, new_extruder_id, m_layer_idx));
|
||||||
gcodegen.placeholder_parser().set("current_hotend",
|
gcodegen.placeholder_parser().set("current_hotend",
|
||||||
hotend_id_for_gcode_placeholder(gcodegen.m_config, group_result, new_filament_id, new_extruder_id, m_layer_idx));
|
hotend_id_for_gcode_placeholder(group_result, gcodegen.m_print->is_BBL_printer(), new_filament_id, new_extruder_id, m_layer_idx));
|
||||||
{
|
{
|
||||||
size_t fi = gcodegen.get_filament_config_index(new_filament_id);
|
size_t fi = gcodegen.get_filament_config_index(new_filament_id);
|
||||||
gcodegen.placeholder_parser().set("retraction_distance_when_cut", gcodegen.m_config.retraction_distances_when_cut.get_at(fi));
|
gcodegen.placeholder_parser().set("retraction_distance_when_cut", gcodegen.m_config.retraction_distances_when_cut.get_at(fi));
|
||||||
@@ -3310,20 +3286,19 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
first_non_support_hotends.reserve(first_non_support_filaments.size());
|
first_non_support_hotends.reserve(first_non_support_filaments.size());
|
||||||
for (int filament_id : first_non_support_filaments)
|
for (int filament_id : first_non_support_filaments)
|
||||||
first_non_support_hotends.push_back(filament_id < 0 ? -1 :
|
first_non_support_hotends.push_back(filament_id < 0 ? -1 :
|
||||||
first_hotend_id_for_gcode_placeholder(m_config, group_result, filament_id, (int) get_extruder_id(filament_id)));
|
first_hotend_id_for_gcode_placeholder(group_result, is_bbl_printers, filament_id, (int) get_extruder_id(filament_id)));
|
||||||
|
|
||||||
this->placeholder_parser().set("first_non_support_tools", new ConfigOptionInts(first_non_support_filaments));
|
this->placeholder_parser().set("first_non_support_tools", new ConfigOptionInts(first_non_support_filaments));
|
||||||
this->placeholder_parser().set("first_non_support_filaments", new ConfigOptionInts(first_non_support_filaments));
|
this->placeholder_parser().set("first_non_support_filaments", new ConfigOptionInts(first_non_support_filaments));
|
||||||
this->placeholder_parser().set("first_non_support_hotend", new ConfigOptionInts(first_non_support_hotends));
|
this->placeholder_parser().set("first_non_support_hotend", new ConfigOptionInts(first_non_support_hotends));
|
||||||
this->placeholder_parser().set("initial_no_support_tool", initial_non_support_extruder_id);
|
this->placeholder_parser().set("initial_no_support_tool", initial_non_support_extruder_id);
|
||||||
this->placeholder_parser().set("initial_no_support_extruder", initial_non_support_extruder_id);
|
this->placeholder_parser().set("initial_no_support_extruder", initial_non_support_extruder_id);
|
||||||
// initial_no_support_hotend/current_hotend (see first_hotend_id_for_gcode_placeholder): multi-nozzle
|
|
||||||
// H2C -> -1 (static; dynamic branch dormant), X2D -> -1, existing printers -> extruder id.
|
|
||||||
this->placeholder_parser().set("initial_no_support_hotend",
|
this->placeholder_parser().set("initial_no_support_hotend",
|
||||||
first_hotend_id_for_gcode_placeholder(m_config, group_result, (int) initial_non_support_extruder_id, (int) get_extruder_id(initial_non_support_extruder_id)));
|
first_hotend_id_for_gcode_placeholder(group_result, is_bbl_printers, (int) initial_non_support_extruder_id,
|
||||||
|
(int) get_extruder_id(initial_non_support_extruder_id)));
|
||||||
this->placeholder_parser().set("current_extruder", initial_extruder_id);
|
this->placeholder_parser().set("current_extruder", initial_extruder_id);
|
||||||
this->placeholder_parser().set("current_hotend",
|
this->placeholder_parser().set("current_hotend",
|
||||||
first_hotend_id_for_gcode_placeholder(m_config, group_result, (int) initial_extruder_id, extruder_id));
|
first_hotend_id_for_gcode_placeholder(group_result, is_bbl_printers, (int) initial_extruder_id, extruder_id));
|
||||||
this->placeholder_parser().set("current_filament_id", (int) initial_extruder_id);
|
this->placeholder_parser().set("current_filament_id", (int) initial_extruder_id);
|
||||||
this->placeholder_parser().set("current_extruder_id", extruder_id);
|
this->placeholder_parser().set("current_extruder_id", extruder_id);
|
||||||
this->placeholder_parser().set("current_nozzle_id",
|
this->placeholder_parser().set("current_nozzle_id",
|
||||||
@@ -3832,7 +3807,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
file.writeln(filament_start_gcode);
|
file.writeln(filament_start_gcode);
|
||||||
// Mark the first filament used in print. Multi-nozzle printers (H2C) get ";VT%d H%d" where
|
// Mark the first filament used in print. Multi-nozzle printers (H2C) get ";VT%d H%d" where
|
||||||
// H = dynamic ? nozzle_id : -1; existing single-nozzle printers keep the bare ";VT%d" so their
|
// H = dynamic ? nozzle_id : -1; existing single-nozzle printers keep the bare ";VT%d" so their
|
||||||
// g-code stays byte-identical. (The dynamic branch is dormant, so H2C currently emits H-1.)
|
// g-code stays byte-identical.
|
||||||
if (is_multi_nozzle_printer(m_config)) {
|
if (is_multi_nozzle_printer(m_config)) {
|
||||||
int initial_nozzle_id = -1;
|
int initial_nozzle_id = -1;
|
||||||
if (group_result && group_result->is_support_dynamic_nozzle_map()) {
|
if (group_result && group_result->is_support_dynamic_nozzle_map()) {
|
||||||
@@ -9616,6 +9591,9 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
|||||||
this->placeholder_parser().set("current_extruder_id", new_extruder_id);
|
this->placeholder_parser().set("current_extruder_id", new_extruder_id);
|
||||||
this->placeholder_parser().set("current_nozzle_id",
|
this->placeholder_parser().set("current_nozzle_id",
|
||||||
nozzle_id_for_gcode_placeholder(m_print->get_layered_nozzle_group_result(), (int) new_filament_id, new_extruder_id, m_layer_index));
|
nozzle_id_for_gcode_placeholder(m_print->get_layered_nozzle_group_result(), (int) new_filament_id, new_extruder_id, m_layer_index));
|
||||||
|
this->placeholder_parser().set("current_hotend",
|
||||||
|
hotend_id_for_gcode_placeholder(m_print->get_layered_nozzle_group_result(), m_print->is_BBL_printer(), (int) new_filament_id,
|
||||||
|
new_extruder_id, m_layer_index));
|
||||||
{
|
{
|
||||||
size_t fi = get_filament_config_index(new_filament_id);
|
size_t fi = get_filament_config_index(new_filament_id);
|
||||||
this->placeholder_parser().set("retraction_distance_when_ec", m_config.retraction_distances_when_ec.get_at(fi));
|
this->placeholder_parser().set("retraction_distance_when_ec", m_config.retraction_distances_when_ec.get_at(fi));
|
||||||
@@ -9794,12 +9772,10 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
|||||||
dyn_config.set_key_value("outer_wall_volumetric_speed", new ConfigOptionFloat(outer_wall_volumetric_speed));
|
dyn_config.set_key_value("outer_wall_volumetric_speed", new ConfigOptionFloat(outer_wall_volumetric_speed));
|
||||||
dyn_config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
dyn_config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
||||||
dyn_config.set_key_value("next_extruder", new ConfigOptionInt((int)new_filament_id));
|
dyn_config.set_key_value("next_extruder", new ConfigOptionInt((int)new_filament_id));
|
||||||
// current_hotend/next_hotend (see hotend_id_for_gcode_placeholder): multi-nozzle H2C -> -1
|
|
||||||
// (static; dynamic branch dormant), X2D -> -1, existing printers -> extruder id.
|
|
||||||
dyn_config.set_key_value("current_hotend", new ConfigOptionInt(
|
dyn_config.set_key_value("current_hotend", new ConfigOptionInt(
|
||||||
hotend_id_for_gcode_placeholder(m_config, group_result, old_filament_id, old_extruder_id, m_layer_index)));
|
hotend_id_for_gcode_placeholder(group_result, m_print->is_BBL_printer(), old_filament_id, old_extruder_id, m_layer_index)));
|
||||||
dyn_config.set_key_value("next_hotend", new ConfigOptionInt(
|
dyn_config.set_key_value("next_hotend", new ConfigOptionInt(
|
||||||
hotend_id_for_gcode_placeholder(m_config, group_result, (int) new_filament_id, new_extruder_id, m_layer_index)));
|
hotend_id_for_gcode_placeholder(group_result, m_print->is_BBL_printer(), (int) new_filament_id, new_extruder_id, m_layer_index)));
|
||||||
dyn_config.set_key_value("current_nozzle_id", new ConfigOptionInt(old_nozzle_id));
|
dyn_config.set_key_value("current_nozzle_id", new ConfigOptionInt(old_nozzle_id));
|
||||||
dyn_config.set_key_value("next_nozzle_id", new ConfigOptionInt(next_nozzle_id));
|
dyn_config.set_key_value("next_nozzle_id", new ConfigOptionInt(next_nozzle_id));
|
||||||
dyn_config.set_key_value("current_filament_id", new ConfigOptionInt(old_filament_id));
|
dyn_config.set_key_value("current_filament_id", new ConfigOptionInt(old_filament_id));
|
||||||
@@ -9977,7 +9953,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
|||||||
|
|
||||||
this->placeholder_parser().set("current_extruder", new_filament_id);
|
this->placeholder_parser().set("current_extruder", new_filament_id);
|
||||||
this->placeholder_parser().set("current_hotend",
|
this->placeholder_parser().set("current_hotend",
|
||||||
hotend_id_for_gcode_placeholder(m_config, group_result, (int) new_filament_id, new_extruder_id, m_layer_index));
|
hotend_id_for_gcode_placeholder(group_result, m_print->is_BBL_printer(), (int) new_filament_id, new_extruder_id, m_layer_index));
|
||||||
// Orca: keep the global current-tool identity coherent for later contexts (see append_tcr).
|
// Orca: keep the global current-tool identity coherent for later contexts (see append_tcr).
|
||||||
this->placeholder_parser().set("current_filament_id", (int) new_filament_id);
|
this->placeholder_parser().set("current_filament_id", (int) new_filament_id);
|
||||||
this->placeholder_parser().set("current_extruder_id", new_extruder_id);
|
this->placeholder_parser().set("current_extruder_id", new_extruder_id);
|
||||||
|
|||||||
@@ -148,8 +148,6 @@ struct ConflictComputeResult
|
|||||||
|
|
||||||
using ConflictComputeOpt = std::optional<ConflictComputeResult>;
|
using ConflictComputeOpt = std::optional<ConflictComputeResult>;
|
||||||
|
|
||||||
using ConflictObjName = std::optional<std::pair<std::string, std::string>>;
|
|
||||||
|
|
||||||
struct ConflictChecker
|
struct ConflictChecker
|
||||||
{
|
{
|
||||||
static ConflictResultOpt find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, std::optional<const FakeWipeTower *> wtdptr);
|
static ConflictResultOpt find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs, std::optional<const FakeWipeTower *> wtdptr);
|
||||||
|
|||||||
@@ -27,8 +27,6 @@
|
|||||||
#include "../PrintConfig.hpp"
|
#include "../PrintConfig.hpp"
|
||||||
#include "../Utils.hpp"
|
#include "../Utils.hpp"
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
|
||||||
#include "libslic3r/libslic3r.h"
|
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -22,9 +22,6 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace PreciseSeam {
|
namespace PreciseSeam {
|
||||||
|
|
||||||
// Import EnforcedBlockedSeamPoint from SeamPlacerImpl namespace for convenience
|
|
||||||
using SeamPlacerImpl::EnforcedBlockedSeamPoint;
|
|
||||||
|
|
||||||
// Geometry and its exterior bounds are prepared together, then treated as read-only.
|
// Geometry and its exterior bounds are prepared together, then treated as read-only.
|
||||||
struct ModifierRegion {
|
struct ModifierRegion {
|
||||||
ExPolygon polygon;
|
ExPolygon polygon;
|
||||||
@@ -137,7 +134,7 @@ SegmentExtraction extract_perimeter_segments(const PreparedPerimeter &prepared,
|
|||||||
|
|
||||||
// Result of weak modifier segment processing
|
// Result of weak modifier segment processing
|
||||||
struct WeakModifierSegment {
|
struct WeakModifierSegment {
|
||||||
EnforcedBlockedSeamPoint type; // Enforced/Blocked/Neutral
|
SeamPlacerImpl::EnforcedBlockedSeamPoint type; // Enforced/Blocked/Neutral
|
||||||
Point left_point; // Coordinates of left (first) point of segment
|
Point left_point; // Coordinates of left (first) point of segment
|
||||||
PerimeterPosition left_position; // Position on the source perimeter before insertion/refinement.
|
PerimeterPosition left_position; // Position on the source perimeter before insertion/refinement.
|
||||||
Point right_point; // Coordinates of right (last) point of segment
|
Point right_point; // Coordinates of right (last) point of segment
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ std::string get_error_string(const ThumbnailErrors& errors);
|
|||||||
|
|
||||||
|
|
||||||
typedef std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> GCodeThumbnailDefinitionsList;
|
typedef std::vector<std::pair<GCodeThumbnailsFormat, Vec2d>> GCodeThumbnailDefinitionsList;
|
||||||
using namespace std::literals;
|
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const std::string& thumbnails_string, const std::string_view def_ext = "PNG");
|
||||||
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const std::string& thumbnails_string, const std::string_view def_ext = "PNG"sv);
|
|
||||||
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const ConfigBase &config);
|
std::pair<GCodeThumbnailDefinitionsList, ThumbnailErrors> make_and_check_thumbnail_list(const ConfigBase &config);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,580 +0,0 @@
|
|||||||
#include "GCodeSender.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
#include <istream>
|
|
||||||
#include <string>
|
|
||||||
#include <thread>
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
|
||||||
#include <boost/algorithm/string/trim.hpp>
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__OpenBSD__)
|
|
||||||
#include <termios.h>
|
|
||||||
#endif
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <IOKit/serial/ioss.h>
|
|
||||||
#endif
|
|
||||||
#ifdef __linux__
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include "/usr/include/asm-generic/ioctls.h"
|
|
||||||
|
|
||||||
/* The following definitions are kindly borrowed from:
|
|
||||||
/usr/include/asm-generic/termbits.h
|
|
||||||
Unfortunately we cannot just include that one because
|
|
||||||
it would redefine the "struct termios" already defined
|
|
||||||
the <termios.h> already included by Boost.ASIO. */
|
|
||||||
#define K_NCCS 19
|
|
||||||
struct termios2 {
|
|
||||||
tcflag_t c_iflag;
|
|
||||||
tcflag_t c_oflag;
|
|
||||||
tcflag_t c_cflag;
|
|
||||||
tcflag_t c_lflag;
|
|
||||||
cc_t c_line;
|
|
||||||
cc_t c_cc[K_NCCS];
|
|
||||||
speed_t c_ispeed;
|
|
||||||
speed_t c_ospeed;
|
|
||||||
};
|
|
||||||
#define BOTHER CBAUDEX
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define DEBUG_SERIAL
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <fstream>
|
|
||||||
std::fstream fs;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define KEEP_SENT 20
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
GCodeSender::GCodeSender()
|
|
||||||
: io(), serial(io), can_send(false), sent(0), open(false), error(false),
|
|
||||||
connected(false), queue_paused(false)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
std::srand(std::time(nullptr));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
GCodeSender::~GCodeSender()
|
|
||||||
{
|
|
||||||
this->disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GCodeSender::connect(std::string devname, unsigned int baud_rate)
|
|
||||||
{
|
|
||||||
this->disconnect();
|
|
||||||
|
|
||||||
this->set_error_status(false);
|
|
||||||
try {
|
|
||||||
this->serial.open(devname);
|
|
||||||
|
|
||||||
this->serial.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::odd));
|
|
||||||
this->serial.set_option(boost::asio::serial_port_base::character_size(boost::asio::serial_port_base::character_size(8)));
|
|
||||||
this->serial.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
|
|
||||||
this->serial.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
|
|
||||||
this->set_baud_rate(baud_rate);
|
|
||||||
|
|
||||||
this->serial.close();
|
|
||||||
this->serial.open(devname);
|
|
||||||
this->serial.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
|
|
||||||
|
|
||||||
// set baud rate again because set_option overwrote it
|
|
||||||
this->set_baud_rate(baud_rate);
|
|
||||||
this->open = true;
|
|
||||||
this->reset();
|
|
||||||
} catch (boost::system::system_error &) {
|
|
||||||
this->set_error_status(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a reset firmware expect line numbers to start again from 1
|
|
||||||
this->sent = 0;
|
|
||||||
this->last_sent.clear();
|
|
||||||
|
|
||||||
/* Initialize debugger */
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
fs.open("serial.txt", std::fstream::out | std::fstream::trunc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// this gives some work to the io_service before it is started
|
|
||||||
// (post() runs the supplied function in its thread)
|
|
||||||
this->io.post(boost::bind(&GCodeSender::do_read, this));
|
|
||||||
|
|
||||||
// start reading in the background thread
|
|
||||||
boost::thread t(boost::bind(&boost::asio::io_service::run, &this->io));
|
|
||||||
this->background_thread.swap(t);
|
|
||||||
|
|
||||||
// always send a M105 to check for connection because firmware might be silent on connect
|
|
||||||
//FIXME Vojtech: This is being sent too early, leading to line number synchronization issues,
|
|
||||||
// from which the GCodeSender never recovers.
|
|
||||||
// this->send("M105", true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::set_baud_rate(unsigned int baud_rate)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// This does not support speeds > 115200
|
|
||||||
this->serial.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
|
|
||||||
} catch (boost::system::system_error &) {
|
|
||||||
boost::asio::serial_port::native_handle_type handle = this->serial.native_handle();
|
|
||||||
|
|
||||||
#if __APPLE__
|
|
||||||
termios ios;
|
|
||||||
::tcgetattr(handle, &ios);
|
|
||||||
::cfsetspeed(&ios, baud_rate);
|
|
||||||
speed_t newSpeed = baud_rate;
|
|
||||||
ioctl(handle, IOSSIOSPEED, &newSpeed);
|
|
||||||
::tcsetattr(handle, TCSANOW, &ios);
|
|
||||||
#elif __linux__
|
|
||||||
termios2 ios;
|
|
||||||
if (ioctl(handle, TCGETS2, &ios))
|
|
||||||
printf("Error in TCGETS2: %s\n", strerror(errno));
|
|
||||||
ios.c_ispeed = ios.c_ospeed = baud_rate;
|
|
||||||
ios.c_cflag &= ~CBAUD;
|
|
||||||
ios.c_cflag |= BOTHER | CLOCAL | CREAD;
|
|
||||||
ios.c_cc[VMIN] = 1; // Minimum of characters to read, prevents eof errors when 0 bytes are read
|
|
||||||
ios.c_cc[VTIME] = 1;
|
|
||||||
if (ioctl(handle, TCSETS2, &ios))
|
|
||||||
printf("Error in TCSETS2: %s\n", strerror(errno));
|
|
||||||
|
|
||||||
#elif __OpenBSD__
|
|
||||||
struct termios ios;
|
|
||||||
::tcgetattr(handle, &ios);
|
|
||||||
::cfsetspeed(&ios, baud_rate);
|
|
||||||
if (::tcsetattr(handle, TCSAFLUSH, &ios) != 0)
|
|
||||||
printf("Failed to set baud rate: %s\n", strerror(errno));
|
|
||||||
#else
|
|
||||||
//throw Slic3r::InvalidArgument("OS does not currently support custom bauds");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::disconnect()
|
|
||||||
{
|
|
||||||
if (!this->open) return;
|
|
||||||
this->open = false;
|
|
||||||
this->connected = false;
|
|
||||||
this->io.post(boost::bind(&GCodeSender::do_close, this));
|
|
||||||
this->background_thread.join();
|
|
||||||
this->io.reset();
|
|
||||||
/*
|
|
||||||
if (this->error_status()) {
|
|
||||||
throw(boost::system::system_error(boost::system::error_code(),
|
|
||||||
"Error while closing the device"));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
fs << "DISCONNECTED" << std::endl << std::flush;
|
|
||||||
fs.close();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GCodeSender::is_connected() const
|
|
||||||
{
|
|
||||||
return this->connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GCodeSender::wait_connected(unsigned int timeout) const
|
|
||||||
{
|
|
||||||
using namespace boost::posix_time;
|
|
||||||
ptime t0 = second_clock::local_time() + seconds(timeout);
|
|
||||||
while (!this->connected) {
|
|
||||||
if (second_clock::local_time() > t0) return false;
|
|
||||||
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
GCodeSender::queue_size() const
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
return this->queue.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::pause_queue()
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
this->queue_paused = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::resume_queue()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
this->queue_paused = false;
|
|
||||||
}
|
|
||||||
this->send();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::purge_queue(bool priority)
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
if (priority) {
|
|
||||||
// clear priority queue
|
|
||||||
std::list<std::string> empty;
|
|
||||||
std::swap(this->priqueue, empty);
|
|
||||||
} else {
|
|
||||||
// clear queue
|
|
||||||
std::queue<std::string> empty;
|
|
||||||
std::swap(this->queue, empty);
|
|
||||||
this->queue_paused = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// purge log and return its contents
|
|
||||||
std::vector<std::string>
|
|
||||||
GCodeSender::purge_log()
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
|
||||||
std::vector<std::string> retval;
|
|
||||||
retval.reserve(this->log.size());
|
|
||||||
while (!this->log.empty()) {
|
|
||||||
retval.push_back(this->log.front());
|
|
||||||
this->log.pop();
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
GCodeSender::getT() const
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
|
||||||
return this->T;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
GCodeSender::getB() const
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
|
||||||
return this->B;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::do_close()
|
|
||||||
{
|
|
||||||
this->set_error_status(false);
|
|
||||||
boost::system::error_code ec;
|
|
||||||
this->serial.cancel(ec);
|
|
||||||
if (ec) this->set_error_status(true);
|
|
||||||
this->serial.close(ec);
|
|
||||||
if (ec) this->set_error_status(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::set_error_status(bool e)
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->error_mutex);
|
|
||||||
this->error = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GCodeSender::error_status() const
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->error_mutex);
|
|
||||||
return this->error;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::do_read()
|
|
||||||
{
|
|
||||||
// read one line
|
|
||||||
boost::asio::async_read_until(
|
|
||||||
this->serial,
|
|
||||||
this->read_buffer,
|
|
||||||
'\n',
|
|
||||||
boost::bind(
|
|
||||||
&GCodeSender::on_read,
|
|
||||||
this,
|
|
||||||
boost::asio::placeholders::error,
|
|
||||||
boost::asio::placeholders::bytes_transferred
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::on_read(const boost::system::error_code& error,
|
|
||||||
size_t bytes_transferred)
|
|
||||||
{
|
|
||||||
this->set_error_status(false);
|
|
||||||
if (error) {
|
|
||||||
#ifdef __APPLE__
|
|
||||||
if (error.value() == 45) {
|
|
||||||
// OS X bug: http://osdir.com/ml/lib.boost.asio.user/2008-08/msg00004.html
|
|
||||||
this->do_read();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// printf("ERROR: [%d] %s\n", error.value(), error.message().c_str());
|
|
||||||
// error can be true even because the serial port was closed.
|
|
||||||
// In this case it is not a real error, so ignore.
|
|
||||||
if (this->open) {
|
|
||||||
this->do_close();
|
|
||||||
this->set_error_status(true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream is(&this->read_buffer);
|
|
||||||
std::string line;
|
|
||||||
std::getline(is, line);
|
|
||||||
if (!line.empty()) {
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
fs << "<< " << line << std::endl << std::flush;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// note that line might contain \r at its end
|
|
||||||
// parse incoming line
|
|
||||||
if (!this->connected
|
|
||||||
&& (boost::starts_with(line, "start")
|
|
||||||
|| boost::starts_with(line, "Grbl ")
|
|
||||||
|| boost::starts_with(line, "ok")
|
|
||||||
|| boost::contains(line, "T:"))) {
|
|
||||||
this->connected = true;
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
this->can_send = true;
|
|
||||||
}
|
|
||||||
this->send();
|
|
||||||
} else if (boost::starts_with(line, "ok")) {
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
this->can_send = true;
|
|
||||||
}
|
|
||||||
this->send();
|
|
||||||
} else if (boost::istarts_with(line, "resend") // Marlin uses "Resend: "
|
|
||||||
|| boost::istarts_with(line, "rs")) {
|
|
||||||
// extract the first number from line
|
|
||||||
boost::algorithm::trim_left_if(line, !boost::algorithm::is_digit());
|
|
||||||
size_t toresend = boost::lexical_cast<size_t>(line.substr(0, line.find_first_not_of("0123456789")));
|
|
||||||
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
fs << "!! line num out of sync: toresend = " << toresend << ", sent = " << sent << ", last_sent.size = " << last_sent.size() << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (toresend > this->sent - this->last_sent.size() && toresend <= this->sent) {
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
|
|
||||||
const auto lines_to_resend = this->sent - toresend + 1;
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
fs << "!! resending " << lines_to_resend << " lines" << std::endl;
|
|
||||||
#endif
|
|
||||||
// move the unsent lines to priqueue
|
|
||||||
this->priqueue.insert(
|
|
||||||
this->priqueue.begin(), // insert at the beginning
|
|
||||||
this->last_sent.begin() + this->last_sent.size() - lines_to_resend,
|
|
||||||
this->last_sent.end()
|
|
||||||
);
|
|
||||||
|
|
||||||
// we can empty last_sent because it's not useful anymore
|
|
||||||
this->last_sent.clear();
|
|
||||||
|
|
||||||
// start resending with the requested line number
|
|
||||||
this->sent = toresend - 1;
|
|
||||||
this->can_send = true;
|
|
||||||
}
|
|
||||||
this->send();
|
|
||||||
} else {
|
|
||||||
printf("Cannot resend %zu (oldest we have is %zu)\n", toresend, this->sent - this->last_sent.size());
|
|
||||||
}
|
|
||||||
} else if (boost::starts_with(line, "wait")) {
|
|
||||||
// ignore
|
|
||||||
} else {
|
|
||||||
// push any other line into the log
|
|
||||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
|
||||||
this->log.push(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse temperature info
|
|
||||||
{
|
|
||||||
size_t pos = line.find("T:");
|
|
||||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
|
||||||
// we got temperature info
|
|
||||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
|
||||||
this->T = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
|
||||||
|
|
||||||
pos = line.find("B:");
|
|
||||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
|
||||||
// we got bed temperature info
|
|
||||||
this->B = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->do_read();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::send(const std::vector<std::string> &lines, bool priority)
|
|
||||||
{
|
|
||||||
// append lines to queue
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
for (std::vector<std::string>::const_iterator line = lines.begin(); line != lines.end(); ++line) {
|
|
||||||
if (priority) {
|
|
||||||
this->priqueue.push_back(*line);
|
|
||||||
} else {
|
|
||||||
this->queue.push(*line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->send();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::send(const std::string &line, bool priority)
|
|
||||||
{
|
|
||||||
// append line to queue
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
if (priority) {
|
|
||||||
this->priqueue.push_back(line);
|
|
||||||
} else {
|
|
||||||
this->queue.push(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->send();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::send()
|
|
||||||
{
|
|
||||||
this->io.post(boost::bind(&GCodeSender::do_send, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::do_send()
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
|
||||||
|
|
||||||
// printer is not connected or we're still waiting for the previous ack
|
|
||||||
if (!this->can_send) return;
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
while (!this->priqueue.empty() || (!this->queue.empty() && !this->queue_paused)) {
|
|
||||||
if (!this->priqueue.empty()) {
|
|
||||||
line = this->priqueue.front();
|
|
||||||
this->priqueue.pop_front();
|
|
||||||
} else {
|
|
||||||
line = this->queue.front();
|
|
||||||
this->queue.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// strip comments
|
|
||||||
size_t comment_pos = line.find_first_of(';');
|
|
||||||
if (comment_pos != std::string::npos)
|
|
||||||
line.erase(comment_pos, std::string::npos);
|
|
||||||
boost::algorithm::trim(line);
|
|
||||||
|
|
||||||
// if line is not empty, send it
|
|
||||||
if (!line.empty()) break;
|
|
||||||
// if line is empty, process next item in queue
|
|
||||||
}
|
|
||||||
if (line.empty()) return;
|
|
||||||
|
|
||||||
// compute full line
|
|
||||||
++ this->sent;
|
|
||||||
#ifndef DEBUG_SERIAL
|
|
||||||
const auto line_num = this->sent;
|
|
||||||
#else
|
|
||||||
// In DEBUG_SERIAL mode, test line re-synchronization by sending bad line number 1/4 of the time
|
|
||||||
const auto line_num = std::rand() < RAND_MAX/4 ? 0 : this->sent;
|
|
||||||
#endif
|
|
||||||
std::string full_line = "N" + boost::lexical_cast<std::string>(line_num) + " " + line;
|
|
||||||
|
|
||||||
// calculate checksum
|
|
||||||
int cs = 0;
|
|
||||||
for (std::string::const_iterator it = full_line.begin(); it != full_line.end(); ++it)
|
|
||||||
cs = cs ^ *it;
|
|
||||||
|
|
||||||
// write line to device
|
|
||||||
full_line += "*";
|
|
||||||
full_line += boost::lexical_cast<std::string>(cs);
|
|
||||||
full_line += "\n";
|
|
||||||
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
fs << ">> " << full_line << std::flush;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
this->last_sent.push_back(line);
|
|
||||||
this->can_send = false;
|
|
||||||
|
|
||||||
while (this->last_sent.size() > KEEP_SENT) {
|
|
||||||
this->last_sent.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
// we can't supply boost::asio::buffer(full_line) to async_write() because full_line is on the
|
|
||||||
// stack and the buffer would lose its underlying storage causing memory corruption
|
|
||||||
std::ostream os(&this->write_buffer);
|
|
||||||
os << full_line;
|
|
||||||
boost::asio::async_write(this->serial, this->write_buffer, boost::bind(&GCodeSender::on_write, this, boost::asio::placeholders::error,
|
|
||||||
boost::asio::placeholders::bytes_transferred));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::on_write(const boost::system::error_code& error,
|
|
||||||
size_t bytes_transferred)
|
|
||||||
{
|
|
||||||
this->set_error_status(false);
|
|
||||||
if (error) {
|
|
||||||
if (this->open) {
|
|
||||||
this->do_close();
|
|
||||||
this->set_error_status(true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->do_send();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::set_DTR(bool on)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
|
||||||
boost::asio::serial_port_service::native_handle_type handle = this->serial.native_handle();
|
|
||||||
if (on)
|
|
||||||
EscapeCommFunction(handle, SETDTR);
|
|
||||||
else
|
|
||||||
EscapeCommFunction(handle, CLRDTR);
|
|
||||||
#else
|
|
||||||
int fd = this->serial.native_handle();
|
|
||||||
int status;
|
|
||||||
ioctl(fd, TIOCMGET, &status);
|
|
||||||
if (on)
|
|
||||||
status |= TIOCM_DTR;
|
|
||||||
else
|
|
||||||
status &= ~TIOCM_DTR;
|
|
||||||
ioctl(fd, TIOCMSET, &status);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCodeSender::reset()
|
|
||||||
{
|
|
||||||
set_DTR(false);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
||||||
set_DTR(true);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
||||||
set_DTR(false);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#ifndef slic3r_GCodeSender_hpp_
|
|
||||||
#define slic3r_GCodeSender_hpp_
|
|
||||||
|
|
||||||
#include "libslic3r.h"
|
|
||||||
#include <queue>
|
|
||||||
#include <boost/core/noncopyable.hpp>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <boost/asio/io_service.hpp>
|
|
||||||
#include <boost/asio/serial_port.hpp>
|
|
||||||
#include <boost/asio/streambuf.hpp>
|
|
||||||
#include <list>
|
|
||||||
#include <deque>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/bind/bind.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
|
||||||
|
|
||||||
class GCodeSender : private boost::noncopyable {
|
|
||||||
public:
|
|
||||||
GCodeSender();
|
|
||||||
~GCodeSender();
|
|
||||||
bool connect(std::string devname, unsigned int baud_rate);
|
|
||||||
void send(const std::vector<std::string> &lines, bool priority = false);
|
|
||||||
void send(const std::string &s, bool priority = false);
|
|
||||||
void disconnect();
|
|
||||||
bool error_status() const;
|
|
||||||
bool is_connected() const;
|
|
||||||
bool wait_connected(unsigned int timeout = 3) const;
|
|
||||||
size_t queue_size() const;
|
|
||||||
void pause_queue();
|
|
||||||
void resume_queue();
|
|
||||||
void purge_queue(bool priority = false);
|
|
||||||
std::vector<std::string> purge_log();
|
|
||||||
std::string getT() const;
|
|
||||||
std::string getB() const;
|
|
||||||
void set_DTR(bool on);
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
asio::io_service io;
|
|
||||||
asio::serial_port serial;
|
|
||||||
boost::thread background_thread;
|
|
||||||
boost::asio::streambuf read_buffer, write_buffer;
|
|
||||||
bool open; // whether the serial socket is connected
|
|
||||||
bool connected; // whether the printer is online
|
|
||||||
bool error;
|
|
||||||
mutable boost::mutex error_mutex;
|
|
||||||
|
|
||||||
// this mutex guards queue, priqueue, can_send, queue_paused, sent, last_sent
|
|
||||||
mutable boost::mutex queue_mutex;
|
|
||||||
std::queue<std::string> queue;
|
|
||||||
std::list<std::string> priqueue;
|
|
||||||
bool can_send;
|
|
||||||
bool queue_paused;
|
|
||||||
size_t sent;
|
|
||||||
std::deque<std::string> last_sent;
|
|
||||||
|
|
||||||
// this mutex guards log, T, B
|
|
||||||
mutable boost::mutex log_mutex;
|
|
||||||
std::queue<std::string> log;
|
|
||||||
std::string T, B;
|
|
||||||
|
|
||||||
void set_baud_rate(unsigned int baud_rate);
|
|
||||||
void set_error_status(bool e);
|
|
||||||
void do_send();
|
|
||||||
void on_write(const boost::system::error_code& error, size_t bytes_transferred);
|
|
||||||
void do_close();
|
|
||||||
void do_read();
|
|
||||||
void on_read(const boost::system::error_code& error, size_t bytes_transferred);
|
|
||||||
void send();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
|
||||||
|
|
||||||
#endif /* slic3r_GCodeSender_hpp_ */
|
|
||||||
@@ -94,8 +94,6 @@ struct Circle {
|
|||||||
|
|
||||||
using Circlef = Circle<Vec2f>;
|
using Circlef = Circle<Vec2f>;
|
||||||
using Circled = Circle<Vec2d>;
|
using Circled = Circle<Vec2d>;
|
||||||
using CircleSqf = CircleSq<Vec2f>;
|
|
||||||
using CircleSqd = CircleSq<Vec2d>;
|
|
||||||
|
|
||||||
/// Find the center of the circle corresponding to the vector of Points as an arc.
|
/// Find the center of the circle corresponding to the vector of Points as an arc.
|
||||||
Point circle_center_taubin_newton(const Points::const_iterator& input_start, const Points::const_iterator& input_end, size_t cycles = 20);
|
Point circle_center_taubin_newton(const Points::const_iterator& input_start, const Points::const_iterator& input_end, size_t cycles = 20);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include "MedialAxis.hpp"
|
#include "MedialAxis.hpp"
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
|
||||||
#include <boost/polygon/polygon.hpp>
|
#include <boost/polygon/polygon.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class PrintObject;
|
|||||||
class Print;
|
class Print;
|
||||||
|
|
||||||
namespace FillAdaptive {
|
namespace FillAdaptive {
|
||||||
struct Octree;
|
struct Octrees;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace FillLightning {
|
namespace FillLightning {
|
||||||
@@ -170,10 +170,10 @@ public:
|
|||||||
ExPolygons lslices;
|
ExPolygons lslices;
|
||||||
ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support
|
ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support
|
||||||
std::vector<BoundingBox> lslices_bboxes;
|
std::vector<BoundingBox> lslices_bboxes;
|
||||||
// Orca: for separated infills / per-model centering. Aligned with lslices: for each island, the
|
// Orca: for separated infills / per-model centering / octree infills. Aligned with lslices: for each
|
||||||
// full bounding box of the 3D connected body (across all layers) it belongs to. Populated by
|
// island, the 3D connected body (across all layers) it belongs to, indexing
|
||||||
// PrintObject::infill() only when the feature is used; empty otherwise.
|
// PrintObject::separated_body_bboxes(). Populated by PrintObject::prepare_infill() only when needed.
|
||||||
std::vector<BoundingBox> lslices_separated_component_bboxes;
|
std::vector<size_t> lslices_separated_component_ids;
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
ExPolygons loverhangs;
|
ExPolygons loverhangs;
|
||||||
@@ -208,9 +208,9 @@ public:
|
|||||||
void make_perimeters();
|
void make_perimeters();
|
||||||
// Phony version of make_fills() without parameters for Perl integration only.
|
// Phony version of make_fills() without parameters for Perl integration only.
|
||||||
void make_fills() { this->make_fills(nullptr, nullptr); }
|
void make_fills() { this->make_fills(nullptr, nullptr); }
|
||||||
void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator = nullptr);
|
void make_fills(const FillAdaptive::Octrees* adaptive_fill_octrees, const FillAdaptive::Octrees* support_fill_octrees, FillLightning::Generator* lightning_generator = nullptr);
|
||||||
Polylines generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree *adaptive_fill_octree,
|
Polylines generate_sparse_infill_polylines_for_anchoring(const FillAdaptive::Octrees *adaptive_fill_octrees,
|
||||||
FillAdaptive::Octree *support_fill_octree,
|
const FillAdaptive::Octrees *support_fill_octrees,
|
||||||
FillLightning::Generator* lightning_generator) const;
|
FillLightning::Generator* lightning_generator) const;
|
||||||
void make_ironing();
|
void make_ironing();
|
||||||
// Returns the filament id (1-based) the region is ironed with, or -1 when the
|
// Returns the filament id (1-based) the region is ironed with, or -1 when the
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge) const
|
|||||||
const PrintObject &print_object = *this->layer()->object();
|
const PrintObject &print_object = *this->layer()->object();
|
||||||
Flow bridge_flow;
|
Flow bridge_flow;
|
||||||
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will fall back to zero'th element, so everything is all right.
|
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will fall back to zero'th element, so everything is all right.
|
||||||
auto nozzle_diameter = float(print_object.print()->config().nozzle_diameter.get_at(region.extruder(role) - 1));
|
auto nozzle_diameter = float(nozzle_diameter_for_filament(print_object.print()->config(), region.extruder(role), print_object.print()->is_BBL_printer()));
|
||||||
const ConfigOptionFloatOrPercent& bridge_width_opt = region_config.bridge_line_width;
|
const ConfigOptionFloatOrPercent& bridge_width_opt = region_config.bridge_line_width;
|
||||||
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
|
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
|
||||||
const bool has_bridge_width = bridge_width > 0.;
|
const bool has_bridge_width = bridge_width > 0.;
|
||||||
|
|||||||
@@ -154,13 +154,12 @@ template<class ExecutionPolicy, class Enable = void> struct _Loop
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add Specialization for using ExecutionTBB for parallel loops.
|
// Add Specialization for using ExecutionTBB for parallel loops.
|
||||||
using namespace Slic3r;
|
template<> struct _Loop<Slic3r::ExecutionTBB>
|
||||||
template<> struct _Loop<ExecutionTBB>
|
|
||||||
{
|
{
|
||||||
template<class It, class Fn> static void for_each_idx(It from, It to, Fn&& fn)
|
template<class It, class Fn> static void for_each_idx(It from, It to, Fn&& fn)
|
||||||
{
|
{
|
||||||
execution::for_each(
|
Slic3r::execution::for_each(
|
||||||
ex_tbb, size_t(0), size_t(to - from), [&from, &fn](size_t i) { fn(from[i], i); }, execution::max_concurrency(ex_tbb));
|
Slic3r::ex_tbb, size_t(0), size_t(to - from), [&from, &fn](size_t i) { fn(from[i], i); }, Slic3r::execution::max_concurrency(Slic3r::ex_tbb));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include "Format/AssimpImport.hpp"
|
#include "Format/AssimpImport.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "Exception.hpp"
|
#include "Exception.hpp"
|
||||||
#include "Model.hpp"
|
|
||||||
#include "ModelArrange.hpp"
|
#include "ModelArrange.hpp"
|
||||||
#include "Arrange.hpp"
|
#include "Arrange.hpp"
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
@@ -1697,6 +1696,9 @@ indexed_triangle_set ModelObject::raw_indexed_triangle_set() const
|
|||||||
size_t j = out.indices.size();
|
size_t j = out.indices.size();
|
||||||
append(out.vertices, v->mesh().its.vertices);
|
append(out.vertices, v->mesh().its.vertices);
|
||||||
append(out.indices, v->mesh().its.indices);
|
append(out.indices, v->mesh().its.indices);
|
||||||
|
// Orca: Point the volume's triangles at its own vertices, which follow those of the volumes before it.
|
||||||
|
for (size_t k = j; k < out.indices.size(); ++ k)
|
||||||
|
out.indices[k] += stl_triangle_vertex_indices::Constant(int(i));
|
||||||
const Transform3d& m = v->get_matrix();
|
const Transform3d& m = v->get_matrix();
|
||||||
for (; i < out.vertices.size(); ++ i)
|
for (; i < out.vertices.size(); ++ i)
|
||||||
out.vertices[i] = (m * out.vertices[i].cast<double>()).cast<float>().eval();
|
out.vertices[i] = (m * out.vertices[i].cast<double>()).cast<float>().eval();
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "TriangleMesh.hpp"
|
#include "TriangleMesh.hpp"
|
||||||
#include "CustomGCode.hpp"
|
#include "CustomGCode.hpp"
|
||||||
#include "calib.hpp"
|
#include "calib.hpp"
|
||||||
#include "enum_bitmask.hpp"
|
|
||||||
#include "TextConfiguration.hpp"
|
#include "TextConfiguration.hpp"
|
||||||
#include "EmbossShape.hpp"
|
#include "EmbossShape.hpp"
|
||||||
#include "TriangleSelector.hpp"
|
#include "TriangleSelector.hpp"
|
||||||
|
|||||||
@@ -3593,24 +3593,6 @@ void PresetBundle::export_selections(AppConfig &config)
|
|||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": printer %1%, print %2%, filaments[0] %3% ")%printers.get_selected_preset_name() % prints.get_selected_preset_name() %filament_presets[0];
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": printer %1%, print %2%, filaments[0] %3% ")%printers.get_selected_preset_name() % prints.get_selected_preset_name() %filament_presets[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preserve metadata only for existing colour slots; new slots get false/empty defaults.
|
|
||||||
static void resize_mixed_filament_metadata(DynamicPrintConfig &config, size_t old_slot_count, size_t new_slot_count)
|
|
||||||
{
|
|
||||||
auto resize = [old_slot_count, new_slot_count](auto *opt) {
|
|
||||||
if (opt) {
|
|
||||||
opt->values.resize(std::min(old_slot_count, opt->values.size()));
|
|
||||||
opt->values.resize(new_slot_count);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
resize(config.option<ConfigOptionBools>("filament_is_mixed"));
|
|
||||||
resize(config.option<ConfigOptionStrings>("filament_mixed_components"));
|
|
||||||
resize(config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios"));
|
|
||||||
resize(config.option<ConfigOptionBools>("filament_mixed_gradient"));
|
|
||||||
resize(config.option<ConfigOptionStrings>("filament_mixed_gradient_range"));
|
|
||||||
resize(config.option<ConfigOptionStrings>("filament_mixed_gradient_curve"));
|
|
||||||
resize(config.option<ConfigOptionBools>("filament_mixed_gradient_per_part"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
||||||
{
|
{
|
||||||
unsigned old_filament_count = this->filament_presets.size();
|
unsigned old_filament_count = this->filament_presets.size();
|
||||||
|
|||||||
@@ -2229,7 +2229,7 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
|
|||||||
for (const PrintRegion ®ion : object->all_regions()) {
|
for (const PrintRegion ®ion : object->all_regions()) {
|
||||||
const auto &bridge_width_opt = region.config().bridge_line_width;
|
const auto &bridge_width_opt = region.config().bridge_line_width;
|
||||||
for (FlowRole bridge_role : { frPerimeter, frInfill, frSolidInfill, frTopSolidInfill }) {
|
for (FlowRole bridge_role : { frPerimeter, frInfill, frSolidInfill, frTopSolidInfill }) {
|
||||||
const double nozzle_diameter = m_config.nozzle_diameter.get_at(region.extruder(bridge_role) - 1);
|
const double nozzle_diameter = nozzle_diameter_for_filament(m_config, region.extruder(bridge_role), this->is_BBL_printer());
|
||||||
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
|
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
|
||||||
if (bridge_width <= 0.)
|
if (bridge_width <= 0.)
|
||||||
continue;
|
continue;
|
||||||
@@ -2606,7 +2606,7 @@ Flow Print::brim_flow() const
|
|||||||
frPerimeter,
|
frPerimeter,
|
||||||
// Flow::new_from_config_width takes care of the percent to value substitution
|
// Flow::new_from_config_width takes care of the percent to value substitution
|
||||||
width,
|
width,
|
||||||
(float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().outer_wall_filament_id-1),
|
(float)nozzle_diameter_for_filament(m_config, m_print_regions.front()->config().outer_wall_filament_id, this->is_BBL_printer()),
|
||||||
(float)this->skirt_first_layer_height());
|
(float)this->skirt_first_layer_height());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2623,12 +2623,13 @@ Flow Print::skirt_flow() const
|
|||||||
extruders and take the one with, say, the smallest index;
|
extruders and take the one with, say, the smallest index;
|
||||||
The same logic should be applied to the code that selects the extruder during G-code
|
The same logic should be applied to the code that selects the extruder during G-code
|
||||||
generation as well. */
|
generation as well. */
|
||||||
return Flow::new_from_config_width(frPerimeter,
|
return Flow::new_from_config_width(
|
||||||
// Flow::new_from_config_width takes care of the percent to value substitution
|
frPerimeter,
|
||||||
width,
|
// Flow::new_from_config_width takes care of the percent to value substitution
|
||||||
(float) m_config.nozzle_diameter.get_at(
|
width,
|
||||||
m_objects.empty() ? 0 : m_objects.front()->config().support_filament - 1),
|
// ORCA: resolve the actual nozzle the support filament is printed with (dual-nozzle printers).
|
||||||
(float) this->skirt_first_layer_height());
|
(float)nozzle_diameter_for_filament(m_config, m_objects.empty() ? 0 : m_objects.front()->config().support_filament, this->is_BBL_printer()),
|
||||||
|
(float)this->skirt_first_layer_height());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Print::has_support_material() const
|
bool Print::has_support_material() const
|
||||||
|
|||||||
@@ -375,6 +375,8 @@ public:
|
|||||||
Transform3d trafo_centered() const
|
Transform3d trafo_centered() const
|
||||||
{ Transform3d t = this->trafo(); t.pretranslate(Vec3d(- unscale<double>(m_center_offset.x()), - unscale<double>(m_center_offset.y()), 0)); return t; }
|
{ Transform3d t = this->trafo(); t.pretranslate(Vec3d(- unscale<double>(m_center_offset.x()), - unscale<double>(m_center_offset.y()), 0)); return t; }
|
||||||
const PrintInstances& instances() const { return m_instances; }
|
const PrintInstances& instances() const { return m_instances; }
|
||||||
|
// Orca: Bounding box of each connected body, indexed by Layer::lslices_separated_component_ids.
|
||||||
|
const std::vector<BoundingBox>& separated_body_bboxes() const { return m_separated_body_bboxes; }
|
||||||
PrintInstances &instances() { return m_instances; }
|
PrintInstances &instances() { return m_instances; }
|
||||||
|
|
||||||
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
|
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
|
||||||
@@ -581,8 +583,8 @@ private:
|
|||||||
void discover_horizontal_shells();
|
void discover_horizontal_shells();
|
||||||
void combine_infill();
|
void combine_infill();
|
||||||
void _generate_support_material();
|
void _generate_support_material();
|
||||||
std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> prepare_adaptive_infill_data(
|
std::pair<FillAdaptive::Octrees, FillAdaptive::Octrees> prepare_adaptive_infill_data(
|
||||||
const std::vector<std::pair<const Surface*, float>>& surfaces_w_bottom_z) const;
|
const std::vector<std::pair<const Surface*, const Layer*>>& surfaces_w_layer) const;
|
||||||
FillLightning::GeneratorPtr prepare_lightning_infill_data();
|
FillLightning::GeneratorPtr prepare_lightning_infill_data();
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
@@ -614,7 +616,8 @@ private:
|
|||||||
// so that next call to make_perimeters() performs a union() before computing loops
|
// so that next call to make_perimeters() performs a union() before computing loops
|
||||||
bool m_typed_slices = false;
|
bool m_typed_slices = false;
|
||||||
|
|
||||||
std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> m_adaptive_fill_octrees;
|
std::pair<FillAdaptive::Octrees, FillAdaptive::Octrees> m_adaptive_fill_octrees;
|
||||||
|
std::vector<BoundingBox> m_separated_body_bboxes;
|
||||||
FillLightning::GeneratorPtr m_lightning_generator;
|
FillLightning::GeneratorPtr m_lightning_generator;
|
||||||
|
|
||||||
std::vector < VolumeSlices > firstLayerObjSliceByVolume;
|
std::vector < VolumeSlices > firstLayerObjSliceByVolume;
|
||||||
|
|||||||
@@ -133,6 +133,15 @@ size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double nozzle_diameter_for_filament(const PrintConfig& config, int filament_id, bool is_bbl_printer)
|
||||||
|
{
|
||||||
|
int extruder = filament_id;
|
||||||
|
if (is_bbl_printer && config.nozzle_diameter.size() > 1 &&
|
||||||
|
filament_id >= 1 && static_cast<size_t>(filament_id - 1) < config.filament_map.size())
|
||||||
|
extruder = config.filament_map.get_at(filament_id - 1);
|
||||||
|
return config.nozzle_diameter.get_at(extruder - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Orca: input shaping values types by flavor
|
// Orca: input shaping values types by flavor
|
||||||
std::vector<std::string> get_shaper_type_values_for_flavor(GCodeFlavor flavor)
|
std::vector<std::string> get_shaper_type_values_for_flavor(GCodeFlavor flavor)
|
||||||
@@ -7602,8 +7611,8 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts "
|
"whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts "
|
||||||
"(or distinct 3D objects) each get their own.\n"
|
"(or distinct 3D objects) each get their own.\n"
|
||||||
"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n"
|
"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n"
|
||||||
"Affects line and grid patterns and rotation-template infills.\n"
|
"Adaptive Cubic and Support Cubic always center each part on itself, and Lightning infill is generated for "
|
||||||
"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected.");
|
"the whole object and is unaffected.");
|
||||||
def->mode = comExpert;
|
def->mode = comExpert;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
@@ -10845,6 +10854,21 @@ void set_filament_dev_options(DynamicPrintConfig &config, const std::vector<cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resize_mixed_filament_metadata(DynamicPrintConfig &config, size_t old_slot_count, size_t new_slot_count)
|
||||||
|
{
|
||||||
|
auto resize = [old_slot_count, new_slot_count](auto *opt) {
|
||||||
|
opt->values.resize(std::min(old_slot_count, opt->values.size()));
|
||||||
|
opt->values.resize(new_slot_count);
|
||||||
|
};
|
||||||
|
resize(config.option<ConfigOptionBools>("filament_is_mixed", true));
|
||||||
|
resize(config.option<ConfigOptionStrings>("filament_mixed_components", true));
|
||||||
|
resize(config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios", true));
|
||||||
|
resize(config.option<ConfigOptionBools>("filament_mixed_gradient", true));
|
||||||
|
resize(config.option<ConfigOptionStrings>("filament_mixed_gradient_range", true));
|
||||||
|
resize(config.option<ConfigOptionStrings>("filament_mixed_gradient_curve", true));
|
||||||
|
resize(config.option<ConfigOptionBools>("filament_mixed_gradient_per_part", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//used for object/region config
|
//used for object/region config
|
||||||
//use the smallest of multiple to single
|
//use the smallest of multiple to single
|
||||||
@@ -12975,7 +12999,7 @@ CustomGcodeSpecificConfigDef::CustomGcodeSpecificConfigDef()
|
|||||||
// Common Defs
|
// Common Defs
|
||||||
def = this->add("layer_num", coInt);
|
def = this->add("layer_num", coInt);
|
||||||
def->label = L("Layer number");
|
def->label = L("Layer number");
|
||||||
def->tooltip = L("Index of the current layer. One-based (i.e. first layer is number 1).");
|
def->tooltip = L("Index of the current layer. Zero-based (i.e. first layer is number 0), except in extrusion role change G-code, where it is one-based.");
|
||||||
|
|
||||||
def = this->add("layer_z", coFloat);
|
def = this->add("layer_z", coFloat);
|
||||||
def->label = L("Layer Z");
|
def->label = L("Layer Z");
|
||||||
|
|||||||
@@ -136,25 +136,31 @@ enum InfillPattern : int {
|
|||||||
ipCount,
|
ipCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Orca: Infill patterns whose alignment origin follows the fill bounding box, so the
|
// Orca: Infill patterns that the "separated_infills" option can center on each connected body.
|
||||||
// "separated_infills" option can re-center them per connected body. Patterns evaluated in
|
|
||||||
// absolute/global coordinates (Gyroid, TPMS, Honeycomb, CrossHatch, ...) or that are shape-relative
|
|
||||||
// (Concentric) ignore that bounding box and are therefore excluded.
|
|
||||||
inline bool is_separable_infill_pattern(InfillPattern pattern)
|
inline bool is_separable_infill_pattern(InfillPattern pattern)
|
||||||
{
|
{
|
||||||
switch (pattern) {
|
switch (pattern) {
|
||||||
|
case ipMonotonic:
|
||||||
|
case ipMonotonicLine:
|
||||||
case ipRectilinear:
|
case ipRectilinear:
|
||||||
case ipAlignedRectilinear:
|
case ipAlignedRectilinear:
|
||||||
case ipZigZag:
|
case ipZigZag:
|
||||||
case ipCrossZag:
|
case ipCrossZag:
|
||||||
case ipLockedZag:
|
case ipLockedZag:
|
||||||
|
case ipLine:
|
||||||
case ipGrid:
|
case ipGrid:
|
||||||
case ipTriangles:
|
case ipTriangles:
|
||||||
case ipStars: // tri-hexagon
|
case ipStars: // tri-hexagon
|
||||||
case ipCubic:
|
case ipCubic:
|
||||||
case ipQuarterCubic:
|
case ipQuarterCubic:
|
||||||
|
case ipHoneycomb:
|
||||||
|
case ip3DHoneycomb:
|
||||||
case ipLateralHoneycomb:
|
case ipLateralHoneycomb:
|
||||||
case ipLateralLattice:
|
case ipLateralLattice:
|
||||||
|
case ipCrossHatch:
|
||||||
|
case ipTpmsD:
|
||||||
|
case ipTpmsFK:
|
||||||
|
case ipGyroid:
|
||||||
case ipHilbertCurve:
|
case ipHilbertCurve:
|
||||||
case ipArchimedeanChords:
|
case ipArchimedeanChords:
|
||||||
case ipOctagramSpiral:
|
case ipOctagramSpiral:
|
||||||
@@ -164,6 +170,9 @@ inline bool is_separable_infill_pattern(InfillPattern pattern)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Orca: Infill patterns laid out by an octree, which each connected body always gets of its own.
|
||||||
|
inline bool is_octree_infill_pattern(InfillPattern pattern) { return pattern == ipAdaptiveCubic || pattern == ipSupportCubic; }
|
||||||
|
|
||||||
// Orca: Infill patterns that round their corners by the "sparse_infill_smooth_factor" option.
|
// Orca: Infill patterns that round their corners by the "sparse_infill_smooth_factor" option.
|
||||||
// Grid, Triangles and Tri-hexagon only do so in their trapezoidal form, which is generated with more
|
// Grid, Triangles and Tri-hexagon only do so in their trapezoidal form, which is generated with more
|
||||||
// than one line per infill wall; a single line makes them plain crossing lines with nothing to round.
|
// than one line per infill wall; a single line makes them plain crossing lines with nothing to round.
|
||||||
@@ -933,6 +942,10 @@ extern std::set<std::string> filament_dev_options;
|
|||||||
// filament_configs, one config per filament in slot order, as the filaments' values one after another.
|
// filament_configs, one config per filament in slot order, as the filaments' values one after another.
|
||||||
void set_filament_dev_options(DynamicPrintConfig &config, const std::vector<const DynamicPrintConfig *> &filament_configs);
|
void set_filament_dev_options(DynamicPrintConfig &config, const std::vector<const DynamicPrintConfig *> &filament_configs);
|
||||||
|
|
||||||
|
// Orca: sizes the per-slot mixed-colour metadata options to new_slot_count, keeping the first
|
||||||
|
// old_slot_count values; an option the config lacks is created.
|
||||||
|
void resize_mixed_filament_metadata(DynamicPrintConfig &config, size_t old_slot_count, size_t new_slot_count);
|
||||||
|
|
||||||
extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1);
|
extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1);
|
||||||
extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config,
|
extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config,
|
||||||
t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector<int>& f_map_indices);
|
t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector<int>& f_map_indices);
|
||||||
@@ -2562,6 +2575,8 @@ static bool has_zero_flush_volume_for_used_filaments(const std::vector<T> &fv_ma
|
|||||||
|
|
||||||
size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id);
|
size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id);
|
||||||
|
|
||||||
|
double nozzle_diameter_for_filament(const PrintConfig& config, int filament_id, bool is_bbl_printer);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
// Serialization through the Cereal library
|
// Serialization through the Cereal library
|
||||||
|
|||||||
+125
-34
@@ -67,6 +67,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <Eigen/Core>
|
||||||
|
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/spin_mutex.h>
|
#include <tbb/spin_mutex.h>
|
||||||
@@ -719,7 +720,8 @@ void PrintObject::prepare_infill()
|
|||||||
bool needs_separated_components = false;
|
bool needs_separated_components = false;
|
||||||
for (size_t i = 0; i < this->num_printing_regions(); ++ i) {
|
for (size_t i = 0; i < this->num_printing_regions(); ++ i) {
|
||||||
const PrintRegionConfig &rc = this->printing_region(i).config();
|
const PrintRegionConfig &rc = this->printing_region(i).config();
|
||||||
if (rc.separated_infills || rc.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model) {
|
if (rc.separated_infills || rc.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model ||
|
||||||
|
(rc.sparse_infill_density > 0 && is_octree_infill_pattern(rc.sparse_infill_pattern))) {
|
||||||
needs_separated_components = true;
|
needs_separated_components = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -736,8 +738,9 @@ void PrintObject::prepare_infill()
|
|||||||
if (parts <= 1 && ! (first_part != nullptr && first_part->is_splittable()))
|
if (parts <= 1 && ! (first_part != nullptr && first_part->is_splittable()))
|
||||||
needs_separated_components = false;
|
needs_separated_components = false;
|
||||||
}
|
}
|
||||||
|
m_separated_body_bboxes.clear();
|
||||||
for (Layer *layer : m_layers)
|
for (Layer *layer : m_layers)
|
||||||
layer->lslices_separated_component_bboxes.clear();
|
layer->lslices_separated_component_ids.clear();
|
||||||
if (needs_separated_components) {
|
if (needs_separated_components) {
|
||||||
const size_t nl = m_layers.size();
|
const size_t nl = m_layers.size();
|
||||||
std::vector<size_t> offset(nl + 1, 0); // Orca: flat index of the first island of each layer
|
std::vector<size_t> offset(nl + 1, 0); // Orca: flat index of the first island of each layer
|
||||||
@@ -788,17 +791,20 @@ void PrintObject::prepare_infill()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Orca: Full bounding box of each body, indexed by its union-find root.
|
// Orca: Number the bodies by their first island and merge the bounding boxes of their islands.
|
||||||
std::vector<BoundingBox> body_bbox(nreg);
|
std::vector<size_t> body_of_root(nreg, size_t(-1));
|
||||||
for (size_t i = 0; i < nl; ++ i)
|
|
||||||
for (size_t a = 0; a < m_layers[i]->lslices.size(); ++ a)
|
|
||||||
body_bbox[find(offset[i] + a)].merge(m_layers[i]->lslices_bboxes[a]);
|
|
||||||
// Orca: Store the body bbox for every island.
|
|
||||||
for (size_t i = 0; i < nl; ++ i) {
|
for (size_t i = 0; i < nl; ++ i) {
|
||||||
Layer *layer = m_layers[i];
|
Layer *layer = m_layers[i];
|
||||||
layer->lslices_separated_component_bboxes.resize(layer->lslices.size());
|
layer->lslices_separated_component_ids.resize(layer->lslices.size());
|
||||||
for (size_t a = 0; a < layer->lslices.size(); ++ a)
|
for (size_t a = 0; a < layer->lslices.size(); ++ a) {
|
||||||
layer->lslices_separated_component_bboxes[a] = body_bbox[find(offset[i] + a)];
|
size_t &body = body_of_root[find(offset[i] + a)];
|
||||||
|
if (body == size_t(-1)) {
|
||||||
|
body = m_separated_body_bboxes.size();
|
||||||
|
m_separated_body_bboxes.emplace_back();
|
||||||
|
}
|
||||||
|
m_separated_body_bboxes[body].merge(layer->lslices_bboxes[a]);
|
||||||
|
layer->lslices_separated_component_ids[a] = body;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,16 +842,13 @@ void PrintObject::infill()
|
|||||||
if (this->set_started(posInfill)) {
|
if (this->set_started(posInfill)) {
|
||||||
m_print->set_status(35, L("Generating infill toolpath"));
|
m_print->set_status(35, L("Generating infill toolpath"));
|
||||||
|
|
||||||
const auto& adaptive_fill_octree = this->m_adaptive_fill_octrees.first;
|
|
||||||
const auto& support_fill_octree = this->m_adaptive_fill_octrees.second;
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
|
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||||
[this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree](const tbb::blocked_range<size_t>& range) {
|
[this](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get(), this->m_lightning_generator.get());
|
m_layers[layer_idx]->make_fills(&m_adaptive_fill_octrees.first, &m_adaptive_fill_octrees.second, this->m_lightning_generator.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -1110,14 +1113,69 @@ void PrintObject::simplify_extrusion_path()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> PrintObject::prepare_adaptive_infill_data(
|
// Orca: Separated body of the island containing a point of a layer, else of the island outline nearest within 1 mm, or -1.
|
||||||
const std::vector<std::pair<const Surface *, float>> &surfaces_w_bottom_z) const
|
static int separated_body_at(const Layer &layer, const Point &point)
|
||||||
|
{
|
||||||
|
int body = -1;
|
||||||
|
double best = scaled<double>(1.);
|
||||||
|
for (size_t i = 0; i < layer.lslices.size() && i < layer.lslices_separated_component_ids.size() && best > 0.; ++ i) {
|
||||||
|
BoundingBox bbox = layer.lslices_bboxes[i];
|
||||||
|
bbox.offset(coord_t(best));
|
||||||
|
if (! bbox.contains(point))
|
||||||
|
continue;
|
||||||
|
const double dist = layer.lslices[i].contains(point) ? 0. : (layer.lslices[i].point_projection(point) - point).cast<double>().norm();
|
||||||
|
if (dist < best) {
|
||||||
|
best = dist;
|
||||||
|
body = int(layer.lslices_separated_component_ids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orca: The object mesh in the octree frame split by separated body. Each connected component goes to the body
|
||||||
|
// most of its sampled triangles lie on, sampled a layer height inside the solid at the layer nearest to them.
|
||||||
|
static std::vector<indexed_triangle_set> split_mesh_by_body(const PrintObject &object, const indexed_triangle_set &mesh, size_t num_bodies)
|
||||||
|
{
|
||||||
|
const Eigen::Matrix3d to_object = FillAdaptive::transform_to_world().toRotationMatrix();
|
||||||
|
const double inset = object.config().layer_height.value;
|
||||||
|
std::vector<indexed_triangle_set> bodies(num_bodies);
|
||||||
|
for (const indexed_triangle_set &component : its_split(mesh)) {
|
||||||
|
std::vector<size_t> votes(num_bodies, 0);
|
||||||
|
const size_t step = std::max<size_t>(1, component.indices.size() / 8);
|
||||||
|
for (size_t i = 0; i < component.indices.size(); i += step) {
|
||||||
|
const stl_triangle_vertex_indices &tri = component.indices[i];
|
||||||
|
const Vec3d a = component.vertices[tri[0]].cast<double>(), b = component.vertices[tri[1]].cast<double>(),
|
||||||
|
d = component.vertices[tri[2]].cast<double>();
|
||||||
|
const Vec3d normal = (b - a).cross(d - a);
|
||||||
|
const double area2 = normal.norm();
|
||||||
|
const Vec3d c = to_object * ((a + b + d) / 3. - (area2 > 0. ? Vec3d(normal * (inset / area2)) : Vec3d::Zero()));
|
||||||
|
size_t lo = 0, hi = object.layer_count();
|
||||||
|
while (lo < hi) {
|
||||||
|
const size_t mid = (lo + hi) / 2;
|
||||||
|
if (object.get_layer(int(mid))->slice_z < c.z())
|
||||||
|
lo = mid + 1;
|
||||||
|
else
|
||||||
|
hi = mid;
|
||||||
|
}
|
||||||
|
if (lo == object.layer_count() || (lo > 0 && c.z() - object.get_layer(int(lo) - 1)->slice_z < object.get_layer(int(lo))->slice_z - c.z()))
|
||||||
|
-- lo;
|
||||||
|
if (const int body = separated_body_at(*object.get_layer(int(lo)), Point(scaled<coord_t>(c.x()), scaled<coord_t>(c.y()))); body >= 0)
|
||||||
|
++ votes[body];
|
||||||
|
}
|
||||||
|
if (const auto best = std::max_element(votes.begin(), votes.end()); *best > 0)
|
||||||
|
its_merge(bodies[best - votes.begin()], component);
|
||||||
|
}
|
||||||
|
return bodies;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<FillAdaptive::Octrees, FillAdaptive::Octrees> PrintObject::prepare_adaptive_infill_data(
|
||||||
|
const std::vector<std::pair<const Surface *, const Layer *>> &surfaces_w_layer) const
|
||||||
{
|
{
|
||||||
using namespace FillAdaptive;
|
using namespace FillAdaptive;
|
||||||
|
|
||||||
auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this);
|
auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this);
|
||||||
if ((adaptive_line_spacing == 0. && support_line_spacing == 0.) || this->layers().empty())
|
if ((adaptive_line_spacing == 0. && support_line_spacing == 0.) || this->layers().empty())
|
||||||
return std::make_pair(OctreePtr(), OctreePtr());
|
return {};
|
||||||
|
|
||||||
indexed_triangle_set mesh = this->model_object()->raw_indexed_triangle_set();
|
indexed_triangle_set mesh = this->model_object()->raw_indexed_triangle_set();
|
||||||
// Rotate mesh and build octree on it with axis-aligned (standart base) cubes.
|
// Rotate mesh and build octree on it with axis-aligned (standart base) cubes.
|
||||||
@@ -1125,27 +1183,60 @@ std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> PrintObject::prepare
|
|||||||
its_transform(mesh, to_octree * this->trafo_centered(), true);
|
its_transform(mesh, to_octree * this->trafo_centered(), true);
|
||||||
|
|
||||||
// Triangulate internal bridging surfaces.
|
// Triangulate internal bridging surfaces.
|
||||||
std::vector<std::vector<Vec3d>> overhangs(std::max(surfaces_w_bottom_z.size(), size_t(1)));
|
std::vector<std::vector<Vec3d>> overhangs(std::max(surfaces_w_layer.size(), size_t(1)));
|
||||||
// ^ make sure vector is not empty, even with no briding surfaces we still want to build the adaptive trees later, some continue normally
|
// ^ make sure vector is not empty, even with no briding surfaces we still want to build the adaptive trees later, some continue normally
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, surfaces_w_bottom_z.size()),
|
tbb::parallel_for(tbb::blocked_range<int>(0, surfaces_w_layer.size()),
|
||||||
[this, &to_octree, &overhangs, &surfaces_w_bottom_z](const tbb::blocked_range<int> &range) {
|
[this, &to_octree, &overhangs, &surfaces_w_layer](const tbb::blocked_range<int> &range) {
|
||||||
PRINT_OBJECT_TIME_LIMIT_MILLIS(PRINT_OBJECT_TIME_LIMIT_DEFAULT);
|
PRINT_OBJECT_TIME_LIMIT_MILLIS(PRINT_OBJECT_TIME_LIMIT_DEFAULT);
|
||||||
for (int surface_idx = range.begin(); surface_idx < range.end(); ++surface_idx) {
|
for (int surface_idx = range.begin(); surface_idx < range.end(); ++surface_idx) {
|
||||||
std::vector<Vec3d> &out = overhangs[surface_idx];
|
std::vector<Vec3d> &out = overhangs[surface_idx];
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
append(out, triangulate_expolygon_3d(surfaces_w_bottom_z[surface_idx].first->expolygon,
|
append(out, triangulate_expolygon_3d(surfaces_w_layer[surface_idx].first->expolygon,
|
||||||
surfaces_w_bottom_z[surface_idx].second));
|
float(surfaces_w_layer[surface_idx].second->bottom_z())));
|
||||||
for (Vec3d &p : out)
|
for (Vec3d &p : out)
|
||||||
p = (to_octree * p).eval();
|
p = (to_octree * p).eval();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Orca: Each body gets the octree it has when sliced on its own, from its own triangles.
|
||||||
|
std::pair<Octrees, Octrees> octrees;
|
||||||
|
const size_t num_bodies = m_separated_body_bboxes.size();
|
||||||
|
bool need_object = num_bodies <= 1;
|
||||||
|
if (num_bodies > 1) {
|
||||||
|
const std::vector<indexed_triangle_set> body_meshes = split_mesh_by_body(*this, mesh, num_bodies);
|
||||||
|
need_object = std::any_of(body_meshes.begin(), body_meshes.end(), [](const indexed_triangle_set &its) { return its.indices.empty(); });
|
||||||
|
std::vector<std::vector<Vec3d>> body_overhangs(num_bodies);
|
||||||
|
for (size_t i = 0; i < surfaces_w_layer.size(); ++ i)
|
||||||
|
if (const int body = separated_body_at(*surfaces_w_layer[i].second, surfaces_w_layer[i].first->expolygon.contour.points.front()); body >= 0)
|
||||||
|
append(body_overhangs[body], overhangs[i]);
|
||||||
|
if (adaptive_line_spacing)
|
||||||
|
octrees.first.bodies.resize(num_bodies);
|
||||||
|
if (support_line_spacing)
|
||||||
|
octrees.second.bodies.resize(num_bodies);
|
||||||
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_bodies), [&, adaptive_spacing = adaptive_line_spacing, support_spacing = support_line_spacing](
|
||||||
|
const tbb::blocked_range<size_t> &range) {
|
||||||
|
for (size_t body = range.begin(); body < range.end(); ++ body) {
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
if (body_meshes[body].indices.empty())
|
||||||
|
continue;
|
||||||
|
if (adaptive_spacing)
|
||||||
|
octrees.first.bodies[body] = build_octree(body_meshes[body], body_overhangs[body], adaptive_spacing, false);
|
||||||
|
if (support_spacing)
|
||||||
|
octrees.second.bodies[body] = build_octree(body_meshes[body], body_overhangs[body], support_spacing, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// and gather them.
|
// and gather them.
|
||||||
for (size_t i = 1; i < overhangs.size(); ++ i)
|
for (size_t i = 1; i < overhangs.size(); ++ i)
|
||||||
append(overhangs.front(), std::move(overhangs[i]));
|
append(overhangs.front(), std::move(overhangs[i]));
|
||||||
|
|
||||||
return std::make_pair(
|
// Orca: The object's octree only serves bodies that have none of their own.
|
||||||
adaptive_line_spacing ? build_octree(mesh, overhangs.front(), adaptive_line_spacing, false) : OctreePtr(),
|
if (need_object && adaptive_line_spacing)
|
||||||
support_line_spacing ? build_octree(mesh, overhangs.front(), support_line_spacing, true) : OctreePtr());
|
octrees.first.object = build_octree(mesh, overhangs.front(), adaptive_line_spacing, false);
|
||||||
|
if (need_object && support_line_spacing)
|
||||||
|
octrees.second.object = build_octree(mesh, overhangs.front(), support_line_spacing, true);
|
||||||
|
return octrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data()
|
FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data()
|
||||||
@@ -2963,14 +3054,14 @@ void PrintObject::bridge_over_infill()
|
|||||||
std::map<size_t, Polylines> infill_lines;
|
std::map<size_t, Polylines> infill_lines;
|
||||||
// SECTION to generate infill polylines
|
// SECTION to generate infill polylines
|
||||||
{
|
{
|
||||||
std::vector<std::pair<const Surface *, float>> surfaces_w_bottom_z;
|
std::vector<std::pair<const Surface *, const Layer *>> surfaces_w_layer;
|
||||||
for (const auto &pair : surfaces_by_layer) {
|
for (const auto &pair : surfaces_by_layer) {
|
||||||
for (const CandidateSurface &c : pair.second) {
|
for (const CandidateSurface &c : pair.second) {
|
||||||
surfaces_w_bottom_z.emplace_back(c.original_surface, c.region->m_layer->bottom_z());
|
surfaces_w_layer.emplace_back(c.original_surface, c.region->m_layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_adaptive_fill_octrees = this->prepare_adaptive_infill_data(surfaces_w_bottom_z);
|
this->m_adaptive_fill_octrees = this->prepare_adaptive_infill_data(surfaces_w_layer);
|
||||||
|
|
||||||
std::vector<size_t> layers_to_generate_infill;
|
std::vector<size_t> layers_to_generate_infill;
|
||||||
for (const auto &pair : surfaces_by_layer) {
|
for (const auto &pair : surfaces_by_layer) {
|
||||||
@@ -2986,8 +3077,8 @@ void PrintObject::bridge_over_infill()
|
|||||||
for (size_t job_idx = r.begin(); job_idx < r.end(); job_idx++) {
|
for (size_t job_idx = r.begin(); job_idx < r.end(); job_idx++) {
|
||||||
size_t lidx = layers_to_generate_infill[job_idx];
|
size_t lidx = layers_to_generate_infill[job_idx];
|
||||||
infill_lines.at(
|
infill_lines.at(
|
||||||
lidx) = po->get_layer(lidx)->generate_sparse_infill_polylines_for_anchoring(po->m_adaptive_fill_octrees.first.get(),
|
lidx) = po->get_layer(lidx)->generate_sparse_infill_polylines_for_anchoring(&po->m_adaptive_fill_octrees.first,
|
||||||
po->m_adaptive_fill_octrees.second.get(),
|
&po->m_adaptive_fill_octrees.second,
|
||||||
po->m_lightning_generator.get());
|
po->m_lightning_generator.get());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -4467,8 +4558,8 @@ void PrintObject::combine_infill()
|
|||||||
// Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
|
// Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
|
||||||
//FIXME limit the layer height to max_layer_height
|
//FIXME limit the layer height to max_layer_height
|
||||||
double nozzle_diameter = std::min(
|
double nozzle_diameter = std::min(
|
||||||
this->print()->config().nozzle_diameter.get_at(region.config().sparse_infill_filament_id.value - 1),
|
nozzle_diameter_for_filament(this->print()->config(), region.config().sparse_infill_filament_id.value, this->print()->is_BBL_printer()),
|
||||||
this->print()->config().nozzle_diameter.get_at(region.config().internal_solid_filament_id.value - 1));
|
nozzle_diameter_for_filament(this->print()->config(), region.config().internal_solid_filament_id.value, this->print()->is_BBL_printer()));
|
||||||
|
|
||||||
//Orca: Limit combination of infill to up to infill_combination_max_layer_height
|
//Orca: Limit combination of infill to up to infill_combination_max_layer_height
|
||||||
const double infill_combination_max_layer_height = region.config().infill_combination_max_layer_height.get_abs_value(nozzle_diameter);
|
const double infill_combination_max_layer_height = region.config().infill_combination_max_layer_height.get_abs_value(nozzle_diameter);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
|
|||||||
|
|
||||||
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
|
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
|
||||||
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
|
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
|
||||||
auto nozzle_diameter = float(print_config.nozzle_diameter.get_at(this->extruder(role) - 1));
|
auto nozzle_diameter = float(nozzle_diameter_for_filament(print_config, this->extruder(role), object.print()->is_BBL_printer()));
|
||||||
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height));
|
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ public:
|
|||||||
using TColor = typename PixelRenderer::color_type;
|
using TColor = typename PixelRenderer::color_type;
|
||||||
using TValue = typename TColor::value_type;
|
using TValue = typename TColor::value_type;
|
||||||
using TPixel = typename PixelRenderer::pixel_type;
|
using TPixel = typename PixelRenderer::pixel_type;
|
||||||
using TRawBuffer = agg::rendering_buffer;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
#include "TDataStd_Name.hxx"
|
#include "TDataStd_Name.hxx"
|
||||||
#include "BRepBuilderAPI_Transform.hxx"
|
#include "BRepBuilderAPI_Transform.hxx"
|
||||||
#include "TopExp_Explorer.hxx"
|
#include "TopExp_Explorer.hxx"
|
||||||
#include "TopExp_Explorer.hxx"
|
|
||||||
#include "BRep_Tool.hxx"
|
#include "BRep_Tool.hxx"
|
||||||
#include "Font_BRepFont.hxx"
|
#include "Font_BRepFont.hxx"
|
||||||
#include "Font_BRepTextBuilder.hxx"
|
#include "Font_BRepTextBuilder.hxx"
|
||||||
|
|||||||
@@ -2180,7 +2180,7 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers(
|
|||||||
|
|
||||||
// check if the sharp tails should be extended higher
|
// check if the sharp tails should be extended higher
|
||||||
bool detect_first_sharp_tail_only = false;
|
bool detect_first_sharp_tail_only = false;
|
||||||
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament-1));
|
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(nozzle_diameter_for_filament(object.print()->config(), object.config().support_interface_filament, object.print()->is_BBL_printer()));
|
||||||
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
||||||
if (is_auto(m_object_config->support_type.value) && g_config_support_sharp_tails && !detect_first_sharp_tail_only) {
|
if (is_auto(m_object_config->support_type.value) && g_config_support_sharp_tails && !detect_first_sharp_tail_only) {
|
||||||
for (size_t layer_nr = layer_id_start; layer_nr < num_layers; layer_nr++) {
|
for (size_t layer_nr = layer_id_start; layer_nr < num_layers; layer_nr++) {
|
||||||
|
|||||||
@@ -1399,7 +1399,7 @@ void TreeSupport::generate_toolpaths()
|
|||||||
{
|
{
|
||||||
const PrintObjectConfig &object_config = m_object->config();
|
const PrintObjectConfig &object_config = m_object->config();
|
||||||
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
|
||||||
coordf_t nozzle_diameter = m_print_config->nozzle_diameter.get_at(object_config.support_filament - 1);
|
coordf_t nozzle_diameter = nozzle_diameter_for_filament(*m_print_config, object_config.support_filament, m_object->print()->is_BBL_printer());
|
||||||
coordf_t layer_height = object_config.layer_height.value;
|
coordf_t layer_height = object_config.layer_height.value;
|
||||||
const size_t wall_count = object_config.tree_support_wall_count.value;
|
const size_t wall_count = object_config.tree_support_wall_count.value;
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ typedef std::vector<Color> ColorList;
|
|||||||
typedef std::array<double, 3> ColorDouble;
|
typedef std::array<double, 3> ColorDouble;
|
||||||
typedef std::array<std::size_t, 3> RGB;
|
typedef std::array<std::size_t, 3> RGB;
|
||||||
|
|
||||||
// Function pointer type that points to a specific color-difference function based on the chosen method.
|
|
||||||
using DistanceFunction = double (*)(const Color&, const Color&);
|
|
||||||
|
|
||||||
// Color space used for computing color differences.
|
// Color space used for computing color differences.
|
||||||
enum struct ColorDifferenceMethod : std::size_t {
|
enum struct ColorDifferenceMethod : std::size_t {
|
||||||
RGB = 0, // Simplest and fastest
|
RGB = 0, // Simplest and fastest
|
||||||
|
|||||||
@@ -24,8 +24,6 @@
|
|||||||
|
|
||||||
namespace Slic3r { namespace tex2color {
|
namespace Slic3r { namespace tex2color {
|
||||||
|
|
||||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
|
||||||
|
|
||||||
// Default upper bound on the number of half-edges in any single boundary cycle
|
// Default upper bound on the number of half-edges in any single boundary cycle
|
||||||
// that CloseBoundariesAndRepairManifoldness will attempt to triangulate. The
|
// that CloseBoundariesAndRepairManifoldness will attempt to triangulate. The
|
||||||
// cost of triangulate_hole grows non-linearly with cycle length, so this caps
|
// cost of triangulate_hole grows non-linearly with cycle length, so this caps
|
||||||
@@ -61,6 +59,7 @@ struct BoundaryEdgeStats
|
|||||||
// any pre-processing (e.g. stitch_borders) needed for the count to be meaningful.
|
// any pre-processing (e.g. stitch_borders) needed for the count to be meaningful.
|
||||||
inline BoundaryEdgeStats ComputeBoundaryEdgeStats(const cgalutils::CGALMesh& cgal_mesh)
|
inline BoundaryEdgeStats ComputeBoundaryEdgeStats(const cgalutils::CGALMesh& cgal_mesh)
|
||||||
{
|
{
|
||||||
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
using CGALMesh = cgalutils::CGALMesh;
|
using CGALMesh = cgalutils::CGALMesh;
|
||||||
using HalfedgeDescriptor = boost::graph_traits<CGALMesh>::halfedge_descriptor;
|
using HalfedgeDescriptor = boost::graph_traits<CGALMesh>::halfedge_descriptor;
|
||||||
|
|
||||||
@@ -87,6 +86,7 @@ inline BoundaryEdgeStats ComputeBoundaryEdgeStats(const cgalutils::CGALMesh& cga
|
|||||||
// boundary statistics; entering this function always triggers triangulation.
|
// boundary statistics; entering this function always triggers triangulation.
|
||||||
inline void CloseBoundariesAndRepairManifoldness(cgalutils::CGALMesh& cgal_mesh)
|
inline void CloseBoundariesAndRepairManifoldness(cgalutils::CGALMesh& cgal_mesh)
|
||||||
{
|
{
|
||||||
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
using CGALMesh = cgalutils::CGALMesh;
|
using CGALMesh = cgalutils::CGALMesh;
|
||||||
using HalfedgeDescriptor = boost::graph_traits<CGALMesh>::halfedge_descriptor;
|
using HalfedgeDescriptor = boost::graph_traits<CGALMesh>::halfedge_descriptor;
|
||||||
using FaceDescriptor = boost::graph_traits<CGALMesh>::face_descriptor;
|
using FaceDescriptor = boost::graph_traits<CGALMesh>::face_descriptor;
|
||||||
@@ -112,6 +112,7 @@ inline bool RepairMesh(const TriMesh& mesh,
|
|||||||
AlgoCancelCallback cancel_callback = nullptr,
|
AlgoCancelCallback cancel_callback = nullptr,
|
||||||
const RepairSetting& setting = RepairSetting{})
|
const RepairSetting& setting = RepairSetting{})
|
||||||
{
|
{
|
||||||
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
using Clock = std::chrono::steady_clock;
|
using Clock = std::chrono::steady_clock;
|
||||||
auto elapsed_ms = [](Clock::time_point t0) {
|
auto elapsed_ms = [](Clock::time_point t0) {
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - t0).count();
|
return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - t0).count();
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string_view>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|||||||
@@ -432,8 +432,6 @@ inline IntegerOnly<I, I> fast_round_up(double a)
|
|||||||
return a == 0.49999999999999994 ? I(0) : I(floor(a + 0.5));
|
return a == 0.49999999999999994 ? I(0) : I(floor(a + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> using SamePair = std::pair<T, T>;
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1012,7 +1012,10 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||||||
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
||||||
if (machine_diameter == 0.0f && preset_bundle) {
|
if (machine_diameter == 0.0f && preset_bundle) {
|
||||||
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
||||||
if (opt) machine_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
|
if (opt) {
|
||||||
|
const auto &nd = static_cast<const ConfigOptionFloats *>(opt)->values;
|
||||||
|
if (!nd.empty()) machine_diameter = nd.size() > 1 ? nd[1] : nd[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||||
std::string nozzle_diameter_str = stream.str();
|
std::string nozzle_diameter_str = stream.str();
|
||||||
@@ -1291,7 +1294,10 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
|||||||
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
||||||
if (machine_diameter == 0.0f) {
|
if (machine_diameter == 0.0f) {
|
||||||
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
||||||
if (opt) machine_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
|
if (opt) {
|
||||||
|
const auto &nd = static_cast<const ConfigOptionFloats *>(opt)->values;
|
||||||
|
if (!nd.empty()) machine_diameter = nd.size() > 1 ? nd[1] : nd[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/dataview.h>
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
@@ -30,7 +29,6 @@
|
|||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/wrapsizer.h>
|
#include <wx/wrapsizer.h>
|
||||||
|
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
|
|||||||
@@ -19,20 +19,17 @@
|
|||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/sizer.h>
|
|
||||||
#include <wx/grid.h>
|
#include <wx/grid.h>
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
#include <wx/bitmap.h>
|
#include <wx/bitmap.h>
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
#include <wx/icon.h>
|
#include <wx/icon.h>
|
||||||
#include <wx/bmpbuttn.h>
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/statbox.h>
|
#include <wx/statbox.h>
|
||||||
#include <wx/tglbtn.h>
|
#include <wx/tglbtn.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/sizer.h>
|
|
||||||
#include <wx/grid.h>
|
#include <wx/grid.h>
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
@@ -36,14 +35,12 @@
|
|||||||
#include <wx/bitmap.h>
|
#include <wx/bitmap.h>
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
#include <wx/icon.h>
|
#include <wx/icon.h>
|
||||||
#include <wx/bmpbuttn.h>
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/statbox.h>
|
#include <wx/statbox.h>
|
||||||
#include <wx/tglbtn.h>
|
#include <wx/tglbtn.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/webrequest.h>
|
#include <wx/webrequest.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "Jobs/ProgressIndicator.hpp"
|
#include "Jobs/ProgressIndicator.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include "Jobs/ProgressIndicator.hpp"
|
#include "Jobs/ProgressIndicator.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
|
||||||
#include <wx/hyperlink.h>
|
#include <wx/hyperlink.h>
|
||||||
|
|
||||||
#include "Jobs/ProgressIndicator.hpp"
|
#include "Jobs/ProgressIndicator.hpp"
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
|
||||||
#include <wx/hyperlink.h>
|
#include <wx/hyperlink.h>
|
||||||
|
|
||||||
#include "Jobs/ProgressIndicator.hpp"
|
#include "Jobs/ProgressIndicator.hpp"
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include <wx/toplevel.h>
|
#include <wx/toplevel.h>
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
#include "Widgets/Button.hpp"
|
|
||||||
#include "CapsuleButton.hpp"
|
#include "CapsuleButton.hpp"
|
||||||
|
|
||||||
namespace Slic3r::GUI { struct IntEvent; }
|
namespace Slic3r::GUI { struct IntEvent; }
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/Polygon.hpp"
|
#include "libslic3r/Polygon.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "GUI_App.hpp"
|
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "Jobs/BoostThreadWorker.hpp"
|
#include "Jobs/BoostThreadWorker.hpp"
|
||||||
#include "Jobs/PlaterWorker.hpp"
|
#include "Jobs/PlaterWorker.hpp"
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/I18N.hpp"
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
#include "slic3r/GUI/format.hpp"
|
#include "slic3r/GUI/format.hpp"
|
||||||
#include "slic3r/Utils/Bonjour.hpp"
|
|
||||||
|
|
||||||
#include "slic3r/GUI/Widgets/DialogButtons.hpp"
|
#include "slic3r/GUI/Widgets/DialogButtons.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/dataview.h>
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
@@ -24,7 +23,6 @@
|
|||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/wrapsizer.h>
|
#include <wx/wrapsizer.h>
|
||||||
|
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// #include "libslic3r/GCodeSender.hpp"
|
|
||||||
#include "ConfigManipulation.hpp"
|
#include "ConfigManipulation.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
@@ -872,10 +871,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
|
|||||||
toggle_line("center_of_surface_pattern", has_centered_surface);
|
toggle_line("center_of_surface_pattern", has_centered_surface);
|
||||||
|
|
||||||
// Orca: separate infills
|
// Orca: separate infills
|
||||||
bool is_internal_infill_separable = is_separable_infill_pattern(config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value) ||
|
toggle_line("separated_infills", is_separable_infill_pattern(pattern));
|
||||||
config->opt_string("sparse_infill_rotate_template") != "" ||
|
|
||||||
config->opt_string("solid_infill_rotate_template") != "";
|
|
||||||
toggle_line("separated_infills", is_internal_infill_separable);
|
|
||||||
|
|
||||||
// Fill order is only meaningful for the center-based surface fill patterns; hide it otherwise.
|
// Fill order is only meaningful for the center-based surface fill patterns; hide it otherwise.
|
||||||
auto is_centered_fill = [](InfillPattern p) { return p == ipConcentric || p == ipSpiralInset || p == ipArchimedeanChords || p == ipOctagramSpiral; };
|
auto is_centered_fill = [](InfillPattern p) { return p == ipConcentric || p == ipSpiralInset || p == ipArchimedeanChords || p == ipOctagramSpiral; };
|
||||||
|
|||||||
@@ -198,6 +198,3 @@ template<> struct std::hash<NozzleDef>
|
|||||||
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// key(extruder_id) -> { key1(nozzle type info), val1( number of the nozzle type)}
|
|
||||||
using ExtruderNozzleInfos = std::unordered_map<int, std::unordered_map<NozzleDef, int>>;
|
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "DeviceErrorDialog.hpp"
|
#include "DeviceErrorDialog.hpp"
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "GUI_App.hpp"
|
|
||||||
#include "ReleaseNote.hpp"
|
#include "ReleaseNote.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|||||||
@@ -2427,11 +2427,15 @@ void GLCanvas3D::_render_scene(const Camera& camera, const Size& cnv_size)
|
|||||||
if (m_canvas_type == ECanvasType::CanvasView3D) {
|
if (m_canvas_type == ECanvasType::CanvasView3D) {
|
||||||
// m_show_bed gates the plate list too: hiding the bed but leaving its grid and outline
|
// m_show_bed gates the plate list too: hiding the bed but leaving its grid and outline
|
||||||
// floating would read as a rendering fault rather than a deliberate view option.
|
// floating would read as a rendering fault rather than a deliberate view option.
|
||||||
// Design tab: while its reference planes are up they draw their own axes from the modeling
|
if (show_bed) {
|
||||||
// origin, where the bed's triad would otherwise sit on top of them.
|
bool show_axes = m_show_world_axes;
|
||||||
if (show_bed)
|
#ifdef SLIC3R_CAD
|
||||||
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(),
|
// Design tab: while its reference planes are up they draw their own axes from the modeling
|
||||||
m_show_world_axes && !(m_design_sketch_tool != nullptr && m_design_sketch_tool->draws_reference_axes()));
|
// origin, where the bed's triad would otherwise sit on top of them.
|
||||||
|
show_axes = show_axes && !(m_design_sketch_tool != nullptr && m_design_sketch_tool->draws_reference_axes());
|
||||||
|
#endif
|
||||||
|
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
|
||||||
|
}
|
||||||
m_frame_profiler.mark("bed");
|
m_frame_profiler.mark("bed");
|
||||||
if (show_bed) //BBS: add outline logic
|
if (show_bed) //BBS: add outline logic
|
||||||
_render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid);
|
_render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid);
|
||||||
|
|||||||
@@ -183,13 +183,10 @@ wxDECLARE_EVENT(EVT_GLCANVAS_PLATE_NAME_CHANGE, SimpleEvent);
|
|||||||
//BBS: declare EVT_GLCANVAS_PLATE_SELECT
|
//BBS: declare EVT_GLCANVAS_PLATE_SELECT
|
||||||
wxDECLARE_EVENT(EVT_GLCANVAS_PLATE_SELECT, SimpleEvent);
|
wxDECLARE_EVENT(EVT_GLCANVAS_PLATE_SELECT, SimpleEvent);
|
||||||
|
|
||||||
using Vec2dEvent = Event<Vec2d>;
|
|
||||||
// _bool_ value is used as a indicator of selection in the 3DScene
|
// _bool_ value is used as a indicator of selection in the 3DScene
|
||||||
using RBtnEvent = Event<std::pair<Vec2d, bool>>;
|
using RBtnEvent = Event<std::pair<Vec2d, bool>>;
|
||||||
using RBtnPlateEvent = Event<std::pair<Vec2d, int>>;
|
using RBtnPlateEvent = Event<std::pair<Vec2d, int>>;
|
||||||
template <size_t N> using Vec2dsEvent = ArrayEvent<Vec2d, N>;
|
|
||||||
|
|
||||||
using Vec3dEvent = Event<Vec3d>;
|
|
||||||
template <size_t N> using Vec3dsEvent = ArrayEvent<Vec3d, N>;
|
template <size_t N> using Vec3dsEvent = ArrayEvent<Vec3d, N>;
|
||||||
|
|
||||||
using HeightProfileSmoothEvent = Event<HeightProfileSmoothingParams>;
|
using HeightProfileSmoothEvent = Event<HeightProfileSmoothingParams>;
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
#include "nanosvg/nanosvgrast.h"
|
#include "nanosvg/nanosvgrast.h"
|
||||||
|
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "GUI_App.hpp"
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <wx/dcgraph.h>
|
#include <wx/dcgraph.h>
|
||||||
#include <wx/dcmemory.h>
|
#include <wx/dcmemory.h>
|
||||||
|
|||||||
@@ -50,7 +50,6 @@
|
|||||||
#include "AboutDialog.hpp"
|
#include "AboutDialog.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "format.hpp"
|
|
||||||
|
|
||||||
#include "WebUserLoginDialog.hpp"
|
#include "WebUserLoginDialog.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -172,12 +172,10 @@
|
|||||||
|
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/I18N.hpp"
|
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "libslic3r/InstanceLock.hpp"
|
#include "libslic3r/InstanceLock.hpp"
|
||||||
#include "libslic3r/Thread.hpp"
|
#include "libslic3r/Thread.hpp"
|
||||||
#include "libslic3r/miniz_extension.hpp"
|
#include "libslic3r/miniz_extension.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
|
||||||
#include "slic3r/plugin/PluginManager.hpp"
|
#include "slic3r/plugin/PluginManager.hpp"
|
||||||
#include "slic3r/plugin/host/PluginHostUi.hpp"
|
#include "slic3r/plugin/host/PluginHostUi.hpp"
|
||||||
#include "slic3r/plugin/PythonInterpreter.hpp"
|
#include "slic3r/plugin/PythonInterpreter.hpp"
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include "libslic3r/Config.hpp"
|
#include "libslic3r/Config.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "libslic3r/Preset.hpp"
|
#include "libslic3r/Preset.hpp"
|
||||||
#include "libslic3r/Config.hpp"
|
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|||||||
@@ -66,7 +66,6 @@
|
|||||||
#include <nanosvg/nanosvg.h>
|
#include <nanosvg/nanosvg.h>
|
||||||
#include <nanosvg/nanosvgrast.h>
|
#include <nanosvg/nanosvgrast.h>
|
||||||
#include "OpenGLManager.hpp"
|
#include "OpenGLManager.hpp"
|
||||||
#include "GUI_App.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|||||||
@@ -113,7 +113,6 @@
|
|||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
#include "Notebook.hpp"
|
#include "Notebook.hpp"
|
||||||
#include "GUI_Factories.hpp"
|
#include "GUI_Factories.hpp"
|
||||||
#include "GUI_ObjectList.hpp"
|
|
||||||
#include "NotificationManager.hpp"
|
#include "NotificationManager.hpp"
|
||||||
#include "MarkdownTip.hpp"
|
#include "MarkdownTip.hpp"
|
||||||
#include "NetworkTestDialog.hpp"
|
#include "NetworkTestDialog.hpp"
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include "wx/evtloop.h"
|
#include "wx/evtloop.h"
|
||||||
|
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "GUI_App.hpp"
|
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "MediaPlayCtrl.h"
|
#include "MediaPlayCtrl.h"
|
||||||
#include "MediaFilePanel.h"
|
#include "MediaFilePanel.h"
|
||||||
#include "Plater.hpp"
|
|
||||||
#include "BindDialog.hpp"
|
#include "BindDialog.hpp"
|
||||||
|
|
||||||
#include "DeviceCore/DevManager.h"
|
#include "DeviceCore/DevManager.h"
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/sizer.h>
|
|
||||||
#include <wx/grid.h>
|
#include <wx/grid.h>
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
@@ -31,14 +30,12 @@
|
|||||||
#include <wx/bitmap.h>
|
#include <wx/bitmap.h>
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
#include <wx/icon.h>
|
#include <wx/icon.h>
|
||||||
#include <wx/bmpbuttn.h>
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/statbox.h>
|
#include <wx/statbox.h>
|
||||||
#include <wx/tglbtn.h>
|
#include <wx/tglbtn.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/webrequest.h>
|
#include <wx/webrequest.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "I18N.hpp"
|
|
||||||
#include "libslic3r_version.h"
|
#include "libslic3r_version.h"
|
||||||
#include "slic3r/Utils/Http.hpp"
|
#include "slic3r/Utils/Http.hpp"
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ struct Option {
|
|||||||
Option(const ConfigOptionDef& _opt, t_config_option_key id) :
|
Option(const ConfigOptionDef& _opt, t_config_option_key id) :
|
||||||
opt(_opt), opt_id(id) {}
|
opt(_opt), opt_id(id) {}
|
||||||
};
|
};
|
||||||
using t_option = std::unique_ptr<Option>; //!
|
|
||||||
|
|
||||||
/// Represents option lines
|
/// Represents option lines
|
||||||
class Line : public UndoValueUIManager
|
class Line : public UndoValueUIManager
|
||||||
|
|||||||
+21
-21
@@ -1862,27 +1862,22 @@ bool Sidebar::priv::switch_diameter(bool single)
|
|||||||
auto diameter_left = left_extruder->combo_diameter->GetValue();
|
auto diameter_left = left_extruder->combo_diameter->GetValue();
|
||||||
auto diameter_right = right_extruder->combo_diameter->GetValue();
|
auto diameter_right = right_extruder->combo_diameter->GetValue();
|
||||||
if (diameter_left != diameter_right) {
|
if (diameter_left != diameter_right) {
|
||||||
std::string printer_type = wxGetApp().preset_bundle->printers.get_edited_preset().get_printer_type(wxGetApp().preset_bundle);
|
double left_value = 0.0, right_value = 0.0;
|
||||||
auto left_name = _L(DevPrinterConfigUtil::get_toolhead_display_name(printer_type, DEPUTY_EXTRUDER_ID, ToolHeadComponent::Nozzle, ToolHeadNameCase::SentenceCase));
|
if (!diameter_left.ToCDouble(&left_value) || !diameter_right.ToCDouble(&right_value))
|
||||||
auto right_name = _L(DevPrinterConfigUtil::get_toolhead_display_name(printer_type, MAIN_EXTRUDER_ID, ToolHeadComponent::Nozzle, ToolHeadNameCase::SentenceCase));
|
|
||||||
MessageDialog dlg(this->plater,
|
|
||||||
_L("The software does not support using different diameter of nozzles for one print. "
|
|
||||||
"If the left and right nozzles are inconsistent, we can only proceed with single-head printing. "
|
|
||||||
"Please confirm which nozzle you would like to use for this project."),
|
|
||||||
_L("Switch diameter"), wxYES_NO | wxNO_DEFAULT);
|
|
||||||
dlg.SetButtonLabel(wxID_YES, wxString::Format("%s: %smm", left_name, diameter_left));
|
|
||||||
dlg.SetButtonLabel(wxID_NO, wxString::Format("%s: %smm", right_name, diameter_right));
|
|
||||||
int result = dlg.ShowModal();
|
|
||||||
if (result == wxID_YES)
|
|
||||||
diameter = diameter_left;
|
|
||||||
else if (result == wxID_NO)
|
|
||||||
diameter = diameter_right;
|
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Tab* printer_tab = wxGetApp().get_tab(Preset::TYPE_PRINTER);
|
||||||
|
DynamicPrintConfig new_conf = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
|
auto* nozzle_diameter_opt = new_conf.option<ConfigOptionFloats>("nozzle_diameter");
|
||||||
|
if (printer_tab == nullptr || nozzle_diameter_opt == nullptr || nozzle_diameter_opt->size() < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nozzle_diameter_opt->values[0] = left_value;
|
||||||
|
nozzle_diameter_opt->values[1] = right_value;
|
||||||
|
printer_tab->load_config(new_conf);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
diameter = diameter_left;
|
||||||
diameter = diameter_left;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return switch_diameter_to(diameter);
|
return switch_diameter_to(diameter);
|
||||||
@@ -1892,15 +1887,20 @@ bool Sidebar::priv::switch_diameter_to(const wxString &diameter)
|
|||||||
{
|
{
|
||||||
// ORCA: Check if the selected diameter matches the current nozzle diameter in the config
|
// ORCA: Check if the selected diameter matches the current nozzle diameter in the config
|
||||||
Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||||
|
auto* nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printer_preset.config.option("nozzle_diameter"));
|
||||||
|
// ORCA: the left/right combos of a BBL multi-nozzle printer set the nozzles apart without leaving
|
||||||
|
// the preset (see switch_diameter), so there the preset is only kept while every nozzle matches.
|
||||||
|
const bool nozzles_apart = nozzle_diameter && nozzle_diameter->size() > 1 && wxGetApp().preset_bundle->is_bbl_vendor() &&
|
||||||
|
std::any_of(nozzle_diameter->values.begin(), nozzle_diameter->values.end(),
|
||||||
|
[&diameter](double value) { return get_diameter_string(value) != diameter.ToStdString(); });
|
||||||
// The combo lists printer variants, and the variant of a mixed-nozzle machine ("0.4+0.6") is no
|
// The combo lists printer variants, and the variant of a mixed-nozzle machine ("0.4+0.6") is no
|
||||||
// single extruder's diameter, so the preset's own variant answers first.
|
// single extruder's diameter, so the preset's own variant answers first.
|
||||||
const std::string &printer_variant = printer_preset.config.opt_string("printer_variant");
|
const std::string &printer_variant = printer_preset.config.opt_string("printer_variant");
|
||||||
if (printer_variant == diameter.ToStdString()) {
|
if (printer_variant == diameter.ToStdString() && !nozzles_apart) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// A named variant ("0.4 High Flow") shares its diameter with the standard profile, which selecting
|
// A named variant ("0.4 High Flow") shares its diameter with the standard profile, which selecting
|
||||||
// the plain diameter switches back to, so only a preset naming no variant is kept by its diameter.
|
// the plain diameter switches back to, so only a preset naming no variant is kept by its diameter.
|
||||||
auto* nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printer_preset.config.option("nozzle_diameter"));
|
|
||||||
if (printer_variant.empty() && nozzle_diameter && nozzle_diameter->size() > 0) {
|
if (printer_variant.empty() && nozzle_diameter && nozzle_diameter->size() > 0) {
|
||||||
auto current_nozzle_dia = get_diameter_string(nozzle_diameter->values[0]);
|
auto current_nozzle_dia = get_diameter_string(nozzle_diameter->values[0]);
|
||||||
// If the selected diameter is the same as current nozzle, don't switch profiles
|
// If the selected diameter is the same as current nozzle, don't switch profiles
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ class PlaterPresetComboBox;
|
|||||||
class PartPlateList;
|
class PartPlateList;
|
||||||
class SyncNozzleAndAmsDialog;
|
class SyncNozzleAndAmsDialog;
|
||||||
class FinishSyncAmsDialog;
|
class FinishSyncAmsDialog;
|
||||||
using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>;
|
|
||||||
|
|
||||||
class Plater;
|
class Plater;
|
||||||
enum class ActionButtonType : int;
|
enum class ActionButtonType : int;
|
||||||
@@ -325,7 +324,6 @@ private:
|
|||||||
class Plater: public wxPanel
|
class Plater: public wxPanel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using fs_path = boost::filesystem::path;
|
|
||||||
|
|
||||||
Plater(wxWindow *parent, MainFrame *main_frame);
|
Plater(wxWindow *parent, MainFrame *main_frame);
|
||||||
Plater(Plater &&) = delete;
|
Plater(Plater &&) = delete;
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include <miniz.h>
|
#include <miniz.h>
|
||||||
#include <OrcaCloudServiceAgent.hpp>
|
#include <OrcaCloudServiceAgent.hpp>
|
||||||
#include <wx/event.h>
|
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|||||||
@@ -79,7 +79,6 @@
|
|||||||
#include "libslic3r_version.h"
|
#include "libslic3r_version.h"
|
||||||
#include "wxExtensions.hpp"
|
#include "wxExtensions.hpp"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include "libslic3r/Preset.hpp"
|
#include "libslic3r/Preset.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "slic3r/GUI/Widgets/Button.hpp"
|
#include "slic3r/GUI/Widgets/Button.hpp"
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "Jobs/ProgressIndicator.hpp"
|
#include "Jobs/ProgressIndicator.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/dataview.h>
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
@@ -32,10 +31,8 @@
|
|||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/wrapsizer.h>
|
#include <wx/wrapsizer.h>
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/hyperlink.h>
|
|
||||||
#include <wx/richtext/richtextctrl.h>
|
#include <wx/richtext/richtextctrl.h>
|
||||||
|
|
||||||
#include "AmsMappingPopup.hpp"
|
#include "AmsMappingPopup.hpp"
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/dataview.h>
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
@@ -38,7 +37,6 @@
|
|||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/wrapsizer.h>
|
#include <wx/wrapsizer.h>
|
||||||
#include <wx/srchctrl.h>
|
#include <wx/srchctrl.h>
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/dataview.h>
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
@@ -29,7 +28,6 @@
|
|||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/wrapsizer.h>
|
#include <wx/wrapsizer.h>
|
||||||
#include <wx/srchctrl.h>
|
#include <wx/srchctrl.h>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/dataview.h>
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
@@ -33,7 +32,6 @@
|
|||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/popupwin.h>
|
#include <wx/popupwin.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/wrapsizer.h>
|
#include <wx/wrapsizer.h>
|
||||||
#include <wx/srchctrl.h>
|
#include <wx/srchctrl.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// #include "libslic3r/GCodeSender.hpp"
|
|
||||||
//#include "slic3r/Utils/Serial.hpp"
|
//#include "slic3r/Utils/Serial.hpp"
|
||||||
#include "Tab.hpp"
|
#include "Tab.hpp"
|
||||||
#include "PresetHints.hpp"
|
#include "PresetHints.hpp"
|
||||||
@@ -102,8 +101,6 @@
|
|||||||
#include "Widgets/MultiNozzleSync.hpp"
|
#include "Widgets/MultiNozzleSync.hpp"
|
||||||
#include "Widgets/SwitchButton.hpp"
|
#include "Widgets/SwitchButton.hpp"
|
||||||
#include "Widgets/TabCtrl.hpp"
|
#include "Widgets/TabCtrl.hpp"
|
||||||
#include "Widgets/ComboBox.hpp"
|
|
||||||
#include "Search.hpp"
|
|
||||||
#include "BedShapeDialog.hpp"
|
#include "BedShapeDialog.hpp"
|
||||||
#include "libslic3r/GCode/Thumbnails.hpp"
|
#include "libslic3r/GCode/Thumbnails.hpp"
|
||||||
#include "WipeTowerDialog.hpp"
|
#include "WipeTowerDialog.hpp"
|
||||||
@@ -5836,7 +5833,8 @@ if (is_marlin_flavor)
|
|||||||
// The page edits the extruder selected on the variant switch.
|
// The page edits the extruder selected on the variant switch.
|
||||||
const size_t extruder_idx = size_t(get_current_active_extruder());
|
const size_t extruder_idx = size_t(get_current_active_extruder());
|
||||||
bool is_SEMM = m_config->opt_bool("single_extruder_multi_material");
|
bool is_SEMM = m_config->opt_bool("single_extruder_multi_material");
|
||||||
if (is_SEMM && m_extruders_count > 1 && boost::starts_with(opt_key, "nozzle_diameter"))
|
bool independent_nozzles = m_preset_bundle && m_preset_bundle->is_bbl_vendor() && m_extruders_count > 1;
|
||||||
|
if (is_SEMM && m_extruders_count > 1 && !independent_nozzles && boost::starts_with(opt_key, "nozzle_diameter"))
|
||||||
{
|
{
|
||||||
SuppressBackgroundProcessingUpdate sbpu;
|
SuppressBackgroundProcessingUpdate sbpu;
|
||||||
const double new_nd = boost::any_cast<double>(value);
|
const double new_nd = boost::any_cast<double>(value);
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ webkit_web_view_run_javascript_finish (WebKitWebView
|
|||||||
GError **error);
|
GError **error);
|
||||||
WEBKIT_API void
|
WEBKIT_API void
|
||||||
webkit_javascript_result_unref (WebKitJavascriptResult *js_result);
|
webkit_javascript_result_unref (WebKitJavascriptResult *js_result);
|
||||||
|
WEBKIT_API unsigned int
|
||||||
|
webkit_get_major_version (void);
|
||||||
|
WEBKIT_API unsigned int
|
||||||
|
webkit_get_minor_version (void);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -401,6 +405,21 @@ bool WebView::NeedsRecreateOnShow()
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebView::WebKitAtLeast(int major, int minor)
|
||||||
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
|
const unsigned int running_major = webkit_get_major_version();
|
||||||
|
if (running_major != static_cast<unsigned int>(major))
|
||||||
|
return running_major > static_cast<unsigned int>(major);
|
||||||
|
return webkit_get_minor_version() >= static_cast<unsigned int>(minor);
|
||||||
|
#else
|
||||||
|
(void) major;
|
||||||
|
(void) minor;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if wxUSE_WEBVIEW_EDGE
|
#if wxUSE_WEBVIEW_EDGE
|
||||||
bool WebView::CheckWebViewRuntime()
|
bool WebView::CheckWebViewRuntime()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ public:
|
|||||||
// ignoring every navigation. A panel that gets true here recreates its view on first Show().
|
// ignoring every navigation. A panel that gets true here recreates its view on first Show().
|
||||||
static bool NeedsRecreateOnShow();
|
static bool NeedsRecreateOnShow();
|
||||||
|
|
||||||
|
// Runtime version of the linked WebKitGTK, for gating the Linux DMA-BUF
|
||||||
|
// renderer workaround. Returns false on non-GTK builds.
|
||||||
|
static bool WebKitAtLeast(int major, int minor);
|
||||||
|
|
||||||
static void RecreateAll();
|
static void RecreateAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
#include "../GUI/DeviceCore/DevConfig.h"
|
#include "../GUI/DeviceCore/DevConfig.h"
|
||||||
#include "../GUI/DeviceCore/DevExtruderSystem.h"
|
#include "../GUI/DeviceCore/DevExtruderSystem.h"
|
||||||
#include "../GUI/DeviceCore/DevManager.h"
|
#include "../GUI/DeviceCore/DevManager.h"
|
||||||
#include "../GUI/DeviceCore/DevStorage.h"
|
|
||||||
#include "libslic3r/FlushVolCalc.hpp"
|
|
||||||
#include "../GUI/Plater.hpp"
|
#include "../GUI/Plater.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "slic3r/GUI/Jobs/Worker.hpp"
|
#include "slic3r/GUI/Jobs/Worker.hpp"
|
||||||
|
|||||||
@@ -365,7 +365,6 @@ void StyleManager::init_trunc_names(float max_width) {
|
|||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
|
||||||
// for get DPI
|
// for get DPI
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
|
||||||
#include "slic3r/GUI/MainFrame.hpp"
|
#include "slic3r/GUI/MainFrame.hpp"
|
||||||
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
|
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
|
||||||
|
|
||||||
@@ -554,8 +553,6 @@ bool StyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr<FontFile>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <libslic3r/AppConfig.hpp>
|
|
||||||
#include "WxFontUtils.hpp"
|
|
||||||
#include "fast_float/fast_float.h"
|
#include "fast_float/fast_float.h"
|
||||||
|
|
||||||
// StylesSerializable
|
// StylesSerializable
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ using fn_ft_job_get_result = ft_err(FT_CALL *)(FT_JobHandle *, uint32_t timeo
|
|||||||
using fn_ft_tunnel_start_job = ft_err(FT_CALL *)(FT_TunnelHandle *, FT_JobHandle *);
|
using fn_ft_tunnel_start_job = ft_err(FT_CALL *)(FT_TunnelHandle *, FT_JobHandle *);
|
||||||
using fn_ft_job_cancel = ft_err(FT_CALL *)(FT_JobHandle *);
|
using fn_ft_job_cancel = ft_err(FT_CALL *)(FT_JobHandle *);
|
||||||
|
|
||||||
using fn_ft_job_msg_destroy = void(FT_CALL *)(ft_job_msg *);
|
|
||||||
using fn_ft_job_set_msg_cb = ft_err(FT_CALL *)(FT_JobHandle *, void(FT_CALL *)(void *user, ft_job_msg msg), void *user);
|
using fn_ft_job_set_msg_cb = ft_err(FT_CALL *)(FT_JobHandle *, void(FT_CALL *)(void *user, ft_job_msg msg), void *user);
|
||||||
using fn_ft_job_try_get_msg = ft_err(FT_CALL *)(FT_JobHandle *, ft_job_msg *out_msg);
|
using fn_ft_job_try_get_msg = ft_err(FT_CALL *)(FT_JobHandle *, ft_job_msg *out_msg);
|
||||||
using fn_ft_job_get_msg = ft_err(FT_CALL *)(FT_JobHandle *, uint32_t timeout_ms, ft_job_msg *out_msg);
|
using fn_ft_job_get_msg = ft_err(FT_CALL *)(FT_JobHandle *, uint32_t timeout_ms, ft_job_msg *out_msg);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user