mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-03 05:41:10 +00:00
Add a Shell-Only Drag Mode That Keeps What Can Be Seen From Outside
A third mode of the drag preference: the reduced set keeps every role but the sparse infill, internal solid infill, internal bridge infill and gap fill, which lie under the skins or between the walls, on every layer. Walls, top and bottom surfaces, bridges, supports and the prime tower are drawn whole, so from outside the print looks as it does at rest, and the two end layers of the visible range stay whole as in every mode. The roles come from the slicer, so the classification is exact wherever the slicer's is. What a role cannot tell apart is the inside of the prime tower or of a support from its outside; both are kept whole. A profile with no top or bottom shell layers exposes infill, which this mode hides.
This commit is contained in:
@@ -9,8 +9,8 @@ let go.
|
|||||||
|
|
||||||
| Preference | Values | Effect |
|
| Preference | Values | Effect |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `preview_reduced_detail_mode` | `off`, `solid`, `layers`, `outer_walls` | what is drawn while dragging |
|
| `preview_reduced_detail_mode` | `off`, `solid`, `layers`, `outer_walls`, `shell` | what is drawn while dragging |
|
||||||
| `preview_reduced_detail_layer_stride` | 1–20 | one layer in every N is kept by the toolpath modes |
|
| `preview_reduced_detail_layer_stride` | 1–20 | one layer in every N is kept by the skip-layers and outer-walls modes |
|
||||||
|
|
||||||
libvgcode (`src/libvgcode`) builds and binds the reduced toolpath set, `GCodeViewer` maps the
|
libvgcode (`src/libvgcode`) builds and binds the reduced toolpath set, `GCodeViewer` maps the
|
||||||
preferences onto it and draws the solid model, and `GLCanvas3D` decides when the user is dragging.
|
preferences onto it and draws the solid model, and `GLCanvas3D` decides when the user is dragging.
|
||||||
@@ -35,6 +35,13 @@ are the faces the range cuts open, and the top is what the user is looking at.
|
|||||||
- `LayersOnly` (`layers`) keeps every role of one layer in every stride.
|
- `LayersOnly` (`layers`) keeps every role of one layer in every stride.
|
||||||
- `OuterWallsOnly` (`outer_walls`) keeps the outer and overhang perimeters of one layer in every
|
- `OuterWallsOnly` (`outer_walls`) keeps the outer and overhang perimeters of one layer in every
|
||||||
stride. The prime tower and supports have other roles and are left out.
|
stride. The prime tower and supports have other roles and are left out.
|
||||||
|
- `ShellOnly` (`shell`) keeps every layer, and every role but the sparse infill, internal solid
|
||||||
|
infill, internal bridge infill and gap fill, which lie under the skins or between the walls.
|
||||||
|
Walls, top and bottom surfaces, bridges, supports and the prime tower are drawn whole, so from
|
||||||
|
outside the print looks as it does at rest, and the stride does not apply. The roles come from
|
||||||
|
the slicer, so the classification is exact wherever the slicer's is; what it cannot express is
|
||||||
|
the inside of the prime tower and of a support, which share one role with their outside and are
|
||||||
|
kept whole. A profile with no top or bottom shell layers exposes infill, which this mode hides.
|
||||||
|
|
||||||
## The solid model
|
## The solid model
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ void AppConfig::set_defaults()
|
|||||||
// what the preview draws while the user drags it, and one layer in how many the toolpath modes keep
|
// what the preview draws while the user drags it, and one layer in how many the toolpath modes keep
|
||||||
{
|
{
|
||||||
const std::string mode = get("preview_reduced_detail_mode");
|
const std::string mode = get("preview_reduced_detail_mode");
|
||||||
if (mode != "off" && mode != "solid" && mode != "layers" && mode != "outer_walls")
|
if (mode != "off" && mode != "solid" && mode != "layers" && mode != "outer_walls" && mode != "shell")
|
||||||
set("preview_reduced_detail_mode", "off");
|
set("preview_reduced_detail_mode", "off");
|
||||||
int stride = 4;
|
int stride = 4;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -172,6 +172,8 @@ enum class EReducedDetailMode : uint8_t
|
|||||||
LayersOnly,
|
LayersOnly,
|
||||||
// one layer in every stride, outer walls only
|
// one layer in every stride, outer walls only
|
||||||
OuterWallsOnly,
|
OuterWallsOnly,
|
||||||
|
// every layer, every role but the infill under the skins and the gap fill: what can be seen from outside
|
||||||
|
ShellOnly,
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <cfloat>
|
||||||
|
|
||||||
namespace libvgcode {
|
namespace libvgcode {
|
||||||
|
|
||||||
@@ -1194,17 +1195,34 @@ void ViewerImpl::load(GCodeInputData&& gcode_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ENABLE_OPENGL_ES
|
#ifndef ENABLE_OPENGL_ES
|
||||||
|
static bool is_outer_wall(EGCodeExtrusionRole role)
|
||||||
|
{
|
||||||
|
return role == EGCodeExtrusionRole::ExternalPerimeter || role == EGCodeExtrusionRole::OverhangPerimeter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the roles that lie under a skin or between walls, never seen from outside the print
|
||||||
|
static bool is_hidden_in_shell(EGCodeExtrusionRole role)
|
||||||
|
{
|
||||||
|
return role == EGCodeExtrusionRole::InternalInfill ||
|
||||||
|
role == EGCodeExtrusionRole::SolidInfill ||
|
||||||
|
role == EGCodeExtrusionRole::InternalBridgeInfill ||
|
||||||
|
role == EGCodeExtrusionRole::GapFill;
|
||||||
|
}
|
||||||
|
|
||||||
bool ViewerImpl::reduced_set_keeps(const PathVertex& v) const
|
bool ViewerImpl::reduced_set_keeps(const PathVertex& v) const
|
||||||
{
|
{
|
||||||
switch (m_settings.reduced_detail_mode) {
|
switch (m_settings.reduced_detail_mode) {
|
||||||
case EReducedDetailMode::OuterWallsOnly:
|
case EReducedDetailMode::OuterWallsOnly:
|
||||||
return v.role == EGCodeExtrusionRole::ExternalPerimeter || v.role == EGCodeExtrusionRole::OverhangPerimeter;
|
return is_outer_wall(v.role);
|
||||||
|
case EReducedDetailMode::ShellOnly:
|
||||||
|
return !is_hidden_in_shell(v.role);
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_OPENGL_ES
|
#endif // ENABLE_OPENGL_ES
|
||||||
|
|
||||||
|
|
||||||
void ViewerImpl::update_enabled_entities()
|
void ViewerImpl::update_enabled_entities()
|
||||||
{
|
{
|
||||||
if (m_vertices.empty())
|
if (m_vertices.empty())
|
||||||
@@ -1222,6 +1240,8 @@ void ViewerImpl::update_enabled_entities()
|
|||||||
std::vector<uint32_t> enabled_segments_reduced;
|
std::vector<uint32_t> enabled_segments_reduced;
|
||||||
std::vector<uint32_t> enabled_options_reduced;
|
std::vector<uint32_t> enabled_options_reduced;
|
||||||
const Interval& layers_range = m_layers.get_view_range();
|
const Interval& layers_range = m_layers.get_view_range();
|
||||||
|
// the shell mode draws every layer, the other toolpath modes one in every stride
|
||||||
|
const bool shell_reduced = reduced_mode == EReducedDetailMode::ShellOnly;
|
||||||
#endif // ENABLE_OPENGL_ES
|
#endif // ENABLE_OPENGL_ES
|
||||||
Interval range = m_view_range.get_visible();
|
Interval range = m_view_range.get_visible();
|
||||||
|
|
||||||
@@ -1276,7 +1296,7 @@ void ViewerImpl::update_enabled_entities()
|
|||||||
const bool end_layer = v.layer_id == layers_range[0] || v.layer_id == layers_range[1];
|
const bool end_layer = v.layer_id == layers_range[0] || v.layer_id == layers_range[1];
|
||||||
if (end_layer)
|
if (end_layer)
|
||||||
(v.is_option() ? enabled_options_reduced : enabled_segments_reduced).push_back(static_cast<uint32_t>(i));
|
(v.is_option() ? enabled_options_reduced : enabled_segments_reduced).push_back(static_cast<uint32_t>(i));
|
||||||
else if (reduced_mode != EReducedDetailMode::EndLayersOnly && (v.layer_id % layer_stride) == 0) {
|
else if (reduced_mode != EReducedDetailMode::EndLayersOnly && (shell_reduced || (v.layer_id % layer_stride) == 0)) {
|
||||||
if (v.is_option())
|
if (v.is_option())
|
||||||
enabled_options_reduced.push_back(static_cast<uint32_t>(i));
|
enabled_options_reduced.push_back(static_cast<uint32_t>(i));
|
||||||
else if (!v.is_extrusion() || reduced_set_keeps(v))
|
else if (!v.is_extrusion() || reduced_set_keeps(v))
|
||||||
|
|||||||
@@ -537,7 +537,7 @@ private:
|
|||||||
|
|
||||||
// The set the next draw reads from: the reduced one while dragging, if one is built.
|
// The set the next draw reads from: the reduced one while dragging, if one is built.
|
||||||
bool use_reduced_set() const { return m_settings.reduced_detail && m_settings.reduced_detail_mode != EReducedDetailMode::Off; }
|
bool use_reduced_set() const { return m_settings.reduced_detail && m_settings.reduced_detail_mode != EReducedDetailMode::Off; }
|
||||||
// Whether an extrusion segment belongs to the reduced set under the current mode
|
// Whether the extrusion segment starting at vertex v belongs to the reduced set under the current mode
|
||||||
bool reduced_set_keeps(const PathVertex& v) const;
|
bool reduced_set_keeps(const PathVertex& v) const;
|
||||||
struct ActiveSet
|
struct ActiveSet
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2069,6 +2069,8 @@ libvgcode::EReducedDetailMode GCodeViewer::reduced_detail_mode_from_string(const
|
|||||||
return libvgcode::EReducedDetailMode::LayersOnly;
|
return libvgcode::EReducedDetailMode::LayersOnly;
|
||||||
if (mode == "outer_walls")
|
if (mode == "outer_walls")
|
||||||
return libvgcode::EReducedDetailMode::OuterWallsOnly;
|
return libvgcode::EReducedDetailMode::OuterWallsOnly;
|
||||||
|
if (mode == "shell")
|
||||||
|
return libvgcode::EReducedDetailMode::ShellOnly;
|
||||||
return libvgcode::EReducedDetailMode::Off;
|
return libvgcode::EReducedDetailMode::Off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ public:
|
|||||||
// while the user drags the camera or a slider, draw the reduced set, if the preference asks for one
|
// while the user drags the camera or a slider, draw the reduced set, if the preference asks for one
|
||||||
void set_interacting(bool interacting);
|
void set_interacting(bool interacting);
|
||||||
bool is_reduced_detail() const { return m_viewer.is_reduced_detail(); }
|
bool is_reduced_detail() const { return m_viewer.is_reduced_detail(); }
|
||||||
// the preference's string value: "off", "solid", "layers" or "outer_walls"
|
// the preference's string value: "off", "solid", "layers", "outer_walls" or "shell"
|
||||||
void set_reduced_detail_mode(const std::string& mode);
|
void set_reduced_detail_mode(const std::string& mode);
|
||||||
void set_reduced_detail_layer_stride(unsigned int value);
|
void set_reduced_detail_layer_stride(unsigned int value);
|
||||||
|
|
||||||
|
|||||||
@@ -2065,10 +2065,12 @@ void PreferencesDialog::create_items()
|
|||||||
"with its bottom and top layers drawn as toolpaths. Supports are not shown, and negative volumes are not cut out.\n"
|
"with its bottom and top layers drawn as toolpaths. Supports are not shown, and negative volumes are not cut out.\n"
|
||||||
"Skip layers: the toolpaths of one layer in every N, set below.\n"
|
"Skip layers: the toolpaths of one layer in every N, set below.\n"
|
||||||
"Outer walls: only the outer walls of one layer in every N. The prime tower and supports are left out.\n"
|
"Outer walls: only the outer walls of one layer in every N. The prime tower and supports are left out.\n"
|
||||||
|
"Shell only: every layer without its sparse infill, internal solid infill and gap fill, which lie under the walls and skins. "
|
||||||
|
"Walls, top and bottom surfaces, bridges, supports and the prime tower are drawn whole, so the print looks the same from outside.\n"
|
||||||
"The bottom and top of the visible layer range are always drawn whole."),
|
"The bottom and top of the visible layer range are always drawn whole."),
|
||||||
"preview_reduced_detail_mode",
|
"preview_reduced_detail_mode",
|
||||||
{_L("Off"), _L("Solid model"), _L("Skip layers"), _L("Outer walls")},
|
{_L("Off"), _L("Solid model"), _L("Skip layers"), _L("Outer walls"), _L("Shell only")},
|
||||||
{"off", "solid", "layers", "outer_walls"},
|
{"off", "solid", "layers", "outer_walls", "shell"},
|
||||||
// apply the new mode immediately to the currently loaded preview
|
// apply the new mode immediately to the currently loaded preview
|
||||||
[this](std::string value) {
|
[this](std::string value) {
|
||||||
if (m_reduced_detail_layer_stride_input)
|
if (m_reduced_detail_layer_stride_input)
|
||||||
|
|||||||
Reference in New Issue
Block a user