mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-08 00:01:09 +00:00
Merge upstream/main into belt-printer
Brings belt-printer up to main4b4a261787. Resolutions: - G-code header (#15897, #15915): main moved the header, config and thumbnail block later in _do_export; write_belt_header() moves with it, still after the thumbnails and outside the BTT_TFT gate. - _extrude: first-layer acceleration keeps the per-path first-layer plane test with main's cached nozzle index (#16028); main's set_speed out-param form (#16108) everywhere else. - GCodeWriter (#16108): the arc-to-polyline fallback for machine mappings that cannot express G2/G3 now runs in the out-param extrude_arc_to_xy, which is the overload GCode calls, and appends to the caller's string. - GCodeProcessorResult: the belt fields join main's forwarding assign. - Clipper2 (#15969): belt arrange helpers take Slic3r::Point; the tree support join types lose their ClipperLib qualifier. - CLI arrange (#15837): belt printers still reserve no wipe tower. - Wipe tower options (#15841): the two new sparse-layer toggles are hidden for belt printers like the rest of the tower options. - Keyboard shortcuts (#15706): main's registry replaces the old key switch; the belt view toggle is re-registered in the next commit. - Print::process: the belt purge-plan undo runs before main's SliceStarted event. - scripts/filament_id_snapshot.json: deleted on main (a77209af8f). - Includes and appended tests: union of both sides.
This commit is contained in:
+258
-45
@@ -17,6 +17,7 @@
|
||||
#include "Plater.hpp"
|
||||
#include "Camera.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "format.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
@@ -29,12 +30,61 @@
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "Widgets/ProgressDialog.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
#include <string>
|
||||
#include "libvgcode/include/Types.hpp"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <cstdio>
|
||||
#include "libslic3r/Technologies.hpp"
|
||||
#include <imgui.h>
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#include "slic3r/GUI/GLShader.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include <math.h>
|
||||
#include "libvgcode/include/Viewer.hpp"
|
||||
#include "libvgcode/include/PathVertex.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include "slic3r/GUI/LibVGCode/LibVGCodeWrapper.hpp"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
#include "slic3r/GUI/IMSlider.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include <exception>
|
||||
#include <iterator>
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "libvgcode/include/GCodeInputData.hpp"
|
||||
#include "libvgcode/include/ColorRange.hpp"
|
||||
#include <optional>
|
||||
#include "libslic3r_version.h"
|
||||
#include <wx/busycursor.h>
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#include "libslic3r/Color.hpp"
|
||||
#include <map>
|
||||
#include "libslic3r/PrintBase.hpp"
|
||||
#include <wx/event.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/slider.h>
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/GUI/Event.hpp"
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
#include "libslic3r/CustomGCode.hpp"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
#include <glad/gl.h>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
@@ -105,6 +155,31 @@ static std::string get_view_type_string(libvgcode::EViewType view_type)
|
||||
return "";
|
||||
}
|
||||
|
||||
// ORCA: Stable, locale independent names used to persist a view type in the application config.
|
||||
// Keep these in sync with the entries of libvgcode::EViewType exposed in the preview combo box.
|
||||
static const std::vector<std::pair<std::string, libvgcode::EViewType>>& view_type_config_map()
|
||||
{
|
||||
static const std::vector<std::pair<std::string, libvgcode::EViewType>> map = {
|
||||
{ "summary", libvgcode::EViewType::Summary },
|
||||
{ "feature_type", libvgcode::EViewType::FeatureType },
|
||||
{ "color_print", libvgcode::EViewType::ColorPrint },
|
||||
{ "speed", libvgcode::EViewType::Speed },
|
||||
{ "actual_speed", libvgcode::EViewType::ActualSpeed },
|
||||
{ "acceleration", libvgcode::EViewType::Acceleration },
|
||||
{ "jerk", libvgcode::EViewType::Jerk },
|
||||
{ "height", libvgcode::EViewType::Height },
|
||||
{ "width", libvgcode::EViewType::Width },
|
||||
{ "volumetric_flow_rate", libvgcode::EViewType::VolumetricFlowRate },
|
||||
{ "actual_volumetric_flow_rate", libvgcode::EViewType::ActualVolumetricFlowRate },
|
||||
{ "layer_time_linear", libvgcode::EViewType::LayerTimeLinear },
|
||||
{ "layer_time_logarithmic", libvgcode::EViewType::LayerTimeLogarithmic },
|
||||
{ "fan_speed", libvgcode::EViewType::FanSpeed },
|
||||
{ "temperature", libvgcode::EViewType::Temperature },
|
||||
{ "pressure_advance", libvgcode::EViewType::PressureAdvance },
|
||||
};
|
||||
return map;
|
||||
}
|
||||
|
||||
// Find an index of a value in a sorted vector, which is in <z-eps, z+eps>.
|
||||
// Returns -1 if there is no such member.
|
||||
static int find_close_layer_idx(const std::vector<double> &zs, double &z, double eps)
|
||||
@@ -998,13 +1073,17 @@ void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file()
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished mapping file " << m_filename;
|
||||
}
|
||||
}
|
||||
void GCodeViewer::SequentialView::render(const bool has_render_path, float legend_height, const libvgcode::Viewer* viewer, uint32_t gcode_id, int canvas_width, int canvas_height, int right_margin, const libvgcode::EViewType& view_type)
|
||||
void GCodeViewer::SequentialView::render_marker(const bool has_render_path, int canvas_width, int canvas_height, const libvgcode::EViewType& view_type)
|
||||
{
|
||||
if (has_render_path && m_show_marker) {
|
||||
if (has_render_path && m_show_marker)
|
||||
// marker.set_world_offset(current_offset);
|
||||
marker.render(canvas_width, canvas_height, view_type);
|
||||
}
|
||||
|
||||
void GCodeViewer::SequentialView::render_overlay(const bool has_render_path, float legend_height, const libvgcode::Viewer* viewer, uint32_t gcode_id, int canvas_width, int canvas_height, int right_margin, const libvgcode::EViewType& view_type)
|
||||
{
|
||||
if (has_render_path && m_show_marker)
|
||||
marker.render_position_window(viewer, canvas_width, canvas_height, view_type);
|
||||
}
|
||||
|
||||
//float bottom = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_height();
|
||||
// BBS
|
||||
@@ -1088,9 +1167,7 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle)
|
||||
// Default view type at first slice.
|
||||
// May be overridden in load() once we know how many tools are actually used in the G-code.
|
||||
m_nozzle_nums = preset_bundle ? preset_bundle->get_printer_extruder_count() : 1;
|
||||
auto it = std::find(view_type_items.begin(), view_type_items.end(), libvgcode::EViewType::FeatureType);
|
||||
m_view_type_sel = (it != view_type_items.end()) ? std::distance(view_type_items.begin(), it) : 0;
|
||||
set_view_type(libvgcode::EViewType::FeatureType);
|
||||
apply_default_view_type();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": finished");
|
||||
}
|
||||
@@ -1111,6 +1188,73 @@ void GCodeViewer::set_scale(float scale)
|
||||
}
|
||||
}
|
||||
|
||||
// ORCA: Preview default view type preference, see "preview_default_view_type" in the application config.
|
||||
std::string GCodeViewer::view_type_to_config_name(libvgcode::EViewType type)
|
||||
{
|
||||
for (const auto& [name, value] : view_type_config_map()) {
|
||||
if (value == type)
|
||||
return name;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool GCodeViewer::view_type_from_config_name(const std::string& name, libvgcode::EViewType& type)
|
||||
{
|
||||
for (const auto& [config_name, value] : view_type_config_map()) {
|
||||
if (config_name == name) {
|
||||
type = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> GCodeViewer::default_view_type_choices()
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> choices = {
|
||||
{ "auto", _u8L("Automatic") },
|
||||
{ "last", _u8L("Last used") },
|
||||
};
|
||||
for (const auto& [name, type] : view_type_config_map())
|
||||
choices.push_back({ name, get_view_type_string(type) });
|
||||
return choices;
|
||||
}
|
||||
|
||||
void GCodeViewer::select_view_type(libvgcode::EViewType type)
|
||||
{
|
||||
auto it = std::find(view_type_items.begin(), view_type_items.end(), type);
|
||||
m_view_type_sel = (it != view_type_items.end()) ? static_cast<int>(std::distance(view_type_items.begin(), it)) : 0;
|
||||
set_view_type(type);
|
||||
}
|
||||
|
||||
// ORCA: Pick the view type the preview opens with, following the "preview_default_view_type" preference:
|
||||
// a fixed view type, the one the user picked last ("last"), or the automatic choice ("auto", the default)
|
||||
// which shows Filament for multi material prints and Line Type for single material ones.
|
||||
// The default is only (re)applied when it actually changes, so a view type picked by hand survives a reslice.
|
||||
void GCodeViewer::apply_default_view_type()
|
||||
{
|
||||
const std::string preference = wxGetApp().app_config->get("preview_default_view_type");
|
||||
|
||||
std::string key = preference;
|
||||
libvgcode::EViewType type = libvgcode::EViewType::FeatureType;
|
||||
if (preference == "last") {
|
||||
if (!view_type_from_config_name(wxGetApp().app_config->get("preview_last_view_type"), type))
|
||||
type = libvgcode::EViewType::FeatureType;
|
||||
}
|
||||
else if (!view_type_from_config_name(preference, type)) {
|
||||
// "auto", or an unknown value written by a newer version
|
||||
const bool multi_material = m_viewer.get_used_extruders_count() > 1;
|
||||
type = multi_material ? libvgcode::EViewType::ColorPrint : libvgcode::EViewType::FeatureType;
|
||||
key = multi_material ? "auto_multi_material" : "auto_single_material";
|
||||
}
|
||||
|
||||
if (m_applied_default_view_type_key == key)
|
||||
return;
|
||||
|
||||
m_applied_default_view_type_key = key;
|
||||
select_view_type(type);
|
||||
}
|
||||
|
||||
void GCodeViewer::update_by_mode(ConfigOptionMode mode)
|
||||
{
|
||||
view_type_items.clear();
|
||||
@@ -1517,6 +1661,7 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
|
||||
libvgcode::EGCodeExtrusionRole::SupportTransition, libvgcode::EGCodeExtrusionRole::Mixed
|
||||
});
|
||||
m_paths_bounding_box = BoundingBoxf3(libvgcode::convert(bbox[0]).cast<double>(), libvgcode::convert(bbox[1]).cast<double>());
|
||||
m_max_bounding_box = m_paths_bounding_box;
|
||||
|
||||
if (wxGetApp().is_editor()) {
|
||||
if (is_belt) {
|
||||
@@ -1571,27 +1716,8 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
|
||||
|
||||
// load_toolpaths(gcode_result, build_volume, exclude_bounding_box);
|
||||
|
||||
// ORCA: Apply smart default view type when extruder count changes.
|
||||
// Multi-color: ColorPrint (Filament), Single-color: FeatureType (Line Type).
|
||||
// User selections persist within same extruder count, defaults reapply on count change.
|
||||
int current_count = m_viewer.get_used_extruders_count();
|
||||
if (current_count > 1) {
|
||||
if (m_last_extruder_count_default_applied != 2) {
|
||||
auto it = std::find(view_type_items.begin(), view_type_items.end(), libvgcode::EViewType::ColorPrint);
|
||||
if (it != view_type_items.end())
|
||||
m_view_type_sel = std::distance(view_type_items.begin(), it);
|
||||
set_view_type(libvgcode::EViewType::ColorPrint);
|
||||
m_last_extruder_count_default_applied = 2;
|
||||
}
|
||||
} else {
|
||||
if (m_last_extruder_count_default_applied != 1) {
|
||||
auto it = std::find(view_type_items.begin(), view_type_items.end(), libvgcode::EViewType::FeatureType);
|
||||
if (it != view_type_items.end())
|
||||
m_view_type_sel = std::distance(view_type_items.begin(), it);
|
||||
set_view_type(libvgcode::EViewType::FeatureType);
|
||||
m_last_extruder_count_default_applied = 1;
|
||||
}
|
||||
}
|
||||
// ORCA: Apply the default view type now that we know how many tools the G-code actually uses.
|
||||
apply_default_view_type();
|
||||
|
||||
// BBS: data for rendering color arrangement recommendation
|
||||
m_nozzle_nums = print.config().option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
@@ -1799,16 +1925,88 @@ void GCodeViewer::reset()
|
||||
}
|
||||
|
||||
//BBS: GUI refactor: add canvas width and height
|
||||
void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
||||
void GCodeViewer::render_scene(int canvas_width, int canvas_height)
|
||||
{
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
render_shells(canvas_width, canvas_height);
|
||||
|
||||
if (m_viewer.get_extrusion_roles().empty())
|
||||
if (m_viewer.get_extrusion_roles_count() == 0)
|
||||
return;
|
||||
|
||||
render_toolpaths();
|
||||
|
||||
auto current = m_viewer.get_view_visible_range();
|
||||
auto endpoints = m_viewer.get_view_full_range();
|
||||
m_sequential_view.m_show_marker = m_sequential_view.m_show_marker || (current.back() != endpoints.back() && !m_no_render_path);
|
||||
const libvgcode::PathVertex& curr_vertex = m_viewer.get_current_vertex();
|
||||
m_sequential_view.marker.set_world_position(libvgcode::convert(curr_vertex.position));
|
||||
m_sequential_view.marker.set_z_offset(m_z_offset + 0.5f);
|
||||
m_sequential_view.render_marker(!m_no_render_path, canvas_width, sequential_view_height(canvas_height), m_viewer.get_view_type());
|
||||
}
|
||||
|
||||
size_t GCodeViewer::shadow_casters_signature() const
|
||||
{
|
||||
size_t hash = m_viewer.get_vertices_count();
|
||||
const libvgcode::Interval& visible = m_viewer.get_view_visible_range();
|
||||
const libvgcode::Interval& layers = m_viewer.get_layers_view_range();
|
||||
for (size_t value : { size_t(visible[0]), size_t(visible[1]), size_t(layers[0]), size_t(layers[1]) })
|
||||
boost::hash_combine(hash, value);
|
||||
for (double value : { m_paths_bounding_box.min.x(), m_paths_bounding_box.min.y(), m_paths_bounding_box.min.z(),
|
||||
m_paths_bounding_box.max.x(), m_paths_bounding_box.max.y(), m_paths_bounding_box.max.z() })
|
||||
boost::hash_combine(hash, value);
|
||||
boost::hash_combine(hash, m_viewer.is_top_layer_only_view_range());
|
||||
for (size_t i = 0; i < libvgcode::GCODE_EXTRUSION_ROLES_COUNT; ++i)
|
||||
boost::hash_combine(hash, m_viewer.is_extrusion_role_visible(libvgcode::EGCodeExtrusionRole(i)));
|
||||
boost::hash_combine(hash, m_viewer.is_option_visible(libvgcode::EOptionType::Travels));
|
||||
boost::hash_combine(hash, m_viewer.is_option_visible(libvgcode::EOptionType::Wipes));
|
||||
for (float value : m_clipping_plane)
|
||||
boost::hash_combine(hash, value);
|
||||
return hash;
|
||||
}
|
||||
|
||||
void GCodeViewer::render_shadow_casters(const Transform3d& light_view_matrix, const Transform3d& light_projection_matrix, const Vec3d& light_position)
|
||||
{
|
||||
if (!has_data())
|
||||
return;
|
||||
|
||||
m_viewer.render_shadow_casters(
|
||||
libvgcode::convert(static_cast<Matrix4f>(light_view_matrix.matrix().cast<float>())),
|
||||
libvgcode::convert(static_cast<Matrix4f>(light_projection_matrix.matrix().cast<float>())),
|
||||
libvgcode::convert(static_cast<Vec3f>(light_position.cast<float>())));
|
||||
}
|
||||
|
||||
void GCodeViewer::set_shadow_map(int texture_unit, const Transform3d& light_view_projection, float intensity, float texel_size)
|
||||
{
|
||||
m_viewer.set_shadow_map(texture_unit,
|
||||
libvgcode::convert(static_cast<Matrix4f>(light_view_projection.matrix().cast<float>())),
|
||||
intensity, texel_size);
|
||||
}
|
||||
|
||||
void GCodeViewer::set_light_top_dir(const Vec3d& direction)
|
||||
{
|
||||
m_viewer.set_light_top_dir(libvgcode::convert(static_cast<Vec3f>(direction.cast<float>())));
|
||||
}
|
||||
|
||||
void GCodeViewer::set_tone(float exposure, float saturation)
|
||||
{
|
||||
m_viewer.set_tone(exposure, saturation);
|
||||
}
|
||||
|
||||
void GCodeViewer::set_clipping_plane(const ClippingPlane& plane)
|
||||
{
|
||||
// Flipped to match ClippingPlane::distance().
|
||||
const Vec3f normal = -plane.get_normal().cast<float>();
|
||||
m_clipping_plane = plane.is_active() ?
|
||||
std::array<float, 4>{ normal.x(), normal.y(), normal.z(), float(plane.get_offset()) } :
|
||||
std::array<float, 4>{ 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
m_viewer.set_clipping_plane(m_clipping_plane);
|
||||
}
|
||||
|
||||
void GCodeViewer::render_overlay(int canvas_width, int canvas_height, int right_margin)
|
||||
{
|
||||
if (m_viewer.get_extrusion_roles().empty())
|
||||
return;
|
||||
|
||||
float legend_height = 0.0f;
|
||||
render_legend(legend_height, canvas_width, canvas_height, right_margin);
|
||||
|
||||
@@ -1817,16 +2015,7 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
||||
m_user_mode = wxGetApp().get_mode();
|
||||
}
|
||||
|
||||
//BBS fixed bottom_margin for space to render horiz slider
|
||||
int bottom_margin = SLIDER_BOTTOM_MARGIN * GCODE_VIEWER_SLIDER_SCALE;
|
||||
auto current = m_viewer.get_view_visible_range();
|
||||
auto endpoints = m_viewer.get_view_full_range();
|
||||
m_sequential_view.m_show_marker = m_sequential_view.m_show_marker || (current.back() != endpoints.back() && !m_no_render_path);
|
||||
const libvgcode::PathVertex& curr_vertex = m_viewer.get_current_vertex();
|
||||
m_sequential_view.marker.set_world_position(libvgcode::convert(curr_vertex.position));
|
||||
m_sequential_view.marker.set_z_offset(m_z_offset + 0.5f);
|
||||
// BBS fixed buttom margin. m_moves_slider.pos_y
|
||||
m_sequential_view.render(!m_no_render_path, legend_height, &m_viewer, m_viewer.get_current_vertex().gcode_id, canvas_width, canvas_height - bottom_margin * m_scale, right_margin * m_scale, m_viewer.get_view_type());
|
||||
m_sequential_view.render_overlay(!m_no_render_path, legend_height, &m_viewer, m_viewer.get_current_vertex().gcode_id, canvas_width, sequential_view_height(canvas_height), right_margin * m_scale, m_viewer.get_view_type());
|
||||
|
||||
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
if (is_legend_shown()) {
|
||||
@@ -1867,6 +2056,14 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
||||
render_slider(canvas_width, canvas_height);
|
||||
}
|
||||
|
||||
int GCodeViewer::sequential_view_height(int canvas_height) const
|
||||
{
|
||||
//BBS fixed bottom_margin for space to render horiz slider
|
||||
const int bottom_margin = SLIDER_BOTTOM_MARGIN * GCODE_VIEWER_SLIDER_SCALE;
|
||||
// BBS fixed buttom margin. m_moves_slider.pos_y
|
||||
return canvas_height - bottom_margin * m_scale;
|
||||
}
|
||||
|
||||
#define ENABLE_CALIBRATION_THUMBNAIL_OUTPUT 0
|
||||
#if ENABLE_CALIBRATION_THUMBNAIL_OUTPUT
|
||||
static void debug_calibration_output_thumbnail(const ThumbnailData& thumbnail_data)
|
||||
@@ -3597,6 +3794,12 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
std::vector<std::pair<ColorRGBA, std::pair<double, double>>> ret;
|
||||
ret.reserve(custom_gcode_per_print_z.size());
|
||||
|
||||
// Loop invariant, but built lazily: this lambda runs once per extruder on every frame
|
||||
// and most prints reach neither colour change below, so fetching it up front would cost
|
||||
// more than the per-item fetch it replaces.
|
||||
std::vector<float> zs;
|
||||
bool zs_built = false;
|
||||
|
||||
for (const auto& item : custom_gcode_per_print_z) {
|
||||
if (extruder_id + 1 != static_cast<unsigned char>(item.extruder))
|
||||
continue;
|
||||
@@ -3604,7 +3807,10 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
if (item.type != ColorChange)
|
||||
continue;
|
||||
|
||||
const std::vector<float> zs = m_viewer.get_layers_zs();
|
||||
if (!zs_built) {
|
||||
zs = m_viewer.get_layers_zs();
|
||||
zs_built = true;
|
||||
}
|
||||
auto lower_b = std::lower_bound(zs.begin(), zs.end(),
|
||||
static_cast<float>(item.print_z - epsilon()));
|
||||
if (lower_b == zs.end())
|
||||
@@ -3625,16 +3831,18 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Whole sentences: the bare "up to"/"above"/"from"/"to" these used to be glued from gave a
|
||||
// translator no context, and left the unit and the numbers stuck in English word order.
|
||||
auto upto_label = [](double z) {
|
||||
char buf[64];
|
||||
::sprintf(buf, "%.2f", z);
|
||||
return _u8L("up to") + " " + std::string(buf) + " " + _u8L("mm");
|
||||
return format(_u8L("up to %1% mm"), buf);
|
||||
};
|
||||
|
||||
auto above_label = [](double z) {
|
||||
char buf[64];
|
||||
::sprintf(buf, "%.2f", z);
|
||||
return _u8L("above") + " " + std::string(buf) + " " + _u8L("mm");
|
||||
return format(_u8L("above %1% mm"), buf);
|
||||
};
|
||||
|
||||
auto fromto_label = [](double z1, double z2) {
|
||||
@@ -3642,7 +3850,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
::sprintf(buf1, "%.2f", z1);
|
||||
char buf2[64];
|
||||
::sprintf(buf2, "%.2f", z2);
|
||||
return _u8L("from") + " " + std::string(buf1) + " " + _u8L("to") + " " + std::string(buf2) + " " + _u8L("mm");
|
||||
return format(_u8L("from %1% to %2% mm"), buf1, buf2);
|
||||
};
|
||||
|
||||
auto role_time_and_percent = [this, total_estimated_time](libvgcode::EGCodeExtrusionRole role) {
|
||||
@@ -3727,6 +3935,10 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
m_view_type_sel = i;
|
||||
set_view_type(view_type_items[m_view_type_sel]);
|
||||
reset_visible(view_type_items[m_view_type_sel]);
|
||||
// ORCA: remember the pick so the "Last used" preview default can restore it
|
||||
const std::string view_type_name = view_type_to_config_name(view_type_items[m_view_type_sel]);
|
||||
if (!view_type_name.empty())
|
||||
wxGetApp().app_config->set("preview_last_view_type", view_type_name);
|
||||
update_moves_slider();
|
||||
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
||||
imgui.set_requires_extra_frame();
|
||||
@@ -4751,6 +4963,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
|
||||
// ORCA: Get layer Zs as doubles
|
||||
std::vector<double> layer_zs = get_layers_zs();
|
||||
// loop invariant, same reason as the layer Zs above
|
||||
const std::vector<float> layer_times = m_viewer.get_layers_estimated_times();
|
||||
|
||||
for (Slic3r::CustomGCode::Item custom_gcode : custom_gcode_per_print_z) {
|
||||
ImGui::Dummy({window_padding, window_padding});
|
||||
@@ -4770,7 +4984,6 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
imgui.text(buf);
|
||||
ImGui::SameLine(max_len * 1.5);
|
||||
|
||||
std::vector<float> layer_times = m_viewer.get_layers_estimated_times();
|
||||
float custom_gcode_time = 0;
|
||||
if (layer > 0)
|
||||
{
|
||||
@@ -4819,7 +5032,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
std::string print_str = _u8L("Model printing time");
|
||||
std::string total_str = _u8L("Total time");
|
||||
float max_len = window_padding + 2 * ImGui::GetStyle().ItemSpacing.x;
|
||||
if (m_viewer.get_layers_estimated_times().empty())
|
||||
if (m_viewer.get_layers_count() == 0)
|
||||
max_len += ImGui::CalcTextSize(total_str.c_str()).x;
|
||||
else {
|
||||
if (m_viewer.get_view_type() == libvgcode::EViewType::FeatureType)
|
||||
|
||||
Reference in New Issue
Block a user