mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 19:01:02 +00:00
Merge branch 'main' into dev/ams-heat
This commit is contained in:
@@ -324,10 +324,12 @@ AboutDialog::AboutDialog()
|
||||
m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
|
||||
m_html->SetMinSize(wxSize(FromDIP(-1), FromDIP(16)));
|
||||
m_html->SetBorders(2);
|
||||
wxColour bgr_clr = GetBackgroundColour();
|
||||
const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()));
|
||||
const auto text = from_u8(
|
||||
(boost::format(
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<body bgcolor= \"" + bgr_clr_str + "\" >"
|
||||
"<p style=\"text-align:left\"><a style=\"color:#009789\" href=\"https://www.orcaslicer.com\">https://www.orcaslicer.com</ a></p>"
|
||||
"</body>"
|
||||
"</html>")
|
||||
|
||||
@@ -569,7 +569,7 @@ void MaterialSyncItem::doRender(wxDC &dc)
|
||||
dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5);
|
||||
|
||||
if (m_selected) {
|
||||
dc.SetPen(wxColour(0x00, 0xAE, 0x42));
|
||||
dc.SetPen(wxColour("#009688")); // ORCA selected item border color
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5);
|
||||
}
|
||||
@@ -580,7 +580,7 @@ void MaterialSyncItem::doRender(wxDC &dc)
|
||||
dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5);
|
||||
|
||||
if (m_selected) {
|
||||
dc.SetPen(wxPen(wxColour(0x00, 0xAE, 0x42), FromDIP(2)));
|
||||
dc.SetPen(wxPen(wxColour("#009688"), FromDIP(2))); // ORCA selected item border color
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_SIZE.x - FromDIP(1), MATERIAL_ITEM_SIZE.y - FromDIP(1), 5);
|
||||
}
|
||||
@@ -813,7 +813,7 @@ void AmsMapingPopup::msw_rescale()
|
||||
m_split_left_line->SetMaxSize(wxSize(-1, 1));
|
||||
sizer_split_ams->Add(0, 0, 0, wxEXPAND, 0);
|
||||
sizer_split_ams->Add(ams_title_text, 0, wxALIGN_CENTER, 0);
|
||||
sizer_split_ams->Add(m_split_left_line, 1, wxEXPAND, 0);
|
||||
sizer_split_ams->Add(m_split_left_line, 1, wxALIGN_CENTER, 0); // ORCA align line vertically
|
||||
return sizer_split_ams;
|
||||
}
|
||||
|
||||
@@ -1420,7 +1420,7 @@ bool AmsMapingPopup::ProcessLeftDown(wxMouseEvent &event)
|
||||
void AmsMapingPopup::paintEvent(wxPaintEvent &evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
|
||||
dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#009688")),FromDIP(2))); // ORCA use colorful border for separation
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0);
|
||||
}
|
||||
@@ -2281,7 +2281,7 @@ AmsRMGroup* AmsReplaceMaterialDialog::create_backup_group(wxString gname, std::m
|
||||
void AmsReplaceMaterialDialog::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
|
||||
dc.SetPen(StateColor::darkModeColorFor(wxColour("#DBDBDB"))); // ORCA fix popup border color for dark mode
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,19 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame(
|
||||
// SetBackgroundStyle(wxBackgroundStyle::wxBG_STYLE_TRANSPARENT);
|
||||
SetTransparent(m_init_transparent);
|
||||
SetBackgroundColour(wxColour(23, 25, 22, 128));
|
||||
|
||||
// ORCA add border
|
||||
Bind(wxEVT_PAINT, [this](wxPaintEvent& evt) {
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#009688")), FromDIP(2)));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0);
|
||||
});
|
||||
|
||||
int window_padding = 15;
|
||||
auto imgsize = 32;
|
||||
auto imgright = 10;
|
||||
|
||||
//Adaptive Frame Width
|
||||
wxClientDC dc(parent);
|
||||
wxSize msg_sz = dc.GetMultiLineTextExtent(ok_text);
|
||||
@@ -44,21 +57,16 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame(
|
||||
|
||||
m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *text_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
text_sizer->AddSpacer(FromDIP(20));
|
||||
auto image_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto imgsize = FromDIP(25);
|
||||
auto completedimg = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("completed", this, 25), wxDefaultPosition, wxSize(imgsize, imgsize), 0);
|
||||
image_sizer->Add(completedimg, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(0));
|
||||
image_sizer->AddStretchSpacer();
|
||||
text_sizer->Add(image_sizer);
|
||||
text_sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
auto completedimg = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("completed", this, imgsize), wxDefaultPosition, FromDIP(wxSize(imgsize, imgsize)), 0);
|
||||
|
||||
text_sizer->Add(completedimg, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(imgright));
|
||||
m_finish_text = new Label(this, win_text, LB_AUTO_WRAP);
|
||||
m_finish_text->SetMinSize(wxSize(FromDIP(win_width - 64), -1));
|
||||
m_finish_text->SetMaxSize(wxSize(FromDIP(win_width - 64), -1));
|
||||
m_finish_text->SetMinSize(wxSize(FromDIP(win_width - (window_padding * 2 + imgright + imgsize)), -1));
|
||||
m_finish_text->SetMaxSize(wxSize(FromDIP(win_width - (window_padding * 2 + imgright + imgsize)), -1));
|
||||
m_finish_text->SetForegroundColour(wxColour(255, 255, 255, 255));
|
||||
text_sizer->Add(m_finish_text, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 0);
|
||||
text_sizer->AddSpacer(FromDIP(20));
|
||||
m_sizer_main->Add(text_sizer, FromDIP(0), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP, FromDIP(15));
|
||||
text_sizer->Add(m_finish_text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
m_sizer_main->Add(text_sizer, 0, wxALL, FromDIP(15));
|
||||
|
||||
wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL);
|
||||
bSizer_button->SetMinSize(wxSize(FromDIP(100), -1));
|
||||
@@ -66,22 +74,18 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame(
|
||||
bSizer_button->Add(m_checkbox, 0, wxALIGN_LEFT);*/
|
||||
bSizer_button->AddStretchSpacer(1);
|
||||
m_button_ok = new Button(this, ok_text);
|
||||
m_button_ok->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
|
||||
m_button_ok->SetSize(wxSize(FromDIP(60), FromDIP(30)));
|
||||
m_button_ok->SetMinSize(wxSize(FromDIP(90), FromDIP(30)));
|
||||
bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10));
|
||||
m_button_ok->SetStyle(ButtonStyle::Confirm, ButtonType::Choice);
|
||||
bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(10));
|
||||
|
||||
m_button_ok->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { deal_ok(); });
|
||||
|
||||
m_button_cancel = new Button(this, cancel_text);
|
||||
m_button_cancel->SetStyle(ButtonStyle::Regular, ButtonType::Window);
|
||||
m_button_cancel->SetSize(wxSize(FromDIP(65), FromDIP(30)));
|
||||
m_button_cancel->SetMinSize(wxSize(FromDIP(65), FromDIP(30)));
|
||||
bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10));
|
||||
m_button_cancel->SetStyle(ButtonStyle::Regular, ButtonType::Choice);
|
||||
bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(10));
|
||||
|
||||
m_button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { deal_cancel(); });
|
||||
|
||||
m_sizer_main->Add(bSizer_button, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(20));
|
||||
m_sizer_main->Add(bSizer_button, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(window_padding));
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, [this](auto &e) {
|
||||
on_hide();
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/listctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/timer.h>
|
||||
@@ -20,6 +19,8 @@
|
||||
#include "slic3r/GUI/format.hpp"
|
||||
#include "slic3r/Utils/Bonjour.hpp"
|
||||
|
||||
#include "slic3r/GUI/Widgets/DialogButtons.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
@@ -63,30 +64,30 @@ BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
|
||||
, timer_state(0)
|
||||
, tech(tech)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
const int em = GUI::wxGetApp().em_unit();
|
||||
list->SetMinSize(wxSize(80 * em, 30 * em));
|
||||
|
||||
wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
label->SetFont(Label::Body_14);
|
||||
vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em);
|
||||
|
||||
list->SetSingleStyle(wxLC_SINGLE_SEL);
|
||||
list->SetSingleStyle(wxLC_SORT_DESCENDING);
|
||||
list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 5 * em);
|
||||
list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 20 * em);
|
||||
list->AppendColumn(_(L("Hostname")), wxLIST_FORMAT_LEFT, 10 * em);
|
||||
list->AppendColumn(_(L("Service name")), wxLIST_FORMAT_LEFT, 20 * em);
|
||||
if (tech == ptFFF) {
|
||||
list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 5 * em);
|
||||
list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 15 * em);
|
||||
}
|
||||
|
||||
vsizer->Add(list, 1, wxEXPAND | wxALL, em);
|
||||
|
||||
wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
button_sizer->Add(new wxButton(this, wxID_OK, _L("OK")), 0, wxALL, em);
|
||||
button_sizer->Add(new wxButton(this, wxID_CANCEL, _L("Cancel")), 0, wxALL, em);
|
||||
// ^ Note: The Ok/Cancel labels are translated by wxWidgets
|
||||
auto dlg_btns = new GUI::DialogButtons(this, {"OK", "Cancel"});
|
||||
|
||||
vsizer->Add(button_sizer, 0, wxALIGN_CENTER);
|
||||
vsizer->Add(dlg_btns, 0, wxEXPAND);
|
||||
SetSizerAndFit(vsizer);
|
||||
|
||||
Bind(EVT_BONJOUR_REPLY, &BonjourDialog::on_reply, this);
|
||||
@@ -241,12 +242,15 @@ IPListDialog::IPListDialog(wxWindow* parent, const wxString& hostname, const std
|
||||
, m_list(new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxSIMPLE_BORDER))
|
||||
, m_selected_index (selected_index)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
const int em = GUI::wxGetApp().em_unit();
|
||||
m_list->SetMinSize(wxSize(40 * em, 30 * em));
|
||||
|
||||
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
auto* label = new wxStaticText(this, wxID_ANY, GUI::format_wxstr(_L("There are several IP addresses resolving to hostname %1%.\nPlease select one that should be used."), hostname));
|
||||
label->SetFont(Label::Body_14);
|
||||
vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em);
|
||||
|
||||
m_list->SetSingleStyle(wxLC_SINGLE_SEL);
|
||||
@@ -259,11 +263,9 @@ IPListDialog::IPListDialog(wxWindow* parent, const wxString& hostname, const std
|
||||
|
||||
vsizer->Add(m_list, 1, wxEXPAND | wxALL, em);
|
||||
|
||||
wxBoxSizer* button_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
button_sizer->Add(new wxButton(this, wxID_OK, _L("OK")), 0, wxALL, em);
|
||||
button_sizer->Add(new wxButton(this, wxID_CANCEL, _L("Cancel")), 0, wxALL, em);
|
||||
auto dlg_btns = new GUI::DialogButtons(this, {"OK", "Cancel"});
|
||||
|
||||
vsizer->Add(button_sizer, 0, wxALIGN_CENTER);
|
||||
vsizer->Add(dlg_btns, 0, wxEXPAND);
|
||||
SetSizerAndFit(vsizer);
|
||||
|
||||
GUI::wxGetApp().UpdateDlgDarkUI(this);
|
||||
|
||||
@@ -713,6 +713,36 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
|
||||
toggle_field("top_layer_direction", has_top_shell);
|
||||
toggle_field("bottom_layer_direction", has_bottom_shell);
|
||||
|
||||
toggle_line("top_surface_expansion", has_top_shell);
|
||||
toggle_line("top_surface_expansion_margin", has_top_shell);
|
||||
bool has_top_surface_expansion = config->opt_float("top_surface_expansion") > 0;
|
||||
toggle_field("top_surface_expansion_margin", has_top_surface_expansion);
|
||||
toggle_line("top_surface_expansion_direction", has_top_shell);
|
||||
toggle_field("top_surface_expansion_direction", has_top_surface_expansion);
|
||||
|
||||
// Orca: Archimedean Chords and Octagram Spiral are the centered surface patterns that the
|
||||
// pattern-centering, anisotropic-surface and separated-infill features act on.
|
||||
auto is_centered_pattern = [](InfillPattern p) {
|
||||
return p == InfillPattern::ipArchimedeanChords || p == InfillPattern::ipOctagramSpiral;
|
||||
};
|
||||
bool is_top_centered = is_centered_pattern(config->option<ConfigOptionEnum<InfillPattern>>("top_surface_pattern")->value);
|
||||
bool is_bottom_centered = is_centered_pattern(config->option<ConfigOptionEnum<InfillPattern>>("bottom_surface_pattern")->value);
|
||||
bool has_centered_surface = (has_top_shell && is_top_centered) || (has_bottom_shell && is_bottom_centered);
|
||||
|
||||
// Orca: center of surface pattern / anisotropic surfaces
|
||||
toggle_line("center_of_surface_pattern", has_centered_surface);
|
||||
toggle_line("anisotropic_surfaces", has_centered_surface);
|
||||
|
||||
// Orca: separate infills
|
||||
bool is_internal_infill_separable = is_separable_infill_pattern(config->option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value) ||
|
||||
config->opt_string("sparse_infill_rotate_template") != "" ||
|
||||
config->opt_string("solid_infill_rotate_template") != "";
|
||||
toggle_line("separated_infills", is_internal_infill_separable);
|
||||
|
||||
// Orca: no need gaps
|
||||
for (auto el : {"gap_fill_target", "filter_out_gap_fill"})
|
||||
toggle_field(el, !config->opt_bool("anisotropic_surfaces"));
|
||||
|
||||
for (auto el : { "infill_direction", "sparse_infill_line_width", "gap_fill_target","filter_out_gap_fill","infill_wall_overlap",
|
||||
"bridge_angle", "internal_bridge_angle", "relative_bridge_angle",
|
||||
"solid_infill_direction", "solid_infill_rotate_template", "internal_solid_infill_pattern", "internal_solid_filament_id", "top_surface_filament_id", "bottom_surface_filament_id",
|
||||
@@ -916,7 +946,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
|
||||
toggle_line("wipe_tower_extra_rib_length", have_rib_wall);
|
||||
toggle_line("wipe_tower_rib_width", have_rib_wall);
|
||||
toggle_line("wipe_tower_fillet_wall", have_rib_wall);
|
||||
toggle_field("prime_tower_width", have_prime_tower && (supports_wipe_tower_2 || have_rib_wall));
|
||||
toggle_field("prime_tower_width", have_prime_tower && !have_rib_wall);
|
||||
|
||||
toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && supports_wipe_tower_2);
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ void ExtrusionCalibration::create()
|
||||
m_button_save_result->SetStyle(ButtonStyle::Confirm, ButtonType::Choice);
|
||||
m_button_save_result->Bind(wxEVT_BUTTON, &ExtrusionCalibration::on_click_save, this);
|
||||
|
||||
m_button_last_step = new Button(m_step_2_panel, _L("Back")); // Back for english
|
||||
m_button_last_step = new Button(m_step_2_panel, _CTX("Back", "Navigation")); // Back for english
|
||||
m_button_last_step->SetStyle(ButtonStyle::Regular, ButtonType::Choice);
|
||||
m_button_last_step->Bind(wxEVT_BUTTON, &ExtrusionCalibration::on_click_last, this);
|
||||
|
||||
|
||||
@@ -936,6 +936,7 @@ bool TextCtrl::value_was_changed()
|
||||
case coString:
|
||||
case coStrings:
|
||||
case coFloatOrPercent:
|
||||
case coFloatsOrPercents:
|
||||
return boost::any_cast<std::string>(m_value) != boost::any_cast<std::string>(val);
|
||||
default:
|
||||
return true;
|
||||
|
||||
@@ -221,16 +221,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
std::vector<std::pair<boost::filesystem::path, size_t>> filtered_entries; // second is unzipped size
|
||||
for (mz_uint i = 0; i < num_entries; ++i) {
|
||||
if (mz_zip_reader_file_stat(archive, i, &stat)) {
|
||||
std::string extra(1024, 0);
|
||||
boost::filesystem::path path;
|
||||
size_t extra_size = mz_zip_reader_get_filename_from_extra(archive, i, extra.data(), extra.size());
|
||||
if (extra_size > 0) {
|
||||
path = boost::filesystem::path(extra.substr(0, extra_size));
|
||||
} else {
|
||||
wxString wname = boost::nowide::widen(stat.m_filename);
|
||||
std::string name = into_u8(wname);
|
||||
path = boost::filesystem::path(name);
|
||||
}
|
||||
boost::filesystem::path path = Slic3r::decode_archive_entry_path(archive, stat);
|
||||
assert(!path.empty());
|
||||
if (!path.has_extension())
|
||||
continue;
|
||||
|
||||
@@ -489,7 +489,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
const float main_row_h = 2.0f * text_h + item_spacing_y; // Two lines of text (position and detail) + spacing between them
|
||||
const float properties_h = static_cast<float>(properties_rows.size()) * (text_h + 2.0f * cell_pad_y) + 2.0f * cell_pad_y + 1.0f + item_spacing_y // table rows
|
||||
+ item_spacing_y + show_button_h // Spacing() + Show/Hide button row
|
||||
+ item_spacing_y + 1.0f + style.FramePadding.y; // Spacing() + Separator() + Dummy()
|
||||
+ item_spacing_y + 1.0f + style.WindowPadding.y; // Spacing() + Separator() + Dummy()
|
||||
const float folded_window_h = std::ceil(window_pad_h + main_row_h); // Height of the window when properties are hidden, with padding, rounded up for better look
|
||||
const float unfolded_window_h = std::ceil(folded_window_h + properties_h); // Height of the window when properties are shown, with padding, rounded up for better look
|
||||
const float window_h = properties_shown ? unfolded_window_h : folded_window_h; // Final window height depending on whether properties are shown or not
|
||||
@@ -615,9 +615,12 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Dummy({0, style.FramePadding.y});
|
||||
ImGui::Dummy({0, style.WindowPadding.y});
|
||||
}
|
||||
|
||||
float draw_area_height = ImGui::GetTextLineHeight() * 2.f + style.ItemSpacing.y;
|
||||
ImGui::Dummy({10.f, draw_area_height}); // reserve area
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding , 3.f * m_scale);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding , ImVec2(2.f, 2.f) * m_scale);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button , ImVec4(0, 0, 0, 0));
|
||||
@@ -625,6 +628,10 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive , ImVec4(84 / 255.f, 84 / 255.f, 90 / 255.f, 1.f));
|
||||
|
||||
const float main_wnd_height = ImGui::GetWindowHeight();
|
||||
const float draw_start_y = main_wnd_height - draw_area_height - style.WindowPadding.y;
|
||||
|
||||
ImGui::SetCursorPos(ImVec2(style.WindowPadding.x, draw_start_y));
|
||||
|
||||
// ORCA use glyph based button for fixing button sizes changing depends on used font size on platform
|
||||
const wchar_t foldIcon = properties_shown ? ImGui::UnfoldButtonIcon : ImGui::FoldButtonIcon;
|
||||
if (imgui.glyph_button(foldIcon, ImVec2(16.f, 16.f) * m_scale)) {
|
||||
@@ -640,10 +647,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if(!properties_shown)
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - style.FramePadding.y); // aligns button with next group
|
||||
ImGui::SetCursorPos(ImVec2(style.WindowPadding.x + style.ItemSpacing.x + 24.f * m_scale, draw_start_y - 1.f * m_scale));
|
||||
|
||||
ImGui::BeginGroup(); // group contents to make information area more compact
|
||||
|
||||
@@ -4258,7 +4262,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
};
|
||||
|
||||
auto append_print = [&imgui, imperial_units](const ColorRGBA& color, const std::array<float, 4>& offsets, const Times& times, std::pair<double, double> used_filament) {
|
||||
imgui.text(_u8L("Print"));
|
||||
imgui.text(_CTX_utf8("Print", "Noun"));
|
||||
ImGui::SameLine();
|
||||
|
||||
float icon_size = ImGui::GetTextLineHeight();
|
||||
@@ -4292,7 +4296,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
for (const PartialTime& item : partial_times) {
|
||||
switch (item.type)
|
||||
{
|
||||
case PartialTime::EType::Print: { labels.push_back(_u8L("Print")); break; }
|
||||
case PartialTime::EType::Print: { labels.push_back(_CTX_utf8("Print", "Noun")); break; }
|
||||
case PartialTime::EType::Pause: { labels.push_back(_u8L("Pause")); break; }
|
||||
case PartialTime::EType::ColorChange: { labels.push_back(_u8L("Color change")); break; }
|
||||
}
|
||||
|
||||
+249
-129
@@ -1231,6 +1231,14 @@ GLCanvas3D::~GLCanvas3D()
|
||||
glsafe(::glDeleteTextures(1, &m_ssao_depth_texture_id));
|
||||
m_ssao_depth_texture_id = 0;
|
||||
}
|
||||
if (m_shadow_map_texture_id != 0) {
|
||||
glsafe(::glDeleteTextures(1, &m_shadow_map_texture_id));
|
||||
m_shadow_map_texture_id = 0;
|
||||
}
|
||||
if (m_shadow_map_fbo != 0) {
|
||||
glsafe(::glDeleteFramebuffers(1, &m_shadow_map_fbo));
|
||||
m_shadow_map_fbo = 0;
|
||||
}
|
||||
m_plate_shadow_mask.reset();
|
||||
}
|
||||
m_plate_shadow_mask_key.clear();
|
||||
@@ -2033,6 +2041,9 @@ void GLCanvas3D::render(bool only_init)
|
||||
|
||||
// draw scene
|
||||
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||
// Invalidate the shadow map each frame; only the View3D path below rebuilds it. This keeps
|
||||
// the Preview / Assemble canvases from sampling a stale map with an outdated light matrix.
|
||||
m_shadow_map_valid = false;
|
||||
_render_background();
|
||||
|
||||
//BBS add partplater rendering logic
|
||||
@@ -2057,7 +2068,8 @@ void GLCanvas3D::render(bool only_init)
|
||||
_render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid);
|
||||
|
||||
//BBS: add outline logic
|
||||
_render_cast_shadows_on_plate(camera.get_view_matrix(), camera.get_projection_matrix());
|
||||
// Depth pass for object-on-object and self shadows; consumed by the gouraud shader below.
|
||||
_render_shadows(camera.get_view_matrix(), camera.get_projection_matrix());
|
||||
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
|
||||
_render_sla_slices();
|
||||
_render_selection();
|
||||
@@ -6036,11 +6048,11 @@ void GLCanvas3D::_render_3d_navigator()
|
||||
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Y], "Z"); // ORCA use uppercase to match text on tranform widgets
|
||||
strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Z], "X"); // ORCA use uppercase to match text on tranform widgets
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_FRONT], _utf8("Front").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _utf8("Back").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _CTX_utf8("Back", "Camera View").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_TOP], _utf8("Top").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BOTTOM], _utf8("Bottom").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_LEFT], _CTX_utf8(L_CONTEXT("Left", "Camera"), "Camera").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_RIGHT], _CTX_utf8(L_CONTEXT("Right", "Camera"), "Camera").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_LEFT], _CTX_utf8("Left", "Camera View").c_str());
|
||||
strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_RIGHT], _CTX_utf8("Right", "Camera View").c_str());
|
||||
|
||||
float sc = get_scale();
|
||||
#ifdef WIN32
|
||||
@@ -7858,9 +7870,8 @@ void GLCanvas3D::_render_platelist(const Transform3d& view_matrix, const Transfo
|
||||
wxGetApp().plater()->get_partplate_list().render(view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali, show_grid);
|
||||
}
|
||||
|
||||
void GLCanvas3D::_render_cast_shadows_on_plate(const Transform3d& view_matrix, const Transform3d& projection_matrix)
|
||||
void GLCanvas3D::_render_shadows(const Transform3d& view_matrix, const Transform3d& projection_matrix)
|
||||
{
|
||||
// Check if shadow rendering is enabled in configuration
|
||||
if (wxGetApp().app_config == nullptr)
|
||||
return;
|
||||
if (!wxGetApp().app_config->get_bool(SETTING_OPENGL_REALISTIC_MODE))
|
||||
@@ -7874,54 +7885,181 @@ void GLCanvas3D::_render_cast_shadows_on_plate(const Transform3d& view_matrix, c
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
// Fixed light direction (pointing downward at an angle)
|
||||
// Drive shadow direction from current view angle: define light in eye-space,
|
||||
// then transform it to world-space with inverse view rotation.
|
||||
const Vec3d light_dir_eye = Vec3d(-0.4574957, 0.4574957, 0.7624929).normalized();
|
||||
const Matrix3d view_rot = view_matrix.matrix().block<3, 3>(0, 0);
|
||||
const Vec3d light_dir_to_light = (view_rot.transpose() * light_dir_eye).normalized();
|
||||
const Vec3d ray_dir = -light_dir_to_light; // Direction of shadow projection
|
||||
|
||||
if (std::abs(ray_dir.z()) < 1e-6)
|
||||
if (OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Arb) {
|
||||
|
||||
// Light direction (same as used in shading and plate shading)
|
||||
const Vec3d light_dir_eye = Vec3d(-0.4574957, 0.4574957, 0.7624929).normalized();
|
||||
const Matrix3d view_rot = view_matrix.matrix().block<3, 3>(0, 0);
|
||||
const Vec3d dir_to_light = (view_rot.transpose() * light_dir_eye).normalized();
|
||||
|
||||
// Bounding box of the printable objects (the shadow casters).
|
||||
BoundingBoxf3 obj_bb;
|
||||
for (const GLVolume* volume : m_volumes.volumes) {
|
||||
if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower)
|
||||
continue;
|
||||
obj_bb.merge(volume->transformed_bounding_box());
|
||||
}
|
||||
if (!obj_bb.defined)
|
||||
return; // no objects to cast shadows
|
||||
|
||||
// Orthographic light-space basis (z points toward the light).
|
||||
const Vec3d up = (std::abs(dir_to_light.z()) > 0.99) ? Vec3d::UnitY() : Vec3d::UnitZ();
|
||||
const Vec3d z_axis = dir_to_light;
|
||||
const Vec3d x_axis = up.cross(z_axis).normalized();
|
||||
const Vec3d y_axis = z_axis.cross(x_axis).normalized();
|
||||
|
||||
// Fit the frustum to the object AABB *and* the object's shadow projected onto the plate
|
||||
// (clamped to the plate footprint). This keeps the map tight/high-res for short shadows
|
||||
// while still covering long shadows at grazing light angles, which previously fell outside
|
||||
// the map and were clipped.
|
||||
const Vec3d ray_dir = -dir_to_light; // direction the shadow travels
|
||||
const BoundingBoxf3 plate_bb = m_bed.build_volume().valid() ? m_bed.build_volume().bounding_volume() : obj_bb;
|
||||
|
||||
Vec3d lmin(DBL_MAX, DBL_MAX, DBL_MAX);
|
||||
Vec3d lmax(-DBL_MAX, -DBL_MAX, -DBL_MAX);
|
||||
auto enclose = [&](const Vec3d& p) {
|
||||
const Vec3d lp(x_axis.dot(p), y_axis.dot(p), z_axis.dot(p));
|
||||
lmin = lmin.cwiseMin(lp);
|
||||
lmax = lmax.cwiseMax(lp);
|
||||
};
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
const Vec3d corner((i & 1) ? obj_bb.max.x() : obj_bb.min.x(),
|
||||
(i & 2) ? obj_bb.max.y() : obj_bb.min.y(),
|
||||
(i & 4) ? obj_bb.max.z() : obj_bb.min.z());
|
||||
enclose(corner);
|
||||
// Where this corner's shadow lands on z = 0, clamped to the plate so a grazing angle
|
||||
// (t -> infinity) stays bounded.
|
||||
if (ray_dir.z() < -1e-6) {
|
||||
const double t = -corner.z() / ray_dir.z();
|
||||
Vec3d s = corner + t * ray_dir;
|
||||
s.x() = std::min(std::max(s.x(), plate_bb.min.x()), plate_bb.max.x());
|
||||
s.y() = std::min(std::max(s.y(), plate_bb.min.y()), plate_bb.max.y());
|
||||
s.z() = 0.0;
|
||||
enclose(s);
|
||||
}
|
||||
}
|
||||
|
||||
// Light "camera" placed just past the nearest enclosed point, looking toward the scene.
|
||||
const double range = lmax.z() - lmin.z();
|
||||
const double margin = std::max(1.0, 0.05 * range);
|
||||
const double cx = 0.5 * (lmin.x() + lmax.x());
|
||||
const double cy = 0.5 * (lmin.y() + lmax.y());
|
||||
const Vec3d eye = x_axis * cx + y_axis * cy + z_axis * (lmax.z() + margin);
|
||||
|
||||
Matrix4d light_view = Matrix4d::Identity();
|
||||
light_view.block<1, 3>(0, 0) = x_axis.transpose();
|
||||
light_view.block<1, 3>(1, 0) = y_axis.transpose();
|
||||
light_view.block<1, 3>(2, 0) = z_axis.transpose();
|
||||
light_view(0, 3) = -x_axis.dot(eye);
|
||||
light_view(1, 3) = -y_axis.dot(eye);
|
||||
light_view(2, 3) = -z_axis.dot(eye);
|
||||
|
||||
// Ortho fit to the light-space extent (symmetric in X/Y around cx,cy; +2% edge padding).
|
||||
const double halfx = std::max(0.5 * (lmax.x() - lmin.x()), 1.0) * 1.02;
|
||||
const double halfy = std::max(0.5 * (lmax.y() - lmin.y()), 1.0) * 1.02;
|
||||
const double near_z = margin * 0.5;
|
||||
const double far_z = range + margin * 1.5;
|
||||
Matrix4d light_proj = Matrix4d::Identity();
|
||||
light_proj(0, 0) = 1.0 / halfx;
|
||||
light_proj(1, 1) = 1.0 / halfy;
|
||||
light_proj(2, 2) = -2.0 / (far_z - near_z);
|
||||
light_proj(2, 3) = -(far_z + near_z) / (far_z - near_z);
|
||||
|
||||
m_shadow_light_vp = Transform3d(light_proj * light_view);
|
||||
|
||||
// Create / resize the depth texture and FBO
|
||||
const unsigned int size = 2048;
|
||||
if (m_shadow_map_texture_id == 0) {
|
||||
glsafe(::glGenTextures(1, &m_shadow_map_texture_id));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER));
|
||||
const float border[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glsafe(::glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border));
|
||||
m_shadow_map_size = 0;
|
||||
}
|
||||
if (m_shadow_map_size != size) {
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id));
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr));
|
||||
m_shadow_map_size = size;
|
||||
}
|
||||
if (m_shadow_map_fbo == 0)
|
||||
glsafe(::glGenFramebuffers(1, &m_shadow_map_fbo));
|
||||
|
||||
// Save OpenGL state that we will modify
|
||||
GLint prev_viewport[4] = { 0, 0, 0, 0 };
|
||||
glsafe(::glGetIntegerv(GL_VIEWPORT, prev_viewport));
|
||||
GLint prev_fbo = 0;
|
||||
glsafe(::glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo));
|
||||
GLboolean prev_color_mask[4] = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };
|
||||
glsafe(::glGetBooleanv(GL_COLOR_WRITEMASK, prev_color_mask));
|
||||
const GLboolean prev_cull = ::glIsEnabled(GL_CULL_FACE);
|
||||
GLint prev_depth_func = GL_LESS;
|
||||
glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func));
|
||||
GLboolean prev_depth_mask = GL_TRUE;
|
||||
glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask));
|
||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, m_shadow_map_fbo));
|
||||
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_shadow_map_texture_id, 0));
|
||||
glsafe(::glDrawBuffer(GL_NONE));
|
||||
glsafe(::glReadBuffer(GL_NONE));
|
||||
|
||||
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(prev_fbo)));
|
||||
m_shadow_map_valid = false;
|
||||
} else {
|
||||
glsafe(::glViewport(0, 0, size, size));
|
||||
glsafe(::glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDepthMask(GL_TRUE));
|
||||
glsafe(::glDepthFunc(GL_LESS));
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_POLYGON_OFFSET_FILL));
|
||||
glsafe(::glPolygonOffset(4.0f, 4.0f));
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("projection_matrix", Transform3d(light_proj));
|
||||
for (GLVolume* volume : m_volumes.volumes) {
|
||||
if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower)
|
||||
continue;
|
||||
const Transform3d view_model = Transform3d(light_view) * volume->world_matrix();
|
||||
shader->set_uniform("view_model_matrix", view_model);
|
||||
volume->model.render(shader);
|
||||
}
|
||||
shader->stop_using();
|
||||
|
||||
// Restore state
|
||||
glsafe(::glDisable(GL_POLYGON_OFFSET_FILL));
|
||||
glsafe(::glColorMask(prev_color_mask[0], prev_color_mask[1], prev_color_mask[2], prev_color_mask[3]));
|
||||
if (prev_cull)
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
else
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
glsafe(::glDepthFunc(prev_depth_func));
|
||||
glsafe(::glDepthMask(prev_depth_mask));
|
||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(prev_fbo)));
|
||||
glsafe(::glViewport(prev_viewport[0], prev_viewport[1], prev_viewport[2], prev_viewport[3]));
|
||||
|
||||
m_shadow_map_valid = true;
|
||||
}
|
||||
} else {
|
||||
m_shadow_map_valid = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Unified plate shadow: draw the build-plate footprint and darken it wherever the same
|
||||
// depth shadow map (built above) says the light is occluded. This replaces the old planar
|
||||
// stencil projection so plate, object and self shadows all come from one technique.
|
||||
// ----------------------------------------------------------------------------------
|
||||
if (!m_shadow_map_valid)
|
||||
return;
|
||||
|
||||
// Shadow projection matrix - flattens geometry onto Z=0 plane along light direction
|
||||
Matrix4d shadow_proj = Matrix4d::Identity();
|
||||
shadow_proj(0, 2) = -ray_dir.x() / ray_dir.z();
|
||||
shadow_proj(1, 2) = -ray_dir.y() / ray_dir.z();
|
||||
shadow_proj(2, 0) = 0.0;
|
||||
shadow_proj(2, 1) = 0.0;
|
||||
shadow_proj(2, 2) = 0.0;
|
||||
shadow_proj(2, 3) = 0.01; // Bias to prevent shadow acne
|
||||
GLShaderProgram* plate_shader = wxGetApp().get_shader("printbed_shadow");
|
||||
if (plate_shader == nullptr)
|
||||
return;
|
||||
|
||||
// Save OpenGL state
|
||||
GLint prev_depth_func = GL_LESS;
|
||||
glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func));
|
||||
GLboolean prev_depth_mask = GL_TRUE;
|
||||
glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask));
|
||||
GLint prev_stencil_mask = 0xFF;
|
||||
glsafe(::glGetIntegerv(GL_STENCIL_WRITEMASK, &prev_stencil_mask));
|
||||
GLboolean prev_stencil_test = GL_FALSE;
|
||||
glsafe(::glGetBooleanv(GL_STENCIL_TEST, &prev_stencil_test));
|
||||
|
||||
// ============================================================
|
||||
// PASS 0: Create stencil mask for the build plate (value = 1)
|
||||
// ============================================================
|
||||
glsafe(::glEnable(GL_STENCIL_TEST));
|
||||
glsafe(::glStencilMask(0xFF));
|
||||
glsafe(::glClearStencil(0));
|
||||
glsafe(::glClear(GL_STENCIL_BUFFER_BIT));
|
||||
|
||||
glsafe(::glStencilFunc(GL_ALWAYS, 1, 0xFF));
|
||||
glsafe(::glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE));
|
||||
|
||||
glsafe(::glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("projection_matrix", projection_matrix);
|
||||
|
||||
// Draw the build plate (cached model to avoid per-frame uploads)
|
||||
if (const BuildVolume& build_volume = m_bed.build_volume(); build_volume.valid()) {
|
||||
const std::string mask_key = build_volume.type() == BuildVolume_Type::Rectangle
|
||||
? (boost::format("rect|%1$.5f|%2$.5f|%3$.5f|%4$.5f")
|
||||
@@ -7977,87 +8115,49 @@ void GLCanvas3D::_render_cast_shadows_on_plate(const Transform3d& view_matrix, c
|
||||
}
|
||||
|
||||
if (m_plate_shadow_mask.is_initialized()) {
|
||||
shader->set_uniform("view_model_matrix", view_matrix);
|
||||
m_plate_shadow_mask.render(shader);
|
||||
// Blend the shadow over the already-drawn plate. Depth test keeps it behind anything
|
||||
// already in front; depth writes are off, and a small negative polygon offset lifts it
|
||||
// just above the bed to avoid z-fighting.
|
||||
GLboolean prev_depth_mask = GL_TRUE;
|
||||
glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask));
|
||||
GLint prev_depth_func = GL_LESS;
|
||||
glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func));
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
glsafe(::glDepthFunc(GL_LEQUAL));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
glsafe(::glEnable(GL_POLYGON_OFFSET_FILL));
|
||||
glsafe(::glPolygonOffset(-1.0f, -1.0f));
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE4));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
|
||||
plate_shader->start_using();
|
||||
plate_shader->set_uniform("view_model_matrix", view_matrix);
|
||||
plate_shader->set_uniform("projection_matrix", projection_matrix);
|
||||
plate_shader->set_uniform("shadow_map", 4);
|
||||
plate_shader->set_uniform("shadow_light_vp", m_shadow_light_vp);
|
||||
plate_shader->set_uniform("shadow_intensity", 0.35f);
|
||||
plate_shader->set_uniform("shadow_map_texel", 1.0f / static_cast<float>(m_shadow_map_size));
|
||||
m_plate_shadow_mask.render(plate_shader);
|
||||
plate_shader->stop_using();
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE4));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
|
||||
glsafe(::glDisable(GL_POLYGON_OFFSET_FILL));
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
glsafe(::glDepthFunc(prev_depth_func));
|
||||
glsafe(::glDepthMask(prev_depth_mask));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// PASS 1: Project object shadows onto plate (increment stencil to 2)
|
||||
// ============================================================
|
||||
// Only render where plate exists (stencil == 1), then increment to 2
|
||||
glsafe(::glStencilFunc(GL_EQUAL, 1, 0xFF));
|
||||
glsafe(::glStencilOp(GL_KEEP, GL_KEEP, GL_INCR));
|
||||
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDepthFunc(GL_ALWAYS)); // Shadows don't need depth testing
|
||||
glsafe(::glEnable(GL_POLYGON_OFFSET_FILL));
|
||||
glsafe(::glPolygonOffset(-2.0f, -2.0f));
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
|
||||
// Render projected shadow geometry
|
||||
for (GLVolume* volume : m_volumes.volumes) {
|
||||
if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower)
|
||||
continue;
|
||||
|
||||
// CRITICAL FIX: Apply shadow projection in object's local space, then to world, then to view
|
||||
// This ensures shadows are cast from the object's actual position
|
||||
Matrix4d world_matrix = volume->world_matrix().matrix();
|
||||
|
||||
// Project the shadow - this flattens the geometry onto Z=0 in WORLD space
|
||||
Matrix4d shadow_world_matrix = shadow_proj * world_matrix;
|
||||
|
||||
// Transform to view space for rendering
|
||||
Matrix4d view_shadow_matrix = view_matrix.matrix() * shadow_world_matrix;
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_shadow_matrix);
|
||||
shader->set_uniform("projection_matrix", projection_matrix);
|
||||
|
||||
volume->model.render(shader);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// PASS 2: Draw shadow color where stencil == 2
|
||||
// ============================================================
|
||||
glsafe(::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
|
||||
glsafe(::glStencilFunc(GL_EQUAL, 2, 0xFF));
|
||||
glsafe(::glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
|
||||
glsafe(::glStencilMask(0x00));
|
||||
|
||||
glsafe(::glDepthFunc(GL_ALWAYS));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// Draw shadow fill
|
||||
shader->set_uniform("view_model_matrix", Transform3d::Identity());
|
||||
shader->set_uniform("projection_matrix", Transform3d::Identity());
|
||||
|
||||
const ColorRGBA shadow_fill_color(0.0f, 0.0f, 0.0f, 0.4f); // Darker shadow for visibility
|
||||
const ColorRGBA prev_bg_color = m_background.get_geometry().color;
|
||||
m_background.set_color(shadow_fill_color);
|
||||
shader->set_uniform("uniform_color", shadow_fill_color);
|
||||
m_background.render(shader);
|
||||
m_background.set_color(prev_bg_color);
|
||||
shader->set_uniform("uniform_color", prev_bg_color);
|
||||
|
||||
shader->stop_using();
|
||||
|
||||
// ============================================================
|
||||
// RESTORE STATE
|
||||
// ============================================================
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDepthMask(prev_depth_mask));
|
||||
glsafe(::glDepthFunc(prev_depth_func));
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
glsafe(::glDisable(GL_POLYGON_OFFSET_FILL));
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
if (!prev_stencil_test)
|
||||
glsafe(::glDisable(GL_STENCIL_TEST));
|
||||
glsafe(::glStencilMask(prev_stencil_mask));
|
||||
}
|
||||
|
||||
|
||||
void GLCanvas3D::_render_plane() const
|
||||
{
|
||||
;//TODO render assemble plane
|
||||
@@ -8142,6 +8242,20 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||
const bool phong_ssao = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SSAO);
|
||||
shader->set_uniform("enable_ssao", phong_ssao);
|
||||
|
||||
// Object-on-object and self shadows: sample the depth map built in _render_shadow_map_pass().
|
||||
// shadow_intensity == 0 disables the effect entirely (unchanged behavior when off / unsupported).
|
||||
if (m_shadow_map_valid && m_shadow_map_texture_id != 0) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE4));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
shader->set_uniform("shadow_map", 4);
|
||||
shader->set_uniform("shadow_light_vp", m_shadow_light_vp);
|
||||
shader->set_uniform("shadow_map_texel", 1.0f / static_cast<float>(m_shadow_map_size));
|
||||
shader->set_uniform("shadow_intensity", 0.35f);
|
||||
}
|
||||
else
|
||||
shader->set_uniform("shadow_intensity", 0.0f);
|
||||
|
||||
const Size& cvn_size = get_canvas_size();
|
||||
{
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
@@ -8233,6 +8347,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||
shader->set_uniform("show_wireframe", false);
|
||||
}*/
|
||||
|
||||
if (m_shadow_map_valid && m_shadow_map_texture_id != 0) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE4));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
}
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
@@ -9324,7 +9444,7 @@ void GLCanvas3D::_render_canvas_toolbar()
|
||||
);
|
||||
|
||||
create_menu_item( _utf8(L("Realistic View")),
|
||||
true,
|
||||
m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
|
||||
cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE),
|
||||
[this, &cfg]{
|
||||
cfg->set_bool(SETTING_OPENGL_REALISTIC_MODE, !cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE));
|
||||
|
||||
@@ -732,6 +732,12 @@ public:
|
||||
std::array<unsigned int, 2> m_ssao_texture_size{ { 0, 0 } };
|
||||
GLModel m_plate_shadow_mask;
|
||||
std::string m_plate_shadow_mask_key;
|
||||
// Depth-based shadow map used to cast object shadows onto other objects and themselves.
|
||||
unsigned int m_shadow_map_fbo{ 0 };
|
||||
unsigned int m_shadow_map_texture_id{ 0 };
|
||||
unsigned int m_shadow_map_size{ 0 };
|
||||
Transform3d m_shadow_light_vp{ Transform3d::Identity() };
|
||||
bool m_shadow_map_valid{ false };
|
||||
public:
|
||||
explicit GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed);
|
||||
~GLCanvas3D();
|
||||
@@ -1251,7 +1257,9 @@ private:
|
||||
void _render_ssao_pass(unsigned int width, unsigned int height);
|
||||
void _render_background();
|
||||
void _render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes);
|
||||
void _render_cast_shadows_on_plate(const Transform3d& view_matrix, const Transform3d& projection_matrix);
|
||||
// Build the light-space depth shadow map (consumed by gouraud/phong for object & self shadows)
|
||||
// and cast it onto the build plate. Realistic view only.
|
||||
void _render_shadows(const Transform3d& view_matrix, const Transform3d& projection_matrix);
|
||||
//BBS: add part plate related logic
|
||||
void _render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false, bool show_grid = true);
|
||||
//BBS: add outline drawing logic
|
||||
|
||||
@@ -457,10 +457,9 @@ void GLModel::init_from(const indexed_triangle_set& its)
|
||||
data.reserve_indices(3 * its.indices.size());
|
||||
|
||||
// Read user preference: smooth normals enabled
|
||||
const bool realistic_mode = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_REALISTIC_MODE);
|
||||
const bool smooth_normals_enabled = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SMOOTH_NORMALS);
|
||||
|
||||
if (realistic_mode && smooth_normals_enabled) {
|
||||
if (smooth_normals_enabled) {
|
||||
// Use per-corner smooth normals (via IGL)
|
||||
using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
|
||||
using MapMatrixXiUnaligned = Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
|
||||
|
||||
@@ -68,6 +68,10 @@ std::pair<bool, std::string> GLShadersManager::init()
|
||||
valid &= append_shader("thumbnail", { prefix + "thumbnail.vs", prefix + "thumbnail.fs"});
|
||||
// used to render printbed
|
||||
valid &= append_shader("printbed", { prefix + "printbed.vs", prefix + "printbed.fs" });
|
||||
#if !SLIC3R_OPENGL_ES
|
||||
// used to cast the object shadow map onto the build plate (realistic view)
|
||||
valid &= append_shader("printbed_shadow", { prefix + "printbed_shadow.vs", prefix + "printbed_shadow.fs" });
|
||||
#endif // !SLIC3R_OPENGL_ES
|
||||
valid &= append_shader("hotbed", {prefix + "hotbed.vs", prefix + "hotbed.fs"});
|
||||
// used to render options in gcode preview
|
||||
if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
|
||||
|
||||
@@ -6965,6 +6965,10 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
// finishFn tears down the progress dialog (and clears the re-entrancy guard), so it
|
||||
// must run on every exit path — otherwise an early bail-out would leak the modal
|
||||
// dialog and leave the guard stuck, blocking all later manual syncs.
|
||||
// Guard the whole thread body: an uncaught exception here (e.g. a transient
|
||||
// boost::filesystem error while scanning the preset folder) would otherwise
|
||||
// propagate out of the thread and terminate the entire application.
|
||||
try {
|
||||
if (!m_agent) { finishFn(false); return; }
|
||||
|
||||
// One-time scan for orphaned .info files left over from offline deletions; queues HTTP DELETEs.
|
||||
@@ -7206,6 +7210,11 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "user preset sync thread terminated by exception: " << e.what();
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "user preset sync thread terminated by unknown exception";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8526,8 +8535,13 @@ void GUI_App::scan_orphaned_info_files()
|
||||
if (!fs::exists(type_dir))
|
||||
continue;
|
||||
|
||||
// Iterate through all .info files
|
||||
for (auto& entry : boost::filesystem::directory_iterator(type_dir)) {
|
||||
// Iterate through all .info files. Use the error_code-based iterator so a transient
|
||||
// directory-read failure (e.g. macOS readdir returning ENOTSUP) is logged and skipped
|
||||
// instead of throwing an uncaught exception that would terminate the app from the
|
||||
// background sync thread this runs on.
|
||||
boost::system::error_code ec;
|
||||
for (boost::filesystem::directory_iterator it(type_dir, ec), end; !ec && it != end; it.increment(ec)) {
|
||||
const auto& entry = *it;
|
||||
if (entry.path().extension() != ".info")
|
||||
continue;
|
||||
|
||||
@@ -8546,6 +8560,8 @@ void GUI_App::scan_orphaned_info_files()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ec)
|
||||
BOOST_LOG_TRIVIAL(warning) << "scan_orphaned_info_files: failed to scan " << type_dir.string() << ": " << ec.message();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,9 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CATE
|
||||
{"infill_anchor", "", 1},
|
||||
{"infill_anchor_max", "", 1},
|
||||
{"top_surface_pattern", "", 1},
|
||||
{"top_surface_expansion", "", 1},
|
||||
{"top_surface_expansion_margin", "", 1},
|
||||
{"top_surface_expansion_direction", "", 1},
|
||||
{"bottom_surface_pattern", "", 1},
|
||||
{"internal_solid_infill_pattern", "", 1},
|
||||
{"align_infill_direction_to_model", "", 1},
|
||||
@@ -187,7 +190,7 @@ std::vector<SimpleSettingData> SettingsFactory::get_visible_options(const std::s
|
||||
//Quality
|
||||
"wall_infill_order", "ironing_type", "inner_wall_line_width", "outer_wall_line_width", "top_surface_line_width",
|
||||
//Shell
|
||||
"wall_loops", "top_shell_layers", "bottom_shell_layers", "top_shell_thickness", "bottom_shell_thickness",
|
||||
"wall_loops", "top_shell_layers", "bottom_shell_layers", "top_shell_thickness", "bottom_shell_thickness", "top_surface_expansion", "top_surface_expansion_margin", "top_surface_expansion_direction",
|
||||
//Infill
|
||||
"sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", "infill_combination", "infill_direction", "infill_wall_overlap",
|
||||
//speed
|
||||
|
||||
@@ -1905,7 +1905,7 @@ bool GLGizmoAdvancedCut::render_slider_double_input(const std::string &label, fl
|
||||
mean_size *= float(units_mm_to_in);
|
||||
min_size *= float(units_mm_to_in);
|
||||
}
|
||||
std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm");
|
||||
std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _CTX_utf8("in", "inches") : "%.2f " + _u8L("mm");
|
||||
|
||||
m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, min_size, mean_size, format.c_str());
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ std::string GLGizmoCut3D::get_tooltip() const
|
||||
std::string tooltip;
|
||||
if (m_hover_id == Z || (m_dragging && m_hover_id == CutPlane)) {
|
||||
double koef = m_imperial_units ? GizmoObjectManipulation::mm_to_in : 1.0;
|
||||
std::string unit_str = " " + (m_imperial_units ? _u8L("in") : _u8L("mm"));
|
||||
std::string unit_str = " " + (m_imperial_units ? _CTX_utf8("in", "inches") : _u8L("mm"));
|
||||
const BoundingBoxf3& tbb = m_transformed_bounding_box;
|
||||
|
||||
const std::string name = m_keep_as_parts ? _u8L("Part") : _u8L("Object");
|
||||
@@ -541,7 +541,7 @@ bool GLGizmoCut3D::render_double_input(const std::string& label, double& value_i
|
||||
ImGui::InputDouble(("##" + label).c_str(), &value, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
|
||||
|
||||
ImGui::SameLine();
|
||||
m_imgui->text(m_imperial_units ? _L("in") : _L("mm"));
|
||||
m_imgui->text(m_imperial_units ? _CTX("in", "inches") : _L("mm"));
|
||||
|
||||
value_in = value * (m_imperial_units ? GizmoObjectManipulation::in_to_mm : 1.0);
|
||||
return !is_approx(old_val, value);
|
||||
@@ -582,7 +582,7 @@ bool GLGizmoCut3D::render_slider_two_input(const std::string& label, float& valu
|
||||
if (m_imperial_units) {
|
||||
min_size *= f_mm_to_in;
|
||||
}
|
||||
std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm");
|
||||
std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _CTX_utf8("in", "inches") : "%.2f " + _u8L("mm");
|
||||
|
||||
m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, min_size, mean_size, format.c_str());
|
||||
|
||||
@@ -653,7 +653,7 @@ bool GLGizmoCut3D::render_slider_input(const std::string& label, float& value_in
|
||||
if (m_imperial_units) {
|
||||
min_size *= f_mm_to_in;
|
||||
}
|
||||
std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm");
|
||||
std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _CTX_utf8("in", "inches") : "%.2f " + _u8L("mm");
|
||||
|
||||
m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, min_size, max_value, format.c_str());
|
||||
|
||||
@@ -2472,7 +2472,7 @@ void GLGizmoCut3D::render_connectors_input_window(CutConnectors &connectors, flo
|
||||
void GLGizmoCut3D::render_build_size()
|
||||
{
|
||||
double koef = m_imperial_units ? GizmoObjectManipulation::mm_to_in : 1.0;
|
||||
wxString unit_str = m_imperial_units ? _L("in") : _L("mm");
|
||||
wxString unit_str = m_imperial_units ? _CTX("in", "inches") : _L("mm");
|
||||
Vec3d tbb_sz = m_transformed_bounding_box.size() * koef; // ORCA
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
||||
@@ -1951,7 +1951,7 @@ void GLGizmoEmboss::draw_model_type()
|
||||
float minimum_spacing_x = 8.0f;
|
||||
float minimum_offset_x = ImGui::GetCursorPosX() + minimum_spacing_x;
|
||||
float offset_x = std::max(m_gui_cfg->input_offset, minimum_offset_x);
|
||||
ImGui::SameLine(offset_x);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGuiWrapper::push_radio_style(m_parent.get_scale()); // ORCA
|
||||
if (ImGui::RadioButton(_u8L("Join").c_str(), type == part))
|
||||
|
||||
@@ -315,6 +315,17 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||
ImGui::SameLine(drag_left_width + sliders_left_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (m_imgui->bbl_checkbox(_L("Vertical"), m_vertical_only)) {
|
||||
if (m_vertical_only) {
|
||||
m_horizontal_only = false;
|
||||
}
|
||||
}
|
||||
if (m_imgui->bbl_checkbox(_L("Horizontal"), m_horizontal_only)) {
|
||||
if (m_horizontal_only) {
|
||||
m_vertical_only = false;
|
||||
}
|
||||
}
|
||||
} else if (m_current_tool == ImGui::SphereButtonIcon) {
|
||||
m_cursor_type = TriangleSelector::CursorType::SPHERE;
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
@@ -327,6 +338,17 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||
ImGui::SameLine(drag_left_width + sliders_left_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (m_imgui->bbl_checkbox(_L("Vertical"), m_vertical_only)) {
|
||||
if (m_vertical_only) {
|
||||
m_horizontal_only = false;
|
||||
}
|
||||
}
|
||||
if (m_imgui->bbl_checkbox(_L("Horizontal"), m_horizontal_only)) {
|
||||
if (m_horizontal_only) {
|
||||
m_vertical_only = false;
|
||||
}
|
||||
}
|
||||
} else if (m_current_tool == ImGui::FillButtonIcon) {
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
m_tool_type = ToolType::SMART_FILL;
|
||||
|
||||
@@ -1252,7 +1252,7 @@ void GLGizmoMeasure::render_dimensioning()
|
||||
const bool use_inches = wxGetApp().app_config->get_bool("use_inches");
|
||||
const double curr_value = use_inches ? GizmoObjectManipulation::mm_to_in * distance : distance;
|
||||
const std::string curr_value_str = format_double(curr_value);
|
||||
const std::string units = use_inches ? _u8L("in") : _u8L("mm");
|
||||
const std::string units = use_inches ? _CTX_utf8("in", "inches") : _u8L("mm");
|
||||
const float value_str_width = 20.0f + ImGui::CalcTextSize(curr_value_str.c_str()).x;
|
||||
static double edit_value = 0.0;
|
||||
|
||||
@@ -1303,7 +1303,7 @@ void GLGizmoMeasure::render_dimensioning()
|
||||
return;
|
||||
|
||||
const double ratio = new_value / old_value;
|
||||
wxGetApp().plater()->take_snapshot(_u8L("Scale"), UndoRedo::SnapshotType::GizmoAction);
|
||||
wxGetApp().plater()->take_snapshot(_CTX_utf8("Scale", "Verb"), UndoRedo::SnapshotType::GizmoAction);
|
||||
// apply scale
|
||||
TransformationType type;
|
||||
type.set_world();
|
||||
@@ -2130,7 +2130,7 @@ void GLGizmoMeasure::show_face_face_assembly_senior()
|
||||
void GLGizmoMeasure::init_render_input_window()
|
||||
{
|
||||
m_use_inches = wxGetApp().app_config->get_bool("use_inches");
|
||||
m_units = m_use_inches ? " " + _u8L("in") : " " + _u8L("mm");
|
||||
m_units = " " + (m_use_inches ? _CTX_utf8("in", "inches") : _u8L("mm"));
|
||||
m_space_size = ImGui::CalcTextSize(" ").x * 2;
|
||||
m_input_size_max = ImGui::CalcTextSize("-100.00").x * 1.2;
|
||||
m_same_model_object = is_two_volume_in_same_model_object();
|
||||
|
||||
@@ -1704,7 +1704,7 @@ void GLGizmoSVG::draw_size()
|
||||
|
||||
if (m_keep_ratio) {
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(2) << std::fixed << width << " x " << height << " " << (use_inch ? "in" : "mm");
|
||||
ss << std::setprecision(2) << std::fixed << width << " x " << height << " " << (use_inch ? _CTX("in", "inches") : _L("mm"));
|
||||
|
||||
ImGui::SameLine(m_gui_cfg->input_offset);
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->input_width);
|
||||
@@ -1989,7 +1989,7 @@ void GLGizmoSVG::draw_mirroring()
|
||||
|
||||
void GLGizmoSVG::draw_model_type()
|
||||
{
|
||||
ImGui::AlignTextToFramePadding();
|
||||
//ImGui::AlignTextToFramePadding();
|
||||
bool is_last_solid_part = m_volume->is_the_only_one_part();
|
||||
std::string title = _u8L("Operation");
|
||||
if (is_last_solid_part) {
|
||||
@@ -2005,6 +2005,8 @@ void GLGizmoSVG::draw_model_type()
|
||||
ModelVolumeType part = ModelVolumeType::MODEL_PART;
|
||||
ModelVolumeType type = m_volume->type();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
//TRN EmbossOperation
|
||||
ImGuiWrapper::push_radio_style(m_parent.get_scale()); //ORCA
|
||||
if (ImGui::RadioButton(_u8L("Join").c_str(), type == part))
|
||||
|
||||
@@ -143,9 +143,9 @@ bool GLGizmoScale3D::on_init()
|
||||
std::string GLGizmoScale3D::on_get_name() const
|
||||
{
|
||||
if (!on_is_activable() && m_state == EState::Off) {
|
||||
return _u8L("Scale") + ":\n" + _u8L("Please select at least one object.");
|
||||
return _CTX_utf8("Scale", "Verb") + ":\n" + _u8L("Please select at least one object.");
|
||||
} else {
|
||||
return _u8L("Scale");
|
||||
return _CTX_utf8("Scale", "Verb");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ GizmoObjectManipulation::GizmoObjectManipulation(GLCanvas3D& glcanvas)
|
||||
: m_glcanvas(glcanvas)
|
||||
{
|
||||
m_imperial_units = wxGetApp().app_config->get("use_inches") == "1";
|
||||
m_new_unit_string = m_imperial_units ? L("in") : L("mm");
|
||||
m_new_unit_string = m_imperial_units ? L_CONTEXT("in", "inches") : L("mm");
|
||||
|
||||
const wxString shift = GUI::shortkey_shift_prefix();
|
||||
const wxString alt = GUI::shortkey_alt_prefix();
|
||||
@@ -92,7 +92,7 @@ void GizmoObjectManipulation::update_ui_from_settings()
|
||||
if (m_imperial_units != (wxGetApp().app_config->get("use_inches") == "1")) {
|
||||
m_imperial_units = wxGetApp().app_config->get("use_inches") == "1";
|
||||
|
||||
m_new_unit_string = m_imperial_units ? L("in") : L("mm");
|
||||
m_new_unit_string = m_imperial_units ? L_CONTEXT("in", "inches") : L("mm");
|
||||
|
||||
update_buffered_value();
|
||||
}
|
||||
@@ -1161,7 +1161,7 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
imgui_wrapper->calc_text_size(_L("Part")).x
|
||||
}) + imgui_wrapper->calc_text_size("xxx"sv).x + imgui_wrapper->scaled(3.5f);
|
||||
float label_max = std::max({
|
||||
imgui_wrapper->calc_text_size(_L("Scale")).x,
|
||||
imgui_wrapper->calc_text_size(_CTX("Scale", "Noun")).x,
|
||||
imgui_wrapper->calc_text_size(_L("Size")).x
|
||||
});
|
||||
float caption_max = std::max(label_max, coord_combo_width - 3 * space_size);
|
||||
@@ -1218,7 +1218,7 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
|
||||
//ImGui::PushItemWidth(unit_size * 2);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
imgui_wrapper->text(_L("Scale"));
|
||||
imgui_wrapper->text(_CTX("Scale", "Noun"));
|
||||
ImGui::SameLine(caption_max + space_size);
|
||||
ImGui::PushItemWidth(unit_size);
|
||||
ImGui::BBLInputDouble(label_scale_values[0][0], &scale[0], 0.0f, 0.0f, "%.2f");
|
||||
|
||||
@@ -2781,6 +2781,11 @@ void ImGuiWrapper::init_font(bool compress)
|
||||
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
|
||||
|
||||
io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
|
||||
// TexDesiredWidth will be increased adaptively below if the built height
|
||||
// exceeds GL_MAX_TEXTURE_SIZE. Leave it at 0 so ImGui picks the minimum
|
||||
// width for small glyph sets and we only widen when actually necessary.
|
||||
io.Fonts->TexDesiredWidth = 0;
|
||||
|
||||
ImFontConfig cfg = ImFontConfig();
|
||||
cfg.OversampleH = cfg.OversampleV = 1;
|
||||
//FIXME replace with io.Fonts->AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, m_font_size, nullptr, ranges.Data);
|
||||
@@ -2852,7 +2857,23 @@ void ImGuiWrapper::init_font(bool compress)
|
||||
io.Fonts->AddCustomRectFontGlyph(default_font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4);
|
||||
}
|
||||
|
||||
// Build texture atlas
|
||||
// Build texture atlas, widening it if the height would exceed GL_MAX_TEXTURE_SIZE.
|
||||
// Increasing the width allows the packing algorithm to grow more horizontally which reduces the height.
|
||||
io.Fonts->Build();
|
||||
GLint gl_max_tex_size = 0;
|
||||
glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_tex_size));
|
||||
constexpr int max_retries = 6;
|
||||
for (int attempt = 0; attempt < max_retries && io.Fonts->TexHeight > gl_max_tex_size; ++attempt) {
|
||||
io.Fonts->TexDesiredWidth = (io.Fonts->TexDesiredWidth > 0 ? io.Fonts->TexDesiredWidth : io.Fonts->TexWidth) * 2;
|
||||
io.Fonts->Build();
|
||||
}
|
||||
if (io.Fonts->TexHeight > gl_max_tex_size) {
|
||||
// Shouldn't really happen
|
||||
BOOST_LOG_TRIVIAL(error) << "Font atlas height " << io.Fonts->TexHeight
|
||||
<< " still exceeds GL_MAX_TEXTURE_SIZE (" << gl_max_tex_size << ")"
|
||||
<< " after " << max_retries << " attempts; rendering may be incomplete";
|
||||
}
|
||||
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
@@ -644,7 +644,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
|
||||
if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) {
|
||||
if (secondAction != _L("Play"))
|
||||
thirdAction = secondAction;
|
||||
secondAction = _L("Print");
|
||||
secondAction = _CTX("Print", "Verb");
|
||||
}
|
||||
// Draw buttons on hovered item
|
||||
wxRect rect{pt.x, pt.y + m_content_rect.GetBottom() - m_buttons_background.GetHeight(), m_content_rect.GetWidth(), m_buttons_background.GetHeight()};
|
||||
|
||||
@@ -2013,10 +2013,10 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
});
|
||||
|
||||
// upload and print
|
||||
SideButton* send_gcode_btn = new SideButton(p, _L("Print"), "");
|
||||
SideButton* send_gcode_btn = new SideButton(p, _CTX("Print", "Verb"), "");
|
||||
send_gcode_btn->SetCornerRadius(0);
|
||||
send_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
|
||||
m_print_btn->SetLabel(_L("Print"));
|
||||
m_print_btn->SetLabel(_CTX("Print", "Verb"));
|
||||
m_print_select = eSendGcode;
|
||||
m_print_enable = get_enable_print_status();
|
||||
m_print_btn->Enable(m_print_enable);
|
||||
@@ -2662,9 +2662,9 @@ static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame,
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Rear") + "\t" + ctrl + "4", _L("Rear View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("rear"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Left", "Camera"), "Camera") + "\t" + ctrl + "5", _L("Left View"),[mainFrame](wxCommandEvent &) {mainFrame->select_view("left"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _CTX("Left", "Camera View") + "\t" + ctrl + "5", _L("Left View"),[mainFrame](wxCommandEvent &) {mainFrame->select_view("left"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Right", "Camera"), "Camera") + "\t" + ctrl + "6", _L("Right View"),[mainFrame](wxCommandEvent &) { mainFrame->select_view("right"); },
|
||||
append_menu_item(view_menu, wxID_ANY, _CTX("Right", "Camera View") + "\t" + ctrl + "6", _L("Right View"),[mainFrame](wxCommandEvent &) { mainFrame->select_view("right"); },
|
||||
"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
|
||||
}
|
||||
|
||||
@@ -2809,21 +2809,6 @@ void MainFrame::init_menubar_as_editor()
|
||||
append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), "");
|
||||
|
||||
fileMenu->AppendSeparator();
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Sync Presets"), _L("Pull and apply the latest presets from OrcaCloud"),
|
||||
[this](wxCommandEvent&) {
|
||||
if (!wxGetApp().is_user_login()) {
|
||||
MessageDialog info_dlg(this, _L("You must be logged in to sync presets from cloud."),
|
||||
_L("Sync Presets"), wxOK | wxICON_INFORMATION);
|
||||
info_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
wxGetApp().restart_sync_user_preset();
|
||||
}, "", nullptr,
|
||||
[this]() {
|
||||
return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode();
|
||||
}, this);
|
||||
|
||||
fileMenu->AppendSeparator();
|
||||
|
||||
#ifndef __APPLE__
|
||||
append_menu_item(fileMenu, wxID_EXIT, _L("Quit"), wxString::Format(_L("Quit")),
|
||||
@@ -3289,6 +3274,8 @@ void MainFrame::init_menubar_as_editor()
|
||||
},
|
||||
"", nullptr, []() { return true; }, this);
|
||||
|
||||
m_topbar->GetTopMenu()->AppendSeparator();
|
||||
|
||||
append_menu_item(
|
||||
m_topbar->GetTopMenu(), wxID_ANY, _L("Preset Bundle") + "\t", "",
|
||||
[this](wxCommandEvent &) {
|
||||
@@ -3316,6 +3303,8 @@ void MainFrame::init_menubar_as_editor()
|
||||
return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode();
|
||||
}, this);
|
||||
|
||||
m_topbar->GetTopMenu()->AppendSeparator();
|
||||
|
||||
//m_topbar->AddDropDownMenuItem(preference_item);
|
||||
//m_topbar->AddDropDownMenuItem(printer_item);
|
||||
//m_topbar->AddDropDownMenuItem(language_item);
|
||||
@@ -3425,6 +3414,25 @@ void MainFrame::init_menubar_as_editor()
|
||||
plater()->get_current_canvas3D()->force_set_focus();
|
||||
},
|
||||
"", nullptr, []() { return true; }, this);
|
||||
|
||||
append_menu_item(
|
||||
fileMenu, wxID_ANY, _L("Sync Presets"), _L("Pull and apply the latest presets from OrcaCloud"),
|
||||
[this](wxCommandEvent&) {
|
||||
if (!wxGetApp().is_user_login()) {
|
||||
MessageDialog info_dlg(this, _L("You must be logged in to sync presets from cloud."),
|
||||
_L("Sync Presets"), wxOK | wxICON_INFORMATION);
|
||||
info_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
if (m_plater)
|
||||
m_plater->get_notification_manager()->push_notification(
|
||||
into_u8(_L("Syncing presets from cloud\u2026")));
|
||||
wxGetApp().restart_sync_user_preset();
|
||||
}, "", nullptr,
|
||||
[this]() {
|
||||
return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode();
|
||||
}, this);
|
||||
|
||||
m_menubar->Append(fileMenu, wxString::Format("&%s", _L("File")));
|
||||
if (editMenu)
|
||||
m_menubar->Append(editMenu, wxString::Format("&%s", _L("Edit")));
|
||||
@@ -4040,7 +4048,7 @@ void MainFrame::set_print_button_to_default(PrintSelectType select_type)
|
||||
m_print_btn->Enable(m_print_enable);
|
||||
this->Layout();
|
||||
} else if (select_type == PrintSelectType::eSendGcode) {
|
||||
m_print_btn->SetLabel(_L("Print"));
|
||||
m_print_btn->SetLabel(_CTX("Print", "Verb"));
|
||||
m_print_select = eSendGcode;
|
||||
if (m_print_enable)
|
||||
m_print_enable = get_enable_print_status() && can_send_gcode();
|
||||
|
||||
@@ -520,7 +520,7 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
|
||||
fs->SetUrl(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, wxGetApp().get_printer_cloud_provider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,7 +556,7 @@ void MediaFilePanel::doAction(size_t index, int action)
|
||||
} else if (action == 1) {
|
||||
if (fs->GetFileType() == PrinterFileSystem::F_MODEL) {
|
||||
if (index != -1) {
|
||||
auto dlg = new MediaProgressDialog(_L("Print"), this, [fs] { fs->FetchModelCancel(); });
|
||||
auto dlg = new MediaProgressDialog(_CTX("Print", "Verb"), this, [fs] { fs->FetchModelCancel(); });
|
||||
dlg->Update(0, _L("Fetching model information..."));
|
||||
fs->FetchModel(index, [this, fs, dlg, index](int result, std::string const &data) {
|
||||
dlg->Destroy();
|
||||
@@ -566,7 +566,7 @@ void MediaFilePanel::doAction(size_t index, int action)
|
||||
wxString msg = data.empty() ? _L("Failed to fetch model information from printer.") :
|
||||
from_u8(data);
|
||||
CallAfter([this, msg] {
|
||||
MessageDialog(this, msg, _L("Print"), wxOK).ShowModal();
|
||||
MessageDialog(this, msg, _CTX("Print", "Verb"), wxOK).ShowModal();
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -579,7 +579,7 @@ void MediaFilePanel::doAction(size_t index, int action)
|
||||
|| plate_data_list.empty()) {
|
||||
MessageDialog(this,
|
||||
_L("Failed to parse model information."),
|
||||
_L("Print"), wxOK).ShowModal();
|
||||
_CTX("Print", "Verb"), wxOK).ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2299,9 +2299,17 @@ void NotificationManager::push_import_finished_notification(const std::string& p
|
||||
void NotificationManager::SharedProfilesNotification::init()
|
||||
{
|
||||
PopNotification::init();
|
||||
// Add two extra lines for the hyperlink row ("Browse shared profiles" + "Don't show again")
|
||||
// and 1 more additional line for adding spacing between them to make it easier to click
|
||||
m_lines_count = m_lines_count + 2; // ORCA
|
||||
|
||||
// PopNotification::count_lines() may append a duplicate "hypertext doesn't fit inline" placeholder endline (same value as the previous entry)
|
||||
// for the generic renderer's benefit. This class always renders its hyperlink on its own dedicated line regardless,
|
||||
// so that placeholder is meaningless here and would otherwise be drawn as a spurious blank text row.
|
||||
if (!m_hypertext.empty() && m_endlines.size() >= 2 && m_endlines.back() == m_endlines[m_endlines.size() - 2]) {
|
||||
m_endlines.pop_back();
|
||||
m_lines_count--;
|
||||
}
|
||||
|
||||
// Reserve rows for: "Browse shared profiles" hyperlink, spacing, "Don't show again"
|
||||
m_lines_count += 3;
|
||||
}
|
||||
|
||||
void NotificationManager::SharedProfilesNotification::render_text(ImGuiWrapper& imgui,
|
||||
@@ -2327,22 +2335,26 @@ void NotificationManager::SharedProfilesNotification::render_text(ImGuiWrapper&
|
||||
}
|
||||
}
|
||||
|
||||
// Render "Browse shared profiles" hyperlink on the next line
|
||||
float hyper_y = starting_y + m_endlines.size() * shift_y - m_line_height / 2.f;
|
||||
render_hypertext(imgui, x_offset, hyper_y, m_hypertext);
|
||||
|
||||
// Render "Don't show again" hyperlink after the browse link
|
||||
{
|
||||
float dont_show_y = hyper_y + ImGui::CalcTextSize((m_hypertext + " ").c_str()).y + m_line_height / 2.f;
|
||||
std::string dont_show_text = _u8L("Don't show again");
|
||||
float hyper_y = starting_y + m_endlines.size() * shift_y + m_line_height * .5f;
|
||||
float dont_show_y = hyper_y + ImGui::CalcTextSize((m_hypertext + " ").c_str()).y + m_line_height * .5f;
|
||||
std::string dont_show_text = _u8L("Don't show again") + std::to_string(m_endlines.size());
|
||||
ImVec2 part_size = ImGui::CalcTextSize(dont_show_text.c_str());
|
||||
|
||||
if (!m_multiline && m_lines_count > 2) {
|
||||
render_hypertext(imgui, x_offset + (m_endlines.size() == 1 ? 0 : ImGui::CalcTextSize((line + " ").c_str()).x) , starting_y + shift_y, _u8L("More"), true);
|
||||
}
|
||||
else {
|
||||
// Render "Browse shared profiles" hyperlink on the next line
|
||||
render_hypertext(imgui, x_offset, hyper_y, m_hypertext);
|
||||
|
||||
// Invisible button
|
||||
ImGui::SetCursorPosX(x_offset); // ORCA render on new line to prevent long translations from being cut off
|
||||
ImGui::SetCursorPosY(dont_show_y);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
|
||||
// Render "Don't show again" hyperlink after the browse link
|
||||
if (imgui.button("##dont_show_btn", part_size.x + 6, part_size.y + 10)) {
|
||||
wxGetApp().app_config->set_bool("show_shared_profiles_notification", false);
|
||||
wxGetApp().app_config->save();
|
||||
@@ -2370,6 +2382,7 @@ void NotificationManager::SharedProfilesNotification::render_text(ImGuiWrapper&
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd,
|
||||
IM_COL32((int)(color.x * 255), (int)(color.y * 255), (int)(color.z * 255),
|
||||
(int)(color.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2382,8 +2395,10 @@ bool NotificationManager::SharedProfilesNotification::on_text_click()
|
||||
void NotificationManager::SharedProfilesNotification::render_hypertext(ImGuiWrapper& imgui,
|
||||
const float text_x, const float text_y, const std::string text, bool more)
|
||||
{
|
||||
render_hyperlink_action(imgui, text_x, text_y, text, "##browse_btn",
|
||||
[this] { if (on_text_click()) close(); });
|
||||
if (more)
|
||||
PopNotification::render_hypertext(imgui, text_x, text_y, text, true);
|
||||
else
|
||||
render_hyperlink_action(imgui, text_x, text_y, text, "##browse_btn", [this] { if (on_text_click()) close(); });
|
||||
}
|
||||
|
||||
void NotificationManager::OrcaSyncConflictNotification::init()
|
||||
|
||||
@@ -385,7 +385,7 @@ void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global)
|
||||
}
|
||||
}
|
||||
|
||||
bool PartPlate::valid_instance(int obj_id, int instance_id)
|
||||
bool PartPlate::valid_instance(int obj_id, int instance_id) const
|
||||
{
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
{
|
||||
@@ -1688,7 +1688,7 @@ std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
if (valid_instance(obj_id, instance_id))
|
||||
{
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
@@ -2359,6 +2359,9 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height
|
||||
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
|
||||
@@ -2833,7 +2836,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
if (valid_instance(obj_id, instance_id))
|
||||
{
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
@@ -2866,7 +2869,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
if (valid_instance(obj_id, instance_id))
|
||||
{
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
@@ -2983,8 +2986,8 @@ int PartPlate::printable_instance_size()
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if (obj_id >= m_model->objects.size())
|
||||
continue;
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject * object = m_model->objects[obj_id];
|
||||
ModelInstance *instance = object->instances[instance_id];
|
||||
@@ -3006,7 +3009,7 @@ bool PartPlate::has_printable_instances()
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if (obj_id >= m_model->objects.size())
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
@@ -3030,7 +3033,8 @@ bool PartPlate::is_all_instances_unprintable()
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if (obj_id >= m_model->objects.size()) continue;
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject * object = m_model->objects[obj_id];
|
||||
ModelInstance *instance = object->instances[instance_id];
|
||||
|
||||
@@ -167,7 +167,7 @@ private:
|
||||
wxCoord m_name_texture_height;
|
||||
|
||||
void init();
|
||||
bool valid_instance(int obj_id, int instance_id);
|
||||
bool valid_instance(int obj_id, int instance_id) const;
|
||||
void generate_print_polygon(ExPolygon &print_polygon);
|
||||
void generate_exclude_polygon(ExPolygon &exclude_polygon);
|
||||
void generate_logo_polygon(ExPolygon &logo_polygon);
|
||||
|
||||
+32
-37
@@ -537,6 +537,7 @@ struct Sidebar::priv
|
||||
//wxComboBox * m_comboBox_print_preset;
|
||||
wxStaticLine * m_staticline1;
|
||||
StaticBox* m_panel_filament_title;
|
||||
wxPanel* m_panel_filament_separator;
|
||||
wxStaticText* m_staticText_filament_settings;
|
||||
wxStaticText* m_staticText_filament_count;
|
||||
ScalableButton * m_bpButton_add_filament;
|
||||
@@ -556,6 +557,7 @@ struct Sidebar::priv
|
||||
|
||||
// BBS printer config
|
||||
StaticBox* m_panel_printer_title = nullptr;
|
||||
wxPanel* m_panel_printer_separator = nullptr;
|
||||
ScalableButton* m_printer_icon = nullptr;
|
||||
ScalableButton* m_printer_connect = nullptr;
|
||||
ScalableButton* m_printer_bbl_sync = nullptr;
|
||||
@@ -1735,10 +1737,6 @@ Sidebar::Sidebar(Plater *parent)
|
||||
p->m_panel_printer_title->Layout();
|
||||
|
||||
// 1.2 Add spliters around title bar
|
||||
// add spliter 1
|
||||
//auto spliter_1 = new ::StaticLine(p->scrolled);
|
||||
//spliter_1->SetBackgroundColour("#A6A9AA");
|
||||
//scrolled_sizer->Add(spliter_1, 0, wxEXPAND);
|
||||
|
||||
// add printer title
|
||||
scrolled_sizer->Add(p->m_panel_printer_title, 0, wxEXPAND | wxALL, 0);
|
||||
@@ -1750,14 +1748,13 @@ Sidebar::Sidebar(Plater *parent)
|
||||
wxString title = _L("Printer") + wxString(!isShown ? "" : (" | " + p->combo_printer->GetValue()));
|
||||
p->m_text_printer_settings->SetLabel(title);
|
||||
p->m_panel_printer_content->Show(!isShown);
|
||||
p->m_panel_printer_separator->Show(isShown);
|
||||
m_scrolled_sizer->Layout();
|
||||
});
|
||||
|
||||
// add spliter 2
|
||||
auto spliter_2 = new ::StaticLine(p->scrolled);
|
||||
spliter_2->SetLineColour("#CECECE");
|
||||
scrolled_sizer->Add(spliter_2, 0, wxEXPAND);
|
||||
|
||||
// ORCA add bottom border for seperation wile sections folded
|
||||
p->m_panel_printer_separator = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(2))); // ORCA staticline class not works without string
|
||||
p->m_panel_printer_separator->SetBackgroundColour("#FFFFFF");
|
||||
scrolled_sizer->Add(p->m_panel_printer_separator, 0, wxEXPAND);
|
||||
|
||||
/*************************** 2. add printer content ************************/
|
||||
|
||||
@@ -1937,9 +1934,9 @@ Sidebar::Sidebar(Plater *parent)
|
||||
}
|
||||
|
||||
wxGridSizer *nozzle_dia_sizer = new wxGridSizer(3, 1, FromDIP(2), 0);
|
||||
nozzle_dia_sizer->Add(p->label_nozzle_title, 0, wxALIGN_CENTER | wxTOP, FromDIP(4));
|
||||
nozzle_dia_sizer->Add(p->combo_nozzle_dia , 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, FromDIP(2));
|
||||
nozzle_dia_sizer->Add(p->label_nozzle_type , 0, wxALIGN_CENTER);
|
||||
nozzle_dia_sizer->Add(p->label_nozzle_title, 1, wxALIGN_CENTER | wxTOP , FromDIP(2));
|
||||
nozzle_dia_sizer->Add(p->combo_nozzle_dia , 0, wxALIGN_CENTER);
|
||||
nozzle_dia_sizer->Add(p->label_nozzle_type , 1, wxALIGN_CENTER | wxBOTTOM, FromDIP(1));
|
||||
|
||||
p->panel_nozzle_dia->SetSizer(nozzle_dia_sizer);
|
||||
|
||||
@@ -2108,7 +2105,9 @@ Sidebar::Sidebar(Plater *parent)
|
||||
else if (ams_btn->IsShown()) exclude_pt = ams_btn->GetPosition().x;
|
||||
if (e.GetPosition().x > exclude_pt)
|
||||
return;
|
||||
p->m_panel_filament_content->Show(!p->m_panel_filament_content->IsShown());
|
||||
bool isShown = p->m_panel_filament_content->IsShown();
|
||||
p->m_panel_filament_content->Show(!isShown);
|
||||
p->m_panel_filament_separator->Show(isShown);
|
||||
m_scrolled_sizer->Layout();
|
||||
|
||||
CallAfter([this]{update_filaments_counter(true);}); // call after all UI processing done
|
||||
@@ -2128,13 +2127,11 @@ Sidebar::Sidebar(Plater *parent)
|
||||
|
||||
p->m_panel_filament_title->SetSizer( bSizer39 );
|
||||
p->m_panel_filament_title->Layout();
|
||||
auto spliter_1 = new ::StaticLine(p->scrolled);
|
||||
spliter_1->SetLineColour("#A6A9AA");
|
||||
scrolled_sizer->Add(spliter_1, 0, wxEXPAND);
|
||||
scrolled_sizer->Add(p->m_panel_filament_title, 0, wxEXPAND | wxALL, 0);
|
||||
auto spliter_2 = new ::StaticLine(p->scrolled);
|
||||
spliter_2->SetLineColour("#CECECE");
|
||||
scrolled_sizer->Add(spliter_2, 0, wxEXPAND);
|
||||
// ORCA add bottom border for seperation wile sections folded
|
||||
p->m_panel_filament_separator = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(2))); // ORCA staticline class not works without string
|
||||
p->m_panel_filament_separator->SetBackgroundColour("#FFFFFF");
|
||||
scrolled_sizer->Add(p->m_panel_filament_separator, 0, wxEXPAND);
|
||||
|
||||
bSizer39->AddStretchSpacer(1);
|
||||
|
||||
@@ -9687,11 +9684,14 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// BBS
|
||||
// wxWindowUpdateLocker noUpdates1(sidebar->print_panel());
|
||||
wxWindowUpdateLocker noUpdates2(sidebar->filament_panel());
|
||||
wxGetApp().get_tab(preset_type)->select_preset(preset_name);
|
||||
// update plater with new config
|
||||
q->on_config_change(wxGetApp().preset_bundle->full_config());
|
||||
}
|
||||
//BBS
|
||||
//wxWindowUpdateLocker noUpdates1(sidebar->print_panel());
|
||||
wxWindowUpdateLocker noUpdates2(sidebar->filament_panel());
|
||||
wxGetApp().get_tab(preset_type)->select_preset(preset_name);
|
||||
}
|
||||
|
||||
// ORCA: Always refresh the selected filament combo so its color swatch (clr_picker)
|
||||
@@ -12212,8 +12212,9 @@ void Plater::load_project(wxString const& filename2,
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": current loading other project, return directly");
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_loading_project = true;
|
||||
|
||||
m_loading_project = true;
|
||||
ScopeGuard loading_project_sc([this]() { m_loading_project = false; }); // Make sure state restored on any early return
|
||||
|
||||
m_only_gcode = false;
|
||||
m_exported_file = false;
|
||||
@@ -12307,7 +12308,6 @@ void Plater::load_project(wxString const& filename2,
|
||||
sidebar().set_flushing_volume_warning(has_modify);
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " load project done";
|
||||
m_loading_project = false;
|
||||
}
|
||||
|
||||
// BBS: save logic
|
||||
@@ -13113,6 +13113,9 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i
|
||||
_obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f));
|
||||
_obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45));
|
||||
_obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));
|
||||
_obj->config.set_key_value("anisotropic_surfaces", new ConfigOptionBool(false));
|
||||
_obj->config.set_key_value("center_of_surface_pattern", new ConfigOptionEnum<CenterOfSurfacePattern>(CenterOfSurfacePattern::Each_Surface));
|
||||
_obj->config.set_key_value("separated_infills", new ConfigOptionBool(false));
|
||||
_obj->config.set_key_value("align_infill_direction_to_model", new ConfigOptionBool(true));
|
||||
_obj->config.set_key_value("ironing_type", new ConfigOptionEnum<IroningType>(IroningType::NoIroning));
|
||||
_obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloatsNullable(internal_solid_speeds));
|
||||
@@ -13923,17 +13926,9 @@ bool Plater::preview_zip_archive(const boost::filesystem::path& archive_path)
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
|
||||
if (size != stat.m_uncomp_size) // size must fit
|
||||
continue;
|
||||
wxString wname = boost::nowide::widen(stat.m_filename);
|
||||
std::string name = into_u8(wname);
|
||||
std::string name = Slic3r::decode_archive_entry_path(&archive, stat);
|
||||
fs::path archive_path(name);
|
||||
|
||||
std::string extra(1024, 0);
|
||||
size_t extra_size = mz_zip_reader_get_filename_from_extra(&archive, i, extra.data(), extra.size());
|
||||
if (extra_size > 0) {
|
||||
archive_path = fs::path(extra.substr(0, extra_size));
|
||||
name = archive_path.string();
|
||||
}
|
||||
|
||||
if (archive_path.empty())
|
||||
continue;
|
||||
if (path != archive_path)
|
||||
@@ -15750,7 +15745,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
||||
std::vector<Preset*> project_presets = preset_bundle.get_current_project_embedded_presets();
|
||||
|
||||
StoreParams store_params;
|
||||
store_params.path = path_u8.c_str();
|
||||
store_params.path = path_u8;
|
||||
store_params.model = &p->model;
|
||||
store_params.plate_data_list = plate_data_list;
|
||||
store_params.export_plate_idx = export_plate_idx;
|
||||
|
||||
@@ -797,7 +797,7 @@ wxBoxSizer *PreferencesDialog::create_item_decimal_input(wxString title, wxStrin
|
||||
input->SetToolTip(tooltip);
|
||||
input->GetTextCtrl()->SetValidator(validator);
|
||||
|
||||
m_sizer->Add(input, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(5));
|
||||
m_sizer->Add(input, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
auto apply_value = [this, param, input, min, max, decimals]() {
|
||||
auto value = input->GetTextCtrl()->GetValue();
|
||||
@@ -1797,6 +1797,17 @@ void PreferencesDialog::create_items()
|
||||
g_sizer = f_sizers.back();
|
||||
g_sizer->AddGrowableCol(0, 1);
|
||||
|
||||
//// GRAPHICS > General
|
||||
g_sizer->Add(create_item_title(_L("General")), 1, wxEXPAND);
|
||||
|
||||
auto smooth_normals = create_item_checkbox(
|
||||
_L("Smooth normals"),
|
||||
_L("Applies smooth normals to the model.\n\nRequires manual scene reload to take effect "
|
||||
"(right-click on 3D view → \"Reload All\")."),
|
||||
SETTING_OPENGL_PHONG_SMOOTH_NORMALS
|
||||
);
|
||||
g_sizer->Add(smooth_normals);
|
||||
|
||||
//// GRAPHICS > Realistic view
|
||||
g_sizer->Add(create_item_title(_L("Realistic View")), 1, wxEXPAND);
|
||||
|
||||
@@ -1816,20 +1827,11 @@ void PreferencesDialog::create_items()
|
||||
|
||||
auto item_realistic_shadows = create_item_checkbox(
|
||||
_L("Shadows"),
|
||||
_L("Renders cast shadows on the plate in realistic view."),
|
||||
_L("Renders cast shadows on the plate, other objects, and each object onto itself in realistic view."),
|
||||
SETTING_OPENGL_PHONG_BASIC_PLATE_SHADOWS
|
||||
);
|
||||
g_sizer->Add(item_realistic_shadows);
|
||||
|
||||
|
||||
auto item_realistic_smooth_normals = create_item_checkbox(
|
||||
_L("Smooth normals"),
|
||||
_L("Applies smooth normals to the realistic view.\n\nRequires manual scene reload to take effect "
|
||||
"(right-click on 3D view → \"Reload All\")."),
|
||||
SETTING_OPENGL_PHONG_SMOOTH_NORMALS
|
||||
);
|
||||
g_sizer->Add(item_realistic_smooth_normals);
|
||||
|
||||
//// GRAPHICS > Anti-aliasing
|
||||
g_sizer->Add(create_item_title(_L("Anti-aliasing")), 1, wxEXPAND);
|
||||
|
||||
|
||||
@@ -1310,7 +1310,7 @@ void PlaterPresetComboBox::update()
|
||||
selected_in_ams = add_ams_filaments(into_u8(selected_user_preset.empty() ? selected_system_preset : selected_user_preset), true);
|
||||
}
|
||||
|
||||
std::vector<std::string> filament_orders = {"Bambu PLA Basic", "Bambu PLA Matte", "Bambu PETG HF", "Bambu ABS", "Bambu PLA Silk", "Bambu PLA-CF",
|
||||
std::vector<wxString> filament_orders = {"Bambu PLA Basic", "Bambu PLA Matte", "Bambu PETG HF", "Bambu ABS", "Bambu PLA Silk", "Bambu PLA-CF",
|
||||
"Bambu PLA Galaxy", "Bambu PLA Metal", "Bambu PLA Marble", "Bambu PETG-CF", "Bambu PETG Translucent", "Bambu ABS-GF"};
|
||||
std::vector<std::string> first_vendors = {"", "Bambu", "Generic"}; // Empty vendor for non-system presets
|
||||
std::vector<std::string> first_types = {"PLA", "PETG", "ABS", "TPU"};
|
||||
@@ -1600,6 +1600,7 @@ TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type)
|
||||
// BBS: new layout
|
||||
PresetComboBox(parent, preset_type, wxSize(20 * wxGetApp().em_unit(), 30 * wxGetApp().em_unit() / 10))
|
||||
{
|
||||
GetDropDown().SetUseContentWidth(true,true);
|
||||
}
|
||||
|
||||
void TabPresetComboBox::OnSelect(wxCommandEvent &evt)
|
||||
|
||||
@@ -138,7 +138,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
|
||||
|
||||
/*mode switch*/
|
||||
/*auto m_sizer_mode_switch = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_mode_print = new SendModeSwitchButton(scroll_area, _L("Print"), true);
|
||||
m_mode_print = new SendModeSwitchButton(scroll_area, _CTX("Print", "Verb"), true);
|
||||
m_mode_send = new SendModeSwitchButton(scroll_area,_L("Save to printer"), false);
|
||||
m_sizer_mode_switch->Add(m_mode_print, 0, wxALIGN_CENTER, 0);
|
||||
m_sizer_mode_switch->Add(0, 0, 0, wxLEFT, FromDIP(8));
|
||||
|
||||
@@ -30,7 +30,7 @@ static int _ITEM_WIDTH() { return _scale(30); }
|
||||
#define SLIDER_SCALE_10(val) ((val) / 0.01)
|
||||
#define SLIDER_UNSCALE_10(val) ((val) * 0.01)
|
||||
#define LEFT_RIGHT_PADING FromDIP(20)
|
||||
#define FONT_COLOR wxColour("#262E30")
|
||||
#define FONT_COLOR wxColour("#363636") // label color
|
||||
|
||||
wxDEFINE_EVENT(wxEVT_THREAD_DONE, wxCommandEvent);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/CheckBox.hpp"
|
||||
#include "Widgets/DialogButtons.hpp"
|
||||
#include "CapsuleButton.hpp"
|
||||
#include "PrePrintChecker.hpp"
|
||||
|
||||
@@ -37,7 +38,7 @@ using namespace Slic3r::GUI;
|
||||
#define SyncAmsInfoDialogWidth FromDIP(675)
|
||||
#define SyncAmsInfoDialogHeightMIN FromDIP(620)
|
||||
#define SyncAmsInfoDialogHeightMIDDLE FromDIP(630)
|
||||
#define SyncAmsInfoDialogHeightMAX FromDIP(660)
|
||||
#define SyncAmsInfoDialogHeightMAX FromDIP(700)
|
||||
#define SyncLabelWidth FromDIP(640)
|
||||
#define SyncAttentionTipWidth FromDIP(550)
|
||||
namespace Slic3r { namespace GUI {
|
||||
@@ -282,14 +283,14 @@ wxBoxSizer *SyncAmsInfoDialog::create_sizer_thumbnail(wxButton *image_button, bo
|
||||
if (left) {
|
||||
wxBoxSizer *text_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto sync_text = new Label(image_button->GetParent(), _CTX(L_CONTEXT("Original", "Sync_AMS"), "Sync_AMS"));
|
||||
sync_text->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
sync_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
text_sizer->Add(sync_text, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
sizer_thumbnail->Add(sync_text, FromDIP(0), wxALIGN_CENTER | wxALL, FromDIP(4));
|
||||
}
|
||||
else {
|
||||
wxBoxSizer *text_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_after_map_text = new Label(image_button->GetParent(), _L("After mapping"));
|
||||
m_after_map_text->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_after_map_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
text_sizer->Add(m_after_map_text, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
sizer_thumbnail->Add(m_after_map_text, FromDIP(0), wxALIGN_CENTER | wxALL, FromDIP(4));
|
||||
}
|
||||
@@ -655,10 +656,6 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
// font
|
||||
SetFont(wxGetApp().normal_font());
|
||||
|
||||
// icon
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
Freeze();
|
||||
SetBackgroundColour(m_colour_def_color);
|
||||
|
||||
@@ -733,7 +730,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
m_colormap_btn->Bind(wxEVT_BUTTON, &SyncAmsInfoDialog::update_when_change_map_mode,this); // update_when_change_map_mode(e.GetSelection());
|
||||
m_override_btn->Bind(wxEVT_BUTTON, &SyncAmsInfoDialog::update_when_change_map_mode,this);
|
||||
|
||||
bSizer->Add(m_mode_combox_sizer, FromDIP(0), wxEXPAND | wxTOP, FromDIP(10));
|
||||
bSizer->Add(m_mode_combox_sizer, FromDIP(0), wxEXPAND | wxTOP | wxBOTTOM, FromDIP(10));
|
||||
}
|
||||
|
||||
m_basic_panel = new wxPanel(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
@@ -847,8 +844,8 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
|
||||
sizer_advanced_options_title = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto advanced_options_title = new Label(m_scrolledWindow, _L("Advanced Options"));
|
||||
advanced_options_title->SetFont(::Label::Body_13);
|
||||
advanced_options_title->SetForegroundColour(wxColour(38, 46, 48));
|
||||
advanced_options_title->SetFont(::Label::Head_14); // ORCA
|
||||
advanced_options_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
|
||||
sizer_advanced_options_title->Add(0, 0, 1, wxEXPAND, 0);
|
||||
sizer_advanced_options_title->Add(advanced_options_title, 0, wxALIGN_CENTER, 0);
|
||||
@@ -914,13 +911,15 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
{//new content//tip confirm ok button
|
||||
wxBoxSizer *tip_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_attention_text = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Tip") + ": ");
|
||||
m_attention_text->SetFont(::Label::Head_14);
|
||||
m_attention_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#009688"))); // ORCA match label colors
|
||||
tip_sizer->Add(m_attention_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(2));
|
||||
m_tip_attention_color_map = _L("Only synchronize filament type and color, not including AMS slot information.");
|
||||
m_tip_attention_override = _L("Replace the project filaments list sequentially based on printer filaments. And unused printer filaments will be automatically added to the end of the list.");
|
||||
m_tip_text = new Label(m_scrolledWindow, m_tip_attention_color_map, LB_AUTO_WRAP);
|
||||
m_tip_text->SetMinSize(wxSize(SyncAttentionTipWidth, -1));
|
||||
m_tip_text->SetMaxSize(wxSize(SyncAttentionTipWidth, -1));
|
||||
m_tip_text->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_tip_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
tip_sizer->Add(m_tip_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(2));
|
||||
tip_sizer->AddSpacer(FromDIP(20));
|
||||
bSizer->Add(tip_sizer, 0, wxEXPAND | wxLEFT, FromDIP(25));
|
||||
@@ -931,7 +930,8 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
|
||||
m_advace_setting_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_more_setting_tips = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Advanced settings"));
|
||||
m_more_setting_tips->SetForegroundColour(wxColour(0, 137, 123));
|
||||
m_more_setting_tips->SetFont(::Label::Head_14); // ORCA
|
||||
m_more_setting_tips->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_more_setting_tips->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
|
||||
m_expand_more_settings = !m_expand_more_settings;
|
||||
update_more_setting(true,true);
|
||||
@@ -959,6 +959,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
m_append_color_sizer->Add(m_append_color_checkbox, 0, wxALIGN_LEFT | wxTOP, FromDIP(4));
|
||||
const int gap_between_checebox_and_text = 2;
|
||||
m_append_color_text = new Label(m_scrolledWindow, _L("Add unused AMS filaments to filaments list."));
|
||||
m_append_color_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_append_color_text->Hide();
|
||||
m_append_color_sizer->AddSpacer(FromDIP(gap_between_checebox_and_text));
|
||||
m_append_color_sizer->Add(m_append_color_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(4));
|
||||
@@ -981,6 +982,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
|
||||
|
||||
m_merge_color_text = new Label(m_scrolledWindow, _L("Automatically merge the same colors in the model after mapping."));
|
||||
m_merge_color_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_merge_color_text->Hide();
|
||||
m_merge_color_sizer->AddSpacer(FromDIP(gap_between_checebox_and_text));
|
||||
m_merge_color_sizer->Add(m_merge_color_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(2));
|
||||
@@ -994,17 +996,19 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
m_override_undone_str = _L("After being synced, this action cannot be undone.");
|
||||
m_undone_str = _L("After being synced, the project's filament presets and colors will be replaced with the mapped filament types and colors. This action cannot be undone.");
|
||||
m_confirm_title = new Label(m_scrolledWindow, m_undone_str, LB_AUTO_WRAP);
|
||||
m_confirm_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_confirm_title->SetMinSize(wxSize(SyncLabelWidth, -1));
|
||||
m_confirm_title->SetMaxSize(wxSize(SyncLabelWidth, -1));
|
||||
confirm_boxsizer->Add(m_confirm_title, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP | wxRIGHT, FromDIP(10));
|
||||
confirm_boxsizer->Add(m_confirm_title, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP | wxRIGHT | wxBOTTOM, FromDIP(10));
|
||||
m_are_you_sure_title = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Are you sure to synchronize the filaments?"));
|
||||
m_are_you_sure_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
//m_are_you_sure_title->SetFont(Label::Head_14);
|
||||
confirm_boxsizer->Add(m_are_you_sure_title, 0, wxALIGN_LEFT | wxTOP, FromDIP(0));
|
||||
bSizer->Add(confirm_boxsizer, 0, wxALIGN_LEFT | wxLEFT , FromDIP(25));
|
||||
|
||||
wxBoxSizer *warning_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_warning_text = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Error") + ":");
|
||||
m_warning_text->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_warning_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_warning_text->Hide();
|
||||
warning_sizer->Add(m_warning_text, 0, wxALIGN_CENTER | wxTOP, FromDIP(2));
|
||||
bSizer->Add(warning_sizer, 0, wxEXPAND | wxLEFT, FromDIP(25));
|
||||
@@ -1012,46 +1016,22 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) :
|
||||
m_scrolledWindow->SetSizerAndFit(m_sizer_main);
|
||||
m_sizer_show_page->Add(m_scrolledWindow, 1, wxEXPAND, 0);
|
||||
|
||||
wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL);
|
||||
bSizer_button->SetMinSize(wxSize(FromDIP(100), -1));
|
||||
/* m_checkbox = new wxCheckBox(this, wxID_ANY, _L("Don't show again"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
bSizer_button->Add(m_checkbox, 0, wxALIGN_LEFT);*/
|
||||
bSizer_button->AddStretchSpacer(1);
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
|
||||
m_button_ok = new Button(m_show_page, _L("Synchronize now"));
|
||||
m_button_ok->SetBackgroundColor(btn_bg_green);
|
||||
m_button_ok->SetBorderColor(*wxWHITE);
|
||||
m_button_ok->SetTextColor(wxColour("#FFFFFE"));
|
||||
m_button_ok->SetFont(Label::Body_12);
|
||||
m_button_ok->SetSize(OK_BUTTON_SIZE);
|
||||
m_button_ok->SetMinSize(OK_BUTTON_SIZE);
|
||||
m_button_ok->SetCornerRadius(FromDIP(12));
|
||||
bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10));
|
||||
|
||||
auto* dlg_btns = new DialogButtons(m_show_page, {"OK", "Cancel"});
|
||||
m_button_ok = dlg_btns->GetOK();
|
||||
m_button_ok->SetLabel(_L("Synchronize now"));
|
||||
m_button_ok->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) {
|
||||
deal_ok();
|
||||
EndModal(wxID_YES);
|
||||
SetFocusIgnoringChildren();
|
||||
});
|
||||
|
||||
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
|
||||
m_button_cancel = new Button(m_show_page, m_input_info.cancel_text_to_later ? _L("Later") : _L("Cancel"));
|
||||
m_button_cancel->SetBackgroundColor(btn_bg_white);
|
||||
m_button_cancel->SetBorderColor(wxColour(38, 46, 48));
|
||||
m_button_cancel->SetFont(Label::Body_12);
|
||||
m_button_cancel->SetSize(CANCEL_BUTTON_SIZE);
|
||||
m_button_cancel->SetMinSize(CANCEL_BUTTON_SIZE);
|
||||
m_button_cancel->SetCornerRadius(FromDIP(12));
|
||||
bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10));
|
||||
|
||||
m_button_cancel = dlg_btns->GetCANCEL();
|
||||
m_button_cancel->SetLabel(m_input_info.cancel_text_to_later ? _L("Later") : _L("Cancel"));
|
||||
m_button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) {
|
||||
EndModal(wxID_CANCEL);
|
||||
});
|
||||
|
||||
m_sizer_show_page->Add(bSizer_button, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(20));
|
||||
m_sizer_show_page->Add(dlg_btns, 0, wxEXPAND);
|
||||
m_show_page->SetSizer(m_sizer_show_page);
|
||||
}
|
||||
show_print_failed_info(false);
|
||||
@@ -2480,10 +2460,10 @@ void SyncAmsInfoDialog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
}
|
||||
m_swipe_left_button->msw_rescale();
|
||||
m_swipe_right_button->msw_rescale();
|
||||
m_button_ok->SetMinSize(OK_BUTTON_SIZE);
|
||||
m_button_ok->SetCornerRadius(FromDIP(12));
|
||||
m_button_cancel->SetMinSize(CANCEL_BUTTON_SIZE);
|
||||
m_button_cancel->SetCornerRadius(FromDIP(12));
|
||||
//m_button_ok->SetMinSize(OK_BUTTON_SIZE); // ORCA DialogButtons automatically manages style and size
|
||||
//m_button_ok->SetCornerRadius(FromDIP(12));
|
||||
//m_button_cancel->SetMinSize(CANCEL_BUTTON_SIZE);
|
||||
//m_button_cancel->SetCornerRadius(FromDIP(12));
|
||||
m_merge_color_checkbox->Rescale();
|
||||
m_append_color_checkbox->Rescale();
|
||||
m_combobox_plate->Rescale();
|
||||
@@ -2628,14 +2608,14 @@ void SyncAmsInfoDialog::reset_and_sync_ams_list()
|
||||
is_first_row = false;
|
||||
if (!m_original_in_colormap) {
|
||||
m_original_in_colormap = new wxStaticText(m_filament_panel, wxID_ANY, _CTX(L_CONTEXT("Original", "Sync_AMS"), "Sync_AMS") + ":");
|
||||
m_original_in_colormap->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_original_in_colormap->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_original_in_colormap->SetFont(::Label::Head_12);
|
||||
}
|
||||
ams_tip_sizer->Add(m_original_in_colormap, 0, wxALIGN_LEFT | wxTOP, FromDIP(6));
|
||||
|
||||
if (!m_ams_or_ext_text_in_colormap) {
|
||||
m_ams_or_ext_text_in_colormap = new wxStaticText(m_filament_panel, wxID_ANY, _L("AMS") + ":");
|
||||
m_ams_or_ext_text_in_colormap->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_ams_or_ext_text_in_colormap->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_ams_or_ext_text_in_colormap->SetFont(::Label::Head_12);
|
||||
}
|
||||
ams_tip_sizer->Add(m_ams_or_ext_text_in_colormap, 0, wxALIGN_LEFT | wxTOP, FromDIP(9));
|
||||
@@ -2840,7 +2820,7 @@ void SyncAmsInfoDialog::generate_override_fix_ams_list()
|
||||
is_first_row = false;
|
||||
if (!m_original_in_override) {
|
||||
m_original_in_override = new wxStaticText(m_fix_filament_panel, wxID_ANY, _CTX(L_CONTEXT("Original", "Sync_AMS"), "Sync_AMS") + ":");
|
||||
m_original_in_override->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_original_in_override->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_original_in_override->SetFont(::Label::Head_12);
|
||||
}
|
||||
ams_tip_sizer->Add(m_original_in_override, 0, wxALIGN_LEFT | wxTOP, FromDIP(6));
|
||||
@@ -2848,7 +2828,7 @@ void SyncAmsInfoDialog::generate_override_fix_ams_list()
|
||||
if (!m_ams_or_ext_text_in_override) {
|
||||
auto text = (m_only_exist_ext_spool_flag ? _L("Ext spool") : _L("AMS")) + ":";
|
||||
m_ams_or_ext_text_in_override = new wxStaticText(m_fix_filament_panel, wxID_ANY, text);
|
||||
m_ams_or_ext_text_in_override->SetForegroundColour(wxColour(107, 107, 107, 100));
|
||||
m_ams_or_ext_text_in_override->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors
|
||||
m_ams_or_ext_text_in_override->SetFont(::Label::Head_12);
|
||||
}
|
||||
ams_tip_sizer->Add(m_ams_or_ext_text_in_override, 0, wxALIGN_LEFT | wxTOP, FromDIP(9));
|
||||
@@ -3236,10 +3216,12 @@ SyncNozzleAndAmsDialog::SyncNozzleAndAmsDialog(InputInfo &input_info)
|
||||
wxGetApp().preset_bundle->get_printer_extruder_count() == 1 ? 370 :320,
|
||||
input_info.dialog_pos,
|
||||
90,
|
||||
(
|
||||
wxGetApp().preset_bundle->get_printer_extruder_count() == 1 ? _L("Successfully synchronized nozzle information.") :
|
||||
_L("Successfully synchronized nozzle and AMS number information."),
|
||||
_L("Continue to sync filaments"),
|
||||
_CTX(L_CONTEXT("Cancel", "Sync_Nozzle_AMS"), "Sync_Nozzle_AMS"),
|
||||
_L("Successfully synchronized nozzle and AMS number information.")
|
||||
) + "\n\n" + _L("Do you want to continue to sync filaments?"),
|
||||
_L("Yes"), // ORCA use shorter text for buttons
|
||||
_CTX(L_CONTEXT(_L("No"), "Sync_Nozzle_AMS"), "Sync_Nozzle_AMS"),
|
||||
DisappearanceMode::TimedDisappearance)
|
||||
, m_input_info(input_info)
|
||||
{
|
||||
|
||||
+18
-6
@@ -1184,7 +1184,7 @@ void Tab::update_extruder_switch_colors()
|
||||
void Tab::check_extruder_options_status(int index, bool &sys_extruder, bool &modified_extruder, const std::vector<PageShp>& pages_to_check)
|
||||
{
|
||||
int config_index = index;
|
||||
if (m_type == Preset::TYPE_PRINT || m_type == Preset::TYPE_PRINTER) {
|
||||
if (m_type == Preset::TYPE_PRINT || m_type == Preset::TYPE_PRINTER || m_type == Preset::TYPE_MODEL) {
|
||||
int extruder_id;
|
||||
NozzleVolumeType nozzle_type;
|
||||
parse_extruder_selection(index, extruder_id, nozzle_type);
|
||||
@@ -2658,7 +2658,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("ironing_angle", "quality_settings_ironing#angle-offset");
|
||||
optgroup->append_single_option_line("ironing_angle_fixed", "quality_settings_ironing#fixed-angle");
|
||||
|
||||
optgroup = page->new_optgroup(L("Z contouring"), L"param_advanced");
|
||||
optgroup = page->new_optgroup(L("Z contouring"), L"param_z_contouring");
|
||||
optgroup->append_single_option_line("zaa_enabled", "quality_settings_z_contouring");
|
||||
optgroup->append_single_option_line("zaa_minimize_perimeter_height", "quality_settings_z_contouring#minimize-wall-height-angle");
|
||||
optgroup->append_single_option_line("zaa_min_z", "quality_settings_z_contouring#minimum-z-height");
|
||||
@@ -2742,12 +2742,17 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
optgroup->append_single_option_line("top_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
|
||||
optgroup->append_single_option_line("top_layer_direction", "strength_settings_infill#top-direction");
|
||||
optgroup->append_single_option_line("top_layer_direction", "strength_settings_infill#top-bottom-direction");
|
||||
optgroup->append_single_option_line("top_surface_expansion", "strength_settings_top_bottom_shells#surface-expansion");
|
||||
optgroup->append_single_option_line("top_surface_expansion_margin", "strength_settings_top_bottom_shells#surface-expansion-margin");
|
||||
optgroup->append_single_option_line("top_surface_expansion_direction", "strength_settings_top_bottom_shells#surface-expansion-direction");
|
||||
optgroup->append_single_option_line("bottom_shell_layers", "strength_settings_top_bottom_shells#shell-layers");
|
||||
optgroup->append_single_option_line("bottom_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("bottom_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
optgroup->append_single_option_line("bottom_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
|
||||
optgroup->append_single_option_line("bottom_layer_direction", "strength_settings_infill#direction");
|
||||
optgroup->append_single_option_line("bottom_layer_direction", "strength_settings_infill#top-bottom-direction");
|
||||
optgroup->append_single_option_line("center_of_surface_pattern", "strength_settings_top_bottom_shells#center-surface-pattern-on");
|
||||
optgroup->append_single_option_line("anisotropic_surfaces", "strength_settings_top_bottom_shells#anisotropic-surfaces");
|
||||
optgroup->append_single_option_line("top_bottom_infill_wall_overlap", "strength_settings_top_bottom_shells#infillwall-overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
|
||||
@@ -2778,10 +2783,11 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("solid_infill_rotate_template", "strength_settings_infill_rotation_template_metalanguage");
|
||||
optgroup->append_single_option_line("gap_fill_target", "strength_settings_infill#apply-gap-fill");
|
||||
optgroup->append_single_option_line("filter_out_gap_fill", "strength_settings_infill#filter-out-tiny-gaps");
|
||||
optgroup->append_single_option_line("separated_infills", "strength_settings_infill#separated-infills");
|
||||
optgroup->append_single_option_line("infill_wall_overlap", "strength_settings_infill#infill-wall-overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("align_infill_direction_to_model", "strength_settings_advanced#align-infill-direction-to-model");
|
||||
optgroup->append_single_option_line("align_infill_direction_to_model", "strength_settings_advanced#align-directions-to-model");
|
||||
optgroup->append_single_option_line("extra_solid_infills", "strength_settings_infill#extra-solid-infill");
|
||||
optgroup->append_single_option_line("bridge_angle", "strength_settings_advanced#bridge-infill-direction");
|
||||
optgroup->append_single_option_line("internal_bridge_angle", "strength_settings_advanced#bridge-infill-direction"); // ORCA: Internal bridge angle override
|
||||
@@ -2976,6 +2982,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("flush_into_support", "multimaterial_settings_flush_options#flush-into-objects-support");
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"advanced");
|
||||
optgroup->append_single_option_line("interlocking_beam", "multimaterial_settings_advanced#interlocking-beam");
|
||||
optgroup->append_single_option_line("toolchange_ordering", "multimaterial_settings_advanced#toolchange-ordering");
|
||||
optgroup->append_single_option_line("interface_shells", "multimaterial_settings_advanced#interface-shells");
|
||||
optgroup->append_single_option_line("mmu_segmented_region_max_width", "multimaterial_settings_advanced#maximum-width-of-segmented-region");
|
||||
optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth", "multimaterial_settings_advanced#interlocking-depth-of-segmented-region");
|
||||
@@ -7677,7 +7684,7 @@ bool Tab::validate_filament_temperature_pairs()
|
||||
|
||||
RichMessageDialog dialog(parent(), msg_text, _L("Temperature Safety Check"), wxYES | wxNO | wxICON_WARNING);
|
||||
dialog.SetButtonLabel(wxID_YES, _L("Continue"), true);
|
||||
dialog.SetButtonLabel(wxID_NO, _L("Back"));
|
||||
dialog.SetButtonLabel(wxID_NO, _CTX("Back", "Navigation"));
|
||||
dialog.ShowCheckBox(_L("Don't warn again for this preset"));
|
||||
const int answer = dialog.ShowModal();
|
||||
// Session-only suppression (does not modify/save filament preset data).
|
||||
@@ -7713,6 +7720,11 @@ void Tab::update_extruder_variants(int extruder_id, bool reload)
|
||||
auto nozzle_volumes = m_preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type");
|
||||
int extruder_nums = m_preset_bundle->get_printer_extruder_count();
|
||||
nozzle_volumes->values.resize(extruder_nums);
|
||||
|
||||
// Orca: update `m_actual_nozzle_volumes` to current selected ones
|
||||
m_actual_nozzle_volumes.resize(extruder_nums, NozzleVolumeType::nvtStandard);
|
||||
for (int i = 0; i < extruder_nums; i++) m_actual_nozzle_volumes[i] = (NozzleVolumeType)nozzle_volumes->values[i];
|
||||
|
||||
if (extruder_nums == 2) {
|
||||
auto options = generate_extruder_options();
|
||||
m_extruder_switch->SetOptions(options);
|
||||
|
||||
@@ -47,7 +47,7 @@ WebViewPanel::WebViewPanel(wxWindow *parent)
|
||||
// Create the button
|
||||
bSizer_toolbar = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_button_back = new wxButton(this, wxID_ANY, _L("Back"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_button_back = new wxButton(this, wxID_ANY, _CTX("Back", "Navigation"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_button_back->Enable(false);
|
||||
bSizer_toolbar->Add(m_button_back, 0, wxALL, 5);
|
||||
|
||||
|
||||
@@ -1471,12 +1471,24 @@ FlowRateCalibrationDialog::FlowRateCalibrationDialog(wxWindow* parent, wxWindowI
|
||||
type_box->Add(m_rbType, 0, wxALL | wxEXPAND, FromDIP(4));
|
||||
v_sizer->Add(type_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
|
||||
|
||||
// Pattern selection
|
||||
auto labeled_box_pattern = new LabeledStaticBox(this, _L("Top Surface Pattern"));
|
||||
auto pattern_box = new wxStaticBoxSizer(labeled_box_pattern, wxVERTICAL);
|
||||
// Settings
|
||||
auto stb = new LabeledStaticBox(this, _L("Settings"));
|
||||
auto settings_sizer = new wxStaticBoxSizer(stb, wxVERTICAL);
|
||||
|
||||
wxString pattern_str = _L("Top Surface Pattern");
|
||||
int text_max = GetTextMax(this, std::vector<wxString>{pattern_str});
|
||||
|
||||
settings_sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
auto st_size = wxSize(text_max, -1);
|
||||
auto ti_size = FromDIP(wxSize(120, -1));
|
||||
|
||||
// Top surface pattern
|
||||
auto pattern_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto pattern_text = new wxStaticText(this, wxID_ANY, pattern_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
|
||||
|
||||
// ORCA: Use ComboBox with icons instead of RadioGroup
|
||||
m_rbPattern = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY);
|
||||
m_rbPattern = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, ti_size, 0, nullptr, wxCB_READONLY);
|
||||
|
||||
boost::filesystem::path image_path(Slic3r::resources_dir());
|
||||
image_path /= "images";
|
||||
@@ -1497,9 +1509,13 @@ FlowRateCalibrationDialog::FlowRateCalibrationDialog(wxWindow* parent, wxWindowI
|
||||
m_rbPattern->SetSelection(0); // Default to Archimedean Chords
|
||||
// ORCA: explicit set value to ensure display on Windows
|
||||
m_rbPattern->SetValue(m_rbPattern->GetString(0));
|
||||
m_rbPattern->GetDropDown().SetUseContentWidth(true);
|
||||
|
||||
pattern_box->Add(m_rbPattern, 0, wxALL | wxEXPAND, FromDIP(4));
|
||||
v_sizer->Add(pattern_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
|
||||
pattern_sizer->Add(pattern_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
|
||||
pattern_sizer->Add(m_rbPattern , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
|
||||
settings_sizer->Add(pattern_sizer, 0, wxLEFT, FromDIP(3));
|
||||
|
||||
v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
|
||||
|
||||
v_sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user