mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-30 23:22:02 +08:00
Merge remote-tracking branch 'remotes/origin/master' into vb_ensurovani
This commit is contained in:
commit
f828cba5f0
10
resources/icons/mode.svg
Normal file
10
resources/icons/mode.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="hex_x5F_green">
|
||||
<g>
|
||||
<polygon fill="#ED6B21" points="8,1 2,5 2,7 2,11 8,15 14,11 14,7 14,5 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 462 B |
Binary file not shown.
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 73 KiB |
Binary file not shown.
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 96 KiB |
@ -430,7 +430,26 @@ static bool contains_skew(const Transform3d& trafo)
|
||||
Matrix3d rotation;
|
||||
Matrix3d scale;
|
||||
trafo.computeRotationScaling(&rotation, &scale);
|
||||
return !scale.isDiagonal();
|
||||
|
||||
if (scale.isDiagonal())
|
||||
return false;
|
||||
|
||||
if (scale.determinant() >= 0.0)
|
||||
return true;
|
||||
|
||||
// the matrix contains mirror
|
||||
const Matrix3d ratio = scale.cwiseQuotient(trafo.matrix().block<3,3>(0,0));
|
||||
|
||||
auto check_skew = [&ratio](int i, int j, bool& skew) {
|
||||
if (!std::isnan(ratio(i, j)) && !std::isnan(ratio(j, i)))
|
||||
skew |= std::abs(ratio(i, j) * ratio(j, i) - 1.0) > EPSILON;
|
||||
};
|
||||
|
||||
bool has_skew = false;
|
||||
check_skew(0, 1, has_skew);
|
||||
check_skew(0, 2, has_skew);
|
||||
check_skew(1, 2, has_skew);
|
||||
return has_skew;
|
||||
}
|
||||
|
||||
Vec3d Transformation::get_rotation() const
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "ButtonsDescription.hpp"
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/clrpicker.h>
|
||||
@ -7,11 +8,82 @@
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
//static ModePaletteComboBox::PalettesMap MODE_PALETTES =
|
||||
static std::vector<std::pair<std::string, std::vector<std::string>>> MODE_PALETTES =
|
||||
{
|
||||
{ L("Palette 1 (default)"), { "#00B000", "#FFDC00", "#E70000" } },
|
||||
{ L("Palette 2"), { "#FC766A", "#B0B8B4", "#184A45" } },
|
||||
{ L("Palette 3"), { "#567572", "#964F4C", "#696667" } },
|
||||
{ L("Palette 4"), { "#DA291C", "#56A8CB", "#53A567" } },
|
||||
{ L("Palette 5"), { "#F65058", "#FBDE44", "#28334A" } },
|
||||
{ L("Palette 6"), { "#FF3EA5", "#EDFF00", "#00A4CC" } },
|
||||
{ L("Palette 7"), { "#E95C20", "#006747", "#4F2C1D" } },
|
||||
{ L("Palette 8"), { "#D9514E", "#2A2B2D", "#2DA8D8" } }
|
||||
};
|
||||
|
||||
ModePaletteComboBox::ModePaletteComboBox(wxWindow* parent) :
|
||||
BitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY)
|
||||
{
|
||||
for (const auto& palette : MODE_PALETTES)
|
||||
Append(_(palette.first), *get_bmp(palette.second));
|
||||
}
|
||||
|
||||
void ModePaletteComboBox::UpdateSelection(const std::vector<wxColour> &palette_in)
|
||||
{
|
||||
for (size_t idx = 0; idx < MODE_PALETTES.size(); ++idx ) {
|
||||
const auto& palette = MODE_PALETTES[idx].second;
|
||||
|
||||
bool is_selected = true;
|
||||
for (size_t mode = 0; mode < palette_in.size(); mode++)
|
||||
if (wxColour(palette[mode]) != palette_in[mode]) {
|
||||
is_selected = false;
|
||||
break;
|
||||
}
|
||||
if (is_selected) {
|
||||
Select(int(idx));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Select(-1);
|
||||
}
|
||||
|
||||
BitmapCache& ModePaletteComboBox::bitmap_cache()
|
||||
{
|
||||
static BitmapCache bmps;
|
||||
return bmps;
|
||||
}
|
||||
|
||||
wxBitmapBundle * ModePaletteComboBox::get_bmp(const std::vector<std::string> &palette)
|
||||
{
|
||||
std::string bitmap_key;
|
||||
for (const auto& color : palette)
|
||||
bitmap_key += color + "+";
|
||||
|
||||
const int icon_height = wxOSX ? 10 : 12;
|
||||
|
||||
wxBitmapBundle* bmp_bndl = bitmap_cache().find_bndl(bitmap_key);
|
||||
if (bmp_bndl == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmapBundle*> bmps;
|
||||
for (const auto& color : palette) {
|
||||
bmps.emplace_back(get_bmp_bundle("mode", icon_height, color));
|
||||
bmps.emplace_back(get_empty_bmp_bundle(wxOSX ? 5 : 6, icon_height));
|
||||
}
|
||||
bmp_bndl = bitmap_cache().insert_bndl(bitmap_key, bmps);
|
||||
}
|
||||
|
||||
return bmp_bndl;
|
||||
}
|
||||
|
||||
|
||||
void ButtonsDescription::FillSizerWithTextColorDescriptions(wxSizer* sizer, wxWindow* parent, wxColourPickerCtrl** sys_colour, wxColourPickerCtrl** mod_colour)
|
||||
{
|
||||
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(3, 5, 5);
|
||||
@ -48,13 +120,81 @@ void ButtonsDescription::FillSizerWithTextColorDescriptions(wxSizer* sizer, wxWi
|
||||
|
||||
grid_sizer->Add(*color_picker, 0, wxALIGN_CENTRE_VERTICAL);
|
||||
grid_sizer->Add(btn, 0, wxALIGN_CENTRE_VERTICAL);
|
||||
grid_sizer->Add(sys_label, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
|
||||
grid_sizer->Add(sys_label, 0, wxALIGN_CENTRE_VERTICAL);
|
||||
};
|
||||
|
||||
add_color(sys_colour, wxGetApp().get_label_clr_sys(), wxGetApp().get_label_default_clr_system(), _L("Value is the same as the system value"));
|
||||
add_color(mod_colour, wxGetApp().get_label_clr_modified(),wxGetApp().get_label_default_clr_modified(), _L("Value was changed and is not equal to the system value or the last saved preset"));
|
||||
}
|
||||
|
||||
void ButtonsDescription::FillSizerWithModeColorDescriptions(
|
||||
wxSizer* sizer, wxWindow* parent,
|
||||
std::vector<wxColourPickerCtrl**> clr_pickers,
|
||||
std::vector<wxColour>& mode_palette)
|
||||
{
|
||||
const int margin = em_unit(parent);
|
||||
|
||||
auto palette_cb = new ModePaletteComboBox(parent);
|
||||
palette_cb->UpdateSelection(mode_palette);
|
||||
|
||||
palette_cb->Bind(wxEVT_COMBOBOX, [clr_pickers, &mode_palette](wxCommandEvent& evt) {
|
||||
const int selection = evt.GetSelection();
|
||||
if (selection < 0)
|
||||
return;
|
||||
const auto& palette = MODE_PALETTES[selection];
|
||||
for (int mode = 0; mode < 3; mode++)
|
||||
if (*clr_pickers[mode]) {
|
||||
wxColour clr = wxColour(palette.second[mode]);
|
||||
(*clr_pickers[mode])->SetColour(clr);
|
||||
mode_palette[mode] = clr;
|
||||
}
|
||||
});
|
||||
|
||||
wxBoxSizer* h_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
h_sizer->Add(new wxStaticText(parent, wxID_ANY, _L("Default palette for mode markers") + ": "), 0, wxALIGN_CENTER_VERTICAL);
|
||||
h_sizer->Add(palette_cb, 1, wxEXPAND);
|
||||
|
||||
sizer->Add(h_sizer, 0, wxEXPAND | wxBOTTOM, margin);
|
||||
|
||||
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(9, 5, 5);
|
||||
sizer->Add(grid_sizer, 0, wxEXPAND);
|
||||
|
||||
const std::vector<wxString> names = { _L("Simple"), _CTX(L_CONTEXT("Advanced", "Mode"), "Mode"), _L("Expert") };
|
||||
|
||||
for (size_t mode = 0; mode < names.size(); ++mode) {
|
||||
wxColour& color = mode_palette[mode];
|
||||
|
||||
wxColourPickerCtrl** color_picker = clr_pickers[mode];
|
||||
*color_picker = new wxColourPickerCtrl(parent, wxID_ANY, color);
|
||||
wxGetApp().UpdateDarkUI((*color_picker)->GetPickerCtrl(), true);
|
||||
|
||||
(*color_picker)->Bind(wxEVT_COLOURPICKER_CHANGED, [color_picker, &color, palette_cb, &mode_palette](wxCommandEvent&) {
|
||||
const wxColour new_color = (*color_picker)->GetColour();
|
||||
if (new_color != color) {
|
||||
color = new_color;
|
||||
palette_cb->UpdateSelection(mode_palette);
|
||||
}
|
||||
});
|
||||
|
||||
wxColour def_color = color;
|
||||
auto btn = new ScalableButton(parent, wxID_ANY, "undo");
|
||||
btn->SetToolTip(_L("Revert color"));
|
||||
|
||||
btn->Bind(wxEVT_BUTTON, [color_picker, &color, def_color, palette_cb, &mode_palette](wxEvent& event) {
|
||||
color = def_color;
|
||||
(*color_picker)->SetColour(def_color);
|
||||
palette_cb->UpdateSelection(mode_palette);
|
||||
});
|
||||
parent->Bind(wxEVT_UPDATE_UI, [color_picker, def_color](wxUpdateUIEvent& evt) {
|
||||
evt.Enable((*color_picker)->GetColour() != def_color);
|
||||
}, btn->GetId());
|
||||
|
||||
grid_sizer->Add(*color_picker, 0, wxALIGN_CENTRE_VERTICAL);
|
||||
grid_sizer->Add(btn, 0, wxALIGN_CENTRE_VERTICAL);
|
||||
grid_sizer->Add(new wxStaticText(parent, wxID_ANY, names[mode]), 0, wxALIGN_CENTRE_VERTICAL | wxRIGHT, 2*margin);
|
||||
}
|
||||
}
|
||||
|
||||
ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vector<Entry> &entries) :
|
||||
wxDialog(parent, wxID_ANY, _(L("Buttons And Text Colors Description")), wxDefaultPosition, wxDefaultSize),
|
||||
m_entries(entries)
|
||||
@ -74,13 +214,20 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vector<Entry
|
||||
auto description = new wxStaticText(this, wxID_ANY, _(entry.symbol));
|
||||
grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
|
||||
description = new wxStaticText(this, wxID_ANY, _(entry.explanation));
|
||||
grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
|
||||
grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
|
||||
}
|
||||
|
||||
// Text color description
|
||||
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
FillSizerWithTextColorDescriptions(sizer, this, &sys_colour, &mod_colour);
|
||||
main_sizer->Add(sizer, 0, wxEXPAND | wxALL, 20);
|
||||
main_sizer->Add(sizer, 0, wxEXPAND | wxALL, 20);
|
||||
|
||||
// Mode color markers description
|
||||
mode_palette = wxGetApp().get_mode_palette();
|
||||
|
||||
wxSizer* mode_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
FillSizerWithModeColorDescriptions(mode_sizer, this, { &simple, &advanced, &expert }, mode_palette);
|
||||
main_sizer->Add(mode_sizer, 0, wxEXPAND | wxALL, 20);
|
||||
|
||||
auto buttons = CreateStdDialogButtonSizer(wxOK|wxCANCEL);
|
||||
main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
|
||||
@ -89,8 +236,10 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vector<Entry
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
wxGetApp().set_label_clr_sys(sys_colour->GetColour());
|
||||
wxGetApp().set_label_clr_modified(mod_colour->GetColour());
|
||||
wxGetApp().set_mode_palette(mode_palette);
|
||||
|
||||
EndModal(wxID_OK);
|
||||
});
|
||||
});
|
||||
|
||||
wxGetApp().UpdateDarkUI(btn);
|
||||
wxGetApp().UpdateDarkUI(static_cast<wxButton*>(FindWindowById(wxID_CANCEL, this)));
|
||||
|
@ -4,16 +4,48 @@
|
||||
#include <wx/dialog.h>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/bmpbndl.h>
|
||||
|
||||
#include "BitmapComboBox.hpp"
|
||||
|
||||
class ScalableBitmap;
|
||||
class wxColourPickerCtrl;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class BitmapCache;
|
||||
|
||||
// ---------------------------------
|
||||
// *** PaletteComboBox ***
|
||||
// ---------------------------------
|
||||
|
||||
// BitmapComboBox used to palets list in GUI Preferences
|
||||
class ModePaletteComboBox : public BitmapComboBox
|
||||
{
|
||||
public:
|
||||
ModePaletteComboBox(wxWindow* parent);
|
||||
~ModePaletteComboBox() = default;
|
||||
|
||||
void UpdateSelection(const std::vector<wxColour>& palette_in);
|
||||
|
||||
protected:
|
||||
// Caching bitmaps for the all bitmaps, used in preset comboboxes
|
||||
static BitmapCache& bitmap_cache();
|
||||
wxBitmapBundle* get_bmp( const std::vector<std::string>& palette);
|
||||
};
|
||||
|
||||
|
||||
class ButtonsDescription : public wxDialog
|
||||
{
|
||||
wxColourPickerCtrl* sys_colour{ nullptr };
|
||||
wxColourPickerCtrl* mod_colour{ nullptr };
|
||||
|
||||
wxColourPickerCtrl* simple { nullptr };
|
||||
wxColourPickerCtrl* advanced { nullptr };
|
||||
wxColourPickerCtrl* expert { nullptr };
|
||||
|
||||
std::vector<wxColour> mode_palette;
|
||||
public:
|
||||
struct Entry {
|
||||
Entry(ScalableBitmap *bitmap, const std::string &symbol, const std::string &explanation) : bitmap(bitmap), symbol(symbol), explanation(explanation) {}
|
||||
@ -27,6 +59,9 @@ public:
|
||||
~ButtonsDescription() {}
|
||||
|
||||
static void FillSizerWithTextColorDescriptions(wxSizer* sizer, wxWindow* parent, wxColourPickerCtrl** sys_colour, wxColourPickerCtrl** mod_colour);
|
||||
static void FillSizerWithModeColorDescriptions(wxSizer* sizer, wxWindow* parent,
|
||||
std::vector<wxColourPickerCtrl**> clr_pickers,
|
||||
std::vector<wxColour>& mode_palette);
|
||||
|
||||
private:
|
||||
std::vector<Entry> m_entries;
|
||||
|
@ -1176,31 +1176,20 @@ PageCustom::PageCustom(ConfigWizard *parent)
|
||||
: ConfigWizardPage(parent, _L("Custom Printer Setup"), _L("Custom Printer"))
|
||||
{
|
||||
cb_custom = new wxCheckBox(this, wxID_ANY, _L("Define a custom printer profile"));
|
||||
tc_profile_name = new wxTextCtrl(this, wxID_ANY, default_profile_name);
|
||||
auto *label = new wxStaticText(this, wxID_ANY, _L("Custom profile name:"));
|
||||
|
||||
wxGetApp().UpdateDarkUI(tc_profile_name);
|
||||
wxBoxSizer* profile_name_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
profile_name_editor = new SavePresetDialog::Item{ this, profile_name_sizer, default_profile_name };
|
||||
profile_name_editor->Enable(false);
|
||||
|
||||
tc_profile_name->Enable(false);
|
||||
tc_profile_name->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &evt) {
|
||||
if (tc_profile_name->GetValue().IsEmpty()) {
|
||||
if (profile_name_prev.IsEmpty()) { tc_profile_name->SetValue(default_profile_name); }
|
||||
else { tc_profile_name->SetValue(profile_name_prev); }
|
||||
} else {
|
||||
profile_name_prev = tc_profile_name->GetValue();
|
||||
}
|
||||
evt.Skip();
|
||||
});
|
||||
|
||||
cb_custom->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) {
|
||||
tc_profile_name->Enable(custom_wanted());
|
||||
cb_custom->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
|
||||
profile_name_editor->Enable(custom_wanted());
|
||||
wizard_p()->on_custom_setup(custom_wanted());
|
||||
|
||||
});
|
||||
|
||||
append(cb_custom);
|
||||
append(label);
|
||||
append(tc_profile_name);
|
||||
append(profile_name_sizer);
|
||||
}
|
||||
|
||||
PageUpdate::PageUpdate(ConfigWizard *parent)
|
||||
@ -2825,7 +2814,7 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||
preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem,
|
||||
{preferred_model, preferred_variant, first_added_filament, first_added_sla_material});
|
||||
|
||||
if (!only_sla_mode && page_custom->custom_wanted()) {
|
||||
if (!only_sla_mode && page_custom->custom_wanted() && page_custom->is_valid_profile_name()) {
|
||||
// if unsaved changes was not cheched till this moment
|
||||
if (!check_unsaved_preset_changes &&
|
||||
!wxGetApp().check_and_keep_current_preset_changes(caption, _L("Custom printer was installed and it will be activated."), act_btns, &apply_keeped_changes))
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "slic3r/Utils/PresetUpdater.hpp"
|
||||
#include "BedShapeDialog.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "SavePresetDialog.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
|
||||
@ -370,16 +371,20 @@ struct PageMaterials: ConfigWizardPage
|
||||
struct PageCustom: ConfigWizardPage
|
||||
{
|
||||
PageCustom(ConfigWizard *parent);
|
||||
~PageCustom() {
|
||||
if (profile_name_editor)
|
||||
delete profile_name_editor;
|
||||
}
|
||||
|
||||
bool custom_wanted() const { return cb_custom->GetValue(); }
|
||||
std::string profile_name() const { return into_u8(tc_profile_name->GetValue()); }
|
||||
bool custom_wanted() const { return cb_custom->GetValue(); }
|
||||
bool is_valid_profile_name() const { return profile_name_editor->is_valid();}
|
||||
std::string profile_name() const { return profile_name_editor->preset_name(); }
|
||||
|
||||
private:
|
||||
static const char* default_profile_name;
|
||||
|
||||
wxCheckBox *cb_custom;
|
||||
wxTextCtrl *tc_profile_name;
|
||||
wxString profile_name_prev;
|
||||
wxCheckBox *cb_custom {nullptr};
|
||||
SavePresetDialog::Item *profile_name_editor {nullptr};
|
||||
|
||||
};
|
||||
|
||||
|
@ -3471,10 +3471,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
for (int hover_volume_id : m_hover_volume_idxs) {
|
||||
const GLVolume &hover_gl_volume = *m_volumes.volumes[hover_volume_id];
|
||||
int object_idx = hover_gl_volume.object_idx();
|
||||
if (object_idx < 0 || object_idx >= m_model->objects.size()) continue;
|
||||
if (object_idx < 0 || static_cast<size_t>(object_idx) >= m_model->objects.size()) continue;
|
||||
const ModelObject* hover_object = m_model->objects[object_idx];
|
||||
int hover_volume_idx = hover_gl_volume.volume_idx();
|
||||
if (hover_volume_idx < 0 || hover_volume_idx >= hover_object->volumes.size()) continue;
|
||||
if (hover_volume_idx < 0 || static_cast<size_t>(hover_volume_idx) >= hover_object->volumes.size()) continue;
|
||||
const ModelVolume* hover_volume = hover_object->volumes[hover_volume_idx];
|
||||
if (!hover_volume->text_configuration.has_value()) continue;
|
||||
m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
|
||||
|
@ -1127,7 +1127,7 @@ bool GUI_App::on_init_inner()
|
||||
NppDarkMode::InitDarkMode(init_dark_color_mode, init_sys_menu_enabled);
|
||||
#endif
|
||||
// initialize label colors and fonts
|
||||
init_label_colours();
|
||||
init_ui_colours();
|
||||
init_fonts();
|
||||
|
||||
std::string older_data_dir_path;
|
||||
@ -1145,8 +1145,8 @@ bool GUI_App::on_init_inner()
|
||||
if (bool new_dark_color_mode = app_config->get("dark_color_mode") == "1";
|
||||
init_dark_color_mode != new_dark_color_mode) {
|
||||
NppDarkMode::SetDarkMode(new_dark_color_mode);
|
||||
init_label_colours();
|
||||
update_label_colours_from_appconfig();
|
||||
init_ui_colours();
|
||||
update_ui_colours_from_appconfig();
|
||||
}
|
||||
if (bool new_sys_menu_enabled = app_config->get("sys_menu_enabled") == "1";
|
||||
init_sys_menu_enabled != new_sys_menu_enabled)
|
||||
@ -1431,10 +1431,16 @@ const wxColour GUI_App::get_label_default_clr_modified()
|
||||
return dark_mode() ? wxColour(253, 111, 40) : wxColour(252, 77, 1);
|
||||
}
|
||||
|
||||
void GUI_App::init_label_colours()
|
||||
const std::vector<std::string> GUI_App::get_mode_default_palette()
|
||||
{
|
||||
return { "#7DF028", "#FFDC00", "#E70000" };
|
||||
}
|
||||
|
||||
void GUI_App::init_ui_colours()
|
||||
{
|
||||
m_color_label_modified = get_label_default_clr_modified();
|
||||
m_color_label_sys = get_label_default_clr_system();
|
||||
m_mode_palette = get_mode_default_palette();
|
||||
|
||||
bool is_dark_mode = dark_mode();
|
||||
#ifdef _WIN32
|
||||
@ -1450,19 +1456,30 @@ void GUI_App::init_label_colours()
|
||||
m_color_window_default = is_dark_mode ? wxColour(43, 43, 43) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
}
|
||||
|
||||
void GUI_App::update_label_colours_from_appconfig()
|
||||
void GUI_App::update_ui_colours_from_appconfig()
|
||||
{
|
||||
// load label colors
|
||||
if (app_config->has("label_clr_sys")) {
|
||||
auto str = app_config->get("label_clr_sys");
|
||||
if (str != "")
|
||||
if (!str.empty())
|
||||
m_color_label_sys = wxColour(str);
|
||||
}
|
||||
|
||||
if (app_config->has("label_clr_modified")) {
|
||||
auto str = app_config->get("label_clr_modified");
|
||||
if (str != "")
|
||||
if (!str.empty())
|
||||
m_color_label_modified = wxColour(str);
|
||||
}
|
||||
|
||||
// load mode markers colors
|
||||
if (app_config->has("mode_palette")) {
|
||||
const auto colors = app_config->get("mode_palette");
|
||||
if (!colors.empty()) {
|
||||
m_mode_palette.clear();
|
||||
if (!unescape_strings_cstyle(colors, m_mode_palette))
|
||||
m_mode_palette = get_mode_default_palette();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::update_label_colours()
|
||||
@ -1649,6 +1666,39 @@ void GUI_App::set_label_clr_sys(const wxColour& clr)
|
||||
app_config->save();
|
||||
}
|
||||
|
||||
const std::string& GUI_App::get_mode_btn_color(int mode_id)
|
||||
{
|
||||
assert(0 <= mode_id && size_t(mode_id) < m_mode_palette.size());
|
||||
return m_mode_palette[mode_id];
|
||||
}
|
||||
|
||||
std::vector<wxColour> GUI_App::get_mode_palette()
|
||||
{
|
||||
return { wxColor(m_mode_palette[0]),
|
||||
wxColor(m_mode_palette[1]),
|
||||
wxColor(m_mode_palette[2]) };
|
||||
}
|
||||
|
||||
void GUI_App::set_mode_palette(const std::vector<wxColour>& palette)
|
||||
{
|
||||
bool save = false;
|
||||
|
||||
for (size_t mode = 0; mode < palette.size(); ++mode) {
|
||||
const wxColour& clr = palette[mode];
|
||||
std::string color_str = clr == wxTransparentColour ? std::string("") : encode_color(ColorRGB(clr.Red(), clr.Green(), clr.Blue()));
|
||||
if (m_mode_palette[mode] != color_str) {
|
||||
m_mode_palette[mode] = color_str;
|
||||
save = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (save) {
|
||||
mainframe->update_mode_markers();
|
||||
app_config->set("mode_palette", escape_strings_cstyle(m_mode_palette));
|
||||
app_config->save();
|
||||
}
|
||||
}
|
||||
|
||||
bool GUI_App::tabs_as_menu() const
|
||||
{
|
||||
return app_config->get("tabs_as_menu") == "1"; // || dark_mode();
|
||||
|
@ -139,6 +139,7 @@ private:
|
||||
wxColour m_color_selected_btn_bg;
|
||||
bool m_force_colors_update { false };
|
||||
#endif
|
||||
std::vector<std::string> m_mode_palette;
|
||||
|
||||
wxFont m_small_font;
|
||||
wxFont m_bold_font;
|
||||
@ -194,8 +195,9 @@ public:
|
||||
static bool dark_mode();
|
||||
const wxColour get_label_default_clr_system();
|
||||
const wxColour get_label_default_clr_modified();
|
||||
void init_label_colours();
|
||||
void update_label_colours_from_appconfig();
|
||||
const std::vector<std::string> get_mode_default_palette();
|
||||
void init_ui_colours();
|
||||
void update_ui_colours_from_appconfig();
|
||||
void update_label_colours();
|
||||
// update color mode for window
|
||||
void UpdateDarkUI(wxWindow *window, bool highlited = false, bool just_font = false);
|
||||
@ -215,6 +217,9 @@ public:
|
||||
const wxColour& get_label_clr_default() { return m_color_label_default; }
|
||||
const wxColour& get_window_default_clr(){ return m_color_window_default; }
|
||||
|
||||
const std::string& get_mode_btn_color(int mode_id);
|
||||
std::vector<wxColour> get_mode_palette();
|
||||
void set_mode_palette(const std::vector<wxColour> &palette);
|
||||
|
||||
#ifdef _WIN32
|
||||
const wxColour& get_label_highlight_clr() { return m_color_highlight_label_default; }
|
||||
|
@ -2660,47 +2660,59 @@ void ObjectList::part_selection_changed()
|
||||
disable_ununiform_scale = true;
|
||||
}
|
||||
else if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot )) {
|
||||
og_name = _L("Group manipulation");
|
||||
|
||||
const Selection& selection = scene_selection();
|
||||
// don't show manipulation panel for case of all Object's parts selection
|
||||
update_and_show_manipulations = !selection.is_single_full_instance();
|
||||
|
||||
if (int obj_idx = selection.get_object_idx(); obj_idx >= 0) {
|
||||
if (selection.is_any_volume() || selection.is_any_modifier())
|
||||
enable_manipulation = !(*m_objects)[obj_idx]->is_cut();
|
||||
else// if (item && m_objects_model->GetItemType(item) == itInstanceRoot)
|
||||
disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
|
||||
if (selection.is_single_full_object()) {
|
||||
og_name = _L("Object manipulation");
|
||||
update_and_show_manipulations = true;
|
||||
|
||||
obj_idx = selection.get_object_idx();
|
||||
ModelObject* object = (*m_objects)[obj_idx];
|
||||
m_config = &object->config;
|
||||
disable_ss_manipulation = object->is_cut();
|
||||
}
|
||||
else {
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
if (selection.is_single_full_object() || selection.is_multiple_full_instance() ) {
|
||||
int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
|
||||
disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
|
||||
og_name = _L("Group manipulation");
|
||||
|
||||
// don't show manipulation panel for case of all Object's parts selection
|
||||
update_and_show_manipulations = !selection.is_single_full_instance();
|
||||
|
||||
if (int obj_idx = selection.get_object_idx(); obj_idx >= 0) {
|
||||
if (selection.is_any_volume() || selection.is_any_modifier())
|
||||
enable_manipulation = !(*m_objects)[obj_idx]->is_cut();
|
||||
else// if (item && m_objects_model->GetItemType(item) == itInstanceRoot)
|
||||
disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
|
||||
}
|
||||
else if (selection.is_mixed() || selection.is_multiple_full_object()) {
|
||||
std::map<CutObjectBase, std::set<int>> cut_objects;
|
||||
|
||||
// find cut objects
|
||||
for (auto item : sels) {
|
||||
int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
const ModelObject* obj = object(obj_idx);
|
||||
if (obj->is_cut()) {
|
||||
if (cut_objects.find(obj->cut_id) == cut_objects.end())
|
||||
cut_objects[obj->cut_id] = std::set<int>{ obj_idx };
|
||||
else
|
||||
cut_objects.at(obj->cut_id).insert(obj_idx);
|
||||
}
|
||||
else {
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
if (selection.is_single_full_object() || selection.is_multiple_full_instance() ) {
|
||||
int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
|
||||
disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
|
||||
}
|
||||
else if (selection.is_mixed() || selection.is_multiple_full_object()) {
|
||||
std::map<CutObjectBase, std::set<int>> cut_objects;
|
||||
|
||||
// check if selected cut objects are "full selected"
|
||||
for (auto cut_object : cut_objects)
|
||||
if (cut_object.first.check_sum() != cut_object.second.size()) {
|
||||
disable_ss_manipulation = true;
|
||||
break;
|
||||
// find cut objects
|
||||
for (auto item : sels) {
|
||||
int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
const ModelObject* obj = object(obj_idx);
|
||||
if (obj->is_cut()) {
|
||||
if (cut_objects.find(obj->cut_id) == cut_objects.end())
|
||||
cut_objects[obj->cut_id] = std::set<int>{ obj_idx };
|
||||
else
|
||||
cut_objects.at(obj->cut_id).insert(obj_idx);
|
||||
}
|
||||
}
|
||||
disable_ununiform_scale = !cut_objects.empty();
|
||||
|
||||
// check if selected cut objects are "full selected"
|
||||
for (auto cut_object : cut_objects)
|
||||
if (cut_object.first.check_sum() != cut_object.second.size()) {
|
||||
disable_ss_manipulation = true;
|
||||
break;
|
||||
}
|
||||
disable_ununiform_scale = !cut_objects.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1198,7 +1198,11 @@ void ObjectManipulation::change_scale_value(int axis, double value)
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
Vec3d ref_scale = m_cache.scale;
|
||||
if (selection.is_single_full_instance()) {
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
if (is_local_coordinates())
|
||||
ref_scale = 100.0 * Vec3d::Ones();
|
||||
}
|
||||
else if (selection.is_single_full_instance()) {
|
||||
scale = scale.cwiseQuotient(ref_scale);
|
||||
ref_scale = Vec3d::Ones();
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type)
|
||||
DataBase emboss_data = priv::create_emboss_data_base(m_text, m_style_manager);
|
||||
const ModelObjectPtrs &objects = selection.get_model()->objects;
|
||||
// No selected object so create new object
|
||||
if (selection.is_empty() || object_idx < 0 || object_idx >= objects.size()) {
|
||||
if (selection.is_empty() || object_idx < 0 || static_cast<size_t>(object_idx) >= objects.size()) {
|
||||
// create Object on center of screen
|
||||
// when ray throw center of screen not hit bed it create object on center of bed
|
||||
priv::start_create_object_job(emboss_data, screen_center);
|
||||
@ -2231,6 +2231,18 @@ void GLGizmoEmboss::draw_delete_style_button() {
|
||||
}
|
||||
}
|
||||
|
||||
namespace priv {
|
||||
/// <summary>
|
||||
/// Transform origin of Text volume onto surface of model.
|
||||
/// </summary>
|
||||
/// <param name="volume">Text</param>
|
||||
/// <param name="raycast_manager">AABB trees of object</param>
|
||||
/// <param name="selection">Transformation of actual instance</param>
|
||||
/// <returns>True when transform otherwise false</returns>
|
||||
bool transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection);
|
||||
} // namespace priv
|
||||
|
||||
|
||||
void GLGizmoEmboss::fix_transformation(const FontProp &from,
|
||||
const FontProp &to)
|
||||
{
|
||||
@ -2252,6 +2264,10 @@ void GLGizmoEmboss::fix_transformation(const FontProp &from,
|
||||
float t_move = t_move_opt.has_value() ? *t_move_opt : .0f;
|
||||
do_translate(Vec3d::UnitZ() * (t_move - f_move));
|
||||
}
|
||||
|
||||
// when start using surface than move volume origin onto surface
|
||||
if (!from.use_surface && to.use_surface)
|
||||
priv::transform_on_surface(*m_volume, m_raycast_manager, m_parent.get_selection());
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_style_list() {
|
||||
@ -2354,8 +2370,11 @@ void GLGizmoEmboss::draw_style_list() {
|
||||
// selected style from combo box
|
||||
if (selected_style_index.has_value()) {
|
||||
const EmbossStyle &style = m_style_manager.get_styles()[*selected_style_index].style;
|
||||
fix_transformation(actual_style.prop, style.prop);
|
||||
// create copy to be able do fix transformation only when successfully load style
|
||||
FontProp act_prop = actual_style.prop; // copy
|
||||
FontProp new_prop = style.prop; // copy
|
||||
if (m_style_manager.load_style(*selected_style_index)) {
|
||||
fix_transformation(act_prop, new_prop);
|
||||
process();
|
||||
} else {
|
||||
wxString title = _L("Not valid style.");
|
||||
@ -2867,16 +2886,8 @@ void GLGizmoEmboss::do_rotate(float relative_z_angle)
|
||||
// snapshot_name = L("Set text rotation");
|
||||
m_parent.do_rotate(snapshot_name);
|
||||
}
|
||||
namespace priv {
|
||||
|
||||
/// <summary>
|
||||
/// Transform origin of Text volume onto surface of model.
|
||||
/// </summary>
|
||||
/// <param name="volume">Text</param>
|
||||
/// <param name="raycast_manager">AABB trees of object</param>
|
||||
/// <param name="selection">Transformation of actual instance</param>
|
||||
/// <returns>True when transform otherwise false</returns>
|
||||
bool transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection)
|
||||
bool priv::transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection)
|
||||
{
|
||||
// Move object on surface
|
||||
auto cond = RaycastManager::SkipVolume({volume.id().id});
|
||||
@ -2911,7 +2922,6 @@ bool transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager,
|
||||
volume.set_transformation(volume.get_matrix() * Eigen::Translation<double, 3>(offset_volume));
|
||||
return true;
|
||||
}
|
||||
} // namespace priv
|
||||
|
||||
void GLGizmoEmboss::draw_advanced()
|
||||
{
|
||||
@ -3590,7 +3600,7 @@ bool priv::start_create_volume_on_surface_job(
|
||||
const ModelObjectPtrs &objects = plater->model().objects;
|
||||
|
||||
int object_idx = gl_volume->object_idx();
|
||||
if (object_idx < 0 || object_idx >= objects.size()) return false;
|
||||
if (object_idx < 0 || static_cast<size_t>(object_idx) >= objects.size()) return false;
|
||||
ModelObject *obj = objects[object_idx];
|
||||
size_t vol_id = obj->volumes[gl_volume->volume_idx()]->id().id;
|
||||
auto cond = RaycastManager::AllowVolumes({vol_id});
|
||||
|
@ -53,6 +53,15 @@ KBShortcutsDialog::KBShortcutsDialog()
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
this->CenterOnParent();
|
||||
|
||||
#ifdef __linux__
|
||||
// workaround to correct pages layout
|
||||
book->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [book](wxBookCtrlEvent& e) {
|
||||
book->GetPage(e.GetSelection())->Fit();
|
||||
});
|
||||
const wxSize sz = this->GetBestSize();
|
||||
this->SetSize(sz.x + 1, sz.y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KBShortcutsDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
|
@ -715,6 +715,8 @@ void MainFrame::update_title()
|
||||
|
||||
void MainFrame::init_tabpanel()
|
||||
{
|
||||
wxGetApp().update_ui_colours_from_appconfig();
|
||||
|
||||
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on Windows 10
|
||||
// with multiple high resolution displays connected.
|
||||
#ifdef _MSW_DARK_MODE
|
||||
@ -847,7 +849,6 @@ void MainFrame::register_win32_callbacks()
|
||||
|
||||
void MainFrame::create_preset_tabs()
|
||||
{
|
||||
wxGetApp().update_label_colours_from_appconfig();
|
||||
add_created_tab(new TabPrint(m_tabpanel), "cog");
|
||||
add_created_tab(new TabFilament(m_tabpanel), "spool");
|
||||
add_created_tab(new TabSLAPrint(m_tabpanel), "cog");
|
||||
@ -1091,7 +1092,9 @@ void MainFrame::on_sys_color_changed()
|
||||
wxBusyCursor wait;
|
||||
|
||||
// update label colors in respect to the system mode
|
||||
wxGetApp().init_label_colours();
|
||||
wxGetApp().init_ui_colours();
|
||||
// but if there are some ui colors in appconfig, they have to be applied
|
||||
wxGetApp().update_ui_colours_from_appconfig();
|
||||
#ifdef __WXMSW__
|
||||
wxGetApp().UpdateDarkUI(m_tabpanel);
|
||||
// m_statusbar->update_dark_ui();
|
||||
@ -1114,6 +1117,24 @@ void MainFrame::on_sys_color_changed()
|
||||
this->Refresh();
|
||||
}
|
||||
|
||||
void MainFrame::update_mode_markers()
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
#ifdef _MSW_DARK_MODE
|
||||
// update markers in common mode sizer
|
||||
if (!wxGetApp().tabs_as_menu())
|
||||
dynamic_cast<Notebook*>(m_tabpanel)->UpdateModeMarkers();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// update mode markers on side_bar
|
||||
wxGetApp().sidebar().update_mode_markers();
|
||||
|
||||
// update mode markers in tabs
|
||||
for (auto tab : wxGetApp().tabs_list)
|
||||
tab->update_mode_markers();
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// \xA0 is a non-breaking space. It is entered here to spoil the automatic accelerators,
|
||||
// as the simple numeric accelerators spoil all numeric data entry.
|
||||
|
@ -143,6 +143,7 @@ public:
|
||||
~MainFrame() = default;
|
||||
|
||||
void update_layout();
|
||||
void update_mode_markers();
|
||||
|
||||
// Called when closing the application and when switching the application language.
|
||||
void shutdown();
|
||||
|
@ -109,9 +109,16 @@ void ButtonsListCtrl::OnColorsChanged()
|
||||
for (ScalableButton* btn : m_pageButtons)
|
||||
btn->sys_color_changed();
|
||||
|
||||
m_mode_sizer->sys_color_changed();
|
||||
|
||||
m_sizer->Layout();
|
||||
}
|
||||
|
||||
void ButtonsListCtrl::UpdateModeMarkers()
|
||||
{
|
||||
m_mode_sizer->update_mode_markers();
|
||||
}
|
||||
|
||||
void ButtonsListCtrl::SetSelection(int sel)
|
||||
{
|
||||
if (m_selection == sel)
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
void UpdateMode();
|
||||
void Rescale();
|
||||
void OnColorsChanged();
|
||||
void UpdateModeMarkers();
|
||||
bool InsertPage(size_t n, const wxString& text, bool bSelect = false, const std::string& bmp_name = "");
|
||||
void RemovePage(size_t n);
|
||||
bool SetPageImage(size_t n, const std::string& bmp_name) const;
|
||||
@ -251,6 +252,11 @@ public:
|
||||
GetBtnsListCtrl()->OnColorsChanged();
|
||||
}
|
||||
|
||||
void UpdateModeMarkers()
|
||||
{
|
||||
GetBtnsListCtrl()->UpdateModeMarkers();
|
||||
}
|
||||
|
||||
void OnNavigationKey(wxNavigationKeyEvent& event)
|
||||
{
|
||||
if (event.IsWindowChange()) {
|
||||
|
@ -45,7 +45,7 @@ OG_CustomCtrl::OG_CustomCtrl( wxWindow* parent,
|
||||
m_v_gap = lround(1.0 * m_em_unit);
|
||||
m_h_gap = lround(0.2 * m_em_unit);
|
||||
|
||||
m_bmp_mode_sz = get_bitmap_size(get_bmp_bundle("mode_simple", wxOSX ? 10 : 12), this);
|
||||
m_bmp_mode_sz = get_bitmap_size(get_bmp_bundle("mode", wxOSX ? 10 : 12), this);
|
||||
m_bmp_blinking_sz = get_bitmap_size(get_bmp_bundle("search_blink"), this);
|
||||
|
||||
init_ctrl_lines();// from og.lines()
|
||||
@ -188,7 +188,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
||||
#else
|
||||
GetTextExtent(label, &label_w, &label_h, 0, 0, &m_font);
|
||||
#endif //__WXMSW__
|
||||
h_pos += label_w + 1 + m_h_gap;
|
||||
h_pos += label_w + m_h_gap;
|
||||
}
|
||||
h_pos += (opt.opt.gui_type == ConfigOptionDef::GUIType::legend ? 1 : 3) * blinking_button_width;
|
||||
|
||||
@ -199,7 +199,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
||||
if (opt.opt.gui_type == ConfigOptionDef::GUIType::legend)
|
||||
h_pos += 2 * blinking_button_width;
|
||||
|
||||
h_pos += field->getWindow()->GetSize().x;
|
||||
h_pos += field->getWindow()->GetSize().x + m_h_gap;
|
||||
|
||||
if (option_set.size() == 1 && option_set.front().opt.full_width)
|
||||
break;
|
||||
@ -418,7 +418,7 @@ void OG_CustomCtrl::msw_rescale()
|
||||
m_v_gap = lround(1.0 * m_em_unit);
|
||||
m_h_gap = lround(0.2 * m_em_unit);
|
||||
|
||||
m_bmp_mode_sz = get_bitmap_size(get_bmp_bundle("mode_simple", wxOSX ? 10 : 12), this);
|
||||
m_bmp_mode_sz = get_bitmap_size(get_bmp_bundle("mode", wxOSX ? 10 : 12), this);
|
||||
m_bmp_blinking_sz = get_bitmap_size(get_bmp_bundle("search_blink"), this);
|
||||
|
||||
init_max_win_width();
|
||||
@ -666,9 +666,7 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos)
|
||||
return ctrl->m_h_gap;
|
||||
|
||||
ConfigOptionMode mode = og_line.get_options()[0].opt.mode;
|
||||
const std::string& bmp_name = mode == ConfigOptionMode::comSimple ? "mode_simple" :
|
||||
mode == ConfigOptionMode::comAdvanced ? "mode_advanced" : "mode_expert";
|
||||
wxBitmapBundle* bmp = get_bmp_bundle(bmp_name, wxOSX ? 10 : 12);
|
||||
wxBitmapBundle* bmp = get_bmp_bundle("mode", wxOSX ? 10 : 12, wxGetApp().get_mode_btn_color(mode));
|
||||
wxCoord y_draw = v_pos + lround((height - get_bitmap_size(bmp, ctrl).GetHeight()) / 2);
|
||||
|
||||
if (og_line.get_options().front().opt.gui_type != ConfigOptionDef::GUIType::legend)
|
||||
|
@ -1183,6 +1183,12 @@ void Sidebar::sys_color_changed()
|
||||
p->searcher.dlg_sys_color_changed();
|
||||
}
|
||||
|
||||
void Sidebar::update_mode_markers()
|
||||
{
|
||||
if (p->mode_sizer)
|
||||
p->mode_sizer->update_mode_markers();
|
||||
}
|
||||
|
||||
void Sidebar::search()
|
||||
{
|
||||
p->searcher.search();
|
||||
@ -2180,9 +2186,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
|
||||
this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
|
||||
this->q->Bind(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, [](PresetUpdateAvailableClickedEvent&) { wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
|
||||
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
|
||||
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this, q](RemovableDriveEjectEvent &evt) {
|
||||
if (evt.data.second) {
|
||||
this->show_action_buttons(this->ready_to_slice);
|
||||
q->show_action_buttons();
|
||||
notification_manager->close_notification_of_type(NotificationType::ExportFinished);
|
||||
notification_manager->push_notification(NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::RegularNotificationLevel,
|
||||
@ -2196,8 +2202,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
);
|
||||
}
|
||||
});
|
||||
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this](RemovableDrivesChangedEvent &) {
|
||||
this->show_action_buttons(this->ready_to_slice);
|
||||
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
|
||||
q->show_action_buttons();
|
||||
// Close notification ExportingFinished but only if last export was to removable
|
||||
notification_manager->device_ejected();
|
||||
});
|
||||
@ -3302,7 +3308,15 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (! this->delayed_error_message.empty()) {
|
||||
else {
|
||||
if (invalidated == Print::APPLY_STATUS_UNCHANGED && !background_process.empty()) {
|
||||
std::string warning;
|
||||
std::string err = background_process.validate(&warning);
|
||||
if (!err.empty())
|
||||
return return_state;
|
||||
}
|
||||
|
||||
if (! this->delayed_error_message.empty())
|
||||
// Reusing the old state.
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
}
|
||||
@ -4987,10 +5001,10 @@ bool Plater::priv::can_layers_editing() const
|
||||
return layers_height_allowed();
|
||||
}
|
||||
|
||||
void Plater::priv::show_action_buttons(const bool ready_to_slice) const
|
||||
void Plater::priv::show_action_buttons(const bool ready_to_slice_) const
|
||||
{
|
||||
// Cache this value, so that the callbacks from the RemovableDriveManager may repeat that value when calling show_action_buttons().
|
||||
this->ready_to_slice = ready_to_slice;
|
||||
this->ready_to_slice = ready_to_slice_;
|
||||
|
||||
wxWindowUpdateLocker noUpdater(sidebar);
|
||||
|
||||
@ -7015,6 +7029,7 @@ void Plater::split_object() { p->split_object(); }
|
||||
void Plater::split_volume() { p->split_volume(); }
|
||||
void Plater::update_menus() { p->menus.update(); }
|
||||
void Plater::show_action_buttons(const bool ready_to_slice) const { p->show_action_buttons(ready_to_slice); }
|
||||
void Plater::show_action_buttons() const { p->show_action_buttons(p->ready_to_slice); }
|
||||
|
||||
void Plater::copy_selection_to_clipboard()
|
||||
{
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
void update_reslice_btn_tooltip() const;
|
||||
void msw_rescale();
|
||||
void sys_color_changed();
|
||||
void update_mode_markers();
|
||||
void search();
|
||||
void jump_to_option(size_t selected);
|
||||
void jump_to_option(const std::string& opt_key, Preset::Type type, const std::wstring& category);
|
||||
@ -312,6 +313,7 @@ public:
|
||||
|
||||
void update_menus();
|
||||
void show_action_buttons(const bool is_ready_to_slice) const;
|
||||
void show_action_buttons() const;
|
||||
|
||||
wxString get_project_filename(const wxString& extension = wxEmptyString) const;
|
||||
void set_project_filename(const wxString& filename);
|
||||
|
@ -80,9 +80,15 @@ void PreferencesDialog::show(const std::string& highlight_opt_key /*= std::strin
|
||||
m_use_custom_toolbar_size = get_app_config()->get("use_custom_toolbar_size") == "1";
|
||||
|
||||
if (wxGetApp().is_editor()) {
|
||||
// update colors for color pickers
|
||||
// update colors for color pickers of the labels
|
||||
update_color(m_sys_colour, wxGetApp().get_label_clr_sys());
|
||||
update_color(m_mod_colour, wxGetApp().get_label_clr_modified());
|
||||
|
||||
// update color pickers for mode palette
|
||||
const auto palette = wxGetApp().get_mode_palette();
|
||||
std::vector<wxColourPickerCtrl*> color_pickres = {m_mode_simple, m_mode_advanced, m_mode_expert};
|
||||
for (size_t mode = 0; mode < color_pickres.size(); ++mode)
|
||||
update_color(color_pickres[mode], palette[mode]);
|
||||
}
|
||||
|
||||
this->ShowModal();
|
||||
@ -506,6 +512,7 @@ void PreferencesDialog::build()
|
||||
|
||||
create_settings_mode_widget();
|
||||
create_settings_text_color_widget();
|
||||
create_settings_mode_color_widget();
|
||||
|
||||
#if ENABLE_ENVIRONMENT_MAP
|
||||
// Add "Render" tab
|
||||
@ -660,6 +667,7 @@ void PreferencesDialog::accept(wxEvent&)
|
||||
if (wxGetApp().is_editor()) {
|
||||
wxGetApp().set_label_clr_sys(m_sys_colour->GetColour());
|
||||
wxGetApp().set_label_clr_modified(m_mod_colour->GetColour());
|
||||
wxGetApp().set_mode_palette(m_mode_palette);
|
||||
}
|
||||
|
||||
EndModal(wxID_OK);
|
||||
@ -935,6 +943,33 @@ void PreferencesDialog::create_settings_text_color_widget()
|
||||
append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title);
|
||||
}
|
||||
|
||||
void PreferencesDialog::create_settings_mode_color_widget()
|
||||
{
|
||||
wxWindow* parent = m_optgroup_gui->parent();
|
||||
|
||||
wxString title = L("Mode markers");
|
||||
wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title));
|
||||
wxGetApp().UpdateDarkUI(stb);
|
||||
if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
|
||||
std::string opt_key = "mode_markers";
|
||||
m_blinkers[opt_key] = new BlinkingBitmap(parent);
|
||||
|
||||
wxSizer* stb_sizer = new wxStaticBoxSizer(stb, wxVERTICAL);
|
||||
|
||||
// Mode color markers description
|
||||
m_mode_palette = wxGetApp().get_mode_palette();
|
||||
ButtonsDescription::FillSizerWithModeColorDescriptions(stb_sizer, parent, { &m_mode_simple, &m_mode_advanced, &m_mode_expert }, m_mode_palette);
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(m_blinkers[opt_key], 0, wxRIGHT, 2);
|
||||
sizer->Add(stb_sizer, 1, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit());
|
||||
|
||||
append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title);
|
||||
}
|
||||
|
||||
void PreferencesDialog::init_highlighter(const t_config_option_key& opt_key)
|
||||
{
|
||||
if (m_blinkers.find(opt_key) != m_blinkers.end())
|
||||
|
@ -48,6 +48,12 @@ class PreferencesDialog : public DPIDialog
|
||||
|
||||
wxColourPickerCtrl* m_sys_colour {nullptr};
|
||||
wxColourPickerCtrl* m_mod_colour {nullptr};
|
||||
|
||||
std::vector<wxColour> m_mode_palette;
|
||||
wxColourPickerCtrl* m_mode_simple { nullptr };
|
||||
wxColourPickerCtrl* m_mode_advanced { nullptr };
|
||||
wxColourPickerCtrl* m_mode_expert { nullptr };
|
||||
|
||||
wxBookCtrlBase* tabs {nullptr};
|
||||
|
||||
bool isOSX {false};
|
||||
@ -81,6 +87,7 @@ protected:
|
||||
void create_icon_size_slider();
|
||||
void create_settings_mode_widget();
|
||||
void create_settings_text_color_widget();
|
||||
void create_settings_mode_color_widget();
|
||||
void init_highlighter(const t_config_option_key& opt_key);
|
||||
std::vector<ConfigOptionsGroup*> optgroups();
|
||||
|
||||
|
@ -555,7 +555,8 @@ bool PresetComboBox::selection_is_changed_according_to_physical_printers()
|
||||
// if new preset wasn't selected, there is no need to call update preset selection
|
||||
if (old_printer_preset == preset_name) {
|
||||
tab->update_preset_choice();
|
||||
wxGetApp().plater()->show_action_buttons(false);
|
||||
// update action buttons to show/hide "Send to" button
|
||||
wxGetApp().plater()->show_action_buttons();
|
||||
|
||||
// we need just to update according Plater<->Tab PresetComboBox
|
||||
if (dynamic_cast<PlaterPresetComboBox*>(this)!=nullptr) {
|
||||
|
@ -29,7 +29,7 @@ constexpr auto BORDER_W = 10;
|
||||
|
||||
std::string SavePresetDialog::Item::get_init_preset_name(const std::string &suffix)
|
||||
{
|
||||
PresetBundle* preset_bundle = m_parent->get_preset_bundle();
|
||||
PresetBundle* preset_bundle = dynamic_cast<SavePresetDialog*>(m_parent)->get_preset_bundle();
|
||||
if (!preset_bundle)
|
||||
preset_bundle = wxGetApp().preset_bundle;
|
||||
m_presets = &preset_bundle->get_presets(m_type);
|
||||
@ -50,13 +50,14 @@ std::string SavePresetDialog::Item::get_init_preset_name(const std::string &suff
|
||||
|
||||
void SavePresetDialog::Item::init_input_name_ctrl(wxBoxSizer *input_name_sizer, const std::string preset_name)
|
||||
{
|
||||
if (m_parent->is_for_rename()) {
|
||||
if (m_use_text_ctrl) {
|
||||
#ifdef _WIN32
|
||||
long style = wxBORDER_SIMPLE;
|
||||
#else
|
||||
long style = 0L;
|
||||
#endif
|
||||
m_text_ctrl = new wxTextCtrl(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1), style);
|
||||
wxGetApp().UpdateDarkUI(m_text_ctrl);
|
||||
m_text_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
|
||||
|
||||
input_name_sizer->Add(m_text_ctrl,1, wxEXPAND, BORDER_W);
|
||||
@ -86,13 +87,14 @@ void SavePresetDialog::Item::init_input_name_ctrl(wxBoxSizer *input_name_sizer,
|
||||
|
||||
wxString SavePresetDialog::Item::get_top_label_text() const
|
||||
{
|
||||
const std::string label_str = m_parent->is_for_rename() ?_u8L("Rename %s to:") : _u8L("Save %s as:");
|
||||
const std::string label_str = m_use_text_ctrl ?_u8L("Rename %s to:") : _u8L("Save %s as:");
|
||||
Tab* tab = wxGetApp().get_tab(m_type);
|
||||
return from_u8((boost::format(label_str) % into_u8(tab->title())).str());
|
||||
}
|
||||
|
||||
SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent):
|
||||
m_type(type),
|
||||
m_use_text_ctrl(parent->is_for_rename()),
|
||||
m_parent(parent),
|
||||
m_valid_bmp(new wxStaticBitmap(m_parent, wxID_ANY, *get_bmp_bundle("tick_mark"))),
|
||||
m_valid_label(new wxStaticText(m_parent, wxID_ANY, ""))
|
||||
@ -110,15 +112,51 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBox
|
||||
sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W);
|
||||
|
||||
if (m_type == Preset::TYPE_PRINTER)
|
||||
m_parent->add_info_for_edit_ph_printer(sizer);
|
||||
parent->add_info_for_edit_ph_printer(sizer);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
SavePresetDialog::Item::Item(wxWindow* parent, wxBoxSizer* sizer, const std::string& def_name, PrinterTechnology pt /*= ptFFF*/):
|
||||
m_preset_name(def_name),
|
||||
m_printer_technology(pt),
|
||||
m_parent(parent),
|
||||
m_valid_bmp(new wxStaticBitmap(m_parent, wxID_ANY, *get_bmp_bundle("tick_mark"))),
|
||||
m_valid_label(new wxStaticText(m_parent, wxID_ANY, ""))
|
||||
{
|
||||
m_valid_label->SetFont(wxGetApp().bold_font());
|
||||
|
||||
wxBoxSizer* input_name_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
input_name_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
|
||||
init_input_name_ctrl(input_name_sizer, m_preset_name);
|
||||
|
||||
sizer->Add(input_name_sizer,0, wxEXPAND | wxBOTTOM, BORDER_W);
|
||||
sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
const Preset* SavePresetDialog::Item::get_existing_preset() const
|
||||
{
|
||||
if (m_presets)
|
||||
return m_presets->find_preset(m_preset_name, false);
|
||||
|
||||
const auto types = m_printer_technology == ptFFF ?
|
||||
std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_PRINT, Preset::TYPE_FILAMENT } :
|
||||
std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL };
|
||||
|
||||
for (auto type : types) {
|
||||
const PresetCollection& presets = wxGetApp().preset_bundle->get_presets(type);
|
||||
if (const Preset* preset = presets.find_preset(m_preset_name, false))
|
||||
return preset;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SavePresetDialog::Item::update()
|
||||
{
|
||||
bool rename = m_parent->is_for_rename();
|
||||
m_preset_name = into_u8(rename ? m_text_ctrl->GetValue() : m_combo->GetValue());
|
||||
m_preset_name = into_u8(m_use_text_ctrl ? m_text_ctrl->GetValue() : m_combo->GetValue());
|
||||
|
||||
m_valid_type = ValidationType::Valid;
|
||||
wxString info_line;
|
||||
@ -138,7 +176,7 @@ void SavePresetDialog::Item::update()
|
||||
if (m_valid_type == ValidationType::Valid && m_preset_name.find(unusable_suffix) != std::string::npos) {
|
||||
info_line = _L("The supplied name is not valid;") + "\n" +
|
||||
_L("the following suffix is not allowed:") + "\n\t" +
|
||||
from_u8(PresetCollection::get_suffix_modified());
|
||||
from_u8(unusable_suffix);
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
@ -147,24 +185,25 @@ void SavePresetDialog::Item::update()
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
const Preset* existing = m_presets->find_preset(m_preset_name, false);
|
||||
const Preset* existing = get_existing_preset();
|
||||
if (m_valid_type == ValidationType::Valid && existing && (existing->is_default || existing->is_system)) {
|
||||
info_line = rename ? _L("The supplied name is used for a system profile.") :
|
||||
info_line = m_use_text_ctrl ? _L("The supplied name is used for a system profile.") :
|
||||
_L("Cannot overwrite a system profile.");
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
if (m_valid_type == ValidationType::Valid && existing && (existing->is_external)) {
|
||||
info_line = rename ? _L("The supplied name is used for a external profile.") :
|
||||
info_line = m_use_text_ctrl ? _L("The supplied name is used for a external profile.") :
|
||||
_L("Cannot overwrite an external profile.");
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
SavePresetDialog* dlg = dynamic_cast<SavePresetDialog*>(m_parent);
|
||||
if (m_valid_type == ValidationType::Valid && existing)
|
||||
{
|
||||
if (m_preset_name == m_presets->get_selected_preset_name()) {
|
||||
if ((!rename && m_presets->get_edited_preset().is_dirty) ||
|
||||
m_parent->get_preset_bundle()) // means that we save modifications from the DiffDialog
|
||||
if (m_presets && m_preset_name == m_presets->get_selected_preset_name()) {
|
||||
if ((!m_use_text_ctrl && m_presets->get_edited_preset().is_dirty) ||
|
||||
(dlg && dlg->get_preset_bundle())) // means that we save modifications from the DiffDialog
|
||||
info_line = _L("Save preset modifications to existing user profile");
|
||||
else
|
||||
info_line = _L("Nothing changed");
|
||||
@ -185,6 +224,17 @@ void SavePresetDialog::Item::update()
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
#ifdef __WXMSW__
|
||||
const int max_path_length = MAX_PATH;
|
||||
#else
|
||||
const int max_path_length = 255;
|
||||
#endif
|
||||
|
||||
if (m_valid_type == ValidationType::Valid && m_presets && m_presets->path_from_name(m_preset_name).length() >= max_path_length) {
|
||||
info_line = _L("The name is too long.");
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
if (m_valid_type == ValidationType::Valid && m_preset_name.find_first_of(' ') == 0) {
|
||||
info_line = _L("The name cannot start with space character.");
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
@ -195,23 +245,23 @@ void SavePresetDialog::Item::update()
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
if (m_valid_type == ValidationType::Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) {
|
||||
if (m_valid_type == ValidationType::Valid && m_presets && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) {
|
||||
info_line = _L("The name cannot be the same as a preset alias name.");
|
||||
m_valid_type = ValidationType::NoValid;
|
||||
}
|
||||
|
||||
if (!m_parent->get_info_line_extention().IsEmpty() && m_valid_type != ValidationType::NoValid)
|
||||
info_line += "\n\n" + m_parent->get_info_line_extention();
|
||||
if ((dlg && !dlg->get_info_line_extention().IsEmpty()) && m_valid_type != ValidationType::NoValid)
|
||||
info_line += "\n\n" + dlg->get_info_line_extention();
|
||||
|
||||
m_valid_label->SetLabel(info_line);
|
||||
m_valid_label->Show(!info_line.IsEmpty());
|
||||
|
||||
update_valid_bmp();
|
||||
|
||||
if (m_type == Preset::TYPE_PRINTER)
|
||||
m_parent->update_info_for_edit_ph_printer(m_preset_name);
|
||||
if (dlg && m_type == Preset::TYPE_PRINTER)
|
||||
dlg->update_info_for_edit_ph_printer(m_preset_name);
|
||||
|
||||
m_parent->layout();
|
||||
m_parent->Layout();
|
||||
}
|
||||
|
||||
void SavePresetDialog::Item::update_valid_bmp()
|
||||
@ -227,6 +277,13 @@ void SavePresetDialog::Item::accept()
|
||||
m_presets->delete_preset(m_preset_name);
|
||||
}
|
||||
|
||||
void SavePresetDialog::Item::Enable(bool enable /*= true*/)
|
||||
{
|
||||
m_valid_label->Enable(enable);
|
||||
m_valid_bmp->Enable(enable);
|
||||
m_use_text_ctrl ? m_text_ctrl->Enable(enable) : m_combo->Enable(enable);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------
|
||||
// SavePresetDialog
|
||||
@ -387,10 +444,11 @@ void SavePresetDialog::update_info_for_edit_ph_printer(const std::string& preset
|
||||
}
|
||||
}
|
||||
|
||||
void SavePresetDialog::layout()
|
||||
bool SavePresetDialog::Layout()
|
||||
{
|
||||
this->Layout();
|
||||
const bool ret = DPIDialog::Layout();
|
||||
this->Fit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SavePresetDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
|
@ -26,7 +26,7 @@ class SavePresetDialog : public DPIDialog
|
||||
Switch,
|
||||
UndefAction
|
||||
};
|
||||
|
||||
public:
|
||||
struct Item
|
||||
{
|
||||
enum class ValidationType
|
||||
@ -37,20 +37,24 @@ class SavePresetDialog : public DPIDialog
|
||||
};
|
||||
|
||||
Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent);
|
||||
Item(wxWindow* parent, wxBoxSizer* sizer, const std::string& def_name, PrinterTechnology pt = ptFFF);
|
||||
|
||||
void update_valid_bmp();
|
||||
void accept();
|
||||
void Enable(bool enable = true);
|
||||
|
||||
bool is_valid() const { return m_valid_type != ValidationType::NoValid; }
|
||||
Preset::Type type() const { return m_type; }
|
||||
std::string preset_name() const { return m_preset_name; }
|
||||
|
||||
private:
|
||||
Preset::Type m_type;
|
||||
Preset::Type m_type {Preset::TYPE_INVALID};
|
||||
std::string m_preset_name;
|
||||
bool m_use_text_ctrl {true};
|
||||
|
||||
PrinterTechnology m_printer_technology {ptAny};
|
||||
ValidationType m_valid_type {ValidationType::NoValid};
|
||||
SavePresetDialog* m_parent {nullptr};
|
||||
wxWindow* m_parent {nullptr};
|
||||
wxStaticBitmap* m_valid_bmp {nullptr};
|
||||
wxComboBox* m_combo {nullptr};
|
||||
wxTextCtrl* m_text_ctrl {nullptr};
|
||||
@ -60,11 +64,12 @@ class SavePresetDialog : public DPIDialog
|
||||
|
||||
std::string get_init_preset_name(const std::string &suffix);
|
||||
void init_input_name_ctrl(wxBoxSizer *input_name_sizer, std::string preset_name);
|
||||
wxString get_top_label_text() const ;
|
||||
const Preset* get_existing_preset() const ;
|
||||
wxString get_top_label_text() const ;
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<Item*> m_items;
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
@ -97,7 +102,7 @@ public:
|
||||
bool enable_ok_btn() const;
|
||||
void add_info_for_edit_ph_printer(wxBoxSizer *sizer);
|
||||
void update_info_for_edit_ph_printer(const std::string &preset_name);
|
||||
void layout();
|
||||
bool Layout() override;
|
||||
bool is_for_rename() { return m_use_for_rename; }
|
||||
|
||||
protected:
|
||||
|
@ -826,17 +826,26 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor
|
||||
const VolumeCache& volume_data = m_cache.volumes_data[i];
|
||||
if (m_mode == Instance && !is_wipe_tower()) {
|
||||
assert(is_from_fully_selected_instance(i));
|
||||
if (transformation_type.world())
|
||||
v.set_instance_transformation(Geometry::translation_transform(displacement) * volume_data.get_instance_full_matrix());
|
||||
else if (transformation_type.instance()) {
|
||||
const Vec3d world_displacement = volume_data.get_instance_rotation_matrix() * displacement;
|
||||
v.set_instance_transformation(Geometry::translation_transform(world_displacement) * volume_data.get_instance_full_matrix());
|
||||
if (transformation_type.instance()) {
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
if (transformation_type.local()) {
|
||||
const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
|
||||
v.set_volume_offset(vol_trafo.get_offset() + vol_trafo.get_rotation_matrix() * displacement);
|
||||
}
|
||||
else {
|
||||
Vec3d relative_disp = displacement;
|
||||
if (transformation_type.instance())
|
||||
relative_disp = volume_data.get_instance_scale_matrix().inverse() * relative_disp;
|
||||
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(relative_disp), m_cache.dragging_center);
|
||||
}
|
||||
}
|
||||
else
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
@ -909,23 +918,16 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
if (m_mode == Instance && !is_wipe_tower()) {
|
||||
assert(is_from_fully_selected_instance(i));
|
||||
Transform3d new_rotation_matrix = Transform3d::Identity();
|
||||
if (transformation_type.absolute())
|
||||
new_rotation_matrix = rotation_matrix;
|
||||
else {
|
||||
if (transformation_type.world())
|
||||
new_rotation_matrix = rotation_matrix * inst_trafo.get_rotation_matrix();
|
||||
else if (transformation_type.instance())
|
||||
new_rotation_matrix = inst_trafo.get_rotation_matrix() * rotation_matrix;
|
||||
else
|
||||
assert(false);
|
||||
if (transformation_type.instance()) {
|
||||
const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
|
||||
const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
|
||||
Matrix3d inst_rotation, inst_scale;
|
||||
inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
|
||||
const Transform3d trafo = inst_trafo.get_rotation_matrix() * rotation_matrix;
|
||||
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * inst_trafo.get_offset_matrix() * trafo * Transform3d(inst_scale) * Geometry::translation_transform(-local_inst_pivot));
|
||||
}
|
||||
|
||||
const Vec3d new_offset = transformation_type.independent() ? inst_trafo.get_offset() :
|
||||
m_cache.dragging_center + new_rotation_matrix * inst_trafo.get_rotation_matrix().inverse() *
|
||||
(inst_trafo.get_offset() - m_cache.dragging_center);
|
||||
v.set_instance_transformation(Geometry::assemble_transform(Geometry::translation_transform(new_offset), new_rotation_matrix,
|
||||
inst_trafo.get_scaling_factor_matrix(), inst_trafo.get_mirror_matrix()));
|
||||
else
|
||||
transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
if (!is_single_volume_or_modifier()) {
|
||||
@ -933,8 +935,15 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
||||
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
transformation_type.set_independent();
|
||||
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
|
||||
if (transformation_type.local()) {
|
||||
const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
|
||||
Matrix3d vol_rotation, vol_scale;
|
||||
vol_trafo.get_matrix().computeRotationScaling(&vol_rotation, &vol_scale);
|
||||
const Transform3d trafo = vol_trafo.get_rotation_matrix() * rotation_matrix;
|
||||
v.set_volume_transformation(vol_trafo.get_offset_matrix() * trafo * Transform3d(vol_scale));
|
||||
}
|
||||
else
|
||||
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1357,32 +1366,17 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
|
||||
}
|
||||
|
||||
if (m_mode == Instance) {
|
||||
assert(is_from_fully_selected_instance(i));
|
||||
if (transformation_type.world()) {
|
||||
const Transform3d scale_matrix = Geometry::scale_transform(relative_scale);
|
||||
const Transform3d offset_matrix = (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) ?
|
||||
// non-constrained scaling - add offset to scale around selection center
|
||||
Geometry::translation_transform(m_cache.dragging_center + scale_matrix * (inst_trafo.get_offset() - m_cache.dragging_center)) :
|
||||
// constrained scaling - add offset to keep constraint
|
||||
Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix();
|
||||
v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset());
|
||||
}
|
||||
else if (transformation_type.instance()) {
|
||||
const Transform3d scale_matrix = Geometry::scale_transform(relative_scale);
|
||||
Vec3d offset;
|
||||
if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) {
|
||||
// non-constrained scaling - add offset to scale around selection center
|
||||
offset = inst_trafo.get_matrix_no_offset().inverse() * (inst_trafo.get_offset() - m_cache.dragging_center);
|
||||
offset = inst_trafo.get_matrix_no_offset() * (scale_matrix * offset - offset);
|
||||
}
|
||||
else
|
||||
// constrained scaling - add offset to keep constraint
|
||||
offset = translation;
|
||||
|
||||
v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix);
|
||||
if (transformation_type.instance()) {
|
||||
const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
|
||||
const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
|
||||
Matrix3d inst_rotation, inst_scale;
|
||||
inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
|
||||
const Transform3d offset_trafo = Geometry::translation_transform(inst_trafo.get_offset() + inst_rotation * translation);
|
||||
const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
|
||||
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo * Geometry::translation_transform(-local_inst_pivot));
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
if (!is_single_volume_or_modifier()) {
|
||||
@ -1390,8 +1384,18 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
}
|
||||
else {
|
||||
transformation_type.set_independent();
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
if (transformation_type.local()) {
|
||||
const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
|
||||
Matrix3d vol_rotation, vol_scale;
|
||||
vol_trafo.get_matrix().computeRotationScaling(&vol_rotation, &vol_scale);
|
||||
const Transform3d offset_trafo = Geometry::translation_transform(vol_trafo.get_offset() + vol_rotation * translation);
|
||||
const Transform3d scale_trafo = Transform3d(vol_scale) * Geometry::scale_transform(relative_scale);
|
||||
v.set_volume_transformation(offset_trafo * Transform3d(vol_rotation) * scale_trafo);
|
||||
}
|
||||
else {
|
||||
transformation_type.set_independent();
|
||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3040,28 +3044,36 @@ void Selection::paste_objects_from_clipboard()
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void Selection::transform_instance_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||
const Transform3d& transform, const Vec3d& world_pivot)
|
||||
{
|
||||
assert(transformation_type.relative());
|
||||
assert(transformation_type.world());
|
||||
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot;
|
||||
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot);
|
||||
volume.set_instance_transformation(trafo * inst_trafo.get_matrix());
|
||||
}
|
||||
|
||||
void Selection::transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||
const Transform3d& transform, const Vec3d& world_pivot)
|
||||
{
|
||||
assert(transformation_type.relative());
|
||||
|
||||
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
|
||||
const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
|
||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
||||
|
||||
if (transformation_type.world()) {
|
||||
const Vec3d inst_pivot = transformation_type.independent() ? volume_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
|
||||
const Vec3d inst_pivot = transformation_type.independent() ? vol_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
|
||||
const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
|
||||
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset * Geometry::translation_transform(-inst_pivot);
|
||||
volume.set_volume_transformation(trafo * volume_trafo.get_matrix());
|
||||
volume.set_volume_transformation(trafo * vol_trafo.get_matrix());
|
||||
}
|
||||
else if (transformation_type.instance()) {
|
||||
const Vec3d inst_pivot = transformation_type.independent() ? volume_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
|
||||
const Vec3d inst_pivot = transformation_type.independent() ? vol_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
|
||||
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot);
|
||||
volume.set_volume_transformation(trafo * volume_trafo.get_matrix());
|
||||
}
|
||||
else if (transformation_type.local()) {
|
||||
const Geometry::Transformation trafo(transform);
|
||||
volume.set_volume_transformation(trafo.get_offset_matrix() * volume_trafo.get_matrix() * trafo.get_matrix_no_offset());
|
||||
volume.set_volume_transformation(trafo * vol_trafo.get_matrix());
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
|
@ -501,6 +501,8 @@ private:
|
||||
void paste_objects_from_clipboard();
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void transform_instance_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||
const Transform3d& transform, const Vec3d& world_pivot);
|
||||
void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||
const Transform3d& transform, const Vec3d& world_pivot);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
@ -892,6 +892,16 @@ void Tab::update_mode()
|
||||
update_changed_tree_ui();
|
||||
}
|
||||
|
||||
void Tab::update_mode_markers()
|
||||
{
|
||||
// update mode for ModeSizer
|
||||
if (m_mode_sizer)
|
||||
m_mode_sizer->update_mode_markers();
|
||||
|
||||
if (m_active_page)
|
||||
m_active_page->refresh();
|
||||
}
|
||||
|
||||
void Tab::update_visibility()
|
||||
{
|
||||
Freeze(); // There is needed Freeze/Thaw to avoid a flashing after Show/Layout
|
||||
|
@ -355,6 +355,7 @@ public:
|
||||
void load_config(const DynamicPrintConfig& config);
|
||||
virtual void reload_config();
|
||||
void update_mode();
|
||||
void update_mode_markers();
|
||||
void update_visibility();
|
||||
virtual void msw_rescale();
|
||||
virtual void sys_color_changed();
|
||||
|
@ -416,7 +416,7 @@ static int scale()
|
||||
}
|
||||
#endif // __WXGTK2__
|
||||
|
||||
wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name_in, int px_cnt/* = 16*/)
|
||||
wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name_in, int px_cnt/* = 16*/, const std::string& new_color/* = std::string()*/)
|
||||
{
|
||||
#ifdef __WXGTK2__
|
||||
px_cnt *= scale();
|
||||
@ -428,7 +428,7 @@ wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name_in, int px_cnt/* = 16
|
||||
boost::replace_last(bmp_name, ".png", "");
|
||||
|
||||
// Try loading an SVG first, then PNG if SVG is not found:
|
||||
wxBitmapBundle* bmp = cache.from_svg(bmp_name, px_cnt, px_cnt, Slic3r::GUI::wxGetApp().dark_mode());
|
||||
wxBitmapBundle* bmp = cache.from_svg(bmp_name, px_cnt, px_cnt, Slic3r::GUI::wxGetApp().dark_mode(), new_color);
|
||||
if (bmp == nullptr) {
|
||||
bmp = cache.from_png(bmp_name, px_cnt, px_cnt);
|
||||
if (!bmp)
|
||||
@ -655,6 +655,17 @@ ModeButton::ModeButton( wxWindow* parent,
|
||||
Init(mode);
|
||||
}
|
||||
|
||||
ModeButton::ModeButton( wxWindow* parent,
|
||||
int mode_id,/*ConfigOptionMode*/
|
||||
const wxString& mode /*= wxEmptyString*/,
|
||||
int px_cnt /*= = 16*/) :
|
||||
ScalableButton(parent, wxID_ANY, "", mode, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT, px_cnt),
|
||||
m_mode_id(mode_id)
|
||||
{
|
||||
update_bitmap();
|
||||
Init(mode);
|
||||
}
|
||||
|
||||
void ModeButton::Init(const wxString &mode)
|
||||
{
|
||||
std::string mode_str = std::string(mode.ToUTF8());
|
||||
@ -684,6 +695,15 @@ void ModeButton::SetState(const bool state)
|
||||
SetToolTip(state ? m_tt_selected : m_tt_focused);
|
||||
}
|
||||
|
||||
void ModeButton::update_bitmap()
|
||||
{
|
||||
m_bmp = *get_bmp_bundle("mode", m_px_cnt, Slic3r::GUI::wxGetApp().get_mode_btn_color(m_mode_id));
|
||||
|
||||
SetBitmap(m_bmp);
|
||||
SetBitmapCurrent(m_bmp);
|
||||
SetBitmapPressed(m_bmp);
|
||||
}
|
||||
|
||||
void ModeButton::focus_button(const bool focus)
|
||||
{
|
||||
const wxFont& new_font = focus ?
|
||||
@ -709,6 +729,12 @@ void ModeButton::focus_button(const bool focus)
|
||||
Update();
|
||||
}
|
||||
|
||||
void ModeButton::sys_color_changed()
|
||||
{
|
||||
Slic3r::GUI::wxGetApp().UpdateDarkUI(this, m_has_border);
|
||||
update_bitmap();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ModeSizer
|
||||
@ -721,21 +747,15 @@ ModeSizer::ModeSizer(wxWindow *parent, int hgap/* = 0*/) :
|
||||
{
|
||||
SetFlexibleDirection(wxHORIZONTAL);
|
||||
|
||||
std::vector < std::pair < wxString, std::string >> buttons = {
|
||||
{_(L("Simple")), "mode_simple"},
|
||||
// {_(L("Advanced")), "mode_advanced"},
|
||||
{_CTX(L_CONTEXT("Advanced", "Mode"), "Mode"), "mode_advanced"},
|
||||
{_(L("Expert")), "mode_expert"},
|
||||
};
|
||||
|
||||
auto modebtnfn = [](wxCommandEvent &event, int mode_id) {
|
||||
Slic3r::GUI::wxGetApp().save_mode(mode_id);
|
||||
event.Skip();
|
||||
};
|
||||
|
||||
m_mode_btns.reserve(3);
|
||||
for (const auto& button : buttons) {
|
||||
m_mode_btns.push_back(new ModeButton(parent, button.first, button.second, mode_icon_px_size()));
|
||||
int mode_id = 0;
|
||||
for (const wxString& label : {_L("Simple"), _CTX(L_CONTEXT("Advanced", "Mode"), "Mode"),_L("Expert")}) {
|
||||
m_mode_btns.push_back(new ModeButton(parent, mode_id++, label, mode_icon_px_size()));
|
||||
|
||||
m_mode_btns.back()->Bind(wxEVT_BUTTON, std::bind(modebtnfn, std::placeholders::_1, int(m_mode_btns.size() - 1)));
|
||||
Add(m_mode_btns.back());
|
||||
@ -762,8 +782,14 @@ void ModeSizer::set_items_border(int border)
|
||||
|
||||
void ModeSizer::sys_color_changed()
|
||||
{
|
||||
for (size_t m = 0; m < m_mode_btns.size(); m++)
|
||||
m_mode_btns[m]->sys_color_changed();
|
||||
for (ModeButton* btn : m_mode_btns)
|
||||
btn->sys_color_changed();
|
||||
}
|
||||
|
||||
void ModeSizer::update_mode_markers()
|
||||
{
|
||||
for (ModeButton* btn : m_mode_btns)
|
||||
btn->update_bitmap();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -50,7 +50,7 @@ void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<
|
||||
int em_unit(wxWindow* win);
|
||||
int mode_icon_px_size();
|
||||
|
||||
wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name, int px_cnt = 16);
|
||||
wxBitmapBundle* get_bmp_bundle(const std::string& bmp_name, int px_cnt = 16, const std::string& new_color_rgb = std::string());
|
||||
wxBitmapBundle* get_empty_bmp_bundle(int width, int height);
|
||||
wxBitmapBundle* get_solid_bmp_bundle(int width, int height, const std::string& color);
|
||||
|
||||
@ -247,7 +247,7 @@ public:
|
||||
void SetBitmapDisabled_(const ScalableBitmap &bmp);
|
||||
int GetBitmapHeight();
|
||||
|
||||
void sys_color_changed();
|
||||
virtual void sys_color_changed();
|
||||
|
||||
private:
|
||||
wxWindow* m_parent { nullptr };
|
||||
@ -256,6 +256,7 @@ private:
|
||||
int m_width {-1}; // should be multiplied to em_unit
|
||||
int m_height{-1}; // should be multiplied to em_unit
|
||||
|
||||
protected:
|
||||
// bitmap dimensions
|
||||
int m_px_cnt{ 16 };
|
||||
bool m_has_border {false};
|
||||
@ -283,6 +284,12 @@ public:
|
||||
const std::string& icon_name = "",
|
||||
int px_cnt = 16);
|
||||
|
||||
ModeButton(
|
||||
wxWindow* parent,
|
||||
int mode_id,/*ConfigOptionMode*/
|
||||
const wxString& mode = wxEmptyString,
|
||||
int px_cnt = 16);
|
||||
|
||||
~ModeButton() {}
|
||||
|
||||
void Init(const wxString& mode);
|
||||
@ -292,16 +299,20 @@ public:
|
||||
void OnLeaveBtn(wxMouseEvent& event) { focus_button(m_is_selected); event.Skip(); }
|
||||
|
||||
void SetState(const bool state);
|
||||
void update_bitmap();
|
||||
bool is_selected() { return m_is_selected; }
|
||||
void sys_color_changed() override;
|
||||
|
||||
protected:
|
||||
void focus_button(const bool focus);
|
||||
|
||||
private:
|
||||
bool m_is_selected = false;
|
||||
bool m_is_selected {false};
|
||||
int m_mode_id {-1};
|
||||
|
||||
wxString m_tt_selected;
|
||||
wxString m_tt_focused;
|
||||
wxBitmapBundle m_bmp;
|
||||
};
|
||||
|
||||
|
||||
@ -322,6 +333,7 @@ public:
|
||||
void set_items_border(int border);
|
||||
|
||||
void sys_color_changed();
|
||||
void update_mode_markers();
|
||||
const std::vector<ModeButton*>& get_btns() { return m_mode_btns; }
|
||||
|
||||
private:
|
||||
|
@ -381,9 +381,9 @@ TEST_CASE("triangle intersection", "[]")
|
||||
|
||||
#if defined _WIN32
|
||||
#define FONT_DIR_PATH "C:/Windows/Fonts";
|
||||
#elif defined __linux__
|
||||
#define FONT_DIR_PATH "/usr/share/fonts";
|
||||
#endif
|
||||
//#elif defined __linux__
|
||||
//#define FONT_DIR_PATH "/usr/share/fonts";
|
||||
//#elif defined __APPLE__
|
||||
//#define FONT_DIR_PATH "//System/Library/Fonts";
|
||||
//#endif
|
||||
@ -391,8 +391,10 @@ TEST_CASE("triangle intersection", "[]")
|
||||
#ifdef FONT_DIR_PATH
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#include <boost/filesystem.hpp>
|
||||
namespace fs = boost::filesystem;
|
||||
//#include <filesystem>
|
||||
//namespace fs = std::filesystem;
|
||||
// Check function Emboss::is_italic that exist some italic and some non-italic font.
|
||||
TEST_CASE("Italic check", "[Emboss]")
|
||||
{
|
||||
@ -406,15 +408,15 @@ TEST_CASE("Italic check", "[Emboss]")
|
||||
dir_paths.pop();
|
||||
for (const auto &entry : fs::directory_iterator(dir_path)) {
|
||||
const fs::path &act_path = entry.path();
|
||||
if (entry.is_directory()) {
|
||||
dir_paths.push(act_path.u8string());
|
||||
if (fs::is_directory(entry)) {
|
||||
dir_paths.push(act_path.string());
|
||||
continue;
|
||||
}
|
||||
std::string ext = act_path.extension().u8string();
|
||||
std::string ext = act_path.extension().string();
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
if (ext != ".ttf") continue;
|
||||
std::string path_str = act_path.u8string();
|
||||
std::string path_str = act_path.string();
|
||||
auto font_opt = Emboss::create_font_file(path_str.c_str());
|
||||
if (font_opt == nullptr) continue;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user