mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-18 13:10:54 +00:00
Sync upstream main
Includes nozzle-diameter guards for printers without nozzle info (#13255, now landed upstream) and manual-calibration nozzle mismatch fix (#13882). # Conflicts: # src/slic3r/GUI/GCodeViewer.cpp # src/slic3r/GUI/GLCanvas3D.hpp # src/slic3r/GUI/Tab.cpp
This commit is contained in:
commit
9b3c1b87f4
725 files changed
+23746
-9117
No files matched your search
+191
-17
@@ -14,6 +14,7 @@
|
||||
#include "libslic3r/Technologies.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "GLShader.hpp"
|
||||
@@ -225,7 +226,7 @@ bool GLCanvas3D::LayersEditing::is_allowed() const
|
||||
|
||||
float GLCanvas3D::LayersEditing::s_overlay_window_width;
|
||||
|
||||
void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanvas3D& canvas) {
|
||||
void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(GLCanvas3D& canvas) {
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
@@ -335,8 +336,23 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
|
||||
GLGizmoUtils::render_tooltip_button(&imgui, canvas, shortcuts, x, y);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (imgui.button(_L("Reset")))
|
||||
wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE));
|
||||
imgui.disabled_begin(check_object_layers_fixed(*m_slicing_parameters, m_layer_height_profile));
|
||||
if (imgui.button(_L("Reset"))) {
|
||||
wxPostEvent((wxEvtHandler*) canvas.get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE));
|
||||
}
|
||||
imgui.disabled_end();
|
||||
|
||||
ImGui::SameLine();
|
||||
GLGizmoUtils::begin_right_aligned_buttons({_L("Done")});
|
||||
if (imgui.button(_L("Done"))) {
|
||||
m_enabled = false;
|
||||
|
||||
GLToolbarItem* item = canvas.m_main_toolbar.get_item("layersediting");
|
||||
item->set_state(GLToolbarItem::Normal);
|
||||
|
||||
canvas.set_as_dirty();
|
||||
canvas.request_extra_frame();
|
||||
}
|
||||
|
||||
GLCanvas3D::LayersEditing::s_overlay_window_width = ImGui::GetWindowSize().x;
|
||||
imgui.end();
|
||||
@@ -344,7 +360,7 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
|
||||
imgui.pop_toolbar_style();
|
||||
}
|
||||
|
||||
void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas)
|
||||
void GLCanvas3D::LayersEditing::render_overlay(GLCanvas3D& canvas)
|
||||
{
|
||||
render_variable_layer_height_dialog(canvas);
|
||||
render_active_object_annotations(canvas);
|
||||
@@ -1202,6 +1218,11 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
|
||||
GLCanvas3D::~GLCanvas3D()
|
||||
{
|
||||
if (m_fxaa_texture_id != 0 && _set_current()) {
|
||||
glsafe(::glDeleteTextures(1, &m_fxaa_texture_id));
|
||||
m_fxaa_texture_id = 0;
|
||||
}
|
||||
|
||||
reset_volumes();
|
||||
|
||||
m_sel_plate_toolbar.del_all_item();
|
||||
@@ -2082,9 +2103,16 @@ void GLCanvas3D::render(bool only_init)
|
||||
if (m_picking_enabled && m_rectangle_selection.is_dragging())
|
||||
m_rectangle_selection.render(*this);
|
||||
|
||||
if (_is_fxaa_enabled())
|
||||
_render_fxaa_pass(static_cast<unsigned int>(cnv_size.get_width()), static_cast<unsigned int>(cnv_size.get_height()));
|
||||
|
||||
// draw overlays
|
||||
_render_overlays();
|
||||
|
||||
const int current_fps = m_render_stats.get_fps_and_reset_if_needed();
|
||||
if (_is_fps_overlay_enabled())
|
||||
_render_fps_overlay(current_fps);
|
||||
|
||||
if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
|
||||
ImGui::ShowMetricsWindow();
|
||||
|
||||
@@ -2092,7 +2120,7 @@ void GLCanvas3D::render(bool only_init)
|
||||
imgui.begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
imgui.text("FPS (SwapBuffers() calls per second):");
|
||||
ImGui::SameLine();
|
||||
imgui.text(std::to_string(m_render_stats.get_fps_and_reset_if_needed()));
|
||||
imgui.text(std::to_string(current_fps));
|
||||
ImGui::Separator();
|
||||
imgui.text("Compressed textures:");
|
||||
ImGui::SameLine();
|
||||
@@ -3202,6 +3230,22 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
||||
wxGetApp().imgui()->reset_requires_extra_frame();
|
||||
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
||||
|
||||
const int fps_cap = _get_effective_fps_cap();
|
||||
if (fps_cap > 0) {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto min_frame_time = std::chrono::duration<double>(1.0 / static_cast<double>(fps_cap));
|
||||
const auto elapsed = now - m_last_frame_start_time;
|
||||
if (elapsed < min_frame_time) {
|
||||
const int wait_ms = std::max(1, static_cast<int>(std::ceil(std::chrono::duration<double, std::milli>(min_frame_time - elapsed).count())));
|
||||
schedule_extra_frame(wait_ms);
|
||||
evt.RequestMore();
|
||||
return;
|
||||
}
|
||||
|
||||
// Pace by frame-start interval so rendering time is part of the target budget.
|
||||
m_last_frame_start_time = now;
|
||||
}
|
||||
|
||||
_refresh_if_shown_on_screen();
|
||||
|
||||
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
||||
@@ -4251,7 +4295,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
|
||||
bool any_gizmo_active = m_gizmos.get_current() != nullptr;
|
||||
bool swap_mouse_buttons = wxGetApp().app_config->get_bool("swap_mouse_buttons");
|
||||
|
||||
std::map<MouseButton, MouseAction> button_mappings;
|
||||
button_mappings[MouseButton::Left] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("left_mouse_drag_action").c_str()));
|
||||
button_mappings[MouseButton::Middle] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("middle_mouse_drag_action").c_str()));
|
||||
button_mappings[MouseButton::Right] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("right_mouse_drag_action").c_str()));
|
||||
|
||||
if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos)) {
|
||||
m_mouse.drag.move_requires_threshold = false;
|
||||
@@ -4466,7 +4514,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_dirty = true;
|
||||
}
|
||||
}
|
||||
else if (evt.Dragging() || is_camera_rotate(evt, swap_mouse_buttons) || is_camera_pan(evt, swap_mouse_buttons)) {
|
||||
else if (evt.Dragging() || is_camera_rotate(evt, button_mappings) || is_camera_pan(evt, button_mappings)) {
|
||||
m_mouse.dragging = true;
|
||||
|
||||
if (m_layers_editing.state != LayersEditing::Unknown && layer_editing_object_idx != -1) {
|
||||
@@ -4476,10 +4524,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
// do not process the dragging if the left mouse was set down in another canvas
|
||||
else if (is_camera_rotate(evt, swap_mouse_buttons)) {
|
||||
else if (is_camera_rotate(evt, button_mappings)) {
|
||||
// Orca: Sphere rotation for painting view
|
||||
// if dragging over blank area with left button or button functions swapped then rotate
|
||||
if ((any_gizmo_active || swap_mouse_buttons || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
|
||||
// if dragging over blank area with left button or other button mapped to rotate, then rotate
|
||||
bool middle_or_right_button_used_as_rotate = (evt.MiddleIsDown() && button_mappings[MouseButton::Middle] == MouseAction::Rotation) ||
|
||||
(evt.RightIsDown() && button_mappings[MouseButton::Right] == MouseAction::Rotation);
|
||||
if ((any_gizmo_active || middle_or_right_button_used_as_rotate || m_hover_volume_idxs.empty()) &&
|
||||
m_mouse.is_start_position_3D_defined()) {
|
||||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
auto mult_pref = wxGetApp().app_config->get("camera_orbit_mult");
|
||||
const double mult = mult_pref.empty() ? 1.0 : std::stod(mult_pref);
|
||||
@@ -4552,7 +4603,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_camera_movement = true;
|
||||
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
|
||||
}
|
||||
else if (is_camera_pan(evt, swap_mouse_buttons)) {
|
||||
else if (is_camera_pan(evt, button_mappings)) {
|
||||
// if dragging with right button or if button functions swapped and dragging with left button over blank area then pan
|
||||
if (m_mouse.is_start_position_2D_defined()) {
|
||||
// get point in model space at Z = 0
|
||||
@@ -4580,10 +4631,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
else if ((evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) ||
|
||||
(m_camera_movement && !is_camera_rotate(evt, swap_mouse_buttons) && !is_camera_pan(evt, swap_mouse_buttons))) {
|
||||
(m_camera_movement && !is_camera_rotate(evt, button_mappings) && !is_camera_pan(evt, button_mappings))) {
|
||||
m_mouse.position = pos.cast<double>();
|
||||
|
||||
if (swap_mouse_buttons ? evt.RightUp() : evt.LeftUp()) {
|
||||
// Check if the button that was released is mapped to rotation
|
||||
if ((evt.LeftUp() && button_mappings[MouseButton::Left] == MouseAction::Rotation) ||
|
||||
(evt.MiddleUp() && button_mappings[MouseButton::Middle] == MouseAction::Rotation) ||
|
||||
(evt.RightUp() && button_mappings[MouseButton::Right] == MouseAction::Rotation)) {
|
||||
m_rotation_center(0) = m_rotation_center(1) = m_rotation_center(2) = 0.f;
|
||||
}
|
||||
|
||||
@@ -4784,21 +4838,42 @@ void GLCanvas3D::on_set_focus(wxFocusEvent& evt)
|
||||
m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style");
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_camera_rotate(const wxMouseEvent& evt, const bool buttonsSwapped) const
|
||||
bool GLCanvas3D::clicked_button_matches_action(const wxMouseEvent& evt, const MouseAction action, const std::map<MouseButton, MouseAction>& mappings) const
|
||||
{
|
||||
MouseButton clicked = MouseButton::None;
|
||||
if (evt.LeftIsDown()) {
|
||||
clicked = MouseButton::Left;
|
||||
}
|
||||
if (evt.MiddleIsDown()) {
|
||||
clicked = MouseButton::Middle;
|
||||
}
|
||||
if (evt.RightIsDown()) {
|
||||
clicked = MouseButton::Right;
|
||||
}
|
||||
|
||||
auto it = mappings.find(clicked);
|
||||
if (it == mappings.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->second == action;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_camera_rotate(const wxMouseEvent& evt, const std::map<MouseButton, MouseAction>& mappings) const
|
||||
{
|
||||
if (m_is_touchpad_navigation) {
|
||||
return evt.Moving() && evt.AltDown() && !evt.ShiftDown();
|
||||
} else {
|
||||
return evt.Dragging() && (buttonsSwapped ? evt.RightIsDown() : evt.LeftIsDown());
|
||||
return evt.Dragging() && clicked_button_matches_action(evt, MouseAction::Rotation, mappings);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_camera_pan(const wxMouseEvent& evt, const bool buttonsSwapped) const
|
||||
bool GLCanvas3D::is_camera_pan(const wxMouseEvent& evt, const std::map<MouseButton, MouseAction>& mappings) const
|
||||
{
|
||||
if (m_is_touchpad_navigation) {
|
||||
return evt.Moving() && evt.ShiftDown() && !evt.AltDown();
|
||||
} else {
|
||||
return evt.Dragging() && (evt.MiddleIsDown() || (buttonsSwapped ? evt.LeftIsDown() : evt.RightIsDown()));
|
||||
return evt.Dragging() && clicked_button_matches_action(evt, MouseAction::Pan, mappings);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7621,6 +7696,105 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
_update_volumes_hover_state();
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_is_fxaa_enabled() const
|
||||
{
|
||||
return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_FXAA_ENABLED);
|
||||
}
|
||||
|
||||
int GLCanvas3D::_get_effective_fps_cap() const
|
||||
{
|
||||
if (wxGetApp().app_config == nullptr)
|
||||
return 0;
|
||||
|
||||
int fps_cap = 0;
|
||||
try {
|
||||
fps_cap = std::stoi(wxGetApp().app_config->get(SETTING_OPENGL_FPS_CAP));
|
||||
}
|
||||
catch (...) {
|
||||
fps_cap = 0;
|
||||
}
|
||||
|
||||
fps_cap = std::max(0, std::min(fps_cap, 240));
|
||||
|
||||
return fps_cap;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_is_fps_overlay_enabled() const
|
||||
{
|
||||
return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_SHOW_FPS_OVERLAY);
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_fps_overlay(int fps) const
|
||||
{
|
||||
if (fps < 0)
|
||||
return;
|
||||
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
const float margin = 10.0f * get_scale();
|
||||
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
ImGui::SetNextWindowPos(ImVec2(display_size.x - margin, margin), ImGuiCond_Always, ImVec2(1.0f, 0.0f));
|
||||
ImGui::SetNextWindowBgAlpha(0.35f);
|
||||
imgui.begin(
|
||||
std::string("###fps_overlay"),
|
||||
ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoInputs);
|
||||
imgui.text(std::string("FPS: ") + std::to_string(fps));
|
||||
imgui.end();
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_fxaa_pass(unsigned int width, unsigned int height)
|
||||
{
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("fxaa");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
if (m_fxaa_texture_id == 0) {
|
||||
glsafe(::glGenTextures(1, &m_fxaa_texture_id));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_fxaa_texture_id));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
}
|
||||
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_fxaa_texture_id));
|
||||
if (m_fxaa_texture_size[0] != width || m_fxaa_texture_size[1] != height) {
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||
m_fxaa_texture_size = { width, height };
|
||||
}
|
||||
|
||||
glsafe(::glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height));
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
glsafe(::glClear(GL_COLOR_BUFFER_BIT));
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("view_model_matrix", Transform3d::Identity());
|
||||
shader->set_uniform("projection_matrix", Transform3d::Identity());
|
||||
shader->set_uniform("uniform_texture", 0);
|
||||
shader->set_uniform("inv_tex_size", Vec2f(1.0f / static_cast<float>(width), 1.0f / static_cast<float>(height)));
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_fxaa_texture_id));
|
||||
m_background.render();
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
shader->stop_using();
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_background()
|
||||
{
|
||||
bool use_error_color = false;
|
||||
|
||||
Reference in new issue
Block a user