mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 19:31:22 +00:00
Keep Only the Solid Model and Shell Modes While Dragging
The skip-layers and outer-walls modes drew one layer in every N, and every visual complaint on the review came from the gaps that leaves at close range. The shell mode draws every layer and looks the same from outside, and the solid model is the one mode whose cost does not depend on the toolpaths, so the two of them cover what the stride modes were for. The layer stride goes with them; a saved preference naming a removed mode falls back to off.
This commit is contained in:
@@ -9,8 +9,7 @@ let go.
|
||||
|
||||
| Preference | Values | Effect |
|
||||
|---|---|---|
|
||||
| `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 skip-layers and outer-walls modes |
|
||||
| `preview_reduced_detail_mode` | `off`, `solid`, `shell` | what is drawn while dragging |
|
||||
|
||||
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.
|
||||
@@ -21,7 +20,7 @@ The OpenGL ES path keeps a single set and ignores the preference.
|
||||
`ViewerImpl::update_enabled_entities()` walks the visible vertex range once and fills two segment
|
||||
index buffers side by side: the **full** set and the **reduced** set (segments and options).
|
||||
Building them together is what makes switching free: starting or ending a drag is a buffer
|
||||
binding, never a rebuild. A change of mode or stride does rebuild. Nothing is built while the mode
|
||||
binding, never a rebuild. A change of mode does rebuild. Nothing is built while the mode
|
||||
is off, and the reduced buffers are then uploaded empty so that the last set does not stay
|
||||
allocated.
|
||||
|
||||
@@ -32,13 +31,10 @@ are the faces the range cuts open, and the top is what the user is looking at.
|
||||
|
||||
- `EndLayersOnly` (`solid` in the preference) keeps only the two end layers. `GCodeViewer` then
|
||||
draws the sliced objects and the prime tower as opaque solids, see below.
|
||||
- `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
|
||||
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
|
||||
- `ShellOnly` (`shell`) 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. 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. 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.
|
||||
|
||||
@@ -205,19 +205,11 @@ void AppConfig::set_defaults()
|
||||
if (get("seq_top_layer_only").empty())
|
||||
set("seq_top_layer_only", "1");
|
||||
|
||||
// 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
|
||||
{
|
||||
const std::string mode = get("preview_reduced_detail_mode");
|
||||
if (mode != "off" && mode != "solid" && mode != "layers" && mode != "outer_walls" && mode != "shell")
|
||||
if (mode != "off" && mode != "solid" && mode != "shell")
|
||||
set("preview_reduced_detail_mode", "off");
|
||||
int stride = 4;
|
||||
try {
|
||||
stride = std::stoi(get("preview_reduced_detail_layer_stride"));
|
||||
}
|
||||
catch (...) {
|
||||
stride = 4;
|
||||
}
|
||||
set("preview_reduced_detail_layer_stride", std::to_string(std::max(1, std::min(stride, 20))));
|
||||
}
|
||||
|
||||
// ORCA: darken the layers the preview layer slider is not scrubbed to
|
||||
|
||||
@@ -168,11 +168,7 @@ enum class EReducedDetailMode : uint8_t
|
||||
// only the bottom and top layers of the visible range, for a caller that draws the print
|
||||
// itself some other way
|
||||
EndLayersOnly,
|
||||
// one layer in every stride, every role kept
|
||||
LayersOnly,
|
||||
// one layer in every stride, outer walls only
|
||||
OuterWallsOnly,
|
||||
// every layer, every role but the infill under the skins and the gap fill: what can be seen from outside
|
||||
// every role but the infill under the skins and the gap fill: what can be seen from outside
|
||||
ShellOnly,
|
||||
COUNT
|
||||
};
|
||||
|
||||
@@ -115,15 +115,12 @@ public:
|
||||
bool is_dim_previous_layers() const;
|
||||
void set_dim_previous_layers(bool value);
|
||||
//
|
||||
// The reduced set drawn while the user drags: what the mode keeps, one layer in every stride
|
||||
// for the toolpath modes, and always the bottom and top layers of the visible range. While a
|
||||
// mode is set it is built alongside the full set, so set_reduced_detail() rebuilds nothing.
|
||||
// Ignored on the OpenGL ES path.
|
||||
// The reduced set drawn while the user drags: what the mode keeps, and always the bottom and
|
||||
// top layers of the visible range. While a mode is set it is built alongside the full set, so
|
||||
// set_reduced_detail() rebuilds nothing. Ignored on the OpenGL ES path.
|
||||
//
|
||||
EReducedDetailMode get_reduced_detail_mode() const;
|
||||
void set_reduced_detail_mode(EReducedDetailMode mode);
|
||||
uint32_t get_reduced_detail_layer_stride() const;
|
||||
void set_reduced_detail_layer_stride(uint32_t value);
|
||||
void set_reduced_detail(bool value);
|
||||
bool is_reduced_detail() const;
|
||||
float get_dim_previous_layers_brightness() const;
|
||||
|
||||
@@ -25,10 +25,8 @@ struct Settings
|
||||
// ORCA: how bright those darkened layers are rendered, 1.0 = unchanged, 0.0 = black
|
||||
float dim_previous_layers_brightness{ 0.4f };
|
||||
bool spiral_vase_mode{ false };
|
||||
// what the reduced set holds, one layer in every reduced_detail_layer_stride for the toolpath
|
||||
// modes, and whether it is drawn. Ignored on the OpenGL ES path.
|
||||
// what the reduced set holds and whether it is drawn. Ignored on the OpenGL ES path.
|
||||
EReducedDetailMode reduced_detail_mode{ EReducedDetailMode::Off };
|
||||
uint32_t reduced_detail_layer_stride{ 4 };
|
||||
bool reduced_detail{ false };
|
||||
//
|
||||
// Required update flags
|
||||
|
||||
@@ -112,16 +112,6 @@ void Viewer::set_reduced_detail_mode(EReducedDetailMode mode)
|
||||
m_impl->set_reduced_detail_mode(mode);
|
||||
}
|
||||
|
||||
uint32_t Viewer::get_reduced_detail_layer_stride() const
|
||||
{
|
||||
return m_impl->get_reduced_detail_layer_stride();
|
||||
}
|
||||
|
||||
void Viewer::set_reduced_detail_layer_stride(uint32_t value)
|
||||
{
|
||||
m_impl->set_reduced_detail_layer_stride(value);
|
||||
}
|
||||
|
||||
void Viewer::set_dim_previous_layers(bool value)
|
||||
{
|
||||
m_impl->set_dim_previous_layers(value);
|
||||
|
||||
@@ -1195,11 +1195,6 @@ void ViewerImpl::load(GCodeInputData&& gcode_data)
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
@@ -1208,18 +1203,6 @@ static bool is_hidden_in_shell(EGCodeExtrusionRole role)
|
||||
role == EGCodeExtrusionRole::InternalBridgeInfill ||
|
||||
role == EGCodeExtrusionRole::GapFill;
|
||||
}
|
||||
|
||||
bool ViewerImpl::reduced_set_keeps(const PathVertex& v) const
|
||||
{
|
||||
switch (m_settings.reduced_detail_mode) {
|
||||
case EReducedDetailMode::OuterWallsOnly:
|
||||
return is_outer_wall(v.role);
|
||||
case EReducedDetailMode::ShellOnly:
|
||||
return !is_hidden_in_shell(v.role);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_OPENGL_ES
|
||||
|
||||
|
||||
@@ -1236,12 +1219,9 @@ void ViewerImpl::update_enabled_entities()
|
||||
// surfaces the range cuts open
|
||||
const EReducedDetailMode reduced_mode = m_settings.reduced_detail_mode;
|
||||
const bool build_reduced = reduced_mode != EReducedDetailMode::Off;
|
||||
const uint32_t layer_stride = std::max<uint32_t>(1, m_settings.reduced_detail_layer_stride);
|
||||
std::vector<uint32_t> enabled_segments_reduced;
|
||||
std::vector<uint32_t> enabled_options_reduced;
|
||||
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
|
||||
Interval range = m_view_range.get_visible();
|
||||
|
||||
@@ -1296,10 +1276,10 @@ void ViewerImpl::update_enabled_entities()
|
||||
const bool end_layer = v.layer_id == layers_range[0] || v.layer_id == layers_range[1];
|
||||
if (end_layer)
|
||||
(v.is_option() ? enabled_options_reduced : enabled_segments_reduced).push_back(static_cast<uint32_t>(i));
|
||||
else if (reduced_mode != EReducedDetailMode::EndLayersOnly && (shell_reduced || (v.layer_id % layer_stride) == 0)) {
|
||||
else if (reduced_mode == EReducedDetailMode::ShellOnly) {
|
||||
if (v.is_option())
|
||||
enabled_options_reduced.push_back(static_cast<uint32_t>(i));
|
||||
else if (!v.is_extrusion() || reduced_set_keeps(v))
|
||||
else if (!v.is_extrusion() || !is_hidden_in_shell(v.role))
|
||||
enabled_segments_reduced.push_back(static_cast<uint32_t>(i));
|
||||
}
|
||||
}
|
||||
@@ -1556,7 +1536,7 @@ void ViewerImpl::toggle_top_layer_only_view_range()
|
||||
update_colors_texture();
|
||||
}
|
||||
|
||||
// Either changes which vertices land in the reduced set, so the sets are rebuilt.
|
||||
// The mode decides which vertices land in the reduced set, so the sets are rebuilt.
|
||||
void ViewerImpl::set_reduced_detail_mode(EReducedDetailMode mode)
|
||||
{
|
||||
if (m_settings.reduced_detail_mode == mode)
|
||||
@@ -1565,15 +1545,6 @@ void ViewerImpl::set_reduced_detail_mode(EReducedDetailMode mode)
|
||||
m_settings.update_enabled_entities = true;
|
||||
}
|
||||
|
||||
void ViewerImpl::set_reduced_detail_layer_stride(uint32_t value)
|
||||
{
|
||||
value = std::max<uint32_t>(1, value);
|
||||
if (m_settings.reduced_detail_layer_stride == value)
|
||||
return;
|
||||
m_settings.reduced_detail_layer_stride = value;
|
||||
m_settings.update_enabled_entities = true;
|
||||
}
|
||||
|
||||
// ORCA: enable/disable darkening of the layers the layer slider is not scrubbed to
|
||||
void ViewerImpl::set_dim_previous_layers(bool value)
|
||||
{
|
||||
|
||||
@@ -122,8 +122,6 @@ public:
|
||||
bool is_reduced_detail() const { return m_settings.reduced_detail; }
|
||||
EReducedDetailMode get_reduced_detail_mode() const { return m_settings.reduced_detail_mode; }
|
||||
void set_reduced_detail_mode(EReducedDetailMode mode);
|
||||
uint32_t get_reduced_detail_layer_stride() const { return m_settings.reduced_detail_layer_stride; }
|
||||
void set_reduced_detail_layer_stride(uint32_t value);
|
||||
float get_dim_previous_layers_brightness() const { return m_settings.dim_previous_layers_brightness; }
|
||||
void set_dim_previous_layers_brightness(float value);
|
||||
|
||||
@@ -537,8 +535,6 @@ private:
|
||||
|
||||
// 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; }
|
||||
// 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;
|
||||
struct ActiveSet
|
||||
{
|
||||
size_t count{ 0 };
|
||||
|
||||
@@ -2037,14 +2037,12 @@ void GCodeViewer::set_interacting(bool interacting)
|
||||
void GCodeViewer::read_reduced_detail_preferences()
|
||||
{
|
||||
m_reduced_detail_mode = reduced_detail_mode_from_string(get_app_config()->get("preview_reduced_detail_mode"));
|
||||
m_reduced_detail_layer_stride = static_cast<unsigned int>(std::max(1, std::stoi(get_app_config()->get("preview_reduced_detail_layer_stride"))));
|
||||
apply_reduced_detail_settings();
|
||||
}
|
||||
|
||||
void GCodeViewer::apply_reduced_detail_settings()
|
||||
{
|
||||
m_viewer.set_reduced_detail_mode(m_reduced_detail_mode);
|
||||
m_viewer.set_reduced_detail_layer_stride(m_reduced_detail_layer_stride);
|
||||
}
|
||||
|
||||
void GCodeViewer::set_reduced_detail_mode(const std::string& mode)
|
||||
@@ -2055,20 +2053,10 @@ void GCodeViewer::set_reduced_detail_mode(const std::string& mode)
|
||||
reload_shells_if_solid_model_changed(was_solid);
|
||||
}
|
||||
|
||||
void GCodeViewer::set_reduced_detail_layer_stride(unsigned int value)
|
||||
{
|
||||
m_reduced_detail_layer_stride = std::max(1u, value);
|
||||
apply_reduced_detail_settings();
|
||||
}
|
||||
|
||||
libvgcode::EReducedDetailMode GCodeViewer::reduced_detail_mode_from_string(const std::string& mode)
|
||||
{
|
||||
if (mode == "solid")
|
||||
return libvgcode::EReducedDetailMode::EndLayersOnly;
|
||||
if (mode == "layers")
|
||||
return libvgcode::EReducedDetailMode::LayersOnly;
|
||||
if (mode == "outer_walls")
|
||||
return libvgcode::EReducedDetailMode::OuterWallsOnly;
|
||||
if (mode == "shell")
|
||||
return libvgcode::EReducedDetailMode::ShellOnly;
|
||||
return libvgcode::EReducedDetailMode::Off;
|
||||
|
||||
@@ -238,7 +238,6 @@ private:
|
||||
bool m_legend_enabled{ true };
|
||||
// the reduced-detail preferences, pushed to libvgcode by apply_reduced_detail_settings()
|
||||
libvgcode::EReducedDetailMode m_reduced_detail_mode{ libvgcode::EReducedDetailMode::Off };
|
||||
unsigned int m_reduced_detail_layer_stride{ 4 };
|
||||
void read_reduced_detail_preferences();
|
||||
void apply_reduced_detail_settings();
|
||||
static libvgcode::EReducedDetailMode reduced_detail_mode_from_string(const std::string& mode);
|
||||
@@ -382,9 +381,8 @@ public:
|
||||
// while the user drags the camera or a slider, draw the reduced set, if the preference asks for one
|
||||
void set_interacting(bool interacting);
|
||||
bool is_reduced_detail() const { return m_viewer.is_reduced_detail(); }
|
||||
// the preference's string value: "off", "solid", "layers", "outer_walls" or "shell"
|
||||
// the preference's string value: "off", "solid" or "shell"
|
||||
void set_reduced_detail_mode(const std::string& mode);
|
||||
void set_reduced_detail_layer_stride(unsigned int value);
|
||||
|
||||
void set_layers_z_range(const std::array<unsigned int, 2>& layers_z_range);
|
||||
|
||||
|
||||
@@ -685,12 +685,6 @@ wxBoxSizer *PreferencesDialog::create_item_input(wxString title, wxString title2
|
||||
return m_sizer;
|
||||
}
|
||||
|
||||
// the reduced-detail modes that keep one layer in every N, so the stride applies
|
||||
static bool reduced_detail_mode_skips_layers(const std::string& mode)
|
||||
{
|
||||
return mode == "layers" || mode == "outer_walls";
|
||||
}
|
||||
|
||||
wxBoxSizer *PreferencesDialog::create_item_spinctrl(wxString title, wxString title2, wxString side_label, wxString tooltip, std::string param, int min, int max, std::function<void(int)> onchange, const wxString wiki_url)
|
||||
{
|
||||
auto tip = tooltip.IsEmpty() ? title : tooltip; // auto fill tooltips with title if its empty
|
||||
@@ -705,11 +699,6 @@ wxBoxSizer *PreferencesDialog::create_item_spinctrl(wxString title, wxString tit
|
||||
m_dim_previous_layers_brightness_input = input;
|
||||
input->Enable(app_config->get_bool("preview_dim_previous_layers"));
|
||||
}
|
||||
// only the toolpath modes skip layers
|
||||
else if (param == "preview_reduced_detail_layer_stride") {
|
||||
m_reduced_detail_layer_stride_input = input;
|
||||
input->Enable(reduced_detail_mode_skips_layers(app_config->get("preview_reduced_detail_mode")));
|
||||
}
|
||||
|
||||
m_sizer->Add(input, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
@@ -2063,18 +2052,14 @@ void PreferencesDialog::create_items()
|
||||
"Off: the full toolpaths.\n"
|
||||
"Solid model: the sliced objects and the prime tower as solid shapes in their filament colors, cut to the visible layer range, "
|
||||
"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"
|
||||
"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."),
|
||||
"preview_reduced_detail_mode",
|
||||
{_L("Off"), _L("Solid model"), _L("Skip layers"), _L("Outer walls"), _L("Shell only")},
|
||||
{"off", "solid", "layers", "outer_walls", "shell"},
|
||||
{_L("Off"), _L("Solid model"), _L("Shell only")},
|
||||
{"off", "solid", "shell"},
|
||||
// apply the new mode immediately to the currently loaded preview
|
||||
[this](std::string value) {
|
||||
if (m_reduced_detail_layer_stride_input)
|
||||
m_reduced_detail_layer_stride_input->Enable(reduced_detail_mode_skips_layers(value));
|
||||
[](std::string value) {
|
||||
if (Plater* plater = wxGetApp().plater()) {
|
||||
if (GLCanvas3D* canvas = plater->get_preview_canvas3D()) {
|
||||
canvas->get_gcode_viewer().set_reduced_detail_mode(value);
|
||||
@@ -2086,27 +2071,6 @@ void PreferencesDialog::create_items()
|
||||
);
|
||||
g_sizer->Add(item_reduced_detail_mode);
|
||||
|
||||
auto item_reduced_detail_layer_stride = create_item_spinctrl(
|
||||
_L("Draw one layer in every"),
|
||||
"",
|
||||
_L("layers"),
|
||||
_L("How many layers the simplified preview keeps one of while dragging: 1 draws every layer, 4 draws every fourth."),
|
||||
"preview_reduced_detail_layer_stride",
|
||||
1,
|
||||
20,
|
||||
// apply the new stride immediately to the currently loaded preview
|
||||
[](int value) {
|
||||
if (Plater* plater = wxGetApp().plater()) {
|
||||
if (GLCanvas3D* canvas = plater->get_preview_canvas3D()) {
|
||||
canvas->get_gcode_viewer().set_reduced_detail_layer_stride(static_cast<unsigned int>(value));
|
||||
canvas->set_as_dirty();
|
||||
canvas->request_extra_frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
g_sizer->Add(item_reduced_detail_layer_stride);
|
||||
|
||||
auto item_dim_previous_layers = create_item_checkbox(
|
||||
_L("Dim lower layers"),
|
||||
_L("When scrubbing the layer slider in the sliced preview, render the layers below the current one darkened so that only the layer being viewed is shown at full brightness."),
|
||||
|
||||
@@ -80,7 +80,6 @@ public:
|
||||
::CheckBox * m_skip_identical_frames_checkbox = {nullptr};
|
||||
::TextInput *m_backup_interval_textinput = {nullptr};
|
||||
::SpinInput *m_dim_previous_layers_brightness_input = {nullptr};
|
||||
::SpinInput *m_reduced_detail_layer_stride_input = {nullptr};
|
||||
::ComboBox * m_network_version_combo = {nullptr};
|
||||
std::vector<NetworkLibraryVersionInfo> m_available_versions;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user